Add manual ipv4 network configuration

Signed-off-by: Adam Stokes <adam.stokes@ubuntu.com>
This commit is contained in:
Adam Stokes 2015-10-08 18:10:54 -04:00
parent 4a878baa21
commit a82fb9e6a8
7 changed files with 243 additions and 20 deletions

View File

@ -16,7 +16,9 @@
from subiquity.controller import ControllerPolicy from subiquity.controller import ControllerPolicy
from subiquity.models import NetworkModel from subiquity.models import NetworkModel
from subiquity.ui.views import (NetworkView, from subiquity.ui.views import (NetworkView,
NetworkSetDefaultRouteView) NetworkSetDefaultRouteView,
NetworkConfigureInterfaceView,
NetworkConfigureIPv4InterfaceView)
from subiquity.ui.dummy import DummyView from subiquity.ui.dummy import DummyView
from subiquity.curtin import curtin_write_network_actions from subiquity.curtin import curtin_write_network_actions
@ -42,9 +44,38 @@ class NetworkController(ControllerPolicy):
self.signal.emit_signal('filesystem:show') self.signal.emit_signal('filesystem:show')
def set_default_route(self): def set_default_route(self):
self.model.prev_signal = ('Back to network view',
'network:show',
'network')
self.ui.set_header("Default route")
self.ui.set_body(NetworkSetDefaultRouteView(self.model, self.ui.set_body(NetworkSetDefaultRouteView(self.model,
self.signal)) self.signal))
def network_configure_interface(self, iface):
self.model.prev_signal = ('Back to network view',
'network:show',
'network')
self.ui.set_header("Network interface {}".format(iface))
self.ui.set_body(NetworkConfigureInterfaceView(self.model,
self.signal,
iface))
def network_configure_ipv4_interface(self, iface):
self.model.prev_signal = ('Back to configure interface menu',
'network:configure-interface-menu',
'network_configure_interface')
self.ui.set_header("Network interface {} manual IPv4 "
"configuration".format(iface))
self.ui.set_body(NetworkConfigureIPv4InterfaceView(self.model,
self.signal,
iface))
def network_configure_ipv6_interface(self, iface):
self.model.prev_signal = ('Back to configure interface menu',
'network:configure-interface-menu',
'network_configure_interface')
self.ui.set_body(DummyView(self.signal))
def bond_interfaces(self): def bond_interfaces(self):
self.ui.set_body(DummyView(self.signal)) self.ui.set_body(DummyView(self.signal))

View File

@ -59,16 +59,22 @@ class NetworkModel(ModelPolicy):
'network'), 'network'),
('Network finish', ('Network finish',
'network:finish', 'network:finish',
'network_finish') 'network_finish'),
('Network configure interface',
'network:configure-interface-menu',
'network_configure_interface'),
('Network configure ipv4 interface',
'network:configure-ipv4-interface',
'network_configure_ipv4_interface')
] ]
additional_options = [ additional_options = [
('Set default route', ('Set default route',
'network:set-default-route', 'network:set-default-route',
'set_default_route'), 'set_default_route'),
('Bond interfaces', # ('Bond interfaces',
'network:bond-interfaces', # 'network:bond-interfaces',
'bond_interfaces'), # 'bond_interfaces'),
# ('Install network driver', # ('Install network driver',
# 'network:install-network-driver', # 'network:install-network-driver',
# 'install_network_driver') # 'install_network_driver')

View File

@ -22,6 +22,8 @@ from .ceph import CephDiskView # NOQA
from .iscsi import IscsiDiskView # NOQA from .iscsi import IscsiDiskView # NOQA
from .network import NetworkView # NOQA from .network import NetworkView # NOQA
from .network_default_route import NetworkSetDefaultRouteView # NOQA from .network_default_route import NetworkSetDefaultRouteView # NOQA
from .network_configure_interface import NetworkConfigureInterfaceView #NOQA
from .network_configure_ipv4_interface import NetworkConfigureIPv4InterfaceView #NOQA
from .installpath import InstallpathView # NOQA from .installpath import InstallpathView # NOQA
from .installprogress import ProgressView # NOQA from .installprogress import ProgressView # NOQA
from .welcome import WelcomeView # NOQA from .welcome import WelcomeView # NOQA

View File

@ -24,7 +24,7 @@ from urwid import (ListBox, Pile, BoxAdapter,
Text, Columns) Text, Columns)
import yaml import yaml
from subiquity.ui.lists import SimpleList from subiquity.ui.lists import SimpleList
from subiquity.ui.buttons import cancel_btn, menu_btn from subiquity.ui.buttons import cancel_btn, menu_btn, done_btn
from subiquity.ui.utils import Padding, Color from subiquity.ui.utils import Padding, Color
from subiquity.view import ViewPolicy from subiquity.view import ViewPolicy
from subiquity.models.actions import RouteAction from subiquity.models.actions import RouteAction
@ -48,9 +48,12 @@ class NetworkView(ViewPolicy):
super().__init__(ListBox(self.body)) super().__init__(ListBox(self.body))
def _build_buttons(self): def _build_buttons(self):
cancel = cancel_btn(on_press=self.cancel)
done = done_btn(on_press=self.done)
buttons = [ buttons = [
Color.button(cancel_btn(on_press=self.cancel), Color.button(done, focus_map='button focus'),
focus_map='button focus'), Color.button(cancel, focus_map='button focus')
] ]
return Pile(buttons) return Pile(buttons)
@ -145,6 +148,10 @@ class NetworkView(ViewPolicy):
def on_net_dev_press(self, result): def on_net_dev_press(self, result):
log.debug("Selected network dev: {}".format(result.label)) log.debug("Selected network dev: {}".format(result.label))
self.signal.emit_signal('network:configure-interface-menu',
result.label)
def done(self, result):
actions = [action.get() for _, action in actions = [action.get() for _, action in
self.model.configured_interfaces.items()] self.model.configured_interfaces.items()]
actions += self.model.get_default_route() actions += self.model.get_default_route()

View File

@ -0,0 +1,65 @@
# 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 urwid import Text, Pile, ListBox
from subiquity.view import ViewPolicy
from subiquity.ui.buttons import done_btn, confirm_btn
from subiquity.ui.utils import Color, Padding
import logging
log = logging.getLogger('subiquity.network.network_configure_interface')
class NetworkConfigureInterfaceView(ViewPolicy):
def __init__(self, model, signal, iface):
self.model = model
self.signal = signal
self.iface = iface
body = [
Padding.center_79(Text("Will use DHCP for IPv4:")),
Padding.center_79(self._build_gateway_info()),
Padding.center_79(self._build_manual_ipv4_button()),
Padding.line_break(""),
Padding.center_79(Text("Checking IPv6...")),
Padding.center_79(self._build_manual_ipv6_button()),
Padding.line_break(""),
Padding.center_20(self._build_buttons())
]
super().__init__(ListBox(body))
def _build_gateway_info(self):
return Pile([Text("<ip> offered by DHCP server <gateway ip>")])
def _build_manual_ipv4_button(self):
btn = confirm_btn(label="Switch to manual IPv4 configuration",
on_press=self.show_ipv4_configuration)
return Pile([Color.menu_button(btn, focus_map="menu_button focus")])
def _build_manual_ipv6_button(self):
return Pile([Text("Switch to manual IPv6 configuration")])
def _build_buttons(self):
done = done_btn(on_press=self.done)
buttons = [
Color.button(done, focus_map='button focus'),
]
return Pile(buttons)
def show_ipv4_configuration(self, btn):
self.signal.emit_signal('network:configure-ipv4-interface', self.iface)
def done(self, result):
self.signal.emit_signal('network:show')

View File

@ -0,0 +1,102 @@
# 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 urwid import Text, Pile, ListBox, Columns
from subiquity.view import ViewPolicy
from subiquity.ui.buttons import done_btn, confirm_btn, cancel_btn
from subiquity.ui.utils import Color, Padding
from subiquity.ui.interactive import StringEditor
import logging
log = logging.getLogger('subiquity.network.network_configure_ipv4_interface')
class NetworkConfigureIPv4InterfaceView(ViewPolicy):
def __init__(self, model, signal, iface):
self.model = model
self.signal = signal
self.iface = iface
self.gateway_input = StringEditor(caption="")
self.address_input = StringEditor(caption="")
self.subnet_input = StringEditor(caption="")
body = [
Padding.center_79(self._build_iface_inputs()),
Padding.line_break(""),
Padding.center_79(self._build_set_as_default_gw_button()),
Padding.center_20(self._build_buttons())
]
super().__init__(ListBox(body))
def _build_iface_inputs(self):
col1 = [
Columns(
[
("weight", 0.2, Text("Subnet")),
("weight", 0.3,
Color.string_input(self.subnet_input,
focus_map="string_input focus")),
("weight", 0.5, Text("CIDR e.g. 192.168.9.0/24"))
], dividechars=2
),
Columns(
[
("weight", 0.2, Text("Address")),
("weight", 0.3,
Color.string_input(self.address_input,
focus_map="string_input focus")),
("weight", 0.5, Text(""))
], dividechars=2
),
Columns(
[
("weight", 0.2, Text("Gateway")),
("weight", 0.3,
Color.string_input(self.gateway_input,
focus_map="string_input focus")),
("weight", 0.5, Text(""))
], dividechars=2
)
]
return Pile(col1)
def _build_set_as_default_gw_button(self):
ifaces = self.model.get_interfaces()
if len(ifaces) > 1:
btn = confirm_btn(label="Set this as default gateway",
on_press=self.set_default_gateway)
else:
btn = Text("This will be your default gateway")
return Pile([btn])
def set_default_gateway(self):
if self.gateway_input.value:
self.model.default_gateway = self.gateway_input.value
def _build_buttons(self):
cancel = cancel_btn(on_press=self.cancel)
done = done_btn(on_press=self.done)
buttons = [
Color.button(done, focus_map='button focus'),
Color.button(cancel, focus_map='button focus')
]
return Pile(buttons)
def done(self, result):
self.signal.emit_signal('network:show')
def cancel(self, button):
self.model.default_gateway = None
self.signal.emit_signal('network:show')

View File

@ -29,23 +29,30 @@ class NetworkSetDefaultRouteView(ViewPolicy):
self.signal = signal self.signal = signal
self.default_gateway_w = None self.default_gateway_w = None
body = [ body = [
Padding.center_50(self._build_default_routes()), Padding.center_79(Text("Please set the default gateway:")),
Padding.line_break(""),
Padding.center_79(self._build_default_routes()),
Padding.line_break(""), Padding.line_break(""),
Padding.center_20(self._build_buttons()) Padding.center_20(self._build_buttons())
] ]
super().__init__(ListBox(body)) super().__init__(ListBox(body))
def _build_default_routes(self): def _build_default_routes(self):
items = [ ifaces = self.model.get_interfaces()
Text("Please set the default gateway:"), items = []
Color.menu_button(done_btn(label="192.168.9.1 (em1, em2)", for iface in ifaces:
items.append(Padding.center_50(
Color.menu_button(done_btn(
label="{ip} ({iface})".format(
ip="FIXME: needs default gateway",
iface=iface),
on_press=self.done), on_press=self.done),
focus_map="menu_button focus"), focus_map="menu_button focus")))
items.append(Padding.center_50(
Color.menu_button( Color.menu_button(
done_btn(label="Specify the default route manually", done_btn(label="Specify the default route manually",
on_press=self.show_edit_default_route), on_press=self.show_edit_default_route),
focus_map="menu_button focus") focus_map="menu_button focus")))
]
self.pile = Pile(items) self.pile = Pile(items)
return self.pile return self.pile
@ -63,14 +70,17 @@ class NetworkSetDefaultRouteView(ViewPolicy):
log.debug("Re-rendering specify default route") log.debug("Re-rendering specify default route")
self.default_gateway_w = StringEditor( self.default_gateway_w = StringEditor(
caption="Default gateway will be ") caption="Default gateway will be ")
self.pile.contents[-1] = (Color.string_input( self.pile.contents[-1] = (Padding.center_50(
Color.string_input(
self.default_gateway_w, self.default_gateway_w,
focus_map="string_input focus"), self.pile.options()) focus_map="string_input focus")), self.pile.options())
# self.signal.emit_signal('refresh') # self.signal.emit_signal('refresh')
def done(self, result): def done(self, result):
if self.default_gateway_w.value: if self.default_gateway_w and self.default_gateway_w.value:
self.model.default_gateway = self.default_gateway_w.value self.model.default_gateway = self.default_gateway_w.value
else:
self.model.default_gateway = result.label
self.signal.emit_signal('network:show') self.signal.emit_signal('network:show')
def cancel(self, button): def cancel(self, button):