summaryrefslogtreecommitdiff
path: root/cloudinit/transforms/rsyslog.py
blob: f2c1de1ea5f6163b5f0c476627d7f1620f6ec8f7 (plain)
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# vi: ts=4 expandtab syntax=python
#
#    Copyright (C) 2009-2010 Canonical Ltd.
#    Copyright (C) 2012 Hewlett-Packard Development Company, L.P.
#
#    Author: Scott Moser <scott.moser@canonical.com>
#    Author: Juerg Haefliger <juerg.haefliger@hp.com>
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License version 3, as
#    published by the Free Software Foundation.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

import os

from cloudinit import util

DEF_FILENAME = "20-cloud-config.conf"
DEF_DIR = "/etc/rsyslog.d"


def handle(name, cfg, cloud, log, _args):
    # rsyslog:
    #  - "*.* @@192.158.1.1"
    #  - content: "*.*   @@192.0.2.1:10514"
    #  - filename: 01-examplecom.conf
    #    content: |
    #      *.*   @@syslogd.example.com

    # process 'rsyslog'
    if not 'rsyslog' in cfg:
        log.debug(("Skipping transform named %s,"
                   " no 'rsyslog' key in configuration"), name)
        return

    def_dir = cfg.get('rsyslog_dir', DEF_DIR)
    def_fname = cfg.get('rsyslog_filename', DEF_FILENAME)

    files = []
    for i, ent in enumerate(cfg['rsyslog']):
        if isinstance(ent, dict):
            if not "content" in ent:
                log.warn("No 'content' entry in config entry %s", i + 1)
                continue
            content = ent['content']
            filename = ent.get("filename", def_fname)
        else:
            content = ent
            filename = def_fname

        filename = filename.strip()
        if not filename:
            log.warn("Entry %s has an empty filename", i + 1)
            continue

        if not filename.startswith("/"):
            filename = os.path.join(def_dir, filename)

        # Truncate filename first time you see it
        omode = "ab"
        if filename not in files:
            omode = "wb"
            files.append(filename)

        try:
            contents = "%s\n" % (content)
            util.write_file(cloud.paths.join(False, filename),
                            contents, omode=omode)
        except Exception:
            util.logexc(log, "Failed to write to %s", filename)

    # Attempt to restart syslogd
    restarted = False
    try:
        # If this config module is running at cloud-init time
        # (before rsyslog is running) we don't actually have to
        # restart syslog.
        #
        # Upstart actually does what we want here, in that it doesn't
        # start a service that wasn't running already on 'restart'
        # it will also return failure on the attempt, so 'restarted'
        # won't get set.
        log.debug("Restarting rsyslog")
        util.subp(['service', 'rsyslog', 'restart'])
        restarted = True
    except Exception:
        util.logexc(log, "Failed restarting rsyslog")

    if restarted:
        # This only needs to run if we *actually* restarted
        # syslog above.
        cloud.cycle_logging()
        # This should now use rsyslog if
        # the logging was setup to use it...
        log.debug("%s configured %s files", name, files)