nova create

来源:互联网 发布:人工智能生活应用实例 编辑:程序博客网 时间:2024/06/06 20:39
instance的入口代码在nova/api/openstack/compute/servers.py,方法是create(),如下    def create(self, req, body):        """Creates a new server for a given user."""            (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,                            **create_kwargs)这里的compute_api是在ServersController的__init__函数中赋值如下: self.compute_api = compute.API()这里的compute是通过from nova import compute 导入的查看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 _get_compute_api_class_name():    """Returns the name of compute API class."""    cell_type = nova.cells.opts.get_cell_type()    return CELL_TYPE_TO_CLS_NAME[cell_type]def API(*args, **kwargs):    class_name = _get_compute_api_class_name()    return importutils.import_object(class_name, *args, **kwargs)看到API()返回的就是nova.compute.api.API,如下。所以compute_api就是nova.compute.api.API继续查看nova/compute/api.c 中的create函数 @hooks.add_hook("create_instance")    def create(self, context, instance_type,               image_href, kernel_id=None, ramdisk_id=None,               min_count=None, max_count=None,               display_name=None, display_description=None,               key_name=None, key_data=None, security_group=None,               availability_zone=None, forced_host=None, forced_node=None,               user_data=None, metadata=None, injected_files=None,               admin_password=None, block_device_mapping=None,               access_ip_v4=None, access_ip_v6=None, requested_networks=None,               config_drive=None, auto_disk_config=None, scheduler_hints=None,               legacy_bdm=True, shutdown_terminate=False,               check_server_group_quota=False):        """Provision instances, sending instance information to the        scheduler.  The scheduler will determine where the instance(s)        go and will handle creating the DB entries.        Returns a tuple of (instances, reservation_id)        """        return self._create_instance(                       context, instance_type,                       image_href, kernel_id, ramdisk_id,                       min_count, max_count,                       display_name, display_description,                       key_name, key_data, security_group,                       availability_zone, user_data, metadata,                       injected_files, admin_password,                       access_ip_v4, access_ip_v6,                       requested_networks, config_drive,                       block_device_mapping, auto_disk_config,                       filter_properties=filter_properties,                       legacy_bdm=legacy_bdm,                       shutdown_terminate=shutdown_terminate,                       check_server_group_quota=check_server_group_quota)继续调用_create_instance    def _create_instance(self, context, instance_type,               image_href, kernel_id, ramdisk_id,               min_count, max_count,               display_name, display_description,               key_name, key_data, security_groups,               availability_zone, user_data, metadata, injected_files,               admin_password, access_ip_v4, access_ip_v6,               requested_networks, config_drive,               block_device_mapping, auto_disk_config, filter_properties,               reservation_id=None, legacy_bdm=True, shutdown_terminate=False,               check_server_group_quota=False):        """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 是在computer/api.py 中的API类中的__init__中赋值的class API(base.Base):    """API for interacting with the compute manager."""    def __init__(self, image_api=None, network_api=None, volume_api=None,                 security_group_api=None, **kwargs):        self.compute_rpcapi = compute_rpcapi.ComputeAPI()        self.compute_task_api = conductor.ComputeTaskAPI()而from nova import conductor,所以从conductor/__init__.py 中from nova.conductor import api as conductor_apiimport nova.confCONF = nova.conf.CONFdef API(*args, **kwargs):    use_local = kwargs.pop('use_local', False)    if CONF.conductor.use_local or use_local:        api = conductor_api.LocalAPI    else:        api = conductor_api.API    return api(*args, **kwargs)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)因为conductor本来就是被设计用来访问数据库的,因此这里use_local 和 CONF.conductor.use_loca 都是false。所以这里的api = conductor_api.ComputeTaskAPI。而这里的conductor_api 又是from nova.conductor import api as conductor_api。所以最终回到conductor/api.py 中的class ComputeTaskAPI(object):    """ComputeTask API that queues up compute tasks for nova-conductor."""    def __init__(self):        self.conductor_compute_rpcapi = 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):        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)这里的conductor_compute_rpcapi 同样是在__init__中赋值为self.conductor_compute_rpcapi = rpcapi.ComputeTaskAPI()而rpcapi又是赋值如下:from nova.conductor import rpcapi因此最终调用到conductor/rpcapipy中的    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 self.client.can_send_version(version):            version = '1.8'            kw['requested_networks'] = kw['requested_networks'].as_tuples()        if not self.client.can_send_version('1.7'):            version = '1.5'            bdm_p = objects_base.obj_to_primitive(block_device_mapping)            kw.update({'block_device_mapping': bdm_p,                       'legacy_bdm': legacy_bdm})        cctxt = self.client.prepare(version=version)        cctxt.cast(context, 'build_instances', **kw)根据rpc 原理,这里额rpc最终是在nova/conductor/manager.py 中有对应的的函数 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.        # TODO(danms): Remove this in version 2.0 of the RPC API                    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'])同理这里的compute_rpcapi 是在nova/conductor/manager.py中的class ComputeTaskManager(base.Base):    """Namespace for compute methods.    This class presents an rpc API for nova-conductor under the 'compute_task'    namespace.  The methods here are compute operations that are invoked    by the API service.  These methods see the operation to completion, which    may involve coordinating activities on multiple compute nodes.    """    target = messaging.Target(namespace='compute_task', version='1.15')    def __init__(self):        super(ComputeTaskManager, self).__init__()        self.compute_rpcapi = compute_rpcapi.ComputeAPI()而from nova.compute import rpcapi as compute_rpcapi。所以这里回到computer的manager.py中查看nova/compute/manager.py  def build_and_run_instance(self, context, instance, image, request_spec,                     filter_properties, admin_password=None,                     injected_files=None, requested_networks=None,                     security_groups=None, block_device_mapping=None,                     node=None, limits=None):        @utils.synchronized(instance.uuid)        def _locked_do_build_and_run_instance(*args, **kwargs):            # NOTE(danms): We grab the semaphore with the instance uuid            # locked because we could wait in line to build this instance            # for a while and we want to make sure that nothing else tries            # to do anything with this instance while we wait.            with self._build_semaphore:                self._do_build_and_run_instance(*args, **kwargs)继续调用_do_build_and_run_instance    def _do_build_and_run_instance(self, context, instance, image,            request_spec, filter_properties, admin_password, injected_files,            requested_networks, security_groups, block_device_mapping,            node=None, limits=None):        try:            with timeutils.StopWatch() as timer:                self._build_and_run_instance(context, instance, image,                        decoded_files, admin_password, requested_networks,                        security_groups, block_device_mapping, node, limits,                        filter_properties)            LOG.info(_LI('Took %0.2f seconds to build instance.'),                     timer.elapsed(), instance=instance)            return build_results.ACTIVE继续调用_build_and_run_instance    def _build_and_run_instance(self, context, instance, image, injected_files,            admin_password, requested_networks, security_groups,            block_device_mapping, node, limits, filter_properties):                        self.driver.spawn(context, instance, image_meta,                                          injected_files, admin_password,                                          network_info=network_info,                                          block_device_info=block_device_info)                    LOG.info(_LI('Took %0.2f seconds to spawn the instance on '                                 'the hypervisor.'), timer.elapsed(),                             instance=instance)最终调用driver.spawn来创建虚拟机

原创粉丝点击