From: Eric Bollengier Date: Sat, 27 May 2006 17:24:10 +0000 (+0000) Subject: o initial add X-Git-Tag: Release-2.0.0~849 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=f88513ccb9b4b46e86326fb9ec343a0dee2fb3dc;p=bacula%2Fbacula o initial add git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@3035 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/lib/runscript.c b/bacula/src/lib/runscript.c new file mode 100644 index 0000000000..8b9b92c6ae --- /dev/null +++ b/bacula/src/lib/runscript.c @@ -0,0 +1,249 @@ +/* + * Manipulation routines for RunScript list + * + * Eric Bollengier, May 2006 + * + * Version $Id$ + * + */ +/* + Copyright (C) 2000-2006 Kern Sibbald + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as amended with additional clauses defined in the + file LICENSE in the main source directory. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + the file LICENSE for additional details. + + */ + + +#include "bacula.h" +#include "jcr.h" + +#define USE_RUNSCRIPT + +#include "runscript.h" + +RUNSCRIPT *new_runscript() +{ + Dmsg0(500, "runscript: creating new RUNSCRIPT object\n"); + RUNSCRIPT *cmd = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT)); + memset(cmd, 0, sizeof(RUNSCRIPT)); + cmd->reset_default(); + + return cmd; +} + +void RUNSCRIPT::reset_default(bool free_strings) +{ + if (free_strings && command) { + free_pool_memory(command); + } + if (free_strings && target) { + free_pool_memory(target); + } + + target = NULL; + command = NULL; + on_success = true; + on_failure = false; + abort_on_error = true; + when = SCRIPT_Never; +} + +RUNSCRIPT *copy_runscript(RUNSCRIPT *src) +{ + Dmsg0(500, "runscript: creating new RUNSCRIPT object from other\n"); + + RUNSCRIPT *dst = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT)); + memcpy(dst, src, sizeof(RUNSCRIPT)); + + dst->command = NULL; + dst->target = NULL; + + dst->set_command(src->command); + dst->set_target(src->target); + + return dst; +} + +void free_runscript(RUNSCRIPT *script) +{ + Dmsg0(500, "runscript: freeing RUNSCRIPT object\n"); + + if (script->command) { + free_pool_memory(script->command); + } + if (script->target) { + free_pool_memory(script->target); + } + free(script); +} + +int run_scripts(JCR *jcr, alist *runscripts, const char *label) +{ + Dmsg2(200, "runscript: running all RUNSCRIPT object (%s) JobStatus=%c\n", label, jcr->JobStatus); + + RUNSCRIPT *script; + bool runit; + bool status; + + if (runscripts == NULL) { + Dmsg0(100, "runscript: WARNING RUNSCRIPTS list is NULL\n"); + return 0; + } + + foreach_alist(script, runscripts) { + Dmsg2(200, "runscript: try to run %s:%s\n", NPRT(script->target), NPRT(script->command)); + runit=false; + + if ((script->when & SCRIPT_Before) && (jcr->JobStatus == JS_Created)) { + Dmsg0(200, "runscript: Run it because SCRIPT_Before\n"); + runit = true; + } + + if ((script->when & SCRIPT_Before) && (jcr->JobStatus == JS_Running)) { + Dmsg0(200, "runscript: Run it because SCRIPT_Before\n"); + runit = true; + } + + if (script->when & SCRIPT_After) { + if ( (script->on_success && (jcr->JobStatus == JS_Terminated)) + || + (script->on_failure && job_canceled(jcr)) + ) + { + Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n", script->command, + script->on_success, + script->on_failure, + jcr->JobStatus ); + script->when ^= SCRIPT_After; /* reset SCRIPT_After bit */ + runit = true; + } + } + + if (!script->is_local()) { + runit=false; + } + + /* we execute it */ + if (runit) { + status = script->run(jcr, label); + + /* cancel running job properly */ + if ( script->abort_on_error + && (status == false) + && (jcr->JobStatus == JS_Created) + ) + { + set_jcr_job_status(jcr, JS_ErrorTerminated); + } + } + } + return 1; +} + +bool RUNSCRIPT::is_local() +{ + if (!target || (strcmp(target, "") == 0)) { + return true; + } else { + return false; + } +} + +/* set this->command to cmd */ +void RUNSCRIPT::set_command(const POOLMEM *cmd) +{ + Dmsg1(500, "runscript: setting command = %s\n", NPRT(cmd)); + + if (!cmd) { + return; + } + + if (!command) { + command = get_pool_memory(PM_FNAME); + } + + pm_strcpy(command, cmd); +} + +/* set this->target to client_name */ +void RUNSCRIPT::set_target(const POOLMEM *client_name) +{ + Dmsg1(500, "runscript: setting target\n", NPRT(client_name)); + + if (!client_name) { + return; + } + + if (!target) { + target = get_pool_memory(PM_FNAME); + } + + pm_strcpy(target, client_name); +} + +int RUNSCRIPT::run(JCR *jcr, const char *name) +{ + Dmsg0(200, "runscript: running a RUNSCRIPT object\n"); + POOLMEM *ecmd = get_pool_memory(PM_FNAME); + int status; + BPIPE *bpipe; + char line[MAXSTRING]; + + ecmd = edit_job_codes(jcr, ecmd, this->command, ""); + Dmsg1(100, "runscript: running '%s'...\n", ecmd); + Jmsg(jcr, M_INFO, 0, _("%s: run command \"%s\"\n"), name, ecmd); + + bpipe = open_bpipe(ecmd, 0, "r"); + free_pool_memory(ecmd); + if (bpipe == NULL) { + berrno be; + Jmsg(jcr, M_FATAL, 0, _("%s could not execute. ERR=%s\n"), name, + be.strerror()); + return false; + } + while (fgets(line, sizeof(line), bpipe->rfd)) { + int len = strlen(line); + if (len > 0 && line[len-1] == '\n') { + line[len-1] = 0; + } + Jmsg(jcr, M_INFO, 0, _("%s: %s\n"), name, line); + } + status = close_bpipe(bpipe); + if (status != 0) { + berrno be; + Jmsg(jcr, M_FATAL, 0, _("%s returned non-zero status=%d. ERR=%s\n"), name, + status, be.strerror(status)); + return false; + } + return true; +} + +void free_runscripts(alist *runscripts) +{ + Dmsg0(500, "runscript: freeing all RUNSCRIPTS object\n"); + + RUNSCRIPT *elt; + foreach_alist(elt, runscripts) { + free_runscript(elt); + } +} + +void RUNSCRIPT::debug() +{ + Dmsg0(200, "runscript: debug\n"); + Dmsg0(200, _(" --> RunScript\n")); + Dmsg1(200, _(" --> Command=%s\n"), NPRT(command)); + Dmsg1(200, _(" --> Target=%s\n"), NPRT(target)); + Dmsg1(200, _(" --> RunOnSuccess=%u\n"), on_success); + Dmsg1(200, _(" --> RunOnFailure=%u\n"), on_failure); + Dmsg1(200, _(" --> AbortJobOnError=%u\n"), abort_on_error); + Dmsg1(200, _(" --> RunWhen=%u\n"), when); +} diff --git a/bacula/src/lib/runscript.h b/bacula/src/lib/runscript.h new file mode 100644 index 0000000000..3d43608505 --- /dev/null +++ b/bacula/src/lib/runscript.h @@ -0,0 +1,94 @@ +/* + * Bacula RUNSCRIPT Structure definition for FileDaemon and Director + * Eric Bollengier May 2006 + * Version $Id$ + */ +/* + Copyright (C) 2000-2006 Kern Sibbald + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as amended with additional clauses defined in the + file LICENSE in the main source directory. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + the file LICENSE for additional details. + + */ + + +#ifndef __RUNSCRIPT_H_ +#define __RUNSCRIPT_H_ 1 + +#if defined(FILE_DAEMON) || defined(DIRECTOR_DAEMON) +# define USE_RUNSCRIPT +#endif + +#ifdef USE_RUNSCRIPT + +/* Usage: + * + * #define USE_RUNSCRIPT + * #include "lib/runscript.h" + * + * RUNSCRIPT *script = new_runscript(); + * script->set_command("/bin/sleep 20"); + * script->on_failure = true; + * script->when = SCRIPT_After; + * + * script->run("Label"); + * free_runscript(script); + */ + +/* + * RUNSCRIPT->when can take following value : + */ +enum { + SCRIPT_Never = 0, + SCRIPT_After = 1, /* AfterJob */ + SCRIPT_Before = 2, /* BeforeJob */ + SCRIPT_Any = 3 /* Before and After */ +}; + +/* + * Structure for RunScript ressource + */ +class RUNSCRIPT { +public: + POOLMEM *command; /* command string */ + POOLMEM *target; /* host target */ + char level; /* Base|Full|Incr...|All (NYI) */ + bool on_success; /* executre command on job success (After) */ + bool on_failure; /* executre command on job failure (After) */ + bool abort_on_error; /* abort job on error (Before) */ + int when; /* SCRIPT_Before|Script_After BEFORE/AFTER JOB*/ + + int run(JCR *job, const char *name=""); + bool can_run_at_level(int JobLevel) { return true;}; /* TODO */ + void set_command(const POOLMEM *cmd); + void set_target(const POOLMEM *client_name); + void reset_default(bool free_string = false); + bool is_local(); /* true if running on local host */ + void debug(); +}; + +/* create new RUNSCRIPT (set all value to 0) */ +RUNSCRIPT *new_runscript(); + +/* create new RUNSCRIPT from an other */ +RUNSCRIPT *copy_runscript(RUNSCRIPT *src); + +/* launch each script from runscripts*/ +int run_scripts(JCR *jcr, alist *runscripts, const char *name); + +/* free RUNSCRIPT (and all POOLMEM) */ +void free_runscript(RUNSCRIPT *script); + +/* foreach_alist free RUNSCRIPT */ +void free_runscripts(alist *runscripts); /* you have to free alist */ + +#endif /* USE_RUNSCRIPT */ + +#endif /* __RUNSCRIPT_H_ */