[node-patches] Change in ovirt-node[master]: plugins: Migrate cim/snmp to new UI

fabiand at fedoraproject.org fabiand at fedoraproject.org
Fri May 3 10:02:39 UTC 2013


Fabian Deutsch has uploaded a new change for review.

Change subject: plugins: Migrate cim/snmp to new UI
......................................................................

plugins: Migrate cim/snmp to new UI

Previously the CIM and SNMP plugins were only shown in th eold UI. Now
the plugin sare also shown in the new UI.

rhbz#953895

Change-Id: Ib715d27982faa2a770c6fb0ac83219a761a1e7c8
Signed-off-by: Fabian Deutsch <fabiand at fedoraproject.org>
---
M ovirt-node.spec.in
M plugins/Makefile.am
M src/Makefile.am
A src/ovirt/node/config/cim.py
M src/ovirt/node/config/defaults.py
A src/ovirt/node/config/snmp.py
A src/ovirt/node/setup/cim_page.py
M src/ovirt/node/setup/snmp_page.py
M src/ovirt/node/utils/__init__.py
9 files changed, 371 insertions(+), 100 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-node refs/changes/96/14396/1

diff --git a/ovirt-node.spec.in b/ovirt-node.spec.in
index bc03d4f..a2a42f1 100644
--- a/ovirt-node.spec.in
+++ b/ovirt-node.spec.in
@@ -426,12 +426,16 @@
 
 %files plugin-snmp
 %{python_sitelib}/ovirt_config_setup/snmp.py
+%{python_sitelib}/ovirt/node/config/snmp.py
+%{python_sitelib}/ovirt/node/setup/snmp_page.py
 %{_sysconfdir}/ovirt-plugins.d/snmp.minimize
 %{_sysconfdir}/ovirt-config-boot.d/snmp_autoinstall.py
 
 
 %files plugin-cim
 %{python_sitelib}/ovirt_config_setup/cim.py
+%{python_sitelib}/ovirt/node/config/cim.py
+%{python_sitelib}/ovirt/node/setup/cim_page.py
 %{_sysconfdir}/ovirt-plugins.d/cim.minimize
 %if %{is_systemd}
 %{_unitdir}/ovirt-cim.service
@@ -527,6 +531,10 @@
 # Files related to the new TUI
 %{python_sitelib}/ovirt/__init__.*
 %{python_sitelib}/ovirt/node/*
+%exclude %{python_sitelib}/ovirt/node/config/snmp.py*
+%exclude %{python_sitelib}/ovirt/node/config/cim.py*
+%exclude %{python_sitelib}/ovirt/node/setup/snmp_page.py*
+%exclude %{python_sitelib}/ovirt/node/setup/cim_page.py*
 %{_bindir}/ovirt-config-setup
 %{_bindir}/ovirt-node-installer
 %{_bindir}/ovirt-node-doc
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index a44f0fa..17e85d2 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -19,6 +19,7 @@
 pyovirtconfigsetupdir =$(pythondir)/ovirt_config_setup
 pyovirtconfigbootdir = $(sysconfdir)/ovirt-config-boot.d
 
+# FIXME this can be removed
 dist_pyovirtconfigsetup_SCRIPTS = \
   snmp.py \
   cim.py
diff --git a/src/Makefile.am b/src/Makefile.am
index cdf7df3..e433711 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -69,9 +69,11 @@
   ovirt/node/base.py
 
 pyovirt_node_config_PYTHON = \
-  ovirt/node/config/defaults.py \
   ovirt/node/config/__init__.py \
-  ovirt/node/config/network.py
+  ovirt/node/config/defaults.py \
+  ovirt/node/config/network.py \
+  ovirt/node/config/cim.py \
+  ovirt/node/config/snmp.py
 
 pyovirt_node_installer_PYTHON = \
   ovirt/node/installer/__init__.py \
@@ -96,9 +98,10 @@
   ovirt/node/setup/ping.py \
   ovirt/node/setup/remote_storage_page.py \
   ovirt/node/setup/security_page.py \
-  ovirt/node/setup/snmp_page.py \
   ovirt/node/setup/status_page.py \
-  ovirt/node/setup/support_page.py
+  ovirt/node/setup/support_page.py \
+  ovirt/node/setup/cim_page.py \
+  ovirt/node/setup/snmp_page.py
 
 pyovirt_node_ui_PYTHON = \
   ovirt/node/ui/__init__.py \
diff --git a/src/ovirt/node/config/cim.py b/src/ovirt/node/config/cim.py
new file mode 100644
index 0000000..f0568d0
--- /dev/null
+++ b/src/ovirt/node/config/cim.py
@@ -0,0 +1,106 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# cim.py - Copyright (C) 2013 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.
+from ovirt.node import utils
+from ovirt.node.config.defaults import NodeConfigFileSection
+from ovirt.node.exceptions import TransactionError
+from ovirt.node.utils import process
+import pwd
+# pylint: disable-msg=E0611
+import grp  # @UnresolvedImport
+# pylint: enable-msg=E0611
+
+
+class CIM(NodeConfigFileSection):
+    """Configure CIM
+
+    >>> from ovirt.node.config.defaults import ConfigFile, SimpleProvider
+    >>> fn = "/tmp/cfg_dummy"
+    >>> cfgfile = ConfigFile(fn, SimpleProvider)
+    >>> n = CIM(cfgfile)
+    >>> n.update(True)
+    >>> n.retrieve()
+    {'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 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 = self.retrieve()
+        enabled = cfg["enabled"]
+
+        tx = utils.Transaction("Configuring CIM")
+        tx.cim_password = None
+
+        class ConfigureCIM(utils.Transaction.Element):
+            def commit(self):
+                action = "restart" if enabled else "stop"
+                try:
+                    process.check_call("service ovirt-cim % 2>/dev/null" %
+                                       action)
+                    self.logger.debug("Configured CIM successfully")
+                except RuntimeError:
+                    raise TransactionError("CIM configuration failed")
+
+        class SetCIMPassword(utils.Transaction.Element):
+            def commit(self):
+                self.create_cim_user()
+
+                if not tx.cim_password:
+                    raise RuntimeError("CIM password is missing.")
+
+                from ovirtnode.password import set_password
+                if not set_password(tx.cim_password, "cim"):
+                    raise RuntimeError("Setting CIM Password Failed")
+
+        tx.append(ConfigureCIM())
+        if enabled:
+            tx.append(SetCIMPassword())
+
+        return tx
+
+
+def create_cim_user(self):
+    from ovirtnode.ovirtfunctions import check_user_exists, add_user
+    if not check_user_exists(self.username):
+        add_user(self.username, self.shell, self.main_group, self.group_list)
+    else:
+        userinfo = pwd.getpwnam(self.username)
+        if not userinfo.pw_gid == grp.getgrnam(self.main_group).gr_gid:
+            process.check_call("usermod -g %s %s" %
+                               (self.main_group, self.username))
+        if not userinfo.pw_shell == self.shell:
+            process.check_call("usermod -s %s %s" %
+                               (self.shell, self.username))
+        for group in self.group_list:
+            if self.username not in grp.getgrnam(group).gr_mem:
+                process.check_call("usermod -G %s %s" %
+                                   (self.group_list.join(",", self.username)))
+                break
diff --git a/src/ovirt/node/config/defaults.py b/src/ovirt/node/config/defaults.py
index 06f066a..048c03a 100644
--- a/src/ovirt/node/config/defaults.py
+++ b/src/ovirt/node/config/defaults.py
@@ -899,45 +899,6 @@
         return tx
 
 
-class SNMP(NodeConfigFileSection):
-    """Configure SNMP
-
-    >>> fn = "/tmp/cfg_dummy"
-    >>> cfgfile = ConfigFile(fn, SimpleProvider)
-    >>> n = SNMP(cfgfile)
-    >>> n.update("secret")
-    >>> n.retrieve().items()
-    [('password', 'secret')]
-    """
-    keys = ("OVIRT_SNMP_PASSWORD",)
-
-    @NodeConfigFileSection.map_and_update_defaults_decorator
-    def update(self, password):
-        # FIXME add validation
-        pass
-
-    def transaction(self):
-        cfg = dict(self.retrieve())
-        password = cfg["password"]
-
-        class ConfigureSNMP(utils.Transaction.Element):
-            title = "Enabling/Disabling SNMP and setting the password"
-
-            def commit(self):
-                # FIXME snmp plugin needs to be placed somewhere else (in src)
-                # pylint: disable-msg=E0611
-                from ovirt_config_setup import snmp  # @UnresolvedImport
-                # pylint: enable-msg=E0611
-                if password:
-                    snmp.enable_snmpd(password)
-                else:
-                    snmp.disable_snmpd()
-
-        tx = utils.Transaction("Configuring SNMP")
-        tx.append(ConfigureSNMP())
-        return tx
-
-
 class Netconsole(NodeConfigFileSection):
     """Configure netconsole
 
@@ -1005,53 +966,6 @@
 
         tx = utils.Transaction("Configuring logrotate")
         tx.append(CreateLogrotateConfig())
-        return tx
-
-
-class CIM(NodeConfigFileSection):
-    """Configure CIM
-
-    >>> fn = "/tmp/cfg_dummy"
-    >>> cfgfile = ConfigFile(fn, SimpleProvider)
-    >>> n = CIM(cfgfile)
-    >>> n.update(True)
-    >>> n.retrieve()
-    {'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 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)
-                # pylint: disable-msg=E0611
-                from ovirt_config_setup import cim  # @UnresolvedImport
-                # pylint: enable-msg=E0611
-                if enabled:
-                    if cim.enable_cim():
-                        self.logger.debug("Configured CIM successfully")
-                    else:
-                        raise exceptions.TransactionError("CIM configuration" +
-                                                          " failed")
-
-        # FIXME setting password is missing
-
-        tx = utils.Transaction("Configuring CIM")
-        tx.append(ConfigureCIM())
         return tx
 
 
diff --git a/src/ovirt/node/config/snmp.py b/src/ovirt/node/config/snmp.py
new file mode 100644
index 0000000..5855e35
--- /dev/null
+++ b/src/ovirt/node/config/snmp.py
@@ -0,0 +1,107 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# cim.py - Copyright (C) 2013 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.
+from ovirt.node import utils
+from ovirt.node.config.defaults import NodeConfigFileSection
+from ovirt.node.utils import process
+import os.path
+
+
+snmp_conf = "/etc/snmp/snmpd.conf"
+
+
+def enable_snmpd(password):
+    from ovirtnode.ovirtfunctions import ovirt_store_config
+
+    process.call("service snmpd stop")
+
+    # get old password #
+    if os.path.exists("/tmp/snmpd.conf"):
+        conf = "/tmp/snmpd.conf"
+    else:
+        conf = snmp_conf
+    cmd = "cat %s|grep createUser|awk '{print $4}'" % conf
+    oldpwd, stderr = process.pipe(cmd)
+    oldpwd = oldpwd.stdout.read().strip()
+    process.call("sed -c -ie '/^createUser root/d' %s" % snmp_conf)
+    f = open(snmp_conf, "a")
+    # create user account
+    f.write("createUser root SHA %s AES\n" % password)
+    f.close()
+    process.check_call("service snmpd start")
+    # change existing password
+    if len(oldpwd) > 0:
+        pwd_change_cmd = (("snmpusm -v 3 -u root -n \"\" -l authNoPriv -a " +
+                           "SHA -A %s localhost passwd %s %s -x AES") %
+                          (oldpwd, oldpwd, password))
+        process.check_call(pwd_change_cmd)
+        # Only reached when no excepion occurs
+        process.call("rm -rf /tmp/snmpd.conf")
+    ovirt_store_config(snmp_conf)
+
+
+def disable_snmpd():
+    from ovirtnode.ovirtfunctions import remove_config
+
+    process.check_call("service snmpd stop")
+    # copy to /tmp for enable/disable toggles w/o reboot
+    process.check_call("cp /etc/snmp/snmpd.conf /tmp")
+    process.check_call("sed -c -ie '/^createUser root/d' %s" % snmp_conf)
+    remove_config(snmp_conf)
+
+
+class SNMP(NodeConfigFileSection):
+    """Configure SNMP
+
+    >>> from ovirt.node.config.defaults import ConfigFile, SimpleProvider
+    >>> fn = "/tmp/cfg_dummy"
+    >>> cfgfile = ConfigFile(fn, SimpleProvider)
+    >>> n = SNMP(cfgfile)
+    >>> n.update("secret")
+    >>> n.retrieve().items()
+    [('password', 'secret')]
+    """
+    keys = ("OVIRT_SNMP_PASSWORD",)
+
+    @NodeConfigFileSection.map_and_update_defaults_decorator
+    def update(self, password):
+        # FIXME add validation
+        pass
+
+    def transaction(self):
+        cfg = dict(self.retrieve())
+        password = cfg["password"]
+
+        class ConfigureSNMP(utils.Transaction.Element):
+            title = "Enabling/Disabling SNMP and setting the password"
+
+            def commit(self):
+                # FIXME snmp plugin needs to be placed somewhere else (in src)
+                # pylint: disable-msg=E0611
+                from ovirt_config_setup import snmp  # @UnresolvedImport
+                # pylint: enable-msg=E0611
+                if password:
+                    snmp.enable_snmpd(password)
+                else:
+                    snmp.disable_snmpd()
+
+        tx = utils.Transaction("Configuring SNMP")
+        tx.append(ConfigureSNMP())
+        return tx
diff --git a/src/ovirt/node/setup/cim_page.py b/src/ovirt/node/setup/cim_page.py
new file mode 100644
index 0000000..92c7a4b
--- /dev/null
+++ b/src/ovirt/node/setup/cim_page.py
@@ -0,0 +1,108 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# snmp_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
+# 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.
+from ovirt.node import plugins, valid, ui, utils, exceptions
+from ovirt.node.config import cim as cim_config
+from ovirt.node.plugins import Changeset
+
+"""
+Configure CIM
+"""
+
+
+class Plugin(plugins.NodePlugin):
+    _model = None
+
+    def __init__(self, app):
+        super(Plugin, self).__init__(app)
+        self._model = {}
+
+    def has_ui(self):
+        return True
+
+    def name(self):
+        return "CIM"
+
+    def rank(self):
+        return 45
+
+    def model(self):
+        cfg = cim_config.CIM().retrieve()
+        self.logger.debug(cfg)
+        model = {"cim.enabled": True if cfg["enabled"] else False,
+                 "cim.password": "",
+                 "cim.password_confirmation": "",
+                 }
+        return model
+
+    def validators(self):
+        return {"cim.password": valid.Text()}
+
+    def ui_content(self):
+        ws = [ui.Header("header[0]", "CIM"),
+              ui.Checkbox("cim.enabled", "Enable CIM"),
+              ui.Divider("divider[0]"),
+              ui.Header("header[1]", "CIM Password"),
+              ui.PasswordEntry("cim.password", "Password:"),
+              ui.PasswordEntry("cim.password_confirmation",
+                               "Confirm Password:"),
+              ]
+
+        page = ui.Page("page", ws)
+        self.widgets.add(ws)
+        return page
+
+    def on_change(self, changes):
+        if changes.contains_any(["cim.password",
+                                 "cim.password_confirmation"]):
+            self._model.update(changes)
+            root_pw, root_pw_conf = self._model.get("cim.password", ""), \
+                self._model.get("cim.password_confirmation", "")
+
+            if root_pw != root_pw_conf:
+                raise exceptions.InvalidData("Passwords must be the same.")
+            else:
+                self.widgets["cim.password"].valid(True)
+                self.widgets["cim.password_confirmation"].valid(True)
+
+    def on_merge(self, effective_changes):
+        self.logger.debug("Saving CIM page")
+        changes = Changeset(self.pending_changes(False))
+        effective_model = Changeset(self.model())
+        effective_model.update(effective_changes)
+
+        self.logger.debug("Changes: %s" % changes)
+        self.logger.debug("Effective Model: %s" % effective_model)
+
+        snmp_keys = ["cim.password_confirmation", "cim.enabled"]
+
+        txs = utils.Transaction("Updating CIM configuration")
+
+        if changes.contains_any(snmp_keys):
+            values = effective_model.values_for(snmp_keys)
+            args = [values[0]]
+            if values[1] is False:  # If set to disabled, set password to None
+                args[0] = None
+            model = cim_config.CIM()
+            model.update(*args)
+            txs += model.transaction()
+
+        progress_dialog = ui.TransactionProgressDialog("dialog.txs", txs, self)
+        progress_dialog.run()
diff --git a/src/ovirt/node/setup/snmp_page.py b/src/ovirt/node/setup/snmp_page.py
index cf69d62..d68f6cc 100644
--- a/src/ovirt/node/setup/snmp_page.py
+++ b/src/ovirt/node/setup/snmp_page.py
@@ -19,20 +19,43 @@
 # 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, exceptions
-from ovirt.node.config import defaults
+from ovirt.node.config import snmp as snmp_config
 from ovirt.node.plugins import Changeset
+from ovirt.node.valid import RegexValidator
 
 """
 Configure SNMP
 """
 
 
+class SnmpPassword(RegexValidator):
+    """A string, but without any space character and at least 8 chars
+
+    >>> SnmpPassword().validate("1234567")
+    False
+    >>> SnmpPassword().validate("12345678")
+    True
+    >>> SnmpPassword().validate("123456 8")
+    False
+    >>> SnmpPassword().validate("Ab9873knad")
+    True
+    >>> SnmpPassword().validate("")
+    False
+    """
+
+    description = "a string without spaces and at least 8 chars"
+    pattern = "^\S{8,}$"
+
+
 class Plugin(plugins.NodePlugin):
     _model = None
 
+    def __init__(self, app):
+        super(Plugin, self).__init__(app)
+        self._model = {}
+
     def has_ui(self):
-        # FIXME is SNMP in a plugin?
-        return False
+        return True
 
     def name(self):
         return "SNMP"
@@ -41,7 +64,7 @@
         return 40
 
     def model(self):
-        cfg = defaults.SNMP().retrieve()
+        cfg = snmp_config.SNMP().retrieve()
         self.logger.debug(cfg)
         model = {"snmp.enabled": True if cfg["password"] else False,
                  "snmp.password": "",
@@ -70,10 +93,11 @@
     def on_change(self, changes):
         if changes.contains_any(["snmp.password",
                                  "snmp.password_confirmation"]):
+            self._model.update(changes)
+            root_pw, root_pw_conf = self._model.get("snmp.password", ""), \
+                self._model.get("snmp.password_confirmation", "")
 
-            snmp_pw = self._model.get("snmp.password", "")
-            snmp_pw_conf = self._model.get("snmp.password_confirmation", "")
-            if snmp_pw != snmp_pw_conf:
+            if root_pw != root_pw_conf:
                 raise exceptions.InvalidData("Passwords must be the same.")
             else:
                 self.widgets["snmp.password"].valid(True)
@@ -97,7 +121,7 @@
             args = [values[0]]
             if values[1] is False:  # If set to disabled, set password to None
                 args[0] = None
-            model = defaults.SNMP()
+            model = snmp_config.SNMP()
             model.update(*args)
             txs += model.transaction()
 
diff --git a/src/ovirt/node/utils/__init__.py b/src/ovirt/node/utils/__init__.py
index f308168..f0c6b95 100644
--- a/src/ovirt/node/utils/__init__.py
+++ b/src/ovirt/node/utils/__init__.py
@@ -117,11 +117,11 @@
     >>> parse_bool(True)
     True
 
-    >>> txts = ["yes", "YES!", "1", 1]
+    >>> txts = ["yes", "YES!", "1", 1, "y"]
     >>> all((parse_bool(txt) for txt in txts))
     True
 
-    >>> txts = ["no", "NO!", "0", 0, False, None, "foo"]
+    >>> txts = ["no", "NO!", "0", 0, False, None, "foo", "n"]
     >>> all((not parse_bool(txt) for txt in txts))
     True
 


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

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