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

Reply via email to