nova-scheduler select-destination源碼梳理

scheduler的調度流程

注: 源碼可以從~/nava/scheduler/managert.py (select_destinations)開始

scheduler從接受到rpc調用開始,所經歷的流程大概如下圖所示:

調用流程

  1. 對rpc傳過來的request_spec參數進行優化(這一步是S版後纔有的,爲了配合nova-api表中的聚合關係,進行預先的篩選,減少後邊查找的範圍)
        if self.driver.USES_ALLOCATION_CANDIDATES and not is_rebuild:
            # Only process the Placement request spec filters when Placement
            # is used.
            try:
                request_filter.process_reqspec(ctxt, spec_obj)
            except exception.RequestFilterFailed as e:
                raise exception.NoValidHost(reason=e.message)
def process_reqspec(ctxt, request_spec):
    """Process an objects.ReqestSpec before calling placement.

    :param ctxt: A RequestContext
    :param request_spec: An objects.RequestSpec to be inspected/modified
    """
    for filter in ALL_REQUEST_FILTERS:
        filter(ctxt, request_spec)

目前包含的4個filter爲:

ALL_REQUEST_FILTERS = [
    require_tenant_aggregate,
    map_az_to_placement_aggregate,
    require_image_type_support,
    compute_status_filter,
]
  1. 將request_spec翻譯爲placement所需的查詢格式並查詢符合的資源集合
resources = utils.resources_from_request_spec(
                ctxt, spec_obj, self.driver.host_manager)
res = self.placement_client.get_allocation_candidates(ctxt,resources)
  1. 根據資源集合去查找相應的hoststate(查詢的表爲:compute_node,services,instance,cell_mapping)
 
selections = self.driver.select_destinations(ctxt, spec_obj,
        instance_uuids, alloc_reqs_by_rp_uuid, provider_summaries,
        allocation_request_version, return_alternates)

從這一步開始進入到/nova/scheduler/filter_cheduler.py的select_destinations方法

 elevated = context.elevated()
       
 hosts = self._get_all_host_states(elevated, spec_obj,
    provider_summaries)
  1. 對hoststate進行過濾和打分,獲得符合條件並排好序的hoststate
        for num, instance_uuid in enumerate(instance_uuids):
            # In a multi-create request, the first request spec from the list
            # is passed to the scheduler and that request spec's instance_uuid
            # might not be the same as the instance we're processing, so we
            # update the instance_uuid in that case before passing the request
            # spec to filters since at least one filter
            # (ServerGroupAntiAffinityFilter) depends on that information being
            # accurate.
            spec_obj.instance_uuid = instance_uuid
            # Reset the field so it's not persisted accidentally.
            spec_obj.obj_reset_changes(['instance_uuid'])

            hosts = self._get_sorted_hosts(spec_obj, hosts, num)

這裏的instance_uuids是rpc傳過來的,相當於創建幾個虛機就有幾個instance_uuid
並且這裏獲得的是一個集合,最優的在第一個

5.對hoststate從最優開始進行claim操作,如果成功則跳出,更新hoststate並繼續下一個虛擬機的創建(回到第4步重新排序)這裏的claim操作只是對placement中的資源進行校驗和更新

claimed_host = None
            for host in hosts:
                cn_uuid = host.uuid
                if cn_uuid not in alloc_reqs_by_rp_uuid:
                    msg = ("A host state with uuid = '%s' that did not have a "
                           "matching allocation_request was encountered while "
                           "scheduling. This host was skipped.")
                    LOG.debug(msg, cn_uuid)
                    continue

                alloc_reqs = alloc_reqs_by_rp_uuid[cn_uuid]
            
                alloc_req = alloc_reqs[0]
                if utils.claim_resources(elevated, self.placement_client,
                        spec_obj, instance_uuid, alloc_req,
                        allocation_request_version=allocation_request_version):
                    claimed_host = host
                    break

            if claimed_host is None:
                LOG.debug("Unable to successfully claim against any host.")
                break

            claimed_instance_uuids.append(instance_uuid)
            claimed_hosts.append(claimed_host)

            # Now consume the resources so the filter/weights will change for
            # the next instance.
            self._consume_selected_host(claimed_host, spec_obj,
                                        instance_uuid=instance_uuid)

6.驗證claim成功的資源數和要求的數量是否相同,不同則回滾對placement的修改,並拋出novalidhost異常

self._ensure_sufficient_hosts(context, claimed_hosts, num_instances,
                claimed_instance_uuids)

7.返回選中的selection信息集合

selections_to_return = self._get_alternate_hosts(
            claimed_hosts, spec_obj, hosts, num, num_alts,
            alloc_reqs_by_rp_uuid, allocation_request_version)
        return selections_to_return

selecttion所包含的字段:

 fields = {
        "compute_node_uuid": fields.UUIDField(),
        "service_host": fields.StringField(),
        "nodename": fields.StringField(),
        "cell_uuid": fields.UUIDField(),
        "limits": fields.ObjectField("SchedulerLimits", nullable=True),
        # An allocation_request is a non-trivial dict, and so it will be stored
        # as an encoded string.
        "allocation_request": fields.StringField(nullable=True),
        "allocation_request_version": fields.StringField(nullable=True),
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章