个人见解,可能会有错误。刚刚开始学习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-11-05 15:21:17