add a --module option for testing one module at a time
[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=['proper', 'conf_files', 'sm', 'bwmon']
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     try: data = plc.GetSlivers()
40     except: logger.log_exc()
41     if (options.verbose):
42         logger.log_slivers(data)
43     # Set i2 ip list for nodes in I2 nodegroup.
44     try: net.GetSlivers(plc, data)
45     except: logger.log_exc()
46     #  All other callback modules
47     for module in modules:
48         try:        
49             callback = getattr(module, 'GetSlivers')
50             callback(data)
51         except: logger.log_exc()
52
53 def run():
54     try:
55         if options.daemon: tools.daemon()
56
57         # set log level
58         if (options.verbose):
59             logger.set_level(logger.LOG_VERBOSE)
60
61         # Load /etc/planetlab/plc_config
62         config = Config(options.config)
63
64         try:
65             other_pid = tools.pid_file()
66             if other_pid != None:
67                 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)
68                 return
69         except OSError, err:
70             print "Warning while writing PID file:", err
71
72         # Load and start modules
73         if options.module:
74             assert options.module in known_modules
75             running_modules=[options.module]
76             logger.verbose('Running single module %s'%options.module)
77         else:
78             running_modules=known_modules
79         for module in running_modules:
80             try:
81                 m = __import__(module)
82                 m.start(options, config)
83                 modules.append(m)
84             except ImportError, err:
85                 print "Warning while loading module %s:" % module, err
86
87         # Load /etc/planetlab/session
88         if os.path.exists(options.session):
89             session = file(options.session).read().strip()
90         else:
91             session = options.session
92
93         # Initialize XML-RPC client
94         iperiod=int(options.period)
95         irandom=int(options.random)
96         plc = PLCAPI(config.plc_api_uri, config.cacert, session, timeout=iperiod/2)
97
98         while True:
99         # Main NM Loop
100             logger.verbose('mainloop - nm:getSlivers - period=%d random=%d'%(iperiod,irandom))
101             GetSlivers(plc)
102             delay=iperiod + random.randrange(0,irandom)
103             logger.verbose('mainloop - sleeping for %d s'%delay)
104             time.sleep(delay)
105     except: logger.log_exc()
106
107
108 if __name__ == '__main__':
109     logger.log("Entering nm.py "+id)
110     stacklim = 512*1024  # 0.5 MiB
111     curlim = resource.getrlimit(resource.RLIMIT_STACK)[0]  # soft limit
112     if curlim > stacklim:
113         resource.setrlimit(resource.RLIMIT_STACK, (stacklim, stacklim))
114         # for some reason, doesn't take effect properly without the exec()
115         python = '/usr/bin/python'
116         os.execv(python, [python] + savedargv)
117     run()
118 else:
119     # This is for debugging purposes.  Open a copy of Python and import nm
120     tools.as_daemon_thread(run)