components/openstack/nova/files/solariszones/driver.py
changeset 5311 92a194d827f0
parent 5279 6c696d36d952
child 5312 b5fa281dd501
equal deleted inserted replaced
5310:a06a01eef195 5311:92a194d827f0
   149 # and what is not supported. A HYPERVISOR_VERSION is defined here for
   149 # and what is not supported. A HYPERVISOR_VERSION is defined here for
   150 # Nova's use but it generally should not be changed unless there is a
   150 # Nova's use but it generally should not be changed unless there is a
   151 # incompatible change such as concerning kernel zone live migration.
   151 # incompatible change such as concerning kernel zone live migration.
   152 HYPERVISOR_VERSION = '5.11'
   152 HYPERVISOR_VERSION = '5.11'
   153 
   153 
       
   154 shared_storage = ['iscsi', 'fibre_channel']
       
   155 
   154 
   156 
   155 def lookup_resource(zone, resource):
   157 def lookup_resource(zone, resource):
   156     """Lookup specified resource from specified Solaris Zone."""
   158     """Lookup specified resource from specified Solaris Zone."""
   157     try:
   159     try:
   158         val = zone.getResources(zonemgr.Resource(resource))
   160         val = zone.getResources(zonemgr.Resource(resource))
   442 
   444 
   443     """
   445     """
   444 
   446 
   445     capabilities = {
   447     capabilities = {
   446         "has_imagecache": False,
   448         "has_imagecache": False,
   447         "supports_recreate": False,
   449         "supports_recreate": True,
   448         }
   450         }
   449 
   451 
   450     def __init__(self, virtapi):
   452     def __init__(self, virtapi):
   451         self.virtapi = virtapi
   453         self.virtapi = virtapi
   452         self._compute_event_callback = None
   454         self._compute_event_callback = None
   788         """Return the UUIDS of all the instances known to the virtualization
   790         """Return the UUIDS of all the instances known to the virtualization
   789         layer, as a list.
   791         layer, as a list.
   790         """
   792         """
   791         raise NotImplementedError()
   793         raise NotImplementedError()
   792 
   794 
       
   795     def _rebuild_block_devices(self, context, instance, bdms, recreate):
       
   796         root_ci = None
       
   797         rootmp = instance['root_device_name']
       
   798         for entry in bdms:
       
   799             if entry['connection_info'] is None:
       
   800                 continue
       
   801 
       
   802             if entry['device_name'] == rootmp:
       
   803                 root_ci = jsonutils.loads(entry['connection_info'])
       
   804                 continue
       
   805 
       
   806             if not recreate:
       
   807                 self._volume_api.detach(context,
       
   808                                         entry['connection_info']['serial'])
       
   809 
       
   810         if root_ci is None:
       
   811             msg = (_("Unable to find the root device for instance %s")
       
   812                    % instance.display_name)
       
   813             raise exception.NovaException(msg)
       
   814 
       
   815         return root_ci
       
   816 
   793     def rebuild(self, context, instance, image_meta, injected_files,
   817     def rebuild(self, context, instance, image_meta, injected_files,
   794                 admin_password, bdms, detach_block_devices,
   818                 admin_password, bdms, detach_block_devices,
   795                 attach_block_devices, network_info=None,
   819                 attach_block_devices, network_info=None,
   796                 recreate=False, block_device_info=None,
   820                 recreate=False, block_device_info=None,
   797                 preserve_ephemeral=False):
   821                 preserve_ephemeral=False):
   828         :param block_device_info: Information about block devices to be
   852         :param block_device_info: Information about block devices to be
   829                                   attached to the instance.
   853                                   attached to the instance.
   830         :param preserve_ephemeral: True if the default ephemeral storage
   854         :param preserve_ephemeral: True if the default ephemeral storage
   831                                    partition must be preserved on rebuild
   855                                    partition must be preserved on rebuild
   832         """
   856         """
   833         raise NotImplementedError()
   857         # rebuild is not supported yet.
       
   858         if not recreate:
       
   859             raise NotImplementedError()
       
   860 
       
   861         extra_specs = self._get_extra_specs(instance)
       
   862         brand = extra_specs.get('zonecfg:brand', ZONE_BRAND_SOLARIS)
       
   863         if recreate and brand == ZONE_BRAND_SOLARIS:
       
   864                 msg = (_("'%s' branded zones do not currently support "
       
   865                          "evacuation.") % brand)
       
   866                 raise exception.NovaException(msg)
       
   867 
       
   868         instance.task_state = task_states.REBUILD_BLOCK_DEVICE_MAPPING
       
   869         instance.save(expected_task_state=[task_states.REBUILDING])
       
   870 
       
   871         root_ci = self._rebuild_block_devices(context, instance, bdms,
       
   872                                               recreate)
       
   873 
       
   874         driver_type = root_ci['driver_volume_type']
       
   875         # If image_meta is provided then the --on-shared-storage option
       
   876         # was not used.
       
   877         if image_meta:
       
   878             # Check to make sure that the root device is actually local.
       
   879             # If not then raise an exception
       
   880             if driver_type in shared_storage:
       
   881                 msg = (_("Root device is on shared storage for instance '%s'")
       
   882                        % instance['name'])
       
   883                 raise exception.NovaException(msg)
       
   884 
       
   885             if recreate:
       
   886                 msg = (_("Evacuate a single host node is not supported"))
       
   887                 raise exception.NovaException(msg)
       
   888         else:
       
   889             # So the root device is not expected to be local so we can move
       
   890             # forward with building the zone.
       
   891             if driver_type not in shared_storage:
       
   892                 msg = (_("Root device is not on shared storage for instance"
       
   893                          "'%s'") % instance['name'])
       
   894                 raise exception.NovaException(msg)
       
   895 
       
   896         instance.task_state = task_states.REBUILD_SPAWNING
       
   897         instance.save(
       
   898             expected_task_state=[task_states.REBUILD_BLOCK_DEVICE_MAPPING])
       
   899         inst_type = flavor_obj.Flavor.get_by_id(
       
   900             nova_context.get_admin_context(read_deleted='yes'),
       
   901             instance['instance_type_id'])
       
   902         extra_specs = inst_type['extra_specs'].copy()
       
   903 
       
   904         self._create_config(context, instance, network_info,
       
   905                             root_ci, extra_specs, None)
       
   906 
       
   907         name = instance['name']
       
   908         zone = self._get_zone_by_name(name)
       
   909         if zone is None:
       
   910             raise exception.InstanceNotFound(instance_id=name)
       
   911 
       
   912         zone.attach(['-x', 'initialize-hostdata'])
       
   913 
       
   914         instance_uuid = instance.uuid
       
   915         rootmp = instance['root_device_name']
       
   916         for entry in bdms:
       
   917             if (entry['connection_info'] is None or
       
   918                     rootmp == entry['device_name']):
       
   919                 continue
       
   920 
       
   921             connection_info = jsonutils.loads(entry['connection_info'])
       
   922             mount = entry['device_name']
       
   923             self.attach_volume(context, connection_info, instance, mount)
       
   924 
       
   925         self._power_on(instance)
   834 
   926 
   835     def _get_extra_specs(self, instance):
   927     def _get_extra_specs(self, instance):
   836         """Retrieve extra_specs of an instance."""
   928         """Retrieve extra_specs of an instance."""
   837         flavor = flavor_obj.Flavor.get_by_id(
   929         flavor = flavor_obj.Flavor.get_by_id(
   838             nova_context.get_admin_context(read_deleted='yes'),
   930             nova_context.get_admin_context(read_deleted='yes'),
  1313         if template is None:
  1405         if template is None:
  1314             msg = (_("Invalid brand '%s' specified for instance '%s'"
  1406             msg = (_("Invalid brand '%s' specified for instance '%s'"
  1315                    % (brand, name)))
  1407                    % (brand, name)))
  1316             raise exception.NovaException(msg)
  1408             raise exception.NovaException(msg)
  1317 
  1409 
       
  1410         # XXX - Adding the REBUILDING task state, but we may want to
       
  1411         # check the sysconfig if the host is completely rebuilding.
  1318         tstate = instance['task_state']
  1412         tstate = instance['task_state']
  1319         if tstate not in [task_states.RESIZE_FINISH,
  1413         if tstate not in [task_states.RESIZE_FINISH,
  1320                           task_states.RESIZE_REVERTING,
  1414                           task_states.RESIZE_REVERTING,
  1321                           task_states.RESIZE_MIGRATING]:
  1415                           task_states.RESIZE_MIGRATING,
       
  1416                           task_states.REBUILD_SPAWNING]:
  1322             sc_profile = extra_specs.get('install:sc_profile')
  1417             sc_profile = extra_specs.get('install:sc_profile')
  1323             if sc_profile is not None:
  1418             if sc_profile is not None:
  1324                 if os.path.isfile(sc_profile):
  1419                 if os.path.isfile(sc_profile):
  1325                     shutil.copy(sc_profile, sc_dir)
  1420                     shutil.copy(sc_profile, sc_dir)
  1326                 elif os.path.isdir(sc_profile):
  1421                 elif os.path.isdir(sc_profile):
  3669 
  3764 
  3670         .. note::
  3765         .. note::
  3671             Used in rebuild for HA implementation and required for validation
  3766             Used in rebuild for HA implementation and required for validation
  3672             of access to instance shared disk files
  3767             of access to instance shared disk files
  3673         """
  3768         """
  3674         return False
  3769         bdmobj = objects.BlockDeviceMappingList
       
  3770         mappings = bdmobj.get_by_instance_uuid(
       
  3771                 nova_context.get_admin_context(),
       
  3772                 instance['uuid'])
       
  3773 
       
  3774         rootmp = instance['root_device_name']
       
  3775         for entry in mappings:
       
  3776             if entry['connection_info'] is None:
       
  3777                 continue
       
  3778 
       
  3779             if entry['device_name'] == rootmp:
       
  3780                 root_ci = jsonutils.loads(entry['connection_info'])
       
  3781                 break
       
  3782 
       
  3783         if root_ci is None:
       
  3784             msg = (_("Unable to find the root device for instance %s",
       
  3785                      instance.display_name))
       
  3786             raise exception.NovaException(msg)
       
  3787 
       
  3788         driver_type = root_ci['driver_volume_type']
       
  3789         if driver_type in shared_storage:
       
  3790             return True
       
  3791         else:
       
  3792             return False
  3675 
  3793 
  3676     def register_event_listener(self, callback):
  3794     def register_event_listener(self, callback):
  3677         """Register a callback to receive events.
  3795         """Register a callback to receive events.
  3678 
  3796 
  3679         Register a callback to receive asynchronous event
  3797         Register a callback to receive asynchronous event