热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Novaclient源码分析---novalist命令

个人见解,可能会有错误。刚刚开始学习nova,就先从api入手学习吧。1、D:\代码\python-novaclient\python-novaclient\novaclient\v1_

个人见解,可能会有错误。刚刚开始学习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 = {
            '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 = {}
    #formatters 字典的关键字
    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)
    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 的区别还不太清楚,先写到这里。下边实战加打印追踪一下看看具体流程。




推荐阅读
author-avatar
mobiledu2502855757
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有