3 * Bacula interface to Python for the File Daemon
5 * Kern Sibbald, March MMV
11 Copyright (C) 2005-2006 Kern Sibbald
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License
15 version 2 as amended with additional clauses defined in the
16 file LICENSE in the main source directory.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 the file LICENSE for additional details.
29 #undef _POSIX_C_SOURCE
32 /* External function pointers to be set */
33 extern bool (*python_set_prog)(JCR *jcr, const char *prog);
34 extern int (*python_open)(BFILE *bfd, const char *fname, int flags, mode_t mode);
35 extern int (*python_close)(BFILE *bfd);
36 extern ssize_t (*python_read)(BFILE *bfd, void *buf, size_t count);
39 extern JCR *get_jcr_from_PyObject(PyObject *self);
40 extern PyObject *find_method(PyObject *eventsObject, PyObject *method,
43 /* Forward referenced functions */
44 static PyObject *set_job_events(PyObject *self, PyObject *arg);
45 static PyObject *job_write(PyObject *self, PyObject *arg);
47 PyMethodDef JobMethods[] = {
48 {"set_events", set_job_events, METH_VARARGS, "Set Job events"},
49 {"write", job_write, METH_VARARGS, "Write to output"},
50 {NULL, NULL, 0, NULL} /* last item */
54 bool my_python_set_prog(JCR *jcr, const char *prog);
55 int my_python_open(BFILE *bfd, const char *fname, int flags, mode_t mode);
56 int my_python_close(BFILE *bfd);
57 ssize_t my_python_read(BFILE *bfd, void *buf, size_t count);
65 /* Read-only variables */
66 static struct s_vars getvars[] = {
67 { NT_("FDName"), "s"}, /* 0 */
68 { NT_("Level"), "s"}, /* 1 */
69 { NT_("Type"), "s"}, /* 2 */
70 { NT_("JobId"), "i"}, /* 3 */
71 { NT_("Client"), "s"}, /* 4 */
72 { NT_("JobName"), "s"}, /* 5 */
73 { NT_("JobStatus"), "s"}, /* 6 */
78 /* Writable variables */
79 static struct s_vars setvars[] = {
80 { NT_("JobReport"), "s"},
85 /* Return Job variables */
86 PyObject *job_getattr(PyObject *self, char *attrname)
94 jcr = get_jcr_from_PyObject(self);
96 bstrncpy(errmsg, _("Job pointer not found."), sizeof(errmsg));
99 for (i=0; getvars[i].name; i++) {
100 if (strcmp(getvars[i].name, attrname) == 0) {
106 /* Try our methods */
107 return Py_FindMethod(JobMethods, self, attrname);
110 case 0: /* FD's name */
111 return Py_BuildValue(getvars[i].fmt, my_name);
113 return Py_BuildValue(getvars[i].fmt, job_level_to_str(jcr->JobLevel));
115 return Py_BuildValue(getvars[i].fmt, job_type_to_str(jcr->JobType));
117 return Py_BuildValue(getvars[i].fmt, jcr->JobId);
119 return Py_BuildValue(getvars[i].fmt, jcr->client_name);
120 case 5: /* JobName */
121 return Py_BuildValue(getvars[i].fmt, jcr->Job);
122 case 6: /* JobStatus */
124 buf[0] = jcr->JobStatus;
125 return Py_BuildValue(getvars[i].fmt, buf);
127 bsnprintf(errmsg, sizeof(errmsg), _("Attribute %s not found."), attrname);
129 PyErr_SetString(PyExc_AttributeError, errmsg);
133 int job_setattr(PyObject *self, char *attrname, PyObject *value)
142 Dmsg2(100, "In job_setattr=%s val=%p.\n", attrname, value);
143 if (value == NULL) { /* Cannot delete variables */
144 bsnprintf(buf, sizeof(buf), _("Cannot delete attribute %s"), attrname);
148 jcr = get_jcr_from_PyObject(self);
150 errmsg = _("Job pointer not found.");
154 /* Find attribute name in list */
155 for (i=0; setvars[i].name; i++) {
156 if (strcmp(setvars[i].name, attrname) == 0) {
162 bsnprintf(buf, sizeof(buf), _("Cannot find attribute %s"), attrname);
166 /* Get argument value ***FIXME*** handle other formats */
167 if (setvars[i].fmt != NULL) {
168 if (!PyArg_Parse(value, setvars[i].fmt, &strval)) {
169 PyErr_SetString(PyExc_TypeError, _("Read-only attribute"));
174 case 0: /* JobReport */
175 Jmsg(jcr, M_INFO, 0, "%s", strval);
178 bsnprintf(buf, sizeof(buf), _("Cannot find attribute %s"), attrname);
181 PyErr_SetString(PyExc_AttributeError, errmsg);
186 static PyObject *job_write(PyObject *self, PyObject *args)
190 if (!PyArg_ParseTuple(args, "s:write", &text)) {
191 Dmsg0(000, "Parse tuple error in job_write\n");
195 Jmsg(NULL, M_INFO, 0, "%s", text);
202 static PyObject *set_job_events(PyObject *self, PyObject *arg)
207 Dmsg0(100, "In set_job_events.\n");
208 if (!PyArg_ParseTuple(arg, "O", &eObject)) {
209 Dmsg0(000, "Parse error looking for Object argument\n");
212 jcr = get_jcr_from_PyObject(self);
214 PyErr_SetString(PyExc_AttributeError, _("Job pointer not found."));
217 Py_XDECREF((PyObject *)jcr->Python_events); /* release any old events Object */
219 jcr->Python_events = (void *)eObject; /* set new events */
221 /* Set function pointers to call here */
222 python_set_prog = my_python_set_prog;
223 python_open = my_python_open;
224 python_close = my_python_close;
225 python_read = my_python_read;
232 int generate_job_event(JCR *jcr, const char *event)
234 PyObject *method = NULL;
235 PyObject *Job = (PyObject *)jcr->Python_job;
236 PyObject *events = (PyObject *)jcr->Python_events;
237 PyObject *result = NULL;
240 if (!Job || !events) {
245 // PyEval_AcquireLock();
247 method = find_method(events, method, event);
252 bstrncpy(jcr->event, event, sizeof(jcr->event));
253 result = PyObject_CallFunction(method, "O", Job);
254 jcr->event[0] = 0; /* no event in progress */
255 if (result == NULL) {
256 if (PyErr_Occurred()) {
258 Dmsg1(000, "Error in Python method %s\n", event);
267 // PyEval_ReleaseLock();
272 bool my_python_set_prog(JCR *jcr, const char *prog)
274 PyObject *events = (PyObject *)jcr->Python_events;
275 BFILE *bfd = &jcr->ff->bfd;
276 char method[MAX_NAME_LENGTH];
281 bstrncpy(method, prog, sizeof(method));
282 bstrncat(method, "_", sizeof(method));
283 bstrncat(method, "open", sizeof(method));
284 bfd->pio.fo = find_method(events, bfd->pio.fo, method);
285 bstrncpy(method, prog, sizeof(method));
286 bstrncat(method, "_", sizeof(method));
287 bstrncat(method, "read", sizeof(method));
288 bfd->pio.fr = find_method(events, bfd->pio.fr, method);
289 bstrncpy(method, prog, sizeof(method));
290 bstrncat(method, "_", sizeof(method));
291 bstrncat(method, "close", sizeof(method));
292 bfd->pio.fc = find_method(events, bfd->pio.fc, method);
293 return bfd->pio.fo && bfd->pio.fr && bfd->pio.fc;
296 int my_python_open(BFILE *bfd, const char *fname, int flags, mode_t mode)
301 int my_python_close(BFILE *bfd)
306 ssize_t my_python_read(BFILE *bfd, void *buf, size_t count)
313 /* Dummy if Python not configured */
314 int generate_job_event(JCR *jcr, const char *event)
318 #endif /* HAVE_PYTHON */