text: # vim: tabstop=4 shiftwidth=4 softtabstop=4
  
  # Copyright 2010 United States Government as represented by the
  # Administrator of the National Aeronautics and Space Administration.
  # Copyright 2011 Justin Santa Barbara
  # Copyright (c) 2012 Samsung SDS Co., LTD
  # All Rights Reserved.
  #
  #    Licensed under the Apache License, Version 2.0 (the "License"); you may
  #    not use this file except in compliance with the License. You may obtain
  #    a copy of the License at
  #
  #         http://www.apache.org/licenses/LICENSE-2.0
  #
  #    Unless required by applicable law or agreed to in writing, software
  #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  #    License for the specific language governing permissions and limitations
  #    under the License.
  
  """Generic Node base class for all workers that run on hosts."""
  
  import inspect
  import os
  
  import eventlet
  import greenlet
  
  from synaps import context
  #from synaps import db
  from synaps import exception
  from synaps import flags
  from synaps import log as logging
  from synaps.openstack.common import cfg
  #from synaps import rpc
  from synaps import utils
  from synaps import version
  from synaps import wsgi
  
  
  LOG = logging.getLogger(__name__)
  
  service_opts = [
      cfg.IntOpt('report_interval',
                 default=10,
                 help='seconds between nodes reporting state to datastore'),
      cfg.IntOpt('periodic_interval',
                 default=60,
                 help='seconds between running periodic tasks'),
  ]
  
  FLAGS = flags.FLAGS
  FLAGS.register_opts(service_opts)
  
  
  class Launcher(object):
      """Launch one or more services and wait for them to complete."""
  
      def __init__(self):
          """Initialize the service launcher.
  
          :returns: None
  
          """
          self._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 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)
          self._services.append(gt)
  
      def stop(self):
          """Stop all services which are currently running.
  
          :returns: None
  
          """
          for service in self._services:
              service.kill()
  
      def wait(self):
          """Waits until all services have been stopped, and then returns.
  
          :returns: None
  
          """
          for service in self._services:
              try:
                  service.wait()
              except greenlet.GreenletExit:
                  pass
  
  
  class WSGIService(object):
      """Provides ability to launch API from a 'paste' configuration."""
  
      def __init__(self, name, loader=None):
          """Initialize, but do not start the WSGI server.
  
          :param name: The name of the WSGI server given to the loader.
          :param loader: Loads the WSGI application using the given name.
          :returns: None
  
          """
          self.name = name
          self.manager = self._get_manager()
          self.loader = loader or wsgi.Loader()
          self.app = self.loader.load_app(name)
          self.host = getattr(FLAGS, '%s_listen' % name, "0.0.0.0")
          self.port = getattr(FLAGS, '%s_listen_port' % name, 0)
          self.server = wsgi.Server(name,
                                    self.app,
                                    host=self.host,
                                    port=self.port)
          
      def _get_manager(self):
          """Initialize a Manager object appropriate for this service.
  
          Use the service name to look up a Manager subclass from the
          configuration and initialize an instance. If no class name
          is configured, just return None.
  
          :returns: a Manager instance, or None.
  
          """
          fl = '%s_manager' % self.name
          if not fl in FLAGS:
              return None
  
          manager_class_name = FLAGS.get(fl, None)
          if not manager_class_name:
              return None
  
          manager_class = utils.import_class(manager_class_name)
          return manager_class()
  
      def start(self):
          """Start serving this service using loaded configuration.
  
          Also, retrieve updated port number in case '0' was passed in, which
          indicates a random port should be used.
  
          :returns: None
  
          """
          utils.cleanup_file_locks()
          if self.manager:
              self.manager.init_host()
          self.server.start()
          self.port = self.server.port
  
      def stop(self):
          """Stop serving this API.
  
          :returns: None
  
          """
          self.server.stop()
  
      def wait(self):
          """Wait for the service to stop serving this API.
  
          :returns: None
  
          """
          self.server.wait()
  
  
  # NOTE(vish): the global launcher is to maintain the existing
  #             functionality of calling service.serve +
  #             service.wait
  _launcher = None
  
  
  def serve(*servers):
      global _launcher
      if not _launcher:
          _launcher = Launcher()
      for server in servers:
          _launcher.launch_server(server)
  
  
  def wait():
      def is_credential(flag, flag_get):
          b_passwd = "_password" in flag
          b_key = (flag is not "cassandra_keyspace") and ("_key" in flag)
          b_mysql = (flag == "sql_connection" and "mysql:" in flag_get)
          
          return b_passwd or b_key or b_mysql
          
      LOG.debug(_('Full set of FLAGS:'))
      for flag in FLAGS:
          flag_get = FLAGS.get(flag, None)
          # hide flag contents from log if contains a password
          # should use secret flag when switch over to openstack-common
          if is_credential(flag, flag_get):
              LOG.debug(_('%(flag)s : FLAG SET ') % locals())
          else:
              LOG.debug('%(flag)s : %(flag_get)s' % locals())
      try:
          _launcher.wait()
      except KeyboardInterrupt:
          _launcher.stop()
      else:
          LOG.info("bye")
          _launcher.stop()
          
  