3 # RunlevelAgent - acts as a heartbeat back to myplc reporting that the node is
4 # online and whether it is in boot or pre-boot run-level.
5 # This is useful to identify nodes that are behind a firewall, as well as to
6 # have the machine report run-time status both in safeboot and boot modes,
7 # so that it is immediately visible at myplc (gui or api).
18 CONFIG_FILE="/tmp/source/configuration"
19 SESSION_FILE="/etc/planetlab/session"
21 def read_config_file(filename):
22 ## NOTE: text copied from BootManager.py
23 # TODO: unify this code to make it common. i.e. use ConfigParser module
25 vars_file= file(filename,'r')
27 for line in vars_file:
28 # if its a comment or a whitespace line, ignore
29 if line[:1] == "#" or string.strip(line) == "":
32 parts= string.split(line,"=")
34 print "Invalid line in vars file: %s" % line
38 name= string.strip(parts[0])
39 value= string.strip(parts[1])
44 print "Unable to read configuration vars."
49 sys.path = ['/etc/planetlab'] + sys.path
51 api_server_url = "https://" + plc_config.PLC_API_HOST + plc_config.PLC_API_PATH
54 vars = read_config_file(filename)
55 api_server_url = vars['BOOT_API_SERVER']
59 def __init__(self, username=None, password=None, **kwargs):
60 if 'session' in kwargs:
61 self.auth= { 'AuthMethod' : 'session',
62 'session' : kwargs['session'] }
64 if username==None and password==None:
65 self.auth = {'AuthMethod': "anonymous"}
67 self.auth = {'Username' : username,
68 'AuthMethod' : 'password',
69 'AuthString' : password}
71 def __init__(self, auth, url):
74 self.api = xmlrpclib.Server(self.url, verbose=False, allow_none=True)
76 def __getattr__(self, name):
77 method = getattr(self.api, name)
79 raise AssertionError("method does not exist")
81 return lambda *params : method(self.auth.auth, *params)
84 return self.api.__repr__()
86 def extract_from(filename, pattern):
87 f = os.popen("grep -E %s %s" % (pattern, filename))
88 val = f.read().strip()
91 def check_running(commandname):
92 f = os.popen("ps ax | grep -E %s | grep -v grep" % (commandname))
93 val = f.read().strip()
99 # Keep trying to authenticate session, waiting for NM to re-write the
100 # session file, or DNS to succeed, until AuthCheck succeeds.
103 f=open(SESSION_FILE,'r')
104 session_str=f.read().strip()
105 api = PLC(Auth(session=session_str), api_server_url)
106 # NOTE: What should we do if this call fails?
107 # TODO: handle dns failure here.
111 print "Retry in 30 seconds: ", os.popen("uptime").read().strip()
112 traceback.print_exc()
117 if len(sys.argv) > 1:
120 traceback.print_exc()
124 # NOTE: here we are inferring the runlevel by environmental
125 # observations. We know how this process was started by the
126 # given command line argument. Then in bootmanager
127 # runlevel, the bm.log gives information about the current
130 # call plc for current boot state?
131 # how long have we been running?
132 if env == "bootmanager":
133 bs_val = extract_from('/tmp/bm.log', "'Current boot state:'")
134 if len(bs_val) > 0: bs_val = bs_val.split()[-1]
135 ex_val = extract_from('/tmp/bm.log', 'Exception')
136 fs_val = extract_from('/tmp/bm.log', 'mke2fs')
137 bm_val = check_running("BootManager.py")
139 if bs_val in ['diag', 'diagnose', 'safeboot', 'disabled', 'disable']:
140 api.ReportRunlevel({'run_level' : 'safeboot'})
142 elif len(ex_val) > len("Exception"):
143 api.ReportRunlevel({'run_level' : 'failboot'})
145 elif len(fs_val) > 0 and len(bm_val) > 0:
146 api.ReportRunlevel({'run_level' : 'reinstall'})
149 api.ReportRunlevel({'run_level' : 'failboot'})
151 elif env == "production":
152 api.ReportRunlevel({'run_level' : 'boot'})
154 api.ReportRunlevel({'run_level' : 'failboot'})
157 print "reporting error: ", os.popen("uptime").read().strip()
158 traceback.print_exc()
161 # TODO: change to a configurable value
164 if __name__ == "__main__":