novaclient代码解析之----novaclient创建过程
来源:互联网 发布:数据可视化培训 编辑:程序博客网 时间:2024/06/06 08:44
nova --debug list
1. 在已经配置好环境变量的终端中,调用过程,可见首先经过认证过程,在获取合法得token之后调用Nova API 中server/detail来获取各个server list.
park@park-ThinkPad-T420:~/openstack/devstack$ nova --debug listDEBUG (session:186) REQ: curl -g -i --cacert "/opt/stack/data/CA/int-ca/ca-chain.pem" -X GET http://localhost:5000/v2.0 -H "Accept: application/json" -H "User-Agent: python-keystoneclient"RESP BODY: {"version": {"status": "stable", "updated": "2014-04-17T00:00:00Z", "media-types": [{"base": "application/json", "type": "application/vnd.openstack.identity-v2.0+json"}], "id": "v2.0", "links": [{"href": "http://localhost:5000/v2.0/", "rel": "self"}, {"href": "http://docs.openstack.org/", "type": "text/html", "rel": "describedby"}]}}DEBUG (session:186) REQ: curl -g -i --cacert "/opt/stack/data/CA/int-ca/ca-chain.pem" -X GET http://xxxxx:8774/v2/e46fc3bb07da4987831fc4fe65d532ea/servers/detail -H "User-Agent: python-novaclient" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}067cafad6460a7d21af1f66c4711c78d666d6866"RESP BODY: {"servers": []}+----+------+--------+------------+-------------+----------+| ID | Name | Status | Task State | Power State | Networks |+----+------+--------+------------+-------------+----------++----+------+--------+------------+-------------+----------+
2. novaclient在哪里呢?他是怎么运行起来的呢?代码是最好的答案。
$ vim /usr/local/bin/nova
1 #!/usr/bin/python 2 3 # -*- coding: utf-8 -*- 4 import re 5 import sys 6 7 from novaclient.shell import main 8 ...见第7行,继续追踪novaclient.shell.main
$ vim /home/park/python-novaclient/novaclient/shell.py,
813 def main():814 try:815 argv = [encodeutils.safe_decode(a) for a in sys.argv[1:]]816 OpenStackComputeShell().main(argv)816行,继续找这个main method, 还好继续在这个文件中....
516 def main(self, argv):517 # Parse args once to find version and debug settings518 parser = self.get_base_parser()519 (options, args) = parser.parse_known_args(argv)520 self.setup_debugging(options.debug)...靠谱了,开始解析变量和参数了。没错,这里就是novaclient真正的入口。
按照上面的调用关系,我关心两个问题:
1. novaclient是如何根据环境变量和参数进行用户认证的?
2. novaclient各种具体命令是如何和nova API进行交互的呢?
第一个用户认证问题这里不想详细描述,有兴趣同学可以利用下面命令逐一测试
在一个未设置相关环境变量得终端中输入
$ nova --debug --os-username abc --os-project-name 123 --os-auth-url http://localhost:5000/v2.0 list
正常情况下应该会有如下错误,不再一一阐述。
Namespace(all_tenants=0, bypass_url='', debug=True, deleted=False, endpoint_type='publicURL', fields=None, flavor=None, func=<function do_list at 0x7fa3fd8856e0>, help=False, host=None, image=None, insecure=False, instance_name=None, ip=None, ip6=None, minimal=False, name=None, os_auth_system='', os_auth_token='', os_auth_url=u'http://<span style="font-family: Arial, Helvetica, sans-serif;">localhost</span><span style="font-family: Arial, Helvetica, sans-serif;">:5000/v2.0', os_cacert=None, os_cache=False, os_cert=None, os_compute_api_version='1.1', os_domain_id=None, os_domain_name=None, os_key=None, os_password='', os_project_domain_id=None, os_project_domain_name=None, os_project_id=None, os_project_name=u'123', os_region_name='', os_tenant_id='', os_tenant_name='', os_trust_id=None, os_user_domain_id=None, os_user_domain_name=None, os_user_id=None, os_username=u'abc', reservation_id=None, service_name='', service_type=None, sort=None, status=None, tenant=None, timeout=600, timings=False, user=None, volume_service_name='')</span>OS Password: DEBUG (session:186) REQ: curl -g -i -X GET http://<span style="font-family: Arial, Helvetica, sans-serif;">localhost</span>:5000/v2.0 -H "Accept: application/json" -H "User-Agent: python-keystoneclient"INFO (connectionpool:188) Starting new HTTP connection (1): <span style="font-family: Arial, Helvetica, sans-serif;">localhost</span>DEBUG (connectionpool:362) "GET /v2.0 HTTP/1.1" 200 339DEBUG (session:214) RESP: [200] content-length: 339 vary: X-Auth-Token keep-alive: timeout=5, max=100 server: Apache/2.4.7 (Ubuntu) connection: Keep-Alive date: Wed, 28 Jan 2015 08:22:41 GMT content-type: application/json RESP BODY: {"version": {"status": "stable", "updated": "2014-04-17T00:00:00Z", "media-types": [{"base": "application/json", "type": "application/vnd.openstack.identity-v2.0+json"}], "id": "v2.0", "links": [{"href": "http://localhost:5000/v2.0/", "rel": "self"}, {"href": "http://docs.openstack.org/", "type": "text/html", "rel": "describedby"}]}}DEBUG (v2:76) Making authentication request to http://localhost:5000/v2.0/tokensDEBUG (connectionpool:362) "POST /v2.0/tokens HTTP/1.1" 401 136DEBUG (session:377) Request returned failure status: 401DEBUG (shell:910) Authentication failure: Could not find user: abc (Disable debug mode to suppress these details.) (HTTP 401)Traceback (most recent call last): File "/opt/stack/python-novaclient/novaclient/shell.py", line 907, in main OpenStackComputeShell().main(argv) File "/opt/stack/python-novaclient/novaclient/shell.py", line 834, in main args.func(self.cs, args) File "/opt/stack/python-novaclient/novaclient/v1_1/shell.py", line 1377, in do_list sort_dirs=sort_dirs) File "/opt/stack/python-novaclient/novaclient/v1_1/servers.py", line 620, in list return self._list("/servers%s%s" % (detail, query_string), "servers") File "/opt/stack/python-novaclient/novaclient/base.py", line 66, in _list _resp, body = self.api.client.get(url) File "/opt/stack/python-keystoneclient/keystoneclient/adapter.py", line 130, in get return self.request(url, 'GET', **kwargs) File "/opt/stack/python-novaclient/novaclient/client.py", line 152, in request **kwargs) File "/opt/stack/python-keystoneclient/keystoneclient/adapter.py", line 166, in request resp = super(LegacyJsonAdapter, self).request(*args, **kwargs) File "/opt/stack/python-keystoneclient/keystoneclient/adapter.py", line 89, in request return self.session.request(url, method, **kwargs) File "/opt/stack/python-keystoneclient/keystoneclient/utils.py", line 318, in inner return func(*args, **kwargs) File "/opt/stack/python-keystoneclient/keystoneclient/session.py", line 298, in request token = self.get_token(auth) File "/opt/stack/python-keystoneclient/keystoneclient/session.py", line 577, in get_token _("Authentication failure: %s") % exc)AuthorizationFailure: Authentication failure: Could not find user: abc (Disable debug mode to suppress these details.) (HTTP 401)ERROR (AuthorizationFailure): Authentication failure: Could not find user: abc (Disable debug mode to suppress these details.) (HTTP 401)
继续看main函数,
756 self.cs = client.Client(757 options.os_compute_api_version,758 os_username, os_password, os_tenant_name,759 tenant_id=os_tenant_id, user_id=os_user_id,760 auth_url=os_auth_url, insecure=insecure,761 region_name=os_region_name, endpoint_type=endpoint_type,762 extensions=self.extensions, service_type=service_type,763 service_name=service_name, auth_system=os_auth_system,764 auth_plugin=auth_plugin, auth_token=auth_token,765 volume_service_name=volume_service_name,766 timings=args.timings, bypass_url=bypass_url,767 os_cache=os_cache, http_log_debug=options.debug,768 cacert=cacert, timeout=timeout,769 session=keystone_session, auth=keystone_auth)770
一直到这里之前,novaclient都在纠缠一些变量的获取,这里是生成了一个Client的对象,这个对象是干嘛的呢?
$ vim /home/park/python-novaclient/novaclient/client.py,
def get_client_class(version): version_map = { '1.1': 'novaclient.v2.client.Client', '2': 'novaclient.v2.client.Client', '3': 'novaclient.v2.client.Client', } try: client_path = version_map[str(version)] except (KeyError, ValueError): msg = _("Invalid client version '%(version)s'. must be one of: " "%(keys)s") % {'version': version, 'keys': ', '.join(version_map.keys())} raise exceptions.UnsupportedVersion(msg) return importutils.import_class(client_path)def Client(version, *args, **kwargs): client_class = get_client_class(version) return client_class(*args, **kwargs)原来是为了找到和version相匹配的Client,所有的都指向了V2,我们来看看这个v2.client都干了什么。
$ vim /home/park/python-novaclient/novaclient/V2/client.py,
def __init__(self, username=None, api_key=None, project_id=None, auth_url=None, insecure=False, timeout=None, proxy_tenant_id=None, proxy_token=None, region_name=None, endpoint_type='publicURL', extensions=None, service_type='compute', service_name=None, volume_service_name=None, timings=False, bypass_url=None, os_cache=False, no_cache=True, http_log_debug=False, auth_system='keystone', auth_plugin=None, auth_token=None, cacert=None, tenant_id=None, user_id=None, connection_pool=False, session=None, auth=None, **kwargs): """ :param str username: Username :param str api_key: API Key :param str project_id: Project ID :param str auth_url: Auth URL :param bool insecure: Allow insecure :param float timeout: API timeout, None or 0 disables :param str proxy_tenant_id: Tenant ID :param str proxy_token: Proxy Token :param str region_name: Region Name :param str endpoint_type: Endpoint Type :param str extensions: Exensions :param str service_type: Service Type :param str service_name: Service Name :param str volume_service_name: Volume Service Name :param bool timings: Timings :param str bypass_url: Bypass URL :param bool os_cache: OS cache :param bool no_cache: No cache :param bool http_log_debug: Enable debugging for HTTP connections :param str auth_system: Auth system :param str auth_plugin: Auth plugin :param str auth_token: Auth token :param str cacert: cacert :param str tenant_id: Tenant ID :param str user_id: User ID :param bool connection_pool: Use a connection pool :param str session: Session :param str auth: Auth """ # FIXME(comstud): Rename the api_key argument above when we # know it's not being used as keyword argument # NOTE(cyeoh): In the novaclient context (unlike Nova) the # project_id is not the same as the tenant_id. Here project_id # is a name (what the Nova API often refers to as a project or # tenant name) and tenant_id is a UUID (what the Nova API # often refers to as a project_id or tenant_id). password = api_key self.projectid = project_id self.tenant_id = tenant_id self.user_id = user_id self.flavors = flavors.FlavorManager(self) self.flavor_access = flavor_access.FlavorAccessManager(self) self.images = images.ImageManager(self) self.limits = limits.LimitsManager(self) self.servers = servers.ServerManager(self) self.versions = versions.VersionManager(self) # extensions self.agents = agents.AgentsManager(self) self.dns_domains = floating_ip_dns.FloatingIPDNSDomainManager(self) self.dns_entries = floating_ip_dns.FloatingIPDNSEntryManager(self) self.cloudpipe = cloudpipe.CloudpipeManager(self) self.certs = certs.CertificateManager(self) self.floating_ips = floating_ips.FloatingIPManager(self) self.floating_ip_pools = floating_ip_pools.FloatingIPPoolManager(self) self.fping = fping.FpingManager(self) self.volumes = volumes.VolumeManager(self) self.volume_snapshots = volume_snapshots.SnapshotManager(self) self.volume_types = volume_types.VolumeTypeManager(self) self.keypairs = keypairs.KeypairManager(self) self.networks = networks.NetworkManager(self) self.quota_classes = quota_classes.QuotaClassSetManager(self) self.quotas = quotas.QuotaSetManager(self) self.security_groups = security_groups.SecurityGroupManager(self) self.security_group_rules = \ security_group_rules.SecurityGroupRuleManager(self) self.security_group_default_rules = \ security_group_default_rules.SecurityGroupDefaultRuleManager(self) self.usage = usage.UsageManager(self) self.virtual_interfaces = \ virtual_interfaces.VirtualInterfaceManager(self) self.aggregates = aggregates.AggregateManager(self) self.hosts = hosts.HostManager(self) self.hypervisors = hypervisors.HypervisorManager(self) self.hypervisor_stats = hypervisors.HypervisorStatsManager(self) self.services = services.ServiceManager(self) self.fixed_ips = fixed_ips.FixedIPsManager(self) self.floating_ips_bulk = floating_ips_bulk.FloatingIPBulkManager(self) self.os_cache = os_cache or not no_cache self.availability_zones = \ availability_zones.AvailabilityZoneManager(self) self.server_groups = server_groups.ServerGroupsManager(self) # Add in any extensions... if extensions: for extension in extensions: if extension.manager_class: setattr(self, extension.name, extension.manager_class(self)) self.client = client._construct_http_client( username=username, password=password, user_id=user_id, project_id=project_id, tenant_id=tenant_id, auth_url=auth_url, auth_token=auth_token, insecure=insecure, timeout=timeout, auth_system=auth_system, auth_plugin=auth_plugin, proxy_token=proxy_token, proxy_tenant_id=proxy_tenant_id, region_name=region_name, endpoint_type=endpoint_type, service_type=service_type, service_name=service_name, volume_service_name=volume_service_name, timings=timings, bypass_url=bypass_url, os_cache=self.os_cache, http_log_debug=http_log_debug, cacert=cacert, connection_pool=connection_pool, session=session, auth=auth, **kwargs)构建基础信息,extension信息等,extension信息指向了一些manager,这里以后再阐述。
最后,通过self.client = client._construct_http_client创建了一个基于http的client,到这里client已经具备了http和api通信的能力了。
但是仍然没有解决上面提到的第二个问题,具体命令是如何执行的呢?回到novaclient/shell.py中:
在创建Client之后会找到下面一小行代码
args.func(self.cs, args)这里才是真正执行具体命令的接口。
至此,一个完整的Client算是构建完成。
- novaclient代码解析之----novaclient创建过程
- novaclient代码分析(1)
- novaclient代码解析之---通过nova show <server-id>命令解析Nova client与Nova API之间的调用关系
- openstack nova 源码解析 — Nova API 执行过程从(novaclient到Action)
- 《openstack-nova》use-novaclient 创建虚拟机(createvms.py)
- novaclient源码结构
- novaclient增加功能
- novaclient源码分析
- novaclient中的源码简析
- 如何扩展openstack python novaclient
- openstack-horizon/novaclient源码分析
- novaclient的api调用流程与开发
- use python-novaclient to manage openstack vm
- novaclient的api调用流程与开发
- novaclient的api调用流程与开发
- python-novaclient源码分析-M版本
- python安装suax调用webservice,安装novaclient调用openstack
- Horizon 源码阅读(四)—— 调用Novaclient流程
- Simplify Path
- 监督学习_最近邻算法(KNN, k-近邻算法)
- 在sublime text2\3中安装svn插件
- Shellcode的编写
- vc6.0 不能打开文件的问题
- novaclient代码解析之----novaclient创建过程
- JS中使用JSTL
- python知识点(一):python检测代码效率常用方法
- HDU 3861 Prison Breake 状态压缩dp+BFS+二分答案
- 从房东那儿迁来的网线如何用路由器
- 程序员少走弯路的14个忠告
- 架构师害怕程序员知道的十项技能
- 注册信息验证时的用户体验提升
- 系统调用的实现原理