]> git.llucax.com Git - z.facultad/75.52/sercom.git/blobdiff - sercom/tester.py
fix de id
[z.facultad/75.52/sercom.git] / sercom / tester.py
index f1229b4ba1640dc3c93dcef4c40e5231f2784e7e..6e4088c1665984d039fbe768bd21a8e950e6477f 100644 (file)
@@ -6,9 +6,9 @@ from zipfile import ZipFile, BadZipfile
 from cStringIO import StringIO
 from shutil import rmtree
 from datetime import datetime
 from cStringIO import StringIO
 from shutil import rmtree
 from datetime import datetime
-from subprocess import Popen, PIPE, call #, check_call XXX Python 2.5
 from os.path import join
 from turbogears import config
 from os.path import join
 from turbogears import config
+import subprocess as sp
 import os, sys, pwd, grp
 import resource as rsrc
 import logging
 import os, sys, pwd, grp
 import resource as rsrc
 import logging
@@ -34,7 +34,7 @@ class UserInfo(object): #{{{
 
 user_info = UserInfo(config.get('sercom.tester.user', 65534))
 
 
 user_info = UserInfo(config.get('sercom.tester.user', 65534))
 
-def check_call(*popenargs, **kwargs): #{{{ Python 2.5 forward-compatibility
+def check_call(*popenargs, **kwargs): #{{{ XXX Python 2.5 forward-compatibility
     """Run command with arguments.  Wait for command to complete.  If
     the exit code was zero then return, otherwise raise
     CalledProcessError.  The CalledProcessError object will have the
     """Run command with arguments.  Wait for command to complete.  If
     the exit code was zero then return, otherwise raise
     CalledProcessError.  The CalledProcessError object will have the
@@ -45,18 +45,19 @@ def check_call(*popenargs, **kwargs): #{{{ Python 2.5 forward-compatibility
 
     check_call(["ls", "-l"])
     """
 
     check_call(["ls", "-l"])
     """
-    retcode = call(*popenargs, **kwargs)
+    retcode = sp.call(*popenargs, **kwargs)
     cmd = kwargs.get("args")
     if cmd is None:
         cmd = popenargs[0]
     if retcode:
     cmd = kwargs.get("args")
     if cmd is None:
         cmd = popenargs[0]
     if retcode:
-        raise CalledProcessError(retcode, cmd)
+        raise sp.CalledProcessError(retcode, cmd)
     return retcode
     return retcode
+sp.check_call = check_call
 #}}}
 
 #{{{ Excepciones
 
 #}}}
 
 #{{{ Excepciones
 
-class CalledProcessError(Exception): #{{{ Python 2.5 forward-compatibility
+class CalledProcessError(Exception): #{{{ XXX Python 2.5 forward-compatibility
     """This exception is raised when a process run by check_call() returns
     a non-zero exit status.  The exit status will be stored in the
     returncode attribute."""
     """This exception is raised when a process run by check_call() returns
     a non-zero exit status.  The exit status will be stored in the
     returncode attribute."""
@@ -66,6 +67,7 @@ class CalledProcessError(Exception): #{{{ Python 2.5 forward-compatibility
     def __str__(self):
         return ("Command '%s' returned non-zero exit status %d"
             % (self.cmd, self.returncode))
     def __str__(self):
         return ("Command '%s' returned non-zero exit status %d"
             % (self.cmd, self.returncode))
+sp.CalledProcessError = CalledProcessError
 #}}}
 
 class Error(StandardError): pass
 #}}}
 
 class Error(StandardError): pass
@@ -103,9 +105,14 @@ class SecureProcess(object): #{{{
     MB = 1048576
     # XXX probar! make de un solo archivo lleva nproc=100 y nofile=15
     def __init__(self, comando, chroot, cwd):
     MB = 1048576
     # XXX probar! make de un solo archivo lleva nproc=100 y nofile=15
     def __init__(self, comando, chroot, cwd):
-            self.comando = comando
-            self.chroot = chroot
-            self.cwd = cwd
+        self.comando = comando
+        self.chroot = chroot
+        self.cwd = cwd
+        log.debug('Proceso segurizado: chroot=%s, cwd=%s, user=%s, cpu=%s, '
+            'as=%sMiB, fsize=%sMiB, nofile=%s, nproc=%s, memlock=%s',
+            self.chroot, self.cwd, self.uid, self.max_tiempo_cpu,
+            self.max_memoria, self.max_tam_archivo, self.max_cant_archivos,
+            self.max_cant_procesos, self.max_locks_memoria)
     def __getattr__(self, name):
         if getattr(self.comando, name) is not None:
             return getattr(self.comando, name)
     def __getattr__(self, name):
         if getattr(self.comando, name) is not None:
             return getattr(self.comando, name)
@@ -124,12 +131,6 @@ class SecureProcess(object): #{{{
         rsrc.setrlimit(rsrc.RLIMIT_NPROC, x2(self.max_cant_procesos))
         rsrc.setrlimit(rsrc.RLIMIT_MEMLOCK, x2(self.max_locks_memoria))
         rsrc.setrlimit(rsrc.RLIMIT_CORE, x2(0))
         rsrc.setrlimit(rsrc.RLIMIT_NPROC, x2(self.max_cant_procesos))
         rsrc.setrlimit(rsrc.RLIMIT_MEMLOCK, x2(self.max_locks_memoria))
         rsrc.setrlimit(rsrc.RLIMIT_CORE, x2(0))
-        log.debug('Proceso segurizado: chroot=%s, cwd=%s, user=%s(%s), '
-            'group=%s(%s), cpu=%s, as=%sMiB, fsize=%sMiB, nofile=%s, nproc=%s, '
-            'memlock=%s', self.chroot, self.cwd, uinfo.user, uinfo.uid,
-            uinfo.group, uinfo.gid, self.max_tiempo_cpu, self.max_memoria,
-            self.max_tam_archivo, self.max_cant_archivos,
-            self.max_cant_procesos, self.max_locks_memoria)
         # Tratamos de forzar un sync para que entre al sleep del padre FIXME
         import time
         time.sleep(0)
         # Tratamos de forzar un sync para que entre al sleep del padre FIXME
         import time
         time.sleep(0)
@@ -159,11 +160,11 @@ class Tester(object): #{{{
     @property
     def chroot(self):
         return join(self.path, 'chroot_' + self.name)
     @property
     def chroot(self):
         return join(self.path, 'chroot_' + self.name)
-    #}}}
 
     @property
     def orig_chroot(self):
         return join(self.path, 'chroot')
 
     @property
     def orig_chroot(self):
         return join(self.path, 'chroot')
+    #}}}
 
     def run(self): #{{{
         entrega_id = self.queue.get() # blocking
 
     def run(self): #{{{
         entrega_id = self.queue.get() # blocking
@@ -211,7 +212,7 @@ class Tester(object): #{{{
         os.seteuid(0) # Dios! (para chroot)
         os.setegid(0)
         try:
         os.seteuid(0) # Dios! (para chroot)
         os.setegid(0)
         try:
-            check_call(rsync)
+            sp.check_call(rsync)
         finally:
             log.debug(_(u'Cambiando usuario y grupo efectivos a %s:%s (%s:%s)'),
                 user_info.user, user_info.group, user_info.uid, user_info.gid)
         finally:
             log.debug(_(u'Cambiando usuario y grupo efectivos a %s:%s (%s:%s)'),
                 user_info.user, user_info.group, user_info.uid, user_info.gid)
@@ -301,28 +302,52 @@ def ejecutar_comando_fuente(self, path, entrega): #{{{
     options = dict(
         close_fds=True,
         stdin=None,
     options = dict(
         close_fds=True,
         stdin=None,
-        stdout=None,
-        stderr=None,
         shell=True,
         preexec_fn=SecureProcess(self, 'var/chroot_pepe', '/home/sercom/build')
     )
         shell=True,
         preexec_fn=SecureProcess(self, 'var/chroot_pepe', '/home/sercom/build')
     )
+    if self.guardar_stdouterr:
+        options['stdout'] = file('/tmp/sercom.tester.%s.stdouterr'
+            % comando_ejecutado.id, 'w') #TODO /var/lib/sercom?
+        options['stderr'] = sp.STDOUT
+    else:
+        if self.guardar_stdout:
+            options['stdout'] = file('/tmp/sercom.tester.%s.stdout'
+                % comando_ejecutado.id, 'w') #TODO /var/lib/sercom?
+        if self.guardar_stderr:
+            options['stderr'] = file('/tmp/sercom.tester.%s.stderr'
+                % comando_ejecutado.id, 'w') #TODO /var/lib/sercom?
     log.debug(_(u'Ejecutando como root: %s'), self.comando)
     os.seteuid(0) # Dios! (para chroot)
     os.setegid(0)
     try:
         try:
     log.debug(_(u'Ejecutando como root: %s'), self.comando)
     os.seteuid(0) # Dios! (para chroot)
     os.setegid(0)
     try:
         try:
-            proc = Popen(self.comando, **options)
+            proc = sp.Popen(self.comando, **options)
         finally:
             log.debug(_(u'Cambiando usuario y grupo efectivos a %s:%s (%s:%s)'),
                 user_info.user, user_info.group, user_info.uid, user_info.gid)
             os.setegid(user_info.gid) # Mortal de nuevo
             os.seteuid(user_info.uid)
         finally:
             log.debug(_(u'Cambiando usuario y grupo efectivos a %s:%s (%s:%s)'),
                 user_info.user, user_info.group, user_info.uid, user_info.gid)
             os.setegid(user_info.gid) # Mortal de nuevo
             os.seteuid(user_info.uid)
-    except Exception, e: # FIXME poner en el manejo de exceptiones estandar
+    except Exception, e:
         if hasattr(e, 'child_traceback'):
             log.error(_(u'Error en el hijo: %s'), e.child_traceback)
         raise
         if hasattr(e, 'child_traceback'):
             log.error(_(u'Error en el hijo: %s'), e.child_traceback)
         raise
-    proc.wait()
+    proc.wait() #TODO un sleep grande nos caga todo, ver sercom viejo
     comando_ejecutado.fin = datetime.now()
     comando_ejecutado.fin = datetime.now()
+    buffer = StringIO()
+    zip = ZipFile(buffer, 'w')
+    if self.guardar_stdouterr:
+        zip.write('/tmp/sercom.tester.%s.stdouterr'
+            % comando_ejecutado.id, '__stdouterr__')
+    else:
+        if self.guardar_stdout:
+            azipwrite('/tmp/sercom.tester.%s.stdout'
+                % comando_ejecutado.id, '__stdout__')
+        if self.guardar_stderr:
+            zip.write('/tmp/sercom.tester.%s.stderr'
+                % comando_ejecutado.id, '__stderr__')
+    zip.close()
+    comando_ejecutado.archivos_guardados = buffer.getvalue()
+
 #    if no_anda_ejecucion: # TODO
 #        comando_ejecutado.exito = False
 #        comando_ejecutado.observaciones += 'No anduvo xxx' # TODO mas info
 #    if no_anda_ejecucion: # TODO
 #        comando_ejecutado.exito = False
 #        comando_ejecutado.observaciones += 'No anduvo xxx' # TODO mas info