X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=tools.py;h=199d799def48edac009eae07c93f02133f922676;hb=refs%2Fheads%2F1.8;hp=994089e1bb69fe5ab4ee43b35106d09b4c4a43e2;hpb=28de48d05b66c4e7826d959a3ad48e87e8f13ee4;p=nodemanager.git diff --git a/tools.py b/tools.py index 994089e..199d799 100644 --- a/tools.py +++ b/tools.py @@ -6,12 +6,34 @@ import os import pwd import tempfile import threading - +import fcntl +import commands import logger - PID_FILE = '/var/run/nm.pid' +def get_default_if(): + interface = get_if_from_hwaddr(get_hwaddr_from_plnode()) + if not interface: interface = "eth0" + return interface + +def get_hwaddr_from_plnode(): + try: + for line in open("/usr/boot/plnode.txt", 'r').readlines(): + if line.startswith("NET_DEVICE"): + return line.split("=")[1].strip().strip('"') + except: + pass + return None + +def get_if_from_hwaddr(hwaddr): + import sioc + devs = sioc.gifconf() + for dev in devs: + dev_hwaddr = sioc.gifhwaddr(dev) + if dev_hwaddr == hwaddr: return dev + return None + def as_daemon_thread(run): """Call function with no arguments in its own thread.""" thr = threading.Thread(target=run) @@ -32,9 +54,13 @@ def daemon(): os.setsid() if os.fork() != 0: os._exit(0) os.chdir('/') - os.umask(0) + os.umask(0022) devnull = os.open(os.devnull, os.O_RDWR) - for fd in range(3): os.dup2(devnull, fd) + os.dup2(devnull, 0) + # xxx fixme - this is just to make sure that nothing gets stupidly lost - should use devnull + crashlog = os.open('/var/log/nm.daemon', os.O_RDWR | os.O_APPEND | os.O_CREAT, 0644) + os.dup2(crashlog, 1) + os.dup2(crashlog, 2) def fork_as(su, function, *args): """fork(), cd / to avoid keeping unused directories open, close all nonstandard file descriptors (to avoid capturing open sockets), fork() again (to avoid zombies) and call with arguments in the grandchild process. If is not None, set our group and user ids appropriately in the child process.""" @@ -43,9 +69,10 @@ def fork_as(su, function, *args): try: os.chdir('/') close_nonstandard_fds() - pw_ent = pwd.getpwnam(su) - os.setegid(pw_ent[3]) - os.seteuid(pw_ent[2]) + if su: + pw_ent = pwd.getpwnam(su) + os.setegid(pw_ent[3]) + os.seteuid(pw_ent[2]) child_pid = os.fork() if child_pid == 0: function(*args) except: @@ -84,3 +111,82 @@ def write_temp_file(do_write, mode=None, uidgid=None): try: do_write(f) finally: f.close() return temporary_filename + +# replace a target file with a new contents - checks for changes +# can handle chmod if requested +# can also remove resulting file if contents are void, if requested +# performs atomically: +# writes in a tmp file, which is then renamed (from sliverauth originally) +# returns True if a change occurred, or the file is deleted +def replace_file_with_string (target, new_contents, chmod=None, remove_if_empty=False): + try: + current=file(target).read() + except: + current="" + if current==new_contents: + # if turns out to be an empty string, and remove_if_empty is set, + # then make sure to trash the file if it exists + if remove_if_empty and not new_contents and os.path.isfile(target): + logger.verbose("tools.replace_file_with_string: removing file %s"%target) + try: os.unlink(target) + finally: return True + return False + # overwrite target file: create a temp in the same directory + path=os.path.dirname(target) or '.' + fd, name = tempfile.mkstemp('','repl',path) + os.write(fd,new_contents) + os.close(fd) + if os.path.exists(target): + os.unlink(target) + os.rename(name,target) + if chmod: os.chmod(target,chmod) + return True + +# utilities functions to get (cached) information from the node + +# get node_id from /etc/planetlab/node_id and cache it +_node_id=None +def node_id(): + global _node_id + if _node_id is None: + try: + _node_id=int(file("/etc/planetlab/node_id").read()) + except: + _node_id="" + return _node_id + +# get slicefamily from /etc/planetlab/slicefamily and cache it +# http://svn.planet-lab.org/wiki/SliceFamily +_slicefamily=None +def slicefamily(): + global _slicefamily + if _slicefamily is None: + try: + _slicefamily=file("/etc/planetlab/slicefamily").read().strip() + except: + _slicefamily="" + return _slicefamily + +_root_context_arch=None +def root_context_arch(): + global _root_context_arch + if not _root_context_arch: + _root_context_arch=commands.getoutput("uname -i") + return _root_context_arch + + +class NMLock: + def __init__(self, file): + logger.log("Lock %s initialized." % file, 2) + self.fd = os.open(file, os.O_RDWR|os.O_CREAT, 0600) + flags = fcntl.fcntl(self.fd, fcntl.F_GETFD) + flags |= fcntl.FD_CLOEXEC + fcntl.fcntl(self.fd, fcntl.F_SETFD, flags) + def __del__(self): + os.close(self.fd) + def acquire(self): + logger.log("Lock acquired.", 2) + fcntl.lockf(self.fd, fcntl.LOCK_SH) + def release(self): + logger.log("Lock released.", 2) + fcntl.lockf(self.fd, fcntl.LOCK_UN)