OpenStack開發基礎-oslo.config

The cfg Module

cfg Module來自於OpenStack中的重要的基礎組件oslo.config,經過cfg Module可以用來經過命令行或者是配置文件來配置一些options,對於每一個選項使用Opt類或者其子類來定義。首先咱們來看一個定義option的樣例:php

example1:
#!/usr/bin/env python
# encoding: utf-8

from oslo_config import cfg
from oslo_config import types

# 定義了一個類型和範圍
PortType = types.Integer(1,65535)

# 定義一組選項
common_opts = [
    #定義了一個Str類型的選項,名字是bind_host。默認值是0.0.0.0,還有幫助信息
    #用的是Opt的子類來定義的,因此無需指定類類型,因爲類型已經定下來了就是Str類型
    cfg.StrOpt('bind_host',default='0.0.0.0',
               help='IP address to listen on.'),
    #使用Opt類來定義一個選項,因爲用的是基類。類型可以是隨意的,因此須要使用type字段明白其類型
    #使用這樣的方式的優勢我認爲就是可以定製類型的值範圍
    cfg.Opt('bind_port',
            type=PortType,
            default=9292,
            help="Port number to listen on.")
]

Opt是父類,其下有很是多特定類型的子類。如下是cfg Module支持的一些類型html

oslo_config.types.String    
oslo_config.types.Boolean
oslo_config.types.Integer
oslo_config.types.Float
oslo_config.types.List
oslo_config.types.Dict
oslo_config.types.IPAddress

這些類型可以用於在傳遞給Opt類,定義選型的類型信息,cfg也給咱們提供了一系列的特定類型的選項類。可以直接使用這些類來定義相應類型的選項node

oslo_config.cfg.StrOpt
oslo_config.cfg.BoolOpt
oslo_config.cfg.IntOpt
oslo_config.cfg.PortOpt
oslo_config.cfg.FloatOpt
oslo_config.cfg.ListOpt
oslo_config.cfg.DictOpt
oslo_config.cfg.IPOpt

我相信一眼就可以看出貓膩,因此這裏就不解釋了。python


cfg Module相同也支持具備多個值的選項。使用oslo_config.cfg.MultiOpt來定義,和oslo_config.cfg.Opt是相對的,前者是支持多個值的選項,後者是支持單個值的在使用MultiOpt類的時候經過設置item_type參數來設置選項的類型。爲了方面MultiOpt相同也又不少可以建立特定類型的子類。請看如下這個樣例:sql

example2:
#!/usr/bin/env python
# encoding: utf-8

from oslo_config import cfg
from oslo_config import types

DEFAULT_EXTENSIONS = [
    'nova.api.openstack.compute.contrib.standard_extensions'
]

# cfg.MultiOpt的子類用來定義一個多值的選項。值的類型是str
osapi_compute_extension_opt = cfg.MultiStrOpt('osapi_compute_extension',default=DEFAULT_EXTENSIONS)

我的感受這個和oslo_config.cfg.ListOpt功能差點兒相同。詳細細節咱就很少說了。繼續往下看吧。api

Registering Options

上文中定義了很是多的選項。但是離真正使用還差一步,那就是註冊。如下的樣例演示了怎樣去註冊選項和使用選項markdown

example3:
#!/usr/bin/env python
# encoding: utf-8

from oslo_config import cfg
from oslo_config import types

PortType = types.Integer(1, 65535)
#定義一組選項
common_opts = [
    cfg.StrOpt('bind_host',
               default='0.0.0.0',
               help='IP address to listen on.'),
    cfg.Opt('bind_port',
            type=PortType,
            default=9292,
            help='Port number to listen on.')
]
#註冊選項
def add_common_opts(conf):
        conf.register_opts(common_opts)
#使用選項
def get_bind_host(conf):
        return conf.bind_host

def get_bind_port(conf):
        return conf.bind_port

#建立配置類
cf = cfg.CONF
#開始註冊
add_common_opts(cf)
print(get_bind_host(cf))

就是這麼簡單。看起來不錯把,也沒有想象中的那麼複雜,畢竟僅僅是一個配置類,搞的太複雜誰還用啊,功能再強大我也不會用的。ide

基於命令行配置選項

上面說了那麼多。經過Opt類平配置了選項,設置選項的類型,默認值。而後經過CONF類來註冊選項,最後經過CONF類使用註冊的選項,讀者有沒有認爲很是雞肋這不就是定義一個變量,賦值而後使用嘛,這哪是配置選項啊,文章的開頭說了,cfg Module是可以經過命令行來傳遞配置選項的值,還可以經過配置文件了來傳遞配置選項的值的,好吧我認可。上面說了那麼多事實上都是在講基礎,真正的還沒開始呢,首先仍是來分析下cfg Module怎樣經過命令行來配置選項。看如下這個樣例:post

example4:
#!/usr/bin/env python
# encoding: utf-8

import sys
from oslo_config import cfg
from oslo_config import types
cli_opts = [
    cfg.BoolOpt('verbose',
                short='v',
                default=False,
                help='Print more verbose output.'),
    cfg.BoolOpt('debug',
                short='d',
                default=False,
                help='Print debugging output.'),
]

def add_common_opts(conf):
        conf.register_cli_opts(cli_opts)

cf = cfg.CONF
add_common_opts(cf);
cf(sys.argv[1:])  #將命令行參數傳遞給CONF類,argv[0]是程序名,因此從1開始

if cf.debug:
    print("開啓調試")
else:
    print("關閉調試")

完了,這個版本號最終不是雞肋了,可以經過命令行參數來改變verbos和debug兩個選項的值,使用一下把。先help一把,輸出例如如下:ui

usage: example4.py [-h] [--config-dir DIR] [--config-file PATH] [--debug]
                 [--nodebug] [--noverbose] [--verbose] [--version]

optional arguments:
  -h, --help show this help message and exit
  --config-dir DIR Path to a config directory to pull *.conf files from.
                      This file set is sorted, so as to provide a predictable parse order if individual options are over-ridden. The set is parsed after the file(s) specified via previous --config-file, arguments hence over-ridden options in the directory take precedence. --config-file PATH Path to a config file to use. Multiple config files can be specified, with values in later files taking precedence. The default files used are: None. --debug, -d Print debugging output. --nodebug The inverse of --debug --noverbose The inverse of --verbose --verbose, -v Print more verbose output. --version show program's version number and exit 

尼瑪好多東西啊。事實上僅僅有倒數幾行是咱們定義的選項,這裏不解釋了,cfg Module幫咱們作了很是多設置,比方提供了–nodebug接下來看看怎麼設置選項的值把,因爲我這裏是bool類型,因此直接使用選項–debug就是debug=True。–nodebug就是debug=False。假設什麼參數也沒有就是debug=False,簡單吧。

基於配置文件配置選項

事實上也很是easy了,代碼不變。依舊example4部分的代碼,相信有的讀者已經猜到了,因爲上面在執行–help的時候出現了–config-file和–config-dir兩個命令行參數這兩個的功能就是用來從配置文件加載配置選項的,前者指定一個配置文件,後者則指定一個文件夾下的所有配置文件。這裏提供一個配置文件,經過配置文件來執行一下example4中代碼:

example4.conf
[DEFAULT]
debug=True
verbose=False
經過如下的命令類加載配置
python example4.py --config-file=example4.conf

簡單吧,但是我認爲仍是有必要解釋一下,DEFAULT是一個默認組。默認狀況下Opt定義的選項都是屬於這個組的。cfg Module給配置選項提供了組的概念。不一樣的組配置選項是可以反覆的。那麼讓咱們看看怎樣使用配置組吧。

Option Groups

先來一段代碼。看看怎樣使用配置組

#!/usr/bin/env python
# encoding: utf-8
#定義了一個名爲rabbit的組,記住組的名字也很是重要,後面會用到
rabbit_group = cfg.OptGroup(name='rabbit',
                            title='RabbitMQ options')

#定義了兩個選項,和上文中說到的定義選項沒有不論什麼差異
rabbit_host_opt = cfg.StrOpt('host',
                             default='localhost',
                             help='IP/hostname to listen on.'),
rabbit_port_opt = cfg.PortOpt('port',
                              default=5672,
                              help='Port number to listen on.')
def register_rabbit_opts(conf):
    #經過CONF類來註冊了一個組。(CONF類啥都要先註冊後使用。註冊事實上就是在CONF類內部作解析呢)
    conf.register_group(rabbit_group)
    # options can be registered under a group in either of these ways:
    #註冊選項的時候經過指定組來把選項加入到特定的組中,指定組可以有例如如下兩種方式,一種就是直接使用OptGroup實例的方式
    #第二種就是使用配置組的名字這裏是rabbit
    conf.register_opt(rabbit_host_opt, group=rabbit_group)
    conf.register_opt(rabbit_port_opt, group='rabbit')
#沒提供group就是默認組DEFAULT

以前僅僅有默認組的時候。在命令行使用–debug就會本身主動去DEFAULT組去找,那麼現在加入了一個rabbit組,假設要找rabbit組中的host該怎麼經過命令行來指定呢這也是很是方便的直接經過前綴來推斷好比–rabbit-host指的就是rabbit組中的host選項。

配置文件句很少說了,定義一個[rabbit]就可以了,怎樣在代碼中訪問呢,也很是easy。直接使用conf.rabbit.host就可以了。

Special Handling Instructions

說了這麼多,是否是感受cfg Module有點強大,我也這麼認爲的,這個部分介紹下cfg Module關於選項提供的一些處理指令吧.

  • 設置必須要輸入的選項值,假設用戶沒有提供就會拋出一個錯誤的異常
    經過在Opt類或者子類中加入required=True這個參數就可以實現了。

  • 設置選型值不計入日誌文件裏
    cfg Module提供了一個LOG類。可以用戶輸入的配置選項的值記錄到日誌文件裏,但是對於一些敏感的配置選項值仍是不要記錄到日誌中把。

    可以經過在Opt類或者子類中加入secret=True這個參數就可以實現了。

小結

cfg Module還有很是多細節在本篇文章還未涉及到,但是本文的初衷僅僅是因爲做者我在分析OpenStack代碼的時候因爲對很是多基礎庫不熟悉。致使分析的時候遇到了很是多困難所以有了本文。但願本文帶您入門,至少可以看懂OpenStack中慣關於配置選項的大部分代碼,那麼我認爲本文的目的就達到了。

如要想知道不少其它關於oslo.config的知識請參考如下的連接。


oslo-config doc

相關文章
相關標籤/搜索