ironicclient是一个cli工具,用来和用户交互的。

首先写一个简单的例子,获取ironic所有的node节点:

from ironicclient import client

if __name__ == '__main__':
kwargs = {'os_username': 'ironic',
'os_password': 'IRONIC_PASSWORD',
'os_auth_url': 'http://192.168.1.72:5000/',
'os_tenant_name': 'services'}
ironic = client.get_client(1, **kwargs)
print ironic.node.list()

这里我们创建了一个client对象,这个对象是通过client类的get_client方法返回的,

这是一个工厂模式,下面看下get_client方法:

def get_client(api_version, os_auth_token=None, ironic_url=None,
os_username=None, os_password=None, os_auth_url=None,
os_project_id=None, os_project_name=None, os_tenant_id=None,
os_tenant_name=None, os_region_name=None,
os_user_domain_id=None, os_user_domain_name=None,
os_project_domain_id=None, os_project_domain_name=None,
os_service_type=None, os_endpoint_type=None,
insecure=None, timeout=None, os_cacert=None, ca_file=None,
os_cert=None, cert_file=None, os_key=None, key_file=None,
os_ironic_api_version=None, max_retries=None,
retry_interval=None, session=None, **ignored_kwargs):
os_service_type = os_service_type or 'baremetal'
os_endpoint_type = os_endpoint_type or 'publicURL'
project_id = (os_project_id or os_tenant_id)
project_name = (os_project_name or os_tenant_name)
kwargs = {
'os_ironic_api_version': os_ironic_api_version,
'max_retries': max_retries,
'retry_interval': retry_interval,
}
endpoint = ironic_url
cacert = os_cacert or ca_file
cert = os_cert or cert_file
key = os_key or key_file
if os_auth_token and endpoint:
kwargs.update({
'token': os_auth_token,
'insecure': insecure,
'ca_file': cacert,
'cert_file': cert,
'key_file': key,
'timeout': timeout,
})
elif os_auth_url:
auth_type = 'password'
auth_kwargs = {
'auth_url': os_auth_url,
'project_id': project_id,
'project_name': project_name,
'user_domain_id': os_user_domain_id,
'user_domain_name': os_user_domain_name,
'project_domain_id': os_project_domain_id,
'project_domain_name': os_project_domain_name,
}
if os_username and os_password:
auth_kwargs.update({
'username': os_username,
'password': os_password,
})
elif os_auth_token:
auth_type = 'token'
auth_kwargs.update({
'token': os_auth_token,
})
# Create new session only if it was not passed in
if not session:
loader = kaloading.get_plugin_loader(auth_type)
auth_plugin = loader.load_from_options(**auth_kwargs)
# Let keystoneauth do the necessary parameter conversions
session = kaloading.session.Session().load_from_options(
auth=auth_plugin, insecure=insecure, cacert=cacert,
cert=cert, key=key, timeout=timeout,
) exception_msg = _('Must provide Keystone credentials or user-defined '
'endpoint and token')
if not endpoint:
if session:
try:
# Pass the endpoint, it will be used to get hostname
# and port that will be used for API version caching. It will
# be also set as endpoint_override.
endpoint = session.get_endpoint(
service_type=os_service_type,
interface=os_endpoint_type,
region_name=os_region_name
)
except Exception as e:
raise exc.AmbiguousAuthSystem(
exception_msg + _(', error was: %s') % e)
else:
# Neither session, nor valid auth parameters provided
raise exc.AmbiguousAuthSystem(exception_msg) # Always pass the session
kwargs['session'] = session return Client(api_version, endpoint, **kwargs)

中间这一大串可以先不看,主要是认证的一些信息。在get_cleint函数结尾,调用了

Client() 方法作为返回值。这里传入了三个参数:

  • api_version
  • endpoint
  • **kwargs

其中api_version是1,endpoint是http://192.168.1.72:6385,kwargs保存了session的

信息:

{'os_ironic_api_version': None, 'session': <keystoneauth1.session.Session object at 0x2441690>, 'retry_interval': None, 'max_retries': None}

我们再来看看Client()方法的具体实现:

def Client(version, *args, **kwargs):
module = utils.import_versioned_module(version, 'client')
client_class = getattr(module, 'Client')
return client_class(*args, **kwargs)

这里module内容如下:

<module 'ironicclient.v1.client' from '/usr/lib/python2.7/site-packages/ironicclient/v1/client.pyc'>

后面的client_class使用反射的机制来获取Client类。简单的说就是调用文件

/usr/lib/python2.7/site-packages/ironicclient/v1/client.py中的

Client类,并返回其对象。

再来看下Client类的具体实现:

class Client(object):
def __init__(self, *args, **kwargs):
"""Initialize a new client for the Ironic v1 API."""
if kwargs.get('os_ironic_api_version'):
kwargs['api_version_select_state'] = "user"
else:
# If the user didn't specify a version, use a cached version if
# one has been stored
host, netport = http.get_server(args[0])
saved_version = filecache.retrieve_data(host=host, port=netport)
if saved_version:
kwargs['api_version_select_state'] = "cached"
kwargs['os_ironic_api_version'] = saved_version
else:
kwargs['api_version_select_state'] = "default"
kwargs['os_ironic_api_version'] = DEFAULT_VER self.http_client = http._construct_http_client(*args, **kwargs) self.chassis = chassis.ChassisManager(self.http_client)
self.node = node.NodeManager(self.http_client)
self.port = port.PortManager(self.http_client)
self.driver = driver.DriverManager(self.http_client)

可以看出Client类的chassis,node,port,driver属性都是对应类的manager。

先看看NodeManager的实现:

class NodeManager(base.CreateManager):
resource_class = Node
_creation_attributes = ['chassis_uuid', 'driver', 'driver_info',
'extra', 'uuid', 'properties', 'name']
_resource_name = 'nodes' def list(self, associated=None, maintenance=None, marker=None, limit=None,
detail=False, sort_key=None, sort_dir=None, fields=None,
provision_state=None, driver=None):
if limit is not None:
limit = int(limit) if detail and fields:
raise exc.InvalidAttribute(_("Can't fetch a subset of fields "
"with 'detail' set")) filters = utils.common_filters(marker, limit, sort_key, sort_dir,
fields)
if associated is not None:
filters.append('associated=%s' % associated)
if maintenance is not None:
filters.append('maintenance=%s' % maintenance)
if provision_state is not None:
filters.append('provision_state=%s' % provision_state)
if driver is not None:
filters.append('driver=%s' % driver) path = ''
if detail:
path += 'detail'
if filters:
path += '?' + '&'.join(filters) if limit is None:
return self._list(self._path(path), "nodes")
else:
return self._list_pagination(self._path(path), "nodes",
limit=limit)
...

我们看list方法,前面是一些过滤条件,因为我们没有穿limit参数,所有limit是None,

然后调用了_list()方法。这个是在父类里定义的。实现代码在:

/usr/lib/python2.7/site-packages/ironicclient/common/base.py

    def _list(self, url, response_key=None, obj_class=None, body=None):
resp, body = self.api.json_request('GET', url) if obj_class is None:
obj_class = self.resource_class data = self._format_body_data(body, response_key)
return [obj_class(self, res, loaded=True) for res in data if res]

我们可以看到,这里是发送了HTTP GET请求,然就将收到的数据格式化并返回。

这里的api是我们在前面传入的,使用http创建的一个client对象。

self.http_client = http._construct_http_client(*args, **kwargs)
... self.node = node.NodeManager(self.http_client)

python ironicclient源码分析的更多相关文章

  1. eos源码分析和应用(一)调试环境搭建

    转载自 http://www.limerence2017.com/2018/09/02/eos1/#more eos基于区块链技术实现的开源引擎,开发人员可以基于该引擎开发DAPP(分布式应用).下面 ...

  2. python multiprocessing 源码分析

    1. 文档是最先需要了解的,读完文档可能会有很多的意外的收获同时也会留下疑惑,对于一般的使用我觉得读完文档就差不多了,除非一些很有疑惑的地方你可能需要再深入的了解一下.我读文档的目的第一个就是为了找出 ...

  3. python slots源码分析

    上次总结Python3的字典实现后的某一天,突然开窍Python的__slots__的实现应该也是类似,于是翻了翻CPython的源码,果然如此! 关于在自定义类里面添加__slots__的效果,网上 ...

  4. Python SocketServer源码分析

    1      XXXServer 1.1      BaseSever 提供基础的循环等待请求的处理框架.使用serve_forever启动服务,使用shutdown停止.同时提供了一些可自行扩展的方 ...

  5. python SocketServer 源码分析

    附上原文链接: http://beginman.cn/python/2015/04/06/python-SocketServer/

  6. selenium3 + python - action_chains源码分析

    ActionChains简介 actionchains是selenium里面专门处理鼠标相关的操作如:鼠标移动,鼠标按钮操作,按键和上下文菜单(鼠标右键)交互.这对于做更复杂的动作非常有用,比如悬停和 ...

  7. Python之美[从菜鸟到高手]--urlparse源码分析

    urlparse是用来解析url格式的,url格式如下:protocol :// hostname[:port] / path / [;parameters][?query]#fragment,其中; ...

  8. [python] 基于词云的关键词提取:wordcloud的使用、源码分析、中文词云生成和代码重写

    1. 词云简介 词云,又称文字云.标签云,是对文本数据中出现频率较高的“关键词”在视觉上的突出呈现,形成关键词的渲染形成类似云一样的彩色图片,从而一眼就可以领略文本数据的主要表达意思.常见于博客.微博 ...

  9. Python源码分析(二) - List对象

    python中的高级特性之一就是内置了list,dict等.今天就先围绕列表(List)进行源码分析. Python中的List对象(PyListObject) Python中的的PyListObje ...

随机推荐

  1. Pandas系列(一)-Series详解

    一.初始Series Series 是一个带有 名称 和索引的一维数组,既然是数组,肯定要说到的就是数组中的元素类型,在 Series 中包含的数据类型可以是整数.浮点.字符串.Python对象等. ...

  2. RocketMQ_问题_启动控制台console报错,connect to <null> failed

    配置如图所示: 问题如图所示: 明明配置了nameserver参数为啥还是connect to null呢? 我的rocketmq部署在CentOS7虚拟机上,原来是没关闭防火墙,执行:systemc ...

  3. Linux性能优化实战:系统的swap变高(08)

    一.Swap 原理 前面提到,Swap 说白了就是把一块磁盘空间或者一个本地文件(以下讲解以磁盘为例),当成内存来使用.它包括换出和换入两个过程 1.所谓换出 就是把进程暂时不用的内存数据存储到磁盘中 ...

  4. SpringBoot系列: Pebble模板引擎

    ===============================Java 模板引擎选择===============================SpringBoot Starter项目向导中可选的J ...

  5. H5取经之路——HTML的基本标签

    一.head中的基本标签 1.HTML文档的结构:     a.<head>头部部分,b.<body>主体部分 <!DOCTYPE html> <!-- ↑为 ...

  6. 代码,java_web

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. sqlserver 获取所有表的字段类型等信息

    USE [MultipleAnalysisDataFY] GO /****** Object: View [dbo].[selectfieldtype] Script Date: 2018/11/7 ...

  8. “Django用户认证系统”学习资料收集

    首推追梦人物——Django用户认证系统 待续……

  9. Educational Codeforces Round 52 (Rated for Div. 2)

    题目链接 A. Vasya and Chocolate 题意 已知钱,价格,赠送规则求最多获得巧克力数 思路常规算即可 代码 #include <bits/stdc++.h> #defin ...

  10. codeblocks1712设置中文

    下载汉化包:百度网盘,密码:7rrz 下载后放到安装目录:D:\Program Files (x86)\CodeBlocks\share\CodeBlocks\locale\zh_CN(根据个人安装目 ...