"""
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):
# 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"
"""
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
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):
"""
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
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):
* 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$
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;
}
/* 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)) {
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);
* Do a backup of the specified FileSet
*
* Returns: false on failure
- * true on success
+ * true on success
*/
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);
/* 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;
}
if (stat == JS_Terminated) {
backup_cleanup(jcr, stat);
return true;
- }
+ }
return false;
}
/* 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 */
*/
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;
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);
}
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;
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) {
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"
" 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"
" 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");
}
return JobId;
bail_out:
- generate_daemon_event(jcr, "JobEnd");
if (jcr->fname) {
free_memory(jcr->fname);
jcr->fname = NULL;
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);
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 */
goto bail_out;
}
}
+
+ generate_job_event(jcr, "JobRun");
+
switch (jcr->JobType) {
case JT_BACKUP:
if (do_backup(jcr)) {
dequeue_messages(jcr);
}
}
+
bail_out:
generate_daemon_event(jcr, "JobEnd");
Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus);
{
BSOCK *sd, *fd;
+ set_jcr_job_status(jcr, JS_Canceled);
+
switch (jcr->JobStatus) {
case JS_Created:
case JS_WaitJobRes:
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) {
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 {
{ 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}
};
}
}
if (!found) {
- goto not_found;
+ /* Try our methods */
+ return Py_FindMethod(JobMethods, self, attrname);
}
switch (i) {
case 0: /* Job */
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);
JCR *jcr;
bool found = false;
char *strval = NULL;
+ int intval = 0;
int i;
Dmsg2(100, "In job_setattr=%s val=%p.\n", attrname, 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)) {
} 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;
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;
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);
/* Writable variables */
static struct s_vars setvars[] = {
- { N_("set_events"), NULL},
{ N_("JobReport"), "s"},
- { N_("write"), "s"},
{ NULL, NULL}
};
}
}
if (!found) {
- goto not_found;
+ /* Try our methods */
+ return Py_FindMethod(JobMethods, self, attrname);
}
switch (i) {
case 0: /* FD's name */
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);
}
}
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;
}
}
+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);
python_close = my_python_close;
python_read = my_python_read;
- return 0;
+ Py_INCREF(Py_None);
+ return Py_None;
}
{
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;
} 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));
{"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 */
/* 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";
/*
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;
}
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);
/*
* 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)
{
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;
}
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;
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) {
/*
* Read Close session command
- * Close the read session
+ * Close the read session
*/
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;
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 {
/* Writable variables */
static struct s_vars setvars[] = {
- { N_("set_events"), NULL},
{ N_("JobReport"), "s"},
- { N_("write"), "s"},
{ NULL, NULL}
};
}
}
if (!found) {
- goto not_found;
+ /* Try our methods */
+ return Py_FindMethod(JobMethods, self, attrname);
}
switch (i) {
case 0: /* Job */
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);
}
}
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;
}
}
-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;
}
{
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;
{
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"
#define TRACE_FILE 1
/* If this is set stdout will not be closed on startup */
-/* #define DEVELOPER 1 */
+#define DEVELOPER 1