openstack服务启动之nova-compute

半城伤御伤魂 提交于 2019-12-17 12:32:44

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

 

未完待续。。。。。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!