Sandro Bonazzola has uploaded a new change for review. Change subject: WIP: packaging: setup: iSCSI support ......................................................................
WIP: packaging: setup: iSCSI support - implemented the customization stage. - TODO: add more validations on user input - TODO: implement misc stage Change-Id: Ide79a130b730d95d3545dcfb80b1b01dfeaf2b12 Signed-off-by: Sandro Bonazzola <[email protected]> --- M src/ovirt_hosted_engine_setup/constants.py M src/plugins/ovirt-hosted-engine-setup/storage/Makefile.am M src/plugins/ovirt-hosted-engine-setup/storage/__init__.py A src/plugins/ovirt-hosted-engine-setup/storage/iscsi.py M src/plugins/ovirt-hosted-engine-setup/storage/storage.py 5 files changed, 310 insertions(+), 16 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-hosted-engine-setup refs/changes/01/26501/1 diff --git a/src/ovirt_hosted_engine_setup/constants.py b/src/ovirt_hosted_engine_setup/constants.py index 068e0cc..8324f76 100644 --- a/src/ovirt_hosted_engine_setup/constants.py +++ b/src/ovirt_hosted_engine_setup/constants.py @@ -414,6 +414,40 @@ def DOMAIN_TYPE(self): return 'OVEHOSTED_STORAGE/domainType' + @ohostedattrs( + answerfile=True, + summary=True, + description=_('iSCSI Portal IP Address'), + ) + def ISCSI_IP_ADDR(self): + return 'OVEHOSTED_STORAGE/iSCSIPortalIPAddress' + + @ohostedattrs( + answerfile=True, + summary=True, + description=_('iSCSI Portal port'), + ) + def ISCSI_PORT(self): + return 'OVEHOSTED_STORAGE/iSCSIPortalPort' + + @ohostedattrs( + answerfile=True, + summary=True, + description=_('iSCSI Portal user'), + ) + def ISCSI_USER(self): + return 'OVEHOSTED_STORAGE/iSCSIPortalUser' + + @ohostedattrs( + answerfile=True, + summary=True, + description=_('iSCSI Target Name'), + ) + def ISCSI_TARGET(self): + return 'OVEHOSTED_STORAGE/iSCSITargetName' + + ISCSI_PASSWORD = 'OVEHOSTED_STORAGE/iSCSIPortalPassword' + @util.export @util.codegen @@ -596,6 +630,7 @@ CONFIG_BOOT_DEVICE = 'ohosted.boot.configuration.available' CONFIG_STORAGE_EARLY = 'ohosted.storage.configuration.early' CONFIG_STORAGE_LATE = 'ohosted.storage.configuration.late' + CONFIG_STORAGE_ISCSI = 'ohosted.storage.iscsi.configuration.available' CONFIG_STORAGE_NFS = 'ohosted.storage.nfs.configuration.available' CONFIG_ADDITIONAL_HOST = 'ohosted.core.additional.host' REQUIRE_ANSWER_FILE = 'ohosted.core.require.answerfile' @@ -661,6 +696,7 @@ DEFAULT_SSHD_PORT = 22 DEFAULT_EMULATED_MACHINE = 'pc' DEAFULT_RHEL_EMULATED_MACHINE = 'rhel6.5.0' + DEFAULT_ISCSI_PORT = 3260 @util.export diff --git a/src/plugins/ovirt-hosted-engine-setup/storage/Makefile.am b/src/plugins/ovirt-hosted-engine-setup/storage/Makefile.am index 1ce7bd8..07a084a 100644 --- a/src/plugins/ovirt-hosted-engine-setup/storage/Makefile.am +++ b/src/plugins/ovirt-hosted-engine-setup/storage/Makefile.am @@ -26,6 +26,7 @@ mydir=$(ovirthostedengineplugindir)/ovirt-hosted-engine-setup/storage dist_my_PYTHON = \ __init__.py \ + iscsi.py \ nfs.py \ storage.py \ $(NULL) diff --git a/src/plugins/ovirt-hosted-engine-setup/storage/__init__.py b/src/plugins/ovirt-hosted-engine-setup/storage/__init__.py index 4c8f748..9f486bf 100644 --- a/src/plugins/ovirt-hosted-engine-setup/storage/__init__.py +++ b/src/plugins/ovirt-hosted-engine-setup/storage/__init__.py @@ -24,12 +24,14 @@ from otopi import util +from . import iscsi from . import nfs from . import storage @util.export def createPlugins(context): + iscsi.Plugin(context=context) nfs.Plugin(context=context) storage.Plugin(context=context) diff --git a/src/plugins/ovirt-hosted-engine-setup/storage/iscsi.py b/src/plugins/ovirt-hosted-engine-setup/storage/iscsi.py new file mode 100644 index 0000000..ae8afdc --- /dev/null +++ b/src/plugins/ovirt-hosted-engine-setup/storage/iscsi.py @@ -0,0 +1,257 @@ +# +# ovirt-hosted-engine-setup -- ovirt hosted engine setup +# Copyright (C) 2014 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 +# + + +""" +iSCSI storage domain plugin. +""" + + +import gettext + + +from otopi import constants as otopicons +from otopi import plugin +from otopi import util + + +from ovirt_hosted_engine_setup import constants as ohostedcons + + +_ = lambda m: gettext.dgettext(message=m, domain='ovirt-hosted-engine-setup') + + [email protected] +class Plugin(plugin.PluginBase): + """ + iSCSI storage domain plugin. + """ + + def __init__(self, context): + super(Plugin, self).__init__(context=context) + self._interactive = False + + def _customize_ip_address(self): + valid = False + address = None + while not valid: + address = self.environment[ohostedcons.StorageEnv.ISCSI_IP_ADDR] + if address is None: + self._interactive = True + address = self.dialog.queryString( + name='OVEHOSTED_STORAGE_ISCSI_IP_ADDR', + note=_( + 'Please specify the iSCSI portal IP address: ' + ), + prompt=True, + caseSensitive=True, + ) + try: + if address: + valid = True + else: + raise ValueError(_('Address must be a valid IP address')) + except ValueError as e: + if self.environment[ + ohostedcons.StorageEnv.ISCSI_IP_ADDR + ] is None: + self.logger.debug('exception', exc_info=True) + self.logger.error(_('Address must be a valid IP address')) + else: + raise e + return address + + def _customize_port(self): + valid = False + port = None + while not valid: + port = self.environment[ohostedcons.StorageEnv.ISCSI_PORT] + if port is None: + self._interactive = True + port = self.dialog.queryString( + name='OVEHOSTED_STORAGE_ISCSI_IP_PORT', + note=_( + 'Please specify the iSCSI portal port [@DEFAULT@]: ' + ), + prompt=True, + caseSensitive=True, + default=ohostedcons.Defaults.DEFAULT_ISCSI_PORT, + ) + try: + if int(port) > 0: + valid = True + else: + raise ValueError(_('Port must be a valid port number')) + except ValueError as e: + if self.environment[ohostedcons.StorageEnv.ISCSI_PORT] is None: + self.logger.debug('exception', exc_info=True) + self.logger.error(_('Port must be a valid port number')) + else: + raise e + return port + + def _customize_user(self): + user = self.environment[ohostedcons.StorageEnv.ISCSI_USER] + if user is None: + self._interactive = True + user = self.dialog.queryString( + name='OVEHOSTED_STORAGE_ISCSI_USER', + note=_( + 'Please specify the iSCSI portal user: ' + ), + prompt=True, + caseSensitive=True, + default='', + ) + return user + + def _customize_password(self): + password = '' + if ( + self.environment[ohostedcons.StorageEnv.ISCSI_USER] and + self.environment[ohostedcons.StorageEnv.ISCSI_PASSWORD] is None + ): + self._interactive = True + password = self.dialog.queryString( + name='OVEHOSTED_STORAGE_ISCSI_PASSWORD', + note=_( + 'Please specify the iSCSI portal password: ' + ), + prompt=True, + hidden=True, + default='' + ) + return password + + def _customize_target(self, values, default): + valid = False + while not valid: + target = self.environment[ohostedcons.StorageEnv.ISCSI_TARGET] + if target is None: + self._interactive = True + target = self.dialog.queryString( + name='OVEHOSTED_STORAGE_ISCSI_TARGET', + note=_( + 'Please specify the target name ' + '(@VALUES@) [@DEFAULT@]: ' + ), + prompt=True, + caseSensitive=True, + default=default, + validValues=values, + ) + #validate + valid = True + + @plugin.event( + stage=plugin.Stages.STAGE_SETUP, + ) + def _setup(self): + self.command.detect('iscsiadm') + + @plugin.event( + stage=plugin.Stages.STAGE_INIT, + ) + def _init(self): + self.environment.setdefault( + ohostedcons.StorageEnv.ISCSI_IP_ADDR, + None + ) + self.environment.setdefault( + ohostedcons.StorageEnv.ISCSI_PORT, + None + ) + self.environment.setdefault( + ohostedcons.StorageEnv.ISCSI_USER, + None + ) + self.environment.setdefault( + ohostedcons.StorageEnv.ISCSI_PASSWORD, + None + ) + self.environment.setdefault( + ohostedcons.StorageEnv.ISCSI_TARGET, + None + ) + + @plugin.event( + stage=plugin.Stages.STAGE_CUSTOMIZATION, + name=ohostedcons.Stages.CONFIG_STORAGE_ISCSI, + priority=plugin.Stages.PRIORITY_FIRST, + after=( + ohostedcons.Stages.CONFIG_STORAGE_EARLY, + ), + before=( + ohostedcons.Stages.CONFIG_STORAGE_LATE, + ), + condition=( + lambda self: self.environment[ + ohostedcons.StorageEnv.DOMAIN_TYPE + ] == 'iscsi' + ), + ) + def _customization(self): + valid_access = False + address = None + port = None + user = None + password = None + while not valid_access: + address = self._customize_ip_address() + port = self._customize_port() + user = self._customize_user() + password = self._customize_password() + self.environment[otopicons.CoreEnv.LOG_FILTER].append(password) + #validating access + try: + rc, stdout, stderr = self.execute( + ( + self.command.get('iscsiadm'), + '-m discovery', + '-t sendtargets', + '-p {address}:{port}'.format( + address=address, + port=port, + ), + ), + raiseOnError=True + ) + for line in stdout: + self.logger.info(line) + #192.168.1.105:3260,1 iqn.2009-02.com.example:for.all + valid_access = True + except RuntimeError as e: + if self._interactive: + self.logger.debug('exception', exc_info=True) + self.logger.error(_('Cannot access to iSCSI portal')) + else: + raise e + self.environment[ohostedcons.StorageEnv.ISCSI_IP_ADDR] = address + self.environment[ohostedcons.StorageEnv.ISCSI_PORT] = port + self.environment[ohostedcons.StorageEnv.ISCSI_USER] = user + self.environment[ohostedcons.StorageEnv.ISCSI_PASSWORD] = password + + self._customize_target( + values=['iqn.2009-02.com.example:for.all'], + default='iqn.2009-02.com.example:for.all' + ) + raise RuntimeError('Need implementation') + + +# vim: expandtab tabstop=4 shiftwidth=4 diff --git a/src/plugins/ovirt-hosted-engine-setup/storage/storage.py b/src/plugins/ovirt-hosted-engine-setup/storage/storage.py index d3f776b..bcf13a7 100644 --- a/src/plugins/ovirt-hosted-engine-setup/storage/storage.py +++ b/src/plugins/ovirt-hosted-engine-setup/storage/storage.py @@ -51,6 +51,7 @@ """ NFS_DOMAIN = 1 + ISCSI_DOMAIN = 3 GLUSTERFS_DOMAIN = 7 DATA_DOMAIN = 1 @@ -652,6 +653,7 @@ ), before=( ohostedcons.Stages.CONFIG_STORAGE_NFS, + ohostedcons.Stages.CONFIG_STORAGE_ISCSI, ), ) def _early_customization(self): @@ -662,12 +664,9 @@ ) self.serv = self.environment[ohostedcons.VDSMEnv.VDS_CLI] self._check_existing_pools() - if self.environment[ - ohostedcons.StorageEnv.DOMAIN_TYPE - ] is None: - self.environment[ - ohostedcons.StorageEnv.DOMAIN_TYPE - ] = self.dialog.queryString( + domain_type = self.environment[ohostedcons.StorageEnv.DOMAIN_TYPE] + if domain_type is None: + domain_type = self.dialog.queryString( name='OVEHOSTED_STORAGE_DOMAIN_TYPE', note=_( 'Please specify the storage ' @@ -678,36 +677,34 @@ validValues=( # Enable when glusterfs issues are solved: # 'glusterfs', + 'iscsi', 'nfs3', 'nfs4', ), default='nfs3', ) - if self.environment[ - ohostedcons.StorageEnv.DOMAIN_TYPE - ] == 'nfs3': + if domain_type == 'nfs3': self.storageType = self.NFS_DOMAIN self.protocol_version = 3 - elif self.environment[ - ohostedcons.StorageEnv.DOMAIN_TYPE - ] == 'nfs4': + elif domain_type == 'nfs4': self.storageType = self.NFS_DOMAIN self.protocol_version = 4 - elif self.environment[ - ohostedcons.StorageEnv.DOMAIN_TYPE - ] == 'glusterfs': + elif domain_type == 'glusterfs': self.storageType = self.GLUSTERFS_DOMAIN + elif domain_type == 'iscsi': + self.storageType = self.ISCSI_DOMAIN else: raise RuntimeError( _( - 'Invalid domain type: {dtype}' + 'Invalid domain type: "{dtype}"' ).format( dtype=self.environment[ ohostedcons.StorageEnv.DOMAIN_TYPE ], ) ) + self.environment[ohostedcons.StorageEnv.DOMAIN_TYPE] = domain_type # Here the execution flow go to specific plugin activated by domain # type. @@ -717,6 +714,7 @@ priority=plugin.Stages.PRIORITY_FIRST, after=( ohostedcons.Stages.CONFIG_STORAGE_NFS, + ohostedcons.Stages.CONFIG_STORAGE_ISCSI, ), before=( ohostedcons.Stages.DIALOG_TITLES_E_STORAGE, -- To view, visit http://gerrit.ovirt.org/26501 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ide79a130b730d95d3545dcfb80b1b01dfeaf2b12 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-hosted-engine-setup Gerrit-Branch: master Gerrit-Owner: Sandro Bonazzola <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
