配置变更处理在版本发布中¶
问题描述:¶
当用户将他们的 OpenStack 系统升级到新版本时,通常需要更新配置文件以适应从旧版本到新版本的变更。基本上,那时他们必须阅读发布说明或变更日志,甚至跟踪源代码变更来完成此操作。
但不幸的是,可能会存在一些误解,发布说明中缺乏信息导致用户感到困惑。应该在 oslo.config 中提供一些帮助,以自动采用新的变更并帮助用户轻松管理他们的配置文件。
场景
以下是用户可以在旧系统上执行的流程,以生成新的配置,为升级到新版本做准备
+--------------+
Old configuration +--------> |
(N-1 release) | Oslo |
| Config +-------> New configuration
Namespaces +--------> Migrator | (N release)
| |
+--------------+
Running on new environment
提议的变更:¶
我们有一种方法可以生成任何项目的机器可读示例配置的数据结构,因此我们可以基于这种方法获取一个 ConfigOpts 实例(CONF 对象),其中包含来自主项目以及命名空间中列出的其他项目的完整选项列表。
基于 CONF 对象,我们可以获取有关选项的信息,例如是否 deprecated_name 和 deprecated_group。如果是,那么可以实现一个函数来从旧配置更新到新配置,因此我们将这种情况称为“1:1 映射,不改变值”。事实上,不仅是这种情况,还包括其他情况,例如
情况 1:1:1 映射,不改变值。
情况 2:1:1 映射,改变值。
情况 3:N:1 映射。这意味着一个选项可以替换一组选项。
情况 4:M*N:1 映射。这意味着一个选项可以替换一个超组的选项。
情况 5:动态部分。
情况 6:动态选项。
通过使用 deprecated_name 和 deprecated_group,我们能够解决 情况 1。情况 1 的示例如下
更改选项的键
[keystone_authtoken]
auth_uri = http://192.168.122.250:5000
-->
[keystone_authtoken]
www_authenticate_uri = http://192.168.122.250:5000
更改选项的部分
[DEFAULT]
api_paste_config = api-paste.ini
-->
[wsgi]
api_paste_config = api-paste.ini
更改选项的部分和键
[DEFAULT]
notification_driver = messaging
-->
[oslo_messaging_notifications]
driver = messaging
为了解决 情况 2,有必要向 Opt 类添加一个参数。它被称为“convert_on_upgrade”。它将是一个函数,用于将旧值映射到新值。
例如
cfg.StrOpt('choices_opt',
choices=('a_new', 'b_new', 'c_new'),
convert_on_upgrade=choice_opt_converter,
help = 'a choice opt')
def choice_opt_converter(opt, value):
return {
'a': 'a_new',
'b': 'b_new',
'c': 'c_new',
}.get(value)
问题:¶
有了这个提议,我们只解决了 2 个基本情况(情况 1 和情况 2)。对于更复杂的情况,我们尚未解决它们。以下是需要实现此功能的剩余情况。
情况 3:将 N 个选项映射到 1 个选项:¶
例如
identify_uri 可以替换 3 个选项:auth_host、auth_port 和 auth_protocol。
[keystone_authtoken]
auth_protocol = http
auth_host = controller
auth_port = 35357
-->
[keystone_authtoken]
identity_uri = http://controller:35357
情况 4:将 M*N 个选项映射到 1 个选项:¶
目前,transport_url 是这种情况的一个很好的例子。其中 M 是消息队列驱动程序中的选项数量,N 是驱动程序数量(N>1)。
例如
如果 RabbitMQ 被用作消息队列的后端,那么 transport_url 可以替换四个选项,例如 rabbit_host、rabbit_port、rabbit_userid 和 rabbit_password (M=4) 通过使用如下模板:rabbit://rabbit_userid:rabbit_password@rabbit_host:rabbit_port。
如果 Kafka 是消息队列的后端,那么 transport_url 可以替换两个选项,包括 kafka_default_host 和 kafka_default_port (M=2) 通过使用如下模板:kafka://kafka_default_host:kafka_default_port。
[DEFAULT]
rpc_backend = rabbit
#rpc_backend = kafka
[oslo_messaging_rabbit]
rabbit_host = controller
rabbit_userid = openstack
rabbit_password = RABBIT_PASS
rabbit_port = 5672
[oslo_messaging_kafka]
#kafka_default_host = controller
#kafka_default_port = 9092
-->
[DEFAULT]
transport_url = rabbit://openstack:RABBIT_PASS@controller:5672
#transport_url = kafka//openstack:9092
情况 5:动态部分¶
一件重要的事情是存在一个动态部分。例如,Cinder 有一个名为 enabled_backends [1] 的选项,如果该选项声明为 enabled_backends = lvm,那么将在 cinder.conf 中声明一个新的部分 [lvm],如下所示。
[DEFAULT]
enabled_backends = lvm
[lvm]
# ...
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_group = cinder-volumes
iscsi_protocol = iscsi
iscsi_helper = tgtadm
但是如果 enabled_backends = ceph 那么新的部分 [ceph] 应该被声明。
[DEFAULT]
enabled_backends=ceph
[ceph]
# ...
volume_driver=cinder.volume.drivers.rbd.RBDDriver
rbd_pool=volumes
rbd_ceph_conf=/etc/ceph/ceph.conf
rbd_store_chunk_size = 4
rados_connect_timeout = -1
rbd_secret_uuid=457eb676-33da-42ec-9a8c-9293d545c337
这两个部分 [lvm] 和 [ceph] 都没有在代码库中注册,这些部分中的选项实际上是在 [backend_defaults] 部分中注册的,并且属于 cinder 命名空间。
那么我们如何理解动态部分中的所有值?可以通过动态组或驱动程序组 [2] 来完成,但我们没有项目使用它们,因此每个项目应该迁移到使用这些东西,而不是他们特殊的方式来读取动态部分。
情况 6:动态选项¶
在 [keystone_authtoken] 中,像 user_domain_id、project_name 这样的选项是动态注册的,基于服务使用哪种 auth_type (密码、token…) [3]。它们不属于任何命名空间。我们如何理解这些选项?
[keystone_authtoken]
...
auth_uri = http://controller:5000
auth_url = http://controller:5000
memcached_servers = controller:11211
auth_type = password
project_domain_id = default
user_domain_id = default
project_name = service
username = cinder
password = cinder
工作项:¶
实现一个属性:mapping_value。
实现一个新函数,基于代码库和旧配置文件来渲染新的配置文件。
文档影响:¶
需要两个文档
有一个文档指导项目更新源代码,如果他们想要这个功能。
有一个文档给操作员,关于逐步使用此功能的步骤。
实现:¶
负责人¶
主要负责人
Phuong Hung Nguyen <phuongnh@vn.fujitsu.com>
Duc Nguyen Van <ducnv@vn.fujitsu.com>