mount /proc before chroot'ing into filesystem.
[util-vserver-pl.git] / python / vserver.py
index c201bc7..65d9c62 100644 (file)
@@ -135,7 +135,7 @@ class VServer:
     INITSCRIPTS = [('/etc/rc.vinit', 'start'),
                    ('/etc/rc.d/rc', '%(runlevel)d')]
 
     INITSCRIPTS = [('/etc/rc.vinit', 'start'),
                    ('/etc/rc.d/rc', '%(runlevel)d')]
 
-    def __init__(self, name, vm_id = None, vm_running = None):
+    def __init__(self, name, vm_id = None, vm_running = None, logfile=None):
 
         self.name = name
         self.rlimits_changed = False
 
         self.name = name
         self.rlimits_changed = False
@@ -151,6 +151,18 @@ class VServer:
         if vm_running == None:
             vm_running = self.is_running()
         self.vm_running = vm_running
         if vm_running == None:
             vm_running = self.is_running()
         self.vm_running = vm_running
+        self.logfile = logfile
+
+    # inspired from nodemanager's logger
+    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))
+                os.close(fd)
+            except:
+                print '%s: (%s failed to open) %s'%(time.asctime(time.gmtime()),self.logfile,msg)
 
     def have_limits_changed(self):
         return self.rlimits_changed
 
     def have_limits_changed(self):
         return self.rlimits_changed
@@ -166,13 +178,13 @@ class VServer:
             if old_minimum != VC_LIM_KEEP and old_minimum <> minimum: changed = True
             self.rlimits_changed = self.rlimits_changed or changed 
         except OSError, e:
             if old_minimum != VC_LIM_KEEP and old_minimum <> minimum: changed = True
             self.rlimits_changed = self.rlimits_changed or changed 
         except OSError, e:
-            if self.is_running(): print "Unexpected error with getrlimit for running context %d" % self.ctx
+            if self.is_running(): self.log("Unexpected error with getrlimit for running context %d" % self.ctx)
 
         resource_type = RLIMITS[type]
         try:
             ret = vserverimpl.setrlimit(self.ctx,resource_type,hard,soft,minimum)
         except OSError, e:
 
         resource_type = RLIMITS[type]
         try:
             ret = vserverimpl.setrlimit(self.ctx,resource_type,hard,soft,minimum)
         except OSError, e:
-            if self.is_running(): print "Unexpected error with setrlimit for running context %d" % self.ctx
+            if self.is_running(): self.log("Unexpected error with setrlimit for running context %d" % self.ctx)
 
     def set_rlimit_config(self,type,hard,soft,minimum):
         """Generic set resource limit function for vserver"""
 
     def set_rlimit_config(self,type,hard,soft,minimum):
         """Generic set resource limit function for vserver"""
@@ -191,7 +203,7 @@ class VServer:
         try:
             ret = vserverimpl.getrlimit(self.ctx,resource_type)
         except OSError, e:
         try:
             ret = vserverimpl.getrlimit(self.ctx,resource_type)
         except OSError, e:
-            print "Unexpected error with getrlimit for context %d" % self.ctx
+            self.log("Unexpected error with getrlimit for context %d" % self.ctx)
             ret = self.get_rlimit_config(type)
         return ret
 
             ret = self.get_rlimit_config(type)
         return ret
 
@@ -271,7 +283,7 @@ class VServer:
             try:
                 vserverimpl.unsetdlimit(self.dir, self.ctx)
             except OSError, e:
             try:
                 vserverimpl.unsetdlimit(self.dir, self.ctx)
             except OSError, e:
-                print "Unexpected error with unsetdlimit for context %d" % self.ctx
+                self.log("Unexpected error with unsetdlimit for context %d" % self.ctx)
             return
 
         if self.vm_running:
             return
 
         if self.vm_running:
@@ -292,7 +304,7 @@ class VServer:
                                   vserverimpl.DLIMIT_INF,  # inode limit
                                   2)   # %age reserved for root
         except OSError, e:
                                   vserverimpl.DLIMIT_INF,  # inode limit
                                   2)   # %age reserved for root
         except OSError, e:
-            print "Unexpected error with setdlimit for context %d" % self.ctx
+            self.log("Unexpected error with setdlimit for context %d" % self.ctx)
 
 
         self.config.update('dlimits/0/space_total', block_limit)
 
 
         self.config.update('dlimits/0/space_total', block_limit)
@@ -369,7 +381,7 @@ class VServer:
             self.set_resources()
             vserverimpl.setup_done(self.ctx)
 
             self.set_resources()
             vserverimpl.setup_done(self.ctx)
 
-    def __prep(self, runlevel, log):
+    def __prep(self, runlevel):
 
         """ Perform all the crap that the vserver script does before
         actually executing the startup scripts. """
 
         """ Perform all the crap that the vserver script does before
         actually executing the startup scripts. """
@@ -391,9 +403,7 @@ class VServer:
                 os.unlink(f)
 
         # set the initial runlevel
                 os.unlink(f)
 
         # set the initial runlevel
-        f = open(RUNDIR + "/utmp", "w")
-        vserverimpl.setrunlevel(f, runlevel)
-        f.close()
+        vserverimpl.setrunlevel(RUNDIR + "/utmp", runlevel)
 
         # mount /proc and /dev/pts
         self.__do_mount("none", self.dir, "/proc", "proc")
 
         # mount /proc and /dev/pts
         self.__do_mount("none", self.dir, "/proc", "proc")
@@ -434,19 +444,19 @@ class VServer:
                 if fd != 0:
                     os.dup2(fd, 0)
                     os.close(fd)
                 if fd != 0:
                     os.dup2(fd, 0)
                     os.close(fd)
+                # perform pre-init cleanup
+                self.__prep(runlevel)
+
                 self.config.cache_it()
                 self.__do_chroot()
                 self.config.cache_it()
                 self.__do_chroot()
-                log = open("/var/log/boot.log", "w", 0)
+                log = open("/var/log/boot.log", "a", 0)
                 if log.fileno() != 1:
                     os.dup2(log.fileno(), 1)
                 os.dup2(1, 2)
 
                 print >>log, ("%s: starting the virtual server %s" %
                               (time.asctime(time.gmtime()), self.name))
                 if log.fileno() != 1:
                     os.dup2(log.fileno(), 1)
                 os.dup2(1, 2)
 
                 print >>log, ("%s: starting the virtual server %s" %
                               (time.asctime(time.gmtime()), self.name))
-
-                # perform pre-init cleanup
-                self.__prep(runlevel, log)
-
                 # execute each init script in turn
                 # XXX - we don't support all scripts that vserver script does
                 self.__do_chcontext(state_file)
                 # execute each init script in turn
                 # XXX - we don't support all scripts that vserver script does
                 self.__do_chcontext(state_file)
@@ -459,12 +469,12 @@ class VServer:
                          print >>log, "executing '%s'" % " ".join(cmd_args)
                          os.spawnvp(os.P_NOWAIT,cmd[0],cmd_args)
                      except:
                          print >>log, "executing '%s'" % " ".join(cmd_args)
                          os.spawnvp(os.P_NOWAIT,cmd[0],cmd_args)
                      except:
-                         traceback.print_exc()
+                         print >>log, traceback.format_exc()
                          os._exit(1)
 
             # we get here due to an exception in the top-level child process
             except Exception, ex:
                          os._exit(1)
 
             # we get here due to an exception in the top-level child process
             except Exception, ex:
-                traceback.print_exc()
+                self.log(traceback.format_exc())
             os._exit(0)
 
         # parent process
             os._exit(0)
 
         # parent process