Alon Bar-Lev has uploaded a new change for review. Change subject: ovirt-vmconsole: initial implementation ......................................................................
ovirt-vmconsole: initial implementation Change-Id: I45e0b91bb678008dc74ced8622251beccefc82b9 Signed-off-by: Alon Bar-Lev <alo...@redhat.com> --- M ChangeLog M configure.ac M ovirt-host-deploy-offline.spec.in M src/ovirt_host_deploy/constants.py M src/plugins/ovirt-host-deploy/Makefile.am M src/plugins/ovirt-host-deploy/core/offlinepackager.py A src/plugins/ovirt-host-deploy/vmconsole/Makefile.am A src/plugins/ovirt-host-deploy/vmconsole/__init__.py A src/plugins/ovirt-host-deploy/vmconsole/packages.py A src/plugins/ovirt-host-deploy/vmconsole/pki.py 10 files changed, 439 insertions(+), 0 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-host-deploy refs/changes/91/38091/6 diff --git a/ChangeLog b/ChangeLog index e4136f6..3130627 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,7 @@ rhbz#1209418. * mgmt: new component to enable host management. * offline: pull iptables-services where available, rhbz#1224804. + * ovirt-vmconsole: initial add. 2015-01-15 - Version 1.3.1 diff --git a/configure.ac b/configure.ac index fd0c5eb..76921b4 100644 --- a/configure.ac +++ b/configure.ac @@ -187,6 +187,7 @@ src/plugins/ovirt-host-deploy/tune/Makefile src/plugins/ovirt-host-deploy/vdsm/Makefile src/plugins/ovirt-host-deploy/vdsmhooks/Makefile + src/plugins/ovirt-host-deploy/vmconsole/Makefile src/plugins/ovirt-host-mgmt/Makefile src/plugins/ovirt-host-mgmt/core/Makefile src/plugins/ovirt-host-mgmt/packages/Makefile diff --git a/ovirt-host-deploy-offline.spec.in b/ovirt-host-deploy-offline.spec.in index f2df16d..2a1cf10 100644 --- a/ovirt-host-deploy-offline.spec.in +++ b/ovirt-host-deploy-offline.spec.in @@ -32,6 +32,7 @@ Requires: iproute Requires: libselinux-python Requires: m2crypto +Requires: ovirt-vmconsole-host Requires: python Requires: tar Requires: tuned diff --git a/src/ovirt_host_deploy/constants.py b/src/ovirt_host_deploy/constants.py index 3949c08..c99f7ae 100644 --- a/src/ovirt_host_deploy/constants.py +++ b/src/ovirt_host_deploy/constants.py @@ -21,6 +21,9 @@ """Constants.""" +import os + + from otopi import util @@ -63,6 +66,18 @@ KDUMP_CONFIG_FILE = '/etc/kdump.conf' + VMCONSOLE_STORE = '/etc/pki/ovirt-vmconsole' + VMCONSOLE_CA_FILE = os.path.join(VMCONSOLE_STORE, 'ca.pub') + VMCONSOLE_CERT_FILE = os.path.join( + VMCONSOLE_STORE, + 'host-ssh_host_rsa-cert.pub', + ) + VMCONSOLE_KEY_FILE = os.path.join(VMCONSOLE_STORE, 'host-ssh_host_rsa') + VMCONSOLE_KEY_PENDING_FILE = os.path.join( + VMCONSOLE_STORE, + 'host-ssh_host_rsa.pending', + ) + @util.export class Defaults(object): @@ -76,6 +91,9 @@ CERTIFICATE_ENROLLMENT_INLINE = 'inline' CERTIFICATE_ENROLLMENT_REQUEST = 'request' CERTIFICATE_ENROLLMENT_ACCEPT = 'accept' + + VMCONSOLE_SUPPORT_NONE = 0 + VMCONSOLE_SUPPORT_V1 = 1 @util.export @@ -123,6 +141,16 @@ @util.export @util.codegen +class VMConsoleEnv(object): + SUPPORT = 'VMCONSOLE/support' + ENABLE = 'VMCONSOLE/enable' + CAKEY = 'VMCONSOLE/caKey' + KEY_SIZE = 'VMCONSOLE/keySize' + CERTIFICATE = 'VMCONSOLE/certificate' + + +@util.export +@util.codegen class VirtEnv(object): ENABLE = 'VIRT/enable' @@ -158,12 +186,14 @@ @util.codegen class Queries(object): CERTIFICATE_CHAIN = 'VDSM_CERTIFICATE_CHAIN' + VMCONSOLE_CERTIFICATE = 'VMCONSOLE_CERTIFICATE' @util.export @util.codegen class Displays(object): CERTIFICATE_REQUEST = 'VDSM_CERTIFICATE_REQUEST' + VMCONSOLE_CERTIFICATE_REQUEST = 'VMCONSOLE_CERTIFICATE_REQUEST' @util.export diff --git a/src/plugins/ovirt-host-deploy/Makefile.am b/src/plugins/ovirt-host-deploy/Makefile.am index 6de5c4d..e1c8e1d 100644 --- a/src/plugins/ovirt-host-deploy/Makefile.am +++ b/src/plugins/ovirt-host-deploy/Makefile.am @@ -30,6 +30,7 @@ tune \ vdsm \ vdsmhooks \ + vmconsole \ $(NULL) install-data-local: diff --git a/src/plugins/ovirt-host-deploy/core/offlinepackager.py b/src/plugins/ovirt-host-deploy/core/offlinepackager.py index cb72b85..1eed2a0 100644 --- a/src/plugins/ovirt-host-deploy/core/offlinepackager.py +++ b/src/plugins/ovirt-host-deploy/core/offlinepackager.py @@ -52,6 +52,7 @@ if pattern in ( 'vdsm', 'vdsm-gluster', + 'ovirt-vmconsole-host', ): ret.append( { diff --git a/src/plugins/ovirt-host-deploy/vmconsole/Makefile.am b/src/plugins/ovirt-host-deploy/vmconsole/Makefile.am new file mode 100644 index 0000000..16a4240 --- /dev/null +++ b/src/plugins/ovirt-host-deploy/vmconsole/Makefile.am @@ -0,0 +1,39 @@ +# +# ovirt-host-deploy -- ovirt host deployer +# Copyright (C) 2012-2013 Red Hat, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# + +include $(top_srcdir)/build/python.inc + +MAINTAINERCLEANFILES = \ + $(srcdir)/Makefile.in \ + $(NULL) + +mydir=$(ovirthostdeployplugindir)/ovirt-host-deploy/sercon +dist_my_PYTHON = \ + __init__.py \ + packages.py \ + pki.py \ + $(NULL) + +clean-local: \ + python-clean \ + $(NULL) + +all-local: \ + python-syntax-check \ + $(NULL) diff --git a/src/plugins/ovirt-host-deploy/vmconsole/__init__.py b/src/plugins/ovirt-host-deploy/vmconsole/__init__.py new file mode 100644 index 0000000..b6bd807 --- /dev/null +++ b/src/plugins/ovirt-host-deploy/vmconsole/__init__.py @@ -0,0 +1,37 @@ +# +# ovirt-host-deploy -- ovirt host deployer +# Copyright (C) 2012-2015 Red Hat, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# + + +"""serial console plugin.""" + + +from otopi import util + + +from . import packages +from . import pki + + +@util.export +def createPlugins(context): + packages.Plugin(context=context) + pki.Plugin(context=context) + + +# vim: expandtab tabstop=4 shiftwidth=4 diff --git a/src/plugins/ovirt-host-deploy/vmconsole/packages.py b/src/plugins/ovirt-host-deploy/vmconsole/packages.py new file mode 100644 index 0000000..5b430f8 --- /dev/null +++ b/src/plugins/ovirt-host-deploy/vmconsole/packages.py @@ -0,0 +1,99 @@ +# +# ovirt-host-deploy -- ovirt host deployer +# Copyright (C) 2012-2015 Red Hat, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# + + +"""Serial console PKI artifacts.""" + + +import gettext + + +from otopi import plugin +from otopi import util + + +from ovirt_host_deploy import constants as odeploycons + + +def _(m): + return gettext.dgettext(message=m, domain='ovirt-host-deploy') + + +@util.export +class Plugin(plugin.PluginBase): + + def __init__(self, context): + super(Plugin, self).__init__(context=context) + self._enabled = False + + @plugin.event( + stage=plugin.Stages.STAGE_INIT, + ) + def _init(self): + self._enabled = False + self.environment.setdefault( + odeploycons.VMConsoleEnv.ENABLE, + False + ) + self.environment.setdefault( + odeploycons.VMConsoleEnv.SUPPORT, + odeploycons.Const.VMCONSOLE_SUPPORT_NONE + ) + + @plugin.event( + stage=plugin.Stages.STAGE_CUSTOMIZATION, + priority=plugin.Stages.PRIORITY_HIGH, + ) + def _customization(self): + if self.packager.queryPackages( + patterns=('ovirt-vmconsole-host',), + ): + self.environment[ + odeploycons.VMConsoleEnv.SUPPORT + ] = odeploycons.Const.VMCONSOLE_SUPPORT_V1 + + @plugin.event( + stage=plugin.Stages.STAGE_VALIDATION, + condition=lambda self: self.environment[ + odeploycons.VMConsoleEnv.ENABLE + ] + ) + def _validation(self): + self._enabled = True + + @plugin.event( + stage=plugin.Stages.STAGE_PACKAGES, + condition=lambda self: self._enabled, + ) + def _packages(self): + self.packager.installUpdate(('ovirt-vmconsole-host',)) + + @plugin.event( + stage=plugin.Stages.STAGE_CLOSEUP, + priority=plugin.Stages.PRIORITY_LOW, + condition=lambda self: self._enabled, + ) + def _start(self): + self.logger.info(_('Starting ovirt-vmconsole-host-sshd')) + if self.services.exists('ovirt-vmconsole-host-sshd'): + self.services.state('ovirt-vmconsole-host-sshd', False) + self.services.state('ovirt-vmconsole-host-sshd', True) + + +# vim: expandtab tabstop=4 shiftwidth=4 diff --git a/src/plugins/ovirt-host-deploy/vmconsole/pki.py b/src/plugins/ovirt-host-deploy/vmconsole/pki.py new file mode 100644 index 0000000..6433c05 --- /dev/null +++ b/src/plugins/ovirt-host-deploy/vmconsole/pki.py @@ -0,0 +1,229 @@ +# +# ovirt-host-deploy -- ovirt host deployer +# Copyright (C) 2012-2015 Red Hat, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# + + +"""Serial console PKI artifacts.""" + + +import gettext +import os + + +from otopi import constants as otopicons +from otopi import filetransaction +from otopi import plugin +from otopi import util + + +from ovirt_host_deploy import constants as odeploycons + + +def _(m): + return gettext.dgettext(message=m, domain='ovirt-host-deploy') + + +@util.export +class Plugin(plugin.PluginBase): + def _genReqM2Crypto(self): + from M2Crypto import X509, RSA, EVP + + rsa = RSA.gen_key( + self.environment[odeploycons.VdsmEnv.KEY_SIZE], + 65537, + ) + rsapem = rsa.as_pem(cipher=None) + evp = EVP.PKey() + evp.assign_rsa(rsa) + rsa = None # should not be freed here + req = X509.Request() + req.set_pubkey(evp) + req.sign(evp, 'sha1') + return rsapem, req.as_pem() + + def __init__(self, context): + super(Plugin, self).__init__(context=context) + self._enabled = False + self._cleanupFiles = [] + + @plugin.event( + stage=plugin.Stages.STAGE_INIT, + ) + def _init(self): + self._enabled = False + self.environment.setdefault( + odeploycons.VMConsoleEnv.CERTIFICATE, + None + ) + self.environment.setdefault( + odeploycons.VMConsoleEnv.KEY_SIZE, + odeploycons.Defaults.DEFAULT_KEY_SIZE + ) + + @plugin.event( + stage=plugin.Stages.STAGE_VALIDATION, + condition=lambda self: self.environment[ + odeploycons.VMConsoleEnv.ENABLE + ] + ) + def _validation(self): + self._enabled = True + + if self.environment[ + odeploycons.VdsmEnv.CERTIFICATE_ENROLLMENT + ] == odeploycons.Const.CERTIFICATE_ENROLLMENT_ACCEPT: + # we cannot perform the following + # in validation stage, as we do not have + # the trust store location. + if not os.path.exists( + odeploycons.FileLocations.VMCONSOLE_KEY_PENDING_FILE + ): + raise RuntimeError( + _('PKI accept mode while no pending request') + ) + + @plugin.event( + stage=plugin.Stages.STAGE_PACKAGES, + condition=lambda self: self._enabled, + ) + def _packages(self): + self.packager.install(('m2crypto',)) + + @plugin.event( + stage=plugin.Stages.STAGE_MISC, + priority=plugin.Stages.PRIORITY_LOW, + condition=lambda self: self._enabled, + ) + def _misc(self): + self.dialog.note(_('Setting up Serial Console PKI')) + + enrollment = self.environment[ + odeploycons.VdsmEnv.CERTIFICATE_ENROLLMENT + ] + + if enrollment == odeploycons.Const.CERTIFICATE_ENROLLMENT_ACCEPT: + with open( + odeploycons.FileLocations.VMCONSOLE_KEY_PENDING_FILE + ) as f: + key = f.read() + else: + key, req = self._genReqM2Crypto() + + self.dialog.displayMultiString( + name=odeploycons.Displays.VMCONSOLE_CERTIFICATE_REQUEST, + value=req.splitlines(), + note=_( + '\n\nPlease issue serial console certificate based ' + 'on this certificate request\n\n' + ), + ) + + if enrollment == odeploycons.Const.CERTIFICATE_ENROLLMENT_REQUEST: + self.environment[odeploycons.CoreEnv.INSTALL_INCOMPLETE] = True + self.environment[ + odeploycons.CoreEnv.INSTALL_INCOMPLETE_REASONS + ].append(_('Serial console certificate enrollment required')) + + self.environment[otopicons.CoreEnv.MAIN_TRANSACTION].append( + filetransaction.FileTransaction( + name=odeploycons.FileLocations.VMCONSOLE_KEY_PENDING_FILE, + mode=0o400, + enforcePermissions=True, + content=key, + modifiedList=self.environment[ + otopicons.CoreEnv.MODIFIED_FILES + ], + ) + ) + else: + self._cleanupFiles.append( + odeploycons.FileLocations.VMCONSOLE_KEY_PENDING_FILE + ) + + cert = self.environment[ + odeploycons.VMConsoleEnv.CERTIFICATE + ] + + if cert is None: + cert = self.environment[ + odeploycons.VMConsoleEnv.CERTIFICATE + ] = self.dialog.queryValue( + name=odeploycons.Queries.VMCONSOLE_CERTIFICATE, + note=_( + '\n\nPlease input serial console certificate chain ' + 'that matches certificate request, top is issuer\n\n' + ), + ) + + self.environment[otopicons.CoreEnv.MAIN_TRANSACTION].append( + filetransaction.FileTransaction( + name=odeploycons.FileLocations.VMCONSOLE_CA_FILE, + enforcePermissions=True, + content='%s\n' % self.environment[ + odeploycons.VMConsoleEnv.CAKEY + ], + modifiedList=self.environment[ + otopicons.CoreEnv.MODIFIED_FILES + ], + ) + ) + + self.environment[otopicons.CoreEnv.MAIN_TRANSACTION].append( + filetransaction.FileTransaction( + name=odeploycons.FileLocations.VMCONSOLE_CERT_FILE, + enforcePermissions=True, + content='%s\n' % cert, + modifiedList=self.environment[ + otopicons.CoreEnv.MODIFIED_FILES + ], + ) + ) + + self.environment[otopicons.CoreEnv.MAIN_TRANSACTION].append( + filetransaction.FileTransaction( + name=odeploycons.FileLocations.VMCONSOLE_KEY_FILE, + owner='ovirt-vmconsole', + group='ovirt-vmconsole', + mode=0o400, + enforcePermissions=True, + content=key, + modifiedList=self.environment[ + otopicons.CoreEnv.MODIFIED_FILES + ], + ) + ) + + @plugin.event( + stage=plugin.Stages.STAGE_CLOSEUP, + condition=lambda self: self._enabled, + ) + def _closeup(self): + for f in self._cleanupFiles: + if os.path.exists(f): + try: + os.unlink(f) + except OSError: + self.logger.warning( + _("Cannot remove file '{name}'.").format( + name=f, + ) + ) + self.logger.debug(exc_info=True) + + +# vim: expandtab tabstop=4 shiftwidth=4 -- To view, visit https://gerrit.ovirt.org/38091 To unsubscribe, visit https://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I45e0b91bb678008dc74ced8622251beccefc82b9 Gerrit-PatchSet: 6 Gerrit-Project: ovirt-host-deploy Gerrit-Branch: master Gerrit-Owner: Alon Bar-Lev <alo...@redhat.com> Gerrit-Reviewer: Alon Bar-Lev <alo...@redhat.com> Gerrit-Reviewer: Francesco Romani <from...@redhat.com> Gerrit-Reviewer: Jenkins CI Gerrit-Reviewer: automat...@ovirt.org _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches