Merge branch 'devel' of ssh://git.planet-lab.org/git/nodemanager into devel devel
authorMarco Yuen <marcoy@gmail.com>
Tue, 12 Jul 2011 16:20:55 +0000 (12:20 -0400)
committerMarco Yuen <marcoy@gmail.com>
Tue, 12 Jul 2011 16:20:55 +0000 (12:20 -0400)
Conflicts:
plugins/euca_iptables.py

NodeManager.spec
bootauth.py
config.py
coresched.py
curlwrapper.py
plcapi.py
plugins/euca_iptables.py
safexmlrpc.py

index 7c709cf..579243f 100644 (file)
@@ -2,7 +2,7 @@
 
 %define name NodeManager
 %define version 2.0
-%define taglevel 32
+%define taglevel 33
 
 %define release %{taglevel}%{?pldistro:.%{pldistro}}%{?date:.%{date}}
 
@@ -131,6 +131,10 @@ rm -rf $RPM_BUILD_ROOT
 /var/lib/
 
 %changelog
+* Thu Jul 07 2011 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - nodemanager-2.0-33
+- tweaked log policy for the core scheduler
+- curlwrapper has an optional verbose mode
+
 * Mon Jun 06 2011 Baris Metin <bmetin@verivue.com> - nodemanager-2.0-32
 - fixes for hmac and omf_control tags
 - optional besteffort flag to core scheduler
index 445891e..dae075c 100755 (executable)
@@ -1,16 +1,11 @@
 #!/usr/bin/python
 #
-# $Id$
-# $URL$
-#
-# Test script for obtaining a node session key. Usually, the Boot
+# Obtaining a node session key. Usually, the Boot
 # Manager obtains it, then writes it to /etc/planetlab/session.
 #
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id$
-#
 
 import os, sys
 import getopt
index 9efdecc..cfc35f8 100644 (file)
--- a/config.py
+++ b/config.py
@@ -1,16 +1,11 @@
 #!/usr/bin/python
 #
-# $Id$
-# $URL$
-#
 # Parses the PLC configuration file /etc/planetlab/plc_config, which
 # is bootstrapped by Boot Manager, but managed by us.
 #
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id$
-#
 
 import os
 
index dd6dd04..0802ad8 100644 (file)
@@ -21,8 +21,32 @@ class CoreSched:
         One core is always left unreserved for system slices.
     """
 
-    def __init__(self):
+    def __init__(self, cgroup_var_name="cpuset.cpus", slice_attr_name="cpu_cores"):
         self.cpus = []
+        self.cgroup_var_name = cgroup_var_name
+        self.slice_attr_name = slice_attr_name
+
+    def get_cgroup_var(self, name):
+        """ decode cpuset.cpus or cpuset.mems into a list of units that can
+            be reserved.
+        """
+
+        data = open("/dev/cgroup/" + name).readline().strip()
+
+        units = []
+
+        # cpuset.cpus could be something as arbitrary as:
+        #    0,1,2-3,4,5-6
+        # deal with commas and ranges
+        for part in data.split(","):
+            unitRange = part.split("-")
+            if len(unitRange) == 1:
+                unitRange = (unitRange[0], unitRange[0])
+            for i in range(int(unitRange[0]), int(unitRange[1])+1):
+                if not i in units:
+                    units.append(i)
+
+        return units
 
     def get_cpus(self):
         """ return a list of available cpu identifiers: [0,1,2,3...]
@@ -33,20 +57,9 @@ class CoreSched:
         if self.cpus!=[]:
             return self.cpus
 
-        cpuset_cpus = open("/dev/cgroup/cpuset.cpus").readline().strip()
+        self.cpus = self.get_cgroup_var(self.cgroup_var_name)
 
-        # cpuset.cpus could be something as arbitrary as:
-        #    0,1,2-3,4,5-6
-        # deal with commas and ranges
-        for part in cpuset_cpus.split(","):
-            cpuRange = part.split("-")
-            if len(cpuRange) == 1:
-                cpuRange = (cpuRange[0], cpuRange[0])
-            for i in range(int(cpuRange[0]), int(cpuRange[1])+1):
-                if not i in self.cpus:
-                    self.cpus.append(i)
-
-            return self.cpus
+        return self.cpus
 
     def get_cgroups (self):
         """ return a list of cgroups
@@ -84,48 +97,50 @@ class CoreSched:
                     rec['_rspec'] is the effective rspec
         """
 
-        logger.log("CoreSched: adjusting cores")
-
         cpus = self.get_cpus()[:]
 
+        logger.log("CoreSched (" + self.cgroup_var_name + "): available units: " + str(cpus))
+
         reservations = {}
 
         # allocate the cores to the slivers that have them reserved
         for name, rec in slivers.iteritems():
             rspec = rec["_rspec"]
-            cores = rspec.get("cpu_cores", 0)
+            cores = rspec.get(self.slice_attr_name, 0)
             (cores, bestEffort) = self.decodeCoreSpec(cores)
 
             while (cores>0):
                 # one cpu core reserved for best effort and system slices
                 if len(cpus)<=1:
-                    logger.log("CoreSched: ran out of cpu cores while scheduling: " + name)
+                    logger.log("CoreSched: ran out of units while scheduling sliver " + name)
                 else:
                     cpu = cpus.pop()
-                    logger.log("CoreSched: allocating cpu " + str(cpu) + " to slice " + name)
+                    logger.log("CoreSched: allocating unit " + str(cpu) + " to slice " + name)
                     reservations[name] = reservations.get(name,[]) + [cpu]
 
                 cores = cores-1
 
         # the leftovers go to everyone else
-        logger.log("CoreSched: allocating cpus " + str(cpus) + " to _default")
+        logger.log("CoreSched: allocating unit " + str(cpus) + " to _default")
         reservations["_default"] = cpus[:]
 
-        # now check and see if any of our reservations had the besteffort flag
+        # now check and see if any of our slices had the besteffort flag
         # set
         for name, rec in slivers.iteritems():
             rspec = rec["_rspec"]
-            cores = rspec.get("cpu_cores", 0)
+            cores = rspec.get(self.slice_attr_name, 0)
             (cores, bestEffort) = self.decodeCoreSpec(cores)
 
-            if not (reservations.get(name,[])):
-                # if there is no reservation for this slice, then it's already
-                # besteffort by default.
+            # if the bestEffort flag isn't set then we have nothing to do
+            if not bestEffort:
                 continue
 
-            if bestEffort:
+            # note that if a reservation is [], then we don't need to add
+            # bestEffort cores to it, since it is bestEffort by default.
+
+            if reservations.get(name,[]) != []:
                 reservations[name] = reservations[name] + reservations["_default"]
-                logger.log("CoreSched: adding besteffort cores to " + name + ". new cores = " + str(reservations[name]))
+                logger.log("CoreSched: adding besteffort units to " + name + ". new units = " + str(reservations[name]))
 
         self.reserveCores(reservations)
 
@@ -146,17 +161,20 @@ class CoreSched:
         self.reserveDefault(default)
 
         for cgroup in self.get_cgroups():
-            cpus = reservations.get(cgroup, default)
-
-            logger.log("CoreSched: reserving " + cgroup + " " + str(cpus))
+            if cgroup in reservations:
+                cpus = reservations[cgroup]
+                logger.log("CoreSched: reserving " + self.cgroup_var_name + " on " + cgroup + ": " + str(cpus))
+            else:
+                # no log message for default; too much verbosity in the common case
+                cpus = default
 
-            file("/dev/cgroup/" + cgroup + "/cpuset.cpus", "w").write( self.listToRange(cpus) + "\n" )
+            file("/dev/cgroup/" + cgroup + "/" + self.cgroup_var_name, "w").write( self.listToRange(cpus) + "\n" )
 
     def reserveDefault (self, cpus):
         if not os.path.exists("/etc/vservers/.defaults/cgroup"):
             os.makedirs("/etc/vservers/.defaults/cgroup")
 
-        file("/etc/vservers/.defaults/cgroup/cpuset.cpus", "w").write( self.listToRange(cpus) + "\n" )
+        file("/etc/vservers/.defaults/cgroup/" + self.cgroup_var_name, "w").write( self.listToRange(cpus) + "\n" )
 
     def listToRange (self, list):
         """ take a list of items [1,2,3,5,...] and return it as a range: "1-3,5"
index 21b499c..08223e3 100644 (file)
@@ -3,7 +3,7 @@
 # it turned out, however, that after around 10 cycles of the nodemanager,
 # attempts to call GetSlivers were failing with a curl error 60
 # we are thus reverting to the version from tag curlwrapper.py-NodeManager-2.0-8
-# the (broekn) pycurl version can be found in tags 2.0-9 and 2.0-10
+# the (broken) pycurl version can be found in tags 2.0-9 and 2.0-10
 
 from subprocess import PIPE, Popen
 from select import select
@@ -13,19 +13,26 @@ import os
 
 import logger
 
+verbose=False
+#verbose=True
+
 class Sopen(Popen):
     def kill(self, signal = signal.SIGTERM):
         os.kill(self.pid, signal)
 
 def retrieve(url, cacert=None, postdata=None, timeout=90):
-#    options = ('/usr/bin/curl', '--fail', '--silent')
-    options = ('/usr/bin/curl', '--fail', )
-    if cacert: options += ('--cacert', cacert)
-    if postdata: options += ('--data', '@-')
+#    command = ('/usr/bin/curl', '--fail', '--silent')
+    command = ('/usr/bin/curl', '--fail', )
+    if cacert: command += ('--cacert', cacert)
+    if postdata: command += ('--data', '@-')
     if timeout: 
-        options += ('--max-time', str(timeout))
-        options += ('--connect-timeout', str(timeout))
-    p = Sopen(options + (url,), stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
+        command += ('--max-time', str(timeout))
+        command += ('--connect-timeout', str(timeout))
+    command += (url,)
+    if verbose:
+        print 'Invoking ',command
+        if postdata: print 'with postdata=',postdata
+    p = Sopen(command , stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
     if postdata: p.stdin.write(postdata)
     p.stdin.close()
     sout, sin, serr = select([p.stdout,p.stderr],[],[], timeout)
index a6a74a4..acccda0 100644 (file)
--- a/plcapi.py
+++ b/plcapi.py
@@ -1,6 +1,3 @@
-# $Id$
-# $URL$
-
 import safexmlrpc
 import hmac
 try:
index 959e859..af4b3f7 100644 (file)
@@ -4,8 +4,30 @@
 #
 # Author: Marco Yuen <marcoy@cs.princeton.edu>
 
+import logger
+import logging
+
+def start():
+    logger.log("euca_iptables: plugin starting up...")
+
+    # Set up a separate logger for debugging/testing purposes
+    l = logging.getLogger('euca_iptables_nm_plugin')
+    fh = logging.FileHandler('/var/log/euca_iptables.log')
+    fh.setLevel(logging.DEBUG)
+    fh.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
+    l.addHandler(fh)
+    l.setLevel(logging.DEBUG)
+
 def GetSlivers(data, config=None, plc=None):
-    pass
+    l = logging.getLogger('euca_iptables_nm_plugin')
+    l.debug('Data: %r' % data)
+    l.debug('config: %r' % config)
+    l.debug('plc: %r' % plc)
+
+    # Get a list of instance -> IPs mappings
+    # if none exists, return
+    if 'euca_inst_ip' not in data:
+        return
 
 if __name__ == '__main__':
     pass
index 4f8b639..2392c0d 100644 (file)
@@ -1,6 +1,3 @@
-# $Id$
-# $URL$
-
 """Leverage curl to make XMLRPC requests that check the server's credentials."""
 
 import xmlrpclib