class VServer:
- INITSCRIPTS = [('/etc/rc.vinit', 'start'),
+ # adding the sliver name is for helping in the forensics
+ INITSCRIPTS = [('/etc/rc.vinit', 'start', '%(name)s'),
('/etc/rc.d/rc', '%(runlevel)d')]
def __init__(self, name, vm_id = None, vm_running = None, logfile=None):
self.logfile = logfile
# inspired from nodemanager's logger
+ def log_in_file (self, fd, msg):
+ if not msg: msg="\n"
+ if not msg.endswith('\n'): msg += '\n'
+ os.write(fd, '%s: %s' % (time.asctime(time.gmtime()), msg))
+
def log(self,msg):
if self.logfile:
try:
fd = os.open(self.logfile,os.O_WRONLY | os.O_CREAT | os.O_APPEND, 0600)
- if not msg.endswith('\n'): msg += '\n'
- os.write(fd, '%s: %s' % (time.asctime(time.gmtime()), msg))
+ self.log_in_file(fd,msg)
os.close(fd)
except:
print '%s: (%s failed to open) %s'%(time.asctime(time.gmtime()),self.logfile,msg)
def enter(self):
subprocess.call("/usr/sbin/vserver %s enter" % self.name, shell=True)
+ # detach the process that triggers the initscripts
+ # after http://code.activestate.com/recipes/278731/
def start(self, runlevel = 3):
- if (os.fork() != 0):
+ if os.fork() != 0:
# Parent should just return.
self.vm_running = True
return
else:
- # child process
+ os.setsid()
+ # first child process: fork again
+ if os.fork() != 0:
+ os._exit(0) # Exit parent (the first child) of the second child.
+ # the grandson is the working one
+ os.chdir('/')
+ os.umask(0)
try:
- subprocess.call("/usr/sbin/vserver %s start" % self.name,
- shell=True)
+ # start the vserver
+ subprocess.call(["/usr/sbin/vserver",self.name,"start"])
# execute initscripts
- for cmd in self.INITSCRIPTS:
+ for cmd_to_expand in self.INITSCRIPTS:
+ # enter vserver context
+ expand = { 'runlevel': runlevel,
+ 'name': self.name, }
+ cmd = [ x % expand for x in cmd_to_expand ]
+ cmd_name = os.path.basename(cmd[0])
+ cmd_file = "/vservers/" + self.name + cmd[0]
+ if not os.path.isfile(cmd_file):
+ self.log("WARNING: could not find %s for %s" % (cmd_file, self.name))
+ break
+ self.log("executing %r" % cmd)
try:
- # enter vserver context
- arg_subst = { 'runlevel': runlevel }
- cmd_args = [cmd[0]] + map(lambda x: x % arg_subst, cmd[1:])
- # add vserver name as the last command argument
- cmd_args += [self.name]
- cmd_file = "/vservers/" + self.name + cmd[0]
- self.log(cmd_file)
- if os.path.isfile(cmd_file):
- self.log("executing '%s'" % " ".join(cmd_args))
- self.chroot_call(subprocess.call, " ".join(cmd_args), shell=True)
- else:
- self.log("WARNING: could not run %s on %s" % (cmd[0], self.name))
- except:
- self.log(traceback.format_exc())
-
- # we get here due to an exception in the top-level child process
+ logname='/vservers/%s/var/log/%s'%(self.name,cmd_name)
+ log_fd=os.open(logname,os.O_WRONLY | os.O_CREAT | os.O_APPEND, 0600)
+ self.log_in_file(log_fd,"Running %r into %s"%(cmd,logname))
+ self.chroot_call(subprocess.call,cmd,
+ stdout=log_fd,stderr=subprocess.STDOUT,
+ close_fds=True)
+ except: self.log(traceback.format_exc())
+ finally: os.close(log_fd)
+
+ # we get here due to an exception in the grandson process
except Exception, ex:
self.log(traceback.format_exc())
os._exit(0)