Statistics
| Branch: | Tag: | Revision:

root / snf-image-host / helper-monitor.py @ 73dddd66

History | View | Annotate | Download (3.6 kB)

1
#!/usr/bin/env python
2

    
3
# Copyright (C) 2012 GRNET S.A.
4
#
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
9
#
10
# This program is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
# General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
# 02110-1301, USA.
19

    
20
import sys
21
import os
22
import time
23
import json
24
import re
25

    
26
LINESIZE = 512
27
PROGNAME = os.path.basename(sys.argv[0])
28
STDERR_MAXLINES = 10
29
MAXLINES = 100
30

    
31
PROTOCOL = {
32
    'TASK_START': ('task-start', 'task'),
33
    'TASK_END': ('task-end', 'task'),
34
    'WARNING': ('warning', 'msg'),
35
    'STDERR': ('error', 'stderr'),
36
    'ERROR': ('error', 'msg')}
37

    
38

    
39
def error(msg):
40
    sys.stderr.write("HELPER-MONITOR ERROR: %s\n" % msg)
41
    sys.exit(1)
42

    
43

    
44
def send(fd, msg_type, value):
45
    subtype, value_name = PROTOCOL[msg_type]
46

    
47
    msg = {}
48
    msg['type'] = 'image-helper'
49
    msg['subtype'] = subtype
50
    msg[value_name] = value
51
    msg['timestamp'] = time.time()
52
    os.write(fd, "%s\n" % json.dumps(msg))
53

    
54

    
55
if __name__ == "__main__":
56
    usage = "Usage: %s <file-descriptor>\n" % PROGNAME
57

    
58
    if len(sys.argv) != 2:
59
        sys.stderr.write(usage)
60
        sys.exit(1)
61

    
62
    try:
63
        fd = int(sys.argv[1])
64
    except ValueError:
65
        error("File descriptor is not an integer")
66

    
67
    try:
68
        os.fstat(fd)
69
    except OSError:
70
        error("File descriptor is not valid")
71

    
72
    lines_left = 0
73
    stderr = ""
74

    
75
    line_count = 0
76
    while 1:
77
        line = sys.stdin.readline(LINESIZE)
78

    
79
        if not line:
80
            break
81
        else:
82
            line_count += 1
83

    
84
        if line[-1] != '\n':
85
            # Line is too long...
86
            error("Too long line...")
87
            sys.exit(1)
88

    
89
        if lines_left > 0:
90
            stderr += line
91
            lines_left -= 1
92
            if lines_left == 0:
93
                send(fd, "STDERR", stderr)
94
                stderr = ""
95
            continue
96

    
97
        if line_count >= MAXLINES + 1:
98
            error("Maximum allowed helper monitor number of lines exceeded.")
99

    
100
        line = line.strip()
101
        if len(line) == 0:
102
            continue
103

    
104
        if line.startswith("STDERR:"):
105
            m = re.match("STDERR:(\d+):(.*)", line)
106
            if not m:
107
                error("Invalid syntax for STDERR line")
108
            try:
109
                lines_left = int(m.group(1))
110
            except ValueError:
111
                error("Second field in STDERR line must be an integer")
112

    
113
            if lines_left > STDERR_MAXLINES:
114
                error("Too many lines in the STDERR output")
115
            elif lines_left < 0:
116
                error("Second field of STDERR: %d is invalid" % lines_left)
117

    
118
            if lines_left > 0:
119
                stderr = m.group(2) + "\n"
120
                lines_left -= 1
121

    
122
            if lines_left == 0:
123
                send(fd, "STDERR", stderr)
124
                stderr = ""
125
        elif line.startswith("TASK_START:") or line.startswith("TASK_END:") \
126
            or line.startswith("WARNING:") or line.startswith("ERROR:"):
127
            (msg_type, _, value) = line.partition(':')
128
            send(fd, msg_type, value)
129
        else:
130
            error("Unknown command!")
131

    
132
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :