ea8af80e2b9cc6cae9374e093c1121191679d74e
[nodemanager.git] / nm.py
1 #!/usr/bin/python
2 """Node Manager"""
3
4 import optparse
5 import time
6 import xmlrpclib
7 import socket
8 import os
9 import sys
10 import resource
11
12 import logger
13 import tools
14
15 from config import Config
16 from plcapi import PLCAPI 
17 import random
18 import net
19
20 id="$Id$"
21 savedargv = sys.argv[:]
22
23 known_modules=['conf_files', 'sm', 'bwmon', 'vsys', 'codemux']
24
25 parser = optparse.OptionParser()
26 parser.add_option('-d', '--daemon', action='store_true', dest='daemon', default=False, help='run daemonized')
27 parser.add_option('-s', '--startup', action='store_true', dest='startup', default=False, help='run all sliver startup scripts')
28 parser.add_option('-f', '--config', action='store', dest='config', default='/etc/planetlab/plc_config', help='PLC configuration file')
29 parser.add_option('-k', '--session', action='store', dest='session', default='/etc/planetlab/session', help='API session key (or file)')
30 parser.add_option('-p', '--period', action='store', dest='period', default=600, help='Polling interval (sec)')
31 parser.add_option('-r', '--random', action='store', dest='random', default=301, help='Range for additional random polling interval (sec)')
32 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False, help='more verbose log')
33 parser.add_option('-m', '--module', action='store', dest='module', default='', help='run a single module among '+' '.join(known_modules))
34 (options, args) = parser.parse_args()
35
36 modules = []
37
38 def GetSlivers(plc):
39     '''Run call backs defined in modules'''
40     try: 
41         logger.log("Syncing w/ PLC")
42         data = plc.GetSlivers()
43     except: 
44         logger.log_exc()
45         #  XXX So some modules can at least boostrap.
46         data = {}
47     if (options.verbose):
48         logger.log_slivers(data)
49     # Set i2 ip list for nodes in I2 nodegroup.
50     try: net.GetSlivers(plc, data)
51     except: logger.log_exc()
52     #  All other callback modules
53     for module in modules:
54         try:        
55             callback = getattr(module, 'GetSlivers')
56             callback(data)
57         except: logger.log_exc()
58
59 def run():
60     try:
61         if options.daemon: tools.daemon()
62
63         # set log level
64         if (options.verbose):
65             logger.set_level(logger.LOG_VERBOSE)
66
67         # Load /etc/planetlab/plc_config
68         config = Config(options.config)
69
70         try:
71             other_pid = tools.pid_file()
72             if other_pid != None:
73                 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)
74                 return
75         except OSError, err:
76             print "Warning while writing PID file:", err
77
78         # Load and start modules
79         if options.module:
80             assert options.module in known_modules
81             running_modules=[options.module]
82             logger.verbose('Running single module %s'%options.module)
83         else:
84             running_modules=known_modules
85         for module in running_modules:
86             try:
87                 m = __import__(module)
88                 m.start(options, config)
89                 modules.append(m)
90             except ImportError, err:
91                 print "Warning while loading module %s:" % module, err
92
93         # Load /etc/planetlab/session
94         if os.path.exists(options.session):
95             session = file(options.session).read().strip()
96         else:
97             session = options.session
98
99         # Initialize XML-RPC client
100         iperiod=int(options.period)
101         irandom=int(options.random)
102         plc = PLCAPI(config.plc_api_uri, config.cacert, session, timeout=iperiod/2)
103
104         while True:
105         # Main NM Loop
106             logger.verbose('mainloop - nm:getSlivers - period=%d random=%d'%(iperiod,irandom))
107             GetSlivers(plc)
108             delay=iperiod + random.randrange(0,irandom)
109             logger.verbose('mainloop - sleeping for %d s'%delay)
110             time.sleep(delay)
111     except: logger.log_exc()
112
113
114 if __name__ == '__main__':
115     logger.log("Entering nm.py "+id)
116     stacklim = 512*1024  # 0.5 MiB
117     curlim = resource.getrlimit(resource.RLIMIT_STACK)[0]  # soft limit
118     if curlim > stacklim:
119         resource.setrlimit(resource.RLIMIT_STACK, (stacklim, stacklim))
120         # for some reason, doesn't take effect properly without the exec()
121         python = '/usr/bin/python'
122         os.execv(python, [python] + savedargv)
123     run()
124 else:
125     # This is for debugging purposes.  Open a copy of Python and import nm
126     tools.as_daemon_thread(run)