]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/pythonfd.c
- Remove the -f option from the chown in Makefile.in for more
[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    Copyright (C) 2005-2006 Kern Sibbald
12
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.
17
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.
22
23  */
24
25 #include "bacula.h"
26 #include "filed.h"
27
28 #ifdef HAVE_PYTHON
29 #undef _POSIX_C_SOURCE
30 #include <Python.h>
31
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);
37
38
39 extern JCR *get_jcr_from_PyObject(PyObject *self);
40 extern PyObject *find_method(PyObject *eventsObject, PyObject *method, 
41           const char *name);
42
43 /* Forward referenced functions */
44 static PyObject *set_job_events(PyObject *self, PyObject *arg);
45 static PyObject *job_write(PyObject *self, PyObject *arg);
46
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 */
51 };
52
53
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);
58
59
60 struct s_vars {
61    const char *name;
62    char *fmt;
63 };
64
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 */
74
75    { NULL,             NULL}
76 };
77
78 /* Writable variables */
79 static struct s_vars setvars[] = {
80    { NT_("JobReport"),   "s"},
81
82    { NULL,             NULL}
83 };
84
85 /* Return Job variables */
86 PyObject *job_getattr(PyObject *self, char *attrname)
87 {
88    JCR *jcr;
89    bool found = false;
90    int i;
91    char buf[10];
92    char errmsg[200];
93
94    jcr = get_jcr_from_PyObject(self);
95    if (!jcr) {
96       bstrncpy(errmsg, _("Job pointer not found."), sizeof(errmsg));
97       goto bail_out;
98    }
99    for (i=0; getvars[i].name; i++) {
100       if (strcmp(getvars[i].name, attrname) == 0) {
101          found = true;
102          break;
103       }
104    }
105    if (!found) {
106       /* Try our methods */
107       return Py_FindMethod(JobMethods, self, attrname);
108    }
109    switch (i) {
110    case 0:                            /* FD's name */
111       return Py_BuildValue(getvars[i].fmt, my_name);
112    case 1:                            /* level */
113       return Py_BuildValue(getvars[i].fmt, job_level_to_str(jcr->JobLevel));
114    case 2:                            /* type */
115       return Py_BuildValue(getvars[i].fmt, job_type_to_str(jcr->JobType));
116    case 3:                            /* JobId */
117       return Py_BuildValue(getvars[i].fmt, jcr->JobId);
118    case 4:                            /* Client */
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 */
123       buf[1] = 0;
124       buf[0] = jcr->JobStatus;
125       return Py_BuildValue(getvars[i].fmt, buf);
126    }
127    bsnprintf(errmsg, sizeof(errmsg), _("Attribute %s not found."), attrname);
128 bail_out:
129    PyErr_SetString(PyExc_AttributeError, errmsg);
130    return NULL;
131 }
132
133 int job_setattr(PyObject *self, char *attrname, PyObject *value)
134 {
135   JCR *jcr;
136    bool found = false;
137    char *strval = NULL;
138    char buf[200];
139    char *errmsg;
140    int i;
141
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);
145       errmsg = buf;
146       goto bail_out;
147    }
148    jcr = get_jcr_from_PyObject(self);
149    if (!jcr) {
150       errmsg = _("Job pointer not found.");
151       goto bail_out;
152    }
153
154    /* Find attribute name in list */
155    for (i=0; setvars[i].name; i++) {
156       if (strcmp(setvars[i].name, attrname) == 0) {
157          found = true;
158          break;
159       }
160    }
161    if (!found) {
162       bsnprintf(buf, sizeof(buf), _("Cannot find attribute %s"), attrname);
163       errmsg = buf;
164       goto bail_out;
165    }
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"));
170          return -1;
171       }
172    }   
173    switch (i) {
174    case 0:                            /* JobReport */
175       Jmsg(jcr, M_INFO, 0, "%s", strval);
176       return 0;
177    }
178    bsnprintf(buf, sizeof(buf), _("Cannot find attribute %s"), attrname);
179    errmsg = buf;
180 bail_out:
181    PyErr_SetString(PyExc_AttributeError, errmsg);
182    return -1;
183 }
184
185
186 static PyObject *job_write(PyObject *self, PyObject *args)
187 {
188    char *text = NULL;
189
190    if (!PyArg_ParseTuple(args, "s:write", &text)) {
191       Dmsg0(000, "Parse tuple error in job_write\n");
192       return NULL;
193    }
194    if (text) {
195       Jmsg(NULL, M_INFO, 0, "%s", text);
196    }
197    Py_INCREF(Py_None);
198    return Py_None;
199 }
200
201
202 static PyObject *set_job_events(PyObject *self, PyObject *arg)
203 {
204    PyObject *eObject;
205    JCR *jcr;
206
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");
210       return NULL;
211    }
212    jcr = get_jcr_from_PyObject(self);
213    if (!jcr) {
214       PyErr_SetString(PyExc_AttributeError, _("Job pointer not found."));
215       return NULL;
216    }
217    Py_XDECREF((PyObject *)jcr->Python_events);  /* release any old events Object */
218    Py_INCREF(eObject);
219    jcr->Python_events = (void *)eObject;        /* set new events */
220
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;
226
227    Py_INCREF(Py_None);
228    return Py_None;
229 }
230
231
232 int generate_job_event(JCR *jcr, const char *event)
233 {
234    PyObject *method = NULL;
235    PyObject *Job = (PyObject *)jcr->Python_job;
236    PyObject *events = (PyObject *)jcr->Python_events;
237    PyObject *result = NULL;
238    int stat = 0;
239
240    if (!Job || !events) {
241       return 0;
242    }
243
244    lock_python();
245 // PyEval_AcquireLock();
246
247    method = find_method(events, method, event);
248    if (!method) {
249       goto bail_out;
250    }
251
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()) {
257          PyErr_Print();
258          Dmsg1(000, "Error in Python method %s\n", event);
259       }
260    } else {
261       stat = 1;
262    }
263    Py_XDECREF(result);
264
265 bail_out:
266    unlock_python();
267 // PyEval_ReleaseLock();
268    return stat;
269 }
270
271
272 bool my_python_set_prog(JCR *jcr, const char *prog)
273 {
274    PyObject *events = (PyObject *)jcr->Python_events;
275    BFILE *bfd = &jcr->ff->bfd;
276    char method[MAX_NAME_LENGTH];
277
278    if (!events) {
279       return false;
280    }
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;
294 }
295
296 int my_python_open(BFILE *bfd, const char *fname, int flags, mode_t mode)
297 {
298    return -1;
299 }
300
301 int my_python_close(BFILE *bfd) 
302 {
303    return 0;
304 }
305
306 ssize_t my_python_read(BFILE *bfd, void *buf, size_t count)
307 {
308    return -1;
309 }
310
311 #else
312
313 /* Dummy if Python not configured */
314 int generate_job_event(JCR *jcr, const char *event)
315 { return 1; }
316
317
318 #endif /* HAVE_PYTHON */