blob: 20eedc58c6f75226119a2564b00913836390641d [file] [log] [blame]
koder aka kdanilovdda86d32015-03-16 11:20:04 +02001import os
2import sys
3import time
4import json
koder aka kdanilove06762a2015-03-22 23:32:09 +02005import glob
koder aka kdanilovdda86d32015-03-16 11:20:04 +02006import signal
7import os.path
8import argparse
9
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030010from .sensors.utils import SensorInfo
11from .daemonize import Daemonize
12from .discover import all_sensors
13from .protocol import create_protocol
koder aka kdanilovdda86d32015-03-16 11:20:04 +020014
15
koder aka kdanilove06762a2015-03-22 23:32:09 +020016# load all sensors
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030017from . import sensors
koder aka kdanilove06762a2015-03-22 23:32:09 +020018sensors_dir = os.path.dirname(sensors.__file__)
19for fname in glob.glob(os.path.join(sensors_dir, "*.py")):
20 mod_name = os.path.basename(fname[:-3])
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030021 __import__("sensors.sensors." + mod_name)
koder aka kdanilove06762a2015-03-22 23:32:09 +020022
23
koder aka kdanilovdda86d32015-03-16 11:20:04 +020024def get_values(required_sensors):
25 result = {}
26 for sensor_name, params in required_sensors:
27 if sensor_name in all_sensors:
28 result.update(all_sensors[sensor_name](**params))
29 else:
30 msg = "Sensor {0!r} isn't available".format(sensor_name)
31 raise ValueError(msg)
koder aka kdanilov57ce4db2015-04-25 21:25:51 +030032 return result
koder aka kdanilovdda86d32015-03-16 11:20:04 +020033
34
35def parse_args(args):
36 parser = argparse.ArgumentParser()
37 parser.add_argument('-d', '--daemon',
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030038 choices=('start', 'stop', 'status',
39 'start_monitoring', 'stop_monitoring',
40 'dump_ram_data'),
koder aka kdanilovdda86d32015-03-16 11:20:04 +020041 default=None)
42
43 parser.add_argument('-u', '--url', default='stdout://')
44 parser.add_argument('-t', '--timeout', type=float, default=1)
koder aka kdanilov8097a4e2015-03-18 11:07:35 +020045 parser.add_argument('-l', '--list-sensors', action='store_true')
koder aka kdanilovdda86d32015-03-16 11:20:04 +020046 parser.add_argument('sensors_config', type=argparse.FileType('r'),
47 default=None, nargs='?')
48 return parser.parse_args(args[1:])
49
50
51def daemon_main(required_sensors, opts):
koder aka kdanilove87ae652015-04-20 02:14:35 +030052 try:
53 source_id = str(required_sensors.pop('source_id'))
54 except KeyError:
55 source_id = None
koder aka kdanilov168f6092015-04-19 02:33:38 +030056
Alyona Kiseleva7f6de4f2015-04-21 01:04:20 +030057 sender = create_protocol(opts.url)
58 prev = {}
koder aka kdanilov57ce4db2015-04-25 21:25:51 +030059 next_data_record_time = time.time()
Alyona Kiseleva7f6de4f2015-04-21 01:04:20 +030060
koder aka kdanilovf86d7af2015-05-06 04:01:54 +030061 first_round = True
koder aka kdanilove87ae652015-04-20 02:14:35 +030062 while True:
koder aka kdanilov57ce4db2015-04-25 21:25:51 +030063 real_time = int(time.time())
64
65 if real_time < int(next_data_record_time):
66 if int(next_data_record_time) - real_time > 2:
67 print "Error: sleep too small portion!!"
68 report_time = int(next_data_record_time)
69 elif real_time > int(next_data_record_time):
70 if real_time - int(next_data_record_time) > 2:
71 report_time = real_time
72 else:
73 report_time = int(next_data_record_time)
74 else:
75 report_time = real_time
76
77 data = get_values(required_sensors.items())
78 curr = {'time': SensorInfo(report_time, True)}
koder aka kdanilovdda86d32015-03-16 11:20:04 +020079 for name, val in data.items():
80 if val.is_accumulated:
81 if name in prev:
82 curr[name] = SensorInfo(val.value - prev[name], True)
83 prev[name] = val.value
84 else:
85 curr[name] = SensorInfo(val.value, False)
koder aka kdanilov168f6092015-04-19 02:33:38 +030086
87 if source_id is not None:
88 curr['source_id'] = source_id
89
koder aka kdanilovf86d7af2015-05-06 04:01:54 +030090 # on first round not all fields was ready
91 # this leads to setting wrong headers list
92 if not first_round:
93 sender.send(curr)
94 else:
95 first_round = False
Alyona Kiseleva7f6de4f2015-04-21 01:04:20 +030096
koder aka kdanilov57ce4db2015-04-25 21:25:51 +030097 next_data_record_time = report_time + opts.timeout + 0.5
98 time.sleep(next_data_record_time - time.time())
koder aka kdanilovdda86d32015-03-16 11:20:04 +020099
100
koder aka kdanilov2c473092015-03-29 17:12:13 +0300101def pid_running(pid):
102 return os.path.exists("/proc/" + str(pid))
103
104
koder aka kdanilovdda86d32015-03-16 11:20:04 +0200105def main(argv):
106 opts = parse_args(argv)
107
koder aka kdanilov8097a4e2015-03-18 11:07:35 +0200108 if opts.list_sensors:
koder aka kdanilove06762a2015-03-22 23:32:09 +0200109 print "\n".join(sorted(all_sensors))
koder aka kdanilov8097a4e2015-03-18 11:07:35 +0200110 return 0
111
koder aka kdanilovdda86d32015-03-16 11:20:04 +0200112 if opts.daemon is not None:
113 pid_file = "/tmp/sensors.pid"
114 if opts.daemon == 'start':
115 required_sensors = json.loads(opts.sensors_config.read())
116
117 def root_func():
118 daemon_main(required_sensors, opts)
119
120 daemon = Daemonize(app="perfcollect_app",
121 pid=pid_file,
122 action=root_func)
123 daemon.start()
124 elif opts.daemon == 'stop':
125 if os.path.isfile(pid_file):
126 pid = int(open(pid_file).read())
koder aka kdanilov2c473092015-03-29 17:12:13 +0300127 if pid_running(pid):
koder aka kdanilovdda86d32015-03-16 11:20:04 +0200128 os.kill(pid, signal.SIGTERM)
129
koder aka kdanilov57ce4db2015-04-25 21:25:51 +0300130 time.sleep(0.5)
koder aka kdanilovdda86d32015-03-16 11:20:04 +0200131
koder aka kdanilov2c473092015-03-29 17:12:13 +0300132 if pid_running(pid):
koder aka kdanilovdda86d32015-03-16 11:20:04 +0200133 os.kill(pid, signal.SIGKILL)
134
koder aka kdanilov57ce4db2015-04-25 21:25:51 +0300135 time.sleep(0.5)
136
koder aka kdanilovdda86d32015-03-16 11:20:04 +0200137 if os.path.isfile(pid_file):
138 os.unlink(pid_file)
139 elif opts.daemon == 'status':
140 if os.path.isfile(pid_file):
141 pid = int(open(pid_file).read())
koder aka kdanilov2c473092015-03-29 17:12:13 +0300142 if pid_running(pid):
koder aka kdanilovdda86d32015-03-16 11:20:04 +0200143 print "running"
144 return
145 print "stopped"
146 else:
147 raise ValueError("Unknown daemon operation {}".format(opts.daemon))
148 else:
149 required_sensors = json.loads(opts.sensors_config.read())
150 daemon_main(required_sensors, opts)
151 return 0
152
153if __name__ == "__main__":
154 exit(main(sys.argv))