monitor: clean directory and parameter sections
[slapos.git] / stack / monitor / monitor.py.in
1 #!{{ python_executable }}
2
3 import datetime
4 import json
5 import os
6 import subprocess
7 import sys
8 import time
9 from optparse import OptionParser, make_option
10
11 instance_path = "{{ directory['home'] }}"
12 monitor_dir = "{{ directory['monitor-custom-scripts'] }}"
13 pid_dir = "{{ directory['run'] }}"
14 promise_dir = "{{ directory['promise'] }}"
15
16 monitoring_file_json = "{{ monitoring_file_json }}"
17 monitoring_folder_bool = "{{ directory['monitor-result-bool'] }}"
18
19 option_list = [
20 make_option("-a", "--all", action="store_true", dest="all",
21 help="test everything : promises, services, customs"),
22 make_option("-n", "--no-write", action="store_true", dest="only_stdout",
23 help="just show the json output on stdout"),
24 make_option("-m", "--monitors", action="store_true", dest="monitor",
25 help="add the custom monitoring file to the files to monitor"),
26 make_option("-p", "--promises", action="store_true", dest="promise",
27 help="add the promises\'file to the files to monitor"),
28 make_option("-s", "--services", action="store_true", dest="service",
29 help="add the file containing services\'pid to the files to monitor")
30 ]
31
32
33 def getListOfScripts(directory):
34 """
35 Get the list of script inside of a directory (not recursive)
36 """
37 scripts = []
38 if os.path.exists(directory) and os.path.isdir(directory):
39 for file_name in os.listdir(directory):
40 file = os.path.join(directory, file_name)
41 if os.access(file, os.X_OK) and not os.path.isdir(file):
42 scripts.append(file)
43 else:
44 exit("There is a problem in your directories" \
45 "of monitoring. Please check them")
46 return scripts
47
48
49 def runServices(directory):
50 services = getListOfScripts(directory)
51 result = {}
52 for service in services:
53 service_path = os.path.join(pid_dir, service)
54 service_name = os.path.basename(service_path)
55 try:
56 pid = int(open(service_path).read())
57 ### because apache (or others) can write sockets
58 except IOError:
59 continue
60 try:
61 os.kill(pid, 0)
62 result[service_name] = ''
63 except OSError:
64 result[service_name] = "This service is not running anymore"
65 return result
66
67
68 def runScripts(directory):
69 scripts = getListOfScripts(directory)
70 script_timeout = 3
71 result = {}
72 for script in scripts:
73 command = [os.path.join(promise_dir, script)]
74 script = os.path.basename(command[0])
75 result[script] = ''
76
77 process_handler = subprocess.Popen(command,
78 cwd=instance_path,
79 env=None if sys.platform == 'cygwin' else {},
80 stdout=subprocess.PIPE,
81 stderr=subprocess.PIPE,
82 stdin=subprocess.PIPE)
83 process_handler.stdin.flush()
84 process_handler.stdin.close()
85 process_handler.stdin = None
86
87 time.sleep(script_timeout)
88
89 if process_handler.poll() is None:
90 process_handler.terminate()
91 result[script] = "Time Out"
92 elif process_handler.poll() != 0:
93 stderr = process_handler.communicate()[1]
94 if stderr is not None:
95 result[script] = stderr.strip()
96 return result
97
98
99 def writeFiles(monitors):
100 fail = False
101 for i in monitors.values():
102 if i != "" :
103 fail = True
104 if fail:
105 message = "FAILURE : something went wrong\n"
106 else:
107 message = "SUCCESS : everything is ok\n"
108 date = datetime.datetime.now().ctime()
109 monitors['datetime'] = date
110 file_bool = os.path.join(monitoring_folder_bool, str(time.time()))
111 open(file_bool, "w+").write(date + "," + message)
112 open(monitoring_file_json, "w+").write(json.dumps(monitors))
113
114
115 if __name__ == "__main__":
116 parser = OptionParser(option_list=option_list)
117 monitors = {}
118 (options, args) = parser.parse_args()
119
120 if not (options.monitor or options.promise
121 or options.service or options.all):
122 exit("Please provide at list one arg in : -a, -m, -p, -s")
123
124 if options.monitor or options.all:
125 monitors.update(runScripts(monitor_dir))
126 if options.promise or options.all:
127 monitors.update(runScripts(promise_dir))
128 if options.service or options.all:
129 monitors.update(runServices(pid_dir))
130
131 if options.only_stdout:
132 print json.dumps(monitors)
133 else:
134 writeFiles(monitors)
135 if len(monitors) == 0:
136 exit(0)
137 else:
138 exit(1)
139