openstack nova 源码分析3-nova目录下的service.py

来源:互联网 发布:夜来风雨声花落知多少 编辑:程序博客网 时间:2024/05/16 19:30

nova下的service.py的源码,今天阅读之后 直接就把我理解的以注释的形式添加到了源码中,有些地方不好或者是错了,希望大家帮我指出!

  1.  
  2. import inspect  
  3. import os  
  4.  
  5. import eventlet  
  6. import greenlet  
  7.  
  8. from nova import context  
  9. from nova import db  
  10. from nova import exception  
  11. from nova import flags  
  12. from nova import log as logging  
  13. from nova import rpc  
  14. from nova import utils  
  15. from nova import version  
  16. from nova import wsgi  
  17.  
  18.  
  19. LOG = logging.getLogger('nova.service')  
  20.  
  21. FLAGS = flags.FLAGS#flags.py中有一句 FLAGS = FlagValues(),那么直接查看FlagValues()这个类,会发现这个类是继承于gflags.FlagValues.  
  22.  
  23. flags.DEFINE_integer('report_interval'10,  
  24.                      'seconds between nodes reporting state to datastore',  
  25.                      lower_bound=1)#参数名称,默认值和简短说明  
  26. flags.DEFINE_integer('periodic_interval'60,  
  27.                      'seconds between running periodic tasks',  
  28.                      lower_bound=1)  
  29. flags.DEFINE_string('ec2_listen'"0.0.0.0",  
  30.                     'IP address for EC2 API to listen')  
  31. flags.DEFINE_integer('ec2_listen_port'8773'port for ec2 api to listen')  
  32. flags.DEFINE_string('osapi_listen'"0.0.0.0",  
  33.                     'IP address for OpenStack API to listen')  
  34. flags.DEFINE_integer('osapi_listen_port'8774'port for os api to listen')  
  35. flags.DEFINE_string('api_paste_config'"api-paste.ini",  
  36.                     'File name for the paste.deploy config for nova-api')  
  37.  
  38. #Launcher 类 包含run_server ,launch_server,stop,wait 4个函数,其实功能非常简单,首先初始化Launcher将self_services弄成一个空列表  
  39. #run_server就是开始和等待一个server的完成,launcher_server就是将该server加入到该类初始化的列表中,  
  40. #stop 就是for循环遍历self_services列表中的服务然后一个一个的kill掉  
  41. #wait 函数就是 Waits until all services have been stopped  
  42. class Launcher(object):  
  43.     """Launch one or more services and wait for them to complete.""" 
  44.  
  45.     def __init__(self):  
  46.         """Initialize the service launcher.  
  47.  
  48.         :returns: None  
  49.  
  50.         """ 
  51.         self._services = []  
  52.  
  53.     @staticmethod 
  54.     def run_server(server):  
  55.         """Start and wait for a server to finish.  
  56.  
  57.         :param service: Server to run and wait for.  
  58.         :returns: None  
  59.  
  60.         """ 
  61.         server.start()  
  62.         server.wait()  
  63.  
  64.     def launch_server(self, server):#在360行被调用  
  65.         """Load and start the given server.  
  66.  
  67.         :param server: The server you would like to start.  
  68.         :returns: None  
  69.  
  70.         """ 
  71.         gt = eventlet.spawn(self.run_server, server)  
  72.         self._services.append(gt)  
  73.  
  74.     def stop(self):  
  75.         """Stop all services which are currently running.  
  76.  
  77.         :returns: None  
  78.  
  79.         """ 
  80.         for service in self._services:  
  81.             service.kill()  
  82.  
  83.     def wait(self):  
  84.         """Waits until all services have been stopped, and then returns.  
  85.  
  86.         :returns: None  
  87.  
  88.         """ 
  89.         for service in self._services:  
  90.             try:  
  91.                 service.wait()  
  92.             except greenlet.GreenletExit:  
  93.                 pass 
  94.  
  95.  
  96. class Service(object):  
  97.     """Service object for binaries running on hosts.  
  98.  
  99.     A service takes a manager and enables rpc by listening to queues based  
  100.     on topic. It also periodically runs tasks on the manager and reports  
  101.     it state to the database services table.""" 
  102.  
  103.     def __init__(self, host, binary, topic, manager, report_interval=None,  
  104.                  periodic_interval=None, *args, **kwargs):  
  105.         self.host = host  
  106.         self.binary = binary  
  107.         self.topic = topic  
  108.         #动态的生成manager类,并动态生成实例  
  109.         self.manager_class_name = manager#在create函数中指定  
  110.         manager_class = utils.import_class(self.manager_class_name)#动态的import该类  
  111.         self.manager = manager_class(host=self.host, *args, **kwargs)#动态的生成实例  
  112.         #  设置参数:应该是服务间隔时间之类的。  
  113.         self.report_interval = report_interval  
  114.         self.periodic_interval = periodic_interval  
  115.         #设置多出来的一些参数。  
  116.         super(Service, self).__init__(*args, **kwargs)  
  117.         self.saved_args, self.saved_kwargs = args, kwargs  
  118.         #设置一个列表 不知道是不是后面有需要用的地方 果然在185行 发现了  
  119.         self.timers = []  
  120.  
  121.     def start(self):  
  122.         #设置版本  
  123.         vcs_string = version.version_string_with_vcs()  
  124.         logging.audit(_('Starting %(topic)s node (version %(vcs_string)s)'),  
  125.                       {'topic'self.topic, 'vcs_string': vcs_string})  
  126.         #初始化host  
  127.         self.manager.init_host()  
  128.           
  129.         self.model_disconnected = False 
  130.         ctxt = context.get_admin_context()  
  131.         try:  
  132.             service_ref = db.service_get_by_args(ctxt,  
  133.                                                  self.host,  
  134.                                                  self.binary)  
  135.             self.service_id = service_ref['id']  
  136.         except exception.NotFound:  
  137.             self._create_service_ref(ctxt)#该函数位于187行  
  138.  
  139.         if 'nova-compute' == self.binary:  
  140.             self.manager.update_available_resource(ctxt)  
  141.  
  142.         self.conn = rpc.create_connection(new=True)  
  143.         logging.debug("Creating Consumer connection for Service %s" %  
  144.                       self.topic)  
  145.  
  146.         # Share this same connection for these Consumers  
  147.         self.conn.create_consumer(self.topic, self, fanout=False)  
  148.  
  149.         node_topic = '%s.%s' % (self.topic, self.host)#节点的topic 包括了topic 和 host  
  150.         self.conn.create_consumer(node_topic, self, fanout=False)  
  151.  
  152.         self.conn.create_consumer(self.topic, self, fanout=True)  
  153.  
  154.         # Consume from all consumers in a thread  
  155.         self.conn.consume_in_thread()  
  156.  
  157.         if self.report_interval:  
  158.             pulse = utils.LoopingCall(self.report_state)#在265中可以找到report_state 他的作用是在存储中更新服务的状态  
  159.             pulse.start(interval=self.report_interval, now=False)  
  160.             self.timers.append(pulse)  
  161.  
  162.         if self.periodic_interval:  
  163.             periodic = utils.LoopingCall(self.periodic_tasks)#在260行发现 Periodic_tasks任务在一个周期性间隔跑  
  164.             periodic.start(interval=self.periodic_interval, now=False)  
  165.             self.timers.append(periodic)  
  166.  
  167.     def _create_service_ref(self, context):  
  168.         zone = FLAGS.node_availability_zone  
  169.         service_ref = db.service_create(context,  
  170.                                         {'host'self.host,  
  171.                                          'binary'self.binary,  
  172.                                          'topic'self.topic,  
  173.                                          'report_count'0,  
  174.                                          'availability_zone': zone})  
  175.         self.service_id = service_ref['id']#猜测应该是获取当前服务的id  
  176.  
  177.     def __getattr__(self, key):  
  178.         manager = self.__dict__.get('manager'None)  
  179.         return getattr(manager, key)  
  180.  
  181.     @classmethod 
  182.     def create(cls, host=None, binary=None, topic=None, manager=None,  
  183.                report_interval=None, periodic_interval=None):  
  184.         """Instantiates class and passes back application object.  
  185.  
  186.         :param host: defaults to FLAGS.host  
  187.         :param binary: defaults to basename of executable  
  188.         :param topic: defaults to bin_name - 'nova-' part  
  189.         :param manager: defaults to FLAGS.<topic>_manager  
  190.         :param report_interval: defaults to FLAGS.report_interval  
  191.         :param periodic_interval: defaults to FLAGS.periodic_interval  
  192.  
  193.         """ 
  194.         if not host:  
  195.             host = FLAGS.host  
  196.         if not binary:  
  197.             binary = os.path.basename(inspect.stack()[-1][1])  
  198.         if not topic:  
  199.             topic = binary.rpartition('nova-')[2]  
  200.         if not manager:  
  201.             manager = FLAGS.get('%s_manager' % topic, None)  
  202.         if not report_interval:  
  203.             report_interval = FLAGS.report_interval  
  204.         if not periodic_interval:  
  205.             periodic_interval = FLAGS.periodic_interval  
  206.         service_obj = cls(host, binary, topic, manager,  
  207.                           report_interval, periodic_interval)#此处 调用的是该类的init的默认函数       
  208.  
  209.         return service_obj  
  210.  
  211.     def kill(self):  
  212.         """Destroy the service object in the datastore.""" 
  213.         self.stop()  
  214.         try:  
  215.             db.service_destroy(context.get_admin_context(), self.service_id)  
  216.         except exception.NotFound:  
  217.             logging.warn(_('Service killed that has no database entry'))  
  218.  
  219.     def stop(self):  
  220.         # Try to shut the connection down, but if we get any sort of  
  221.         # errors, go ahead and ignore them.. as we're shutting down anyway  
  222.         try:  
  223.             self.conn.close()  
  224.         except Exception:  
  225.             pass 
  226.         for x in self.timers:   #遍历曾经添加到self.timers中的每一个“间隔”(不是很清楚) 然后将其stop  
  227.             try:  
  228.                 x.stop()  
  229.             except Exception:  
  230.                 pass 
  231.         self.timers = [] #重新将self.timers置空  
  232.  
  233.     def wait(self):  
  234.         for x in self.timers:  
  235.             try:  
  236.                 x.wait()  
  237.             except Exception:  
  238.                 pass 
  239.  
  240.     def periodic_tasks(self):  
  241.         """Tasks to be run at a periodic interval.""" 
  242.         #任务在一个周期性间隔跑  
  243.         self.manager.periodic_tasks(context.get_admin_context())  
  244.  
  245.     def report_state(self):  
  246.         """Update the state of this service in the datastore.""" 
  247.         #在数据存储更新服务的状态。  
  248.         ctxt = context.get_admin_context()  
  249.         try:  
  250.             try:  
  251.                 service_ref = db.service_get(ctxt, self.service_id)  
  252.             except exception.NotFound:  
  253.                 logging.debug(_('The service database object disappeared, ' 
  254.                                 'Recreating it.'))  
  255.                 self._create_service_ref(ctxt)  
  256.                 service_ref = db.service_get(ctxt, self.service_id)  
  257.  
  258.             db.service_update(ctxt,  
  259.                              self.service_id,  
  260.                              {'report_count': service_ref['report_count'] + 1})  
  261.  
  262.             # TODO(termie): make this pattern be more elegant.  
  263.             if getattr(self'model_disconnected'False):  
  264.                 self.model_disconnected = False 
  265.                 logging.error(_('Recovered model server connection!'))  
  266.  
  267.         # TODO(vish): this should probably only catch connection errors  
  268.         except Exception:  # pylint: disable=W0702  
  269.             if not getattr(self'model_disconnected'False):  
  270.                 self.model_disconnected = True 
  271.                 logging.exception(_('model server went away'))  
  272.  
  273.  
  274. class WSGIService(object):  
  275.     """Provides ability to launch API from a 'paste' configuration.""" 
  276.     #提供能够从一个‘paste’配置启动api的服务  
  277.  
  278.     def __init__(self, name, loader=None):  
  279.         """Initialize, but do not start the WSGI server.  
  280.  
  281.         :param name: The name of the WSGI server given to the loader.  
  282.         :param loader: Loads the WSGI application using the given name.  
  283.         :returns: None  
  284.  
  285.         """ 
  286.         #初始化 但是并没有开是wsgi的服务。  
  287.         self.name = name  
  288.         self.loader = loader or wsgi.Loader()  
  289.         self.app = self.loader.load_app(name)#将wsgi服务的名字给到self.loader,然后用那名字将其 装载到wsgi application  
  290.         self.host = getattr(FLAGS, '%s_listen' % name, "0.0.0.0"#返回主机host getattr Found at: __builtin__  
  291.         #getattr(object, name[, default]) -> value得知返回的是value  
  292.  
  293.  
  294.         self.port = getattr(FLAGS, '%s_listen_port' % name, 0)#端口 port  
  295.         self.server = wsgi.Server(name,  
  296.                                   self.app,  
  297.                                   host=self.host,  
  298.                                   port=self.port)  
  299.  
  300.     def start(self):  
  301.         """Start serving this service using loaded configuration.  
  302.  
  303.         Also, retrieve updated port number in case '0' was passed in, which  
  304.         indicates a random port should be used.  
  305.  
  306.         :returns: None  
  307.  
  308.         """ 
  309.         self.server.start()  
  310.         self.port = self.server.port  
  311.  
  312.     def stop(self):  
  313.         """Stop serving this API.  
  314.  
  315.         :returns: None  
  316.  
  317.         """ 
  318.         self.server.stop()  
  319.  
  320.     def wait(self):  
  321.         """Wait for the service to stop serving this API.  
  322.  
  323.         :returns: None  
  324.  
  325.         """ 
  326.         self.server.wait()  
  327.  
  328.  
  329. # NOTE(vish): the global launcher is to maintain the existing  
  330. #             functionality of calling service.serve +  
  331. #             service.wait  
  332. _launcher = None 
  333.  
  334.  
  335. def serve(*servers):  
  336.     global _launcher  
  337.     if not _launcher:  
  338.         _launcher = Launcher() #s实例化Launcher  
  339.     for server in servers:  
  340.         _launcher.launch_server(server)  
  341.  
  342.  
  343. def wait():  
  344.     # After we've loaded up all our dynamic bits, check  
  345.     # whether we should print help  
  346.       
  347.  
  348.     #flags.py中 有一句  
  349.     #FLAGS = FlagValues(),那么直接查看FlagValues()这个类,这个类是继承于gflags.FlagValues.  
  350.  
  351.  
  352.     flags.DEFINE_flag(flags.HelpFlag())  
  353.     flags.DEFINE_flag(flags.HelpshortFlag())  
  354.     flags.DEFINE_flag(flags.HelpXMLFlag())  
  355.     FLAGS.ParseNewFlags()  
  356.     logging.debug(_('Full set of FLAGS:'))  
  357.     for flag in FLAGS:  
  358.         flag_get = FLAGS.get(flag, None)  
  359.         logging.debug('%(flag)s : %(flag_get)s' % locals())  
  360.     try:  
  361.         _launcher.wait()  
  362.     except KeyboardInterrupt:  
  363.         _launcher.stop()  

 

本文出自 “LuoZhengWu” 博客,请务必保留此出处http://brucemars.blog.51cto.com/5288106/965124

0 0