Merge pull request #833 from mwhudson/zdev-view-changes
make zdev view/controller interface more client/server friendly
This commit is contained in:
commit
58d1f2f385
|
@ -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 = ''
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue