Update host key in main loop.
[nodemanager.git] / nm.py
1 #!/usr/bin/python
2
3 """Node Manager"""
4
5 import optparse
6 import time
7 import xmlrpclib
8 import socket
9 import os
10 import sys
11 import resource
12
13 import logger
14 import tools
15
16 from config import Config
17 from plcapi import PLCAPI 
18 import random
19
20 savedargv = sys.argv[:]
21
22 parser = optparse.OptionParser()
23 parser.add_option('-d', '--daemon', action='store_true', dest='daemon', default=False, help='run daemonized')
24 parser.add_option('-s', '--startup', action='store_true', dest='startup', default=False, help='run all sliver startup scripts')
25 parser.add_option('-f', '--config', action='store', dest='config', default='/etc/planetlab/plc_config', help='PLC configuration file')
26 parser.add_option('-k', '--session', action='store', dest='session', default='/etc/planetlab/session', help='API session key (or file)')
27 parser.add_option('-p', '--period', action='store', dest='period', default=600, help='Polling interval (sec)')
28 (options, args) = parser.parse_args()
29
30 modules = []
31
32 def GetSlivers(plc):
33     data = plc.GetSlivers()
34     # net needs access to API for i2 nodes.
35     for module in modules:
36         if module.__name__ == 'net':
37             module.GetSlivers(plc, data)
38         else:
39             callback = getattr(module, 'GetSlivers')
40             callback(data)
41
42 def UpdateHostKey(plc):
43     logger.log('Trying to update ssh host key at PLC...')
44     ssh_host_key = open('/etc/ssh/ssh_host_rsa_key.pub').read().strip()
45     plc.BootUpdateNode(dict(ssh_host_key=ssh_host_key))
46     logger.log('Host key update succeeded')
47
48 def run():
49     try:
50         if options.daemon: tools.daemon()
51
52         # Load /etc/planetlab/plc_config
53         config = Config(options.config)
54
55         try:
56             other_pid = tools.pid_file()
57             if other_pid != None:
58                 print """There might be another instance of the node manager running as pid %d.  If this is not the case, please remove the pid file %s""" % (other_pid, tools.PID_FILE)
59                 return
60         except OSError, err:
61             print "Warning while writing PID file:", err
62
63         # Load and start modules
64         for module in ['net', 'proper', 'conf_files', 'sm', 'bwmon']:
65             try:
66                 m = __import__(module)
67                 m.start(options, config)
68                 modules.append(m)
69             except ImportError, err:
70                 print "Warning while loading module %s:" % module, err
71
72         # Load /etc/planetlab/session
73         if os.path.exists(options.session):
74             session = file(options.session).read().strip()
75         else:
76             session = options.session
77
78         # Initialize XML-RPC client
79         plc = PLCAPI(config.plc_api_uri, config.cacert, session, timeout=options.period/2)
80
81         while True:
82             try: UpdateHostKey(plc)
83             except: logger.log_exc()
84             try: GetSlivers(plc)
85             except: logger.log_exc()
86             time.sleep(options.period + random.randrange(0,301))
87     except: logger.log_exc()
88
89
90 if __name__ == '__main__':
91     stacklim = 512*1024  # 0.5 MiB
92     curlim = resource.getrlimit(resource.RLIMIT_STACK)[0]  # soft limit
93     if curlim > stacklim:
94         resource.setrlimit(resource.RLIMIT_STACK, (stacklim, stacklim))
95         # for some reason, doesn't take effect properly without the exec()
96         python = '/usr/bin/python'
97         os.execv(python, [python] + savedargv)
98     run()
99 else:
100     # This is for debugging purposes.  Open a copy of Python and import nm
101     tools.as_daemon_thread(run)