nova-compute启动分析-1
来源:互联网 发布:华为淘宝无法联网 编辑:程序博客网 时间:2024/05/17 01:58
python启动脚本 bin/nova-compute
utils.default_flagfile() #设置flag文件路径. flags.FLAGS(sys.argv) #把flag文件中的参数放到args中。 logging.setup() #设置日志 utils.monkey_patch() server = service.Service.create(binary='nova-compute') #创建服务 service.serve(server) #启动服务 service.wait() #等待请求
下面我讲按6大步进行讲述:
第一步:utils.default_flagfile()
if args is None: args = sys.argv for arg in args: if arg.find('flagfile') != -1: break else: if not os.path.isabs(filename): # turn relative filename into an absolute path script_dir = os.path.dirname(inspect.stack()[-1][1]) filename = os.path.abspath(os.path.join(script_dir, filename)) if not os.path.exists(filename): filename = "./nova.conf" if not os.path.exists(filename): filename = '/etc/nova/nova.conf' flagfile = '--flagfile=%s' % filename args.insert(1, flagfile) 其实所完成的功能也就是把--flagfile=/etc/nova/nova.conf加到入参数列表中。
第二步:flags.FLAGS(sys.argv)
flags.py中有一句
FLAGS = FlagValues(),那么直接查看FlagValues()这个类,这个类是继承于gflags.FlagValues.
第三步:logging.setup()
这个是对这个服务开启日志功能。
第四步:server = service.Service.create(binary='nova-compute')
这个函数位于/nova/service.py: 类Service中
class Service(object): """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 it state to the database services table.""" 函数定义如下: @classmethod def create(cls, host=None, binary=None, topic=None, manager=None, report_interval=None, periodic_interval=None): """Instantiates class and passes back application object. :param host: defaults to FLAGS.host :param binary: defaults to basename of executable :param topic: defaults to bin_name - 'nova-' part :param manager: defaults to FLAGS.<topic>_manager :param report_interval: defaults to FLAGS.report_interval :param periodic_interval: defaults to FLAGS.periodic_interval """ if not host: host = FLAGS.host #host name ‘nova’ if not binary: binary = os.path.basename(inspect.stack()[-1][1]) # 这是因为python可以查看动栈的内容。 # 所以可以得到压入栈中的脚本的名字 这时,binary="nova-compute" if not topic: topic = binary.rpartition('nova-')[2] #设置topic的名字:也就是把 binary的nova-去掉。 if not manager: manager = FLAGS.get('%s_manager' % topic, None) #很明显这里得到的是compute_manager. if not report_interval: report_interval = FLAGS.report_interval if not periodic_interval: periodic_interval = FLAGS.periodic_interval service_obj = cls(host, binary, topic, manager, report_interval, periodic_interval) #利用 Service.__init__()构造函数生成一个对象 return service_obj
接下来我们看看Service.__init__()
def __init__(self, host, binary, topic, manager, report_interval=None, periodic_interval=None, *args, **kwargs): self.host = host self.binary = binary self.topic = topic self.manager_class_name = manager manager_class = utils.import_class(self.manager_class_name) self.manager = manager_class(host=self.host, *args, **kwargs) self.report_interval = report_interval self.periodic_interval = periodic_interval super(Service, self).__init__(*args, **kwargs) self.saved_args, self.saved_kwargs = args, kwargs self.timers = []
1、指定host、binary、topic。这个相对简单。
self.host = host
self.binary = binary
self.topic = topic
2、动态指定manager类,并动态生成实例 。
self.manager_class_name = manager #在create函数中指定。
manager_class = utils.import_class(self.manager_class_name) #动态地import此类。
self.manager = manager_class(host=self.host, *args, **kwargs) #动态地生成这个类的实例 。
那么这时会调用ComputeManager::__init__()函数
我们进入ComputeManager::__init__()函数
def __init__(self, compute_driver=None, *args, **kwargs): """Load configuration options and connect to the hypervisor.""" # TODO(vish): sync driver creation logic with the rest of the system # and re-document the module docstring if not compute_driver: compute_driver = FLAGS.compute_driver #这部分在后面会仔细分析 #cfg.StrOpt('compute_driver',default='nova.virt.connection.get_connection', #help='Driver to use for controlling virtualization') try: self.driver = utils.check_isinstance( utils.import_object(compute_driver), driver.ComputeDriver) #动态的加载 虚拟机的控制驱动对象 except ImportError as e: LOG.error(_("Unable to load the virtualization driver: %s") % (e)) sys.exit(1) self.network_api = network.API() self.volume_api = volume.API() self.network_manager = utils.import_object(FLAGS.network_manager) self._last_host_check = 0 self._last_bw_usage_poll = 0 self._last_info_cache_heal = 0 super(ComputeManager, self).__init__(service_name="compute", *args, **kwargs)
3、设置参数:应该是服务间隔时间之类的。
self.report_interval = report_interval
self.periodic_interval = periodic_interval
4、 设置多出来的一些参数。
super(Service, self).__init__(*args, **kwargs)
self.saved_args, self.saved_kwargs = args, kwargs
self.timers = []
第五步:service.serve(server)开启服务
def serve(*servers): global _launcher # class Launcher 一个全局对象 if not _launcher: _launcher = Launcher() for server in servers: _launcher.launch_server(server)
类Launcher 主要作用是为每个服务开启一个线程
def launch_server(self, server): """Load and start the given server. :param server: The server you would like to start. :returns: None """ gt = eventlet.spawn(self.run_server, server) #启动线程运行 run_server self._services.append(gt) #保存到 _services里面 @staticmethod def run_server(server): """Start and wait for a server to finish. :param service: Server to run and wait for. :returns: None """ server.start() server.wait()
def start(self): vcs_string = version.version_string_with_vcs() #获取版本号 LOG.audit(_('Starting %(topic)s node (version %(vcs_string)s)'), {'topic': self.topic, 'vcs_string': vcs_string}) utils.cleanup_file_locks() #清除锁文件 self.manager.init_host() self.model_disconnected = False ctxt = context.get_admin_context() try: service_ref = db.service_get_by_args(ctxt, self.host, self.binary) self.service_id = service_ref['id'] except exception.NotFound: self._create_service_ref(ctxt) if 'nova-compute' == self.binary: self.manager.update_available_resource(ctxt) self.conn = rpc.create_connection(new=True) LOG.debug(_("Creating Consumer connection for Service %s") % self.topic) # Share this same connection for these Consumers self.conn.create_consumer(self.topic, self, fanout=False) node_topic = '%s.%s' % (self.topic, self.host) self.conn.create_consumer(node_topic, self, fanout=False) self.conn.create_consumer(self.topic, self, fanout=True) # Consume from all consumers in a thread self.conn.consume_in_thread() if self.report_interval: pulse = utils.LoopingCall(self.report_state) pulse.start(interval=self.report_interval, now=False) self.timers.append(pulse) if self.periodic_interval: periodic = utils.LoopingCall(self.periodic_tasks) periodic.start(interval=self.periodic_interval, now=False) self.timers.append(periodic)
下面我们对start方法进行分析:
1、设置版本
vcs_string = version.version_string_with_vcs()
logging.audit(_('Starting %(topic)s node (version %(vcs_string)s)'),
{'topic': self.topic, 'vcs_string': vcs_string})
2、初始化init_host(self): nova.compute.ComputeManager
其中 self.driver.init_host(host=self.host)
这里需要查看一下在__init__函数中driver的设置。
if not compute_driver:
compute_driver = FLAGS.compute_driver
FLAGS.compute_driver的值也是在/nova/compute/manager.py中设置:
flags.DEFINE_string('compute_driver', 'nova.virt.connection.get_connection',
'Driver to use for controlling virtualization')
关于get_connection下篇blog继续分析
3 . 接着从service.start()接着init_host()之后,
得到context.然后再更新当前机器上可用的资源。
self.model_disconnected = False ctxt = context.get_admin_context() try: service_ref = db.service_get_by_args(ctxt, self.host, self.binary) self.service_id = service_ref['id'] except exception.NotFound: self._create_service_ref(ctxt) if 'nova-compute' == self.binary: self.manager.update_available_resource(ctxt)
4. 更新RPC链接
self.conn = rpc.create_connection(new=True) LOG.debug(_("Creating Consumer connection for Service %s") % self.topic) # Share this same connection for these Consumers self.conn.create_consumer(self.topic, self, fanout=False) node_topic = '%s.%s' % (self.topic, self.host) self.conn.create_consumer(node_topic, self, fanout=False) self.conn.create_consumer(self.topic, self, fanout=True) # Consume from all consumers in a thread self.conn.consume_in_thread() if self.report_interval: pulse = utils.LoopingCall(self.report_state) #循环调用report_state pulse.start(interval=self.report_interval, now=False) self.timers.append(pulse) if self.periodic_interval: periodic = utils.LoopingCall(self.periodic_tasks) #循环调用 periodic_tasks 下面详细说明 periodic.start(interval=self.periodic_interval, now=False) self.timers.append(periodic)
Nova-Compute启动的主要工作是把环境配置好。让RqbbitMQ的消息队列建立起来。最后服务的启动则主要是让rabbitmq的consumer运行。并且进入wait状态。消息的响应则主要是找到相应的函数地址,并执行之。
六. Wait() 等待
一般服务启动之后,都会有wait()。那么这里也需要看一下服务的wait()。从而可以知道是什么东西在后台真正地运行。
/usr/bin/nova-computeservice.wait()/nova/service.py:Class:Service::wait() def wait(self): for x in self.timers: try: x.wait() except Exception: pass
- nova-compute启动分析-1
- nova-compute启动分析
- nova-compute启动分析-2
- nova-compute启动分析-3
- nova-compute启动分析之一
- NOVA架构 nova-compute启动分析
- 【Nova】nova-compute代码学习1-启动时准备工作
- 【OpenStack源码分析之三】Nova-Compute启动流程分析
- openstack nova 源码分析2之nova-api,nova-compute
- OpenStack源码分析之Nova-Compute服务启动过程(icehouse)
- nova-compute
- 【OpenStack源码分析之十】虚机启动流程中Nova Compute与周边组件的交互
- nova-compute不能成功启动的原因总结
- Openstack liberty中nova-compute服务的启动过程
- 启动nova-compute不成功报错AMQP server controller:5672
- OpenStack Compute(Nova)功能分析
- OpenStack Compute(Nova)功能分析
- OpenStack Compute(Nova)功能分析
- BOOST 字符串查找示例
- Expression Tree 上手指南 (三)
- exe注册成windows服务
- InternetOpen\InternetOpenUrl\InternetReadFile 等相关Win32 网络API 使用详细说明
- javascript大括号赋值给变量
- nova-compute启动分析-1
- zend framework环境搭建
- 【weka】官网常用链接
- oracle 常用操作/常用查询
- 如何遍历一个实例的所有属性,得到属性的名称和值
- 自动化部署实践capistrano
- 简单的POST提交方法
- <<java面试宝典>>学习笔记
- IOS判断设备是否已越狱(isJailbroken)