support for editing existing partitions
This commit is contained in:
parent
620d7b1973
commit
628758811e
|
@ -267,7 +267,11 @@ class FilesystemController(BaseController):
|
||||||
|
|
||||||
def create_filesystem(self, volume, spec):
|
def create_filesystem(self, volume, spec):
|
||||||
if spec['fstype'] is None:
|
if spec['fstype'] is None:
|
||||||
|
fs = volume.original_fs()
|
||||||
|
if fs is None:
|
||||||
return
|
return
|
||||||
|
self.model.readd_filesystem(fs)
|
||||||
|
else:
|
||||||
fs = self.model.add_filesystem(volume, spec['fstype'])
|
fs = self.model.add_filesystem(volume, spec['fstype'])
|
||||||
if isinstance(volume, Partition):
|
if isinstance(volume, Partition):
|
||||||
if spec['fstype'] == "swap":
|
if spec['fstype'] == "swap":
|
||||||
|
@ -390,6 +394,7 @@ class FilesystemController(BaseController):
|
||||||
log.debug('disk.freespace: {}'.format(disk.free_for_partitions))
|
log.debug('disk.freespace: {}'.format(disk.free_for_partitions))
|
||||||
|
|
||||||
if partition is not None:
|
if partition is not None:
|
||||||
|
if 'size' in spec:
|
||||||
partition.size = align_up(spec['size'])
|
partition.size = align_up(spec['size'])
|
||||||
if disk.free_for_partitions < 0:
|
if disk.free_for_partitions < 0:
|
||||||
raise Exception("partition size too large")
|
raise Exception("partition size too large")
|
||||||
|
@ -420,7 +425,9 @@ class FilesystemController(BaseController):
|
||||||
log.debug('vg.freespace: {}'.format(vg.free_for_partitions))
|
log.debug('vg.freespace: {}'.format(vg.free_for_partitions))
|
||||||
|
|
||||||
if lv is not None:
|
if lv is not None:
|
||||||
|
if 'name' in spec:
|
||||||
lv.name = spec['name']
|
lv.name = spec['name']
|
||||||
|
if 'size' in spec:
|
||||||
lv.size = align_up(spec['size'])
|
lv.size = align_up(spec['size'])
|
||||||
if vg.free_for_partitions < 0:
|
if vg.free_for_partitions < 0:
|
||||||
raise Exception("lv size too large")
|
raise Exception("lv size too large")
|
||||||
|
|
|
@ -389,6 +389,7 @@ class _Formattable(ABC):
|
||||||
|
|
||||||
# Filesystem
|
# Filesystem
|
||||||
_fs = attributes.backlink()
|
_fs = attributes.backlink()
|
||||||
|
_original_fs = attributes.backlink()
|
||||||
# Raid or LVM_VolGroup for now, but one day ZPool, BCache...
|
# Raid or LVM_VolGroup for now, but one day ZPool, BCache...
|
||||||
_constructed_device = attributes.backlink()
|
_constructed_device = attributes.backlink()
|
||||||
|
|
||||||
|
@ -420,6 +421,9 @@ class _Formattable(ABC):
|
||||||
def fs(self):
|
def fs(self):
|
||||||
return self._fs
|
return self._fs
|
||||||
|
|
||||||
|
def original_fs(self):
|
||||||
|
return self._original_fs
|
||||||
|
|
||||||
def constructed_device(self, skip_dm_crypt=True):
|
def constructed_device(self, skip_dm_crypt=True):
|
||||||
cd = self._constructed_device
|
cd = self._constructed_device
|
||||||
if cd is None:
|
if cd is None:
|
||||||
|
@ -937,6 +941,9 @@ class Filesystem:
|
||||||
def _available(self):
|
def _available(self):
|
||||||
# False if mounted or if fs does not require a mount, True otherwise.
|
# False if mounted or if fs does not require a mount, True otherwise.
|
||||||
if self._mount is None:
|
if self._mount is None:
|
||||||
|
if self.preserve:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
return FilesystemModel.is_mounted_filesystem(self.fstype)
|
return FilesystemModel.is_mounted_filesystem(self.fstype)
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
@ -1044,6 +1051,8 @@ class FilesystemModel(object):
|
||||||
kw['info'] = StorageInfo({path: blockdevs[path]})
|
kw['info'] = StorageInfo({path: blockdevs[path]})
|
||||||
kw['preserve'] = True
|
kw['preserve'] = True
|
||||||
obj = byid[action['id']] = c(m=self, **kw)
|
obj = byid[action['id']] = c(m=self, **kw)
|
||||||
|
if action['type'] == "format":
|
||||||
|
obj.volume._original_fs = obj
|
||||||
objs.append(obj)
|
objs.append(obj)
|
||||||
|
|
||||||
# We filter out anything that can be reached from a currently
|
# We filter out anything that can be reached from a currently
|
||||||
|
@ -1267,6 +1276,10 @@ class FilesystemModel(object):
|
||||||
self._actions.append(fs)
|
self._actions.append(fs)
|
||||||
return fs
|
return fs
|
||||||
|
|
||||||
|
def readd_filesystem(self, fs):
|
||||||
|
_set_backlinks(fs)
|
||||||
|
self._actions.append(fs)
|
||||||
|
|
||||||
def remove_filesystem(self, fs):
|
def remove_filesystem(self, fs):
|
||||||
if fs._mount:
|
if fs._mount:
|
||||||
raise Exception("can only remove unmounted filesystem")
|
raise Exception("can only remove unmounted filesystem")
|
||||||
|
|
|
@ -62,9 +62,18 @@ class FSTypeField(FormField):
|
||||||
('btrfs', True),
|
('btrfs', True),
|
||||||
('---', False),
|
('---', False),
|
||||||
('swap', True),
|
('swap', True),
|
||||||
('---', False),
|
|
||||||
('leave unformatted', True, None),
|
|
||||||
]
|
]
|
||||||
|
if form.existing_fs_type is None:
|
||||||
|
options = options + [
|
||||||
|
('---', False),
|
||||||
|
(_('Leave unformatted'), True, None),
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
label = _('Leave formatted as {}').format(form.existing_fs_type)
|
||||||
|
options = [
|
||||||
|
(label, True, None),
|
||||||
|
('---', False),
|
||||||
|
] + options
|
||||||
sel = Selector(opts=options)
|
sel = Selector(opts=options)
|
||||||
sel.value = None
|
sel.value = None
|
||||||
return sel
|
return sel
|
||||||
|
@ -128,8 +137,14 @@ LVNameField = simple_field(LVNameEditor)
|
||||||
|
|
||||||
class PartitionForm(Form):
|
class PartitionForm(Form):
|
||||||
|
|
||||||
def __init__(self, model, max_size, initial, lvm_names):
|
def __init__(self, model, max_size, initial, lvm_names, device):
|
||||||
self.model = model
|
self.model = model
|
||||||
|
self.device = device
|
||||||
|
self.existing_fs_type = None
|
||||||
|
if device:
|
||||||
|
existing_fs = device.original_fs()
|
||||||
|
if existing_fs:
|
||||||
|
self.existing_fs_type = existing_fs.fstype
|
||||||
initial_path = initial.get('mount')
|
initial_path = initial.get('mount')
|
||||||
self.mountpoints = {
|
self.mountpoints = {
|
||||||
m.path: m.device.volume for m in self.model.all_mounts()
|
m.path: m.device.volume for m in self.model.all_mounts()
|
||||||
|
@ -146,6 +161,8 @@ class PartitionForm(Form):
|
||||||
self.select_fstype(None, self.fstype.widget.value)
|
self.select_fstype(None, self.fstype.widget.value)
|
||||||
|
|
||||||
def select_fstype(self, sender, fstype):
|
def select_fstype(self, sender, fstype):
|
||||||
|
if fstype is None:
|
||||||
|
fstype = self.existing_fs_type
|
||||||
self.mount.enabled = self.model.is_mounted_filesystem(fstype)
|
self.mount.enabled = self.model.is_mounted_filesystem(fstype)
|
||||||
|
|
||||||
name = LVNameField(_("Name: "))
|
name = LVNameField(_("Name: "))
|
||||||
|
@ -253,7 +270,9 @@ class PartitionStretchy(Stretchy):
|
||||||
max_size += self.partition.size
|
max_size += self.partition.size
|
||||||
fs = self.partition.fs()
|
fs = self.partition.fs()
|
||||||
if fs is not None:
|
if fs is not None:
|
||||||
if partition.flag != "boot":
|
if fs.preserve:
|
||||||
|
initial['fstype'] = None
|
||||||
|
elif partition.flag != "boot":
|
||||||
initial['fstype'] = fs.fstype
|
initial['fstype'] = fs.fstype
|
||||||
if self.model.is_mounted_filesystem(fs.fstype):
|
if self.model.is_mounted_filesystem(fs.fstype):
|
||||||
mount = fs.mount()
|
mount = fs.mount()
|
||||||
|
@ -275,7 +294,8 @@ class PartitionStretchy(Stretchy):
|
||||||
x += 1
|
x += 1
|
||||||
initial['name'] = name
|
initial['name'] = name
|
||||||
|
|
||||||
self.form = PartitionForm(self.model, max_size, initial, lvm_names)
|
self.form = PartitionForm(
|
||||||
|
self.model, max_size, initial, lvm_names, partition)
|
||||||
|
|
||||||
if not isinstance(disk, LVM_VolGroup):
|
if not isinstance(disk, LVM_VolGroup):
|
||||||
self.form.remove_field('name')
|
self.form.remove_field('name')
|
||||||
|
@ -297,6 +317,9 @@ class PartitionStretchy(Stretchy):
|
||||||
self.form.mount.enabled = False
|
self.form.mount.enabled = False
|
||||||
self.form.fstype.enabled = False
|
self.form.fstype.enabled = False
|
||||||
self.form.size.enabled = False
|
self.form.size.enabled = False
|
||||||
|
if partition.preserve:
|
||||||
|
self.form.name.enabled = False
|
||||||
|
self.form.size.enabled = False
|
||||||
|
|
||||||
connect_signal(self.form, 'submit', self.done)
|
connect_signal(self.form, 'submit', self.done)
|
||||||
connect_signal(self.form, 'cancel', self.cancel)
|
connect_signal(self.form, 'cancel', self.cancel)
|
||||||
|
@ -373,6 +396,10 @@ class FormatEntireStretchy(Stretchy):
|
||||||
initial = {}
|
initial = {}
|
||||||
fs = device.fs()
|
fs = device.fs()
|
||||||
if fs is not None:
|
if fs is not None:
|
||||||
|
if fs.preserve:
|
||||||
|
initial['fstype'] = None
|
||||||
|
else:
|
||||||
|
initial['fstype'] = fs.fstype
|
||||||
initial['fstype'] = fs.fstype
|
initial['fstype'] = fs.fstype
|
||||||
if self.model.is_mounted_filesystem(fs.fstype):
|
if self.model.is_mounted_filesystem(fs.fstype):
|
||||||
mount = fs.mount()
|
mount = fs.mount()
|
||||||
|
@ -380,7 +407,7 @@ class FormatEntireStretchy(Stretchy):
|
||||||
initial['mount'] = mount.path
|
initial['mount'] = mount.path
|
||||||
elif not isinstance(device, Disk):
|
elif not isinstance(device, Disk):
|
||||||
initial['fstype'] = 'ext4'
|
initial['fstype'] = 'ext4'
|
||||||
self.form = PartitionForm(self.model, 0, initial, None)
|
self.form = PartitionForm(self.model, 0, initial, None, device)
|
||||||
self.form.remove_field('size')
|
self.form.remove_field('size')
|
||||||
self.form.remove_field('name')
|
self.form.remove_field('name')
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,26 @@ class PartitionViewTests(unittest.TestCase):
|
||||||
view.controller.partition_disk_handler.assert_called_once_with(
|
view.controller.partition_disk_handler.assert_called_once_with(
|
||||||
stretchy.disk, stretchy.partition, expected_data)
|
stretchy.disk, stretchy.partition, expected_data)
|
||||||
|
|
||||||
|
def test_edit_existing_partition(self):
|
||||||
|
form_data = {
|
||||||
|
'fstype': "xfs",
|
||||||
|
}
|
||||||
|
model, disk = make_model_and_disk()
|
||||||
|
partition = model.add_partition(disk, 512*(2**20))
|
||||||
|
partition.preserve = True
|
||||||
|
model.add_filesystem(partition, "ext4")
|
||||||
|
view, stretchy = make_view(model, disk, partition)
|
||||||
|
self.assertFalse(stretchy.form.size.enabled)
|
||||||
|
self.assertTrue(stretchy.form.done_btn.enabled)
|
||||||
|
view_helpers.enter_data(stretchy.form, form_data)
|
||||||
|
view_helpers.click(stretchy.form.done_btn.base_widget)
|
||||||
|
expected_data = {
|
||||||
|
'fstype': 'xfs',
|
||||||
|
'mount': None,
|
||||||
|
}
|
||||||
|
view.controller.partition_disk_handler.assert_called_once_with(
|
||||||
|
stretchy.disk, stretchy.partition, expected_data)
|
||||||
|
|
||||||
def test_edit_boot_partition(self):
|
def test_edit_boot_partition(self):
|
||||||
form_data = {
|
form_data = {
|
||||||
'size': "256M",
|
'size': "256M",
|
||||||
|
|
|
@ -82,4 +82,6 @@ def get_focus_path(w):
|
||||||
|
|
||||||
def enter_data(form, data):
|
def enter_data(form, data):
|
||||||
for k, v in data.items():
|
for k, v in data.items():
|
||||||
getattr(form, k).value = v
|
bf = getattr(form, k)
|
||||||
|
assert bf.enabled, "%s is not enabled" % (k,)
|
||||||
|
bf.value = v
|
||||||
|
|
Loading…
Reference in New Issue