3 * Bacula interface to Python for the File Daemon
5 * Kern Sibbald, March MMV
12 Copyright (C) 2005 Kern Sibbald
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of
17 the License, or (at your option) any later version.
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
24 You should have received a copy of the GNU General Public
25 License along with this program; if not, write to the Free
26 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
35 #undef _POSIX_C_SOURCE
38 /* External function pointers to be set */
39 extern bool (*python_set_prog)(JCR *jcr, const char *prog);
40 extern int (*python_open)(BFILE *bfd, const char *fname, int flags, mode_t mode);
41 extern int (*python_close)(BFILE *bfd);
42 extern ssize_t (*python_read)(BFILE *bfd, void *buf, size_t count);
45 extern JCR *get_jcr_from_PyObject(PyObject *self);
46 extern PyObject *find_method(PyObject *eventsObject, PyObject *method,
49 /* Forward referenced functions */
50 static PyObject *job_get(PyObject *self, PyObject *args);
51 static PyObject *job_write(PyObject *self, PyObject *args);
52 static PyObject *job_set(PyObject *self, PyObject *args, PyObject *keyw);
53 static PyObject *set_job_events(PyObject *self, PyObject *args);
55 bool my_python_set_prog(JCR *jcr, const char *prog);
56 int my_python_open(BFILE *bfd, const char *fname, int flags, mode_t mode);
57 int my_python_close(BFILE *bfd);
58 ssize_t my_python_read(BFILE *bfd, void *buf, size_t count);
61 /* Define Job entry points */
62 PyMethodDef JobMethods[] = {
63 {"get", job_get, METH_VARARGS, "Get Job variables."},
64 {"set", (PyCFunction)job_set, METH_VARARGS|METH_KEYWORDS,
65 "Set Job variables."},
66 {"set_events", set_job_events, METH_VARARGS, "Define Job events."},
67 {"write", job_write, METH_VARARGS, "Write output."},
68 {NULL, NULL, 0, NULL} /* last item */
76 /* Read-only variables */
77 static struct s_vars vars[] = {
78 { N_("FDName"), "s"}, /* 0 */
79 { N_("Level"), "s"}, /* 1 */
80 { N_("Type"), "s"}, /* 2 */
81 { N_("JobId"), "i"}, /* 3 */
82 { N_("Client"), "s"}, /* 4 */
83 { N_("JobName"), "s"}, /* 5 */
84 { N_("JobStatus"), "s"}, /* 6 */
89 /* Return Job variables */
90 PyObject *job_get(PyObject *self, PyObject *args)
98 if (!PyArg_ParseTuple(args, "s:get", &item)) {
101 jcr = get_jcr_from_PyObject(self);
102 for (i=0; vars[i].name; i++) {
103 if (strcmp(vars[i].name, item) == 0) {
112 case 0: /* FD's name */
113 return Py_BuildValue(vars[i].fmt, my_name);
115 return Py_BuildValue(vars[i].fmt, job_level_to_str(jcr->JobLevel));
117 return Py_BuildValue(vars[i].fmt, job_type_to_str(jcr->JobType));
119 return Py_BuildValue(vars[i].fmt, jcr->JobId);
121 return Py_BuildValue(vars[i].fmt, jcr->client_name);
122 case 5: /* JobName */
123 return Py_BuildValue(vars[i].fmt, jcr->Job);
124 case 6: /* JobStatus */
126 buf[0] = jcr->JobStatus;
127 return Py_BuildValue(vars[i].fmt, buf);
132 /* Set Job variables */
133 PyObject *job_set(PyObject *self, PyObject *args, PyObject *keyw)
137 static char *kwlist[] = {"JobReport", NULL};
139 if (!PyArg_ParseTupleAndKeywords(args, keyw, "|s:set", kwlist,
143 jcr = get_jcr_from_PyObject(self);
146 Jmsg(jcr, M_INFO, 0, "%s", msg);
148 return Py_BuildValue("i", 1);
152 static PyObject *set_job_events(PyObject *self, PyObject *args)
157 Dmsg0(100, "In set_job_events.\n");
159 if (!PyArg_ParseTuple(args, "O:set_events", &eObject)) {
162 jcr = get_jcr_from_PyObject(self);
163 Py_XDECREF((PyObject *)jcr->Python_events);
165 jcr->Python_events = (void *)eObject;
167 /* Set function pointers to call here */
168 python_set_prog = my_python_set_prog;
169 python_open = my_python_open;
170 python_close = my_python_close;
171 python_read = my_python_read;
177 /* Write text to job output */
178 static PyObject *job_write(PyObject *self, PyObject *args)
182 if (!PyArg_ParseTuple(args, "s:write", &text)) {
186 JCR *jcr = get_jcr_from_PyObject(self);
187 Jmsg(jcr, M_INFO, 0, "%s", text);
194 int generate_job_event(JCR *jcr, const char *event)
196 PyObject *method = NULL;
197 PyObject *Job = (PyObject *)jcr->Python_job;
198 PyObject *result = NULL;
205 PyEval_AcquireLock();
207 PyObject *events = (PyObject *)jcr->Python_events;
208 method = find_method(events, method, event);
213 bstrncpy(jcr->event, event, sizeof(jcr->event));
214 result = PyObject_CallFunction(method, "O", Job);
215 jcr->event[0] = 0; /* no event in progress */
216 if (result == NULL) {
217 if (PyErr_Occurred()) {
219 Dmsg1(000, "Error in Python method %s\n", event);
227 PyEval_ReleaseLock();
232 bool my_python_set_prog(JCR *jcr, const char *prog)
234 PyObject *events = (PyObject *)jcr->Python_events;
235 BFILE *bfd = &jcr->ff->bfd;
236 char method[MAX_NAME_LENGTH];
241 bstrncpy(method, prog, sizeof(method));
242 bstrncat(method, "_", sizeof(method));
243 bstrncat(method, "open", sizeof(method));
244 bfd->pio.fo = find_method(events, bfd->pio.fo, method);
245 bstrncpy(method, prog, sizeof(method));
246 bstrncat(method, "_", sizeof(method));
247 bstrncat(method, "read", sizeof(method));
248 bfd->pio.fr = find_method(events, bfd->pio.fr, method);
249 bstrncpy(method, prog, sizeof(method));
250 bstrncat(method, "_", sizeof(method));
251 bstrncat(method, "close", sizeof(method));
252 bfd->pio.fc = find_method(events, bfd->pio.fc, method);
253 return bfd->pio.fo && bfd->pio.fr && bfd->pio.fc;
256 int my_python_open(BFILE *bfd, const char *fname, int flags, mode_t mode)
261 int my_python_close(BFILE *bfd)
266 ssize_t my_python_read(BFILE *bfd, void *buf, size_t count)
273 /* Dummy if Python not configured */
274 int generate_job_event(JCR *jcr, const char *event)
278 #endif /* HAVE_PYTHON */