From 0c5d8b51885dac300f98665302313e889bdb5503 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sat, 30 Apr 2005 14:47:49 +0000 Subject: [PATCH] - Remove a few HAVE_TLS #ifdefs - Implement final Python style interface. More implemention to be done, but the interface should change little if at all. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1968 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/examples/python/DirStartUp.py | 28 +-- bacula/examples/python/FDStartUp.py | 18 +- bacula/examples/python/SDStartUp.py | 17 +- bacula/src/baconfig.h | 5 + bacula/src/console/console.c | 4 - bacula/src/dird/Makefile.in | 4 +- bacula/src/dird/dird.c | 2 - bacula/src/dird/{python.c => pythondir.c} | 200 +++++++++-------- bacula/src/filed/Makefile.in | 4 +- bacula/src/filed/filed.c | 2 - bacula/src/filed/{python.c => pythonfd.c} | 159 +++++++------ bacula/src/lib/pythonlib.c | 138 ++---------- bacula/src/stored/Makefile.in | 6 +- bacula/src/stored/dircmd.c | 1 + bacula/src/stored/job.c | 1 + bacula/src/stored/python.c | 208 ----------------- bacula/src/stored/pythonsd.c | 261 ++++++++++++++++++++++ bacula/src/stored/stored.c | 2 - bacula/src/version.h | 6 +- 19 files changed, 532 insertions(+), 534 deletions(-) rename bacula/src/dird/{python.c => pythondir.c} (53%) rename bacula/src/filed/{python.c => pythonfd.c} (62%) delete mode 100644 bacula/src/stored/python.c create mode 100644 bacula/src/stored/pythonsd.c diff --git a/bacula/examples/python/DirStartUp.py b/bacula/examples/python/DirStartUp.py index 230f307c09..37eaa28d5c 100644 --- a/bacula/examples/python/DirStartUp.py +++ b/bacula/examples/python/DirStartUp.py @@ -21,19 +21,19 @@ 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.get("JobId"); client = job.get("Client"); - numvols = job.get("NumVols") - job.set(JobReport="Python StartJob: JobId=%d Client=%s NumVols=%d\n" % (jobid,client,numvols)) + 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.get("JobId") - client = job.get("Client") - job.set(JobReport="Python EndJob output: JobId=%d Client=%s.\n" % (jobid, client)) + 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 @@ -55,13 +55,13 @@ class JobEvents: noop = 1 def NewVolume(self, job): - jobid = job.get("JobId") - client = job.get("Client") - numvol = job.get("NumVols"); + jobid = job.JobId + client = job.Client + numvol = job.NumVols; print "JobId=%d Client=%s NumVols=%d" % (jobid, client, numvol) - job.set(JobReport="Python before New Volume set for Job.\n") - job.set(VolumeName="TestA-001") - job.set(JobReport="Python after New Volume set for Job.\n") + job.JobReport="Python before New Volume set for Job.\n" + job.VolumeName="TestA-001" + job.JobReport="Python after New Volume set for Job.\n" return 1 @@ -73,7 +73,7 @@ class JobEvents: def open(self, file): print "Open %s called" % file self.fd = open('m.py', 'rb') - jobid = self.job.get("JobId") + jobid = self.job.JobId print "Open: JobId=%d" % jobid print "name=%s" % bacula.name diff --git a/bacula/examples/python/FDStartUp.py b/bacula/examples/python/FDStartUp.py index 7b06ead863..d553f2cd9e 100644 --- a/bacula/examples/python/FDStartUp.py +++ b/bacula/examples/python/FDStartUp.py @@ -20,23 +20,23 @@ 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.get("JobId") - client = job.get("Client") - job.set(JobReport="Python FD StartJob: JobId=%d Client=%s \n" % (jobid,client)) + jobid = job.JobId + client = job.Client + job.JobReport="Python FD JobStart: JobId=%d Client=%s \n" % (jobid,client) return 1 # Bacula Job is going to terminate def JobEnd(self, job): - jobid = job.get("JobId") - client = job.get("Client") - job.set(JobReport="Python FD EndJob output: JobId=%d Client=%s.\n" % (jobid, client)) + 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, job): + def Exit(self): noop = 1 bacula.set_events(BaculaEvents()) # register daemon events desired @@ -58,7 +58,7 @@ class JobEvents: def Python_open(self, file): print "Open %s called" % file self.fd = open(file, 'rb') - jobid = self.job.get("JobId") + jobid = self.job.JobId print "Open: %s" % file # Read file data into Bacula memory buffer (mem) diff --git a/bacula/examples/python/SDStartUp.py b/bacula/examples/python/SDStartUp.py index 480f7fb287..ff6a97b2e5 100644 --- a/bacula/examples/python/SDStartUp.py +++ b/bacula/examples/python/SDStartUp.py @@ -20,24 +20,24 @@ 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.get("JobId") - client = job.get("Client") - job.set(JobReport="Python SD StartJob: JobId=%d Client=%s \n" % (jobid,client)) + jobid = job.JobId + client = job.Client + job.JobReport="Python SD JobStart: JobId=%d Client=%s \n" % (jobid,client) return 1 # Bacula Job is going to terminate def JobEnd(self, job): - jobid = job.get("JobId") - client = job.get("Client") - job.set(JobReport="Python SD EndJob output: JobId=%d Client=%s.\n" % (jobid, client)) + 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 # Called here when the Bacula daemon is going to exit - def Exit(self, job): + def Exit(self): noop = 1 bacula.set_events(BaculaEvents()) # register daemon events desired @@ -54,4 +54,3 @@ class JobEvents: # Pass output back to Bacula def write(self, text): self.job.write(text) - diff --git a/bacula/src/baconfig.h b/bacula/src/baconfig.h index d74b673f5e..f1347cc312 100644 --- a/bacula/src/baconfig.h +++ b/bacula/src/baconfig.h @@ -71,6 +71,11 @@ /* #define bindtextdomain(p, d) */ #endif +#ifndef HAVE_TLS +#define init_tls(x) 0 +#define cleanup_tls() +#endif + /* This should go away! ****FIXME***** */ #define MAXSTRING 500 diff --git a/bacula/src/console/console.c b/bacula/src/console/console.c index f6a6d98510..bdc0cc3431 100644 --- a/bacula/src/console/console.c +++ b/bacula/src/console/console.c @@ -394,11 +394,9 @@ int main(int argc, char *argv[]) parse_config(configfile); -#ifdef HAVE_TLS if (init_tls() != 0) { Emsg0(M_ERROR_TERM, 0, _("TLS library initialization failed.\n")); } -#endif if (!check_resources()) { Emsg1(M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile); @@ -551,9 +549,7 @@ static void terminate_console(int sig) exit(1); } already_here = true; -#ifdef HAVE_TLS cleanup_tls(); -#endif free_pool_memory(args); con_term(); (void)WSACleanup(); /* Cleanup Windows sockets */ diff --git a/bacula/src/dird/Makefile.in b/bacula/src/dird/Makefile.in index 504f4d4f05..3304e86327 100644 --- a/bacula/src/dird/Makefile.in +++ b/bacula/src/dird/Makefile.in @@ -34,7 +34,7 @@ SVRSRCS = dird.c admin.c authenticate.c \ fd_cmds.c getmsg.c inc_conf.c job.c \ jobq.c mac.c \ mountreq.c msgchan.c next_vol.c newvol.c \ - python.c \ + pythondir.c \ recycle.c restore.c run_conf.c \ scheduler.c sql_cmds.c \ ua_acl.c ua_cmds.c ua_dotcmds.c \ @@ -49,7 +49,7 @@ SVROBJS = dird.o admin.o authenticate.o \ fd_cmds.o getmsg.o inc_conf.o job.o \ jobq.o mac.o \ mountreq.o msgchan.o next_vol.o newvol.o \ - python.o \ + pythondir.o \ recycle.o restore.o run_conf.o \ scheduler.o sql_cmds.o \ ua_acl.o ua_cmds.o ua_dotcmds.o \ diff --git a/bacula/src/dird/dird.c b/bacula/src/dird/dird.c index 286987fd5a..c1909f8c4e 100644 --- a/bacula/src/dird/dird.c +++ b/bacula/src/dird/dird.c @@ -194,11 +194,9 @@ int main (int argc, char *argv[]) parse_config(configfile); -#ifdef HAVE_TLS if (init_tls() != 0) { Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("TLS library initialization failed.\n")); } -#endif if (!check_resources()) { Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile); diff --git a/bacula/src/dird/python.c b/bacula/src/dird/pythondir.c similarity index 53% rename from bacula/src/dird/python.c rename to bacula/src/dird/pythondir.c index 09dfaebe6b..9869753cef 100644 --- a/bacula/src/dird/python.c +++ b/bacula/src/dird/pythondir.c @@ -39,23 +39,8 @@ extern JCR *get_jcr_from_PyObject(PyObject *self); extern PyObject *find_method(PyObject *eventsObject, PyObject *method, const char *name); -static PyObject *job_get(PyObject *self, PyObject *args); -static PyObject *job_write(PyObject *self, PyObject *args); -static PyObject *job_set(PyObject *self, PyObject *args, PyObject *keyw); -static PyObject *set_job_events(PyObject *self, PyObject *args); -static PyObject *jcr_run(PyObject *self, PyObject *args); - -/* Define Job entry points */ -PyMethodDef JobMethods[] = { - {"get", job_get, METH_VARARGS, "Get Job variables."}, - {"set", (PyCFunction)job_set, METH_VARARGS|METH_KEYWORDS, - "Set Job variables."}, - {"set_events", set_job_events, METH_VARARGS, "Define Job events."}, - {"write", job_write, METH_VARARGS, "Write output."}, - {"run", (PyCFunction)jcr_run, METH_VARARGS, "Run a Bacula command."}, - {NULL, NULL, 0, NULL} /* last item */ -}; - +static int set_job_events(PyObject *self, PyObject *arg); +static int job_run(PyObject *self, PyObject *arg); struct s_vars { const char *name; @@ -63,7 +48,7 @@ struct s_vars { }; /* Read-only variables */ -static struct s_vars vars[] = { +static struct s_vars getvars[] = { { N_("Job"), "s"}, { N_("DirName"), "s"}, { N_("Level"), "s"}, @@ -81,143 +66,171 @@ static struct s_vars vars[] = { { 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"}, + + { NULL, NULL} +}; + + /* Return Job variables */ -static PyObject *job_get(PyObject *self, PyObject *args) +/* Returns: NULL if error + * PyObject * return value if OK + */ +PyObject *job_getattr(PyObject *self, char *attrname) { JCR *jcr; - char *item; bool found = false; int i; char buf[10]; + char errmsg[200]; - Dmsg0(100, "In job_get.\n"); - if (!PyArg_ParseTuple(args, "s:get", &item)) { - return NULL; - } + Dmsg0(100, "In job_getattr.\n"); jcr = get_jcr_from_PyObject(self); - for (i=0; vars[i].name; i++) { - if (strcmp(vars[i].name, item) == 0) { + if (!jcr) { + bstrncpy(errmsg, "Job pointer not found.", sizeof(errmsg)); + goto bail_out; + } + for (i=0; getvars[i].name; i++) { + if (strcmp(getvars[i].name, attrname) == 0) { found = true; break; } } if (!found) { - return NULL; + goto not_found; } switch (i) { case 0: /* Job */ - return Py_BuildValue(vars[i].fmt, jcr->job->hdr.name); + return Py_BuildValue(getvars[i].fmt, jcr->job->hdr.name); case 1: /* Director's name */ - return Py_BuildValue(vars[i].fmt, my_name); + return Py_BuildValue(getvars[i].fmt, my_name); case 2: /* level */ - return Py_BuildValue(vars[i].fmt, job_level_to_str(jcr->JobLevel)); + return Py_BuildValue(getvars[i].fmt, job_level_to_str(jcr->JobLevel)); case 3: /* type */ - return Py_BuildValue(vars[i].fmt, job_type_to_str(jcr->JobType)); + return Py_BuildValue(getvars[i].fmt, job_type_to_str(jcr->JobType)); case 4: /* JobId */ - return Py_BuildValue(vars[i].fmt, jcr->JobId); + return Py_BuildValue(getvars[i].fmt, jcr->JobId); case 5: /* Client */ - return Py_BuildValue(vars[i].fmt, jcr->client->hdr.name); + return Py_BuildValue(getvars[i].fmt, jcr->client->hdr.name); case 6: /* NumVols */ - return Py_BuildValue(vars[i].fmt, jcr->NumVols); + return Py_BuildValue(getvars[i].fmt, jcr->NumVols); case 7: /* Pool */ - return Py_BuildValue(vars[i].fmt, jcr->pool->hdr.name); + return Py_BuildValue(getvars[i].fmt, jcr->pool->hdr.name); case 8: /* Storage */ - return Py_BuildValue(vars[i].fmt, jcr->store->hdr.name); + return Py_BuildValue(getvars[i].fmt, jcr->store->hdr.name); case 9: - return Py_BuildValue(vars[i].fmt, jcr->catalog->hdr.name); + return Py_BuildValue(getvars[i].fmt, jcr->catalog->hdr.name); case 10: /* MediaType */ - return Py_BuildValue(vars[i].fmt, jcr->store->media_type); + return Py_BuildValue(getvars[i].fmt, jcr->store->media_type); case 11: /* JobName */ - return Py_BuildValue(vars[i].fmt, jcr->Job); + return Py_BuildValue(getvars[i].fmt, jcr->Job); case 12: /* JobStatus */ buf[1] = 0; buf[0] = jcr->JobStatus; - return Py_BuildValue(vars[i].fmt, buf); + 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); return NULL; } + /* Set Job variables */ -static PyObject *job_set(PyObject *self, PyObject *args, PyObject *keyw) +/* Returns: 0 for OK + * -1 for error + */ +int job_setattr(PyObject *self, char *attrname, PyObject *value) { JCR *jcr; - char *msg = NULL; - char *VolumeName = NULL; - static char *kwlist[] = {"JobReport", "VolumeName", NULL}; - - Dmsg0(100, "In job_set.\n"); - if (!PyArg_ParseTupleAndKeywords(args, keyw, "|ss:set", kwlist, - &msg, &VolumeName)) { - return NULL; + bool found = false; + char *strval = NULL; + int i; + + Dmsg2(100, "In job_setattr=%s val=%p.\n", attrname, value); + if (value == NULL) { /* Cannot delete variables */ + goto bail_out; } jcr = get_jcr_from_PyObject(self); - - if (msg) { - Jmsg(jcr, M_INFO, 0, "%s", msg); + if (!jcr) { + goto bail_out; } - if (!VolumeName) { - Dmsg1(100, "No VolumeName. Event=%s\n", jcr->event); - } else { - Dmsg2(100, "Vol=%s Event=%s\n", VolumeName, jcr->event); + /* Find attribute name in list */ + for (i=0; setvars[i].name; i++) { + if (strcmp(setvars[i].name, attrname) == 0) { + found = true; + break; + } + } + if (!found) { + goto bail_out; } - /* Make sure VolumeName is valid and we are in VolumeName event */ - if (VolumeName && strcmp("NewVolume", jcr->event) == 0 && - is_volume_name_legal(NULL, VolumeName)) { - pm_strcpy(jcr->VolumeName, VolumeName); - Dmsg1(100, "Set Vol=%s\n", VolumeName); - } else if (VolumeName) { - jcr->VolumeName[0] = 0; - Dmsg0(100, "Zap VolumeName.\n"); - return Py_BuildValue("i", 0); /* invalid volume name */ + /* Get argument value ***FIXME*** handle other formats */ + if (setvars[i].fmt != NULL) { + if (!PyArg_Parse(value, setvars[i].fmt, &strval)) { + PyErr_SetString(PyExc_TypeError, "Read-only attribute"); + return -1; + } + } + 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 */ + Jmsg(jcr, M_INFO, 0, "%s", strval); + return 0; + case 4: /* VolumeName */ + /* Make sure VolumeName is valid and we are in VolumeName event */ + if (strcmp("NewVolume", jcr->event) == 0 && + is_volume_name_legal(NULL, strval)) { + pm_strcpy(jcr->VolumeName, strval); + Dmsg1(100, "Set Vol=%s\n", strval); + return 0; + } else { + jcr->VolumeName[0] = 0; + } } - return Py_BuildValue("i", 1); +bail_out: + PyErr_SetString(PyExc_AttributeError, attrname); + return -1; } -static PyObject *set_job_events(PyObject *self, PyObject *args) + +static int set_job_events(PyObject *self, PyObject *arg) { PyObject *eObject; JCR *jcr; Dmsg0(100, "In set_job_events.\n"); - if (!PyArg_ParseTuple(args, "O:set_events", &eObject)) { - return NULL; + if (!PyArg_Parse(arg, "O", &eObject)) { + return -1; } jcr = get_jcr_from_PyObject(self); Py_XDECREF((PyObject *)jcr->Python_events); Py_INCREF(eObject); jcr->Python_events = (void *)eObject; - - Py_INCREF(Py_None); - return Py_None; -} - -/* Write text to job output */ -static PyObject *job_write(PyObject *self, PyObject *args) -{ - char *text; - - if (!PyArg_ParseTuple(args, "s:write", &text)) { - return NULL; - } - if (text) { - JCR *jcr = get_jcr_from_PyObject(self); - Jmsg(jcr, M_INFO, 0, "%s", text); - } - - Py_INCREF(Py_None); - return Py_None; + return 0; /* good return */ } /* Run a Bacula command */ -static PyObject *jcr_run(PyObject *self, PyObject *args) +static int job_run(PyObject *self, PyObject *arg) { JCR *jcr; char *item; int stat; - if (!PyArg_ParseTuple(args, "s:get", &item)) { - return NULL; + if (!PyArg_Parse(arg, "s", &item)) { + return -1; } jcr = get_jcr_from_PyObject(self); UAContext *ua = new_ua_context(jcr); @@ -226,7 +239,8 @@ static PyObject *jcr_run(PyObject *self, PyObject *args) parse_ua_args(ua); /* parse command */ stat = run_cmd(ua, ua->cmd); free_ua_context(ua); - return Py_BuildValue("i", stat); + /* ***FIXME*** check stat */ + return 0; } diff --git a/bacula/src/filed/Makefile.in b/bacula/src/filed/Makefile.in index 859b7e39ab..9cfbaf286c 100755 --- a/bacula/src/filed/Makefile.in +++ b/bacula/src/filed/Makefile.in @@ -30,10 +30,10 @@ dummy: # SVRSRCS = filed.c authenticate.c acl.c backup.c chksum.c estimate.c \ - filed_conf.c heartbeat.c job.c python.c \ + filed_conf.c heartbeat.c job.c pythonfd.c \ restore.c status.c verify.c verify_vol.c SVROBJS = filed.o authenticate.o acl.o backup.o chksum.o estimate.o \ - filed_conf.o heartbeat.o job.o python.o \ + filed_conf.o heartbeat.o job.o pythonfd.o \ restore.o status.o verify.o verify_vol.o # these are the objects that are changed by the .configure process diff --git a/bacula/src/filed/filed.c b/bacula/src/filed/filed.c index 4ef2a0b657..688a3e4ce5 100644 --- a/bacula/src/filed/filed.c +++ b/bacula/src/filed/filed.c @@ -181,12 +181,10 @@ int main (int argc, char *argv[]) parse_config(configfile); -#ifdef HAVE_TLS if (init_tls() != 0) { Emsg0(M_ERROR, 0, _("TLS library initialization failed.\n")); terminate_filed(1); } -#endif if (!check_resources()) { Emsg1(M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile); diff --git a/bacula/src/filed/python.c b/bacula/src/filed/pythonfd.c similarity index 62% rename from bacula/src/filed/python.c rename to bacula/src/filed/pythonfd.c index 7ccbd16575..acb70906bd 100644 --- a/bacula/src/filed/python.c +++ b/bacula/src/filed/pythonfd.c @@ -47,10 +47,7 @@ extern PyObject *find_method(PyObject *eventsObject, PyObject *method, const char *name); /* Forward referenced functions */ -static PyObject *job_get(PyObject *self, PyObject *args); -static PyObject *job_write(PyObject *self, PyObject *args); -static PyObject *job_set(PyObject *self, PyObject *args, PyObject *keyw); -static PyObject *set_job_events(PyObject *self, PyObject *args); +static int set_job_events(PyObject *self, PyObject *arg); bool my_python_set_prog(JCR *jcr, const char *prog); int my_python_open(BFILE *bfd, const char *fname, int flags, mode_t mode); @@ -58,23 +55,13 @@ int my_python_close(BFILE *bfd); ssize_t my_python_read(BFILE *bfd, void *buf, size_t count); -/* Define Job entry points */ -PyMethodDef JobMethods[] = { - {"get", job_get, METH_VARARGS, "Get Job variables."}, - {"set", (PyCFunction)job_set, METH_VARARGS|METH_KEYWORDS, - "Set Job variables."}, - {"set_events", set_job_events, METH_VARARGS, "Define Job events."}, - {"write", job_write, METH_VARARGS, "Write output."}, - {NULL, NULL, 0, NULL} /* last item */ -}; - struct s_vars { const char *name; char *fmt; }; /* Read-only variables */ -static struct s_vars vars[] = { +static struct s_vars getvars[] = { { N_("FDName"), "s"}, /* 0 */ { N_("Level"), "s"}, /* 1 */ { N_("Type"), "s"}, /* 2 */ @@ -86,83 +73,138 @@ static struct s_vars vars[] = { { NULL, NULL} }; +/* Writable variables */ +static struct s_vars setvars[] = { + { N_("set_events"), NULL}, + { N_("JobReport"), "s"}, + { N_("write"), "s"}, + + { NULL, NULL} +}; + /* Return Job variables */ -PyObject *job_get(PyObject *self, PyObject *args) +PyObject *job_getattr(PyObject *self, char *attrname) { JCR *jcr; - char *item; bool found = false; int i; char buf[10]; + char errmsg[200]; - if (!PyArg_ParseTuple(args, "s:get", &item)) { - return NULL; - } jcr = get_jcr_from_PyObject(self); - for (i=0; vars[i].name; i++) { - if (strcmp(vars[i].name, item) == 0) { + if (!jcr) { + bstrncpy(errmsg, "Job pointer not found.", sizeof(errmsg)); + goto bail_out; + } + for (i=0; getvars[i].name; i++) { + if (strcmp(getvars[i].name, attrname) == 0) { found = true; break; } } if (!found) { - return NULL; + goto not_found; } switch (i) { case 0: /* FD's name */ - return Py_BuildValue(vars[i].fmt, my_name); + return Py_BuildValue(getvars[i].fmt, my_name); case 1: /* level */ - return Py_BuildValue(vars[i].fmt, job_level_to_str(jcr->JobLevel)); + return Py_BuildValue(getvars[i].fmt, job_level_to_str(jcr->JobLevel)); case 2: /* type */ - return Py_BuildValue(vars[i].fmt, job_type_to_str(jcr->JobType)); + return Py_BuildValue(getvars[i].fmt, job_type_to_str(jcr->JobType)); case 3: /* JobId */ - return Py_BuildValue(vars[i].fmt, jcr->JobId); + return Py_BuildValue(getvars[i].fmt, jcr->JobId); case 4: /* Client */ - return Py_BuildValue(vars[i].fmt, jcr->client_name); + return Py_BuildValue(getvars[i].fmt, jcr->client_name); case 5: /* JobName */ - return Py_BuildValue(vars[i].fmt, jcr->Job); + return Py_BuildValue(getvars[i].fmt, jcr->Job); case 6: /* JobStatus */ buf[1] = 0; buf[0] = jcr->JobStatus; - return Py_BuildValue(vars[i].fmt, buf); + 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); return NULL; } -/* Set Job variables */ -PyObject *job_set(PyObject *self, PyObject *args, PyObject *keyw) +int job_setattr(PyObject *self, char *attrname, PyObject *value) { - JCR *jcr; - char *msg = NULL; - static char *kwlist[] = {"JobReport", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, keyw, "|s:set", kwlist, - &msg)) { - return NULL; + JCR *jcr; + bool found = false; + char *strval = NULL; + char buf[200]; + char *errmsg; + int i; + + Dmsg2(100, "In job_setattr=%s val=%p.\n", attrname, value); + if (value == NULL) { /* Cannot delete variables */ + bsnprintf(buf, sizeof(buf), "Cannot delete attribute %s", attrname); + errmsg = buf; + goto bail_out; } jcr = get_jcr_from_PyObject(self); - - if (msg) { - Jmsg(jcr, M_INFO, 0, "%s", msg); + if (!jcr) { + errmsg = "Job pointer not found."; + goto bail_out; } - return Py_BuildValue("i", 1); + + /* Find attribute name in list */ + for (i=0; setvars[i].name; i++) { + if (strcmp(setvars[i].name, attrname) == 0) { + found = true; + break; + } + } + if (!found) { + bsnprintf(buf, sizeof(buf), "Cannot find attribute %s", attrname); + errmsg = buf; + goto bail_out; + } + /* Get argument value ***FIXME*** handle other formats */ + if (setvars[i].fmt != NULL) { + if (!PyArg_Parse(value, setvars[i].fmt, &strval)) { + PyErr_SetString(PyExc_TypeError, "Read-only attribute"); + return -1; + } + } + switch (i) { + case 0: /* set_events */ + return set_job_events(self, value); + case 1: /* JobReport */ + case 2: /* write */ + Jmsg(jcr, M_INFO, 0, "%s", strval); + return 0; + } + bsnprintf(buf, sizeof(buf), "Cannot find attribute %s", attrname); + errmsg = buf; +bail_out: + PyErr_SetString(PyExc_AttributeError, errmsg); + return -1; } -static PyObject *set_job_events(PyObject *self, PyObject *args) + +static int set_job_events(PyObject *self, PyObject *arg) { PyObject *eObject; JCR *jcr; Dmsg0(100, "In set_job_events.\n"); - - if (!PyArg_ParseTuple(args, "O:set_events", &eObject)) { - return NULL; + if (!PyArg_Parse(arg, "O", &eObject)) { + Dmsg0(000, "Parse error looking for Object argument\n"); + return -1; } jcr = get_jcr_from_PyObject(self); - Py_XDECREF((PyObject *)jcr->Python_events); + if (!jcr) { + PyErr_SetString(PyExc_AttributeError, "Job pointer not found."); + return -1; + } + Py_XDECREF((PyObject *)jcr->Python_events); /* release any old events Object */ Py_INCREF(eObject); - jcr->Python_events = (void *)eObject; + jcr->Python_events = (void *)eObject; /* set new events */ /* Set function pointers to call here */ python_set_prog = my_python_set_prog; @@ -170,26 +212,9 @@ static PyObject *set_job_events(PyObject *self, PyObject *args) python_close = my_python_close; python_read = my_python_read; - Py_INCREF(Py_None); - return Py_None; + return 0; } -/* Write text to job output */ -static PyObject *job_write(PyObject *self, PyObject *args) -{ - char *text = NULL; - - if (!PyArg_ParseTuple(args, "s:write", &text)) { - return NULL; - } - if (text) { - JCR *jcr = get_jcr_from_PyObject(self); - Jmsg(jcr, M_INFO, 0, "%s", text); - } - - Py_INCREF(Py_None); - return Py_None; -} int generate_job_event(JCR *jcr, const char *event) { diff --git a/bacula/src/lib/pythonlib.c b/bacula/src/lib/pythonlib.c index b507960a7e..378c85036a 100644 --- a/bacula/src/lib/pythonlib.c +++ b/bacula/src/lib/pythonlib.c @@ -37,7 +37,9 @@ #include /* Imported subroutines */ -extern PyMethodDef JobMethods[]; +//extern PyMethodDef JobMethods[]; +extern PyObject *job_getattr(PyObject *self, char *attrname); +extern int job_setattr(PyObject *self, char *attrname, PyObject *value); static PyObject *bacula_module = NULL; /* We create this */ static PyObject *StartUp_module = NULL; /* We import this */ @@ -72,49 +74,15 @@ typedef struct s_JobObject { static PyTypeObject JobType = { PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "bacula.jcr", /*tp_name*/ - sizeof(JobObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - "Job objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - JobMethods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ + /* Other items filled in in code below */ }; /* Return the JCR pointer from the JobObject */ JCR *get_jcr_from_PyObject(PyObject *self) { + if (!self) { + return NULL; + } return ((JobObject *)self)->jcr; } @@ -135,6 +103,7 @@ void init_python_interpreter(const char *progname, const char *scripts, Py_Initialize(); PyEval_InitThreads(); bacula_module = Py_InitModule("bacula", BaculaMethods); + PyModule_AddStringConstant(bacula_module, "name", my_name); if (!bacula_module) { Jmsg0(NULL, M_ERROR_TERM, 0, "Could not initialize Python\n"); } @@ -143,7 +112,15 @@ void init_python_interpreter(const char *progname, const char *scripts, if (PyRun_SimpleString(buf) != 0) { Jmsg1(NULL, M_ERROR_TERM, 0, "Could not Run Python string %s\n", buf); } - JobType.tp_methods = JobMethods; + + /* Explicitly set values we want */ + JobType.tp_name = "Bacula.Job"; + JobType.tp_basicsize = sizeof(JobObject); + JobType.tp_flags = Py_TPFLAGS_DEFAULT; + JobType.tp_doc = "Bacula Job object"; + JobType.tp_getattr = job_getattr; + JobType.tp_setattr = job_setattr; + if (PyType_Ready(&JobType) != 0) { Jmsg0(NULL, M_ERROR_TERM, 0, "Could not initialize Python Job type.\n"); PyErr_Print(); @@ -273,19 +250,20 @@ int generate_daemon_event(JCR *jcr, const char *event) } else if (strcmp(event, "JobEnd") == 0) { if (!JobEnd_method || !jcr->Python_job) { - Dmsg0(100, "No JobEnd method\n"); + Dmsg2(000, "No JobEnd method=%p Job=%p\n", JobEnd_method, jcr->Python_job); stat = 0; goto bail_out; } bstrncpy(jcr->event, event, sizeof(jcr->event)); - Dmsg1(100, "Call event=%s\n", event); + Dmsg1(100, "Call daemon event=%s\n", event); result = PyObject_CallFunction(JobEnd_method, "O", jcr->Python_job); jcr->event[0] = 0; /* no event in progress */ if (result == NULL) { - JobEnd_method = NULL; if (PyErr_Occurred()) { PyErr_Print(); - Dmsg1(000, "Python JobEnd error. JobId=%d\n", jcr->JobId); + Dmsg2(000, "Python JobEnd error. job=%p JobId=%d\n", jcr->Python_job, + jcr->JobId); + JobEnd_method = NULL; } Jmsg(jcr, M_ERROR, 0, "Python function \"%s\" not found.\n", event); goto bail_out; @@ -296,13 +274,13 @@ int generate_daemon_event(JCR *jcr, const char *event) stat = 0; goto bail_out; } - result = PyObject_CallFunction(JobEnd_method, NULL); + result = PyObject_CallFunction(Exit_method, NULL); if (result == NULL) { goto bail_out; } stat = 1; /* OK */ } else { - Emsg1(M_ABORT, 0, "Unknown Python daemon event %s\n", event); + Jmsg1(jcr, M_ABORT, 0, "Unknown Python daemon event %s\n", event); } bail_out: @@ -317,74 +295,6 @@ jobstart_ok: return stat; } -#ifdef xxx - PyObject *pName, *pModule, *pDict, *pFunc; - PyObject *pArgs, *pJCR, *pCall; - - Dmsg1(100, "Generate event %s\n", event); - pName = PyString_FromString(event); - if (!pName) { - Jmsg(jcr, M_ERROR, 0, "Could not convert \"%s\" to Python string.\n", event); - return -1; /* Could not convert string */ - } - - pModule = PyImport_Import(pName); - Py_DECREF(pName); /* release pName */ - - if (pModule != NULL) { - pDict = PyModule_GetDict(pModule); - /* pDict is a borrowed reference */ - - pFunc = PyDict_GetItemString(pDict, (char *)event); - /* pFun: Borrowed reference */ - - if (pFunc && PyCallable_Check(pFunc)) { - /* Create JCR argument to send to function */ - pArgs = PyTuple_New(1); - pJCR = (PyObject *)PyObject_New(JCRObject, &JCRType); - ((JCRObject *)pJCR)->jcr = jcr; - if (!pJCR) { - Py_DECREF(pArgs); - Py_DECREF(pModule); - Jmsg0(jcr, M_ERROR, 0, "Could not create JCR Python Object.\n"); - return -1; - } - Py_INCREF(pJCR); - /* pJCR reference stolen here: */ - PyTuple_SetItem(pArgs, 0, pJCR); - - /* Finally, we call the module here */ - bstrncpy(jcr->event, event, sizeof(jcr->event)); - pCall = PyObject_CallObject(pFunc, pArgs); - jcr->event[0] = 0; /* no event in progress */ - Py_DECREF(pArgs); - Py_DECREF(pJCR); - if (pCall != NULL) { - Py_DECREF(pCall); - } else { - Py_DECREF(pModule); - PyErr_Print(); - Jmsg1(jcr, M_ERROR, 0, "Error running Python module: %s\n", event); - return 0; /* error running function */ - } - /* pDict and pFunc are borrowed and must not be Py_DECREF-ed */ - } else { - if (PyErr_Occurred()) { - PyErr_Print(); - Dmsg1(000, "Python event %s function not callable.\n", event); - } - Jmsg1(jcr, M_ERROR, 0, "Python function \"%s\" not found in module.\n", event); - return -1; /* function not found */ - } - Py_DECREF(pModule); - } else { - return 0; /* Module not present */ - } - Dmsg0(100, "Generate event OK\n"); - return 1; -} -#endif - #else /* diff --git a/bacula/src/stored/Makefile.in b/bacula/src/stored/Makefile.in index 3899ecffd9..777f287c15 100644 --- a/bacula/src/stored/Makefile.in +++ b/bacula/src/stored/Makefile.in @@ -27,7 +27,7 @@ SVRSRCS = stored.c ansi_label.c \ block.c butil.c dev.c \ device.c dircmd.c dvd.c ebcdic.c fd_cmds.c job.c \ label.c match_bsr.c mount.c parse_bsr.c \ - python.c \ + pythonsd.c \ read.c read_record.c record.c \ spool.c status.c stored_conf.c wait.c SVROBJS = stored.o ansi_label.o \ @@ -36,7 +36,7 @@ SVROBJS = stored.o ansi_label.o \ block.o butil.o dev.o \ device.o dircmd.o dvd.o ebcdic.c fd_cmds.o job.o \ label.o match_bsr.o mount.o parse_bsr.o \ - python.o \ + pythonsd.o \ read.o read_record.o record.o \ spool.o status.o stored_conf.o wait.o @@ -60,7 +60,7 @@ BLSOBJS = bls.o block.o butil.o device.o dev.o label.o match_bsr.o \ BEXTOBJS = bextract.o block.o device.o dev.o label.o record.o \ ansi_label.o dvd.o ebcdic.o \ autochanger.o acquire.o mount.o match_bsr.o parse_bsr.o butil.o \ - python.o \ + pythonsd.o \ read_record.o stored_conf.o spool.o wait.o # bscan diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 5884e57559..02c2fc9169 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -219,6 +219,7 @@ void *handle_connection_request(void *arg) } } bail_out: + generate_daemon_event(jcr, "JobEnd"); dequeue_messages(jcr); /* send any queued messages */ bnet_sig(bs, BNET_TERMINATE); free_jcr(jcr); diff --git a/bacula/src/stored/job.c b/bacula/src/stored/job.c index 2e161f3406..6bde98a8a7 100644 --- a/bacula/src/stored/job.c +++ b/bacula/src/stored/job.c @@ -139,6 +139,7 @@ bool job_cmd(JCR *jcr) Dmsg1(100, ">dird: %s", dir->msg); jcr->sd_auth_key = bstrdup(auth_key); memset(auth_key, 0, sizeof(auth_key)); + generate_daemon_event(jcr, "JobStart"); return true; } diff --git a/bacula/src/stored/python.c b/bacula/src/stored/python.c deleted file mode 100644 index aa9e7e86a1..0000000000 --- a/bacula/src/stored/python.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * - * Bacula interface to Python for the Storage Daemon - * - * Kern Sibbald, January MMV - * - * Version $Id$ - * - */ - -/* - Copyright (C) 2005 Kern Sibbald - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. - - 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., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - */ - -#include "bacula.h" -#include "stored.h" - -#ifdef HAVE_PYTHON -#undef _POSIX_C_SOURCE -#include - -extern JCR *get_jcr_from_PyObject(PyObject *self); -extern PyObject *find_method(PyObject *eventsObject, PyObject *method, - const char *name); - -static PyObject *jcr_get(PyObject *self, PyObject *args); -static PyObject *jcr_write(PyObject *self, PyObject *args); -static PyObject *jcr_set(PyObject *self, PyObject *args, PyObject *keyw); -static PyObject *set_jcr_events(PyObject *self, PyObject *args); - - -/* Define Job entry points */ -PyMethodDef JobMethods[] = { - {"get", jcr_get, METH_VARARGS, "Get Job variables."}, - {"set", (PyCFunction)jcr_set, METH_VARARGS|METH_KEYWORDS, - "Set Job variables."}, - {"set_events", set_jcr_events, METH_VARARGS, "Define Job events."}, - {"write", jcr_write, METH_VARARGS, "Write output."}, - {NULL, NULL, 0, NULL} /* last item */ -}; - - -struct s_vars { - const char *name; - char *fmt; -}; - -static struct s_vars vars[] = { - { N_("Job"), "s"}, /* 0 */ - { N_("SDName"), "s"}, /* 1 */ - { N_("Level"), "s"}, /* 2 */ - { N_("Type"), "s"}, /* 3 */ - { N_("JobId"), "i"}, /* 4 */ - { N_("Client"), "s"}, /* 5 */ - { N_("Pool"), "s"}, /* 6 */ - { N_("MediaType"), "s"}, /* 7 */ - { N_("JobName"), "s"}, /* 8 */ - { N_("JobStatus"), "s"}, /* 9 */ - { N_("VolumeName"), "s"}, /* 10 */ - { N_("Device"), "s"}, /* 11 */ - - { NULL, NULL} -}; - -/* Return Job variables */ -PyObject *jcr_get(PyObject *self, PyObject *args) -{ - JCR *jcr; - char *item; - bool found = false; - int i; - char buf[10]; - - if (!PyArg_ParseTuple(args, "s:get", &item)) { - return NULL; - } - jcr = get_jcr_from_PyObject(self); - - for (i=0; vars[i].name; i++) { - if (strcmp(vars[i].name, item) == 0) { - found = true; - break; - } - } - if (!found) { - return NULL; - } - switch (i) { - case 0: /* Job */ - return Py_BuildValue(vars[i].fmt, jcr->job_name); /* Non-unique name */ - case 1: /* SD's name */ - return Py_BuildValue(vars[i].fmt, my_name); - case 2: /* level */ - return Py_BuildValue(vars[i].fmt, job_level_to_str(jcr->JobLevel)); - case 3: /* type */ - return Py_BuildValue(vars[i].fmt, job_type_to_str(jcr->JobType)); - case 4: /* JobId */ - return Py_BuildValue(vars[i].fmt, jcr->JobId); - case 5: /* Client */ - return Py_BuildValue(vars[i].fmt, jcr->client_name); - case 6: /* Pool */ - return Py_BuildValue(vars[i].fmt, jcr->dcr->pool_name); - case 7: /* MediaType */ - return Py_BuildValue(vars[i].fmt, jcr->dcr->media_type); - case 8: /* JobName */ - return Py_BuildValue(vars[i].fmt, jcr->Job); - case 9: /* JobStatus */ - buf[1] = 0; - buf[0] = jcr->JobStatus; - return Py_BuildValue(vars[i].fmt, buf); - case 10: - return Py_BuildValue(vars[i].fmt, jcr->dcr->VolumeName); - case 11: - return Py_BuildValue(vars[i].fmt, jcr->dcr->dev_name); - } - return NULL; -} - -/* Set Job variables */ -PyObject *jcr_set(PyObject *self, PyObject *args, PyObject *keyw) -{ - JCR *jcr; - char *msg = NULL; - static char *kwlist[] = {"JobReport", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, keyw, "|s:set", kwlist, - &msg)) { - return NULL; - } - jcr = get_jcr_from_PyObject(self); - - if (msg) { - Jmsg(jcr, M_INFO, 0, "%s", msg); - } - return Py_BuildValue("i", 1); -} - -static PyObject *set_jcr_events(PyObject *self, PyObject *args) -{ - PyObject *eObject; - JCR *jcr; - if (!PyArg_ParseTuple(args, "O:set_events_hook", &eObject)) { - return NULL; - } - Py_XINCREF(eObject); - jcr = get_jcr_from_PyObject(self); -// jcr->ff->bfd.pio.fc = find_method(eObject, close_method, "close"); - Py_INCREF(Py_None); - return Py_None; -} - -/* Write text to job output */ -static PyObject *jcr_write(PyObject *self, PyObject *args) -{ - char *text; - if (!PyArg_ParseTuple(args, "s:write", &text)) { - return NULL; - } - if (text) { - JCR *jcr = get_jcr_from_PyObject(self); - Jmsg(jcr, M_INFO, 0, "%s", text); - } - - Py_INCREF(Py_None); - return Py_None; -} - -int generate_job_event(JCR *jcr, const char *event) -{ -#ifdef implemented - PyEval_AcquireLock(); - - PyObject *result = PyObject_CallFunction(open_method, "s", "m.py"); - if (result == NULL) { - PyErr_Print(); - PyErr_Clear(); - } - Py_XDECREF(result); - - PyEval_ReleaseLock(); -#endif - return 1; -} - -#else - -/* Dummy if Python not configured */ -int generate_job_event(JCR *jcr, const char *event) -{ return 1; } - - -#endif /* HAVE_PYTHON */ diff --git a/bacula/src/stored/pythonsd.c b/bacula/src/stored/pythonsd.c new file mode 100644 index 0000000000..85ca46ed2e --- /dev/null +++ b/bacula/src/stored/pythonsd.c @@ -0,0 +1,261 @@ +/* + * + * Bacula interface to Python for the Storage Daemon + * + * Kern Sibbald, January MMV + * + * Version $Id$ + * + */ + +/* + Copyright (C) 2005 Kern Sibbald + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + 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., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + */ + +#include "bacula.h" +#include "stored.h" + +#ifdef HAVE_PYTHON +#undef _POSIX_C_SOURCE +#include + +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); + + +struct s_vars { + const char *name; + char *fmt; +}; + +static struct s_vars getvars[] = { + { N_("Job"), "s"}, /* 0 */ + { N_("SDName"), "s"}, /* 1 */ + { N_("Level"), "s"}, /* 2 */ + { N_("Type"), "s"}, /* 3 */ + { N_("JobId"), "i"}, /* 4 */ + { N_("Client"), "s"}, /* 5 */ + { N_("Pool"), "s"}, /* 6 */ + { N_("MediaType"), "s"}, /* 7 */ + { N_("JobName"), "s"}, /* 8 */ + { N_("JobStatus"), "s"}, /* 9 */ + { N_("VolumeName"), "s"}, /* 10 */ + { N_("Device"), "s"}, /* 11 */ + + { NULL, NULL} +}; + + +/* Writable variables */ +static struct s_vars setvars[] = { + { N_("set_events"), NULL}, + { N_("JobReport"), "s"}, + { N_("write"), "s"}, + + { NULL, NULL} +}; + + +/* Return Job variables */ +PyObject *job_getattr(PyObject *self, char *attrname) +{ + JCR *jcr; + bool found = false; + int i; + char buf[10]; + char errmsg[200]; + + Dmsg1(100, "In job_getattr=%s\n", attrname); + jcr = get_jcr_from_PyObject(self); + if (!jcr) { + bstrncpy(errmsg, "Job pointer not found.", sizeof(errmsg)); + goto bail_out; + } + + for (i=0; getvars[i].name; i++) { + if (strcmp(getvars[i].name, attrname) == 0) { + found = true; + break; + } + } + if (!found) { + goto not_found; + } + switch (i) { + case 0: /* Job */ + return Py_BuildValue(getvars[i].fmt, jcr->job_name); /* Non-unique name */ + case 1: /* SD's name */ + return Py_BuildValue(getvars[i].fmt, my_name); + case 2: /* level */ + return Py_BuildValue(getvars[i].fmt, job_level_to_str(jcr->JobLevel)); + case 3: /* type */ + return Py_BuildValue(getvars[i].fmt, job_type_to_str(jcr->JobType)); + case 4: /* JobId */ + return Py_BuildValue(getvars[i].fmt, jcr->JobId); + case 5: /* Client */ + return Py_BuildValue(getvars[i].fmt, jcr->client_name); + case 6: /* Pool */ + return Py_BuildValue(getvars[i].fmt, jcr->dcr->pool_name); + case 7: /* MediaType */ + return Py_BuildValue(getvars[i].fmt, jcr->dcr->media_type); + case 8: /* JobName */ + return Py_BuildValue(getvars[i].fmt, jcr->Job); + case 9: /* JobStatus */ + buf[1] = 0; + buf[0] = jcr->JobStatus; + return Py_BuildValue(getvars[i].fmt, buf); + case 10: + return Py_BuildValue(getvars[i].fmt, jcr->dcr->VolumeName); + 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); + return NULL; +} + +int job_setattr(PyObject *self, char *attrname, PyObject *value) +{ + JCR *jcr; + bool found = false; + char *strval = NULL; + char buf[200]; + char *errmsg; + int i; + + Dmsg2(100, "In job_setattr=%s val=%p.\n", attrname, value); + if (value == NULL) { /* Cannot delete variables */ + bsnprintf(buf, sizeof(buf), "Cannot delete attribute %s", attrname); + errmsg = buf; + goto bail_out; + } + jcr = get_jcr_from_PyObject(self); + if (!jcr) { + errmsg = "Job pointer not found."; + goto bail_out; + } + + /* Find attribute name in list */ + for (i=0; setvars[i].name; i++) { + if (strcmp(setvars[i].name, attrname) == 0) { + found = true; + break; + } + } + if (!found) { + goto not_found; + } + /* Get argument value ***FIXME*** handle other formats */ + if (setvars[i].fmt != NULL) { + if (!PyArg_Parse(value, setvars[i].fmt, &strval)) { + PyErr_SetString(PyExc_TypeError, "Read-only attribute"); + return -1; + } + } + switch (i) { + case 0: /* set_events */ + return set_job_events(self, value); + case 1: /* JobReport */ + case 2: /* write */ + Jmsg(jcr, M_INFO, 0, "%s", strval); + return 0; + } +not_found: + bsnprintf(buf, sizeof(buf), "Cannot find attribute %s", attrname); + errmsg = buf; +bail_out: + PyErr_SetString(PyExc_AttributeError, errmsg); + return -1; +} + + +static int 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; + } + 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_INCREF(eObject); + jcr->Python_events = (void *)eObject; /* set new events */ + + return 0; +} + + +int generate_job_event(JCR *jcr, const char *event) +{ + PyObject *method = NULL; + PyObject *Job = (PyObject *)jcr->Python_job; + PyObject *result = NULL; + int stat = 0; + + if (!Job) { + return 0; + } + + PyEval_AcquireLock(); + + PyObject *events = (PyObject *)jcr->Python_events; + method = find_method(events, method, event); + if (!method) { + goto bail_out; + } + + bstrncpy(jcr->event, event, sizeof(jcr->event)); + result = PyObject_CallFunction(method, "O", Job); + jcr->event[0] = 0; /* no event in progress */ + if (result == NULL) { + if (PyErr_Occurred()) { + PyErr_Print(); + Dmsg1(000, "Error in Python method %s\n", event); + } + } else { + stat = 1; + } + Py_XDECREF(result); + +bail_out: + PyEval_ReleaseLock(); + return stat; +} + + +#else + +/* Dummy if Python not configured */ +int generate_job_event(JCR *jcr, const char *event) +{ return 1; } + + +#endif /* HAVE_PYTHON */ diff --git a/bacula/src/stored/stored.c b/bacula/src/stored/stored.c index fd7c09dba1..a20be7cf50 100644 --- a/bacula/src/stored/stored.c +++ b/bacula/src/stored/stored.c @@ -185,11 +185,9 @@ int main (int argc, char *argv[]) parse_config(configfile); -#ifdef HAVE_TLS if (init_tls() != 0) { Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("TLS library initialization failed.\n")); } -#endif if (!check_resources()) { Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile); diff --git a/bacula/src/version.h b/bacula/src/version.h index f3881e505e..2e73fb83aa 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #undef VERSION -#define VERSION "1.37.14" -#define BDATE "26 April 2005" -#define LSMDATE "26Apr05" +#define VERSION "1.37.15" +#define BDATE "30 April 2005" +#define LSMDATE "30Apr05" /* Debug flags */ #undef DEBUG -- 2.39.5