tntzbzc 发表于 2014-11-20 15:34:49

OpenStack Swift源码分析(1)----swift服务启动源码分析之一

本帖最后由 pig2 于 2014-11-21 15:07 编辑

问题导读
1.swift-init main start命令的作用是什么?
2.哪个类是管理各个server执行操作的类?



static/image/hrline/4.gif




   
    从头开始,部署完成swift以后,就可以执行命令swift-init main start来执行swift的初始化工作。这里实际上执行的是/bin/swift-init中的main方法,下面我们开始看代码:
if __name__ == "__main__":
    sys.exit(main())   


进一步调用方法main:


def main():
    parser = OptionParser(USAGE)
    parser.add_option('-v', '--verbose', action="store_true",
                      default=False, help="display verbose output")
    parser.add_option('-w', '--no-wait', action="store_false", dest="wait",
                      default=True, help="won't wait for server to start "
                      "before returning")
    parser.add_option('-o', '--once', action="store_true",
                      default=False, help="only run one pass of daemon")
    # this is a negative option, default is options.daemon = True
    parser.add_option('-n', '--no-daemon', action="store_false", dest="daemon",
                      default=True, help="start server interactively")
    parser.add_option('-g', '--graceful', action="store_true",
                      default=False, help="send SIGHUP to supporting servers")
    parser.add_option('-c', '--config-num', metavar="N", type="int",
                      dest="number", default=0,
                      help="send command to the Nth server only")
    parser.add_option('-k', '--kill-wait', metavar="N", type="int",
                      dest="kill_wait", default=KILL_WAIT,
                      help="wait N seconds for processes to die (default 15)")
    parser.add_option('-r', '--run-dir', type="str",
                      dest="run_dir", default=RUN_DIR,
                      help="alternative directory to store running pid files "
                      "default: %s" % RUN_DIR)

    options, args = parser.parse_args()

    if len(args) < 2:
      parser.print_help()
      print 'ERROR: specify server(s) and command'
      return 1

    # 在这里对命令和参数进行了分割,从而决定接下来的执行任务:
    # command此处为start;
    # servers此处为['swift-init','main'];
    command = args[-1]
    servers = args[:-1]

    # this is just a silly swap for me cause I always try to "start main"
    commands = dict(Manager.list_commands()).keys()
    if command not in commands and servers in commands:
      servers.append(command)
      command = servers.pop(0)

    # 实例化类Manager;
    # Manager是直接管理各个servers的类;
    # 初始化各个服务;
    manager = Manager(servers, run_dir=options.run_dir)
    try:
      status = manager.run_command(command, **options.__dict__)
    except UnknownCommandError:
      parser.print_help()
      print 'ERROR: unknown command, %s' % command
      status = 1

    return 1 if status else 0




看其中的一段代码:
# list_commands:获取所有可公开访问的命令;
    commands = dict(Manager.list_commands()).keys()
    if command not in commands and servers in commands:
      servers.append(command)
      command = servers.pop(0)
   

经过调试输出:
commands = ['status', 'start', 'force-reload', 'stop', 'no-wait', 'no-daemon', 'reload', 'shutdown', 'restart', 'once']
# 实例化类Manager;
# Manager是直接管理各个servers的类;
# 初始化各个服务;
manager = Manager(servers, run_dir=options.run_dir)   

其中Manager是管理各个server执行操作的类,这条语句实现了对类Manager的初始化并获取实力对象;
    具体来看:


class Manager():
    """
    管理各个server执行操作的类;
    param servers:服务名称列表;
    """
    def __init__(self, servers, run_dir=RUN_DIR):
      server_names = set()
      for server in servers:
            if server == 'all':
                server_names.update(ALL_SERVERS)
            # MAIN_SERVERS = ['proxy-server', 'account-server', 'container-server', 'object-server']
            elif server == 'main':
                server_names.update(MAIN_SERVERS)
            elif server == 'rest':
                server_names.update(REST_SERVERS)
            elif '*' in server:
                # convert glob to regex
                server_names.update()
            else:
                server_names.add(server)
      self.servers = set()
      # 如果servers中包含‘main’:
      # server_names = ['proxy-server', 'account-server', 'container-server', 'object-server'];
      # run_dir = /var/run/swift;
      # Server:依次初始化四个服务;
      for name in server_names:
            self.servers.add(Server(name, run_dir))   



我们前面测试得到servers = ['swift-init', 'main'],可见server_names = ['proxy-server', 'account-server', 'container-server', 'object-server'],这是swift四个服务的名称;
    所以这个初始化方法根据传入servers的参数值,确定了server_names的值;
    再回到/bin/swift-init中的main方法:
    try:
      status = manager.run_command(command, **options.__dict__)
    except UnknownCommandError:
      parser.print_help()
      print 'ERROR: unknown command, %s' % command
      status = 1   



其中:
    command = start
    options = {'run_dir': '/var/run/swift', 'daemon': True, 'verbose': False, 'number': 0, 'kill_wait': 15, 'graceful': False, 'wait': True, 'once': False}
    进一步看方法run_command:
def run_command(self, cmd, **kwargs):
    """
    找到命令名称并运行它;
    """
    f = self.get_command(cmd)
    return f(**kwargs)   



再看方法get_command:

    def get_command(self, cmd):
      """
      查找并返回cmd指定的方法名称;
      """
      cmd = cmd.lower().replace('-', '_')
      try:
            f = getattr(self, cmd)
      except AttributeError:
            raise UnknownCommandError(cmd)
      if not hasattr(f, 'publicly_accessible'):
            raise UnknownCommandError(cmd)
      return f   


可以知道通过这两个方法的结合,可以定位到cmd指定的方法,并进一步运行它;
    这里具体调用并执行的是def start(self, **kwargs):
def start(self, **kwargs):
      """
      启动一个服务;
      """
      setup_env()
      status = 0
      for server in self.servers:
            server.launch(**kwargs)
      if not kwargs.get('daemon', True):
            for server in self.servers:
                try:
                  status += server.interact(**kwargs)
                except KeyboardInterrupt:
                  print _('\nuser quit')
                  self.stop(**kwargs)
                  break
      elif kwargs.get('wait', True):
            for server in self.servers:
                status += server.wait(**kwargs)
      return status



   这个方法中将会依次启动servers指定的服务,即servers = ['proxy-server', 'account-server', 'container-server', 'object-server'];
    具体实现将会在下一篇博文中进行解析。
    博文中不免有不正确的地方,欢迎朋友们不吝批评指正,谢谢大家了!

相关内容:
OpenStack Swift源码分析(1)----swift服务启动源码分析之一

OpenStack Swift源码分析(2)----swift服务启动源码分析之二

OpenStack Swift源码分析(3)----swift服务启动源码分析之三





yangdy 发表于 2015-11-20 16:28:51

Usage: swift-init <server>[.config] [<server>[.config] ...] <command> 这个是什么意思?可以swift-init proxy等等 start来启动吗?除了这个还有什么方式
页: [1]
查看完整版本: OpenStack Swift源码分析(1)----swift服务启动源码分析之一