接上一篇: Openstack liberty源码分析 之 云主机的启动过程1
nova-conductor
nova-api
通过rpc发送启动云主机请求后,nova-conductor
会收到该请求,根据路由映射,该请求会递交给
nova/conductor/manager.py.ComputeTaskManager.build_instances
处理,如下(函数说明见注释):
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.
#为nova-scheduler生成请求参数
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
"""
flavor = objects.Flavor.get_by_id(context, flavor['id'])
filter_properties = dict(filter_properties,
instance_type=flavor)
try:
'''
如果指定了group信息并且支持相应的filter,就添加group过滤信息到
filter_properties
'''
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)
"""
发送同步消息给nova-scheduler,选取用于创建云主机的主机
接口调用如下:SchedulerClient -> SchedulerQueryClient -
> SchedulerAPI
与主机过滤相关的`filter_prorerties`参数是一个字典,内容如下:
{
u'instance_type':
Flavor(created_at=None,deleted=False,deleted_at=None,disabled=False,ephemeral_gb=0,extra_specs={},flavorid='2',id=5,is_public=True,memory_mb=2048,name='m1.small',projects=[],root_gb=20,rxtx_factor=1.0,swap=0,updated_at=None,vcpu_weight=0,vcpus=1),
'retry': {'num_attempts': 1, 'hosts': []},
u'scheduler_hints': {}
}
启动命令中没有指定`--hints`选项,所以`scheduler_hints`为空,而
`instance_type`是一个Flavor实例与命令行中的`--flavor 2`相关
"""
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
#依次发送启动instance的rpc请求到host,由nova-compute完成instance的启动过程
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'])
从上面的源码可以看出,build_instances
方法主要实现过滤参数的组装,然后通过客户端api发送rpc请求到scheduler
完成host的选取,最后发送rpc请求到选取的host上,由nova-compute
完成云主机的启动。下面来看看nova-scheduler
是如何选取主机的。
nova-scheduler
scheduler
收到客户端发来的select_destination
请求消息后,