5 # Mark Huang <mlhuang@cs.princeton.edu>
6 # Copyright (C) 2006 The Trustees of Princeton University
17 # /etc/planetlab/plc_config.py is a Python fragment maintained by
18 # PlanetLabConf that contains PLC configuration variables.
20 sys.path.append("/etc/planetlab")
21 from plc_config import *
23 print "Warning: Configuration file /etc/planetlab/plc_config.py not found"
24 PLC_NAME = "PlanetLab"
25 PLC_SLICE_PREFIX = "pl"
26 PLC_MAIL_SUPPORT_ADDRESS = "support@planet-lab.org"
27 PLC_MAIL_SLICE_ADDRESS = "SLICE@slices.planet-lab.org"
29 def format_bytes(bytes, si = True):
31 Formats bytes into a string
36 # Officially, a kibibyte
39 if bytes >= (kilo * kilo * kilo):
40 return "%.1f GB" % (bytes / (kilo * kilo * kilo))
41 elif bytes >= 1000000:
42 return "%.1f MB" % (bytes / (kilo * kilo))
44 return "%.1f KB" % (bytes / kilo)
46 return "%.0f bytes" % bytes
48 def format_period(seconds):
50 Formats a period in seconds into a string
53 if seconds == (24 * 60 * 60):
55 elif seconds == (60 * 60):
57 elif seconds > (24 * 60 * 60):
58 return "%.1f days" % (seconds / 24. / 60. / 60.)
59 elif seconds > (60 * 60):
60 return "%.1f hours" % (seconds / 60. / 60.)
62 return "%.1f minutes" % (seconds / 60.)
64 return "%.0f seconds" % seconds
68 Check PID file. Exit if already running. Update PID file.
72 pidfile = file("/var/run/%s.pid" % prog, "r")
73 pid = pidfile.readline().strip()
75 if os.path.isdir("/proc/" + pid):
76 print "Error: Another copy of %s is still running (%s)" % (prog, pid)
81 pidfile = file("/var/run/%s.pid" % prog, "w")
82 pidfile.write(str(os.getpid()))
86 os.unlink("/var/run/%s.pid" % prog)
88 def slicemail(slice, subject, body):
89 sendmail = os.popen("/usr/sbin/sendmail -t -f%s" % PLC_MAIL_SUPPORT_ADDRESS, "w")
91 # PLC has a separate list for pl_mom messages
92 if PLC_MAIL_SUPPORT_ADDRESS == "support@planet-lab.org":
93 to = ["pl-mom@planet-lab.org"]
95 to = [PLC_MAIL_SUPPORT_ADDRESS]
97 if slice is not None and slice != "root":
98 to.append(PLC_MAIL_SLICE_ADDRESS.replace("SLICE", slice))
100 header = {'from': "%s Support <%s>" % (PLC_NAME, PLC_MAIL_SUPPORT_ADDRESS),
102 'version': sys.version.split(" ")[0],
108 Content-type: text/plain
112 X-Mailer: Python/%(version)s
115 """.lstrip() % header)
125 Simple file-like class for redirecting stdout and stderr to /var/log/messages
128 def write(self, text):
135 Daemonize self. Detach from terminal, close all open files, and fork twice.
140 # Detach from terminal
151 # Close all open file descriptors
153 maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
154 if (maxfd == resource.RLIM_INFINITY):
156 for fd in range(0, maxfd):
162 # Redirect stdin to /dev/null
163 os.open("/dev/null", os.O_RDWR)
167 Simple interface to local Node Manager API
170 def __init__(self, url = "http://localhost:812/", timeout = 10):
172 Open a new connection to the local Node Manager
175 socket.setdefaulttimeout(timeout)
177 self.nm = xmlrpclib.ServerProxy(url)
178 except Exception, err:
179 print "Warning: Exception received while opening connection to Node Manager:", err
184 Close connection to the local Node Manager
187 if self.nm is not None:
190 def query(self, slice, attributes):
192 Get values of various slice attributes from the local Node Manager
195 attributes - [attribute_name, (attribute_name, return_value_if_not_set), ...]
198 values = [None for attribute in attributes]
200 if self.nm is not None:
202 # Read rspec (the NM hash code for the slice)
203 rcap = open("/var/run/pl_nm/%s.vm_rcap" % slice, "r")
204 rspec = rcap.readline().strip()
207 for i, attribute in enumerate(attributes):
208 # NM interface allows you to pass in a tuple
209 # (attribute, default) instead of just an
210 # attribute name. default is returned if the
211 # attribute is not set.
212 if type(attribute) != tuple:
213 attribute = (attribute, 0)
214 (rc, (value,)) = self.nm.nm_inspect(rspec, [attribute])
215 if rc == 0 and value != attribute[1]:
217 except Exception, err:
218 print "Warning: Exception received while querying Node Manager:", err