add --noslicehome option, and check /etc/lxcsu_default for default arguments
[lxc-userspace.git] / lxcsu
diff --git a/lxcsu b/lxcsu
index 5756162..c1ad9d1 100755 (executable)
--- a/lxcsu
+++ b/lxcsu
@@ -47,6 +47,17 @@ def main ():
     parser.add_argument("-d","--debug",
                         action='store_true', dest='debug', default=False,
                         help="debug option")
+    parser.add_argument("-s","--nosliceuid",
+                        action='store_true', dest="nosliceuid", default=False,
+                        help="do not change to slice uid inside of slice")
+    parser.add_argument("-o","--noslicehome",
+                        action='store_true', dest="noslicehome", default=False,
+                        help="do not change to slice home directory inside of slice")
+
+    if os.path.exists("/etc/lxcsu_default"):
+        defaults = parser.parse_args(file("/etc/lxcsu_default","r").read().split())
+        parser.set_defaults(**defaults.__dict__)
+
     parser.add_argument ("slice_name")
     parser.add_argument ("command_to_run",nargs="*")
 
@@ -56,11 +67,16 @@ def main ():
     # unless we run the symlink 'lxcsu-internal', or we specify the -i option, prepend '--' '-c'
     if sys.argv[0].find('internal')>=0: args.internal=True
 
-    # plain lxcsu 
+    if len(args.command_to_run)>0 and (args.command_to_run[0] == "/sbin/service"):
+        # A quick hack to support nodemanager interfaces.py when restarting
+        # networking in a slice.
+        args.nosliceuid = True
+
+    # plain lxcsu
     if not args.internal:
         # no command given: enter interactive shell
         if not args.command_to_run: args.command_to_run=['/bin/sh']
-        args.command_to_run = [ '-c' ] + args.command_to_run
+        args.command_to_run = [ '-c' ] + [" ".join(args.command_to_run)]
 
     # support for either setting debug at the top of this file, or on the command-line
     if args.debug:
@@ -112,6 +128,7 @@ def main ():
         arch = 'x86_64'
 
     # Set sysctls specific to slice
+    sysctls = []
     sysctl_dir = '/etc/planetlab/vsys-attributes/%s'%slice_name
     if (os.access(sysctl_dir,0)):
         entries = os.listdir(sysctl_dir)
@@ -121,8 +138,8 @@ def main ():
                 sysctl_file = '/'.join([sysctl_dir,e])
                 sysctl_name = e[len(prefix):]
                 sysctl_val = open(sysctl_file).read()
-                os.system('sysctl -w %s=%s'%(sysctl_name,sysctl_val)) 
-        
+                sysctls.append((sysctl_file, sysctl_name, sysctl_val))
+
     # Enter cgroups
     try:
         for subsystem in ['cpuset','memory','blkio']:
@@ -164,14 +181,18 @@ def main ():
     if (not args.mntns):
         setns.chcontext('/proc/%s/ns/mnt'%pid)
 
-    
-
     proc_mounted = False
     if (not os.access('/proc/self',0)):
         proc_mounted = True
         setns.proc_mount()
 
-    
+    for (sysctl_file, sysctl_name, sysctl_val) in sysctls:
+                for fn in ["/sbin/sysctl", "/usr/sbin/sysctl", "/bin/sysctl", "/usr/bin/sysctl"]:
+                    if os.path.exists(fn):
+                        os.system('%s -w %s=%s'%(fn, sysctl_name,sysctl_val))
+                        break
+                else:
+                    print "Error: image does not have a sysctl binary"
 
     # cgroups is not yet LXC-safe, so we need to use the coarse grained access control
     # strategy of unmounting the filesystem
@@ -213,21 +234,27 @@ def main ():
         cap_arg = '--drop='+drop_capabilities
 
         if (not args.root):
-            uid = getuid (slice_name)
-            if not uid:
-                print "lxcsu-internal could not spot %s in /etc/passwd - exiting"%slice_name
-                exit(1)
-            exec_args = [arch,'/usr/sbin/capsh',cap_arg,'--uid=%s'%uid,'--','--login',]+args.command_to_run
+            if (args.nosliceuid):
+                # we still want to drop capabilities, but don't want to switch UIDs
+                exec_args = [arch,'/usr/sbin/capsh',cap_arg,'--','--login',]+args.command_to_run
+            else:
+                uid = getuid (slice_name)
+                if not uid:
+                    print "lxcsu could not spot %s in /etc/passwd - exiting"%slice_name
+                    exit(1)
+                exec_args = [arch,'/usr/sbin/capsh',cap_arg,'--uid=%s'%uid,'--','--login',]+args.command_to_run
 # once we can drop f12, it would be nicer to instead go for
-#            exec_args = [arch,'/usr/sbin/capsh',cap_arg,'--user=%s'%slice_name,'--','--login',]+args.command_to_run
+#                exec_args = [arch,'/usr/sbin/capsh',cap_arg,'--user=%s'%slice_name,'--','--login',]+args.command_to_run
         else:
             exec_args = [arch,'/usr/sbin/capsh','--','--login']+args.command_to_run
 
         os.environ['SHELL'] = '/bin/sh'
-        os.environ['HOME'] = '/home/%s'%slice_name
-        os.environ['LD_PRELOAD'] = '/etc/planetlab/lib/bind_public.so'
-        os.chdir("/home/%s"%(slice_name))
-        print 'lxcsu-internal:execv:','/usr/bin/setarch',exec_args
+        if os.path.exists('/etc/planetlab/lib/bind_public.so'):
+            os.environ['LD_PRELOAD'] = '/etc/planetlab/lib/bind_public.so'
+        if not args.noslicehome:
+            os.environ['HOME'] = '/home/%s'%slice_name
+            os.chdir("/home/%s"%(slice_name))
+        if debug: print 'lxcsu:execv:','/usr/bin/setarch',exec_args
         os.execv('/usr/bin/setarch',exec_args)
     else:
         setns.proc_umount()