python ironicclient源码分析
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源码分析的更多相关文章
- eos源码分析和应用(一)调试环境搭建
		
转载自 http://www.limerence2017.com/2018/09/02/eos1/#more eos基于区块链技术实现的开源引擎,开发人员可以基于该引擎开发DAPP(分布式应用).下面 ...
 - python multiprocessing 源码分析
		
1. 文档是最先需要了解的,读完文档可能会有很多的意外的收获同时也会留下疑惑,对于一般的使用我觉得读完文档就差不多了,除非一些很有疑惑的地方你可能需要再深入的了解一下.我读文档的目的第一个就是为了找出 ...
 - python slots源码分析
		
上次总结Python3的字典实现后的某一天,突然开窍Python的__slots__的实现应该也是类似,于是翻了翻CPython的源码,果然如此! 关于在自定义类里面添加__slots__的效果,网上 ...
 - Python SocketServer源码分析
		
1 XXXServer 1.1 BaseSever 提供基础的循环等待请求的处理框架.使用serve_forever启动服务,使用shutdown停止.同时提供了一些可自行扩展的方 ...
 - python SocketServer 源码分析
		
附上原文链接: http://beginman.cn/python/2015/04/06/python-SocketServer/
 - selenium3 + python - action_chains源码分析
		
ActionChains简介 actionchains是selenium里面专门处理鼠标相关的操作如:鼠标移动,鼠标按钮操作,按键和上下文菜单(鼠标右键)交互.这对于做更复杂的动作非常有用,比如悬停和 ...
 - Python之美[从菜鸟到高手]--urlparse源码分析
		
urlparse是用来解析url格式的,url格式如下:protocol :// hostname[:port] / path / [;parameters][?query]#fragment,其中; ...
 - [python] 基于词云的关键词提取:wordcloud的使用、源码分析、中文词云生成和代码重写
		
1. 词云简介 词云,又称文字云.标签云,是对文本数据中出现频率较高的“关键词”在视觉上的突出呈现,形成关键词的渲染形成类似云一样的彩色图片,从而一眼就可以领略文本数据的主要表达意思.常见于博客.微博 ...
 - Python源码分析(二) - List对象
		
python中的高级特性之一就是内置了list,dict等.今天就先围绕列表(List)进行源码分析. Python中的List对象(PyListObject) Python中的的PyListObje ...
 
随机推荐
- 导出python的环境
			
1.导出 pip freeze > packegas.txt 2.在其他环境安装 pip install -r packages.txt
 - 继续沿用旧的网络访问模式Apache HTTP 客户端,防止Android9闪退
			
注意位置,在application 节点里面.
 - python14 1.带参装饰器 | wrapper  了了解 # 2.迭代器  ***** # 可迭代对象 # 迭代器对象 # for迭代器 # 枚举对象
			
## 复习 '''函数的嵌套定义:在函数内部定义另一个函数 闭包:被嵌套的函数 -- 1.外层通过形参给内层函数传参 -- 2.验证执行 开放封闭原则: 功能可以拓展,但源代码与调用方式都不可以改变 ...
 - Numpy系列(一)- array
			
初始Numpy 一.什么是Numpy? 简单来说,Numpy 是 Python 的一个科学计算包,包含了多维数组以及多维数组的操作. Numpy 的核心是 ndarray 对象,这个对象封装了同质数据 ...
 - Fiddler--Filters
			
本篇主要介绍Fiddler中Filters(过滤器)选项功能. 先看看Filters的界面: 一.模块一 当勾选“Use Filters”,Filters才开始工作:否则Filters中的设置内容将无 ...
 - Java中多态性的实现
			
class A ...{ public String show(D obj)...{ return ("A and D"); } public String show(A obj) ...
 - ArcGis汇总篇
			
ArcGis-javascript-API下载 bigemap.太乐地图 可下载地图文件 用arcgis for js 可以河流流域水质图 ArcGis导出shp文件(dbf.prj.sbn.sbx. ...
 - github及git使用
			
一.github及git Github用于托管和协作项目的网站,git是通常与github一起使用的版本控制系统.Github上有上百万个开源项目,在使用git的时候每个开发人员都在他们的计算机上有一 ...
 - WPS或xls 数据分列 清洗
			
一 .一般分离 时间:2017年11月27日14:55:12 数据如下: 501陈**:田莨铺58 502陈**:田莨铺58 503陈**.六麻杨冲58元 504陈**.石脚哗.200元 505陈** ...
 - shiro执行原理
			
一.架构 要学习如何使用Shiro必须先从它的架构谈起,作为一款安全框架Shiro的设计相当精妙.Shiro的应用不依赖任何容器,它也可以在JavaSE下使用.但是最常用的环境还是JavaEE.下面以 ...