您的位置:首页 > 运维架构

Openstack nova service 启动过程

2015-07-23 22:48 267 查看
Openstack 中nova主要是用作运算,其是有多个service组成的。

在每个service启动的时候都会注册一个RPC server(nova-api 除外)以供RPC的client调用。

nova compute

nova/cmd/compute.py

def main():
config.parse_args(sys.argv)
logging.setup('nova')
utils.monkey_patch()
objects.register_all()

gmr.TextGuruMeditation.setup_autorun(version)

if not CONF.conductor.use_local:
block_db_access()
objects_base.NovaObject.indirection_api = \
conductor_rpcapi.ConductorAPI()

<em><strong> server = service.Service.create(binary='nova-compute',
topic=CONF.compute_topic,
db_allowed=CONF.conductor.use_local)
service.serve(server)
service.wait()</strong></em>


service在程序的开头通过import导入

from nova import service


Service 是定义在nova/service .py 里面的一个类

其create方法使用@classmethod 修饰因此可以直接使用类名调用。此方法的作用是返回一个service的对象。

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,
db_allowed=True):
"""Instantiates class and passes back application object.

:param host: defaults to CONF.host
:param binary: defaults to basename of executable
:param topic: defaults to bin_name - 'nova-' part
:param manager: defaults to CONF.<topic>_manager
:param report_interval: defaults to CONF.report_interval
:param periodic_enable: defaults to CONF.periodic_enable
:param periodic_fuzzy_delay: defaults to CONF.periodic_fuzzy_delay
:param periodic_interval_max: if set, the max time to wait between runs

"""
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_cls = ('%s_manager' %
binary.rpartition('nova-')[2])
manager = CONF.get(manager_cls, None)
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,
db_allowed=db_allowed)

return service_obj

<em><strong>service.serve(server)</strong></em>
用来启动service

nova/service.py

def serve(server, workers=None):
global _launcher
if _launcher:
raise RuntimeError(_('serve() can only be called once'))

_<strong><em>launcher = service.launch(server, workers=workers)</em></strong>


在 service.py 中 service在开头import

from nova.openstack.common import service


service中的launch的实现为(nova/openstack/common/service.py)

def launch(service, workers=1):
if workers is None or workers == 1:
launcher = ServiceLauncher()
launcher.launch_service(service)
else:
launcher = ProcessLauncher()
launcher.launch_service(service, workers=workers)

return launcher
此处有两种加载方法ServiceLauncher和ProcessLauncher

ServiceLauncher类中的launch_service 实现为:注意ServiceLauncher类中并没有单独定义此方法而是继承自其父类Launcher
<pre name="code" class="python"> def launch_service(self, service):
"""Load and start the given service.

:param service: The service you would like to start.
:returns: None

"""
service.backdoor_port = self.backdoor_port
self.services.add(service)



services.add()方法实现使用了GreenThread关于Greenthraed会在单独一个文章里面介绍。

def add(self, service):
self.services.append(service)
self.tg.add_thread(self.run_service, service, self.done)
def run_service(service, done):
"""Service start wrapper.

:param service: service to run
:param done: event to wait on until a shutdown is triggered
:returns: None

"""
service.start()
done.wait()


greenthread会执行run_service()方法。run_service()方法执行service.start()和done.wait(),完成了服务的启动,然后等待,一开始我看到Service类中有个start()方法,知道一个服务的启动实质性的内容都在这个方法里,但是就是找不到在哪里调用了这个方法,原来是在这里。。

def start(self):
verstr = version.version_string_with_package()
LOG.audit(_('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()
try:
self.service_ref = self.conductor_api.service_get_by_args(ctxt,
self.host, self.binary)
self.service_id = self.service_ref['id']
except exception.NotFound:
try:
self.service_ref = self._create_service_ref(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 = self.conductor_api.service_get_by_args(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",

4000
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)

def get_server(target, endpoints, serializer=None):
assert TRANSPORT is not None
serializer = RequestContextSerializer(serializer)
return messaging.get_rpc_server(TRANSPORT,
target,
endpoints,
executor='eventlet',
serializer=serializer)



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: