[node-patches] Change in ovirt-node[master]: network: Improve page and NIC details dialog
fabiand at fedoraproject.org
fabiand at fedoraproject.org
Tue Dec 11 20:09:39 UTC 2012
Fabian Deutsch has uploaded a new change for review.
Change subject: network: Improve page and NIC details dialog
......................................................................
network: Improve page and NIC details dialog
Change-Id: Ie20873b30fa18250fa9fdbe7e84753cb96bd67a8
Signed-off-by: Fabian Deutsch <fabiand at fedoraproject.org>
---
M scripts/tui/src/ovirt/node/app.py
M scripts/tui/src/ovirt/node/config/defaults.py
M scripts/tui/src/ovirt/node/plugins.py
M scripts/tui/src/ovirt/node/setup/logging_page.py
M scripts/tui/src/ovirt/node/setup/network_page.py
M scripts/tui/src/ovirt/node/setup/ping.py
M scripts/tui/src/ovirt/node/setup/security_page.py
M scripts/tui/src/ovirt/node/setup/status_page.py
M scripts/tui/src/ovirt/node/setup/support_page.py
M scripts/tui/src/ovirt/node/ui/__init__.py
M scripts/tui/src/ovirt/node/ui/builder.py
M scripts/tui/src/ovirt/node/ui/tui.py
M scripts/tui/src/ovirt/node/ui/widgets.py
M scripts/tui/src/ovirt/node/utils/network.py
M scripts/tui/src/ovirt/node/valid.py
15 files changed, 471 insertions(+), 215 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/ovirt-node refs/changes/34/9934/1
diff --git a/scripts/tui/src/ovirt/node/app.py b/scripts/tui/src/ovirt/node/app.py
index 483c96d..65e5cd7 100644
--- a/scripts/tui/src/ovirt/node/app.py
+++ b/scripts/tui/src/ovirt/node/app.py
@@ -46,7 +46,7 @@
def __init__(self, plugin_base, ui_backend="urwid"):
super(Application, self).__init__()
self.__parse_cmdline()
-
+
ui_backend_class = {
"urwid": ovirt.node.ui.tui.UrwidTUI
}[ui_backend]
@@ -87,7 +87,8 @@
def __check_terminal_size(self):
cols, rows = self.ui.size()
if cols < 80 or rows < 24:
- self.logger.warning("Window size is too small: %dx%d" % (cols, rows))
+ self.logger.warning("Window size is too small: %dx%d" % (cols,
+ rows))
def model(self, plugin_name):
model = None
diff --git a/scripts/tui/src/ovirt/node/config/defaults.py b/scripts/tui/src/ovirt/node/config/defaults.py
index ee1028f..7ca3438 100644
--- a/scripts/tui/src/ovirt/node/config/defaults.py
+++ b/scripts/tui/src/ovirt/node/config/defaults.py
@@ -29,7 +29,7 @@
There are classes for all components which can be configured through that
central configuration file.
Each class (for a component) can have a configure and apply_config method. Look
-at the CentralNodeConfiguration for more informations.
+at the NodeConfigFileSection for more informations.
Each class should implement a configure method, mainly to define all the
required arguments (or keys).
@@ -155,9 +155,11 @@
return self.provider.get_dict()
-class CentralNodeConfiguration(base.Base):
+class NodeConfigFileSection(base.Base):
+ none_value = ""
+
def __init__(self, cfgfile=None):
- super(CentralNodeConfiguration, self).__init__()
+ super(NodeConfigFileSection, self).__init__()
self.defaults = cfgfile or ConfigFile()
def update(self, *args, **kwargs):
@@ -181,7 +183,7 @@
values = ()
cfg = self.defaults.get_dict()
for key in self.keys:
- value = cfg[key] if key in cfg else ""
+ value = cfg[key] if key in cfg else self.none_value
values += (value,)
assert len(varnames) == len(values)
return zip(varnames, values)
@@ -196,7 +198,8 @@
def _map_config_and_update_defaults(self, *args, **kwargs):
assert len(args) == 0
- assert (set(self.keys) ^ set(kwargs.keys())) == set()
+ assert (set(self.keys) ^ set(kwargs.keys())) == set(), \
+ "Keys: %s, Args: %s" % (self.keys, kwargs)
new_dict = {k.upper(): v for k, v in kwargs.items()}
self.defaults.update(new_dict, remove_empty=True)
@@ -207,7 +210,7 @@
... keys = None
... def _map_config_and_update_defaults(self, *args, **kwargs):
... return kwargs
- ... @CentralNodeConfiguration.map_and_update_defaults_decorator
+ ... @NodeConfigFileSection.map_and_update_defaults_decorator
... def meth(self, a, b, c):
... assert type(a) is int
... assert type(b) is int
@@ -218,6 +221,7 @@
{'OVIRT_A': 1, 'OVIRT_B': 2, 'OVIRT_C': 'c3'}
"""
def wrapper(self, *args, **kwargs):
+ assert kwargs == {}, "kwargs are not allowed for these functions"
if len(self.keys) != len(args):
raise Exception("There are not enough arguments given for " +
"%s of %s" % (func, self))
@@ -230,7 +234,7 @@
return wrapper
-class Network(CentralNodeConfiguration):
+class Network(NodeConfigFileSection):
"""Sets network stuff
- OVIRT_BOOTIF
- OVIRT_IP_ADDRESS, OVIRT_IP_NETMASK, OVIRT_IP_GATEWAY
@@ -246,14 +250,14 @@
>>> data[:3]
[('iface', 'eth0'), ('bootproto', 'static'), ('ipaddr', '10.0.0.1')]
>>> data [3:]
- [('netmask', '255.0.0.0'), ('gw', '10.0.0.255'), ('vlanid', '20')]
+ [('netmask', '255.0.0.0'), ('gateway', '10.0.0.255'), ('vlanid', '20')]
>>> n.clear()
>>> data = n.retrieve()
>>> data [:3]
- [('iface', None), ('bootproto', None), ('ipaddr', None)]
+ [('iface', ''), ('bootproto', ''), ('ipaddr', '')]
>>> data [3:]
- [('netmask', None), ('gw', None), ('vlanid', None)]
+ [('netmask', ''), ('gateway', ''), ('vlanid', '')]
"""
keys = ("OVIRT_BOOTIF",
"OVIRT_BOOTPROTO",
@@ -262,18 +266,18 @@
"OVIRT_GATEWAY",
"OVIRT_VLAN")
- @CentralNodeConfiguration.map_and_update_defaults_decorator
- def update(self, iface, bootproto, ipaddr=None, netmask=None, gw=None,
+ @NodeConfigFileSection.map_and_update_defaults_decorator
+ def update(self, iface, bootproto, ipaddr=None, netmask=None, gateway=None,
vlanid=None):
- if bootproto not in ["static", "none", "dhcp"]:
+ if bootproto not in ["static", "none", "dhcp", None]:
raise exceptions.InvalidData("Unknown bootprotocol: %s" %
bootproto)
- (valid.IPv4Address() | valid.Empty())(ipaddr)
- (valid.IPv4Address() | valid.Empty())(netmask)
- (valid.IPv4Address() | valid.Empty())(gw)
+ (valid.IPv4Address() | valid.Empty(or_none=True))(ipaddr)
+ (valid.IPv4Address() | valid.Empty(or_none=True))(netmask)
+ (valid.IPv4Address() | valid.Empty(or_none=True))(gateway)
-class Nameservers(CentralNodeConfiguration):
+class Nameservers(NodeConfigFileSection):
"""Configure nameservers
>>> fn = "/tmp/cfg_dummy"
>>> cfgfile = ConfigFile(fn, SimpleProvider)
@@ -286,7 +290,7 @@
"""
keys = ("OVIRT_DNS",)
- @CentralNodeConfiguration.map_and_update_defaults_decorator
+ @NodeConfigFileSection.map_and_update_defaults_decorator
def update(self, servers):
assert type(servers) is list
servers = filter(lambda i: i.strip() not in ["", None], servers)
@@ -296,7 +300,7 @@
}
def retrieve(self):
- cfg = dict(CentralNodeConfiguration.retrieve(self))
+ cfg = dict(NodeConfigFileSection.retrieve(self))
return {
"servers": cfg["servers"].split(",")
}
@@ -346,7 +350,7 @@
utils.fs.persist_config("/etc/resolv.conf")
-class Timeservers(CentralNodeConfiguration):
+class Timeservers(NodeConfigFileSection):
"""Configure timeservers
>>> fn = "/tmp/cfg_dummy"
@@ -360,7 +364,7 @@
"""
keys = ("OVIRT_NTP",)
- @CentralNodeConfiguration.map_and_update_defaults_decorator
+ @NodeConfigFileSection.map_and_update_defaults_decorator
def update(self, servers):
assert type(servers) is list
servers = filter(lambda i: i.strip() not in ["", None], servers)
@@ -370,13 +374,13 @@
}
def retrieve(self):
- cfg = dict(CentralNodeConfiguration.retrieve(self))
+ cfg = dict(NodeConfigFileSection.retrieve(self))
return {
"servers": cfg["servers"].split(",")
}
-class Syslog(CentralNodeConfiguration):
+class Syslog(NodeConfigFileSection):
"""Configure rsyslog
>>> fn = "/tmp/cfg_dummy"
@@ -391,13 +395,13 @@
keys = ("OVIRT_SYSLOG_SERVER",
"OVIRT_SYSLOG_PORT")
- @CentralNodeConfiguration.map_and_update_defaults_decorator
+ @NodeConfigFileSection.map_and_update_defaults_decorator
def update(self, server, port):
valid.FQDNOrIPAddress()(server)
valid.Port()(port)
-class Collectd(CentralNodeConfiguration):
+class Collectd(NodeConfigFileSection):
"""Configure collectd
>>> fn = "/tmp/cfg_dummy"
@@ -412,13 +416,13 @@
keys = ("OVIRT_COLLECTD_SERVER",
"OVIRT_COLLECTD_PORT")
- @CentralNodeConfiguration.map_and_update_defaults_decorator
+ @NodeConfigFileSection.map_and_update_defaults_decorator
def update(self, server, port):
valid.FQDNOrIPAddress()(server)
valid.Port()(port)
-class RHN(CentralNodeConfiguration):
+class RHN(NodeConfigFileSection):
keys = ("OVIRT_RHN_TYPE",
"OVIRT_RHN_URL",
"OVIRT_RHN_CA_CERT",
@@ -431,13 +435,13 @@
"OVIRT_RHN_PROXYUSER",
"OVIRT_RHN_PROXYPASSWORD")
- @CentralNodeConfiguration.map_and_update_defaults_decorator
+ @NodeConfigFileSection.map_and_update_defaults_decorator
def update(self, rhntype, url, ca_cert, username, password, profile,
activationkey, org, proxy, proxyuser, proxypassword):
pass
-class KDump(CentralNodeConfiguration):
+class KDump(NodeConfigFileSection):
"""Configure kdump
>>> fn = "/tmp/cfg_dummy"
@@ -452,13 +456,13 @@
keys = ("OVIRT_KDUMP_NFS",
"OVIRT_KDUMP_SSH")
- @CentralNodeConfiguration.map_and_update_defaults_decorator
+ @NodeConfigFileSection.map_and_update_defaults_decorator
def update(self, nfs, ssh):
valid.FQDNOrIPAddress()(nfs)
valid.URL()(ssh)
-class iSCSI(CentralNodeConfiguration):
+class iSCSI(NodeConfigFileSection):
"""Configure iSCSI
>>> fn = "/tmp/cfg_dummy"
@@ -476,13 +480,13 @@
"OVIRT_ISCSI_TARGET_IP",
"OVIRT_ISCSI_TARGET_PORT")
- @CentralNodeConfiguration.map_and_update_defaults_decorator
+ @NodeConfigFileSection.map_and_update_defaults_decorator
def update(self, name, target_name, target_host, target_port):
# FIXME add validation
pass
-class SNMP(CentralNodeConfiguration):
+class SNMP(NodeConfigFileSection):
"""Configure SNMP
>>> fn = "/tmp/cfg_dummy"
@@ -494,13 +498,13 @@
"""
keys = ("OVIRT_SNMP_PASSWORD",)
- @CentralNodeConfiguration.map_and_update_defaults_decorator
+ @NodeConfigFileSection.map_and_update_defaults_decorator
def update(self, password):
# FIXME add validation
pass
-class Netconsole(CentralNodeConfiguration):
+class Netconsole(NodeConfigFileSection):
"""Configure netconsole
>>> fn = "/tmp/cfg_dummy"
@@ -515,13 +519,13 @@
keys = ("OVIRT_NETCONSOLE_SERVER",
"OVIRT_NETCONSOLE_PORT")
- @CentralNodeConfiguration.map_and_update_defaults_decorator
+ @NodeConfigFileSection.map_and_update_defaults_decorator
def update(self, server, port):
# FIXME add validation
pass
-class CIM(CentralNodeConfiguration):
+class CIM(NodeConfigFileSection):
"""Configure CIM
>>> fn = "/tmp/cfg_dummy"
@@ -533,7 +537,7 @@
"""
keys = ("OVIRT_CIM_ENABLED",)
- @CentralNodeConfiguration.map_and_update_defaults_decorator
+ @NodeConfigFileSection.map_and_update_defaults_decorator
def update(self, enabled):
return {
"OVIRT_CIM_ENABLED": "1" if utils.parse_bool(enabled) else "0"
diff --git a/scripts/tui/src/ovirt/node/plugins.py b/scripts/tui/src/ovirt/node/plugins.py
index 4f55be2..3d82a31 100644
--- a/scripts/tui/src/ovirt/node/plugins.py
+++ b/scripts/tui/src/ovirt/node/plugins.py
@@ -206,7 +206,7 @@
Args:
changes (dict): changes which shall be applied to the model
Returns:
- True on success, or False otherwise
+ (False)True on (no)success or a ui.Dialog/ui.Page
Raises:
Errors
"""
@@ -235,7 +235,11 @@
"""
self.logger.debug("Request to apply model changes")
effective_changes = self.pending_changes() or {}
- successfull_merge = self.on_merge(effective_changes) is not False
+ successfull_merge = self.on_merge(effective_changes)
+ if successfull_merge is None:
+ #raise Exception("on_save needs to return " +
+ # "True/False or a Page/Dialog")
+ successfull_merge = True
if successfull_merge:
self.logger.info("Changes were merged successfully")
self.__changes = {}
@@ -273,3 +277,83 @@
else:
self.logger.debug("No effective changes detected.")
return effective_changes if len(effective_changes) > 0 else None
+
+
+class ChangesHelper(base.Base):
+ def __init__(self, changes):
+ self.changes = changes
+
+ def if_keys_exist_run(self, keys, func):
+ """Run func if all keys are present in the changes.
+ The values of the change entries for each key in keys are passed as
+ arguments to the function func
+
+ >>> changes = {
+ ... "foo": 1,
+ ... "bar": 2,
+ ... "baz": 0
+ ... }
+ >>> helper = ChangesHelper(changes)
+ >>> cb = lambda foo, bar: foo + bar
+ >>> helper.if_keys_exist_run(["foo", "bar"], cb)
+ 3
+ >>> helper.if_keys_exist_run(["foo", "baz"], cb)
+ 1
+ >>> helper.if_keys_exist_run(["win", "dow"], cb)
+
+ Args:
+ keys: A list of keys which need to be present in the changes
+ func: The function to be run, values of keys are passed as args
+ """
+ if self.all_keys_in_change(keys):
+ return func(*[self.changes[key] for key in keys])
+
+ def get_key_values(self, keys):
+ assert self.all_keys_in_change(keys), "Missing keys: %s" % ( \
+ set(keys).difference(set(self.changes.keys())))
+ return [self.changes[key] for key in keys]
+
+ def all_keys_in_change(self, keys):
+ return set(keys).issubset(set(self.changes.keys()))
+
+ def any_key_in_change(self, keys):
+ return any([key in self.changes for key in keys])
+
+ def __getitem__(self, key):
+ if key in self.changes:
+ return self.changes[key]
+ return None
+
+
+class WidgetsHelper(dict, base.Base):
+ """A helper class to handle widgets
+ """
+ def __init__(self):
+ super(WidgetsHelper, self).__init__()
+ base.Base.__init__(self)
+
+ def subset(self, paths):
+ return [self[p] for p in paths]
+
+ def group(self, paths):
+ """Group the specified (by-path) widgets
+
+ Args:
+ paths: A list of paths of widgets to be grouped
+ Returns:
+ A WidgetsHelper.WidgetGroup
+ """
+ return WidgetsHelper.WidgetGroup(self, paths)
+
+ class WidgetGroup(list, base.Base):
+ def __init__(self, widgethelper, paths):
+ super(WidgetsHelper.WidgetGroup, self).__init__()
+ base.Base.__init__(self)
+ self.widgethelper = widgethelper
+ self.extend(paths)
+
+ def enabled(self, is_enable):
+ """Enable or disable all widgets of this group
+ """
+ self.logger.debug("Enabling widget group: %s" % self)
+ map(lambda w: w.enabled(is_enable), self.widgethelper.subset(self))
\ No newline at end of file
diff --git a/scripts/tui/src/ovirt/node/setup/logging_page.py b/scripts/tui/src/ovirt/node/setup/logging_page.py
index 9069014..5b87d9e 100644
--- a/scripts/tui/src/ovirt/node/setup/logging_page.py
+++ b/scripts/tui/src/ovirt/node/setup/logging_page.py
@@ -54,7 +54,7 @@
"""Validators validate the input on change and give UI feedback
"""
return {
- "max_log_size": ovirt.node.valid.Number(min=0),
+ "max_log_size": ovirt.node.valid.Number(range=[0, None]),
"rsyslog.address": ovirt.node.valid.FQDNOrIPAddress(),
"rsyslog.port": ovirt.node.valid.Port(),
"netconsole.address": ovirt.node.valid.FQDNOrIPAddress(),
diff --git a/scripts/tui/src/ovirt/node/setup/network_page.py b/scripts/tui/src/ovirt/node/setup/network_page.py
index 8fd528e..3be2acc 100644
--- a/scripts/tui/src/ovirt/node/setup/network_page.py
+++ b/scripts/tui/src/ovirt/node/setup/network_page.py
@@ -18,17 +18,17 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA. A copy of the GNU General Public License is
# also available at http://www.gnu.org/copyleft/gpl.html.
-
"""
-Network plugin
+Network page plugin
"""
-import ovirt.node.plugins
-import ovirt.node.valid
-import ovirt.node.ui
-import ovirt.node.utils.network
-import ovirt.node.config.network
+import time
+
+from ovirt.node import ui
from ovirt.node.config import defaults
+from ovirt.node import plugins
+import ovirt.node.utils.network
+from ovirt.node import valid
class Plugin(ovirt.node.plugins.NodePlugin):
@@ -43,6 +43,18 @@
"ntp[1]": "",
}
_widgets = None
+
+ def __init__(self, app):
+ super(Plugin, self).__init__(app)
+ self._widgets = plugins.WidgetsHelper()
+
+ # Keys/Paths to widgets related to NIC settings
+ self._nic_details_group = self._widgets.group([
+ "dialog.nic.ipv4.bootproto",
+ "dialog.nic.ipv4.address",
+ "dialog.nic.ipv4.netmask",
+ "dialog.nic.ipv4.gateway",
+ "dialog.nic.vlanid"])
def name(self):
return "Network"
@@ -64,14 +76,20 @@
def validators(self):
Empty = ovirt.node.valid.Empty
- ip_or_empty = ovirt.node.valid.IPAddress() | Empty()
- fqdn_ip_or_empty = ovirt.node.valid.FQDNOrIPAddress() | Empty()
+ ip_or_empty = valid.IPAddress() | Empty()
+ fqdn_ip_or_empty = valid.FQDNOrIPAddress() | Empty()
+
return {
- "hostname": ovirt.node.valid.FQDNOrIPAddress(),
- "dns[0]": ovirt.node.valid.IPAddress(),
+ "hostname": valid.FQDNOrIPAddress(),
+ "dns[0]": valid.IPAddress(),
"dns[1]": ip_or_empty,
- "ntp[0]": ovirt.node.valid.FQDNOrIPAddress(),
+ "ntp[0]": valid.FQDNOrIPAddress(),
"ntp[1]": fqdn_ip_or_empty,
+
+ "dialog.nic.ipv4.address": valid.IPv4Address(),
+ "dialog.nic.ipv4.netmask": valid.IPv4Address(),
+ "dialog.nic.ipv4.gateway": valid.IPv4Address(),
+ "dialog.nic.vlanid": valid.Number(range=[0, 4096]),
}
def ui_content(self):
@@ -80,33 +98,33 @@
"""
widgets = [
("hostname",
- ovirt.node.ui.Entry("Hostname:")),
- ("hostname._space", ovirt.node.ui.Divider()),
+ ui.Entry("Hostname:")),
+ ("hostname._space", ui.Divider()),
- ("nics", ovirt.node.ui.Table("Available System NICs",
+ ("nics", ui.Table("Available System NICs",
"Device Status Model MAC Address",
self._get_nics())),
- ("nics._space", ovirt.node.ui.Divider()),
+ ("nics._space", ui.Divider()),
- ("dns[0]", ovirt.node.ui.Entry("DNS Server 1:")),
- ("dns[1]", ovirt.node.ui.Entry("DNS Server 2:")),
- ("dns._space", ovirt.node.ui.Divider()),
+ ("dns[0]", ui.Entry("DNS Server 1:")),
+ ("dns[1]", ui.Entry("DNS Server 2:")),
+ ("dns._space", ui.Divider()),
- ("ntp[0]", ovirt.node.ui.Entry("NTP Server 1:")),
- ("ntp[1]", ovirt.node.ui.Entry("NTP Server 2:")),
- ("ntp._space", ovirt.node.ui.Divider()),
+ ("ntp[0]", ui.Entry("NTP Server 1:")),
+ ("ntp[1]", ui.Entry("NTP Server 2:")),
+ ("ntp._space", ui.Divider()),
]
# Save it "locally" as a dict, for better accessability
- self._widgets = dict(widgets)
+ self._widgets.update(dict(widgets))
- page = ovirt.node.ui.Page(widgets)
+ page = ui.Page(widgets)
return page
def _get_nics(self):
justify = lambda txt, l: txt.ljust(l)[0:l]
node_nics = []
first_nic = None
- for name, nic in ovirt.node.utils.network.node_nics().items():
+ for name, nic in sorted(ovirt.node.utils.network.node_nics().items()):
if first_nic == None:
first_nic = name
bootproto = "Configured" if nic["bootproto"] else "Unconfigured"
@@ -122,7 +140,7 @@
def _build_dialog(self, path, txt, widgets):
self._widgets.update(dict(widgets))
- self._widgets[path] = ovirt.node.ui.Dialog(txt, widgets)
+ self._widgets[path] = ui.Dialog(txt, widgets)
return self._widgets[path]
def _build_nic_details_dialog(self):
@@ -130,7 +148,9 @@
iface = self._model["nics"]
self.logger.debug("Getting informations for NIC details page")
live = ovirt.node.utils.network.node_nics()[iface]
+ cfg = dict(defaults.Network().retrieve())
+ self.logger.debug(cfg)
self._model.update({
"dialog.nic.iface": live["name"],
"dialog.nic.driver": live["driver"],
@@ -139,100 +159,150 @@
"dialog.nic.link_status": "Connected" if live["link_detected"]
else "Disconnected",
"dialog.nic.hwaddress": live["hwaddr"],
- "dialog.nic.ipv4.bootproto": live["bootproto"],
- "dialog.nic.ipv4.address": live["ipaddr"] or "",
- "dialog.nic.ipv4.netmask": live["netmask"] or "",
- "dialog.nic.ipv4.gateway": live["gateway"] or "",
- "dialog.nic.vlanid": live["vlanid"] or "",
+
+ "dialog.nic.ipv4.bootproto": cfg["bootproto"],
+ "dialog.nic.ipv4.address": cfg["ipaddr"] or "",
+ "dialog.nic.ipv4.netmask": cfg["netmask"] or "",
+ "dialog.nic.ipv4.gateway": cfg["gateway"] or "",
+ "dialog.nic.vlanid": cfg["vlanid"] or "",
})
padd = lambda l: l.ljust(14)
dialog = self._build_dialog("dialog.nic", "NIC Details: %s" % iface, [
- ("dialog.nic._row[0]", ovirt.node.ui.Row([
+ ("dialog.nic._row[0]", ui.Row([
("dialog.nic.iface",
- ovirt.node.ui.KeywordLabel(padd("Interface: "))),
+ ui.KeywordLabel(padd("Interface: "))),
("dialog.nic.driver",
- ovirt.node.ui.KeywordLabel(padd("Driver: "))),
+ ui.KeywordLabel(padd("Driver: "))),
])),
- ("dialog.nic._row[1]", ovirt.node.ui.Row([
+ ("dialog.nic._row[1]", ui.Row([
("dialog.nic.protocol",
- ovirt.node.ui.KeywordLabel(padd("Protocol: "))),
+ ui.KeywordLabel(padd("Protocol: "))),
("dialog.nic.vendor",
- ovirt.node.ui.KeywordLabel(padd("Vendor: "))),
+ ui.KeywordLabel(padd("Vendor: "))),
])),
- ("dialog.nic._row[2]", ovirt.node.ui.Row([
+ ("dialog.nic._row[2]", ui.Row([
("dialog.nic.link_status",
- ovirt.node.ui.KeywordLabel(padd("Link Status: "))),
+ ui.KeywordLabel(padd("Link Status: "))),
("dialog.nic.hwaddress",
- ovirt.node.ui.KeywordLabel(padd("MAC Address: "))),
+ ui.KeywordLabel(padd("MAC Address: "))),
])),
- ("dialog.nic._divider[0]", ovirt.node.ui.Divider()),
+ ("dialog.nic._divider[0]", ui.Divider()),
- ("dialog.nic.ipv4._header", ovirt.node.ui.Header("IPv4 Settings")),
- ("dialog.nic.ipv4.bootproto", ovirt.node.ui.Options(
+ ("dialog.nic.ipv4._header", ui.Header("IPv4 Settings")),
+ ("dialog.nic.ipv4.bootproto", ui.Options(
"Bootprotocol: ", [
("none", "Disabled"),
("dhcp", "DHCP"),
("static", "Static")
])),
("dialog.nic.ipv4.address",
- ovirt.node.ui.Entry(padd("IP Address: "))),
+ ui.Entry(padd("IP Address: "))),
("dialog.nic.ipv4.netmask",
- ovirt.node.ui.Entry(padd("Netmask: "))),
+ ui.Entry(padd("Netmask: "))),
("dialog.nic.ipv4.gateway",
- ovirt.node.ui.Entry(padd("Gateway: "))),
+ ui.Entry(padd("Gateway: "))),
- ("dialog.nic._divider[1]", ovirt.node.ui.Divider()),
+ ("dialog.nic._divider[1]", ui.Divider()),
("dialog.nic.vlanid",
- ovirt.node.ui.Entry(padd("VLAN ID: "))),
+ ui.Entry(padd("VLAN ID: "))),
- ("dialog.nic._buttons", ovirt.node.ui.Row([
+ ("dialog.nic._buttons", ui.Row([
("dialog.nic.save",
- ovirt.node.ui.Button("Save & Close")),
+ ui.Button("Save & Close")),
("dialog.nic.close",
- ovirt.node.ui.Button("Close")),
+ ui.Button("Close")),
]))
])
dialog.has_save_button = False
+
+ self._nic_details_group.enabled(False)
+
return dialog
def on_change(self, changes):
- pass
+ self.logger.info("Checking network stuff")
+ helper = plugins.ChangesHelper(changes)
+ bootproto = helper["dialog.nic.ipv4.bootproto"]
+ if bootproto:
+ if bootproto in ["static"]:
+ self._nic_details_group.enabled(True)
+ else:
+ self._nic_details_group.enabled(False)
+ self._widgets["dialog.nic.ipv4.bootproto"].enabled(True)
def on_merge(self, effective_changes):
+ self.logger.info("Saving network stuff")
changes = self.pending_changes(False)
effective_model = dict(self._model)
effective_model.update(effective_changes)
- self.logger.info("effm %s" % effective_model)
- self.logger.info("effc %s" % effective_changes)
- self.logger.info("allc %s" % changes)
+ self.logger.info("Effective model %s" % effective_model)
+ self.logger.info("Effective changes %s" % effective_changes)
+ self.logger.info("All changes %s" % changes)
- nameservers = []
- for key in ["dns[0]", "dns[1]"]:
- if key in effective_changes:
- nameservers.append(effective_changes[key])
- if nameservers:
- self.logger.info("Setting new nameservers: %s" % nameservers)
- model = ovirt.node.config.defaults.Nameservers()
- model.update(nameservers)
-
- timeservers = []
- for key in ["ntp[0]", "ntp[1]"]:
- if key in effective_changes:
- timeservers.append(effective_changes[key])
- if timeservers:
- self.logger.info("Setting new timeservers: %s" % timeservers)
- model = ovirt.node.config.defaults.Timeservers()
- model.update(timeservers)
-
+ # Special case: A NIC was selected, display that dialog!
if "nics" in changes and len(changes) == 1:
iface = changes["nics"]
self.logger.debug("Opening NIC Details dialog for '%s'" % iface)
return self._build_nic_details_dialog()
- return True
\ No newline at end of file
+ def set_progress(txt):
+ set_progress.txt += txt + "\n"
+ progress.set_text(set_progress.txt)
+ set_progress.txt = "Applying changes ...\n"
+
+ progress = ui.Label(set_progress.txt)
+ d = self.application.ui.show_dialog(self._build_dialog("dialog.dia",
+ "fooo", [
+ ("dialog.dia.text[0]", progress),
+ ]))
+
+ nameservers = []
+ for key in ["dns[0]", "dns[1]"]:
+ if key in effective_changes:
+ nameservers.append(effective_model[key])
+ if nameservers:
+ set_progress("Applying DNS changes.")
+ self.logger.info("Setting new nameservers: %s" % nameservers)
+ model = defaults.Nameservers()
+ model.update(nameservers)
+
+ timeservers = []
+ for key in ["ntp[0]", "ntp[1]"]:
+ if key in effective_changes:
+ timeservers.append(effective_model[key])
+ if timeservers:
+ set_progress("Applying NTP changes.")
+ self.logger.info("Setting new timeservers: %s" % timeservers)
+ model = defaults.Timeservers()
+ model.update(timeservers)
+
+ change_helper = plugins.ChangesHelper(effective_changes)
+ if change_helper.any_key_in_change(self._nic_details_group):
+ # If any networking related key was changed, reconfigure networking
+ helper = plugins.ChangesHelper(effective_model)
+ self._configure_nic(*helper.get_key_values(self._nic_details_group))
+
+ set_progress("All changes were applied.")
+ time.sleep(3)
+ d.close()
+
+ def _configure_nic(self, bootproto, ipaddr, netmask, gateway, vlanid):
+ model = defaults.Network()
+ iface = self._model["dialog.nic.iface"]
+ if bootproto == "none":
+ self.logger.debug("Configuring no networking")
+ model.update(None, None, None, None, None, None)
+ elif bootproto == "dhcp":
+ self.logger.debug("Configuring dhcp")
+ model.update(iface, "dhcp", None, None, None, vlanid)
+ elif bootproto == "static":
+ self.logger.debug("Configuring static ip")
+ model.update(iface, "none", ipaddr, netmask, gateway, vlanid)
+ else:
+ self.logger.debug("No interface configuration found")
diff --git a/scripts/tui/src/ovirt/node/setup/ping.py b/scripts/tui/src/ovirt/node/setup/ping.py
index bb5d8d1..6c6437f 100644
--- a/scripts/tui/src/ovirt/node/setup/ping.py
+++ b/scripts/tui/src/ovirt/node/setup/ping.py
@@ -60,7 +60,7 @@
return {
# The address must be fqdn, ipv4 or ipv6 address
"ping.address": ovirt.node.valid.FQDNOrIPAddress(),
- "ping.count": ovirt.node.valid.Number(min=1, max=20),
+ "ping.count": ovirt.node.valid.Number(range=[1, 20]),
}
def ui_content(self):
diff --git a/scripts/tui/src/ovirt/node/setup/security_page.py b/scripts/tui/src/ovirt/node/setup/security_page.py
index bb62d45..9de6d85 100644
--- a/scripts/tui/src/ovirt/node/setup/security_page.py
+++ b/scripts/tui/src/ovirt/node/setup/security_page.py
@@ -50,9 +50,10 @@
return self._model
def validators(self):
+ number_or_empty = ovirt.node.valid.Number(range=[0, None]) | \
+ ovirt.node.valid.Empty()
return {
- "stringrng.bytes_used": ovirt.node.valid.Number(min=0) | \
- ovirt.node.valid.Empty,
+ "strongrng.num_bytes": number_or_empty,
"passwd.admin.password": ovirt.node.valid.Text(),
"passwd.admin.password_confirmation": ovirt.node.valid.Text(),
}
diff --git a/scripts/tui/src/ovirt/node/setup/status_page.py b/scripts/tui/src/ovirt/node/setup/status_page.py
index 9e19019..c78ae49 100644
--- a/scripts/tui/src/ovirt/node/setup/status_page.py
+++ b/scripts/tui/src/ovirt/node/setup/status_page.py
@@ -48,7 +48,9 @@
def model(self):
net_status, net_br, net_addrs = utils.network.networking_status()
- net_addrs_str = "\nIPv4: {inet}\nIPv6: {inet6}".format(**net_addrs)
+ net_addrs_str = ""
+ if net_addrs:
+ net_addrs_str = "\nIPv4: {inet}\nIPv6: {inet6}".format(**net_addrs)
num_domains = "N/A"
# with virt.LibvirtConnection() as con:
diff --git a/scripts/tui/src/ovirt/node/setup/support_page.py b/scripts/tui/src/ovirt/node/setup/support_page.py
index 992c4ca..5d829c9 100644
--- a/scripts/tui/src/ovirt/node/setup/support_page.py
+++ b/scripts/tui/src/ovirt/node/setup/support_page.py
@@ -30,8 +30,8 @@
class Plugin(ovirt.node.plugins.NodePlugin):
def __init__(self, application):
# Register F8: Display this plugin when F( is pressed
- application.ui.register_hotkey(["f8"],
- lambda: application.ui.display_plugin(self))
+ display_page = lambda: application.ui.display_page(self.ui_content())
+ application.ui.register_hotkey(["f8"], display_page)
def name(self):
return "Support"
diff --git a/scripts/tui/src/ovirt/node/ui/__init__.py b/scripts/tui/src/ovirt/node/ui/__init__.py
index 2423f67..cc4191a 100644
--- a/scripts/tui/src/ovirt/node/ui/__init__.py
+++ b/scripts/tui/src/ovirt/node/ui/__init__.py
@@ -229,7 +229,7 @@
self.char = char
-class Options(Element):
+class Options(InputElement):
"""A selection of options
Args:
@@ -237,7 +237,7 @@
options:
"""
def __init__(self, label, options):
- super(Options, self).__init__()
+ super(Options, self).__init__(None, True)
self.label = label
self.options = options
self.option(options[0])
@@ -348,5 +348,23 @@
self.logger.debug("Registering hotkey '%s': %s" % (hotkey, cb))
self._hotkeys[str(hotkey)] = cb
+ def show_dialog(self, dialog):
+ """Show a dialog.
+ The dialog can be closed using dialog.close()
+
+ Args:
+ dialog: The dialog to be shown
+ """
+ raise NotImplementedError
+
+ def show_page(self, page):
+ """Show / switch to a page.
+ Displays the given page (which does not need to be patr of a plugin)
+
+ Args:
+ page: The page to be shown
+ """
+ raise NotImplementedError
+
def run(self):
raise NotImplementedError
diff --git a/scripts/tui/src/ovirt/node/ui/builder.py b/scripts/tui/src/ovirt/node/ui/builder.py
index 18718e9..471657e 100644
--- a/scripts/tui/src/ovirt/node/ui/builder.py
+++ b/scripts/tui/src/ovirt/node/ui/builder.py
@@ -125,12 +125,16 @@
widget_class = ovirt.node.ui.widgets.PasswordEntry
widget = widget_class(item.label, align_vertical=item.align_vertical)
- widget.enable(item.enabled)
+ widget.enable(item.enabled())
def on_item_enabled_change_cb(w, v):
LOGGER.debug("Element changed, updating entry '%s': %s" % (w, v))
if widget.selectable() != v:
widget.enable(v)
+ if v == False:
+ widget.notice = ""
+ widget.valid(True)
+
item.connect_signal("enabled", on_item_enabled_change_cb)
def on_widget_value_change(widget, new_value):
@@ -148,14 +152,15 @@
except ovirt.node.exceptions.InvalidData as e:
LOGGER.error("Invalid data when updating: %s" % e)
- widget.notice = e.message
+ if widget._selectable:
+ widget.notice = e.message
widget.valid(False)
plugin._save_button.enable(False)
# FIXME page validation must happen within tui, not plugin
# as UI data should be handled in tui
- tui.draw_screen()
+ tui._draw_screen()
urwid.connect_signal(widget, 'change', on_widget_value_change)
return widget
@@ -175,7 +180,7 @@
widget.text(v)
# Redraw the screen if widget text is updated "outside" of the
# mainloop
- tui.draw_screen()
+ tui._draw_screen()
item.connect_signal("text", on_item_text_change_cb)
return widget
@@ -237,7 +242,7 @@
def on_item_current_change_cb(w, v):
LOGGER.debug("Model changed, updating progressbar '%s': %s" % (w, v))
widget.set_completion(v)
- tui.draw_screen()
+ tui._draw_screen()
item.connect_signal("current", on_item_current_change_cb)
return widget
@@ -276,13 +281,11 @@
if type(result) in [ovirt.node.ui.Page]:
LOGGER.debug("Page requested.")
- w = build_page(tui, plugin, result)
- tui.display_page(w)
+ tui.show_page(result)
elif type(result) in [ovirt.node.ui.Dialog]:
LOGGER.debug("Dialog requested.")
- w = build_page(tui, plugin, result)
- dialog = tui.display_dialog(w, result.title)
+ dialog = tui.show_dialog(result)
def on_item_close_changed_cb(i, v):
dialog.close()
diff --git a/scripts/tui/src/ovirt/node/ui/tui.py b/scripts/tui/src/ovirt/node/ui/tui.py
index ab1f005..b6a2a8d 100644
--- a/scripts/tui/src/ovirt/node/ui/tui.py
+++ b/scripts/tui/src/ovirt/node/ui/tui.py
@@ -23,15 +23,12 @@
The urwid TUI base library
"""
+import timeit
import urwid
-import logging
-import timeit
-
-import ovirt.node.ui.widgets
+from ovirt.node import ui
import ovirt.node.ui.builder
-
-LOGGER = logging.getLogger(__name__)
+import ovirt.node.ui.widgets
class UrwidTUI(ovirt.node.ui.Window):
@@ -50,14 +47,17 @@
_current_plugin = None
header = u"\n Configuration TUI\n"
- footer = u"Press ctrl+c to exit"
+ footer = u"Press ctrl+c to quit"
element_styles = {
- "text": "dark gray",
- "label": "dark gray, bold",
+ "text": "black",
+ "label": "black, bold",
+ "disabled": "white",
+ "background": "light gray"
}
- palette = [(None, 'default', 'light gray', 'bold', None, None),
+ palette = [(None, 'default', element_styles["background"], 'bold',
+ None, None),
('screen', None),
('header', 'white', 'dark blue'),
('table', element_styles["text"]),
@@ -69,10 +69,12 @@
('main.menu.frame', element_styles["text"]),
('notice', 'light red'),
('plugin.widget.entry', element_styles["text"]),
- ('plugin.widget.entry.disabled', 'dark gray', 'light gray'),
+ ('plugin.widget.entry.disabled', element_styles["disabled"]),
('plugin.widget.entry.label', element_styles["label"]),
('plugin.widget.entry.frame', element_styles["text"]),
('plugin.widget.entry.frame.invalid', 'dark red'),
+ ('plugin.widget.entry.frame.disabled',
+ element_styles["disabled"]),
('plugin.widget.notice', 'light red'),
('plugin.widget.header', 'black, bold'),
('plugin.widget.divider', element_styles["text"]),
@@ -94,11 +96,53 @@
super(UrwidTUI, self).__init__(app)
self.logger.info("Creating urwid tui for '%s'" % app)
+ def show_body(self, body):
+ """
+ """
+ assert type(body) is ui.Page
+ widget = ui.builder.build_page(self, self._current_plugin, body)
+ self.__display_as_body(widget)
+
+ def show_page(self, page):
+ """Shows the ui.Page as a page.
+ This transforms the abstract ui.Page to a urwid specififc version
+ and displays it.
+ """
+ assert type(page) is ui.Page
+ widget = ui.builder.build_page(self, self._current_plugin, page)
+ self.__display_as_page(widget)
+
+ def show_dialog(self, dialog):
+ """Shows the ui.Dialog as a dialog.
+ This transforms the abstract ui.Dialog to a urwid specififc version
+ and displays it.
+ """
+ assert type(dialog) is ui.Dialog
+ widget = ui.builder.build_page(self, self._current_plugin, dialog)
+ return self.__display_as_dialog(widget, dialog.title)
+
+ def quit(self):
+ """Quit the UI
+ """
+ self.logger.info("Quitting, exitting mainloop")
+ raise urwid.ExitMainLoop()
+
+ def run(self):
+ """Run the UI
+ """
+ self.__main_frame = self.__create_screen()
+ self.__register_default_hotkeys()
+
+ self.__loop = urwid.MainLoop(self.__main_frame,
+ self._convert_palette(),
+ input_filter=self.__filter_hotkeys)
+ self.__loop.run()
+
def __build_menu(self):
self.__menu = ovirt.node.ui.widgets.PluginMenu(self._plugins)
def menu_item_changed(plugin):
- self.display_plugin(plugin)
+ self.__display_plugin(plugin)
urwid.connect_signal(self.__menu, 'changed', menu_item_changed)
def __create_screen(self):
@@ -123,97 +167,122 @@
screen = urwid.Frame(body, header, footer)
return urwid.AttrMap(screen, "screen")
- def display_plugin(self, plugin):
- if self._check_outstanding_changes():
- return
- timer = timeit.Timer()
- self._current_plugin = plugin
- page = ovirt.node.ui.builder.page_from_plugin(self, plugin)
- self.display_page(page)
- LOGGER.debug("Build and displayed page in %ss" % timer.timeit())
-
def _check_outstanding_changes(self):
- has_outstanding_changes = False
+ has_outstanding_changes = False
if self._current_plugin:
pending_changes = self._current_plugin.pending_changes()
if pending_changes:
- LOGGER.warning("Pending changes: %s" % pending_changes)
+ self.logger.warning("Pending changes: %s" % pending_changes)
msg = ""
widgets = dict(self._current_plugin.ui_content().children)
- LOGGER.debug("Available widgets: %s" % widgets)
+ self.logger.debug("Available widgets: %s" % widgets)
for path, value in pending_changes.items():
if path in widgets:
field = widgets[path].name
msg += "- %s\n" % (field.strip(":"))
- self.display_dialog(urwid.Filler(urwid.Text(
+ self.__display_as_dialog(urwid.Filler(urwid.Text(
"The following fields were changed:\n%s" % msg)),
"Pending changes")
has_outstanding_changes = True
return has_outstanding_changes
- def display_page(self, page):
- LOGGER.debug("Displaying page %s" % page)
+ def __display_as_body(self, widget):
+ self.__main_frame.body = widget
+
+ def __display_as_page(self, page):
+ self.logger.debug("Displaying page %s" % page)
# filler = urwid.Filler(page, ("fixed top", 1), height=35)
filler = urwid.Pile([page])
self.__page_frame.body = filler
- def display_dialog(self, body, title):
- LOGGER.debug("Displaying dialog: %s / %s" % (body, title))
+ def __display_plugin(self, plugin):
+ if self._check_outstanding_changes():
+ return
+ timer = timeit.Timer()
+ self._current_plugin = plugin
+ plugin_page = ovirt.node.ui.builder.page_from_plugin(self, plugin)
+ self.__display_as_page(plugin_page)
+ self.logger.debug("Build and displayed plugin_page in %ss" %
+ timer.timeit())
+
+ def __display_as_dialog(self, body, title):
+ self.logger.debug("Displaying dialog: %s / %s" % (body, title))
# filler = urwid.Filler(body, ("fixed top", 1), height=35)
filler = urwid.Pile([body])
dialog = ovirt.node.ui.widgets.ModalDialog(title, filler, "esc",
self.__loop.widget)
urwid.connect_signal(dialog, "close",
- lambda: self.close_dialog(dialog))
+ lambda: self.__close_dialog(dialog))
self.__loop.widget = dialog
self.__widget_stack.append(dialog)
+ self._draw_screen()
return dialog
- def close_dialog(self, dialog):
- # FIXME stack to allow more than one dialog
+ def __close_dialog(self, dialog):
if type(self.__loop.widget) is ovirt.node.ui.widgets.ModalDialog:
if dialog == self.__widget_stack[-1]:
self.__widget_stack.pop()
if len(self.__widget_stack) > 0:
self.__loop.widget = self.__widget_stack[:-1]
else:
- LOGGER.debug("No more dialog, main frame " + \
+ self.logger.debug("No more dialog, main frame " + \
"%s" % self.__main_frame)
self.__loop.widget = self.__main_frame
- self.draw_screen()
- LOGGER.debug("Dialog closed")
-
- def popup(self, title, msg, buttons=None):
- LOGGER.debug("Launching popup")
- body = urwid.Filler(urwid.Text(msg))
- self.display_dialog(body)
+ self.logger.debug("Loop widget: %s" % self.__loop.widget)
+ self._draw_screen()
+ self.logger.debug("Dialog closed")
def __filter_hotkeys(self, keys, raw):
key = str(keys)
if type(self.__loop.widget) is ovirt.node.ui.widgets.ModalDialog:
- LOGGER.debug("Modal dialog escape: %s" % key)
+ self.logger.debug("Modal dialog escape: %s" % key)
if self.__loop.widget.escape_key in keys:
- self.close_dialog(self.__widget_stack[-1])
+ self.__close_dialog(self.__widget_stack[-1])
return
if key in self._hotkeys.keys():
- LOGGER.debug("Running hotkeys: %s" % key)
+ self.logger.debug("Running hotkeys: %s" % key)
self._hotkeys[key]()
- LOGGER.debug("Keypress: %s" % key)
+ self.logger.debug("Keypress: %s" % key)
return keys
def __register_default_hotkeys(self):
self.register_hotkey(["esc"], self.quit)
self.register_hotkey(["q"], self.quit)
+ self.register_hotkey(["window resize"], self._check_min_size_cb)
- def draw_screen(self):
+ def _draw_screen(self):
self.__loop.draw_screen()
def size(self):
+ if not self.__loop.screen:
+ # FIXME sometimes screen is None, but why?
+ return (0, 0)
return self.__loop.screen.get_cols_rows()
+
+ def _min_size(self):
+ return (80, 23)
+
+ def _check_min_size_cb(self):
+ size = self.size()
+ msize = self._min_size()
+ width, height = size
+ min_width, min_height = msize
+ if width < min_width or height < min_height:
+ msg = ("The current window size %s is smaller " +
+ "than the minimum size %s") % (size, msize)
+ self.logger.warning(msg)
+ if not hasattr(self, "_error_dialog") or not self._error_dialog:
+ d = ui.Dialog("Error", [("dialog.error", ui.Label(msg))])
+ d.has_save_button = False
+ self._error_dialog = self.show_dialog(d)
+ else:
+ if hasattr(self, "_error_dialog") and self._error_dialog:
+ self._error_dialog.close()
+ self._error_dialog = None
def watch_pipe(self, cb):
"""Return a fd to be used as stdout, cb called for each line
@@ -221,7 +290,7 @@
return self.__loop.watch_pipe(cb)
def notify(self, category, msg):
- LOGGER.info("UI notification (%s): %s" % (category, msg))
+ self.logger.info("UI notification (%s): %s" % (category, msg))
# FIXME do notification
def suspended(self):
@@ -237,12 +306,6 @@
def __exit__(self, a, b, c):
self.__loop.screen.start()
return SuspendedScreen(self.__loop)
-
- def quit(self):
- """Quit the UI
- """
- LOGGER.info("Quitting, exitting mainloop")
- raise urwid.ExitMainLoop()
def _convert_palette(self):
"""Convert our palette to the format urwid understands.
@@ -264,14 +327,3 @@
rest = default[len(colors):]
palette.append(tuple([k] + colors + rest))
return palette
-
- def run(self):
- """Run the UI
- """
- self.__main_frame = self.__create_screen()
- self.__register_default_hotkeys()
-
- self.__loop = urwid.MainLoop(self.__main_frame,
- self._convert_palette(),
- input_filter=self.__filter_hotkeys)
- self.__loop.run()
diff --git a/scripts/tui/src/ovirt/node/ui/widgets.py b/scripts/tui/src/ovirt/node/ui/widgets.py
index 05ddbcf..f32c47e 100644
--- a/scripts/tui/src/ovirt/node/ui/widgets.py
+++ b/scripts/tui/src/ovirt/node/ui/widgets.py
@@ -292,16 +292,21 @@
def enable(self, is_enabled):
self._selectable = is_enabled
- attr_map = {None: "plugin.widget.entry"}
+ edit_attr_map = {None: "plugin.widget.entry"}
+ linebox_attr_map = {None: "plugin.widget.entry.frame"}
if not is_enabled:
- attr_map = {None: "plugin.widget.entry.disabled"}
- self._edit_attrmap.set_attr_map(attr_map)
+ edit_attr_map = {None: "plugin.widget.entry.disabled"}
+ linebox_attr_map = {None: "plugin.widget.entry.frame.disabled"}
+ self._edit_attrmap.set_attr_map(edit_attr_map)
+ self._linebox_attrmap.set_attr_map(linebox_attr_map)
def valid(self, is_valid):
attr_map = {None: "plugin.widget.entry.frame"}
if not is_valid:
attr_map = {None: "plugin.widget.entry.frame.invalid"}
- self._linebox_attrmap.set_attr_map(attr_map)
+ if self._selectable:
+ # Only update style if it is selectable/enabled
+ self._linebox_attrmap.set_attr_map(attr_map)
def set_text(self, txt):
self._edit.set_edit_text(txt)
diff --git a/scripts/tui/src/ovirt/node/utils/network.py b/scripts/tui/src/ovirt/node/utils/network.py
index 4e134e8..17c0ef3 100644
--- a/scripts/tui/src/ovirt/node/utils/network.py
+++ b/scripts/tui/src/ovirt/node/utils/network.py
@@ -182,6 +182,7 @@
n.startswith("vnet") or \
n.startswith("tun") or \
n.startswith("wlan") or \
+ n.startswith("virbr") or \
(filter_vlans and ("." in n)))
# FIXME!!!
# valid_props = lambda i, p: (filter_bridges and (p["type"] != "bridge"))
@@ -382,11 +383,15 @@
status = "Not connected"
iface = iface or node_bridge()
- addresses = nic_ip_addresses(iface)
- has_address = any([a != None for a in addresses.values()])
+ addresses = []
+ if iface:
+ addresses = nic_ip_addresses(iface)
+ has_address = any([a != None for a in addresses.values()])
- if nic_link_detected(iface) and has_address:
- status = "Connected"
+ if nic_link_detected(iface):
+ status = "Connected (Link only, no IP)"
+ if has_address:
+ status = "Connected"
summary = (status, iface, addresses)
LOGGER.debug(summary)
diff --git a/scripts/tui/src/ovirt/node/valid.py b/scripts/tui/src/ovirt/node/valid.py
index e47a58e..af00158 100644
--- a/scripts/tui/src/ovirt/node/valid.py
+++ b/scripts/tui/src/ovirt/node/valid.py
@@ -127,25 +127,32 @@
True
>>> Number()("42")
True
+ >>> Number(range=[0, None]).validate(-10)
+ False
+ >>> Number(range=[0, 10]).validate(11)
+ False
>>> Number().validate("4 2")
False
"""
description = "a number"
- pattern = "^[-]?\d+$"
- minmax = (None, None)
+ pattern = "^[-+]?\d+$"
+ range = [None, None]
- def __init__(self, min=None, max=None):
- if min or max:
- self.minmax = (min, max)
- self.description = "%s (%s - %s)" % (self.description, min, max)
+ def __init__(self, range=None):
+ super(Number, self).__init__()
+ if range:
+ self.range = range
+ self.description = "%s in the range %s" % (self.description, range)
def validate(self, value):
valid = RegexValidator.validate(self, value)
if valid:
- min, max = self.minmax
+ self.logger.debug("Checking range: %s" % self.range)
+ vmin, vmax = self.range
value = int(value)
- if (min and value < min) or (max and value > max):
+ if (vmin != None and value < vmin) or \
+ (vmax != None and value > vmax):
valid = False
return valid
@@ -164,7 +171,7 @@
description = "a port number"
def __init__(self):
- super(Port, self).__init__(1, 65535)
+ super(Port, self).__init__(range=[1, 65535])
class NoSpaces(RegexValidator):
@@ -302,8 +309,12 @@
class Empty(Validator):
description = "an empty string"
+ def __init__(self, or_none=False):
+ super(Empty, self).__init__()
+ self.or_none = or_none
+
def validate(self, value):
- return value == ""
+ return value == "" or (self.or_none and value == None)
class URL(Validator):
--
To view, visit http://gerrit.ovirt.org/9934
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie20873b30fa18250fa9fdbe7e84753cb96bd67a8
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-node
Gerrit-Branch: master
Gerrit-Owner: Fabian Deutsch <fabiand at fedoraproject.org>
More information about the node-patches
mailing list