这里大致包括以下内容:
- devstack安装环境中中cinder mq相关信息
- volume表host字段相关信息
- cinder-volume和cinder-backup部署关系的问题
接着上一篇笔记,”Cinder multiple backend”,来学习一下cinder中的rpc。
为什么要说这个呢?
因为我在开发volume虚机备份功能的时候,参考cinder-backup rpcapi.py,会这样发送rpc request:
# cinder/backup/rpcapi.py
def create_backup(self, ctxt, host, backup_id, volume_id):
LOG.debug("create_backup in rpcapi backup_id %s", backup_id)
cctxt = self.client.prepare(server=host)
cctxt.cast(ctxt, 'create_backup', backup_id=backup_id)
其中的host参数就是cinder数据库中backup表的host字段。而该字段是用如下方法从volume表的host字段中抽取出来的:
# cinder/backup/api.py
volume_host = volume_utils.extract_host(volume['host'], 'host')
if not self._is_backup_service_enabled(volume, volume_host):
raise exception.ServiceNotFound(service_id='cinder-backup')
Note:后面有关于_is_backup_service_enabled
方法的分析。
先来看看volume_utils.extract_host
方法,这里说明了cinder中“host”的结构。
“Host”结构
看注释最清楚了:
# cinder/volumes/utils.py
def extract_host(host, level='backend', default_pool_name=False):
"""Extract Host, Backend or Pool information from host string.
:param host: String for host, which could include host@backend#pool info
:param level: Indicate which level of information should be extracted
from host string. Level can be 'host', 'backend' or 'pool',
default value is 'backend'
:param default_pool_name: this flag specify what to do if level == 'pool'
and there is no 'pool' info encoded in host
string. default_pool_name=True will return
DEFAULT_POOL_NAME, otherwise we return None.
Default value of this parameter is False.
:return: expected level of information
For example:
host = 'HostA@BackendB#PoolC'
ret = extract_host(host, 'host')
# ret is 'HostA'
ret = extract_host(host, 'backend')
# ret is 'HostA@BackendB'
ret = extract_host(host, 'pool')
# ret is 'PoolC'
host = 'HostX@BackendY'
ret = extract_host(host, 'pool')
# ret is None
ret = extract_host(host, 'pool', True)
# ret is '_pool0'
"""
host字段结构为:host@backend#pool
。分三个层次,具体由来还得以后分析(例如:Spec1)
extract_host
默认会抽取到backend
层次。
看了Kilo版本代码:
- volume相关的方法,都抽取到了默认的
backend
层次 - volume backup相关的方法,都抽取到了
host
层次(因为backup时,需要读取volume的数据,必须指定特定的host。当然对于Ceph,Sheepdog之类的存储,host不一定是某个物理机。)
分析实验环境
cinder.conf参见“Cinder multiple backend”笔记。
从上面的测试结果来看,数据库中是这样的:
MariaDB [cinder]> select host from volumes where status='available';
+---------------------------------------------------------+
| host |
+---------------------------------------------------------+
| maqi-openstack.novalocal@lvmdriver-1#lvmdriver-1 |
| maqi-openstack.novalocal@whatever_it_is#new_lvm_backend |
+---------------------------------------------------------+
所以,
host为maqi-openstack.novalocal
backend有两个:lvmdriver-1
, whatever_it_is
(cinder.conf中的enabled_backends
,也就是section name)
pool也有两个:lvmdriver-1
, new_lvm_backend
(cinder.conf中的volume_backend_name
,也是extra_specs中的值)
以下先试图分析创建bacup时,rpc msg中的host以及msg的收发。
创建volume的过程涉及到scheduler,比较复杂,以后再看。
先来看实验环境中一些rabbitmq相关的信息。
Rabbitmq相关的信息
在rabbitmq中,message处理的基本过程是:
- publisher构造message,把它发送到指定的exchange上。该message中包含routing_key。
- 这个exchange收到该message之后,根据自己的类型(fanout,direct,topic等),分析routing_key。routing_key的作用是让exchange找到queue,因为queue在创建的时候,已经把该routing_key注册到exchange上了。所以,exchange根据routing_key把message发送到对应的queue上。
- 该queue有一个或多个consumer,一直在监听queue上的message。当有新message到达queue时,这个consumer就取出message,并且执行这个message中指定的方法。
先来看看环境中有哪些exchange、queue。
官方文档在说明volume multiple backend时有如下介绍:
Cinder volume backends are spawned as children to cinder-volume, and they are keyed from a unique Queue. They are named
cinder-volume.HOST.BACKEND
. Example cinder-volume.ubuntu.lvmdriver. The filter scheduler determines where to send the volume based on the volume type thats passed in.
看看有没有这样一个queue:
[root@maqi-openstack admin]# rabbitmqctl list_queues | grep cinder
cinder-scheduler 0
cinder-scheduler.maqi-openstack.novalocal 0
cinder-scheduler_fanout_fc01cfa5062041d9ac0f592ff9d83c90 0
cinder-volume 0
cinder-volume.maqi-openstack.novalocal@lvmdriver