]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/fd_cmds.c
kes Simplify locking in the reservations system.
[bacula/bacula] / bacula / src / dird / fd_cmds.c
index dfc4cc11dbf8b39a4f865e508b7188429375a2f7..785d6794b8e1c16fd108aa06b01ae8cb15bbe219 100644 (file)
@@ -1,3 +1,30 @@
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+
+   The main author of Bacula is Kern Sibbald, with contributions from
+   many others, a complete list can be found in the file AUTHORS.
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version two of the GNU General Public
+   License as published by the Free Software Foundation plus additions
+   that are listed in the file LICENSE.
+
+   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 GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Bacula® is a registered trademark of John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
 /*
  *
  *   Bacula Director -- fd_cmds.c -- send commands to File daemon
  *
  *   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 "dird.h"
 
 /* Commands sent to File daemon */
 static char filesetcmd[]  = "fileset%s\n"; /* set full fileset */
-static char jobcmd[]      = "JobId=%d Job=%s SDid=%u SDtime=%u Authorization=%s\n";
+static char jobcmd[]      = "JobId=%s Job=%s SDid=%u SDtime=%u Authorization=%s\n";
 /* Note, mtime_only is not used here -- implemented as file option */
 static char levelcmd[]    = "level = %s%s mtime_only=%d\n";
-static char runbefore[]   = "RunBeforeJob %s\n";
-static char runafter[]    = "RunAfterJob %s\n";
-
+static char runscript[]   = "Run OnSuccess=%u OnFailure=%u AbortOnError=%u When=%u Command=%s\n";
+static char runbeforenow[]= "RunBeforeNow\n";
 
 /* Responses received from File daemon */
-static char OKinc[]       = "2000 OK include\n";
-static char OKjob[]       = "2000 OK Job";
-static char OKlevel[]     = "2000 OK level\n";
-static char OKRunBefore[] = "2000 OK RunBefore\n";
-static char OKRunAfter[]  = "2000 OK RunAfter\n";
+static char OKinc[]          = "2000 OK include\n";
+static char OKjob[]          = "2000 OK Job";
+static char OKlevel[]        = "2000 OK level\n";
+static char OKRunScript[]    = "2000 OK RunScript\n";
+static char OKRunBeforeNow[] = "2000 OK RunBeforeNow\n";
 
 /* Forward referenced functions */
 
 /* External functions */
-extern int debug_level;
 extern DIRRES *director;
 extern int FDConnectTimeout;
 
@@ -67,6 +78,7 @@ int connect_to_file_daemon(JCR *jcr, int retry_interval, int max_retry_time,
                            int verbose)
 {
    BSOCK   *fd;
+   char ed1[30];
 
    if (!jcr->file_bsock) {
       fd = bnet_connect(jcr, retry_interval, max_retry_time,
@@ -92,7 +104,7 @@ int connect_to_file_daemon(JCR *jcr, int retry_interval, int max_retry_time,
    /*
     * Now send JobId and authorization key
     */
-   bnet_fsend(fd, jobcmd, jcr->JobId, jcr->Job, jcr->VolSessionId,
+   bnet_fsend(fd, jobcmd, edit_int64(jcr->JobId, ed1), jcr->Job, jcr->VolSessionId,
       jcr->VolSessionTime, jcr->sd_auth_key);
    if (strcmp(jcr->sd_auth_key, "dummy") != 0) {
       memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
@@ -161,14 +173,14 @@ void get_level_since_time(JCR *jcr, char *since, int since_len)
       if (!db_find_job_start_time(jcr, jcr->db, &jcr->jr, &jcr->stime)) {
          /* No job found, so upgrade this one to Full */
          Jmsg(jcr, M_INFO, 0, "%s", db_strerror(jcr->db));
-         Jmsg(jcr, M_INFO, 0, _("No prior or suitable Full backup found. Doing FULL backup.\n"));
+         Jmsg(jcr, M_INFO, 0, _("No prior or suitable Full backup found in catalog. Doing FULL backup.\n"));
          bsnprintf(since, since_len, _(" (upgraded from %s)"),
             level_to_str(jcr->JobLevel));
          jcr->JobLevel = jcr->jr.JobLevel = L_FULL;
       } else {
          if (jcr->job->rerun_failed_levels) {
             if (db_find_failed_job_since(jcr, jcr->db, &jcr->jr, jcr->stime, JobLevel)) {
-               Jmsg(jcr, M_INFO, 0, _("Prior failed job found. Upgrading to %s.\n"),
+               Jmsg(jcr, M_INFO, 0, _("Prior failed job found in catalog. Upgrading to %s.\n"),
                   level_to_str(JobLevel));
                bsnprintf(since, since_len, _(" (upgraded from %s)"),
                   level_to_str(jcr->JobLevel));
@@ -193,7 +205,7 @@ static void send_since_time(JCR *jcr)
    char ed1[50];
 
    stime = str_to_utime(jcr->stime);
-   bnet_fsend(fd, levelcmd, _("since_utime "), edit_uint64(stime, ed1), 0);
+   bnet_fsend(fd, levelcmd, NT_("since_utime "), edit_uint64(stime, ed1), 0);
    while (bget_dirmsg(fd) >= 0) {  /* allow him to poll us to sync clocks */
       Jmsg(jcr, M_INFO, 0, "%s\n", fd->msg);
    }
@@ -243,7 +255,7 @@ bool send_level_command(JCR *jcr)
 /*
  * Send either an Included or an Excluded list to FD
  */
-static int send_fileset(JCR *jcr)
+static bool send_fileset(JCR *jcr)
 {
    FILESET *fileset = jcr->fileset;
    BSOCK   *fd = jcr->file_bsock;
@@ -275,6 +287,15 @@ static int send_fileset(JCR *jcr)
          for (j=0; j<ie->num_opts; j++) {
             FOPTS *fo = ie->opts_list[j];
             bnet_fsend(fd, "O %s\n", fo->opts);
+
+            bool enhanced_wild = false;
+            for (k=0; fo->opts[k]!='\0'; k++) {
+               if (fo->opts[k]=='W') {
+                  enhanced_wild = true;
+                  break;
+               }
+            }
+
             for (k=0; k<fo->regex.size(); k++) {
                bnet_fsend(fd, "R %s\n", fo->regex.get(k));
             }
@@ -293,12 +314,18 @@ static int send_fileset(JCR *jcr)
             for (k=0; k<fo->wildfile.size(); k++) {
                bnet_fsend(fd, "WF %s\n", fo->wildfile.get(k));
             }
+            for (k=0; k<fo->wildbase.size(); k++) {
+               bnet_fsend(fd, "W%c %s\n", enhanced_wild ? 'B' : 'F', fo->wildbase.get(k));
+            }
             for (k=0; k<fo->base.size(); k++) {
                bnet_fsend(fd, "B %s\n", fo->base.get(k));
             }
             for (k=0; k<fo->fstype.size(); k++) {
                bnet_fsend(fd, "X %s\n", fo->fstype.get(k));
             }
+            for (k=0; k<fo->drivetype.size(); k++) {
+               bnet_fsend(fd, "XD %s\n", fo->drivetype.get(k));
+            }
             if (fo->reader) {
                bnet_fsend(fd, "D %s\n", fo->reader);
             }
@@ -341,7 +368,7 @@ static int send_fileset(JCR *jcr)
                break;
             case '<':
                p++;                      /* skip over < */
-               if ((ffd = fopen(p, "r")) == NULL) {
+               if ((ffd = fopen(p, "rb")) == NULL) {
                   berrno be;
                   Jmsg(jcr, M_FATAL, 0, _("Cannot open included file: %s. ERR=%s\n"),
                      p, be.strerror());
@@ -385,11 +412,11 @@ static int send_fileset(JCR *jcr)
    if (!response(jcr, fd, OKinc, "Include", DISPLAY_ERROR)) {
       goto bail_out;
    }
-   return 1;
+   return true;
 
 bail_out:
    set_jcr_job_status(jcr, JS_ErrorTerminated);
-   return 0;
+   return false;
 
 }
 
@@ -435,7 +462,7 @@ bool send_bootstrap_file(JCR *jcr, BSOCK *sock)
    if (!jcr->RestoreBootstrap) {
       return true;
    }
-   bs = fopen(jcr->RestoreBootstrap, "r");
+   bs = fopen(jcr->RestoreBootstrap, "rb");
    if (!bs) {
       berrno be;
       Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
@@ -456,34 +483,99 @@ bool send_bootstrap_file(JCR *jcr, BSOCK *sock)
    return true;
 }
 
+/* TODO: drop this with runscript.old_proto in bacula 1.42 */
+static char runbefore[]   = "RunBeforeJob %s\n";
+static char runafter[]    = "RunAfterJob %s\n";
+static char OKRunBefore[] = "2000 OK RunBefore\n";
+static char OKRunAfter[]  = "2000 OK RunAfter\n";
+
+int send_runscript_with_old_proto(JCR *jcr, int when, POOLMEM *msg)
+{
+   int ret;
+   Dmsg1(120, "bdird: sending old runcommand to fd '%s'\n",msg);
+   if (when & SCRIPT_Before) {
+      bnet_fsend(jcr->file_bsock, runbefore, msg);
+      ret = response(jcr, jcr->file_bsock, OKRunBefore, "ClientRunBeforeJob", DISPLAY_ERROR);
+   } else {
+      bnet_fsend(jcr->file_bsock, runafter, msg);
+      ret = response(jcr, jcr->file_bsock, OKRunAfter, "ClientRunAfterJob", DISPLAY_ERROR);
+   }
+   return ret;
+} /* END OF TODO */
+
 /*
- * Send ClientRunBeforeJob and ClientRunAfterJob to File daemon
+ * Send RunScripts to File daemon
+ * 1) We send all runscript to FD, they can be executed Before, After, or twice
+ * 2) Then, we send a "RunBeforeNow" command to the FD to tell him to do the
+ *    first run_script() call. (ie ClientRunBeforeJob)
  */
-int send_run_before_and_after_commands(JCR *jcr)
+int send_runscripts_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;
+   RUNSCRIPT *cmd;
+   bool launch_before_cmd = false;
+   POOLMEM *ehost = get_pool_memory(PM_FNAME);
+   int result;
+
+   Dmsg0(120, "bdird: sending runscripts to fd\n");
+   
+   foreach_alist(cmd, jcr->job->RunScripts) {
+      
+      if (cmd->can_run_at_level(jcr->JobLevel) && cmd->target) {
+
+         ehost = edit_job_codes(jcr, ehost, cmd->target, "");
+         Dmsg2(200, "bdird: runscript %s -> %s\n", cmd->target, ehost);
+
+         if (strcmp(ehost, jcr->client->hdr.name) == 0) {
+            pm_strcpy(msg, cmd->command);
+            bash_spaces(msg);
+
+            Dmsg1(120, "bdird: sending runscripts to fd '%s'\n", cmd->command);
+            
+            /* TODO: remove this with bacula 1.42 */
+            if (cmd->old_proto) {
+               result = send_runscript_with_old_proto(jcr, cmd->when, msg);
+
+            } else {
+               bnet_fsend(fd, runscript, cmd->on_success, 
+                                         cmd->on_failure,
+                                         cmd->abort_on_error,
+                                         cmd->when,
+                                         msg);
+
+               result = response(jcr, fd, OKRunScript, "RunScript", DISPLAY_ERROR);
+               launch_before_cmd=true;
+            }
+            
+            if (!result) {
+               set_jcr_job_status(jcr, JS_ErrorTerminated);
+               free_pool_memory(msg);
+               free_pool_memory(ehost);
+               return 0;
+            }
+         }
+         /* TODO : we have to play with other client */
+        /*
+           else {
+           send command to an other client
+           }
+         */
+      }        
+   } 
+
+   /* We tell to the FD that i can execute commands (ie ClientRunBeforeJob) */
+   if (launch_before_cmd) {
+      bnet_fsend(fd, runbeforenow);
+      if (!response(jcr, fd, OKRunBeforeNow, "RunBeforeNow", DISPLAY_ERROR)) {
+        set_jcr_job_status(jcr, JS_ErrorTerminated);
+        free_pool_memory(msg);
+        free_pool_memory(ehost);
+        return 0;
       }
    }
    free_pool_memory(msg);
+   free_pool_memory(ehost);
    return 1;
 }