nova API代码解析之----extension机制(未完成)

#声明: 自己原创草书,纯属爱好。

为记录自己学习历程,学浅,难免错误,欢迎批评指正。

如需转载,请标明出处。


继续上篇博客问题,#nova show <server-id>并没有明显调用security groups,那其中信息是从哪里来的呢?

#nova show <server-id>

+--------------------------------------+----------------------------------------------------------------+
| Property                             | Value                                                          |
+--------------------------------------+----------------------------------------------------------------+
| OS-DCF:diskConfig                    | AUTO                                                           |
| OS-EXT-AZ:availability_zone          | nova                                                           |
| OS-EXT-SRV-ATTR:host                 | park-ThinkPad-T420                                             |
| OS-EXT-SRV-ATTR:hypervisor_hostname  | park-ThinkPad-T420                                             |
| OS-EXT-SRV-ATTR:instance_name        | instance-00000003                                              |
| OS-EXT-STS:power_state               | 1                                                              |
| OS-EXT-STS:task_state                | -                                                              |
| OS-EXT-STS:vm_state                  | active                                                         |
| OS-SRV-USG:launched_at               | 2015-05-11T07:14:35.000000                                     |
| OS-SRV-USG:terminated_at             | -                                                              |
| accessIPv4                           |                                                                |
| accessIPv6                           |                                                                |
| config_drive                         | True                                                           |
| created                              | 2015-05-11T07:14:31Z                                           |
| flavor                               | m1.nano (42)                                                   |
| hostId                               | ff03327555887251b281acf0eac8c71d920efd27171b0813b7778ad6       |
| id                                   | 33b937f9-2785-4fe0-8f88-6474ff50f7bb                           |
| image                                | cirros-0.3.4-x86_64-uec (16f62e95-57b0-4ddd-88ee-2b063ce5f1e3) |
| key_name                             | -                                                              |
| metadata                             | {}                                                             |
| name                                 | vm1                                                            |
| os-extended-volumes:volumes_attached | []                                                             |
| private network                      | 10.0.0.2                                                       |
| progress                             | 0                                                              |
<span style="color:#ff0000;">| security_groups                      | default                                                        |</span>
| status                               | ACTIVE                                                         |
| tenant_id                            | ecb571eb456242f1af7e37c5190382bd                               |
| updated                              | 2015-05-11T07:14:35Z                                           |
| user_id                              | 722f205503d64644b53e22923d388f25                               |
+--------------------------------------+----------------------------------------------------------------+

nova show 对应会调用nova REST API 中api/openstack/compute/servers.py中Controller.show(),我们就来看看这里面的逻辑关系。

# vim api/openstack/compute/servers.py

    def show(self, req, id):
        """Returns server details by server id."""
        context = req.environ['nova.context']
        instance = self._get_server(context, req, id)
        return self._view_builder.show(req, instance)
直接调用了view_builder.show(),这个view_builder在哪里呢?如下。

#vim api/openstack/compute/views/servers.py

    def show(self, request, instance):
        """Detailed view of a single instance."""
        ip_v4 = instance.get('access_ip_v4')
        ip_v6 = instance.get('access_ip_v6')
        server = {
            "server": {
                "id": instance["uuid"],
                "name": instance["display_name"],
                "status": self._get_vm_status(instance),
                "tenant_id": instance.get("project_id") or "",
                "user_id": instance.get("user_id") or "",
                "metadata": self._get_metadata(instance),
                "hostId": self._get_host_id(instance) or "",
                "image": self._get_image(request, instance),
                "flavor": self._get_flavor(request, instance),
                "created": timeutils.isotime(instance["created_at"]),
                "updated": timeutils.isotime(instance["updated_at"]),
                "addresses": self._get_addresses(request, instance),
                "accessIPv4": str(ip_v4) if ip_v4 is not None else '',
                "accessIPv6": str(ip_v6) if ip_v6 is not None else '',
                "links": self._get_links(request,
                                         instance["uuid"],
                                         self._collection_name),
            },
        }
        if server["server"]["status"] in self._fault_statuses:
            _inst_fault = self._get_fault(request, instance)
            if _inst_fault:
                server['server']['fault'] = _inst_fault

        if server["server"]["status"] in self._progress_statuses:
            server["server"]["progress"] = instance.get("progress", 0)

        return server
这里组装了各种server信息,但是并没有security-groups相关调用。

代码追踪到这里,似乎陷入了一个悖论,单纯API中server.show()并没有返回securitygroups信息,但是从nova client端调用能够得到securitygroups信息,中间的这个缺失从哪里来的呢?先看看client端的信息

# vim novaclient/v2/shell.py

def _print_server(cs, args, server=None):
    ...
    if not server:
        server = _find_server(cs, args.server)
    ....

    if 'security_groups' in info:
        # when we have multiple nics the info will include the
        # security groups N times where N == number of nics. Be nice
        # and only display it once.
        info['security_groups'] = ', '.join(
            sorted(set(group['name'] for group in info['security_groups'])))

的确有securitygroups信息。仔细回顾一下整个过程似乎没有疏漏....只剩下extension似乎有可以怀疑的地方。


回头重新看extension机制,从最基础wsgi.Resource类看起,在stack函数的调用过程中,必须经过_process_stack,而这里第一步就是处理extension

    def _process_stack(self, request, action, action_args,
                       content_type, body, accept):
        """Implement the processing stack."""

        # Get the implementing method
        try:
            meth, extensions = self.get_method(request, action,
                                               content_type, body)
其中meth是指当前request所指向的操作(Controller.show of nova.api.openstack.compute.servers.Controller object),而extensions表示在当前操作的对象(servers对象)上其他挂载的extensions具有相同名字(show)的操作,具体为

[<bound method ServerDiskConfigController.show of <nova.api.openstack.compute.contrib.disk_config.ServerDiskConfigController object at 0x7f454d1d9390>>, 
<bound method ExtendedAZController.show of <nova.api.openstack.compute.contrib.extended_availability_zone.ExtendedAZController object at 0x7f454ce7d790>>, 
[bound method ExtendedIpsController.show of <nova.api.openstack.compute.contrib.extended_ips.ExtendedIpsController object at 0x7f454ce7d890>>, 
<bound method ExtendedIpsMacController.show of <nova.api.openstack.compute.contrib.extended_ips_mac.ExtendedIpsMacController object at 0x7f454ce91390>>, 
<bound method ExtendedServerAttributesController.show of <nova.api.openstack.compute.contrib.extended_server_attributes.ExtendedServerAttributesController object at 0x7f454ce91410>>, 
<bound method ExtendedStatusController.show of <nova.api.openstack.compute.contrib.extended_status.ExtendedStatusController object at 0x7f454ce91490>>, 
<bound method ServerUsageController.show of <nova.api.openstack.compute.contrib.server_usage.ServerUsageController object at 0x7f454ce91b90>>, 
<bound method Controller.show of <nova.api.openstack.compute.contrib.config_drive.Controller object at 0x7f454ce96250>>, 
<bound method ExtendedVolumesController.show of 
<nova.api.openstack.compute.contrib.extended_volumes.ExtendedVolumesController object at 0x7f454d202210>>, 
<bound method Controller.show of <nova.api.openstack.compute.contrib.hide_server_addresses.Controller object at 0x7f454ce2cdd0>>, 
<bound method Controller.show of <nova.api.openstack.compute.contrib.keypairs.Controller object at 0x7f454ce2cc10>>, 
<bound method SecurityGroupsOutputController.show of <nova.api.openstack.compute.contrib.security_groups.SecurityGroupsOutputController object at 0x7f454ce3a5d0>>]

接下来我会想,这些extensions是如何注册到这里的呢?不着急,后面慢慢说明,先继续往下看_process_stack。

        if not response:
            try:
                with ResourceExceptionHandler():
                    action_result = self.dispatch(meth, request, action_args)
            except Fault as ex:
                response = ex

这里即是处理client调用本身,本例中即为servers.show(), 如果没有错误,继续往下执行post_process_extensions

                # Process post-processing extensions
                response = self.post_process_extensions(post, resp_obj,
                                                        request, action_args)

    def post_process_extensions(self, extensions, resp_obj, request,
                                action_args):
        for ext in extensions:
            response = None
            if inspect.isgenerator(ext):
                # If it's a generator, run the second half of
                # processing
                try:
                    with ResourceExceptionHandler():
                        response = ext.send(resp_obj)
                except StopIteration:
                    # Normal exit of generator
                    continue
                except Fault as ex:
                    response = ex
            else:
                # Regular functions get post-processing...
                try:
                    with ResourceExceptionHandler():
                        response = ext(req=request, resp_obj=resp_obj,
                                       **action_args)
                except exception.VersionNotFoundForAPIMethod:
                    # If an attached extension (@wsgi.extends) for the
                    # method has no version match its not an error. We
                    # just don't run the extends code
                    continue
                except Fault as ex:
                    response = ex

            # We had a response...
            if response:
                return response

        return None
看到这里,柳暗花明,真正执行的extensions就是在这里,这里将上文提到的在当前操作的对象(servers对象)上其他挂载的extensions具有相同名字(show)的extensions都执行一遍。作为返回数据反馈给调用者。


到这里,我们明白了为什么nova show <server-id>会有很多的extensions信息在里面,那么问题来了....

这些extensions是什么时候注册到servers这个对象上的呢?










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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值