OpenStack Nova分析——Nova Scheduler调度算法分析(3)

一、回顾

这一小节主要是过滤和权值计算。FilterScheduler的_schedule方法在实现虚拟机调度算法的时,调用了两个很重要的

方法:

(1)调用了HostManager对象的get_filtered_hosts方法 获取可用的计算节点列表。

(2)调用了HostManager对象的get_weighed_hosts方法 计算可用计算节点的权值。

/nova/scheduler/host_manager.py:

def __init__(self):
        ...
        self.filter_handler = filters.HostFilterHandler()
        filter_classes = self.filter_handler.get_matching_classes(
                CONF.scheduler_available_filters)
        self.filter_cls_map = {cls.__name__: cls for cls in filter_classes}
        self.filter_obj_map = {}
        self.default_filters = self._choose_host_filters(self._load_filters())
        self.weight_handler = weights.HostWeightHandler()
        weigher_classes = self.weight_handler.get_matching_classes(
                CONF.scheduler_weight_classes)
       ....

HostManager类的初始化方法中,分别调用HostFilterHandler对象和HostWeightHandler对象get_matching_classes

方法加载可用的过滤器类和权值类。过滤器类和权值类是实现get_filtered_hosts和get_weighed_hosts方法的基

础。

二、get_filtered_hosts方法

HostManager对象的get_filtered_hosts方法定义如下:(获取可用的计算节点列表)

class HostManager(object):
    def get_filtered_hosts(self, hosts, filter_properties, filter_class_names=None):
        ...
        #获取过滤器列表
        filter_classes = self._choose_host_filters(filter_class_names)
        ...
        #返回过滤后的主机(计算节点)列表
        return self.filter_handler.get_filtered_objects(filter_classes,
                                                        hosts, filter_properties)

(1)、为了确定计算节点是否可用,Nova Scheduler定义了多个过滤器,每个过滤器检查计算节点的某一种属性。只

有通过所有过滤器检查的计算节点才是可用的计算节点。

(2)、上面的方法首先调用_choose_host_filters获取过滤器类列表。然后调用filter_handler变量的

get_filtered_objects方法使用过滤器检查计算节点是否可用。另外get_filtered_hosts方法还可以通过参数

filter_properties传入force_hosts和ignore_hosts两个变量(主机淘汰规则)。

三、HostManager类的_choose_host_filters方法

_choose_host_filters方法:HostManager类的_choose_host_filters方法的功能是获取过滤器类列表

class HostManager(object):
    def _choose_host_filters(self, filter_cls_names):
        #如果外部没有传入filter_cls_names参数,则使用默认的过滤器
        if filter_cls_names is None:
            filter_cls_names = CONF.scheduler_default_filters
        #将filter_cls_names封装成列表
        if not isinstance(filter_cls_names, (list, tuple)):
            filter_cls_names = [filter_cls_names]
        good_filters = []
        bad_filters = []
        #遍历所有配置的过滤器
        for filter_name in filter_cls_names:
            found_class = False
            #遍历所有注册的过滤器
            for cls in self.filter_classes:
                #如果filter_name对应的过滤器在注册的过滤器列表中,则认为是好过滤器
                if cls.__name__ == filter_name:
                    good_filters.append(cls)
                    found_class = True
                    break
            #如果filter_name对应的过滤器不在注册的过滤器列表中,则认为是坏过滤器
            if not found_class:
                bad_filters.append(filter_name)
        ...
        return good_filter
遍历filter_cls_names参数中所有的过滤器,从中提取好的过滤器,所谓好的过滤器就是指 这个过滤器之前被注册

。这个注册过程在HostManager类的初始化方法中通过调用filter_handler对象的get_matching_classes方法注册

可用的滤波器get_matching_classes方法会注册nova.scheduler.filters包下定义的所有过滤器

注意:

(1) 如果外部没有传入filter_cls_names参数。_choose_host_filters方法会将filter_cls_names设置为默认的过

滤器列表。默认的过滤器列表由nova.conf配置文件的scheduler_default_filters配置项设置。

(2) filter_handler对象的get_matching_classes方法会注册nova.scheduler.filters包下定义的所有滤波器。

四、filter_handler对象的get_filtered_objects方法

1、filter_handler对象的get_filtered_objects方法调用客户指定的过滤器类,检查计算节点是否可用。

get_filtered_objects方法最终返回可用的计算节点列表。

2、filter_handler对象的类型为HostFilterHandler类。HostFilterHandler类继承自BaseFilterHandler类。

get_filtered_objects方法定义在BaseFilterHandler类中:

class BaseFilterHandler(loadables.BaseLoader):
    def get_filtered_objects(self, filter_classes, objs, filter_properties):
        #遍历每个过滤器
        for filter_cls in filter_classes:
            #调用过滤器类的filter_all方法
            objs = filter_cls().filter_all(objs, filter_properties)
        return list(objs)
filter_classes参数是过滤器类型列表,objs参数是待过滤的计算节点列表,filter_properties参数是客户定制的

过滤参数。

3、get_filtered_objects方法依次调用了每个过滤器对象的filter_all方法。每个过滤器对象的filter_all方法返

回一个迭代器对象,该迭代器包含通过该过滤器检查的主机列表

4、每个过滤器对象都继承字BaseHostFilter类,BaseHostFilter类继承自BaseFilter类。filter_all方法定义在

BaseFilter类中,定义:/nova/filters.py

class BaseFilter(object):  
    def filter_all(self, filter_obj_list, filter_properties):  
        for obj in filter_obj_list:  
            if self._filter_one(obj, filter_properties):  
                yield obj  
filter_obj_list待过滤的计算节点列表, filter_properties客户定制的过滤参数

(1)、filter_all方法对每个主机都掉用_filter_one方法,如果返回True,则返回该主机的引用。BaseFilter类中的

_filter_one方法始终返回True。BaseHostFilter类重载_filter_one方法,调用自身的host_passes方法。

(2)、BaseFilter类中的_filter_one方法:

class BaseHostFilter(filters.BaseFilter):
    def _filter_one(self, obj, filter_properties):
        return self.host_pass(obj, filter_properties)

过滤器类的内部逻辑定义在host_passes方法中。参数:待过滤的主机引用,客户定制的过滤参数

对于一个主机,如果过滤器的host_passes方法返回True,则主机通过该过滤器的检查,认为是可用的。

五、举例说明

更好的理解过滤器如何工作,着重分析ComputeFilter过滤器的host_passes方法的定义:

class ComputeFilter(filters.BaseHostFilter):
    def host_passes(self, host_state, filter_properties):
        """Returns True for only active compute nodes."""
        #节点的服务信息
		service = host_state.service  
        #如果节点的服务不是活动状态或者被禁用,则不通过检查
		if service['disabled']: 
            LOG.debug("%(host_state)s is disabled, reason: %(reason)s",
                      {'host_state': host_state,
                       'reason': service.get('disabled_reason')})
            return False
        else:
            if not self.servicegroup_api.service_is_up(service):
                LOG.warning(_LW("%(host_state)s has not been heard from in a "
                                "while"), {'host_state': host_state})
                return False
        return True
1、ComputeFilter过滤器主要调用servicegroup_api的service_is_up方法, 检查计算节点上的Nova Compute服务是

否处于激活状态

2、openstack中,任何一个服务都会有一个定时任务,定时在数据库中更新自己的状态。servicegroup_api的

service_is_up方法(/novaservicegroup/api.py)会查询数据库,检查服务最近的更新时间。没有更新,认为服务已

经关闭。

注意:ComputeFilter是一个最基本的过滤器。如果一个节点上连Nova Compute服务没有启动,根本谈不上创建虚拟

机。


总结:HostManager对象的get_filtered_hosts方法的工作流程。

1、HostManager对象的get_filtered_hosts方法首先调用HostManager对象的_choose_host_filters方法获取过滤器

类列表。然后使用HostManager对象的get_filtered_objects方法使用过滤器检查计算节点是否可用。

2、_choose_host_filters方法依次检查filter_cls_names参数中的过滤器名,如果过滤器名对应的过滤器被预先注

册过,则认为是好的过滤器。最终,_choose_host_filters方法会返回所有好过滤器列表

 如果外部没有指定filter_cls_names参数,_choose_host_filters会使用nova.conf配置文件默认过滤器。

3、HostManager对象的get_filtered_objects方法依次调用每个过滤器对象的filter_all方法。返回的是通过该滤波

器的主机列表。

4、过滤器对象的filter_all方法对每个待过滤的主机调用filter_one方法,如果返回True,则代表主机通过检查。

5、filter_one方法调用host_passes。过滤器对象的主要逻辑都定义在host_passes方法中。

你可能感兴趣的:(openstack组件研究)