Skip to content
This repository has been archived by the owner on Oct 31, 2021. It is now read-only.

Commit

Permalink
Another big update.
Browse files Browse the repository at this point in the history
More Unit Tests.
The 'module' module has been merged into the 'salt' module.
  • Loading branch information
jrd committed Jan 26, 2013
1 parent b161960 commit 9d3d3fb
Show file tree
Hide file tree
Showing 7 changed files with 285 additions and 83 deletions.
1 change: 0 additions & 1 deletion src/salix-live-installer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
from kernel import *
from keyboard import *
from language import *
from module import *
from mounting import *
from package import *
from salt import *
Expand Down
2 changes: 2 additions & 0 deletions src/salix-live-installer/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ def execCall(cmd, shell = True, env = {'LANG' : 'en_US'}):
"""
Execute a command and return the exit code.
The command is executed by default in a /bin/sh shell and using english locale.
The output of the command is not read. With some commands, it hangs if the output is not read when run in a shell.
For this type of command, prefer using execGetOutput even if you don't read the return value or using shell = False.
"""
return subprocess.call(cmd, shell = shell, env = env)

Expand Down
31 changes: 22 additions & 9 deletions src/salix-live-installer/freesize.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,18 @@
import os
from stat import *
from execute import *
import mounting

def _getMountPoint(device):
"Copied from 'mounting' module to break circular dependancies"
mountpoint = None
for line in execGetOutput('mount', shell = False):
p, _, mp, _ = line.split(' ', 3) # 3 splits max, _ is discarded
if os.path.islink(p):
p = os.path.realpath(p)
if p == device:
mountpoint = mp
break
return mountpoint

def getHumanSize(size):
"Returns the human readable format of the size in bytes"
Expand All @@ -26,6 +37,7 @@ def getHumanSize(size):

def getSizes(path):
"""
Compute the different sizes of the fileystem denoted by path (either a device or a file in filesystem).
Returns the following sizes (in a dictionary):
- size (total size)
- free (total free size)
Expand All @@ -35,7 +47,7 @@ def getSizes(path):
+ all of them with the corresponding 'Human' suffix.
"""
if S_ISBLK(os.stat(path).st_mode):
mountpoint = getMountPoint(path)
mountpoint = _getMountPoint(path)
if mountpoint:
# mounted, so will use mountpoint to get information about different sizes
path = mountpoint
Expand Down Expand Up @@ -118,10 +130,11 @@ def getUsedSize(path, blocksize = None):
assertTrue(stats['used'] == None)
assertTrue(stats['uuUsed'] == None)
print 'getUsedSize(.)'
stats = getUsedSize('.')
print stats
assertTrue(stats['size'] > 0)
print 'getUsedSize(., 16384)'
stats = getUsedSize('.', 16384)
print stats
assertTrue(stats['size'] > 0)
stats1 = getUsedSize('.')
print stats1
assertTrue(stats1['size'] > 0)
print 'getUsedSize(., 524288)'
stats2 = getUsedSize('.', 524288)
print stats2
assertTrue(stats2['size'] > 0)
assertTrue(stats2['size'] > stats1['size'])
119 changes: 84 additions & 35 deletions src/salix-live-installer/fs.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,53 +11,66 @@
- makeFs
"""
from execute import *
from freesize import getSizes
import os
from stat import *
import re

def getFsType(partitionDevice):
"""
Returns the file system type for that partition.
'partitionDevice' should no be prefilled with '/dev/'.
'partitionDevice' should no be prefilled with '/dev/' if it's a block device.
It can be a full path if the partition is contains in a file.
Returns 'Extended' if the partition is an extended partition and has no filesystem.
"""
checkRoot()
if S_ISBLK(os.stat('/dev/{0}'.format(partitionDevice)).st_mode):
if os.path.exists('/dev/{0}'.format(partitionDevice)) and S_ISBLK(os.stat('/dev/{0}'.format(partitionDevice)).st_mode):
path = '/dev/{0}'.format(partitionDevice)
elif os.path.isfile(partitionDevice):
path = partitionDevice
else:
fstype = False
if path:
try:
fstype = execGetOutput(['/sbin/blkid', '-c', '/dev/null', '-s', 'TYPE', '-o', 'value', '/dev/{0}'.format(partitionDevice)])[0]
fstype = execGetOutput(['/sbin/blkid', '-s', 'TYPE', '-o', 'value', path], shell = False)[0]
except subprocess.CalledProcessError as e:
fstype = False
if fstype == '':
fstype = 'Extended'
else:
fstype = False
return fstype

def getFsLabel(partitionDevice):
"""
Returns the label for that partition (if any).
'partitionDevice' should no be prefilled with '/dev/'.
'partitionDevice' should no be prefilled with '/dev/' if it's a block device.
It can be a full path if the partition is contains in a file.
"""
checkRoot()
if S_ISBLK(os.stat('/dev/{0}'.format(partitionDevice)).st_mode):
try:
label = execGetOutput(['/sbin/blkid', '-c', '/dev/null', '-s', 'LABEL', '-o', 'value', '/dev/{0}'.format(partitionDevice)])[0]
except subprocess.CalledProcessError as e:
label = ''
if os.path.exists('/dev/{0}'.format(partitionDevice)) and S_ISBLK(os.stat('/dev/{0}'.format(partitionDevice)).st_mode):
path = '/dev/{0}'.format(partitionDevice)
elif os.path.isfile(partitionDevice):
path = partitionDevice
else:
label = False
if path:
try:
label = execGetOutput(['/sbin/blkid', '-s', 'LABEL', '-o', 'value', path], shell = False)[0]
except subprocess.CalledProcessError as e:
label = False
return label

def makeFs(partitionDevice, fsType, label=None, options=None, force=False):
def makeFs(partitionDevice, fsType, label=None, force=False, options=None):
"""
Creates a filesystem on the device.
'partitionDevice' should no be prefilled with '/dev/'.
'partitionDevice' should no be prefilled with '/dev/' if it's a block device.
'fsType' could be ext2, ext3, ext4, xfs, reiserfs, jfs, btrfs, ntfs, fat16, fat32, swap
Use 'options' to force passing these options to the creation process (use a list)
Use 'force=True' if you want to force creating the filesystem and if 'partitionDevice' is a full path to a file (not a block device).
Use 'options' to force passing these options to the creation process (use a list)
"""
if force and os.path.exists(partitionDevice):
path = partitionDevice
else:
path = '/dev/{0}'.format(partitionDevice)
if not os.path.exists(path):
raise IOError('{0} does not exist'.format(path))
if not S_ISBLK(os.stat(path).st_mode):
raise IOError('{0} is not a block device'.format(path))
if fsType not in ('ext2', 'ext3', 'ext4', 'xfs', 'reiserfs', 'jfs', 'btrfs', 'ntfs', 'fat16', 'fat32', 'swap'):
Expand All @@ -82,7 +95,7 @@ def makeFs(partitionDevice, fsType, label=None, options=None, force=False):

def _makeExtFs(path, version, label, options, force):
"ExtX block size: 4k per default in /etc/mke2fs.conf"
cmd = '/sbin/mkfs.ext{0:d}'.format(version)
cmd = ['/sbin/mkfs.ext{0:d}'.format(version)]
if not options:
options = []
if label:
Expand All @@ -92,23 +105,33 @@ def _makeExtFs(path, version, label, options, force):
options.append(label)
if force:
options.append('-F')
return execCall([cmd].extend(options))
cmd.extend(options)
cmd.append(path)
return execCall(cmd, shell = False)

def _makeXfs(path, label, options, force):
"http://blog.peacon.co.uk/wiki/Creating_and_Tuning_XFS_Partitions"
cmd = '/sbin/mkfs.xfs'
cmd = ['/sbin/mkfs.xfs']
if not options:
options = ['-l', 'size=64m,lazy-count=1', '-f']
# -f is neccessary to have this or you cannot create XFS on a non-empty partition or disk
options = ['-f'] # -f is neccessary to have this or you cannot create XFS on a non-empty partition or disk
if os.path.isfile(path):
size = os.stat(path).st_size
else:
size = getSizes(path)['size']
if size > 104857600: # > 100M
options = ['-l', 'size=64m,lazy-count=1'] # optimizations
if label:
if len(label) > 12: # max 12 chars
label = label[0:11]
options.append('-L')
options.append(label)
return execCall([cmd].extend(options))
cmd.extend(options)
cmd.append(path)
print 'cmd={0}'.format(cmd)
return execCall(cmd, shell = False)

def _makeReiserfs(path, label, options, force):
cmd = '/sbin/mkfs.reiserfs'
cmd = ['/sbin/mkfs.reiserfs']
if not options:
options = []
if label:
Expand All @@ -119,10 +142,12 @@ def _makeReiserfs(path, label, options, force):
if force:
options.append('-f')
options.append('-f') # twice for no confirmation
return execCall([cmd].extend(options))
cmd.extend(options)
cmd.append(path)
return execCall(cmd, shell = False)

def _makeJfs(path, label, options, force):
cmd = '/sbin/mkfs.jfs'
cmd = ['/sbin/mkfs.jfs']
if not options:
options = ['-f'] # if not specified, will ask to continue
if label:
Expand All @@ -132,21 +157,25 @@ def _makeJfs(path, label, options, force):
options.append(label)
if force:
pass # no need to do anything
return execCall([cmd].extend(options))
cmd.extend(options)
cmd.append(path)
return execCall(cmd, shell = False)

def _makeBtrfs(path, label, options, force):
cmd = '/sbin/mkfs.btrfs'
cmd = ['/sbin/mkfs.btrfs']
if not options:
options = []
if label:
options.append('-L')
options.append(label) # no restriction on size
if force:
pass # no need to do anything
return execCall([cmd].extend(options))
cmd.extend(options)
cmd.append(path)
return execCall(cmd, shell = False)

def _makeNtfs(path, label, options, force):
cmd = '/sbin/mkfs.ntfs'
cmd = ['/sbin/mkfs.ntfs']
if not options:
options = ['-Q']
if label:
Expand All @@ -156,10 +185,12 @@ def _makeNtfs(path, label, options, force):
options.append(label)
if force:
options.append('-F')
return execCall([cmd].extend(options))
cmd.extend(options)
cmd.append(path)
return execCall(cmd, shell = False)

def _makeFat(path, is32, label, options, force):
cmd = '/sbin/mkfs.vfat'
cmd = ['/sbin/mkfs.vfat']
if is32:
size = ['-F', '32']
else:
Expand All @@ -175,18 +206,22 @@ def _makeFat(path, is32, label, options, force):
options.append(label)
if force:
options.append('-I') # permit to use whole disk
return execCall([cmd].extend(options))
cmd.extend(options)
cmd.append(path)
return execCall(cmd, shell = False)

def _makeSwap(path, label, options, force):
cmd = '/sbin/mkswap'
cmd = ['/sbin/mkswap']
if not options:
options = ['-f'] # it is neccessary to have this or you cannot create a swap on a non-empty partition or disk
if label:
options.append('-L') # I didn't find any restriction in the label size
options.append(label)
if force:
pass # nothing to do, writing to a file is always ok
return execCall([cmd].extend(options))
cmd.extend(options)
cmd.append(path)
return execCall(cmd, shell = False)

# Unit test
if __name__ == '__main__':
Expand All @@ -199,4 +234,18 @@ def _makeSwap(path, label, options, force):
assertTrue(len(fstype) > 0)
assertTrue(label)
assertTrue(len(label) > 0)
# TODO : add Unit Test for making filesystems
for ft in ('ext2', 'ext4', 'xfs', 'reiserfs', 'jfs', 'btrfs', 'ntfs', 'fat16', 'fat32', 'swap'):
f = '{0}.fs'.format(ft)
if ft == 'btrfs':
size = 300 # btrfs minimum size is 256M
else:
size = 50
execCall(['dd', 'if=/dev/zero', 'of={0}'.format(f), 'bs=1M', 'count={0:d}'.format(size)], shell = False)
assertEquals(0, makeFs(f, ft, 'test_{0}'.format(ft), True))
if ft in ('fat16', 'fat32'):
expectedFt = 'vfat'
else:
expectedFt = ft
assertEquals(expectedFt, getFsType(f))
assertEquals('test_{0}'.format(ft), getFsLabel(f))
os.unlink(f)
6 changes: 0 additions & 6 deletions src/salix-live-installer/module.py

This file was deleted.

Loading

0 comments on commit 9d3d3fb

Please sign in to comment.