X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=python%2Fvserver.py;h=aee6d03452a3c0c8c83ff9a2868cdc0de4b77ec3;hb=c1ae0033ced3a112ed01eaa90d1479a78305923c;hp=e638149f9f6d9a227042f44d2108328f27230460;hpb=6d0cf1f215994c864ff932bf5507b5147d9d1ffc;p=util-vserver-pl.git diff --git a/python/vserver.py b/python/vserver.py index e638149..aee6d03 100644 --- a/python/vserver.py +++ b/python/vserver.py @@ -129,6 +129,26 @@ class VServerConfig: os.path.walk(self.dir, add_to_cache, self.cache) +def adjust_lim(goal, curr): + gh = goal[0] + gs = goal[1] + gm = goal[2] + soft = curr[0] + hard = curr[1] + if gm != VC_LIM_KEEP: + if gm > soft or gm == resource.RLIM_INFINITY: + soft = gm + if gm > hard or gm == resource.RLIM_INFINITY: + hard = gm + if gs != VC_LIM_KEEP: + if gs > soft or gs == resource.RLIM_INFINITY: + soft = gs + if gh != VC_LIM_KEEP: + if gh > hard or gh == resource.RLIM_INFINITY: + hard = gh + return (soft, hard) + + class VServer: INITSCRIPTS = [('/etc/rc.vinit', 'start'), @@ -181,24 +201,49 @@ class VServer: resource_type = RLIMITS[type] try: vserverimpl.setrlimit(self.ctx, resource_type, hard, soft, min) + if hasattr(resource, 'RLIMIT_' + type): + lim = resource.getrlimit(resource_type) + lim = adjust_lim((hard, soft, min), lim) + resource.setrlimit(resource_type, lim) except OSError, e: self.log("Error: setrlimit(%d, %s, %d, %d, %d): %s" % (self.ctx, type.lower(), hard, soft, min)) return update - def set_capabilities(self, capabilities): - return vserverimpl.setbcaps(self.ctx, vserverimpl.text2bcaps(capabilities)) + def get_prefix_from_capabilities(self, capabilities, prefix): + split_caps = capabilities.split(',') + return ",".join(["%s" % (c) for c in split_caps if c.startswith(prefix.upper()) or c.startswith(prefix.lower())]) + + def get_bcaps_from_capabilities(self, capabilities): + return self.get_prefix_from_capabilities(capabilities, "cap_") + + def get_ccaps_from_capabilities(self, capabilities): + return self.get_prefix_from_capabilities(capabilities, "vxc_") def set_capabilities_config(self, capabilities): - self.config.update('bcapabilities', capabilities) - self.set_capabilities(capabilities) + bcaps = self.get_bcaps_from_capabilities(capabilities) + ccaps = self.get_ccaps_from_capabilities(capabilities) + self.config.update('bcapabilities', bcaps) + self.config.update('ccapabilities', ccaps) + ret = vserverimpl.setbcaps(self.ctx, vserverimpl.text2bcaps(bcaps)) + if ret > 0: + return ret + return vserverimpl.setccaps(self.ctx, vserverimpl.text2ccaps(ccaps)) def get_capabilities(self): - return vserverimpl.bcaps2text(vserverimpl.getbcaps(self.ctx)) + bcaps = vserverimpl.bcaps2text(vserverimpl.getbcaps(self.ctx)) + ccaps = vserverimpl.ccaps2text(vserverimpl.getccaps(self.ctx)) + if bcaps and ccaps: + ccaps = "," + ccaps + return (bcaps + ccaps) def get_capabilities_config(self): - return self.config.get('bcapabilities', '') + bcaps = self.config.get('bcapabilities', '') + ccaps = self.config.get('ccapabilities', '') + if bcaps and ccaps: + ccaps = "," + ccaps + return (bcaps + ccaps) def set_ipaddresses(self, addresses): vserverimpl.netremove(self.ctx, "all") @@ -256,7 +301,7 @@ class VServer: try: vserverimpl.unsetdlimit(self.dir, self.ctx) except OSError, e: - self.log("Unexpected error with unsetdlimit for context %d" % self.ctx) + self.log("Unexpected error with unsetdlimit for context %d: %r" % (self.ctx,e)) return if self.vm_running: @@ -276,7 +321,7 @@ class VServer: vserverimpl.DLIMIT_INF, # inode limit 2) # %age reserved for root except OSError, e: - self.log("Unexpected error with setdlimit for context %d" % self.ctx) + self.log("Unexpected error with setdlimit for context %d: %r" % (self.ctx, e)) self.config.update('dlimits/0/space_total', block_limit) @@ -348,40 +393,47 @@ class VServer: state_file.close() if vserverimpl.chcontext(self.ctx, vserverimpl.text2bcaps(self.get_capabilities_config())): - self.set_resources() + self.set_resources(True) vserverimpl.setup_done(self.ctx) + def __prep(self, runlevel): """ Perform all the crap that the vserver script does before actually executing the startup scripts. """ - # remove /var/run and /var/lock/subsys files - # but don't remove utmp from the top-level /var/run - RUNDIR = "/var/run" - LOCKDIR = "/var/lock/subsys" - filter_fn = lambda fs: filter(lambda f: f != 'utmp', fs) - garbage = reduce((lambda (out, ff), (dir, subdirs, files): - (out + map((dir + "/").__add__, ff(files)), - lambda fs: fs)), - list(os.walk(RUNDIR)), - ([], filter_fn))[0] - garbage += filter(os.path.isfile, map((LOCKDIR + "/").__add__, - os.listdir(LOCKDIR))) - if False: - for f in garbage: - os.unlink(f) # set the initial runlevel - vserverimpl.setrunlevel(RUNDIR + "/utmp", runlevel) + vserverimpl.setrunlevel(self.dir + "/var/run/utmp", runlevel) # mount /proc and /dev/pts self.__do_mount("none", self.dir, "/proc", "proc") # XXX - magic mount options self.__do_mount("none", self.dir, "/dev/pts", "devpts", 0, "gid=5,mode=0620") - def __do_mount(self, *mount_args): + def __cleanvar(self): + """ + Clean the /var/ directory so RH startup scripts can run + """ + + RUNDIR = "/var/run" + LOCKDIR = "/var/lock/subsys" + + filter = ["utmp"] + garbage = [] + for topdir in [RUNDIR, LOCKDIR]: + #os.walk() = (dirpath, dirnames, filenames) + for root, dirs, files in os.walk(topdir): + for file in files: + if not file in filter: + garbage.append(root + "/" + file) + + for f in garbage: os.unlink(f) + return garbage + + + def __do_mount(self, *mount_args): try: vserverimpl.mount(*mount_args) except OSError, ex: @@ -390,11 +442,13 @@ class VServer: return raise ex + def enter(self): self.config.cache_it() self.__do_chroot() self.__do_chcontext(None) + def start(self, runlevel = 3): if (os.fork() != 0): @@ -413,7 +467,7 @@ class VServer: # open state file to record vserver info state_file = open("/var/run/vservers/%s" % self.name, "w") - # use /dev/null for stdin, /var/log/boot.log for stdout/err + # use /dev/null for stdin, /var/log/nm for stdout/err fd = os.open("/dev/null", os.O_RDONLY) if fd != 0: os.dup2(fd, 0) @@ -424,13 +478,18 @@ class VServer: self.config.cache_it() self.__do_chroot() - log = open("/var/log/boot.log", "a", 0) + if not self.is_running(): + removed = self.__cleanvar() + + log = open("/var/log/nm", "a", 0) if log.fileno() != 1: os.dup2(log.fileno(), 1) os.dup2(1, 2) + print >>log, ("%s: removing %s" % + (time.asctime(time.gmtime()), removed)) print >>log, ("%s: starting the virtual server %s" % - (time.asctime(time.gmtime()), self.name)) + (time.asctime(time.gmtime()), self.name)) # execute each init script in turn # XXX - we don't support all scripts that vserver script does self.__do_chcontext(state_file) @@ -443,6 +502,8 @@ class VServer: if os.path.isfile(cmd[0]): print >>log, "executing '%s'" % " ".join(cmd_args) os.spawnvp(os.P_NOWAIT,cmd[0],cmd_args) + else: + print >>log, "WARNING: could not run %s"%cmd[0] except: print >>log, traceback.format_exc() @@ -451,7 +512,7 @@ class VServer: self.log(traceback.format_exc()) os._exit(0) - def set_resources(self): + def set_resources(self,setup=False): """ Called when vserver context is entered for first time, should be overridden by subclass. """ @@ -459,6 +520,13 @@ class VServer: pass def init_disk_info(self): + try: + dlimit = vserverimpl.getdlimit(self.dir, self.ctx) + self.disk_blocks = dlimit[0] + self.disk_inodes = dlimit[2] + return self.disk_blocks * 1024 + except Exception, e: + pass cmd = "/usr/sbin/vdu --script --space --inodes --blocksize 1024 --xid %d %s" % (self.ctx, self.dir) p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,