diff --git a/aif.xsd b/aif.xsd index 73d601a..1cfd517 100644 --- a/aif.xsd +++ b/aif.xsd @@ -5,134 +5,230 @@ xmlns:aif="http://aif-ng.io/" elementFormDefault="qualified" attributeFormDefault="unqualified"> - - - See https://aif.square-r00t.net/ for more information about this project. - - - - - - - This element specifies a type to be used for validating storage devices, such as hard disks or - mdadm-managed devices. - - + + + - - - - This element specifies a type to validate what kind of disk formatting. Accepts either GPT or BIOS (for - MBR systems) only. - - + + + + + + + + + + + - + + - - - - This element validates a disk size specification for a partition. Same rules apply as those in parted's - size specification. - - - - - - - - + - - - This element validates a filesystem type to be specified for formatting a partition (NOT applying a filesystem!); valid values are: affs0, affs1, affs2, affs3, affs4, affs5, affs6, affs7, amufs, amufs0, amufs1, amufs2, amufs3, amufs4, amufs5, apfs1, apfs2, asfs, btrfs, ext2, ext3, ext4, fat16, fat32, hfs, hfs+, hfsx, hp-ufs, jfs, linux-swap(v0), linux-swap(v1), nilfs2, ntfs, reiserfs, sun-ufs, swsusp, udf, xfs - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - + + - + - - + + + - + + + + + + + + + + + + + + + + + + - + + + + + + + + + + - + + - + + - - - - - - - + + + - + + - + + - + + - + + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -145,52 +241,173 @@ - + - - - - - + + + + + + - - - - - - + + - + - - + + + - - - - - + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - @@ -198,20 +415,65 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - + - - + @@ -219,64 +481,88 @@ + + + + + + + + + + + + + + + + + + + + + + + - + - - + + + - - - - - - - - - + + - - - - - - - + + + + + + + + - + - + - - + + + + + - + - - - - - + + + + + + @@ -289,10 +575,10 @@ - + - + @@ -301,10 +587,11 @@ - + - + @@ -314,24 +601,27 @@ - - + + + + + - + - - - + + + @@ -341,18 +631,18 @@ - - - - - - - + + + + + + - + @@ -361,4 +651,4 @@ - + \ No newline at end of file diff --git a/aif/config.py b/aif/config.py index 7501007..2200334 100644 --- a/aif/config.py +++ b/aif/config.py @@ -2,7 +2,7 @@ import os ## from lxml import etree -#https://stackoverflow.com/questions/30232031/how-can-i-strip-namespaces-out-of-an-lxml-tree/30233635#30233635 ? +# https://stackoverflow.com/questions/30232031/how-can-i-strip-namespaces-out-of-an-lxml-tree/30233635#30233635 ? class Config(object): def __init__(self): diff --git a/aif/constants.py b/aif/constants.py index aa7edf0..160005a 100644 --- a/aif/constants.py +++ b/aif/constants.py @@ -1,8 +1,3 @@ import os import re -## -import parted - - -PARTED_FSTYPES = list(dict(vars(parted.filesystem))['fileSystemType'].keys()) diff --git a/aif/disk/block.py b/aif/disk/block.py index 89a5cb0..76db82f 100644 --- a/aif/disk/block.py +++ b/aif/disk/block.py @@ -39,8 +39,8 @@ _units = {'B': 0, _pos_re = re.compile((r'^(?P-|\+)?\s*' r'(?P[0-9]+)\s*' # empty means size in sectors - r'(?P%|[{0}]|)\s*$'.format(''.join(list(_units.keys())))), - re.IGNORECASE) + r'(?P%|{0}|)\s*$'.format('|'.join(list(_units.keys()))) + )) def convertSizeUnit(pos): @@ -69,6 +69,7 @@ class Partition(object): raise ValueError(('You must specify if this is a ' 'primary, extended, or logical partition for msdos partition tables')) self.xml = part_xml + self.id = part_xml.attrib['id'] self.partnum = partnum if tbltype == 'msdos': if partnum > 4: diff --git a/aif/disk/filesystem.py b/aif/disk/filesystem.py index ee45a2f..d94f337 100644 --- a/aif/disk/filesystem.py +++ b/aif/disk/filesystem.py @@ -24,7 +24,7 @@ with open('/proc/filesystems', 'r') as fh: _mod_dir = os.path.join('/lib/modules', os.uname().release, 'kernel/fs') -_strip_mod_suffix = re.compile(r'(?P)\.ko(\.(x|g)?z))?$', re.IGNORECASE) +_strip_mod_suffix = re.compile(r'(?P)\.ko(\.(x|g)?z)?$', re.IGNORECASE) for i in os.listdir(_mod_dir): path = os.path.join(_mod_dir, i) fs_name = None diff --git a/aif/disk/mdadm.py b/aif/disk/mdadm.py index 29dc2a0..a59b751 100644 --- a/aif/disk/mdadm.py +++ b/aif/disk/mdadm.py @@ -1,11 +1,59 @@ +import copy +import subprocess +## +import mdstat +## +from aif.disk.block import Disk +from aif.disk.block import Partition + + +SUPPORTED_LEVELS = (0, 1, 4, 5, 6) + class Member(object): def __init__(self, member_xml, partobj): self.xml = member_xml self.device = partobj + if not isinstance(self.device, (Partition, Disk, Array)): + raise ValueError(('partobj must be of type aif.disk.block.Partition, ' + 'aif.disk.block.Disk, or aif.disk.mdadm.Array')) self.devpath = self.device.devpath - pass + + def prepare(self): + # TODO: logging + subprocess.run(['mdadm', '--misc', '--zero-superblock', self.devpath]) + return() class Array(object): def __init__(self, array_xml): - self.devpath = None - pass + self.xml = array_xml + self.id = array_xml.attrib['id'] + self.level = int(array_xml.attrib['level']) + if self.level not in SUPPORTED_LEVELS: + raise ValueError('RAID level must be one of: {0}'.format(', '.join(SUPPORTED_LEVELS))) + self.devname = self.xml.attrib['name'] + self.devpath = '/dev/md/{0}'.format(self.devname) + self.updateStatus() + self.members = [] + + def addMember(self, memberobj): + if not isinstance(memberobj, Member): + raise ValueError('memberobj must be of type aif.disk.mdadm.Member') + + def assemble(self): + cmd = ['mdadm', '--assemble', self.devpath] + for m in self.members: + cmd.append(m.devpath) + subprocess.run(cmd) + + def stop(self): + # TODO: logging + subprocess.run(['mdadm', '--stop', self.devpath]) + return() + + def updateStatus(self): + _info = mdstat.parse() + for k, v in _info['devices'].items(): + if k != self.devname: + del(_info['devices'][k]) + self.info = copy.deepcopy(_info) + return() diff --git a/aif/envsetup.py b/aif/envsetup.py index f59e846..60f0f72 100644 --- a/aif/envsetup.py +++ b/aif/envsetup.py @@ -13,8 +13,8 @@ import tempfile import venv # TODO: a more consistent way of managing deps? -depmods = ['blkinfo', 'gpg', 'lxml', 'passlib', 'psutil', - 'pyparted', 'pytz', 'requests', 'validators'] +depmods = ['blkinfo', 'gpg', 'lxml', 'mdstat', 'passlib', 'psutil', + 'pyparted', 'pyroute2', 'pytz', 'requests', 'validators'] class EnvBuilder(object): def __init__(self): diff --git a/aif/system/__init__.py b/aif/system/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/aif/system/locales.py b/aif/system/locales.py new file mode 100644 index 0000000..e69de29 diff --git a/aif/users.py b/aif/system/users.py similarity index 100% rename from aif/users.py rename to aif/system/users.py diff --git a/docs/examples/aif.xml b/docs/examples/aif.xml index ab66868..23802ac 100644 --- a/docs/examples/aif.xml +++ b/docs/examples/aif.xml @@ -5,18 +5,35 @@ - - - - - - + + + + + + - + + + + + secrets1 + + + + secrets1 + /boot/.decrypt.plaintext + + + + /root/.decrypt.key + + @@ -24,7 +41,9 @@ - + + @@ -40,48 +59,67 @@ seekrit - - - - - lzo - - - 5 - / - - - - - + + + + + + lzo + + + 5 + / + + + + + + - + + + +
dhcp
+
+ +
slaac
+
fde4:16b9:654b:bbfa::15/64
+
+
+ + 8.8.8.8 + +
- + + + en_US.UTF-8 + - - - - + + + - + - - - - - - - + + + + + + + http://arch.mirror.square-r00t.net/$repo/os/$arch @@ -92,17 +130,17 @@ http://mirror.jmu.edu/pub/archlinux/$repo/os/$arch - - - - + + + + - + -