Merge pull request #474 from mwhudson/fs-action-labels

Introduce the idea of filesystem action annotations
This commit is contained in:
Dimitri John Ledkov 2019-05-10 13:47:50 +01:00 committed by GitHub
commit 1b3a23f93d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 89 additions and 25 deletions

View File

@ -320,6 +320,15 @@ class _Formattable(ABC):
# Base class for anything that can be formatted and mounted, # Base class for anything that can be formatted and mounted,
# e.g. a disk or a RAID or a partition. # e.g. a disk or a RAID or a partition.
@property
@abstractmethod
def label(self):
pass
@property
def annotations(self):
return []
# Filesystem # Filesystem
_fs = attr.ib(default=None, repr=False) _fs = attr.ib(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...
@ -564,6 +573,17 @@ class Partition(_Formattable):
flag = attr.ib(default=None) flag = attr.ib(default=None)
preserve = attr.ib(default=False) preserve = attr.ib(default=False)
@property
def annotations(self):
r = super().annotations
if self.flag == "prep":
r.append("PReP")
elif self.flag == "boot":
r.append("ESP")
elif self.flag == "bios_grub":
r.append("bios_grub")
return r
def desc(self): def desc(self):
return _("partition of {}").format(self.device.desc()) return _("partition of {}").format(self.device.desc())
@ -701,6 +721,14 @@ class LVM_VolGroup(_Device):
def free_for_partitions(self): def free_for_partitions(self):
return self.size - self.used return self.size - self.used
@property
def annotations(self):
r = super().annotations
member = next(iter(self.devices))
if member.type == "dm_crypt":
r.append("encrypted")
return r
@property @property
def label(self): def label(self):
return self.name return self.name

View File

@ -1,5 +1,26 @@
# Copyright 2019 Canonical, Ltd.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from collections import namedtuple
import unittest import unittest
from subiquity.models.filesystem import dehumanize_size, humanize_size
from subiquity.models.filesystem import (
dehumanize_size,
FilesystemModel,
humanize_size,
)
class TestHumanizeSize(unittest.TestCase): class TestHumanizeSize(unittest.TestCase):
@ -78,3 +99,30 @@ class TestDehumanizeSize(unittest.TestCase):
self.fail( self.fail(
"dehumanize_size({!r}) did not error".format(input)) "dehumanize_size({!r}) did not error".format(input))
self.assertEqual(expected_error, actual_error) self.assertEqual(expected_error, actual_error)
FakeStorageInfo = namedtuple(
'FakeStorageInfo', ['name', 'size', 'free', 'serial', 'model'])
FakeStorageInfo.__new__.__defaults__ = (None,) * len(FakeStorageInfo._fields)
def make_model_and_disk():
model = FilesystemModel()
model._disk_info.append(FakeStorageInfo(
name='disk-name', size=100*(2**30), free=50*(2**30)))
model.reset()
return model, model._actions[0]
class TestFilesystemModel(unittest.TestCase):
def test_vg_default_annotations(self):
model, disk = make_model_and_disk()
vg = model.add_volgroup('vg-0', {disk})
self.assertEqual(vg.annotations, [])
def test_vg_encrypted_annotations(self):
model, disk = make_model_and_disk()
dm_crypt = model.add_dm_crypt(disk, key='passw0rd')
vg = model.add_volgroup('vg-0', {dm_crypt})
self.assertEqual(vg.annotations, ['encrypted'])

View File

@ -407,10 +407,8 @@ class DeviceList(WidgetWrap):
for device in devices: for device in devices:
menu = self._action_menu_for_device(device) menu = self._action_menu_for_device(device)
label = device.label label = device.label
if device.type == "lvm_volgroup": if device.annotations:
member = next(iter(device.devices)) label = "{} ({})".format(label, ", ".join(device.annotations))
if member.type == "dm_crypt":
label += _(" (encrypted)")
cells = [ cells = [
Text("["), Text("["),
Text(label), Text(label),
@ -437,9 +435,13 @@ class DeviceList(WidgetWrap):
part_size = "{:>9} ({}%)".format( part_size = "{:>9} ({}%)".format(
humanize_size(part.size), humanize_size(part.size),
int(100 * part.size / device.size)) int(100 * part.size / device.size))
part_label = part.short_label
if part.annotations:
part_label = "{} ({})".format(
part_label, ", ".join(part.annotations))
cells = [ cells = [
Text("["), Text("["),
Text(" " + part.short_label), Text(" " + part_label),
(2, Text(part_size)), (2, Text(part_size)),
menu, menu,
Text("]"), Text("]"),
@ -447,12 +449,10 @@ class DeviceList(WidgetWrap):
row = make_action_menu_row(cells, menu, cursor_x=4) row = make_action_menu_row(cells, menu, cursor_x=4)
rows.append(row) rows.append(row)
if part.flag in ["bios_grub", "prep"]: if part.flag in ["bios_grub", "prep"]:
label = part.flag continue
else:
label = _usage_label(part)
rows.append(TableRow([ rows.append(TableRow([
Text(""), Text(""),
(3, Text(" " + label)), (3, Text(" " + _usage_label(part))),
Text(""), Text(""),
Text(""), Text(""),
])) ]))

View File

@ -1,6 +1,5 @@
import unittest import unittest
from unittest import mock from unittest import mock
from collections import namedtuple
import urwid import urwid
@ -10,24 +9,13 @@ from subiquitycore.view import BaseView
from subiquity.controllers.filesystem import FilesystemController from subiquity.controllers.filesystem import FilesystemController
from subiquity.models.filesystem import ( from subiquity.models.filesystem import (
dehumanize_size, dehumanize_size,
FilesystemModel, )
from subiquity.models.tests.test_filesystem import (
make_model_and_disk,
) )
from subiquity.ui.views.filesystem.partition import PartitionStretchy from subiquity.ui.views.filesystem.partition import PartitionStretchy
FakeStorageInfo = namedtuple(
'FakeStorageInfo', ['name', 'size', 'free', 'serial', 'model'])
FakeStorageInfo.__new__.__defaults__ = (None,) * len(FakeStorageInfo._fields)
def make_model_and_disk():
model = FilesystemModel()
model._disk_info.append(FakeStorageInfo(
name='disk-name', size=100*(2**30), free=50*(2**30)))
model.reset()
return model, model._actions[0]
def make_view(model, disk, partition=None): def make_view(model, disk, partition=None):
controller = mock.create_autospec(spec=FilesystemController) controller = mock.create_autospec(spec=FilesystemController)
base_view = BaseView(urwid.Text("")) base_view = BaseView(urwid.Text(""))