make zdev view/controller interface more client/server friendly

This commit is contained in:
Michael Hudson-Doyle 2020-09-21 17:06:30 +12:00
parent d92c8e862a
commit 7d02ee17f6
4 changed files with 72 additions and 64 deletions

View File

@ -19,6 +19,7 @@
import datetime
import enum
import shlex
from typing import List, Optional
import attr
@ -31,6 +32,34 @@ class KeyboardSetting:
toggle: Optional[str] = None
@attr.s(auto_attribs=True)
class ZdevInfo:
id: str
type: str
on: bool
exists: bool
pers: bool
auto: bool
failed: bool
names: str
@classmethod
def from_row(cls, row):
row = dict((k.split('=', 1) for k in shlex.split(row)))
for k, v in row.items():
if v == "yes":
row[k] = True
if v == "no":
row[k] = False
return ZdevInfo(**row)
@property
def typeclass(self):
if self.type.startswith('zfcp'):
return 'zfcp'
return self.type
@attr.s(auto_attribs=True)
class IdentityData:
realname: str = ''

View File

@ -13,17 +13,19 @@
# 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/>.
import attr
import asyncio
import logging
import platform
import shlex
import random
from collections import OrderedDict
from urwid import Text
from subiquitycore.ui.utils import Color
from subiquitycore.utils import run_command
from subiquitycore.tuicontroller import (
Skip,
)
from subiquitycore.utils import arun_command, run_command
from subiquity.common.types import ZdevInfo
from subiquity.controller import SubiquityTuiController
from subiquity.ui.views import ZdevView
@ -590,47 +592,6 @@ id="0.0.f1fe:0.0.f1ff" type="ctc" on="no" exists="yes" pers="no" auto="no" faile
id="0.0.c0fe" type="generic-ccw" on="no" exists="yes" pers="no" auto="no" failed="yes" names=""''' # noqa: E501
@attr.s
class ZdevInfo:
id = attr.ib()
type = attr.ib()
on = attr.ib()
exists = attr.ib()
pers = attr.ib()
auto = attr.ib()
failed = attr.ib()
names = attr.ib()
@classmethod
def from_row(cls, row):
row = dict((k.split('=', 1) for k in shlex.split(row)))
for k, v in row.items():
if v == "yes":
row[k] = True
if v == "no":
row[k] = False
return ZdevInfo(**row)
@property
def status(self):
if self.failed:
# for translator: failed is a zdev device status
return Color.info_error(Text(_("failed"), align="center"))
if self.auto and self.on:
# for translator: auto is a zdev device status
return Color.info_minor(Text(_("auto"), align="center"))
if self.pers and self.on:
# for translator: online is a zdev device status
return Text(_("online"), align="center")
return Text("", align="center")
@property
def typeclass(self):
if self.type.startswith('zfcp'):
return 'zfcp'
return self.type
class ZdevController(SubiquityTuiController):
def __init__(self, app):
@ -645,7 +606,10 @@ class ZdevController(SubiquityTuiController):
self.zdevinfos = OrderedDict([(i.id, i) for i in zdevinfos])
def make_ui(self):
self.ui.set_body(ZdevView(self))
if not self.app.opts.bootloader == 'none' \
and platform.machine() != 's390x':
raise Skip
return ZdevView(self, self.get_zdevinfos())
def run_answers(self):
if 'accept-default' in self.answers:
@ -658,14 +622,16 @@ class ZdevController(SubiquityTuiController):
# switch to next screen
self.app.next_screen()
def chzdev(self, action, zdevinfo):
async def chzdev(self, action, zdevinfo):
if self.opts.dry_run:
await asyncio.sleep(random.random()*0.4)
on = action == 'enable'
self.zdevinfos[zdevinfo.id].on = on
self.zdevinfos[zdevinfo.id].pers = on
else:
chzdev_cmd = ['chzdev', '--%s' % action, zdevinfo.id]
run_command(chzdev_cmd)
await arun_command(chzdev_cmd)
return self.get_zdevinfos()
def get_zdevinfos(self):
if self.opts.dry_run:

View File

@ -50,6 +50,19 @@ from subiquitycore.view import BaseView
log = logging.getLogger('subiquity.ui.zdev')
def status(zdevinfo):
if zdevinfo.failed:
# for translator: failed is a zdev device status
return Color.info_error(Text(_("failed"), align="center"))
if zdevinfo.auto and zdevinfo.on:
# for translator: auto is a zdev device status
return Color.info_minor(Text(_("auto"), align="center"))
if zdevinfo.pers and zdevinfo.on:
# for translator: online is a zdev device status
return Text(_("online"), align="center")
return Text("", align="center")
class ZdevList(WidgetWrap):
def __init__(self, parent):
@ -64,14 +77,16 @@ class ZdevList(WidgetWrap):
Text(_("No zdev devices found.")))
super().__init__(self.table)
def _zdev_action(self, sender, action, zdevinfo):
if action in ('disable', 'enable'):
self.parent.controller.chzdev(action, zdevinfo)
self.parent.refresh_model_inputs()
async def _zdev_action(self, action, zdevinfo):
new_zdevinfos = await self.parent.controller.app.wait_with_text_dialog(
self.parent.controller.chzdev(action, zdevinfo), "Updating...")
self.update(new_zdevinfos)
def refresh_model_inputs(self):
zdevinfos = self.parent.controller.get_zdevinfos()
def zdev_action(self, sender, action, zdevinfo):
self.parent.controller.app.aio_loop.create_task(
self._zdev_action(action, zdevinfo))
def update(self, zdevinfos):
rows = [TableRow([
Color.info_minor(heading) for heading in [
Text(_("ID")),
@ -95,7 +110,7 @@ class ZdevList(WidgetWrap):
if zdevinfo.type == 'zfcp-lun':
rows.append(TableRow([
Color.info_minor(Text(zdevinfo.id[9:])),
zdevinfo.status,
status(zdevinfo),
Text(zdevinfo.names),
]))
continue
@ -103,10 +118,10 @@ class ZdevList(WidgetWrap):
actions = [(_("Enable"), not zdevinfo.on, 'enable'),
(_("Disable"), zdevinfo.on, 'disable')]
menu = ActionMenu(actions)
connect_signal(menu, 'action', self._zdev_action, zdevinfo)
connect_signal(menu, 'action', self.zdev_action, zdevinfo)
cells = [
Text(zdevinfo.id),
zdevinfo.status,
status(zdevinfo),
Text(zdevinfo.names),
menu,
]
@ -128,16 +143,16 @@ class ZdevList(WidgetWrap):
class ZdevView(BaseView):
title = _("Zdev setup")
def __init__(self, controller):
def __init__(self, controller, zdevinfos):
log.debug('FileSystemView init start()')
self.controller = controller
self.zdev_list = ZdevList(self)
self.zdev_list.update(zdevinfos)
frame = screen(
self.zdev_list, self._build_buttons(),
focus_buttons=False)
super().__init__(frame)
self.refresh_model_inputs()
# Prevent urwid from putting the first focused widget at the
# very top of the display (obscuring the headings)
self.zdev_list._w._w.base_widget.set_focus_valign("bottom")
@ -148,9 +163,6 @@ class ZdevView(BaseView):
back_btn(_("Back"), on_press=self.cancel),
]
def refresh_model_inputs(self):
self.zdev_list.refresh_model_inputs()
def cancel(self, button=None):
self.controller.cancel()

View File

@ -184,7 +184,8 @@ class TuiApplication(Application):
def hide_load():
ld.close()
await self._wait_with_indication(awaitable, show_load, hide_load)
return await self._wait_with_indication(
awaitable, show_load, hide_load)
async def _move_screen(self, increment, coro):
if coro is not None: