"""
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
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
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
"""
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
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)
"""
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
# Pass output back to Bacula
def write(self, text):
self.job.write(text)
-
/* #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
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);
exit(1);
}
already_here = true;
-#ifdef HAVE_TLS
cleanup_tls();
-#endif
free_pool_memory(args);
con_term();
(void)WSACleanup(); /* Cleanup Windows sockets */
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 \
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 \
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);
+++ /dev/null
-/*
- *
- * Bacula interface to Python for the Director
- *
- * Kern Sibbald, November MMIV
- *
- * Version $Id$
- *
- */
-
-/*
- Copyright (C) 2004-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 "dird.h"
-
-#ifdef HAVE_PYTHON
-#undef _POSIX_C_SOURCE
-#include <Python.h>
-
-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 */
-};
-
-
-struct s_vars {
- const char *name;
- char *fmt;
-};
-
-/* Read-only variables */
-static struct s_vars vars[] = {
- { N_("Job"), "s"},
- { N_("DirName"), "s"},
- { N_("Level"), "s"},
- { N_("Type"), "s"},
- { N_("JobId"), "i"},
- { N_("Client"), "s"},
- { N_("NumVols"), "i"},
- { N_("Pool"), "s"},
- { N_("Storage"), "s"},
- { N_("Catalog"), "s"},
- { N_("MediaType"), "s"},
- { N_("JobName"), "s"},
- { N_("JobStatus"), "s"},
-
- { NULL, NULL}
-};
-
-/* Return Job variables */
-static PyObject *job_get(PyObject *self, PyObject *args)
-{
- JCR *jcr;
- char *item;
- bool found = false;
- int i;
- char buf[10];
-
- Dmsg0(100, "In job_get.\n");
- 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->hdr.name);
- case 1: /* Director'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->hdr.name);
- case 6: /* NumVols */
- return Py_BuildValue(vars[i].fmt, jcr->NumVols);
- case 7: /* Pool */
- return Py_BuildValue(vars[i].fmt, jcr->pool->hdr.name);
- case 8: /* Storage */
- return Py_BuildValue(vars[i].fmt, jcr->store->hdr.name);
- case 9:
- return Py_BuildValue(vars[i].fmt, jcr->catalog->hdr.name);
- case 10: /* MediaType */
- return Py_BuildValue(vars[i].fmt, jcr->store->media_type);
- case 11: /* JobName */
- return Py_BuildValue(vars[i].fmt, jcr->Job);
- case 12: /* JobStatus */
- buf[1] = 0;
- buf[0] = jcr->JobStatus;
- return Py_BuildValue(vars[i].fmt, buf);
- }
- return NULL;
-}
-
-/* Set Job variables */
-static PyObject *job_set(PyObject *self, PyObject *args, PyObject *keyw)
-{
- 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;
- }
- jcr = get_jcr_from_PyObject(self);
-
- if (msg) {
- Jmsg(jcr, M_INFO, 0, "%s", msg);
- }
-
- if (!VolumeName) {
- Dmsg1(100, "No VolumeName. Event=%s\n", jcr->event);
- } else {
- Dmsg2(100, "Vol=%s Event=%s\n", VolumeName, jcr->event);
- }
- /* 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 */
- }
- return Py_BuildValue("i", 1);
-}
-
-static PyObject *set_job_events(PyObject *self, PyObject *args)
-{
- PyObject *eObject;
- JCR *jcr;
-
- Dmsg0(100, "In set_job_events.\n");
- if (!PyArg_ParseTuple(args, "O:set_events", &eObject)) {
- return NULL;
- }
- 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;
-}
-
-/* Run a Bacula command */
-static PyObject *jcr_run(PyObject *self, PyObject *args)
-{
- JCR *jcr;
- char *item;
- int stat;
-
- if (!PyArg_ParseTuple(args, "s:get", &item)) {
- return NULL;
- }
- jcr = get_jcr_from_PyObject(self);
- UAContext *ua = new_ua_context(jcr);
- ua->batch = true;
- pm_strcpy(ua->cmd, item); /* copy command */
- parse_ua_args(ua); /* parse command */
- stat = run_cmd(ua, ua->cmd);
- free_ua_context(ua);
- return Py_BuildValue("i", stat);
-}
-
-
-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;
-}
-
-bool python_set_prog(JCR*, char const*) { return false; }
-
-#else
-
-/* Dummy if Python not configured */
-int generate_job_event(JCR *jcr, const char *event) { return 1; }
-
-
-#endif /* HAVE_PYTHON */
--- /dev/null
+/*
+ *
+ * Bacula interface to Python for the Director
+ *
+ * Kern Sibbald, November MMIV
+ *
+ * Version $Id$
+ *
+ */
+
+/*
+ Copyright (C) 2004-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 "dird.h"
+
+#ifdef HAVE_PYTHON
+#undef _POSIX_C_SOURCE
+#include <Python.h>
+
+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 int job_run(PyObject *self, PyObject *arg);
+
+struct s_vars {
+ const char *name;
+ char *fmt;
+};
+
+/* Read-only variables */
+static struct s_vars getvars[] = {
+ { N_("Job"), "s"},
+ { N_("DirName"), "s"},
+ { N_("Level"), "s"},
+ { N_("Type"), "s"},
+ { N_("JobId"), "i"},
+ { N_("Client"), "s"},
+ { N_("NumVols"), "i"},
+ { N_("Pool"), "s"},
+ { N_("Storage"), "s"},
+ { N_("Catalog"), "s"},
+ { N_("MediaType"), "s"},
+ { N_("JobName"), "s"},
+ { N_("JobStatus"), "s"},
+
+ { 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 */
+/* Returns: NULL if error
+ * PyObject * return value if OK
+ */
+PyObject *job_getattr(PyObject *self, char *attrname)
+{
+ JCR *jcr;
+ bool found = false;
+ int i;
+ char buf[10];
+ char errmsg[200];
+
+ Dmsg0(100, "In job_getattr.\n");
+ 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->hdr.name);
+ case 1: /* Director'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->hdr.name);
+ case 6: /* NumVols */
+ return Py_BuildValue(getvars[i].fmt, jcr->NumVols);
+ case 7: /* Pool */
+ return Py_BuildValue(getvars[i].fmt, jcr->pool->hdr.name);
+ case 8: /* Storage */
+ return Py_BuildValue(getvars[i].fmt, jcr->store->hdr.name);
+ case 9:
+ return Py_BuildValue(getvars[i].fmt, jcr->catalog->hdr.name);
+ case 10: /* MediaType */
+ return Py_BuildValue(getvars[i].fmt, jcr->store->media_type);
+ case 11: /* JobName */
+ return Py_BuildValue(getvars[i].fmt, jcr->Job);
+ case 12: /* JobStatus */
+ buf[1] = 0;
+ 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);
+ return NULL;
+}
+
+
+/* Set Job variables */
+/* Returns: 0 for OK
+ * -1 for error
+ */
+int job_setattr(PyObject *self, char *attrname, PyObject *value)
+{
+ JCR *jcr;
+ 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 (!jcr) {
+ 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 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: /* 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;
+ }
+ }
+bail_out:
+ PyErr_SetString(PyExc_AttributeError, attrname);
+ 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)) {
+ return -1;
+ }
+ jcr = get_jcr_from_PyObject(self);
+ Py_XDECREF((PyObject *)jcr->Python_events);
+ Py_INCREF(eObject);
+ jcr->Python_events = (void *)eObject;
+ return 0; /* good return */
+}
+
+/* Run a Bacula command */
+static int job_run(PyObject *self, PyObject *arg)
+{
+ JCR *jcr;
+ char *item;
+ int stat;
+
+ if (!PyArg_Parse(arg, "s", &item)) {
+ return -1;
+ }
+ jcr = get_jcr_from_PyObject(self);
+ UAContext *ua = new_ua_context(jcr);
+ ua->batch = true;
+ pm_strcpy(ua->cmd, item); /* copy command */
+ parse_ua_args(ua); /* parse command */
+ stat = run_cmd(ua, ua->cmd);
+ free_ua_context(ua);
+ /* ***FIXME*** check stat */
+ 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;
+}
+
+bool python_set_prog(JCR*, char const*) { return false; }
+
+#else
+
+/* Dummy if Python not configured */
+int generate_job_event(JCR *jcr, const char *event) { return 1; }
+
+
+#endif /* HAVE_PYTHON */
#
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
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);
+++ /dev/null
-/*
- *
- * Bacula interface to Python for the File Daemon
- *
- * Kern Sibbald, March 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 "filed.h"
-
-#ifdef HAVE_PYTHON
-#undef _POSIX_C_SOURCE
-#include <Python.h>
-
-/* External function pointers to be set */
-extern bool (*python_set_prog)(JCR *jcr, const char *prog);
-extern int (*python_open)(BFILE *bfd, const char *fname, int flags, mode_t mode);
-extern int (*python_close)(BFILE *bfd);
-extern ssize_t (*python_read)(BFILE *bfd, void *buf, size_t count);
-
-
-extern JCR *get_jcr_from_PyObject(PyObject *self);
-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);
-
-bool my_python_set_prog(JCR *jcr, const char *prog);
-int my_python_open(BFILE *bfd, const char *fname, int flags, mode_t mode);
-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[] = {
- { N_("FDName"), "s"}, /* 0 */
- { N_("Level"), "s"}, /* 1 */
- { N_("Type"), "s"}, /* 2 */
- { N_("JobId"), "i"}, /* 3 */
- { N_("Client"), "s"}, /* 4 */
- { N_("JobName"), "s"}, /* 5 */
- { N_("JobStatus"), "s"}, /* 6 */
-
- { NULL, NULL}
-};
-
-/* Return Job variables */
-PyObject *job_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: /* FD's name */
- return Py_BuildValue(vars[i].fmt, my_name);
- case 1: /* level */
- return Py_BuildValue(vars[i].fmt, job_level_to_str(jcr->JobLevel));
- case 2: /* type */
- return Py_BuildValue(vars[i].fmt, job_type_to_str(jcr->JobType));
- case 3: /* JobId */
- return Py_BuildValue(vars[i].fmt, jcr->JobId);
- case 4: /* Client */
- return Py_BuildValue(vars[i].fmt, jcr->client_name);
- case 5: /* JobName */
- return Py_BuildValue(vars[i].fmt, jcr->Job);
- case 6: /* JobStatus */
- buf[1] = 0;
- buf[0] = jcr->JobStatus;
- return Py_BuildValue(vars[i].fmt, buf);
- }
- return NULL;
-}
-
-/* Set Job variables */
-PyObject *job_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_job_events(PyObject *self, PyObject *args)
-{
- PyObject *eObject;
- JCR *jcr;
-
- Dmsg0(100, "In set_job_events.\n");
-
- if (!PyArg_ParseTuple(args, "O:set_events", &eObject)) {
- return NULL;
- }
- jcr = get_jcr_from_PyObject(self);
- Py_XDECREF((PyObject *)jcr->Python_events);
- Py_INCREF(eObject);
- jcr->Python_events = (void *)eObject;
-
- /* Set function pointers to call here */
- python_set_prog = my_python_set_prog;
- python_open = my_python_open;
- python_close = my_python_close;
- python_read = my_python_read;
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-/* 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)
-{
- 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;
-}
-
-
-bool my_python_set_prog(JCR *jcr, const char *prog)
-{
- PyObject *events = (PyObject *)jcr->Python_events;
- BFILE *bfd = &jcr->ff->bfd;
- char method[MAX_NAME_LENGTH];
-
- if (!events) {
- return false;
- }
- bstrncpy(method, prog, sizeof(method));
- bstrncat(method, "_", sizeof(method));
- bstrncat(method, "open", sizeof(method));
- bfd->pio.fo = find_method(events, bfd->pio.fo, method);
- bstrncpy(method, prog, sizeof(method));
- bstrncat(method, "_", sizeof(method));
- bstrncat(method, "read", sizeof(method));
- bfd->pio.fr = find_method(events, bfd->pio.fr, method);
- bstrncpy(method, prog, sizeof(method));
- bstrncat(method, "_", sizeof(method));
- bstrncat(method, "close", sizeof(method));
- bfd->pio.fc = find_method(events, bfd->pio.fc, method);
- return bfd->pio.fo && bfd->pio.fr && bfd->pio.fc;
-}
-
-int my_python_open(BFILE *bfd, const char *fname, int flags, mode_t mode)
-{
- return -1;
-}
-
-int my_python_close(BFILE *bfd)
-{
- return 0;
-}
-
-ssize_t my_python_read(BFILE *bfd, void *buf, size_t count)
-{
- return -1;
-}
-
-#else
-
-/* Dummy if Python not configured */
-int generate_job_event(JCR *jcr, const char *event)
-{ return 1; }
-
-
-#endif /* HAVE_PYTHON */
--- /dev/null
+/*
+ *
+ * Bacula interface to Python for the File Daemon
+ *
+ * Kern Sibbald, March 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 "filed.h"
+
+#ifdef HAVE_PYTHON
+#undef _POSIX_C_SOURCE
+#include <Python.h>
+
+/* External function pointers to be set */
+extern bool (*python_set_prog)(JCR *jcr, const char *prog);
+extern int (*python_open)(BFILE *bfd, const char *fname, int flags, mode_t mode);
+extern int (*python_close)(BFILE *bfd);
+extern ssize_t (*python_read)(BFILE *bfd, void *buf, size_t count);
+
+
+extern JCR *get_jcr_from_PyObject(PyObject *self);
+extern PyObject *find_method(PyObject *eventsObject, PyObject *method,
+ const char *name);
+
+/* Forward referenced functions */
+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);
+int my_python_close(BFILE *bfd);
+ssize_t my_python_read(BFILE *bfd, void *buf, size_t count);
+
+
+struct s_vars {
+ const char *name;
+ char *fmt;
+};
+
+/* Read-only variables */
+static struct s_vars getvars[] = {
+ { N_("FDName"), "s"}, /* 0 */
+ { N_("Level"), "s"}, /* 1 */
+ { N_("Type"), "s"}, /* 2 */
+ { N_("JobId"), "i"}, /* 3 */
+ { N_("Client"), "s"}, /* 4 */
+ { N_("JobName"), "s"}, /* 5 */
+ { N_("JobStatus"), "s"}, /* 6 */
+
+ { 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];
+
+ 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: /* FD's name */
+ return Py_BuildValue(getvars[i].fmt, my_name);
+ case 1: /* level */
+ return Py_BuildValue(getvars[i].fmt, job_level_to_str(jcr->JobLevel));
+ case 2: /* type */
+ return Py_BuildValue(getvars[i].fmt, job_type_to_str(jcr->JobType));
+ case 3: /* JobId */
+ return Py_BuildValue(getvars[i].fmt, jcr->JobId);
+ case 4: /* Client */
+ return Py_BuildValue(getvars[i].fmt, jcr->client_name);
+ case 5: /* JobName */
+ return Py_BuildValue(getvars[i].fmt, jcr->Job);
+ case 6: /* JobStatus */
+ buf[1] = 0;
+ 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);
+ 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) {
+ 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 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 */
+
+ /* Set function pointers to call here */
+ python_set_prog = my_python_set_prog;
+ python_open = my_python_open;
+ python_close = my_python_close;
+ python_read = my_python_read;
+
+ 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;
+}
+
+
+bool my_python_set_prog(JCR *jcr, const char *prog)
+{
+ PyObject *events = (PyObject *)jcr->Python_events;
+ BFILE *bfd = &jcr->ff->bfd;
+ char method[MAX_NAME_LENGTH];
+
+ if (!events) {
+ return false;
+ }
+ bstrncpy(method, prog, sizeof(method));
+ bstrncat(method, "_", sizeof(method));
+ bstrncat(method, "open", sizeof(method));
+ bfd->pio.fo = find_method(events, bfd->pio.fo, method);
+ bstrncpy(method, prog, sizeof(method));
+ bstrncat(method, "_", sizeof(method));
+ bstrncat(method, "read", sizeof(method));
+ bfd->pio.fr = find_method(events, bfd->pio.fr, method);
+ bstrncpy(method, prog, sizeof(method));
+ bstrncat(method, "_", sizeof(method));
+ bstrncat(method, "close", sizeof(method));
+ bfd->pio.fc = find_method(events, bfd->pio.fc, method);
+ return bfd->pio.fo && bfd->pio.fr && bfd->pio.fc;
+}
+
+int my_python_open(BFILE *bfd, const char *fname, int flags, mode_t mode)
+{
+ return -1;
+}
+
+int my_python_close(BFILE *bfd)
+{
+ return 0;
+}
+
+ssize_t my_python_read(BFILE *bfd, void *buf, size_t count)
+{
+ return -1;
+}
+
+#else
+
+/* Dummy if Python not configured */
+int generate_job_event(JCR *jcr, const char *event)
+{ return 1; }
+
+
+#endif /* HAVE_PYTHON */
#include <Python.h>
/* 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 */
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;
}
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");
}
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();
} 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;
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:
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
/*
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 \
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
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
}
}
bail_out:
+ generate_daemon_event(jcr, "JobEnd");
dequeue_messages(jcr); /* send any queued messages */
bnet_sig(bs, BNET_TERMINATE);
free_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;
}
+++ /dev/null
-/*
- *
- * 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 <Python.h>
-
-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 */
--- /dev/null
+/*
+ *
+ * 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 <Python.h>
+
+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 */
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);
/* */
#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