[node-patches] Change in ovirt-node[master]: defaults: Add activation stuff
fabiand at fedoraproject.org
fabiand at fedoraproject.org
Tue Dec 11 20:09:41 UTC 2012
Fabian Deutsch has uploaded a new change for review.
Change subject: defaults: Add activation stuff
......................................................................
defaults: Add activation stuff
Change-Id: I0c6b09e6ab4c03ef62b53517a9e869f8a2854888
Signed-off-by: Fabian Deutsch <fabiand at fedoraproject.org>
---
M scripts/tui/TODO
M scripts/tui/src/ovirt/node/config/defaults.py
M scripts/tui/src/ovirt/node/setup/remote_storage_page.py
M scripts/tui/src/ovirt/node/utils/security.py
4 files changed, 324 insertions(+), 22 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/ovirt-node refs/changes/54/9954/1
diff --git a/scripts/tui/TODO b/scripts/tui/TODO
index c20eabf..882af49 100644
--- a/scripts/tui/TODO
+++ b/scripts/tui/TODO
@@ -1,4 +1,3 @@
- Pull common functionality into NodePlugins (changes helper)
- Ensure that 80x23 size works
- Improve List widget - It needs to have a scrollbar or display it's status in another way
-- Add NFSv4 support to storage page
diff --git a/scripts/tui/src/ovirt/node/config/defaults.py b/scripts/tui/src/ovirt/node/config/defaults.py
index 81f9815..5851951 100644
--- a/scripts/tui/src/ovirt/node/config/defaults.py
+++ b/scripts/tui/src/ovirt/node/config/defaults.py
@@ -18,6 +18,11 @@
# 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 base, exceptions, valid, utils
+import glob
+import logging
+import os
+import ovirt.node.config
"""
Classes and functions related to model of the configuration of oVirt Node.
@@ -34,13 +39,6 @@
Each class should implement a configure method, mainly to define all the
required arguments (or keys).
"""
-
-import logging
-import glob
-
-import ovirt.node.config
-from ovirt.node import base, exceptions, valid, utils
-
LOGGER = logging.getLogger(__name__)
@@ -516,17 +514,119 @@
>>> nfs_url = "host.example.com"
>>> ssh_url = "root at host.example.com"
>>> n = KDump(cfgfile)
- >>> n.update(nfs_url, ssh_url)
- >>> n.retrieve()
+ >>> n.update(nfs_url, ssh_url, '')
+ >>> d = n.retrieve()
+ >>> d[:2]
[('nfs', 'host.example.com'), ('ssh', 'root at host.example.com')]
+ >>> d[2:]
+ [('local', '')]
"""
keys = ("OVIRT_KDUMP_NFS",
- "OVIRT_KDUMP_SSH")
+ "OVIRT_KDUMP_SSH",
+ "OVIRT_KDUMP_LOCAL")
@NodeConfigFileSection.map_and_update_defaults_decorator
- def update(self, nfs, ssh):
- valid.FQDNOrIPAddress()(nfs)
- valid.URL()(ssh)
+ def update(self, nfs, ssh, local):
+ (valid.Empty(or_none=True) | valid.FQDNOrIPAddress())(nfs)
+ (valid.Empty(or_none=True) | valid.URL())(ssh)
+
+ def transaction(self):
+ cfg = dict(self.retrieve())
+ nfs, ssh, restore = (cfg["nfs"], cfg["ssh"], cfg["local"])
+
+ class BackupKdumpConfig(utils.Transaction.Element):
+ def __init__(self):
+ self.backups = utils.fs.BackupedFiles(["/etc/kdump.conf"])
+
+ def commit(self):
+ self.backups.create()
+
+ class RestoreKdumpConfig(utils.Transaction.Element):
+ def commit(self):
+ import ovirtnode.kdump as okdump
+ okdump.restore_kdump_config()
+
+ class CreateNfsKdumpConfig(utils.Transaction.Element):
+ def commit(self):
+ import ovirtnode.kdump as okdump
+ okdump.write_kdump_config(nfs)
+
+ class CreateSshKdumpConfig(utils.Transaction.Element):
+ def commit(self):
+ import ovirtnode.kdump as okdump
+ from ovirtnode.ovirtfunctions import ovirt_store_config
+
+ okdump.write_kdump_config(ssh)
+
+ if os.path.exists("/usr/bin/kdumpctl"):
+ cmd = "kdumpctl propagate"
+ else:
+ cmd = "service kdump propagate"
+ cmd += "2>&1"
+
+ success, stdout = utils.process.pipe(cmd)
+
+ if success:
+ ovirt_store_config(["/root/.ssh/kdump_id_rsa.pub",
+ "/root/.ssh/kdump_id_rsa",
+ "/root/.ssh/known_hosts",
+ "/root/.ssh/config"])
+ else:
+ self.logger.warning("Failed to activate KDump with " +
+ "SSH: %s" % stdout)
+
+ class RemoveKdumpConfig(utils.Transaction.Element):
+ def __init__(self, backups):
+ self.backups = backups
+
+ def commit(self):
+ from ovirtnode.ovirtfunctions import remove_config
+
+ remove_config("/etc/kdump.conf")
+ utils.process.system("service kdump stop")
+ open('/etc/kdump.conf', 'w').close()
+
+ self.backups.remove()
+
+ class RestartKdumpService(utils.Transaction.Element):
+ def __init__(self, backups):
+ self.backups = backups
+
+ def commit(self):
+ from ovirtnode.ovirtfunctions import unmount_config, \
+ ovirt_store_config
+ from ovirt.node.utils.process import system
+
+ if utils.process.system("service kdump restart") > 0:
+ unmount_config("/etc/kdump.conf")
+ self.backups.restore("/etc/kdump.conf")
+ system("service kdump restart")
+
+ raise RuntimeError("KDump configuration failed, " +
+ "location unreachable. Previous " +
+ "configuration was restored.")
+
+ ovirt_store_config("/etc/kdump.conf")
+ self.backups.remove()
+
+ tx = utils.Transaction("Configuring kdump")
+
+ backup_txe = BackupKdumpConfig()
+ tx.append(backup_txe)
+
+ final_txe = RestartKdumpService(backup_txe.backups)
+ if nfs:
+ tx.append(CreateNfsKdumpConfig())
+ elif ssh:
+ tx.append(CreateSshKdumpConfig())
+ elif restore:
+ tx.append(RestoreKdumpConfig())
+ else:
+ final_txe = RemoveKdumpConfig(backup_txe.backups)
+
+ tx.append(final_txe)
+
+ return tx
class iSCSI(NodeConfigFileSection):
@@ -551,6 +651,19 @@
def update(self, name, target_name, target_host, target_port):
# FIXME add validation
pass
+
+ def transaction(self):
+ cfg = dict(self.retrieve())
+ initiator_name = cfg["name"]
+
+ class ConfigureIscsiInitiator(utils.Transaction.Element):
+ def commit(self):
+ from ovirtnode.iscsi import set_iscsi_initiator
+ set_iscsi_initiator(initiator_name)
+
+ tx = utils.Transaction("Configuring the iSCSI Initiator")
+ tx.append(ConfigureIscsiInitiator())
+ return tx
class SNMP(NodeConfigFileSection):
@@ -690,3 +803,93 @@
tx = utils.Transaction("Configuring keyboard layout")
tx.append(CreateKeyboardConfig())
return tx
+
+
+class NFSv4(NodeConfigFileSection):
+ """Configure NFSv4
+
+ >>> fn = "/tmp/cfg_dummy"
+ >>> cfgfile = ConfigFile(fn, SimpleProvider)
+ >>> n = NFSv4(cfgfile)
+ >>> domain = "foo.example"
+ >>> n.update(domain)
+ >>> n.retrieve()
+ [('domain', 'foo.example')]
+ """
+ # FIXME this key is new!
+ keys = ("OVIRT_NFSV4_DOMAIN",)
+
+ @NodeConfigFileSection.map_and_update_defaults_decorator
+ def update(self, domain):
+ # FIXME Some validation that layout is in the list of available layouts
+ pass
+
+ def transaction(self):
+ cfg = dict(self.retrieve())
+ domain = cfg["domain"]
+
+ class ConfigureNfsv4(utils.Transaction.Element):
+ def commit(self):
+ from ovirtnode.network import set_nfsv4_domain
+ set_nfsv4_domain(domain)
+
+ tx = utils.Transaction("Configuring NFSv4")
+ if domain:
+ tx.append(ConfigureNfsv4())
+ return tx
+
+
+class SSH(NodeConfigFileSection):
+ """Configure SSH
+
+ >>> fn = "/tmp/cfg_dummy"
+ >>> cfgfile = ConfigFile(fn, SimpleProvider)
+ >>> n = SSH(cfgfile)
+ >>> pwauth = True
+ >>> n.update(pwauth)
+ >>> n.retrieve()
+ [('pwauth', True)]
+ """
+ keys = ("OVIRT_SSH_PWAUTH",
+ "OVIRT_USE_STRONG_RNG",
+ "OVIRT_ENABLE_AES_NI")
+
+ @NodeConfigFileSection.map_and_update_defaults_decorator
+ def update(self, pwauth, num_bytes, aesni):
+ valid.Boolean()(pwauth)
+ valid.Number()(num_bytes)
+ valid.Boolean()(aesni)
+
+ def retrieve(self):
+ cfg = dict(NodeConfigFileSection.retrieve(self))
+ return {
+ "pwauth": True if cfg["pwauth"] == "yes" else False
+ }
+
+ def transaction(self):
+ cfg = dict(self.retrieve())
+ pwauth, num_bytes, aesni = (cfg["pwauth"], cfg["num_bytes"],
+ cfg["aesni"])
+
+ ssh = utils.security.Ssh()
+
+ class ConfigurePasswordAuthentication(utils.Transaction.Element):
+ def commit(self):
+ ssh.password_authentication(pwauth)
+
+ class ConfigureStrongRNG(utils.Transaction.Element):
+ def commit(self):
+ ssh.strong_rng(num_bytes)
+
+ class ConfigureAESNI(utils.Transaction.Element):
+ def commit(self):
+ ssh.aes_ni(aesni)
+
+ tx = utils.Transaction("Configuring SSH")
+ if pwauth:
+ tx.append(ConfigurePasswordAuthentication())
+ if num_bytes:
+ tx.append(ConfigureStrongRNG())
+ if aesni:
+ tx.append(ConfigureAESNI())
+ return tx
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 2ca19c6..cb40d0f 100644
--- a/scripts/tui/src/ovirt/node/setup/remote_storage_page.py
+++ b/scripts/tui/src/ovirt/node/setup/remote_storage_page.py
@@ -18,13 +18,15 @@
# 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 import defaults
+from ovirt.node.plugins import ChangesHelper
+import ovirt.node.plugins
+import ovirt.node.ui
"""
Configure Remote Storage
"""
-
-import ovirt.node.plugins
-import ovirt.node.ui
class Plugin(ovirt.node.plugins.NodePlugin):
@@ -70,4 +72,25 @@
self._model.update(changes)
def on_merge(self, effective_changes):
- pass
+ self.logger.debug("Saving remote storage page")
+ changes = ChangesHelper(self.pending_changes(False))
+ model = self.model()
+ model.update(effective_changes)
+ effective_model = ChangesHelper(model)
+
+ self.logger.debug("Saving remote storage page: %s" % changes.changes)
+ self.logger.debug("Remote storage page model: %s" %
+ effective_model.changes)
+
+ iscsi_keys = ["iscsi.initiator_name"]
+ # FIXME nfsv4 is missing
+
+ txs = utils.Transaction("Updating remote storage configuration")
+
+ if changes.any_key_in_change(iscsi_keys):
+ model = defaults.iSCSI()
+ model.update(*effective_model.get_key_values(iscsi_keys))
+ 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/utils/security.py b/scripts/tui/src/ovirt/node/utils/security.py
index 387d324..e236ca7 100644
--- a/scripts/tui/src/ovirt/node/utils/security.py
+++ b/scripts/tui/src/ovirt/node/utils/security.py
@@ -18,14 +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 base, valid, utils
+import process
+import os.path
"""
Some convenience functions related to security
"""
-
-import os.path
-
-import process
def get_ssh_hostkey(variant="rsa"):
@@ -40,3 +39,81 @@
stdout = process.pipe(hostkey_fp_cmd, without_retval=True)
fingerprint = stdout.strip().split(" ")[1]
return (fingerprint, hostkey)
+
+
+class Passwd(base.Base):
+ def set_password(self, username, password):
+ import ovirtnode.password as opasswd
+ opasswd.set_password(password, username)
+
+
+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):
+ additional_lines = []
+ self.ofunc.unmount_config("/etc/profile")
+
+ process.system("sed -i '/OPENSSL_DISABLE_AES_NI/d' /etc/profile")
+ if not enable_aes:
+ additional_lines += ["export OPENSSL_DISABLE_AES_NI=1"]
+
+ process.system("sed -i '/SSH_USE_STRONG_RNG/d' /etc/profile")
+ if rng_num_bytes:
+ additional_lines += ["export SSH_USE_STRONG_RNG=%s" %
+ rng_num_bytes]
+
+ if additional_lines:
+ self.logger.debug("Updating /etc/profile")
+ with open("/etc/profile", "a") as f:
+ lines = "\n" + "\n".join(additional_lines)
+ f.write(lines)
+ self.ofunc.ovirt_store_config("/etc/profile")
+
+ self.restart()
+
+ def aes_ni(self, enable=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)
+ else:
+ self.logger.warning("Unknown value for AES NI: %s" % enable)
+ return self.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()
+ if valid.Number(range=[0, None]).validate(num_bytes):
+ self.__update_profile(num_bytes, aes)
+ elif num_bytes is None:
+ pass
+ else:
+ self.logger.warning("Unknown value for RNG num bytes: " +
+ "%s" % num_bytes)
+ return self.ofunc.rng_status()[0]
+
+ def restart(self):
+ self.logger.debug("Restarting SSH")
+ process.system("service sshd restart &>/dev/null")
+
+ def password_authentication(self, enable=None):
+ augpath = "/files/etc/ssh/sshd_config/PasswordAuthentication"
+ aug = utils.AugeasWrapper()
+ if enable in [True, False]:
+ import ovirtnode.ovirtfunctions as ofunc
+ value = "yes" if enable else "no"
+ self.logger.debug("Setting SSH PasswordAuthentication to " +
+ "%s" % value)
+ aug.set(augpath, value)
+ ofunc.ovirt_store_config("/etc/ssh/sshd_config")
+ self.restart()
+ return aug.get(augpath)
--
To view, visit http://gerrit.ovirt.org/9954
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I0c6b09e6ab4c03ef62b53517a9e869f8a2854888
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