From dc153cb54ad74a0b46ad37a25fcc70b17d74b6b8 Mon Sep 17 00:00:00 2001 From: Adam Stokes Date: Wed, 24 Jun 2015 15:44:31 -0400 Subject: [PATCH] add network view/controller Signed-off-by: Adam Stokes --- bin/subiquity | 6 +-- subiquity/controllers/__init__.py | 24 +++++++--- subiquity/controllers/installpath.py | 8 ++-- subiquity/controllers/network.py | 45 ++++++++++++++++++ subiquity/controllers/welcome.py | 8 ++-- subiquity/models/welcome.py | 3 ++ subiquity/routes.py | 4 +- subiquity/views/network.py | 71 ++++++++++++++++++++++++++++ 8 files changed, 147 insertions(+), 22 deletions(-) create mode 100644 subiquity/controllers/network.py create mode 100644 subiquity/views/network.py diff --git a/bin/subiquity b/bin/subiquity index 2c2515ca..fd38eda3 100755 --- a/bin/subiquity +++ b/bin/subiquity @@ -21,7 +21,6 @@ from subiquity.log import setup_logger from subiquity import __version__ as VERSION from subiquity.controllers import BaseController as Subiquity from subiquity.ui.frame import SubiquityUI -from subiquity.palette import STYLES, STYLES_MONO def parse_options(argv): @@ -42,11 +41,8 @@ def main(): logger.info("Arguments passed: {}".format(sys.argv)) ui = SubiquityUI() - palette = STYLES - if opts.run_on_serial: - palette = STYLES_MONO - subiquity_interface = Subiquity(ui, palette, opts) + subiquity_interface = Subiquity(ui, opts) subiquity_interface.run() if __name__ == '__main__': diff --git a/subiquity/controllers/__init__.py b/subiquity/controllers/__init__.py index 3ae49aec..9ee58b5f 100644 --- a/subiquity/controllers/__init__.py +++ b/subiquity/controllers/__init__.py @@ -15,7 +15,9 @@ import logging import urwid +import urwid.curses_display from subiquity.routes import Routes +from subiquity.palette import STYLES, STYLES_MONO log = logging.getLogger('subiquity.controller') @@ -27,9 +29,8 @@ class BaseControllerError(Exception): class BaseController: - def __init__(self, ui, palette, opts): + def __init__(self, ui, opts): self.ui = ui - self.palette = palette self.opts = opts def next_controller(self, *args, **kwds): @@ -52,15 +53,17 @@ class BaseController: return def update(self, *args, **kwds): - log.debug("Updating ...") route = Routes.current_idx() if route == 0: self.begin() self.set_alarm_in(1, self.update) + def exit(self): + raise urwid.ExitMainLoop() + def header_hotkeys(self, key): if key in ['q', 'Q']: - raise urwid.ExitMainLoop() + self.exit() def set_body(self, w): self.ui.set_body(w) @@ -76,11 +79,20 @@ class BaseController: def run(self): if not hasattr(self, 'loop'): - self.loop = urwid.MainLoop(self.ui, self.palette, + if self.opts.run_on_serial: + screen = urwid.raw_display.Screen() + screen.register_palette(STYLES_MONO) + else: + screen = urwid.raw_display.Screen() + screen.set_mouse_tracking(False) + screen.set_terminal_properties(256) + screen.register_palette(STYLES) + + self.loop = urwid.MainLoop(self.ui, screen=screen, unhandled_input=self.header_hotkeys) try: - self.update() + self.begin() self.loop.run() except: log.exception("Exception in controller.run():") diff --git a/subiquity/controllers/installpath.py b/subiquity/controllers/installpath.py index 5521516a..985ccb8d 100644 --- a/subiquity/controllers/installpath.py +++ b/subiquity/controllers/installpath.py @@ -17,6 +17,7 @@ from subiquity.controllers.policy import ControllerPolicy from subiquity.views.installpath import InstallpathView from subiquity.models.installpath import InstallpathModel import logging +import subprocess log = logging.getLogger('subiquity.installpath') @@ -41,10 +42,7 @@ class InstallpathController(ControllerPolicy): return def finish(self, install_selection=None): - if install_selection is None: - raise Exception("No install selection found") - else: - raise Exception( - "Install selection: {}".format(install_selection)) + # subprocess.check_call("/usr/local/bin/curtin_wrap.sh") + return self.ui.next_controller() __controller_class__ = InstallpathController diff --git a/subiquity/controllers/network.py b/subiquity/controllers/network.py new file mode 100644 index 00000000..dc289de4 --- /dev/null +++ b/subiquity/controllers/network.py @@ -0,0 +1,45 @@ +# Copyright 2015 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 . + +from subiquity.controllers.policy import ControllerPolicy +from subiquity.views.network import NetworkView +from subiquity.models.network import NetworkModel +import logging + +log = logging.getLogger('subiquity.network') + + +class NetworkController(ControllerPolicy): + """InstallpathController""" + + title = "Network connections" + excerpt = ("Configure at least the main interface this server will " + "use to talk to other machines, and preferably provide " + "sufficient access for updates.") + + footer = ("Additional networking info here") + + def show(self, *args, **kwds): + self.ui.set_header(self.title, self.excerpt) + self.ui.set_footer(self.footer) + model = NetworkModel() + self.ui.set_body(NetworkView(model, self.finish)) + return + + def finish(self, interface=None): + log.info("Network Interface choosen: {}".format(interface)) + return self.ui.exit() + +__controller_class__ = NetworkController diff --git a/subiquity/controllers/welcome.py b/subiquity/controllers/welcome.py index 4318f2fb..8e1d2119 100644 --- a/subiquity/controllers/welcome.py +++ b/subiquity/controllers/welcome.py @@ -16,7 +16,6 @@ from subiquity.controllers.policy import ControllerPolicy from subiquity.views.welcome import WelcomeView from subiquity.models.welcome import WelcomeModel -import subprocess import logging @@ -33,16 +32,15 @@ class WelcomeController(ControllerPolicy): def show(self, *args, **kwds): self.ui.set_header(self.title, self.excerpt) self.ui.set_footer(self.footer) - model = WelcomeModel() - self.ui.set_body(WelcomeView(model, self.finish)) + self.ui.set_body(WelcomeView(WelcomeModel, self.finish)) return def finish(self, language=None): if language is None: raise SystemExit("No language selected, exiting as there are no " "more previous controllers to render.") - self.selected_language = language - # subprocess.check_call("/usr/local/bin/curtin_wrap.sh") + WelcomeModel.selected_language = language + log.debug("Welcome Model: {}".format(WelcomeModel())) return self.ui.next_controller() __controller_class__ = WelcomeController diff --git a/subiquity/models/welcome.py b/subiquity/models/welcome.py index 0e3e2a9e..67c6460c 100644 --- a/subiquity/models/welcome.py +++ b/subiquity/models/welcome.py @@ -28,3 +28,6 @@ class WelcomeModel(models.Model): supported_languages = ['English', 'Belgian', 'German', 'Italian'] selected_language = None + + def __repr__(self): + return "".format(self.selected_language) diff --git a/subiquity/routes.py b/subiquity/routes.py index e9d940df..e0f5a38b 100644 --- a/subiquity/routes.py +++ b/subiquity/routes.py @@ -15,6 +15,7 @@ from subiquity.controllers.welcome import WelcomeController from subiquity.controllers.installpath import InstallpathController +from subiquity.controllers.network import NetworkController class RoutesError(Exception): @@ -29,7 +30,8 @@ class Routes: this order is required for routing to work. """ routes = [WelcomeController, - InstallpathController] + InstallpathController, + NetworkController] current_route_idx = 0 @classmethod diff --git a/subiquity/views/network.py b/subiquity/views/network.py new file mode 100644 index 00000000..e5f9b311 --- /dev/null +++ b/subiquity/views/network.py @@ -0,0 +1,71 @@ +# Copyright 2015 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 . + +import logging +from urwid import (WidgetWrap, ListBox, Pile, BoxAdapter, Text) +from subiquity.ui.lists import SimpleList +from subiquity.ui.buttons import confirm_btn, cancel_btn +from subiquity.ui.utils import Padding, Color + + +log = logging.getLogger('subiquity.networkView') + + +class NetworkView(WidgetWrap): + def __init__(self, model, cb): + self.model = model + self.cb = cb + self.items = [] + self.body = [ + Padding.center_79(self._build_model_inputs()), + Padding.line_break(""), + Padding.center_79(self._build_additional_options()), + Padding.line_break(""), + Padding.center_20(self._build_buttons()), + ] + super().__init__(ListBox(self.body)) + + def _build_buttons(self): + buttons = [ + Color.button_secondary(cancel_btn(on_press=self.cancel), + focus_map='button_secondary focus'), + ] + return Pile(buttons) + + def _build_model_inputs(self): + sl = [] + for iface in self.model.interfaces: + sl.append(Color.button_primary(confirm_btn(label=iface, + on_press=self.confirm), + focus_map='button_primary focus')) + sl.append(Padding.push_10(Text("Adapter info"))) + + return BoxAdapter(SimpleList(sl), + height=len(sl)) + + def _build_additional_options(self): + opts = [] + for opt in self.model.additional_options: + opts.append( + Color.button_secondary(confirm_btn(label=opt, + on_press=self.confirm), + focus_map='button_secondary focus')) + return Pile(opts) + + def confirm(self, button): + return self.cb(button.label) + + def cancel(self, button): + return self.cb(None)