Statistics
| Branch: | Tag: | Revision:

root / snf-image-host / helper-monitor.py @ 26b128ad

History | View | Annotate | Download (4.3 kB)

1 f32664b2 Nikos Skalkotos
#!/usr/bin/env python
2 f32664b2 Nikos Skalkotos
3 f32664b2 Nikos Skalkotos
# Copyright (C) 2012 GRNET S.A.
4 f32664b2 Nikos Skalkotos
#
5 f32664b2 Nikos Skalkotos
# This program is free software; you can redistribute it and/or modify
6 f32664b2 Nikos Skalkotos
# it under the terms of the GNU General Public License as published by
7 f32664b2 Nikos Skalkotos
# the Free Software Foundation; either version 2 of the License, or
8 f32664b2 Nikos Skalkotos
# (at your option) any later version.
9 f32664b2 Nikos Skalkotos
#
10 f32664b2 Nikos Skalkotos
# This program is distributed in the hope that it will be useful, but
11 f32664b2 Nikos Skalkotos
# WITHOUT ANY WARRANTY; without even the implied warranty of
12 f32664b2 Nikos Skalkotos
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 f32664b2 Nikos Skalkotos
# General Public License for more details.
14 f32664b2 Nikos Skalkotos
#
15 f32664b2 Nikos Skalkotos
# You should have received a copy of the GNU General Public License
16 f32664b2 Nikos Skalkotos
# along with this program; if not, write to the Free Software
17 f32664b2 Nikos Skalkotos
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 f32664b2 Nikos Skalkotos
# 02110-1301, USA.
19 f32664b2 Nikos Skalkotos
20 f32664b2 Nikos Skalkotos
import sys
21 f32664b2 Nikos Skalkotos
import os
22 f32664b2 Nikos Skalkotos
import time
23 f32664b2 Nikos Skalkotos
import json
24 f32664b2 Nikos Skalkotos
import re
25 f32664b2 Nikos Skalkotos
26 f32664b2 Nikos Skalkotos
LINESIZE = 512
27 13965151 Nikos Skalkotos
BUFSIZE = 512
28 f32664b2 Nikos Skalkotos
PROGNAME = os.path.basename(sys.argv[0])
29 f32664b2 Nikos Skalkotos
STDERR_MAXLINES = 10
30 f32664b2 Nikos Skalkotos
MAXLINES = 100
31 0b51f509 Nikos Skalkotos
MSG_TYPE = 'image-helper'
32 f32664b2 Nikos Skalkotos
33 f32664b2 Nikos Skalkotos
PROTOCOL = {
34 f32664b2 Nikos Skalkotos
    'TASK_START': ('task-start', 'task'),
35 f32664b2 Nikos Skalkotos
    'TASK_END': ('task-end', 'task'),
36 654f87c0 Nikos Skalkotos
    'WARNING': ('warning', 'messages'),
37 f32664b2 Nikos Skalkotos
    'STDERR': ('error', 'stderr'),
38 654f87c0 Nikos Skalkotos
    'ERROR': ('error', 'messages')}
39 f32664b2 Nikos Skalkotos
40 f32664b2 Nikos Skalkotos
41 f32664b2 Nikos Skalkotos
def error(msg):
42 73dddd66 Nikos Skalkotos
    sys.stderr.write("HELPER-MONITOR ERROR: %s\n" % msg)
43 f32664b2 Nikos Skalkotos
    sys.exit(1)
44 f32664b2 Nikos Skalkotos
45 f32664b2 Nikos Skalkotos
46 f32664b2 Nikos Skalkotos
def send(fd, msg_type, value):
47 f32664b2 Nikos Skalkotos
    subtype, value_name = PROTOCOL[msg_type]
48 f32664b2 Nikos Skalkotos
49 f32664b2 Nikos Skalkotos
    msg = {}
50 0b51f509 Nikos Skalkotos
    msg['type'] = MSG_TYPE
51 f32664b2 Nikos Skalkotos
    msg['subtype'] = subtype
52 f32664b2 Nikos Skalkotos
    msg[value_name] = value
53 f32664b2 Nikos Skalkotos
    msg['timestamp'] = time.time()
54 f32664b2 Nikos Skalkotos
    os.write(fd, "%s\n" % json.dumps(msg))
55 f32664b2 Nikos Skalkotos
56 f32664b2 Nikos Skalkotos
57 f32664b2 Nikos Skalkotos
if __name__ == "__main__":
58 f32664b2 Nikos Skalkotos
    usage = "Usage: %s <file-descriptor>\n" % PROGNAME
59 f32664b2 Nikos Skalkotos
60 f32664b2 Nikos Skalkotos
    if len(sys.argv) != 2:
61 f32664b2 Nikos Skalkotos
        sys.stderr.write(usage)
62 f32664b2 Nikos Skalkotos
        sys.exit(1)
63 f32664b2 Nikos Skalkotos
64 f32664b2 Nikos Skalkotos
    try:
65 f32664b2 Nikos Skalkotos
        fd = int(sys.argv[1])
66 f32664b2 Nikos Skalkotos
    except ValueError:
67 f32664b2 Nikos Skalkotos
        error("File descriptor is not an integer")
68 f32664b2 Nikos Skalkotos
69 f32664b2 Nikos Skalkotos
    try:
70 f32664b2 Nikos Skalkotos
        os.fstat(fd)
71 f32664b2 Nikos Skalkotos
    except OSError:
72 f32664b2 Nikos Skalkotos
        error("File descriptor is not valid")
73 f32664b2 Nikos Skalkotos
74 f32664b2 Nikos Skalkotos
    lines_left = 0
75 f32664b2 Nikos Skalkotos
    line_count = 0
76 13965151 Nikos Skalkotos
    stderr = ""
77 13965151 Nikos Skalkotos
    line = ""
78 13965151 Nikos Skalkotos
    while True:
79 13965151 Nikos Skalkotos
        # Can't use sys.stdin.readline since I want unbuffered I/O
80 13965151 Nikos Skalkotos
        new_data = os.read(sys.stdin.fileno(), BUFSIZE)
81 13965151 Nikos Skalkotos
82 13965151 Nikos Skalkotos
        if not new_data:
83 13965151 Nikos Skalkotos
            if not line:
84 13965151 Nikos Skalkotos
                break
85 13965151 Nikos Skalkotos
            else:
86 13965151 Nikos Skalkotos
                new_data = '\n'
87 13965151 Nikos Skalkotos
88 13965151 Nikos Skalkotos
        while True:
89 13965151 Nikos Skalkotos
            split = new_data.split('\n', 1)
90 13965151 Nikos Skalkotos
            line += split[0]
91 13965151 Nikos Skalkotos
            if len(split) == 1:
92 13965151 Nikos Skalkotos
                if len(line) > LINESIZE:
93 13965151 Nikos Skalkotos
                    error("Line size exceeded the maximum allowed size")
94 13965151 Nikos Skalkotos
                break
95 13965151 Nikos Skalkotos
96 13965151 Nikos Skalkotos
            new_data = split[1]
97 f32664b2 Nikos Skalkotos
98 f32664b2 Nikos Skalkotos
            line_count += 1
99 13965151 Nikos Skalkotos
            if line_count >= MAXLINES + 1:
100 13965151 Nikos Skalkotos
                error("Exceeded maximum allowed number of lines: %d." %
101 13965151 Nikos Skalkotos
                      MAXLINES)
102 f32664b2 Nikos Skalkotos
103 f32664b2 Nikos Skalkotos
            if lines_left > 0:
104 13965151 Nikos Skalkotos
                stderr += "%s\n" % line
105 f32664b2 Nikos Skalkotos
                lines_left -= 1
106 13965151 Nikos Skalkotos
                if lines_left == 0:
107 13965151 Nikos Skalkotos
                    send(fd, "STDERR", stderr)
108 13965151 Nikos Skalkotos
                    stderr = ""
109 13965151 Nikos Skalkotos
                line = ""
110 13965151 Nikos Skalkotos
                continue
111 13965151 Nikos Skalkotos
112 13965151 Nikos Skalkotos
            line = line.strip()
113 13965151 Nikos Skalkotos
            if len(line) == 0:
114 13965151 Nikos Skalkotos
                continue
115 13965151 Nikos Skalkotos
116 13965151 Nikos Skalkotos
            if line.startswith("STDERR:"):
117 13965151 Nikos Skalkotos
                m = re.match("STDERR:(\d+):(.*)", line)
118 13965151 Nikos Skalkotos
                if not m:
119 13965151 Nikos Skalkotos
                    error("Invalid syntax for STDERR line")
120 13965151 Nikos Skalkotos
                try:
121 13965151 Nikos Skalkotos
                    lines_left = int(m.group(1))
122 13965151 Nikos Skalkotos
                except ValueError:
123 13965151 Nikos Skalkotos
                    error("Second field in STDERR line must be an integer")
124 13965151 Nikos Skalkotos
125 13965151 Nikos Skalkotos
                if lines_left > STDERR_MAXLINES:
126 13965151 Nikos Skalkotos
                    error("Too many lines in the STDERR output")
127 13965151 Nikos Skalkotos
                elif lines_left < 0:
128 13965151 Nikos Skalkotos
                    error("Second field of STDERR: %d is invalid" % lines_left)
129 13965151 Nikos Skalkotos
130 13965151 Nikos Skalkotos
                if lines_left > 0:
131 13965151 Nikos Skalkotos
                    stderr = m.group(2) + "\n"
132 13965151 Nikos Skalkotos
                    lines_left -= 1
133 13965151 Nikos Skalkotos
134 13965151 Nikos Skalkotos
                if lines_left == 0:
135 13965151 Nikos Skalkotos
                    send(fd, "STDERR", stderr)
136 13965151 Nikos Skalkotos
                    stderr = ""
137 13965151 Nikos Skalkotos
            elif line.startswith("TASK_START:") \
138 13965151 Nikos Skalkotos
                or line.startswith("TASK_END:") \
139 13965151 Nikos Skalkotos
                or line.startswith("WARNING:") \
140 13965151 Nikos Skalkotos
                or line.startswith("ERROR:"):
141 13965151 Nikos Skalkotos
                (msg_type, _, value) = line.partition(':')
142 654f87c0 Nikos Skalkotos
143 654f87c0 Nikos Skalkotos
                if line.startswith("WARNING:") or line.startswith("ERROR:"):
144 654f87c0 Nikos Skalkotos
                    value = [value]
145 13965151 Nikos Skalkotos
                send(fd, msg_type, value)
146 13965151 Nikos Skalkotos
            else:
147 13965151 Nikos Skalkotos
                error("Unknown command!")
148 13965151 Nikos Skalkotos
149 13965151 Nikos Skalkotos
            # Remove the processed line
150 13965151 Nikos Skalkotos
            line = ""
151 f32664b2 Nikos Skalkotos
152 f32664b2 Nikos Skalkotos
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :