From 00e9c546d7d54f942ecd7ed99d18e6d28b01034d Mon Sep 17 00:00:00 2001 From: brent s Date: Wed, 6 Nov 2019 16:58:58 -0500 Subject: [PATCH] i *think* i'm done the gi version of disk.lvm. LVM is such a mess. --- aif.xsd | 10 ++-- aif/disk/lvm.py | 99 +++++++++++++++++++++++++++++++++----- aif/disk/mdadm.py | 16 +++--- aif/disk/mdadm_fallback.py | 8 +-- examples/aif.xml | 14 +++--- examples/most_minimal.xml | 63 ++++++++++++++++++++++++ 6 files changed, 174 insertions(+), 36 deletions(-) create mode 100644 examples/most_minimal.xml diff --git a/aif.xsd b/aif.xsd index 3e31758..d0cc6ea 100644 --- a/aif.xsd +++ b/aif.xsd @@ -357,7 +357,7 @@ - + @@ -670,7 +670,7 @@ - @@ -687,10 +687,10 @@ - + - + - + diff --git a/aif/disk/lvm.py b/aif/disk/lvm.py index c357dfd..9c76ea8 100644 --- a/aif/disk/lvm.py +++ b/aif/disk/lvm.py @@ -107,12 +107,13 @@ class VG(object): self.name = self.xml.attrib('name') self.lvs = [] self.pvs = [] - self.tags = [] - for te in self.xml.findall('tags/tag'): - self.tags.append(te.text) + # self.tags = [] + # for te in self.xml.findall('tags/tag'): + # self.tags.append(te.text) _common.addBDPlugin('lvm') self.devpath = self.name self.info = None + self.created = False def addPV(self, pvobj): if not isinstance(pvobj, PV): @@ -128,26 +129,31 @@ class VG(object): # FUCK. LVM. You can't *specify* a UUID. # u = uuid.uuid4() # opts.append(_BlockDev.ExtraArg.new('--uuid', str(u))) - for t in self.tags: - opts.append(_BlockDev.ExtraArg.new('--addtag', t)) + # for t in self.tags: + # opts.append(_BlockDev.ExtraArg.new('--addtag', t)) _BlockDev.lvm.vgcreate(self.name, [p.devpath for p in self.pvs], 0, opts) for p in self.pvs: p._parseMeta() + self.created = True self.updateInfo() return() def createLV(self, lv_xml = None): + if not self.created: + raise RuntimeError('VG must be created before LVs can be added') # If lv_xml is None, we loop through our own XML. if lv_xml: lv = LV(lv_xml, self) lv.create() - self.lvs.append(lv) + # self.lvs.append(lv) else: for le in self.xml.findall('logicalVolumes/lv'): - pass + lv = LV(le, self) + lv.create() + # self.lvs.append(lv) self.updateInfo() return() @@ -162,6 +168,8 @@ class VG(object): return() def updateInfo(self): + if not self.created: + return() _info = _BlockDev.lvm.vginfo(self.name) # TODO: parity with lvm_fallback.VG.updateInfo # key names currently (probably) don't match and need to confirm the information's all present @@ -182,11 +190,78 @@ class LV(object): self.xml = lv_xml self.id = self.xml.attrib('id') self.name = self.xml.attrib('name') - self.size = self.xml.attrib('size') # Convert to bytes. Can get max from _BlockDev.lvm.vginfo().free - self.vg = vg_obj + self.size = self.xml.attrib('size') # Convert to bytes. Can get max from _BlockDev.lvm.vginfo().free TODO + self.vg = vgobj + self.pvs = [] if not isinstance(self.vg, VG): - raise ValueError('vg_obj must be of type aif.disk.lvm.VG') + raise ValueError('vgobj must be of type aif.disk.lvm.VG') _common.addBDPlugin('lvm') + self.info = None + self.devpath = '/dev/{0}/{1}'.format(self.vg.name, self.name) + self.created = False + self.updateInfo() + self._initLV() - self.devpath = None - pass + def _initLV(self): + self.pvs = [] + _indexed_pvs = {i.id: i for i in self.vg.pvs} + for pe in self.xml.findall('pvMember'): + pv_id = pe.attrib('source') + if pv_id in _indexed_pvs.keys(): + self.pvs.append(_indexed_pvs[pv_id]) + if not self.pvs: # We get all in the VG instead since none were explicitly assigned + self.pvs = self.vg.pvs + return() + + def create(self): + if not self.pvs: + raise RuntimeError('Cannot create LV with no associated LVs') + opts = [_BlockDev.ExtraArg.new('--reportformat', 'json')] + # FUCK. LVM. You can't *specify* a UUID. + # u = uuid.uuid4() + # opts.append(_BlockDev.ExtraArg.new('--uuid', str(u))) + # for t in self.tags: + # opts.append(_BlockDev.ExtraArg.new('--addtag', t)) + _BlockDev.lvm.lvcreate(self.vg.name, + self.name, + self.size, + None, + [i.devpath for i in self.pvs], + opts) + self.vg.lvs.append(self) + self.created = True + self.updateInfo() + self.vg.updateInfo() + return() + + def start(self): + _BlockDev.lvm.lvactivate(self.vg.name, + self.name, + True, + None) + self.updateInfo() + return() + + def stop(self): + _BlockDev.lvm.lvdeactivate(self.vg.name, + self.name, + None) + self.updateInfo() + return() + + def updateInfo(self): + if not self.created: + return() + _info = _BlockDev.lvm.lvinfo(self.vg.name, self.name) + # TODO: parity with lvm_fallback.LV.updateInfo + # key names currently (probably) don't match and need to confirm the information's all present + info = {} + for k in dir(_info): + if k.startswith('_'): + continue + elif k in ('copy',): + continue + v = getattr(_info, k) + info[k] = v + self.info = info + return() diff --git a/aif/disk/mdadm.py b/aif/disk/mdadm.py index 59f956b..501b1d0 100644 --- a/aif/disk/mdadm.py +++ b/aif/disk/mdadm.py @@ -104,11 +104,11 @@ class Array(object): self.layout = None # TODO: log.warn? else: self.layout = None - self.devname = self.xml.attrib['name'] - self.fulldevname = '{0}:{1}'.format(self.homehost, self.devname) + self.name = self.xml.attrib['name'] + self.fullname = '{0}:{1}'.format(self.homehost, self.name) self.devpath = devpath if not self.devpath: - self.devpath = '/dev/md/{0}'.format(self.devname) + self.devpath = '/dev/md/{0}'.format(self.name) self.updateStatus() self.homehost = homehost self.members = [] @@ -128,11 +128,11 @@ class Array(object): opts = [_BlockDev.ExtraArg.new('--homehost', self.homehost), _BlockDev.ExtraArg.new('--name', - self.devname)] + self.name)] if self.layout: opts.append(_BlockDev.ExtraArg.new('--layout', self.layout)) - _BlockDev.md.create(self.devname, + _BlockDev.md.create(self.name, str(self.level), [i.devpath for i in self.members], 0, @@ -154,7 +154,7 @@ class Array(object): if scan: target = None else: - target = self.devname + target = self.name _BlockDev.md.activate(target, [i.devpath for i in self.members], # Ignored if scan mode enabled None, @@ -164,12 +164,12 @@ class Array(object): return() def stop(self): - _BlockDev.md.deactivate(self.devname) + _BlockDev.md.deactivate(self.name) self.state = 'disassembled' return() def updateStatus(self): - _status = _BlockDev.md.detail(self.devname) + _status = _BlockDev.md.detail(self.name) # TODO: parity with mdadm_fallback.Array.updateStatus # key names currently (probably) don't match and need to confirm the information's all present info = {} diff --git a/aif/disk/mdadm_fallback.py b/aif/disk/mdadm_fallback.py index 88484cd..15686b3 100644 --- a/aif/disk/mdadm_fallback.py +++ b/aif/disk/mdadm_fallback.py @@ -158,10 +158,10 @@ class Array(object): self.layout = None # TODO: log.warn? else: self.layout = None - self.devname = self.xml.attrib['name'] + self.name = self.xml.attrib['name'] self.devpath = devpath if not self.devpath: - self.devpath = '/dev/md/{0}'.format(self.devname) + self.devpath = '/dev/md/{0}'.format(self.name) self.updateStatus() self.homehost = homehost self.members = [] @@ -179,7 +179,7 @@ class Array(object): if not self.members: raise RuntimeError('Cannot create an array with no members') cmd = ['mdadm', '--create', - '--name={0}'.format(self.devname), + '--name={0}'.format(self.name), '--bitmap=internal', '--level={0}'.format(self.level), '--metadata={0}'.format(self.metadata), @@ -224,7 +224,7 @@ class Array(object): def updateStatus(self): _info = mdstat.parse() for k, v in _info['devices'].items(): - if k != self.devname: + if k != self.name: del(_info['devices'][k]) self.info = copy.deepcopy(_info) return() diff --git a/examples/aif.xml b/examples/aif.xml index fe660d6..87e2fb4 100644 --- a/examples/aif.xml +++ b/examples/aif.xml @@ -31,15 +31,15 @@ + group, and then another LUKS volume - so plan accordingly and/or perform that in + a script instead. --> - + secrets1 @@ -63,7 +63,7 @@ - + @@ -88,7 +88,7 @@ seekrit - + diff --git a/examples/most_minimal.xml b/examples/most_minimal.xml new file mode 100644 index 0000000..a661a97 --- /dev/null +++ b/examples/most_minimal.xml @@ -0,0 +1,63 @@ + + + + + + + esp + + + root + + + + + + 32 + + + + + + + + + + + + +
dhcp
+
+ +
slaac
+
+
+ + 4.2.2.1 + 4.2.2.2 + 4.2.2.3 + +
+
+ + + en_US.UTF-8 + + + + + + + + + + + http://arch.mirror.square-r00t.net/$repo/os/$arch + + + +
+