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]
async def _guided_choice(self, choice): status = await self.app.wait_with_progress( self.endpoint.guided.POST(choice)) self.model = FilesystemModel(status.bootloader) self.model.load_server_data(status) if self.model.bootloader == Bootloader.PREP: self.supports_resilient_boot = False else: release = lsb_release()['release'] self.supports_resilient_boot = release >= '20.04' self.ui.set_body(FilesystemView(self.model, self))
async def make_ui_real(self, status): if status.status == ProbeStatus.FAILED: self.app.show_error_report(status.error_report) return ProbingFailed(self, status.error_report) self.model = FilesystemModel(status.bootloader) self.model.load_server_data(status) if self.model.bootloader == Bootloader.PREP: self.supports_resilient_boot = False else: release = lsb_release()['release'] self.supports_resilient_boot = release >= '20.04' if status.error_report: self.app.show_error_report(status.error_report) return GuidedDiskSelectionView(self)
def make_model_and_disk(): model = FilesystemModel(prober=None) disk = Disk.from_info( FakeStorageInfo(name='disk-name', size=100 * (2**30), free=50 * (2**30))) model._available_disks[disk.name] = disk return model, disk
def make_model(bootloader=None): model = FilesystemModel() if bootloader is not None: model.bootloader = bootloader return model
class FilesystemController(SubiquityTuiController, FilesystemManipulator): endpoint_name = 'storage' def __init__(self, app): super().__init__(app) self.model = None self.answers.setdefault('guided', False) self.answers.setdefault('guided-index', 0) self.answers.setdefault('manual', []) async def make_ui(self): status = await self.endpoint.guided.GET(MIN_SIZE_GUIDED) if status.status == ProbeStatus.PROBING: self.app.aio_loop.create_task(self._wait_for_probing()) return SlowProbing(self) else: return self.make_guided_ui(status) async def _wait_for_probing(self): status = await self.endpoint.guided.GET(MIN_SIZE_GUIDED, wait=True) if isinstance(self.ui.body, SlowProbing): self.ui.set_body(self.make_guided_ui(status)) def make_guided_ui(self, status): if status.status == ProbeStatus.FAILED: self.app.show_error_report(status.error_report) return ProbingFailed(self, status.error_report) if status.error_report: self.app.show_error_report(status.error_report) return GuidedDiskSelectionView(self, status.disks) async def run_answers(self): # Wait for probing to finish. while not isinstance(self.ui.body, GuidedDiskSelectionView): await asyncio.sleep(0.1) if self.answers['guided']: disk = self.ui.body.form.disks[self.answers['guided-index']] method = self.answers.get('guided-method') self.ui.body.form.guided_choice.value = { 'disk': disk, 'use_lvm': method == "lvm", } self.ui.body.done(self.ui.body.form) await self.app.confirm_install() while not isinstance(self.ui.body, FilesystemView): await asyncio.sleep(0.1) self.finish() elif self.answers['manual']: await self._guided_choice(None) await self._run_actions(self.answers['manual']) self.answers['manual'] = [] def _action_get(self, id): dev_spec = id[0].split() dev = None if dev_spec[0] == "disk": if dev_spec[1] == "index": dev = self.model.all_disks()[int(dev_spec[2])] elif dev_spec[1] == "serial": dev = self.model._one(type='disk', serial=dev_spec[2]) elif dev_spec[0] == "raid": if dev_spec[1] == "name": for r in self.model.all_raids(): if r.name == dev_spec[2]: dev = r break elif dev_spec[0] == "volgroup": if dev_spec[1] == "name": for r in self.model.all_volgroups(): if r.name == dev_spec[2]: dev = r break if dev is None: raise Exception("could not resolve {}".format(id)) if len(id) > 1: part, index = id[1].split() if part == "part": return dev.partitions()[int(index)] else: return dev raise Exception("could not resolve {}".format(id)) def _action_clean_devices_raid(self, devices): r = { self._action_get(d): v for d, v in zip(devices[::2], devices[1::2]) } for d in r: assert d.ok_for_raid return r def _action_clean_devices_vg(self, devices): r = {self._action_get(d): 'active' for d in devices} for d in r: assert d.ok_for_lvm_vg return r def _action_clean_level(self, level): return raidlevels_by_value[level] async def _answers_action(self, action): from subiquitycore.ui.stretchy import StretchyOverlay from subiquity.ui.views.filesystem.delete import ConfirmDeleteStretchy log.debug("_answers_action %r", action) if 'obj' in action: obj = self._action_get(action['obj']) action_name = action['action'] if action_name == "MAKE_BOOT": action_name = "TOGGLE_BOOT" meth = getattr(self.ui.body.avail_list, "_{}_{}".format(obj.type, action_name)) meth(obj) yield body = self.ui.body._w if not isinstance(body, StretchyOverlay): return if isinstance(body.stretchy, ConfirmDeleteStretchy): if action.get("submit", True): body.stretchy.done() else: async for _ in self._enter_form_data( body.stretchy.form, action['data'], action.get("submit", True)): pass elif action['action'] == 'create-raid': self.ui.body.create_raid() yield body = self.ui.body._w async for _ in self._enter_form_data(body.stretchy.form, action['data'], action.get("submit", True), clean_suffix='raid'): pass elif action['action'] == 'create-vg': self.ui.body.create_vg() yield body = self.ui.body._w async for _ in self._enter_form_data(body.stretchy.form, action['data'], action.get("submit", True), clean_suffix='vg'): pass elif action['action'] == 'done': if not self.ui.body.done.enabled: raise Exception("answers did not provide complete fs config") await self.app.confirm_install() self.finish() else: raise Exception("could not process action {}".format(action)) async def _guided_choice(self, choice): status = await self.app.wait_with_progress( self.endpoint.guided.POST(choice)) self.model = FilesystemModel(status.bootloader) self.model.load_server_data(status) if self.model.bootloader == Bootloader.PREP: self.supports_resilient_boot = False else: release = lsb_release()['release'] self.supports_resilient_boot = release >= '20.04' self.ui.set_body(FilesystemView(self.model, self)) def guided_choice(self, choice): self.app.aio_loop.create_task(self._guided_choice(choice)) async def _guided(self): self.ui.set_body(await self.make_ui()) def guided(self): self.app.aio_loop.create_task(self._guided()) def reset(self): log.info("Resetting Filesystem model") self.app.ui.block_input = True self.app.aio_loop.create_task(self._reset()) async def _reset(self): status = await self.endpoint.reset.POST() self.app.ui.block_input = False self.model.load_server_data(status) self.ui.set_body(FilesystemView(self.model, self)) def cancel(self): self.app.prev_screen() def finish(self): log.debug("FilesystemController.finish next_screen") self.app.next_screen(self.endpoint.POST(self.model._render_actions()))