[node-patches] Change in ovirt-node[master]: defaults: Build objects around configuration
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: defaults: Build objects around configuration
......................................................................
defaults: Build objects around configuration
Each configuration item (e.g. network, snmp, ...) can now be configured
using the appropriate defaults.* class.
Change-Id: I684d85f1689ab97d22e5be4b5c740676751464c1
Signed-off-by: Fabian Deutsch <fabiand at fedoraproject.org>
---
M scripts/tui/bin/ovirt-config-installer
M scripts/tui/bin/ovirt-config-setup
R scripts/tui/src/ovirt/node/app.py
D scripts/tui/src/ovirt/node/app/installer.py
M scripts/tui/src/ovirt/node/base.py
M scripts/tui/src/ovirt/node/config/__init__.py
M scripts/tui/src/ovirt/node/config/defaults.py
R scripts/tui/src/ovirt/node/installer/__init__.py
R scripts/tui/src/ovirt/node/plugins.py
D scripts/tui/src/ovirt/node/plugins/setup/__init__.py
A scripts/tui/src/ovirt/node/setup/__init__.py
R scripts/tui/src/ovirt/node/setup/__main__.py
R scripts/tui/src/ovirt/node/setup/engine_page.py
R scripts/tui/src/ovirt/node/setup/example.py
R scripts/tui/src/ovirt/node/setup/features.py
R scripts/tui/src/ovirt/node/setup/kdump_page.py
R scripts/tui/src/ovirt/node/setup/keyboard_page.py
R scripts/tui/src/ovirt/node/setup/logging_page.py
R scripts/tui/src/ovirt/node/setup/monitoring_page.py
R scripts/tui/src/ovirt/node/setup/network_page.py
R scripts/tui/src/ovirt/node/setup/ping.py
R scripts/tui/src/ovirt/node/setup/remote_storage_page.py
R scripts/tui/src/ovirt/node/setup/security_page.py
R scripts/tui/src/ovirt/node/setup/snmp_page.py
R scripts/tui/src/ovirt/node/setup/status_page.py
R scripts/tui/src/ovirt/node/setup/support_page.py
R scripts/tui/src/ovirt/node/setup/usage.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/utils/fs.py
M scripts/tui/src/ovirt/node/utils/security.py
M scripts/tui/src/ovirt/node/valid.py
33 files changed, 484 insertions(+), 210 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/ovirt-node refs/changes/32/9932/1
diff --git a/scripts/tui/bin/ovirt-config-installer b/scripts/tui/bin/ovirt-config-installer
index f50eca4..9f97418 100755
--- a/scripts/tui/bin/ovirt-config-installer
+++ b/scripts/tui/bin/ovirt-config-installer
@@ -5,4 +5,4 @@
#export PYTHONUNBUFFERED=x
#export PYTHONDEBUG=
#export PYTHONVERBOSE=x
-python -t -m ovirt.node.app.installer "$@"
+python -t -m ovirt.node.installer "$@"
diff --git a/scripts/tui/bin/ovirt-config-setup b/scripts/tui/bin/ovirt-config-setup
index af0610b..0a65367 100755
--- a/scripts/tui/bin/ovirt-config-setup
+++ b/scripts/tui/bin/ovirt-config-setup
@@ -5,4 +5,4 @@
#export PYTHONUNBUFFERED=x
#export PYTHONDEBUG=
#export PYTHONVERBOSE=x
-python -t -m ovirt.node.app.setup "$@"
+python -t -m ovirt.node.setup "$@"
diff --git a/scripts/tui/src/ovirt/node/app/__init__.py b/scripts/tui/src/ovirt/node/app.py
similarity index 62%
rename from scripts/tui/src/ovirt/node/app/__init__.py
rename to scripts/tui/src/ovirt/node/app.py
index 92f57fc..63be409 100644
--- a/scripts/tui/src/ovirt/node/app/__init__.py
+++ b/scripts/tui/src/ovirt/node/app.py
@@ -24,46 +24,69 @@
which communicate with each other.
"""
+import argparse
import logging
logging.basicConfig(level=logging.DEBUG,
filename="app.log", filemode="w",
format="%(asctime)s %(levelname)s %(name)s %(message)s")
-LOGGER = logging.getLogger(__name__)
import ovirt.node.ui.tui
-import ovirt.node.utils
-import ovirt.node.plugins
+from ovirt.node import base, utils, plugins
+from ovirt.node.config import defaults
-class Application(object):
+class Application(base.Base):
plugins = []
ui = None
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]
self.ui = ui_backend_class(self)
self.plugin_base = plugin_base
+ def __parse_cmdline(self):
+ parser = argparse.ArgumentParser(description='oVirt Node Utility')
+ parser.add_argument("--config",
+ type=str,
+ help="Central oVirt Node configuration file")
+ args = parser.parse_args()
+ self.logger.debug("Parsed args: %s" % args)
+ if args.config:
+ defaults.OVIRT_NODE_DEFAULTS_FILENAME = args.config
+ self.logger.debug("Setting config file: %s (%s)" % (
+ args.config,
+ defaults.OVIRT_NODE_DEFAULTS_FILENAME))
+
def __load_plugins(self):
- self.plugins = [m.Plugin(self) for m in ovirt.node.plugins.load(self.plugin_base)]
+ self.plugins = []
+ for m in plugins.load(self.plugin_base):
+ if hasattr(m, "Plugin"):
+ self.logger.debug("Found plugin in module: %s" % m)
+ plugin = m.Plugin(self)
+ self.plugins.append(plugin)
+ else:
+ self.logger.debug("Found no plugin in module: %s" % m)
for plugin in self.plugins:
- LOGGER.debug("Loading plugin %s" % plugin)
+ self.logger.debug("Loading plugin %s" % plugin)
self.ui.register_plugin(plugin.ui_name(), plugin)
def __drop_to_shell(self):
with self.ui.suspended():
- ovirt.node.utils.process.system("reset ; bash")
+ utils.process.system("reset ; bash")
def __check_terminal_size(self):
cols, rows = self.ui.size()
if cols < 80 or rows < 24:
- 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
@@ -82,5 +105,5 @@
self.ui.run()
def quit(self):
- LOGGER.info("Quitting")
- self.ui.quit()
\ No newline at end of file
+ self.logger.info("Quitting")
+ self.ui.quit()
diff --git a/scripts/tui/src/ovirt/node/app/installer.py b/scripts/tui/src/ovirt/node/app/installer.py
deleted file mode 100644
index ae6e730..0000000
--- a/scripts/tui/src/ovirt/node/app/installer.py
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/python
-#
-# ovirt-config-setup.py - Copyright (C) 2012 Red Hat, Inc.
-# Written by Fabian Deutsch <fabiand at redhat.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# 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 General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# 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.
-
-"""
-Create an installer application instance an start it.
-"""
-
-import ovirt.node.app
-import ovirt.node.plugins.installer
-
-
-if __name__ == '__main__':
- app = ovirt.node.app.Application(ovirt.node.plugins.installer)
- app.run()
diff --git a/scripts/tui/src/ovirt/node/base.py b/scripts/tui/src/ovirt/node/base.py
index 7b8c055..87d0138 100644
--- a/scripts/tui/src/ovirt/node/base.py
+++ b/scripts/tui/src/ovirt/node/base.py
@@ -35,4 +35,4 @@
def __init__(self):
"""Contructor."""
- self._logger = logging.getLogger(self.__module__)
\ No newline at end of file
+ self._logger = logging.getLogger(self.__module__)
diff --git a/scripts/tui/src/ovirt/node/config/__init__.py b/scripts/tui/src/ovirt/node/config/__init__.py
index 5bcef55..cc4a463 100644
--- a/scripts/tui/src/ovirt/node/config/__init__.py
+++ b/scripts/tui/src/ovirt/node/config/__init__.py
@@ -1,3 +1,6 @@
"""
This package is expected to contain modules which handle locale config files.
-"""
\ No newline at end of file
+
+All the informations provided by any module in this package must be derived
+from some file.
+"""
diff --git a/scripts/tui/src/ovirt/node/config/defaults.py b/scripts/tui/src/ovirt/node/config/defaults.py
index 44f0aa1..9385e0e 100644
--- a/scripts/tui/src/ovirt/node/config/defaults.py
+++ b/scripts/tui/src/ovirt/node/config/defaults.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# model.py - Copyright (C) 2012 Red Hat, Inc.
+# defaults.py - Copyright (C) 2012 Red Hat, Inc.
# Written by Fabian Deutsch <fabiand at redhat.com>
#
# This program is free software; you can redistribute it and/or modify
@@ -28,7 +28,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 CentralNodeConfiguration for more informations.
Each class should implement a configure method, mainly to define all the
required arguments (or keys).
@@ -37,9 +37,8 @@
import logging
import glob
-import ovirt.node.utils
import ovirt.node.config
-from ovirt.node import base
+from ovirt.node import base, exceptions, valid, utils
LOGGER = logging.getLogger(__name__)
@@ -47,93 +46,187 @@
OVIRT_NODE_DEFAULTS_FILENAME = "/etc/defaults/ovirt"
-def defaults(new_dict=None, filename=OVIRT_NODE_DEFAULTS_FILENAME,
- remove_empty=False):
- """Reads /etc/defaults/ovirt and creates a dictionary
- The dict will contain all OVIRT_* entries of the defaults file.
+class AugeasProvider(base.Base):
+ def __init__(self, filename):
+ super(AugeasProvider, self).__init__()
+ self.filename = filename
- Args:
- new_dict: New values to be used for setting the defaults
- filename: The filename to read the defaults from
- remove_empty: Remove a key from defaults file, if the new value is None
- Returns:
- A dict
+ def update(self, new_dict, remove_empty):
+ aug = utils.AugeasWrapper()
+ basepath = "/files/%s/" % self.filename.strip("/")
+ if new_dict:
+ # If values are given, update the file
+ LOGGER.debug("Updating oVirtNode defaults file '%s': %s %s" % (
+ self.filename,
+ new_dict,
+ basepath))
+ aug.set_many(new_dict, basepath)
+
+ if remove_empty:
+ paths_to_be_removed = [p for p, v in new_dict.items()
+ if v is None]
+ aug.remove_many(paths_to_be_removed, basepath)
+
+ def get_dict(self):
+ aug = utils.AugeasWrapper()
+ basepath = "/files/%s/" % self.filename.strip("/")
+
+ # Retrieve all entries of the default file and return their values
+ paths = aug.match(basepath + "*")
+ return aug.get_many(paths, strip_basepath=basepath)
+
+
+class SimpleProvider(base.Base):
+ """Can write our simple configuration file
+
+ >>> fn = "/tmp/cfg_dummy.simple"
+ >>> open(fn, "w").close()
+ >>> cfg = {
+ ... "IP_ADDR": "127.0.0.1",
+ ... "NETMASK": "255.255.255.0",
+ ... }
+ >>> p = SimpleProvider(fn)
+ >>> p.get_dict()
+ {}
+ >>> p.update(cfg, True)
+ >>> p.get_dict() == cfg
+ True
"""
+ def __init__(self, filename):
+ super(SimpleProvider, self).__init__()
+ self.filename = filename
+ self.logger.debug("Using %s" % self.filename)
- aug = ovirt.node.utils.AugeasWrapper()
- basepath = "/files/%s/" % filename.strip("/")
- if new_dict:
- # If values are given, update the file
- LOGGER.debug("Updating oVirtNode defaults file '%s': %s %s" % (
- filename,
- new_dict,
- basepath))
- aug.set_many(new_dict, basepath)
+ def update(self, new_dict, remove_empty):
+ cfg = self.get_dict()
+ cfg.update(new_dict)
- if remove_empty:
- paths_to_be_removed = [p for p, v in new_dict.items() if v is None]
- aug.remove_many(paths_to_be_removed, basepath)
+ for key, value in cfg.items():
+ if remove_empty and value is None:
+ del cfg[key]
+ assert type(value) in [str, unicode] or value is None
+ self._write(cfg)
- # Retrieve all entries of the default file and return their values
- paths = aug.match(basepath + "*")
- return aug.get_many(paths, strip_basepath=basepath)
+ def get_dict(self):
+ cfg = {}
+ with open(self.filename) as source:
+ for line in source:
+ if line.startswith("#"):
+ continue
+ key, value = line.split("=", 1)
+ cfg[key] = value.strip("\"' \n")
+ return cfg
+
+ def _write(self, cfg):
+ # FIXME make atomic
+ contents = []
+ # Sort the dict, looks nicer
+ for key in sorted(cfg.iterkeys()):
+ contents.append("%s='%s'" % (key, cfg[key]))
+ with open(self.filename, "w+") as dst:
+ dst.write("\n".join(contents))
-def map_and_update_defaults(func):
- """
- >>> class Foo(object):
- ... keys = None
- ... def _map_config_and_update_defaults(self, *args, **kwargs):
- ... return kwargs
- ... @map_and_update_defaults
- ... def meth(self, a, b):
- ... assert type(a) is int
- ... assert type(b) is int
- >>> foo = Foo()
- >>> foo.keys = ("OVIRT_A", "OVIRT_B")
- >>> foo.meth(1, 2)
- {'OVIRT_A': 1, 'OVIRT_B': 2}
- """
- def wrapper(self, *args, **kwargs):
- new_dict = dict(zip(self.keys, args))
- func(self, *args, **kwargs)
- return self._map_config_and_update_defaults(**new_dict)
- return wrapper
+class ConfigFile(base.Base):
+ def __init__(self, filename=None, provider_class=None):
+ super(ConfigFile, self).__init__()
+ filename = filename or OVIRT_NODE_DEFAULTS_FILENAME
+ provider_class = provider_class or SimpleProvider
+ self.provider = provider_class(filename)
+
+ def update(self, new_dict, remove_empty=False):
+ """Reads /etc/defaults/ovirt and creates a dictionary
+ The dict will contain all OVIRT_* entries of the defaults file.
+
+ Args:
+ new_dict: New values to be used for setting the defaults
+ filename: The filename to read the defaults from
+ remove_empty: Remove a key from defaults file, if the new value
+ is None
+ Returns:
+ A dict
+ """
+ self.logger.debug("Updating defaults: %s" % new_dict)
+ self.logger.debug("Removing empty entries? %s" % remove_empty)
+ self.provider.update(new_dict, remove_empty)
+
+ def get_dict(self):
+ return self.provider.get_dict()
class CentralNodeConfiguration(base.Base):
- def __init__(self, keys):
- assert type(keys) is tuple, "Keys need to have an order, " + \
- "therefor a tuple expected"
- self.keys = keys
+ def __init__(self, cfgfile=None):
+ super(CentralNodeConfiguration, self).__init__()
+ self.defaults = cfgfile or ConfigFile()
- def configure(self, *args, **kwargs):
+ def update(self, *args, **kwargs):
"""This function set's the correct entries in the defaults file for
that specififc subclass.
Is expected to call _map_config_and_update_defaults()
"""
raise NotImplementedError
- def _map_config_and_update_defaults(self, *args, **kwargs):
- assert len(args) == 0
- assert (set(self.keys) ^ set(kwargs.keys())) == set()
- new_dict = {k.upper(): v for k, v in kwargs.items()}
- defaults(new_dict, remove_empty=True)
-
- def apply_config(self, *args, **kwargs):
- """This method updates the to this subclass specififc configuration
+ def apply(self, *args, **kwargs):
+ """This method updates the to this subclass specific configuration
files according to the config keys set with configure.
"""
raise NotImplementedError
- def get_config(self):
+ def retrieve(self):
"""Returns the config keys of the current component
"""
- items = {}
- for key, value in defaults().items():
- if key in self.keys:
- items[key] = value
- return items
+ func = self.update.wrapped_func
+ varnames = func.func_code.co_varnames[1:]
+ values = ()
+ cfg = self.defaults.get_dict()
+ for key in self.keys:
+ value = cfg[key] if key in cfg else ""
+ values += (value,)
+ assert len(varnames) == len(values)
+ return zip(varnames, values)
+
+ def clear(self):
+ """Remove the configuration for this item
+ """
+ cfg = self.defaults.get_dict()
+ to_be_deleted = {k: None for k in self.keys}
+ cfg.update(to_be_deleted)
+ self.defaults.update(cfg, remove_empty=True)
+
+ def _map_config_and_update_defaults(self, *args, **kwargs):
+ assert len(args) == 0
+ assert (set(self.keys) ^ set(kwargs.keys())) == set()
+ new_dict = {k.upper(): v for k, v in kwargs.items()}
+ self.defaults.update(new_dict, remove_empty=True)
+
+ @staticmethod
+ def map_and_update_defaults_decorator(func):
+ """
+ >>> class Foo(object):
+ ... keys = None
+ ... def _map_config_and_update_defaults(self, *args, **kwargs):
+ ... return kwargs
+ ... @CentralNodeConfiguration.map_and_update_defaults_decorator
+ ... def meth(self, a, b, c):
+ ... assert type(a) is int
+ ... assert type(b) is int
+ ... return {"OVIRT_C": "c%s" % c}
+ >>> foo = Foo()
+ >>> foo.keys = ("OVIRT_A", "OVIRT_B", "OVIRT_C")
+ >>> foo.meth(1, 2, 3)
+ {'OVIRT_A': 1, 'OVIRT_B': 2, 'OVIRT_C': 'c3'}
+ """
+ def wrapper(self, *args, **kwargs):
+ if len(self.keys) != len(args):
+ raise Exception("There are not enough arguments given for " +
+ "%s of %s" % (func, self))
+ new_cfg = dict(zip(self.keys, args))
+ custom_cfg = func(self, *args, **kwargs) or {}
+ assert type(custom_cfg) is dict, "%s must return a dict" % func
+ new_cfg.update(custom_cfg)
+ return self._map_config_and_update_defaults(**new_cfg)
+ wrapper.wrapped_func = func
+ return wrapper
class Network(CentralNodeConfiguration):
@@ -142,29 +235,72 @@
- OVIRT_IP_ADDRESS, OVIRT_IP_NETMASK, OVIRT_IP_GATEWAY
- OVIRT_VLAN
- OVIRT_IPV6
+
+ >>> fn = "/tmp/cfg_dummy"
+ >>> cfgfile = ConfigFile(fn, SimpleProvider)
+ >>> n = Network(cfgfile)
+ >>> n.update("eth0", "static", "10.0.0.1", "255.0.0.0", "10.0.0.255",
+ ... "20")
+ >>> data = n.retrieve()
+ >>> 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')]
+
+ >>> n.clear()
+ >>> data = n.retrieve()
+ >>> data [:3]
+ [('iface', None), ('bootproto', None), ('ipaddr', None)]
+ >>> data [3:]
+ [('netmask', None), ('gw', None), ('vlanid', None)]
"""
keys = ("OVIRT_BOOTIF",
"OVIRT_BOOTPROTO",
"OVIRT_IP_ADDRESS",
- "OVIRT_IP_NETMASK",
- "OVIRT_IP_GATEWAY",
+ "OVIRT_NETMASK",
+ "OVIRT_GATEWAY",
"OVIRT_VLAN")
- @map_and_update_defaults
- def configure(self, iface, bootproto, ipaddr=None, netmask=None, gw=None,
+ @CentralNodeConfiguration.map_and_update_defaults_decorator
+ def update(self, iface, bootproto, ipaddr=None, netmask=None, gw=None,
vlanid=None):
- pass
+ if bootproto not in ["static", "none", "dhcp"]:
+ raise exceptions.InvalidData("Unknown bootprotocol: %s" %
+ bootproto)
+ (valid.IPv4Address() | valid.Empty())(ipaddr)
+ (valid.IPv4Address() | valid.Empty())(netmask)
+ (valid.IPv4Address() | valid.Empty())(gw)
class Nameservers(CentralNodeConfiguration):
- keys = ("OVIRT_DNS")
+ """Configure nameservers
+ >>> fn = "/tmp/cfg_dummy"
+ >>> cfgfile = ConfigFile(fn, SimpleProvider)
+ >>> servers = ["10.0.0.2", "10.0.0.3"]
+ >>> n = Nameservers(cfgfile)
+ >>> n.update(servers)
+ >>> data = n.retrieve()
+ >>> all([servers[idx] == s for idx, s in enumerate(data["servers"])])
+ True
+ """
+ keys = ("OVIRT_DNS",)
- @map_and_update_defaults
- def configure(self, servers):
- pass
+ @CentralNodeConfiguration.map_and_update_defaults_decorator
+ def update(self, servers):
+ assert type(servers) is list
+ servers = filter(lambda i: i.strip() not in ["", None], servers)
+ map(valid.IPv4Address(), servers)
+ return {
+ "OVIRT_DNS": ",".join(servers)
+ }
+ def retrieve(self):
+ cfg = dict(CentralNodeConfiguration.retrieve(self))
+ return {
+ "servers": cfg["servers"].split(",")
+ }
- def apply_config(self):
+ def apply(self):
"""Derives the nameserver config from OVIRT_DNS
1. Parse nameservers from defaults
@@ -175,7 +311,7 @@
Args:
servers: List of servers (str)
"""
- ovirt_config = defaults()
+ ovirt_config = self.defaults.get_dict()
if "OVIRT_DNS" not in ovirt_config:
self.logger.debug("No DNS server entry in default config")
return
@@ -186,7 +322,7 @@
servers = servers.split(",")
- aug = ovirt.node.utils.AugeasWrapper()
+ aug = utils.AugeasWrapper()
# Write resolv.conf any way, sometimes without servers
comment = ("Please make changes through the TUI. " + \
"Manual edits to this file will be " + \
@@ -206,33 +342,79 @@
else:
aug.remove(path)
- ovirt.node.utils.fs.persist_config("/etc/resolv.conf")
+ utils.fs.persist_config("/etc/resolv.conf")
class Timeservers(CentralNodeConfiguration):
- keys = ("OVIRT_NTP")
+ """Configure timeservers
- @map_and_update_defaults
- def configure(self, servers):
- pass
+ >>> fn = "/tmp/cfg_dummy"
+ >>> cfgfile = ConfigFile(fn, SimpleProvider)
+ >>> servers = ["10.0.0.4", "10.0.0.5"]
+ >>> n = Timeservers(cfgfile)
+ >>> n.update(servers)
+ >>> data = n.retrieve()
+ >>> all([servers[idx] == s for idx, s in enumerate(data["servers"])])
+ True
+ """
+ keys = ("OVIRT_NTP",)
+
+ @CentralNodeConfiguration.map_and_update_defaults_decorator
+ def update(self, servers):
+ assert type(servers) is list
+ servers = filter(lambda i: i.strip() not in ["", None], servers)
+ map(valid.IPv4Address(), servers)
+ return {
+ "OVIRT_NTP": ",".join(servers)
+ }
+
+ def retrieve(self):
+ cfg = dict(CentralNodeConfiguration.retrieve(self))
+ return {
+ "servers": cfg["servers"].split(",")
+ }
class Syslog(CentralNodeConfiguration):
+ """Configure rsyslog
+
+ >>> fn = "/tmp/cfg_dummy"
+ >>> cfgfile = ConfigFile(fn, SimpleProvider)
+ >>> server = "10.0.0.6"
+ >>> port = "514"
+ >>> n = Syslog(cfgfile)
+ >>> n.update(server, port)
+ >>> n.retrieve()
+ [('server', '10.0.0.6'), ('port', '514')]
+ """
keys = ("OVIRT_SYSLOG_SERVER",
"OVIRT_SYSLOG_PORT")
- @map_and_update_defaults
- def configure(self, server, port):
- pass
+ @CentralNodeConfiguration.map_and_update_defaults_decorator
+ def update(self, server, port):
+ valid.FQDNOrIPAddress()(server)
+ valid.Port()(port)
class Collectd(CentralNodeConfiguration):
+ """Configure collectd
+
+ >>> fn = "/tmp/cfg_dummy"
+ >>> cfgfile = ConfigFile(fn, SimpleProvider)
+ >>> server = "10.0.0.7"
+ >>> port = "42"
+ >>> n = Collectd(cfgfile)
+ >>> n.update(server, port)
+ >>> n.retrieve()
+ [('server', '10.0.0.7'), ('port', '42')]
+ """
keys = ("OVIRT_COLLECTD_SERVER",
"OVIRT_COLLECTD_PORT")
- @map_and_update_defaults
- def configure(self, server, port):
- pass
+ @CentralNodeConfiguration.map_and_update_defaults_decorator
+ def update(self, server, port):
+ valid.FQDNOrIPAddress()(server)
+ valid.Port()(port)
class RHN(CentralNodeConfiguration):
@@ -248,52 +430,110 @@
"OVIRT_RHN_PROXYUSER",
"OVIRT_RHN_PROXYPASSWORD")
- @map_and_update_defaults
- def configure(self, rhntype, url, ca_cert, username, password, profile,
+ @CentralNodeConfiguration.map_and_update_defaults_decorator
+ def update(self, rhntype, url, ca_cert, username, password, profile,
activationkey, org, proxy, proxyuser, proxypassword):
pass
class KDump(CentralNodeConfiguration):
+ """Configure kdump
+
+ >>> fn = "/tmp/cfg_dummy"
+ >>> cfgfile = ConfigFile(fn, SimpleProvider)
+ >>> nfs_url = "host.example.com"
+ >>> ssh_url = "root at host.example.com"
+ >>> n = KDump(cfgfile)
+ >>> n.update(nfs_url, ssh_url)
+ >>> n.retrieve()
+ [('nfs', 'host.example.com'), ('ssh', 'root at host.example.com')]
+ """
keys = ("OVIRT_KDUMP_NFS",
"OVIRT_KDUMP_SSH")
- @map_and_update_defaults
- def configure(self, nfs, ssh):
- pass
+ @CentralNodeConfiguration.map_and_update_defaults_decorator
+ def update(self, nfs, ssh):
+ valid.FQDNOrIPAddress()(nfs)
+ valid.URL()(ssh)
class iSCSI(CentralNodeConfiguration):
+ """Configure iSCSI
+
+ >>> fn = "/tmp/cfg_dummy"
+ >>> cfgfile = ConfigFile(fn, SimpleProvider)
+ >>> n = iSCSI(cfgfile)
+ >>> n.update("node.example.com", "target.example.com", "10.0.0.8", "42")
+ >>> data = n.retrieve()
+ >>> data[:2]
+ [('name', 'node.example.com'), ('target_name', 'target.example.com')]
+ >>> data[2:]
+ [('target_host', '10.0.0.8'), ('target_port', '42')]
+ """
keys = ("OVIRT_ISCSI_NODE_NAME",
"OVIRT_ISCSI_TARGET_NAME",
"OVIRT_ISCSI_TARGET_IP",
"OVIRT_ISCSI_TARGET_PORT")
- @map_and_update_defaults
- def configure(self, name, target_name, target_host, target_port):
+ @CentralNodeConfiguration.map_and_update_defaults_decorator
+ def update(self, name, target_name, target_host, target_port):
+ # FIXME add validation
pass
class SNMP(CentralNodeConfiguration):
- keys = ("OVIRT_SNMP_PASSWORD")
+ """Configure SNMP
- @map_and_update_defaults
- def configure(self, password):
+ >>> fn = "/tmp/cfg_dummy"
+ >>> cfgfile = ConfigFile(fn, SimpleProvider)
+ >>> n = SNMP(cfgfile)
+ >>> n.update("secret")
+ >>> n.retrieve()
+ [('password', 'secret')]
+ """
+ keys = ("OVIRT_SNMP_PASSWORD",)
+
+ @CentralNodeConfiguration.map_and_update_defaults_decorator
+ def update(self, password):
+ # FIXME add validation
pass
class Netconsole(CentralNodeConfiguration):
+ """Configure netconsole
+
+ >>> fn = "/tmp/cfg_dummy"
+ >>> cfgfile = ConfigFile(fn, SimpleProvider)
+ >>> n = Netconsole(cfgfile)
+ >>> server = "10.0.0.9"
+ >>> port = "666"
+ >>> n.update(server, port)
+ >>> n.retrieve()
+ [('server', '10.0.0.9'), ('port', '666')]
+ """
keys = ("OVIRT_NETCONSOLE_SERVER",
"OVIRT_NETCONSOLE_PORT")
- @map_and_update_defaults
- def configure(self, server, port):
+ @CentralNodeConfiguration.map_and_update_defaults_decorator
+ def update(self, server, port):
+ # FIXME add validation
pass
class CIM(CentralNodeConfiguration):
- keys = ("OVIRT_CIM_ENABLED")
+ """Configure CIM
- @map_and_update_defaults
- def configure(self, enabled):
- assert enabled in ["1", "0"]
\ No newline at end of file
+ >>> fn = "/tmp/cfg_dummy"
+ >>> cfgfile = ConfigFile(fn, SimpleProvider)
+ >>> n = CIM(cfgfile)
+ >>> n.update(True)
+ >>> n.retrieve()
+ [('enabled', '1')]
+ """
+ keys = ("OVIRT_CIM_ENABLED",)
+
+ @CentralNodeConfiguration.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/installer/__init__.py b/scripts/tui/src/ovirt/node/installer/__init__.py
similarity index 98%
rename from scripts/tui/src/ovirt/node/plugins/installer/__init__.py
rename to scripts/tui/src/ovirt/node/installer/__init__.py
index a38f201..f5390bc 100644
--- a/scripts/tui/src/ovirt/node/plugins/installer/__init__.py
+++ b/scripts/tui/src/ovirt/node/installer/__init__.py
@@ -1,3 +1,3 @@
"""
This package contains all UI plugins for the installer
-"""
\ No newline at end of file
+"""
diff --git a/scripts/tui/src/ovirt/node/plugins/__init__.py b/scripts/tui/src/ovirt/node/plugins.py
similarity index 92%
rename from scripts/tui/src/ovirt/node/plugins/__init__.py
rename to scripts/tui/src/ovirt/node/plugins.py
index a4b52d2..b8819d5 100644
--- a/scripts/tui/src/ovirt/node/plugins/__init__.py
+++ b/scripts/tui/src/ovirt/node/plugins.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# __init__.py - Copyright (C) 2012 Red Hat, Inc.
+# plugins.py - Copyright (C) 2012 Red Hat, Inc.
# Written by Fabian Deutsch <fabiand at redhat.com>
#
# This program is free software; you can redistribute it and/or modify
@@ -40,7 +40,9 @@
modules = []
for importer, modname, ispkg in __walk_plugins(basemodule):
#print("Found submodule %s (is a package: %s)" % (modname, ispkg))
- module = __import__(basemodule.__name__ + "." + modname, fromlist="dummy")
+ modpath = basemodule.__name__ + "." + modname
+ module = __import__(modpath,
+ fromlist="dummy")
#print("Imported", module)
modules += [module]
return modules
@@ -189,8 +191,8 @@
except NotImplementedError:
self.logger.debug("Plugin has no model")
except ovirt.node.exceptions.InvalidData:
- self.logger.warning("Plugins model does not pass sematic check: %s" % \
- model)
+ self.logger.warning("Plugins model does not pass sematic " +
+ "check: %s" % model)
is_valid = False
finally:
self.__changes = {}
@@ -216,12 +218,14 @@
if type(change) is not dict:
self.logger.warning("Change is not a dict: %s" % change)
- self.logger.debug("Passing UI change to callback on_change: %s" % change)
+ self.logger.debug("Passing UI change to callback on_change: %s" % \
+ change)
if self.validate_changes:
self.validate(change)
self.on_change(change)
self.__changes.update(change)
- self.logger.debug("Sum of all UI changes up to now: %s" % self.__changes)
+ self.logger.debug("Sum of all UI changes up to now: %s" % \
+ self.__changes)
return True
def _on_ui_save(self):
@@ -230,8 +234,9 @@
"""
self.logger.debug("Request to apply model changes")
effective_changes = self.pending_changes() or {}
- successfull_merge = self.on_merge(effective_changes)
+ successfull_merge = self.on_merge(effective_changes) is not False
if successfull_merge:
+ self.logger.info("Changes were merged successfully")
self.__changes = {}
return successfull_merge
@@ -259,8 +264,9 @@
model = self.model()
for key, value in self.__changes.items():
if key in model and value == model[key]:
- self.logger.debug(("Skipping pseudo-change of '%s', value " + \
- "(%s) did not change") % (key, value))
+ self.logger.debug(("Skipping pseudo-change of '%s', " + \
+ "value (%s) did not change") % (key,
+ value))
else:
effective_changes[key] = value
else:
diff --git a/scripts/tui/src/ovirt/node/plugins/setup/__init__.py b/scripts/tui/src/ovirt/node/plugins/setup/__init__.py
deleted file mode 100644
index 32f8845..0000000
--- a/scripts/tui/src/ovirt/node/plugins/setup/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
-This package contains all UI plugins for the setup
-"""
\ No newline at end of file
diff --git a/scripts/tui/src/ovirt/node/setup/__init__.py b/scripts/tui/src/ovirt/node/setup/__init__.py
new file mode 100644
index 0000000..7fafb86
--- /dev/null
+++ b/scripts/tui/src/ovirt/node/setup/__init__.py
@@ -0,0 +1,3 @@
+"""
+This package contains all plugins and the __main__ for the setup application
+"""
diff --git a/scripts/tui/src/ovirt/node/app/setup.py b/scripts/tui/src/ovirt/node/setup/__main__.py
similarity index 88%
rename from scripts/tui/src/ovirt/node/app/setup.py
rename to scripts/tui/src/ovirt/node/setup/__main__.py
index 074391b..e15714f 100644
--- a/scripts/tui/src/ovirt/node/app/setup.py
+++ b/scripts/tui/src/ovirt/node/setup/__main__.py
@@ -22,10 +22,9 @@
Create an setup application instance an start it.
"""
-import ovirt.node.app
-import ovirt.node.plugins.setup
+from ovirt.node import app, setup
if __name__ == '__main__':
- app = ovirt.node.app.Application(ovirt.node.plugins.setup)
+ app = app.Application(setup)
app.run()
diff --git a/scripts/tui/src/ovirt/node/plugins/setup/engine_page.py b/scripts/tui/src/ovirt/node/setup/engine_page.py
similarity index 100%
rename from scripts/tui/src/ovirt/node/plugins/setup/engine_page.py
rename to scripts/tui/src/ovirt/node/setup/engine_page.py
diff --git a/scripts/tui/src/ovirt/node/plugins/setup/example.py b/scripts/tui/src/ovirt/node/setup/example.py
similarity index 100%
rename from scripts/tui/src/ovirt/node/plugins/setup/example.py
rename to scripts/tui/src/ovirt/node/setup/example.py
diff --git a/scripts/tui/src/ovirt/node/plugins/setup/features.py b/scripts/tui/src/ovirt/node/setup/features.py
similarity index 100%
rename from scripts/tui/src/ovirt/node/plugins/setup/features.py
rename to scripts/tui/src/ovirt/node/setup/features.py
diff --git a/scripts/tui/src/ovirt/node/plugins/setup/kdump_page.py b/scripts/tui/src/ovirt/node/setup/kdump_page.py
similarity index 98%
rename from scripts/tui/src/ovirt/node/plugins/setup/kdump_page.py
rename to scripts/tui/src/ovirt/node/setup/kdump_page.py
index 8d7d03e..5cdfa64 100644
--- a/scripts/tui/src/ovirt/node/plugins/setup/kdump_page.py
+++ b/scripts/tui/src/ovirt/node/setup/kdump_page.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# kdump.py - Copyright (C) 2012 Red Hat, Inc.
+# kdump_page.py - Copyright (C) 2012 Red Hat, Inc.
# Written by Fabian Deutsch <fabiand at redhat.com>
#
# This program is free software; you can redistribute it and/or modify
diff --git a/scripts/tui/src/ovirt/node/plugins/setup/keyboard_page.py b/scripts/tui/src/ovirt/node/setup/keyboard_page.py
similarity index 100%
rename from scripts/tui/src/ovirt/node/plugins/setup/keyboard_page.py
rename to scripts/tui/src/ovirt/node/setup/keyboard_page.py
diff --git a/scripts/tui/src/ovirt/node/plugins/setup/logging_page.py b/scripts/tui/src/ovirt/node/setup/logging_page.py
similarity index 98%
rename from scripts/tui/src/ovirt/node/plugins/setup/logging_page.py
rename to scripts/tui/src/ovirt/node/setup/logging_page.py
index 4a2f86e..0f3783c 100644
--- a/scripts/tui/src/ovirt/node/plugins/setup/logging_page.py
+++ b/scripts/tui/src/ovirt/node/setup/logging_page.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# logging.py - Copyright (C) 2012 Red Hat, Inc.
+# logging_page.py - Copyright (C) 2012 Red Hat, Inc.
# Written by Fabian Deutsch <fabiand at redhat.com>
#
# This program is free software; you can redistribute it and/or modify
@@ -26,6 +26,7 @@
import ovirt.node.valid
import ovirt.node.ui
+
class Plugin(ovirt.node.plugins.NodePlugin):
_model = None
_widgets = None
diff --git a/scripts/tui/src/ovirt/node/plugins/setup/monitoring_page.py b/scripts/tui/src/ovirt/node/setup/monitoring_page.py
similarity index 100%
rename from scripts/tui/src/ovirt/node/plugins/setup/monitoring_page.py
rename to scripts/tui/src/ovirt/node/setup/monitoring_page.py
diff --git a/scripts/tui/src/ovirt/node/plugins/setup/network_page.py b/scripts/tui/src/ovirt/node/setup/network_page.py
similarity index 89%
rename from scripts/tui/src/ovirt/node/plugins/setup/network_page.py
rename to scripts/tui/src/ovirt/node/setup/network_page.py
index 0ef7954..d1f625f 100644
--- a/scripts/tui/src/ovirt/node/plugins/setup/network_page.py
+++ b/scripts/tui/src/ovirt/node/setup/network_page.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# status.py - Copyright (C) 2012 Red Hat, Inc.
+# network_page.py - Copyright (C) 2012 Red Hat, Inc.
# Written by Fabian Deutsch <fabiand at redhat.com>
#
# This program is free software; you can redistribute it and/or modify
@@ -27,6 +27,7 @@
import ovirt.node.ui
import ovirt.node.utils.network
import ovirt.node.config.network
+from ovirt.node.config import defaults
class Plugin(ovirt.node.plugins.NodePlugin):
@@ -50,11 +51,11 @@
def model(self):
# Pull name-/timeservers from config files (not defaults)
- nameservers = ovirt.node.config.network.nameservers()
+ nameservers = dict(defaults.Nameservers().retrieve())["servers"]
for idx, nameserver in enumerate(nameservers):
self._model["dns[%d]" % idx] = nameserver
- timeservers = ovirt.node.config.network.timeservers()
+ timeservers = dict(defaults.Timeservers().retrieve())["servers"]
for idx, timeserver in enumerate(timeservers):
self._model["ntp[%d]" % idx] = timeserver
@@ -210,23 +211,27 @@
self.logger.info("effc %s" % effective_changes)
self.logger.info("allc %s" % changes)
- if "dns[0]" in effective_changes or \
- "dns[1]" in effective_changes:
- new_servers = [v for k, v in effective_model \
- if k.startswith("dns[")]
- self.logger.info("Setting new nameservers: %s" % new_servers)
+ 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.configure(new_servers)
+ model.update(nameservers)
- if "ntp[0]" in effective_changes or \
- "ntp[1]" in effective_changes:
- new_servers = [v for k, v in effective_model \
- if k.startswith("ntp[")]
- self.logger.info("Setting new timeservers: %s" % new_servers)
+ 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.configure(new_servers)
+ model.update(timeservers)
- if "nics" in changes:
+ 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()
\ No newline at end of file
+ return self._build_nic_details_dialog()
+
+ return True
\ No newline at end of file
diff --git a/scripts/tui/src/ovirt/node/plugins/setup/ping.py b/scripts/tui/src/ovirt/node/setup/ping.py
similarity index 98%
rename from scripts/tui/src/ovirt/node/plugins/setup/ping.py
rename to scripts/tui/src/ovirt/node/setup/ping.py
index aaa4717..7a13c7d 100644
--- a/scripts/tui/src/ovirt/node/plugins/setup/ping.py
+++ b/scripts/tui/src/ovirt/node/setup/ping.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# ping.py - Copyright (C) 2012 Red Hat, Inc.
+# ping_page.py - Copyright (C) 2012 Red Hat, Inc.
# Written by Fabian Deutsch <fabiand at redhat.com>
#
# This program is free software; you can redistribute it and/or modify
diff --git a/scripts/tui/src/ovirt/node/plugins/setup/remote_storage_page.py b/scripts/tui/src/ovirt/node/setup/remote_storage_page.py
similarity index 100%
rename from scripts/tui/src/ovirt/node/plugins/setup/remote_storage_page.py
rename to scripts/tui/src/ovirt/node/setup/remote_storage_page.py
diff --git a/scripts/tui/src/ovirt/node/plugins/setup/security_page.py b/scripts/tui/src/ovirt/node/setup/security_page.py
similarity index 100%
rename from scripts/tui/src/ovirt/node/plugins/setup/security_page.py
rename to scripts/tui/src/ovirt/node/setup/security_page.py
diff --git a/scripts/tui/src/ovirt/node/plugins/setup/snmp_page.py b/scripts/tui/src/ovirt/node/setup/snmp_page.py
similarity index 100%
rename from scripts/tui/src/ovirt/node/plugins/setup/snmp_page.py
rename to scripts/tui/src/ovirt/node/setup/snmp_page.py
diff --git a/scripts/tui/src/ovirt/node/plugins/setup/status_page.py b/scripts/tui/src/ovirt/node/setup/status_page.py
similarity index 98%
rename from scripts/tui/src/ovirt/node/plugins/setup/status_page.py
rename to scripts/tui/src/ovirt/node/setup/status_page.py
index 667f3b8..14c2860 100644
--- a/scripts/tui/src/ovirt/node/plugins/setup/status_page.py
+++ b/scripts/tui/src/ovirt/node/setup/status_page.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# status.py - Copyright (C) 2012 Red Hat, Inc.
+# status_page.py - Copyright (C) 2012 Red Hat, Inc.
# Written by Fabian Deutsch <fabiand at redhat.com>
#
# This program is free software; you can redistribute it and/or modify
diff --git a/scripts/tui/src/ovirt/node/plugins/setup/support_page.py b/scripts/tui/src/ovirt/node/setup/support_page.py
similarity index 100%
rename from scripts/tui/src/ovirt/node/plugins/setup/support_page.py
rename to scripts/tui/src/ovirt/node/setup/support_page.py
diff --git a/scripts/tui/src/ovirt/node/plugins/setup/usage.py b/scripts/tui/src/ovirt/node/setup/usage.py
similarity index 100%
rename from scripts/tui/src/ovirt/node/plugins/setup/usage.py
rename to scripts/tui/src/ovirt/node/setup/usage.py
diff --git a/scripts/tui/src/ovirt/node/ui/__init__.py b/scripts/tui/src/ovirt/node/ui/__init__.py
index 4aefe8f..0be7d37 100644
--- a/scripts/tui/src/ovirt/node/ui/__init__.py
+++ b/scripts/tui/src/ovirt/node/ui/__init__.py
@@ -61,7 +61,8 @@
self._signal_cbs = {}
if name not in self._signal_cbs:
self._signal_cbs[name] = []
- self.logger.debug("Registered new signal '%s' for '%s'" % (name, self))
+ self.logger.debug("Registered new signal '%s' for '%s'" % (name,
+ self))
def connect_signal(self, name, cb):
"""Connect an callback to a signal
@@ -257,8 +258,8 @@
label: Caption of this checkbox
state: The initial change
"""
- def __init__(self, label, state=False):
- super(Checkbox, self).__init__()
+ def __init__(self, label, state=False, is_enabled=True):
+ super(Checkbox, self).__init__(label, is_enabled)
self.label = label
self.state(state)
@@ -347,4 +348,4 @@
self._hotkeys[str(hotkey)] = cb
def run(self):
- raise NotImplementedError
\ No newline at end of file
+ raise NotImplementedError
diff --git a/scripts/tui/src/ovirt/node/ui/builder.py b/scripts/tui/src/ovirt/node/ui/builder.py
index 8129720..7573258 100644
--- a/scripts/tui/src/ovirt/node/ui/builder.py
+++ b/scripts/tui/src/ovirt/node/ui/builder.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# tui.py - Copyright (C) 2012 Red Hat, Inc.
+# builder.py - Copyright (C) 2012 Red Hat, Inc.
# Written by Fabian Deutsch <fabiand at redhat.com>
#
# This program is free software; you can redistribute it and/or modify
@@ -185,8 +185,8 @@
def on_widget_click_cb(widget, data=None):
LOGGER.debug("Button click: %s %s" % (path, widget))
-# if type(item) is ovirt.node.ui.SaveButton:
- plugin._on_ui_change({path: True})
+ if type(item) is ovirt.node.ui.Button:
+ plugin._on_ui_change({path: True})
r = plugin._on_ui_save()
parse_plugin_result(tui, plugin, r)
diff --git a/scripts/tui/src/ovirt/node/ui/tui.py b/scripts/tui/src/ovirt/node/ui/tui.py
index 043233b..21791fb 100644
--- a/scripts/tui/src/ovirt/node/ui/tui.py
+++ b/scripts/tui/src/ovirt/node/ui/tui.py
@@ -123,6 +123,16 @@
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
if self._current_plugin:
pending_changes = self._current_plugin.pending_changes()
if pending_changes:
@@ -131,18 +141,14 @@
widgets = dict(self._current_plugin.ui_content().children)
LOGGER.debug("Available widgets: %s" % widgets)
for path, value in pending_changes.items():
- field = widgets[path].name
- msg += "- %s\n" % (field.strip(":"))
+ if path in widgets:
+ field = widgets[path].name
+ msg += "- %s\n" % (field.strip(":"))
self.display_dialog(urwid.Filler(urwid.Text(
"The following fields were changed:\n%s" % msg)),
"Pending 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())
+ has_outstanding_changes = True
+ return has_outstanding_changes
def display_page(self, page):
LOGGER.debug("Displaying page %s" % page)
diff --git a/scripts/tui/src/ovirt/node/utils/fs.py b/scripts/tui/src/ovirt/node/utils/fs.py
index fd72aed..e6f1f83 100644
--- a/scripts/tui/src/ovirt/node/utils/fs.py
+++ b/scripts/tui/src/ovirt/node/utils/fs.py
@@ -26,7 +26,7 @@
import shutil
import os
from ovirt.node.utils import checksum, is_bind_mount
-from ovirt.node.utils.process import system
+from process import system
LOGGER = logging.getLogger(__name__)
@@ -43,6 +43,7 @@
contents = f.read()
return contents
+
def copy_contents(src, dst):
assert all([os.path.isfile(f) for f in [src, dst]]), \
"Source and destination need to exist"
diff --git a/scripts/tui/src/ovirt/node/utils/security.py b/scripts/tui/src/ovirt/node/utils/security.py
index a368b16..5be7359 100644
--- a/scripts/tui/src/ovirt/node/utils/security.py
+++ b/scripts/tui/src/ovirt/node/utils/security.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# virt.py - Copyright (C) 2012 Red Hat, Inc.
+# security.py - Copyright (C) 2012 Red Hat, Inc.
# Written by Fabian Deutsch <fabiand at redhat.com>
#
# This program is free software; you can redistribute it and/or modify
@@ -24,7 +24,7 @@
import os.path
-from . import process
+import process
def get_ssh_hostkey(variant="rsa"):
diff --git a/scripts/tui/src/ovirt/node/valid.py b/scripts/tui/src/ovirt/node/valid.py
index 5c21dd0..06f3c90 100644
--- a/scripts/tui/src/ovirt/node/valid.py
+++ b/scripts/tui/src/ovirt/node/valid.py
@@ -23,9 +23,10 @@
"""
import re
import socket
+import urlparse
-from . import base
-from . import exceptions
+import base
+import exceptions
class Validator(base.Base):
@@ -302,3 +303,22 @@
def validate(self, value):
return value == ""
+
+
+class URL(Validator):
+ description = "a valid URL"
+
+ requires_scheme = False
+ requires_netloc = False
+ requires_path = True
+
+ def validate(self, value):
+ p = urlparse.urlparse(value)
+ is_valid = True
+ if self.requires_scheme:
+ is_valid &= p.scheme != ""
+ if self.requires_netloc:
+ is_valid &= p.netloc != ""
+ if self.requires_path:
+ is_valid &= p.path != ""
+ return is_valid
--
To view, visit http://gerrit.ovirt.org/9932
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I684d85f1689ab97d22e5be4b5c740676751464c1
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