MultiStrOpt vs ListOpt




最近需要设置OpenStack senlin里一个配置项event_dispatchers,这个配置项是MultiStrOpt类型的,按照官方文档尝试了很久还是不能用,senlin-engine日志报warning:

2018-02-02 16:43:58.170 32363 DEBUG senlin.engine.event [-] Loading dispatchers load_dispatcher /usr/share/senlin_venv/senlin/se
nlin/engine/event.py:30
2018-02-02 16:43:58.170 32363 WARNING stevedore.named [-] Could not load database, message
2018-02-02 16:43:58.171 32363 WARNING senlin.engine.event [-] No dispatchers configured for 'senlin.dispatchers'

起初以为是我们用virtualenv虚拟环境的问题,没找到setup.cfg的entry_points里面配置的namespace senlin.dispatchers:

def load_dispatcher():
    """Load dispatchers."""
    global dispatchers

    LOG.debug("Loading dispatchers")
    dispatchers = named.NamedExtensionManager(
        namespace="senlin.dispatchers",   ### setup.cfg里配置
        names=cfg.CONF.event_dispatchers,
        invoke_on_load=True,
        propagate_map_exceptions=True)
    if not list(dispatchers):
        LOG.warning("No dispatchers configured for 'senlin.dispatchers'")
    else:
        LOG.info("Loaded dispatchers: %s", dispatchers.names())
[entry_points]
......
senlin.dispatchers =
    database = senlin.events.database:DBEvent
    message = senlin.events.message:MessageEvent
# DEFAULT, event dispatchers
event_opts = [
    cfg.MultiStrOpt("event_dispatchers", default=['database'],
                    help=_("Event dispatchers to enable."))]
cfg.CONF.register_opts(event_opts)

加断点单步调试,发现拿到的配置项是[‘database, message’] ,而不是[‘database’, ‘message’] 。

尝试把MultiStrOpt改成ListOpt之后,可以正常加载了。这表明要么是senlin的bug,要么是文档配置示例写错了。

MultiStrOpt到底怎么配置?找了好几个OpenStack项目,终于在keystone项目里面找到了一个示例

[federation]
trusted_dashboard = http://acme.horizon.com/auth/websso/
trusted_dashboard = http://beta.horizon.com/auth/websso/

原来是要分多行写的。而ListOpt则是写一行,用逗号分隔。

二者的区别可以参考:http://markmail.org/message/5ut4rdjivpw6a6a6

我理解主要是为了支持等号后面的值里面包含逗号的配置项情况,比如”value1,value2″是一项,”value3,value4″是另一项,如果用ListOpt类型配置项,就没办法做到拆成两项(会拆成value1~4共4项),只能用MultiStrOpt来解决。

测试代码:

from oslo_config import cfg

event_opts = [
    cfg.MultiStrOpt("event_dispatchers", default=['database'],
                    help=("Event dispatchers to enable."))]
cfg.CONF.register_opts(event_opts)

if __name__ == '__main__':
    cfg.CONF(project='senlin', prog='senlin-engine')
    print type(cfg.CONF.event_dispatchers)
    print cfg.CONF.event_dispatchers
    for i in  cfg.CONF.event_dispatchers:
        print i

测试配置文件1:

[DEFAULT]
event_dispatchers = value1
event_dispatchers = value2

执行结果:

root@host-10-0-80-25 ~ $ python test.py --config-file test.conf
<type 'list'>
['value1', 'value2']
value1
value2

测试配置文件2:

[DEFAULT]
event_dispatchers = value1,value2 

执行结果:

root@host-10-0-80-25 ~ $ python test.py --config-file test.conf
<type 'list'>
['value1,value2']
value1,value2