Nova Conductor服务的大部分方法都是数据库的查询操作(/nova/conductor/manager.py ConductorManager类)。主
要作用是避免Nova Compute服务直接访问数据库,增加系统的安全性。
1、nova compute服务的数据库查询更新操作都需要通过向nova conductor服务发送RPC请求来实现。
2、在创建Nova Compute服务的Service对象时,会调用conductor_api的wait_until_ready方法等待nova conductor服
务完成初始化工作。以下是Service类的初始化代码片段(/nova/service.py)。
class Service(service.Service):
def __init__(self, host, binary, topic, manager, report_interval=None,
periodic_enable=None, periodic_fuzzy_delay=None,
periodic_interval_max=None, db_allowed=True,
*args, **kwargs):
...
#创建conductor_api对象
self.conductor_api = conductor.API(use_local=db_allowed)
#等待nova conductor服务开始工作
self.conductor_api.wait_until_ready(context.get_admin_context())
db_allowed默认值是True。nova compute服务的启动脚本(/bin/nova-compute),显式设置参数为False。
注意:nova scheduler启动脚本中,没有显式设置db_allowed参数。因此,db_allowed的值为默认值True。所以,具
有访问数据库的权限。
conductor.API方法定义如下:
def API(*args, **kwargs):
#获取外部传入的use_local参数
use_local = kwargs.pop('use_local', False)
#如果nova.conf配置文件中配置了use_local配置项为True
#或者外部传入的use_local参数为True,则使用LocalAPI对象
if oslo_config.cfg.CONF.conductor.use_local or use_local:
api = conductor_api.LocalAPI
#否则创建远程API对象
else:
api = conductor_api.API
return api(*args, **kwargs)
True,则为Nova服务创建LocalAPI对象;否则创建远程API对象。
注意:nova.conf配置文件use_local配置项默认值False。conductor.API方法会为nova compute服务创建远程API对
象;由于nova scheduler服务传入的use_local值为True,为nova scheduler服务创建Local API对象。
Nova服务的conductor_api对象的类型可能是LocalAPI对象或者API类。LocalAPI类和API类初始化方法和
wait_until_ready方法。
1、LocalAPI类
LocalAPI类的初始化方法定义如下:
class LocalAPI(object):
def __init__(self):
self._manager = utils.ExceptionHelper(manager.ConductorManager())
(1)创建了一个ConductorManager对象。 在ConductorManager类中,定义许多数据库访问的方法,这些方法都在本
机建立与数据库的连接。
(2)LocalAPI类定义了许多接口方法供Nova其他服务(Nova Scheduler)调用,底层都是直接调用ConductorManager
对象中定义的相应的方法,并没有向nova conductor服务发送RPC请求。
注意:Nova Scheduler服务使用的conductor_api是LocalAPI对象。当Nova Scheduler调用conductor_api访问数据库
时,直接在本地建立与数据库的连接。因此Nova Scheduler服务的运行并不依赖nova conductor服务。
(3)既然不依赖nova conductor服务,nova scheduler没有必要等待nova conductor服务开始运行。实现代码重用,
创建nova scheduler服务对象时,调用conductor_api的wait_until_ready方法。 LocalAPI类为空。
2、远程API方法
远程API类的初始化方法定义:
class API(LocalAPI):
def __init__(self):
self._manager = rpcapi.ConductorAPI()
(1)创建了一个Conductor RPC API对象。Conductor RPC API类中定义许多接口方法向nova conductor发送RPC请求。
而nova consuctor服务处理RPC请求的manager对象是一个ConductorManager对象。API类中定义的接口方法底层会调
用Conductor RPC API对象中相应的方法。
注意:
(1)默认,nova compute服务使用的conductor_api是API对象。当nova compute调用conductor_api访问数据库时,会
通过Conductor RPC服务向Nova Conductor服务发送RPC请求。因此conpute服务依赖于conductor服务。
(2)既然nova compute服务访问数据库需要通过nova conductor服务中转,效率比nova scheduler服务低。
(2)创建Nova Compute服务对象时,调用API对象的wait_until_ready方法,定义如下:
class API(LocalAPI):
def wait_until_ready(self, context, early_timeout=10, early_attempts=10):
#尝试次数
attempt = 0
#请求等待时间
timeout = early_timeout
has_timedout = False
#不断尝试ping Nova conductor服务
while True:
#如果尝试此时达到early_attempts,则不设置RPC请求等待时间
if attempt == early_attempts:
timeout = None
attempt += 1
try:
#尝试向nova conductor服务发送RPC请求
self.base_rpcapi.ping(context, '1.21 GigaWatts',
timeout=timeout)
if has_timedout:
LOG.info(_LI('nova-conductor connection '
'established successfully'))
#如果请求成功,说明nova conductor服务正常工作,结束循环
break
#如果请求失败,进入下一个循环,继续发送RPC请求
except messaging.MessagingTimeout:
has_timedout = True
LOG.warning(_LW('Timed out waiting for nova-conductor. '
'Is it running? Or did this service start '
'before nova-conductor? '
'Reattempting establishment of '
'nova-conductor connection...'))
不断向Nova Conductor服务发送ping RPC请求。当请求等待正常响应时,则认为nova conductor服务已经正常工作
了。nova conductor服务最终会把ping RPC请求交给ConductorManager对象的ping方法处理。
总结:
1、创建虚拟机请求的处理流程
通过虚拟机创建请求,分析Nova API、Nova Scheduler和Nova Compute服务的工作和协作机制。
虚拟机创建请求的处理流程:
servers资源底层(nova.api.openstack.compute.legacy_v2.servers.py) Controller类的create方法
2、调度算法
虚拟机调度算法是Nova Scheduler服务实现的最主要的功能,算法的框架定义在FilterScheduler类的_scheduler方
法中。_scheduler工作流程:
(1)调用HostManager对象的get_all_hosts方法获取所有的计算节点列表。
(2)调用HostManager对象的get_filtered_hosts方法获取可用的计算节点列表。
(3)调用HostManager对象的get_weighted_hosts方法计算可用计算节点的权值。
(4)从权值最高的scheduler_host_subset_size个计算节点中随机选择一个计算节点作为创建虚拟机的节点。
(5)调用被选中计算节点对应的 HostState对象的 consume_from_instance方法,更新选择的计算节点的硬件资源信
息,为虚拟机预留资源。
(6)HostManager对象的get_all_hosts方法首先调用HostManager对象的_choose_host_filters方法获取过滤器类列
表,然后调用HostFilterHandler对象的get_filtered_objects方法使用过滤器检查计算节点。
(7)HostFilterHandler对象的get_filtered_objects方法依次调用每个过滤器对象的filter_all方法。过滤器的
filter_all方法返回的是通过该过滤器的主机列表。只有通过所有的过滤器检查的节点才是可用的节点。
(8)HostManager对象的get_weighted_hosts方法调用了HostWeightHandler对象的get_weighted_objects方法。
(9)HostWeightHandler对象的get_weighted_objects方法首先为每个主机创建一个WeightedObject对象。然后,依
次调用权值对象的weigh_objects方法不断修改主机WeightedObject对象的权值。
主机最终的权值是所有权值对象赋予给主机权值的加权和。最后将主机按照权值由高到低顺序排列。