nova源码分析--创建虚拟机(2)

接上一篇文章继续分析文件nova/api/openstack/compute/servers.py中类ServersController中的create()函数。

        self._create_by_func_list(server_dict, create_kwargs, body)

        availability_zone = create_kwargs.pop("availability_zone", None)

        if api_version_request.is_supported(req, min_version='2.52'):
            create_kwargs['tags'] = server_dict.get('tags')

        helpers.translate_attributes(helpers.CREATE,
                                     server_dict, create_kwargs)

        target = {
            'project_id': context.project_id,
            'user_id': context.user_id,
            'availability_zone': availability_zone}
        context.can(server_policies.SERVERS % 'create', target)

        # TODO(Shao He, Feng) move this policy check to os-availability-zone
        # extension after refactor it.
        parse_az = self.compute_api.parse_availability_zone
        try:
            availability_zone, host, node = parse_az(context,
                                                     availability_zone)
        except exception.InvalidInput as err:
            raise exc.HTTPBadRequest(explanation=six.text_type(err))
        if host or node:
            context.can(server_policies.SERVERS % 'create:forced_host', {})

        min_compute_version = service_obj.get_minimum_version_all_cells(
            nova_context.get_admin_context(), ['nova-compute'])
        supports_device_tagging = (min_compute_version >=
                                   DEVICE_TAGGING_MIN_COMPUTE_VERSION)

       从create_kwargs中获取availability_zone,在本实例中,availability_zone位空。如果api的版本大于2.52,则从server中获取tags,在本实例中,也为空。

       helpers.translate_attributes()函数继续从用户请求中提取变量,如access_ip_v4,函数在文件nova/api/openstack/compute/helpers.py中定义,在本实例中,改函数中提取的变量全都为空。

       接下来定义变量target,其中包含project_id,user_id和availability_zone,在本实例中project_id的值为5043d96c15f541ba9deb29e3850bb458,user_id的值为0fdce610fa2544998cd340e90c2eda96,availability_zone为空。

       context.can(server_policies.SERVERS % 'create', target),根据网上查阅的资料说是对用户的执行权限进行验证,server_policies.SERVERS的的定义在nova/policies/servers.py文件中,policies目录中的函数与policy策略相关,通过/etc/nova/policy.json中定义的规则来执行各种操作策略,即执行某个操作的用户需要具有什么样的身份,以下为文件policy.json中定义的两条规则,规定请求需求启动或关闭的用户必须是admin或是虚拟机的属主。

   "os_compute_api:servers:start": "rule:admin_or_owner",
    "os_compute_api:servers:stop": "rule:admin_or_owner",

      接下来调用nova/compute/api.py文件中的parse_availability_zone()函数获取availability_zone, host, node,该函数的定义如下:

        
    @staticmethod
    def parse_availability_zone(context, availability_zone):
        # NOTE(vish): We have a legacy hack to allow admins to specify hosts
        #             via az using az:host:node. It might be nice to expose an
        #             api to specify specific hosts to force onto, but for
        #             now it just supports this legacy hack.
        # NOTE(deva): It is also possible to specify az::node, in which case
        #             the host manager will determine the correct host.
        forced_host = None
        forced_node = None 
        if availability_zone and ':' in availability_zone:
            c = availability_zone.count(':')
            if c == 1:
                availability_zone, forced_host = availability_zone.split(':')
            elif c == 2:
                if '::' in availability_zone:
                    availability_zone, forced_node = \
                            availability_zone.split('::')
                else:
                    availability_zone, forced_host, forced_node = \
                            availability_zone.split(':')
            else:
                raise exception.InvalidInput(
                        reason="Unable to parse availability_zone")

        if not availability_zone:
            availability_zone = CONF.default_schedule_zone

        return availability_zone, forced_host, forced_node

       在本实例中,availability_zone将被设置在配置文件中定义的默认值,host和node为空。

       继续分析类ServersController中的create()函数,接下来的两行设置变量supports_device_tagging的值,暂时还不知道这个变量的作用,create()函数的后续代码如下:

        block_device_mapping = create_kwargs.get("block_device_mapping")
        # TODO(Shao He, Feng) move this policy check to os-block-device-mapping
        # extension after refactor it.
        if block_device_mapping:
            context.can(server_policies.SERVERS % 'create:attach_volume',
                        target)
            for bdm in block_device_mapping:
                if bdm.get('tag', None) and not supports_device_tagging:
                    msg = _('Block device tags are not yet supported.')
                    raise exc.HTTPBadRequest(explanation=msg)

        image_uuid = self._image_from_req_data(server_dict, create_kwargs)

       从用户传递过来的参数中获取block_device_mapping的值,在本实例中为空,代码image_uuid = self._image_from_req_data(server_dict, create_kwargs)为获取image_uuid,在本实例中,该值为af711ee1-dacd-435b-9968-798bf7244bb0。继续分析ServersController中的create()函数中的代码。

        # NOTE(cyeoh): Although upper layer can set the value of
        # return_reservation_id in order to request that a reservation
        # id be returned to the client instead of the newly created
        # instance information we do not want to pass this parameter
        # to the compute create call which always returns both. We use
        # this flag after the instance create call to determine what
        # to return to the client
        return_reservation_id = create_kwargs.pop('return_reservation_id',
                                                  False)

        requested_networks = server_dict.get('networks', None)

        if requested_networks is not None:
            requested_networks = self._get_requested_networks(
                requested_networks, supports_device_tagging)

        # Skip policy check for 'create:attach_network' if there is no
        # network allocation request.
        if requested_networks and len(requested_networks) and \
                not requested_networks.no_allocate:
            context.can(server_policies.SERVERS % 'create:attach_network',
                        target)

          获取变量return_reservation_id和requested_networks的值,如果requested_networks不为空,则需要做权限验证,本实例中,这连个变量均为空。继续分析ServersController中的create()函数中的代码。

        flavor_id = self._flavor_id_from_req_data(body)
        try:
            inst_type = flavors.get_flavor_by_flavor_id(
                    flavor_id, ctxt=context, read_deleted="no")

            (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)
        except (exception.QuotaError,
                exception.PortLimitExceeded) as error:
            raise exc.HTTPForbidden(
                explanation=error.format_message())
        except exception.ImageNotFound:
            msg = _("Can not find requested image")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.KeypairNotFound:
            msg = _("Invalid key_name provided.")
            raise exc.HTTPBadRequest(explanation=msg)
        except exception.ConfigDriveInvalidValue:
            msg = _("Invalid config_drive provided.")
            raise exc.HTTPBadRequest(explanation=msg)
        except (exception.BootFromVolumeRequiredForZeroDiskFlavor,
                exception.ExternalNetworkAttachForbidden) as error:
            raise exc.HTTPForbidden(explanation=error.format_message())
        except messaging.RemoteError as err:
            msg = "%(err_type)s: %(err_msg)s" % {'err_type': err.exc_type,
                                                 'err_msg': err.value}
            raise exc.HTTPBadRequest(explanation=msg)
        except UnicodeDecodeError as error:
            msg = "UnicodeError: %s" % error
            raise exc.HTTPBadRequest(explanation=msg)
        except (exception.CPUThreadPolicyConfigurationInvalid,
                exception.ImageNotActive,
                exception.ImageBadRequest,
                exception.ImageNotAuthorized,

       这段代码首先通过调用本类中的_flavor_id_from_req_data()获取变量flavor_id的值,在本实例中为2,并通过flavor_id获取flavor的内容,flavors.get_flavor_by_flavor_id在nova/compute/flavors.py文件中定义。flavor指定了虚拟机的配置,即配置几个虚拟CPU,多少内存容量,多少硬盘容量。

     接下来调用nova/compute/api.py文件中的类API中的create()函数。在后续的文章中,将继续分析类API中的create()函数。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值