Branch 2.0 for module NodeManager created (as new trunk) from tag NodeManager-1.8-23
authorThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Fri, 29 Jan 2010 14:14:32 +0000 (14:14 +0000)
committerThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Fri, 29 Jan 2010 14:14:32 +0000 (14:14 +0000)
18 files changed:
NodeManager.spec
accounts.py
api.py
bwmon.py
conf_files.py
doc/Makefile
net.py
nm.py
plcapi.py
plugins/codemux.py
plugins/rawdisk.py [new file with mode: 0644]
plugins/sliverauth.py [new file with mode: 0644]
plugins/specialaccounts.py [new file with mode: 0644]
plugins/vsys.py
plugins/vsys_privs.py [new file with mode: 0755]
sliver_vs.py
sm.py
tools.py

index 8896fac..ca181e7 100644 (file)
@@ -7,7 +7,7 @@
 
 %define name NodeManager
 %define version 1.8
-%define taglevel 7
+%define taglevel 23
 
 %define release %{taglevel}%{?pldistro:.%{pldistro}}%{?date:.%{date}}
 
@@ -25,7 +25,8 @@ Packager: PlanetLab Central <support@planet-lab.org>
 Distribution: PlanetLab %{plrelease}
 URL: %(echo %{url} | cut -d ' ' -f 2)
 
-BuildArch: noarch
+# not possible because of forward_api_calls
+#BuildArch: noarch
 
 # Old Node Manager
 Obsoletes: sidewinder, sidewinder-common
@@ -35,7 +36,7 @@ Requires: vserver-%{slicefamily}
 Requires: util-vserver >= 0.30.208-17
 
 # vserver.py
-Requires: util-vserver-python
+Requires: util-vserver-python > 0.3-16
 
 # Signed tickets
 Requires: gnupg
@@ -108,6 +109,69 @@ rm -rf $RPM_BUILD_ROOT
 %{_sysconfdir}/logrotate.d/nm
 
 %changelog
+* Tue Jan 12 2010 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - NodeManager-1.8-23
+- emergency tag - make the setting of hmac by the sliverauth plugin more robust
+
+* Mon Jan 11 2010 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - NodeManager-1.8-22
+- support for f10 and f12 in the vref slice tag
+
+* Sat Jan 09 2010 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - NodeManager-1.8-21
+- build on fedora12
+- uses slicename 'sfacm' instead of 'genicw'
+
+* Fri Oct 30 2009 Sapan Bhatia <sapanb@cs.princeton.edu> - NodeManager-1.8-20
+- This tag is identical to 1.8-19. The main addition is PLC-controllable vsys scripts. The reason I am
+- retagging is to eliminate any confusion associated with the -19 tag which was (temporarily) modified a few
+- days ago.
+
+* Tue Oct 27 2009 Sapan Bhatia <sapanb@cs.princeton.edu> - NodeManager-1.8-19
+- This patch makes vsys scripts PLC-configurable. Previously, vsys scripts needed to be
+- self-contained. With this change, they will be able to refer to the attributes associated with a
+- slice.
+
+* Thu Oct 22 2009 Baris Metin <Talip-Baris.Metin@sophia.inria.fr> - NodeManager-1.8-18
+- fix for syntax error
+
+* Wed Oct 21 2009 anil vengalil <avengali@sophia.inria.fr> - NodeManager-1.8-17
+- -fixed problem with sioc import at the build side
+- -bwlimit.set() now accepts the device and does not asume that it is eth0
+
+* Tue Oct 20 2009 Baris Metin <Talip-Baris.Metin@sophia.inria.fr> - NodeManager-1.8-16
+- - don't hardcode the device name (depends on util-vserver-pl change rev. 15385)
+
+* Fri Oct 09 2009 Marc Fiuczynski <mef@cs.princeton.edu> - NodeManager-1.8-15
+- The seed for random previously was the meaning of life (i.e., 42) but
+- that resulted in a not so random choice for the hmac.  This
+- implementation now uses a random.seed that is based on the current
+- time.
+
+* Tue Oct 06 2009 Marc Fiuczynski <mef@cs.princeton.edu> - NodeManager-1.8-14
+- Minor fix such that sliverauth.py makes a more specific call to
+- GetSliceTags that include that specific tagname it is looking for.
+
+* Sat Sep 19 2009 Stephen Soltesz <soltesz@cs.princeton.edu> - NodeManager-1.8-13
+- Fix bug that prevented 'OVERRIDES' for working correctly.
+
+* Tue Sep 08 2009 Faiyaz Ahmed <faiyaza@cs.princeton.edu> - NodeManager-1.8-12
+- Increase disk limits to 10G per sliver
+- Sanity check slice for home directory before starting (hack)
+- Check codemux arguments
+
+* Thu Aug 06 2009 Faiyaz Ahmed <faiyaza@cs.princeton.edu> - NodeManager-1.8-11
+- * Fix Delegation
+- * Move plcapi in plugin-api GetSlivers() calls.
+- * Persistent Authcheck and resync session when auth failure
+
+* Tue Aug 04 2009 Faiyaz Ahmed <faiyaza@cs.princeton.edu> - NodeManager-1.8-10
+- Disabling sliverauth module.  Not ready for deployment.
+
+* Mon Aug 03 2009 Faiyaz Ahmed <faiyaza@cs.princeton.edu> - NodeManager-1.8-9
+- Fixing overrides semantics.
+
+* Mon Aug 03 2009 Faiyaz Ahmed <faiyaza@cs.princeton.edu> - NodeManager-1.8-8
+- Generalized plugins
+- Fixed initscript start up bug.
+
 * Tue Jun 30 2009 Faiyaz Ahmed <faiyaza@cs.princeton.edu> - NodeManager-1.8-7
 - * Fix delegation authentication problem
 - * Can now disable codemux using _default slice, and setting tag {codemux: -1}
index 480129c..df33977 100644 (file)
@@ -23,7 +23,7 @@ maximum stack size.
 import Queue
 import os
 import pwd
-from grp import getgrnam
+import grp
 import threading
 
 import logger
@@ -85,16 +85,35 @@ class Account:
         logger.verbose('%s: in accounts:configure'%self.name)
         new_keys = rec['keys']
         if new_keys != self.keys:
-            self.keys = new_keys
-            dot_ssh = '/home/%s/.ssh' % self.name
-            if not os.access(dot_ssh, os.F_OK): os.mkdir(dot_ssh)
+            # get the unix account info
+            gid = grp.getgrnam("slices")[2]
+            pw_info = pwd.getpwnam(self.name)
+            uid = pw_info[2]
+            pw_dir = pw_info[5]
+
+            # write out authorized_keys file and conditionally create
+            # the .ssh subdir if need be.
+            dot_ssh = os.path.join(pw_dir,'.ssh')
+            if not os.path.isdir(dot_ssh):
+                if not os.path.isdir(pw_dir):
+                    logger.verbose('WARNING: homedir %s does not exist for %s!'%(pw_dir,self.name))
+                    os.mkdir(pw_dir)
+                    os.chown(pw_dir, uid, gid)
+                os.mkdir(dot_ssh)
+
+            auth_keys = os.path.join(dot_ssh,'authorized_keys')
+            tools.write_file(auth_keys, lambda f: f.write(new_keys))
+
+            # set access permissions and ownership properly
             os.chmod(dot_ssh, 0700)
-            tools.write_file(dot_ssh + '/authorized_keys', lambda f: f.write(new_keys))
-            logger.log('%s: installing ssh keys' % self.name)
-            user = pwd.getpwnam(self.name)[2]
-            group = getgrnam("slices")[2]
-            os.chown(dot_ssh, user, group)
-            os.chown(dot_ssh + '/authorized_keys', user, group)
+            os.chown(dot_ssh, uid, gid)
+            os.chmod(auth_keys, 0600)
+            os.chown(auth_keys, uid, gid)
+
+            # set self.keys to new_keys only when all of the above ops succeed
+            self.keys = new_keys
+
+            logger.log('%s: installed ssh keys' % self.name)
 
     def start(self, delay=0): pass
     def stop(self): pass
diff --git a/api.py b/api.py
index 350cb25..c0e360f 100644 (file)
--- a/api.py
+++ b/api.py
@@ -65,12 +65,9 @@ class APIRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
             xid = struct.unpack('3i', ucred)[1]
             caller_name = pwd.getpwuid(xid)[0]
             # Special case the genicw
-            if method_name == "AdminTicket":
-                if caller_name == PLC_SLICE_PREFIX+"_genicw":
-                    try: result = method(*args)
-                    except Exception, err: raise xmlrpclib.Fault(104, 'Error in call: %s' %err)
-                else:
-                    raise xmlrpclib.Fault(108, '%s: Permission denied.' % caller_name)
+            if caller_name == PLC_SLICE_PREFIX+"_sfacm":
+                try: result = method(*args)
+                except Exception, err: raise xmlrpclib.Fault(104, 'Error in call: %s' %err)
             # Anyone can call these functions
             elif method_name not in ('Help', 'Ticket', 'GetXIDs', 'GetSSHKeys'):
                 # Authenticate the caller if not in the above fncts.
index 69325c9..91a79f3 100644 (file)
--- a/bwmon.py
+++ b/bwmon.py
@@ -52,8 +52,9 @@ except:
 seconds_per_day = 24 * 60 * 60
 bits_per_byte = 8
 
+dev_default = tools.get_default_if()
 # Burst to line rate (or node cap).  Set by NM. in KBit/s
-default_MaxRate = int(bwlimit.get_bwcap() / 1000)
+default_MaxRate = int(bwlimit.get_bwcap(dev_default) / 1000)
 default_Maxi2Rate = int(bwlimit.bwmax / 1000)
 # 5.4 Gbyte per day. 5.4 * 1024 k * 1024M * 1024G 
 # 5.4 Gbyte per day max allowed transfered per recording period
@@ -323,7 +324,7 @@ class Slice:
                   (self.name,
                    bwlimit.format_tc_rate(maxrate),
                    bwlimit.format_tc_rate(maxi2rate)), 1)
-            bwlimit.set(xid = self.xid, 
+            bwlimit.set(xid = self.xid, dev = dev_default,
                 minrate = self.MinRate * 1000, 
                 maxrate = self.MaxRate * 1000, 
                 maxexemptrate = self.Maxi2Rate * 1000,
@@ -704,7 +705,7 @@ def run():
         nmdbcopy = copy.deepcopy(database.db)
         database.db_lock.release()
         try:  
-            if getDefaults(nmdbcopy) and len(bwlimit.tc("class show dev eth0")) > 0:
+            if getDefaults(nmdbcopy) and len(bwlimit.tc("class show dev %s" % dev_default)) > 0:
                 # class show to check if net:InitNodeLimit:bwlimit.init has run.
                 sync(nmdbcopy)
             else: logger.log("bwmon:  BW limits DISABLED.")
index 31c325c..b3b65f8 100644 (file)
@@ -86,7 +86,7 @@ class conf_files:
 
 def start(options, config): pass
 
-def GetSlivers(plc, data, config = None):
+def GetSlivers(data, config = None, plc = None):
     logger.log("conf_files: Running.")
     cf = conf_files()
     cf.run_once(data)
index 36b2c1e..5d3870f 100644 (file)
@@ -23,7 +23,7 @@ NMAPI.xml: NMAPI.xml.in
        $(if $(local-docbook-43), \
        echo Using locally installed DTD $(local-docbook-43), \
        echo WARNING - could not locate local DTD - using remote $(remote-docbook-43))
-       sed -e s:@DOCBOOK-43@:$(docbook-43): $< > $@
+       sed -e s,@DOCBOOK-43@,$(docbook-43), $< > $@
 
 .NMAPI.xml.valid: Methods.xml
 
diff --git a/net.py b/net.py
index 7c9242d..be4e16e 100644 (file)
--- a/net.py
+++ b/net.py
@@ -11,18 +11,20 @@ import os, string, time, socket
 import sioc, plnet
 
 # local modules
-import bwlimit, logger, iptables
+import bwlimit, logger, iptables, tools
+
+dev_default = tools.get_default_if()
 
 def start(options, conf):
     logger.log("net plugin starting up...")
 
-def GetSlivers(plc, data, config):
+def GetSlivers(data, config, plc):
     logger.verbose("net:GetSlivers called.")
     InitInterfaces(plc, data) # writes sysconfig files.
     if 'OVERRIDES' in dir(config): 
         if config.OVERRIDES.get('net_max_rate') == '-1':
             logger.log("net: Slice and node BW Limits disabled.")
-            if len(bwlimit.tc("class show dev eth0")): 
+            if len(bwlimit.tc("class show dev %s" % dev_default)): 
                 logger.verbose("*** DISABLING NODE BW LIMITS ***")
                 bwlimit.stop()
         else:
diff --git a/nm.py b/nm.py
index 62d9ece..5531554 100755 (executable)
--- a/nm.py
+++ b/nm.py
@@ -54,7 +54,7 @@ if os.path.exists(options.path):
 
 modules = []
 
-def GetSlivers(plc, config):
+def GetSlivers(config, plc):
     '''Run call backs defined in modules'''
     try: 
         logger.log("Syncing w/ PLC")
@@ -70,7 +70,7 @@ def GetSlivers(plc, config):
     for module in modules:
         try:        
             callback = getattr(module, 'GetSlivers')
-            callback(plc, data, config)
+            callback(data, config, plc)
         except: logger.log_exc()
 
 
@@ -85,7 +85,10 @@ def getPLCDefaults(data, config):
             if len(attr_dict):
                 logger.verbose("Found default slice overrides.\n %s" % attr_dict)
                 config.OVERRIDES = attr_dict
-            return 
+                return
+    # NOTE: if an _default slice existed, it would have been found above and
+       #               the routine would return.  Thus, if we've gotten here, then no default
+       #               slice is bound to this node.
     if 'OVERRIDES' in dir(config): del config.OVERRIDES
 
 
@@ -134,10 +137,22 @@ def run():
         irandom=int(options.random)
         plc = PLCAPI(config.plc_api_uri, config.cacert, session, timeout=iperiod/2)
 
+        #check auth
+        logger.log("Checking Auth.")
+        while plc.check_authentication() != True:
+            try:
+                plc.update_session()
+                logger.log("Authentication Failure.  Retrying")
+            except:
+                logger.log("Retry Failed.  Waiting")
+            time.sleep(iperiod)
+        logger.log("Authentication Succeeded!")
+
+
         while True:
         # Main NM Loop
             logger.verbose('mainloop - nm:getSlivers - period=%d random=%d'%(iperiod,irandom))
-            GetSlivers(plc, config)
+            GetSlivers(config, plc)
             delay=iperiod + random.randrange(0,irandom)
             logger.verbose('mainloop - sleeping for %d s'%delay)
             time.sleep(delay)
@@ -146,13 +161,6 @@ def run():
 
 if __name__ == '__main__':
     logger.log("Entering nm.py "+id)
-    stacklim = 512*1024  # 0.5 MiB
-    curlim = resource.getrlimit(resource.RLIMIT_STACK)[0]  # soft limit
-    if curlim > stacklim:
-        resource.setrlimit(resource.RLIMIT_STACK, (stacklim, stacklim))
-        # for some reason, doesn't take effect properly without the exec()
-        python = '/usr/bin/python'
-        os.execv(python, [python] + savedargv)
     run()
 else:
     # This is for debugging purposes.  Open a copy of Python and import nm
index 03a9ca7..be77171 100644 (file)
--- a/plcapi.py
+++ b/plcapi.py
@@ -2,6 +2,7 @@
 
 import safexmlrpc
 import hmac, sha
+import logger
 
 class PLCAPI:
     """
@@ -32,11 +33,9 @@ class PLCAPI:
             self.node_id = self.key = self.session = None
 
         self.server = safexmlrpc.ServerProxy(self.uri, self.cacert, self.timeout, allow_none = 1, **kwds)
-        
-        self.__check_authentication()
 
 
-    def __update_session(self, f="/usr/boot/plnode.txt"):
+    def update_session(self, f="/usr/boot/plnode.txt"):
         # try authenticatipopulate /etc.planetlab/session 
         def plnode(key):
             try:
@@ -48,25 +47,17 @@ class PLCAPI:
         plc = PLCAPI(self.uri, self.cacert, auth, self.timeout)
         open("/etc/planetlab/session", 'w').write(plc.GetSession().strip())
         self.session = open("/etc/planetlab/session").read().strip()
+
         
-    def __check_authentication(self):
-        # just a simple call to check authentication
-        def check():
-            if (self.node_id and self.key) or self.session:
-                try:
-                    if self.AuthCheck() == 1: return True
-                except:
-                    return False
-            return False
-        if not check():
-            if self.node_id and self.key:
-                # if hmac fails, just make it fail
-                raise Exception, "Unable to authenticate with hmac"
-            else:
-                self.__update_session()
-                if not check():
-                    raise Exception, "Unable to authenticate with session"
-    
+    def check_authentication(self):
+        authstatus = False
+        if self.key or self.session:
+            try: 
+                authstatus = self.AuthCheck()
+            except: 
+                logger.log_exc()
+        return authstatus
+
 
     def add_auth(self, function):
         """
index b367b58..fa5311f 100644 (file)
@@ -14,7 +14,7 @@ CODEMUXCONF="/etc/codemux/codemux.conf"
 def start(options, conf):
     logger.log("codemux plugin starting up...")
 
-def GetSlivers(plc, data, config):
+def GetSlivers(data, config, plc = None):
     """
     For each sliver with the codemux attribute, parse out "host,port" 
     and make entry in conf.  Restart service after.
@@ -40,8 +40,11 @@ def GetSlivers(plc, data, config):
         for attribute in sliver['attributes']:
             if attribute['tagname'] == 'codemux':
                 # add to conf.  Attribute is [host, port]
-                params = {'host': attribute['value'].split(",")[0], 
-                          'port': attribute['value'].split(",")[1]}
+                parts = attribute['value'].split(",")
+                if len(parts)<2:
+                    logger.log("codemux: attribute value (%s) for codemux not separated by comma. Skipping."%attribute['value'])
+                    continue
+                params = {'host': parts[0], 'port': parts[1]}
                 try:
                     # Check to see if sliver is running.  If not, continue
                     if vserver.VServer(sliver['name']).is_running():
diff --git a/plugins/rawdisk.py b/plugins/rawdisk.py
new file mode 100644 (file)
index 0000000..c222366
--- /dev/null
@@ -0,0 +1,71 @@
+#!/usr/bin/python -tt
+# vim:set ts=4 sw=4 expandtab:
+# NodeManager plugin to support mapping unused raw disks into a slice
+# that has the rawdisk sliver tag
+
+"""
+Raw disk support for NodeManager.
+
+Copies all unused devices into slices with the rawdisk attribute set.
+"""
+
+import errno
+import os
+import time
+import re
+
+import logger
+import tools
+
+def start(options, config):
+    logger.log("rawdisk plugin starting up...")
+
+def get_unused_devices():
+    devices = []
+    if os.path.exists("/dev/mapper/planetlab-rawdisk"):
+        devices.append("/dev/mapper/planetlab-rawdisk")
+    # Figure out which partitions are part of the VG
+    in_vg = []
+    for i in os.listdir("/sys/block"):
+        if not i.startswith("dm-"):
+            continue
+        in_vg.extend(os.listdir("/sys/block/%s/slaves" % i))
+    # Read the list of partitions
+    partitions = file("/proc/partitions", "r")
+    pat = re.compile("\s+")
+    while True:
+        buf = partitions.readline()
+        if buf == "":
+            break
+        buf = buf.strip()
+        fields = re.split(pat, buf)
+        dev = fields[-1]
+        if not dev.startswith("dm-") and dev.endswith("1") and dev not in in_vg:
+            devices.append("/dev/%s" % dev)
+    partitions.close()
+    return devices
+
+def GetSlivers(data, config=None, plc=None):
+    if 'slivers' not in data: 
+        logger.log("sliverauth: getslivers data lack's sliver information. IGNORING!")
+        return
+
+    devices = get_unused_devices()
+    for sliver in data['slivers']:
+        for attribute in sliver['attributes']:
+           name = attribute.get('tagname',attribute.get('name',''))
+            if name == 'rawdisk':
+                for i in devices:
+                    st = os.stat(i)
+                    path = "/vservers/%s%s" % (sliver['name'], i)
+                    if os.path.exists(path):
+                        # should check whether its the proper type of device
+                        continue
+                    
+                    logger.log("Copying %s to %s" % (i, path))
+                    try:
+                        if os.path.exists(path):
+                            os.unlink(path)
+                    except:
+                        pass
+                    os.mknod(path, st.st_mode, st.st_rdev)
diff --git a/plugins/sliverauth.py b/plugins/sliverauth.py
new file mode 100644 (file)
index 0000000..9cf9076
--- /dev/null
@@ -0,0 +1,85 @@
+#!/usr/bin/python -tt
+# vim:set ts=4 sw=4 expandtab:
+# NodeManager plugin to empower slivers to make API calls
+
+"""
+Sliver authentication support for NodeManager.
+
+"""
+
+import errno
+import os
+import random
+import string
+import tempfile
+import time
+
+import logger
+import tools
+
+def start(options, conf):
+    logger.log("sliverauth plugin starting up...")
+
+def SetSliverTag(plc, slice, tagname, value):
+    node_id = tools.node_id()
+    slivertags=plc.GetSliceTags({"name":slice,"node_id":node_id,"tagname":tagname})
+    if len(slivertags)==0:
+        # looks like GetSlivers reports about delegated/nm-controller slices that do *not* belong to this node
+        # and this is something that AddSliceTag does not like
+        try:
+            slivertag_id=plc.AddSliceTag(slice,tagname,value,node_id)
+        except:
+            logger.log ("SetSliverTag - CAUGHT exception for (probably delegated) slice=%(slice)s tag=%(tagname)s node_id=%(node_id)d"%locals())
+            pass
+    else:
+        slivertag_id=slivertags[0]['slice_tag_id']
+        plc.UpdateSliceTag(slivertag_id,value)
+
+def GetSlivers(data, config, plc):
+    if 'OVERRIDES' in dir(config):
+        if config.OVERRIDES.get('sliverauth') == '-1':
+            logger.log("sliverauth:  Disabled", 2)
+            return
+
+    if 'slivers' not in data:
+        logger.log("sliverauth: getslivers data lack's sliver information. IGNORING!")
+        return
+
+    for sliver in data['slivers']:
+        found_hmac = False
+        for attribute in sliver['attributes']:
+            name = attribute.get('tagname',attribute.get('name',''))
+            if name == 'hmac':
+                found_hmac = True
+                hmac = attribute['value']
+                break
+
+        if not found_hmac:
+            # XXX need a better random seed?!
+            random.seed(time.time())
+            d = [random.choice(string.letters) for x in xrange(32)]
+            hmac = "".join(d)
+            SetSliverTag(plc,sliver['name'],'hmac',hmac)
+            logger.log("sliverauth setting %s hmac" % sliver['name'])
+
+        path = '/vservers/%s/etc/planetlab' % sliver['name']
+        if os.path.exists(path):
+            keyfile = '%s/key' % path 
+            oldhmac = ''
+            if os.path.exists(keyfile):
+                f = open(keyfile,'r')
+                oldhmac = f.read()
+                f.close()
+
+            if oldhmac <> hmac:
+                # create a temporary file in the vserver
+                fd, name = tempfile.mkstemp('','key',path)
+                os.write(fd,hmac)
+                os.close(fd)
+                if os.path.exists(keyfile):
+                    os.unlink(keyfile)
+                os.rename(name,keyfile)
+                logger.log("sliverauth writing hmac to %s " % keyfile)
+
+            os.chmod(keyfile,0400)
+
diff --git a/plugins/specialaccounts.py b/plugins/specialaccounts.py
new file mode 100644 (file)
index 0000000..545910f
--- /dev/null
@@ -0,0 +1,61 @@
+#!/usr/bin/python -tt
+# vim:set ts=4 sw=4 expandtab:
+# NodeManager plugin to create special accounts
+
+"""
+Have NM create/populate accounts/ssh keys for special persons such as root, site_admin, etc.
+
+"""
+
+import errno
+import os
+import random
+import string
+import tempfile
+import grp
+import pwd
+
+import logger
+import tools
+
+def start(options, conf):
+    logger.log("personkeys plugin starting up...")
+
+def GetSlivers(data, conf = None, plc = None):
+    if 'accounts' not in data: 
+        logger.log("specialaccounts: No account information found.  DISABLED!")
+        return
+
+    for account in data['accounts']:
+        name = account['name']
+        new_keys = account['keys']
+
+        # look up account name, which must exist
+        pw_info = pwd.getpwnam(name)
+        uid = pw_info[2]
+        gid = pw_info[3]
+        pw_dir = pw_info[5]
+
+        # populate account's .ssh/authorized_keys file
+        dot_ssh = os.path.join(pw_dir,'.ssh')
+        if not os.access(dot_ssh, os.F_OK): os.mkdir(dot_ssh)
+        auth_keys = os.path.join(dot_ssh,'authorized_keys')
+
+        logger.log("new keys = %s" % auth_keys)
+        fd, fname = tempfile.mkstemp('','authorized_keys',dot_ssh)
+
+        for key in new_keys:
+            os.write(fd,key)
+            os.write(fd,'\n')
+
+        os.close(fd)
+        if os.path.exists(auth_keys): os.unlink(auth_keys)
+        os.rename(fname, auth_keys)
+
+        # set permissions properly
+        os.chmod(dot_ssh, 0700)
+        os.chown(dot_ssh, uid,gid)
+        os.chmod(auth_keys, 0600)
+        os.chown(auth_keys, uid,gid)
+
+        logger.log('specialacounts: installed ssh keys for %s' % name)
index a2bc2bb..927c7c1 100644 (file)
@@ -13,7 +13,7 @@ VSYSBKEND="/vsys"
 def start(options, conf):
     logger.log("vsys plugin starting up...")
 
-def GetSlivers(plc, data, config=None):
+def GetSlivers(data, config=None, plc=None):
     """For each sliver with the vsys attribute, set the script ACL, create the vsys directory in the slice, and restart vsys."""
     # Touch ACLs and create dict of available
     scripts = {}
diff --git a/plugins/vsys_privs.py b/plugins/vsys_privs.py
new file mode 100755 (executable)
index 0000000..7012a59
--- /dev/null
@@ -0,0 +1,122 @@
+"""
+vsys sub-configurator.  Maintains configuration parameters associated with vsys scripts.
+All slice attributes with the prefix vsys_ are written into configuration files on the
+node for the reference of vsys scripts.
+"""
+
+import logger
+import os
+from sets import Set
+
+VSYS_PRIV_DIR = "/etc/planetlab/vsys-attributes"
+
+def start(options, conf):
+    logger.log("vsys_privs plugin v0.1")
+    if (not os.path.exists(VSYS_PRIV_DIR)):
+        os.makedirs(VSYS_PRIV_DIR)
+        logger.log("Created vsys attributes dir")
+
+def GetSlivers(data, config=None, plc=None):
+    privs = {}
+
+    # Parse attributes and update dict of scripts
+    for sliver in data['slivers']:
+        slice = sliver['name']
+        for attribute in sliver['attributes']:
+            tag = attribute['tagname']
+            value = attribute['value']
+            if tag.startswith('vsys_'):
+                if (privs.has_key(slice)):
+                    slice_priv = privs[slice]
+                    if (slice_priv.has_key(tag)):
+                        slice_priv[tag].append(value)
+                    else:
+                        slice_priv[tag]=[value]
+
+                    privs[slice] = slice_priv
+                else:
+                    privs[slice] = {tag:[value]}
+
+    cur_privs = read_privs()
+    write_privs(cur_privs, privs)
+
+def read_privs():
+    cur_privs={}
+    priv_finder = os.walk(VSYS_PRIV_DIR)
+    priv_find = [i for i in priv_finder]
+    (rootdir,slices,foo) = priv_find[0]
+
+    for slice in slices:
+        cur_privs[slice]={}
+
+    if (len(priv_find)>1):
+        for (slicedir,bar,tagnames) in priv_find[1:]:
+            if (bar != []):
+                # The depth of the vsys-privileges directory = 1
+                pass
+
+            for tagname in tagnames:
+                tagfile = os.path.join(slicedir,tagname)
+                values_n = file(tagfile).readlines()
+                values = map(lambda s:s.rstrip(),values_n)
+                slice = os.path.basename(slicedir)
+                cur_privs[slice][tagname]=values
+
+    return cur_privs
+
+def write_privs(cur_privs,privs):
+    for slice in privs.keys():
+        variables = privs[slice]
+        slice_dir = os.path.join(VSYS_PRIV_DIR,slice)
+        if (not os.path.exists(slice_dir)):
+            os.mkdir(slice_dir)
+
+        # Add values that do not exist
+        for k in variables.keys():
+            v = variables[k]
+            if (cur_privs.has_key(slice) 
+                    and cur_privs[slice].has_key(k)
+                    and cur_privs[slice][k] == v):
+                # The binding has not changed
+                pass
+            else:
+                v_file = os.path.join(slice_dir, k)
+                f = open(v_file,'w')
+                data = '\n'.join(v)
+                f.write(data)
+                f.close()
+                logger.log("Added vsys attribute %s for %s"%(k,slice))
+
+    # Remove files and directories 
+    # that are invalid
+    for slice in cur_privs.keys():
+        variables = cur_privs[slice]
+        slice_dir = os.path.join(VSYS_PRIV_DIR,slice)
+
+        # Add values that do not exist
+        for k in variables.keys():
+            if (privs.has_key(slice) 
+                    and cur_privs[slice].has_key(k)):
+                # ok, spare this tag
+                print "Sparing  %s, %s "%(slice,k) 
+            else:
+                v_file = os.path.join(slice_dir, k)
+                os.remove(v_file)    
+
+        if (not privs.has_key(slice)):
+            os.rmdir(slice_dir)
+
+
+if __name__ == "__main__":           
+    test_slivers = {'slivers':[
+        {'name':'foo','attributes':[
+            {'tagname':'vsys_m','value':'2'},
+            {'tagname':'vsys_m','value':'3'},
+            {'tagname':'vsys_m','value':'4'}
+            ]},
+        {'name':'bar','attributes':[
+            #{'tagname':'vsys_x','value':'z'}
+            ]}
+        ]}
+    start(None,None)
+    GetSlivers(test_slivers)
index 579e2ab..82523a5 100644 (file)
@@ -94,7 +94,7 @@ class Sliver_VS(accounts.Account, vserver.VServer):
             (pldistro,fcdistro,arch) = default.split("-")
 
             known_archs = [ 'i386', 'x86_64' ]
-            known_fcdistros = [ 'f8', 'f9', 'centos5' ]
+            known_fcdistros = [ 'centos5', 'f8', 'f9', 'f10', 'f11', 'f12' ]
             # from the slice attribute: cut dashes and try to figure the meaning
             slice_wishes = vref.split("-")
             for wish in slice_wishes:
diff --git a/sm.py b/sm.py
index 62de7f9..ca21d48 100644 (file)
--- a/sm.py
+++ b/sm.py
@@ -39,7 +39,7 @@ DEFAULT_ALLOCATION = {
     'net_i2_max_kbyte': 31640625,
     'net_i2_thresh_kbyte': 28476562,
     # disk space limit
-    'disk_max': 5000000, # bytes
+    'disk_max': 10000000, # bytes
     # capabilities
     'capabilities': '',
     # IP addresses
@@ -54,7 +54,7 @@ DEFAULT_ALLOCATION = {
 start_requested = False  # set to True in order to request that all slivers be started
 
 @database.synchronized
-def GetSlivers(plc, data, config = None, fullupdate=True):
+def GetSlivers(data, config = None, plc=None, fullupdate=True):
     """This function has two purposes.  One, convert GetSlivers() data
     into a more convenient format.  Two, even if no updates are coming
     in, use the GetSlivers() heartbeat as a cue to scan for expired
@@ -99,7 +99,7 @@ def GetSlivers(plc, data, config = None, fullupdate=True):
         rec.setdefault('keys', '\n'.join([key_struct['key'] for key_struct in keys]))
 
         ## 'Type' isn't returned by GetSlivers() for whatever reason.  We're overloading
-        ## instantiation here, but i suppose its the ssame thing when you think about it. -FA
+        ## instantiation here, but i suppose its the same thing when you think about it. -FA
         # Handle nm controller here
         if rec['instantiation'].lower() == 'nm-controller':
             rec.setdefault('type', attr_dict.get('type', 'controller.Controller'))
index bc4b49e..122b321 100644 (file)
--- a/tools.py
+++ b/tools.py
@@ -8,12 +8,32 @@ 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 <run> with no arguments in its own thread."""
     thr = threading.Thread(target=run)