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 datetime
|
||||||
import enum
|
import enum
|
||||||
|
import shlex
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
|
@ -31,6 +32,34 @@ class KeyboardSetting:
|
||||||
toggle: Optional[str] = None
|
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)
|
@attr.s(auto_attribs=True)
|
||||||
class IdentityData:
|
class IdentityData:
|
||||||
realname: str = ''
|
realname: str = ''
|
||||||
|
|
|
@ -13,17 +13,19 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import attr
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import platform
|
import platform
|
||||||
import shlex
|
import random
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from urwid import Text
|
|
||||||
|
|
||||||
from subiquitycore.ui.utils import Color
|
from subiquitycore.tuicontroller import (
|
||||||
from subiquitycore.utils import run_command
|
Skip,
|
||||||
|
)
|
||||||
|
from subiquitycore.utils import arun_command, run_command
|
||||||
|
|
||||||
|
from subiquity.common.types import ZdevInfo
|
||||||
from subiquity.controller import SubiquityTuiController
|
from subiquity.controller import SubiquityTuiController
|
||||||
from subiquity.ui.views import ZdevView
|
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
|
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):
|
class ZdevController(SubiquityTuiController):
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
|
@ -645,7 +606,10 @@ class ZdevController(SubiquityTuiController):
|
||||||
self.zdevinfos = OrderedDict([(i.id, i) for i in zdevinfos])
|
self.zdevinfos = OrderedDict([(i.id, i) for i in zdevinfos])
|
||||||
|
|
||||||
def make_ui(self):
|
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):
|
def run_answers(self):
|
||||||
if 'accept-default' in self.answers:
|
if 'accept-default' in self.answers:
|
||||||
|
@ -658,14 +622,16 @@ class ZdevController(SubiquityTuiController):
|
||||||
# switch to next screen
|
# switch to next screen
|
||||||
self.app.next_screen()
|
self.app.next_screen()
|
||||||
|
|
||||||
def chzdev(self, action, zdevinfo):
|
async def chzdev(self, action, zdevinfo):
|
||||||
if self.opts.dry_run:
|
if self.opts.dry_run:
|
||||||
|
await asyncio.sleep(random.random()*0.4)
|
||||||
on = action == 'enable'
|
on = action == 'enable'
|
||||||
self.zdevinfos[zdevinfo.id].on = on
|
self.zdevinfos[zdevinfo.id].on = on
|
||||||
self.zdevinfos[zdevinfo.id].pers = on
|
self.zdevinfos[zdevinfo.id].pers = on
|
||||||
else:
|
else:
|
||||||
chzdev_cmd = ['chzdev', '--%s' % action, zdevinfo.id]
|
chzdev_cmd = ['chzdev', '--%s' % action, zdevinfo.id]
|
||||||
run_command(chzdev_cmd)
|
await arun_command(chzdev_cmd)
|
||||||
|
return self.get_zdevinfos()
|
||||||
|
|
||||||
def get_zdevinfos(self):
|
def get_zdevinfos(self):
|
||||||
if self.opts.dry_run:
|
if self.opts.dry_run:
|
||||||
|
|
|
@ -50,6 +50,19 @@ from subiquitycore.view import BaseView
|
||||||
log = logging.getLogger('subiquity.ui.zdev')
|
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):
|
class ZdevList(WidgetWrap):
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
|
@ -64,14 +77,16 @@ class ZdevList(WidgetWrap):
|
||||||
Text(_("No zdev devices found.")))
|
Text(_("No zdev devices found.")))
|
||||||
super().__init__(self.table)
|
super().__init__(self.table)
|
||||||
|
|
||||||
def _zdev_action(self, sender, action, zdevinfo):
|
async def _zdev_action(self, action, zdevinfo):
|
||||||
if action in ('disable', 'enable'):
|
new_zdevinfos = await self.parent.controller.app.wait_with_text_dialog(
|
||||||
self.parent.controller.chzdev(action, zdevinfo)
|
self.parent.controller.chzdev(action, zdevinfo), "Updating...")
|
||||||
self.parent.refresh_model_inputs()
|
self.update(new_zdevinfos)
|
||||||
|
|
||||||
def refresh_model_inputs(self):
|
def zdev_action(self, sender, action, zdevinfo):
|
||||||
zdevinfos = self.parent.controller.get_zdevinfos()
|
self.parent.controller.app.aio_loop.create_task(
|
||||||
|
self._zdev_action(action, zdevinfo))
|
||||||
|
|
||||||
|
def update(self, zdevinfos):
|
||||||
rows = [TableRow([
|
rows = [TableRow([
|
||||||
Color.info_minor(heading) for heading in [
|
Color.info_minor(heading) for heading in [
|
||||||
Text(_("ID")),
|
Text(_("ID")),
|
||||||
|
@ -95,7 +110,7 @@ class ZdevList(WidgetWrap):
|
||||||
if zdevinfo.type == 'zfcp-lun':
|
if zdevinfo.type == 'zfcp-lun':
|
||||||
rows.append(TableRow([
|
rows.append(TableRow([
|
||||||
Color.info_minor(Text(zdevinfo.id[9:])),
|
Color.info_minor(Text(zdevinfo.id[9:])),
|
||||||
zdevinfo.status,
|
status(zdevinfo),
|
||||||
Text(zdevinfo.names),
|
Text(zdevinfo.names),
|
||||||
]))
|
]))
|
||||||
continue
|
continue
|
||||||
|
@ -103,10 +118,10 @@ class ZdevList(WidgetWrap):
|
||||||
actions = [(_("Enable"), not zdevinfo.on, 'enable'),
|
actions = [(_("Enable"), not zdevinfo.on, 'enable'),
|
||||||
(_("Disable"), zdevinfo.on, 'disable')]
|
(_("Disable"), zdevinfo.on, 'disable')]
|
||||||
menu = ActionMenu(actions)
|
menu = ActionMenu(actions)
|
||||||
connect_signal(menu, 'action', self._zdev_action, zdevinfo)
|
connect_signal(menu, 'action', self.zdev_action, zdevinfo)
|
||||||
cells = [
|
cells = [
|
||||||
Text(zdevinfo.id),
|
Text(zdevinfo.id),
|
||||||
zdevinfo.status,
|
status(zdevinfo),
|
||||||
Text(zdevinfo.names),
|
Text(zdevinfo.names),
|
||||||
menu,
|
menu,
|
||||||
]
|
]
|
||||||
|
@ -128,16 +143,16 @@ class ZdevList(WidgetWrap):
|
||||||
class ZdevView(BaseView):
|
class ZdevView(BaseView):
|
||||||
title = _("Zdev setup")
|
title = _("Zdev setup")
|
||||||
|
|
||||||
def __init__(self, controller):
|
def __init__(self, controller, zdevinfos):
|
||||||
log.debug('FileSystemView init start()')
|
log.debug('FileSystemView init start()')
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
self.zdev_list = ZdevList(self)
|
self.zdev_list = ZdevList(self)
|
||||||
|
self.zdev_list.update(zdevinfos)
|
||||||
|
|
||||||
frame = screen(
|
frame = screen(
|
||||||
self.zdev_list, self._build_buttons(),
|
self.zdev_list, self._build_buttons(),
|
||||||
focus_buttons=False)
|
focus_buttons=False)
|
||||||
super().__init__(frame)
|
super().__init__(frame)
|
||||||
self.refresh_model_inputs()
|
|
||||||
# Prevent urwid from putting the first focused widget at the
|
# Prevent urwid from putting the first focused widget at the
|
||||||
# very top of the display (obscuring the headings)
|
# very top of the display (obscuring the headings)
|
||||||
self.zdev_list._w._w.base_widget.set_focus_valign("bottom")
|
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),
|
back_btn(_("Back"), on_press=self.cancel),
|
||||||
]
|
]
|
||||||
|
|
||||||
def refresh_model_inputs(self):
|
|
||||||
self.zdev_list.refresh_model_inputs()
|
|
||||||
|
|
||||||
def cancel(self, button=None):
|
def cancel(self, button=None):
|
||||||
self.controller.cancel()
|
self.controller.cancel()
|
||||||
|
|
||||||
|
|
|
@ -184,7 +184,8 @@ class TuiApplication(Application):
|
||||||
def hide_load():
|
def hide_load():
|
||||||
ld.close()
|
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):
|
async def _move_screen(self, increment, coro):
|
||||||
if coro is not None:
|
if coro is not None:
|
||||||
|
|
Loading…
Reference in New Issue