常见问题解答¶
为什么 oslo.config 有一个 CONF 对象?全局对象太糟糕了!¶
的确如此。好吧,这是一个漫长的故事,并且在邮件列表存档中有充分的记录,如果有人关心,可以去查找相关链接。
在福尔索姆设计峰会(Folsom Design Summit)左右的时候,曾尝试移除对像这样全局对象的依赖。经过大量的讨论,最终达成共识,坚持使用这种方法。
Nova 通过其对 gflags 库的使用,从 commit zero 开始就使用了这种方法。一些 OpenStack 项目最初没有使用这种方法,但现在大多数都使用了。这个想法是,让所有项目使用相同的方法比反对这种方法更重要。项目之间共享代码很好,但通过让项目也使用相同的惯用语来处理类似的事情,可以更容易地让人们在多个项目上工作。
不过,这场争论可能永远不会完全消失。请参阅 2014 年 8 月的最新讨论
为什么配置选项不属于库的 API?¶
配置选项是部署者更改 OpenStack 行为的方式。应用程序不应该知道库中定义的和使用的配置选项,因为库 API 应该无论配置了什么后端都能透明地工作。
库中的配置选项可以像应用程序中的配置选项一样被重命名、移动和弃用。但是,如果允许应用程序直接读取或写入配置选项,将它们视为 API,则在不破坏应用程序的情况下无法重命名该选项。相反,库应该提供一个编程 API(通常是一个 set_defaults() 函数)来设置配置选项的默认值。例如,oslo.log 中的这个函数允许调用者更改格式字符串和默认日志级别
def set_defaults(logging_context_format_string=None,
default_log_levels=None):
"""Set default values for the configuration options used by oslo.log."""
# Just in case the caller is not setting the
# default_log_level. This is insurance because
# we introduced the default_log_level parameter
# later in a backwards in-compatible change
if default_log_levels is not None:
cfg.set_defaults(
_options.log_opts,
default_log_levels=default_log_levels)
if logging_context_format_string is not None:
cfg.set_defaults(
_options.log_opts,
logging_context_format_string=logging_context_format_string)
如果任一选项的名称发生更改,set_defaults() 的 API 可以更新为允许同时使用两种名称,并在提供旧名称时发出警告。使用像这样的受支持的 API 比让应用程序直接在配置对象上调用 set_default() 更好,例如
cfg.CONF.set_default('default_log_levels', default_log_levels)
这种形式如果日志选项从默认选项组移动到配置文件的单独部分,将触发错误。如果 default_log_levels 选项尚未注册,或者如果它被重命名,也会失败。所有这些情况都可以通过拥有选项的库中的 set_defaults() 函数来保护。
同样,不拥有配置选项定义的代码不应该读取选项值。例如,应用程序不应该做类似的事情
log_file = cfg.CONF.log_file
log_file 配置选项的类型、名称和存在都可能发生变化。oslo.config 使其能够以一种允许其旧配置文件继续工作的方式向部署者传达这种变化。但是,它没有机制在应用程序代码中执行此操作。