[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