-----------------------------------------------------------------------------*/
require_once 'YATTA/Proceso.php';
-require_once 'YATTA/ProcesoWeb.php';
+require_once 'YATTA/ProcesoDB.php';
require_once 'YATTA/Servidor.php';
/**
* @access private
*/
function _obtenerServidor($db) {
+
+ //@FIXME La ponderacion esta mal. No tengo que buscar el que tenga mas
+ //alta o mas baja OJO!!! Volver a pensar el calculo.
+
$res = $db->query('SELECT s.id, s.escala * s.procesos AS ponderacion
FROM yatta.servidores AS s
ORDER BY ponderacion ASC, s.escala DESC');
$proceso->owner = $owner;
if (@$id) {
$proceso->id = $id;
+ $res = $proceso->buscar($db, MECON_DBO_AND, ' id ASC');
+ $res = $proceso->cargar($res);
+ return $proceso;
+ }
+ else {
+ return $proceso->buscar($db, MECON_DBO_AND, ' id ASC');
}
- return $proceso->buscar($db, MECON_DBO_AND, ' id ASC');
}
/**
- * Obtiene un proceso de un usuario.
+ * Actualiza los datos de un proceso al terminar.
*
* @param DB $db Conexion a la base de datos.
- * @param string $owner Usuario duenio de los procesos.
- * @param int $id Identificador del proceso a buscar
+ * @param int $id_proceso Identificador del proceso.
+ * @param int $id_server Identificador del Servidor.
+ * @param int $status Identificador del estado de finalizacion.
+ * @param string $nota Nota de error o similar.
+ * @param string $archivo Nombre del archivo temporal que esta en el fs.
+ * @param int $notificar Indica si hay que notificar al owner.
*
* @return mixed
* @access public
*/
- function obtenerProcesoUsuario($db, $owner, $id) {
- $proceso =& new YATTA_ProcesoDB;
- $proceso->owner = $owner;
- $proceso->id = $id;
- $res = $proceso->buscar($db, MECON_DBO_AND, ' id ASC');
- $res = $proceso->cargar($res);
- return $proceso;
+ function terminarProceso($db, $id_proceso, $id_server, $status, $nota =
+ null, $archivo = null, $notificar = 0) {
+
+ //Actualizo la base procesos
+ $sql = 'UPDATE yatta.procesos SET status = '. $status;
+
+ if (@$nota) {
+ $sql.= ', nota = '. $nota;
+ }
+ if (@$archivo) {
+ $sql.= ', archivo = '. $archivo;
+ }
+ if (@$notificar) {
+ $sql.= ', notificar = '. $notificar;
+ }
+ $sql.= ' WHERE id = '. $id_proceso;
+
+ $res = $db->query($sql);
+ // Si hay error lo devuelve.
+ if (DB::isError($res)) {
+ return $res;
+ }
+
+ //@TODO Aca notificar
+// if (@$notificar) {
+// }
+
+ //Actualizo los servidores
+ $SERVER =& new YATTA_Servidor;
+ return $SERVER->quitarProceso($db, $id_server);
+ }
+
+ /**
+ * Busca un proceso en cola para el servidor
+ *
+ * @param DB $db Conexion a la base de datos.
+ * @param int $id Identificador del servidor.
+ *
+ * @return mixed
+ * @access public
+ */
+ function obtenerNuevoProceso($db, $id) {
+ $res = $db->query('SELECT p.id AS id, p.script AS script
+ FROM yatta.procesos AS p
+ WHERE p.server = '.$id.' AND status = 0
+ ORDER BY p.prioridad, p.id');
+ // Si hay error lo devuelve.
+ if (DB::isError($res)) {
+ return $res;
+ }
+ return $res->fetchRow(DB_FETCHMODE_ASSOC);
+ }
+
+ /**
+ * Busca si un proceso que se esta ejecutando tiene pedido de cancelacion.
+ *
+ * @param DB $db Conexion a la base de datos.
+ * @param int $id Identificador del proceso.
+ *
+ * @return mixed
+ * @access public
+ */
+ function abortar($db, $id) {
+ $res = $db->query('SELECT count(*) AS cuenta
+ FROM yatta.procesos
+ WHERE id = '.$id.' AND status = 5');
+ // Si hay error lo devuelve.
+ if (DB::isError($res)) {
+ return $res;
+ }
+ $res = $res->fetchRow(DB_FETCHMODE_ASSOC);
+ return $res['cuenta'];
}
}
?>
\ No newline at end of file
$Id$
-----------------------------------------------------------------------------*/
-require_once 'MECON/DBO.php';
-require_once 'PEAR.php';
-require_once 'Date.php';
-
/**
* Clase para el manejo de los procesos.
*
* @access public
*/
-class YATTA_Proceso extends MECON_DBO {
+class YATTA_Proceso {
/**
- * Identificador del proceso.
+ * Indica si hay que notificar o no al owner del resultado del script.
*
- * @var int $id
- * @access public
- */
- var $id = null;
-
- /**
- * Fecha cuando se agrego el proceso.
- * Formato = DD/MM/YYYY
- * Puede ser un objeto Date.
- *
- * @var string $fecha
- * @access public
- */
- var $fecha = null;
-
- /**
- * Proceso a ejecutar.
- *
- * @var string $script
+ * @var int $notificar
* @access public
*/
- var $script = null;
+ var $notificar = 0;
/**
- * Identificador del sistema en el cual se lanzo el proceso.
- *
- * @var int $id_sistema
- * @access public
- */
- var $id_sistema = null;
-
- /**
- * Nombre del sistema en el cual se lanzo el proceso.
+ * Contiene el texto del error.
*
- * @var string $nombre_sistema
+ * @var string $error
* @access public
*/
- var $nombre_sistema = null;
+ var $error = 'Desconocido';
/**
- * Descripcion del proceso.
- *
- * @var string $descripcion
- * @access public
- */
- var $descripcion = null;
-
- /**
- * PID del proceso en el servidor de proceso.
- *
- * @var int $pid
- * @access public
- */
- var $pid = null;
-
- /**
- * Servidor en donde se ejecuto/a/ara el proceso.
- *
- * @var int $server
- * @access public
- */
- var $server = null;
-
- /**
- * Estado del proceso.
- * 0 = En Espera
- * 1 = Procesando
- * 2 = Finalizado
- * 3 = Error
- * 4 = Abortado
- *
- * @var int $status
- * @access public
- */
- var $status = null;
-
- /**
- * Identificador del usuario responsable por el proceso.
- *
- * @var string $owner
- * @access public
- */
- var $owner = null;
-
- /**
- * Destinos para el resultado.
- * array ('mmarre@mecon', 'gmeray@mecon')
- *
- * @var array $destinos
- * @access public
- */
- var $destinos = null;
-
- /**
- * Prioridad el proceso.
- *
- * @var int $prioridad
- * @access public
- */
- var $prioridad = null;
-
- /**
- * Fecha de ejecucion fijada.
- *
- * @var string $scheduling
- * @access public
- */
- var $scheduling = null;
-
- /**
- * Indica si se debe notificar o no al owner sobre el resultado.
- *
- * @var int $notificar
- * @access public
- */
- var $notificar = null;
-
- /**
- * Nombre del archivo resultado
- *
- * @var string $resultado
- * @access public
- */
- var $resultado = null;
-
- /**
- * Nombre del archivo en el tacho
+ * Indica el nombre del archivo en el filesystem.
*
* @var string $archivo
* @access public
*/
var $archivo = null;
-
- /**
- * Nota explicativa sobre el error producido o el motivo por el cual se
- * aborto el proceso.
- *
- * @var string $nota
- * @access public
- */
- var $nota = null;
-
- /**
- * Descripcion del estado.
- *
- * @var string $icono
- * @access public
- */
- var $icono = null;
-
+
/**
- * Carga el objeto con los datos que se pasan por parametro.
- *
- * @param DB $db DB o DB_Result a usar para la carga.
+ * Funcion que realiza la ejecucion del script.
*
- * @return mixed
- * @access public
- */
- function cargar($db = null)
- {
- // Si es un resultado, obtengo los elemento.
- if (is_a($db, 'db_result')) {
- $this->predefinirAtributos();
- $res = $db->fetchRow(DB_FETCHMODE_ASSOC);
- // Si hay error lo devuelve.
- if (DB::isError($res)) {
- return $res;
- }
- elseif (!$res) {
- return false;
- }
- $this->id = $res['id'];
- $this->fecha = $res['fecha'];
- $this->script = $res['script'];
- $this->id_sistema = $res['id_sistema'];
- $this->nombre_sistema = $res['nombre_sistema'];
- $this->descripcion = $res['descripcion'];
- $this->pid = $res['pid'];
- $this->server = $res['server'];
- $this->status = $res['status'];
- $this->owner = $res['owner'];
- $this->destinos = split(',', $res['destinos']);
- $this->prioridad = $res['prioridad'];
- $this->scheduling = $res['scheduling'];
- $this->notificar = $res['notificar'];
- $this->resultado = $res['resultado'];
- $this->archivo = $res['archivo'];
- $this->nota = $res['nota'];
- $this->icono = $res['icono'];
- return true;
- }
- return false;
- }
-
- /**
- * Borra el objeto de una base de datos.
- *
- * @param DB $db Base de datos de donde borrar el objeto.
- *
- * @return mixed
- * @access public
- */
- function borrar($db = null)
- {
- trigger_error('Not implemented!', E_USER_WARNING);
- }
-
- /**
- * Busca los datos en la base.
- *
- * @param DB $db Conexion a la base de datos.
- * @param string $operador Indica como deben concatenarse las condiciones de busqueda
- * @param string $orden Indica de que manera deben ordenarse los resultados de la busqueda
- *
- * @return mixed
- * @access public
- */
- function buscar($db = null, $operador = MECON_DBO_OR, $orden = null)
- {
- // Armo el WHERE.
- if (is_null($this->owner)) {
- return new PEAR_Error ('Debe definirse el Owner del proceso.');
- }
- $where = array();
- if (!is_null($this->id)) {
- $where[] = 'p.id = '.$this->id;
- }
- if (!is_null($this->fecha)) {
- if (is_object($this->fecha) ) {
- $fecha = $this->fecha->format("%Y-%m-%d");
- }
- else {
- list ($dia, $mes, $anio) = split ('[/.-]', $this->fecha);
- $fecha = $anio.'-'.$mes.'-'.$dia;
- }
- $where[] = 'p.fecha = '. $db->quote("$fecha");
- }
- if (!is_null($this->script)) {
- $where[] = 'p.script LIKE '. $db->quote("%$this->script%");
- }
- if (!is_null($this->id_sistema)) {
- $where[] = 'p.id_sistema = '. $this->id_sistema;
- }
- if (!is_null($this->nombre_sistema)) {
- $where[] = 's.nombre_sistema LIKE '. $db->quote("%$this->nombre_sistema%");
- }
- if (!is_null($this->descripcion)) {
- $where[] = 'p.descripcion LIKE '. $db->quote("%$this->descripcion%");
- }
- if (!is_null($this->pid)) {
- $where[] = 'p.pid = '.$this->pid;
- }
- if (!is_null($this->server)) {
- $where[] = 'p.server = '.$this->server;
- }
- if (!is_null($this->status)) {
- $where[] = 'p.status = '.$this->status;
- }
- if (!is_null($this->destinos)) {
- if (is_array($this->destinos)) {
- foreach ($this->destinos as $destino) {
- $where[] = 'p.destinos LIKE '. $db->quote("%$destino");
- }
- }
- else {
- $where[] = 'p.destinos LIKE '. $db->quote("%$this->destinos%");
- }
- }
- if (!is_null($this->prioridad)) {
- $where[] = 'p.prioridad = '.$this->prioridad;
- }
- if (!is_null($this->scheduling)) {
- $where[] = 'p.scheduling LIKE '. $db->quote("%$this->scheduling%");
- }
- if (!is_null($this->notificar)) {
- $where[] = 'p.notificar ='. $this->notificar;
- }
- if (!is_null($this->resultado)) {
- $where[] = 'p.resultado LIKE '. $db->quote("%$this->resultado%");
- }
- if (!is_null($this->nota)) {
- $where[] = 'p.nota LIKE '. $db->quote("%$this->nota%");
- }
- if ($where) {
- $where = 'WHERE p.owner = '. $db->quote("$this->owner").
- 'AND p.id_sistema = s.id_sistema AND ('. join ("$operador
- ", $where).')';
- }
- else {
- $where = 'WHERE p.owner = '. $db->quote("$this->owner").
- 'AND p.id_sistema = s.id_sistema';
- }
- // Armo el ORDER BY.
- if (is_string($orden))
- {
- $orden = array($orden);
- }
- if ($orden)
- {
- $orden = 'ORDER BY '.join(',',$orden);
- }
- else {
- $orden = '';
- }
-
- return $db->query("SELECT p.id AS id,
- DATE_FORMAT(p.fecha, '%d-%m-%Y') AS fecha,
- p.script AS
- script, p.id_sistema AS id_sistema, s.nombre_sistema AS
- nombre_sistema, p.descripcion AS descripcion, p.pid AS pid,
- p.server AS server, p.status AS status, p.owner AS owner,
- p.destinos AS destinos, p.prioridad AS prioridad, p.scheduling
- AS scheduling, p.notificar AS notificar, p.resultado AS
- resultado, p.nota AS nota, p.archivo AS archivo, ".
- "IF (p.status = 0, 'El proceso esta en cola. Aun no se ejecuto.".
- "', ".
- "IF(p.status = 1, 'El proceso se esta ejecutando en este momento.".
- "',".
- "IF(p.status = 2, 'El proceso ha finalizado. ".
- "',".
- "IF(p.status = 3, 'Se produjo un error durante la ejecucion".
- " del proceso.".
- "',".
- "'El proceso fue detenido por alguna persona (el responsable o".
- " el administrador).".
- "'".
- ")".
- ")".
- ")".
- ") AS icono
- FROM yatta.procesos AS p, samurai.sistema AS s
- $where
- $orden");
- }
-
- /**
- * Guarda los datos en la base.
- *
- * @param DB $db Conexion a la base de datos.
- * @param bool $nuevo Indica si se trata de un nuevo registro en la base.
- *
- * @return mixed
- * @access public
- */
- function guardar($db = null, $nuevo = true)
- {
-/*
- //@TODO PASAR ESTO A UNA CLASE SERVIDOR
- //Busco el servidor
- $res = $db->query('SELECT id, escala * procesos AS ponderacion
- FROM yatta.servidores
- ORDER BY ponderacion, escala');
- $res = $res->fetchRow(DB_FETCHMODE_ASSOC);
- // Si hay error lo devuelve.
- if (DB::isError($res)) {
- return $res;
- }
- $this->server = $res['id'];
- //Asigno la fecha
- if (@is_null($this->fecha)) {
- $this->fecha = date ('Y-m-d');
- }
-
- if ($nuevo) {
- $datos = array (
- 'fecha' => $this->fecha,
- 'script' => $this->script,
- 'id_sistema' => $this->id_sistema,
- 'descripcion' => $this->descripcion,
- 'pid' => $this->pid,
- 'server' => $this->server,
- 'status' => $this->status,
- 'owner' => $this->owner,
- 'destinos' => $this->destinos,
- 'prioridad' => $this->prioridad,
- 'scheduling' => $this->scheduling,
- 'notificar' => $this->notificar,
- 'resultado' => $this->resultado,
- 'archivo' => $this->archivo,
- 'nota' => $this->nota
- );
-
- $res = $db->autoExecute('yatta.procesos', $datos,
- DB_AUTOQUERY_INSERT);
- }
- else {
- $datos = array (
- 'fecha' => $this->fecha,
- 'script' => $this->script,
- 'id_sistema' => $this->id_sistema,
- 'descripcion' => $this->descripcion,
- 'pid' => $this->pid,
- 'server' => $this->server,
- 'status' => $this->status,
- 'owner' => $this->owner,
- 'destinos' => $this->destinos,
- 'prioridad' => $this->prioridad,
- 'scheduling' => $this->scheduling,
- 'notificar' => $this->notificar,
- 'resultado' => $this->resultado,
- 'archivo' => $this->archivo,
- 'nota' => $this->nota
- );
-
- $res = $db->autoExecute('yatta.procesos', $datos,
- DB_AUTOQUERY_UPDATE, 'id = '.$this->id);
-
- }
-
- if (DB::isError($res)) {
- return $res;
- }
-
- return $db->query('
- UPDATE yatta.servidores
- SET procesos = procesos + 1
- WHERE id = '. $this->server);
-*/
- }
-
- /**
- * Hace un reset de los atributos.
- *
* @return void
* @access public
*/
- function predefinirAtributos() {
- $this->id = null;
- $this->fecha = null;
- $this->script = null;
- $this->id_sistema = null;
- $this->nombre_sistema = null;
- $this->descripcion = null;
- $this->pid = null;
- $this->server = null;
- $this->status = null;
- $this->owner = null;
- $this->destinos = null;
- $this->prioridad = null;
- $this->scheduling = null;
- $this->notificar = null;
- $this->resultado = null;
- $this->archivo = null;
- $this->nota = null;
- $this->icono = null;
- }
-
- /**
- * Devuelve un array asociativo con los valores del proceso.
- *
- * @return array
- * @access public
- */
- function obtenerDatos() {
- return array (
- 'script' => $this->script,
- 'id_sistema' => $this->id_sistema,
- 'descripcion' => $this->descripcion,
- 'owner' => $this->owner,
- 'destinos' => $this->destinos,
- 'prioridad' => $this->prioridad,
- 'scheduling' => $this->scheduling,
- 'notificar' => $this->notificar,
- );
+ function run() {
+ $this->error = 'No se implemento el metodo RUN.';
}
}
?>
\ No newline at end of file
$Id$
-----------------------------------------------------------------------------*/
-//Sacar el \n al final
-$SERVIDOR = substr(file_get_contents('/etc/hostname'), 0, strpos
- (file_get_contents('/etc/hostname'), "\n"));
+//XXX LANZAR ESTE SCRIPT CON NICE -19
+
+//@TODO Agregar las linea de logueo
-var_dump($SERVIDOR);
-exit;
+//YATTA LOG {{{
+function yatta_log ($texto) {
+ GLOBAL $YATTA_SERVER;
+ GLOBAL $FH;
+ $linea = strftime("%b %e %H:%M:%S").' '.$YATTA_SERVER['name'].' '.
+ $YATTA_SERVER['script'].'['.$YATTA_SERVER['pid'].']: '. $texto ."\n";
+ fwrite($FH, $linea);
+}
+//}}}
+
+//ABRO EL ARCHIVO DE LOG {{{
+//Como root:
+//# touch /var/log/apache/YATTA_Server.log
+//# chown root.www-data /var/log/apache/YATTA_Server.log
+//# chmod 660 /var/log/apache/YATTA_Server.log
+if (!($FH = fopen ("/var/log/apache/YATTA_Server.log", "a"))) {
+ die ("No se pudo abrir el archivo de log. Se detiene el script.");
+}
+//}}}
//REQUIRE ONCE {{{
-require_once 'YATTA/Proceso.php';
require_once 'DB.php';
+require_once 'PEAR.php';
+require_once 'YATTA/Controlador.php';
+require_once 'YATTA/Servidor.php';
//}}}
//CREO UNA CONEXION MYSQL{{{
-$DB =& DB::connect('mysql://intranet:intranet@bal747f/yatta', true);
-if (DB::isError($DB)) {
- die ($DB->getMessage());
+$db =& DB::connect('mysql://intranet:intranet@bal747f/yatta', true);
+if (DB::isError($db)) {
+ die ($db->getMessage());
+}
+//}}}
+
+//CREO LOS OBJETOS NECESARIOS {{{
+$CONTROLADOR =& new YATTA_Controlador;
+//}}}
+
+//OBTENGO LOS DATOS DEL SERVER {{{
+$YATTA_SERVER['script'] = $argv[0];
+$YATTA_SERVER['pid'] = getmypid();
+$YATTA_SERVER['name'] = substr(file_get_contents('/etc/hostname'), 0, strpos
+ (file_get_contents('/etc/hostname'), "\n"));
+$YATTA_SERVER['id'] = $SERVIDOR->obtenerId($db, $YATTA_SERVER['name']);
+if (PEAR::isError($YATTA_SERVER['id'])) {
+ die('Error: ' . $YATTA_SERVER['id']->getMessage() . "\n");
}
+yatta_log ('*************** Comienzo Ejecución ***************');
//}}}
-//BUSCO EL ESTADO DEL SERVIDOR EN LA BASE {{{
-$sql = 'SELECT count(procesos.id) AS cuenta
- FROM procesos, servidores
- WHERE servidores.nombre = ? and procesos.server = servidores.id and
- procesos.status = 1;'; //Status 1 -> Procesando
+//WHILEO LAS OPCIONES {{{
+while (1) {
+
+ //Busco un nuevo proceso {{{
+ $proceso = $CONTROLADOR->obtenerNuevoProceso($db,
+ $YATTA_SERVER['id']);
+ //}}}
+
+ //Si hay un proceso lo lanzo {{{
+ if (@$proceso) {
+ $pid = pcntl_fork();
+
+ //FORK ERROR {{{
+ if ($pid == -1) {
+ yatta_log('ERROR: No se pudo forkear.');
+ $res = $CONTROLADOR->terminarProceso($db, $proceso['id'],
+ $YATTA_SERVER['id'], 3, 'No se pudo forkear el script.');
+ if (PEAR::isError($res)) {
+ yatta_log('ERROR: YATTA_Controlador. '.$res->getMessage());
+ }
+ }
+ //}}}
+
+ //FORK PADRE {{{
+ elseif ($pid) {
+ //Espero a que termine el proceso.
+ while (($wapid = pcntl_waitpid ($pid, $status, WNOHANG)) != $pid) {
+ if ($CONTROLADOR->abortar($db, $proceso['id'])) {
+ posix_kill($pid, 15); //SIGTERM
+ $CONTROLADOR->terminarProceso($db, $proceso['id'],
+ $YATTA_SERVER['id'], 4);
+ }
+ sleep(10);
+ }
+ //Cuando un proceso hijo termina no hay que hacer nada, de eso se
+ //encargo YATTA_Controlador::terminarProceso
+ }
+ //}}}
+
+ //FORk HIJO {{{
+ else {
+ require_once $proceso['script'];
+
+ if (function_exists('create_process')) {
+ $SCRIPT =& create_process();
+ $SCRIPT->run();
+ }
+ else {
+ require_once 'YATTA/Proceso.php';
+ $SCRIPT =& new YATTA_Proceso;
+ $SCRIPT->error = 'No existe la funcion create_process en'.
+ $proceso['script'];
+ }
+
+
+ if (@$SCRIPT->error) {
+ $estado = 3;
+ }
+ else {
+ $estado = 2;
+ }
+ $CONROLADOR->terminarProceso($db, $proceso['id'],
+ $YATTA_SERVER['id'], $estado, @$SCRIPT->error,
+ @$SCRIPT->archivo, @$SCRIPT->notificar);
+ }
+ //}}}
+
+ }
+ // }}}
+
+ //No hay proceso {{{
+ else {
+ yatta_log('No hay procesos asignados a este servidor.');
+ sleep(60);
+ }
+ //}}}
+
+}
//}}}
+//CIERRO EL ARCHIVO DE LOG {{{
+fclose ($FH);
+//}}}
?>
\ No newline at end of file