components/openstack/nova/files/solariszones/driver.py
changeset 5279 6c696d36d952
parent 5252 947514442d05
child 5311 92a194d827f0
--- a/components/openstack/nova/files/solariszones/driver.py	Thu Jan 14 11:26:28 2016 -0800
+++ b/components/openstack/nova/files/solariszones/driver.py	Thu Jan 14 17:07:53 2016 -0800
@@ -27,14 +27,11 @@
 import tempfile
 import uuid
 
+import rad.bindings.com.oracle.solaris.rad.archivemgr_1 as archivemgr
 import rad.bindings.com.oracle.solaris.rad.kstat_1 as kstat
 import rad.bindings.com.oracle.solaris.rad.zonemgr_1 as zonemgr
 import rad.client
 import rad.connect
-from solaris_install.archive.checkpoints import InstantiateUnifiedArchive
-from solaris_install.archive import LOGFILE as ARCHIVE_LOGFILE
-from solaris_install.archive import UnifiedArchive
-from solaris_install.engine import InstallEngine
 from solaris_install.target.size import Size
 
 from cinderclient import exceptions as cinder_exception
@@ -481,20 +478,19 @@
         return self._rad_connection
 
     def _init_rad(self):
-        """Connect to RAD providers for kernel statistics and Solaris
-        Zones. By connecting to the local rad(1M) service through a
-        UNIX domain socket, kernel statistics can be read via
-        kstat(3RAD) and Solaris Zones can be configured and controlled
-        via zonemgr(3RAD).
+        """Obtain required RAD objects for Solaris Zones, kernel statistics,
+        and Unified Archive management.
         """
-
         try:
+            self._zone_manager = self.rad_connection.get_object(
+                zonemgr.ZoneManager())
             self._kstat_control = self.rad_connection.get_object(
                 kstat.Control())
-        except Exception as reason:
-            msg = (_('Unable to connect to svc:/system/rad:local: %s')
-                   % reason)
-            raise exception.NovaException(msg)
+            self._archive_manager = self.rad_connection.get_object(
+                archivemgr.ArchiveManager())
+        except Exception as ex:
+            reason = _("Unable to obtain RAD object: %s") % ex
+            raise exception.NovaException(reason)
 
     def init_host(self, host):
         """Initialize anything that is necessary for the driver to function,
@@ -865,63 +861,42 @@
         return image
 
     def _validate_image(self, image, instance):
-        """Validate a glance image for compatibility with the instance"""
-        # Skip if the image was already checked and confirmed as valid
+        """Validate a glance image for compatibility with the instance."""
+        # Skip if the image was already checked and confirmed as valid.
         if instance['image_ref'] in self._validated_archives:
             return
 
-        if self._install_engine is None:
-            self._install_engine = InstallEngine(ARCHIVE_LOGFILE)
-
         try:
-            init_ua_cp = InstantiateUnifiedArchive(instance['image_ref'],
-                                                   image)
-            init_ua_cp.execute()
-        except Exception:
-            reason = (_("Image query failed. Possibly invalid or corrupt. "
-                        "Log file location: %s:%s")
-                      % (self._uname[1], ARCHIVE_LOGFILE))
-            LOG.error(reason)
-            raise exception.ImageUnacceptable(image_id=instance['image_ref'],
-                                              reason=reason)
-
-        try:
-            ua = self._install_engine.doc.volatile.get_first_child(
-                class_type=UnifiedArchive)
-            # Validate the image at this point to ensure:
-            # - contains one deployable system
-            deployables = ua.archive_objects
-            if len(deployables) != 1:
-                reason = (_('Image must contain only 1 deployable system'))
+            ua = self._archive_manager.getArchive(image)
+        except Exception as ex:
+                reason = ex.get_payload().info
                 raise exception.ImageUnacceptable(
                     image_id=instance['image_ref'],
                     reason=reason)
-            # - matching architecture
-            deployable_arch = deployables[0].system.arch
-            compute_arch = platform.processor()
-            if deployable_arch != compute_arch:
-                reason = (_('Image architecture "%s" is incompatible with this'
-                          'compute host architecture: "%s"')
-                          % (deployable_arch, compute_arch))
-                raise exception.ImageUnacceptable(
-                    image_id=instance['image_ref'],
-                    reason=reason)
-            # - single root pool only
-            streams = deployables[0].zfs_streams
-            stream_pools = set(stream.zpool for stream in streams)
-            if len(stream_pools) > 1:
-                reason = (_('Image contains more than one zpool: "%s"')
-                          % (stream_pools))
-                raise exception.ImageUnacceptable(
-                    image_id=instance['image_ref'],
-                    reason=reason)
-            # - looks like it's OK
-            self._validated_archives.append(instance['image_ref'])
-        finally:
-            # Clear the reference to the UnifiedArchive object in the engine
-            # data cache to avoid collision with the next checkpoint execution.
-            self._install_engine.doc.volatile.delete_children(
-                class_type=UnifiedArchive)
+
+        # Validate the image at this point to ensure:
+        # - contains one deployable system
+        deployables = ua.getArchivedSystems()
+        if len(deployables) != 1:
+            reason = _("Image must contain only a single deployable system.")
+            raise exception.ImageUnacceptable(image_id=instance['image_ref'],
+                                              reason=reason)
+        # - matching architecture
+        deployable_arch = str(ua.isa)
+        compute_arch = platform.processor()
+        if deployable_arch.lower() != compute_arch:
+            reason = (_("Unified Archive architecture '%s' is incompatible "
+                      "with this compute host's architecture, '%s'.")
+                      % (deployable_arch, compute_arch))
+            raise exception.ImageUnacceptable(image_id=instance['image_ref'],
+                                              reason=reason)
+        # - single root pool only
+        if not deployables[0].rootOnly:
+            reason = _("Image contains more than one ZFS pool.")
+            raise exception.ImageUnacceptable(image_id=instance['image_ref'],
+                                              reason=reason)
+        # - looks like it's OK
+        self._validated_archives.append(instance['image_ref'])
 
     def _suri_from_volume_info(self, connection_info):
         """Returns a suri(5) formatted string based on connection_info
@@ -1356,9 +1331,8 @@
 
         LOG.debug(_("Creating zone configuration for '%s' (%s)")
                   % (name, instance['display_name']))
-        zonemanager = self.rad_connection.get_object(zonemgr.ZoneManager())
         try:
-            zonemanager.create(name, None, template)
+            self._zone_manager.create(name, None, template)
             self._set_global_properties(name, extra_specs, brand)
             if connection_info is not None:
                 self._set_boot_device(name, connection_info, brand)
@@ -1620,9 +1594,8 @@
         if self._get_zone_by_name(name) is None:
             raise exception.InstanceNotFound(instance_id=name)
 
-        zonemanager = self.rad_connection.get_object(zonemgr.ZoneManager())
         try:
-            zonemanager.delete(name)
+            self._zone_manager.delete(name)
         except Exception as ex:
             reason = zonemgr_strerror(ex)
             LOG.error(_("Unable to delete configuration for instance '%s' via "