d959dc9acf60fa12e9bd1d0ca8cd29bd5c2c8cc8
[monitor.git] / RunlevelAgent.py
1 #!/usr/bin/python
2
3 import xml, xmlrpclib
4 import logging
5 import time
6 import traceback
7 import sys
8 import os
9 import string
10
11 CONFIG_FILE="/tmp/source/configuration"
12 SESSION_FILE="/etc/planetlab/session"
13
14 def read_config_file(filename):
15     ## NOTE: text copied from BootManager.py 
16     # TODO: unify this code to make it common. i.e. use ConfigParser module
17     vars = {}
18     vars_file= file(filename,'r')
19     validConfFile = True
20     for line in vars_file:
21         # if its a comment or a whitespace line, ignore
22         if line[:1] == "#" or string.strip(line) == "":
23             continue
24
25         parts= string.split(line,"=")
26         if len(parts) != 2:
27             print "Invalid line in vars file: %s" % line
28             validConfFile = False
29             break
30
31         name= string.strip(parts[0])
32         value= string.strip(parts[1])
33         vars[name]= value
34
35     vars_file.close()
36     if not validConfFile:
37         print "Unable to read configuration vars."
38
39     return vars
40
41 try:
42     sys.path = ['/etc/planetlab'] + sys.path
43     import plc_config
44     api_server_url = "https://" + plc_config.PLC_API_HOST + plc_config.PLC_API_PATH
45 except:
46     filename=CONFIG_FILE
47     vars = read_config_file(filename)
48     api_server_url = vars['BOOT_API_SERVER']
49
50
51 class Auth:
52     def __init__(self, username=None, password=None, **kwargs):
53         if 'session' in kwargs:
54             self.auth= { 'AuthMethod' : 'session',
55                     'session' : kwargs['session'] }
56         else:
57             if username==None and password==None:
58                 self.auth = {'AuthMethod': "anonymous"}
59             else:
60                 self.auth = {'Username' : username,
61                             'AuthMethod' : 'password',
62                             'AuthString' : password}
63 class PLC:
64     def __init__(self, auth, url):
65         self.auth = auth
66         self.url = url
67         self.api = xmlrpclib.Server(self.url, verbose=False, allow_none=True)
68
69     def __getattr__(self, name):
70         method = getattr(self.api, name)
71         if method is None:
72             raise AssertionError("method does not exist")
73
74         return lambda *params : method(self.auth.auth, *params)
75
76     def __repr__(self):
77         return self.api.__repr__()
78
79 def extract_from(filename, pattern):
80         f = os.popen("grep -E %s %s" % (pattern, filename))
81         val = f.read().strip()
82         return val
83
84 def check_running(commandname):
85         f = os.popen("ps ax | grep -E %s | grep -v grep" % (commandname))
86         val = f.read().strip()
87         return val
88         
89
90 def main():
91
92     f=open(SESSION_FILE,'r')
93     session_str=f.read().strip()
94     api = PLC(Auth(session=session_str), api_server_url)
95         # NOTE: What should we do if this call fails?
96     api.AuthCheck()
97
98     try:
99         env = 'production'
100         if len(sys.argv) > 1:
101             env = sys.argv[1]
102     except:
103         traceback.print_exc()
104
105     while True:
106         #print "reporting status: ", os.popen("uptime").read().strip()
107         try:
108             # NOTE: here we are inferring the runlevel by environmental
109                         #               observations.  We know how this process was started by the
110                         #               given command line argument.  Then in bootmanager
111                         #               runlevle, the bm.log gives information about the current
112                         #               activity.
113                         # other options:
114                         #   call plc for current boot state?
115                         #   how long have we been running?
116             if env == "bootmanager":
117                                 bs_val = extract_from('/tmp/bm.log', 'Current boot state:').split()[3]
118                                 ex_val = extract_from('/tmp/bm.log', 'Exception')
119                                 fs_val = extract_from('/tmp/bm.log', 'mke2fs')
120                                 bm_val = check_running("BootManager.py")
121
122                                 if bs_val in ['diag', 'diagnose', 'safeboot', 'disabled', 'disable']:
123                         api.ReportRunlevel({'run_level' : 'safeboot'})
124
125                                 elif len(ex_val) > len("Exception"):
126                         api.ReportRunlevel({'run_level' : 'failboot'})
127
128                                 elif len(fs_val) > 0 and len(bm_val) > 0:
129                         api.ReportRunlevel({'run_level' : 'reinstall'})
130
131                                 else:
132                         api.ReportRunlevel({'run_level' : 'failboot'})
133
134             elif env == "production":
135                 api.ReportRunlevel({'run_level' : 'boot'})
136             else:
137                 api.ReportRunlevel({'run_level' : 'failboot'})
138                 
139         except:
140             traceback.print_exc()
141
142         # TODO: change to a configurable value
143         sys.stdout.flush()
144         time.sleep(60*15)
145
146 if __name__ == "__main__":
147     main()