diff --git a/aif.xsd b/aif.xsd index 2a01ea0..2b2327c 100644 --- a/aif.xsd +++ b/aif.xsd @@ -408,39 +408,102 @@ + + + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + - - - - + + + + + + - + @@ -474,6 +537,14 @@ + + + + + + + + diff --git a/aif/disk/block.py b/aif/disk/block.py index 7e46303..15357e7 100644 --- a/aif/disk/block.py +++ b/aif/disk/block.py @@ -20,6 +20,8 @@ import psutil ## from aif.utils import xmlBool, size +# TODO: https://serverfault.com/questions/356534/ssd-erase-block-size-lvm-pv-on-raw-device-alignment + PARTED_FSTYPES = sorted(list(dict(vars(parted.filesystem))['fileSystemType'].keys())) PARTED_FLAGS = sorted(list(parted.partition.partitionFlag.values())) diff --git a/aif/disk/filesystem.py b/aif/disk/filesystem.py index 91c8298..0e58c19 100644 --- a/aif/disk/filesystem.py +++ b/aif/disk/filesystem.py @@ -6,7 +6,7 @@ import psutil ## from aif.disk.block import Partition from aif.disk.luks import LUKS -from aif.disk.lvm import Group as LVMGroup +from aif.disk.lvm import LV as LVMVolume from aif.disk.mdadm import Array as MDArray # I wish there was a better way of doing this. @@ -44,11 +44,11 @@ for i in os.listdir(_mod_dir): class FS(object): def __init__(self, fs_xml, sourceobj): self.xml = fs_xml - if not isinstance(sourceobj, (Partition, LUKS, LVMGroup, MDArray)): + if not isinstance(sourceobj, (Partition, LUKS, LVMVolume, MDArray)): raise ValueError(('sourceobj must be of type ' 'aif.disk.block.Partition, ' 'aif.disk.luks.LUKS, ' - 'aif.disk.lvm.Group, or' + 'aif.disk.lvm.LV, or' 'aif.disk.mdadm.Array')) self.source = sourceobj self.devpath = sourceobj.devpath diff --git a/aif/disk/luks.py b/aif/disk/luks.py index e3d6d06..946ea73 100644 --- a/aif/disk/luks.py +++ b/aif/disk/luks.py @@ -1,4 +1,8 @@ +from aif.disk.block import Disk, Partition +from aif.disk.lvm import LV +from aif.disk.mdadm import Array + class LUKS(object): - def __init__(self): + def __init__(self, partobj): self.devpath = None pass diff --git a/aif/disk/lvm.py b/aif/disk/lvm.py index 6f03d1a..fac8f74 100644 --- a/aif/disk/lvm.py +++ b/aif/disk/lvm.py @@ -1,13 +1,29 @@ +try: + import dbus + has_mod = True +except ImportError: + # This is ineffecient; the native dbus module is preferred. + # In Arch, this can be installed via the 'extra' repository package "python-dbus". + import subprocess + has_mod = False +## +from aif.disk.block import Disk, Partition +from aif.disk.luks import LUKS +from aif.disk.mdadm import Array + + class PV(object): def __init__(self, partobj): self.devpath = None pass -class LV(object): - def __init__(self, lv_xml, pv_objs): - pass -class Group(object): +class VG(object): def __init__(self, vg_xml, lv_objs): self.devpath = None pass + + +class LV(object): + def __init__(self, lv_xml, pv_objs): + pass diff --git a/aif/disk/mdadm.py b/aif/disk/mdadm.py index 72a76d8..3623e9f 100644 --- a/aif/disk/mdadm.py +++ b/aif/disk/mdadm.py @@ -7,8 +7,9 @@ import uuid ## import mdstat ## -from aif.disk.block import Disk -from aif.disk.block import Partition +from aif.disk.block import Disk, Partition +from aif.disk.luks import LUKS +from aif.disk.lvm import LV SUPPORTED_LEVELS = (0, 1, 4, 5, 6, 10) @@ -173,8 +174,10 @@ class Array(object): self.devname = self.xml.attrib['name'] self.devpath = devpath self.updateStatus() + self.homehost = homehost self.members = [] self.state = None + self.info = None def addMember(self, memberobj): if not isinstance(memberobj, Member): @@ -183,20 +186,18 @@ class Array(object): self.members.append(memberobj) return() - def assemble(self, scan = False): + def start(self, scan = False): if not any((self.members, self.devpath)): raise RuntimeError('Cannot assemble an array with no members (for hints) or device path') - cmd = ['mdadm', '--assemble', self.devpath] if not scan: for m in self.members: cmd.append(m.devpath) else: - cmd.extend(['']) + cmd.append('--scan') # TODO: logging! subprocess.run(cmd) - - pass + self.state = 'assembled' return() def create(self): @@ -206,6 +207,7 @@ class Array(object): '--level={0}'.format(self.level), '--metadata={0}'.format(self.metadata), '--chunk={0}'.format(self.chunksize), + '--homehost={0}'.format(self.homehost), '--raid-devices={0}'.format(len(self.members))] if self.layout: cmd.append('--layout={0}'.format(self.layout)) @@ -214,13 +216,14 @@ class Array(object): cmd.append(m.devpath) # TODO: logging! subprocess.run(cmd) - - pass + self.writeConf() + self.state = 'new' return() def stop(self): # TODO: logging subprocess.run(['mdadm', '--stop', self.devpath]) + self.state = 'disassembled' return() def updateStatus(self): @@ -232,4 +235,22 @@ class Array(object): return() def writeConf(self, conf = '/etc/mdadm.conf'): - pass + with open(conf, 'r') as fh: + conflines = fh.read().splitlines() + # TODO: logging + arrayinfo = subprocess.run(['mdadm', '--detail', '--brief', self.devpath], + stdout = subprocess.PIPE).stdout.decode('utf-8').strip() + if arrayinfo not in conflines: + r = re.compile(r'^ARRAY\s+{0}'.format(self.devpath)) + nodev = True + for l in conflines: + if r.search(l): + nodev = False + # TODO: logging? + # and/or Raise an exception here; + # an array already exists with that name but not with the same opts/GUID/etc. + break + if nodev: + with open(conf, 'a') as fh: + fh.write('{0}\n'.format(arrayinfo)) + return() diff --git a/examples/aif.xml b/examples/aif.xml index 43f25fc..920859d 100644 --- a/examples/aif.xml +++ b/examples/aif.xml @@ -55,9 +55,20 @@ - - - + + + + + + + + data + + + + + +