[node-patches] Change in ovirt-node[master]: setup: Add more logic and fixes to pages
fabiand at fedoraproject.org
fabiand at fedoraproject.org
Tue Dec 11 20:09:43 UTC 2012
Fabian Deutsch has uploaded a new change for review.
Change subject: setup: Add more logic and fixes to pages
......................................................................
setup: Add more logic and fixes to pages
Change-Id: I1e8b50d71990a3df3e69f0ff00b0ae52d17a7cdc
Signed-off-by: Fabian Deutsch <fabiand at fedoraproject.org>
---
M scripts/tui/src/ovirt/node/config/defaults.py
M scripts/tui/src/ovirt/node/exceptions.py
M scripts/tui/src/ovirt/node/plugins.py
M scripts/tui/src/ovirt/node/setup/keyboard_page.py
M scripts/tui/src/ovirt/node/setup/logging_page.py
M scripts/tui/src/ovirt/node/setup/monitoring_page.py
M scripts/tui/src/ovirt/node/setup/remote_storage_page.py
M scripts/tui/src/ovirt/node/setup/security_page.py
M scripts/tui/src/ovirt/node/setup/snmp_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/__init__.py
M scripts/tui/src/ovirt/node/utils/security.py
15 files changed, 307 insertions(+), 126 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/ovirt-node refs/changes/68/9968/1
diff --git a/scripts/tui/src/ovirt/node/config/defaults.py b/scripts/tui/src/ovirt/node/config/defaults.py
index 19a7069..5e90eae 100644
--- a/scripts/tui/src/ovirt/node/config/defaults.py
+++ b/scripts/tui/src/ovirt/node/config/defaults.py
@@ -203,7 +203,8 @@
value = cfg[key] if key in cfg else self.none_value
values += (value,)
assert len(varnames) == len(values)
- return dict(zip(varnames, values))
+ cfg = dict(zip(varnames, values))
+ return cfg
def clear(self):
"""Remove the configuration for this item
@@ -354,6 +355,20 @@
return cfg
def transaction(self):
+ return self.__legacy_transaction()
+
+ def __legacy_transaction(self):
+ class ConfigureNameservers(utils.Transaction.Element):
+ def commit(self):
+ import ovirtnode.network as onet
+ net = onet.Network()
+ net.configure_dns()
+
+ tx = utils.Transaction("Configuring nameservers")
+ tx.append(ConfigureNameservers())
+ return tx
+
+ def __new_transaction(self):
"""Derives the nameserver config from OVIRT_DNS
1. Parse nameservers from defaults
@@ -445,7 +460,18 @@
return cfg
def transaction(self):
- return utils.Transaction("Configuring timeserver")
+ return self.__legacy_transaction()
+
+ def __legacy_transaction(self):
+ class ConfigureTimeservers(utils.Transaction.Element):
+ def commit(self):
+ import ovirtnode.network as onet
+ net = onet.Network()
+ net.configure_ntp()
+
+ tx = utils.Transaction("Configuring timeservers")
+ tx.append(ConfigureTimeservers())
+ return tx
class Syslog(NodeConfigFileSection):
@@ -469,6 +495,9 @@
valid.Port()(port)
def transaction(self):
+ return self.__legacy_transaction()
+
+ def __legacy_transaction(self):
cfg = dict(self.retrieve())
server, port = (cfg["server"], cfg["port"])
@@ -501,6 +530,26 @@
def update(self, server, port):
valid.FQDNOrIPAddress()(server)
valid.Port()(port)
+
+ def transaction(self):
+ self.__legacy_transaction()
+
+ def __legacy_transaction(self):
+ cfg = dict(self.retrieve())
+ server, port = (cfg["server"], cfg["port"])
+
+ class ConfigureCollectd(utils.Transaction.Element):
+ def commit(self):
+ import ovirt_config_setup.collectd as ocollectd
+ if ocollectd.write_collectd_config(server, port):
+ self.logger.debug("Collectd was configured successfully")
+ else:
+ raise exceptions.TransactionError("Failed to configure " +
+ "collectd")
+
+ tx = utils.Transaction("Configuring collectd")
+ tx.append(ConfigureCollectd())
+ return tx
class RHN(NodeConfigFileSection):
@@ -662,12 +711,13 @@
>>> fn = "/tmp/cfg_dummy"
>>> cfgfile = ConfigFile(fn, SimpleProvider)
>>> n = iSCSI(cfgfile)
- >>> n.update("node.example.com", "target.example.com", "10.0.0.8", "42")
+ >>> n.update("iqn.1992-01.com.example:node",
+ ... "iqn.1992-01.com.example:target", "10.0.0.8", "42")
>>> data = sorted(n.retrieve().items())
>>> data[:2]
- [('name', 'node.example.com'), ('target_host', '10.0.0.8')]
+ [('name', 'iqn.1992-01.com.example:node'), ('target_host', '10.0.0.8')]
>>> data[2:]
- [('target_name', 'target.example.com'), ('target_port', '42')]
+ [('target_name', 'iqn.1992-01.com.example:target'), ('target_port', '42')]
"""
keys = ("OVIRT_ISCSI_NODE_NAME",
"OVIRT_ISCSI_TARGET_NAME",
@@ -805,15 +855,43 @@
>>> n = CIM(cfgfile)
>>> n.update(True)
>>> n.retrieve()
- {'enabled': '1'}
+ {'enabled': True}
"""
keys = ("OVIRT_CIM_ENABLED",)
@NodeConfigFileSection.map_and_update_defaults_decorator
def update(self, enabled):
return {
- "OVIRT_CIM_ENABLED": "1" if utils.parse_bool(enabled) else "0"
+ "OVIRT_CIM_ENABLED": "1" if utils.parse_bool(enabled) else None
}
+
+ def retrieve(self):
+ cfg = dict(NodeConfigFileSection.retrieve(self))
+ cfg.update({
+ "enabled": True if cfg["enabled"] == "1" else None
+ })
+ return cfg
+
+ def transaction(self):
+ cfg = dict(self.retrieve())
+ enabled = cfg["enabled"]
+
+ class ConfigureCIM(utils.Transaction.Element):
+ def commit(self):
+ # FIXME snmp plugin needs to be placed somewhere else (in src)
+ import ovirt_config_setup.cim as ocim
+ if enabled:
+ if ocim.enable_cim():
+ self.logger.debug("Configured CIM successfully")
+ else:
+ raise exceptions.TransactionError("CIM configuration" +
+ " failed")
+
+ # FIXME setting password is missing
+
+ tx = utils.Transaction("Configuring SNMP")
+ tx.append(ConfigureCIM())
+ return tx
class Keyboard(NodeConfigFileSection):
@@ -924,8 +1002,8 @@
def transaction(self):
cfg = dict(self.retrieve())
- pwauth, num_bytes, aesni = (cfg["pwauth"], cfg["num_bytes"],
- cfg["aesni"])
+ pwauth, num_bytes, disable_aesni = (cfg["pwauth"], cfg["num_bytes"],
+ cfg["disable_aesni"])
ssh = utils.security.Ssh()
@@ -939,13 +1017,13 @@
class ConfigureAESNI(utils.Transaction.Element):
def commit(self):
- ssh.aes_ni(aesni)
+ ssh.disable_aesni(disable_aesni)
tx = utils.Transaction("Configuring SSH")
if pwauth:
tx.append(ConfigurePasswordAuthentication())
if num_bytes:
tx.append(ConfigureStrongRNG())
- if aesni:
+ if disable_aesni:
tx.append(ConfigureAESNI())
return tx
diff --git a/scripts/tui/src/ovirt/node/exceptions.py b/scripts/tui/src/ovirt/node/exceptions.py
index 181c587..eae160d 100644
--- a/scripts/tui/src/ovirt/node/exceptions.py
+++ b/scripts/tui/src/ovirt/node/exceptions.py
@@ -24,30 +24,30 @@
"""
-class InvalidData(Exception):
- """E.g. if a string contains characters which are not allowed
- """
+class ExceptionWithMessage(Exception):
def __init__(self, msg):
self.message = msg
def __str__(self):
return repr(self.message)
+
+
+class InvalidData(ExceptionWithMessage):
+ """E.g. if a string contains characters which are not allowed
+ """
+ pass
class Concern(InvalidData):
"""E.g. if a password is not secure enough
FIXME very ... unspecific
"""
- def __init__(self, msg):
- self.message = msg
-
- def __str__(self):
- return repr(self.message)
+ pass
-class PreconditionFailed(Exception):
- def __init__(self, msg):
- self.message = msg
+class TransactionError(ExceptionWithMessage):
+ pass
- def __str__(self):
- return repr(self.message)
+
+class PreconditionError(TransactionError):
+ pass
diff --git a/scripts/tui/src/ovirt/node/plugins.py b/scripts/tui/src/ovirt/node/plugins.py
index 94f99d6..2ae6d3c 100644
--- a/scripts/tui/src/ovirt/node/plugins.py
+++ b/scripts/tui/src/ovirt/node/plugins.py
@@ -239,7 +239,7 @@
"""Called when data should be saved
Calls merge_changes, but only with values that really changed
"""
- effective_changes = self.pending_changes() or {}
+ effective_changes = self.pending_changes()
is_valid = False
self.logger.debug("Request to apply model changes: %s" %
@@ -254,7 +254,7 @@
if self.only_merge_on_valid_changes and not is_valid:
msg = "There are still fields with invalid values."
self.logger.warning(msg)
- raise exceptions.PreconditionFailed(msg)
+ raise exceptions.PreconditionError(msg)
successfull_merge = self.on_merge(effective_changes)
@@ -309,13 +309,16 @@
else:
effective_changes[key] = value
else:
+ self.logger.debug("No changes at all detected.")
+ if not effective_changes:
self.logger.debug("No effective changes detected.")
- return effective_changes if len(effective_changes) > 0 else None
+ return effective_changes
def dry_or(self, func):
if self.application.args.dry:
self.logger.info("Running dry, otherwise: %s" % func)
else:
+ self.logger.info("Running %s" % func)
func()
diff --git a/scripts/tui/src/ovirt/node/setup/keyboard_page.py b/scripts/tui/src/ovirt/node/setup/keyboard_page.py
index 840aca6..89e8cfc 100644
--- a/scripts/tui/src/ovirt/node/setup/keyboard_page.py
+++ b/scripts/tui/src/ovirt/node/setup/keyboard_page.py
@@ -39,7 +39,6 @@
def model(self):
cfg = defaults.Keyboard().retrieve()
- self.logger.debug(cfg)
model = {}
model["keyboard.layout"] = cfg["layout"] or ""
return model
diff --git a/scripts/tui/src/ovirt/node/setup/logging_page.py b/scripts/tui/src/ovirt/node/setup/logging_page.py
index 65e9af6..ee25e88 100644
--- a/scripts/tui/src/ovirt/node/setup/logging_page.py
+++ b/scripts/tui/src/ovirt/node/setup/logging_page.py
@@ -52,10 +52,10 @@
model["logrotate.max_size"] = logrotate["max_size"] or "1024"
model["rsyslog.address"] = syslog["server"] or ""
- model["rsyslog.port"] = syslog["port"] or ""
+ model["rsyslog.port"] = syslog["port"] or "514"
model["netconsole.address"] = netconsole["server"] or ""
- model["netconsole.port"] = netconsole["port"] or ""
+ model["netconsole.port"] = netconsole["port"] or "6666"
return model
diff --git a/scripts/tui/src/ovirt/node/setup/monitoring_page.py b/scripts/tui/src/ovirt/node/setup/monitoring_page.py
index bbfb6d1..14f35e8 100644
--- a/scripts/tui/src/ovirt/node/setup/monitoring_page.py
+++ b/scripts/tui/src/ovirt/node/setup/monitoring_page.py
@@ -18,17 +18,16 @@
# 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.
+from ovirt.node import plugins, ui, valid, utils
+from ovirt.node.config import defaults
+from ovirt.node.plugins import ChangesHelper
"""
Configure Monitoring
"""
-import ovirt.node.plugins
-import ovirt.node.valid
-import ovirt.node.ui
-
-class Plugin(ovirt.node.plugins.NodePlugin):
+class Plugin(plugins.NodePlugin):
_model = None
_widgets = None
@@ -39,40 +38,58 @@
return 90
def model(self):
- if not self._model:
- self._model = {
- "collectd.address": "",
- "collectd.port": "7634",
- }
- return self._model
+ cfg = defaults.Collectd().retrieve()
+ model = {
+ "collectd.address": cfg["server"] or "",
+ "collectd.port": cfg["port"] or "7634",
+ }
+ return model
def validators(self):
return {
- "collectd.address": ovirt.node.valid.FQDNOrIPAddress(),
- "collectd.port": ovirt.node.valid.Port(),
+ "collectd.address": valid.Empty() | valid.FQDNOrIPAddress(),
+ "collectd.port": valid.Port(),
}
def ui_content(self):
widgets = [
- ("header", ovirt.node.ui.Header("Monitoring Configuration")),
+ ("header", ui.Header("Monitoring Configuration")),
- ("label", ovirt.node.ui.Label("Collectd gathers statistics " +
+ ("label", ui.Label("Collectd gathers statistics " +
"about the system and can be used to find " +
"performance bottlenecks and predict future " +
"system load.")),
- ("collectd.address", ovirt.node.ui.Entry("Server Address:")),
- ("collectd.port", ovirt.node.ui.Entry("Server Port:")),
+ ("collectd.address", ui.Entry("Server Address:")),
+ ("collectd.port", ui.Entry("Server Port:")),
]
# Save it "locally" as a dict, for better accessability
self._widgets = dict(widgets)
- page = ovirt.node.ui.Page(widgets)
+ page = ui.Page(widgets)
return page
def on_change(self, changes):
pass
- self._model.update(changes)
def on_merge(self, effective_changes):
- pass
+ self.logger.debug("Saving monitoring page")
+ changes = ChangesHelper(self.pending_changes(False))
+ model = self.model()
+ model.update(effective_changes)
+ effective_model = ChangesHelper(model)
+
+ self.logger.debug("Saving monitoring page: %s" % changes.changes)
+ self.logger.debug("monitoring model: %s" % effective_model.changes)
+
+ collectd_keys = ["collectd.address", "collectd.port"]
+
+ txs = utils.Transaction("Updating monitoring configuration")
+
+ if changes.any_key_in_change(collectd_keys):
+ model = defaults.Collectd()
+ model.update(*effective_model.get_key_values(collectd_keys))
+ txs += model.transaction()
+
+ txs.prepare()
+ self.dry_or(lambda: txs())
diff --git a/scripts/tui/src/ovirt/node/setup/remote_storage_page.py b/scripts/tui/src/ovirt/node/setup/remote_storage_page.py
index 202e8f6..55801c0 100644
--- a/scripts/tui/src/ovirt/node/setup/remote_storage_page.py
+++ b/scripts/tui/src/ovirt/node/setup/remote_storage_page.py
@@ -18,18 +18,16 @@
# 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.
-from ovirt.node import utils, valid
+from ovirt.node import utils, valid, plugins, ui
from ovirt.node.config import defaults
from ovirt.node.plugins import ChangesHelper
-import ovirt.node.plugins
-import ovirt.node.ui
"""
Configure Remote Storage
"""
-class Plugin(ovirt.node.plugins.NodePlugin):
+class Plugin(plugins.NodePlugin):
_model = None
_widgets = None
@@ -55,23 +53,21 @@
def ui_content(self):
widgets = [
- ("header", ovirt.node.ui.Header("Remote Storage")),
+ ("header", ui.Header("Remote Storage")),
- ("iscsi.initiator_name", ovirt.node.ui.Entry("iSCSI Initiator " +
- "Name:",
- align_vertical=True)),
+ ("iscsi.initiator_name", ui.Entry("iSCSI Initiator Name:",
+ align_vertical=True)),
- ("divider", ovirt.node.ui.Divider()),
+ ("divider", ui.Divider()),
- ("nfsv4.domain", ovirt.node.ui.Entry("NFSv4 Domain " +
- "(example.redhat.com):",
- align_vertical=True)),
+ ("nfsv4.domain", ui.Entry("NFSv4 Domain (example.redhat.com):",
+ align_vertical=True)),
]
# Save it "locally" as a dict, for better accessability
self._widgets = dict(widgets)
- page = ovirt.node.ui.Page(widgets)
+ page = ui.Page(widgets)
return page
def on_change(self, changes):
diff --git a/scripts/tui/src/ovirt/node/setup/security_page.py b/scripts/tui/src/ovirt/node/setup/security_page.py
index 65f89b3..47d88fd 100644
--- a/scripts/tui/src/ovirt/node/setup/security_page.py
+++ b/scripts/tui/src/ovirt/node/setup/security_page.py
@@ -38,15 +38,16 @@
return 20
def model(self):
- if not self._model:
- self._model = {
- "ssh.enabled": "no",
- "strongrng.aesni": "no",
- "strongrng.bytes_used": "",
- "passwd.admin.password": "",
- "passwd.admin.password_confirmation": "",
- }
- return self._model
+ cfg = defaults.SSH().retrieve()
+ self.logger.debug(cfg)
+ model = {
+ "ssh.pwauth": cfg["pwauth"] or False,
+ "strongrng.aesni": cfg["disable_aesni"] or False,
+ "strongrng.num_bytes": cfg["num_bytes"] or "",
+ "passwd.admin.password": "",
+ "passwd.admin.password_confirmation": "",
+ }
+ return model
def validators(self):
number_or_empty = valid.Number(range=[0, None]) | \
@@ -60,7 +61,7 @@
def ui_content(self):
widgets = [
("header[0]", ui.Header("Remote Access")),
- ("ssh.enabled", ui.Checkbox("Enable ssh password authentication")),
+ ("ssh.pwauth", ui.Checkbox("Enable SSH password authentication")),
("header[1]", ui.Header("Strong Random Number Generator")),
("strongrng.aesni", ui.Checkbox("Enable AES-NI")),
@@ -78,11 +79,16 @@
return page
def on_change(self, changes):
- self._model.update(changes)
+ m = self.model()
+ m.update(self.pending_changes() or {})
+ effective_model = ChangesHelper(m)
- if self._model["passwd.admin.password"] != \
- self._model["passwd.admin.password_confirmation"]:
- raise exceptions.InvalidData("Passwords do not match.")
+ passwd_keys = ["passwd.admin.password",
+ "passwd.admin.password_confirmation"]
+ if effective_model.any_key_in_change(passwd_keys):
+ passwd, passwdc = effective_model.get_key_values(passwd_keys)
+ if passwd != passwdc:
+ raise exceptions.InvalidData("Passwords do not match.")
def on_merge(self, effective_changes):
self.logger.debug("Saving security page")
@@ -95,7 +101,7 @@
self.logger.debug("Remote security model: %s" %
effective_model.changes)
- ssh_keys = ["ssh.enabled", "strongrng.num_bytes", "strongrng.aesni"]
+ ssh_keys = ["ssh.pwauth", "strongrng.num_bytes", "strongrng.aesni"]
passwd_keys = ["passwd.admin.password",
"passwd.admin.password_confirmation"]
@@ -112,8 +118,11 @@
raise exceptions.InvalidData("Passwords do not match")
passwd = utils.security.Passwd()
- self.logger.debug("Setting admin password.")
- self.dry_or(lambda: passwd.set_password("admin", pw))
+ class SetAdminPasswd(utils.Transaction.Element):
+ def commit(self):
+ self.logger.debug("Setting admin password.")
+ passwd.set_password("admin", pw)
+ txs += [SetAdminPasswd()]
txs.prepare() # Just to display something in dry mode
self.dry_or(lambda: txs())
diff --git a/scripts/tui/src/ovirt/node/setup/snmp_page.py b/scripts/tui/src/ovirt/node/setup/snmp_page.py
index f25818b..d2fc9ab 100644
--- a/scripts/tui/src/ovirt/node/setup/snmp_page.py
+++ b/scripts/tui/src/ovirt/node/setup/snmp_page.py
@@ -18,12 +18,13 @@
# 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.
+from ovirt.node import plugins, valid, ui, utils
+from ovirt.node.config import defaults
+from ovirt.node.plugins import ChangesHelper
"""
Configure SNMP
"""
-
-from ovirt.node import plugins, valid, ui, exceptions
class Plugin(plugins.NodePlugin):
@@ -37,13 +38,14 @@
return 40
def model(self):
- if not self._model:
- self._model = {
- "snmp.enabled": "no",
- "snmp.password": "",
- "snmp.password_confirmation": "",
- }
- return self._model
+ cfg = defaults.SNMP().retrieve()
+ self.logger.debug(cfg)
+ model = {
+ "snmp.enabled": True if cfg["password"] else False,
+ "snmp.password": "",
+ "snmp.password_confirmation": "",
+ }
+ return model
def validators(self):
return {
@@ -53,15 +55,14 @@
def ui_content(self):
widgets = [
- ("snmp._header", ui.Header("SNMP")),
+ ("header[0]", ui.Header("SNMP")),
("snmp.enabled", ui.Checkbox("Enable SNMP")),
- ("ssh._divider", ui.Divider()),
+ ("divider[0]", ui.Divider()),
-
- ("snmp.password._header", ui.Header("SNMP Password")),
+ ("header[1]", ui.Header("SNMP Password")),
("snmp.password", ui.PasswordEntry("Password:")),
- ("snmp.password_confirmation", ui.PasswordEntry(
- "Confirm Password:")),
+ ("snmp.password_confirmation",
+ ui.PasswordEntry("Confirm Password:")),
]
# Save it "locally" as a dict, for better accessability
self._widgets = dict(widgets)
@@ -70,11 +71,39 @@
return page
def on_change(self, changes):
- self._model.update(changes)
+ m = self.model()
+ m.update(self.pending_changes() or {})
+ effective_model = ChangesHelper(m)
- if self._model["snmp.password"] != \
- self._model["snmp.password_confirmation"]:
- raise exceptions.InvalidData("Passwords do not match.")
+ snmp_keys = ["snmp.password",
+ "snmp.password_confirmation"]
+ if effective_model.any_key_in_change(snmp_keys):
+ passwd, passwdc = effective_model.get_key_values(snmp_keys)
+ #if passwd != passwdc:
+ # raise exceptions.InvalidData("Passwords do not match.")
def on_merge(self, effective_changes):
- pass
+ self.logger.debug("Saving SNMP page")
+ changes = ChangesHelper(self.pending_changes(False))
+ model = self.model()
+ model.update(effective_changes)
+ effective_model = ChangesHelper(model)
+
+ self.logger.debug("Saving SNMP page: %s" % changes.changes)
+ self.logger.debug("SNMP model: %s" % effective_model.changes)
+
+ snmp_keys = ["snmp.password", "snmp.enabled"]
+
+ txs = utils.Transaction("Updating SNMP configuration")
+
+ if changes.any_key_in_change(snmp_keys):
+ values = effective_model.get_key_values(snmp_keys)
+ args = [values[0]]
+ if values[1] is False: # If set to disabled, set password to None
+ args[0] = None
+ model = defaults.SNMP()
+ model.update(*args)
+ txs += model.transaction()
+
+ txs.prepare()
+ self.dry_or(lambda: txs())
diff --git a/scripts/tui/src/ovirt/node/ui/__init__.py b/scripts/tui/src/ovirt/node/ui/__init__.py
index dc3f086..0bc5b86 100644
--- a/scripts/tui/src/ovirt/node/ui/__init__.py
+++ b/scripts/tui/src/ovirt/node/ui/__init__.py
@@ -94,7 +94,7 @@
def __init__(self, children):
super(Page, self).__init__(children)
- self.buttons = [
+ self.buttons = self.buttons or [
(None, SaveButton()),
(None, ResetButton())
]
@@ -112,6 +112,12 @@
@Element.signal_change
def close(self, v=True):
self._close = v
+
+
+class InfoDialog(Dialog):
+ def __init__(self, title, children):
+ super(InfoDialog, self).__init__(title, children)
+ self.buttons = [(None, CloseButton())]
class Row(ContainerElement):
@@ -196,6 +202,11 @@
super(ResetButton, self).__init__("Reset", enabled)
+class CloseButton(Button):
+ def __init__(self, enabled=True):
+ super(CloseButton, self).__init__("Close", enabled)
+
+
class Divider(Element):
def __init__(self, char=u" "):
super(Divider, self).__init__()
diff --git a/scripts/tui/src/ovirt/node/ui/builder.py b/scripts/tui/src/ovirt/node/ui/builder.py
index bca8423..4710d51 100644
--- a/scripts/tui/src/ovirt/node/ui/builder.py
+++ b/scripts/tui/src/ovirt/node/ui/builder.py
@@ -57,7 +57,8 @@
# Add buttons
button_widgets = []
for path, item in container.buttons:
- assert type(item) in [ui.SaveButton, ui.ResetButton, ui.Button]
+ assert type(item) in [ui.SaveButton, ui.ResetButton, ui.CloseButton,
+ ui.Button]
button_widgets.append(build_button(path, item, tui, plugin))
if button_widgets:
@@ -144,7 +145,8 @@
item.connect_signal("enabled", on_item_enabled_change_cb)
def on_widget_value_change(widget, new_value):
- LOGGER.debug("Entry changed, calling callback: '%s'" % path)
+ LOGGER.debug("Entry %s changed, calling callback: '%s'" % (widget,
+ path))
try:
change = {path: new_value}
@@ -195,11 +197,13 @@
plugin.sig_valid.connect(lambda w, v: widget.enable(v))
def on_widget_click_cb(widget, data=None):
- LOGGER.debug("Button click: %s %s" % (path, widget))
+ LOGGER.debug("Button click: %s" % {"path": path, "widget": widget})
if itemtype is ui.Button:
plugin._on_ui_change({path: True})
if itemtype in [ui.Button, ui.SaveButton]:
r = plugin._on_ui_save()
+ if itemtype in [ui.CloseButton]:
+ r = tui.close_topmost_dialog()
if itemtype in [ui.ResetButton]:
r = plugin._on_ui_reset()
tui._display_plugin(plugin)
@@ -233,6 +237,13 @@
def build_checkbox(path, item, tui, plugin):
widget = ui.widgets.Checkbox(item.label, item.state())
+
+ def on_widget_change_cb(widget, data=None):
+ item.state(data)
+ LOGGER.debug("Checkbox changed, calling callback: %s" % data)
+ plugin._on_ui_change({path: data})
+
+ urwid.connect_signal(widget, "change", on_widget_change_cb)
return widget
diff --git a/scripts/tui/src/ovirt/node/ui/tui.py b/scripts/tui/src/ovirt/node/ui/tui.py
index 3756d5a..669ce69 100644
--- a/scripts/tui/src/ovirt/node/ui/tui.py
+++ b/scripts/tui/src/ovirt/node/ui/tui.py
@@ -128,6 +128,12 @@
widget = ui.builder.build_page(self, self._current_plugin, dialog)
return self.__display_as_dialog(widget, dialog.title)
+ def close_topmost_dialog(self):
+ dialog = [w for w in self.__widget_stack
+ if type(w) is ovirt.node.ui.widgets.ModalDialog][-1]
+ assert len(dialog) == 1
+ self.__close_dialog(dialog)
+
def quit(self):
"""Quit the UI
"""
@@ -192,7 +198,7 @@
msg += "- %s\n" % (field.strip(":"))
if msg:
self.__display_as_dialog(urwid.Filler(urwid.Text(
- "The following fields were changed:\n%s" %
+ "The following fields have changed:\n%s" %
msg)),
"Pending changes")
has_outstanding_changes = True
diff --git a/scripts/tui/src/ovirt/node/ui/widgets.py b/scripts/tui/src/ovirt/node/ui/widgets.py
index 5967f8a..7564ce7 100644
--- a/scripts/tui/src/ovirt/node/ui/widgets.py
+++ b/scripts/tui/src/ovirt/node/ui/widgets.py
@@ -429,6 +429,8 @@
class Checkbox(urwid.WidgetWrap):
+ signals = ['change']
+
def __init__(self, label, state):
self._label = urwid.Text(label)
self._label_attrmap = urwid.AttrMap(self._label,
@@ -437,12 +439,19 @@
self._divider = urwid.Divider()
self._container = urwid.Columns([self._label_attrmap,
self._checkbox])
+
+ def on_change_cb(widget, new_value):
+ urwid.emit_signal(self, 'change', self, new_value)
+ urwid.connect_signal(self._checkbox, 'change', on_change_cb)
+
super(Checkbox, self).__init__(urwid.Pile([self._container,
self._divider]))
def set_text(self, s):
if s in [True, False]:
self._checkbox.set_state(s)
+ else:
+ raise Exception("Invalid value: %s" % s)
class PageWidget(urwid.WidgetWrap):
@@ -488,10 +497,21 @@
(maxcol,) = size
self._shift_view_to_cursor = bool(focus)
- txt = self.get_edit_text().ljust(maxcol, self.char)[:maxcol]
+ txt = self.get_edit_text()
+ txt = u"".join([self._mask] * len(txt)) if self._mask else txt
+ txt = txt.ljust(maxcol, self.char)[:maxcol]
canv = urwid.Text(txt).render((maxcol,))
if focus:
canv = urwid.CompositeCanvas(canv)
canv.cursor = self.get_cursor_coords((maxcol,))
return canv
+
+
+class TabablePile(urwid.Pile):
+ def keypress(self, size, key):
+ #if "tab" in key:
+ # self.focus_position += 1
+ #elif "shift tab" in key:
+ # self.focus_position -= 1
+ return (size, key)
diff --git a/scripts/tui/src/ovirt/node/utils/__init__.py b/scripts/tui/src/ovirt/node/utils/__init__.py
index 2562030..c42342b 100644
--- a/scripts/tui/src/ovirt/node/utils/__init__.py
+++ b/scripts/tui/src/ovirt/node/utils/__init__.py
@@ -27,11 +27,10 @@
And use the model.py module for oVirt Node's defaults file.
"""
-import hashlib
+from ovirt.node import base, exceptions
import augeas as _augeas
+import hashlib
import system_config_keyboard.keyboard
-
-from ovirt.node import base
class AugeasWrapper(base.Base):
@@ -216,7 +215,7 @@
>>> tx()
Traceback (most recent call last):
...
- RuntimeError: Transaction failed: Step C
+ TransactionError: 'Transaction failed: Step C'
"""
def __init__(self, title, elements=[]):
super(Transaction, self).__init__()
@@ -229,7 +228,8 @@
for element in self:
self.logger.debug("Preparing element '%s'" % element)
if Transaction.Element not in element.__class__.mro():
- raise Exception("%s is no Transaction.Element" % element)
+ raise exceptions.PreconditionError(("%s is no Transaction." +
+ "Element") % element)
self._prepared_elements.append(element)
element.prepare()
return True
@@ -255,7 +255,8 @@
except Exception as e:
self.logger.warning("Transaction failed: %s" % e.message)
self.abort()
- raise RuntimeError("Transaction failed: %s" % e.message)
+ raise exceptions.TransactionError("Transaction failed: " +
+ "%s" % e.message)
self.logger.info("Transaction '%s' succeeded" % self)
return True
diff --git a/scripts/tui/src/ovirt/node/utils/security.py b/scripts/tui/src/ovirt/node/utils/security.py
index e236ca7..7d2f200 100644
--- a/scripts/tui/src/ovirt/node/utils/security.py
+++ b/scripts/tui/src/ovirt/node/utils/security.py
@@ -50,15 +50,14 @@
class Ssh(base.Base):
def __init__(self):
super(Ssh, self).__init__()
- import ovirtnode.ovirtfunctions as ofunc
- self.ofunc = ofunc
- def __update_profile(self, rng_num_bytes, enable_aes):
+ def __update_profile(self, rng_num_bytes, disable_aes):
+ import ovirtnode.ovirtfunctions as ofunc
additional_lines = []
- self.ofunc.unmount_config("/etc/profile")
+ ofunc.unmount_config("/etc/profile")
process.system("sed -i '/OPENSSL_DISABLE_AES_NI/d' /etc/profile")
- if not enable_aes:
+ if disable_aes:
additional_lines += ["export OPENSSL_DISABLE_AES_NI=1"]
process.system("sed -i '/SSH_USE_STRONG_RNG/d' /etc/profile")
@@ -71,27 +70,29 @@
with open("/etc/profile", "a") as f:
lines = "\n" + "\n".join(additional_lines)
f.write(lines)
- self.ofunc.ovirt_store_config("/etc/profile")
+ ofunc.ovirt_store_config("/etc/profile")
self.restart()
- def aes_ni(self, enable=None):
+ def disable_aesni(self, disable=None):
"""Set/Get AES NI for OpenSSL
Args:
enable: True or False
Returns:
The status of aes_ni
"""
- rng, aes = self.ofunc.rng_status()
- if enable in [True, False]:
- self.__update_profile(rng, enable)
+ import ovirtnode.ovirtfunctions as ofunc
+ rng, aes = ofunc.rng_status()
+ if disable in [True, False]:
+ self.__update_profile(rng, disable)
else:
- self.logger.warning("Unknown value for AES NI: %s" % enable)
- return self.ofunc.rng_status()[1] # FIXME should rurn bool
+ self.logger.warning("Unknown value for AES NI: %s" % disable)
+ return ofunc.rng_status()[1] # FIXME should rurn bool
# and does it return disable_aes_ni?
def strong_rng(self, num_bytes=None):
- rng, aes = self.ofunc.rng_status()
+ import ovirtnode.ovirtfunctions as ofunc
+ rng, aes = ofunc.rng_status()
if valid.Number(range=[0, None]).validate(num_bytes):
self.__update_profile(num_bytes, aes)
elif num_bytes is None:
@@ -99,7 +100,7 @@
else:
self.logger.warning("Unknown value for RNG num bytes: " +
"%s" % num_bytes)
- return self.ofunc.rng_status()[0]
+ return ofunc.rng_status()[0]
def restart(self):
self.logger.debug("Restarting SSH")
--
To view, visit http://gerrit.ovirt.org/9968
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I1e8b50d71990a3df3e69f0ff00b0ae52d17a7cdc
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