[node-patches] Change in ovirt-node[master]: setup: Improve validity checks

fabiand at fedoraproject.org fabiand at fedoraproject.org
Tue Dec 11 20:09:42 UTC 2012


Fabian Deutsch has uploaded a new change for review.

Change subject: setup: Improve validity checks
......................................................................

setup: Improve validity checks

Change-Id: I4274c55c09ada89e85d30ad5c5c6ed2762d4a24d
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/kdump_page.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/network_page.py
M scripts/tui/src/ovirt/node/setup/remote_storage_page.py
M scripts/tui/src/ovirt/node/setup/security_page.py
9 files changed, 225 insertions(+), 115 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-node refs/changes/56/9956/1

diff --git a/scripts/tui/src/ovirt/node/config/defaults.py b/scripts/tui/src/ovirt/node/config/defaults.py
index 5851951..a382ed7 100644
--- a/scripts/tui/src/ovirt/node/config/defaults.py
+++ b/scripts/tui/src/ovirt/node/config/defaults.py
@@ -154,7 +154,7 @@
 
 
 class NodeConfigFileSection(base.Base):
-    none_value = ""
+    none_value = None
 
     def __init__(self, cfgfile=None):
         super(NodeConfigFileSection, self).__init__()
@@ -189,6 +189,11 @@
 
     def retrieve(self):
         """Returns the config keys of the current component
+        
+        Returns:
+            A dict with a mapping (arg, value).
+            arg corresponds to the named arguments of the subclass's configure()
+            method.
         """
         func = self.update.wrapped_func
         varnames = func.func_code.co_varnames[1:]
@@ -198,7 +203,7 @@
             value = cfg[key] if key in cfg else self.none_value
             values += (value,)
         assert len(varnames) == len(values)
-        return zip(varnames, values)
+        return dict(zip(varnames, values))
 
     def clear(self):
         """Remove the configuration for this item
@@ -218,6 +223,9 @@
     @staticmethod
     def map_and_update_defaults_decorator(func):
         """
+        FIXME Use some kind of map to map between args and env_Vars
+              this would alsoallow kwargs
+
         >>> class Foo(object):
         ...     keys = None
         ...     def _map_config_and_update_defaults(self, *args, **kwargs):
@@ -258,18 +266,18 @@
     >>> n = Network(cfgfile)
     >>> n.update("eth0", "static", "10.0.0.1", "255.0.0.0", "10.0.0.255",
     ...          "20")
-    >>> data = n.retrieve()
+    >>> data = sorted(n.retrieve().items())
     >>> data[:3]
-    [('iface', 'eth0'), ('bootproto', 'static'), ('ipaddr', '10.0.0.1')]
-    >>> data [3:]
-    [('netmask', '255.0.0.0'), ('gateway', '10.0.0.255'), ('vlanid', '20')]
+    [('bootproto', 'static'), ('gateway', '10.0.0.255'), ('iface', 'eth0')]
+    >>> data[3:]
+    [('ipaddr', '10.0.0.1'), ('netmask', '255.0.0.0'), ('vlanid', '20')]
 
     >>> n.clear()
-    >>> data = n.retrieve()
-    >>> data [:3]
-    [('iface', ''), ('bootproto', ''), ('ipaddr', '')]
-    >>> data [3:]
-    [('netmask', ''), ('gateway', ''), ('vlanid', '')]
+    >>> data = sorted(n.retrieve().items())
+    >>> data[:3]
+    [('bootproto', ''), ('gateway', ''), ('iface', '')]
+    >>> data[3:]
+    [('ipaddr', ''), ('netmask', ''), ('vlanid', '')]
     """
     keys = ("OVIRT_BOOTIF",
             "OVIRT_BOOTPROTO",
@@ -337,9 +345,10 @@
         """We mangle the original vale a bit for py convenience
         """
         cfg = dict(NodeConfigFileSection.retrieve(self))
-        return {
-                "servers": cfg["servers"].split(",")
-                }
+        cfg.update({
+            "servers": cfg["servers"].split(",")
+            })
+        return cfg
 
     def transaction(self):
         """Derives the nameserver config from OVIRT_DNS
@@ -424,9 +433,10 @@
 
     def retrieve(self):
         cfg = dict(NodeConfigFileSection.retrieve(self))
-        return {
-                "servers": cfg["servers"].split(",")
-                }
+        cfg.update({
+            "servers": cfg["servers"].split(",")
+            })
+        return cfg
 
     def transaction(self):
         return utils.Transaction("Configuring timeserver")
@@ -441,8 +451,8 @@
     >>> port = "514"
     >>> n = Syslog(cfgfile)
     >>> n.update(server, port)
-    >>> n.retrieve()
-    [('server', '10.0.0.6'), ('port', '514')]
+    >>> sorted(n.retrieve().items())
+    [('port', '514'), ('server', '10.0.0.6')]
     """
     keys = ("OVIRT_SYSLOG_SERVER",
             "OVIRT_SYSLOG_PORT")
@@ -475,8 +485,8 @@
     >>> port = "42"
     >>> n = Collectd(cfgfile)
     >>> n.update(server, port)
-    >>> n.retrieve()
-    [('server', '10.0.0.7'), ('port', '42')]
+    >>> sorted(n.retrieve().items())
+    [('port', '42'), ('server', '10.0.0.7')]
     """
     keys = ("OVIRT_COLLECTD_SERVER",
             "OVIRT_COLLECTD_PORT")
@@ -514,12 +524,12 @@
     >>> nfs_url = "host.example.com"
     >>> ssh_url = "root at host.example.com"
     >>> n = KDump(cfgfile)
-    >>> n.update(nfs_url, ssh_url, '')
-    >>> d = n.retrieve()
+    >>> n.update(nfs_url, ssh_url, True)
+    >>> d = sorted(n.retrieve().items())
     >>> d[:2]
-    [('nfs', 'host.example.com'), ('ssh', 'root at host.example.com')]
+    [('local', True), ('nfs', 'host.example.com')]
     >>> d[2:]
-    [('local', '')]
+    [('ssh', 'root at host.example.com')]
     """
     keys = ("OVIRT_KDUMP_NFS",
             "OVIRT_KDUMP_SSH",
@@ -529,6 +539,10 @@
     def update(self, nfs, ssh, local):
         (valid.Empty(or_none=True) | valid.FQDNOrIPAddress())(nfs)
         (valid.Empty(or_none=True) | valid.URL())(ssh)
+        (valid.Empty(or_none=True) | valid.Boolean())(local)
+        return {
+                "OVIRT_KDUMP_LOCAL": "true" if local else None
+                }
 
     def transaction(self):
         cfg = dict(self.retrieve())
@@ -636,11 +650,11 @@
     >>> cfgfile = ConfigFile(fn, SimpleProvider)
     >>> n = iSCSI(cfgfile)
     >>> n.update("node.example.com", "target.example.com", "10.0.0.8", "42")
-    >>> data = n.retrieve()
+    >>> data = sorted(n.retrieve().items())
     >>> data[:2]
-    [('name', 'node.example.com'), ('target_name', 'target.example.com')]
+    [('name', 'node.example.com'), ('target_host', '10.0.0.8')]
     >>> data[2:]
-    [('target_host', '10.0.0.8'), ('target_port', '42')]
+    [('target_name', 'target.example.com'), ('target_port', '42')]
     """
     keys = ("OVIRT_ISCSI_NODE_NAME",
             "OVIRT_ISCSI_TARGET_NAME",
@@ -673,7 +687,7 @@
     >>> cfgfile = ConfigFile(fn, SimpleProvider)
     >>> n = SNMP(cfgfile)
     >>> n.update("secret")
-    >>> n.retrieve()
+    >>> n.retrieve().items()
     [('password', 'secret')]
     """
     keys = ("OVIRT_SNMP_PASSWORD",)
@@ -693,8 +707,8 @@
     >>> server = "10.0.0.9"
     >>> port = "666"
     >>> n.update(server, port)
-    >>> n.retrieve()
-    [('server', '10.0.0.9'), ('port', '666')]
+    >>> sorted(n.retrieve().items())
+    [('port', '666'), ('server', '10.0.0.9')]
     """
     keys = ("OVIRT_NETCONSOLE_SERVER",
             "OVIRT_NETCONSOLE_PORT")
@@ -726,7 +740,7 @@
     >>> n = Logrotate(cfgfile)
     >>> max_size = "42"
     >>> n.update(max_size)
-    >>> n.retrieve()
+    >>> n.retrieve().items()
     [('max_size', '42')]
     """
     # FIXME this key is new!
@@ -758,7 +772,7 @@
     >>> n = CIM(cfgfile)
     >>> n.update(True)
     >>> n.retrieve()
-    [('enabled', '1')]
+    {'enabled': '1'}
     """
     keys = ("OVIRT_CIM_ENABLED",)
 
@@ -778,7 +792,7 @@
     >>> layout = "de_DE.UTF-8"
     >>> n.update(layout)
     >>> n.retrieve()
-    [('layout', 'de_DE.UTF-8')]
+    {'layout': 'de_DE.UTF-8'}
     """
     # FIXME this key is new!
     keys = ("OVIRT_KEYBOARD_LAYOUT",)
@@ -813,7 +827,7 @@
     >>> n = NFSv4(cfgfile)
     >>> domain = "foo.example"
     >>> n.update(domain)
-    >>> n.retrieve()
+    >>> n.retrieve().items()
     [('domain', 'foo.example')]
     """
     # FIXME this key is new!
@@ -846,25 +860,34 @@
     >>> cfgfile = ConfigFile(fn, SimpleProvider)
     >>> n = SSH(cfgfile)
     >>> pwauth = True
-    >>> n.update(pwauth)
-    >>> n.retrieve()
-    [('pwauth', True)]
+    >>> num_bytes = "24"
+    >>> disable_aesni = True
+    >>> n.update(pwauth, num_bytes, disable_aesni)
+    >>> sorted(n.retrieve().items())
+    [('disable_aesni', True), ('num_bytes', '24'), ('pwauth', True)]
     """
     keys = ("OVIRT_SSH_PWAUTH",
             "OVIRT_USE_STRONG_RNG",
-            "OVIRT_ENABLE_AES_NI")
+            "OVIRT_DISABLE_AES_NI")
 
     @NodeConfigFileSection.map_and_update_defaults_decorator
-    def update(self, pwauth, num_bytes, aesni):
+    def update(self, pwauth, num_bytes, disable_aesni):
         valid.Boolean()(pwauth)
         valid.Number()(num_bytes)
-        valid.Boolean()(aesni)
+        valid.Boolean()(disable_aesni)
+        return {
+                "OVIRT_SSH_PWAUTH": "yes" if pwauth else None,
+                "OVIRT_DISABLE_AES_NI": "true" if disable_aesni else None
+                }
 
     def retrieve(self):
         cfg = dict(NodeConfigFileSection.retrieve(self))
-        return {
-                "pwauth": True if cfg["pwauth"] == "yes" else False
-                }
+        cfg.update({
+                "pwauth": True if cfg["pwauth"] == "yes" else False,
+                "disable_aesni": True if cfg["disable_aesni"] == "true" \
+                                      else False
+                })
+        return cfg
 
     def transaction(self):
         cfg = dict(self.retrieve())
diff --git a/scripts/tui/src/ovirt/node/exceptions.py b/scripts/tui/src/ovirt/node/exceptions.py
index 5c2dc9f..181c587 100644
--- a/scripts/tui/src/ovirt/node/exceptions.py
+++ b/scripts/tui/src/ovirt/node/exceptions.py
@@ -43,3 +43,11 @@
 
     def __str__(self):
         return repr(self.message)
+
+
+class PreconditionFailed(Exception):
+    def __init__(self, msg):
+        self.message = msg
+
+    def __str__(self):
+        return repr(self.message)
diff --git a/scripts/tui/src/ovirt/node/plugins.py b/scripts/tui/src/ovirt/node/plugins.py
index fdaed68..fea4845 100644
--- a/scripts/tui/src/ovirt/node/plugins.py
+++ b/scripts/tui/src/ovirt/node/plugins.py
@@ -22,10 +22,10 @@
 """
 This contains much stuff related to plugins
 """
+from ovirt.node import base, exceptions
+import ovirt.node.exceptions
 import pkgutil
 
-from ovirt.node import base
-import ovirt.node.exceptions
 
 
 def __walk_plugins(module):
@@ -67,6 +67,7 @@
     """
 
     validate_changes = True
+    only_merge_on_valid_changes = True
 
     def __init__(self, application):
         super(NodePlugin, self).__init__()
@@ -233,16 +234,36 @@
         """Called when data should be saved
         Calls merge_changes, but only with values that really changed
         """
-        self.logger.debug("Request to apply model changes")
         effective_changes = self.pending_changes() or {}
+        is_valid = False
+
+        self.logger.debug("Request to apply model changes: %s" %
+                          effective_changes)
+
+        try:
+            is_valid = self.validate(effective_changes)
+        except exceptions.InvalidData as e:
+            self.logger.info("Changes to be merged are invalid: %s" %
+                             e.message)
+
+        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)
+
         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")
+            self.logger.debug("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 = {}
+        else:
+            self.logger.info("Changes were not merged.")
+
         return successfull_merge
 
     def _on_ui_reset(self):
diff --git a/scripts/tui/src/ovirt/node/setup/kdump_page.py b/scripts/tui/src/ovirt/node/setup/kdump_page.py
index a08f9d9..9daf83b 100644
--- a/scripts/tui/src/ovirt/node/setup/kdump_page.py
+++ b/scripts/tui/src/ovirt/node/setup/kdump_page.py
@@ -18,21 +18,21 @@
 # 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.
-
 """
 Configure KDump
 """
 
-import ovirt.node.plugins
-import ovirt.node.valid
-import ovirt.node.ui
+from ovirt.node import utils, plugins, ui, valid
+from ovirt.node.config import defaults
+from ovirt.node.plugins import ChangesHelper
 
 
-class Plugin(ovirt.node.plugins.NodePlugin):
+class Plugin(plugins.NodePlugin):
     _model = None
     _widgets = None
 
     _types = [
+                 ("disabled", "Disable"),
                  ("local", "Local"),
                  ("ssh", "SSH"),
                  ("nfs", "NFS")
@@ -48,22 +48,30 @@
         """Returns the model of this plugin
         This is expected to parse files and all stuff to build up the model.
         """
-        if not self._model:
-            self._model = {
-                # The target address
-                "kdump.type": "ssh",
-                "kdump.ssh_location": "",
-                "kdump.nfs_location": "",
-            }
-        return self._model
+        cfg = defaults.KDump().retrieve()
+
+        ktype = "disabled"
+        for k in ["local", "ssh", "nfs"]:
+            if cfg[k]:
+                ktype = k
+                break
+
+        model = {
+            # The target address
+            "kdump.type": ktype,
+            "kdump.ssh_location": cfg["ssh"]or "",
+            "kdump.nfs_location": cfg["nfs"]or "",
+        }
+        return model
 
     def validators(self):
         """Validators validate the input on change and give UI feedback
         """
+        # FIXME improve validation for ssh and nfs
         return {
-                "kdump.type": ovirt.node.valid.Options(self._types),
-                "kdump.ssh_location": ovirt.node.valid.NoSpaces(),
-                "kdump.nfs_location": ovirt.node.valid.NoSpaces(),
+                "kdump.type": valid.Options(dict(self._types).keys()),
+                "kdump.ssh_location": valid.NoSpaces(),
+                "kdump.nfs_location": valid.NoSpaces(),
             }
 
     def ui_content(self):
@@ -71,17 +79,17 @@
         This is an ordered list of (path, widget) tuples.
         """
         widgets = [
-            ("kdump._header", ovirt.node.ui.Header("Configure Kdump")),
-            ("kdump.type", ovirt.node.ui.Options("Type", self._types)),
-            ("kdump.ssh_location", ovirt.node.ui.Entry("SSH Location:",
-                                                       align_vertical=True)),
-            ("kdump.nfs_location", ovirt.node.ui.Entry("NFS Location:",
-                                                       align_vertical=True)),
+            ("kdump._header", ui.Header("Configure Kdump")),
+            ("kdump.type", ui.Options("Type", self._types)),
+            ("kdump.ssh_location", ui.Entry("SSH Location:",
+                                            align_vertical=True)),
+            ("kdump.nfs_location", ui.Entry("NFS Location:",
+                                            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):
@@ -98,15 +106,36 @@
             if w in net_types:
                 self._widgets[w].enabled(True),
 
-            self._model.update(changes)
-
     def on_merge(self, effective_changes):
         """Applies the changes to the plugins model, will do all required logic
         Normally on_merge is called by pushing the SaveButton instance, in this
         case it is called by on_change
         """
+        self.logger.debug("Saving kdump page")
+        changes = ChangesHelper(self.pending_changes(False))
+        model = self.model()
+        model.update(effective_changes)
+        effective_model = ChangesHelper(model)
 
-        if effective_changes:
-            self.logger.debug("Generating conf according to model and changes")
-        else:
-            self.logger.debug("Generating no new conf as there are no changes")
+        self.logger.debug("Saving kdump page: %s" % changes.changes)
+        self.logger.debug("Kdump page model: %s" % effective_model.changes)
+
+        kdump_keys = ["kdump.type", "kdump.ssh_location", "kdump.nfs_location"]
+
+        txs = utils.Transaction("Updating kdump related configuration")
+
+        if changes.any_key_in_change(kdump_keys):
+            model = defaults.KDump()
+            ktype, sshloc, nfsloc = effective_model.get_key_values(kdump_keys)
+            if ktype == "nfs":
+                model.update(nfsloc, None, None)
+            elif ktype == "ssh":
+                model.update(None, sshloc, None)
+            elif ktype == "local":
+                model.update(None, None, True)
+            else:
+                model.update(None, None, None)
+            txs += model.transaction()
+
+        txs.prepare()  # Just to display something in dry mode
+        self.dry_or(lambda: txs())
diff --git a/scripts/tui/src/ovirt/node/setup/keyboard_page.py b/scripts/tui/src/ovirt/node/setup/keyboard_page.py
index c0841bf..c321020 100644
--- a/scripts/tui/src/ovirt/node/setup/keyboard_page.py
+++ b/scripts/tui/src/ovirt/node/setup/keyboard_page.py
@@ -38,10 +38,10 @@
         return 30
 
     def model(self):
-        keyboard = dict(defaults.Logrotate().retrieve())
+        cfg = defaults.Logrotate().retrieve()
 
         model = {}
-        model["keyboard.layout"] = keyboard["layout"] or ""
+        model["keyboard.layout"] = cfg["layout"] or ""
 
     def validators(self):
         return {}
diff --git a/scripts/tui/src/ovirt/node/setup/logging_page.py b/scripts/tui/src/ovirt/node/setup/logging_page.py
index f9478d8..fa5ba0d 100644
--- a/scripts/tui/src/ovirt/node/setup/logging_page.py
+++ b/scripts/tui/src/ovirt/node/setup/logging_page.py
@@ -38,9 +38,9 @@
         return 50
 
     def model(self):
-        logrotate = dict(defaults.Logrotate().retrieve())
-        netconsole = dict(defaults.Netconsole().retrieve())
-        syslog = dict(defaults.Syslog().retrieve())
+        logrotate = defaults.Logrotate().retrieve()
+        netconsole = defaults.Netconsole().retrieve()
+        syslog = defaults.Syslog().retrieve()
 
         model = {
             "logrotate.max_size": "1024",
diff --git a/scripts/tui/src/ovirt/node/setup/network_page.py b/scripts/tui/src/ovirt/node/setup/network_page.py
index 4bfe888..bd65bb2 100644
--- a/scripts/tui/src/ovirt/node/setup/network_page.py
+++ b/scripts/tui/src/ovirt/node/setup/network_page.py
@@ -61,11 +61,11 @@
 
     def model(self):
         # Pull name-/timeservers from config files (not defaults)
-        nameservers = dict(defaults.Nameservers().retrieve())["servers"]
+        nameservers = defaults.Nameservers().retrieve()["servers"]
         for idx, nameserver in enumerate(nameservers):
             self._model["dns[%d]" % idx] = nameserver
 
-        timeservers = dict(defaults.Timeservers().retrieve())["servers"]
+        timeservers = defaults.Timeservers().retrieve()["servers"]
         for idx, timeserver in enumerate(timeservers):
             self._model["ntp[%d]" % idx] = timeserver
 
@@ -146,7 +146,7 @@
         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())
+        cfg = defaults.Network().retrieve()
 
         self.logger.debug(cfg)
         self._model.update({
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 cb40d0f..fbf983c 100644
--- a/scripts/tui/src/ovirt/node/setup/remote_storage_page.py
+++ b/scripts/tui/src/ovirt/node/setup/remote_storage_page.py
@@ -89,7 +89,9 @@
 
         if changes.any_key_in_change(iscsi_keys):
             model = defaults.iSCSI()
-            model.update(*effective_model.get_key_values(iscsi_keys))
+            args = effective_model.get_key_values(iscsi_keys)
+            args += [None, None, None]  # No target config
+            model.update(*args)
             txs += model.transaction()
 
         txs.prepare()  # Just to display something in dry mode
diff --git a/scripts/tui/src/ovirt/node/setup/security_page.py b/scripts/tui/src/ovirt/node/setup/security_page.py
index 9de6d85..b3269db 100644
--- a/scripts/tui/src/ovirt/node/setup/security_page.py
+++ b/scripts/tui/src/ovirt/node/setup/security_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 utils, plugins, ui, valid, exceptions
+from ovirt.node.config import defaults
+from ovirt.node.plugins import ChangesHelper
 
 """
 Configure Security
 """
 
-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
 
@@ -42,7 +41,7 @@
         if not self._model:
             self._model = {
                 "ssh.enabled": "no",
-                "strongrng.enabled": "no",
+                "strongrng.aesni": "no",
                 "strongrng.bytes_used": "",
                 "passwd.admin.password": "",
                 "passwd.admin.password_confirmation": "",
@@ -50,41 +49,38 @@
         return self._model
 
     def validators(self):
-        number_or_empty = ovirt.node.valid.Number(range=[0, None]) | \
-                          ovirt.node.valid.Empty()
+        number_or_empty = valid.Number(range=[0, None]) | \
+                          valid.Empty()
         return {
                 "strongrng.num_bytes": number_or_empty,
-                "passwd.admin.password": ovirt.node.valid.Text(),
-                "passwd.admin.password_confirmation": ovirt.node.valid.Text(),
+                "passwd.admin.password": valid.Text(),
+                "passwd.admin.password_confirmation": valid.Text(),
             }
 
     def ui_content(self):
         widgets = [
-            ("ssh.address", ovirt.node.ui.Header("Remote Access")),
-            ("ssh.enabled", ovirt.node.ui.Options(
-                "Enable ssh password authentication",
-                [("yes", "Yes"), ("no", "No")])),
-            ("ssh._divider", ovirt.node.ui.Divider()),
+            ("header[0]", ui.Header("Remote Access")),
+            ("ssh.enabled", ui.Options("Enable ssh password authentication",
+                                       [("yes", "Yes"), ("no", "No")])),
+            ("divider[0]", ui.Divider()),
 
-            ("strongrng._label", ovirt.node.ui.Header(
-                                            "Strong Random Number Generator")),
-            ("strongrng.enabled", ovirt.node.ui.Options(
-                "Enable AES-NI",
-                [("yes", "Yes"), ("no", "No")])),
-            ("strongrng.num_bytes", ovirt.node.ui.Entry("Bytes Used:")),
-            ("strongrng._divider", ovirt.node.ui.Divider()),
+            ("header[1]", ui.Header("Strong Random Number Generator")),
+            ("strongrng.aesni", ui.Options("Enable AES-NI",
+                                           [("yes", "Yes"), ("no", "No")])),
+            ("strongrng.num_bytes", ui.Entry("Bytes Used:")),
+            ("divider[1]", ui.Divider()),
 
 
-            ("passwd._label", ovirt.node.ui.Label("Local Access")),
-            ("passwd.admin.password", ovirt.node.ui.PasswordEntry(
+            ("header[2]", ui.Label("Local Access")),
+            ("passwd.admin.password", ui.PasswordEntry(
                                                                 "Password:")),
-            ("passwd.admin.password_confirmation", ovirt.node.ui.PasswordEntry(
+            ("passwd.admin.password_confirmation", ui.PasswordEntry(
                 "Confirm Password:")),
         ]
         # 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):
@@ -92,7 +88,38 @@
 
         if self._model["passwd.admin.password"] != \
            self._model["passwd.admin.password_confirmation"]:
-            raise ovirt.node.exceptions.InvalidData("Passwords do not match.")
+            raise exceptions.InvalidData("Passwords do not match.")
 
     def on_merge(self, effective_changes):
-        pass
+        self.logger.debug("Saving security page")
+        changes = ChangesHelper(self.pending_changes(False))
+        model = self.model()
+        model.update(effective_changes)
+        effective_model = ChangesHelper(model)
+
+        self.logger.debug("Saving security page: %s" % changes.changes)
+        self.logger.debug("Remote security model: %s" %
+                          effective_model.changes)
+
+        ssh_keys = ["ssh.enabled", "strongrng.num_bytes", "strongrng.aesni"]
+        passwd_keys = ["passwd.admin.password",
+                       "passwd.admin.password_confirmation"]
+
+        txs = utils.Transaction("Updating security configuration")
+
+        if changes.any_key_in_change(ssh_keys):
+            model = defaults.SSH()
+            model.update(*effective_model.get_key_values(ssh_keys))
+            txs += model.transaction()
+
+        if changes.any_key_in_change(passwd_keys):
+            pw, pwc = effective_model.get_key_values(passwd_keys)
+            if pw != pwc:
+                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))
+
+        txs.prepare()  # Just to display something in dry mode
+        self.dry_or(lambda: txs())


--
To view, visit http://gerrit.ovirt.org/9956
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I4274c55c09ada89e85d30ad5c5c6ed2762d4a24d
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