定义选项

配置选项可以在命令行、环境或配置文件中设置。选项的优先级顺序为:命令行 > 环境 > 配置文件。

每个选项的模式使用 Opt 类或其子类定义,例如

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.')
]

选项类型

选项可以通过 type 参数传递给 Opt 构造函数来拥有任意类型。 type 参数是一个可调用对象,它接收一个字符串并返回该特定类型的值,或者如果无法转换该值,则引发 ValueError 异常。

为了方便起见,oslo_config.cfg 中存在预定义的选项子类,它们将选项的 type 设置为下表所示:

类型

选项

oslo_config.types.String

oslo_config.cfg.StrOpt

oslo_config.types.String

oslo_config.cfg.SubCommandOpt

oslo_config.types.Boolean

oslo_config.cfg.BoolOpt

oslo_config.types.Integer

oslo_config.cfg.IntOpt

oslo_config.types.Float

oslo_config.cfg.FloatOpt

oslo_config.types.Port

oslo_config.cfg.PortOpt

oslo_config.types.List

oslo_config.cfg.ListOpt

oslo_config.types.Dict

oslo_config.cfg.DictOpt

oslo_config.types.IPAddress

oslo_config.cfg.IPOpt

oslo_config.types.Hostname

oslo_config.cfg.HostnameOpt

oslo_config.types.HostAddress

oslo_config.cfg.HostAddressOpt

oslo_config.types.URI

oslo_config.cfg.URIOpt

对于 oslo_config.cfg.MultiOptitem_type 参数定义了值的类型。为了方便起见,oslo_config.cfg.MultiStrOptMultiOpt,其 item_type 参数设置为 oslo_config.types.MultiString

以下示例使用便捷类定义选项

enabled_apis_opt = cfg.ListOpt('enabled_apis',
                               default=['ec2', 'osapi_compute'],
                               help='List of APIs to enable by default.')

DEFAULT_EXTENSIONS = [
    'nova.api.openstack.compute.contrib.standard_extensions'
]
osapi_compute_extension_opt = cfg.MultiStrOpt('osapi_compute_extension',
                                              default=DEFAULT_EXTENSIONS)

注册选项

选项模式在运行时与配置管理器注册,但在引用选项之前。

class ExtensionManager:

    enabled_apis_opt = cfg.ListOpt(...)

    def __init__(self, conf):
        self.conf = conf
        self.conf.register_opt(enabled_apis_opt)
        ...

    def _load_extensions(self):
        for ext_factory in self.conf.osapi_compute_extension:
            ....

一种常见的用法模式是每个选项模式都定义在使用的模块或类中

opts = ...

def add_common_opts(conf):
    conf.register_opts(opts)

def get_bind_host(conf):
    return conf.bind_host

def get_bind_port(conf):
    return conf.bind_port

选项可以选择性地通过命令行提供。此类选项必须在解析命令行之前与配置管理器注册(用于 –help 和 CLI 参数验证)。

请注意,为 CLI 使用注册的选项无需再次注册以从其他配置源(如文件)使用。CLI 选项可以从 CLI 或其他启用的配置源读取。

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)

选项组

选项可以注册到组中

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.register_group(rabbit_group)
    # options can be registered under a group in either of these ways:
    conf.register_opt(rabbit_host_opt, group=rabbit_group)
    conf.register_opt(rabbit_port_opt, group='rabbit')

如果除了组名之外不需要其他组属性,则无需显式注册该组,例如

def register_rabbit_opts(conf):
    # The group will automatically be created, equivalent calling:
    #   conf.register_group(OptGroup(name='rabbit'))
    conf.register_opt(rabbit_port_opt, group='rabbit')

如果未指定组,则选项属于配置文件的“DEFAULT”部分

glance-api.conf:
  [DEFAULT]
  bind_port = 9292
  ...

  [rabbit]
  host = localhost
  port = 5672
  use_ssl = False
  userid = guest
  password = guest
  virtual_host = /

组中的命令行选项会自动以组名为前缀

--rabbit-host localhost --rabbit-port 9999

动态组

组可以由应用程序代码动态注册。这给示例生成器、发现机制和验证工具带来挑战,因为它们事先不知道所有组的名称。构造函数的 dynamic_group_owner 参数指定了另一个组中注册的选项的完整名称,该选项控制动态组的重复实例。此选项通常是 MultiStrOpt。

例如,Cinder 支持多个存储后端设备和服务。为了配置 Cinder 与多个后端通信,enabled_backends 选项设置为后端的名称列表。每个后端组都包含与该设备或服务通信的选项。

驱动组

组可以具有动态选项集,通常基于具有唯一要求的驱动程序。这在运行时有效,因为代码在注册选项之前使用它们,但它给示例生成器、发现机制和验证工具带来挑战,因为它们事先不知道组的正确选项。

为了解决此问题,可以使用 driver_option 参数命名组的驱动程序选项。每个驱动程序选项应定义其自己的发现入口点命名空间,以使用 "oslo.config.opts." 前缀后跟驱动程序选项名称来返回该驱动程序的选项集。

在上述 Cinder 的情况下,volume_backend_name 选项是组的静态定义的一部分,因此 driver_option 应设置为 "volume_backend_name"。插件应使用与使用 "oslo.config.opts" 注册的主插件相同的名称在 "oslo.config.opts.volume_backend_name" 下注册。Cinder 代码库中的驱动程序具有名为 "cinder" 的入口点注册。

特殊处理说明

可以声明选项为必需,以便如果用户未为该选项提供值,则会引发错误

opts = [
    cfg.StrOpt('service_name', required=True),
    cfg.StrOpt('image_id', required=True),
    ...
]

可以声明选项为机密,以便其值不会泄漏到日志文件中

opts = [
   cfg.StrOpt('s3_store_access_key', secret=True),
   cfg.StrOpt('s3_store_secret_key', secret=True),
   ...
]

字典选项

如果您需要最终用户指定键/值对的字典,则可以使用 DictOpt

opts = [
    cfg.DictOpt('foo',
                default={})
]

然后,最终用户可以在他们的配置文件中指定选项 foo,如下所示

[DEFAULT]
foo = k1:v1,k2:v2

高级选项

如果您需要将选项标记为高级选项,指示该选项通常不被大多数用户使用,并且可能对稳定性和/或性能产生重大影响,请使用

from oslo_config import cfg

opts = [
    cfg.StrOpt('option1', default='default_value',
                advanced=True, help='This is help '
                'text.'),
    cfg.PortOpt('option2', default='default_value',
                 help='This is help text.'),
]

CONF = cfg.CONF
CONF.register_opts(opts)

这将导致该选项被推送到命名空间的底部,并在示例文件中标记为高级选项,并附带有关可能影响的说明

[DEFAULT]
...
# This is help text. (string value)
# option2 = default_value
...
<pushed to bottom of section>
...
# This is help text. (string value)
# Advanced Option: intended for advanced users and not used
# by the majority of users, and might have a significant
# effect on stability and/or performance.
# option1 = default_value