]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/pythonfd.c
8e4469956d68ad8222c194ed2b6395d5913623aa
[bacula/bacula] / bacula / src / filed / pythonfd.c
1 /*
2  *
3  * Bacula interface to Python for the File Daemon
4  *
5  * Kern Sibbald, March MMV
6  *
7  *   Version $Id$
8  *
9  */
10 /*
11    Bacula® - The Network Backup Solution
12
13    Copyright (C) 2005-2006 Free Software Foundation Europe e.V.
14
15    The main author of Bacula is Kern Sibbald, with contributions from
16    many others, a complete list can be found in the file AUTHORS.
17    This program is Free Software; you can redistribute it and/or
18    modify it under the terms of version two of the GNU General Public
19    License as published by the Free Software Foundation plus additions
20    that are listed in the file LICENSE.
21
22    This program is distributed in the hope that it will be useful, but
23    WITHOUT ANY WARRANTY; without even the implied warranty of
24    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25    General Public License for more details.
26
27    You should have received a copy of the GNU General Public License
28    along with this program; if not, write to the Free Software
29    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30    02110-1301, USA.
31
32    Bacula® is a registered trademark of John Walker.
33    The licensor of Bacula is the Free Software Foundation Europe
34    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
35    Switzerland, email:ftf@fsfeurope.org.
36 */
37
38 #include "bacula.h"
39 #include "filed.h"
40
41 #ifdef HAVE_PYTHON
42 #undef _POSIX_C_SOURCE
43 #include <Python.h>
44
45 /* External function pointers to be set */
46 extern bool    (*python_set_prog)(JCR *jcr, const char *prog);
47 extern int     (*python_open)(BFILE *bfd, const char *fname, int flags, mode_t mode);
48 extern int     (*python_close)(BFILE *bfd);
49 extern ssize_t (*python_read)(BFILE *bfd, void *buf, size_t count);
50
51
52 extern JCR *get_jcr_from_PyObject(PyObject *self);
53 extern PyObject *find_method(PyObject *eventsObject, PyObject *method, 
54           const char *name);
55
56 /* Forward referenced functions */
57 static PyObject *set_job_events(PyObject *self, PyObject *arg);
58 static PyObject *job_write(PyObject *self, PyObject *arg);
59
60 PyMethodDef JobMethods[] = {
61     {"set_events", set_job_events, METH_VARARGS, "Set Job events"},
62     {"write", job_write, METH_VARARGS, "Write to output"},
63     {NULL, NULL, 0, NULL}             /* last item */
64 };
65
66
67 bool my_python_set_prog(JCR *jcr, const char *prog);
68 int my_python_open(BFILE *bfd, const char *fname, int flags, mode_t mode);
69 int my_python_close(BFILE *bfd);
70 ssize_t my_python_read(BFILE *bfd, void *buf, size_t count);
71
72
73 struct s_vars {
74    const char *name;
75    char *fmt;
76 };
77
78 /* Read-only variables */
79 static struct s_vars getvars[] = {
80    { NT_("FDName"),     "s"},          /* 0 */
81    { NT_("Level"),      "s"},          /* 1 */
82    { NT_("Type"),       "s"},          /* 2 */
83    { NT_("JobId"),      "i"},          /* 3 */
84    { NT_("Client"),     "s"},          /* 4 */
85    { NT_("JobName"),    "s"},          /* 5 */
86    { NT_("JobStatus"),  "s"},          /* 6 */
87
88    { NULL,             NULL}
89 };
90
91 /* Writable variables */
92 static struct s_vars setvars[] = {
93    { NT_("JobReport"),   "s"},
94
95    { NULL,             NULL}
96 };
97
98 /* Return Job variables */
99 PyObject *job_getattr(PyObject *self, char *attrname)
100 {
101    JCR *jcr;
102    bool found = false;
103    int i;
104    char buf[10];
105    char errmsg[200];
106
107    jcr = get_jcr_from_PyObject(self);
108    if (!jcr) {
109       bstrncpy(errmsg, _("Job pointer not found."), sizeof(errmsg));
110       goto bail_out;
111    }
112    for (i=0; getvars[i].name; i++) {
113       if (strcmp(getvars[i].name, attrname) == 0) {
114          found = true;
115          break;
116       }
117    }
118    if (!found) {
119       /* Try our methods */
120       return Py_FindMethod(JobMethods, self, attrname);
121    }
122    switch (i) {
123    case 0:                            /* FD's name */
124       return Py_BuildValue(getvars[i].fmt, my_name);
125    case 1:                            /* level */
126       return Py_BuildValue(getvars[i].fmt, job_level_to_str(jcr->JobLevel));
127    case 2:                            /* type */
128       return Py_BuildValue(getvars[i].fmt, job_type_to_str(jcr->JobType));
129    case 3:                            /* JobId */
130       return Py_BuildValue(getvars[i].fmt, jcr->JobId);
131    case 4:                            /* Client */
132       return Py_BuildValue(getvars[i].fmt, jcr->client_name);
133    case 5:                            /* JobName */
134       return Py_BuildValue(getvars[i].fmt, jcr->Job);
135    case 6:                            /* JobStatus */
136       buf[1] = 0;
137       buf[0] = jcr->JobStatus;
138       return Py_BuildValue(getvars[i].fmt, buf);
139    }
140    bsnprintf(errmsg, sizeof(errmsg), _("Attribute %s not found."), attrname);
141 bail_out:
142    PyErr_SetString(PyExc_AttributeError, errmsg);
143    return NULL;
144 }
145
146 int job_setattr(PyObject *self, char *attrname, PyObject *value)
147 {
148   JCR *jcr;
149    bool found = false;
150    char *strval = NULL;
151    char buf[200];
152    char *errmsg;
153    int i;
154
155    Dmsg2(100, "In job_setattr=%s val=%p.\n", attrname, value);
156    if (value == NULL) {                /* Cannot delete variables */
157       bsnprintf(buf, sizeof(buf), _("Cannot delete attribute %s"), attrname);
158       errmsg = buf;
159       goto bail_out;
160    }
161    jcr = get_jcr_from_PyObject(self);
162    if (!jcr) {
163       errmsg = _("Job pointer not found.");
164       goto bail_out;
165    }
166
167    /* Find attribute name in list */
168    for (i=0; setvars[i].name; i++) {
169       if (strcmp(setvars[i].name, attrname) == 0) {
170          found = true;
171          break;
172       }
173    }
174    if (!found) {
175       bsnprintf(buf, sizeof(buf), _("Cannot find attribute %s"), attrname);
176       errmsg = buf;
177       goto bail_out;
178    }
179    /* Get argument value ***FIXME*** handle other formats */
180    if (setvars[i].fmt != NULL) {
181       if (!PyArg_Parse(value, setvars[i].fmt, &strval)) {
182          PyErr_SetString(PyExc_TypeError, _("Read-only attribute"));
183          return -1;
184       }
185    }   
186    switch (i) {
187    case 0:                            /* JobReport */
188       Jmsg(jcr, M_INFO, 0, "%s", strval);
189       return 0;
190    }
191    bsnprintf(buf, sizeof(buf), _("Cannot find attribute %s"), attrname);
192    errmsg = buf;
193 bail_out:
194    PyErr_SetString(PyExc_AttributeError, errmsg);
195    return -1;
196 }
197
198
199 static PyObject *job_write(PyObject *self, PyObject *args)
200 {
201    char *text = NULL;
202
203    if (!PyArg_ParseTuple(args, "s:write", &text)) {
204       Dmsg0(000, "Parse tuple error in job_write\n");
205       return NULL;
206    }
207    if (text) {
208       Jmsg(NULL, M_INFO, 0, "%s", text);
209    }
210    Py_INCREF(Py_None);
211    return Py_None;
212 }
213
214
215 static PyObject *set_job_events(PyObject *self, PyObject *arg)
216 {
217    PyObject *eObject;
218    JCR *jcr;
219
220    Dmsg0(100, "In set_job_events.\n");
221    if (!PyArg_ParseTuple(arg, "O", &eObject)) {
222       Dmsg0(000, "Parse error looking for Object argument\n");
223       return NULL;
224    }
225    jcr = get_jcr_from_PyObject(self);
226    if (!jcr) {
227       PyErr_SetString(PyExc_AttributeError, _("Job pointer not found."));
228       return NULL;
229    }
230    Py_XDECREF((PyObject *)jcr->Python_events);  /* release any old events Object */
231    Py_INCREF(eObject);
232    jcr->Python_events = (void *)eObject;        /* set new events */
233
234    /* Set function pointers to call here */
235    python_set_prog = my_python_set_prog;
236    python_open     = my_python_open;
237    python_close    = my_python_close;
238    python_read     = my_python_read;
239
240    Py_INCREF(Py_None);
241    return Py_None;
242 }
243
244
245 int generate_job_event(JCR *jcr, const char *event)
246 {
247    PyObject *method = NULL;
248    PyObject *Job = (PyObject *)jcr->Python_job;
249    PyObject *events = (PyObject *)jcr->Python_events;
250    PyObject *result = NULL;
251    int stat = 0;
252
253    if (!Job || !events) {
254       return 0;
255    }
256
257    lock_python();
258 // PyEval_AcquireLock();
259
260    method = find_method(events, method, event);
261    if (!method) {
262       goto bail_out;
263    }
264
265    bstrncpy(jcr->event, event, sizeof(jcr->event));
266    result = PyObject_CallFunction(method, "O", Job);
267    jcr->event[0] = 0;             /* no event in progress */
268    if (result == NULL) {
269       if (PyErr_Occurred()) {
270          PyErr_Print();
271          Dmsg1(000, "Error in Python method %s\n", event);
272       }
273    } else {
274       stat = 1;
275    }
276    Py_XDECREF(result);
277
278 bail_out:
279    unlock_python();
280 // PyEval_ReleaseLock();
281    return stat;
282 }
283
284
285 bool my_python_set_prog(JCR *jcr, const char *prog)
286 {
287    PyObject *events = (PyObject *)jcr->Python_events;
288    BFILE *bfd = &jcr->ff->bfd;
289    char method[MAX_NAME_LENGTH];
290
291    if (!events) {
292       return false;
293    }
294    bstrncpy(method, prog, sizeof(method));
295    bstrncat(method, "_", sizeof(method));
296    bstrncat(method, "open", sizeof(method));
297    bfd->pio.fo = find_method(events, bfd->pio.fo, method);
298    bstrncpy(method, prog, sizeof(method));
299    bstrncat(method, "_", sizeof(method));
300    bstrncat(method, "read", sizeof(method));
301    bfd->pio.fr = find_method(events, bfd->pio.fr, method);
302    bstrncpy(method, prog, sizeof(method));
303    bstrncat(method, "_", sizeof(method));
304    bstrncat(method, "close", sizeof(method));
305    bfd->pio.fc = find_method(events, bfd->pio.fc, method);
306    return bfd->pio.fo && bfd->pio.fr && bfd->pio.fc;
307 }
308
309 int my_python_open(BFILE *bfd, const char *fname, int flags, mode_t mode)
310 {
311    return -1;
312 }
313
314 int my_python_close(BFILE *bfd) 
315 {
316    return 0;
317 }
318
319 ssize_t my_python_read(BFILE *bfd, void *buf, size_t count)
320 {
321    return -1;
322 }
323
324 #else
325
326 /* Dummy if Python not configured */
327 int generate_job_event(JCR *jcr, const char *event)
328 { return 1; }
329
330
331 #endif /* HAVE_PYTHON */