]> git.sur5r.net Git - bacula/bacula/commitdiff
Implement ClientRunBeforeJob and ClientRunAfterJob
authorKern Sibbald <kern@sibbald.com>
Sat, 6 Sep 2003 10:17:22 +0000 (10:17 +0000)
committerKern Sibbald <kern@sibbald.com>
Sat, 6 Sep 2003 10:17:22 +0000 (10:17 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@688 91ce42f0-d328-0410-95d8-f526ca767f89

14 files changed:
bacula/ChangeLog
bacula/ReleaseNotes
bacula/src/dird/backup.c
bacula/src/dird/dird_conf.c
bacula/src/dird/dird_conf.h
bacula/src/dird/fd_cmds.c
bacula/src/dird/protos.h
bacula/src/dird/restore.c
bacula/src/dird/verify.c
bacula/src/filed/job.c
bacula/src/jcr.h
bacula/src/lib/parse_conf.h
bacula/src/stored/btape.c
bacula/src/version.h

index dcfad2ea2c0c0bd5d9549306e3fb9598c505b591..8e8e0b8732e0ab5b3d3fea346b9b7ce90e6c17aa 100644 (file)
@@ -1,4 +1,16 @@
-2003-08-02 Version 1.32 02Sep03 Beta
+2003-08-02 Version 1.32 06Sep03 Beta
+- Implement ClientRunBeforeJob and ClientRunAfterJob.
+- Corrected BSRatEOF to be BSFatEOF in btape --
+  reported by Lars Koller.
+- Documented BSFatEof
+- Eliminated save_level in FD replaced by JobLevel.
+- Increased MAX_RES_ITEMS from 35 to 50 to handle
+  new ClientRunBeforeJob ...
+- Add line number in error message for restore from file.
+- Correct editing of jobids (misplaced comma).
+- Implement restore files.
+- Quickie patch to allow Purged Volumes to be mounted.   
+  Must review algorithm.
 - Eliminate a duplicated query from query.sql
 - Restructure ua_restore.c so that I can add restore files.
 - Correct positioning problem at beginning of a second volume 
index ee4848594572fb5e37a6025c9f1a012583d5512e..76a9a971a25fa50e6acb1bbfb72023bc74eb38b5 100644 (file)
@@ -1,15 +1,17 @@
 
           Release Notes for Bacula 1.32
 
-  Bacula code: Total files = 259 Total lines = 76,690 (*.h *.c *.in)
+  Bacula code: Total files = 259 Total lines = 77,120 (*.h *.c *.in)
 
 Major Changes this Release:
 - Fixed gnome-console to compile with RH9 (Gnome 2.0)
 - Implemented a single routine to read_records. It also returns
   a different record packet for each session.  This means
   that multiple simultaneous jobs should work.
-- Implemented forward space file/block whenever possible.
+- Implemented forward space file/block whenever possible 
+  during restore.
 - Added SDConnectTimeout to FD.    
+- Added ClientRunBeforeJob and ClientRunAfterJob.
 
 
 Other Changes this Release:
index 43f7513c1a0ce1a33280008492de8c78cc79b5af..8d547b406563bc8c47e94c32d38ad4487c8aa1c9 100644 (file)
@@ -198,6 +198,10 @@ int do_backup(JCR *jcr)
       goto bail_out;
    }
 
+   if (!send_run_before_and_after_commands(jcr)) {
+      goto bail_out;
+   }
+
    /* Send backup command */
    bnet_fsend(fd, backupcmd);
    if (!response(jcr, fd, OKbackup, "backup", DISPLAY_ERROR)) {
index 25cab2dc79c85a5acc87a1f8c02394f6afb66c1d..2170928f4e45ef165f1ad51dcdfcb602fb2e74f8 100644 (file)
@@ -208,6 +208,8 @@ static struct res_items job_items[] = {
    {"prunevolumes", store_yesno, ITEM(res_job.PruneVolumes), 1, ITEM_DEFAULT, 0},
    {"runbeforejob", store_str,  ITEM(res_job.RunBeforeJob), 0, 0, 0},
    {"runafterjob",  store_str,  ITEM(res_job.RunAfterJob),  0, 0, 0},
+   {"clientrunbeforejob", store_str,  ITEM(res_job.ClientRunBeforeJob), 0, 0, 0},
+   {"clientrunafterjob",  store_str,  ITEM(res_job.ClientRunAfterJob),  0, 0, 0},
    {"spoolattributes", store_yesno, ITEM(res_job.SpoolAttributes), 1, ITEM_DEFAULT, 0},
    {"writebootstrap", store_dir, ITEM(res_job.WriteBootstrap), 0, 0, 0},
    {"maximumconcurrentjobs", store_pint, ITEM(res_job.MaxConcurrentJobs), 0, ITEM_DEFAULT, 1},
@@ -815,12 +817,20 @@ void free_resource(int type)
       if (res->res_job.RunAfterJob) {
         free(res->res_job.RunAfterJob);
       }
+      if (res->res_job.ClientRunBeforeJob) {
+        free(res->res_job.ClientRunBeforeJob);
+      }
+      if (res->res_job.ClientRunAfterJob) {
+        free(res->res_job.ClientRunAfterJob);
+      }
       break;
    case R_MSGS:
-      if (res->res_msgs.mail_cmd)
+      if (res->res_msgs.mail_cmd) {
         free(res->res_msgs.mail_cmd);
-      if (res->res_msgs.operator_cmd)
+      }
+      if (res->res_msgs.operator_cmd) {
         free(res->res_msgs.operator_cmd);
+      }
       free_msgs_res((MSGS *)res);  /* free message resource */
       res = NULL;
       break;
index 247610f1a5d5ac8a54a06f2c4a9783fa3bdee0f3..717805ff3a4fbe43bda0f2841bc0cbeebb248b2f 100644 (file)
@@ -185,6 +185,8 @@ struct JOB {
    char *RestoreBootstrap;            /* Bootstrap file */
    char *RunBeforeJob;                /* Run program before Job */
    char *RunAfterJob;                 /* Run program after Job */
+   char *ClientRunBeforeJob;          /* Run client program before Job */
+   char *ClientRunAfterJob;           /* Run client program after Job */
    char *WriteBootstrap;              /* Where to write bootstrap Job updates */
    int   replace;                     /* How (overwrite, ..) */
    utime_t MaxRunTime;                /* max run time in seconds */
index 09c62413b9f4aab799a77191c17ace1650f721df..0c53376ca6ce845eb7e9385aedd70d6d3ec4ed6a 100644 (file)
@@ -40,6 +40,8 @@ static char inc[]         = "include\n";
 static char exc[]         = "exclude\n";
 static char jobcmd[]      = "JobId=%d Job=%s SDid=%u SDtime=%u Authorization=%s\n";
 static char levelcmd[]    = "level = %s%s mtime_only=%d\n";
+static char runbefore[]   = "RunBeforeJob %s\n";
+static char runafter[]    = "RunAfterJob %s\n";
 
 
 /* Responses received from File daemon */
@@ -48,6 +50,8 @@ static char OKexc[]       = "2000 OK exclude\n";
 static char OKjob[]       = "2000 OK Job";
 static char OKbootstrap[] = "2000 OK bootstrap\n";
 static char OKlevel[]     = "2000 OK level\n";
+static char OKRunBefore[] = "2000 OK RunBefore\n";
+static char OKRunAfter[]  = "2000 OK RunAfter\n";
 
 /* Forward referenced functions */
 
@@ -328,7 +332,7 @@ bail_out:
 int send_include_list(JCR *jcr)
 {
    BSOCK *fd = jcr->file_bsock;
-   fd->msglen = sprintf(fd->msg, inc);
+   fd->msglen = pm_strcpy(&fd->msg, inc);
    bnet_send(fd);
    return send_list(jcr, INC_LIST);
 }
@@ -340,7 +344,7 @@ int send_include_list(JCR *jcr)
 int send_exclude_list(JCR *jcr)
 {
    BSOCK *fd = jcr->file_bsock;
-   fd->msglen = sprintf(fd->msg, exc);
+   fd->msglen = pm_strcpy(&fd->msg, exc);
    bnet_send(fd);
    return send_list(jcr, EXC_LIST);
 }
@@ -368,12 +372,9 @@ int send_bootstrap_file(JCR *jcr)
       set_jcr_job_status(jcr, JS_ErrorTerminated);
       return 0;
    }
-   strcpy(fd->msg, bootstrap); 
-   fd->msglen = strlen(fd->msg);
-   bnet_send(fd);
+   bnet_fsend(fd, bootstrap);
    while (fgets(buf, sizeof(buf), bs)) {
-      fd->msglen = Mmsg(&fd->msg, "%s", buf);
-      bnet_send(fd);      
+      bnet_fsend(fd, "%s", buf);       
    }
    bnet_sig(fd, BNET_EOD);
    fclose(bs);
@@ -384,6 +385,37 @@ int send_bootstrap_file(JCR *jcr)
    return 1;
 }
 
+/*
+ * Send ClientRunBeforeJob and ClientRunAfterJob to File daemon
+ */
+int send_run_before_and_after_commands(JCR *jcr)
+{
+   POOLMEM *msg = get_pool_memory(PM_FNAME);
+   BSOCK *fd = jcr->file_bsock;
+   if (jcr->job->ClientRunBeforeJob) {
+      pm_strcpy(&msg, jcr->job->ClientRunBeforeJob);
+      bash_spaces(msg);
+      bnet_fsend(fd, runbefore, msg);
+      if (!response(jcr, fd, OKRunBefore, "ClientRunBeforeJob", DISPLAY_ERROR)) {
+        set_jcr_job_status(jcr, JS_ErrorTerminated);
+        free_pool_memory(msg);
+        return 0;
+      }
+   }
+   if (jcr->job->ClientRunAfterJob) {
+      fd->msglen = pm_strcpy(&msg, jcr->job->ClientRunAfterJob);
+      bash_spaces(msg);
+      bnet_fsend(fd, runafter, msg);
+      if (!response(jcr, fd, OKRunAfter, "ClientRunAfterJob", DISPLAY_ERROR)) {
+        set_jcr_job_status(jcr, JS_ErrorTerminated);
+        free_pool_memory(msg);
+        return 0;
+      }
+   }
+   free_pool_memory(msg);
+   return 1;
+}
+
 
 /* 
  * Read the attributes from the File daemon for
index a53a94820a701b81a72aa6e02e1fd30541e0919f..5ec7d8d6ce5869208eb82482c528f830159f1aec 100644 (file)
@@ -72,6 +72,7 @@ extern int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId);
 extern int put_file_into_catalog(JCR *jcr, long file_index, char *fname, 
                          char *link, char *attr, int stream);
 extern void get_level_since_time(JCR *jcr, char *since, int since_len);
+extern int send_run_before_and_after_commands(JCR *jcr);
 
 /* getmsg.c */
 enum e_prtmsg {
index 341ac3aa33c4ca5d09e597b15c1c62c76e6a2a31..a8459d7ad257eeda4a2e75589d30428d6ff95602 100644 (file)
@@ -219,6 +219,11 @@ int do_restore(JCR *jcr)
       }
    }
 
+   if (!send_run_before_and_after_commands(jcr)) {
+      restore_cleanup(jcr, JS_ErrorTerminated);
+      return 0;
+   }
+
    /* Send restore command */
    char replace, *where;
 
index 31ab1f3ffd4f70f97c21ba835ea8e1802e23c1ce..40faac1e41f1669c9af3e6688d8be073dc42ad7d 100644 (file)
@@ -267,6 +267,10 @@ int do_verify(JCR *jcr)
       goto bail_out;
    }
 
+   if (!send_run_before_and_after_commands(jcr)) {
+      goto bail_out;
+   }
+
    /* 
     * Send verify command/level to File daemon
     */
index e23828c37fb4675251d336776ca025500900417c..dd7c4856dfdd1080bb45b6517464e1d6ae249514 100644 (file)
@@ -54,6 +54,9 @@ static int response(JCR *jcr, BSOCK *sd, char *resp, char *cmd);
 static void filed_free_jcr(JCR *jcr);
 static int open_sd_read_session(JCR *jcr);
 static int send_bootstrap_file(JCR *jcr);
+static int runbefore_cmd(JCR *jcr);
+static int runafter_cmd(JCR *jcr);
+static int run_cmd(JCR *jcr, char *cmd, char *name);
 
 
 /* Exported functions */
@@ -67,21 +70,23 @@ struct s_cmds {
  * The following are the recognized commands from the Director. 
  */
 static struct s_cmds cmds[] = {
-   {"backup",   backup_cmd},
-   {"cancel",   cancel_cmd},
-   {"setdebug=", setdebug_cmd},
-   {"estimate", estimate_cmd},
-   {"exclude",  exclude_cmd},
-   {"Hello",    hello_cmd},
-   {"include",  include_cmd},
-   {"JobId=",   job_cmd},
-   {"level = ", level_cmd},
-   {"restore",  restore_cmd},
-   {"session",  session_cmd},
-   {"status",   status_cmd},
-   {"storage ", storage_cmd},
-   {"verify",   verify_cmd},
-   {"bootstrap",bootstrap_cmd},
+   {"backup",       backup_cmd},
+   {"cancel",       cancel_cmd},
+   {"setdebug=",    setdebug_cmd},
+   {"estimate",     estimate_cmd},
+   {"exclude",      exclude_cmd},
+   {"Hello",        hello_cmd},
+   {"include",      include_cmd},
+   {"JobId=",       job_cmd},
+   {"level = ",     level_cmd},
+   {"restore",      restore_cmd},
+   {"session",      session_cmd},
+   {"status",       status_cmd},
+   {"storage ",     storage_cmd},
+   {"verify",       verify_cmd},
+   {"bootstrap",    bootstrap_cmd},
+   {"RunBeforeJob", runbefore_cmd},
+   {"RunAfterJob",  runafter_cmd},
    {NULL,      NULL}                  /* list terminator */
 };
 
@@ -93,6 +98,8 @@ static char restorecmd[]  = "restore replace=%c prelinks=%d where=%s\n";
 static char restorecmd1[] = "restore replace=%c prelinks=%d where=\n";
 static char verifycmd[]   = "verify level=%30s\n";
 static char estimatecmd[] = "estimate listing=%d\n";
+static char runbefore[]   = "RunBeforeJob %s\n";
+static char runafter[]    = "RunAfterJob %s\n";
 
 /* Responses sent to Director */
 static char errmsg[]      = "2999 Invalid command\n";
@@ -111,6 +118,8 @@ static char OKjob[]       = "2000 OK Job " HOST_OS "," DISTNAME "," DISTVER;
 static char OKsetdebug[]  = "2000 OK setdebug=%d\n";
 static char BADjob[]      = "2901 Bad Job\n";
 static char EndJob[]      = "2800 End Job TermCode=%d JobFiles=%u ReadBytes=%s JobBytes=%s Errors=%u\n";
+static char OKRunBefore[] = "2000 OK RunBefore\n";
+static char OKRunAfter[]  = "2000 OK RunAfter\n";
 
 /* Responses received from Storage Daemon */
 static char OK_end[]       = "3000 OK end\n";
@@ -201,6 +210,10 @@ void *handle_client_request(void *dirp)
       bnet_sig(jcr->store_bsock, BNET_TERMINATE);
    }
 
+   if (jcr->RunAfterJob && !job_canceled(jcr)) {
+      run_cmd(jcr, jcr->RunAfterJob, "ClientRunAfterJob");
+   }
+
    /* Inform Director that we are done */
    bnet_sig(dir, BNET_TERMINATE);
 
@@ -323,6 +336,81 @@ static int job_cmd(JCR *jcr)
    return bnet_fsend(dir, OKjob);
 }
 
+static int runbefore_cmd(JCR *jcr)
+{
+   int stat;
+   BSOCK *dir = jcr->dir_bsock;
+   POOLMEM *cmd = get_memory(dir->msglen+1);
+
+   Dmsg1(100, "runbefore_cmd: %s", dir->msg);
+   if (sscanf(dir->msg, runbefore, cmd) != 1) {
+      pm_strcpy(&jcr->errmsg, dir->msg);
+      Jmsg1(jcr, M_FATAL, 0, _("Bad RunBeforeJob command: %s\n"), jcr->errmsg);
+      bnet_fsend(dir, "2905 Bad RunBeforeJob command.\n");
+      free_memory(cmd);
+      return 0;
+   }
+   unbash_spaces(cmd);
+
+   /* Run the command now */
+   stat = run_cmd(jcr, cmd, "ClientRunBeforeJob");
+   free_memory(cmd);
+   if (stat) {
+      bnet_fsend(dir, OKRunBefore);
+      return 1;
+   } else {
+      bnet_fsend(dir, "2905 Bad RunBeforeJob command.\n");
+      return 0;
+   }
+}
+
+static int runafter_cmd(JCR *jcr)
+{
+   BSOCK *dir = jcr->dir_bsock;
+   POOLMEM *msg = get_memory(dir->msglen+1);
+
+   Dmsg1(100, "runafter_cmd: %s", dir->msg);
+   if (sscanf(dir->msg, runafter, msg) != 1) {
+      pm_strcpy(&jcr->errmsg, dir->msg);
+      Jmsg1(jcr, M_FATAL, 0, _("Bad RunAfter command: %s\n"), jcr->errmsg);
+      bnet_fsend(dir, "2905 Bad RunAfterJob command.\n");
+      free_memory(msg);
+      return 0;
+   }
+   unbash_spaces(msg);
+   if (jcr->RunAfterJob) {
+      free_pool_memory(jcr->RunAfterJob);
+   }
+   jcr->RunAfterJob = get_pool_memory(PM_FNAME);
+   pm_strcpy(&jcr->RunAfterJob, msg);
+   free_pool_memory(msg);
+   return bnet_fsend(dir, OKRunAfter);
+}
+
+static int run_cmd(JCR *jcr, char *cmd, char *name)
+{
+   POOLMEM *ecmd = get_pool_memory(PM_FNAME);
+   int status;
+   BPIPE *bpipe;
+   char line[MAXSTRING];
+   
+   ecmd = edit_job_codes(jcr, ecmd, cmd, "");
+   bpipe = open_bpipe(ecmd, 0, "r");
+   free_pool_memory(ecmd);
+   while (fgets(line, sizeof(line), bpipe->rfd)) {
+      Jmsg(jcr, M_INFO, 0, _("%s: %s"), name, line);
+   }
+   status = close_bpipe(bpipe);
+   if (status != 0) {
+      Jmsg(jcr, M_FATAL, 0, _("%s returned non-zero status=%d\n"), name,
+        status);
+      set_jcr_job_status(jcr, JS_FatalError);
+      return 0;
+   }
+   return 1;
+}
+
+
 #define INC_LIST 0
 #define EXC_LIST 1
 
@@ -443,16 +531,16 @@ static int level_cmd(JCR *jcr)
    }
    /* Base backup requested? */
    if (strcmp(level, "base") == 0) {
-      jcr->save_level = L_BASE;
+      jcr->JobLevel = L_BASE;
    /* Full backup requested? */ 
    } else if (strcmp(level, "full") == 0) {
-      jcr->save_level = L_FULL;
+      jcr->JobLevel = L_FULL;
    /* 
     * Backup requested since <date> <time>
     *  This form is also used for incremental and differential
     */
    } else if (strcmp(level, "since") == 0) {
-      jcr->save_level = L_SINCE;
+      jcr->JobLevel = L_SINCE;
       if (sscanf(dir->msg, "level = since %d-%d-%d %d:%d:%d mtime_only=%d", 
                 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
                 &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &mtime_only) != 7) {
@@ -891,6 +979,9 @@ static void filed_free_jcr(JCR *jcr)
    if (jcr->last_fname) {
       free_pool_memory(jcr->last_fname);
    }
+   if (jcr->RunAfterJob) {
+      free_pool_memory(jcr->RunAfterJob);
+   }
    return;
 }
 
index f0e3e2cb3296909adf84b06de71071b18803b33a..e3e012b61cd80f8747cd63bf3cc9c45fde98b4d6 100644 (file)
@@ -174,7 +174,6 @@ struct JCR {
    int mtime_only;                    /* compare only mtime and not ctime as well */
    int listing;                       /* job listing in estimate */
    long Ticket;                       /* Ticket */
-   int save_level;                    /* save level */
    char *big_buf;                     /* I/O buffer */
    POOLMEM *compress_buf;             /* Compression buffer */
    int32_t compress_buf_size;         /* Length of compression buffer */
@@ -188,6 +187,7 @@ struct JCR {
    uint32_t EndBlock;
    pthread_t heartbeat_id;            /* id of heartbeat thread */
    volatile BSOCK *hb_bsock;          /* duped SD socket */
+   POOLMEM *RunAfterJob;              /* Command to run after job */
 #endif /* FILE_DAEMON */
 
 
index ea51399922a069d63129b19942a39069698b1403..1227d0a937e30272fa8ccf23372dd4d8ea1299f6 100644 (file)
@@ -41,7 +41,7 @@ struct res_items {
 /* For storing name_addr items in res_items table */
 #define ITEM(x) ((void **)&res_all.x)
 
-#define MAX_RES_ITEMS 32              /* maximum resource items per RES */
+#define MAX_RES_ITEMS 50              /* maximum resource items per RES */
 
 /* This is the universal header that is
  * at the beginning of every resource
index 072b4e4c5b35cf137452fa2c29ab102fce1321a8..7b2c5642fedf6c3558b903e648f9b367de405462 100644 (file)
@@ -749,7 +749,7 @@ static void testcmd()
            if (stat == 1) {
                Pmsg0(-1, "\n\nIt looks like the test worked this time, please add:\n\n"
                      "    Hardware End of Medium = No\n"
-                     "    BSR at EOM = yes\n\n"
+                     "    BSF at EOM = yes\n\n"
                      "to your Device resource in the Storage conf file.\n");
               goto all_done;
            }
index 69bcd2f10e035a3fcdb10e867a4c2cb17c3433e1..0f34138c30fc26406c197d73a4a4478734db05d5 100644 (file)
@@ -2,8 +2,8 @@
 #undef  VERSION
 #define VERSION "1.32"
 #define VSTRING "1"
-#define BDATE   "04 Sep 2003"
-#define LSMDATE "04Sep03"
+#define BDATE   "06 Sep 2003"
+#define LSMDATE "06Sep03"
 
 /* Debug flags */
 #undef  DEBUG