Coin163

nova boot代码流程分析二:nova-scheduler主机选择 timer.schedule参数 schedule的音标 daily schedul

2016-07-27by admin, 次阅读

本篇文章主要介绍了"nova boot代码流程分析二:nova-scheduler主机选择",主要涉及到schedule,boot方面的内容,对于MySql感兴趣的同学可以参考一下: 本篇文章将分析nova-scheduler服务在创建VM时如何进行主机的选择。完整来说,nova-scheduler主机选择的过程主要分为以下几个阶段:1. n...

本篇文章将分析nova-scheduler服务在创建VM时如何进行主机的选择。完整来说,nova-scheduler主机选择的过程主要分为以下几个阶段:

1. nova.scheduler.rpcapi.SchedulerAPI发出RPC请求到nova.scheduler.manager.SchedulerManager。

2. 从SchedulerManager到调度器(类SchedulerDriver)。

3. 从SchedulerDriver到Filters。

4. 从Filters到权重计算和排序。

具体接到上一篇文章中跳过的选择主机的代码进行分析,代码如下。

#/nova/conductor/Manager.py:ComputeTaskManager    def build_instances(self, context, instances, image, filter_properties,            admin_password, injected_files, requested_networks,            security_groups, block_device_mapping=None, legacy_bdm=True):        # TODO(ndipanov): Remove block_device_mapping and legacy_bdm in version        #                 2.0 of the RPC API.        request_spec = scheduler_utils.build_request_spec(context, image,                                                          instances)        # TODO(danms): Remove this in version 2.0 of the RPC API        if (requested_networks and                not isinstance(requested_networks,                               objects.NetworkRequestList)):            requested_networks = objects.NetworkRequestList(                objects=[objects.NetworkRequest.from_tuple(t)                         for t in requested_networks])        # TODO(melwitt): Remove this in version 2.0 of the RPC API        flavor = filter_properties.get('instance_type')        if flavor and not isinstance(flavor, objects.Flavor):            # Code downstream may expect extra_specs to be populated since it            # is receiving an object, so lookup the flavor to ensure this.            flavor = objects.Flavor.get_by_id(context, flavor['id'])            filter_properties = dict(filter_properties, instance_type=flavor)        try:            scheduler_utils.setup_instance_group(context, request_spec,                                                 filter_properties)            # check retry policy. Rather ugly use of instances[0]...            # but if we've exceeded max retries... then we really only            # have a single instance.            scheduler_utils.populate_retry(filter_properties,                instances[0].uuid)            hosts = self.scheduler_client.select_destinations(context,                    request_spec, filter_properties)        except Exception as exc:            updates = {'vm_state': vm_states.ERROR, 'task_state': None}            for instance in instances:                self._set_vm_state_and_notify(                    context, instance.uuid, 'build_instances', updates,                    exc, request_spec)            return        for (instance, host) in itertools.izip(instances, hosts):            try:                instance.refresh()            except (exception.InstanceNotFound,                    exception.InstanceInfoCacheNotFound):                LOG.debug('Instance deleted during build', instance=instance)                continue            local_filter_props = copy.deepcopy(filter_properties)            scheduler_utils.populate_filter_properties(local_filter_props,                host)            # The block_device_mapping passed from the api doesn't contain            # instance specific information            bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(                    context, instance.uuid)            self.compute_rpcapi.build_and_run_instance(context,                    instance=instance, host=host['host'], image=image,                    request_spec=request_spec,                    filter_properties=local_filter_props,                    admin_password=admin_password,                    injected_files=injected_files,                    requested_networks=requested_networks,                    security_groups=security_groups,                    block_device_mapping=bdms, node=host['nodename'],                    limits=host['limits'])

其中

hosts =self.scheduler_client.select_destinations(context,

       request_spec, filter_properties)

是nova-scheduler服务选择host的代码流程,在本篇文章我们将重点进行分析,其中self.scheduler_client是/nova/scheduler/client/__init__.py: SchedulerClient对象。

1. nova.scheduler.rpcapi.SchedulerAPI发出RPC请求到nova.scheduler.manager.SchedulerManager

#/nova/scheduler/client/__init__.py:LazyLoaderclass LazyLoader(object):    def __init__(self, klass, *args, **kwargs):        self.klass = klass        self.args = args        self.kwargs = kwargs        self.instance = None    def __getattr__(self, name):        return functools.partial(self.__run_method, name)    def __run_method(self, __name, *args, **kwargs):        if self.instance is None:            self.instance = self.klass(*self.args, **self.kwargs)        return getattr(self.instance, __name)(*args, **kwargs)#/nova/scheduler/client/__init__.py:SchedulerClientclass SchedulerClient(object):    """Client library for placing calls to the scheduler."""    def __init__(self):        self.queryclient = LazyLoader(importutils.import_class(            'nova.scheduler.client.query.SchedulerQueryClient'))        self.reportclient = LazyLoader(importutils.import_class(            'nova.scheduler.client.report.SchedulerReportClient'))    @utils.retry_select_destinations    def select_destinations(self, context, request_spec, filter_properties):        return self.queryclient.select_destinations(            context, request_spec, filter_properties)

从上述的代码可以看出,SchedulerClient类中的self.queryclient和self.reportclient其实质应该分别为nova.scheduler.client.query.SchedulerQueryClient和nova.scheduler.client.report.SchedulerReportClient对象。不过只是被LazyLoader类进行包裹了,LazyLoader类的作用主要是起到单例模式和代理的作用。这里的主机选择的代码流程是调用nova.scheduler.client.query.SchedulerQueryClient对象的select_destinations函数。

#/nova/scheduler/client/query.py:SchedulerQueryClientclass SchedulerQueryClient(object):    """Client class for querying to the scheduler."""    def __init__(self):        self.scheduler_rpcapi = scheduler_rpcapi.SchedulerAPI()    def select_destinations(self, context, request_spec, filter_properties):        """Returns destinations(s) best suited for this request_spec and        filter_properties.        The result should be a list of dicts with 'host', 'nodename' and        'limits' as keys.        """        return self.scheduler_rpcapi.select_destinations(            context, request_spec, filter_properties)#/nova/scheduler/rpcapi.py:SchedulerAPI    def select_destinations(self, ctxt, request_spec, filter_properties):        cctxt = self.client.prepare(version='4.0')        return cctxt.call(ctxt, 'select_destinations',            request_spec=request_spec, filter_properties=filter_properties)

从上面的代码可以看出,nova-conductor服务最终会通过rpc调用去执行nova-scheduler服务的select_destinations函数。该函数在nova-scheduler的manager.py文件中。

2. 从SchedulerManager到调度器(类SchedulerDriver)


Docker 搭建gitlab docker hub docker官网 dockerfile

Docker 搭建gitlab",主要涉及到docker方面的内容,对于MySql感兴趣的同学可以参考一下: Docker搭建sameersbn/gitlab安装内容docker 当前使用版本1.9.0+;gitlab sameersbn/gitlabm... Docker搭...

Mysql查询和表结构最佳实践

Mysql查询最佳实践: 1. 不要用 SELECT *,否则,会读多,传输多,且增加可避免的表扫描 2. 不要 like %item% but item% 前面有%,这索引就没办法利用了。所以,若想用索引加快查询速度,那前面别加...

MySQL查询数据

MySQL查询数据",主要涉及到Mysql方面的内容,对于MySql感兴趣的同学可以参考一下: MySQL 查询数据MySQL 数据库使用SQL SELECT语句来查询数据。 你可以通过 mysql 命令提示窗口...

------分隔线----------------------------