#!/usr/bin/python # # Utility functions # # Mark Huang # Copyright (C) 2006 The Trustees of Princeton University # # $Id$ # import os import sys import syslog import socket import xmlrpclib # /etc/planetlab/plc_config.py is a Python fragment maintained by # PlanetLabConf that contains PLC configuration variables. try: sys.path.append("/etc/planetlab") from plc_config import * except: print "Warning: Configuration file /etc/planetlab/plc_config.py not found" PLC_NAME = "PlanetLab" PLC_SLICE_PREFIX = "pl" PLC_MAIL_SUPPORT_ADDRESS = "root@" + socket.gethostname() PLC_MAIL_SLICE_ADDRESS = "SLICE@" + socket.gethostname() def format_bytes(bytes, si = True): """ Formats bytes into a string """ if si: kilo = 1000. else: # Officially, a kibibyte kilo = 1024. if bytes >= (kilo * kilo * kilo): return "%.1f GB" % (bytes / (kilo * kilo * kilo)) elif bytes >= 1000000: return "%.1f MB" % (bytes / (kilo * kilo)) elif bytes >= 1000: return "%.1f KB" % (bytes / kilo) else: return "%.0f bytes" % bytes def format_period(seconds): """ Formats a period in seconds into a string """ if seconds == (24 * 60 * 60): return "day" elif seconds == (60 * 60): return "hour" elif seconds > (24 * 60 * 60): return "%.1f days" % (seconds / 24. / 60. / 60.) elif seconds > (60 * 60): return "%.1f hours" % (seconds / 60. / 60.) elif seconds > (60): return "%.1f minutes" % (seconds / 60.) else: return "%.0f seconds" % seconds def writepid(prog): """ Check PID file. Exit if already running. Update PID file. """ try: pidfile = file("/var/run/%s.pid" % prog, "r") pid = pidfile.readline().strip() pidfile.close() if os.path.isdir("/proc/" + pid): print "Error: Another copy of %s is still running (%s)" % (prog, pid) sys.exit(1) except IOError: pass pidfile = file("/var/run/%s.pid" % prog, "w") pidfile.write(str(os.getpid())) pidfile.close() def removepid(prog): os.unlink("/var/run/%s.pid" % prog) def slicemail(slice, subject, body): sendmail = os.popen("/usr/sbin/sendmail -N never -t -f%s" % PLC_MAIL_SUPPORT_ADDRESS, "w") to = [PLC_MAIL_MOM_LIST_ADDRESS] if slice is not None and slice != "root": to.append(PLC_MAIL_SLICE_ADDRESS.replace("SLICE", slice)) header = {'from': "%s Support <%s>" % (PLC_NAME, PLC_MAIL_SUPPORT_ADDRESS), 'to': ", ".join(to), 'version': sys.version.split(" ")[0], 'subject': subject} # Write headers sendmail.write( """ Content-type: text/plain From: %(from)s Reply-To: %(from)s To: %(to)s X-Mailer: Python/%(version)s Subject: %(subject)s """.lstrip() % header) # Write body sendmail.write(body) # Done sendmail.close() class Logger: """ Simple file-like class for redirecting stdout and stderr to /var/log/messages """ def write(self, text): text = text.strip() if text: syslog.syslog(text) def daemonize(): """ Daemonize self. Detach from terminal, close all open files, and fork twice. """ pid = os.fork() if pid == 0: # Detach from terminal os.setsid() # Orphan myself pid = os.fork() if pid == 0: os.chdir("/") else: os._exit(0) else: os._exit(0) # Close all open file descriptors import resource maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1] if (maxfd == resource.RLIM_INFINITY): maxfd = 1024 for fd in range(0, maxfd): try: os.close(fd) except OSError: pass # Redirect stdin to /dev/null os.open("/dev/null", os.O_RDWR) class NM: """ Simple interface to local Node Manager API """ def __init__(self, url = "http://localhost:812/", timeout = 30): """ Open a new connection to the local Node Manager """ socket.setdefaulttimeout(timeout) try: self.nm = xmlrpclib.ServerProxy(url) except Exception, err: print "Warning: Exception received while opening connection to Node Manager:", err self.nm = None def query(self, slice, attributes): """ Get values of various slice attributes from the local Node Manager slice - slice name attributes - [(attribute_name, return_value_if_not_set), ...] """ values = [attribute[1] for attribute in attributes] if self.nm is not None: # Read rspec (the NM hash code for the slice) rcap = open("/var/run/pl_nm/%s.vm_rcap" % slice, "r") rspec = rcap.readline().strip() rcap.close() (rc, result) = self.nm.nm_inspect(rspec, attributes) if rc == 0 and type(result) == list and len(result) == len(values): values = result return values