def _find_destination(self): # TODO(johngarbutt) this retry loop should be shared attempted_hosts = [self.source] request_spec = self._get_request_spec_for_select_destinations( attempted_hosts) host = None while host is None: self._check_not_over_max_retries(attempted_hosts) request_spec.ignore_hosts = attempted_hosts try: selection_lists = self.query_client.select_destinations( self.context, request_spec, [self.instance.uuid], return_objects=True, return_alternates=False) # We only need the first item in the first list, as there is # only one instance, and we don't care about any alternates. selection = selection_lists[0][0] host = selection.service_host except messaging.RemoteError as ex: # TODO(ShaoHe Feng) There maybe multi-scheduler, and the # scheduling algorithm is R-R, we can let other scheduler try. # Note(ShaoHe Feng) There are types of RemoteError, such as # NoSuchMethod, UnsupportedVersion, we can distinguish it by # ex.exc_type. raise exception.MigrationSchedulerRPCError( reason=six.text_type(ex)) scheduler_utils.fill_provider_mapping(request_spec, selection) provider_mapping = request_spec.get_request_group_mapping() if provider_mapping: # NOTE(gibi): this call might update the pci_requests of the # instance based on the destination host if so then such change # will be persisted when post_live_migration_at_destination # runs. compute_utils.\ update_pci_request_spec_with_allocated_interface_name( self.context, self.report_client, self.instance, provider_mapping) try: self._check_compatible_with_source_hypervisor(host) self._call_livem_checks_on_host(host, provider_mapping) except (exception.Invalid, exception.MigrationPreCheckError) as e: LOG.debug("Skipping host: %(host)s because: %(e)s", { "host": host, "e": e }) attempted_hosts.append(host) # The scheduler would have created allocations against the # selected destination host in Placement, so we need to remove # those before moving on. self._remove_host_allocations(selection.compute_node_uuid) host = None # TODO(artom) We should probably just return the whole selection object # at this point. return (selection.service_host, selection.nodename, selection.limits)
def _reschedule(self): # Since the resources on these alternates may have been consumed and # might not be able to support the migrated instance, we need to first # claim the resources to verify the host still has sufficient # available resources. elevated = self.context.elevated() host_available = False selection = None while self.host_list and not host_available: selection = self.host_list.pop(0) if (self.request_spec.requested_resources and not self._support_resource_request(selection)): LOG.debug( 'Scheduler returned alternate host %(host)s as a possible ' 'migration target for re-schedule but that host is not ' 'new enough to support the migration with resource ' 'request %(request)s. Trying another alternate.', { 'host': selection.service_host, 'request': self.request_spec.requested_resources }, instance=self.instance) continue if selection.allocation_request: alloc_req = jsonutils.loads(selection.allocation_request) else: alloc_req = None if alloc_req: # If this call succeeds, the resources on the destination # host will be claimed by the instance. host_available = scheduler_utils.claim_resources( elevated, self.reportclient, self.request_spec, self.instance.uuid, alloc_req, selection.allocation_request_version) if host_available: scheduler_utils.fill_provider_mapping( self.context, self.reportclient, self.request_spec, selection) else: # Some deployments use different schedulers that do not # use Placement, so they will not have an # allocation_request to claim with. For those cases, # there is no concept of claiming, so just assume that # the host is valid. host_available = True # There are no more available hosts. Raise a MaxRetriesExceeded # exception in that case. if not host_available: reason = ("Exhausted all hosts available for retrying build " "failures for instance %(instance_uuid)s." % { "instance_uuid": self.instance.uuid }) raise exception.MaxRetriesExceeded(reason=reason) return selection
def _schedule(self): selection_lists = self.query_client.select_destinations( self.context, self.request_spec, [self.instance.uuid], return_objects=True, return_alternates=True) # Since there is only ever one instance to migrate per call, we # just need the first returned element. selection_list = selection_lists[0] selection, self.host_list = self._get_host_supporting_request( selection_list) scheduler_utils.fill_provider_mapping( self.context, self.reportclient, self.request_spec, selection) return selection
def _schedule(self): selection_lists = self.query_client.select_destinations( self.context, self.request_spec, [self.instance.uuid], return_objects=True, return_alternates=True) # Since there is only ever one instance to migrate per call, we # just need the first returned element. selection_list = selection_lists[0] # The selected host is the first item in the list, with the # alternates being the remainder of the list. selection, self.host_list = selection_list[0], selection_list[1:] scheduler_utils.fill_provider_mapping( self.context, self.reportclient, self.request_spec, selection) return selection
def _schedule(self): selection_lists = self.query_client.select_destinations( self.context, self.request_spec, [self.instance.uuid], return_objects=True, return_alternates=True) # Since there is only ever one instance to migrate per call, we # just need the first returned element. selection_list = selection_lists[0] # Scheduler allocated resources on the first host so try that first selection, self.host_list = selection_list[0], selection_list[1:] scheduler_utils.fill_provider_mapping(self.request_spec, selection) return selection