Nova client源码分析---nova list命令

个人见解,可能会有错误。刚刚开始学习nova,就先从api入手学习吧。

1、D:\代码\python-novaclient\python-novaclient\novaclient\v1_1\shell.py,最上边怎么调用不太清楚了,先从这里开始。

def do_list(cs, args):
    """List active servers."""
    imageid = None
    flavorid = None
    #查找镜像
    if args.image:
        imageid = _find_image(cs, args.image).id
    #查找套餐类型
    if args.flavor:
        flavorid = _find_flavor(cs, args.flavor).id
    search_opts</span> = {
            'all_tenants': args.all_tenants,
            'reservation_id': args.reservation_id,
            'ip': args.ip,
            'ip6': args.ip6,
            'name': args.name,
            'image': imageid,
            'flavor': flavorid,
            'status': args.status,
            'tenant_id': args.tenant,  #租赁人id
            'host': args.host,
            'instance_name': args.instance_name}
    #过滤条件
    filters = {'flavor': lambda f: f['id'],
               'security_groups': utils._format_security_groups}
    #存放过滤后的结果
    formatters = {}
    <span style="font-family: Arial, Helvetica, sans-serif;">#formatters 字典的关键字</span>
    field_titles = []
    if args.fields:
        for field in args.fields.split(','):
            #让field 格式化成某种字符串
            field_title, formatter = utils._make_field_formatter(field,
                                                                 filters)
            field_titles.append(field_title)
            formatters[field_title] = formatter

    id_col = 'ID'

    #同一目录下 servers.py里面的list方法,下一个函数讲解这里。
    #这里的返回值是server 的列表
    servers = cs.servers.list(search_opts=search_opts)</span></strong>
    convert = [('OS-EXT-SRV-ATTR:host', 'host'),
               ('OS-EXT-STS:task_state', 'task_state'),
               ('OS-EXT-SRV-ATTR:instance_name', 'instance_name'),
               ('hostId', 'host_id')]
    _translate_keys(servers, convert)
    #这个columns 应该是列的意思,和打印有关吧。
    if field_titles:
        columns = [id_col] + field_titles
    else:
        columns = [id_col, 'Name', 'Status', 'Networks']
    formatters['Networks'] = utils._format_servers_list_networks
    #这里负责具体输出nova list 命令的输出。
    utils.print_list(servers, columns,
                     formatters, sortby_index=1)

2、D:\代码\python-novaclient\python-novaclient\novaclient\v1_1\servers.py  ---- ServerManager类中的list方法。

    def list(self, detailed=True, search_opts=None):
        """
        # detailed 负责是否返回详细服务器信息,reservation_id仅仅返回对应id的。
        Get a list of servers.
        Optional detailed returns details server info.
        Optional reservation_id only returns instances with that
        reservation_id.

        :rtype: list of :class:`Server`
        """
        #search_opt 的内容见上一个函数的绿色字体,是一个字典。
        if search_opts is None:
            search_opts = {}

        qparams = {}
        #这里吧search_opt 的字典内容拷贝到qparams
        for opt, val in search_opts.iteritems():
            if val:
                qparams[opt] = val
        
        #这里把我们的选项进行url编码,因为要发送http请求嘛
        query_string = "?%s" % urllib.urlencode(qparams) if qparams else ""

        detail = ""
        if detailed:
            detail = "/detail"
        #这里继续调用_list方法,该函数下边继续分析。这个函数第一个参数是url,第二个参数是response_key
        return self._list("/servers%s%s" % (detail, query_string), "servers")

3、D:\代码\python-novaclient\python-novaclient\novaclient\base.py ----- _list 方法

    def _list(self, url, response_key, obj_class=None, body=None):
        #根据body是否为空调用post或者get方法,这两个函数都调用一个函数,只不过传参不太一样---_cs_request
        if body:
            _resp, body = self.api.client.post(url, body=body)
        else:
            _resp, body = self.api.client.get(url)

        if obj_class is None:
            obj_class = self.resource_class
        
        #参考上边的传参,可以发现这个response_key的内容应该是“servers”
        #到这里我们获取了数据。
        data = body[response_key]
        # NOTE(ja): keystone returns values as list as {'values': [ ... ]}
        #           unlike other services which just return the list...
        #上边的注释讲的很清楚,如果data是个字典,具体的server的内容是里面的对应key='values'的字段值,结果是一个list
        if isinstance(data, dict):
            try:
                data = data['values']
            except KeyError:
                pass

        #这里没有仔细看了,最后一句话是返回结果。with语句和try finally 一样能够处理异常情况的上下文清理工作。
        with self.completion_cache('human_id', obj_class, mode="w"):
            with self.completion_cache('uuid', obj_class, mode="w"):
                return [obj_class(self, res, loaded=True)
                        for res in data if res]

4、D:\代码\python-novaclient\python-novaclient\novaclient\client.py ---- post

def post(self, url, **kwargs):
        return self._cs_request(url, 'POST', **kwargs)

5、D:\代码\python-novaclient\python-novaclient\novaclient\client.py ---- _cs_request
    # 客户端向服务端发送请求序列。
    def _cs_request(self, url, method, **kwargs):
        if not self.management_url:
            self.authenticate()

        # Perform the request once. If we get a 401 back then it
        # might be because the auth token expired, so try to
        # re-authenticate and try again. If it still fails, bail.
        try:
            #headers 如果没有这个关键就设置为空,然后给headers字典的属性 ‘X-Auth-Token’赋值
            kwargs.setdefault('headers', {})['X-Auth-Token'] = self.auth_token
            if self.projectid:
                kwargs['headers']['X-Auth-Project-Id'] = self.projectid

            #这里进一步发送消息。
            resp, body = self._time_request(self.management_url + url, method,
                                            **kwargs)
            return resp, body
        except exceptions.Unauthorized as e:
            try:
                self.authenticate()
                kwargs['headers']['X-Auth-Token'] = self.auth_token
                resp, body = self._time_request(self.management_url + url,
                                                method, **kwargs)
                return resp, body
            except exceptions.Unauthorized:
                raise e

6、D:\代码\python-novaclient\python-novaclient\novaclient\client.py ---- _time_request

    def _time_request(self, url, method, **kwargs):
        start_time = time.time()
        resp, body = self.request(url, method, **kwargs)
        self.times.append(("%s %s" % (method, url),
                           start_time, time.time()))
        return resp, body

7、D:\代码\python-novaclient\python-novaclient\novaclient\client.py ---- request

   def request(self, url, method, **kwargs):
        kwargs.setdefault('headers', kwargs.get('headers', {}))
        kwargs['headers']['User-Agent'] = self.USER_AGENT
        kwargs['headers']['Accept'] = 'application/json'
        if 'body' in kwargs:
            kwargs['headers']['Content-Type'] = 'application/json'
            kwargs['data'] = json.dumps(kwargs['body'])
            del kwargs['body']
        if self.timeout is not None:
            kwargs.setdefault('timeout', self.timeout)

        # 打印请求部分
        self.http_log_req((url, method,), kwargs)
        #这里发送http请求并得到相应的response,到此大功告成。
        resp =self.http.request(
            method,
            url,
            verify=self.verify_cert,
            **kwargs)
            
        #打印相应部分
        self.http_log_resp(resp)

        #检查响应的内容。
        if resp.text:
            # TODO(dtroyer): verify the note below in a requests context
            # NOTE(alaski): Because force_exceptions_to_status_code=True
            # httplib2 returns a connection refused event as a 400 response.
            # To determine if it is a bad request or refused connection we need
            # to check the body.  httplib2 tests check for 'Connection refused'
            # or 'actively refused' in the body, so that's what we'll do.
            if resp.status_code == 400:
                if ('Connection refused' in resp.text or
                    'actively refused' in resp.text):
                    raise exceptions.ConnectionRefused(resp.text)
            try:
                body = json.loads(resp.text)
            except ValueError:
                pass
                body = None
        else:
            body = None

        if resp.status_code >= 400:
            raise exceptions.from_response(resp, body, url, method)

        return resp, body

里面还有一些内容自己没搞清楚,以后再补充,do_list 最外边被谁调用还没有写进来, post 和 get 的区别还不太清楚,先写到这里。下边实战加打印追踪一下看看具体流程。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-25 17:40:22

Nova client源码分析---nova list命令的相关文章

nova api源码分析(一)

说明: 源码版本:H版 参考文档:http://www.choudan.net/2013/12/09/OpenStack-WSGI-APP%E5%AD%A6%E4%B9%A0.html 一.前奏 nova api本身作为一个WSGI服务器,对外提供HTTP请求服务,对内调用nova的其他模块响应相应的HTTP请求.分为两大部分,一是创建该服务器时加载的app,这个用来处理请求:一是服务器本身的启动与运行. 目录结构如下: 首先,nova api是作为一个WSGI服务,肯定要查看它的启动过程,查看

Docker Client源码分析(一)

主要内容: Docker Client在Docker中的定位,以及Docker Client源码的初步分析. 本文选取Docker拆分为DockerCE(社区版)和DockerEE(企业版)之后的Docker-CE的第一个稳定版本v17.06.0-ce. https://github.com/docker/docker-ce Docker背景: Docker Client是绝大部分用户使用Docker的入口,例如一次docker pull请求,需要经过很多层调用,如下图: Client创建一个d

nova api源码分析(二)

转载于:http://www.it165.net/pro/html/201407/17020.html (经过部分编辑) 一.使用到的库或组件如下: paste.deploy 用来解析/etc/nova/api-paste.ini文件,加载用于服务的wsgi app.它的功能有: 1.api-paste.ini中配置多个wsgi app,deploy可根据传入的app name加载指定的wsgi app: deploy.loadapp("config:/etc/nova/api-paste.in

Docker源码分析(二):Docker Client创建与命令执行

1. 前言 如今,Docker作为业界领先的轻量级虚拟化容器管理引擎,给全球开发者提供了一种新颖.便捷的软件集成测试与部署之道.在团队开发软件时,Docker可以提供可复用的运行环境.灵活的资源配置.便捷的集成测试方法以及一键式的部署方式.可以说,Docker的优势在简化持续集成.运维部署方面体现得淋漓尽致,它完全让开发者从持续集成.运维部署方面中解放出来,把精力真正地倾注在开发上. 然而,把Docker的功能发挥到极致,并非一件易事.在深刻理解Docker架构的情况下,熟练掌握Docker C

nova创建虚拟机源码分析系列之七 传入参数转换成内部id

上一篇博文将nova创建虚机的流程推进到了/compute/api.py中的create()函数,接下来就继续分析. 在分析之前简单介绍nova组件源码的架构.以conductor组件为例: 每个组件都会有这三个文件:api.py rpcapi.py manager.py. api.py              conductor实现自身功能的文件 rpcapi.py         conductor提供给其他组件通过消息队列调用的接口函数 manager.py    其他组件通过消息队列调

Docker源码分析之——Docker Client的启动与命令执行

在上文Docker源码分析之--Docker Daemon的启动 中,介绍了Docker Daemon进程的启动.Docker Daemon可以认为是一个Docker作为Server的运行载体,而真正发送关于docker container操作的请求的载体,在于Docker Client.本文从Docker源码的角度,分析Docker Client启动与执行请求的过程. Docker Client启动的流程与Docker Daemon启动的过程相仿.首先执行reexec.Init():随后解析f

Linux c 开发 - Memcached源码分析之命令解析(2)

前言 从我们上一章<Linux c 开发 - Memcached源码分析之基于Libevent的网络模型>我们基本了解了Memcached的网络模型.这一章节,我们需要详细解读Memcached的命令解析. 我们回顾上一章发现Memcached会分成主线程和N个工作线程.主线程主要用于监听accpet客户端的Socket连接,而工作线程主要用于接管具体的客户端连接. 主线程和工作线程之间主要通过基于Libevent的pipe的读写事件来监听,当有连接练上来的时候,主线程会将连接交个某一个工作线

docker stats 命令源码分析

本文是基于docker 1.10.3版本的源码,对docker stats命令进行源码分析,看看docker stats命令输出的数据是从cgroups fs中怎么怎么计算出来的. docker client相关代码入口可参考:/docker/docker/api/client/stats.go#141 docker daemon相关代码入口可参考:/docker/docker/daemon/daemon.go#1474 源码分析结果 Cpu数据: docker daemon会记录这次读取/sy

zeromq源码分析笔记之线程间收发命令(2)

在zeromq源码分析笔记之架构说到了zmq的整体架构,可以看到线程间通信包括两类,一类是用于收发命令,告知对象该调用什么方法去做什么事情,命令的结构由command_t结构体确定:另一类是socket_base_t实例与session的消息通信,消息的结构由msg_t确定.命令的发送与存储是通过mailbox_t实现的,消息的发送和存储是通过pipe_t实现的,这两个结构都会详细说到,今天先说一下线程间的收发命令. zeromq的线程可分为两类,一类是io线程,像reaper_t.io_thr