Add diagnose() method in OSBase derived classes
authorNikos Skalkotos <skalkoto@grnet.gr>
Wed, 16 Oct 2013 13:46:07 +0000 (16:46 +0300)
committerNikos Skalkotos <skalkoto@grnet.gr>
Wed, 16 Oct 2013 13:46:07 +0000 (16:46 +0300)
This can be used to perform various tests to determine if the media
is supported.

image_creator/dialog_main.py
image_creator/dialog_menu.py
image_creator/image.py
image_creator/main.py
image_creator/os_type/__init__.py
image_creator/os_type/freebsd.py
image_creator/os_type/linux.py

index 0586327..2a56a1c 100644 (file)
@@ -101,7 +101,7 @@ def create_image(d, media, out, tmp):
                    "image": image,
                    "metadata": metadata}
 
-        if hasattr(image, "unsupported"):
+        if image.is_unsupported():
 
             session['excluded_tasks'] = [-1]
             session['task_metadata'] = ["EXCLUDE_ALL_TASKS"]
@@ -112,7 +112,7 @@ def create_image(d, media, out, tmp):
                 "since the image won't be cleaned up and you will not be " \
                 "able to configure it during the deployment. Press <YES> if " \
                 "you still want to continue with the image creation process." \
-                % image.unsupported
+                % image._unsupported
 
             if not d.yesno(msg, width=WIDTH, defaultno=1, height=12):
                 main_menu(session)
index ba29ea1..1e74970 100644 (file)
@@ -585,9 +585,9 @@ def exclude_tasks(session):
     d = session['dialog']
     image = session['image']
 
-    if hasattr(image, "unsupported"):
-        d.msgbox("You cannot configure the deployment tasks for an unsupported"
-                 " image.", width=SMALL_WIDTH)
+    if image.is_unsupported():
+        d.msgbox("Image deployment configuration is disabled for unsupported "
+                 "images.", width=SMALL_WIDTH)
         return False
 
     index = 0
index 2eb97dd..bbc53ae 100644 (file)
@@ -95,23 +95,19 @@ class Image(object):
             self.distro = "unsupported"
             self.guestfs_device = '/dev/sda'
             self.size = self.g.blockdev_getsize64(self.guestfs_device)
+
             if len(roots) > 1:
-                self.unsupported = "Multiple operating systems found on the " \
-                    "media. We only support images with one OS."
+                reason = "Multiple operating systems found on the media."
             else:
-                self.unsupported = \
-                    "Unable to detect any operating system on the media"
+                reason = "Unable to detect any operating system on the media."
 
-            self.meta['UNSUPPORTED'] = "Reason: %s" % self.unsupported
-            self.out.warn('Media is not supported. %s' %
-                          self.meta['UNSUPPORTED'])
+            self.set_unsupported(reason)
             return
 
         self.root = roots[0]
-        self.guestfs_device = self.g.part_to_dev(self.root)
+        self.meta['PARTITION_TABLE'] = self.g.part_get_parttype('/dev/sda')
+        self.guestfs_device = '/dev/sda'  # self.g.part_to_dev(self.root)
         self.size = self.g.blockdev_getsize64(self.guestfs_device)
-        self.meta['PARTITION_TABLE'] = \
-            self.g.part_get_parttype(self.guestfs_device)
 
         self.ostype = self.g.inspect_get_type(self.root)
         self.distro = self.g.inspect_get_distro(self.root)
@@ -119,6 +115,20 @@ class Image(object):
             'found a(n) %s system' %
             self.ostype if self.distro == "unknown" else self.distro)
 
+        # Run OS-specific diagnostics
+        self.os.diagnose()
+
+    def set_unsupported(self, reason):
+        """Flag this image us ansupported"""
+
+        self._unsupported = reason
+        self.meta['UNSUPPORTED'] = reason
+        self.out.warn('Media is not supported. Reason: %s' % reason)
+
+    def is_unsupported(self):
+        """Returns if this image is unsupported"""
+        return hasattr(self, '_unsupported')
+
     def enable_guestfs(self):
         """Enable the guestfs handler"""
 
@@ -278,8 +288,8 @@ class Image(object):
 
         self.out.output("Shrinking image (this may take a while) ...", False)
 
-        if hasattr(self, "unsupported"):
-            self.out.warn("Unable to shrink unsupported image")
+        if self.is_unsupported():
+            self.out.warn("Shrinking is disabled for unsupported images")
             return self.size
 
         sector_size = self.g.blockdev_getss(self.guestfs_device)
index 29ed068..26e1be5 100644 (file)
@@ -50,6 +50,7 @@ import optparse
 import StringIO
 import signal
 import json
+import textwrap
 
 
 def check_writable_dir(option, opt_str, value, parser):
@@ -277,13 +278,15 @@ def image_creator():
 
         image = disk.get_image(snapshot, sysprep_params=options.sysprep_params)
 
-        if hasattr(image, 'unsupported') and not options.allow_unsupported:
+        if image.is_unsupported() and not options.allow_unsupported:
             raise FatalError(
-                "The media seems to be unsupported. If you insist on creating "
-                "an image out of it, use the `--allow-unsupported' option. "
-                "Using this is highly discouraged, since the resulting image "
-                "will not be cleaned up from sensitive data and will not get "
-                "configured during the deployment")
+                "The media seems to be unsupported.\n\n" +
+                textwrap.fill("To create an image from an unsupported media, "
+                              "you'll need to use the`--allow-unsupported' "
+                              "command line option. Using this is highly "
+                              "discouraged, since the resulting image will "
+                              "not be cleared out of sensitive data and will "
+                              "not get customized during the deployment."))
 
         for sysprep in options.disabled_syspreps:
             image.os.disable_sysprep(image.os.get_sysprep_by_name(sysprep))
@@ -310,7 +313,7 @@ def image_creator():
         size = options.shrink and image.shrink() or image.size
         metadata.update(image.meta)
 
-        if hasattr(image, 'unsupported'):
+        if image.is_unsupported():
             metadata['EXCLUDE_ALL_TASKS'] = "yes"
 
         # Add command line metadata to the collected ones...
index ff51deb..63b7f5a 100644 (file)
@@ -144,6 +144,22 @@ class OSBase(object):
         except RuntimeError:
             self._scrub_support = False
 
+    def diagnose(self):
+        """Run diagnostics to check if the media is supported"""
+
+        if self.image.is_unsupported():
+            return
+
+        self.out.output('Running OS diagnostics:')
+        try:
+            if not self.mount(readonly=True):
+                raise FatalError("Unable to mount the media read-only")
+            self._do_diagnose()
+        finally:
+            self.umount()
+
+        self.out.output()
+
     def collect_metadata(self):
         """Collect metadata about the OS"""
         try:
@@ -249,7 +265,7 @@ class OSBase(object):
 
         self.out.output('Preparing system for image creation:')
 
-        if hasattr(self.image, "unsupported"):
+        if self.image.is_unsupported():
             self.out.warn(
                 "System preparation is disabled for unsupported media")
             return
@@ -356,10 +372,20 @@ class OSBase(object):
             if has_ftype(f, ftype):
                 action(full_path)
 
+    def _do_diagnose(self):
+        """helper method for diagnose"""
+        pass
+
     def _do_collect_metadata(self):
         """helper method for collect_metadata"""
-        self.meta['ROOT_PARTITION'] = \
-            "%d" % self.image.g.part_to_partnum(self.root)
+
+        try:
+            self.meta['ROOT_PARTITION'] = \
+                "%d" % self.image.g.part_to_partnum(self.root)
+        except RuntimeError:
+            self.out.warn("Unable to identify the partition number from root "
+                          "partition: %s" % self.root)
+
         self.meta['OSFAMILY'] = self.image.g.inspect_get_type(self.root)
         self.meta['OS'] = self.image.g.inspect_get_distro(self.root)
         if self.meta['OS'] == "unknown":
index 5f81481..8ee5427 100644 (file)
@@ -82,6 +82,18 @@ class Freebsd(Unix):
             self.out.warn("No passworded users found!")
             del self.meta['USERS']
 
+    def _do_diagnose(self):
+        """Run various diagnostics to check if media is supported"""
+
+        self.out.output('Checking partition table type...', False)
+        ptype = self.image.g.part_get_parttype(self.image.guestfs_device)
+        if ptype != 'gpt':
+            self.out.warn("partition table type is: `%s'" % ptype)
+            self.image.set_unsupported(
+                'On FreeBSD only GUID partition tables are supported')
+        else:
+            self.out.success(ptype)
+
     def _get_passworded_users(self):
         """Returns a list of non-locked user accounts"""
         users = []
index 31b660f..d0ca04a 100644 (file)
@@ -298,6 +298,20 @@ class Linux(Unix):
 
         return orig, dev, mpoint
 
+    def _do_diagnose(self):
+        """Run various diagnostics to check if media is supported"""
+
+        self.out.output(
+            'Checking if the media contains logical volumes (LVM)...', False)
+
+        has_lvm = True if len(self.image.g.lvs()) else False
+
+        if has_lvm:
+            self.out.output()
+            self.image.set_unsupported('The media contains logical volumes')
+        else:
+            self.out.success('no')
+
     def _do_collect_metadata(self):
         """Collect metadata about the OS"""
         super(Linux, self)._do_collect_metadata()