Best Python code snippet using autotest_python
manager.py
Source:manager.py  
...345    instances.346    """347    @functools.wraps(function)348    def decorated_function(self, context, *args, **kwargs):349        def _load_instance(instance_or_dict):350            if isinstance(instance_or_dict, dict):351                instance = objects.Instance._from_db_object(352                    context, objects.Instance(), instance_or_dict,353                    expected_attrs=metas)354                instance._context = context355                return instance356            return instance_or_dict357        metas = ['metadata', 'system_metadata']358        try:359            kwargs['instance'] = _load_instance(kwargs['instance'])360        except KeyError:361            args = (_load_instance(args[0]),) + args[1:]362        migration = kwargs.get('migration')363        if isinstance(migration, dict):364            migration = objects.Migration._from_db_object(365                    context.elevated(), objects.Migration(),366                    migration)367            kwargs['migration'] = migration368        return function(self, context, *args, **kwargs)369    return decorated_function370# TODO(danms): Remove me after Icehouse371def aggregate_object_compat(function):372    """Wraps a method that expects a new-world aggregate."""373    @functools.wraps(function)374    def decorated_function(self, context, *args, **kwargs):375        aggregate = kwargs.get('aggregate')376        if isinstance(aggregate, dict):377            aggregate = objects.Aggregate._from_db_object(378                context.elevated(), objects.Aggregate(),379                aggregate)380            kwargs['aggregate'] = aggregate381        return function(self, context, *args, **kwargs)382    return decorated_function383class InstanceEvents(object):384    def __init__(self):385        self._events = {}386    @staticmethod387    def _lock_name(instance):388        return '%s-%s' % (instance.uuid, 'events')389    def prepare_for_instance_event(self, instance, event_name):390        """Prepare to receive an event for an instance.391        This will register an event for the given instance that we will392        wait on later. This should be called before initiating whatever393        action will trigger the event. The resulting eventlet.event.Event394        object should be wait()'d on to ensure completion.395        :param instance: the instance for which the event will be generated396        :param event_name: the name of the event we're expecting397        :returns: an event object that should be wait()'d on398        """399        @utils.synchronized(self._lock_name(instance))400        def _create_or_get_event():401            if instance.uuid not in self._events:402                self._events.setdefault(instance.uuid, {})403            return self._events[instance.uuid].setdefault(404                event_name, eventlet.event.Event())405        LOG.debug('Preparing to wait for external event %(event)s',406                  {'event': event_name}, instance=instance)407        return _create_or_get_event()408    def pop_instance_event(self, instance, event):409        """Remove a pending event from the wait list.410        This will remove a pending event from the wait list so that it411        can be used to signal the waiters to wake up.412        :param instance: the instance for which the event was generated413        :param event: the nova.objects.external_event.InstanceExternalEvent414                      that describes the event415        :returns: the eventlet.event.Event object on which the waiters416                  are blocked417        """418        no_events_sentinel = object()419        no_matching_event_sentinel = object()420        @utils.synchronized(self._lock_name(instance))421        def _pop_event():422            events = self._events.get(instance.uuid)423            if not events:424                return no_events_sentinel425            _event = events.pop(event.key, None)426            if not events:427                del self._events[instance.uuid]428            if _event is None:429                return no_matching_event_sentinel430            return _event431        result = _pop_event()432        if result == no_events_sentinel:433            LOG.debug('No waiting events found dispatching %(event)s',434                      {'event': event.key},435                      instance=instance)436            return None437        elif result == no_matching_event_sentinel:438            LOG.debug('No event matching %(event)s in %(events)s',439                      {'event': event.key,440                       'events': self._events.get(instance.uuid, {}).keys()},441                      instance=instance)442            return None443        else:444            return result445    def clear_events_for_instance(self, instance):446        """Remove all pending events for an instance.447        This will remove all events currently pending for an instance448        and return them (indexed by event name).449        :param instance: the instance for which events should be purged450        :returns: a dictionary of {event_name: eventlet.event.Event}451        """452        @utils.synchronized(self._lock_name(instance))453        def _clear_events():454            # NOTE(danms): Use getitem syntax for the instance until455            # all the callers are using objects456            return self._events.pop(instance['uuid'], {})457        return _clear_events()458class ComputeVirtAPI(virtapi.VirtAPI):459    def __init__(self, compute):460        super(ComputeVirtAPI, self).__init__()461        self._compute = compute462    def provider_fw_rule_get_all(self, context):463        return self._compute.conductor_api.provider_fw_rule_get_all(context)464    def _default_error_callback(self, event_name, instance):465        raise exception.NovaException(_('Instance event failed'))466    @contextlib.contextmanager467    def wait_for_instance_event(self, instance, event_names, deadline=300,468                                error_callback=None):469        """Plan to wait for some events, run some code, then wait.470        This context manager will first create plans to wait for the471        provided event_names, yield, and then wait for all the scheduled472        events to complete.473        Note that this uses an eventlet.timeout.Timeout to bound the474        operation, so callers should be prepared to catch that475        failure and handle that situation appropriately.476        If the event is not received by the specified timeout deadline,477        eventlet.timeout.Timeout is raised.478        If the event is received but did not have a 'completed'479        status, a NovaException is raised.  If an error_callback is480        provided, instead of raising an exception as detailed above481        for the failure case, the callback will be called with the482        event_name and instance, and can return True to continue483        waiting for the rest of the events, False to stop processing,484        or raise an exception which will bubble up to the waiter.485        :param instance: The instance for which an event is expected486        :param event_names: A list of event names. Each element can be a487                            string event name or tuple of strings to488                            indicate (name, tag).489        :param deadline: Maximum number of seconds we should wait for all490                         of the specified events to arrive.491        :param error_callback: A function to be called if an event arrives492        """493        if error_callback is None:494            error_callback = self._default_error_callback495        events = {}496        for event_name in event_names:497            if isinstance(event_name, tuple):498                name, tag = event_name499                event_name = objects.InstanceExternalEvent.make_key(500                    name, tag)501            events[event_name] = (502                self._compute.instance_events.prepare_for_instance_event(503                    instance, event_name))504        yield505        with eventlet.timeout.Timeout(deadline):506            for event_name, event in events.items():507                actual_event = event.wait()508                if actual_event.status == 'completed':509                    continue510                decision = error_callback(event_name, instance)511                if decision is False:512                    break513class ComputeManager(manager.Manager):514    """Manages the running instances from creation to destruction."""515    target = messaging.Target(version='3.34')516    # How long to wait in seconds before re-issuing a shutdown517    # signal to a instance during power off.  The overall518    # time to wait is set by CONF.shutdown_timeout.519    SHUTDOWN_RETRY_INTERVAL = 10520    def __init__(self, compute_driver=None, *args, **kwargs):521        """Load configuration options and connect to the hypervisor."""522        self.virtapi = ComputeVirtAPI(self)523        self.network_api = network.API()524        self.volume_api = volume.API()525        self.image_api = image.API()526        self._last_host_check = 0527        self._last_bw_usage_poll = 0528        self._bw_usage_supported = True529        self._last_bw_usage_cell_update = 0530        self.compute_api = compute.API()531        self.compute_rpcapi = compute_rpcapi.ComputeAPI()532        self.conductor_api = conductor.API()533        self.compute_task_api = conductor.ComputeTaskAPI()534        self.is_neutron_security_groups = (535            openstack_driver.is_neutron_security_groups())536        self.consoleauth_rpcapi = consoleauth.rpcapi.ConsoleAuthAPI()537        self.cells_rpcapi = cells_rpcapi.CellsAPI()538        self.scheduler_rpcapi = scheduler_rpcapi.SchedulerAPI()539        self._resource_tracker_dict = {}540        self.instance_events = InstanceEvents()541        self._sync_power_pool = eventlet.GreenPool()542        self._syncs_in_progress = {}543        super(ComputeManager, self).__init__(service_name="compute",544                                             *args, **kwargs)545        # NOTE(russellb) Load the driver last.  It may call back into the546        # compute manager via the virtapi, so we want it to be fully547        # initialized before that happens.548        self.driver = driver.load_compute_driver(self.virtapi, compute_driver)549        self.use_legacy_block_device_info = \550                            self.driver.need_legacy_block_device_info551    def _get_resource_tracker(self, nodename):552        rt = self._resource_tracker_dict.get(nodename)553        if not rt:554            if not self.driver.node_is_available(nodename):555                raise exception.NovaException(556                        _("%s is not a valid node managed by this "557                          "compute host.") % nodename)558            rt = resource_tracker.ResourceTracker(self.host,559                                                  self.driver,560                                                  nodename)561            self._resource_tracker_dict[nodename] = rt562        return rt563    def _update_resource_tracker(self, context, instance):564        """Let the resource tracker know that an instance has changed state."""565        if (instance['host'] == self.host and566                self.driver.node_is_available(instance['node'])):567            rt = self._get_resource_tracker(instance.get('node'))568            rt.update_usage(context, instance)569    def _instance_update(self, context, instance_uuid, **kwargs):570        """Update an instance in the database using kwargs as value."""571        instance_ref = self.conductor_api.instance_update(context,572                                                          instance_uuid,573                                                          **kwargs)574        self._update_resource_tracker(context, instance_ref)575        return instance_ref576    def _set_instance_error_state(self, context, instance):577        instance_uuid = instance['uuid']578        try:579            self._instance_update(context, instance_uuid,580                                  vm_state=vm_states.ERROR)581        except exception.InstanceNotFound:582            LOG.debug('Instance has been destroyed from under us while '583                      'trying to set it to ERROR',584                      instance_uuid=instance_uuid)585    def _set_instance_obj_error_state(self, context, instance):586        try:587            instance.vm_state = vm_states.ERROR588            instance.save()589        except exception.InstanceNotFound:590            LOG.debug('Instance has been destroyed from under us while '591                      'trying to set it to ERROR', instance=instance)592    def _get_instances_on_driver(self, context, filters=None):593        """Return a list of instance records for the instances found594        on the hypervisor which satisfy the specified filters. If filters=None595        return a list of instance records for all the instances found on the596        hypervisor.597        """598        if not filters:599            filters = {}600        try:601            driver_uuids = self.driver.list_instance_uuids()602            filters['uuid'] = driver_uuids603            local_instances = objects.InstanceList.get_by_filters(604                context, filters, use_slave=True)605            return local_instances606        except NotImplementedError:607            pass608        # The driver doesn't support uuids listing, so we'll have609        # to brute force.610        driver_instances = self.driver.list_instances()611        instances = objects.InstanceList.get_by_filters(context, filters,612                                                        use_slave=True)613        name_map = dict((instance.name, instance) for instance in instances)614        local_instances = []615        for driver_instance in driver_instances:616            instance = name_map.get(driver_instance)617            if not instance:618                continue619            local_instances.append(instance)620        return local_instances621    def _destroy_evacuated_instances(self, context):622        """Destroys evacuated instances.623        While nova-compute was down, the instances running on it could be624        evacuated to another host. Check that the instances reported625        by the driver are still associated with this host.  If they are626        not, destroy them, with the exception of instances which are in627        the MIGRATING, RESIZE_MIGRATING, RESIZE_MIGRATED, RESIZE_FINISH628        task state or RESIZED vm state.629        """630        our_host = self.host631        filters = {'deleted': False}632        local_instances = self._get_instances_on_driver(context, filters)633        for instance in local_instances:634            if instance.host != our_host:635                if (instance.task_state in [task_states.MIGRATING,636                                            task_states.RESIZE_MIGRATING,637                                            task_states.RESIZE_MIGRATED,638                                            task_states.RESIZE_FINISH]639                    or instance.vm_state in [vm_states.RESIZED]):640                    LOG.debug('Will not delete instance as its host ('641                              '%(instance_host)s) is not equal to our '642                              'host (%(our_host)s) but its task state is '643                              '(%(task_state)s) and vm state is '644                              '(%(vm_state)s)',645                              {'instance_host': instance.host,646                               'our_host': our_host,647                               'task_state': instance.task_state,648                               'vm_state': instance.vm_state},649                              instance=instance)650                    continue651                LOG.info(_('Deleting instance as its host ('652                           '%(instance_host)s) is not equal to our '653                           'host (%(our_host)s).'),654                         {'instance_host': instance.host,655                          'our_host': our_host}, instance=instance)656                try:657                    network_info = self._get_instance_nw_info(context,658                                                              instance)659                    bdi = self._get_instance_block_device_info(context,660                                                               instance)661                    destroy_disks = not (self._is_instance_storage_shared(662                                                            context, instance))663                except exception.InstanceNotFound:664                    network_info = network_model.NetworkInfo()665                    bdi = {}666                    LOG.info(_('Instance has been marked deleted already, '667                               'removing it from the hypervisor.'),668                             instance=instance)669                    # always destroy disks if the instance was deleted670                    destroy_disks = True671                self.driver.destroy(context, instance,672                                    network_info,673                                    bdi, destroy_disks)674    def _is_instance_storage_shared(self, context, instance):675        shared_storage = True676        data = None677        try:678            data = self.driver.check_instance_shared_storage_local(context,679                                                       instance)680            if data:681                shared_storage = (self.compute_rpcapi.682                                  check_instance_shared_storage(context,683                                  instance, data))684        except NotImplementedError:685            LOG.warning(_('Hypervisor driver does not support '686                          'instance shared storage check, '687                          'assuming it\'s not on shared storage'),688                        instance=instance)689            shared_storage = False690        except Exception:691            LOG.exception(_LE('Failed to check if instance shared'),692                      instance=instance)693        finally:694            if data:695                self.driver.check_instance_shared_storage_cleanup(context,696                                                                  data)697        return shared_storage698    def _complete_partial_deletion(self, context, instance):699        """Complete deletion for instances in DELETED status but not marked as700        deleted in the DB701        """702        instance.destroy()703        bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(704                context, instance.uuid)705        quotas = objects.Quotas(context)706        project_id, user_id = quotas_obj.ids_from_instance(context, instance)707        quotas.reserve(context, project_id=project_id, user_id=user_id,708                       instances=-1, cores=-instance.vcpus,709                       ram=-instance.memory_mb)710        self._complete_deletion(context,711                                instance,712                                bdms,713                                quotas,714                                instance.system_metadata)715    def _complete_deletion(self, context, instance, bdms,716                           quotas, system_meta):717        if quotas:718            quotas.commit()719        # ensure block device mappings are not leaked720        for bdm in bdms:721            bdm.destroy()722        self._notify_about_instance_usage(context, instance, "delete.end",723                system_metadata=system_meta)724        if CONF.vnc_enabled or CONF.spice.enabled:725            if CONF.cells.enable:726                self.cells_rpcapi.consoleauth_delete_tokens(context,727                        instance.uuid)728            else:729                self.consoleauth_rpcapi.delete_tokens_for_instance(context,730                        instance.uuid)731    def _init_instance(self, context, instance):732        '''Initialize this instance during service init.'''733        # Instances that are shut down, or in an error state can not be734        # initialized and are not attempted to be recovered. The exception735        # to this are instances that are in RESIZE_MIGRATING or DELETING,736        # which are dealt with further down.737        if (instance.vm_state == vm_states.SOFT_DELETED or738            (instance.vm_state == vm_states.ERROR and739            instance.task_state not in740            (task_states.RESIZE_MIGRATING, task_states.DELETING))):741            LOG.debug("Instance is in %s state.",742                      instance.vm_state, instance=instance)743            return744        if instance.vm_state == vm_states.DELETED:745            try:746                self._complete_partial_deletion(context, instance)747            except Exception:748                # we don't want that an exception blocks the init_host749                msg = _LE('Failed to complete a deletion')750                LOG.exception(msg, instance=instance)751            return752        if (instance.vm_state == vm_states.BUILDING or753            instance.task_state in [task_states.SCHEDULING,754                                    task_states.BLOCK_DEVICE_MAPPING,755                                    task_states.NETWORKING,756                                    task_states.SPAWNING]):757            # NOTE(dave-mcnally) compute stopped before instance was fully758            # spawned so set to ERROR state. This is safe to do as the state759            # may be set by the api but the host is not so if we get here the760            # instance has already been scheduled to this particular host.761            LOG.debug("Instance failed to spawn correctly, "762                      "setting to ERROR state", instance=instance)763            instance.task_state = None764            instance.vm_state = vm_states.ERROR765            instance.save()766            return767        if (instance.vm_state in [vm_states.ACTIVE, vm_states.STOPPED] and768            instance.task_state in [task_states.REBUILDING,769                                    task_states.REBUILD_BLOCK_DEVICE_MAPPING,770                                    task_states.REBUILD_SPAWNING]):771            # NOTE(jichenjc) compute stopped before instance was fully772            # spawned so set to ERROR state. This is consistent to BUILD773            LOG.debug("Instance failed to rebuild correctly, "774                      "setting to ERROR state", instance=instance)775            instance.task_state = None776            instance.vm_state = vm_states.ERROR777            instance.save()778            return779        if (instance.vm_state != vm_states.ERROR and780            instance.task_state in [task_states.IMAGE_SNAPSHOT_PENDING,781                                    task_states.IMAGE_PENDING_UPLOAD,782                                    task_states.IMAGE_UPLOADING,783                                    task_states.IMAGE_SNAPSHOT]):784            LOG.debug("Instance in transitional state %s at start-up "785                      "clearing task state",786                      instance['task_state'], instance=instance)787            try:788                self._post_interrupted_snapshot_cleanup(context, instance)789            except Exception:790                # we don't want that an exception blocks the init_host791                msg = _LE('Failed to cleanup snapshot.')792                LOG.exception(msg, instance=instance)793            instance.task_state = None794            instance.save()795        if instance.task_state == task_states.DELETING:796            try:797                LOG.info(_('Service started deleting the instance during '798                           'the previous run, but did not finish. Restarting '799                           'the deletion now.'), instance=instance)800                instance.obj_load_attr('metadata')801                instance.obj_load_attr('system_metadata')802                bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(803                        context, instance.uuid)804                # FIXME(comstud): This needs fixed. We should be creating805                # reservations and updating quotas, because quotas806                # wouldn't have been updated for this instance since it is807                # still in DELETING.  See bug 1296414.808                #809                # Create a dummy quota object for now.810                quotas = objects.Quotas.from_reservations(811                        context, None, instance=instance)812                self._delete_instance(context, instance, bdms, quotas)813            except Exception:814                # we don't want that an exception blocks the init_host815                msg = _LE('Failed to complete a deletion')816                LOG.exception(msg, instance=instance)817                self._set_instance_error_state(context, instance)818            return819        try_reboot, reboot_type = self._retry_reboot(context, instance)820        current_power_state = self._get_power_state(context, instance)821        if try_reboot:822            LOG.debug("Instance in transitional state (%(task_state)s) at "823                      "start-up and power state is (%(power_state)s), "824                      "triggering reboot",825                      {'task_state': instance['task_state'],826                       'power_state': current_power_state},827                      instance=instance)828            self.compute_rpcapi.reboot_instance(context, instance,829                                                block_device_info=None,830                                                reboot_type=reboot_type)831            return832        elif (current_power_state == power_state.RUNNING and833           instance.task_state in [task_states.REBOOT_STARTED,834                                   task_states.REBOOT_STARTED_HARD]):835            LOG.warning(_("Instance in transitional state "836                          "(%(task_state)s) at start-up and power state "837                          "is (%(power_state)s), clearing task state"),838                        {'task_state': instance['task_state'],839                         'power_state': current_power_state},840                        instance=instance)841            instance.task_state = None842            instance.vm_state = vm_states.ACTIVE843            instance.save()844        if instance.task_state == task_states.POWERING_OFF:845            try:846                LOG.debug("Instance in transitional state %s at start-up "847                          "retrying stop request",848                          instance['task_state'], instance=instance)849                self.stop_instance(context, instance)850            except Exception:851                # we don't want that an exception blocks the init_host852                msg = _LE('Failed to stop instance')853                LOG.exception(msg, instance=instance)854            return855        if instance.task_state == task_states.POWERING_ON:856            try:857                LOG.debug("Instance in transitional state %s at start-up "858                          "retrying start request",859                          instance['task_state'], instance=instance)860                self.start_instance(context, instance)861            except Exception:862                # we don't want that an exception blocks the init_host863                msg = _LE('Failed to start instance')864                LOG.exception(msg, instance=instance)865            return866        net_info = compute_utils.get_nw_info_for_instance(instance)867        try:868            self.driver.plug_vifs(instance, net_info)869        except NotImplementedError as e:870            LOG.debug(e, instance=instance)871        if instance.task_state == task_states.RESIZE_MIGRATING:872            # We crashed during resize/migration, so roll back for safety873            try:874                # NOTE(mriedem): check old_vm_state for STOPPED here, if it's875                # not in system_metadata we default to True for backwards876                # compatibility877                power_on = (instance.system_metadata.get('old_vm_state') !=878                            vm_states.STOPPED)879                block_dev_info = self._get_instance_block_device_info(context,880                                                                      instance)881                self.driver.finish_revert_migration(context,882                    instance, net_info, block_dev_info, power_on)883            except Exception as e:884                LOG.exception(_LE('Failed to revert crashed migration'),885                              instance=instance)886            finally:887                LOG.info(_('Instance found in migrating state during '888                           'startup. Resetting task_state'),889                         instance=instance)890                instance.task_state = None891                instance.save()892        if instance.task_state == task_states.MIGRATING:893            # Live migration did not complete, but instance is on this894            # host, so reset the state.895            instance.task_state = None896            instance.save(expected_task_state=[task_states.MIGRATING])897        db_state = instance.power_state898        drv_state = self._get_power_state(context, instance)899        expect_running = (db_state == power_state.RUNNING and900                          drv_state != db_state)901        LOG.debug('Current state is %(drv_state)s, state in DB is '902                  '%(db_state)s.',903                  {'drv_state': drv_state, 'db_state': db_state},904                  instance=instance)905        if expect_running and CONF.resume_guests_state_on_host_boot:906            LOG.info(_('Rebooting instance after nova-compute restart.'),907                     instance=instance)908            block_device_info = \909                self._get_instance_block_device_info(context, instance)910            try:911                self.driver.resume_state_on_host_boot(912                    context, instance, net_info, block_device_info)913            except NotImplementedError:914                LOG.warning(_('Hypervisor driver does not support '915                              'resume guests'), instance=instance)916            except Exception:917                # NOTE(vish): The instance failed to resume, so we set the918                #             instance to error and attempt to continue.919                LOG.warning(_('Failed to resume instance'), instance=instance)920                self._set_instance_error_state(context, instance)921        elif drv_state == power_state.RUNNING:922            # VMwareAPI drivers will raise an exception923            try:924                self.driver.ensure_filtering_rules_for_instance(925                                       instance, net_info)926            except NotImplementedError:927                LOG.warning(_('Hypervisor driver does not support '928                              'firewall rules'), instance=instance)929    def _retry_reboot(self, context, instance):930        current_power_state = self._get_power_state(context, instance)931        current_task_state = instance.task_state932        retry_reboot = False933        reboot_type = compute_utils.get_reboot_type(current_task_state,934                                                    current_power_state)935        pending_soft = (current_task_state == task_states.REBOOT_PENDING and936                        instance.vm_state in vm_states.ALLOW_SOFT_REBOOT)937        pending_hard = (current_task_state == task_states.REBOOT_PENDING_HARD938                        and instance.vm_state in vm_states.ALLOW_HARD_REBOOT)939        started_not_running = (current_task_state in940                               [task_states.REBOOT_STARTED,941                                task_states.REBOOT_STARTED_HARD] and942                               current_power_state != power_state.RUNNING)943        if pending_soft or pending_hard or started_not_running:944            retry_reboot = True945        return retry_reboot, reboot_type946    def handle_lifecycle_event(self, event):947        LOG.info(_("VM %(state)s (Lifecycle Event)") %948                  {'state': event.get_name()},949                 instance_uuid=event.get_instance_uuid())950        context = nova.context.get_admin_context(read_deleted='yes')951        instance = objects.Instance.get_by_uuid(context,952                                                event.get_instance_uuid())953        vm_power_state = None954        if event.get_transition() == virtevent.EVENT_LIFECYCLE_STOPPED:955            vm_power_state = power_state.SHUTDOWN956        elif event.get_transition() == virtevent.EVENT_LIFECYCLE_STARTED:957            vm_power_state = power_state.RUNNING958        elif event.get_transition() == virtevent.EVENT_LIFECYCLE_PAUSED:959            vm_power_state = power_state.PAUSED960        elif event.get_transition() == virtevent.EVENT_LIFECYCLE_RESUMED:961            vm_power_state = power_state.RUNNING962        else:963            LOG.warning(_("Unexpected power state %d") %964                        event.get_transition())965        if vm_power_state is not None:966            LOG.debug('Synchronizing instance power state after lifecycle '967                      'event "%(event)s"; current vm_state: %(vm_state)s, '968                      'current task_state: %(task_state)s, current DB '969                      'power_state: %(db_power_state)s, VM power_state: '970                      '%(vm_power_state)s',971                      dict(event=event.get_name(),972                           vm_state=instance.vm_state,973                           task_state=instance.task_state,974                           db_power_state=instance.power_state,975                           vm_power_state=vm_power_state),976                      instance_uuid=instance.uuid)977            self._sync_instance_power_state(context,978                                            instance,979                                            vm_power_state)980    def handle_events(self, event):981        if isinstance(event, virtevent.LifecycleEvent):982            try:983                self.handle_lifecycle_event(event)984            except exception.InstanceNotFound:985                LOG.debug("Event %s arrived for non-existent instance. The "986                          "instance was probably deleted.", event)987        else:988            LOG.debug("Ignoring event %s", event)989    def init_virt_events(self):990        self.driver.register_event_listener(self.handle_events)991    def init_host(self):992        """Initialization for a standalone compute service."""993        self.driver.init_host(host=self.host)994        context = nova.context.get_admin_context()995        instances = objects.InstanceList.get_by_host(996            context, self.host, expected_attrs=['info_cache'])997        if CONF.defer_iptables_apply:998            self.driver.filter_defer_apply_on()999        self.init_virt_events()1000        try:1001            # checking that instance was not already evacuated to other host1002            self._destroy_evacuated_instances(context)1003            for instance in instances:1004                self._init_instance(context, instance)1005        finally:1006            if CONF.defer_iptables_apply:1007                self.driver.filter_defer_apply_off()1008    def cleanup_host(self):1009        self.driver.cleanup_host(host=self.host)1010    def pre_start_hook(self):1011        """After the service is initialized, but before we fully bring1012        the service up by listening on RPC queues, make sure to update1013        our available resources (and indirectly our available nodes).1014        """1015        self.update_available_resource(nova.context.get_admin_context())1016    def _get_power_state(self, context, instance):1017        """Retrieve the power state for the given instance."""1018        LOG.debug('Checking state', instance=instance)1019        try:1020            return self.driver.get_info(instance)["state"]1021        except exception.NotFound:1022            return power_state.NOSTATE1023    def get_console_topic(self, context):1024        """Retrieves the console host for a project on this host.1025        Currently this is just set in the flags for each compute host.1026        """1027        # TODO(mdragon): perhaps make this variable by console_type?1028        return '%s.%s' % (CONF.console_topic, CONF.console_host)1029    def get_console_pool_info(self, context, console_type):1030        return self.driver.get_console_pool_info(console_type)1031    @wrap_exception()1032    def refresh_security_group_rules(self, context, security_group_id):1033        """Tell the virtualization driver to refresh security group rules.1034        Passes straight through to the virtualization driver.1035        """1036        return self.driver.refresh_security_group_rules(security_group_id)1037    @wrap_exception()1038    def refresh_security_group_members(self, context, security_group_id):1039        """Tell the virtualization driver to refresh security group members.1040        Passes straight through to the virtualization driver.1041        """1042        return self.driver.refresh_security_group_members(security_group_id)1043    @wrap_exception()1044    def refresh_instance_security_rules(self, context, instance):1045        """Tell the virtualization driver to refresh security rules for1046        an instance.1047        Passes straight through to the virtualization driver.1048        Synchronise the call because we may still be in the middle of1049        creating the instance.1050        """1051        @utils.synchronized(instance['uuid'])1052        def _sync_refresh():1053            try:1054                return self.driver.refresh_instance_security_rules(instance)1055            except NotImplementedError:1056                LOG.warning(_('Hypervisor driver does not support '1057                              'security groups.'), instance=instance)1058        return _sync_refresh()1059    @wrap_exception()1060    def refresh_provider_fw_rules(self, context):1061        """This call passes straight through to the virtualization driver."""1062        return self.driver.refresh_provider_fw_rules()1063    def _get_instance_nw_info(self, context, instance, use_slave=False):1064        """Get a list of dictionaries of network data of an instance."""1065        if (not hasattr(instance, 'system_metadata') or1066                len(instance['system_metadata']) == 0):1067            # NOTE(danms): Several places in the code look up instances without1068            # pulling system_metadata for performance, and call this function.1069            # If we get an instance without it, re-fetch so that the call1070            # to network_api (which requires it for instance_type) will1071            # succeed.1072            instance = objects.Instance.get_by_uuid(context,1073                                                    instance['uuid'],1074                                                    use_slave=use_slave)1075        network_info = self.network_api.get_instance_nw_info(context,1076                                                             instance)1077        return network_info1078    def _await_block_device_map_created(self, context, vol_id):1079        # TODO(yamahata): creating volume simultaneously1080        #                 reduces creation time?1081        # TODO(yamahata): eliminate dumb polling1082        start = time.time()1083        retries = CONF.block_device_allocate_retries1084        if retries < 0:1085            LOG.warn(_LW("Treating negative config value (%(retries)s) for "1086                         "'block_device_retries' as 0."),1087                     {'retries': retries})1088        # (1) treat  negative config value as 01089        # (2) the configured value is 0, one attempt should be made1090        # (3) the configured value is > 0, then the total number attempts1091        #      is (retries + 1)1092        attempts = 11093        if retries >= 1:1094            attempts = retries + 11095        for attempt in range(1, attempts + 1):1096            volume = self.volume_api.get(context, vol_id)1097            volume_status = volume['status']1098            if volume_status not in ['creating', 'downloading']:1099                if volume_status != 'available':1100                    LOG.warn(_("Volume id: %s finished being created but was"1101                               " not set as 'available'"), vol_id)1102                return attempt1103            greenthread.sleep(CONF.block_device_allocate_retries_interval)1104        # NOTE(harlowja): Should only happen if we ran out of attempts1105        raise exception.VolumeNotCreated(volume_id=vol_id,1106                                         seconds=int(time.time() - start),1107                                         attempts=attempts)1108    def _decode_files(self, injected_files):1109        """Base64 decode the list of files to inject."""1110        if not injected_files:1111            return []1112        def _decode(f):1113            path, contents = f1114            try:1115                decoded = base64.b64decode(contents)1116                return path, decoded1117            except TypeError:1118                raise exception.Base64Exception(path=path)1119        return [_decode(f) for f in injected_files]1120    def _run_instance(self, context, request_spec,1121                      filter_properties, requested_networks, injected_files,1122                      admin_password, is_first_time, node, instance,1123                      legacy_bdm_in_spec):1124        """Launch a new instance with specified options."""1125        extra_usage_info = {}1126        def notify(status, msg="", fault=None, **kwargs):1127            """Send a create.{start,error,end} notification."""1128            type_ = "create.%(status)s" % dict(status=status)1129            info = extra_usage_info.copy()1130            info['message'] = msg1131            self._notify_about_instance_usage(context, instance, type_,1132                    extra_usage_info=info, fault=fault, **kwargs)1133        try:1134            self._prebuild_instance(context, instance)1135            if request_spec and request_spec.get('image'):1136                image_meta = request_spec['image']1137            else:1138                image_meta = {}1139            extra_usage_info = {"image_name": image_meta.get('name', '')}1140            notify("start")  # notify that build is starting1141            instance, network_info = self._build_instance(context,1142                    request_spec, filter_properties, requested_networks,1143                    injected_files, admin_password, is_first_time, node,1144                    instance, image_meta, legacy_bdm_in_spec)1145            notify("end", msg=_("Success"), network_info=network_info)1146        except exception.RescheduledException as e:1147            # Instance build encountered an error, and has been rescheduled.1148            notify("error", fault=e)1149        except exception.BuildAbortException as e:1150            # Instance build aborted due to a non-failure1151            LOG.info(e)1152            notify("end", msg=e.format_message())  # notify that build is done1153        except Exception as e:1154            # Instance build encountered a non-recoverable error:1155            with excutils.save_and_reraise_exception():1156                self._set_instance_error_state(context, instance)1157                notify("error", fault=e)  # notify that build failed1158    def _prebuild_instance(self, context, instance):1159        self._check_instance_exists(context, instance)1160        try:1161            self._start_building(context, instance)1162        except (exception.InstanceNotFound,1163                exception.UnexpectedDeletingTaskStateError):1164            msg = _("Instance disappeared before we could start it")1165            # Quickly bail out of here1166            raise exception.BuildAbortException(instance_uuid=instance.uuid,1167                    reason=msg)1168    def _validate_instance_group_policy(self, context, instance,1169            filter_properties):1170        # NOTE(russellb) Instance group policy is enforced by the scheduler.1171        # However, there is a race condition with the enforcement of1172        # anti-affinity.  Since more than one instance may be scheduled at the1173        # same time, it's possible that more than one instance with an1174        # anti-affinity policy may end up here.  This is a validation step to1175        # make sure that starting the instance here doesn't violate the policy.1176        scheduler_hints = filter_properties.get('scheduler_hints') or {}1177        group_hint = scheduler_hints.get('group')1178        if not group_hint:1179            return1180        @utils.synchronized(group_hint)1181        def _do_validation(context, instance, group_hint):1182            group = objects.InstanceGroup.get_by_hint(context, group_hint)1183            if 'anti-affinity' not in group.policies:1184                return1185            group_hosts = group.get_hosts(context, exclude=[instance.uuid])1186            if self.host in group_hosts:1187                msg = _("Anti-affinity instance group policy was violated.")1188                raise exception.RescheduledException(1189                        instance_uuid=instance.uuid,1190                        reason=msg)1191        _do_validation(context, instance, group_hint)1192    def _build_instance(self, context, request_spec, filter_properties,1193            requested_networks, injected_files, admin_password, is_first_time,1194            node, instance, image_meta, legacy_bdm_in_spec):1195        original_context = context1196        context = context.elevated()1197        # NOTE(danms): This method is deprecated, but could be called,1198        # and if it is, it will have an old megatuple for requested_networks.1199        if requested_networks is not None:1200            requested_networks_obj = objects.NetworkRequestList(1201                objects=[objects.NetworkRequest.from_tuple(t)1202                         for t in requested_networks])1203        else:1204            requested_networks_obj = None1205        # If neutron security groups pass requested security1206        # groups to allocate_for_instance()1207        if request_spec and self.is_neutron_security_groups:1208            security_groups = request_spec.get('security_group')1209        else:1210            security_groups = []1211        if node is None:1212            node = self.driver.get_available_nodes(refresh=True)[0]1213            LOG.debug("No node specified, defaulting to %s", node)1214        network_info = None1215        bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(1216                context, instance.uuid)1217        # b64 decode the files to inject:1218        injected_files_orig = injected_files1219        injected_files = self._decode_files(injected_files)1220        rt = self._get_resource_tracker(node)1221        try:1222            limits = filter_properties.get('limits', {})1223            with rt.instance_claim(context, instance, limits):1224                # NOTE(russellb) It's important that this validation be done1225                # *after* the resource tracker instance claim, as that is where1226                # the host is set on the instance.1227                self._validate_instance_group_policy(context, instance,1228                        filter_properties)1229                macs = self.driver.macs_for_instance(instance)1230                dhcp_options = self.driver.dhcp_options_for_instance(instance)1231                network_info = self._allocate_network(original_context,1232                        instance, requested_networks_obj, macs,1233                        security_groups, dhcp_options)1234                instance.vm_state = vm_states.BUILDING1235                instance.task_state = task_states.BLOCK_DEVICE_MAPPING1236                instance.save()1237                # Verify that all the BDMs have a device_name set and assign a1238                # default to the ones missing it with the help of the driver.1239                self._default_block_device_names(context, instance, image_meta,1240                                                 bdms)1241                block_device_info = self._prep_block_device(1242                        context, instance, bdms)1243                set_access_ip = (is_first_time and1244                                 not instance.access_ip_v4 and1245                                 not instance.access_ip_v6)1246                instance = self._spawn(context, instance, image_meta,1247                                       network_info, block_device_info,1248                                       injected_files, admin_password,1249                                       set_access_ip=set_access_ip)1250        except (exception.InstanceNotFound,1251                exception.UnexpectedDeletingTaskStateError):1252            # the instance got deleted during the spawn1253            # Make sure the async call finishes1254            if network_info is not None:1255                network_info.wait(do_raise=False)1256            try:1257                self._deallocate_network(context, instance)1258            except Exception:1259                msg = _LE('Failed to dealloc network '1260                          'for deleted instance')1261                LOG.exception(msg, instance=instance)1262            raise exception.BuildAbortException(1263                instance_uuid=instance.uuid,1264                reason=_("Instance disappeared during build"))1265        except (exception.UnexpectedTaskStateError,1266                exception.VirtualInterfaceCreateException) as e:1267            # Don't try to reschedule, just log and reraise.1268            with excutils.save_and_reraise_exception():1269                LOG.debug(e.format_message(), instance=instance)1270                # Make sure the async call finishes1271                if network_info is not None:1272                    network_info.wait(do_raise=False)1273        except exception.InvalidBDM:1274            with excutils.save_and_reraise_exception():1275                if network_info is not None:1276                    network_info.wait(do_raise=False)1277                try:1278                    self._deallocate_network(context, instance)1279                except Exception:1280                    msg = _LE('Failed to dealloc network '1281                              'for failed instance')1282                    LOG.exception(msg, instance=instance)1283        except Exception:1284            exc_info = sys.exc_info()1285            # try to re-schedule instance:1286            # Make sure the async call finishes1287            if network_info is not None:1288                network_info.wait(do_raise=False)1289            rescheduled = self._reschedule_or_error(original_context, instance,1290                    exc_info, requested_networks, admin_password,1291                    injected_files_orig, is_first_time, request_spec,1292                    filter_properties, bdms, legacy_bdm_in_spec)1293            if rescheduled:1294                # log the original build error1295                self._log_original_error(exc_info, instance.uuid)1296                raise exception.RescheduledException(1297                        instance_uuid=instance.uuid,1298                        reason=unicode(exc_info[1]))1299            else:1300                # not re-scheduling, go to error:1301                raise exc_info[0], exc_info[1], exc_info[2]1302        # spawn success1303        return instance, network_info1304    def _log_original_error(self, exc_info, instance_uuid):1305        LOG.error(_('Error: %s') % exc_info[1], instance_uuid=instance_uuid,1306                  exc_info=exc_info)1307    def _reschedule_or_error(self, context, instance, exc_info,1308            requested_networks, admin_password, injected_files, is_first_time,1309            request_spec, filter_properties, bdms=None,1310            legacy_bdm_in_spec=True):1311        """Try to re-schedule the build or re-raise the original build error to1312        error out the instance.1313        """1314        original_context = context1315        context = context.elevated()1316        instance_uuid = instance['uuid']1317        rescheduled = False1318        compute_utils.add_instance_fault_from_exc(context,1319                instance, exc_info[1], exc_info=exc_info)1320        self._notify_about_instance_usage(context, instance,1321                'instance.create.error', fault=exc_info[1])1322        try:1323            LOG.debug("Clean up resource before rescheduling.",1324                      instance=instance)1325            if bdms is None:1326                bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(1327                        context, instance.uuid)1328            self._shutdown_instance(context, instance,1329                                    bdms, requested_networks)1330            self._cleanup_volumes(context, instance['uuid'], bdms)1331        except Exception:1332            # do not attempt retry if clean up failed:1333            with excutils.save_and_reraise_exception():1334                self._log_original_error(exc_info, instance_uuid)1335        try:1336            method_args = (request_spec, admin_password, injected_files,1337                    requested_networks, is_first_time, filter_properties,1338                    legacy_bdm_in_spec)1339            task_state = task_states.SCHEDULING1340            rescheduled = self._reschedule(original_context, request_spec,1341                    filter_properties, instance,1342                    self.scheduler_rpcapi.run_instance, method_args,1343                    task_state, exc_info)1344        except Exception:1345            rescheduled = False1346            LOG.exception(_LE("Error trying to reschedule"),1347                          instance_uuid=instance_uuid)1348        return rescheduled1349    def _reschedule(self, context, request_spec, filter_properties,1350            instance, reschedule_method, method_args, task_state,1351            exc_info=None):1352        """Attempt to re-schedule a compute operation."""1353        instance_uuid = instance['uuid']1354        retry = filter_properties.get('retry', None)1355        if not retry:1356            # no retry information, do not reschedule.1357            LOG.debug("Retry info not present, will not reschedule",1358                      instance_uuid=instance_uuid)1359            return1360        if not request_spec:1361            LOG.debug("No request spec, will not reschedule",1362                      instance_uuid=instance_uuid)1363            return1364        request_spec['instance_uuids'] = [instance_uuid]1365        LOG.debug("Re-scheduling %(method)s: attempt %(num)d",1366                  {'method': reschedule_method.func_name,1367                   'num': retry['num_attempts']}, instance_uuid=instance_uuid)1368        # reset the task state:1369        self._instance_update(context, instance_uuid, task_state=task_state)1370        if exc_info:1371            # stringify to avoid circular ref problem in json serialization:1372            retry['exc'] = traceback.format_exception_only(exc_info[0],1373                                    exc_info[1])1374        reschedule_method(context, *method_args)1375        return True1376    @periodic_task.periodic_task1377    def _check_instance_build_time(self, context):1378        """Ensure that instances are not stuck in build."""1379        timeout = CONF.instance_build_timeout1380        if timeout == 0:1381            return1382        filters = {'vm_state': vm_states.BUILDING,1383                   'host': self.host}1384        building_insts = objects.InstanceList.get_by_filters(context,1385                           filters, expected_attrs=[], use_slave=True)1386        for instance in building_insts:1387            if timeutils.is_older_than(instance['created_at'], timeout):1388                self._set_instance_error_state(context, instance)1389                LOG.warn(_("Instance build timed out. Set to error state."),1390                         instance=instance)1391    def _check_instance_exists(self, context, instance):1392        """Ensure an instance with the same name is not already present."""1393        if self.driver.instance_exists(instance):1394            raise exception.InstanceExists(name=instance.name)1395    def _start_building(self, context, instance):1396        """Save the host and launched_on fields and log appropriately."""1397        LOG.audit(_('Starting instance...'), context=context,1398                  instance=instance)1399        self._instance_update(context, instance.uuid,1400                              vm_state=vm_states.BUILDING,1401                              task_state=None,1402                              expected_task_state=(task_states.SCHEDULING,1403                                                   None))1404    def _allocate_network_async(self, context, instance, requested_networks,1405                                macs, security_groups, is_vpn, dhcp_options):1406        """Method used to allocate networks in the background.1407        Broken out for testing.1408        """1409        LOG.debug("Allocating IP information in the background.",1410                  instance=instance)1411        retries = CONF.network_allocate_retries1412        if retries < 0:1413            LOG.warn(_("Treating negative config value (%(retries)s) for "1414                       "'network_allocate_retries' as 0."),1415                     {'retries': retries})1416        attempts = retries > 1 and retries + 1 or 11417        retry_time = 11418        for attempt in range(1, attempts + 1):1419            try:1420                nwinfo = self.network_api.allocate_for_instance(1421                        context, instance, vpn=is_vpn,1422                        requested_networks=requested_networks,1423                        macs=macs,1424                        security_groups=security_groups,1425                        dhcp_options=dhcp_options)1426                LOG.debug('Instance network_info: |%s|', nwinfo,1427                          instance=instance)1428                sys_meta = instance.system_metadata1429                sys_meta['network_allocated'] = 'True'1430                self._instance_update(context, instance.uuid,1431                        system_metadata=sys_meta)1432                return nwinfo1433            except Exception:1434                exc_info = sys.exc_info()1435                log_info = {'attempt': attempt,1436                            'attempts': attempts}1437                if attempt == attempts:1438                    LOG.exception(_LE('Instance failed network setup '1439                                      'after %(attempts)d attempt(s)'),1440                                  log_info)1441                    raise exc_info[0], exc_info[1], exc_info[2]1442                LOG.warn(_('Instance failed network setup '1443                           '(attempt %(attempt)d of %(attempts)d)'),1444                         log_info, instance=instance)1445                time.sleep(retry_time)1446                retry_time *= 21447                if retry_time > 30:1448                    retry_time = 301449        # Not reached.1450    def _build_networks_for_instance(self, context, instance,1451            requested_networks, security_groups):1452        # If we're here from a reschedule the network may already be allocated.1453        if strutils.bool_from_string(1454                instance.system_metadata.get('network_allocated', 'False')):1455            return self._get_instance_nw_info(context, instance)1456        if not self.is_neutron_security_groups:1457            security_groups = []1458        macs = self.driver.macs_for_instance(instance)1459        dhcp_options = self.driver.dhcp_options_for_instance(instance)1460        network_info = self._allocate_network(context, instance,1461                requested_networks, macs, security_groups, dhcp_options)1462        if not instance.access_ip_v4 and not instance.access_ip_v6:1463            # If CONF.default_access_ip_network_name is set, grab the1464            # corresponding network and set the access ip values accordingly.1465            # Note that when there are multiple ips to choose from, an1466            # arbitrary one will be chosen.1467            network_name = CONF.default_access_ip_network_name1468            if not network_name:1469                return network_info1470            for vif in network_info:1471                if vif['network']['label'] == network_name:1472                    for ip in vif.fixed_ips():1473                        if ip['version'] == 4:1474                            instance.access_ip_v4 = ip['address']1475                        if ip['version'] == 6:1476                            instance.access_ip_v6 = ip['address']1477                    instance.save()1478                    break1479        return network_info1480    def _allocate_network(self, context, instance, requested_networks, macs,1481                          security_groups, dhcp_options):1482        """Start network allocation asynchronously.  Return an instance1483        of NetworkInfoAsyncWrapper that can be used to retrieve the1484        allocated networks when the operation has finished.1485        """1486        # NOTE(comstud): Since we're allocating networks asynchronously,1487        # this task state has little meaning, as we won't be in this1488        # state for very long.1489        instance.vm_state = vm_states.BUILDING1490        instance.task_state = task_states.NETWORKING1491        instance.save(expected_task_state=[None])1492        self._update_resource_tracker(context, instance)1493        is_vpn = pipelib.is_vpn_image(instance.image_ref)1494        return network_model.NetworkInfoAsyncWrapper(1495                self._allocate_network_async, context, instance,1496                requested_networks, macs, security_groups, is_vpn,1497                dhcp_options)1498    def _default_root_device_name(self, instance, image_meta, root_bdm):1499        try:1500            return self.driver.default_root_device_name(instance,1501                                                        image_meta,1502                                                        root_bdm)1503        except NotImplementedError:1504            return compute_utils.get_next_device_name(instance, [])1505    def _default_device_names_for_instance(self, instance,1506                                           root_device_name,1507                                           *block_device_lists):1508        try:1509            self.driver.default_device_names_for_instance(instance,1510                                                          root_device_name,1511                                                          *block_device_lists)1512        except NotImplementedError:1513            compute_utils.default_device_names_for_instance(1514                instance, root_device_name, *block_device_lists)1515    def _default_block_device_names(self, context, instance,1516                                    image_meta, block_devices):1517        """Verify that all the devices have the device_name set. If not,1518        provide a default name.1519        It also ensures that there is a root_device_name and is set to the1520        first block device in the boot sequence (boot_index=0).1521        """1522        root_bdm = block_device.get_root_bdm(block_devices)1523        if not root_bdm:1524            return1525        # Get the root_device_name from the root BDM or the instance1526        root_device_name = None1527        update_instance = False1528        update_root_bdm = False1529        if root_bdm.device_name:1530            root_device_name = root_bdm.device_name1531            instance.root_device_name = root_device_name1532            update_instance = True1533        elif instance.root_device_name:1534            root_device_name = instance.root_device_name1535            root_bdm.device_name = root_device_name1536            update_root_bdm = True1537        else:1538            root_device_name = self._default_root_device_name(instance,1539                                                              image_meta,1540                                                              root_bdm)1541            instance.root_device_name = root_device_name1542            root_bdm.device_name = root_device_name1543            update_instance = update_root_bdm = True1544        if update_instance:1545            instance.save()1546        if update_root_bdm:1547            root_bdm.save()1548        ephemerals = filter(block_device.new_format_is_ephemeral,1549                            block_devices)1550        swap = filter(block_device.new_format_is_swap,1551                      block_devices)1552        block_device_mapping = filter(1553              driver_block_device.is_block_device_mapping, block_devices)1554        self._default_device_names_for_instance(instance,1555                                                root_device_name,1556                                                ephemerals,1557                                                swap,1558                                                block_device_mapping)1559    def _prep_block_device(self, context, instance, bdms,1560                           do_check_attach=True):1561        """Set up the block device for an instance with error logging."""1562        try:1563            block_device_info = {1564                'root_device_name': instance['root_device_name'],1565                'swap': driver_block_device.convert_swap(bdms),1566                'ephemerals': driver_block_device.convert_ephemerals(bdms),1567                'block_device_mapping': (1568                    driver_block_device.attach_block_devices(1569                        driver_block_device.convert_volumes(bdms),1570                        context, instance, self.volume_api,1571                        self.driver, do_check_attach=do_check_attach) +1572                    driver_block_device.attach_block_devices(1573                        driver_block_device.convert_snapshots(bdms),1574                        context, instance, self.volume_api,1575                        self.driver, self._await_block_device_map_created,1576                        do_check_attach=do_check_attach) +1577                    driver_block_device.attach_block_devices(1578                        driver_block_device.convert_images(bdms),1579                        context, instance, self.volume_api,1580                        self.driver, self._await_block_device_map_created,1581                        do_check_attach=do_check_attach) +1582                    driver_block_device.attach_block_devices(1583                        driver_block_device.convert_blanks(bdms),1584                        context, instance, self.volume_api,1585                        self.driver, self._await_block_device_map_created,1586                        do_check_attach=do_check_attach))1587            }1588            if self.use_legacy_block_device_info:1589                for bdm_type in ('swap', 'ephemerals', 'block_device_mapping'):1590                    block_device_info[bdm_type] = \1591                        driver_block_device.legacy_block_devices(1592                        block_device_info[bdm_type])1593            # Get swap out of the list1594            block_device_info['swap'] = driver_block_device.get_swap(1595                block_device_info['swap'])1596            return block_device_info1597        except exception.OverQuota:1598            msg = _LW('Failed to create block device for instance due to '1599                      'being over volume resource quota')1600            LOG.warn(msg, instance=instance)1601            raise exception.InvalidBDM()1602        except Exception:1603            LOG.exception(_LE('Instance failed block device setup'),1604                          instance=instance)1605            raise exception.InvalidBDM()1606    @object_compat1607    def _spawn(self, context, instance, image_meta, network_info,1608               block_device_info, injected_files, admin_password,1609               set_access_ip=False):1610        """Spawn an instance with error logging and update its power state."""1611        instance.vm_state = vm_states.BUILDING1612        instance.task_state = task_states.SPAWNING1613        instance.save(expected_task_state=task_states.BLOCK_DEVICE_MAPPING)1614        try:1615            self.driver.spawn(context, instance, image_meta,1616                              injected_files, admin_password,1617                              network_info,1618                              block_device_info)1619        except Exception:1620            with excutils.save_and_reraise_exception():1621                LOG.exception(_LE('Instance failed to spawn'),1622                              instance=instance)1623        current_power_state = self._get_power_state(context, instance)1624        instance.power_state = current_power_state1625        instance.vm_state = vm_states.ACTIVE1626        instance.task_state = None1627        instance.launched_at = timeutils.utcnow()1628        def _set_access_ip_values():1629            """Add access ip values for a given instance.1630            If CONF.default_access_ip_network_name is set, this method will1631            grab the corresponding network and set the access ip values1632            accordingly. Note that when there are multiple ips to choose1633            from, an arbitrary one will be chosen.1634            """1635            network_name = CONF.default_access_ip_network_name1636            if not network_name:1637                return1638            for vif in network_info:1639                if vif['network']['label'] == network_name:1640                    for ip in vif.fixed_ips():1641                        if ip['version'] == 4:1642                            instance.access_ip_v4 = ip['address']1643                        if ip['version'] == 6:1644                            instance.access_ip_v6 = ip['address']1645                    return1646        if set_access_ip:1647            _set_access_ip_values()1648        network_info.wait(do_raise=True)1649        instance.info_cache.network_info = network_info1650        instance.save(expected_task_state=task_states.SPAWNING)1651        return instance1652    def _notify_about_instance_usage(self, context, instance, event_suffix,1653                                     network_info=None, system_metadata=None,1654                                     extra_usage_info=None, fault=None):1655        compute_utils.notify_about_instance_usage(1656            self.notifier, context, instance, event_suffix,1657            network_info=network_info,1658            system_metadata=system_metadata,1659            extra_usage_info=extra_usage_info, fault=fault)1660    def _deallocate_network(self, context, instance,1661                            requested_networks=None):1662        LOG.debug('Deallocating network for instance', instance=instance)1663        self.network_api.deallocate_for_instance(1664            context, instance, requested_networks=requested_networks)1665    def _get_instance_block_device_info(self, context, instance,1666                                        refresh_conn_info=False,1667                                        bdms=None):1668        """Transform block devices to the driver block_device format."""1669        if not bdms:1670            bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(1671                    context, instance['uuid'])1672        swap = driver_block_device.convert_swap(bdms)1673        ephemerals = driver_block_device.convert_ephemerals(bdms)1674        block_device_mapping = (1675            driver_block_device.convert_volumes(bdms) +1676            driver_block_device.convert_snapshots(bdms) +1677            driver_block_device.convert_images(bdms))1678        if not refresh_conn_info:1679            # if the block_device_mapping has no value in connection_info1680            # (returned as None), don't include in the mapping1681            block_device_mapping = [1682                bdm for bdm in block_device_mapping1683                if bdm.get('connection_info')]1684        else:1685            block_device_mapping = driver_block_device.refresh_conn_infos(1686                block_device_mapping, context, instance, self.volume_api,1687                self.driver)1688        if self.use_legacy_block_device_info:1689            swap = driver_block_device.legacy_block_devices(swap)1690            ephemerals = driver_block_device.legacy_block_devices(ephemerals)1691            block_device_mapping = driver_block_device.legacy_block_devices(1692                block_device_mapping)1693        # Get swap out of the list1694        swap = driver_block_device.get_swap(swap)1695        return {'swap': swap,1696                'ephemerals': ephemerals,1697                'block_device_mapping': block_device_mapping}1698    # NOTE(mikal): No object_compat wrapper on this method because its1699    # callers all pass objects already1700    @wrap_exception()1701    @reverts_task_state1702    @wrap_instance_event1703    @wrap_instance_fault1704    def build_and_run_instance(self, context, instance, image, request_spec,1705                     filter_properties, admin_password=None,1706                     injected_files=None, requested_networks=None,1707                     security_groups=None, block_device_mapping=None,1708                     node=None, limits=None):1709        # NOTE(danms): Remove this in v4.0 of the RPC API1710        if (requested_networks and1711                not isinstance(requested_networks,1712                               objects.NetworkRequestList)):1713            requested_networks = objects.NetworkRequestList(1714                objects=[objects.NetworkRequest.from_tuple(t)1715                         for t in requested_networks])1716        @utils.synchronized(instance.uuid)1717        def do_build_and_run_instance(context, instance, image, request_spec,1718                filter_properties, admin_password, injected_files,1719                requested_networks, security_groups, block_device_mapping,1720                node=None, limits=None):1721            try:1722                LOG.audit(_('Starting instance...'), context=context,1723                      instance=instance)1724                instance.vm_state = vm_states.BUILDING1725                instance.task_state = None1726                instance.save(expected_task_state=1727                        (task_states.SCHEDULING, None))1728            except exception.InstanceNotFound:1729                msg = 'Instance disappeared before build.'1730                LOG.debug(msg, instance=instance)1731                return1732            except exception.UnexpectedTaskStateError as e:1733                LOG.debug(e.format_message(), instance=instance)1734                return1735            # b64 decode the files to inject:1736            decoded_files = self._decode_files(injected_files)1737            if limits is None:1738                limits = {}1739            if node is None:1740                node = self.driver.get_available_nodes(refresh=True)[0]1741                LOG.debug('No node specified, defaulting to %s', node,1742                          instance=instance)1743            try:1744                self._build_and_run_instance(context, instance, image,1745                        decoded_files, admin_password, requested_networks,1746                        security_groups, block_device_mapping, node, limits,1747                        filter_properties)1748            except exception.RescheduledException as e:1749                LOG.debug(e.format_message(), instance=instance)1750                retry = filter_properties.get('retry', None)1751                if not retry:1752                    # no retry information, do not reschedule.1753                    LOG.debug("Retry info not present, will not reschedule",1754                        instance=instance)1755                    self._cleanup_allocated_networks(context, instance,1756                        requested_networks)1757                    compute_utils.add_instance_fault_from_exc(context,1758                            instance, e, sys.exc_info())1759                    self._set_instance_error_state(context, instance)1760                    return1761                retry['exc'] = traceback.format_exception(*sys.exc_info())1762                # NOTE(comstud): Deallocate networks if the driver wants1763                # us to do so.1764                if self.driver.deallocate_networks_on_reschedule(instance):1765                    self._cleanup_allocated_networks(context, instance,1766                            requested_networks)1767                instance.task_state = task_states.SCHEDULING1768                instance.save()1769                self.compute_task_api.build_instances(context, [instance],1770                        image, filter_properties, admin_password,1771                        injected_files, requested_networks, security_groups,1772                        block_device_mapping)1773            except (exception.InstanceNotFound,1774                    exception.UnexpectedDeletingTaskStateError):1775                msg = 'Instance disappeared during build.'1776                LOG.debug(msg, instance=instance)1777                self._cleanup_allocated_networks(context, instance,1778                        requested_networks)1779            except exception.BuildAbortException as e:1780                LOG.exception(e.format_message(), instance=instance)1781                self._cleanup_allocated_networks(context, instance,1782                        requested_networks)1783                self._cleanup_volumes(context, instance.uuid,1784                        block_device_mapping, raise_exc=False)1785                compute_utils.add_instance_fault_from_exc(context, instance,1786                        e, sys.exc_info())1787                self._set_instance_error_state(context, instance)1788            except Exception as e:1789                # Should not reach here.1790                msg = _LE('Unexpected build failure, not rescheduling build.')1791                LOG.exception(msg, instance=instance)1792                self._cleanup_allocated_networks(context, instance,1793                        requested_networks)1794                self._cleanup_volumes(context, instance.uuid,1795                        block_device_mapping, raise_exc=False)1796                compute_utils.add_instance_fault_from_exc(context, instance,1797                        e, sys.exc_info())1798                self._set_instance_error_state(context, instance)1799        do_build_and_run_instance(context, instance, image, request_spec,1800                filter_properties, admin_password, injected_files,1801                requested_networks, security_groups, block_device_mapping,1802                node, limits)1803    def _build_and_run_instance(self, context, instance, image, injected_files,1804            admin_password, requested_networks, security_groups,1805            block_device_mapping, node, limits, filter_properties):1806        image_name = image.get('name')1807        self._notify_about_instance_usage(context, instance, 'create.start',1808                extra_usage_info={'image_name': image_name})1809        try:1810            rt = self._get_resource_tracker(node)1811            with rt.instance_claim(context, instance, limits):1812                # NOTE(russellb) It's important that this validation be done1813                # *after* the resource tracker instance claim, as that is where1814                # the host is set on the instance.1815                self._validate_instance_group_policy(context, instance,1816                        filter_properties)1817                with self._build_resources(context, instance,1818                        requested_networks, security_groups, image,1819                        block_device_mapping) as resources:1820                    instance.vm_state = vm_states.BUILDING1821                    instance.task_state = task_states.SPAWNING1822                    instance.save(expected_task_state=1823                            task_states.BLOCK_DEVICE_MAPPING)1824                    block_device_info = resources['block_device_info']1825                    network_info = resources['network_info']1826                    self.driver.spawn(context, instance, image,1827                                      injected_files, admin_password,1828                                      network_info=network_info,1829                                      block_device_info=block_device_info)1830        except (exception.InstanceNotFound,1831                exception.UnexpectedDeletingTaskStateError) as e:1832            with excutils.save_and_reraise_exception():1833                self._notify_about_instance_usage(context, instance,1834                    'create.end', fault=e)1835        except exception.ComputeResourcesUnavailable as e:1836            LOG.debug(e.format_message(), instance=instance)1837            self._notify_about_instance_usage(context, instance,1838                    'create.error', fault=e)1839            raise exception.RescheduledException(1840                    instance_uuid=instance.uuid, reason=e.format_message())1841        except exception.BuildAbortException as e:1842            with excutils.save_and_reraise_exception():1843                LOG.debug(e.format_message(), instance=instance)1844                self._notify_about_instance_usage(context, instance,1845                    'create.error', fault=e)1846        except (exception.FixedIpLimitExceeded,1847                exception.NoMoreNetworks) as e:1848            LOG.warn(_LW('No more network or fixed IP to be allocated'),1849                     instance=instance)1850            self._notify_about_instance_usage(context, instance,1851                    'create.error', fault=e)1852            msg = _('Failed to allocate the network(s) with error %s, '1853                    'not rescheduling.') % e.format_message()1854            raise exception.BuildAbortException(instance_uuid=instance.uuid,1855                    reason=msg)1856        except (exception.VirtualInterfaceCreateException,1857                exception.VirtualInterfaceMacAddressException) as e:1858            LOG.exception(_LE('Failed to allocate network(s)'),1859                          instance=instance)1860            self._notify_about_instance_usage(context, instance,1861                    'create.error', fault=e)1862            msg = _('Failed to allocate the network(s), not rescheduling.')1863            raise exception.BuildAbortException(instance_uuid=instance.uuid,1864                    reason=msg)1865        except (exception.FlavorDiskTooSmall,1866                exception.FlavorMemoryTooSmall,1867                exception.ImageNotActive,1868                exception.ImageUnacceptable) as e:1869            self._notify_about_instance_usage(context, instance,1870                    'create.error', fault=e)1871            raise exception.BuildAbortException(instance_uuid=instance.uuid,1872                    reason=e.format_message())1873        except Exception as e:1874            self._notify_about_instance_usage(context, instance,1875                    'create.error', fault=e)1876            raise exception.RescheduledException(1877                    instance_uuid=instance.uuid, reason=six.text_type(e))1878        # NOTE(alaski): This is only useful during reschedules, remove it now.1879        instance.system_metadata.pop('network_allocated', None)1880        instance.power_state = self._get_power_state(context, instance)1881        instance.vm_state = vm_states.ACTIVE1882        instance.task_state = None1883        instance.launched_at = timeutils.utcnow()1884        try:1885            instance.save(expected_task_state=task_states.SPAWNING)1886        except (exception.InstanceNotFound,1887                exception.UnexpectedDeletingTaskStateError) as e:1888            with excutils.save_and_reraise_exception():1889                self._notify_about_instance_usage(context, instance,1890                    'create.end', fault=e)1891        self._notify_about_instance_usage(context, instance, 'create.end',1892                extra_usage_info={'message': _('Success')},1893                network_info=network_info)1894    @contextlib.contextmanager1895    def _build_resources(self, context, instance, requested_networks,1896            security_groups, image, block_device_mapping):1897        resources = {}1898        network_info = None1899        try:1900            network_info = self._build_networks_for_instance(context, instance,1901                    requested_networks, security_groups)1902            resources['network_info'] = network_info1903        except (exception.InstanceNotFound,1904                exception.UnexpectedDeletingTaskStateError):1905            raise1906        except exception.UnexpectedTaskStateError as e:1907            raise exception.BuildAbortException(instance_uuid=instance.uuid,1908                    reason=e.format_message())1909        except Exception:1910            # Because this allocation is async any failures are likely to occur1911            # when the driver accesses network_info during spawn().1912            LOG.exception(_LE('Failed to allocate network(s)'),1913                          instance=instance)1914            msg = _('Failed to allocate the network(s), not rescheduling.')1915            raise exception.BuildAbortException(instance_uuid=instance.uuid,1916                    reason=msg)1917        try:1918            # Verify that all the BDMs have a device_name set and assign a1919            # default to the ones missing it with the help of the driver.1920            self._default_block_device_names(context, instance, image,1921                    block_device_mapping)1922            instance.vm_state = vm_states.BUILDING1923            instance.task_state = task_states.BLOCK_DEVICE_MAPPING1924            instance.save()1925            block_device_info = self._prep_block_device(context, instance,1926                    block_device_mapping)1927            resources['block_device_info'] = block_device_info1928        except (exception.InstanceNotFound,1929                exception.UnexpectedDeletingTaskStateError):1930            with excutils.save_and_reraise_exception() as ctxt:1931                # Make sure the async call finishes1932                if network_info is not None:1933                    network_info.wait(do_raise=False)1934        except exception.UnexpectedTaskStateError as e:1935            # Make sure the async call finishes1936            if network_info is not None:1937                network_info.wait(do_raise=False)1938            raise exception.BuildAbortException(instance_uuid=instance.uuid,1939                    reason=e.format_message())1940        except Exception:1941            LOG.exception(_LE('Failure prepping block device'),1942                    instance=instance)1943            # Make sure the async call finishes1944            if network_info is not None:1945                network_info.wait(do_raise=False)1946            msg = _('Failure prepping block device.')1947            raise exception.BuildAbortException(instance_uuid=instance.uuid,1948                    reason=msg)1949        try:1950            yield resources1951        except Exception as exc:1952            with excutils.save_and_reraise_exception() as ctxt:1953                if not isinstance(exc, (exception.InstanceNotFound,1954                    exception.UnexpectedDeletingTaskStateError)):1955                        LOG.exception(_LE('Instance failed to spawn'),1956                                instance=instance)1957                # Make sure the async call finishes1958                if network_info is not None:1959                    network_info.wait(do_raise=False)1960                try:1961                    self._shutdown_instance(context, instance,1962                            block_device_mapping, requested_networks,1963                            try_deallocate_networks=False)1964                except Exception:1965                    ctxt.reraise = False1966                    msg = _('Could not clean up failed build,'1967                            ' not rescheduling')1968                    raise exception.BuildAbortException(1969                            instance_uuid=instance.uuid, reason=msg)1970    def _cleanup_allocated_networks(self, context, instance,1971            requested_networks):1972        try:1973            self._deallocate_network(context, instance, requested_networks)1974        except Exception:1975            msg = _LE('Failed to deallocate networks')1976            LOG.exception(msg, instance=instance)1977            return1978        instance.system_metadata['network_allocated'] = 'False'1979        try:1980            instance.save()1981        except exception.InstanceNotFound:1982            # NOTE(alaski): It's possible that we're cleaning up the networks1983            # because the instance was deleted.  If that's the case then this1984            # exception will be raised by instance.save()1985            pass1986    @object_compat1987    @messaging.expected_exceptions(exception.BuildAbortException,1988                                   exception.UnexpectedTaskStateError,1989                                   exception.VirtualInterfaceCreateException,1990                                   exception.RescheduledException)1991    @wrap_exception()1992    @reverts_task_state1993    @wrap_instance_event1994    @wrap_instance_fault1995    def run_instance(self, context, instance, request_spec,1996                     filter_properties, requested_networks,1997                     injected_files, admin_password,1998                     is_first_time, node, legacy_bdm_in_spec):1999        # NOTE(alaski) This method should be deprecated when the scheduler and2000        # compute rpc interfaces are bumped to 4.x, and slated for removal in2001        # 5.x as it is no longer used.2002        if filter_properties is None:2003            filter_properties = {}2004        @utils.synchronized(instance.uuid)2005        def do_run_instance():2006            self._run_instance(context, request_spec,2007                    filter_properties, requested_networks, injected_files,2008                    admin_password, is_first_time, node, instance,2009                    legacy_bdm_in_spec)2010        do_run_instance()2011    def _try_deallocate_network(self, context, instance,2012                                requested_networks=None):2013        try:2014            # tear down allocated network structure2015            self._deallocate_network(context, instance, requested_networks)2016        except Exception:2017            with excutils.save_and_reraise_exception():2018                LOG.error(_('Failed to deallocate network for instance.'),2019                          instance=instance)2020                self._set_instance_error_state(context, instance)2021    def _get_power_off_values(self, context, instance, clean_shutdown):2022        """Get the timing configuration for powering down this instance."""2023        if clean_shutdown:2024            timeout = compute_utils.get_value_from_system_metadata(instance,2025                          key='image_os_shutdown_timeout', type=int,2026                          default=CONF.shutdown_timeout)2027            retry_interval = self.SHUTDOWN_RETRY_INTERVAL2028        else:2029            timeout = 02030            retry_interval = 02031        return timeout, retry_interval2032    def _power_off_instance(self, context, instance, clean_shutdown=True):2033        """Power off an instance on this host."""2034        timeout, retry_interval = self._get_power_off_values(context,2035                                        instance, clean_shutdown)2036        self.driver.power_off(instance, timeout, retry_interval)2037    def _shutdown_instance(self, context, instance,2038                           bdms, requested_networks=None, notify=True,2039                           try_deallocate_networks=True):2040        """Shutdown an instance on this host.2041        :param:context: security context2042        :param:instance: a nova.objects.Instance object2043        :param:bdms: the block devices for the instance to be torn2044                     down2045        :param:requested_networks: the networks on which the instance2046                                   has ports2047        :param:notify: true if a final usage notification should be2048                       emitted2049        :param:try_deallocate_networks: false if we should avoid2050                                        trying to teardown networking2051        """2052        context = context.elevated()2053        LOG.audit(_('%(action_str)s instance') % {'action_str': 'Terminating'},2054                  context=context, instance=instance)2055        if notify:2056            self._notify_about_instance_usage(context, instance,2057                                              "shutdown.start")2058        network_info = compute_utils.get_nw_info_for_instance(instance)2059        # NOTE(vish) get bdms before destroying the instance2060        vol_bdms = [bdm for bdm in bdms if bdm.is_volume]2061        block_device_info = self._get_instance_block_device_info(2062            context, instance, bdms=bdms)2063        # NOTE(melwitt): attempt driver destroy before releasing ip, may2064        #                want to keep ip allocated for certain failures2065        try:2066            self.driver.destroy(context, instance, network_info,2067                    block_device_info)2068        except exception.InstancePowerOffFailure:2069            # if the instance can't power off, don't release the ip2070            with excutils.save_and_reraise_exception():2071                pass2072        except Exception:2073            with excutils.save_and_reraise_exception():2074                # deallocate ip and fail without proceeding to2075                # volume api calls, preserving current behavior2076                if try_deallocate_networks:2077                    self._try_deallocate_network(context, instance,2078                                                 requested_networks)2079        if try_deallocate_networks:2080            self._try_deallocate_network(context, instance, requested_networks)2081        for bdm in vol_bdms:2082            try:2083                # NOTE(vish): actual driver detach done in driver.destroy, so2084                #             just tell cinder that we are done with it.2085                connector = self.driver.get_volume_connector(instance)2086                self.volume_api.terminate_connection(context,2087                                                     bdm.volume_id,2088                                                     connector)2089                self.volume_api.detach(context, bdm.volume_id)2090            except exception.DiskNotFound as exc:2091                LOG.debug('Ignoring DiskNotFound: %s', exc,2092                          instance=instance)2093            except exception.VolumeNotFound as exc:2094                LOG.debug('Ignoring VolumeNotFound: %s', exc,2095                          instance=instance)2096            except cinder_exception.EndpointNotFound as exc:2097                LOG.warn(_LW('Ignoring EndpointNotFound: %s'), exc,2098                             instance=instance)2099        if notify:2100            self._notify_about_instance_usage(context, instance,2101                                              "shutdown.end")2102    def _cleanup_volumes(self, context, instance_uuid, bdms, raise_exc=True):2103        exc_info = None2104        for bdm in bdms:2105            LOG.debug("terminating bdm %s", bdm,2106                      instance_uuid=instance_uuid)2107            if bdm.volume_id and bdm.delete_on_termination:2108                try:2109                    self.volume_api.delete(context, bdm.volume_id)2110                except Exception as exc:2111                    exc_info = sys.exc_info()2112                    LOG.warn(_LW('Failed to delete volume: %(volume_id)s due '2113                                 'to %(exc)s'), {'volume_id': bdm.volume_id,2114                                                  'exc': unicode(exc)})2115        if exc_info is not None and raise_exc:2116            six.reraise(exc_info[0], exc_info[1], exc_info[2])2117    @hooks.add_hook("delete_instance")2118    def _delete_instance(self, context, instance, bdms, quotas):2119        """Delete an instance on this host.  Commit or rollback quotas2120        as necessary.2121        """2122        instance_uuid = instance['uuid']2123        was_soft_deleted = instance['vm_state'] == vm_states.SOFT_DELETED2124        if was_soft_deleted:2125            # Instances in SOFT_DELETED vm_state have already had quotas2126            # decremented.2127            try:2128                quotas.rollback()2129            except Exception:2130                pass2131        try:2132            events = self.instance_events.clear_events_for_instance(instance)2133            if events:2134                LOG.debug('Events pending at deletion: %(events)s',2135                          {'events': ','.join(events.keys())},2136                          instance=instance)2137            instance.info_cache.delete()2138            self._notify_about_instance_usage(context, instance,2139                                              "delete.start")2140            self._shutdown_instance(context, instance, bdms)2141            # NOTE(vish): We have already deleted the instance, so we have2142            #             to ignore problems cleaning up the volumes. It2143            #             would be nice to let the user know somehow that2144            #             the volume deletion failed, but it is not2145            #             acceptable to have an instance that can not be2146            #             deleted. Perhaps this could be reworked in the2147            #             future to set an instance fault the first time2148            #             and to only ignore the failure if the instance2149            #             is already in ERROR.2150            self._cleanup_volumes(context, instance_uuid, bdms,2151                    raise_exc=False)2152            # if a delete task succeed, always update vm state and task2153            # state without expecting task state to be DELETING2154            instance.vm_state = vm_states.DELETED2155            instance.task_state = None2156            instance.terminated_at = timeutils.utcnow()2157            instance.save()2158            self._update_resource_tracker(context, instance)2159            system_meta = instance.system_metadata2160            instance.destroy()2161        except Exception:2162            with excutils.save_and_reraise_exception():2163                quotas.rollback()2164        self._complete_deletion(context,2165                                instance,2166                                bdms,2167                                quotas,2168                                system_meta)2169    @wrap_exception()2170    @reverts_task_state2171    @wrap_instance_event2172    @wrap_instance_fault2173    def terminate_instance(self, context, instance, bdms, reservations):2174        """Terminate an instance on this host."""2175        # NOTE (ndipanov): If we get non-object BDMs, just get them from the2176        # db again, as this means they are sent in the old format and we want2177        # to avoid converting them back when we can just get them.2178        # Remove this when we bump the RPC major version to 4.02179        if (bdms and2180            any(not isinstance(bdm, obj_base.NovaObject)2181                for bdm in bdms)):2182            bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(2183                    context, instance.uuid)2184        quotas = objects.Quotas.from_reservations(context,2185                                                  reservations,2186                                                  instance=instance)2187        @utils.synchronized(instance['uuid'])2188        def do_terminate_instance(instance, bdms):2189            try:2190                self._delete_instance(context, instance, bdms, quotas)2191            except exception.InstanceNotFound:2192                LOG.info(_("Instance disappeared during terminate"),2193                         instance=instance)2194            except Exception:2195                # As we're trying to delete always go to Error if something2196                # goes wrong that _delete_instance can't handle.2197                with excutils.save_and_reraise_exception():2198                    LOG.exception(_LE('Setting instance vm_state to ERROR'),2199                                  instance=instance)2200                    self._set_instance_error_state(context, instance)2201        do_terminate_instance(instance, bdms)2202    # NOTE(johannes): This is probably better named power_off_instance2203    # so it matches the driver method, but because of other issues, we2204    # can't use that name in grizzly.2205    @wrap_exception()2206    @reverts_task_state2207    @wrap_instance_event2208    @wrap_instance_fault2209    def stop_instance(self, context, instance, clean_shutdown=True):2210        """Stopping an instance on this host."""2211        @utils.synchronized(instance.uuid)2212        def do_stop_instance():2213            current_power_state = self._get_power_state(context, instance)2214            LOG.debug('Stopping instance; current vm_state: %(vm_state)s, '2215                      'current task_state: %(task_state)s, current DB '2216                      'power_state: %(db_power_state)s, current VM '2217                      'power_state: %(current_power_state)s',2218                      dict(vm_state=instance.vm_state,2219                           task_state=instance.task_state,2220                           db_power_state=instance.power_state,2221                           current_power_state=current_power_state),2222                      instance_uuid=instance.uuid)2223            # NOTE(mriedem): If the instance is already powered off, we are2224            # possibly tearing down and racing with other operations, so we can2225            # expect the task_state to be None if something else updates the2226            # instance and we're not locking it.2227            expected_task_state = [task_states.POWERING_OFF]2228            # The list of power states is from _sync_instance_power_state.2229            if current_power_state in (power_state.NOSTATE,2230                                       power_state.SHUTDOWN,2231                                       power_state.CRASHED):2232                LOG.info(_LI('Instance is already powered off in the '2233                             'hypervisor when stop is called.'),2234                         instance=instance)2235                expected_task_state.append(None)2236            self._notify_about_instance_usage(context, instance,2237                                              "power_off.start")2238            self._power_off_instance(context, instance, clean_shutdown)2239            current_power_state = self._get_power_state(context, instance)2240            instance.power_state = current_power_state2241            instance.vm_state = vm_states.STOPPED2242            instance.task_state = None2243            instance.save(expected_task_state=expected_task_state)2244            self._notify_about_instance_usage(context, instance,2245                                              "power_off.end")2246        do_stop_instance()2247    def _power_on(self, context, instance):2248        network_info = self._get_instance_nw_info(context, instance)2249        block_device_info = self._get_instance_block_device_info(context,2250                                                                 instance)2251        self.driver.power_on(context, instance,2252                             network_info,2253                             block_device_info)2254    # NOTE(johannes): This is probably better named power_on_instance2255    # so it matches the driver method, but because of other issues, we2256    # can't use that name in grizzly.2257    @wrap_exception()2258    @reverts_task_state2259    @wrap_instance_event2260    @wrap_instance_fault2261    def start_instance(self, context, instance):2262        """Starting an instance on this host."""2263        self._notify_about_instance_usage(context, instance, "power_on.start")2264        self._power_on(context, instance)2265        current_power_state = self._get_power_state(context, instance)2266        instance.power_state = current_power_state2267        instance.vm_state = vm_states.ACTIVE2268        instance.task_state = None2269        instance.save(expected_task_state=task_states.POWERING_ON)2270        self._notify_about_instance_usage(context, instance, "power_on.end")2271    @wrap_exception()2272    @reverts_task_state2273    @wrap_instance_event2274    @wrap_instance_fault2275    def soft_delete_instance(self, context, instance, reservations):2276        """Soft delete an instance on this host."""2277        quotas = objects.Quotas.from_reservations(context,2278                                                  reservations,2279                                                  instance=instance)2280        try:2281            self._notify_about_instance_usage(context, instance,2282                                              "soft_delete.start")2283            try:2284                self.driver.soft_delete(instance)2285            except NotImplementedError:2286                # Fallback to just powering off the instance if the2287                # hypervisor doesn't implement the soft_delete method2288                self.driver.power_off(instance)2289            current_power_state = self._get_power_state(context, instance)2290            instance.power_state = current_power_state2291            instance.vm_state = vm_states.SOFT_DELETED2292            instance.task_state = None2293            instance.save(expected_task_state=[task_states.SOFT_DELETING])2294        except Exception:2295            with excutils.save_and_reraise_exception():2296                quotas.rollback()2297        quotas.commit()2298        self._notify_about_instance_usage(context, instance, "soft_delete.end")2299    @object_compat2300    @wrap_exception()2301    @reverts_task_state2302    @wrap_instance_event2303    @wrap_instance_fault2304    def restore_instance(self, context, instance):2305        """Restore a soft-deleted instance on this host."""2306        self._notify_about_instance_usage(context, instance, "restore.start")2307        try:2308            self.driver.restore(instance)2309        except NotImplementedError:2310            # Fallback to just powering on the instance if the hypervisor2311            # doesn't implement the restore method2312            self._power_on(context, instance)2313        current_power_state = self._get_power_state(context, instance)2314        instance.power_state = current_power_state2315        instance.vm_state = vm_states.ACTIVE2316        instance.task_state = None2317        instance.save(expected_task_state=task_states.RESTORING)2318        self._notify_about_instance_usage(context, instance, "restore.end")2319    def _rebuild_default_impl(self, context, instance, image_meta,2320                              injected_files, admin_password, bdms,2321                              detach_block_devices, attach_block_devices,2322                              network_info=None,2323                              recreate=False, block_device_info=None,2324                              preserve_ephemeral=False):2325        if preserve_ephemeral:2326            # The default code path does not support preserving ephemeral2327            # partitions.2328            raise exception.PreserveEphemeralNotSupported()2329        detach_block_devices(context, bdms)2330        if not recreate:2331            self.driver.destroy(context, instance, network_info,2332                                block_device_info=block_device_info)2333        instance.task_state = task_states.REBUILD_BLOCK_DEVICE_MAPPING2334        instance.save(expected_task_state=[task_states.REBUILDING])2335        new_block_device_info = attach_block_devices(context, instance, bdms)2336        instance.task_state = task_states.REBUILD_SPAWNING2337        instance.save(2338            expected_task_state=[task_states.REBUILD_BLOCK_DEVICE_MAPPING])2339        self.driver.spawn(context, instance, image_meta, injected_files,2340                          admin_password, network_info=network_info,2341                          block_device_info=new_block_device_info)2342    @object_compat2343    @messaging.expected_exceptions(exception.PreserveEphemeralNotSupported)2344    @wrap_exception()2345    @reverts_task_state2346    @wrap_instance_event2347    @wrap_instance_fault2348    def rebuild_instance(self, context, instance, orig_image_ref, image_ref,2349                         injected_files, new_pass, orig_sys_metadata,2350                         bdms, recreate, on_shared_storage,2351                         preserve_ephemeral=False):2352        """Destroy and re-make this instance.2353        A 'rebuild' effectively purges all existing data from the system and2354        remakes the VM with given 'metadata' and 'personalities'.2355        :param context: `nova.RequestContext` object2356        :param instance: Instance object2357        :param orig_image_ref: Original image_ref before rebuild2358        :param image_ref: New image_ref for rebuild2359        :param injected_files: Files to inject2360        :param new_pass: password to set on rebuilt instance2361        :param orig_sys_metadata: instance system metadata from pre-rebuild2362        :param bdms: block-device-mappings to use for rebuild2363        :param recreate: True if the instance is being recreated (e.g. the2364            hypervisor it was on failed) - cleanup of old state will be2365            skipped.2366        :param on_shared_storage: True if instance files on shared storage2367        :param preserve_ephemeral: True if the default ephemeral storage2368                                   partition must be preserved on rebuild2369        """2370        context = context.elevated()2371        # NOTE (ndipanov): If we get non-object BDMs, just get them from the2372        # db again, as this means they are sent in the old format and we want2373        # to avoid converting them back when we can just get them.2374        # Remove this on the next major RPC version bump2375        if (bdms and2376            any(not isinstance(bdm, obj_base.NovaObject)2377                for bdm in bdms)):2378            bdms = None2379        orig_vm_state = instance.vm_state2380        with self._error_out_instance_on_exception(context, instance):2381            LOG.audit(_("Rebuilding instance"), context=context,2382                      instance=instance)2383            if recreate:2384                if not self.driver.capabilities["supports_recreate"]:2385                    raise exception.InstanceRecreateNotSupported2386                self._check_instance_exists(context, instance)2387                # To cover case when admin expects that instance files are on2388                # shared storage, but not accessible and vice versa2389                if on_shared_storage != self.driver.instance_on_disk(instance):2390                    raise exception.InvalidSharedStorage(2391                            _("Invalid state of instance files on shared"2392                              " storage"))2393                if on_shared_storage:2394                    LOG.info(_('disk on shared storage, recreating using'2395                               ' existing disk'))2396                else:2397                    image_ref = orig_image_ref = instance.image_ref2398                    LOG.info(_("disk not on shared storage, rebuilding from:"2399                               " '%s'") % str(image_ref))2400                # NOTE(mriedem): On a recreate (evacuate), we need to update2401                # the instance's host and node properties to reflect it's2402                # destination node for the recreate.2403                node_name = None2404                try:2405                    compute_node = self._get_compute_info(context, self.host)2406                    node_name = compute_node.hypervisor_hostname2407                except exception.NotFound:2408                    LOG.exception(_LE('Failed to get compute_info for %s'),2409                                  self.host)2410                finally:2411                    instance.host = self.host2412                    instance.node = node_name2413                    instance.save()2414            if image_ref:2415                image_meta = self.image_api.get(context, image_ref)2416            else:2417                image_meta = {}2418            # This instance.exists message should contain the original2419            # image_ref, not the new one.  Since the DB has been updated2420            # to point to the new one... we have to override it.2421            # TODO(jaypipes): Move generate_image_url() into the nova.image.api2422            orig_image_ref_url = glance.generate_image_url(orig_image_ref)2423            extra_usage_info = {'image_ref_url': orig_image_ref_url}2424            self.conductor_api.notify_usage_exists(context,2425                    obj_base.obj_to_primitive(instance),2426                    current_period=True, system_metadata=orig_sys_metadata,2427                    extra_usage_info=extra_usage_info)2428            # This message should contain the new image_ref2429            extra_usage_info = {'image_name': image_meta.get('name', '')}2430            self._notify_about_instance_usage(context, instance,2431                    "rebuild.start", extra_usage_info=extra_usage_info)2432            instance.power_state = self._get_power_state(context, instance)2433            instance.task_state = task_states.REBUILDING2434            instance.save(expected_task_state=[task_states.REBUILDING])2435            if recreate:2436                self.network_api.setup_networks_on_host(2437                        context, instance, self.host)2438            network_info = compute_utils.get_nw_info_for_instance(instance)2439            if bdms is None:2440                bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(2441                        context, instance.uuid)2442            block_device_info = \2443                self._get_instance_block_device_info(2444                        context, instance, bdms=bdms)2445            def detach_block_devices(context, bdms):2446                for bdm in bdms:2447                    if bdm.is_volume:2448                        self.volume_api.detach(context, bdm.volume_id)2449            files = self._decode_files(injected_files)2450            kwargs = dict(2451                context=context,2452                instance=instance,2453                image_meta=image_meta,2454                injected_files=files,2455                admin_password=new_pass,2456                bdms=bdms,2457                detach_block_devices=detach_block_devices,2458                attach_block_devices=self._prep_block_device,2459                block_device_info=block_device_info,2460                network_info=network_info,2461                preserve_ephemeral=preserve_ephemeral)2462            try:2463                self.driver.rebuild(**kwargs)2464            except NotImplementedError:2465                # NOTE(rpodolyaka): driver doesn't provide specialized version2466                # of rebuild, fall back to the default implementation2467                self._rebuild_default_impl(**kwargs)2468            instance.power_state = self._get_power_state(context, instance)2469            instance.vm_state = vm_states.ACTIVE2470            instance.task_state = None2471            instance.launched_at = timeutils.utcnow()2472            instance.save(expected_task_state=[task_states.REBUILD_SPAWNING])2473            if orig_vm_state == vm_states.STOPPED:2474                LOG.info(_LI("bringing vm to original state: '%s'"),2475                         orig_vm_state, instance=instance)2476                instance.vm_state = vm_states.ACTIVE2477                instance.task_state = task_states.POWERING_OFF2478                instance.progress = 02479                instance.save()2480                self.stop_instance(context, instance)2481            self._notify_about_instance_usage(2482                    context, instance, "rebuild.end",2483                    network_info=network_info,2484                    extra_usage_info=extra_usage_info)2485    def _handle_bad_volumes_detached(self, context, instance, bad_devices,2486                                     block_device_info):2487        """Handle cases where the virt-layer had to detach non-working volumes2488        in order to complete an operation.2489        """2490        for bdm in block_device_info['block_device_mapping']:2491            if bdm.get('mount_device') in bad_devices:2492                try:2493                    volume_id = bdm['connection_info']['data']['volume_id']2494                except KeyError:2495                    continue2496                # NOTE(sirp): ideally we'd just call2497                # `compute_api.detach_volume` here but since that hits the2498                # DB directly, that's off limits from within the2499                # compute-manager.2500                #2501                # API-detach2502                LOG.info(_("Detaching from volume api: %s") % volume_id)2503                volume = self.volume_api.get(context, volume_id)2504                self.volume_api.check_detach(context, volume)2505                self.volume_api.begin_detaching(context, volume_id)2506                # Manager-detach2507                self.detach_volume(context, volume_id, instance)2508    @wrap_exception()2509    @reverts_task_state2510    @wrap_instance_event2511    @wrap_instance_fault2512    def reboot_instance(self, context, instance, block_device_info,2513                        reboot_type):2514        """Reboot an instance on this host."""2515        # acknowledge the request made it to the manager2516        if reboot_type == "SOFT":2517            instance.task_state = task_states.REBOOT_PENDING2518            expected_states = (task_states.REBOOTING,2519                               task_states.REBOOT_PENDING,2520                               task_states.REBOOT_STARTED)2521        else:2522            instance.task_state = task_states.REBOOT_PENDING_HARD2523            expected_states = (task_states.REBOOTING_HARD,2524                               task_states.REBOOT_PENDING_HARD,2525                               task_states.REBOOT_STARTED_HARD)2526        context = context.elevated()2527        LOG.audit(_("Rebooting instance"), context=context, instance=instance)2528        block_device_info = self._get_instance_block_device_info(context,2529                                                                 instance)2530        network_info = self._get_instance_nw_info(context, instance)2531        self._notify_about_instance_usage(context, instance, "reboot.start")2532        current_power_state = self._get_power_state(context, instance)2533        instance.power_state = current_power_state2534        instance.save(expected_task_state=expected_states)2535        if instance['power_state'] != power_state.RUNNING:2536            state = instance['power_state']2537            running = power_state.RUNNING2538            LOG.warn(_('trying to reboot a non-running instance:'2539                       ' (state: %(state)s expected: %(running)s)'),2540                     {'state': state, 'running': running},2541                     context=context, instance=instance)2542        def bad_volumes_callback(bad_devices):2543            self._handle_bad_volumes_detached(2544                    context, instance, bad_devices, block_device_info)2545        try:2546            # Don't change it out of rescue mode2547            if instance['vm_state'] == vm_states.RESCUED:2548                new_vm_state = vm_states.RESCUED2549            else:2550                new_vm_state = vm_states.ACTIVE2551            new_power_state = None2552            if reboot_type == "SOFT":2553                instance.task_state = task_states.REBOOT_STARTED2554                expected_state = task_states.REBOOT_PENDING2555            else:2556                instance.task_state = task_states.REBOOT_STARTED_HARD2557                expected_state = task_states.REBOOT_PENDING_HARD2558            instance.save(expected_task_state=expected_state)2559            self.driver.reboot(context, instance,2560                               network_info,2561                               reboot_type,2562                               block_device_info=block_device_info,2563                               bad_volumes_callback=bad_volumes_callback)2564        except Exception as error:2565            with excutils.save_and_reraise_exception() as ctxt:2566                exc_info = sys.exc_info()2567                # if the reboot failed but the VM is running don't2568                # put it into an error state2569                new_power_state = self._get_power_state(context, instance)2570                if new_power_state == power_state.RUNNING:2571                    LOG.warning(_('Reboot failed but instance is running'),2572                                context=context, instance=instance)2573                    compute_utils.add_instance_fault_from_exc(context,2574                            instance, error, exc_info)2575                    self._notify_about_instance_usage(context, instance,2576                            'reboot.error', fault=error)2577                    ctxt.reraise = False2578                else:2579                    LOG.error(_('Cannot reboot instance: %s'), error,2580                              context=context, instance=instance)2581                    self._set_instance_obj_error_state(context, instance)2582        if not new_power_state:2583            new_power_state = self._get_power_state(context, instance)2584        try:2585            instance.power_state = new_power_state2586            instance.vm_state = new_vm_state2587            instance.task_state = None2588            instance.save()2589        except exception.InstanceNotFound:2590            LOG.warn(_("Instance disappeared during reboot"),2591                     context=context, instance=instance)2592        self._notify_about_instance_usage(context, instance, "reboot.end")2593    @delete_image_on_error2594    def _do_snapshot_instance(self, context, image_id, instance, rotation):2595        if rotation < 0:2596            raise exception.RotationRequiredForBackup()2597        self._snapshot_instance(context, image_id, instance,2598                                task_states.IMAGE_BACKUP)2599    @wrap_exception()2600    @reverts_task_state2601    @wrap_instance_fault2602    def backup_instance(self, context, image_id, instance, backup_type,2603                        rotation):2604        """Backup an instance on this host.2605        :param backup_type: daily | weekly2606        :param rotation: int representing how many backups to keep around2607        """2608        self._do_snapshot_instance(context, image_id, instance, rotation)2609        self._rotate_backups(context, instance, backup_type, rotation)2610    @wrap_exception()2611    @reverts_task_state2612    @wrap_instance_fault2613    @delete_image_on_error2614    def snapshot_instance(self, context, image_id, instance):2615        """Snapshot an instance on this host.2616        :param context: security context2617        :param instance: a nova.objects.instance.Instance object2618        :param image_id: glance.db.sqlalchemy.models.Image.Id2619        """2620        # NOTE(dave-mcnally) the task state will already be set by the api2621        # but if the compute manager has crashed/been restarted prior to the2622        # request getting here the task state may have been cleared so we set2623        # it again and things continue normally2624        try:2625            instance.task_state = task_states.IMAGE_SNAPSHOT2626            instance.save(2627                        expected_task_state=task_states.IMAGE_SNAPSHOT_PENDING)2628        except exception.InstanceNotFound:2629            # possibility instance no longer exists, no point in continuing2630            LOG.debug("Instance not found, could not set state %s "2631                      "for instance.",2632                      task_states.IMAGE_SNAPSHOT, instance=instance)2633            return2634        except exception.UnexpectedDeletingTaskStateError:2635            LOG.debug("Instance being deleted, snapshot cannot continue",2636                      instance=instance)2637            return2638        self._snapshot_instance(context, image_id, instance,2639                                task_states.IMAGE_SNAPSHOT)2640    def _snapshot_instance(self, context, image_id, instance,2641                           expected_task_state):2642        context = context.elevated()2643        current_power_state = self._get_power_state(context, instance)2644        try:2645            instance.power_state = current_power_state2646            instance.save()2647            LOG.audit(_('instance snapshotting'), context=context,2648                  instance=instance)2649            if instance.power_state != power_state.RUNNING:2650                state = instance.power_state2651                running = power_state.RUNNING2652                LOG.warn(_('trying to snapshot a non-running instance: '2653                       '(state: %(state)s expected: %(running)s)'),2654                     {'state': state, 'running': running},2655                     instance=instance)2656            self._notify_about_instance_usage(2657                context, instance, "snapshot.start")2658            def update_task_state(task_state,2659                                  expected_state=expected_task_state):2660                instance.task_state = task_state2661                instance.save(expected_task_state=expected_state)2662            self.driver.snapshot(context, instance, image_id,2663                                 update_task_state)2664            instance.task_state = None2665            instance.save(expected_task_state=task_states.IMAGE_UPLOADING)2666            self._notify_about_instance_usage(context, instance,2667                                              "snapshot.end")2668        except (exception.InstanceNotFound,2669                exception.UnexpectedDeletingTaskStateError):2670            # the instance got deleted during the snapshot2671            # Quickly bail out of here2672            msg = 'Instance disappeared during snapshot'2673            LOG.debug(msg, instance=instance)2674            try:2675                image_service = glance.get_default_image_service()2676                image = image_service.show(context, image_id)2677                if image['status'] != 'active':2678                    image_service.delete(context, image_id)2679            except Exception:2680                LOG.warning(_("Error while trying to clean up image %s"),2681                            image_id, instance=instance)2682        except exception.ImageNotFound:2683            instance.task_state = None2684            instance.save()2685            msg = _("Image not found during snapshot")2686            LOG.warn(msg, instance=instance)2687    def _post_interrupted_snapshot_cleanup(self, context, instance):2688        self.driver.post_interrupted_snapshot_cleanup(context, instance)2689    @object_compat2690    @messaging.expected_exceptions(NotImplementedError)2691    def volume_snapshot_create(self, context, instance, volume_id,2692                               create_info):2693        self.driver.volume_snapshot_create(context, instance, volume_id,2694                                           create_info)2695    @object_compat2696    @messaging.expected_exceptions(NotImplementedError)2697    def volume_snapshot_delete(self, context, instance, volume_id,2698                               snapshot_id, delete_info):2699        self.driver.volume_snapshot_delete(context, instance, volume_id,2700                                           snapshot_id, delete_info)2701    @wrap_instance_fault2702    def _rotate_backups(self, context, instance, backup_type, rotation):2703        """Delete excess backups associated to an instance.2704        Instances are allowed a fixed number of backups (the rotation number);2705        this method deletes the oldest backups that exceed the rotation2706        threshold.2707        :param context: security context2708        :param instance: Instance dict2709        :param backup_type: daily | weekly2710        :param rotation: int representing how many backups to keep around;2711            None if rotation shouldn't be used (as in the case of snapshots)2712        """2713        filters = {'property-image_type': 'backup',2714                   'property-backup_type': backup_type,2715                   'property-instance_uuid': instance.uuid}2716        images = self.image_api.get_all(context, filters=filters,2717                                        sort_key='created_at', sort_dir='desc')2718        num_images = len(images)2719        LOG.debug("Found %(num_images)d images (rotation: %(rotation)d)",2720                  {'num_images': num_images, 'rotation': rotation},2721                  instance=instance)2722        if num_images > rotation:2723            # NOTE(sirp): this deletes all backups that exceed the rotation2724            # limit2725            excess = len(images) - rotation2726            LOG.debug("Rotating out %d backups", excess,2727                      instance=instance)2728            for i in xrange(excess):2729                image = images.pop()2730                image_id = image['id']2731                LOG.debug("Deleting image %s", image_id,2732                          instance=instance)2733                self.image_api.delete(context, image_id)2734    @object_compat2735    @wrap_exception()2736    @reverts_task_state2737    @wrap_instance_event2738    @wrap_instance_fault2739    def set_admin_password(self, context, instance, new_pass):2740        """Set the root/admin password for an instance on this host.2741        This is generally only called by API password resets after an2742        image has been built.2743        @param context: Nova auth context.2744        @param instance: Nova instance object.2745        @param new_pass: The admin password for the instance.2746        """2747        context = context.elevated()2748        if new_pass is None:2749            # Generate a random password2750            new_pass = utils.generate_password()2751        current_power_state = self._get_power_state(context, instance)2752        expected_state = power_state.RUNNING2753        if current_power_state != expected_state:2754            instance.task_state = None2755            instance.save(expected_task_state=task_states.UPDATING_PASSWORD)2756            _msg = _('Failed to set admin password. Instance %s is not'2757                     ' running') % instance.uuid2758            raise exception.InstancePasswordSetFailed(2759                instance=instance.uuid, reason=_msg)2760        try:2761            self.driver.set_admin_password(instance, new_pass)2762            LOG.audit(_("Root password set"), instance=instance)2763            instance.task_state = None2764            instance.save(2765                expected_task_state=task_states.UPDATING_PASSWORD)2766        except NotImplementedError:2767            _msg = _('set_admin_password is not implemented '2768                     'by this driver or guest instance.')2769            LOG.warn(_msg, instance=instance)2770            instance.task_state = None2771            instance.save(2772                expected_task_state=task_states.UPDATING_PASSWORD)2773            raise NotImplementedError(_msg)2774        except exception.UnexpectedTaskStateError:2775            # interrupted by another (most likely delete) task2776            # do not retry2777            raise2778        except Exception as e:2779            # Catch all here because this could be anything.2780            LOG.exception(_LE('set_admin_password failed: %s'), e,2781                          instance=instance)2782            self._set_instance_obj_error_state(context, instance)2783            # We create a new exception here so that we won't2784            # potentially reveal password information to the2785            # API caller.  The real exception is logged above2786            _msg = _('error setting admin password')2787            raise exception.InstancePasswordSetFailed(2788                instance=instance.uuid, reason=_msg)2789    @wrap_exception()2790    @reverts_task_state2791    @wrap_instance_fault2792    def inject_file(self, context, path, file_contents, instance):2793        """Write a file to the specified path in an instance on this host."""2794        # NOTE(russellb) Remove this method, as well as the underlying virt2795        # driver methods, when the compute rpc interface is bumped to 4.x2796        # as it is no longer used.2797        context = context.elevated()2798        current_power_state = self._get_power_state(context, instance)2799        expected_state = power_state.RUNNING2800        if current_power_state != expected_state:2801            LOG.warn(_('trying to inject a file into a non-running (state: '2802                       '%(current_state)s expected: %(expected_state)s)'),2803                     {'current_state': current_power_state,2804                      'expected_state': expected_state},2805                     instance=instance)2806        LOG.audit(_('injecting file to %s'), path,2807                    instance=instance)2808        self.driver.inject_file(instance, path, file_contents)2809    def _get_rescue_image(self, context, instance, rescue_image_ref=None):2810        """Determine what image should be used to boot the rescue VM."""2811        # 1. If rescue_image_ref is passed in, use that for rescue.2812        # 2. Else, use the base image associated with instance's current image.2813        #       The idea here is to provide the customer with a rescue2814        #       environment which they are familiar with.2815        #       So, if they built their instance off of a Debian image,2816        #       their rescue VM will also be Debian.2817        # 3. As a last resort, use instance's current image.2818        if not rescue_image_ref:2819            system_meta = utils.instance_sys_meta(instance)2820            rescue_image_ref = system_meta.get('image_base_image_ref')2821        if not rescue_image_ref:2822            LOG.warn(_('Unable to find a different image to use for rescue VM,'2823                       ' using instance\'s current image'), instance=instance)2824            rescue_image_ref = instance.image_ref2825        image_meta = compute_utils.get_image_metadata(context, self.image_api,2826                                                      rescue_image_ref,2827                                                      instance)2828        # NOTE(belliott) bug #1227350 - xenapi needs the actual image id2829        image_meta['id'] = rescue_image_ref2830        return image_meta2831    @object_compat2832    @wrap_exception()2833    @reverts_task_state2834    @wrap_instance_event2835    @wrap_instance_fault2836    def rescue_instance(self, context, instance, rescue_password,2837                        rescue_image_ref=None, clean_shutdown=True):2838        context = context.elevated()2839        LOG.audit(_('Rescuing'), context=context, instance=instance)2840        admin_password = (rescue_password if rescue_password else2841                      utils.generate_password())2842        network_info = self._get_instance_nw_info(context, instance)2843        rescue_image_meta = self._get_rescue_image(context, instance,2844                                                   rescue_image_ref)2845        extra_usage_info = {'rescue_image_name':2846                            rescue_image_meta.get('name', '')}2847        self._notify_about_instance_usage(context, instance,2848                "rescue.start", extra_usage_info=extra_usage_info,2849                network_info=network_info)2850        try:2851            self._power_off_instance(context, instance, clean_shutdown)2852            self.driver.rescue(context, instance,2853                               network_info,2854                               rescue_image_meta, admin_password)2855        except Exception as e:2856            LOG.exception(_LE("Error trying to Rescue Instance"),2857                          instance=instance)2858            raise exception.InstanceNotRescuable(2859                instance_id=instance.uuid,2860                reason=_("Driver Error: %s") % unicode(e))2861        self.conductor_api.notify_usage_exists(context, instance,2862                                               current_period=True)2863        current_power_state = self._get_power_state(context, instance)2864        instance.vm_state = vm_states.RESCUED2865        instance.task_state = None2866        instance.power_state = current_power_state2867        instance.launched_at = timeutils.utcnow()2868        instance.save(expected_task_state=task_states.RESCUING)2869        self._notify_about_instance_usage(context, instance,2870                "rescue.end", extra_usage_info=extra_usage_info,2871                network_info=network_info)2872    @object_compat2873    @wrap_exception()2874    @reverts_task_state2875    @wrap_instance_event2876    @wrap_instance_fault2877    def unrescue_instance(self, context, instance):2878        context = context.elevated()2879        LOG.audit(_('Unrescuing'), context=context, instance=instance)2880        network_info = self._get_instance_nw_info(context, instance)2881        self._notify_about_instance_usage(context, instance,2882                "unrescue.start", network_info=network_info)2883        with self._error_out_instance_on_exception(context, instance):2884            self.driver.unrescue(instance,2885                                 network_info)2886        current_power_state = self._get_power_state(context, instance)2887        instance.vm_state = vm_states.ACTIVE2888        instance.task_state = None2889        instance.power_state = current_power_state2890        instance.save(expected_task_state=task_states.UNRESCUING)2891        self._notify_about_instance_usage(context,2892                                          instance,2893                                          "unrescue.end",2894                                          network_info=network_info)2895    @object_compat2896    @wrap_exception()2897    @wrap_instance_fault2898    def change_instance_metadata(self, context, diff, instance):2899        """Update the metadata published to the instance."""2900        LOG.debug("Changing instance metadata according to %r",2901                  diff, instance=instance)2902        self.driver.change_instance_metadata(context, instance, diff)2903    def _cleanup_stored_instance_types(self, migration, instance,2904                                       restore_old=False):2905        """Clean up "old" and "new" instance_type information stored in2906        instance's system_metadata. Optionally update the "current"2907        instance_type to the saved old one first.2908        Returns the updated system_metadata as a dict, the2909        post-cleanup current instance type and the to-be dropped2910        instance type.2911        """2912        sys_meta = instance.system_metadata2913        if restore_old:2914            instance_type = flavors.extract_flavor(instance, 'old_')2915            drop_instance_type = flavors.extract_flavor(instance)2916            sys_meta = flavors.save_flavor_info(sys_meta, instance_type)2917        else:2918            instance_type = flavors.extract_flavor(instance)2919            drop_instance_type = flavors.extract_flavor(instance, 'old_')2920        flavors.delete_flavor_info(sys_meta, 'old_')2921        flavors.delete_flavor_info(sys_meta, 'new_')2922        return sys_meta, instance_type, drop_instance_type2923    @wrap_exception()2924    @wrap_instance_event2925    @wrap_instance_fault2926    def confirm_resize(self, context, instance, reservations, migration):2927        quotas = objects.Quotas.from_reservations(context,2928                                                  reservations,2929                                                  instance=instance)2930        @utils.synchronized(instance['uuid'])2931        def do_confirm_resize(context, instance, migration_id):2932            # NOTE(wangpan): Get the migration status from db, if it has been2933            #                confirmed, we do nothing and return here2934            LOG.debug("Going to confirm migration %s", migration_id,2935                      context=context, instance=instance)2936            try:2937                # TODO(russellb) Why are we sending the migration object just2938                # to turn around and look it up from the db again?2939                migration = objects.Migration.get_by_id(2940                                    context.elevated(), migration_id)2941            except exception.MigrationNotFound:2942                LOG.error(_("Migration %s is not found during confirmation") %2943                            migration_id, context=context, instance=instance)2944                quotas.rollback()2945                return2946            if migration.status == 'confirmed':2947                LOG.info(_("Migration %s is already confirmed") %2948                            migration_id, context=context, instance=instance)2949                quotas.rollback()2950                return2951            elif migration.status not in ('finished', 'confirming'):2952                LOG.warn(_("Unexpected confirmation status '%(status)s' of "2953                           "migration %(id)s, exit confirmation process") %2954                           {"status": migration.status, "id": migration_id},2955                           context=context, instance=instance)2956                quotas.rollback()2957                return2958            # NOTE(wangpan): Get the instance from db, if it has been2959            #                deleted, we do nothing and return here2960            expected_attrs = ['metadata', 'system_metadata']2961            try:2962                instance = objects.Instance.get_by_uuid(2963                        context, instance.uuid,2964                        expected_attrs=expected_attrs)2965            except exception.InstanceNotFound:2966                LOG.info(_("Instance is not found during confirmation"),2967                            context=context, instance=instance)2968                quotas.rollback()2969                return2970            self._confirm_resize(context, instance, quotas,2971                                 migration=migration)2972        do_confirm_resize(context, instance, migration.id)2973    def _confirm_resize(self, context, instance, quotas,2974                        migration=None):2975        """Destroys the source instance."""2976        self._notify_about_instance_usage(context, instance,2977                                          "resize.confirm.start")2978        with self._error_out_instance_on_exception(context, instance,2979                                                   quotas=quotas):2980            # NOTE(danms): delete stashed migration information2981            sys_meta, instance_type, old_instance_type = (2982                self._cleanup_stored_instance_types(migration, instance))2983            sys_meta.pop('old_vm_state', None)2984            instance.system_metadata = sys_meta2985            instance.save()2986            # NOTE(tr3buchet): tear down networks on source host2987            self.network_api.setup_networks_on_host(context, instance,2988                               migration.source_compute, teardown=True)2989            network_info = self._get_instance_nw_info(context, instance)2990            self.driver.confirm_migration(migration, instance,2991                                          network_info)2992            migration.status = 'confirmed'2993            migration.save(context.elevated())2994            rt = self._get_resource_tracker(migration.source_node)2995            rt.drop_resize_claim(context, instance, old_instance_type)2996            # NOTE(mriedem): The old_vm_state could be STOPPED but the user2997            # might have manually powered up the instance to confirm the2998            # resize/migrate, so we need to check the current power state2999            # on the instance and set the vm_state appropriately. We default3000            # to ACTIVE because if the power state is not SHUTDOWN, we3001            # assume _sync_instance_power_state will clean it up.3002            p_state = instance.power_state3003            vm_state = None3004            if p_state == power_state.SHUTDOWN:3005                vm_state = vm_states.STOPPED3006                LOG.debug("Resized/migrated instance is powered off. "3007                          "Setting vm_state to '%s'.", vm_state,3008                          instance=instance)3009            else:3010                vm_state = vm_states.ACTIVE3011            instance.vm_state = vm_state3012            instance.task_state = None3013            instance.save(expected_task_state=[None, task_states.DELETING])3014            self._notify_about_instance_usage(3015                context, instance, "resize.confirm.end",3016                network_info=network_info)3017            quotas.commit()3018    @wrap_exception()3019    @reverts_task_state3020    @wrap_instance_event3021    @wrap_instance_fault3022    def revert_resize(self, context, instance, migration, reservations):3023        """Destroys the new instance on the destination machine.3024        Reverts the model changes, and powers on the old instance on the3025        source machine.3026        """3027        quotas = quotas_obj.Quotas.from_reservations(context,3028                                                     reservations,3029                                                     instance=instance)3030        # NOTE(comstud): A revert_resize is essentially a resize back to3031        # the old size, so we need to send a usage event here.3032        self.conductor_api.notify_usage_exists(3033                context, instance, current_period=True)3034        with self._error_out_instance_on_exception(context, instance,3035                                                   quotas=quotas):3036            # NOTE(tr3buchet): tear down networks on destination host3037            self.network_api.setup_networks_on_host(context, instance,3038                                                    teardown=True)3039            instance_p = obj_base.obj_to_primitive(instance)3040            migration_p = obj_base.obj_to_primitive(migration)3041            self.network_api.migrate_instance_start(context,3042                                                    instance_p,3043                                                    migration_p)3044            network_info = self._get_instance_nw_info(context, instance)3045            bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(3046                    context, instance.uuid)3047            block_device_info = self._get_instance_block_device_info(3048                                context, instance, bdms=bdms)3049            self.driver.destroy(context, instance, network_info,3050                                block_device_info)3051            self._terminate_volume_connections(context, instance, bdms)3052            migration.status = 'reverted'3053            migration.save(context.elevated())3054            rt = self._get_resource_tracker(instance.node)3055            rt.drop_resize_claim(context, instance)3056            self.compute_rpcapi.finish_revert_resize(context, instance,3057                    migration, migration.source_compute,3058                    quotas.reservations)3059    @wrap_exception()3060    @reverts_task_state3061    @wrap_instance_event3062    @wrap_instance_fault3063    def finish_revert_resize(self, context, instance, reservations, migration):3064        """Finishes the second half of reverting a resize.3065        Bring the original source instance state back (active/shutoff) and3066        revert the resized attributes in the database.3067        """3068        quotas = quotas_obj.Quotas.from_reservations(context,3069                                                     reservations,3070                                                     instance=instance)3071        with self._error_out_instance_on_exception(context, instance,3072                                                   quotas=quotas):3073            network_info = self._get_instance_nw_info(context, instance)3074            self._notify_about_instance_usage(3075                    context, instance, "resize.revert.start")3076            sys_meta, instance_type, drop_instance_type = (3077                self._cleanup_stored_instance_types(migration, instance, True))3078            # NOTE(mriedem): delete stashed old_vm_state information; we3079            # default to ACTIVE for backwards compatibility if old_vm_state3080            # is not set3081            old_vm_state = sys_meta.pop('old_vm_state', vm_states.ACTIVE)3082            instance.system_metadata = sys_meta3083            instance.memory_mb = instance_type['memory_mb']3084            instance.vcpus = instance_type['vcpus']3085            instance.root_gb = instance_type['root_gb']3086            instance.ephemeral_gb = instance_type['ephemeral_gb']3087            instance.instance_type_id = instance_type['id']3088            instance.host = migration['source_compute']3089            instance.node = migration['source_node']3090            instance.save()3091            self.network_api.setup_networks_on_host(context, instance,3092                                            migration['source_compute'])3093            block_device_info = self._get_instance_block_device_info(3094                    context, instance, refresh_conn_info=True)3095            power_on = old_vm_state != vm_states.STOPPED3096            self.driver.finish_revert_migration(context, instance,3097                                       network_info,3098                                       block_device_info, power_on)3099            instance.launched_at = timeutils.utcnow()3100            instance.save(expected_task_state=task_states.RESIZE_REVERTING)3101            instance_p = obj_base.obj_to_primitive(instance)3102            migration_p = obj_base.obj_to_primitive(migration)3103            self.network_api.migrate_instance_finish(context,3104                                                     instance_p,3105                                                     migration_p)3106            # if the original vm state was STOPPED, set it back to STOPPED3107            LOG.info(_("Updating instance to original state: '%s'") %3108                     old_vm_state)3109            if power_on:3110                instance.vm_state = vm_states.ACTIVE3111                instance.task_state = None3112                instance.save()3113            else:3114                instance.task_state = task_states.POWERING_OFF3115                instance.save()3116                self.stop_instance(context, instance=instance)3117            self._notify_about_instance_usage(3118                    context, instance, "resize.revert.end")3119            quotas.commit()3120    def _prep_resize(self, context, image, instance, instance_type,3121            quotas, request_spec, filter_properties, node):3122        if not filter_properties:3123            filter_properties = {}3124        if not instance['host']:3125            self._set_instance_error_state(context, instance)3126            msg = _('Instance has no source host')3127            raise exception.MigrationError(msg)3128        same_host = instance['host'] == self.host3129        if same_host and not CONF.allow_resize_to_same_host:3130            self._set_instance_error_state(context, instance)3131            msg = _('destination same as source!')3132            raise exception.MigrationError(msg)3133        # NOTE(danms): Stash the new instance_type to avoid having to3134        # look it up in the database later3135        sys_meta = instance.system_metadata3136        flavors.save_flavor_info(sys_meta, instance_type, prefix='new_')3137        # NOTE(mriedem): Stash the old vm_state so we can set the3138        # resized/reverted instance back to the same state later.3139        vm_state = instance['vm_state']3140        LOG.debug('Stashing vm_state: %s', vm_state, instance=instance)3141        sys_meta['old_vm_state'] = vm_state3142        instance.save()3143        limits = filter_properties.get('limits', {})3144        rt = self._get_resource_tracker(node)3145        with rt.resize_claim(context, instance, instance_type,3146                             image_meta=image, limits=limits) as claim:3147            LOG.audit(_('Migrating'), context=context, instance=instance)3148            self.compute_rpcapi.resize_instance(3149                    context, instance, claim.migration, image,3150                    instance_type, quotas.reservations)3151    @wrap_exception()3152    @reverts_task_state3153    @wrap_instance_event3154    @wrap_instance_fault3155    def prep_resize(self, context, image, instance, instance_type,3156                    reservations, request_spec, filter_properties, node):3157        """Initiates the process of moving a running instance to another host.3158        Possibly changes the RAM and disk size in the process.3159        """3160        if node is None:3161            node = self.driver.get_available_nodes(refresh=True)[0]3162            LOG.debug("No node specified, defaulting to %s", node,3163                      instance=instance)3164        quotas = quotas_obj.Quotas.from_reservations(context,3165                                                     reservations,3166                                                     instance=instance)3167        with self._error_out_instance_on_exception(context, instance,3168                                                   quotas=quotas):3169            self.conductor_api.notify_usage_exists(3170                    context, instance, current_period=True)3171            self._notify_about_instance_usage(3172                    context, instance, "resize.prep.start")3173            try:3174                self._prep_resize(context, image, instance,3175                                  instance_type, quotas,3176                                  request_spec, filter_properties,3177                                  node)3178            # NOTE(dgenin): This is thrown in LibvirtDriver when the3179            #               instance to be migrated is backed by LVM.3180            #               Remove when LVM migration is implemented.3181            except exception.MigrationPreCheckError:3182                raise3183            except Exception:3184                # try to re-schedule the resize elsewhere:3185                exc_info = sys.exc_info()3186                self._reschedule_resize_or_reraise(context, image, instance,3187                        exc_info, instance_type, quotas, request_spec,3188                        filter_properties)3189            finally:3190                extra_usage_info = dict(3191                        new_instance_type=instance_type['name'],3192                        new_instance_type_id=instance_type['id'])3193                self._notify_about_instance_usage(3194                    context, instance, "resize.prep.end",3195                    extra_usage_info=extra_usage_info)3196    def _reschedule_resize_or_reraise(self, context, image, instance, exc_info,3197            instance_type, quotas, request_spec, filter_properties):3198        """Try to re-schedule the resize or re-raise the original error to3199        error out the instance.3200        """3201        if not request_spec:3202            request_spec = {}3203        if not filter_properties:3204            filter_properties = {}3205        rescheduled = False3206        instance_uuid = instance['uuid']3207        try:3208            reschedule_method = self.compute_task_api.resize_instance3209            scheduler_hint = dict(filter_properties=filter_properties)3210            method_args = (instance, None, scheduler_hint, instance_type,3211                           quotas.reservations)3212            task_state = task_states.RESIZE_PREP3213            rescheduled = self._reschedule(context, request_spec,3214                    filter_properties, instance, reschedule_method,3215                    method_args, task_state, exc_info)3216        except Exception as error:3217            rescheduled = False3218            LOG.exception(_LE("Error trying to reschedule"),3219                          instance_uuid=instance_uuid)3220            compute_utils.add_instance_fault_from_exc(context,3221                    instance, error,3222                    exc_info=sys.exc_info())3223            self._notify_about_instance_usage(context, instance,3224                    'resize.error', fault=error)3225        if rescheduled:3226            self._log_original_error(exc_info, instance_uuid)3227            compute_utils.add_instance_fault_from_exc(context,3228                    instance, exc_info[1], exc_info=exc_info)3229            self._notify_about_instance_usage(context, instance,3230                    'resize.error', fault=exc_info[1])3231        else:3232            # not re-scheduling3233            raise exc_info[0], exc_info[1], exc_info[2]3234    @wrap_exception()3235    @reverts_task_state3236    @wrap_instance_event3237    @errors_out_migration3238    @wrap_instance_fault3239    def resize_instance(self, context, instance, image,3240                        reservations, migration, instance_type,3241                        clean_shutdown=True):3242        """Starts the migration of a running instance to another host."""3243        quotas = quotas_obj.Quotas.from_reservations(context,3244                                                     reservations,3245                                                     instance=instance)3246        with self._error_out_instance_on_exception(context, instance,3247                                                   quotas=quotas):3248            if not instance_type:3249                instance_type = objects.Flavor.get_by_id(3250                    context, migration['new_instance_type_id'])3251            network_info = self._get_instance_nw_info(context, instance)3252            migration.status = 'migrating'3253            migration.save(context.elevated())3254            instance.task_state = task_states.RESIZE_MIGRATING3255            instance.save(expected_task_state=task_states.RESIZE_PREP)3256            self._notify_about_instance_usage(3257                context, instance, "resize.start", network_info=network_info)3258            bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(3259                    context, instance.uuid)3260            block_device_info = self._get_instance_block_device_info(3261                                context, instance, bdms=bdms)3262            timeout, retry_interval = self._get_power_off_values(context,3263                                            instance, clean_shutdown)3264            disk_info = self.driver.migrate_disk_and_power_off(3265                    context, instance, migration.dest_host,3266                    instance_type, network_info,3267                    block_device_info,3268                    timeout, retry_interval)3269            self._terminate_volume_connections(context, instance, bdms)3270            migration_p = obj_base.obj_to_primitive(migration)3271            instance_p = obj_base.obj_to_primitive(instance)3272            self.network_api.migrate_instance_start(context,3273                                                    instance_p,3274                                                    migration_p)3275            migration.status = 'post-migrating'3276            migration.save(context.elevated())3277            instance.host = migration.dest_compute3278            instance.node = migration.dest_node3279            instance.task_state = task_states.RESIZE_MIGRATED3280            instance.save(expected_task_state=task_states.RESIZE_MIGRATING)3281            self.compute_rpcapi.finish_resize(context, instance,3282                    migration, image, disk_info,3283                    migration.dest_compute, reservations=quotas.reservations)3284            self._notify_about_instance_usage(context, instance, "resize.end",3285                                              network_info=network_info)3286            self.instance_events.clear_events_for_instance(instance)3287    def _terminate_volume_connections(self, context, instance, bdms):3288        connector = self.driver.get_volume_connector(instance)3289        for bdm in bdms:3290            if bdm.is_volume:3291                self.volume_api.terminate_connection(context, bdm.volume_id,3292                                                     connector)3293    @staticmethod3294    def _save_instance_info(instance, instance_type, sys_meta):3295        flavors.save_flavor_info(sys_meta, instance_type)3296        instance.instance_type_id = instance_type['id']3297        instance.memory_mb = instance_type['memory_mb']3298        instance.vcpus = instance_type['vcpus']3299        instance.root_gb = instance_type['root_gb']3300        instance.ephemeral_gb = instance_type['ephemeral_gb']3301        instance.system_metadata = sys_meta3302        instance.save()3303    def _finish_resize(self, context, instance, migration, disk_info,3304                       image):3305        resize_instance = False3306        old_instance_type_id = migration['old_instance_type_id']3307        new_instance_type_id = migration['new_instance_type_id']3308        old_instance_type = flavors.extract_flavor(instance)3309        sys_meta = instance.system_metadata3310        # NOTE(mriedem): Get the old_vm_state so we know if we should3311        # power on the instance. If old_vm_state is not set we need to default3312        # to ACTIVE for backwards compatibility3313        old_vm_state = sys_meta.get('old_vm_state', vm_states.ACTIVE)3314        flavors.save_flavor_info(sys_meta,3315                                 old_instance_type,3316                                 prefix='old_')3317        if old_instance_type_id != new_instance_type_id:3318            instance_type = flavors.extract_flavor(instance, prefix='new_')3319            self._save_instance_info(instance, instance_type, sys_meta)3320            resize_instance = True3321        # NOTE(tr3buchet): setup networks on destination host3322        self.network_api.setup_networks_on_host(context, instance,3323                                                migration['dest_compute'])3324        instance_p = obj_base.obj_to_primitive(instance)3325        migration_p = obj_base.obj_to_primitive(migration)3326        self.network_api.migrate_instance_finish(context,3327                                                 instance_p,3328                                                 migration_p)3329        network_info = self._get_instance_nw_info(context, instance)3330        instance.task_state = task_states.RESIZE_FINISH3331        instance.system_metadata = sys_meta3332        instance.save(expected_task_state=task_states.RESIZE_MIGRATED)3333        self._notify_about_instance_usage(3334            context, instance, "finish_resize.start",3335            network_info=network_info)3336        block_device_info = self._get_instance_block_device_info(3337                            context, instance, refresh_conn_info=True)3338        # NOTE(mriedem): If the original vm_state was STOPPED, we don't3339        # automatically power on the instance after it's migrated3340        power_on = old_vm_state != vm_states.STOPPED3341        try:3342            self.driver.finish_migration(context, migration, instance,3343                                         disk_info,3344                                         network_info,3345                                         image, resize_instance,3346                                         block_device_info, power_on)3347        except Exception:3348            with excutils.save_and_reraise_exception():3349                if resize_instance:3350                    self._save_instance_info(instance,3351                                             old_instance_type, sys_meta)3352        migration.status = 'finished'3353        migration.save(context.elevated())3354        instance.vm_state = vm_states.RESIZED3355        instance.task_state = None3356        instance.launched_at = timeutils.utcnow()3357        instance.save(expected_task_state=task_states.RESIZE_FINISH)3358        self._notify_about_instance_usage(3359            context, instance, "finish_resize.end",3360            network_info=network_info)3361    @wrap_exception()3362    @reverts_task_state3363    @wrap_instance_event3364    @errors_out_migration3365    @wrap_instance_fault3366    def finish_resize(self, context, disk_info, image, instance,3367                      reservations, migration):3368        """Completes the migration process.3369        Sets up the newly transferred disk and turns on the instance at its3370        new host machine.3371        """3372        quotas = quotas_obj.Quotas.from_reservations(context,3373                                                     reservations,3374                                                     instance=instance)3375        try:3376            self._finish_resize(context, instance, migration,3377                                disk_info, image)3378            quotas.commit()3379        except Exception:3380            LOG.exception(_LE('Setting instance vm_state to ERROR'),3381                          instance=instance)3382            with excutils.save_and_reraise_exception():3383                try:3384                    quotas.rollback()3385                except Exception as qr_error:3386                    LOG.exception(_LE("Failed to rollback quota for failed "3387                                      "finish_resize: %s"),3388                                  qr_error, instance=instance)3389                self._set_instance_error_state(context, instance)3390    @object_compat3391    @wrap_exception()3392    @wrap_instance_fault3393    def add_fixed_ip_to_instance(self, context, network_id, instance):3394        """Calls network_api to add new fixed_ip to instance3395        then injects the new network info and resets instance networking.3396        """3397        self._notify_about_instance_usage(3398                context, instance, "create_ip.start")3399        network_info = self.network_api.add_fixed_ip_to_instance(context,3400                                                                 instance,3401                                                                 network_id)3402        self._inject_network_info(context, instance, network_info)3403        self.reset_network(context, instance)3404        # NOTE(russellb) We just want to bump updated_at.  See bug 1143466.3405        instance.updated_at = timeutils.utcnow()3406        instance.save()3407        self._notify_about_instance_usage(3408            context, instance, "create_ip.end", network_info=network_info)3409    @object_compat3410    @wrap_exception()3411    @wrap_instance_fault3412    def remove_fixed_ip_from_instance(self, context, address, instance):3413        """Calls network_api to remove existing fixed_ip from instance3414        by injecting the altered network info and resetting3415        instance networking.3416        """3417        self._notify_about_instance_usage(3418                context, instance, "delete_ip.start")3419        network_info = self.network_api.remove_fixed_ip_from_instance(context,3420                                                                      instance,3421                                                                      address)3422        self._inject_network_info(context, instance, network_info)3423        self.reset_network(context, instance)3424        # NOTE(russellb) We just want to bump updated_at.  See bug 1143466.3425        instance.updated_at = timeutils.utcnow()3426        instance.save()3427        self._notify_about_instance_usage(3428            context, instance, "delete_ip.end", network_info=network_info)3429    @wrap_exception()3430    @reverts_task_state3431    @wrap_instance_event3432    @wrap_instance_fault3433    def pause_instance(self, context, instance):3434        """Pause an instance on this host."""3435        context = context.elevated()3436        LOG.audit(_('Pausing'), context=context, instance=instance)3437        self._notify_about_instance_usage(context, instance, 'pause.start')3438        self.driver.pause(instance)3439        current_power_state = self._get_power_state(context, instance)3440        instance.power_state = current_power_state3441        instance.vm_state = vm_states.PAUSED3442        instance.task_state = None3443        instance.save(expected_task_state=task_states.PAUSING)3444        self._notify_about_instance_usage(context, instance, 'pause.end')3445    @wrap_exception()3446    @reverts_task_state3447    @wrap_instance_event3448    @wrap_instance_fault3449    def unpause_instance(self, context, instance):3450        """Unpause a paused instance on this host."""3451        context = context.elevated()3452        LOG.audit(_('Unpausing'), context=context, instance=instance)3453        self._notify_about_instance_usage(context, instance, 'unpause.start')3454        self.driver.unpause(instance)3455        current_power_state = self._get_power_state(context, instance)3456        instance.power_state = current_power_state3457        instance.vm_state = vm_states.ACTIVE3458        instance.task_state = None3459        instance.save(expected_task_state=task_states.UNPAUSING)3460        self._notify_about_instance_usage(context, instance, 'unpause.end')3461    @wrap_exception()3462    def host_power_action(self, context, action):3463        """Reboots, shuts down or powers up the host."""3464        # TODO(russellb) Remove the unused host parameter from the driver API3465        return self.driver.host_power_action(None, action)3466    @wrap_exception()3467    def host_maintenance_mode(self, context, host, mode):3468        """Start/Stop host maintenance window. On start, it triggers3469        guest VMs evacuation.3470        """3471        return self.driver.host_maintenance_mode(host, mode)3472    @wrap_exception()3473    def set_host_enabled(self, context, enabled):3474        """Sets the specified host's ability to accept new instances."""3475        # TODO(russellb) Remove the unused host parameter from the driver API3476        return self.driver.set_host_enabled(None, enabled)3477    @wrap_exception()3478    def get_host_uptime(self, context):3479        """Returns the result of calling "uptime" on the target host."""3480        return self.driver.get_host_uptime(self.host)3481    @object_compat3482    @wrap_exception()3483    @wrap_instance_fault3484    def get_diagnostics(self, context, instance):3485        """Retrieve diagnostics for an instance on this host."""3486        current_power_state = self._get_power_state(context, instance)3487        if current_power_state == power_state.RUNNING:3488            LOG.audit(_("Retrieving diagnostics"), context=context,3489                      instance=instance)3490            return self.driver.get_diagnostics(instance)3491        else:3492            raise exception.InstanceInvalidState(3493                attr='power_state',3494                instance_uuid=instance.uuid,3495                state=instance.power_state,3496                method='get_diagnostics')3497    @object_compat3498    @wrap_exception()3499    @wrap_instance_fault3500    def get_instance_diagnostics(self, context, instance):3501        """Retrieve diagnostics for an instance on this host."""3502        current_power_state = self._get_power_state(context, instance)3503        if current_power_state == power_state.RUNNING:3504            LOG.audit(_("Retrieving diagnostics"), context=context,3505                      instance=instance)3506            diags = self.driver.get_instance_diagnostics(instance)3507            return diags.serialize()3508        else:3509            raise exception.InstanceInvalidState(3510                attr='power_state',3511                instance_uuid=instance.uuid,3512                state=instance.power_state,3513                method='get_diagnostics')3514    @wrap_exception()3515    @reverts_task_state3516    @wrap_instance_event3517    @wrap_instance_fault3518    def suspend_instance(self, context, instance):3519        """Suspend the given instance."""3520        context = context.elevated()3521        # Store the old state3522        instance.system_metadata['old_vm_state'] = instance.vm_state3523        with self._error_out_instance_on_exception(context, instance,3524             instance_state=instance['vm_state']):3525            self.driver.suspend(instance)3526        current_power_state = self._get_power_state(context, instance)3527        instance.power_state = current_power_state3528        instance.vm_state = vm_states.SUSPENDED3529        instance.task_state = None3530        instance.save(expected_task_state=task_states.SUSPENDING)3531        self._notify_about_instance_usage(context, instance, 'suspend')3532    @wrap_exception()3533    @reverts_task_state3534    @wrap_instance_event3535    @wrap_instance_fault3536    def resume_instance(self, context, instance):3537        """Resume the given suspended instance."""3538        context = context.elevated()3539        LOG.audit(_('Resuming'), context=context, instance=instance)3540        network_info = self._get_instance_nw_info(context, instance)3541        block_device_info = self._get_instance_block_device_info(3542                            context, instance)3543        self.driver.resume(context, instance, network_info,3544                           block_device_info)3545        instance.power_state = self._get_power_state(context, instance)3546        # We default to the ACTIVE state for backwards compatibility3547        instance.vm_state = instance.system_metadata.pop('old_vm_state',3548                                                         vm_states.ACTIVE)3549        instance.task_state = None3550        instance.save(expected_task_state=task_states.RESUMING)3551        self._notify_about_instance_usage(context, instance, 'resume')3552    @wrap_exception()3553    @reverts_task_state3554    @wrap_instance_event3555    @wrap_instance_fault3556    def shelve_instance(self, context, instance, image_id,3557                        clean_shutdown=True):3558        """Shelve an instance.3559        This should be used when you want to take a snapshot of the instance.3560        It also adds system_metadata that can be used by a periodic task to3561        offload the shelved instance after a period of time.3562        :param context: request context3563        :param instance: an Instance object3564        :param image_id: an image id to snapshot to.3565        """3566        self.conductor_api.notify_usage_exists(3567            context, obj_base.obj_to_primitive(instance),3568            current_period=True)3569        self._notify_about_instance_usage(context, instance, 'shelve.start')3570        def update_task_state(task_state, expected_state=task_states.SHELVING):3571            shelving_state_map = {3572                    task_states.IMAGE_PENDING_UPLOAD:3573                        task_states.SHELVING_IMAGE_PENDING_UPLOAD,3574                    task_states.IMAGE_UPLOADING:3575                        task_states.SHELVING_IMAGE_UPLOADING,3576                    task_states.SHELVING: task_states.SHELVING}3577            task_state = shelving_state_map[task_state]3578            expected_state = shelving_state_map[expected_state]3579            instance.task_state = task_state3580            instance.save(expected_task_state=expected_state)3581        self._power_off_instance(context, instance, clean_shutdown)3582        current_power_state = self._get_power_state(context, instance)3583        self.driver.snapshot(context, instance, image_id, update_task_state)3584        instance.system_metadata['shelved_at'] = timeutils.strtime()3585        instance.system_metadata['shelved_image_id'] = image_id3586        instance.system_metadata['shelved_host'] = self.host3587        instance.vm_state = vm_states.SHELVED3588        instance.task_state = None3589        if CONF.shelved_offload_time == 0:3590            instance.task_state = task_states.SHELVING_OFFLOADING3591        instance.power_state = current_power_state3592        instance.save(expected_task_state=[3593                task_states.SHELVING,3594                task_states.SHELVING_IMAGE_UPLOADING])3595        self._notify_about_instance_usage(context, instance, 'shelve.end')3596        if CONF.shelved_offload_time == 0:3597            self.shelve_offload_instance(context, instance)3598    @wrap_exception()3599    @reverts_task_state3600    @wrap_instance_fault3601    def shelve_offload_instance(self, context, instance):3602        """Remove a shelved instance from the hypervisor.3603        This frees up those resources for use by other instances, but may lead3604        to slower unshelve times for this instance.  This method is used by3605        volume backed instances since restoring them doesn't involve the3606        potentially large download of an image.3607        :param context: request context3608        :param instance: nova.objects.instance.Instance3609        """3610        self._notify_about_instance_usage(context, instance,3611                'shelve_offload.start')3612        self.driver.power_off(instance)3613        current_power_state = self._get_power_state(context, instance)3614        network_info = self._get_instance_nw_info(context, instance)3615        block_device_info = self._get_instance_block_device_info(context,3616                                                                 instance)3617        self.driver.destroy(context, instance, network_info,3618                block_device_info)3619        instance.power_state = current_power_state3620        instance.host = None3621        instance.node = None3622        instance.vm_state = vm_states.SHELVED_OFFLOADED3623        instance.task_state = None3624        instance.save(expected_task_state=[task_states.SHELVING,3625                                           task_states.SHELVING_OFFLOADING])3626        self._notify_about_instance_usage(context, instance,3627                'shelve_offload.end')3628    @wrap_exception()3629    @reverts_task_state3630    @wrap_instance_event3631    @wrap_instance_fault3632    def unshelve_instance(self, context, instance, image,3633                          filter_properties=None, node=None):3634        """Unshelve the instance.3635        :param context: request context3636        :param instance: a nova.objects.instance.Instance object3637        :param image: an image to build from.  If None we assume a3638            volume backed instance.3639        :param filter_properties: dict containing limits, retry info etc.3640        :param node: target compute node3641        """3642        if filter_properties is None:3643            filter_properties = {}3644        @utils.synchronized(instance['uuid'])3645        def do_unshelve_instance():3646            self._unshelve_instance(context, instance, image,3647                                    filter_properties, node)3648        do_unshelve_instance()3649    def _unshelve_instance_key_scrub(self, instance):3650        """Remove data from the instance that may cause side effects."""3651        cleaned_keys = dict(3652                key_data=instance.key_data,3653                auto_disk_config=instance.auto_disk_config)3654        instance.key_data = None3655        instance.auto_disk_config = False3656        return cleaned_keys3657    def _unshelve_instance_key_restore(self, instance, keys):3658        """Restore previously scrubbed keys before saving the instance."""3659        instance.update(keys)3660    def _unshelve_instance(self, context, instance, image, filter_properties,3661                           node):3662        self._notify_about_instance_usage(context, instance, 'unshelve.start')3663        instance.task_state = task_states.SPAWNING3664        instance.save()3665        bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(3666                context, instance.uuid)3667        block_device_info = self._prep_block_device(context, instance, bdms,3668                                                    do_check_attach=False)3669        scrubbed_keys = self._unshelve_instance_key_scrub(instance)3670        if node is None:3671            node = self.driver.get_available_nodes()[0]3672            LOG.debug('No node specified, defaulting to %s', node,3673                      instance=instance)3674        rt = self._get_resource_tracker(node)3675        limits = filter_properties.get('limits', {})3676        if image:3677            shelved_image_ref = instance.image_ref3678            instance.image_ref = image['id']3679        self.network_api.migrate_instance_finish(context, instance,3680            {'source_compute': '', 'dest_compute': self.host})3681        network_info = self._get_instance_nw_info(context, instance)3682        try:3683            with rt.instance_claim(context, instance, limits):3684                self.driver.spawn(context, instance, image, injected_files=[],3685                                  admin_password=None,3686                                  network_info=network_info,3687                                  block_device_info=block_device_info)3688        except Exception:3689            with excutils.save_and_reraise_exception():3690                LOG.exception(_LE('Instance failed to spawn'),3691                              instance=instance)3692        if image:3693            instance.image_ref = shelved_image_ref3694            self.image_api.delete(context, image['id'])3695        self._unshelve_instance_key_restore(instance, scrubbed_keys)3696        instance.power_state = self._get_power_state(context, instance)3697        instance.vm_state = vm_states.ACTIVE3698        instance.task_state = None3699        instance.launched_at = timeutils.utcnow()3700        instance.save(expected_task_state=task_states.SPAWNING)3701        self._notify_about_instance_usage(context, instance, 'unshelve.end')3702    @messaging.expected_exceptions(NotImplementedError)3703    @wrap_instance_fault3704    def reset_network(self, context, instance):3705        """Reset networking on the given instance."""3706        LOG.debug('Reset network', context=context, instance=instance)3707        self.driver.reset_network(instance)3708    def _inject_network_info(self, context, instance, network_info):3709        """Inject network info for the given instance."""3710        LOG.debug('Inject network info', context=context, instance=instance)3711        LOG.debug('network_info to inject: |%s|', network_info,3712                  instance=instance)3713        self.driver.inject_network_info(instance,3714                                        network_info)3715    @wrap_instance_fault3716    def inject_network_info(self, context, instance):3717        """Inject network info, but don't return the info."""3718        network_info = self._get_instance_nw_info(context, instance)3719        self._inject_network_info(context, instance, network_info)3720    @object_compat3721    @messaging.expected_exceptions(NotImplementedError,3722                                   exception.InstanceNotFound)3723    @wrap_exception()3724    @wrap_instance_fault3725    def get_console_output(self, context, instance, tail_length):3726        """Send the console output for the given instance."""3727        context = context.elevated()3728        LOG.audit(_("Get console output"), context=context,3729                  instance=instance)3730        output = self.driver.get_console_output(context, instance)3731        if tail_length is not None:3732            output = self._tail_log(output, tail_length)3733        return output.decode('utf-8', 'replace').encode('ascii', 'replace')3734    def _tail_log(self, log, length):3735        try:3736            length = int(length)3737        except ValueError:3738            length = 03739        if length == 0:3740            return ''3741        else:3742            return '\n'.join(log.split('\n')[-int(length):])3743    @messaging.expected_exceptions(exception.ConsoleTypeInvalid,3744                                   exception.InstanceNotReady,3745                                   exception.InstanceNotFound,3746                                   exception.ConsoleTypeUnavailable,3747                                   NotImplementedError)3748    @object_compat3749    @wrap_exception()3750    @wrap_instance_fault3751    def get_vnc_console(self, context, console_type, instance):3752        """Return connection information for a vnc console."""3753        context = context.elevated()3754        LOG.debug("Getting vnc console", instance=instance)3755        token = str(uuid.uuid4())3756        if not CONF.vnc_enabled:3757            raise exception.ConsoleTypeUnavailable(console_type=console_type)3758        if console_type == 'novnc':3759            # For essex, novncproxy_base_url must include the full path3760            # including the html file (like http://myhost/vnc_auto.html)3761            access_url = '%s?token=%s' % (CONF.novncproxy_base_url, token)3762        elif console_type == 'xvpvnc':3763            access_url = '%s?token=%s' % (CONF.xvpvncproxy_base_url, token)3764        else:3765            raise exception.ConsoleTypeInvalid(console_type=console_type)3766        try:3767            # Retrieve connect info from driver, and then decorate with our3768            # access info token3769            console = self.driver.get_vnc_console(context, instance)3770            connect_info = console.get_connection_info(token, access_url)3771        except exception.InstanceNotFound:3772            if instance['vm_state'] != vm_states.BUILDING:3773                raise3774            raise exception.InstanceNotReady(instance_id=instance['uuid'])3775        return connect_info3776    @object_compat3777    @messaging.expected_exceptions(exception.ConsoleTypeInvalid,3778                                   exception.InstanceNotReady,3779                                   exception.InstanceNotFound,3780                                   exception.ConsoleTypeUnavailable)3781    @wrap_exception()3782    @wrap_instance_fault3783    def get_spice_console(self, context, console_type, instance):3784        """Return connection information for a spice console."""3785        context = context.elevated()3786        LOG.debug("Getting spice console", instance=instance)3787        token = str(uuid.uuid4())3788        if not CONF.spice.enabled:3789            raise exception.ConsoleTypeUnavailable(console_type=console_type)3790        if console_type == 'spice-html5':3791            # For essex, spicehtml5proxy_base_url must include the full path3792            # including the html file (like http://myhost/spice_auto.html)3793            access_url = '%s?token=%s' % (CONF.spice.html5proxy_base_url,3794                                          token)3795        else:3796            raise exception.ConsoleTypeInvalid(console_type=console_type)3797        try:3798            # Retrieve connect info from driver, and then decorate with our3799            # access info token3800            console = self.driver.get_spice_console(context, instance)3801            connect_info = console.get_connection_info(token, access_url)3802        except exception.InstanceNotFound:3803            if instance['vm_state'] != vm_states.BUILDING:3804                raise3805            raise exception.InstanceNotReady(instance_id=instance['uuid'])3806        return connect_info3807    @object_compat3808    @messaging.expected_exceptions(exception.ConsoleTypeInvalid,3809                                   exception.InstanceNotReady,3810                                   exception.InstanceNotFound,3811                                   exception.ConsoleTypeUnavailable,3812                                   NotImplementedError)3813    @wrap_exception()3814    @wrap_instance_fault3815    def get_rdp_console(self, context, console_type, instance):3816        """Return connection information for a RDP console."""3817        context = context.elevated()3818        LOG.debug("Getting RDP console", instance=instance)3819        token = str(uuid.uuid4())3820        if not CONF.rdp.enabled:3821            raise exception.ConsoleTypeUnavailable(console_type=console_type)3822        if console_type == 'rdp-html5':3823            access_url = '%s?token=%s' % (CONF.rdp.html5_proxy_base_url,3824                                          token)3825        else:3826            raise exception.ConsoleTypeInvalid(console_type=console_type)3827        try:3828            # Retrieve connect info from driver, and then decorate with our3829            # access info token3830            console = self.driver.get_rdp_console(context, instance)3831            connect_info = console.get_connection_info(token, access_url)3832        except exception.InstanceNotFound:3833            if instance['vm_state'] != vm_states.BUILDING:3834                raise3835            raise exception.InstanceNotReady(instance_id=instance['uuid'])3836        return connect_info3837    @messaging.expected_exceptions(3838        exception.ConsoleTypeInvalid,3839        exception.InstanceNotReady,3840        exception.InstanceNotFound,3841        exception.ConsoleTypeUnavailable,3842        exception.SocketPortRangeExhaustedException,3843        exception.ImageSerialPortNumberInvalid,3844        exception.ImageSerialPortNumberExceedFlavorValue,3845        NotImplementedError)3846    @wrap_exception()3847    @wrap_instance_fault3848    def get_serial_console(self, context, console_type, instance):3849        """Returns connection information for a serial console."""3850        LOG.debug("Getting serial console", instance=instance)3851        if not CONF.serial_console.enabled:3852            raise exception.ConsoleTypeUnavailable(console_type=console_type)3853        context = context.elevated()3854        token = str(uuid.uuid4())3855        access_url = '%s?token=%s' % (CONF.serial_console.base_url, token)3856        try:3857            # Retrieve connect info from driver, and then decorate with our3858            # access info token3859            console = self.driver.get_serial_console(context, instance)3860            connect_info = console.get_connection_info(token, access_url)3861        except exception.InstanceNotFound:3862            if instance.vm_state != vm_states.BUILDING:3863                raise3864            raise exception.InstanceNotReady(instance_id=instance['uuid'])3865        return connect_info3866    @messaging.expected_exceptions(exception.ConsoleTypeInvalid,3867                                   exception.InstanceNotReady,3868                                   exception.InstanceNotFound)3869    @object_compat3870    @wrap_exception()3871    @wrap_instance_fault3872    def validate_console_port(self, ctxt, instance, port, console_type):3873        if console_type == "spice-html5":3874            console_info = self.driver.get_spice_console(ctxt, instance)3875        elif console_type == "rdp-html5":3876            console_info = self.driver.get_rdp_console(ctxt, instance)3877        elif console_type == "serial":3878            console_info = self.driver.get_serial_console(ctxt, instance)3879        else:3880            console_info = self.driver.get_vnc_console(ctxt, instance)3881        return console_info.port == port3882    @object_compat3883    @wrap_exception()3884    @reverts_task_state3885    @wrap_instance_fault3886    def reserve_block_device_name(self, context, instance, device,3887                                  volume_id, disk_bus=None, device_type=None):3888        # NOTE(ndipanov): disk_bus and device_type will be set to None if not3889        # passed (by older clients) and defaulted by the virt driver. Remove3890        # default values on the next major RPC version bump.3891        @utils.synchronized(instance['uuid'])3892        def do_reserve():3893            bdms = (3894                objects.BlockDeviceMappingList.get_by_instance_uuid(3895                    context, instance.uuid))3896            device_name = compute_utils.get_device_name_for_instance(3897                    context, instance, bdms, device)3898            # NOTE(vish): create bdm here to avoid race condition3899            bdm = objects.BlockDeviceMapping(3900                    source_type='volume', destination_type='volume',3901                    instance_uuid=instance.uuid,3902                    volume_id=volume_id or 'reserved',3903                    device_name=device_name,3904                    disk_bus=disk_bus, device_type=device_type)3905            bdm.create(context)3906            return device_name3907        return do_reserve()3908    @object_compat3909    @wrap_exception()3910    @reverts_task_state3911    @wrap_instance_fault3912    def attach_volume(self, context, volume_id, mountpoint,3913                      instance, bdm=None):3914        """Attach a volume to an instance."""3915        if not bdm:3916            bdm = objects.BlockDeviceMapping.get_by_volume_id(3917                    context, volume_id)3918        driver_bdm = driver_block_device.DriverVolumeBlockDevice(bdm)3919        @utils.synchronized(instance.uuid)3920        def do_attach_volume(context, instance, driver_bdm):3921            try:3922                return self._attach_volume(context, instance, driver_bdm)3923            except Exception:3924                with excutils.save_and_reraise_exception():3925                    bdm.destroy(context)3926        do_attach_volume(context, instance, driver_bdm)3927    def _attach_volume(self, context, instance, bdm):3928        context = context.elevated()3929        LOG.audit(_('Attaching volume %(volume_id)s to %(mountpoint)s'),3930                  {'volume_id': bdm.volume_id,3931                  'mountpoint': bdm['mount_device']},3932                  context=context, instance=instance)3933        try:3934            bdm.attach(context, instance, self.volume_api, self.driver,3935                       do_check_attach=False, do_driver_attach=True)3936        except Exception:  # pylint: disable=W07023937            with excutils.save_and_reraise_exception():3938                LOG.exception(_LE("Failed to attach %(volume_id)s "3939                                  "at %(mountpoint)s"),3940                              {'volume_id': bdm.volume_id,3941                               'mountpoint': bdm['mount_device']},3942                              context=context, instance=instance)3943                self.volume_api.unreserve_volume(context, bdm.volume_id)3944        info = {'volume_id': bdm.volume_id}3945        self._notify_about_instance_usage(3946            context, instance, "volume.attach", extra_usage_info=info)3947    def _detach_volume(self, context, instance, bdm):3948        """Do the actual driver detach using block device mapping."""3949        mp = bdm.device_name3950        volume_id = bdm.volume_id3951        LOG.audit(_('Detach volume %(volume_id)s from mountpoint %(mp)s'),3952                  {'volume_id': volume_id, 'mp': mp},3953                  context=context, instance=instance)3954        connection_info = jsonutils.loads(bdm.connection_info)3955        # NOTE(vish): We currently don't use the serial when disconnecting,3956        #             but added for completeness in case we ever do.3957        if connection_info and 'serial' not in connection_info:3958            connection_info['serial'] = volume_id3959        try:3960            if not self.driver.instance_exists(instance):3961                LOG.warn(_('Detaching volume from unknown instance'),3962                         context=context, instance=instance)3963            encryption = encryptors.get_encryption_metadata(3964                context, self.volume_api, volume_id, connection_info)3965            self.driver.detach_volume(connection_info,3966                                      instance,3967                                      mp,3968                                      encryption=encryption)3969        except Exception:  # pylint: disable=W07023970            with excutils.save_and_reraise_exception():3971                LOG.exception(_LE('Failed to detach volume %(volume_id)s '3972                                  'from %(mp)s'),3973                              {'volume_id': volume_id, 'mp': mp},3974                              context=context, instance=instance)3975                self.volume_api.roll_detaching(context, volume_id)3976    @object_compat3977    @wrap_exception()3978    @reverts_task_state3979    @wrap_instance_fault3980    def detach_volume(self, context, volume_id, instance):3981        """Detach a volume from an instance."""3982        bdm = objects.BlockDeviceMapping.get_by_volume_id(3983                context, volume_id)3984        if CONF.volume_usage_poll_interval > 0:3985            vol_stats = []3986            mp = bdm.device_name3987            # Handle bootable volumes which will not contain /dev/3988            if '/dev/' in mp:3989                mp = mp[5:]3990            try:3991                vol_stats = self.driver.block_stats(instance.name, mp)3992            except NotImplementedError:3993                pass3994            if vol_stats:3995                LOG.debug("Updating volume usage cache with totals",3996                          instance=instance)3997                rd_req, rd_bytes, wr_req, wr_bytes, flush_ops = vol_stats3998                self.conductor_api.vol_usage_update(context, volume_id,3999                                                    rd_req, rd_bytes,4000                                                    wr_req, wr_bytes,4001                                                    instance,4002                                                    update_totals=True)4003        self._detach_volume(context, instance, bdm)4004        connector = self.driver.get_volume_connector(instance)4005        self.volume_api.terminate_connection(context, volume_id, connector)4006        bdm.destroy()4007        info = dict(volume_id=volume_id)4008        self._notify_about_instance_usage(4009            context, instance, "volume.detach", extra_usage_info=info)4010        self.volume_api.detach(context.elevated(), volume_id)4011    def _init_volume_connection(self, context, new_volume_id,4012                                old_volume_id, connector, instance, bdm):4013        new_cinfo = self.volume_api.initialize_connection(context,4014                                                          new_volume_id,4015                                                          connector)4016        old_cinfo = jsonutils.loads(bdm['connection_info'])4017        if old_cinfo and 'serial' not in old_cinfo:4018            old_cinfo['serial'] = old_volume_id4019        new_cinfo['serial'] = old_cinfo['serial']4020        return (old_cinfo, new_cinfo)4021    def _swap_volume(self, context, instance, bdm, connector, old_volume_id,4022                                                              new_volume_id):4023        mountpoint = bdm['device_name']4024        failed = False4025        new_cinfo = None4026        resize_to = 04027        try:4028            old_cinfo, new_cinfo = self._init_volume_connection(context,4029                                                                new_volume_id,4030                                                                old_volume_id,4031                                                                connector,4032                                                                instance,4033                                                                bdm)4034            old_vol_size = self.volume_api.get(context, old_volume_id)['size']4035            new_vol_size = self.volume_api.get(context, new_volume_id)['size']4036            if new_vol_size > old_vol_size:4037                resize_to = new_vol_size4038            self.driver.swap_volume(old_cinfo, new_cinfo, instance, mountpoint,4039                                    resize_to)4040        except Exception:  # pylint: disable=W07024041            failed = True4042            with excutils.save_and_reraise_exception():4043                if new_cinfo:4044                    msg = _LE("Failed to swap volume %(old_volume_id)s "4045                              "for %(new_volume_id)s")4046                    LOG.exception(msg, {'old_volume_id': old_volume_id,4047                                        'new_volume_id': new_volume_id},4048                                  context=context,4049                                  instance=instance)4050                else:4051                    msg = _LE("Failed to connect to volume %(volume_id)s "4052                              "with volume at %(mountpoint)s")4053                    LOG.exception(msg, {'volume_id': new_volume_id,4054                                        'mountpoint': bdm['device_name']},4055                                  context=context,4056                                  instance=instance)4057                self.volume_api.roll_detaching(context, old_volume_id)4058                self.volume_api.unreserve_volume(context, new_volume_id)4059        finally:4060            conn_volume = new_volume_id if failed else old_volume_id4061            if new_cinfo:4062                self.volume_api.terminate_connection(context,4063                                                     conn_volume,4064                                                     connector)4065            # If Cinder initiated the swap, it will keep4066            # the original ID4067            comp_ret = self.volume_api.migrate_volume_completion(4068                                                      context,4069                                                      old_volume_id,4070                                                      new_volume_id,4071                                                      error=failed)4072        return (comp_ret, new_cinfo)4073    @wrap_exception()4074    @reverts_task_state4075    @wrap_instance_fault4076    def swap_volume(self, context, old_volume_id, new_volume_id, instance):4077        """Swap volume for an instance."""4078        context = context.elevated()4079        bdm = objects.BlockDeviceMapping.get_by_volume_id(4080                context, old_volume_id, instance_uuid=instance.uuid)4081        connector = self.driver.get_volume_connector(instance)4082        comp_ret, new_cinfo = self._swap_volume(context, instance,4083                                                         bdm,4084                                                         connector,4085                                                         old_volume_id,4086                                                         new_volume_id)4087        save_volume_id = comp_ret['save_volume_id']4088        mountpoint = bdm.device_name4089        # Update bdm4090        values = {4091            'connection_info': jsonutils.dumps(new_cinfo),4092            'delete_on_termination': False,4093            'source_type': 'volume',4094            'destination_type': 'volume',4095            'snapshot_id': None,4096            'volume_id': save_volume_id,4097            'volume_size': None,4098            'no_device': None}4099        bdm.update(values)4100        bdm.save()4101        self.volume_api.attach(context,4102                               new_volume_id,4103                               instance.uuid,4104                               mountpoint)4105        # Remove old connection4106        self.volume_api.detach(context.elevated(), old_volume_id)4107    @wrap_exception()4108    def remove_volume_connection(self, context, volume_id, instance):4109        """Remove a volume connection using the volume api."""4110        # NOTE(vish): We don't want to actually mark the volume4111        #             detached, or delete the bdm, just remove the4112        #             connection from this host.4113        # NOTE(PhilDay): Can't use object_compat decorator here as4114        #                instance is not the second parameter4115        if isinstance(instance, dict):4116            metas = ['metadata', 'system_metadata']4117            instance = objects.Instance._from_db_object(4118                    context, objects.Instance(), instance,4119                    expected_attrs=metas)4120            instance._context = context4121        try:4122            bdm = objects.BlockDeviceMapping.get_by_volume_id(4123                    context, volume_id)4124            self._detach_volume(context, instance, bdm)4125            connector = self.driver.get_volume_connector(instance)4126            self.volume_api.terminate_connection(context, volume_id, connector)4127        except exception.NotFound:4128            pass4129    @object_compat4130    @wrap_exception()4131    @reverts_task_state4132    @wrap_instance_fault4133    def attach_interface(self, context, instance, network_id, port_id,4134                         requested_ip):4135        """Use hotplug to add an network adapter to an instance."""4136        network_info = self.network_api.allocate_port_for_instance(4137            context, instance, port_id, network_id, requested_ip)4138        if len(network_info) != 1:4139            LOG.error(_('allocate_port_for_instance returned %(ports)s ports')4140                      % dict(ports=len(network_info)))4141            raise exception.InterfaceAttachFailed(4142                    instance_uuid=instance.uuid)4143        image_ref = instance.get('image_ref')4144        image_meta = compute_utils.get_image_metadata(4145            context, self.image_api, image_ref, instance)4146        self.driver.attach_interface(instance, image_meta, network_info[0])4147        return network_info[0]4148    @object_compat4149    @wrap_exception()4150    @reverts_task_state4151    @wrap_instance_fault4152    def detach_interface(self, context, instance, port_id):4153        """Detach an network adapter from an instance."""4154        network_info = instance.info_cache.network_info4155        condemned = None4156        for vif in network_info:4157            if vif['id'] == port_id:4158                condemned = vif4159                break4160        if condemned is None:4161            raise exception.PortNotFound(_("Port %s is not "4162                                           "attached") % port_id)4163        self.network_api.deallocate_port_for_instance(context, instance,4164                                                      port_id)4165        self.driver.detach_interface(instance, condemned)4166    def _get_compute_info(self, context, host):4167        service = objects.Service.get_by_compute_host(context, host)4168        try:4169            return service.compute_node4170        except IndexError:4171            raise exception.NotFound(_("Host %s not found") % host)4172    @wrap_exception()4173    def check_instance_shared_storage(self, ctxt, instance, data):4174        """Check if the instance files are shared4175        :param context: security context4176        :param data: result of driver.check_instance_shared_storage_local4177        Returns True if instance disks located on shared storage and4178        False otherwise.4179        """4180        return self.driver.check_instance_shared_storage_remote(ctxt, data)4181    @wrap_exception()4182    @wrap_instance_fault4183    def check_can_live_migrate_destination(self, ctxt, instance,4184                                           block_migration, disk_over_commit):4185        """Check if it is possible to execute live migration.4186        This runs checks on the destination host, and then calls4187        back to the source host to check the results.4188        :param context: security context4189        :param instance: dict of instance data4190        :param block_migration: if true, prepare for block migration4191        :param disk_over_commit: if true, allow disk over commit4192        :returns: a dict containing migration info4193        """4194        src_compute_info = obj_base.obj_to_primitive(4195            self._get_compute_info(ctxt, instance.host))4196        dst_compute_info = obj_base.obj_to_primitive(4197            self._get_compute_info(ctxt, CONF.host))4198        dest_check_data = self.driver.check_can_live_migrate_destination(ctxt,4199            instance, src_compute_info, dst_compute_info,4200            block_migration, disk_over_commit)4201        migrate_data = {}4202        try:4203            migrate_data = self.compute_rpcapi.\4204                                check_can_live_migrate_source(ctxt, instance,4205                                                              dest_check_data)4206        finally:4207            self.driver.check_can_live_migrate_destination_cleanup(ctxt,4208                    dest_check_data)4209        if 'migrate_data' in dest_check_data:4210            migrate_data.update(dest_check_data['migrate_data'])4211        return migrate_data4212    @wrap_exception()4213    @wrap_instance_fault4214    def check_can_live_migrate_source(self, ctxt, instance, dest_check_data):4215        """Check if it is possible to execute live migration.4216        This checks if the live migration can succeed, based on the4217        results from check_can_live_migrate_destination.4218        :param context: security context4219        :param instance: dict of instance data4220        :param dest_check_data: result of check_can_live_migrate_destination4221        :returns: a dict containing migration info4222        """4223        is_volume_backed = self.compute_api.is_volume_backed_instance(ctxt,4224                                                                      instance)4225        dest_check_data['is_volume_backed'] = is_volume_backed4226        return self.driver.check_can_live_migrate_source(ctxt, instance,4227                                                         dest_check_data)4228    @object_compat4229    @wrap_exception()4230    @wrap_instance_fault4231    def pre_live_migration(self, context, instance, block_migration, disk,4232                           migrate_data):4233        """Preparations for live migration at dest host.4234        :param context: security context4235        :param instance: dict of instance data4236        :param block_migration: if true, prepare for block migration4237        :param migrate_data: if not None, it is a dict which holds data4238                             required for live migration without shared4239                             storage.4240        """4241        block_device_info = self._get_instance_block_device_info(4242                            context, instance, refresh_conn_info=True)4243        network_info = self._get_instance_nw_info(context, instance)4244        self._notify_about_instance_usage(4245                     context, instance, "live_migration.pre.start",4246                     network_info=network_info)4247        pre_live_migration_data = self.driver.pre_live_migration(context,4248                                       instance,4249                                       block_device_info,4250                                       network_info,4251                                       disk,4252                                       migrate_data)4253        # NOTE(tr3buchet): setup networks on destination host4254        self.network_api.setup_networks_on_host(context, instance,4255                                                         self.host)4256        # Creating filters to hypervisors and firewalls.4257        # An example is that nova-instance-instance-xxx,4258        # which is written to libvirt.xml(Check "virsh nwfilter-list")4259        # This nwfilter is necessary on the destination host.4260        # In addition, this method is creating filtering rule4261        # onto destination host.4262        self.driver.ensure_filtering_rules_for_instance(instance,4263                                            network_info)4264        self._notify_about_instance_usage(4265                     context, instance, "live_migration.pre.end",4266                     network_info=network_info)4267        return pre_live_migration_data4268    @wrap_exception()4269    @wrap_instance_fault4270    def live_migration(self, context, dest, instance, block_migration,4271                       migrate_data):4272        """Executing live migration.4273        :param context: security context4274        :param instance: a nova.objects.instance.Instance object4275        :param dest: destination host4276        :param block_migration: if true, prepare for block migration4277        :param migrate_data: implementation specific params4278        """4279        # NOTE(danms): since instance is not the first parameter, we can't4280        # use @object_compat on this method. Since this is the only example,4281        # we do this manually instead of complicating the decorator4282        if not isinstance(instance, obj_base.NovaObject):4283            expected = ['metadata', 'system_metadata',4284                        'security_groups', 'info_cache']4285            instance = objects.Instance._from_db_object(4286                context, objects.Instance(), instance,4287                expected_attrs=expected)4288        # Create a local copy since we'll be modifying the dictionary4289        migrate_data = dict(migrate_data or {})4290        try:4291            if block_migration:4292                disk = self.driver.get_instance_disk_info(instance.name)4293            else:4294                disk = None4295            pre_migration_data = self.compute_rpcapi.pre_live_migration(4296                context, instance,4297                block_migration, disk, dest, migrate_data)4298            migrate_data['pre_live_migration_result'] = pre_migration_data4299        except Exception:4300            with excutils.save_and_reraise_exception():4301                LOG.exception(_LE('Pre live migration failed at %s'),4302                              dest, instance=instance)4303                self._rollback_live_migration(context, instance, dest,4304                                              block_migration, migrate_data)4305        # Executing live migration4306        # live_migration might raises exceptions, but4307        # nothing must be recovered in this version.4308        self.driver.live_migration(context, instance, dest,4309                                   self._post_live_migration,4310                                   self._rollback_live_migration,4311                                   block_migration, migrate_data)4312    def _live_migration_cleanup_flags(self, block_migration, migrate_data):4313        """Determine whether disks or intance path need to be cleaned up after4314        live migration (at source on success, at destination on rollback)4315        Block migration needs empty image at destination host before migration4316        starts, so if any failure occurs, any empty images has to be deleted.4317        Also Volume backed live migration w/o shared storage needs to delete4318        newly created instance-xxx dir on the destination as a part of its4319        rollback process4320        :param block_migration: if true, it was a block migration4321        :param migrate_data: implementation specific data4322        :returns: (bool, bool) -- do_cleanup, destroy_disks4323        """4324        # NOTE(angdraug): block migration wouldn't have been allowed if either4325        #                 block storage or instance path were shared4326        is_shared_block_storage = not block_migration4327        is_shared_instance_path = not block_migration4328        if migrate_data:4329            is_shared_block_storage = migrate_data.get(4330                    'is_shared_block_storage', is_shared_block_storage)4331            is_shared_instance_path = migrate_data.get(4332                    'is_shared_instance_path', is_shared_instance_path)4333        # No instance booting at source host, but instance dir4334        # must be deleted for preparing next block migration4335        # must be deleted for preparing next live migration w/o shared storage4336        do_cleanup = block_migration or not is_shared_instance_path4337        destroy_disks = not is_shared_block_storage4338        return (do_cleanup, destroy_disks)4339    @wrap_exception()4340    @wrap_instance_fault4341    def _post_live_migration(self, ctxt, instance,4342                            dest, block_migration=False, migrate_data=None):4343        """Post operations for live migration.4344        This method is called from live_migration4345        and mainly updating database record.4346        :param ctxt: security context4347        :param instance: instance dict4348        :param dest: destination host4349        :param block_migration: if true, prepare for block migration4350        :param migrate_data: if not None, it is a dict which has data4351        required for live migration without shared storage4352        """4353        LOG.info(_('_post_live_migration() is started..'),4354                 instance=instance)4355        bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(4356                ctxt, instance['uuid'])4357        # Cleanup source host post live-migration4358        block_device_info = self._get_instance_block_device_info(4359                            ctxt, instance, bdms=bdms)4360        self.driver.post_live_migration(ctxt, instance, block_device_info,4361                                        migrate_data)4362        # Detaching volumes.4363        connector = self.driver.get_volume_connector(instance)4364        for bdm in bdms:4365            # NOTE(vish): We don't want to actually mark the volume4366            #             detached, or delete the bdm, just remove the4367            #             connection from this host.4368            # remove the volume connection without detaching from hypervisor4369            # because the instance is not running anymore on the current host4370            if bdm.is_volume:4371                self.volume_api.terminate_connection(ctxt, bdm.volume_id,4372                                                     connector)4373        # Releasing vlan.4374        # (not necessary in current implementation?)4375        network_info = self._get_instance_nw_info(ctxt, instance)4376        self._notify_about_instance_usage(ctxt, instance,4377                                          "live_migration._post.start",4378                                          network_info=network_info)4379        # Releasing security group ingress rule.4380        self.driver.unfilter_instance(instance,4381                                      network_info)4382        migration = {'source_compute': self.host,4383                     'dest_compute': dest, }4384        self.network_api.migrate_instance_start(ctxt,4385                                                instance,4386                                                migration)4387        destroy_vifs = False4388        try:4389            self.driver.post_live_migration_at_source(ctxt, instance,4390                                                      network_info)4391        except NotImplementedError as ex:4392            LOG.debug(ex, instance=instance)4393            # For all hypervisors other than libvirt, there is a possibility4394            # they are unplugging networks from source node in the cleanup4395            # method4396            destroy_vifs = True4397        # Define domain at destination host, without doing it,4398        # pause/suspend/terminate do not work.4399        self.compute_rpcapi.post_live_migration_at_destination(ctxt,4400                instance, block_migration, dest)4401        do_cleanup, destroy_disks = self._live_migration_cleanup_flags(4402                block_migration, migrate_data)4403        if do_cleanup:4404            self.driver.cleanup(ctxt, instance, network_info,4405                                destroy_disks=destroy_disks,4406                                migrate_data=migrate_data,4407                                destroy_vifs=destroy_vifs)4408        # NOTE(tr3buchet): tear down networks on source host4409        self.network_api.setup_networks_on_host(ctxt, instance,4410                                                self.host, teardown=True)4411        self.instance_events.clear_events_for_instance(instance)4412        # NOTE(timello): make sure we update available resources on source4413        # host even before next periodic task.4414        self.update_available_resource(ctxt)4415        self._notify_about_instance_usage(ctxt, instance,4416                                          "live_migration._post.end",4417                                          network_info=network_info)4418        LOG.info(_('Migrating instance to %s finished successfully.'),4419                 dest, instance=instance)4420        LOG.info(_("You may see the error \"libvirt: QEMU error: "4421                   "Domain not found: no domain with matching name.\" "4422                   "This error can be safely ignored."),4423                 instance=instance)4424        if CONF.vnc_enabled or CONF.spice.enabled or CONF.rdp.enabled:4425            if CONF.cells.enable:4426                self.cells_rpcapi.consoleauth_delete_tokens(ctxt,4427                        instance['uuid'])4428            else:4429                self.consoleauth_rpcapi.delete_tokens_for_instance(ctxt,4430                        instance['uuid'])4431    @object_compat4432    @wrap_exception()4433    @wrap_instance_fault4434    def post_live_migration_at_destination(self, context, instance,4435                                           block_migration):4436        """Post operations for live migration .4437        :param context: security context4438        :param instance: Instance dict4439        :param block_migration: if true, prepare for block migration4440        """4441        LOG.info(_('Post operation of migration started'),4442                 instance=instance)4443        # NOTE(tr3buchet): setup networks on destination host4444        #                  this is called a second time because4445        #                  multi_host does not create the bridge in4446        #                  plug_vifs4447        self.network_api.setup_networks_on_host(context, instance,4448                                                         self.host)4449        migration = {'source_compute': instance['host'],4450                     'dest_compute': self.host, }4451        self.network_api.migrate_instance_finish(context,4452                                                 instance,4453                                                 migration)4454        network_info = self._get_instance_nw_info(context, instance)4455        self._notify_about_instance_usage(4456                     context, instance, "live_migration.post.dest.start",4457                     network_info=network_info)4458        block_device_info = self._get_instance_block_device_info(context,4459                                                                 instance)4460        self.driver.post_live_migration_at_destination(context, instance,4461                                            network_info,4462                                            block_migration, block_device_info)4463        # Restore instance state4464        current_power_state = self._get_power_state(context, instance)4465        node_name = None4466        try:4467            compute_node = self._get_compute_info(context, self.host)4468            node_name = compute_node.hypervisor_hostname4469        except exception.NotFound:4470            LOG.exception(_LE('Failed to get compute_info for %s'), self.host)4471        finally:4472            instance.host = self.host4473            instance.power_state = current_power_state4474            instance.vm_state = vm_states.ACTIVE4475            instance.task_state = None4476            instance.node = node_name4477            instance.save(expected_task_state=task_states.MIGRATING)4478        # NOTE(vish): this is necessary to update dhcp4479        self.network_api.setup_networks_on_host(context, instance, self.host)4480        self._notify_about_instance_usage(4481                     context, instance, "live_migration.post.dest.end",4482                     network_info=network_info)4483    @wrap_exception()4484    @wrap_instance_fault4485    def _rollback_live_migration(self, context, instance,4486                                 dest, block_migration, migrate_data=None):4487        """Recovers Instance/volume state from migrating -> running.4488        :param context: security context4489        :param instance: nova.db.sqlalchemy.models.Instance4490        :param dest:4491            This method is called from live migration src host.4492            This param specifies destination host.4493        :param block_migration: if true, prepare for block migration4494        :param migrate_data:4495            if not none, contains implementation specific data.4496        """4497        instance.vm_state = vm_states.ACTIVE4498        instance.task_state = None4499        instance.save(expected_task_state=[task_states.MIGRATING])4500        # NOTE(tr3buchet): setup networks on source host (really it's re-setup)4501        self.network_api.setup_networks_on_host(context, instance, self.host)4502        bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(4503                context, instance['uuid'])4504        for bdm in bdms:4505            if bdm.is_volume:4506                self.compute_rpcapi.remove_volume_connection(4507                        context, instance, bdm.volume_id, dest)4508        self._notify_about_instance_usage(context, instance,4509                                          "live_migration._rollback.start")4510        do_cleanup, destroy_disks = self._live_migration_cleanup_flags(4511                block_migration, migrate_data)4512        if do_cleanup:4513            self.compute_rpcapi.rollback_live_migration_at_destination(4514                    context, instance, dest, destroy_disks=destroy_disks,4515                    migrate_data=migrate_data)4516        self._notify_about_instance_usage(context, instance,4517                                          "live_migration._rollback.end")4518    @object_compat4519    @wrap_exception()4520    @wrap_instance_fault4521    def rollback_live_migration_at_destination(self, context, instance,4522                                               destroy_disks=True,4523                                               migrate_data=None):4524        """Cleaning up image directory that is created pre_live_migration.4525        :param context: security context4526        :param instance: a nova.objects.instance.Instance object sent over rpc4527        """4528        network_info = self._get_instance_nw_info(context, instance)4529        self._notify_about_instance_usage(4530                      context, instance, "live_migration.rollback.dest.start",4531                      network_info=network_info)4532        # NOTE(tr3buchet): tear down networks on destination host4533        self.network_api.setup_networks_on_host(context, instance,4534                                                self.host, teardown=True)4535        # NOTE(vish): The mapping is passed in so the driver can disconnect4536        #             from remote volumes if necessary4537        block_device_info = self._get_instance_block_device_info(context,4538                                                                 instance)4539        self.driver.rollback_live_migration_at_destination(4540                        context, instance, network_info, block_device_info,4541                        destroy_disks=destroy_disks, migrate_data=migrate_data)4542        self._notify_about_instance_usage(4543                        context, instance, "live_migration.rollback.dest.end",4544                        network_info=network_info)4545    @periodic_task.periodic_task(4546        spacing=CONF.heal_instance_info_cache_interval)4547    def _heal_instance_info_cache(self, context):4548        """Called periodically.  On every call, try to update the4549        info_cache's network information for another instance by4550        calling to the network manager.4551        This is implemented by keeping a cache of uuids of instances4552        that live on this host.  On each call, we pop one off of a4553        list, pull the DB record, and try the call to the network API.4554        If anything errors don't fail, as it's possible the instance4555        has been deleted, etc.4556        """4557        heal_interval = CONF.heal_instance_info_cache_interval4558        if not heal_interval:4559            return4560        instance_uuids = getattr(self, '_instance_uuids_to_heal', [])4561        instance = None4562        LOG.debug('Starting heal instance info cache')4563        if not instance_uuids:4564            # The list of instances to heal is empty so rebuild it4565            LOG.debug('Rebuilding the list of instances to heal')4566            db_instances = objects.InstanceList.get_by_host(4567                context, self.host, expected_attrs=[], use_slave=True)4568            for inst in db_instances:4569                # We don't want to refersh the cache for instances4570                # which are building or deleting so don't put them4571                # in the list. If they are building they will get4572                # added to the list next time we build it.4573                if (inst.vm_state == vm_states.BUILDING):4574                    LOG.debug('Skipping network cache update for instance '4575                              'because it is Building.', instance=inst)4576                    continue4577                if (inst.task_state == task_states.DELETING):4578                    LOG.debug('Skipping network cache update for instance '4579                              'because it is being deleted.', instance=inst)4580                    continue4581                if not instance:4582                    # Save the first one we find so we don't4583                    # have to get it again4584                    instance = inst4585                else:4586                    instance_uuids.append(inst['uuid'])4587            self._instance_uuids_to_heal = instance_uuids4588        else:4589            # Find the next valid instance on the list4590            while instance_uuids:4591                try:4592                    inst = objects.Instance.get_by_uuid(4593                            context, instance_uuids.pop(0),4594                            expected_attrs=['system_metadata', 'info_cache'],4595                            use_slave=True)4596                except exception.InstanceNotFound:4597                    # Instance is gone.  Try to grab another.4598                    continue4599                # Check the instance hasn't been migrated4600                if inst.host != self.host:4601                    LOG.debug('Skipping network cache update for instance '4602                              'because it has been migrated to another '4603                              'host.', instance=inst)4604                # Check the instance isn't being deleting4605                elif inst.task_state == task_states.DELETING:4606                    LOG.debug('Skipping network cache update for instance '4607                              'because it is being deleted.', instance=inst)4608                else:4609                    instance = inst4610                    break4611        if instance:4612            # We have an instance now to refresh4613            try:4614                # Call to network API to get instance info.. this will4615                # force an update to the instance's info_cache4616                self._get_instance_nw_info(context, instance, use_slave=True)4617                LOG.debug('Updated the network info_cache for instance',4618                          instance=instance)4619            except Exception:4620                LOG.error(_('An error occurred while refreshing the network '4621                            'cache.'), instance=instance, exc_info=True)4622        else:4623            LOG.debug("Didn't find any instances for network info cache "4624                      "update.")4625    @periodic_task.periodic_task4626    def _poll_rebooting_instances(self, context):4627        if CONF.reboot_timeout > 0:4628            filters = {'task_state': task_states.REBOOTING,4629                       'host': self.host}4630            rebooting = objects.InstanceList.get_by_filters(4631                context, filters, expected_attrs=[], use_slave=True)4632            to_poll = []4633            for instance in rebooting:4634                if timeutils.is_older_than(instance['updated_at'],4635                                           CONF.reboot_timeout):4636                    to_poll.append(instance)4637            self.driver.poll_rebooting_instances(CONF.reboot_timeout, to_poll)4638    @periodic_task.periodic_task4639    def _poll_rescued_instances(self, context):4640        if CONF.rescue_timeout > 0:4641            filters = {'vm_state': vm_states.RESCUED,4642                       'host': self.host}4643            rescued_instances = objects.InstanceList.get_by_filters(4644                context, filters, expected_attrs=["system_metadata"],4645                use_slave=True)4646            to_unrescue = []4647            for instance in rescued_instances:4648                if timeutils.is_older_than(instance['launched_at'],4649                                           CONF.rescue_timeout):4650                    to_unrescue.append(instance)4651            for instance in to_unrescue:4652                self.compute_api.unrescue(context, instance)4653    @periodic_task.periodic_task4654    def _poll_unconfirmed_resizes(self, context):4655        if CONF.resize_confirm_window == 0:4656            return4657        migrations = objects.MigrationList.get_unconfirmed_by_dest_compute(4658                context, CONF.resize_confirm_window, self.host,4659                use_slave=True)4660        migrations_info = dict(migration_count=len(migrations),4661                confirm_window=CONF.resize_confirm_window)4662        if migrations_info["migration_count"] > 0:4663            LOG.info(_("Found %(migration_count)d unconfirmed migrations "4664                       "older than %(confirm_window)d seconds"),4665                     migrations_info)4666        def _set_migration_to_error(migration, reason, **kwargs):4667            LOG.warn(_("Setting migration %(migration_id)s to error: "4668                       "%(reason)s"),4669                     {'migration_id': migration['id'], 'reason': reason},4670                     **kwargs)4671            migration.status = 'error'4672            migration.save(context.elevated())4673        for migration in migrations:4674            instance_uuid = migration.instance_uuid4675            LOG.info(_("Automatically confirming migration "4676                       "%(migration_id)s for instance %(instance_uuid)s"),4677                     {'migration_id': migration.id,4678                      'instance_uuid': instance_uuid})4679            expected_attrs = ['metadata', 'system_metadata']4680            try:4681                instance = objects.Instance.get_by_uuid(context,4682                            instance_uuid, expected_attrs=expected_attrs,4683                            use_slave=True)4684            except exception.InstanceNotFound:4685                reason = (_("Instance %s not found") %4686                          instance_uuid)4687                _set_migration_to_error(migration, reason)4688                continue4689            if instance['vm_state'] == vm_states.ERROR:4690                reason = _("In ERROR state")4691                _set_migration_to_error(migration, reason,4692                                        instance=instance)4693                continue4694            # race condition: The instance in DELETING state should not be4695            # set the migration state to error, otherwise the instance in4696            # to be deleted which is in RESIZED state4697            # will not be able to confirm resize4698            if instance.task_state in [task_states.DELETING,4699                                       task_states.SOFT_DELETING]:4700                msg = ("Instance being deleted or soft deleted during resize "4701                       "confirmation. Skipping.")4702                LOG.debug(msg, instance=instance)4703                continue4704            vm_state = instance['vm_state']4705            task_state = instance['task_state']4706            if vm_state != vm_states.RESIZED or task_state is not None:4707                reason = (_("In states %(vm_state)s/%(task_state)s, not "4708                           "RESIZED/None") %4709                          {'vm_state': vm_state,4710                           'task_state': task_state})4711                _set_migration_to_error(migration, reason,4712                                        instance=instance)4713                continue4714            try:4715                self.compute_api.confirm_resize(context, instance,4716                                                migration=migration)4717            except Exception as e:4718                LOG.info(_("Error auto-confirming resize: %s. "4719                           "Will retry later."),4720                         e, instance=instance)4721    @compute_utils.periodic_task_spacing_warn("shelved_poll_interval")4722    @periodic_task.periodic_task(spacing=CONF.shelved_poll_interval)4723    def _poll_shelved_instances(self, context):4724        if CONF.shelved_offload_time <= 0:4725            return4726        filters = {'vm_state': vm_states.SHELVED,4727                   'host': self.host}4728        shelved_instances = objects.InstanceList.get_by_filters(4729            context, filters=filters, expected_attrs=['system_metadata'],4730            use_slave=True)4731        to_gc = []4732        for instance in shelved_instances:4733            sys_meta = instance.system_metadata4734            shelved_at = timeutils.parse_strtime(sys_meta['shelved_at'])4735            if timeutils.is_older_than(shelved_at, CONF.shelved_offload_time):4736                to_gc.append(instance)4737        for instance in to_gc:4738            try:4739                instance.task_state = task_states.SHELVING_OFFLOADING4740                instance.save()4741                self.shelve_offload_instance(context, instance)4742            except Exception:4743                LOG.exception(_LE('Periodic task failed to offload instance.'),4744                        instance=instance)4745    @periodic_task.periodic_task4746    def _instance_usage_audit(self, context):4747        if not CONF.instance_usage_audit:4748            return4749        if compute_utils.has_audit_been_run(context,4750                                            self.conductor_api,4751                                            self.host):4752            return4753        begin, end = utils.last_completed_audit_period()4754        instances = objects.InstanceList.get_active_by_window_joined(4755            context, begin, end, host=self.host,4756            expected_attrs=['system_metadata', 'info_cache', 'metadata'],4757            use_slave=True)4758        num_instances = len(instances)4759        errors = 04760        successes = 04761        LOG.info(_("Running instance usage audit for"4762                   " host %(host)s from %(begin_time)s to "4763                   "%(end_time)s. %(number_instances)s"4764                   " instances."),4765                 dict(host=self.host,4766                      begin_time=begin,4767                      end_time=end,4768                      number_instances=num_instances))4769        start_time = time.time()4770        compute_utils.start_instance_usage_audit(context,4771                                      self.conductor_api,4772                                      begin, end,4773                                      self.host, num_instances)4774        for instance in instances:4775            try:4776                self.conductor_api.notify_usage_exists(4777                    context, instance,4778                    ignore_missing_network_data=False)4779                successes += 14780            except Exception:4781                LOG.exception(_LE('Failed to generate usage '4782                                  'audit for instance '4783                                  'on host %s'), self.host,4784                              instance=instance)4785                errors += 14786        compute_utils.finish_instance_usage_audit(context,4787                                      self.conductor_api,4788                                      begin, end,4789                                      self.host, errors,4790                                      "Instance usage audit ran "4791                                      "for host %s, %s instances "4792                                      "in %s seconds." % (4793                                      self.host,4794                                      num_instances,4795                                      time.time() - start_time))4796    @compute_utils.periodic_task_spacing_warn("bandwidth_poll_interval")4797    @periodic_task.periodic_task(spacing=CONF.bandwidth_poll_interval)4798    def _poll_bandwidth_usage(self, context):4799        if (CONF.bandwidth_poll_interval <= 0 or not self._bw_usage_supported):4800            return4801        prev_time, start_time = utils.last_completed_audit_period()4802        curr_time = time.time()4803        if (curr_time - self._last_bw_usage_poll >4804                CONF.bandwidth_poll_interval):4805            self._last_bw_usage_poll = curr_time4806            LOG.info(_("Updating bandwidth usage cache"))4807            cells_update_interval = CONF.cells.bandwidth_update_interval4808            if (cells_update_interval > 0 and4809                   curr_time - self._last_bw_usage_cell_update >4810                           cells_update_interval):4811                self._last_bw_usage_cell_update = curr_time4812                update_cells = True4813            else:4814                update_cells = False4815            instances = objects.InstanceList.get_by_host(context,4816                                                              self.host,4817                                                              use_slave=True)4818            try:4819                bw_counters = self.driver.get_all_bw_counters(instances)4820            except NotImplementedError:4821                # NOTE(mdragon): Not all hypervisors have bandwidth polling4822                # implemented yet.  If they don't it doesn't break anything,4823                # they just don't get the info in the usage events.4824                # NOTE(PhilDay): Record that its not supported so we can4825                # skip fast on future calls rather than waste effort getting4826                # the list of instances.4827                LOG.warning(_("Bandwidth usage not supported by hypervisor."))4828                self._bw_usage_supported = False4829                return4830            refreshed = timeutils.utcnow()4831            for bw_ctr in bw_counters:4832                # Allow switching of greenthreads between queries.4833                greenthread.sleep(0)4834                bw_in = 04835                bw_out = 04836                last_ctr_in = None4837                last_ctr_out = None4838                usage = objects.BandwidthUsage.get_by_instance_uuid_and_mac(4839                    context, bw_ctr['uuid'], bw_ctr['mac_address'],4840                    start_period=start_time, use_slave=True)4841                if usage:4842                    bw_in = usage.bw_in4843                    bw_out = usage.bw_out4844                    last_ctr_in = usage.last_ctr_in4845                    last_ctr_out = usage.last_ctr_out4846                else:4847                    usage = (objects.BandwidthUsage.4848                             get_by_instance_uuid_and_mac(4849                        context, bw_ctr['uuid'], bw_ctr['mac_address'],4850                        start_period=prev_time, use_slave=True))4851                    if usage:4852                        last_ctr_in = usage.last_ctr_in4853                        last_ctr_out = usage.last_ctr_out4854                if last_ctr_in is not None:4855                    if bw_ctr['bw_in'] < last_ctr_in:4856                        # counter rollover4857                        bw_in += bw_ctr['bw_in']4858                    else:4859                        bw_in += (bw_ctr['bw_in'] - last_ctr_in)4860                if last_ctr_out is not None:4861                    if bw_ctr['bw_out'] < last_ctr_out:4862                        # counter rollover4863                        bw_out += bw_ctr['bw_out']4864                    else:4865                        bw_out += (bw_ctr['bw_out'] - last_ctr_out)4866                objects.BandwidthUsage.create(context,4867                                              bw_ctr['uuid'],4868                                              bw_ctr['mac_address'],4869                                              bw_in,4870                                              bw_out,4871                                              bw_ctr['bw_in'],4872                                              bw_ctr['bw_out'],4873                                              start_period=start_time,4874                                              last_refreshed=refreshed,4875                                              update_cells=update_cells)4876    def _get_host_volume_bdms(self, context, use_slave=False):4877        """Return all block device mappings on a compute host."""4878        compute_host_bdms = []4879        instances = objects.InstanceList.get_by_host(context, self.host)4880        for instance in instances:4881            bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(4882                    context, instance.uuid, use_slave=use_slave)4883            instance_bdms = [bdm for bdm in bdms if bdm.is_volume]4884            compute_host_bdms.append(dict(instance=instance,4885                                          instance_bdms=instance_bdms))4886        return compute_host_bdms4887    def _update_volume_usage_cache(self, context, vol_usages):4888        """Updates the volume usage cache table with a list of stats."""4889        for usage in vol_usages:4890            # Allow switching of greenthreads between queries.4891            greenthread.sleep(0)4892            self.conductor_api.vol_usage_update(context, usage['volume'],4893                                                usage['rd_req'],4894                                                usage['rd_bytes'],4895                                                usage['wr_req'],4896                                                usage['wr_bytes'],4897                                                usage['instance'])4898    @periodic_task.periodic_task(spacing=CONF.volume_usage_poll_interval)4899    def _poll_volume_usage(self, context, start_time=None):4900        if CONF.volume_usage_poll_interval == 0:4901            return4902        if not start_time:4903            start_time = utils.last_completed_audit_period()[1]4904        compute_host_bdms = self._get_host_volume_bdms(context,4905                                                       use_slave=True)4906        if not compute_host_bdms:4907            return4908        LOG.debug("Updating volume usage cache")4909        try:4910            vol_usages = self.driver.get_all_volume_usage(context,4911                                                          compute_host_bdms)4912        except NotImplementedError:4913            return4914        self._update_volume_usage_cache(context, vol_usages)4915    @compute_utils.periodic_task_spacing_warn("sync_power_state_interval")4916    @periodic_task.periodic_task(spacing=CONF.sync_power_state_interval,4917                                 run_immediately=True)4918    def _sync_power_states(self, context):4919        """Align power states between the database and the hypervisor.4920        To sync power state data we make a DB call to get the number of4921        virtual machines known by the hypervisor and if the number matches the4922        number of virtual machines known by the database, we proceed in a lazy4923        loop, one database record at a time, checking if the hypervisor has the4924        same power state as is in the database.4925        """4926        db_instances = objects.InstanceList.get_by_host(context,4927                                                             self.host,4928                                                             use_slave=True)4929        num_vm_instances = self.driver.get_num_instances()4930        num_db_instances = len(db_instances)4931        if num_vm_instances != num_db_instances:4932            LOG.warn(_("Found %(num_db_instances)s in the database and "4933                       "%(num_vm_instances)s on the hypervisor."),4934                     {'num_db_instances': num_db_instances,4935                      'num_vm_instances': num_vm_instances})4936        def _sync(db_instance):4937            # NOTE(melwitt): This must be synchronized as we query state from4938            #                two separate sources, the driver and the database.4939            #                They are set (in stop_instance) and read, in sync.4940            @utils.synchronized(db_instance.uuid)4941            def query_driver_power_state_and_sync():4942                self._query_driver_power_state_and_sync(context, db_instance)4943            try:4944                query_driver_power_state_and_sync()4945            except Exception:4946                LOG.exception(_LE("Periodic sync_power_state task had an "4947                                  "error while processing an instance."),4948                              instance=db_instance)4949            self._syncs_in_progress.pop(db_instance.uuid)4950        for db_instance in db_instances:4951            # process syncs asynchronously - don't want instance locking to4952            # block entire periodic task thread4953            uuid = db_instance.uuid4954            if uuid in self._syncs_in_progress:4955                LOG.debug('Sync already in progress for %s' % uuid)4956            else:4957                LOG.debug('Triggering sync for uuid %s' % uuid)4958                self._syncs_in_progress[uuid] = True4959                self._sync_power_pool.spawn_n(_sync, db_instance)4960    def _query_driver_power_state_and_sync(self, context, db_instance):4961        if db_instance.task_state is not None:4962            LOG.info(_LI("During sync_power_state the instance has a "4963                         "pending task (%(task)s). Skip."),4964                     {'task': db_instance.task_state}, instance=db_instance)4965            return4966        # No pending tasks. Now try to figure out the real vm_power_state.4967        try:4968            vm_instance = self.driver.get_info(db_instance)4969            vm_power_state = vm_instance['state']4970        except exception.InstanceNotFound:4971            vm_power_state = power_state.NOSTATE4972        # Note(maoy): the above get_info call might take a long time,4973        # for example, because of a broken libvirt driver.4974        try:4975            self._sync_instance_power_state(context,4976                                            db_instance,4977                                            vm_power_state,4978                                            use_slave=True)4979        except exception.InstanceNotFound:4980            # NOTE(hanlind): If the instance gets deleted during sync,4981            # silently ignore.4982            pass4983    def _sync_instance_power_state(self, context, db_instance, vm_power_state,4984                                   use_slave=False):4985        """Align instance power state between the database and hypervisor.4986        If the instance is not found on the hypervisor, but is in the database,4987        then a stop() API will be called on the instance.4988        """4989        # We re-query the DB to get the latest instance info to minimize4990        # (not eliminate) race condition.4991        db_instance.refresh(use_slave=use_slave)4992        db_power_state = db_instance.power_state4993        vm_state = db_instance.vm_state4994        if self.host != db_instance.host:4995            # on the sending end of nova-compute _sync_power_state4996            # may have yielded to the greenthread performing a live4997            # migration; this in turn has changed the resident-host4998            # for the VM; However, the instance is still active, it4999            # is just in the process of migrating to another host.5000            # This implies that the compute source must relinquish5001            # control to the compute destination.5002            LOG.info(_("During the sync_power process the "5003                       "instance has moved from "5004                       "host %(src)s to host %(dst)s") %5005                       {'src': db_instance.host,5006                        'dst': self.host},5007                     instance=db_instance)5008            return5009        elif db_instance.task_state is not None:5010            # on the receiving end of nova-compute, it could happen5011            # that the DB instance already report the new resident5012            # but the actual VM has not showed up on the hypervisor5013            # yet. In this case, let's allow the loop to continue5014            # and run the state sync in a later round5015            LOG.info(_("During sync_power_state the instance has a "5016                       "pending task (%(task)s). Skip."),5017                     {'task': db_instance.task_state},5018                     instance=db_instance)5019            return5020        if vm_power_state != db_power_state:5021            # power_state is always updated from hypervisor to db5022            db_instance.power_state = vm_power_state5023            db_instance.save()5024            db_power_state = vm_power_state5025        # Note(maoy): Now resolve the discrepancy between vm_state and5026        # vm_power_state. We go through all possible vm_states.5027        if vm_state in (vm_states.BUILDING,5028                        vm_states.RESCUED,5029                        vm_states.RESIZED,5030                        vm_states.SUSPENDED,5031                        vm_states.ERROR):5032            # TODO(maoy): we ignore these vm_state for now.5033            pass5034        elif vm_state == vm_states.ACTIVE:5035            # The only rational power state should be RUNNING5036            if vm_power_state in (power_state.SHUTDOWN,5037                                  power_state.CRASHED):5038                LOG.warn(_LW("Instance shutdown by itself. Calling the stop "5039                             "API. Current vm_state: %(vm_state)s, current "5040                             "task_state: %(task_state)s, current DB "5041                             "power_state: %(db_power_state)s, current VM "5042                             "power_state: %(vm_power_state)s"),5043                         {'vm_state': vm_state,5044                          'task_state': db_instance.task_state,5045                          'db_power_state': db_power_state,5046                          'vm_power_state': vm_power_state},5047                         instance=db_instance)5048                try:5049                    # Note(maoy): here we call the API instead of5050                    # brutally updating the vm_state in the database5051                    # to allow all the hooks and checks to be performed.5052                    if db_instance.shutdown_terminate:5053                        self.compute_api.delete(context, db_instance)5054                    else:5055                        self.compute_api.stop(context, db_instance)5056                except Exception:5057                    # Note(maoy): there is no need to propagate the error5058                    # because the same power_state will be retrieved next5059                    # time and retried.5060                    # For example, there might be another task scheduled.5061                    LOG.exception(_LE("error during stop() in "5062                                      "sync_power_state."),5063                                  instance=db_instance)5064            elif vm_power_state == power_state.SUSPENDED:5065                LOG.warn(_("Instance is suspended unexpectedly. Calling "5066                           "the stop API."), instance=db_instance)5067                try:5068                    self.compute_api.stop(context, db_instance)5069                except Exception:5070                    LOG.exception(_LE("error during stop() in "5071                                      "sync_power_state."),5072                                  instance=db_instance)5073            elif vm_power_state == power_state.PAUSED:5074                # Note(maoy): a VM may get into the paused state not only5075                # because the user request via API calls, but also5076                # due to (temporary) external instrumentations.5077                # Before the virt layer can reliably report the reason,5078                # we simply ignore the state discrepancy. In many cases,5079                # the VM state will go back to running after the external5080                # instrumentation is done. See bug 1097806 for details.5081                LOG.warn(_("Instance is paused unexpectedly. Ignore."),5082                         instance=db_instance)5083            elif vm_power_state == power_state.NOSTATE:5084                # Occasionally, depending on the status of the hypervisor,5085                # which could be restarting for example, an instance may5086                # not be found.  Therefore just log the condition.5087                LOG.warn(_("Instance is unexpectedly not found. Ignore."),5088                         instance=db_instance)5089        elif vm_state == vm_states.STOPPED:5090            if vm_power_state not in (power_state.NOSTATE,5091                                      power_state.SHUTDOWN,5092                                      power_state.CRASHED):5093                LOG.warn(_LW("Instance is not stopped. Calling "5094                             "the stop API. Current vm_state: %(vm_state)s, "5095                             "current task_state: %(task_state)s, "5096                             "current DB power_state: %(db_power_state)s, "5097                             "current VM power_state: %(vm_power_state)s"),5098                         {'vm_state': vm_state,5099                          'task_state': db_instance.task_state,5100                          'db_power_state': db_power_state,5101                          'vm_power_state': vm_power_state},5102                         instance=db_instance)5103                try:5104                    # NOTE(russellb) Force the stop, because normally the5105                    # compute API would not allow an attempt to stop a stopped5106                    # instance.5107                    self.compute_api.force_stop(context, db_instance)5108                except Exception:5109                    LOG.exception(_LE("error during stop() in "5110                                      "sync_power_state."),5111                                  instance=db_instance)5112        elif vm_state == vm_states.PAUSED:5113            if vm_power_state in (power_state.SHUTDOWN,5114                                  power_state.CRASHED):5115                LOG.warn(_("Paused instance shutdown by itself. Calling "5116                           "the stop API."), instance=db_instance)5117                try:5118                    self.compute_api.force_stop(context, db_instance)5119                except Exception:5120                    LOG.exception(_LE("error during stop() in "5121                                      "sync_power_state."),5122                                  instance=db_instance)5123        elif vm_state in (vm_states.SOFT_DELETED,5124                          vm_states.DELETED):5125            if vm_power_state not in (power_state.NOSTATE,5126                                      power_state.SHUTDOWN):5127                # Note(maoy): this should be taken care of periodically in5128                # _cleanup_running_deleted_instances().5129                LOG.warn(_("Instance is not (soft-)deleted."),5130                         instance=db_instance)5131    @periodic_task.periodic_task5132    def _reclaim_queued_deletes(self, context):5133        """Reclaim instances that are queued for deletion."""5134        interval = CONF.reclaim_instance_interval5135        if interval <= 0:5136            LOG.debug("CONF.reclaim_instance_interval <= 0, skipping...")5137            return5138        # TODO(comstud, jichenjc): Dummy quota object for now See bug 1296414.5139        # The only case that the quota might be inconsistent is5140        # the compute node died between set instance state to SOFT_DELETED5141        # and quota commit to DB. When compute node starts again5142        # it will have no idea the reservation is committed or not or even5143        # expired, since it's a rare case, so marked as todo.5144        quotas = quotas_obj.Quotas.from_reservations(context, None)5145        filters = {'vm_state': vm_states.SOFT_DELETED,5146                   'task_state': None,5147                   'host': self.host}5148        instances = objects.InstanceList.get_by_filters(5149            context, filters,5150            expected_attrs=instance_obj.INSTANCE_DEFAULT_FIELDS,5151            use_slave=True)5152        for instance in instances:5153            if self._deleted_old_enough(instance, interval):5154                bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(5155                        context, instance.uuid)5156                LOG.info(_('Reclaiming deleted instance'), instance=instance)5157                try:5158                    self._delete_instance(context, instance, bdms, quotas)5159                except Exception as e:5160                    LOG.warning(_("Periodic reclaim failed to delete "5161                                  "instance: %s"),5162                                unicode(e), instance=instance)5163    @periodic_task.periodic_task5164    def update_available_resource(self, context):5165        """See driver.get_available_resource()5166        Periodic process that keeps that the compute host's understanding of5167        resource availability and usage in sync with the underlying hypervisor.5168        :param context: security context5169        """5170        new_resource_tracker_dict = {}5171        nodenames = set(self.driver.get_available_nodes())5172        for nodename in nodenames:5173            rt = self._get_resource_tracker(nodename)5174            rt.update_available_resource(context)5175            new_resource_tracker_dict[nodename] = rt5176        # Delete orphan compute node not reported by driver but still in db5177        compute_nodes_in_db = self._get_compute_nodes_in_db(context,5178                                                            use_slave=True)5179        for cn in compute_nodes_in_db:5180            if cn.hypervisor_hostname not in nodenames:5181                LOG.audit(_("Deleting orphan compute node %s") % cn.id)5182                cn.destroy()5183        self._resource_tracker_dict = new_resource_tracker_dict5184    def _get_compute_nodes_in_db(self, context, use_slave=False):5185        service = objects.Service.get_by_compute_host(context, self.host,5186                                                        use_slave=use_slave)5187        if not service:5188            LOG.error(_("No service record for host %s"), self.host)5189            return []5190        return objects.ComputeNodeList.get_by_service(context,5191                                                      service,5192                                                      use_slave=use_slave)5193    @periodic_task.periodic_task(5194        spacing=CONF.running_deleted_instance_poll_interval)5195    def _cleanup_running_deleted_instances(self, context):5196        """Cleanup any instances which are erroneously still running after5197        having been deleted.5198        Valid actions to take are:5199            1. noop - do nothing5200            2. log - log which instances are erroneously running5201            3. reap - shutdown and cleanup any erroneously running instances5202            4. shutdown - power off *and disable* any erroneously running5203                          instances5204        The use-case for this cleanup task is: for various reasons, it may be5205        possible for the database to show an instance as deleted but for that5206        instance to still be running on a host machine (see bug5207        https://bugs.launchpad.net/nova/+bug/911366).5208        This cleanup task is a cross-hypervisor utility for finding these5209        zombied instances and either logging the discrepancy (likely what you5210        should do in production), or automatically reaping the instances (more5211        appropriate for dev environments).5212        """5213        action = CONF.running_deleted_instance_action5214        if action == "noop":5215            return5216        # NOTE(sirp): admin contexts don't ordinarily return deleted records5217        with utils.temporary_mutation(context, read_deleted="yes"):5218            for instance in self._running_deleted_instances(context):5219                bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(5220                        context, instance.uuid, use_slave=True)5221                if action == "log":5222                    LOG.warning(_("Detected instance with name label "5223                                  "'%s' which is marked as "5224                                  "DELETED but still present on host."),5225                                instance['name'], instance=instance)5226                elif action == 'shutdown':5227                    LOG.info(_("Powering off instance with name label "5228                               "'%s' which is marked as "5229                               "DELETED but still present on host."),5230                               instance['name'], instance=instance)5231                    try:5232                        try:5233                            # disable starting the instance5234                            self.driver.set_bootable(instance, False)5235                        except NotImplementedError:5236                            LOG.warn(_("set_bootable is not implemented for "5237                                       "the current driver"))5238                        # and power it off5239                        self.driver.power_off(instance)5240                    except Exception:5241                        msg = _("Failed to power off instance")5242                        LOG.warn(msg, instance=instance, exc_info=True)5243                elif action == 'reap':5244                    LOG.info(_("Destroying instance with name label "5245                               "'%s' which is marked as "5246                               "DELETED but still present on host."),5247                             instance['name'], instance=instance)5248                    self.instance_events.clear_events_for_instance(instance)5249                    try:5250                        self._shutdown_instance(context, instance, bdms,5251                                                notify=False)5252                        self._cleanup_volumes(context, instance['uuid'], bdms)5253                    except Exception as e:5254                        LOG.warning(_("Periodic cleanup failed to delete "5255                                      "instance: %s"),5256                                    unicode(e), instance=instance)5257                else:5258                    raise Exception(_("Unrecognized value '%s'"5259                                      " for CONF.running_deleted_"5260                                      "instance_action") % action)5261    def _running_deleted_instances(self, context):5262        """Returns a list of instances nova thinks is deleted,5263        but the hypervisor thinks is still running.5264        """5265        timeout = CONF.running_deleted_instance_timeout5266        filters = {'deleted': True,5267                   'soft_deleted': False,5268                   'host': self.host}5269        instances = self._get_instances_on_driver(context, filters)5270        return [i for i in instances if self._deleted_old_enough(i, timeout)]5271    def _deleted_old_enough(self, instance, timeout):5272        deleted_at = instance['deleted_at']5273        if isinstance(instance, obj_base.NovaObject) and deleted_at:5274            deleted_at = deleted_at.replace(tzinfo=None)5275        return (not deleted_at or timeutils.is_older_than(deleted_at, timeout))5276    @contextlib.contextmanager5277    def _error_out_instance_on_exception(self, context, instance,5278                                         quotas=None,5279                                         instance_state=vm_states.ACTIVE):5280        instance_uuid = instance['uuid']5281        try:5282            yield5283        except NotImplementedError as error:5284            with excutils.save_and_reraise_exception():5285                if quotas:5286                    quotas.rollback()5287                LOG.info(_("Setting instance back to %(state)s after: "5288                           "%(error)s") %5289                         {'state': instance_state, 'error': error},5290                         instance_uuid=instance_uuid)5291                self._instance_update(context, instance_uuid,5292                                      vm_state=instance_state,5293                                      task_state=None)5294        except exception.InstanceFaultRollback as error:5295            if quotas:5296                quotas.rollback()5297            LOG.info(_("Setting instance back to ACTIVE after: %s"),5298                     error, instance_uuid=instance_uuid)5299            self._instance_update(context, instance_uuid,5300                                  vm_state=vm_states.ACTIVE,5301                                  task_state=None)5302            raise error.inner_exception5303        except Exception:5304            LOG.exception(_LE('Setting instance vm_state to ERROR'),5305                          instance_uuid=instance_uuid)5306            with excutils.save_and_reraise_exception():5307                if quotas:5308                    quotas.rollback()5309                self._set_instance_error_state(context, instance)5310    @aggregate_object_compat5311    @wrap_exception()5312    def add_aggregate_host(self, context, aggregate, host, slave_info):5313        """Notify hypervisor of change (for hypervisor pools)."""5314        try:5315            self.driver.add_to_aggregate(context, aggregate, host,5316                                         slave_info=slave_info)5317        except NotImplementedError:5318            LOG.debug('Hypervisor driver does not support '5319                      'add_aggregate_host')5320        except exception.AggregateError:5321            with excutils.save_and_reraise_exception():5322                self.driver.undo_aggregate_operation(5323                                    context,5324                                    aggregate.delete_host,5325                                    aggregate, host)5326    @aggregate_object_compat5327    @wrap_exception()5328    def remove_aggregate_host(self, context, host, slave_info, aggregate):5329        """Removes a host from a physical hypervisor pool."""5330        try:5331            self.driver.remove_from_aggregate(context, aggregate, host,5332                                              slave_info=slave_info)5333        except NotImplementedError:5334            LOG.debug('Hypervisor driver does not support '5335                      'remove_aggregate_host')5336        except (exception.AggregateError,5337                exception.InvalidAggregateAction) as e:5338            with excutils.save_and_reraise_exception():5339                self.driver.undo_aggregate_operation(5340                                    context,5341                                    aggregate.add_host,5342                                    aggregate, host,5343                                    isinstance(e, exception.AggregateError))5344    def _process_instance_event(self, instance, event):5345        _event = self.instance_events.pop_instance_event(instance, event)5346        if _event:5347            LOG.debug('Processing event %(event)s',5348                      {'event': event.key}, instance=instance)5349            _event.send(event)5350    @wrap_exception()5351    def external_instance_event(self, context, instances, events):5352        # NOTE(danms): Some event types are handled by the manager, such5353        # as when we're asked to update the instance's info_cache. If it's5354        # not one of those, look for some thread(s) waiting for the event and5355        # unblock them if so.5356        for event in events:5357            instance = [inst for inst in instances...rpcapi.py
Source:rpcapi.py  
...56        * 1.1 - Adds get_host_uptime()57        * 1.2 - Adds check_can_live_migrate_[destination|source]58        * 1.3 - Adds change_instance_metadata()59        * 1.4 - Remove instance_uuid, add instance argument to60                reboot_instance()61        * 1.5 - Remove instance_uuid, add instance argument to62                pause_instance(), unpause_instance()63        * 1.6 - Remove instance_uuid, add instance argument to64                suspend_instance()65        * 1.7 - Remove instance_uuid, add instance argument to66                get_console_output()67        * 1.8 - Remove instance_uuid, add instance argument to68                add_fixed_ip_to_instance()69        * 1.9 - Remove instance_uuid, add instance argument to attach_volume()70        * 1.10 - Remove instance_id, add instance argument to71                 check_can_live_migrate_destination()72        * 1.11 - Remove instance_id, add instance argument to73                 check_can_live_migrate_source()74        * 1.12 - Remove instance_uuid, add instance argument to75                 confirm_resize()76        * 1.13 - Remove instance_uuid, add instance argument to detach_volume()77        * 1.14 - Remove instance_uuid, add instance argument to finish_resize()78        * 1.15 - Remove instance_uuid, add instance argument to79                 finish_revert_resize()80        * 1.16 - Remove instance_uuid, add instance argument to81                 get_diagnostics()82        * 1.17 - Remove instance_uuid, add instance argument to83                 get_vnc_console()84        * 1.18 - Remove instance_uuid, add instance argument to inject_file()85        * 1.19 - Remove instance_uuid, add instance argument to86                 inject_network_info()87        * 1.20 - Remove instance_id, add instance argument to88                 post_live_migration_at_destination()89        * 1.21 - Remove instance_uuid, add instance argument to90                 power_off_instance() and stop_instance()91        * 1.22 - Remove instance_uuid, add instance argument to92                 power_on_instance() and start_instance()93        * 1.23 - Remove instance_id, add instance argument to94                 pre_live_migration()95        * 1.24 - Remove instance_uuid, add instance argument to96                 rebuild_instance()97        * 1.25 - Remove instance_uuid, add instance argument to98                 remove_fixed_ip_from_instance()99        * 1.26 - Remove instance_id, add instance argument to100                 remove_volume_connection()101        * 1.27 - Remove instance_uuid, add instance argument to102                 rescue_instance()103        * 1.28 - Remove instance_uuid, add instance argument to reset_network()104        * 1.29 - Remove instance_uuid, add instance argument to105                 resize_instance()106        * 1.30 - Remove instance_uuid, add instance argument to107                 resume_instance()108        * 1.31 - Remove instance_uuid, add instance argument to revert_resize()109        * 1.32 - Remove instance_id, add instance argument to110                 rollback_live_migration_at_destination()111        * 1.33 - Remove instance_uuid, add instance argument to112                 set_admin_password()113        * 1.34 - Remove instance_uuid, add instance argument to114                 snapshot_instance()115        * 1.35 - Remove instance_uuid, add instance argument to116                 unrescue_instance()117        * 1.36 - Remove instance_uuid, add instance argument to118                 change_instance_metadata()119        * 1.37 - Remove instance_uuid, add instance argument to120                 terminate_instance()121        * 1.38 - Changes to prep_resize():122            * remove instance_uuid, add instance123            * remove instance_type_id, add instance_type124            * remove topic, it was unused125        * 1.39 - Remove instance_uuid, add instance argument to run_instance()126        * 1.40 - Remove instance_id, add instance argument to live_migration()127        * 1.41 - Adds refresh_instance_security_rules()128        * 1.42 - Add reservations arg to prep_resize(), resize_instance(),129                 finish_resize(), confirm_resize(), revert_resize() and130                 finish_revert_resize()131        * 1.43 - Add migrate_data to live_migration()132        * 1.44 - Adds reserve_block_device_name()133        * 2.0 - Remove 1.x backwards compat134        * 2.1 - Adds orig_sys_metadata to rebuild_instance()135        * 2.2 - Adds slave_info parameter to add_aggregate_host() and136                remove_aggregate_host()137        * 2.3 - Adds volume_id to reserve_block_device_name()138        * 2.4 - Add bdms to terminate_instance139        * 2.5 - Add block device and network info to reboot_instance140        * 2.6 - Remove migration_id, add migration to resize_instance141        * 2.7 - Remove migration_id, add migration to confirm_resize142        * 2.8 - Remove migration_id, add migration to finish_resize143        * 2.9 - Add publish_service_capabilities()144        * 2.10 - Adds filter_properties and request_spec to prep_resize()145        * 2.11 - Adds soft_delete_instance() and restore_instance()146        * 2.12 - Remove migration_id, add migration to revert_resize147        * 2.13 - Remove migration_id, add migration to finish_revert_resize148        * 2.14 - Remove aggregate_id, add aggregate to add_aggregate_host149        * 2.15 - Remove aggregate_id, add aggregate to remove_aggregate_host150        * 2.16 - Add instance_type to resize_instance151        * 2.17 - Add get_backdoor_port()152        * 2.18 - Add bdms to rebuild_instance153        * 2.19 - Add node to run_instance154        * 2.20 - Add node to prep_resize155        * 2.21 - Add migrate_data dict param to pre_live_migration()156        * 2.22 - Add recreate, on_shared_storage and host arguments to157                 rebuild_instance()158        * 2.23 - Remove network_info from reboot_instance159        * 2.24 - Added get_spice_console method160        * 2.25 - Add attach_interface() and detach_interface()161        * 2.26 - Add validate_console_port to ensure the service connects to162                 vnc on the correct port163        * 2.27 - Adds 'reservations' to terminate_instance() and164                 soft_delete_instance()165        ... Grizzly supports message version 2.27.  So, any changes to existing166        methods in 2.x after that point should be done such that they can167        handle the version_cap being set to 2.27.168        * 2.28 - Adds check_instance_shared_storage()169        * 2.29 - Made start_instance() and stop_instance() take new-world170                 instance objects171        * 2.30 - Adds live_snapshot_instance()172        * 2.31 - Adds shelve_instance(), shelve_offload_instance, and173                 unshelve_instance()174        * 2.32 - Make reboot_instance take a new world instance object175        * 2.33 - Made suspend_instance() and resume_instance() take new-world176                 instance objects177        * 2.34 - Added swap_volume()178        * 2.35 - Made terminate_instance() and soft_delete_instance() take179                 new-world instance objects180        * 2.36 - Made pause_instance() and unpause_instance() take new-world181                 instance objects182        * 2.37 - Added the legacy_bdm_in_spec parameter to run_instance183        * 2.38 - Made check_can_live_migrate_[destination|source] take184                 new-world instance objects185        * 2.39 - Made revert_resize() and confirm_resize() take new-world186                 instance objects187        * 2.40 - Made reset_network() take new-world instance object188        * 2.41 - Make inject_network_info take new-world instance object189        * 2.42 - Splits snapshot_instance() into snapshot_instance() and190                 backup_instance() and makes them take new-world instance191                 objects.192        * 2.43 - Made prep_resize() take new-world instance object193        * 2.44 - Add volume_snapshot_create(), volume_snapshot_delete()194        * 2.45 - Made resize_instance() take new-world objects195        * 2.46 - Made finish_resize() take new-world objects196        * 2.47 - Made finish_revert_resize() take new-world objects197        ... Havana supports message version 2.47.  So, any changes to existing198        methods in 2.x after that point should be done such that they can199        handle the version_cap being set to 2.47.200        * 2.48 - Make add_aggregate_host() and remove_aggregate_host() take201          new-world objects202        * ... - Remove live_snapshot() that was never actually used203        * 3.0 - Remove 2.x compatibility204        * 3.1 - Update get_spice_console() to take an instance object205        * 3.2 - Update get_vnc_console() to take an instance object206        * 3.3 - Update validate_console_port() to take an instance object207        * 3.4 - Update rebuild_instance() to take an instance object208        * 3.5 - Pass preserve_ephemeral flag to rebuild_instance()209        * 3.6 - Make volume_snapshot_{create,delete} use new-world objects210        * 3.7 - Update change_instance_metadata() to take an instance object211        * 3.8 - Update set_admin_password() to take an instance object212        * 3.9 - Update rescue_instance() to take an instance object213        * 3.10 - Added get_rdp_console method214        * 3.11 - Update unrescue_instance() to take an object215        * 3.12 - Update add_fixed_ip_to_instance() to take an object216        * 3.13 - Update remove_fixed_ip_from_instance() to take an object217        * 3.14 - Update post_live_migration_at_destination() to take an object218        * 3.15 - Adds filter_properties and node to unshelve_instance()219        * 3.16 - Make reserve_block_device_name and attach_volume use new-world220                 objects, and add disk_bus and device_type params to221                 reserve_block_device_name, and bdm param to attach_volume222        * 3.17 - Update attach_interface and detach_interface to take an object223        * 3.18 - Update get_diagnostics() to take an instance object224            * Removed inject_file(), as it was unused.225        * 3.19 - Update pre_live_migration to take instance object226        * 3.20 - Make restore_instance take an instance object227        * 3.21 - Made rebuild take new-world BDM objects228        * 3.22 - Made terminate_instance take new-world BDM objects229        * 3.23 - Added external_instance_event()230            * build_and_run_instance was added in Havana and not used or231              documented.232        ... Icehouse supports message version 3.23.  So, any changes to233        existing methods in 3.x after that point should be done such that they234        can handle the version_cap being set to 3.23.235        * 3.24 - Update rescue_instance() to take optional rescue_image_ref236        * 3.25 - Make detach_volume take an object237        * 3.26 - Make live_migration() and238          rollback_live_migration_at_destination() take an object239        * ... Removed run_instance()240        * 3.27 - Make run_instance() accept a new-world object241        * 3.28 - Update get_console_output() to accept a new-world object242        * 3.29 - Make check_instance_shared_storage accept a new-world object243        * 3.30 - Make remove_volume_connection() accept a new-world object244        * 3.31 - Add get_instance_diagnostics245        * 3.32 - Add destroy_disks and migrate_data optional parameters to246                 rollback_live_migration_at_destination()247        * 3.33 - Make build_and_run_instance() take a NetworkRequestList object248        * 3.34 - Add get_serial_console method249    '''250    VERSION_ALIASES = {251        'icehouse': '3.23',252    }253    def __init__(self):254        super(ComputeAPI, self).__init__()255        target = messaging.Target(topic=CONF.compute_topic, version='3.0')256        version_cap = self.VERSION_ALIASES.get(CONF.upgrade_levels.compute,257                                               CONF.upgrade_levels.compute)258        serializer = objects_base.NovaObjectSerializer()259        self.client = self.get_client(target, version_cap, serializer)260    # Cells overrides this261    def get_client(self, target, version_cap, serializer):262        return rpc.get_client(target,263                              version_cap=version_cap,264                              serializer=serializer)265    def _check_live_migration_api_version(self, server):266        # NOTE(angdraug): live migration involving a compute host running Nova267        # API older than v3.32 as either source or destination can cause268        # instance disks to be deleted from shared storage269        if not self.client.can_send_version('3.32'):270            raise exception.LiveMigrationWithOldNovaNotSafe(server=server)271    def add_aggregate_host(self, ctxt, aggregate, host_param, host,272                           slave_info=None):273        '''Add aggregate host.274        :param ctxt: request context275        :param aggregate_id:276        :param host_param: This value is placed in the message to be the 'host'277                           parameter for the remote method.278        :param host: This is the host to send the message to.279        '''280        version = '3.0'281        cctxt = self.client.prepare(server=host, version=version)282        cctxt.cast(ctxt, 'add_aggregate_host',283                   aggregate=aggregate, host=host_param,284                   slave_info=slave_info)285    def add_fixed_ip_to_instance(self, ctxt, instance, network_id):286        version = '3.12'287        cctxt = self.client.prepare(server=_compute_host(None, instance),288                version=version)289        cctxt.cast(ctxt, 'add_fixed_ip_to_instance',290                   instance=instance, network_id=network_id)291    def attach_interface(self, ctxt, instance, network_id, port_id,292                         requested_ip):293        version = '3.17'294        cctxt = self.client.prepare(server=_compute_host(None, instance),295                version=version)296        return cctxt.call(ctxt, 'attach_interface',297                          instance=instance, network_id=network_id,298                          port_id=port_id, requested_ip=requested_ip)299    def attach_volume(self, ctxt, instance, volume_id, mountpoint, bdm=None):300        # NOTE(ndipanov): Remove volume_id and mountpoint on the next major301        # version bump - they are not needed when using bdm objects.302        version = '3.16'303        kw = {'instance': instance, 'volume_id': volume_id,304              'mountpoint': mountpoint, 'bdm': bdm}305        cctxt = self.client.prepare(server=_compute_host(None, instance),306                version=version)307        cctxt.cast(ctxt, 'attach_volume', **kw)308    def change_instance_metadata(self, ctxt, instance, diff):309        version = '3.7'310        cctxt = self.client.prepare(server=_compute_host(None, instance),311                version=version)312        cctxt.cast(ctxt, 'change_instance_metadata',313                   instance=instance, diff=diff)314    def check_can_live_migrate_destination(self, ctxt, instance, destination,315                                           block_migration, disk_over_commit):316        self._check_live_migration_api_version(destination)317        cctxt = self.client.prepare(server=destination, version='3.32')318        return cctxt.call(ctxt, 'check_can_live_migrate_destination',319                          instance=instance,320                          block_migration=block_migration,321                          disk_over_commit=disk_over_commit)322    def check_can_live_migrate_source(self, ctxt, instance, dest_check_data):323        source = _compute_host(None, instance)324        self._check_live_migration_api_version(source)325        cctxt = self.client.prepare(server=source, version='3.32')326        return cctxt.call(ctxt, 'check_can_live_migrate_source',327                          instance=instance,328                          dest_check_data=dest_check_data)329    def check_instance_shared_storage(self, ctxt, instance, data):330        if self.client.can_send_version('3.29'):331            version = '3.29'332        else:333            version = '3.0'334            instance = jsonutils.to_primitive(instance)335        cctxt = self.client.prepare(server=_compute_host(None, instance),336                version=version)337        return cctxt.call(ctxt, 'check_instance_shared_storage',338                          instance=instance,339                          data=data)340    def confirm_resize(self, ctxt, instance, migration, host,341            reservations=None, cast=True):342        version = '3.0'343        cctxt = self.client.prepare(server=_compute_host(host, instance),344                version=version)345        rpc_method = cctxt.cast if cast else cctxt.call346        return rpc_method(ctxt, 'confirm_resize',347                          instance=instance, migration=migration,348                          reservations=reservations)349    def detach_interface(self, ctxt, instance, port_id):350        version = '3.17'351        cctxt = self.client.prepare(server=_compute_host(None, instance),352                version=version)353        cctxt.cast(ctxt, 'detach_interface',354                   instance=instance, port_id=port_id)355    def detach_volume(self, ctxt, instance, volume_id):356        if self.client.can_send_version('3.25'):357            version = '3.25'358        else:359            version = '3.0'360            instance = jsonutils.to_primitive(instance)361        cctxt = self.client.prepare(server=_compute_host(None, instance),362                version=version)363        cctxt.cast(ctxt, 'detach_volume',364                   instance=instance, volume_id=volume_id)365    def finish_resize(self, ctxt, instance, migration, image, disk_info,366            host, reservations=None):367        version = '3.0'368        cctxt = self.client.prepare(server=host, version=version)369        cctxt.cast(ctxt, 'finish_resize',370                   instance=instance, migration=migration,371                   image=image, disk_info=disk_info, reservations=reservations)372    def finish_revert_resize(self, ctxt, instance, migration, host,373                             reservations=None):374        version = '3.0'375        cctxt = self.client.prepare(server=host, version=version)376        cctxt.cast(ctxt, 'finish_revert_resize',377                   instance=instance, migration=migration,378                   reservations=reservations)379    def get_console_output(self, ctxt, instance, tail_length):380        if self.client.can_send_version('3.28'):381            version = '3.28'382        else:383            version = '3.0'384            instance = jsonutils.to_primitive(instance)385        cctxt = self.client.prepare(server=_compute_host(None, instance),386                version=version)387        return cctxt.call(ctxt, 'get_console_output',388                          instance=instance, tail_length=tail_length)389    def get_console_pool_info(self, ctxt, console_type, host):390        version = '3.0'391        cctxt = self.client.prepare(server=host, version=version)392        return cctxt.call(ctxt, 'get_console_pool_info',393                          console_type=console_type)394    def get_console_topic(self, ctxt, host):395        version = '3.0'396        cctxt = self.client.prepare(server=host, version=version)397        return cctxt.call(ctxt, 'get_console_topic')398    def get_diagnostics(self, ctxt, instance):399        version = '3.18'400        cctxt = self.client.prepare(server=_compute_host(None, instance),401                version=version)402        return cctxt.call(ctxt, 'get_diagnostics', instance=instance)403    def get_instance_diagnostics(self, ctxt, instance):404        instance_p = jsonutils.to_primitive(instance)405        kwargs = {'instance': instance_p}406        version = '3.31'407        cctxt = self.client.prepare(server=_compute_host(None, instance),408                version=version)409        return cctxt.call(ctxt, 'get_instance_diagnostics', **kwargs)410    def get_vnc_console(self, ctxt, instance, console_type):411        version = '3.2'412        cctxt = self.client.prepare(server=_compute_host(None, instance),413                version=version)414        return cctxt.call(ctxt, 'get_vnc_console',415                          instance=instance, console_type=console_type)416    def get_spice_console(self, ctxt, instance, console_type):417        version = '3.1'418        cctxt = self.client.prepare(server=_compute_host(None, instance),419                version=version)420        return cctxt.call(ctxt, 'get_spice_console',421                          instance=instance, console_type=console_type)422    def get_rdp_console(self, ctxt, instance, console_type):423        version = '3.10'424        cctxt = self.client.prepare(server=_compute_host(None, instance),425                version=version)426        return cctxt.call(ctxt, 'get_rdp_console',427                          instance=instance, console_type=console_type)428    def get_serial_console(self, ctxt, instance, console_type):429        version = '3.34'430        cctxt = self.client.prepare(server=_compute_host(None, instance),431                                    version=version)432        return cctxt.call(ctxt, 'get_serial_console',433                          instance=instance, console_type=console_type)434    def validate_console_port(self, ctxt, instance, port, console_type):435        version = '3.3'436        cctxt = self.client.prepare(server=_compute_host(None, instance),437                version=version)438        return cctxt.call(ctxt, 'validate_console_port',439                          instance=instance, port=port,440                          console_type=console_type)441    def host_maintenance_mode(self, ctxt, host_param, mode, host):442        '''Set host maintenance mode443        :param ctxt: request context444        :param host_param: This value is placed in the message to be the 'host'445                           parameter for the remote method.446        :param mode:447        :param host: This is the host to send the message to.448        '''449        version = '3.0'450        cctxt = self.client.prepare(server=host, version=version)451        return cctxt.call(ctxt, 'host_maintenance_mode',452                          host=host_param, mode=mode)453    def host_power_action(self, ctxt, action, host):454        version = '3.0'455        cctxt = self.client.prepare(server=host, version=version)456        return cctxt.call(ctxt, 'host_power_action', action=action)457    def inject_network_info(self, ctxt, instance):458        version = '3.0'459        cctxt = self.client.prepare(server=_compute_host(None, instance),460                version=version)461        cctxt.cast(ctxt, 'inject_network_info', instance=instance)462    def live_migration(self, ctxt, instance, dest, block_migration, host,463                       migrate_data=None):464        if self.client.can_send_version('3.26'):465            version = '3.26'466        else:467            version = '3.0'468            instance = jsonutils.to_primitive(instance)469        cctxt = self.client.prepare(server=host, version=version)470        cctxt.cast(ctxt, 'live_migration', instance=instance,471                   dest=dest, block_migration=block_migration,472                   migrate_data=migrate_data)473    def pause_instance(self, ctxt, instance):474        version = '3.0'475        cctxt = self.client.prepare(server=_compute_host(None, instance),476                version=version)477        cctxt.cast(ctxt, 'pause_instance', instance=instance)478    def post_live_migration_at_destination(self, ctxt, instance,479            block_migration, host):480        version = '3.14'481        cctxt = self.client.prepare(server=host, version=version)482        cctxt.cast(ctxt, 'post_live_migration_at_destination',483            instance=instance, block_migration=block_migration)484    def pre_live_migration(self, ctxt, instance, block_migration, disk,485            host, migrate_data=None):486        version = '3.19'487        cctxt = self.client.prepare(server=host, version=version)488        return cctxt.call(ctxt, 'pre_live_migration',489                          instance=instance,490                          block_migration=block_migration,491                          disk=disk, migrate_data=migrate_data)492    def prep_resize(self, ctxt, image, instance, instance_type, host,493                    reservations=None, request_spec=None,494                    filter_properties=None, node=None):495        version = '3.0'496        instance_type_p = jsonutils.to_primitive(instance_type)497        image_p = jsonutils.to_primitive(image)498        cctxt = self.client.prepare(server=host, version=version)499        cctxt.cast(ctxt, 'prep_resize',500                   instance=instance,501                   instance_type=instance_type_p,502                   image=image_p, reservations=reservations,503                   request_spec=request_spec,504                   filter_properties=filter_properties,505                   node=node)506    def reboot_instance(self, ctxt, instance, block_device_info,507                        reboot_type):508        version = '3.0'509        cctxt = self.client.prepare(server=_compute_host(None, instance),510                version=version)511        cctxt.cast(ctxt, 'reboot_instance',512                   instance=instance,513                   block_device_info=block_device_info,514                   reboot_type=reboot_type)515    def rebuild_instance(self, ctxt, instance, new_pass, injected_files,516            image_ref, orig_image_ref, orig_sys_metadata, bdms,517            recreate=False, on_shared_storage=False, host=None,518            preserve_ephemeral=False, kwargs=None):519        # NOTE(danms): kwargs is only here for cells compatibility, don't520        # actually send it to compute521        extra = {'preserve_ephemeral': preserve_ephemeral}522        version = '3.21'523        cctxt = self.client.prepare(server=_compute_host(host, instance),524                version=version)525        cctxt.cast(ctxt, 'rebuild_instance',526                   instance=instance, new_pass=new_pass,527                   injected_files=injected_files, image_ref=image_ref,528                   orig_image_ref=orig_image_ref,529                   orig_sys_metadata=orig_sys_metadata, bdms=bdms,530                   recreate=recreate, on_shared_storage=on_shared_storage,531                   **extra)532    def refresh_provider_fw_rules(self, ctxt, host):533        version = '3.0'534        cctxt = self.client.prepare(server=host, version=version)535        cctxt.cast(ctxt, 'refresh_provider_fw_rules')536    def remove_aggregate_host(self, ctxt, aggregate, host_param, host,537                              slave_info=None):538        '''Remove aggregate host.539        :param ctxt: request context540        :param aggregate_id:541        :param host_param: This value is placed in the message to be the 'host'542                           parameter for the remote method.543        :param host: This is the host to send the message to.544        '''545        version = '3.0'546        cctxt = self.client.prepare(server=host, version=version)547        cctxt.cast(ctxt, 'remove_aggregate_host',548                   aggregate=aggregate, host=host_param,549                   slave_info=slave_info)550    def remove_fixed_ip_from_instance(self, ctxt, instance, address):551        version = '3.13'552        cctxt = self.client.prepare(server=_compute_host(None, instance),553                version=version)554        cctxt.cast(ctxt, 'remove_fixed_ip_from_instance',555                   instance=instance, address=address)556    def remove_volume_connection(self, ctxt, instance, volume_id, host):557        if self.client.can_send_version('3.30'):558            version = '3.30'559        else:560            version = '3.0'561            instance = jsonutils.to_primitive(instance)562        cctxt = self.client.prepare(server=host, version=version)563        return cctxt.call(ctxt, 'remove_volume_connection',564                          instance=instance, volume_id=volume_id)565    def rescue_instance(self, ctxt, instance, rescue_password,566                        rescue_image_ref=None):567        msg_args = {'rescue_password': rescue_password}568        if self.client.can_send_version('3.24'):569            version = '3.24'570            msg_args['rescue_image_ref'] = rescue_image_ref571        else:572            version = '3.9'573        msg_args['instance'] = instance574        cctxt = self.client.prepare(server=_compute_host(None, instance),575                version=version)576        cctxt.cast(ctxt, 'rescue_instance', **msg_args)577    def reset_network(self, ctxt, instance):578        version = '3.0'579        cctxt = self.client.prepare(server=_compute_host(None, instance),580                version=version)581        cctxt.cast(ctxt, 'reset_network', instance=instance)582    def resize_instance(self, ctxt, instance, migration, image, instance_type,583                        reservations=None):584        version = '3.0'585        instance_type_p = jsonutils.to_primitive(instance_type)586        cctxt = self.client.prepare(server=_compute_host(None, instance),587                version=version)588        cctxt.cast(ctxt, 'resize_instance',589                   instance=instance, migration=migration,590                   image=image, reservations=reservations,591                   instance_type=instance_type_p)592    def resume_instance(self, ctxt, instance):593        version = '3.0'594        cctxt = self.client.prepare(server=_compute_host(None, instance),595                version=version)596        cctxt.cast(ctxt, 'resume_instance', instance=instance)597    def revert_resize(self, ctxt, instance, migration, host,598                      reservations=None):599        version = '3.0'600        cctxt = self.client.prepare(server=_compute_host(host, instance),601                version=version)602        cctxt.cast(ctxt, 'revert_resize',603                   instance=instance, migration=migration,604                   reservations=reservations)605    def rollback_live_migration_at_destination(self, ctxt, instance, host,606                                               destroy_disks=True,607                                               migrate_data=None):608        self._check_live_migration_api_version(host)609        cctxt = self.client.prepare(server=host, version='3.32')610        cctxt.cast(ctxt, 'rollback_live_migration_at_destination',611                   instance=instance,612                   destroy_disks=destroy_disks, migrate_data=migrate_data)613    # NOTE(alaski): Remove this method when the scheduler rpc interface is614    # bumped to 4.x as the only callers of this method will be removed.615    def run_instance(self, ctxt, instance, host, request_spec,616                     filter_properties, requested_networks,617                     injected_files, admin_password,618                     is_first_time, node=None, legacy_bdm_in_spec=True):619        if self.client.can_send_version('3.27'):620            version = '3.27'621        else:622            version = '3.0'623            instance = jsonutils.to_primitive(instance)624        msg_kwargs = {'instance': instance, 'request_spec': request_spec,625                      'filter_properties': filter_properties,626                      'requested_networks': requested_networks,627                      'injected_files': injected_files,628                      'admin_password': admin_password,629                      'is_first_time': is_first_time, 'node': node,630                      'legacy_bdm_in_spec': legacy_bdm_in_spec}631        cctxt = self.client.prepare(server=host, version=version)632        cctxt.cast(ctxt, 'run_instance', **msg_kwargs)633    def set_admin_password(self, ctxt, instance, new_pass):634        version = '3.8'635        cctxt = self.client.prepare(server=_compute_host(None, instance),636                version=version)637        return cctxt.call(ctxt, 'set_admin_password',638                          instance=instance, new_pass=new_pass)639    def set_host_enabled(self, ctxt, enabled, host):640        version = '3.0'641        cctxt = self.client.prepare(server=host, version=version)642        return cctxt.call(ctxt, 'set_host_enabled', enabled=enabled)643    def swap_volume(self, ctxt, instance, old_volume_id, new_volume_id):644        version = '3.0'645        cctxt = self.client.prepare(server=_compute_host(None, instance),646                version=version)647        cctxt.cast(ctxt, 'swap_volume',648                   instance=instance, old_volume_id=old_volume_id,649                   new_volume_id=new_volume_id)650    def get_host_uptime(self, ctxt, host):651        version = '3.0'652        cctxt = self.client.prepare(server=host, version=version)653        return cctxt.call(ctxt, 'get_host_uptime')654    def reserve_block_device_name(self, ctxt, instance, device, volume_id,655                                  disk_bus=None, device_type=None):656        version = '3.16'657        kw = {'instance': instance, 'device': device,658              'volume_id': volume_id, 'disk_bus': disk_bus,659              'device_type': device_type}660        cctxt = self.client.prepare(server=_compute_host(None, instance),661                version=version)662        return cctxt.call(ctxt, 'reserve_block_device_name', **kw)663    def backup_instance(self, ctxt, instance, image_id, backup_type,664                        rotation):665        version = '3.0'666        cctxt = self.client.prepare(server=_compute_host(None, instance),667                version=version)668        cctxt.cast(ctxt, 'backup_instance',669                   instance=instance,670                   image_id=image_id,671                   backup_type=backup_type,672                   rotation=rotation)673    def snapshot_instance(self, ctxt, instance, image_id):674        version = '3.0'675        cctxt = self.client.prepare(server=_compute_host(None, instance),676                version=version)677        cctxt.cast(ctxt, 'snapshot_instance',678                   instance=instance,679                   image_id=image_id)680    def start_instance(self, ctxt, instance):681        version = '3.0'682        cctxt = self.client.prepare(server=_compute_host(None, instance),683                version=version)684        cctxt.cast(ctxt, 'start_instance', instance=instance)685    def stop_instance(self, ctxt, instance, do_cast=True):686        version = '3.0'687        cctxt = self.client.prepare(server=_compute_host(None, instance),688                version=version)689        rpc_method = cctxt.cast if do_cast else cctxt.call690        return rpc_method(ctxt, 'stop_instance', instance=instance)691    def suspend_instance(self, ctxt, instance):692        version = '3.0'693        cctxt = self.client.prepare(server=_compute_host(None, instance),694                version=version)695        cctxt.cast(ctxt, 'suspend_instance', instance=instance)696    def terminate_instance(self, ctxt, instance, bdms, reservations=None):697        version = '3.22'698        cctxt = self.client.prepare(server=_compute_host(None, instance),699                version=version)700        cctxt.cast(ctxt, 'terminate_instance',701                   instance=instance, bdms=bdms,702                   reservations=reservations)703    def unpause_instance(self, ctxt, instance):704        version = '3.0'705        cctxt = self.client.prepare(server=_compute_host(None, instance),706                version=version)707        cctxt.cast(ctxt, 'unpause_instance', instance=instance)708    def unrescue_instance(self, ctxt, instance):709        version = '3.11'710        cctxt = self.client.prepare(server=_compute_host(None, instance),711                version=version)712        cctxt.cast(ctxt, 'unrescue_instance', instance=instance)713    def soft_delete_instance(self, ctxt, instance, reservations=None):714        version = '3.0'715        cctxt = self.client.prepare(server=_compute_host(None, instance),716                version=version)717        cctxt.cast(ctxt, 'soft_delete_instance',718                   instance=instance, reservations=reservations)719    def restore_instance(self, ctxt, instance):720        version = '3.20'721        cctxt = self.client.prepare(server=_compute_host(None, instance),722                version=version)723        cctxt.cast(ctxt, 'restore_instance', instance=instance)724    def shelve_instance(self, ctxt, instance, image_id=None):725        version = '3.0'726        cctxt = self.client.prepare(server=_compute_host(None, instance),727                version=version)728        cctxt.cast(ctxt, 'shelve_instance',729                   instance=instance, image_id=image_id)730    def shelve_offload_instance(self, ctxt, instance):731        version = '3.0'732        cctxt = self.client.prepare(server=_compute_host(None, instance),733                version=version)734        cctxt.cast(ctxt, 'shelve_offload_instance', instance=instance)735    def unshelve_instance(self, ctxt, instance, host, image=None,736                          filter_properties=None, node=None):737        version = '3.15'738        msg_kwargs = {739            'instance': instance,740            'image': image,741            'filter_properties': filter_properties,742            'node': node,743        }744        cctxt = self.client.prepare(server=host, version=version)745        cctxt.cast(ctxt, 'unshelve_instance', **msg_kwargs)746    def volume_snapshot_create(self, ctxt, instance, volume_id,747                               create_info):748        version = '3.6'749        cctxt = self.client.prepare(server=_compute_host(None, instance),750                version=version)751        cctxt.cast(ctxt, 'volume_snapshot_create', instance=instance,752                   volume_id=volume_id, create_info=create_info)753    def volume_snapshot_delete(self, ctxt, instance, volume_id, snapshot_id,754                               delete_info):755        version = '3.6'756        cctxt = self.client.prepare(server=_compute_host(None, instance),757                version=version)758        cctxt.cast(ctxt, 'volume_snapshot_delete', instance=instance,759                   volume_id=volume_id, snapshot_id=snapshot_id,760                   delete_info=delete_info)761    def external_instance_event(self, ctxt, instances, events):762        cctxt = self.client.prepare(763            server=_compute_host(None, instances[0]),764            version='3.23')765        cctxt.cast(ctxt, 'external_instance_event', instances=instances,766                   events=events)767    def build_and_run_instance(self, ctxt, instance, host, image, request_spec,768            filter_properties, admin_password=None, injected_files=None,769            requested_networks=None, security_groups=None,770            block_device_mapping=None, node=None, limits=None):771        version = '3.33'772        if not self.client.can_send_version(version):773            version = '3.23'774            if requested_networks is not None:775                requested_networks = requested_networks.as_tuples()776        cctxt = self.client.prepare(server=host, version=version)777        cctxt.cast(ctxt, 'build_and_run_instance', instance=instance,778                image=image, request_spec=request_spec,779                filter_properties=filter_properties,780                admin_password=admin_password,781                injected_files=injected_files,...navtreeindex2.js
Source:navtreeindex2.js  
1var NAVTREEINDEX2 =2{3"structarm__biquad__cascade__df2T__instance__f64.html":[4,6],4"structarm__biquad__cascade__df2T__instance__f64.html#a0bde57b618e3f9059b23b0de64e12ce3":[4,6,2],5"structarm__biquad__cascade__df2T__instance__f64.html#ad55380ff835b533aa5168f836db8a4de":[4,6,0],6"structarm__biquad__cascade__df2T__instance__f64.html#ae2f0180f9038c0393e1d6921bb3b878b":[4,6,1],7"structarm__biquad__cascade__stereo__df2T__instance__f32.html":[4,7],8"structarm__biquad__cascade__stereo__df2T__instance__f32.html#a2cb00048bb1fe957a03c1ff56dfaf8f0":[4,7,2],9"structarm__biquad__cascade__stereo__df2T__instance__f32.html#a5655328252da5c2c2425ceed253bc4f1":[4,7,0],10"structarm__biquad__cascade__stereo__df2T__instance__f32.html#a68a22132ff134715ed2cc8d0f8225bc0":[4,7,1],11"structarm__biquad__casd__df1__inst__f32.html":[4,8],12"structarm__biquad__casd__df1__inst__f32.html#a4e873ff8bb6273858481cfd4c7f8f6d5":[4,8,1],13"structarm__biquad__casd__df1__inst__f32.html#a8c245d79e0d8cfabc82409d4b54fb682":[4,8,2],14"structarm__biquad__casd__df1__inst__f32.html#af69820c37a87252c46453e4cfe120585":[4,8,0],15"structarm__biquad__casd__df1__inst__q15.html":[4,9],16"structarm__biquad__casd__df1__inst__q15.html#a5481104ef2f8f81360b80b47d69ae932":[4,9,3],17"structarm__biquad__casd__df1__inst__q15.html#a9219b50b6ca227c92da85f2151ea362e":[4,9,1],18"structarm__biquad__casd__df1__inst__q15.html#ad6d95e70abcf4ff1300181415ad92153":[4,9,0],19"structarm__biquad__casd__df1__inst__q15.html#ada7e9d6269e6ed4eacf8f68729e9832d":[4,9,2],20"structarm__biquad__casd__df1__inst__q31.html":[4,10],21"structarm__biquad__casd__df1__inst__q31.html#a2c2b579f1df1d8273a5d9d945c27e1b2":[4,10,0],22"structarm__biquad__casd__df1__inst__q31.html#a5dcf4727f58eb4e8e8b392508d8657bb":[4,10,3],23"structarm__biquad__casd__df1__inst__q31.html#a636c7fbe09ec4bef0bc0a4b4e2151cbe":[4,10,2],24"structarm__biquad__casd__df1__inst__q31.html#aee29599a6db153ff0e9a5de18b6af73d":[4,10,1],25"structarm__cfft__instance__f32.html":[4,11],26"structarm__cfft__instance__f32.html#a21ceaf59a1bb8440af57c28d2dd9bbab":[4,11,2],27"structarm__cfft__instance__f32.html#a3ba329ed153d182746376208e773d648":[4,11,0],28"structarm__cfft__instance__f32.html#a59cc6f753f1498716e1444ac054c06de":[4,11,3],29"structarm__cfft__instance__f32.html#acd8f9e9540e3dd348212726e5d6aaa95":[4,11,1],30"structarm__cfft__instance__q15.html":[4,12],31"structarm__cfft__instance__q15.html#a5f9e1d3a8c127ee323b5e6929aeb90df":[4,12,1],32"structarm__cfft__instance__q15.html#a738907cf34bdbbaf724414ac2decbc3c":[4,12,0],33"structarm__cfft__instance__q15.html#ac9160b80243b99a0b6e2f75ddb5cf0ae":[4,12,2],34"structarm__cfft__instance__q15.html#afdaf12ce4687cec021c5ae73d0987a3f":[4,12,3],35"structarm__cfft__instance__q31.html":[4,13],36"structarm__cfft__instance__q31.html#a2250fa6b8fe73292c5418c50c0549f87":[4,13,0],37"structarm__cfft__instance__q31.html#a4406f23e8fd0bff8d555225612e2a2a8":[4,13,1],38"structarm__cfft__instance__q31.html#a8a464461649f023325ced1e10470f5d0":[4,13,2],39"structarm__cfft__instance__q31.html#af751114feb91de3ace8600e91bdd0872":[4,13,3],40"structarm__cfft__radix2__instance__f32.html":[4,14],41"structarm__cfft__radix2__instance__f32.html#a18f2a5bea3038dfe36b8ee0b2e655403":[4,14,5],42"structarm__cfft__radix2__instance__f32.html#a1d3d289d47443e597d88a40effd14b8f":[4,14,4],43"structarm__cfft__radix2__instance__f32.html#a1d7f92796c5ffd02a7373f48313c26b5":[4,14,6],44"structarm__cfft__radix2__instance__f32.html#a2f915a1c29635c1623086aaaa726be8f":[4,14,2],45"structarm__cfft__radix2__instance__f32.html#a411f75b6ed01690293f4f5988030ea42":[4,14,7],46"structarm__cfft__radix2__instance__f32.html#a8dbe98d2c924e35e0a3fed2fe948176f":[4,14,3],47"structarm__cfft__radix2__instance__f32.html#ac1688dafa5177f6b1505abbfd0cf8b21":[4,14,1],48"structarm__cfft__radix2__instance__f32.html#af713b4ac5256a19bc965c89fe3005fa3":[4,14,0],49"structarm__cfft__radix2__instance__q15.html":[4,15],50"structarm__cfft__radix2__instance__q15.html#a1bfc91c423e8a1fa6b71f9091df54f39":[4,15,4],51"structarm__cfft__radix2__instance__q15.html#a68eaf57e58bbc42f7e1dfa8de8145647":[4,15,5],52"structarm__cfft__radix2__instance__q15.html#a6f2ab87fb4c568656e1f92f687b5c850":[4,15,6],53"structarm__cfft__radix2__instance__q15.html#a8722720c542cabd41df83fe88ef4f4cb":[4,15,1],54"structarm__cfft__radix2__instance__q15.html#a874085647351dcf3f0de39d2b1d49744":[4,15,2],55"structarm__cfft__radix2__instance__q15.html#ab5c073286bdd2f6e2bf783ced36bf1de":[4,15,3],56"structarm__cfft__radix2__instance__q15.html#af8300c1f60caa21e6b44b9240ab5af19":[4,15,0],57"structarm__cfft__radix2__instance__q31.html":[4,16],58"structarm__cfft__radix2__instance__q31.html#a2607378ce64be16698bb8a3b1af8d3c8":[4,16,3],59"structarm__cfft__radix2__instance__q31.html#a6239b8d268285334e88c008c07d68616":[4,16,0],60"structarm__cfft__radix2__instance__q31.html#a6a965fcf4ba88bd2661a263a5f18a6b1":[4,16,5],61"structarm__cfft__radix2__instance__q31.html#a960199f1373a192366878ef279eab00f":[4,16,2],62"structarm__cfft__radix2__instance__q31.html#a9d17a87263953fe3559a007512c9f3a4":[4,16,1],63"structarm__cfft__radix2__instance__q31.html#adf510de23a78c9119e0442f7f35efcd1":[4,16,4],64"structarm__cfft__radix2__instance__q31.html#ae63ca9193322cd477970c1d2086407d1":[4,16,6],65"structarm__cfft__radix4__instance__f32.html":[4,17],66"structarm__cfft__radix4__instance__f32.html#a25d1da64dd6487c291f04d226f9acc66":[4,17,3],67"structarm__cfft__radix4__instance__f32.html#a7e6a6d290ce158ce9a15a45e364b021a":[4,17,2],68"structarm__cfft__radix4__instance__f32.html#ab6e84ac830b6d413768dcafe271514a1":[4,17,5],69"structarm__cfft__radix4__instance__f32.html#ab9eed39e40b8d7c16381fbccf84467cd":[4,17,4],70"structarm__cfft__radix4__instance__f32.html#abe31ea2157dfa233e389cdfd3b9993ee":[4,17,7],71"structarm__cfft__radix4__instance__f32.html#ac10927a1620195a88649ce63dab66120":[4,17,0],72"structarm__cfft__radix4__instance__f32.html#ac1455c9894e7fc53c41f3806b13bd274":[4,17,6],73"structarm__cfft__radix4__instance__f32.html#acc8cb18a8b901b8321ab9d86491e41a3":[4,17,1],74"structarm__cfft__radix4__instance__q15.html":[4,18],75"structarm__cfft__radix4__instance__q15.html#a101e3f7b0bd6b5b14cd5214f23df4133":[4,18,0],76"structarm__cfft__radix4__instance__q15.html#a2ecff6ea735cb4d22e922d0fd5736655":[4,18,3],77"structarm__cfft__radix4__instance__q15.html#a5fc543e7d84ca8cb7cf6648970f21ca6":[4,18,2],78"structarm__cfft__radix4__instance__q15.html#a69a91f93a3cae666b56c42d47beab1b4":[4,18,5],79"structarm__cfft__radix4__instance__q15.html#a6b010e5f02d1130c621e3d2e26b95df1":[4,18,1],80"structarm__cfft__radix4__instance__q15.html#a821544995ab3a0fd8f33bef3110cce0e":[4,18,4],81"structarm__cfft__radix4__instance__q15.html#af32fdc78bcc27ca385f9b76a0a1f71c3":[4,18,6],82"structarm__cfft__radix4__instance__q31.html":[4,19],83"structarm__cfft__radix4__instance__q31.html#a499e97268c131e20faea4b8565d4204c":[4,19,5],84"structarm__cfft__radix4__instance__q31.html#a5a7c4f4c7b3fb655cbb2bc11ef160a2a":[4,19,0],85"structarm__cfft__radix4__instance__q31.html#a64b58f7643b0e27c7f2d66ec0ef2e3dc":[4,19,4],86"structarm__cfft__radix4__instance__q31.html#a8cf8187b8232815cf17ee82bf572ecf9":[4,19,6],87"structarm__cfft__radix4__instance__q31.html#a94d2fead4efa4d5eaae142bbe30b0e15":[4,19,1],88"structarm__cfft__radix4__instance__q31.html#ab413d2a5d3f45fa187d93813bf3bf81b":[4,19,2],89"structarm__cfft__radix4__instance__q31.html#adc0a62ba669ad2282ecbe43d5d96abab":[4,19,3],90"structarm__dct4__instance__f32.html":[4,20],91"structarm__dct4__instance__f32.html#a018f7860b6e070af533fb7d76c7cdc32":[4,20,3],92"structarm__dct4__instance__f32.html#a01fe45dbe46c782245832f2169622c29":[4,20,6],93"structarm__dct4__instance__f32.html#a262b29a51c371b46efc89120e31ccf37":[4,20,0],94"structarm__dct4__instance__f32.html#a61ce8c967b2e998a9c0041cca73cdef8":[4,20,2],95"structarm__dct4__instance__f32.html#a7762296d8871c58f2ef0b6ce327b8f4e":[4,20,4],96"structarm__dct4__instance__f32.html#a978f37fc19add31af243ab5c63ae502f":[4,20,5],97"structarm__dct4__instance__f32.html#adb1ef2739ddbe62e5cdadc47455a4147":[4,20,1],98"structarm__dct4__instance__q15.html":[4,21],99"structarm__dct4__instance__q15.html#a11cf95c1cd9dd2dd5e4b81b8f88dc208":[4,21,5],100"structarm__dct4__instance__q15.html#a197098140d68e89a08f7a249003a0b86":[4,21,2],101"structarm__dct4__instance__q15.html#a53d24009bb9b2e93d0aa07db7f1a6c25":[4,21,0],102"structarm__dct4__instance__q15.html#a7284932ee8c36107c33815eb62eadffc":[4,21,3],103"structarm__dct4__instance__q15.html#aa1a1d7e957ca6af3f341721f5fa3b95b":[4,21,6],104"structarm__dct4__instance__q15.html#aad2097a5525c1a5b3f5cbd7235c06499":[4,21,4],105"structarm__dct4__instance__q15.html#af43dcbbc2fc661ffbc525afe3dcbd7da":[4,21,1],106"structarm__dct4__instance__q31.html":[4,22],107"structarm__dct4__instance__q31.html#a107b210eca05f0bd16246b28fd32c4e7":[4,22,6],108"structarm__dct4__instance__q31.html#a32d3268ba4629908dba056599f0a904d":[4,22,1],109"structarm__dct4__instance__q31.html#a34241ee5930de99d4f22a040d32026e3":[4,22,4],110"structarm__dct4__instance__q31.html#a46a9f136457350676e2bfd3768ff9d6d":[4,22,0],111"structarm__dct4__instance__q31.html#ac80ff7b28fca36aeef74dea12e8312dd":[4,22,2],112"structarm__dct4__instance__q31.html#ac96579cfb28d08bb11dd2fe4c6303833":[4,22,3],113"structarm__dct4__instance__q31.html#af1487dab5e7963b85dc0fdc6bf492542":[4,22,5],114"structarm__fir__decimate__instance__f32.html":[4,23],115"structarm__fir__decimate__instance__f32.html#a1aef1d796b60749d87ff36e282284628":[4,23,2],116"structarm__fir__decimate__instance__f32.html#a2aa2986129db8affef03ede88dd45a03":[4,23,1],117"structarm__fir__decimate__instance__f32.html#a5bddf29aaaf2011d2e3bcec59a83f633":[4,23,3],118"structarm__fir__decimate__instance__f32.html#a76a8b2161731638eb3d67f277919f95d":[4,23,0],119"structarm__fir__decimate__instance__q15.html":[4,24],120"structarm__fir__decimate__instance__q15.html#a3f7b5184bb28853ef401b001df121047":[4,24,3],121"structarm__fir__decimate__instance__q15.html#a44ba13cf8aa4425c34adc82dc468ad54":[4,24,2],122"structarm__fir__decimate__instance__q15.html#aad9320284218b3aa378527ea518cf093":[4,24,0],123"structarm__fir__decimate__instance__q15.html#ac1e9844488ec717da334fbd4c4f41990":[4,24,1],124"structarm__fir__decimate__instance__q31.html":[4,25],125"structarm__fir__decimate__instance__q31.html#a0ef0ef9e265f7ab873cfc6daa7593fdb":[4,25,3],126"structarm__fir__decimate__instance__q31.html#a37915d42b0dc5e3057ebe83110798482":[4,25,1],127"structarm__fir__decimate__instance__q31.html#a530ab6a5d1a39367b281206cd7201dae":[4,25,2],128"structarm__fir__decimate__instance__q31.html#ad3d6936c36303b30dd38f1eddf248ae5":[4,25,0],129"structarm__fir__instance__f32.html":[4,26],130"structarm__fir__instance__f32.html#a20cf98c92b5323799b7881c9ff4d2f7c":[4,26,0],131"structarm__fir__instance__f32.html#a7afcf4022e8560db9b8fd28b0d090a15":[4,26,2],132"structarm__fir__instance__f32.html#aa590e6c845fcb19e027d77307c8ef016":[4,26,1],133"structarm__fir__instance__q15.html":[4,27],134"structarm__fir__instance__q15.html#a0e46f93cf51bfb18b1be808be9c5bfc9":[4,27,0],135"structarm__fir__instance__q15.html#aa8d25f44f45b6a6c4cf38c31569b8a01":[4,27,2],136"structarm__fir__instance__q15.html#ac7f6e5f1b0be8d07c4c35b4be07157b0":[4,27,1],137"structarm__fir__instance__q31.html":[4,28],138"structarm__fir__instance__q31.html#a409f39c93b744784648bdc365541444d":[4,28,2],139"structarm__fir__instance__q31.html#a918fadd775b7a0482b21bf34dae2f094":[4,28,0],140"structarm__fir__instance__q31.html#ae8bb1e9787be4578a23671bf53d3b7cb":[4,28,1],141"structarm__fir__instance__q7.html":[4,29],142"structarm__fir__instance__q7.html#a6947bd695db2d5f8e198e68ca0c72026":[4,29,1],143"structarm__fir__instance__q7.html#a9b50840e2c5ef5b17e1a584fb4cf0d06":[4,29,0],144"structarm__fir__instance__q7.html#aaddea3b9c7e16ddfd9428b7bf9f9c200":[4,29,2],145"structarm__fir__interpolate__instance__f32.html":[4,30],146"structarm__fir__interpolate__instance__f32.html#a389e669e13ec56292a70db8e92194b12":[4,30,2],147"structarm__fir__interpolate__instance__f32.html#a42a8ba1bda85fa86d7b6c84d3da4c75b":[4,30,3],148"structarm__fir__interpolate__instance__f32.html#a9e1258a3dbe84fde28d5ee67311337f4":[4,30,1],149"structarm__fir__interpolate__instance__f32.html#ae6f94dcc0ccd8aa4bc699b20985d9df5":[4,30,0],150"structarm__fir__interpolate__instance__q15.html":[4,31],151"structarm__fir__interpolate__instance__q15.html#a239cee528ee8f79188fc34a94c86673b":[4,31,1],152"structarm__fir__interpolate__instance__q15.html#a26b864363fa47954248f2590e3a82a3c":[4,31,3],153"structarm__fir__interpolate__instance__q15.html#a5431bdc079e72a973b51d359f7f13603":[4,31,0],154"structarm__fir__interpolate__instance__q15.html#ad5178a02a697a77e0d0e60705d9f0a19":[4,31,2],155"structarm__fir__interpolate__instance__q31.html":[4,32],156"structarm__fir__interpolate__instance__q31.html#a5cdf0a631cb74e0e9588c388abe5235c":[4,32,0],157"structarm__fir__interpolate__instance__q31.html#a5d243796584afc7cd6c557f00b7acca5":[4,32,2],158"structarm__fir__interpolate__instance__q31.html#a89c871637896a08168e87ec13691f020":[4,32,1],159"structarm__fir__interpolate__instance__q31.html#addde04514b6e6ac72be3d609f0398b1a":[4,32,3],160"structarm__fir__lattice__instance__f32.html":[4,33],161"structarm__fir__lattice__instance__f32.html#ad369bd9997a250f195254df37408a38f":[4,33,0],162"structarm__fir__lattice__instance__f32.html#ae348884a1ba9b83fadccd5da640cbcaf":[4,33,2],163"structarm__fir__lattice__instance__f32.html#aec9f6580180489d073bb5be700d72bbc":[4,33,1],164"structarm__fir__lattice__instance__q15.html":[4,34],165"structarm__fir__lattice__instance__q15.html#a0248d4f9908c38f9c7865ea5261f6856":[4,34,1],166"structarm__fir__lattice__instance__q15.html#a37b90dea2bc3ee7c9951a9fe74db0cbb":[4,34,2],167"structarm__fir__lattice__instance__q15.html#a38b179138d6a6c9cac4f8f79b6fd5357":[4,34,0],168"structarm__fir__lattice__instance__q31.html":[4,35],169"structarm__fir__lattice__instance__q31.html#a08fe9494ab7cd336b791e9657adadcf6":[4,35,2],170"structarm__fir__lattice__instance__q31.html#a9f3773bbb76bc5a8a5ee9d37786bf478":[4,35,0],171"structarm__fir__lattice__instance__q31.html#ac9e648f1e5bc7d5ee6d5f7d8d22b1e74":[4,35,1],172"structarm__fir__sparse__instance__f32.html":[4,36],173"structarm__fir__sparse__instance__f32.html#a4bc78b1761b6349e6842241e813d6446":[4,36,2],174"structarm__fir__sparse__instance__f32.html#a57585aeca9dc8686e08df2865375a86d":[4,36,5],175"structarm__fir__sparse__instance__f32.html#a5e19e7f234ac30a3db843352bf2a8515":[4,36,1],176"structarm__fir__sparse__instance__f32.html#a794af0916666d11cc564d6df08553555":[4,36,3],177"structarm__fir__sparse__instance__f32.html#aaa54ae67e5d10c6dd0d697945c638d31":[4,36,4],178"structarm__fir__sparse__instance__f32.html#af8b8c775f4084c36774f06c082b4c078":[4,36,0],179"structarm__fir__sparse__instance__q15.html":[4,37],180"structarm__fir__sparse__instance__q15.html#a0f66b126dd8b85f7467cfb01b7bc4d77":[4,37,1],181"structarm__fir__sparse__instance__q15.html#a4180a6d16a979b59b707a3e7b8cc274b":[4,37,2],182"structarm__fir__sparse__instance__q15.html#a89487f28cab52637426024005e478985":[4,37,5],183"structarm__fir__sparse__instance__q15.html#a98b92b0f5208110129b9a67b1db90408":[4,37,3],184"structarm__fir__sparse__instance__q15.html#ad14cc1070eecf7e1926d8f67a8273182":[4,37,0],185"structarm__fir__sparse__instance__q15.html#aeab2855176c6efdb231a73a3672837d5":[4,37,4],186"structarm__fir__sparse__instance__q31.html":[4,38],187"structarm__fir__sparse__instance__q31.html#a07b6c01e58ec6dde384719130d36b0dc":[4,38,1],188"structarm__fir__sparse__instance__q31.html#a557ed9d477e76e4ad2019344f19f568a":[4,38,5],189"structarm__fir__sparse__instance__q31.html#a830be89daa5a393b225048889aa045d1":[4,38,3],190"structarm__fir__sparse__instance__q31.html#ab87ae457adec8f727afefaa2599fc983":[4,38,4],191"structarm__fir__sparse__instance__q31.html#af714d56f8fec4f93ad557abce6994d45":[4,38,2],192"structarm__fir__sparse__instance__q31.html#afdd3a1dc72132c854dc379154b68b674":[4,38,0],193"structarm__fir__sparse__instance__q7.html":[4,39],194"structarm__fir__sparse__instance__q7.html#a18072cf3ef3666d588f0d49512f2b28f":[4,39,3],195"structarm__fir__sparse__instance__q7.html#a2d2e65473fe3a3f2b953b4e0b60824df":[4,39,5],196"structarm__fir__sparse__instance__q7.html#a54cdd27ca1c672b126c38763ce678b1c":[4,39,1],197"structarm__fir__sparse__instance__q7.html#a7f0989ef34fdb5d08ce5a5abf917218f":[4,39,2],198"structarm__fir__sparse__instance__q7.html#ac625393c84bc0342ffdf26fc4eba1ac1":[4,39,4],199"structarm__fir__sparse__instance__q7.html#af74dacc1d34c078283e50f2530eb91df":[4,39,0],200"structarm__iir__lattice__instance__f32.html":[4,40],201"structarm__iir__lattice__instance__f32.html#a30babe7815510219e6e3d28e6e4a5969":[4,40,2],202"structarm__iir__lattice__instance__f32.html#aa69fcdd3775e828d450ce1bbd978fa31":[4,40,1],203"structarm__iir__lattice__instance__f32.html#af8de449af5efe1f30be82f9ba35587ee":[4,40,0],204"structarm__iir__lattice__instance__f32.html#afc7c8f577e6f27d097fe55f57e707f72":[4,40,3],205"structarm__iir__lattice__instance__q15.html":[4,41],206"structarm__iir__lattice__instance__q15.html#a41c214a1ec38d4a82fae8899d715dd29":[4,41,1],207"structarm__iir__lattice__instance__q15.html#a4c4f57f45b223abbe2a9fb727bd2cad9":[4,41,3],208"structarm__iir__lattice__instance__q15.html#a96fbed313bef01070409fa182d26ba3f":[4,41,0],209"structarm__iir__lattice__instance__q15.html#afd0136ab917b529554d93f41a5e04618":[4,41,2],210"structarm__iir__lattice__instance__q31.html":[4,42],211"structarm__iir__lattice__instance__q31.html#a04507e2b982b1dfa97b7b55752dea6b9":[4,42,3],212"structarm__iir__lattice__instance__q31.html#a1d30aa16aac7722936ea9dee59211863":[4,42,1],213"structarm__iir__lattice__instance__q31.html#a941282745effd26a889fbfadf4b95e6a":[4,42,2],214"structarm__iir__lattice__instance__q31.html#a9df4570ed28c50fd9193ab654ff236ad":[4,42,0],215"structarm__linear__interp__instance__f32.html":[4,43],216"structarm__linear__interp__instance__f32.html#a08352dc6ea82fbc0827408e018535481":[4,43,2],217"structarm__linear__interp__instance__f32.html#a95f02a926b16d35359aca5b31e813b11":[4,43,0],218"structarm__linear__interp__instance__f32.html#aa8e2d686b5434a406d390b347b183511":[4,43,3],219"structarm__linear__interp__instance__f32.html#ab373001f6afad0850359c344a4d7eee4":[4,43,1],220"structarm__lms__instance__f32.html":[4,44],221"structarm__lms__instance__f32.html#a4795c6f7d3f17cec15c2fd09f66edd1a":[4,44,2],222"structarm__lms__instance__f32.html#aaf94285be2f99b5b9af40bea8dcb14b9":[4,44,3],223"structarm__lms__instance__f32.html#ae2af43d74c93dba16b876e10c97a5b99":[4,44,0],224"structarm__lms__instance__f32.html#af73880d9009982f5d14529869494ec3d":[4,44,1],225"structarm__lms__instance__q15.html":[4,45],226"structarm__lms__instance__q15.html#a0078e894f805af1b360369e619fb57b3":[4,45,1],227"structarm__lms__instance__q15.html#a42f95368b94898eb82608e1113d18cab":[4,45,2],228"structarm__lms__instance__q15.html#a9a575ff82c1e68cbb583083439260d08":[4,45,4],229"structarm__lms__instance__q15.html#aae46129d7cfd7f1c162cc502ed0a9d49":[4,45,0],230"structarm__lms__instance__q15.html#acca5fbaef4a52ae411de24c9a0b929cf":[4,45,3],231"structarm__lms__instance__q31.html":[4,46],232"structarm__lms__instance__q31.html#a206d47b49de6f357f933ebe61520753c":[4,46,4],233"structarm__lms__instance__q31.html#a4705a8f0011bb9166e09bf5bd51e595e":[4,46,3],234"structarm__lms__instance__q31.html#a4afe56e991a5416adfd462aa88bda500":[4,46,2],235"structarm__lms__instance__q31.html#ac0d84f7d054555931ef8a62511fbcb8a":[4,46,1],236"structarm__lms__instance__q31.html#acb6ca9996b3c5f740d5d6c8e9f4f1d46":[4,46,0],237"structarm__lms__norm__instance__f32.html":[4,47],238"structarm__lms__norm__instance__f32.html#a0bc03338687002ed5f2e4a363eb095ec":[4,47,4],239"structarm__lms__norm__instance__f32.html#a1ba688d90aba7de003ed4ad8e2e7ddda":[4,47,3],240"structarm__lms__norm__instance__f32.html#a6a4119e4f39447bbee31b066deafa16f":[4,47,0],241"structarm__lms__norm__instance__f32.html#a84401d3cfc6c40f69c08223cf341b886":[4,47,1],242"structarm__lms__norm__instance__f32.html#ac95f8ca3d816524c2070643852fac5e8":[4,47,2],243"structarm__lms__norm__instance__f32.html#aec958fe89b164a30f38bcca9f5d96218":[4,47,5],244"structarm__lms__norm__instance__q15.html":[4,48],245"structarm__lms__norm__instance__q15.html#a07d272351a3291ed09e3f42447609df0":[4,48,6],246"structarm__lms__norm__instance__q15.html#a1c81ded399919d8181026bc1c8602e7b":[4,48,0],247"structarm__lms__norm__instance__q15.html#a3fc1d6f97d2c6d5324871de6895cb7e9":[4,48,7],248"structarm__lms__norm__instance__q15.html#a7ce00f21d11cfda6d963240641deea8c":[4,48,1],249"structarm__lms__norm__instance__q15.html#a9ee7a45f4f315d7996a969e25fdc7146":[4,48,2],250"structarm__lms__norm__instance__q15.html#aa0d435fbcf7dedb7179d4467e9b79e9f":[4,48,4],251"structarm__lms__norm__instance__q15.html#aa4de490b3bdbd03561b76ee07901c8e3":[4,48,5],252"structarm__lms__norm__instance__q15.html#ae7bca648c75a2ffa02d87852bb78bc8a":[4,48,3]...main.js
Source:main.js  
1AUI.add(2	'liferay-plugin-mail',3	function(A) {4		Liferay.Mail = {5			init: function(params) {6				var instance = this;7				instance.namespace = params.namespace;8				instance.accountId = params.initialAccountId;9				instance.folderId = params.initialFolderId;10				instance.accountsContainer = A.one('#accountsContainer');11				instance.composeContainer = A.one('#composeContainer');12				instance.controlContainer = A.one('#controlContainer');13				instance.contentContainer = A.one('#contentContainer');14				instance.foldersContainer = A.one('#foldersContainer');15				instance.mailContainer = A.one('#mailContainer');16				instance.manageFoldersContainer = A.one('#manageFoldersContainer');17				instance.messageContainer = A.one('#messageContainer');18				instance.messagesContainer = A.one('#messagesContainer');19				instance._assignEvents();20				if (instance.accountId == 0) {21					return;22				}23				instance.loadAccount(instance.accountId, instance.folderId);24				Liferay.on('closePortlet', instance._pollStopMessages, instance);25			},26			addAccount: function() {27				var instance = this;28				instance.dialog = Liferay.Util.Window.getWindow(29					{30						dialog: {31							centered: true,32							cssClass: 'mail-dialog',33							destroyOnClose: true,34							modal: true,35							width: 60036						},37						title: Liferay.Language.get('add-account')38					}39				).plug(40					A.Plugin.IO,41					{42						uri: themeDisplay.getLayoutURL() + '/-/mail/add_account'43					}44				).render();45			},46			checkMessages: function(folderId) {47				var instance = this;48				if (instance.accountId <= 0) {49					return;50				}51				A.io.request(52					themeDisplay.getLayoutURL() + '/-/mail/check_messages',53					{54						data: Liferay.Util.ns(55							instance.namespace,56							{57								accountId: instance.accountId,58								folderId: folderId59							}60						),61						dataType: 'JSON',62						method: 'POST',63						on: {64							success: function(event, id, obj) {65								var responseData = this.get('responseData');66								if (responseData.status != 'success' || responseData.value == 'false') {67									return;68								}69								instance.loadFolders(instance.accountId);70								if (instance.folderId == folderId) {71									instance.loadMessages(folderId, instance.pageNumber, instance.orderByField, instance.orderByType, instance.keywords, true);72								}73							}74						}75					}76				);77			},78			deleteMessages: function(messageIds) {79				var instance = this;80				instance.setStatus('info', Liferay.Language.get('deleting-messages'));81				A.io.request(82					themeDisplay.getLayoutURL() + '/-/mail/delete_messages',83					{84						data: Liferay.Util.ns(85							instance.namespace,86							{87								messageIds: messageIds88							}89						),90						dataType: 'JSON',91						method: 'POST',92						on: {93							failure: function(event, id, obj) {94								instance.setStatus('error', Liferay.Language.get('unable-to-connect-with-mail-server'));95							},96							success: function(event, id, obj) {97								var responseData = this.get('responseData');98								instance.setStatus(responseData.status, responseData.message);99								if (responseData.status == 'success') {100									instance.loadMessages(instance.folderId, instance.pageNumber, instance.orderByField, instance.orderByType, instance.keywords);101								}102							}103						}104					}105				);106			},107			editAccount: function(accountId) {108				var instance = this;109				instance.dialog = Liferay.Util.Window.getWindow(110					{111						dialog: {112							centered: true,113							cssClass: 'mail-dialog',114							destroyOnClose: true,115							modal: true,116							width: 600117						},118						title: Liferay.Language.get('edit-account')119					}120				).plug(121					A.Plugin.IO,122					{123						data: Liferay.Util.ns(124							instance.namespace,125							{126								accountId: accountId127							}128						),129						uri: themeDisplay.getLayoutURL() + '/-/mail/edit_account'130					}131				).render();132			},133			flagMessages: function(flag, value, messageIds) {134				var instance = this;135				instance.setStatus('info', Liferay.Language.get('flagging-messages'));136				A.io.request(137					themeDisplay.getLayoutURL() + '/-/mail/flag_messages',138					{139						data: Liferay.Util.ns(140							instance.namespace,141							{142								flag: flag,143								messageIds: messageIds,144								value: value145							}146						),147						dataType: 'JSON',148						method: 'POST',149						on: {150							failure: function(event, id, obj) {151								instance.setStatus('error', Liferay.Language.get('unable-to-connect-with-mail-server'));152							},153							success: function(event, id, obj) {154								var responseData = this.get('responseData');155								instance.setStatus(responseData.status, responseData.message);156								instance.loadMessages(instance.folderId, instance.pageNumber, instance.orderByField, instance.orderByType, instance.keywords);157							}158						}159					}160				);161			},162			loadAccount: function(accountId, inboxFolderId) {163				var instance = this;164				instance._displayContainer(instance.messagesContainer);165				A.io.request(166					themeDisplay.getLayoutURL() + '/-/mail/password_saved',167					{168						data: Liferay.Util.ns(169							instance.namespace,170							{171								accountId: accountId,172								inboxFolderId: inboxFolderId173							}174						),175						method: 'POST',176						on: {177							failure: function(event, id, obj) {178								instance.setStatus('error', Liferay.Language.get('unable-to-connect-with-mail-server'));179							},180							success: function(event, id, obj) {181								var responseData = this.get('responseData');182								if (A.DataType.Boolean.parse(responseData)) {183									instance.accountId = accountId;184									instance.inboxFolderId = inboxFolderId;185									instance.loadFolders(accountId);186									instance.loadMessages(inboxFolderId, 1, 'sentDate', 'desc', '');187								}188								else {189									instance.passwordPrompt(accountId, inboxFolderId);190								}191							}192						}193					}194				);195				instance._hideWindow();196			},197			loadAccounts: function(accountId) {198				var instance = this;199				instance.accountsContainer.io.set(200					'data',201					Liferay.Util.ns(202						instance.namespace,203						{204							accountId: accountId205						}206					)207				);208				instance.accountsContainer.io.start();209			},210			loadCompose: function(accountId, messageId, messageType, replyMessageId) {211				var instance = this;212				instance._displayContainer(instance.composeContainer);213				instance.composeContainer.io.set(214					'data',215					Liferay.Util.ns(216						instance.namespace,217						{218							accountId: accountId,219							messageId: messageId,220							messageType: messageType,221							replyMessageId: replyMessageId222						}223					)224				);225				instance.composeContainer.io.start();226			},227			loadFolders: function(accountId) {228				var instance = this;229				if (accountId > 0) {230					instance.controlContainer.show();231					instance.foldersContainer.io.set(232						'data',233						Liferay.Util.ns(234							instance.namespace,235							{236								accountId: accountId237							}238						)239					);240					instance.foldersContainer.io.start();241				}242				instance._hideWindow();243			},244			loadManageFolders: function(accountId) {245				var instance = this;246				instance._displayContainer(instance.manageFoldersContainer);247				instance.manageFoldersContainer.io.set(248					'data',249					Liferay.Util.ns(250						instance.namespace,251						{252							accountId: accountId253						}254					)255				);256				instance.manageFoldersContainer.io.start();257			},258			loadMessage: function(folderId, messageNumber, orderByField, orderByType, keywords) {259				var instance = this;260				instance.folderId = folderId;261				instance.orderByField = orderByField;262				instance.orderByType = orderByType;263				instance.keywords = keywords;264				instance._displayContainer(instance.messageContainer);265				instance.messageContainer.io.set(266					'data',267					Liferay.Util.ns(268						instance.namespace,269						{270							folderId: folderId,271							keywords: keywords,272							messageNumber: messageNumber,273							orderByField: orderByField,274							orderByType: orderByType275						}276					)277				);278				instance.messageContainer.io.start();279			},280			loadMessages: function(folderId, pageNumber, orderByField, orderByType, keywords, autoLoad) {281				var instance = this;282				instance.folderId = folderId;283				instance.pageNumber = pageNumber;284				instance.orderByField = orderByField;285				instance.orderByType = orderByType;286				instance.keywords = keywords;287				if (autoLoad) {288					instance.messagesContainer.io.set('showLoading', false);289				}290				else {291					instance._displayContainer(instance.messagesContainer);292					if (pageNumber == 1) {293						instance.checkMessages(folderId);294					}295				}296				instance.messagesContainer.io.set(297					'data',298					Liferay.Util.ns(299						instance.namespace,300						{301							folderId: folderId,302							keywords: keywords,303							orderByField: orderByField,304							orderByType: orderByType,305							pageNumber: pageNumber306						}307					)308				);309				instance.messagesContainer.io.start();310				instance.messagesContainer.io.set('showLoading', true);311			},312			moveMessages: function(folderId, messageIds) {313				var instance = this;314				instance.setStatus('info', Liferay.Language.get('moving-messages'));315				A.io.request(316					themeDisplay.getLayoutURL() + '/-/mail/move_messages',317					{318						data: Liferay.Util.ns(319							instance.namespace,320							{321								folderId: folderId,322								messageIds: messageIds323							}324						),325						dataType: 'JSON',326						method: 'POST',327						on: {328							failure: function(event, id, obj) {329								instance.setStatus('error', Liferay.Language.get('unable-to-connect-with-mail-server'));330							},331							success: function(event, id, obj) {332								var responseData = this.get('responseData');333								instance.setStatus(responseData.status, responseData.message);334								instance.loadFolders(instance.accountId);335								instance.loadMessages(instance.folderId, instance.pageNumber, instance.orderByField, instance.orderByType, instance.keywords);336							}337						}338					}339				);340			},341			passwordPrompt: function(accountId, inboxFolderId) {342				var instance = this;343				instance.dialog = Liferay.Util.Window.getWindow(344					{345						dialog: {346							centered: true,347							cssClass: 'mail-dialog',348							destroyOnClose: true,349							modal: true,350							width: 600351						},352						title: Liferay.Language.get('password')353					}354				).plug(355					A.Plugin.IO,356					{357						data: Liferay.Util.ns(358							instance.namespace,359							{360								accountId: accountId,361								inboxFolderId: inboxFolderId362							}363						),364						uri: themeDisplay.getLayoutURL() + '/-/mail/password_prompt'365					}366				).render();367			},368			reset: function() {369				var instance = this;370				instance.accountId = null;371				instance.folderId = null;372				instance.inboxFolderId = null;373				instance.keywords = '';374				instance.orderByField = 'sentDate';375				instance.orderByType = 'desc';376				instance.pageNumber = 1;377				instance.composeContainer.html('');378				instance.foldersContainer.html('');379				instance.manageFoldersContainer.html('');380				instance.messageContainer.html('');381				instance.messagesContainer.html('');382				instance.controlContainer.hide();383				instance.loadAccounts();384				instance._pollStopMessages();385				instance._hideWindow();386			},387			setStatus: function(type, message, indefinite) {388				var instance = this;389				var statusContainers = A.all('.mail-status').html('<table style="margin: 0 auto;"><tr><td> </td><td><span class="alert message alert-' + type + '">' + message + '</span></td><td> </td></tr></table>');390				var status = statusContainers.all('table');391				if (!indefinite) {392					setTimeout(393						function() {394							status.remove();395						},396						5000397					);398				}399			},400			_assignEvents: function() {401				var instance = this;402				instance.accountsContainer.plug(403					A.Plugin.IO,404					{405						autoLoad: true,406						data: Liferay.Util.ns(407							instance.namespace,408							{409								accountId: instance.accountId410							}411						),412						method: 'POST',413						showLoading: false,414						uri: themeDisplay.getLayoutURL() + '/-/mail/view_accounts'415					}416				);417				instance.composeContainer.plug(418					A.Plugin.IO,419					{420						autoLoad: false,421						method: 'POST',422						on: {423							success: function(event) {424								try {425									window[instance.namespace + 'editor'] = null;426									delete window[instance.namespace + 'editor'];427								}428								catch (e) {429								}430							}431						},432						uri: themeDisplay.getLayoutURL() + '/-/mail/compose'433					}434				);435				instance.foldersContainer.plug(436					A.Plugin.IO,437					{438						autoLoad: false,439						method: 'POST',440						showLoading: false,441						uri: themeDisplay.getLayoutURL() + '/-/mail/view_folders'442					}443				);444				instance.messageContainer.plug(445					A.Plugin.IO,446					{447						after: {448							success: function() {449								instance.loadFolders(instance.accountId);450							}451						},452						autoLoad: false,453						method: 'POST',454						uri: themeDisplay.getLayoutURL() + '/-/mail/view_message'455					}456				);457				instance.messagesContainer.plug(458					A.Plugin.IO,459					{460						after: {461							success: function() {462								instance.messagesContainer.all('.flag-messages').on(463									'click',464									function(event) {465										var messageIds = instance._getSelectedMessageIds();466										var currentTarget = event.currentTarget;467										var flagToggle = currentTarget.getData('flagToggle');468										var flagType = currentTarget.getData('flagType');469										instance.flagMessages(flagType, flagToggle, messageIds);470									}471								);472								instance.messagesContainer.all('.move-messages').on(473									'click',474									function(event) {475										var folderId = event.currentTarget.text().trim();476										var messageIds = instance._getSelectedMessageIds();477										instance.moveMessages(folderId, messageIds);478									}479								);480							}481						},482						autoLoad: false,483						method: 'POST',484						uri: themeDisplay.getLayoutURL() + '/-/mail/view_messages'485					}486				);487				instance.accountsContainer.delegate(488					'click',489					function(event) {490						var link = event.currentTarget;491						var accountId = link.getData('accountId');492						var inboxFolderId = link.getData('inboxFolderId');493						instance.loadAccounts(accountId);494						instance.loadAccount(accountId, inboxFolderId);495					},496					'.folders-link'497				);498				instance.composeContainer.delegate(499					'click',500					function(event) {501						var messageId = event.currentTarget.getData('messageId');502						instance.deleteMessages([messageId]);503					},504					'.discard-draft'505				);506				instance.contentContainer.delegate(507					'click',508					function(event) {509						var link = event.currentTarget;510						var li = link.ancestor('li');511						if (!li || !li.hasClass('disabled')) {512							var folderId = link.getData('folderId');513							var keywords = link.getData('keywords');514							var messageNumber = link.getData('messageNumber');515							var orderByField = link.getData('orderByField');516							var orderByType = link.getData('orderByType');517							instance.loadMessage(folderId, messageNumber, orderByField, orderByType, keywords);518						}519					},520					'.message-link'521				);522				instance.contentContainer.delegate(523					'click',524					function(event) {525						var link = event.currentTarget;526						var messageId = link.getData('messageId');527						instance.loadCompose(instance.accountId, messageId, 'edit', 0);528					},529					'.draft-link'530				);531				instance.foldersContainer.delegate(532					'click',533					function(event) {534						instance.editAccount(instance.accountId);535					},536					'.edit-account'537				);538				instance.foldersContainer.delegate(539					'click',540					function(event) {541						instance.loadManageFolders(instance.accountId);542					},543					'.manage-folders'544				);545				instance.mailContainer.delegate(546					'click',547					function(event) {548						var link = event.currentTarget;549						var li = link.ancestor('li');550						if (!li || !li.hasClass('disabled')) {551							var folderId = link.getData('folderId');552							var keywords = link.getData('keywords');553							var orderByField = link.getData('orderByField');554							var orderByType = link.getData('orderByType');555							var pageNumber = link.getData('pageNumber');556							instance.loadMessages(folderId, pageNumber, orderByField, orderByType, keywords);557						}558					},559					'.messages-link'560				);561				instance.mailContainer.delegate(562					'click',563					function(event) {564						var link = event.currentTarget;565						if (!link.hasAttribute('data-messageType')) {566							link = link.one('input[type="button"]');567						}568						var messageId = link.getData('messageId');569						var messageType = link.getData('messageType');570						var replyMessageId = link.getData('replyMessageId');571						instance.loadCompose(instance.accountId, messageId, messageType, replyMessageId);572					},573					'.compose-message'574				);575				instance.manageFoldersContainer.plug(576					A.Plugin.IO,577					{578						autoLoad: false,579						method: 'POST',580						uri: themeDisplay.getLayoutURL() + '/-/mail/manage_folders'581					}582				);583				instance.messageContainer.delegate(584					'click',585					function(event) {586						var messageId = event.currentTarget.getData('messageId');587						instance.deleteMessages([messageId]);588					},589					'.delete-message'590				);591				instance.messagesContainer.delegate(592					'click',593					function(event) {594						var messageIds = instance._getSelectedMessageIds();595						instance.deleteMessages(messageIds);596					},597					'.delete-messages'598				);599				instance.messagesContainer.delegate(600					'click',601					function(event) {602						var keywords = event.currentTarget.ancestor('.search-messages').one('input').val();603						instance.loadMessages(instance.folderId, 1, instance.orderByField, instance.orderByType, keywords);604					},605					'.search-messages button'606				);607				instance.messagesContainer.delegate(608					'keyup',609					function(event) {610						if (event.keyCode != 13) {611							return;612						}613						var keywords = event.currentTarget.val();614						instance.loadMessages(instance.folderId, 1, instance.orderByField, instance.orderByType, keywords);615					},616					'.search-messages input'617				);618				instance.messagesContainer.delegate(619					'click',620					function(event) {621						instance.messagesContainer.all('input[type=checkbox]').each(622							function(item, index, collection) {623								item.set('checked', true);624							}625						);626					},627					'.select-all'628				);629				instance.messagesContainer.delegate(630					'click',631					function(event) {632						instance.messagesContainer.all('input[type=checkbox]').each(633							function(item, index, collection) {634								item.set('checked', false);635							}636						);637					},638					'.select-none'639				);640				instance._pollCheckMessages();641			},642			_displayContainer: function(container) {643				var instance = this;644				instance.composeContainer.hide();645				instance.manageFoldersContainer.hide();646				instance.messagesContainer.hide();647				instance.messageContainer.hide();648				container.show();649			},650			_getSelectedMessageIds: function() {651				var instance = this;652				var messageIds = [];653				instance.messagesContainer.all('input[type=checkbox]').each(654					function(item, index, collection) {655						var messageId = item.getAttribute('messageId');656						if (messageId && item.get('checked')) {657							messageIds.push(messageId);658						}659					}660				);661				return messageIds;662			},663			_hideWindow: function() {664				var instance = this;665				var dialog = instance.dialog;666				if (dialog) {667					dialog.hide();668				}669			},670			_pollCheckMessages: function() {671				var instance = this;672				if (instance.inboxFolderId) {673					instance.checkMessages(instance.inboxFolderId);674				}675				if (instance.timeoutMessages) {676					clearTimeout(instance.timeoutMessages);677				}678				instance.timeoutMessages = setTimeout(A.bind('_pollCheckMessages', instance), instance._pollInterval);679			},680			_pollStopMessages: function() {681				var instance = this;682				clearTimeout(instance.timeoutMessages);683			},684			accountId: null,685			folderId: null,686			inboxFolderId: null,687			keywords: '',688			orderByField: 'sentDate',689			orderByType: 'desc',690			pageNumber: 1,691			_pollInterval: 60000692		};693	},694	'',695	{696		requires: ['aui-base', 'aui-datatype', 'aui-io-deprecated', 'liferay-util-window']697	}...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
