在openstack中,消息的传递一共有两种方式,分别是:服务之间的传递调用Restful api,服务中模块之间的传递使用消息队列。每一个模块在启动是都会启动消息队列,等待队列中的有消息到来。所以模块的启动是openstack运行起来最早做的工作。以nova-compute模块为例,说明该服务模块是如何启动并运行的。
nova的架构设计图如下:
nova启动时使用service命令,如下图:

service命令实际上是调用/etc/init.d/nova-compute来实现的。在/etc/init.d/文件下有一个nova-compute脚本,负责nova-compute的启动,停止,状态查询等。


/etc/init.d/nova-compute脚本的执行是通过/etc/init/nova-compute.conf中的配置项来完成的,下面看看nova-compute.conf文件中的内容。

/etc/init/nova-compute.conf
1 #!/bin/sh
2 ### BEGIN INIT INFO
3 # Provides: nova-compute
4 # Required-Start: $network $local_fs $remote_fs $syslog
5 # Required-Stop: $remote_fs
6 # Should-Start: libvirt-bin postgresql mysql keystone rabbitmq-server ntp neutron-ovs-cleanup
7 # Should-Stop: libvirt-bin postgresql mysql keystone rabbitmq-server ntp
8 # Default-Start: 2 3 4 5
9 # Default-Stop: 0 1 6
10 # Short-Description: Nova Compute server
11 # Description: Provides compute server resources for the
12 # OpenStack cloud computing system
13 ### END INIT INFO
14
15 # Author: Julien Danjou <acid@debian.org>
16
17 # PATH should only include /usr/* if it runs after the mountnfs.sh script
18 PATH=/sbin:/usr/sbin:/bin:/usr/bin
19 DESC="OpenStack Compute"
20 PROJECT_NAME=nova
21 NAME=${PROJECT_NAME}-compute
22 DAEMON_ARGS=""
23 if [ -f '/etc/nova/nova-compute.conf' ] ; then
24 DAEMON_ARGS="--config-file=/etc/nova/nova-compute.conf"
25 fi
26
27 #!/bin/sh
28 # The content after this line comes from openstack-pkg-tools
29 # and has been automatically added to a .init.in script, which
30 # contains only the descriptive part for the daemon. Everything
31 # else is standardized as a single unique script.
32
33 # Author: Thomas Goirand <zigo@debian.org>
34
35 # PATH should only include /usr/* if it runs after the mountnfs.sh script
36 PATH=/sbin:/usr/sbin:/bin:/usr/bin
37
38 if [ -z "${DAEMON}" ] ; then
39 DAEMON=/usr/bin/${NAME}
40 fi
41 PIDFILE=/var/run/${PROJECT_NAME}/${NAME}.pid
42 if [ -z "${SCRIPTNAME}" ] ; then
43 SCRIPTNAME=/etc/init.d/${NAME}
44 fi
45 if [ -z "${SYSTEM_USER}" ] ; then
46 SYSTEM_USER=${PROJECT_NAME}
47 fi
48 if [ -z "${SYSTEM_GROUP}" ] ; then
49 SYSTEM_GROUP=${PROJECT_NAME}
50 fi
51 if [ "${SYSTEM_USER}" != "root" ] ; then
52 STARTDAEMON_CHUID="--chuid ${SYSTEM_USER}:${SYSTEM_GROUP}"
53 fi
54 if [ -z "${CONFIG_FILE}" ] ; then
55 CONFIG_FILE=/etc/${PROJECT_NAME}/${PROJECT_NAME}.conf
56 fi
57 LOGFILE=/var/log/${PROJECT_NAME}/${NAME}.log
58 if [ -z "${NO_OPENSTACK_CONFIG_FILE_DAEMON_ARG}" ] ; then
59 DAEMON_ARGS="--config-file=${CONFIG_FILE} ${DAEMON_ARGS}"
60 fi
61
62 # Exit if the package is not installed
63 [ -x $DAEMON ] || exit 0
64
65 # If ran as root, create /var/lock/X, /var/run/X, /var/lib/X and /var/log/X as needed
66 if [ `whoami` = "root" ] ; then
67 for i in lock run lib ; do
68 mkdir -p /var/$i/${PROJECT_NAME}
69 chown ${SYSTEM_USER}:${SYSTEM_GROUP} /var/$i/${PROJECT_NAME}
70 done
71 for i in log ; do
72 mkdir -p /var/$i/${PROJECT_NAME}
73 chown ${SYSTEM_USER}:adm /var/$i/${PROJECT_NAME}
74 done
75 fi
76
77 # This defines init_is_upstart which we use later on (+ more...)
78 . /lib/lsb/init-functions
79
80 # Manage log options: logfile and/or syslog, depending on user's choosing
81 [ -r /etc/default/openstack ] && . /etc/default/openstack
82 [ -r /etc/default/$NAME ] && . /etc/default/$NAME
83 [ "x$USE_SYSLOG" = "xyes" ] && DAEMON_ARGS="$DAEMON_ARGS --use-syslog"
84 if [ -z "${NO_OPENSTACK_LOGFILE_DAEMON_ARG}" ] ; then
85 [ "x$USE_LOGFILE" != "xno" ] && DAEMON_ARGS="$DAEMON_ARGS --log-file=$LOGFILE"
86 fi
87
88 do_start() {
89 start-stop-daemon --start --quiet --background ${STARTDAEMON_CHUID} --make-pidfile --pidfile ${PIDFILE} --chdir /var/lib/${PROJECT_NAME} --startas $DAEMON \
90 --test > /dev/null || return 1
91 start-stop-daemon --start --quiet --background ${STARTDAEMON_CHUID} --make-pidfile --pidfile ${PIDFILE} --chdir /var/lib/${PROJECT_NAME} --startas $DAEMON \
92 -- $DAEMON_ARGS || return 2
93 }
94
95 do_stop() {
96 start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE
97 RETVAL=$?
98 rm -f $PIDFILE
99 return "$RETVAL"
100 }
101
102 do_systemd_start() {
103 exec $DAEMON $DAEMON_ARGS
104 }
105
106 case "$1" in
107 start)
108 init_is_upstart > /dev/null 2>&1 && exit 1
109 log_daemon_msg "Starting $DESC" "$NAME"
110 do_start
111 case $? in
112 0|1) log_end_msg 0 ;;
113 2) log_end_msg 1 ;;
114 esac
115 ;;
116 stop)
117 init_is_upstart > /dev/null 2>&1 && exit 0
118 log_daemon_msg "Stopping $DESC" "$NAME"
119 do_stop
120 case $? in
121 0|1) log_end_msg 0 ;;
122 2) log_end_msg 1 ;;
123 esac
124 ;;
125 status)
126 status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
127 ;;
128 systemd-start)
129 do_systemd_start
130 ;;
131 restart|force-reload)
132 init_is_upstart > /dev/null 2>&1 && exit 1
133 log_daemon_msg "Restarting $DESC" "$NAME"
134 do_stop
135 case $? in
136 0|1)
137 do_start
138 case $? in
139 0) log_end_msg 0 ;;
140 1) log_end_msg 1 ;; # Old process is still running
141 *) log_end_msg 1 ;; # Failed to start
142 esac
143 ;;
144 *) log_end_msg 1 ;; # Failed to stop
145 esac
146 ;;
147 *)
148 echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload|systemd-start}" >&2
149 exit 3
150 ;;
151 esac
152
153 exit 0
/etc/init/nova-compute.conf
1 # vim: set ft=upstart et ts=2:
2 description "Nova compute worker"
3 author "Soren Hansen <soren@linux2go.dk>"
4
5 start on runlevel [2345]
6 stop on runlevel [!2345]
7
8 chdir /var/run
9
10 env MAX_STATUS_CHECK_RETRIES=20
11
12 pre-start script
13 mkdir -p /var/run/nova
14 chown nova:root /var/run/nova/
15
16 mkdir -p /var/lock/nova
17 chown nova:root /var/lock/nova/
18
19 # Only try to modprobe if not running within a container
20 if [ ! -f /run/container_type ]; then
21 modprobe nbd
22 fi
23
24 # If libvirt-bin is installed, always wait for it to start first
25 if status libvirt-bin; then
26 start wait-for-state WAIT_FOR=libvirt-bin WAIT_STATE=running WAITER=nova-compute
27 fi
28
29 # If installed, wait for neutron-ovs-cleanup to complete prior to starting
30 # nova-compute.
31 if status neutron-ovs-cleanup; then
32 # See LP #1471022 for explanation of why we do like this
33 retries=$MAX_STATUS_CHECK_RETRIES
34 delay=1
35 while true; do
36 # Already running?
37 s=`status neutron-ovs-cleanup`
38 echo $s
39 `echo $s| grep -qE "\sstart/running"` && break
40 if retries=`expr $retries - 1`; then
41 # Give it a push
42 echo "Attempting to start neutron-ovs-cleanup"
43 start neutron-ovs-cleanup || :
44 # Wait a bit to avoid hammering ovs-cleanup (which itself may be waiting
45 # on dependencies)
46 echo "Recheck neutron-ovs-cleanup status in ${delay}s"
47 sleep $delay
48 if _=`expr $retries % 2`; then
49 delay=`expr $delay + 2`
50 fi
51 else
52 echo "Max retries ($MAX_STATUS_CHECK_RETRIES) reached - no longer waiting for neutron-ovs-cleanup to start"
53 break
54 fi
55 done
56 fi
57 end script
58
59 exec start-stop-daemon --start --chuid nova --exec /usr/bin/nova-compute -- --config-file=/etc/nova/nova.conf --config-file=/etc/nova/nova-compute.conf
其中最后一行代码是关键代码,这个脚本之所以能启动是执行了nova-compute的可执行脚本,位置在/usr/bin/nova-compute。
/usr/bin/nova-compute
1 #!/usr/bin/python 2 # PBR Generated from u'console_scripts' 3 4 import sys 5 6 from nova.cmd.compute import main 7 8 9 if __name__ == "__main__": 10 sys.exit(main())
该脚本导入了/nova/cmd/compute中的main函数来完成启动任务。
/nova/nova/cmd/compute
1 # Copyright 2010 United States Government as represented by the
2 # Administrator of the National Aeronautics and Space Administration.
3 # All Rights Reserved.
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License"); you may
6 # not use this file except in compliance with the License. You may obtain
7 # a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 # License for the specific language governing permissions and limitations
15 # under the License.
16
17 """Starter script for Nova Compute."""
18
19 import shlex
20 import sys
21
22 import os_vif
23 from oslo_log import log as logging
24 from oslo_privsep import priv_context
25 from oslo_reports import guru_meditation_report as gmr
26
27 from nova.cmd import common as cmd_common
28 from nova.conductor import rpcapi as conductor_rpcapi
29 import nova.conf
30 from nova import config
31 from nova import objects
32 from nova.objects import base as objects_base
33 from nova import service
34 from nova import utils
35 from nova import version
36
37 CONF = nova.conf.CONF
38 LOG = logging.getLogger('nova.compute')
39
40
41 def main():
42 config.parse_args(sys.argv)
43 logging.setup(CONF, 'nova')
44 priv_context.init(root_helper=shlex.split(utils.get_root_helper()))
45 utils.monkey_patch()
46 objects.register_all()
47 # Ensure os-vif objects are registered and plugins loaded
48 os_vif.initialize()
49
50 gmr.TextGuruMeditation.setup_autorun(version)
51
52 cmd_common.block_db_access('nova-compute')
53 objects_base.NovaObject.indirection_api = conductor_rpcapi.ConductorAPI()
54
55 server = service.Service.create(binary='nova-compute',
56 topic=CONF.compute_topic)
57 service.serve(server)
58 service.wait()
1 # Copyright 2010 United States Government as represented by the 2 # Administrator of the National Aeronautics and Space Administration. 3 # All Rights Reserved. 4 # Copyright 2012 Red Hat, Inc. 5 # 6 # Licensed under the Apache License, Version 2.0 (the "License"); you may 7 # not use this file except in compliance with the License. You may obtain 8 # a copy of the License at 9 # 10 # http://www.apache.org/licenses/LICENSE-2.0 11 # 12 # Unless required by applicable law or agreed to in writing, software 13 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15 # License for the specific language governing permissions and limitations 16 # under the License. 17 18 from oslo_log import log 19 20 from nova.common import config 21 import nova.conf 22 from nova.db.sqlalchemy import api as sqlalchemy_api 23 from nova import rpc 24 from nova import version 25 26 27 CONF = nova.conf.CONF 28 29 30 def parse_args(argv, default_config_files=None, configure_db=True, 31 init_rpc=True): 32 log.register_options(CONF) 33 # We use the oslo.log default log levels which includes suds=INFO 34 # and add only the extra levels that Nova needs 35 if CONF.glance.debug: 36 extra_default_log_levels = ['glanceclient=DEBUG'] 37 else: 38 extra_default_log_levels = ['glanceclient=WARN'] 39 log.set_defaults(default_log_levels=log.get_default_log_levels() + 40 extra_default_log_levels) 41 rpc.set_defaults(control_exchange='nova') 42 config.set_middleware_defaults() 43 44 CONF(argv[1:], 45 project='nova', 46 version=version.version_string(), 47 default_config_files=default_config_files) 48 49 if init_rpc: 50 rpc.init(CONF) 51 52 if configure_db: 53 sqlalchemy_api.configure(CONF)
/nova/nova/service.py
1 class Service(service.Service): 2 """Service object for binaries running on hosts. 3 4 A service takes a manager and enables rpc by listening to queues based 5 on topic. It also periodically runs tasks on the manager and reports 6 its state to the database services table. 7 """ 8 9 def __init__(self, host, binary, topic, manager, report_interval=None, 10 periodic_enable=None, periodic_fuzzy_delay=None, 11 periodic_interval_max=None, db_allowed=True, 12 *args, **kwargs): 13 super(Service, self).__init__() 14 self.host = host 15 self.binary = binary 16 self.topic = topic 17 self.manager_class_name = manager 18 self.servicegroup_api = servicegroup.API() 19 manager_class = importutils.import_class(self.manager_class_name) 20 self.manager = manager_class(host=self.host, *args, **kwargs) 21 self.rpcserver = None 22 self.report_interval = report_interval 23 self.periodic_enable = periodic_enable 24 self.periodic_fuzzy_delay = periodic_fuzzy_delay 25 self.periodic_interval_max = periodic_interval_max 26 self.saved_args, self.saved_kwargs = args, kwargs 27 self.backdoor_port = None 28 self.conductor_api = conductor.API(use_local=db_allowed) 29 self.conductor_api.wait_until_ready(context.get_admin_context())
/nova/nova/service.py
1 @classmethod
2 def create(cls, host=None, binary=None, topic=None, manager=None,
3 report_interval=None, periodic_enable=None,
4 periodic_fuzzy_delay=None, periodic_interval_max=None,
5 db_allowed=True):
6 """Instantiates class and passes back application object.
7
8 :param host: defaults to CONF.host
9 :param binary: defaults to basename of executable
10 :param topic: defaults to bin_name - 'nova-' part
11 :param manager: defaults to CONF.<topic>_manager
12 :param report_interval: defaults to CONF.report_interval
13 :param periodic_enable: defaults to CONF.periodic_enable
14 :param periodic_fuzzy_delay: defaults to CONF.periodic_fuzzy_delay
15 :param periodic_interval_max: if set, the max time to wait between runs
16
17 """
18 if not host:
19 host = CONF.host
20 if not binary:
21 binary = os.path.basename(sys.argv[0])
22 if not topic:
23 topic = binary.rpartition('nova-')[2]
24 if not manager:
25 manager_cls = ('%s_manager' %
26 binary.rpartition('nova-')[2])
27 manager = CONF.get(manager_cls, None)
28 if report_interval is None:
29 report_interval = CONF.report_interval
30 if periodic_enable is None:
31 periodic_enable = CONF.periodic_enable
32 if periodic_fuzzy_delay is None:
33 periodic_fuzzy_delay = CONF.periodic_fuzzy_delay
34
35 debugger.init()
36
37 service_obj = cls(host, binary, topic, manager,
38 report_interval=report_interval,
39 periodic_enable=periodic_enable,
40 periodic_fuzzy_delay=periodic_fuzzy_delay,
41 periodic_interval_max=periodic_interval_max,
42 db_allowed=db_allowed)
43
44 return service_obj
/nova/nova/service.py
1 def serve(server, workers=None):
2 global _launcher
3 if _launcher:
4 raise RuntimeError(_('serve() can only be called once'))
5
6 _launcher = service.launch(CONF, server, workers=workers)
未完待续。。。。。
来源:https://www.cnblogs.com/goldsunshine/p/8675462.html