]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/pythonfd.c
4ba9c9c5ad75310c1beb8ffe560f749d1c4bfc38
[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 /*
12    Copyright (C) 2005 Kern Sibbald
13
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.
18
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.
23
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,
27    MA 02111-1307, USA.
28
29  */
30
31 #include "bacula.h"
32 #include "filed.h"
33
34 #ifdef HAVE_PYTHON
35 #undef _POSIX_C_SOURCE
36 #include <Python.h>
37
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);
43
44
45 extern JCR *get_jcr_from_PyObject(PyObject *self);
46 extern PyObject *find_method(PyObject *eventsObject, PyObject *method, 
47           const char *name);
48
49 /* Forward referenced functions */
50 static PyObject *set_job_events(PyObject *self, PyObject *arg);
51 static PyObject *job_write(PyObject *self, PyObject *arg);
52
53 PyMethodDef JobMethods[] = {
54     {"set_events", set_job_events, METH_VARARGS, "Set Job events"},
55     {"write", job_write, METH_VARARGS, "Write to output"},
56     {NULL, NULL, 0, NULL}             /* last item */
57 };
58
59
60 bool my_python_set_prog(JCR *jcr, const char *prog);
61 int my_python_open(BFILE *bfd, const char *fname, int flags, mode_t mode);
62 int my_python_close(BFILE *bfd);
63 ssize_t my_python_read(BFILE *bfd, void *buf, size_t count);
64
65
66 struct s_vars {
67    const char *name;
68    char *fmt;
69 };
70
71 /* Read-only variables */
72 static struct s_vars getvars[] = {
73    { N_("FDName"),     "s"},          /* 0 */
74    { N_("Level"),      "s"},          /* 1 */
75    { N_("Type"),       "s"},          /* 2 */
76    { N_("JobId"),      "i"},          /* 3 */
77    { N_("Client"),     "s"},          /* 4 */
78    { N_("JobName"),    "s"},          /* 5 */
79    { N_("JobStatus"),  "s"},          /* 6 */
80
81    { NULL,             NULL}
82 };
83
84 /* Writable variables */
85 static struct s_vars setvars[] = {
86    { N_("JobReport"),   "s"},
87
88    { NULL,             NULL}
89 };
90
91 /* Return Job variables */
92 PyObject *job_getattr(PyObject *self, char *attrname)
93 {
94    JCR *jcr;
95    bool found = false;
96    int i;
97    char buf[10];
98    char errmsg[200];
99
100    jcr = get_jcr_from_PyObject(self);
101    if (!jcr) {
102       bstrncpy(errmsg, _("Job pointer not found."), sizeof(errmsg));
103       goto bail_out;
104    }
105    for (i=0; getvars[i].name; i++) {
106       if (strcmp(getvars[i].name, attrname) == 0) {
107          found = true;
108          break;
109       }
110    }
111    if (!found) {
112       /* Try our methods */
113       return Py_FindMethod(JobMethods, self, attrname);
114    }
115    switch (i) {
116    case 0:                            /* FD's name */
117       return Py_BuildValue(getvars[i].fmt, my_name);
118    case 1:                            /* level */
119       return Py_BuildValue(getvars[i].fmt, job_level_to_str(jcr->JobLevel));
120    case 2:                            /* type */
121       return Py_BuildValue(getvars[i].fmt, job_type_to_str(jcr->JobType));
122    case 3:                            /* JobId */
123       return Py_BuildValue(getvars[i].fmt, jcr->JobId);
124    case 4:                            /* Client */
125       return Py_BuildValue(getvars[i].fmt, jcr->client_name);
126    case 5:                            /* JobName */
127       return Py_BuildValue(getvars[i].fmt, jcr->Job);
128    case 6:                            /* JobStatus */
129       buf[1] = 0;
130       buf[0] = jcr->JobStatus;
131       return Py_BuildValue(getvars[i].fmt, buf);
132    }
133    bsnprintf(errmsg, sizeof(errmsg), _("Attribute %s not found."), attrname);
134 bail_out:
135    PyErr_SetString(PyExc_AttributeError, errmsg);
136    return NULL;
137 }
138
139 int job_setattr(PyObject *self, char *attrname, PyObject *value)
140 {
141   JCR *jcr;
142    bool found = false;
143    char *strval = NULL;
144    char buf[200];
145    char *errmsg;
146    int i;
147
148    Dmsg2(100, "In job_setattr=%s val=%p.\n", attrname, value);
149    if (value == NULL) {                /* Cannot delete variables */
150       bsnprintf(buf, sizeof(buf), _("Cannot delete attribute %s"), attrname);
151       errmsg = buf;
152       goto bail_out;
153    }
154    jcr = get_jcr_from_PyObject(self);
155    if (!jcr) {
156       errmsg = _("Job pointer not found.");
157       goto bail_out;
158    }
159
160    /* Find attribute name in list */
161    for (i=0; setvars[i].name; i++) {
162       if (strcmp(setvars[i].name, attrname) == 0) {
163          found = true;
164          break;
165       }
166    }
167    if (!found) {
168       bsnprintf(buf, sizeof(buf), _("Cannot find attribute %s"), attrname);
169       errmsg = buf;
170       goto bail_out;
171    }
172    /* Get argument value ***FIXME*** handle other formats */
173    if (setvars[i].fmt != NULL) {
174       if (!PyArg_Parse(value, setvars[i].fmt, &strval)) {
175          PyErr_SetString(PyExc_TypeError, _("Read-only attribute"));
176          return -1;
177       }
178    }   
179    switch (i) {
180    case 0:                            /* JobReport */
181       Jmsg(jcr, M_INFO, 0, "%s", strval);
182       return 0;
183    }
184    bsnprintf(buf, sizeof(buf), _("Cannot find attribute %s"), attrname);
185    errmsg = buf;
186 bail_out:
187    PyErr_SetString(PyExc_AttributeError, errmsg);
188    return -1;
189 }
190
191
192 static PyObject *job_write(PyObject *self, PyObject *args)
193 {
194    char *text = NULL;
195
196    if (!PyArg_ParseTuple(args, "s:write", &text)) {
197       Dmsg0(000, "Parse tuple error in job_write\n");
198       return NULL;
199    }
200    if (text) {
201       Jmsg(NULL, M_INFO, 0, "%s", text);
202    }
203    Py_INCREF(Py_None);
204    return Py_None;
205 }
206
207
208 static PyObject *set_job_events(PyObject *self, PyObject *arg)
209 {
210    PyObject *eObject;
211    JCR *jcr;
212
213    Dmsg0(100, "In set_job_events.\n");
214    if (!PyArg_ParseTuple(arg, "O", &eObject)) {
215       Dmsg0(000, "Parse error looking for Object argument\n");
216       return NULL;
217    }
218    jcr = get_jcr_from_PyObject(self);
219    if (!jcr) {
220       PyErr_SetString(PyExc_AttributeError, _("Job pointer not found."));
221       return NULL;
222    }
223    Py_XDECREF((PyObject *)jcr->Python_events);  /* release any old events Object */
224    Py_INCREF(eObject);
225    jcr->Python_events = (void *)eObject;        /* set new events */
226
227    /* Set function pointers to call here */
228    python_set_prog = my_python_set_prog;
229    python_open     = my_python_open;
230    python_close    = my_python_close;
231    python_read     = my_python_read;
232
233    Py_INCREF(Py_None);
234    return Py_None;
235 }
236
237
238 int generate_job_event(JCR *jcr, const char *event)
239 {
240    PyObject *method = NULL;
241    PyObject *Job = (PyObject *)jcr->Python_job;
242    PyObject *events = (PyObject *)jcr->Python_events;
243    PyObject *result = NULL;
244    int stat = 0;
245
246    if (!Job || !events) {
247       return 0;
248    }
249
250    PyEval_AcquireLock();
251
252    method = find_method(events, method, event);
253    if (!method) {
254       goto bail_out;
255    }
256
257    bstrncpy(jcr->event, event, sizeof(jcr->event));
258    result = PyObject_CallFunction(method, "O", Job);
259    jcr->event[0] = 0;             /* no event in progress */
260    if (result == NULL) {
261       if (PyErr_Occurred()) {
262          PyErr_Print();
263          Dmsg1(000, "Error in Python method %s\n", event);
264       }
265    } else {
266       stat = 1;
267    }
268    Py_XDECREF(result);
269
270 bail_out:
271    PyEval_ReleaseLock();
272    return stat;
273 }
274
275
276 bool my_python_set_prog(JCR *jcr, const char *prog)
277 {
278    PyObject *events = (PyObject *)jcr->Python_events;
279    BFILE *bfd = &jcr->ff->bfd;
280    char method[MAX_NAME_LENGTH];
281
282    if (!events) {
283       return false;
284    }
285    bstrncpy(method, prog, sizeof(method));
286    bstrncat(method, "_", sizeof(method));
287    bstrncat(method, "open", sizeof(method));
288    bfd->pio.fo = find_method(events, bfd->pio.fo, method);
289    bstrncpy(method, prog, sizeof(method));
290    bstrncat(method, "_", sizeof(method));
291    bstrncat(method, "read", sizeof(method));
292    bfd->pio.fr = find_method(events, bfd->pio.fr, method);
293    bstrncpy(method, prog, sizeof(method));
294    bstrncat(method, "_", sizeof(method));
295    bstrncat(method, "close", sizeof(method));
296    bfd->pio.fc = find_method(events, bfd->pio.fc, method);
297    return bfd->pio.fo && bfd->pio.fr && bfd->pio.fc;
298 }
299
300 int my_python_open(BFILE *bfd, const char *fname, int flags, mode_t mode)
301 {
302    return -1;
303 }
304
305 int my_python_close(BFILE *bfd) 
306 {
307    return 0;
308 }
309
310 ssize_t my_python_read(BFILE *bfd, void *buf, size_t count)
311 {
312    return -1;
313 }
314
315 #else
316
317 /* Dummy if Python not configured */
318 int generate_job_event(JCR *jcr, const char *event)
319 { return 1; }
320
321
322 #endif /* HAVE_PYTHON */