add network view/controller
Signed-off-by: Adam Stokes <adam.stokes@ubuntu.com>
This commit is contained in:
parent
18d011693b
commit
dc153cb54a
|
@ -21,7 +21,6 @@ from subiquity.log import setup_logger
|
||||||
from subiquity import __version__ as VERSION
|
from subiquity import __version__ as VERSION
|
||||||
from subiquity.controllers import BaseController as Subiquity
|
from subiquity.controllers import BaseController as Subiquity
|
||||||
from subiquity.ui.frame import SubiquityUI
|
from subiquity.ui.frame import SubiquityUI
|
||||||
from subiquity.palette import STYLES, STYLES_MONO
|
|
||||||
|
|
||||||
|
|
||||||
def parse_options(argv):
|
def parse_options(argv):
|
||||||
|
@ -42,11 +41,8 @@ def main():
|
||||||
logger.info("Arguments passed: {}".format(sys.argv))
|
logger.info("Arguments passed: {}".format(sys.argv))
|
||||||
|
|
||||||
ui = SubiquityUI()
|
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()
|
subiquity_interface.run()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -15,7 +15,9 @@
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import urwid
|
import urwid
|
||||||
|
import urwid.curses_display
|
||||||
from subiquity.routes import Routes
|
from subiquity.routes import Routes
|
||||||
|
from subiquity.palette import STYLES, STYLES_MONO
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger('subiquity.controller')
|
log = logging.getLogger('subiquity.controller')
|
||||||
|
@ -27,9 +29,8 @@ class BaseControllerError(Exception):
|
||||||
|
|
||||||
|
|
||||||
class BaseController:
|
class BaseController:
|
||||||
def __init__(self, ui, palette, opts):
|
def __init__(self, ui, opts):
|
||||||
self.ui = ui
|
self.ui = ui
|
||||||
self.palette = palette
|
|
||||||
self.opts = opts
|
self.opts = opts
|
||||||
|
|
||||||
def next_controller(self, *args, **kwds):
|
def next_controller(self, *args, **kwds):
|
||||||
|
@ -52,15 +53,17 @@ class BaseController:
|
||||||
return
|
return
|
||||||
|
|
||||||
def update(self, *args, **kwds):
|
def update(self, *args, **kwds):
|
||||||
log.debug("Updating ...")
|
|
||||||
route = Routes.current_idx()
|
route = Routes.current_idx()
|
||||||
if route == 0:
|
if route == 0:
|
||||||
self.begin()
|
self.begin()
|
||||||
self.set_alarm_in(1, self.update)
|
self.set_alarm_in(1, self.update)
|
||||||
|
|
||||||
|
def exit(self):
|
||||||
|
raise urwid.ExitMainLoop()
|
||||||
|
|
||||||
def header_hotkeys(self, key):
|
def header_hotkeys(self, key):
|
||||||
if key in ['q', 'Q']:
|
if key in ['q', 'Q']:
|
||||||
raise urwid.ExitMainLoop()
|
self.exit()
|
||||||
|
|
||||||
def set_body(self, w):
|
def set_body(self, w):
|
||||||
self.ui.set_body(w)
|
self.ui.set_body(w)
|
||||||
|
@ -76,11 +79,20 @@ class BaseController:
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if not hasattr(self, 'loop'):
|
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)
|
unhandled_input=self.header_hotkeys)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.update()
|
self.begin()
|
||||||
self.loop.run()
|
self.loop.run()
|
||||||
except:
|
except:
|
||||||
log.exception("Exception in controller.run():")
|
log.exception("Exception in controller.run():")
|
||||||
|
|
|
@ -17,6 +17,7 @@ from subiquity.controllers.policy import ControllerPolicy
|
||||||
from subiquity.views.installpath import InstallpathView
|
from subiquity.views.installpath import InstallpathView
|
||||||
from subiquity.models.installpath import InstallpathModel
|
from subiquity.models.installpath import InstallpathModel
|
||||||
import logging
|
import logging
|
||||||
|
import subprocess
|
||||||
|
|
||||||
log = logging.getLogger('subiquity.installpath')
|
log = logging.getLogger('subiquity.installpath')
|
||||||
|
|
||||||
|
@ -41,10 +42,7 @@ class InstallpathController(ControllerPolicy):
|
||||||
return
|
return
|
||||||
|
|
||||||
def finish(self, install_selection=None):
|
def finish(self, install_selection=None):
|
||||||
if install_selection is None:
|
# subprocess.check_call("/usr/local/bin/curtin_wrap.sh")
|
||||||
raise Exception("No install selection found")
|
return self.ui.next_controller()
|
||||||
else:
|
|
||||||
raise Exception(
|
|
||||||
"Install selection: {}".format(install_selection))
|
|
||||||
|
|
||||||
__controller_class__ = InstallpathController
|
__controller_class__ = InstallpathController
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
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
|
|
@ -16,7 +16,6 @@
|
||||||
from subiquity.controllers.policy import ControllerPolicy
|
from subiquity.controllers.policy import ControllerPolicy
|
||||||
from subiquity.views.welcome import WelcomeView
|
from subiquity.views.welcome import WelcomeView
|
||||||
from subiquity.models.welcome import WelcomeModel
|
from subiquity.models.welcome import WelcomeModel
|
||||||
import subprocess
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,16 +32,15 @@ class WelcomeController(ControllerPolicy):
|
||||||
def show(self, *args, **kwds):
|
def show(self, *args, **kwds):
|
||||||
self.ui.set_header(self.title, self.excerpt)
|
self.ui.set_header(self.title, self.excerpt)
|
||||||
self.ui.set_footer(self.footer)
|
self.ui.set_footer(self.footer)
|
||||||
model = WelcomeModel()
|
self.ui.set_body(WelcomeView(WelcomeModel, self.finish))
|
||||||
self.ui.set_body(WelcomeView(model, self.finish))
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def finish(self, language=None):
|
def finish(self, language=None):
|
||||||
if language is None:
|
if language is None:
|
||||||
raise SystemExit("No language selected, exiting as there are no "
|
raise SystemExit("No language selected, exiting as there are no "
|
||||||
"more previous controllers to render.")
|
"more previous controllers to render.")
|
||||||
self.selected_language = language
|
WelcomeModel.selected_language = language
|
||||||
# subprocess.check_call("/usr/local/bin/curtin_wrap.sh")
|
log.debug("Welcome Model: {}".format(WelcomeModel()))
|
||||||
return self.ui.next_controller()
|
return self.ui.next_controller()
|
||||||
|
|
||||||
__controller_class__ = WelcomeController
|
__controller_class__ = WelcomeController
|
||||||
|
|
|
@ -28,3 +28,6 @@ class WelcomeModel(models.Model):
|
||||||
|
|
||||||
supported_languages = ['English', 'Belgian', 'German', 'Italian']
|
supported_languages = ['English', 'Belgian', 'German', 'Italian']
|
||||||
selected_language = None
|
selected_language = None
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<Selected: {}>".format(self.selected_language)
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
from subiquity.controllers.welcome import WelcomeController
|
from subiquity.controllers.welcome import WelcomeController
|
||||||
from subiquity.controllers.installpath import InstallpathController
|
from subiquity.controllers.installpath import InstallpathController
|
||||||
|
from subiquity.controllers.network import NetworkController
|
||||||
|
|
||||||
|
|
||||||
class RoutesError(Exception):
|
class RoutesError(Exception):
|
||||||
|
@ -29,7 +30,8 @@ class Routes:
|
||||||
this order is required for routing to work.
|
this order is required for routing to work.
|
||||||
"""
|
"""
|
||||||
routes = [WelcomeController,
|
routes = [WelcomeController,
|
||||||
InstallpathController]
|
InstallpathController,
|
||||||
|
NetworkController]
|
||||||
current_route_idx = 0
|
current_route_idx = 0
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
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)
|
Loading…
Reference in New Issue