nova-compute 启动流程

service.Service 对象初始化

  • nova.cmd.compute:main 函数发起调用初始化 service.Service,如下:
    1
    2
    server = service.Service.create(binary='nova-compute',
    topic=compute_rpcapi.RPC_TOPIC)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
class Service(service.Service):
# 英文注释已经很好的解释了改对象的作用
"""Service object for binaries running on hosts.

A service takes a manager and enables rpc by listening to queues based
on topic. It also periodically runs tasks on the manager and reports
its state to the database services table.
"""

def __init__(self, host, binary, topic, manager, report_interval=None,
periodic_enable=None, periodic_fuzzy_delay=None,
periodic_interval_max=None, *args, **kwargs):
super(Service, self).__init__()
self.host = host
self.binary = binary
self.topic = topic
self.manager_class_name = manager
self.servicegroup_api = servicegroup.API()
# 导入ComputeManager类
manager_class = importutils.import_class(self.manager_class_name)
if objects_base.NovaObject.indirection_api:
conductor_api = conductor.API()
conductor_api.wait_until_ready(context.get_admin_context())
# 实例化ComputeManager类
self.manager = manager_class(host=self.host, *args, **kwargs)
self.rpcserver = None
self.report_interval = report_interval
self.periodic_enable = periodic_enable
self.periodic_fuzzy_delay = periodic_fuzzy_delay
self.periodic_interval_max = periodic_interval_max
self.saved_args, self.saved_kwargs = args, kwargs
self.backdoor_port = None
setup_profiler(binary, self.host)


@classmethod
def create(cls, host=None, binary=None, topic=None, manager=None,
report_interval=None, periodic_enable=None,
periodic_fuzzy_delay=None, periodic_interval_max=None):
if not host:
host = CONF.host
if not binary:
binary = os.path.basename(sys.argv[0])
if not topic:
topic = binary.rpartition('nova-')[2]
if not manager:
manager = SERVICE_MANAGERS.get(binary)
if report_interval is None:
report_interval = CONF.report_interval
if periodic_enable is None:
periodic_enable = CONF.periodic_enable
if periodic_fuzzy_delay is None:
periodic_fuzzy_delay = CONF.periodic_fuzzy_delay

debugger.init()

service_obj = cls(host, binary, topic, manager,
report_interval=report_interval,
periodic_enable=periodic_enable,
periodic_fuzzy_delay=periodic_fuzzy_delay,
periodic_interval_max=periodic_interval_max)

return service_obj
  • create 函数用于初始化 service.Service 对象
  • create 函数做了简单的初始化参数处理,然后调用 service.Service 类的构造方法
  • 在类的构造方法中动态加载 ComputeManager 类,然后示例化类,它是 nova-compute 最重要的依赖

service.Service 启动

基于之前的知识,nova-compute 启动时都会执行 service.Servicestart() 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
def start(self):
"""Start the service.

This includes starting an RPC service, initializing
periodic tasks, etc.
"""
context.CELL_CACHE = {}

assert_eventlet_uses_monotonic_clock()

verstr = version.version_string_with_package()
LOG.info(_LI('Starting %(topic)s node (version %(version)s)'),
{'topic': self.topic, 'version': verstr})
self.basic_config_check()
self.manager.init_host()
self.model_disconnected = False
ctxt = context.get_admin_context()
self.service_ref = objects.Service.get_by_host_and_binary(
ctxt, self.host, self.binary)
if self.service_ref:
_update_service_ref(self.service_ref)

else:
try:
self.service_ref = _create_service_ref(self, ctxt)
except (exception.ServiceTopicExists,
exception.ServiceBinaryExists):
# NOTE(danms): If we race to create a record with a sibling
# worker, don't fail here.
self.service_ref = objects.Service.get_by_host_and_binary(
ctxt, self.host, self.binary)

self.manager.pre_start_hook()

if self.backdoor_port is not None:
self.manager.backdoor_port = self.backdoor_port

LOG.debug("Creating RPC server for service %s", self.topic)

target = messaging.Target(topic=self.topic, server=self.host)

endpoints = [
self.manager,
baserpc.BaseRPCAPI(self.manager.service_name, self.backdoor_port)
]
endpoints.extend(self.manager.additional_endpoints)

serializer = objects_base.NovaObjectSerializer()

self.rpcserver = rpc.get_server(target, endpoints, serializer)
self.rpcserver.start()

self.manager.post_start_hook()

LOG.debug("Join ServiceGroup membership for this service %s",
self.topic)
# Add service to the ServiceGroup membership group.
self.servicegroup_api.join(self.host, self.topic, self)

if self.periodic_enable:
if self.periodic_fuzzy_delay:
initial_delay = random.randint(0, self.periodic_fuzzy_delay)
else:
initial_delay = None

self.tg.add_dynamic_timer(self.periodic_tasks,
initial_delay=initial_delay,
periodic_interval_max=
self.periodic_interval_max)

启动分为三个重要的部分:

  • self.manager.pre_start_hook():在服务启动前,先更新下可用的资源
  • self.rpcserver.start():创建 rpc server 并监听
  • self.manager.post_start_hook():没实现,扩展接口

nova-compute 启动流程
http://mybestcheng.site/2023/09/20/openstack/nova/compute/service_start/
作者
mybestcheng
发布于
2023年9月20日
许可协议