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
-
-
-
-
+
+
+
+
-
+
-
-
-
-
+
+
+
+
diff --git a/setup.py b/setup.py
index 61c7197..75a1fcc 100644
--- a/setup.py
+++ b/setup.py
@@ -31,6 +31,6 @@ setuptools.setup(
project_urls = {'Documentation': 'https://aif-ng.io/',
'Source': 'https://git.square-r00t.net/AIF-NG/',
'Tracker': 'https://bugs.square-r00t.net/index.php?project=9'},
- install_requires = ['blkinfo', 'gpg', 'lxml', 'passlib', 'psutil',
- 'pyparted', 'pytz', 'requests', 'validators']
+ install_requires = ['blkinfo', 'gpg', 'lxml', 'mdstat', 'passlib', 'psutil',
+ 'pyparted', 'pyroute2', 'pytz', 'requests', 'validators']
)