nova部署虚拟机源码调用过程简要分析,关于novaclient的程序处理流程暂时还没有分析。后期如果有时间会进一步分析novaclient的程序执行过程,以及客户端和服务之间的http请求响应关系。
nova/api/openstack/compute/servers.py
def create(self, req, body):
...
(instances, resv_id) = self.compute_api.create(context,
inst_type,
image_uuid,
display_name=name,
display_description=description,
availability_zone=availability_zone,
forced_host=host, forced_node=node,
metadata=server_dict.get('metadata', {}),
admin_password=password,
requested_networks=requested_networks,
check_server_group_quota=True,
...
上面self.compute_api=compute.API(skip_policy_check=True)
nova/compute/init.py
CELL_TYPE_TO_CLS_NAME = {
'api': 'nova.compute.cells_api.ComputeCellsAPI',
'compute': 'nova.compute.api.API',
None: 'nova.compute.api.API',
}
...
def API(*args, **kwargs):
class_name = _get_compute_api_class_name()
return importutils.import_object(class_name, *args, **kwargs)
上述分析可知,nova/api/openstack/compute/servers.py中的create方法调用的是nova/compute/cells_api.py中的create()方法。
nova/compute/cells_api.py:class ComputeCellsAPI(compute_api.API)
def create(self, *args, **kwargs):
"""We can use the base functionality, but I left this here just
for completeness.
"""
return super(ComputeCellsAPI, self).create(*args, **kwargs)
从代码代码中可以看出,其调用了父类的create()方法。
从导包可以看出compute_api为nova.compute.api,所以ComputeCellsAPI继承于nova.compute.api.API。查看nova.compute.api.API中的create()方法。
nova.compute.api.API:
@hooks.add_hook("create_instance")
def create(self, context, instance_type,
image_href, kernel_id=None, ramdisk_id=None,...):
...
return self._create_instance(
context, instance_type,
image_href, kernel_id, ramdisk_id,...)
其返回的是self._create_instance()方法。
def _create_instance(self, context, instance_type,
image_href, kernel_id, ...):
"""Verify all the input parameters regardless of the provisioning
strategy being performed and schedule the instance(s) for
creation.
"""
self.compute_task_api.build_instances(context,
instances=instances, image=boot_meta,
filter_properties=filter_properties,
admin_password=admin_password,
injected_files=injected_files,
requested_networks=requested_networks,
security_groups=security_groups,
block_device_mapping=block_device_mapping,
legacy_bdm=False)
return (instances, reservation_id)
上面调用了compute_task_api.build_instances()方法。因为self.compute_task_api = conductor.ComputeTaskAPI(),所以转向conductor中。
nova.conductor.init.py:
from nova.conductor import api as conductor_api
def ComputeTaskAPI(*args, **kwargs):
use_local = kwargs.pop('use_local', False)
if CONF.conductor.use_local or use_local:
api = conductor_api.LocalComputeTaskAPI
else:
api = conductor_api.ComputeTaskAPI
return api(*args, **kwargs)
可以看出调用的API接口是nova.conductor.api。
nova.conductor.api.ComputeTaskAPI:
def build_instances(self, context, instances, image, filter_properties,
admin_password, injected_files, requested_networks,
security_groups, block_device_mapping, legacy_bdm=True):
self.conductor_compute_rpcapi.build_instances(context,
instances=instances, image=image,
filter_properties=filter_properties,
admin_password=admin_password, injected_files=injected_files,
requested_networks=requested_networks,
security_groups=security_groups,
block_device_mapping=block_device_mapping,
legacy_bdm=legacy_bdm)
上述中self.conductor_compute_rpcapi = rpcapi.ComputeTaskAPI(),转向conductor.rpcapi.ComputeTaskAPI。
nova.conductor.rpcapi.ComputeTaskAPI:
def build_instances(self, context, instances, image, filter_properties,
admin_password, injected_files, requested_networks,
security_groups, block_device_mapping, legacy_bdm=True):
image_p = jsonutils.to_primitive(image)
version = '1.10'
if not self.client.can_send_version(version):
version = '1.9'
if 'instance_type' in filter_properties:
flavor = filter_properties['instance_type']
flavor_p = objects_base.obj_to_primitive(flavor)
filter_properties = dict(filter_properties,
instance_type=flavor_p)
kw = {
'instances': instances, 'image': image_p,
'filter_properties': filter_properties,
'admin_password': admin_password,
'injected_files': injected_files,
'requested_networks': requested_networks,
'security_groups': security_groups}
if not