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