Remove defaults from some fields that should not have them

This required marking some "behind the scenes" attributes as init=False
(which makes some logical sense) and reordering some other attributes
(including "id" and "type", which are now added generically) to move
optional ones after mandatory ones.  Neither of these would be necessary
with a newer version of attrs (where we could use kw_only=True on the
class) but well, not too bad.

Leave Disk mostly alone for now because how they get created is going to
change completely with reusing partitions.
This commit is contained in:
Michael Hudson-Doyle 2019-05-13 12:53:41 +12:00
parent 2d18f8e4ac
commit 4c187a0afb
1 changed files with 40 additions and 50 deletions

View File

@ -68,10 +68,15 @@ def _remove_backlinks(obj):
setattr(vv, backlink, None) setattr(vv, backlink, None)
def fsobj(c): def fsobj(typ):
def wrapper(c):
c.__attrs_post_init__ = _set_backlinks c.__attrs_post_init__ = _set_backlinks
c.type = attributes.const(typ)
c.id = attributes.idfield(typ)
c._m = attr.ib(default=None) c._m = attr.ib(default=None)
return attr.s(cmp=False)(c) c = attr.s(cmp=False)(c)
return c
return wrapper
def dependencies(obj): def dependencies(obj):
@ -217,14 +222,14 @@ class attributes:
metadata = {'ref': True} metadata = {'ref': True}
if backlink: if backlink:
metadata['backlink'] = backlink metadata['backlink'] = backlink
return attr.ib(default=None, metadata=metadata) return attr.ib(metadata=metadata)
@staticmethod @staticmethod
def reflist(*, backlink=None): def reflist(*, backlink=None):
metadata = {'reflist': True} metadata = {'reflist': True}
if backlink: if backlink:
metadata['backlink'] = backlink metadata['backlink'] = backlink
return attr.ib(default=attr.Factory(set), metadata=metadata) return attr.ib(metadata=metadata)
@staticmethod @staticmethod
def const(value): def const(value):
@ -335,9 +340,9 @@ class _Formattable(ABC):
return [] return []
# Filesystem # Filesystem
_fs = attr.ib(default=None, repr=False) _fs = attr.ib(init=False, default=None, repr=False)
# Raid or LVM_VolGroup for now, but one day ZPool, BCache... # Raid or LVM_VolGroup for now, but one day ZPool, BCache...
_constructed_device = attr.ib(default=None, repr=False) _constructed_device = attr.ib(init=False, default=None, repr=False)
def _is_entirely_used(self): def _is_entirely_used(self):
return self._fs is not None or self._constructed_device is not None return self._fs is not None or self._constructed_device is not None
@ -395,7 +400,7 @@ class _Device(_Formattable, ABC):
pass pass
# [Partition] # [Partition]
_partitions = attr.ib(default=attr.Factory(list), repr=False) _partitions = attr.ib(init=False, default=attr.Factory(list), repr=False)
def partitions(self): def partitions(self):
return self._partitions return self._partitions
@ -472,11 +477,8 @@ class _Device(_Formattable, ABC):
return _generic_can_DELETE(self) return _generic_can_DELETE(self)
@fsobj @fsobj("disk")
class Disk(_Device): class Disk(_Device):
id = attributes.idfield("disk")
type = attributes.const("disk")
ptable = attr.ib(default=None) ptable = attr.ib(default=None)
serial = attr.ib(default=None) serial = attr.ib(default=None)
path = attr.ib(default=None) path = attr.ib(default=None)
@ -578,13 +580,11 @@ class Disk(_Device):
ok_for_raid = ok_for_lvm_vg = _can_FORMAT ok_for_raid = ok_for_lvm_vg = _can_FORMAT
@fsobj @fsobj("partition")
class Partition(_Formattable): class Partition(_Formattable):
id = attributes.idfield("part")
type = attributes.const("partition")
device = attributes.ref(backlink="_partitions") # Disk device = attributes.ref(backlink="_partitions") # Disk
size = attr.ib(default=None) size = attr.ib()
wipe = attr.ib(default=None) wipe = attr.ib(default=None)
flag = attr.ib(default=None) flag = attr.ib(default=None)
preserve = attr.ib(default=False) preserve = attr.ib(default=False)
@ -652,15 +652,14 @@ class Partition(_Formattable):
ok_for_lvm_vg = ok_for_raid ok_for_lvm_vg = ok_for_raid
@fsobj @fsobj("raid")
class Raid(_Device): class Raid(_Device):
id = attributes.idfield("raid") name = attr.ib()
type = attributes.const("raid") raidlevel = attr.ib() # raid0, raid1, raid5, raid6, raid10
preserve = attr.ib(default=False)
name = attr.ib(default=None)
raidlevel = attr.ib(default=None) # raid0, raid1, raid5, raid6, raid10
devices = attributes.reflist(backlink="_constructed_device") devices = attributes.reflist(backlink="_constructed_device")
spare_devices = attributes.reflist(backlink="_constructed_device") spare_devices = attributes.reflist(backlink="_constructed_device")
preserve = attr.ib(default=False)
ptable = attr.ib(default=None) ptable = attr.ib(default=None)
@property @property
@ -720,15 +719,13 @@ class Raid(_Device):
component_name = "component" component_name = "component"
@fsobj @fsobj("lvm_volgroup")
class LVM_VolGroup(_Device): class LVM_VolGroup(_Device):
name = attr.ib()
id = attributes.idfield("vg")
type = attributes.const("lvm_volgroup")
preserve = attr.ib(default=False)
name = attr.ib(default=None)
devices = attributes.reflist(backlink="_constructed_device") devices = attributes.reflist(backlink="_constructed_device")
preserve = attr.ib(default=False)
@property @property
def size(self): def size(self):
return get_lvm_size(self.devices) return get_lvm_size(self.devices)
@ -777,14 +774,12 @@ class LVM_VolGroup(_Device):
component_name = "PV" component_name = "PV"
@fsobj @fsobj("lvm_partition")
class LVM_LogicalVolume(_Formattable): class LVM_LogicalVolume(_Formattable):
name = attr.ib()
id = attributes.idfield("lv")
type = attributes.const("lvm_partition")
name = attr.ib(default=None)
volgroup = attributes.ref(backlink="_partitions") # LVM_VolGroup volgroup = attributes.ref(backlink="_partitions") # LVM_VolGroup
size = attr.ib(default=None) size = attr.ib()
preserve = attr.ib(default=False) preserve = attr.ib(default=False)
def serialize_size(self): def serialize_size(self):
@ -823,13 +818,12 @@ class LVM_LogicalVolume(_Formattable):
LUKS_OVERHEAD = 16*(2**20) LUKS_OVERHEAD = 16*(2**20)
@fsobj @fsobj("dm_crypt")
class DM_Crypt: class DM_Crypt:
id = attributes.idfield("crypt")
type = attributes.const("dm_crypt")
dm_name = attr.ib(default=None)
volume = attributes.ref(backlink="_constructed_device") # _Formattable volume = attributes.ref(backlink="_constructed_device") # _Formattable
key = attr.ib(default=None, repr=False) key = attr.ib(repr=False)
dm_name = attr.ib(default=None)
preserve = attr.ib(default=False) preserve = attr.ib(default=False)
_constructed_device = attr.ib(default=None, repr=False) _constructed_device = attr.ib(default=None, repr=False)
@ -842,13 +836,11 @@ class DM_Crypt:
return self.volume.size - LUKS_OVERHEAD return self.volume.size - LUKS_OVERHEAD
@fsobj @fsobj("format")
class Filesystem: class Filesystem:
fstype = attr.ib()
id = attributes.idfield("fs")
type = attributes.const("format")
fstype = attr.ib(default=None)
volume = attributes.ref(backlink="_fs") # _Formattable volume = attributes.ref(backlink="_fs") # _Formattable
label = attr.ib(default=None) label = attr.ib(default=None)
uuid = attr.ib(default=None) uuid = attr.ib(default=None)
preserve = attr.ib(default=False) preserve = attr.ib(default=False)
@ -866,12 +858,10 @@ class Filesystem:
return False return False
@fsobj @fsobj("mount")
class Mount: class Mount:
id = attributes.idfield("mount")
type = attributes.const("mount")
device = attributes.ref(backlink="_mount") # Filesystem device = attributes.ref(backlink="_mount") # Filesystem
path = attr.ib(default=None) path = attr.ib()
def can_delete(self): def can_delete(self):
# Can't delete mount of /boot/efi or swap, anything else is fine. # Can't delete mount of /boot/efi or swap, anything else is fine.