~ltrager/maas/lp1654432_2.1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#!/usr/bin/env python3.5
# -*- mode: python -*-
# Copyright 2012-2016 Canonical Ltd.  This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).

"""Script to start services, tail logs, and stop services at the end.

Service names should be provided on the command-line.

If a service name is preceded by a "+" (plus) it is started in the
foreground. For example, to start the `rackd` service in the background
and `regiond` in the foreground:

  $ services/run rackd +regiond

It does not matter if a service name appears twice in the list. If the service
name appears once with a preceding "+" and once without, the "+" one takes
precedence, and that service will be started in the foreground. Only one
service may be started in the foreground.

If no service has a preceding "+" then all the services named are started and
their logs tailed.
"""

from contextlib import contextmanager
from os.path import join
from subprocess import (
    CalledProcessError,
    check_call,
)
from sys import (
    argv,
    stderr,
)


@contextmanager
def service(services):
    started = []
    try:
        for service in services:
            control(service, "start")
            started.append(service)
        yield
    finally:
        for service in started:
            control(service, "stop")


def control(service, action):
    stderr.write("--> %s `%s`\n" % (action.capitalize(), service))
    return check_call(
        ("make", "--no-print-directory",
         "services/%s/@%s" % (service, action)))


def tail_logs(services):
    command = ["tail", "--follow=name", "--retry", "--"]
    command.extend(
        join("logs", service, "current")
        for service in services)
    check_call(command)


if __name__ == "__main__":
    if len(argv) == 1:
        raise SystemExit(__doc__)
    services_bg = {name for name in argv[1:] if not name.startswith("+")}
    services_fg = {name[1:] for name in argv[1:] if name.startswith("+")}
    services_bg = services_bg - services_fg
    service_fg = services_fg.pop() if services_fg else None
    if len(services_fg) != 0:
        raise SystemExit("Only zero or one foreground services permitted.")
    try:
        with service(services_bg):
            if service_fg:
                control(service_fg, "run")
            else:
                tail_logs(services_bg)
    except CalledProcessError as error:
        raise SystemExit(error.returncode)
    except KeyboardInterrupt:
        pass  # Ignore.