X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lxcsu;h=8fa6a0914d20ca597383bb235c0aaa921f716256;hb=refs%2Fheads%2Fopenvswitch;hp=3c63f74413f4faf041d25ac26f6e0e9fb5fd1fb9;hpb=247503f76b815841ec5b567b7cc35d54225218c2;p=lxc-userspace.git diff --git a/lxcsu b/lxcsu index 3c63f74..8fa6a09 100755 --- a/lxcsu +++ b/lxcsu @@ -11,6 +11,131 @@ drop_capabilities='cap_sys_admin,cap_sys_boot,cap_sys_module' # can set to True here, but also use the -d option debug = False +#################### should go into a separate libvirtsystemd.py +# but we want to keep packaging simple for now + +# reproducing libvirt's systemd-oriented escaping mechanism +# http://code.metager.de/source/xref/lib/virt/src/util/virsystemd.c +# (see original code at the end of this file) + +def virSystemdEscapeName (name): + result='' + def ESCAPE(c,s): + # replace hex's output '0x..' into '\x..' + return s+hex(ord(c)).replace('0','\\',1) + VALID_CHARS = \ + "0123456789" + \ + "abcdefghijklmnopqrstuvwxyz" + \ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + \ + ":-_.\\" + for c in name: + if c=='/': + result += '-' + elif c in '-\\' or c not in VALID_CHARS: + result=ESCAPE(c,result) + else: + result += c + return result + +#35static void virSystemdEscapeName(virBufferPtr buf, +#36 const char *name) +#37{ +#38 static const char hextable[16] = "0123456789abcdef"; +#39 +#40#define ESCAPE(c) \ +#41 do { \ +#42 virBufferAddChar(buf, '\\'); \ +#43 virBufferAddChar(buf, 'x'); \ +#44 virBufferAddChar(buf, hextable[(c >> 4) & 15]); \ +#45 virBufferAddChar(buf, hextable[c & 15]); \ +#46 } while (0) +#47 +#48#define VALID_CHARS \ +#49 "0123456789" \ +#50 "abcdefghijklmnopqrstuvwxyz" \ +#51 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ +#52 ":-_.\\" +#53 +#54 if (*name == '.') { +#55 ESCAPE(*name); +#56 name++; +#57 } +#58 +#59 while (*name) { +#60 if (*name == '/') +#61 virBufferAddChar(buf, '-'); +#62 else if (*name == '-' || +#63 *name == '\\' || +#64 !strchr(VALID_CHARS, *name)) +#65 ESCAPE(*name); +#66 else +#67 virBufferAddChar(buf, *name); +#68 name++; +#69 } +#70 +#71#undef ESCAPE +#72#undef VALID_CHARS +#73} + +def virSystemdMakeScopeName (name, drivername, partition): + result='' + result += virSystemdEscapeName (partition) + result += '-' + result += virSystemdEscapeName (drivername) + result += '\\x2d' + result += virSystemdEscapeName (name) + result += '.scope' + return result + +#76char *virSystemdMakeScopeName(const char *name, +#77 const char *drivername, +#78 const char *partition) +#79{ +#80 virBuffer buf = VIR_BUFFER_INITIALIZER; +#81 +#82 if (*partition == '/') +#83 partition++; +#84 +#85 virSystemdEscapeName(&buf, partition); +#86 virBufferAddChar(&buf, '-'); +#87 virSystemdEscapeName(&buf, drivername); +#88 virBufferAddLit(&buf, "\\x2d"); +#89 virSystemdEscapeName(&buf, name); +#90 virBufferAddLit(&buf, ".scope"); +#91 +#92 if (virBufferError(&buf)) { +#93 virReportOOMError(); +#94 return NULL; +#95 } +#96 +#97 return virBufferContentAndReset(&buf); +#98} + +### our own additions +# heuristics to locate /sys/fs/cgroup stuff +import os.path +def find_first_dir (candidates): + for candidate in candidates: + if os.path.isdir(candidate): return candidate + raise Exception,"Cannot find valid dir among\n" + "\n".join([" ->"+c for c in candidates]) + +def find_sysfs_scope (subsystem, slice_name): + subsystem1=subsystem + subsystem2=subsystem + if subsystem=='cpuacct': + subsystem2='cpu,cpuacct' + candidates = [ + # for f16 and our locally brewed libvirt 1.0.4 + "/sys/fs/cgroup/%s/libvirt/lxc/%s"%(subsystem1, slice_name), + "/sys/fs/cgroup/%s/system/libvirtd.service/libvirt/lxc/%s"%(subsystem1, slice_name), + # f20 and libvirt 1.1.3 + "/sys/fs/cgroup/%s/machine.slice/%s"%(subsystem2, + virSystemdMakeScopeName(slice_name,'lxc','machine')), + ] + return find_first_dir (candidates) + +#################### end of libvirtsystemd.py + def getarch(f): output = os.popen('readelf -h %s 2>&1'%f).readlines() classlines = [x for x in output if ('Class' in x.split(':')[0])] @@ -87,7 +212,7 @@ def main (): cmd = '/usr/bin/virsh --connect lxc:/// domid %s'%slice_name pidnum = int(os.popen(cmd).read().rstrip()) except: - print "Error finding slice %s"%slice_name + print "Domain %s not found"%slice_name exit(1) pid = '%s'%pidnum @@ -96,7 +221,7 @@ def main (): arch = getarch('/proc/%s/exe'%pid) if (not pid): - print "Not started: %s"%slice_name + print "Domain %s not started"%slice_name exit(1) if arch is None: @@ -116,28 +241,23 @@ def main (): sysctls.append((sysctl_file, sysctl_name, sysctl_val)) # Enter cgroups - try: - for subsystem in ['cpuset','memory','blkio']: - open('/sys/fs/cgroup/%s/libvirt/lxc/%s/tasks'%(subsystem,slice_name),'w').write(str(os.getpid())) - - except Exception,e: - if debug: print e - print "Error assigning resources: %s"%slice_name - exit(1) - - try: - open('/sys/fs/cgroup/cpuacct/system/libvirtd.service/libvirt/lxc/%s/tasks'%slice_name,'w').write(str(os.getpid())) - except Exception,e: - if debug: print e - print "Error assigning cpuacct: %s" % slice_name - exit(1) + # do not exit right away when something goes wrong + # check as much as we can and only then exit + cgroups_ok=True + for subsystem in ['cpuset' ,'memory' ,'blkio', 'cpuacct']: + try: + open( find_sysfs_scope (subsystem, slice_name)+"/tasks", 'w').write(str(os.getpid())) + except Exception,e: + if debug: print e + print "ERROR assigning resources for %s in subsystem %s - bailing out"%(slice_name,subsystem) + cgroups_ok=False # If the slice is frozen, then we'll get an EBUSY when trying to write to the task # list for the freezer cgroup. Since the user couldn't do anything anyway, it's best # in this case to error out the shell. (an alternative would be to un-freeze it, # add the task, and re-freeze it) try: - f=open('/sys/fs/cgroup/freezer/libvirt/lxc/%s/tasks'%(slice_name),'w') + f=open( find_sysfs_scope ('freezer', slice_name)+"/tasks", 'w') f.write(str(os.getpid())) # note: we need to call f.close() explicitly, or we'll get an exception in # the object destructor, which will not be caught @@ -145,7 +265,7 @@ def main (): except Exception,e: if debug: print e print "Error adding task to freezer cgroup. Slice is probably frozen: %s" % slice_name - exit(1) + cgroups_ok=False setns.chcontext('/proc/%s/ns/uts'%pid) setns.chcontext('/proc/%s/ns/ipc'%pid) @@ -186,6 +306,10 @@ def main (): if (not umount('/sys/fs/cgroup')): print "Error disabling cgroup access" + cgroups_ok=False + + if not cgroups_ok: + print 'exiting' exit(1) pid = os.fork()