Simone Tiraboschi has uploaded a new change for review.

Change subject: packaging: setup: auto-detect available appliance images and 
suggest them
......................................................................

packaging: setup: auto-detect available appliance images and suggest them

Autodetects available appliance images
Suggest them if no one is available
Validate the sha1sum of the selected appliance
Makes the appliance flow the default one

https://bugzilla.redhat.com/1211532

Change-Id: Iaddd10521e71d5c855473817a563c8c1c6a1b0a8
Signed-off-by: Simone Tiraboschi <stira...@redhat.com>
---
M src/ovirt_hosted_engine_setup/constants.py
M src/plugins/ovirt-hosted-engine-setup/vm/boot_disk.py
M src/plugins/ovirt-hosted-engine-setup/vm/configurevm.py
3 files changed, 146 insertions(+), 19 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-hosted-engine-setup 
refs/changes/87/41987/1

diff --git a/src/ovirt_hosted_engine_setup/constants.py 
b/src/ovirt_hosted_engine_setup/constants.py
index c21882a..091afb9 100644
--- a/src/ovirt_hosted_engine_setup/constants.py
+++ b/src/ovirt_hosted_engine_setup/constants.py
@@ -151,6 +151,11 @@
         'glusterfs',
         'glusterd.vol'
     )
+    OVIRT_APPLIANCES_DESC_DIR = os.path.join(
+        config.SYSCONFDIR,
+        OVIRT_HOSTED_ENGINE,
+    )
+    OVIRT_APPLIANCES_DESC_FILENAME_TEMPLATE = '*-appliance.conf'
     OVIRT_HOSTED_ENGINE_TEMPLATE = os.path.join(
         config.DATADIR,
         OVIRT_HOSTED_ENGINE_SETUP,
@@ -945,7 +950,7 @@
     DEFAULT_IMAGE_DESC = 'Hosted Engine Image'
     DEFAULT_IMAGE_SIZE_GB = 25  # based on minimum requirements.
     DEFAULT_MEM_SIZE_MB = 4096  # based on minimum requirements.
-    DEFAULT_BOOT = 'cdrom'  # boot device - drive C or cdrom or pxe
+    DEFAULT_BOOT = 'disk'  # boot device - drive C or cdrom or pxe
     DEFAULT_CDROM = '/dev/null'
     DEFAULT_BRIDGE_IF = 'em1'
     DEFAULT_BRIDGE_NAME = 'ovirtmgmt'
diff --git a/src/plugins/ovirt-hosted-engine-setup/vm/boot_disk.py 
b/src/plugins/ovirt-hosted-engine-setup/vm/boot_disk.py
index c3dbd8f..ca81549 100644
--- a/src/plugins/ovirt-hosted-engine-setup/vm/boot_disk.py
+++ b/src/plugins/ovirt-hosted-engine-setup/vm/boot_disk.py
@@ -23,8 +23,11 @@
 """
 
 
+import configparser
 import gettext
 import glob
+import hashlib
+from io import StringIO
 import json
 import os
 import shutil
@@ -223,6 +226,63 @@
         self._image_path = None
         self._ovf_mem_size_mb = None
 
+    def _detect_appliances(self):
+        self.logger.info(_('Detecting available oVirt engine appliances'))
+        appliances = []
+        config = configparser.ConfigParser()
+        config.optionxform = str
+        confdir = os.path.join(
+            ohostedcons.FileLocations.OVIRT_APPLIANCES_DESC_DIR,
+            ohostedcons.FileLocations.OVIRT_APPLIANCES_DESC_FILENAME_TEMPLATE,
+        )
+        conffiles = glob.glob(confdir)
+        fakesection = 'appliance'
+        keys = ['description', 'version', 'path', 'sha1sum']
+        for cf in conffiles:
+            self.logger.debug('parsing: ' + cf)
+            with open(cf) as stream:
+                fakefile = StringIO(
+                    u'[{s}]\n'.format(s=fakesection) + stream.read()
+                )
+                config.readfp(fakefile)
+            if set(
+                    [config.has_option(fakesection, k) for k in keys]
+            ) == set([True]):
+                app = {k: self.config.get(fakesection, k)
+                       for k in keys
+                       }
+                app.update(
+                    {'index': str(len(appliances)+1)}
+                )
+                appliances.append(app)
+            else:
+                self.logger.error('error parsing: ' + cf)
+        self.logger.debug('available appliances: ' + str(self._appliances))
+        if not appliances:
+            self.logger.info(
+                'No engine appliance image is available on your system\n'
+                'Using an oVirt engine appliance could greatly speed-up '
+                'ovirt hosted-engine deploy\n'
+                'You could get oVirt engine appliance installing '
+                'ovirt-engine-appliance rpm'
+            )
+        return appliances
+
+    def _file_hash(self, filename):
+        h = hashlib.sha1()
+        with open(filename, 'rb') as file:
+            chunk = 0
+            while chunk != b'':
+                chunk = file.read(1024)
+                h.update(chunk)
+        self.logger.debug(
+            "calculated sha1sum for {f}: {g}".format(
+                f=filename,
+                h=h.hexdigest(),
+            )
+        )
+        return h.hexdigest()
+
     def _parse_ovf(self, tar, ovf_xml):
         valid = True
         tmpdir = tempfile.mkdtemp()
@@ -402,26 +462,86 @@
         interactive = self.environment[
             ohostedcons.VMEnv.OVF
         ] is None
+        appliances = []
+        if interactive:
+            appliances = self._detect_appliances()
+            if appliances:
+                directlyOVA = str(len(appliances)+1)
+                app_list = ''
+                for entry in appliances:
+                    app_list += _(
+                        '\t[{i}] - {description} - {version}\n'
+                    ).format(
+                        i=entry['index'],
+                        description=entry['description'],
+                        version=entry['version'],
+                    )
+                app_list += (
+                    _('\t[{i}] - {Directly select an OVA file}\n').format(
+                        i=directlyOVA,
+                        description=_('Directly select an OVA file'),
+                    )
+                )
+
         valid = False
         while not valid:
             if interactive:
-                self.environment[
-                    ohostedcons.VMEnv.OVF
-                ] = self.dialog.queryString(
-                    name='OVEHOSTED_VMENV_OVF',
-                    note=_(
-                        'Please specify path to OVF archive '
-                        'you would like to use [@DEFAULT@]: '
-                    ),
-                    prompt=True,
-                    caseSensitive=True,
-                    default=str(self.environment[
-                        ohostedcons.VMEnv.OVF
-                    ]),
-                )
+                ova_path = ''
+                if appliances:
+                    self.dialog.note(
+                        _(
+                            'The following appliance have been '
+                            'found on your system:\n'
+                            '{app_list}'
+                        ).format(
+                            app_list=app_list,
+                        )
+                    )
+                    sapp = self.dialog.queryString(
+                        name='OVEHOSTED_STORAGE_BLOCKD_LUN',
+                        note=_(
+                            'Please select the destination LUN '
+                            '(@VALUES@) [@DEFAULT@]: '
+                        ),
+                        prompt=True,
+                        caseSensitive=True,
+                        default='1',
+                        validValues=[str(i+1) for i in range(len(app_list))],
+                    )
+                    if sapp != directlyOVA:
+                        ova_path = appliances[int(sapp)-1]['path']
+                        if (
+                            self._file_hash(ova_path) !=
+                            appliances[int(sapp)-1]['sha1sum']
+                        ):
+                            self.logger.error(
+                                _(
+                                    "The selected appliance is invalid: the "
+                                    "sha1sum of the selected file ('{p}') "
+                                    "doesn't match the expected value."
+                                ).format(p=ova_path)
+                            )
+                            continue
+                if not ova_path:
+                    ova_path = self.dialog.queryString(
+                        name='OVEHOSTED_VMENV_OVF',
+                        note=_(
+                            'Please specify path to OVF archive '
+                            'you would like to use [@DEFAULT@]: '
+                        ),
+                        prompt=True,
+                        caseSensitive=True,
+                        default=str(self.environment[
+                            ohostedcons.VMEnv.OVF
+                        ]),
+                    )
+            else:  # Not interactive
+                ova_path = self.environment[ohostedcons.VMEnv.OVF]
 
-            valid = self._check_ovf(self.environment[ohostedcons.VMEnv.OVF])
-            if not valid:
+            valid = self._check_ovf(ova_path)
+            if valid:
+                self.environment[ohostedcons.VMEnv.OVF] = ova_path
+            else:
                 if interactive:
                     self.logger.error(
                         _(
diff --git a/src/plugins/ovirt-hosted-engine-setup/vm/configurevm.py 
b/src/plugins/ovirt-hosted-engine-setup/vm/configurevm.py
index 74e9c0d..4a2185c 100644
--- a/src/plugins/ovirt-hosted-engine-setup/vm/configurevm.py
+++ b/src/plugins/ovirt-hosted-engine-setup/vm/configurevm.py
@@ -126,6 +126,7 @@
             self.environment[ohostedcons.VMEnv.CDROM] = None
             self.environment[ohostedcons.VMEnv.OVF] = None
         else:
+            self._detect_appliances()
             interactive = self.environment[
                 ohostedcons.VMEnv.BOOT
             ] is None
@@ -137,8 +138,9 @@
                     ] = self.dialog.queryString(
                         name='OVEHOSTED_VMENV_BOOT',
                         note=_(
-                            'Please specify the device to boot the VM '
-                            'from (@VALUES@) [@DEFAULT@]: '
+                            'Please specify the device to boot the VM from '
+                            '(choose disk for the oVirt engine appliance)\n'
+                            '(@VALUES@) [@DEFAULT@]: '
                         ),
                         prompt=True,
                         caseSensitive=True,


-- 
To view, visit https://gerrit.ovirt.org/41987
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Iaddd10521e71d5c855473817a563c8c1c6a1b0a8
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-hosted-engine-setup
Gerrit-Branch: master
Gerrit-Owner: Simone Tiraboschi <stira...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to