# HG changeset patch # User david.comay@oracle.com # Date 1452820073 28800 # Node ID 6c696d36d9528387be7d99c9c22aba1e42e430b2 # Parent 3ae19990a6f8a530e10caf9b0caafc1ba005be28 22471983 Nova's archive logic should account for archive RAD changes diff -r 3ae19990a6f8 -r 6c696d36d952 components/openstack/nova/files/solariszones/driver.py --- 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 " diff -r 3ae19990a6f8 -r 6c696d36d952 components/openstack/nova/nova.p5m --- a/components/openstack/nova/nova.p5m Thu Jan 14 11:26:28 2016 -0800 +++ b/components/openstack/nova/nova.p5m Thu Jan 14 17:07:53 2016 -0800 @@ -20,7 +20,7 @@ # # -# Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. # set name=pkg.fmri \ @@ -1022,6 +1022,9 @@ # force a dependency on rad-python; pkgdepend work is needed to flush this out. depend type=require fmri=system/management/rad/client/rad-python +# force a dependency on rad-archivemgr +depend type=require fmri=system/management/rad/module/rad-archivemgr + # force a dependency on rad-kstat depend type=require fmri=system/management/rad/module/rad-kstat