]> git.sur5r.net Git - bacula/bacula/commitdiff
- Move test for MaxStartDelay as suggested by Peter.
authorKern Sibbald <kern@sibbald.com>
Fri, 6 May 2005 15:54:59 +0000 (15:54 +0000)
committerKern Sibbald <kern@sibbald.com>
Fri, 6 May 2005 15:54:59 +0000 (15:54 +0000)
- Implement Python methods (I had to read the Python source
  code).
- Implement run() method in Director.
- Add Priority and Scheduled time to Job report.
- Add JobInit and JobRun events.
- Add Priority as Python read/write attribute to Job.
- Correct typo in bsmtp reported by Jo.

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1999 91ce42f0-d328-0410-95d8-f526ca767f89

12 files changed:
bacula/examples/python/DirStartUp.py
bacula/examples/python/FDStartUp.py
bacula/examples/python/SDStartUp.py
bacula/src/dird/backup.c
bacula/src/dird/job.c
bacula/src/dird/pythondir.c
bacula/src/filed/pythonfd.c
bacula/src/lib/pythonlib.c
bacula/src/stored/fd_cmds.c
bacula/src/stored/pythonsd.c
bacula/src/tools/bsmtp.c
bacula/src/version.h

index 37eaa28d5cf20a301dc95bc39cf58b8cfce0a53f..5a9942b66cbd85f5126944128ef197748b3d923e 100644 (file)
@@ -21,23 +21,18 @@ class BaculaEvents:
      """
      events = JobEvents()         # create instance of Job class
      events.job = job             # save Bacula's job pointer
-     job.set_events = events      # register events desired
+     job.set_events(events)       # register events desired
      sys.stderr = events          # send error output to Bacula
      sys.stdout = events          # send stdout to Bacula
      jobid = job.JobId; client = job.Client
      numvols = job.NumVols 
      job.JobReport="Python Dir JobStart: JobId=%d Client=%s NumVols=%d\n" % (jobid,client,numvols) 
-     return 1
 
   # Bacula Job is going to terminate
   def JobEnd(self, job):    
      jobid = job.JobId
      client = job.Client 
-     job.JobReport="Python Dir JobEnd output: JobId=%d Client=%s.\n" % (jobid, client) 
-     if (jobid < 2) :
-        startid = job.run("run kernsave")
-        print "Python started new Job: jobid=", startid
-     return 1
+     job.JobReport="Python Dir JobEnd output: JobId=%d Status=%s Client=%s.\n" % (jobid, job.JobStatus, client) 
 
   # Called here when the Bacula daemon is going to exit
   def Exit(self, job):
@@ -54,11 +49,20 @@ class JobEvents:
      # normally used
      noop = 1
 
+  def JobInit(self, job):
+     noop = 1
+     if (job.JobId < 2):
+        startid = job.run("run kernsave")
+        job.JobReport = "Python started new Job: jobid=%d\n" % startid
+
+  def JobRun(self, job):
+     noop = 1
+
   def NewVolume(self, job):
      jobid = job.JobId
      client = job.Client 
      numvol = job.NumVols;
-     print "JobId=%d Client=%s NumVols=%d" % (jobid, client, numvol)
+     job.JobReport = "JobId=%d Client=%s NumVols=%d" % (jobid, client, numvol)
      job.JobReport="Python before New Volume set for Job.\n"
      job.VolumeName="TestA-001"
      job.JobReport="Python after New Volume set for Job.\n"  
index d553f2cd9e511575bda1ce2498e0c0cb7d29156c..0c274c8c0fe668f19d761cb9cd5b92d1938fd83a 100644 (file)
@@ -20,7 +20,7 @@ class BaculaEvents:
      """
      events = JobEvents()         # create instance of Job class
      events.job = job             # save Bacula's job pointer
-     job.set_events = events      # register events desired
+     job.set_events(events)       # register events desired
      sys.stderr = events          # send error output to Bacula
      sys.stdout = events          # send stdout to Bacula
      jobid = job.JobId
@@ -33,7 +33,7 @@ class BaculaEvents:
      jobid = job.JobId
      client = job.Client 
      job.JobReport="Python FD JobEnd output: JobId=%d Client=%s.\n" % (jobid, client)
-     return 1
+     
 
   # Called here when the Bacula daemon is going to exit
   def Exit(self):
index ff6a97b2e54623f5dc3b23680440a1d3abf72f4e..8430e4f1ceec5f3ccc128f438973c4e30816a4bd 100644 (file)
@@ -20,7 +20,7 @@ class BaculaEvents:
      """
      events = JobEvents()         # create instance of Job class
      events.job = job             # save Bacula's job pointer
-     job.set_events = events      # register events desired
+     job.set_events(events)       # register events desired
      sys.stderr = events          # send error output to Bacula
      sys.stdout = events          # send stdout to Bacula
      jobid = job.JobId
@@ -33,8 +33,8 @@ class BaculaEvents:
      jobid = job.JobId
      client = job.Client 
      job.JobReport="Python SD JobEnd output: JobId=%d Client=%s.\n" % (jobid, client)
-     print "Python SD JobEnd\n"  
-     return 1
+#    print "Python SD JobEnd\n"  
+     
 
   # Called here when the Bacula daemon is going to exit
   def Exit(self):
index f2976ec9ece642d2f805a37932f557ad2accd63f..39f9ce56d5c4d5b61dd89a2b6c583cd48c4b4a49 100644 (file)
@@ -8,7 +8,7 @@
  *     Open DB and create records for this job.
  *     Open Message Channel with Storage daemon to tell him a job will be starting.
  *     Open connection with File daemon and pass him commands
- *      to do the backup.
+ *       to do the backup.
  *     When the File daemon finishes the job, update the DB.
  *
  *   Version $Id$
@@ -62,17 +62,17 @@ bool do_backup_init(JCR *jcr)
    switch (jcr->JobLevel) {
    case L_FULL:
       if (jcr->full_pool) {
-        jcr->pool = jcr->full_pool;
+         jcr->pool = jcr->full_pool;
       }
       break;
    case L_INCREMENTAL:
       if (jcr->inc_pool) {
-        jcr->pool = jcr->inc_pool;
+         jcr->pool = jcr->inc_pool;
       }
       break;
    case L_DIFFERENTIAL:
       if (jcr->dif_pool) {
-        jcr->pool = jcr->dif_pool;
+         jcr->pool = jcr->dif_pool;
       }
       break;
    }
@@ -83,18 +83,18 @@ bool do_backup_init(JCR *jcr)
       /* Try to create the pool */
       if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
          Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
-           db_strerror(jcr->db));
-        return false;
+            db_strerror(jcr->db));
+         return false;
       } else {
          Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
-        if (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
+         if (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
             Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
-              db_strerror(jcr->db));
-           return false;
-        }
+               db_strerror(jcr->db));
+            return false;
+         }
       }
    }
-   jcr->PoolId = pr.PoolId;              /****FIXME**** this can go away */
+   jcr->PoolId = pr.PoolId;               /****FIXME**** this can go away */
    jcr->jr.PoolId = pr.PoolId;
 
    if (!get_or_create_fileset_record(jcr, &fsr)) {
@@ -115,13 +115,13 @@ bool do_backup_init(JCR *jcr)
          cmd = edit_job_codes(jcr, cmd, runcmd, "");              
          Mmsg(ua->cmd, "run %s cloned=yes", cmd);
          Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
-        parse_ua_args(ua);                 /* parse command */
-        int stat = run_cmd(ua, ua->cmd);
-        if (stat == 0) {
+         parse_ua_args(ua);                 /* parse command */
+         int stat = run_cmd(ua, ua->cmd);
+         if (stat == 0) {
             Jmsg(jcr, M_ERROR, 0, _("Could not start clone job.\n"));
-        } else {
+         } else {
             Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
-        }
+         }
       }
       free_ua_context(ua);
       free_pool_memory(cmd);
@@ -134,7 +134,7 @@ bool do_backup_init(JCR *jcr)
  * Do a backup of the specified FileSet
  *
  *  Returns:  false on failure
- *           true  on success
+ *            true  on success
  */
 bool do_backup(JCR *jcr)
 {
@@ -146,7 +146,7 @@ bool do_backup(JCR *jcr)
 
    /* Print Job Start message */
    Jmsg(jcr, M_INFO, 0, _("Start Backup JobId %u, Job=%s\n"),
-       jcr->JobId, jcr->Job);
+        jcr->JobId, jcr->Job);
 
    set_jcr_job_status(jcr, JS_Running);
    Dmsg2(100, "JobId=%d JobLevel=%c\n", jcr->jr.JobId, jcr->jr.JobLevel);
@@ -215,15 +215,15 @@ bool do_backup(JCR *jcr)
    /* TLS Requirement */
    if (store->tls_enable) {
       if (store->tls_require) {
-        tls_need = BNET_TLS_REQUIRED;
+         tls_need = BNET_TLS_REQUIRED;
       } else {
-        tls_need = BNET_TLS_OK;
+         tls_need = BNET_TLS_OK;
       }
    }
 #endif
 
    bnet_fsend(fd, storaddr, store->address, store->SDDport,
-             tls_need);
+              tls_need);
    if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
       return false;
    }
@@ -244,7 +244,7 @@ bool do_backup(JCR *jcr)
    if (stat == JS_Terminated) {
       backup_cleanup(jcr, stat);
       return true;
-   }    
+   }     
    return false;
 }
 
@@ -267,21 +267,21 @@ int wait_for_job_termination(JCR *jcr)
    /* Wait for Client to terminate */
    while ((n = bget_dirmsg(fd)) >= 0) {
       if (!fd_ok && sscanf(fd->msg, EndJob, &jcr->FDJobStatus, &JobFiles,
-         &ReadBytes, &JobBytes, &Errors) == 5) {
-        fd_ok = true;
-        set_jcr_job_status(jcr, jcr->FDJobStatus);
+          &ReadBytes, &JobBytes, &Errors) == 5) {
+         fd_ok = true;
+         set_jcr_job_status(jcr, jcr->FDJobStatus);
          Dmsg1(100, "FDStatus=%c\n", (char)jcr->JobStatus);
       } else {
          Jmsg(jcr, M_WARNING, 0, _("Unexpected Client Job message: %s\n"),
-           fd->msg);
+            fd->msg);
       }
       if (job_canceled(jcr)) {
-        break;
+         break;
       }
    }
    if (is_bnet_error(fd)) {
       Jmsg(jcr, M_FATAL, 0, _("Network error with FD during %s: ERR=%s\n"),
-         job_type_to_str(jcr->JobType), bnet_strerror(fd));
+          job_type_to_str(jcr->JobType), bnet_strerror(fd));
    }
    bnet_sig(fd, BNET_TERMINATE);   /* tell Client we are terminating */
 
@@ -320,7 +320,7 @@ int wait_for_job_termination(JCR *jcr)
  */
 void backup_cleanup(JCR *jcr, int TermCode)
 {
-   char sdt[50], edt[50];
+   char sdt[50], edt[50], schedt[50];
    char ec1[30], ec2[30], ec3[30], ec4[30], ec5[30], compress[50];
    char term_code[100], fd_term_msg[100], sd_term_msg[100];
    const char *term_msg;
@@ -330,22 +330,22 @@ void backup_cleanup(JCR *jcr, int TermCode)
    utime_t RunTime;
 
    Dmsg2(100, "Enter backup_cleanup %d %c\n", TermCode, TermCode);
-   dequeue_messages(jcr);            /* display any queued messages */
+   dequeue_messages(jcr);             /* display any queued messages */
    memset(&mr, 0, sizeof(mr));
    set_jcr_job_status(jcr, TermCode);
 
-   update_job_end_record(jcr);       /* update database */
+   update_job_end_record(jcr);        /* update database */
 
    if (!db_get_job_record(jcr, jcr->db, &jcr->jr)) {
       Jmsg(jcr, M_WARNING, 0, _("Error getting job record for stats: %s"),
-        db_strerror(jcr->db));
+         db_strerror(jcr->db));
       set_jcr_job_status(jcr, JS_ErrorTerminated);
    }
 
    bstrncpy(mr.VolumeName, jcr->VolumeName, sizeof(mr.VolumeName));
    if (!db_get_media_record(jcr, jcr->db, &mr)) {
       Jmsg(jcr, M_WARNING, 0, _("Error getting Media record for Volume \"%s\": ERR=%s"),
-        mr.VolumeName, db_strerror(jcr->db));
+         mr.VolumeName, db_strerror(jcr->db));
       set_jcr_job_status(jcr, JS_ErrorTerminated);
    }
 
@@ -360,88 +360,89 @@ void backup_cleanup(JCR *jcr, int TermCode)
       int VolCount;
 
       if (*fname == '|') {
-        fname++;
-        got_pipe = 1;
+         fname++;
+         got_pipe = 1;
          bpipe = open_bpipe(fname, 0, "w");
-        fd = bpipe ? bpipe->wfd : NULL;
+         fd = bpipe ? bpipe->wfd : NULL;
       } else {
-        /* ***FIXME*** handle BASE */
+         /* ***FIXME*** handle BASE */
          fd = fopen(fname, jcr->JobLevel==L_FULL?"w+":"a+");
       }
       if (fd) {
-        VolCount = db_get_job_volume_parameters(jcr, jcr->db, jcr->JobId,
-                   &VolParams);
-        if (VolCount == 0) {
+         VolCount = db_get_job_volume_parameters(jcr, jcr->db, jcr->JobId,
+                    &VolParams);
+         if (VolCount == 0) {
             Jmsg(jcr, M_ERROR, 0, _("Could not get Job Volume Parameters to "
                  "update Bootstrap file. ERR=%s\n"), db_strerror(jcr->db));
-            if (jcr->SDJobFiles != 0) {
-               set_jcr_job_status(jcr, JS_ErrorTerminated);
-            }
+             if (jcr->SDJobFiles != 0) {
+                set_jcr_job_status(jcr, JS_ErrorTerminated);
+             }
 
-        }
-        for (int i=0; i < VolCount; i++) {
-           /* Write the record */
+         }
+         for (int i=0; i < VolCount; i++) {
+            /* Write the record */
             fprintf(fd, "Volume=\"%s\"\n", VolParams[i].VolumeName);
             fprintf(fd, "MediaType=\"%s\"\n", VolParams[i].MediaType);
             fprintf(fd, "VolSessionId=%u\n", jcr->VolSessionId);
             fprintf(fd, "VolSessionTime=%u\n", jcr->VolSessionTime);
             fprintf(fd, "VolFile=%u-%u\n", VolParams[i].StartFile,
-                        VolParams[i].EndFile);
+                         VolParams[i].EndFile);
             fprintf(fd, "VolBlock=%u-%u\n", VolParams[i].StartBlock,
-                        VolParams[i].EndBlock);
+                         VolParams[i].EndBlock);
             fprintf(fd, "FileIndex=%d-%d\n", VolParams[i].FirstIndex,
-                        VolParams[i].LastIndex);
-        }
-        if (VolParams) {
-           free(VolParams);
-        }
-        if (got_pipe) {
-           close_bpipe(bpipe);
-        } else {
-           fclose(fd);
-        }
+                         VolParams[i].LastIndex);
+         }
+         if (VolParams) {
+            free(VolParams);
+         }
+         if (got_pipe) {
+            close_bpipe(bpipe);
+         } else {
+            fclose(fd);
+         }
       } else {
-        berrno be;
+         berrno be;
          Jmsg(jcr, M_ERROR, 0, _("Could not open WriteBootstrap file:\n"
               "%s: ERR=%s\n"), fname, be.strerror());
-        set_jcr_job_status(jcr, JS_ErrorTerminated);
+         set_jcr_job_status(jcr, JS_ErrorTerminated);
       }
    }
 
-   msg_type = M_INFO;                /* by default INFO message */
+   msg_type = M_INFO;                 /* by default INFO message */
    switch (jcr->JobStatus) {
       case JS_Terminated:
-        if (jcr->Errors || jcr->SDErrors) {
+         if (jcr->Errors || jcr->SDErrors) {
             term_msg = _("Backup OK -- with warnings");
-        } else {
+         } else {
             term_msg = _("Backup OK");
-        }
-        break;
+         }
+         break;
       case JS_FatalError:
       case JS_ErrorTerminated:
          term_msg = _("*** Backup Error ***");
-        msg_type = M_ERROR;          /* Generate error message */
-        if (jcr->store_bsock) {
-           bnet_sig(jcr->store_bsock, BNET_TERMINATE);
-           if (jcr->SD_msg_chan) {
-              pthread_cancel(jcr->SD_msg_chan);
-           }
-        }
-        break;
+         msg_type = M_ERROR;          /* Generate error message */
+         if (jcr->store_bsock) {
+            bnet_sig(jcr->store_bsock, BNET_TERMINATE);
+            if (jcr->SD_msg_chan) {
+               pthread_cancel(jcr->SD_msg_chan);
+            }
+         }
+         break;
       case JS_Canceled:
          term_msg = _("Backup Canceled");
-        if (jcr->store_bsock) {
-           bnet_sig(jcr->store_bsock, BNET_TERMINATE);
-           if (jcr->SD_msg_chan) {
-              pthread_cancel(jcr->SD_msg_chan);
-           }
-        }
-        break;
+         if (jcr->store_bsock) {
+            bnet_sig(jcr->store_bsock, BNET_TERMINATE);
+            if (jcr->SD_msg_chan) {
+               pthread_cancel(jcr->SD_msg_chan);
+            }
+         }
+         break;
       default:
-        term_msg = term_code;
+         term_msg = term_code;
          sprintf(term_code, _("Inappropriate term code: %c\n"), jcr->JobStatus);
-        break;
+         break;
    }
+   bstrftimes(schedt, sizeof(schedt), jcr->jr.SchedTime);
    bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
    bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
    RunTime = jcr->jr.EndTime - jcr->jr.StartTime;
@@ -460,7 +461,7 @@ void backup_cleanup(JCR *jcr, int TermCode)
       if (jcr->JobStatus == JS_Terminated && jcr->jr.JobBytes) {
          Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
       }
-      jcr->VolumeName[0] = 0;        /* none */
+      jcr->VolumeName[0] = 0;         /* none */
    }
 
    if (jcr->ReadBytes == 0) {
@@ -476,7 +477,7 @@ void backup_cleanup(JCR *jcr, int TermCode)
    jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
    jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
 
-// bmicrosleep(15, 0);               /* for debugging SIGHUP */
+// bmicrosleep(15, 0);                /* for debugging SIGHUP */
 
    Jmsg(jcr, msg_type, 0, _("Bacula " VERSION " (" LSMDATE "): %s\n"
 "  JobId:                  %d\n"
@@ -486,8 +487,10 @@ void backup_cleanup(JCR *jcr, int TermCode)
 "  FileSet:                \"%s\" %s\n"
 "  Pool:                   \"%s\"\n"
 "  Storage:                \"%s\"\n"
+"  Scheduled time:         %s\n"
 "  Start time:             %s\n"
 "  End time:               %s\n"
+"  Priority:               %d\n"
 "  FD Files Written:       %s\n"
 "  SD Files Written:       %s\n"
 "  FD Bytes Written:       %s\n"
@@ -503,31 +506,33 @@ void backup_cleanup(JCR *jcr, int TermCode)
 "  FD termination status:  %s\n"
 "  SD termination status:  %s\n"
 "  Termination:            %s\n\n"),
-       edt,
-       jcr->jr.JobId,
-       jcr->jr.Job,
-       level_to_str(jcr->JobLevel), jcr->since,
-       jcr->client->hdr.name,
-       jcr->fileset->hdr.name, jcr->FSCreateTime,
-       jcr->pool->hdr.name,
-       jcr->store->hdr.name,
-       sdt,
-       edt,
-       edit_uint64_with_commas(jcr->jr.JobFiles, ec1),
-       edit_uint64_with_commas(jcr->SDJobFiles, ec4),
-       edit_uint64_with_commas(jcr->jr.JobBytes, ec2),
-       edit_uint64_with_commas(jcr->SDJobBytes, ec5),
-       (float)kbps,
-       compress,
-       jcr->VolumeName,
-       jcr->VolSessionId,
-       jcr->VolSessionTime,
-       edit_uint64_with_commas(mr.VolBytes, ec3),
-       jcr->Errors,
-       jcr->SDErrors,
-       fd_term_msg,
-       sd_term_msg,
-       term_msg);
+        edt,
+        jcr->jr.JobId,
+        jcr->jr.Job,
+        level_to_str(jcr->JobLevel), jcr->since,
+        jcr->client->hdr.name,
+        jcr->fileset->hdr.name, jcr->FSCreateTime,
+        jcr->pool->hdr.name,
+        jcr->store->hdr.name,
+        schedt,
+        sdt,
+        edt,
+        jcr->JobPriority,
+        edit_uint64_with_commas(jcr->jr.JobFiles, ec1),
+        edit_uint64_with_commas(jcr->SDJobFiles, ec4),
+        edit_uint64_with_commas(jcr->jr.JobBytes, ec2),
+        edit_uint64_with_commas(jcr->SDJobBytes, ec5),
+        (float)kbps,
+        compress,
+        jcr->VolumeName,
+        jcr->VolSessionId,
+        jcr->VolSessionTime,
+        edit_uint64_with_commas(mr.VolBytes, ec3),
+        jcr->Errors,
+        jcr->SDErrors,
+        fd_term_msg,
+        sd_term_msg,
+        term_msg);
 
    Dmsg0(100, "Leave backup_cleanup()\n");
 }
index f8bad7653eb60b6b834a60b7b98ecf466b432f5f..5f5de77d8d039d09a4243da6b93fe35f8dd36673 100644 (file)
@@ -151,7 +151,6 @@ JobId_t run_job(JCR *jcr)
    return JobId;
 
 bail_out:
-   generate_daemon_event(jcr, "JobEnd");
    if (jcr->fname) {
       free_memory(jcr->fname);
       jcr->fname = NULL;
@@ -178,7 +177,21 @@ static void *job_thread(void *arg)
    Dmsg0(200, "=====Start Job=========\n");
    jcr->start_time = time(NULL);      /* set the real start time */
    jcr->jr.StartTime = jcr->start_time;
-   set_jcr_job_status(jcr, JS_Running);
+
+   if (jcr->job->MaxStartDelay != 0 && jcr->job->MaxStartDelay <
+       (utime_t)(jcr->start_time - jcr->sched_time)) {
+      Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n"));
+      set_jcr_job_status(jcr, JS_Canceled);
+   }
+
+   /*                                
+    * Note, we continue, even if the job is canceled above. This
+    *  will permit proper setting of the job start record and
+    *  the error (cancel) will be picked up below.
+    */
+
+   generate_job_event(jcr, "JobInit");
+   set_jcr_job_status(jcr, JS_Running);   /* this will be set only if no error */
 
    if (!jcr->fname) {
       jcr->fname = get_pool_memory(PM_FNAME);
@@ -230,12 +243,6 @@ static void *job_thread(void *arg)
    if (job_canceled(jcr)) {
       update_job_end_record(jcr);
 
-   } else if (jcr->job->MaxStartDelay != 0 && jcr->job->MaxStartDelay <
-       (utime_t)(jcr->start_time - jcr->sched_time)) {
-      Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n"));
-      set_jcr_job_status(jcr, JS_Canceled);
-      update_job_end_record(jcr);
-
    } else {
 
       /* Run Job */
@@ -260,6 +267,9 @@ static void *job_thread(void *arg)
             goto bail_out;
          }
       }
+
+      generate_job_event(jcr, "JobRun");
+
       switch (jcr->JobType) {
       case JT_BACKUP:
          if (do_backup(jcr)) {
@@ -338,6 +348,7 @@ static void *job_thread(void *arg)
          dequeue_messages(jcr);
       }
    }
+
 bail_out:
    generate_daemon_event(jcr, "JobEnd");
    Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus);
@@ -357,6 +368,8 @@ int cancel_job(UAContext *ua, JCR *jcr)
 {
    BSOCK *sd, *fd;
 
+   set_jcr_job_status(jcr, JS_Canceled);
+
    switch (jcr->JobStatus) {
    case JS_Created:
    case JS_WaitJobRes:
@@ -365,14 +378,12 @@ int cancel_job(UAContext *ua, JCR *jcr)
    case JS_WaitPriority:
    case JS_WaitMaxJobs:
    case JS_WaitStartTime:
-      set_jcr_job_status(jcr, JS_Canceled);
       bsendmsg(ua, _("JobId %d, Job %s marked to be canceled.\n"),
               jcr->JobId, jcr->Job);
       jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */
       return 1;
 
    default:
-      set_jcr_job_status(jcr, JS_Canceled);
 
       /* Cancel File daemon */
       if (jcr->file_bsock) {
index 4ab14fb7856269d51a4454967fef7a4c6ac05da0..a3452fd1159475e3e44230e2cf852f4c67053b05 100644 (file)
@@ -40,22 +40,16 @@ extern PyObject *find_method(PyObject *eventsObject, PyObject *method,
          const char *name);
 
 
-static int set_job_events(PyObject *self, PyObject *arg);
-static int job_run(PyObject *self, PyObject *arg);
+static PyObject *set_job_events(PyObject *self, PyObject *arg);
+static PyObject *job_run(PyObject *self, PyObject *arg);
+static PyObject *job_write(PyObject *self, PyObject *arg);
 
-#ifdef needed
-static PyObject *set_bacula_job_events(PyObject *self, PyObject *arg)
-{
-   Dmsg2(000, "In set_bacula_job_events self=%p arg=%p\n",
-      self, arg);
-   Py_INCREF(Py_None);
-   return Py_None;
-}
 PyMethodDef JobMethods[] = {
-    {"set_events", set_bacula_job_events, METH_VARARGS, "Define Bacula events."},
+    {"set_events", set_job_events, METH_VARARGS, "Set Job events"},
+    {"run", job_run, METH_VARARGS, "Run a Job"},
+    {"write", job_write, METH_VARARGS, "Write to output"},
     {NULL, NULL, 0, NULL}             /* last item */
 };
-#endif
  
 
 struct s_vars {
@@ -78,17 +72,16 @@ static struct s_vars getvars[] = {
    { N_("MediaType"),  "s"},
    { N_("JobName"),    "s"},
    { N_("JobStatus"),  "s"},
+   { N_("Priority"),   "i"},
 
    { NULL,             NULL}
 };
 
 /* Writable variables */
 static struct s_vars setvars[] = {
-   { N_("set_events"), NULL},
-   { N_("run"),        NULL},
    { N_("JobReport"),   "s"},
-   { N_("write"),       "s"},
-   { N_("VolumeName") , "s"},
+   { N_("VolumeName"),  "s"},
+   { N_("Priority"),    "i"},
 
    { NULL,             NULL}
 };
@@ -119,7 +112,8 @@ PyObject *job_getattr(PyObject *self, char *attrname)
       }
    }
    if (!found) {
-      goto not_found;
+      /* Try our methods */
+      return Py_FindMethod(JobMethods, self, attrname);
    }
    switch (i) {
    case 0:                            /* Job */
@@ -150,8 +144,9 @@ PyObject *job_getattr(PyObject *self, char *attrname)
       buf[1] = 0;
       buf[0] = jcr->JobStatus;
       return Py_BuildValue(getvars[i].fmt, buf);
+   case 13:                           /* Priority */
+      return Py_BuildValue(getvars[i].fmt, jcr->JobPriority);
    }
-not_found:
    bsnprintf(errmsg, sizeof(errmsg), "Attribute %s not found.", attrname);
 bail_out:
    PyErr_SetString(PyExc_AttributeError, errmsg);
@@ -168,6 +163,7 @@ int job_setattr(PyObject *self, char *attrname, PyObject *value)
    JCR *jcr;
    bool found = false;
    char *strval = NULL;
+   int intval = 0;
    int i;
 
    Dmsg2(100, "In job_setattr=%s val=%p.\n", attrname, value);
@@ -189,23 +185,28 @@ int job_setattr(PyObject *self, char *attrname, PyObject *value)
    if (!found) {
       goto bail_out;
    }
-   /* Get argument value ***FIXME*** handle other formats */
+   /* Get argument value */
    if (setvars[i].fmt != NULL) {
-      if (!PyArg_Parse(value, setvars[i].fmt, &strval)) {
-         PyErr_SetString(PyExc_TypeError, "Read-only attribute");
-         return -1;
+      switch (setvars[i].fmt[0]) {
+      case 's':
+         if (!PyArg_Parse(value, setvars[i].fmt, &strval)) {
+            PyErr_SetString(PyExc_TypeError, "Read-only attribute");
+            return -1;
+         }
+         break;
+      case 'i':
+         if (!PyArg_Parse(value, setvars[i].fmt, &intval)) {
+            PyErr_SetString(PyExc_TypeError, "Read-only attribute");
+            return -1;
+         }
+         break;
       }
    }   
    switch (i) {
-   case 0:                            /* set_events */
-      return set_job_events(self, value);
-   case 1:                            /* run */
-      return job_run(self, value);
-   case 2:                            /* JobReport */
-   case 3:                            /* write */
+   case 0:                            /* JobReport */
       Jmsg(jcr, M_INFO, 0, "%s", strval);
       return 0;
-   case 4:                            /* VolumeName */
+   case 1:                            /* VolumeName */
       /* Make sure VolumeName is valid and we are in VolumeName event */
       if (strcmp("NewVolume", jcr->event) == 0 &&
           is_volume_name_legal(NULL, strval)) {
@@ -215,49 +216,48 @@ int job_setattr(PyObject *self, char *attrname, PyObject *value)
       } else {
          jcr->VolumeName[0] = 0;
       }
+      break;
+   case 2:                            /* Priority */
+      Dmsg1(000, "Set priority=%d\n", intval);
+      return 0;
    }
 bail_out:
    PyErr_SetString(PyExc_AttributeError, attrname);
    return -1;
 }
 
-#ifdef needed
-static PyObject *set_bacula_job_events(PyObject *self, PyObject *arg)
-{
-   Dmsg2(000, "In set_bacula_job_events self=%p arg=%p\n",
-      self, arg);
-   Py_INCREF(Py_None);
-   return Py_None;
-}
-#endif
 
-
-static int set_job_events(PyObject *self, PyObject *arg)
+static PyObject *set_job_events(PyObject *self, PyObject *arg)
 {
    PyObject *eObject;
    JCR *jcr;
 
    Dmsg0(100, "In set_job_events.\n");
-   if (!PyArg_Parse(arg, "O", &eObject)) {
-      return -1;
+   if (!PyArg_ParseTuple(arg, "O:set_events", &eObject)) {
+      Dmsg0(000, "Error in ParseTuple\n");
+      return NULL;
    }
    jcr = get_jcr_from_PyObject(self);
    Py_XDECREF((PyObject *)jcr->Python_events);
    Py_INCREF(eObject);
    jcr->Python_events = (void *)eObject;
-   return 0;                    /* good return */
+   Py_INCREF(Py_None);
+   return Py_None;
 }
 
 /* Run a Bacula command */
-static int job_run(PyObject *self, PyObject *arg)
+static PyObject *job_run(PyObject *self, PyObject *arg)
 {
    JCR *jcr;
    char *item;
    int stat;
 
-   if (!PyArg_Parse(arg, "s", &item)) {
-      return -1;
+   if (!PyArg_ParseTuple(arg, "s:run", &item)) {
+      Dmsg0(000, "Error in ParseTuple\n");
+      return NULL;
    }
+   /* Release lock due to recursion */
+   PyEval_ReleaseLock();
    jcr = get_jcr_from_PyObject(self);
    UAContext *ua = new_ua_context(jcr);
    ua->batch = true;
@@ -265,25 +265,45 @@ static int job_run(PyObject *self, PyObject *arg)
    parse_ua_args(ua);                 /* parse command */
    stat = run_cmd(ua, ua->cmd);
    free_ua_context(ua);
-   /* ***FIXME*** check stat */
-   return 0;
+   PyEval_AcquireLock();
+   return PyInt_FromLong((long)stat);
+}
+
+static PyObject *job_write(PyObject *self, PyObject *args)
+{
+   char *text = NULL;
+
+   if (!PyArg_ParseTuple(args, "s:write", &text)) {
+      Dmsg0(000, "Parse tuple error in job_write\n");
+      return NULL;
+   }
+   if (text) {
+      Jmsg(NULL, M_INFO, 0, "%s", text);
+   }
+   Py_INCREF(Py_None);
+   return Py_None;
 }
 
 
+/*
+ * Generate a Job event, which means look up the event
+ *  method defined by the user, and if it exists, 
+ *  call it.
+ */
 int generate_job_event(JCR *jcr, const char *event)
 {
    PyObject *method = NULL;
    PyObject *Job = (PyObject *)jcr->Python_job;
+   PyObject *events = (PyObject *)jcr->Python_events;
    PyObject *result = NULL;
    int stat = 0;
 
-   if (!Job) {
+   if (!Job || !events) {
       return 0;
    }
 
    PyEval_AcquireLock();
 
-   PyObject *events = (PyObject *)jcr->Python_events;
    method = find_method(events, method, event);
    if (!method) {
       goto bail_out;
index acb70906bdba794766cffe3ef24c9a3b1fdfabb5..bf2646973d84643f22b64a2f1673a406cf391b4f 100644 (file)
@@ -47,7 +47,15 @@ extern PyObject *find_method(PyObject *eventsObject, PyObject *method,
           const char *name);
 
 /* Forward referenced functions */
-static int set_job_events(PyObject *self, PyObject *arg);
+static PyObject *set_job_events(PyObject *self, PyObject *arg);
+static PyObject *job_write(PyObject *self, PyObject *arg);
+
+PyMethodDef JobMethods[] = {
+    {"set_events", set_job_events, METH_VARARGS, "Set Job events"},
+    {"write", job_write, METH_VARARGS, "Write to output"},
+    {NULL, NULL, 0, NULL}             /* last item */
+};
+
 
 bool my_python_set_prog(JCR *jcr, const char *prog);
 int my_python_open(BFILE *bfd, const char *fname, int flags, mode_t mode);
@@ -75,9 +83,7 @@ static struct s_vars getvars[] = {
 
 /* Writable variables */
 static struct s_vars setvars[] = {
-   { N_("set_events"), NULL},
    { N_("JobReport"),   "s"},
-   { N_("write"),       "s"},
 
    { NULL,             NULL}
 };
@@ -103,7 +109,8 @@ PyObject *job_getattr(PyObject *self, char *attrname)
       }
    }
    if (!found) {
-      goto not_found;
+      /* Try our methods */
+      return Py_FindMethod(JobMethods, self, attrname);
    }
    switch (i) {
    case 0:                            /* FD's name */
@@ -123,7 +130,6 @@ PyObject *job_getattr(PyObject *self, char *attrname)
       buf[0] = jcr->JobStatus;
       return Py_BuildValue(getvars[i].fmt, buf);
    }
-not_found:
    bsnprintf(errmsg, sizeof(errmsg), "Attribute %s not found.", attrname);
 bail_out:
    PyErr_SetString(PyExc_AttributeError, errmsg);
@@ -171,10 +177,7 @@ int job_setattr(PyObject *self, char *attrname, PyObject *value)
       }
    }   
    switch (i) {
-   case 0:                            /* set_events */
-      return set_job_events(self, value);
-   case 1:                            /* JobReport */
-   case 2:                            /* write */
+   case 0:                            /* JobReport */
       Jmsg(jcr, M_INFO, 0, "%s", strval);
       return 0;
    }
@@ -186,21 +189,36 @@ bail_out:
 }
 
 
+static PyObject *job_write(PyObject *self, PyObject *args)
+{
+   char *text = NULL;
+
+   if (!PyArg_ParseTuple(args, "s:write", &text)) {
+      Dmsg0(000, "Parse tuple error in job_write\n");
+      return NULL;
+   }
+   if (text) {
+      Jmsg(NULL, M_INFO, 0, "%s", text);
+   }
+   Py_INCREF(Py_None);
+   return Py_None;
+}
+
 
-static int set_job_events(PyObject *self, PyObject *arg)
+static PyObject *set_job_events(PyObject *self, PyObject *arg)
 {
    PyObject *eObject;
    JCR *jcr;
 
    Dmsg0(100, "In set_job_events.\n");
-   if (!PyArg_Parse(arg, "O", &eObject)) {
+   if (!PyArg_ParseTuple(arg, "O", &eObject)) {
       Dmsg0(000, "Parse error looking for Object argument\n");
-      return -1;
+      return NULL;
    }
    jcr = get_jcr_from_PyObject(self);
    if (!jcr) {
       PyErr_SetString(PyExc_AttributeError, "Job pointer not found.");
-      return -1;
+      return NULL;
    }
    Py_XDECREF((PyObject *)jcr->Python_events);  /* release any old events Object */
    Py_INCREF(eObject);
@@ -212,7 +230,8 @@ static int set_job_events(PyObject *self, PyObject *arg)
    python_close    = my_python_close;
    python_read     = my_python_read;
 
-   return 0;
+   Py_INCREF(Py_None);
+   return Py_None;
 }
 
 
@@ -220,16 +239,16 @@ int generate_job_event(JCR *jcr, const char *event)
 {
    PyObject *method = NULL;
    PyObject *Job = (PyObject *)jcr->Python_job;
+   PyObject *events = (PyObject *)jcr->Python_events;
    PyObject *result = NULL;
    int stat = 0;
 
-   if (!Job) {
+   if (!Job || !events) {
       return 0;
    }
 
    PyEval_AcquireLock();
 
-   PyObject *events = (PyObject *)jcr->Python_events;
    method = find_method(events, method, event);
    if (!method) {
       goto bail_out;
index 5af7ff6a0a9ba5e6825fb7e4dda73e1b117b399f..cbfe67bd4224354f0266ee31b24602049469fd8b 100644 (file)
@@ -250,8 +250,7 @@ int generate_daemon_event(JCR *jcr, const char *event)
 
    } else if (strcmp(event, "JobEnd") == 0) {
       if (!JobEnd_method || !jcr->Python_job) {
-         Dmsg2(000, "No JobEnd method=%p Job=%p\n", JobEnd_method, jcr->Python_job);
-         stat = 0;
+         stat = 0;                    /* probably already here */
          goto bail_out;
       }
       bstrncpy(jcr->event, event, sizeof(jcr->event));
index 71a75615cd94f4a122ce70311531927894b8cddb..330ee30b9a15910c51f800c1e4d6ffc9a743ff5b 100644 (file)
@@ -74,7 +74,7 @@ static struct s_cmds fd_cmds[] = {
    {"read data",    read_data_cmd},
    {"read close",   read_close_session},
    {"bootstrap",    bootstrap_cmd},
-   {NULL,          NULL}                  /* list terminator */
+   {NULL,           NULL}                  /* list terminator */
 };
 
 /* Commands from the File daemon that require additional scanning */
@@ -93,7 +93,7 @@ static char ERROR_bootstrap[] = "3904 Error bootstrap\n";
 
 /* Information sent to the Director */
 static char Job_start[] = "3010 Job %s start\n";
-static char Job_end[]  =
+static char Job_end[]   =
    "3099 Job %s end JobStatus=%d JobFiles=%d JobBytes=%s\n";
 
 /*
@@ -120,43 +120,44 @@ void run_job(JCR *jcr)
    jcr->start_time = time(NULL);
    jcr->run_time = jcr->start_time;
    set_jcr_job_status(jcr, JS_Running);
-   dir_send_job_status(jcr);         /* update director */
+   dir_send_job_status(jcr);          /* update director */
    for (quit=false; !quit;) {
       int stat;
 
       /* Read command coming from the File daemon */
       stat = bnet_recv(fd);
-      if (is_bnet_stop(fd)) {        /* hardeof or error */
-        break;                       /* connection terminated */
+      if (is_bnet_stop(fd)) {         /* hardeof or error */
+         break;                       /* connection terminated */
       }
       if (stat <= 0) {
-        continue;                    /* ignore signals and zero length msgs */
+         continue;                    /* ignore signals and zero length msgs */
       }
       Dmsg1(110, "<filed: %s", fd->msg);
       found = false;
       for (i=0; fd_cmds[i].cmd; i++) {
-        if (strncmp(fd_cmds[i].cmd, fd->msg, strlen(fd_cmds[i].cmd)) == 0) {
-           found = true;               /* indicate command found */
-           if (!fd_cmds[i].func(jcr)) {    /* do command */
-              set_jcr_job_status(jcr, JS_ErrorTerminated);
-              quit = true;
-           }
-           break;
-        }
+         if (strncmp(fd_cmds[i].cmd, fd->msg, strlen(fd_cmds[i].cmd)) == 0) {
+            found = true;               /* indicate command found */
+            if (!fd_cmds[i].func(jcr)) {    /* do command */
+               set_jcr_job_status(jcr, JS_ErrorTerminated);
+               quit = true;
+            }
+            break;
+         }
       }
-      if (!found) {                  /* command not found */
+      if (!found) {                   /* command not found */
          Dmsg1(110, "<filed: Command not found: %s\n", fd->msg);
-        bnet_fsend(fd, ferrmsg);
-        break;
+         bnet_fsend(fd, ferrmsg);
+         break;
       }
    }
    bnet_sig(fd, BNET_TERMINATE);      /* signal to FD job is done */
    jcr->end_time = time(NULL);
-   dequeue_messages(jcr);            /* send any queued messages */
+   dequeue_messages(jcr);             /* send any queued messages */
    set_jcr_job_status(jcr, JS_Terminated);
+   generate_daemon_event(jcr, "JobEnd");
    bnet_fsend(dir, Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles,
       edit_uint64(jcr->JobBytes, ec1));
-   bnet_sig(dir, BNET_EOD);          /* send EOD to Director daemon */
+   bnet_sig(dir, BNET_EOD);           /* send EOD to Director daemon */
    return;
 }
 
@@ -175,10 +176,10 @@ static bool append_data_cmd(JCR *jcr)
       Dmsg1(110, "<bfiled: %s", fd->msg);
       jcr->JobType = JT_BACKUP;
       if (do_append_data(jcr)) {
-        return bnet_fsend(fd, OK_append);
+         return bnet_fsend(fd, OK_append);
       } else {
-        bnet_suppress_error_messages(fd, 1); /* ignore errors at this point */
-        bnet_fsend(fd, ERROR_append);
+         bnet_suppress_error_messages(fd, 1); /* ignore errors at this point */
+         bnet_fsend(fd, ERROR_append);
       }
    } else {
       bnet_fsend(fd, NOT_opened);
@@ -225,8 +226,8 @@ static bool append_open_session(JCR *jcr)
 
 /*
  *   Append Close session command
- *     Close the append session and send back Statistics
- *        (need to fix statistics)
+ *      Close the append session and send back Statistics
+ *         (need to fix statistics)
  */
 static bool append_close_session(JCR *jcr)
 {
@@ -241,7 +242,7 @@ static bool append_close_session(JCR *jcr)
    bnet_fsend(fd, OK_close, jcr->JobStatus);
    Dmsg1(120, ">filed: %s", fd->msg);
 
-   bnet_sig(fd, BNET_EOD);           /* send EOD to File daemon */
+   bnet_sig(fd, BNET_EOD);            /* send EOD to File daemon */
 
    jcr->session_opened = false;
    return true;
@@ -284,18 +285,18 @@ static bool read_open_session(JCR *jcr)
    }
 
    if (sscanf(fd->msg, read_open, jcr->dcr->VolumeName, &jcr->read_VolSessionId,
-        &jcr->read_VolSessionTime, &jcr->read_StartFile, &jcr->read_EndFile,
-        &jcr->read_StartBlock, &jcr->read_EndBlock) == 7) {
+         &jcr->read_VolSessionTime, &jcr->read_StartFile, &jcr->read_EndFile,
+         &jcr->read_StartBlock, &jcr->read_EndBlock) == 7) {
       if (jcr->session_opened) {
-        bnet_fsend(fd, NOT_opened);
-        return false;
+         bnet_fsend(fd, NOT_opened);
+         return false;
       }
       Dmsg4(100, "read_open_session got: JobId=%d Vol=%s VolSessId=%ld VolSessT=%ld\n",
-        jcr->JobId, jcr->dcr->VolumeName, jcr->read_VolSessionId,
-        jcr->read_VolSessionTime);
+         jcr->JobId, jcr->dcr->VolumeName, jcr->read_VolSessionId,
+         jcr->read_VolSessionTime);
       Dmsg4(100, "  StartF=%ld EndF=%ld StartB=%ld EndB=%ld\n",
-        jcr->read_StartFile, jcr->read_EndFile, jcr->read_StartBlock,
-        jcr->read_EndBlock);
+         jcr->read_StartFile, jcr->read_EndFile, jcr->read_StartBlock,
+         jcr->read_EndBlock);
    }
 
    jcr->session_opened = true;
@@ -326,7 +327,7 @@ bool bootstrap_cmd(JCR *jcr)
    bs = fopen(fname, "a+");           /* create file */
    if (!bs) {
       Jmsg(jcr, M_FATAL, 0, _("Could not create bootstrap file %s: ERR=%s\n"),
-        jcr->RestoreBootstrap, strerror(errno));
+         jcr->RestoreBootstrap, strerror(errno));
       goto bail_out;
    }
    while (bnet_recv(fd) >= 0) {
@@ -358,7 +359,7 @@ bail_out:
 
 /*
  *   Read Close session command
- *     Close the read session
+ *      Close the read session
  */
 static bool read_close_session(JCR *jcr)
 {
@@ -373,7 +374,7 @@ static bool read_close_session(JCR *jcr)
    bnet_fsend(fd, OK_close);
    Dmsg1(160, ">filed: %s\n", fd->msg);
 
-   bnet_sig(fd, BNET_EOD);         /* send EOD to File daemon */
+   bnet_sig(fd, BNET_EOD);          /* send EOD to File daemon */
 
    jcr->session_opened = false;
    return true;
index 85ca46ed2e741a8e180b20a149847e4d6f98c18c..40b21880e6818fbc583b885ed825b8113b66e1e2 100644 (file)
@@ -39,7 +39,14 @@ extern JCR *get_jcr_from_PyObject(PyObject *self);
 extern PyObject *find_method(PyObject *eventsObject, PyObject *method, 
          const char *name);
 
-static int set_job_events(PyObject *self, PyObject *arg);
+static PyObject *set_job_events(PyObject *self, PyObject *arg);
+static PyObject *job_write(PyObject *self, PyObject *arg);
+
+PyMethodDef JobMethods[] = {
+    {"set_events", set_job_events, METH_VARARGS, "Set Job events"},
+    {"write", job_write, METH_VARARGS, "Write to output"},
+    {NULL, NULL, 0, NULL}             /* last item */
+};
 
 
 struct s_vars {
@@ -67,9 +74,7 @@ static struct s_vars getvars[] = {
 
 /* Writable variables */
 static struct s_vars setvars[] = {
-   { N_("set_events"), NULL},
    { N_("JobReport"),   "s"},
-   { N_("write"),       "s"},
 
    { NULL,             NULL}
 };
@@ -98,7 +103,8 @@ PyObject *job_getattr(PyObject *self, char *attrname)
       }
    }
    if (!found) {
-      goto not_found;
+      /* Try our methods */
+      return Py_FindMethod(JobMethods, self, attrname);
    }  
    switch (i) {
    case 0:                            /* Job */
@@ -128,7 +134,6 @@ PyObject *job_getattr(PyObject *self, char *attrname)
    case 11:
       return Py_BuildValue(getvars[i].fmt, jcr->dcr->dev_name);
    }
-not_found:
    bsnprintf(errmsg, sizeof(errmsg), "Attribute %s not found.", attrname);
 bail_out:
    PyErr_SetString(PyExc_AttributeError, errmsg);
@@ -174,10 +179,7 @@ int job_setattr(PyObject *self, char *attrname, PyObject *value)
       }
    }   
    switch (i) {
-   case 0:                            /* set_events */
-      return set_job_events(self, value);
-   case 1:                            /* JobReport */
-   case 2:                            /* write */
+   case 0:                            /* JobReport */
       Jmsg(jcr, M_INFO, 0, "%s", strval);
       return 0;
    }
@@ -190,26 +192,37 @@ bail_out:
 }
 
 
-static int set_job_events(PyObject *self, PyObject *arg)
+static PyObject *set_job_events(PyObject *self, PyObject *arg)
 {
    PyObject *eObject;
    JCR *jcr;
 
    Dmsg0(100, "In set_job_events.\n");
-   if (!PyArg_Parse(arg, "O", &eObject)) {
-      Dmsg0(000, "Parse error looking for Object argument\n");
-      return -1;
+   if (!PyArg_ParseTuple(arg, "O:set_events", &eObject)) {
+      Dmsg0(000, "Error in ParseTuple\n");
+      return NULL;
    }
    jcr = get_jcr_from_PyObject(self);
-   if (!jcr) {
-      PyErr_SetString(PyExc_AttributeError, "Job pointer not found.");
-      return -1;
-   }
-   Py_XDECREF((PyObject *)jcr->Python_events);  /* release any old events Object */
+   Py_XDECREF((PyObject *)jcr->Python_events);
    Py_INCREF(eObject);
-   jcr->Python_events = (void *)eObject;        /* set new events */
+   jcr->Python_events = (void *)eObject;
+   Py_INCREF(Py_None);
+   return Py_None;
+}
 
-   return 0;
+static PyObject *job_write(PyObject *self, PyObject *args)
+{
+   char *text = NULL;
+
+   if (!PyArg_ParseTuple(args, "s:write", &text)) {
+      Dmsg0(000, "Parse tuple error in job_write\n");
+      return NULL;
+   }
+   if (text) {
+      Jmsg(NULL, M_INFO, 0, "%s", text);
+   }
+   Py_INCREF(Py_None);
+   return Py_None;
 }
 
 
@@ -217,16 +230,16 @@ int generate_job_event(JCR *jcr, const char *event)
 {
    PyObject *method = NULL;
    PyObject *Job = (PyObject *)jcr->Python_job;
+   PyObject *events = (PyObject *)jcr->Python_events;
    PyObject *result = NULL;
    int stat = 0;
 
-   if (!Job) {
+   if (!Job || !events) {
       return 0;
    }
 
    PyEval_AcquireLock();
 
-   PyObject *events = (PyObject *)jcr->Python_events;
    method = find_method(events, method, event);
    if (!method) {
       goto bail_out;
index f9135266a799826612bb97ad4e234ac03c6794ff..3fddb610cb6f1c9476b4e21cfef47123e649a0c7 100644 (file)
@@ -125,7 +125,7 @@ static void usage()
 {
    fprintf(stderr,
 "\n"
-"Usage: %s [-f from] [-h mailhost] [-s subject] [-c copy] [recepient ...]\n"
+"Usage: %s [-f from] [-h mailhost] [-s subject] [-c copy] [recipient ...]\n"
 "       -c          set the Cc: field\n"
 "       -dnn        set debug level to nn\n"
 "       -f          set the From: field\n"
index c8b4c9d4c88ec13ca5f55e7b063ae9e7d72abcee..7b9538329c2bffc14c4916435636d72e29dd1af0 100644 (file)
@@ -12,7 +12,7 @@
 #define TRACE_FILE 1
 
 /* If this is set stdout will not be closed on startup */
-/* #define DEVELOPER 1 */
+#define DEVELOPER 1