¡@

Home 

OpenStack Study: control.py

OpenStack Index

**** CubicPower OpenStack Study ****

def gated_by(predicate):

    def wrap(f):

        def wrapped_f(*args):

            if predicate:

                return f(*args)

            else:

                return None

        return wrapped_f

    return wrap

**** CubicPower OpenStack Study ****

def pid_files(server, pid_file):

    pid_files = []

    if pid_file:

        if os.path.exists(os.path.abspath(pid_file)):

            pid_files = [os.path.abspath(pid_file)]

    else:

        if os.path.exists('/var/run/glance/%s.pid' % server):

            pid_files = ['/var/run/glance/%s.pid' % server]

    for pid_file in pid_files:

        pid = int(open(pid_file).read().strip())

        yield pid_file, pid

**** CubicPower OpenStack Study ****

def do_start(verb, pid_file, server, args):

    if verb != 'Respawn' and pid_file == CONF.pid_file:

        for pid_file, pid in pid_files(server, pid_file):

            if os.path.exists('/proc/%s' % pid):

                print(_("%(serv)s appears to already be running: %(pid)s") %

                      {'serv': server, 'pid': pid_file})

                return

            else:

                print(_("Removing stale pid file %s") % pid_file)

                os.unlink(pid_file)

        try:

            resource.setrlimit(resource.RLIMIT_NOFILE,

                               (MAX_DESCRIPTORS, MAX_DESCRIPTORS))

            resource.setrlimit(resource.RLIMIT_DATA,

                               (MAX_MEMORY, MAX_MEMORY))

        except ValueError:

            print(_('Unable to increase file descriptor limit.  '

                    'Running as non-root?'))

        os.environ['PYTHON_EGG_CACHE'] = '/tmp'

    def write_pid_file(pid_file, pid):

        fp = open(pid_file, 'w')

        fp.write('%d\n' % pid)

        fp.close()

    def redirect_to_null(fds):

        with open(os.devnull, 'r+b') as nullfile:

            for desc in fds:  # close fds

                try:

                    os.dup2(nullfile.fileno(), desc)

                except OSError:

                    pass

    def redirect_to_syslog(fds, server):

        log_cmd = 'logger -t "%s[%d]"' % (server, os.getpid())

        process = subprocess.Popen(log_cmd,

                                   shell=True,

                                   stdin=subprocess.PIPE)

        for desc in fds:  # pipe to logger command

            try:

                os.dup2(process.stdin.fileno(), desc)

            except OSError:

                pass

    def redirect_stdio(server, capture_output):

        input = [sys.stdin.fileno()]

        output = [sys.stdout.fileno(), sys.stderr.fileno()]

        redirect_to_null(input)

        if capture_output:

            redirect_to_syslog(output, server)

        else:

            redirect_to_null(output)

    @gated_by(CONF.capture_output)

    def close_stdio_on_exec():

        fds = [sys.stdin.fileno(), sys.stdout.fileno(), sys.stderr.fileno()]

        for desc in fds:  # set close on exec flag

            fcntl.fcntl(desc, fcntl.F_SETFD, fcntl.FD_CLOEXEC)

    def launch(pid_file, conf_file=None, capture_output=False, await_time=0):

        args = [server]

        msg = (_('%(verb)sing %(serv)s') % {'verb': verb, 'serv': server})

        if conf_file:

            args += ['--config-file', conf_file]

            msg += 'with %s' % conf_file

        print(msg)

        close_stdio_on_exec()

        pid = os.fork()

        if pid == 0:

            os.setsid()

            redirect_stdio(server, capture_output)

            try:

                os.execlp('%s' % server, *args)

            except OSError as e:

                msg = (_('unable to launch %(serv)s. Got error: %(e)s') %

                       {'serv': server, 'e': e})

                sys.exit(msg)

            sys.exit(0)

        else:

            write_pid_file(pid_file, pid)

            await_child(pid, await_time)

            return pid

    @gated_by(CONF.await_child)

    def await_child(pid, await_time):

        bail_time = time.time() + await_time

        while time.time() < bail_time:

            reported_pid, status = os.waitpid(pid, os.WNOHANG)

            if reported_pid == pid:

                global exitcode

                exitcode = os.WEXITSTATUS(status)

                break

            time.sleep(0.05)

    conf_file = None

    if args and os.path.exists(args[0]):

        conf_file = os.path.abspath(os.path.expanduser(args[0]))

    return launch(pid_file, conf_file, CONF.capture_output, CONF.await_child)

**** CubicPower OpenStack Study ****

def do_check_status(pid_file, server):

    if os.path.exists(pid_file):

        pid = open(pid_file).read().strip()

        print(_("%(serv)s (pid %(pid)s) is running...") %

              {'serv': server, 'pid': pid})

    else:

        print(_("%s is stopped") % server)

**** CubicPower OpenStack Study ****

def get_pid_file(server, pid_file):

    pid_file = (os.path.abspath(pid_file) if pid_file else

                '/var/run/glance/%s.pid' % server)

    dir, file = os.path.split(pid_file)

    if not os.path.exists(dir):

        try:

            os.makedirs(dir)

        except OSError:

            pass

    if not os.access(dir, os.W_OK):

        fallback = os.path.join(tempfile.mkdtemp(), '%s.pid' % server)

        msg = (_('Unable to create pid file %(pid)s.  Running as non-root?\n'

                 'Falling back to a temp file, you can stop %(service)s '

                 'service using:\n'

                 '  %(file)s %(server)s stop --pid-file %(fb)s') %

               {'pid': pid_file,

                'service': server,

                'file': __file__,

                'server': server,

                'fb': fallback})

        print(msg)

        pid_file = fallback

    return pid_file

**** CubicPower OpenStack Study ****

def do_stop(server, args, graceful=False):

    if graceful and server in GRACEFUL_SHUTDOWN_SERVERS:

        sig = signal.SIGHUP

    else:

        sig = signal.SIGTERM

    did_anything = False

    pfiles = pid_files(server, CONF.pid_file)

    for pid_file, pid in pfiles:

        did_anything = True

        try:

            os.unlink(pid_file)

        except OSError:

            pass

        try:

            print(_('Stopping %(serv)s (pid %(pid)s) with signal(%(sig)s)')

                  % {'serv': server, 'pid': pid, 'sig': sig})

            os.kill(pid, sig)

        except OSError:

            print(_("Process %d not running") % pid)

    for pid_file, pid in pfiles:

        for _junk in xrange(150):  # 15 seconds

            if not os.path.exists('/proc/%s' % pid):

                break

            time.sleep(0.1)

        else:

            print(_('Waited 15 seconds for pid %(pid)s (%(file)s) to die;'

                    ' giving up') % {'pid': pid, 'file': pid_file})

    if not did_anything:

        print(_('%s is already stopped') % server)

**** CubicPower OpenStack Study ****

def add_command_parsers(subparsers):

    cmd_parser = argparse.ArgumentParser(add_help=False)

    cmd_subparsers = cmd_parser.add_subparsers(dest='command')

    for cmd in ALL_COMMANDS:

        parser = cmd_subparsers.add_parser(cmd)

        parser.add_argument('args', nargs=argparse.REMAINDER)

    for server in ALL_SERVERS:

        full_name = 'glance-' + server

        parser = subparsers.add_parser(server, parents=[cmd_parser])

        parser.set_defaults(servers=[full_name])

        parser = subparsers.add_parser(full_name, parents=[cmd_parser])

        parser.set_defaults(servers=[full_name])

    parser = subparsers.add_parser('all', parents=[cmd_parser])

    parser.set_defaults(servers=['glance-' + s for s in ALL_SERVERS])

**** CubicPower OpenStack Study ****

def main():

    global exitcode

    opts = [

        cfg.SubCommandOpt('server',

                          title='Server types',

                          help='Available server types',

                          handler=add_command_parsers),

        cfg.StrOpt('pid-file',

                   metavar='PATH',

                   help='File to use as pid file. Default: '

                   '/var/run/glance/$server.pid.'),

        cfg.IntOpt('await-child',

                   metavar='DELAY',

                   default=0,

                   help='Period to wait for service death '

                        'in order to report exit code '

                        '(default is to not wait at all).'),

        cfg.BoolOpt('capture-output',

                    default=False,

                    help='Capture stdout/err in syslog '

                    'instead of discarding it.'),

        cfg.BoolOpt('respawn',

                    default=False,

                    help='Restart service on unexpected death.'),

    ]

    CONF.register_cli_opts(opts)

    config.parse_args(usage=USAGE)

    @gated_by(CONF.await_child)

    @gated_by(CONF.respawn)

    def mutually_exclusive():

        sys.stderr.write('--await-child and --respawn are mutually exclusive')

        sys.exit(1)

    mutually_exclusive()

    @gated_by(CONF.respawn)

    def anticipate_respawn(children):

        while children:

            pid, status = os.wait()

            if pid in children:

                (pid_file, server, args) = children.pop(pid)

                running = os.path.exists(pid_file)

                one_second_ago = time.time() - 1

                bouncing = (running and

                            os.path.getmtime(pid_file) >= one_second_ago)

                if running and not bouncing:

                    args = (pid_file, server, args)

                    new_pid = do_start('Respawn', *args)

                    children[new_pid] = args

                else:

                    rsn = 'bouncing' if bouncing else 'deliberately stopped'

                    print(_('Supressed respawn as %(serv)s was %(rsn)s.')

                          % {'serv': server, 'rsn': rsn})

    if CONF.server.command == 'start':

        children = {}

        for server in CONF.server.servers:

            pid_file = get_pid_file(server, CONF.pid_file)

            args = (pid_file, server, CONF.server.args)

            pid = do_start('Start', *args)

            children[pid] = args

        anticipate_respawn(children)

    if CONF.server.command == 'status':

        for server in CONF.server.servers:

            pid_file = get_pid_file(server, CONF.pid_file)

            do_check_status(pid_file, server)

    if CONF.server.command == 'stop':

        for server in CONF.server.servers:

            do_stop(server, CONF.server.args)

    if CONF.server.command == 'shutdown':

        for server in CONF.server.servers:

            do_stop(server, CONF.server.args, graceful=True)

    if CONF.server.command == 'restart':

        for server in CONF.server.servers:

            do_stop(server, CONF.server.args)

        for server in CONF.server.servers:

            pid_file = get_pid_file(server, CONF.pid_file)

            do_start('Restart', pid_file, server, CONF.server.args)

    if (CONF.server.command == 'reload' or

            CONF.server.command == 'force-reload'):

        for server in CONF.server.servers:

            do_stop(server, CONF.server.args, graceful=True)

            pid_file = get_pid_file(server, CONF.pid_file)

            do_start('Restart', pid_file, server, CONF.server.args)

    sys.exit(exitcode)