首页 > 网络 > 云计算 >

世界杯外围投注官网

2016-09-15

1 首先我们要清楚,为nova添加一个新的api是很简单的,因为上面的那一套HTTP请求不需要我们管,只是照着来写就行了,主要是你的api内的自己的逻辑;2 所有的api文件都是放在目录 nova api openstack compute 下,M版本的世界杯外围投注网站没有了目录。

Nova API的实现,以创建云主机过程分析

1. 首先我们要清楚,为nova添加一个新的api是很简单的,因为上面的那一套HTTP请求不需要我们管,只是照着来写就行了,
主要是你的api内的自己的逻辑;

2. 所有的api文件都是放在目录&世界杯外围投注官网39;nova/api/openstack/compute&世界杯外围投注官网39;下,M版本的世界杯外围投注网站没有了目录&世界杯外围投注官网39;nova/api/openstack/compute/contrib&世界杯外围投注官网39;

3. 以创建云主机来分析:

REQ: curl -i &世界杯外围投注官网39;http://192.168.1.9:8774/v2/14fd316568bc4f6992ba161fd4e23001/servers&世界杯外围投注官网39; -X POST -H "X-Auth-Project-Id: 14fd316568bc4f6992ba161fd4e23001" 
-H "User-Agent: python-novaclient" -H "Content-Type: application/json" -H "Accept: application/json" -H "X-Auth-Token: 3b9da36bfcf4491f88994b25c3045f95" 
-d &世界杯外围投注官网39;{"server": {"name": "createVm", "imageRef": "db281a42-df86-4a3d-a8df-1af7b2eb80bc", "availability_zone": "nova", "key_name": "keyName", 
"flavorRef": "8", "max_count": 1, "min_count": 1, "networks": [{"port": "406b40b4-6b66-47d9-a943-9e341aeae6ef"}]}}&世界杯外围投注官网39;
3.1 根据这个请求,nova-api服务监听到后,可以很快的定位到文件&世界杯外围投注官网39;nova/api/openstack/compute/servers.py&世界杯外围投注官网39;
  世界杯外围投注官网 vim nova/api/openstack/compute/servers.py
  class ServersController(wsgi.Controller):
    """The Server API base controller class for the OpenStack API."""
    世界杯外围投注官网 这些命名空间(对应于文件setup.cfg内定义的方法)会作为扩展api的形式被加载进来,下面的世界杯外围投注网站通过stevedore.enabled.EnabledExtensionManager实现的
    EXTENSION_CREATE_NAMESPACE = &世界杯外围投注官网39;nova.api.v21.extensions.server.create&世界杯外围投注官网39;
    EXTENSION_REBUILD_NAMESPACE = &世界杯外围投注官网39;nova.api.v21.extensions.server.rebuild&世界杯外围投注官网39;
    EXTENSION_UPDATE_NAMESPACE = &世界杯外围投注官网39;nova.api.v21.extensions.server.update&世界杯外围投注官网39;
    EXTENSION_RESIZE_NAMESPACE = &世界杯外围投注官网39;nova.api.v21.extensions.server.resize&世界杯外围投注官网39;
    世界杯外围投注官网 NOTE:在目录&世界杯外围投注官网39;nova/api/openstack/compute&世界杯外围投注官网39;下有两个文件夹&世界杯外围投注官网39;schemas&世界杯外围投注官网39;/&世界杯外围投注官网39;views&世界杯外围投注官网39;,这两个文件夹下的内容将会在创建云主机的时候初始化
    _view_builder_class = views_servers.ViewBuilderV21
    schema_server_create = schema_servers.base_create
    schema_server_update = schema_servers.base_update
    schema_server_rebuild = schema_servers.base_rebuild
    schema_server_resize = schema_servers.base_resize
    schema_server_create_v20 = schema_servers.base_create_v20
    schema_server_update_v20 = schema_servers.base_update_v20
    schema_server_rebuild_v20 = schema_servers.base_rebuild_v20
    schema_server_create_v219 = schema_servers.base_create_v219
    schema_server_update_v219 = schema_servers.base_update_v219
    schema_server_rebuild_v219 = schema_servers.base_rebuild_v219
3.2 进入具体的方法内
    @wsgi.response(202)
    @extensions.expected_errors((400, 403, 409, 413))
    @validation.schema(schema_server_create_v20, &世界杯外围投注官网39;2.0&世界杯外围投注官网39;, &世界杯外围投注官网39;2.0&世界杯外围投注官网39;)
    @validation.schema(schema_server_create, &世界杯外围投注官网39;2.1&世界杯外围投注官网39;, &世界杯外围投注官网39;2.18&世界杯外围投注官网39;)
    @validation.schema(schema_server_create_v219, &世界杯外围投注官网39;2.19&世界杯外围投注官网39;)
    def create(self, req, body):
        """Creates a new server for a given user."""
    前面进行一些操作的策略权限的判断主要是和文件(policy.json),部分参数的读取;
    然后进入方法:
    (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(&世界杯外围投注官网39;metadata&世界杯外围投注官网39;, {}),
                    admin_password=password,
                    requested_networks=requested_networks,
                    check_server_group_quota=True,
                    **create_kwargs)
3.3 进入文件‘nova/compute/api.py’
    世界杯外围投注官网 这个hooks很有意思,你可以用它来做很多的事情
    @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)
        """
        世界杯外围投注官网 为什么又进行一次策略的检查?
        世界杯外围投注官网 Check policies up front to fail before performing more expensive work
        self._check_create_policies(context, availability_zone,
                requested_networks, block_device_mapping, forced_host,
                forced_node)
        if requested_networks and max_count > 1:
            self._check_multiple_instances_and_specified_ip(requested_networks)
            if utils.is_neutron():
                self._check_multiple_instances_neutron_ports(
                    requested_networks)
        if availability_zone:
            available_zones = availability_zones.\
                get_availability_zones(context.elevated(), True)
            if forced_host is None and availability_zone not in \
                    available_zones:
                msg = _(&世界杯外围投注官网39;The requested availability zone is not available&世界杯外围投注官网39;)
                raise exception.InvalidRequest(msg)
        世界杯外围投注官网 生成一个主机过滤的字典
        filter_properties = scheduler_utils.build_filter_properties(
                scheduler_hints, forced_host, forced_node, instance_type)
        世界杯外围投注官网 进入方法&世界杯外围投注官网39;def _create_instance()&世界杯外围投注官网39;
        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)
3.4 进入方法&世界杯外围投注官网39;def _create_instance()&世界杯外围投注官网39;
这个方法的主要作用是:
    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)
3.5 调用方法
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)
3.5.1 我们先来看看&世界杯外围投注官网39;self.compute_task_api&世界杯外围投注官网39;

根据世界杯外围投注网站流程可以很快的知道它调到文件&世界杯外围投注官网39;nova/conductor/rpcapi.py&世界杯外围投注官网39;内的类class ComputeTaskAPI(object):
先看它的初始化函数:

      def __init__(self):
          super(ComputeTaskAPI, self).__init__()
          target = messaging.Target(topic=CONF.conductor.topic,
                                    namespace=&世界杯外围投注官网39;compute_task&世界杯外围投注官网39;,
                                    version=&世界杯外围投注官网39;1.0&世界杯外围投注官网39;)
          serializer = objects_base.NovaObjectSerializer()
          self.client = rpc.get_client(target, serializer=serializer)
引入了一个新的模块&世界杯外围投注官网39;oslo_messaging&世界杯外围投注官网39;,利用了rpc消息队列处理,这些东西这里就不展开将了,下次可以专门开一篇博客将,
我们主要要知道的是,这里主要是通过利用包装后的rpc消息队列(rabbitMQ/ZeroMQ/...)来各个服务之间的通信

3.6 现在进入文件"nova/conductor/api.py",进入函数:

    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)
3.7 进入文件&世界杯外围投注官网39;nova/conductor/rpcapi.py&世界杯外围投注官网39;,进入函数:
    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 = &世界杯外围投注官网39;1.10&世界杯外围投注官网39;
        if not self.client.can_send_version(version):
            version = &世界杯外围投注官网39;1.9&世界杯外围投注官网39;
            if &世界杯外围投注官网39;instance_type&世界杯外围投注官网39; in filter_properties:
                flavor = filter_properties[&世界杯外围投注官网39;instance_type&世界杯外围投注官网39;]
                flavor_p = objects_base.obj_to_primitive(flavor)
                filter_properties = dict(filter_properties,
                                         instance_type=flavor_p)
        kw = {&世界杯外围投注官网39;instances&世界杯外围投注官网39;: instances, &世界杯外围投注官网39;image&世界杯外围投注官网39;: image_p,
               &世界杯外围投注官网39;filter_properties&世界杯外围投注官网39;: filter_properties,
               &世界杯外围投注官网39;admin_password&世界杯外围投注官网39;: admin_password,
               &世界杯外围投注官网39;injected_files&世界杯外围投注官网39;: injected_files,
               &世界杯外围投注官网39;requested_networks&世界杯外围投注官网39;: requested_networks,
               &世界杯外围投注官网39;security_groups&世界杯外围投注官网39;: security_groups}
        if not self.client.can_send_version(version):
            version = &世界杯外围投注官网39;1.8&世界杯外围投注官网39;
            kw[&世界杯外围投注官网39;requested_networks&世界杯外围投注官网39;] = kw[&世界杯外围投注官网39;requested_networks&世界杯外围投注官网39;].as_tuples()
        if not self.client.can_send_version(&世界杯外围投注官网39;1.7&世界杯外围投注官网39;):
            version = &世界杯外围投注官网39;1.5&世界杯外围投注官网39;
            bdm_p = objects_base.obj_to_primitive(block_device_mapping)
            kw.update({&世界杯外围投注官网39;block_device_mapping&世界杯外围投注官网39;: bdm_p,
                       &世界杯外围投注官网39;legacy_bdm&世界杯外围投注官网39;: legacy_bdm})
        世界杯外围投注官网 前面主要是进行版本的判断和少量的参数重组
        世界杯外围投注官网 下面这两行才是关键
        世界杯外围投注官网 准备rpc服务
        世界杯外围投注官网 调用cast方法,这是一个异步任务,其中参数&世界杯外围投注官网39;build_instances&世界杯外围投注官网39;表示消息接受方的方法
        cctxt = self.client.prepare(version=version)
        cctxt.cast(context, &世界杯外围投注官网39;build_instances&世界杯外围投注官网39;, **kw)
3.8 进入文件&世界杯外围投注官网39;nova/conductor/manager.py&世界杯外围投注官网39;,调用函数:
    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
        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(&世界杯外围投注官网39;instance_type&世界杯外围投注官网39;)
        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[&世界杯外围投注官网39;id&世界杯外围投注官网39;])
            filter_properties = dict(filter_properties, instance_type=flavor)
        request_spec = {}
        try:
            世界杯外围投注官网 check retry policy. Rather ugly use of instances[0]...
            世界杯外围投注官网 but if we&世界杯外围投注官网39;ve exceeded max retries... then we really only
            世界杯外围投注官网 have a single instance.
            世界杯外围投注官网 为过滤做一些基本判断和参数的组合
            scheduler_utils.populate_retry(
                filter_properties, instances[0].uuid)
            request_spec = scheduler_utils.build_request_spec(
                    context, image, instances)
            世界杯外围投注官网 结果一系列的过滤条件,得到符合条件的物理主机,用来启动云主机
            世界杯外围投注官网 为每一台云主机分配一个物理主机
            世界杯外围投注官网 具体的过滤规则会另外开一篇博客讲解
            hosts = self._schedule_instances(
                    context, request_spec, filter_properties)
        except Exception as exc:
            updates = {&世界杯外围投注官网39;vm_state&世界杯外围投注官网39;: vm_states.ERROR, &世界杯外围投注官网39;task_state&世界杯外围投注官网39;: None}
            for instance in instances:
                self._set_vm_state_and_notify(
                    context, instance.uuid, &世界杯外围投注官网39;build_instances&世界杯外围投注官网39;, updates,
                    exc, request_spec)
                self._cleanup_allocated_networks(
                    context, instance, requested_networks)
            return
        世界杯外围投注官网 循环创建云主机
        世界杯外围投注官网 个人感觉这里会有一些问题,如果数量很多的话,这个循环就相当于排队执行,会不会耗时间,可以在这里加一些策略
        世界杯外围投注官网 但是仔细想想,因为你调用libvirt的api它就是一个一个的来的,所以循环还是得要,所以可以考虑对相同的hosts的云主机进行优化
        for (instance, host) in six.moves.zip(instances, hosts):
            try:
                instance.refresh()
            except (exception.InstanceNotFound,
                    exception.InstanceInfoCacheNotFound):
                LOG.debug(&世界杯外围投注官网39;Instance deleted during build&世界杯外围投注官网39;, 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&世界杯外围投注官网39;t contain
            世界杯外围投注官网 instance specific information
            bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
                    context, instance.uuid)
            世界杯外围投注官网 host--表示你要往哪台物理主机上启动这个云主机,主要是通过rpc发送过去的
            self.compute_rpcapi.build_and_run_instance(context,
                    instance=instance, host=host[&世界杯外围投注官网39;host&世界杯外围投注官网39;], 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[&世界杯外围投注官网39;nodename&世界杯外围投注官网39;],
                    limits=host[&世界杯外围投注官网39;limits&世界杯外围投注官网39;])
3.9 现在进入文件&世界杯外围投注官网39;nova/compute/rpcapi.py&世界杯外围投注官网39;,找到函数:
    def build_and_run_instance(self, ctxt, instance, host, 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):
        version = &世界杯外围投注官网39;4.0&世界杯外围投注官网39;
        世界杯外围投注官网 准备rpc客户端,进行rpc消息队列的调用,server参数很重要,它表示这个动作会往哪台物理主机上发送
        世界杯外围投注官网 说白了就是这个云主机将会在哪台物理主机上启动
        cctxt = self.client.prepare(server=host, version=version)
        世界杯外围投注官网 异步的方法,这里必须使用异步的方法,不然前面的循环就会成为鸡肋
        cctxt.cast(ctxt, &世界杯外围投注官网39;build_and_run_instance&世界杯外围投注官网39;, instance=instance,
                image=image, request_spec=request_spec,
                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, node=node,
                limits=limits)
3.10 进入文件&世界杯外围投注官网39;nova/compute/manager.py&世界杯外围投注官网39;,调用函数:
    @wrap_exception()
    @reverts_task_state
    @wrap_instance_fault
    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)
        世界杯外围投注官网 NOTE(danms): We spawn here to return the RPC worker thread back to
        世界杯外围投注官网 the pool. Since what follows could take a really long time, we don&世界杯外围投注官网39;t
        世界杯外围投注官网 want to tie up RPC workers.
        世界杯外围投注官网 这里主要是使用了python的第三方库eventlet,以实现高并发
        世界杯外围投注官网 函数的第一个参数就是它将要执行的func
        utils.spawn_n(_locked_do_build_and_run_instance,
                      context, instance, image, request_spec,
                      filter_properties, admin_password, injected_files,
                      requested_networks, security_groups,
                      block_device_mapping, node, limits)
3.11 接下来进入方法:
    @hooks.add_hook(&世界杯外围投注官网39;build_instance&世界杯外围投注官网39;)
    @wrap_exception()
    @reverts_task_state
    @wrap_instance_event
    @wrap_instance_fault
    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(&世界杯外围投注官网39;Took %0.2f seconds to build instance.&世界杯外围投注官网39;),
                     timer.elapsed(), instance=instance)
            return build_results.ACTIVE
3.12 进入方法:
    def _build_and_run_instance(self, context, instance, image, injected_files,
            admin_password, requested_networks, security_groups,
            block_device_mapping, node, limits, filter_properties):
        image_name = image.get(&世界杯外围投注官网39;name&世界杯外围投注官网39;)
        世界杯外围投注官网 notify,事件通知,使用了rpc的消息机制
        self._notify_about_instance_usage(context, instance, &世界杯外围投注官网39;create.start&世界杯外围投注官网39;,
                extra_usage_info={&世界杯外围投注官网39;image_name&世界杯外围投注官网39;: image_name})
        try:
            世界杯外围投注官网 获取参数node主机上的可用资源
            rt = self._get_resource_tracker(node)
            世界杯外围投注官网 在启动之前就先得到主机上的资源
            with rt.instance_claim(context, instance, limits):
                世界杯外围投注官网 NOTE(russellb) It&世界杯外围投注官网39;s important that this validation be done
                世界杯外围投注官网 *after* the resource tracker instance claim, as that is where
                世界杯外围投注官网 the host is set on the instance.
                世界杯外围投注官网 之前在做过滤scheduler的时候,引入了,所以这个时候要对主机在参数filter_properties
                世界杯外围投注官网 内做判断
                self._validate_instance_group_policy(context, instance,
                        filter_properties)
                image_meta = objects.ImageMeta.from_dict(image)
                世界杯外围投注官网 建立云主机所需的资源
                世界杯外围投注官网 其中包括网络,bdm
                with self._build_resources(context, instance,
                        requested_networks, security_groups, image_meta,
                        block_device_mapping) as resources:
                    instance.vm_state = vm_states.BUILDING
                    instance.task_state = task_states.SPAWNING
                    世界杯外围投注官网 NOTE(JoshNang) This also saves the changes to the
                    世界杯外围投注官网 instance from _allocate_network_async, as they aren&世界杯外围投注官网39;t
                    世界杯外围投注官网 saved in that function to prevent races.
                    instance.save(expected_task_state=
                            task_states.BLOCK_DEVICE_MAPPING)
                    block_device_info = resources[&世界杯外围投注官网39;block_device_info&世界杯外围投注官网39;]
                    network_info = resources[&世界杯外围投注官网39;network_info&世界杯外围投注官网39;]
                    LOG.debug(&世界杯外围投注官网39;Start spawning the instance on the hypervisor.&世界杯外围投注官网39;,
                              instance=instance)
                    with timeutils.StopWatch() as timer:
                        世界杯外围投注官网 self.driver表示用的是哪种类型的后端虚拟化技术
                        世界杯外围投注官网 可以通过配置文件来进行配置
                        世界杯外围投注官网 现在跳到3.13
                        self.driver.spawn(context, instance, image_meta,
                                          injected_files, admin_password,
                                          network_info=network_info,
                                          block_device_info=block_device_info)
                    LOG.info(_LI(&世界杯外围投注官网39;Took %0.2f seconds to spawn the instance on &世界杯外围投注官网39;
                                 &世界杯外围投注官网39;the hypervisor.&世界杯外围投注官网39;), timer.elapsed(),
                             instance=instance)
        except ......
            ......
        世界杯外围投注官网 If CONF.default_access_ip_network_name is set, grab the
        世界杯外围投注官网 corresponding network and set the access ip values accordingly.
        network_name = CONF.default_access_ip_network_name
        if (network_name and not instance.access_ip_v4 and
                not instance.access_ip_v6):
            世界杯外围投注官网 Note that when there are multiple ips to choose from, an
            世界杯外围投注官网 arbitrary one will be chosen.
            for vif in network_info:
                if vif[&世界杯外围投注官网39;network&世界杯外围投注官网39;][&世界杯外围投注官网39;label&世界杯外围投注官网39;] == network_name:
                    for ip in vif.fixed_ips():
                        if not instance.access_ip_v4 and ip[&世界杯外围投注官网39;version&世界杯外围投注官网39;] == 4:
                            instance.access_ip_v4 = ip[&世界杯外围投注官网39;address&世界杯外围投注官网39;]
                        if not instance.access_ip_v6 and ip[&世界杯外围投注官网39;version&世界杯外围投注官网39;] == 6:
                            instance.access_ip_v6 = ip[&世界杯外围投注官网39;address&世界杯外围投注官网39;]
                    break
        self._update_instance_after_spawn(context, instance)
        try:
            instance.save(expected_task_state=task_states.SPAWNING)
        except (exception.InstanceNotFound,
                exception.UnexpectedDeletingTaskStateError) as e:
            with excutils.save_and_reraise_exception():
                self._notify_about_instance_usage(context, instance,
                    &世界杯外围投注官网39;create.end&世界杯外围投注官网39;, fault=e)
        self._update_scheduler_instance_info(context, instance)
        self._notify_about_instance_usage(context, instance, &世界杯外围投注官网39;create.end&世界杯外围投注官网39;,
                extra_usage_info={&世界杯外围投注官网39;message&世界杯外围投注官网39;: _(&世界杯外围投注官网39;Success&世界杯外围投注官网39;)},
                network_info=network_info)
3.13 进入文件&世界杯外围投注官网39;nova/virt/libvirt/driver.py&世界杯外围投注官网39;,调用方法:
    首先我们要知道,它最后肯定调用的是libvirt的api,只是在这里组一个xml文件出来
    世界杯外围投注官网 NOTE(ilyaalekseyev): Implementation like in multinics
    世界杯外围投注官网 for xenapi(tr3buchet)
    def spawn(self, context, instance, image_meta, injected_files,
              admin_password, network_info=None, block_device_info=None):
        disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
                                            instance,
                                            image_meta,
                                            block_device_info)
        世界杯外围投注官网 创建云主机所需的镜像
        世界杯外围投注官网 期间用到了镜像缓存的小功能
        世界杯外围投注官网 原理很简单,就是先规定一个系统目录,将所需的image都会缓存到此,然后如果第二次基于这个image启动云主机时
        世界杯外围投注官网 就会去这个目录先判断,如果有了,就不去远端下载了
        self._create_image(context, instance,
                           disk_info[&世界杯外围投注官网39;mapping&世界杯外围投注官网39;],
                           network_info=network_info,
                           block_device_info=block_device_info,
                           files=injected_files,
                           admin_pass=admin_password)
        世界杯外围投注官网 组合出一个xml文件出来
        世界杯外围投注官网 如果你要修改云主机的xml,可以从这里进入入手做修改
        xml = self._get_guest_xml(context, instance, network_info,
                                  disk_info, image_meta,
                                  block_device_info=block_device_info,
                                  write_to_disk=True)
        世界杯外围投注官网 现在进入这个方法,3.14
        self._create_domain_and_network(context, xml, instance, network_info,
                                        disk_info,
                                        block_device_info=block_device_info)
        LOG.debug("Instance is running", instance=instance)
        def _wait_for_boot():
            """Called at an interval until the VM is running."""
            state = self.get_info(instance).state
            if state == power_state.RUNNING:
                LOG.info(_LI("Instance spawned successfully."),
                         instance=instance)
                raise loopingcall.LoopingCallDone()
        timer = loopingcall.FixedIntervalLoopingCall(_wait_for_boot)
        timer.start(interval=0.5).wait()
3.14 进入函数
    def _create_domain_and_network(self, context, xml, instance, network_info,
                                   disk_info, block_device_info=None,
                                   power_on=True, reboot=False,
                                   vifs_already_plugged=False):
        """Do required network setup and create domain."""
        ......
        guest = None
        try:
            with self.virtapi.wait_for_instance_event(
                    instance, events, deadline=timeout,
                    error_callback=self._neutron_failed_callback):
                self.plug_vifs(instance, network_info)
                self.firewall_driver.setup_basic_filtering(instance,
                                                           network_info)
                self.firewall_driver.prepare_instance_filter(instance,
                                                             network_info)
                with self._lxc_disk_handler(instance, instance.image_meta,
                                            block_device_info, disk_info):
                    世界杯外围投注官网 现在进入到3.15
                    guest = self._create_domain(
                        xml, pause=pause, power_on=power_on)
                self.firewall_driver.apply_instance_filter(instance,
                                                           network_info)
3.15 进入函数:‘def _create_domain’
    世界杯外围投注官网 TODO(sahid): Consider renaming this to _create_guest.
    def _create_domain(self, xml=None, domain=None,
                       power_on=True, pause=False):
        """Create a domain.
        Either domain or xml must be passed in. If both are passed, then
        the domain definition is overwritten from the xml.
        :returns guest.Guest: Guest just created
        """
        if xml:
            世界杯外围投注官网 从这里往下看很快就会看到调用的libvirt的api是&世界杯外围投注官网39;defineXML(xml)&世界杯外围投注官网39;
            世界杯外围投注官网 param xml: XML domain definition of the guest.
            世界杯外围投注官网 returns: a virDomain instance
            guest = libvirt_guest.Guest.create(xml, self._host)
        else:
            guest = libvirt_guest.Guest(domain)
        if power_on or pause:
            guest.launch(pause=pause)
        if not utils.is_neutron():
            guest.enable_hairpin()
        return guest

3.16 到这里一个云主机的创建步骤就简单的结束了,当然,后期libvirt会通过返回event事件的形式来通知上层云主机的状态
相关文章
最新文章
热点推荐