]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/pythonfd.c
- Remove a few HAVE_TLS #ifdefs
[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 int set_job_events(PyObject *self, PyObject *arg);
51
52 bool my_python_set_prog(JCR *jcr, const char *prog);
53 int my_python_open(BFILE *bfd, const char *fname, int flags, mode_t mode);
54 int my_python_close(BFILE *bfd);
55 ssize_t my_python_read(BFILE *bfd, void *buf, size_t count);
56
57
58 struct s_vars {
59    const char *name;
60    char *fmt;
61 };
62
63 /* Read-only variables */
64 static struct s_vars getvars[] = {
65    { N_("FDName"),     "s"},          /* 0 */
66    { N_("Level"),      "s"},          /* 1 */
67    { N_("Type"),       "s"},          /* 2 */
68    { N_("JobId"),      "i"},          /* 3 */
69    { N_("Client"),     "s"},          /* 4 */
70    { N_("JobName"),    "s"},          /* 5 */
71    { N_("JobStatus"),  "s"},          /* 6 */
72
73    { NULL,             NULL}
74 };
75
76 /* Writable variables */
77 static struct s_vars setvars[] = {
78    { N_("set_events"), NULL},
79    { N_("JobReport"),   "s"},
80    { N_("write"),       "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       goto not_found;
107    }
108    switch (i) {
109    case 0:                            /* FD's name */
110       return Py_BuildValue(getvars[i].fmt, my_name);
111    case 1:                            /* level */
112       return Py_BuildValue(getvars[i].fmt, job_level_to_str(jcr->JobLevel));
113    case 2:                            /* type */
114       return Py_BuildValue(getvars[i].fmt, job_type_to_str(jcr->JobType));
115    case 3:                            /* JobId */
116       return Py_BuildValue(getvars[i].fmt, jcr->JobId);
117    case 4:                            /* Client */
118       return Py_BuildValue(getvars[i].fmt, jcr->client_name);
119    case 5:                            /* JobName */
120       return Py_BuildValue(getvars[i].fmt, jcr->Job);
121    case 6:                            /* JobStatus */
122       buf[1] = 0;
123       buf[0] = jcr->JobStatus;
124       return Py_BuildValue(getvars[i].fmt, buf);
125    }
126 not_found:
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:                            /* set_events */
175       return set_job_events(self, value);
176    case 1:                            /* JobReport */
177    case 2:                            /* write */
178       Jmsg(jcr, M_INFO, 0, "%s", strval);
179       return 0;
180    }
181    bsnprintf(buf, sizeof(buf), "Cannot find attribute %s", attrname);
182    errmsg = buf;
183 bail_out:
184    PyErr_SetString(PyExc_AttributeError, errmsg);
185    return -1;
186 }
187
188
189
190 static int set_job_events(PyObject *self, PyObject *arg)
191 {
192    PyObject *eObject;
193    JCR *jcr;
194
195    Dmsg0(100, "In set_job_events.\n");
196    if (!PyArg_Parse(arg, "O", &eObject)) {
197       Dmsg0(000, "Parse error looking for Object argument\n");
198       return -1;
199    }
200    jcr = get_jcr_from_PyObject(self);
201    if (!jcr) {
202       PyErr_SetString(PyExc_AttributeError, "Job pointer not found.");
203       return -1;
204    }
205    Py_XDECREF((PyObject *)jcr->Python_events);  /* release any old events Object */
206    Py_INCREF(eObject);
207    jcr->Python_events = (void *)eObject;        /* set new events */
208
209    /* Set function pointers to call here */
210    python_set_prog = my_python_set_prog;
211    python_open     = my_python_open;
212    python_close    = my_python_close;
213    python_read     = my_python_read;
214
215    return 0;
216 }
217
218
219 int generate_job_event(JCR *jcr, const char *event)
220 {
221    PyObject *method = NULL;
222    PyObject *Job = (PyObject *)jcr->Python_job;
223    PyObject *result = NULL;
224    int stat = 0;
225
226    if (!Job) {
227       return 0;
228    }
229
230    PyEval_AcquireLock();
231
232    PyObject *events = (PyObject *)jcr->Python_events;
233    method = find_method(events, method, event);
234    if (!method) {
235       goto bail_out;
236    }
237
238    bstrncpy(jcr->event, event, sizeof(jcr->event));
239    result = PyObject_CallFunction(method, "O", Job);
240    jcr->event[0] = 0;             /* no event in progress */
241    if (result == NULL) {
242       if (PyErr_Occurred()) {
243          PyErr_Print();
244          Dmsg1(000, "Error in Python method %s\n", event);
245       }
246    } else {
247       stat = 1;
248    }
249    Py_XDECREF(result);
250
251 bail_out:
252    PyEval_ReleaseLock();
253    return stat;
254 }
255
256
257 bool my_python_set_prog(JCR *jcr, const char *prog)
258 {
259    PyObject *events = (PyObject *)jcr->Python_events;
260    BFILE *bfd = &jcr->ff->bfd;
261    char method[MAX_NAME_LENGTH];
262
263    if (!events) {
264       return false;
265    }
266    bstrncpy(method, prog, sizeof(method));
267    bstrncat(method, "_", sizeof(method));
268    bstrncat(method, "open", sizeof(method));
269    bfd->pio.fo = find_method(events, bfd->pio.fo, method);
270    bstrncpy(method, prog, sizeof(method));
271    bstrncat(method, "_", sizeof(method));
272    bstrncat(method, "read", sizeof(method));
273    bfd->pio.fr = find_method(events, bfd->pio.fr, method);
274    bstrncpy(method, prog, sizeof(method));
275    bstrncat(method, "_", sizeof(method));
276    bstrncat(method, "close", sizeof(method));
277    bfd->pio.fc = find_method(events, bfd->pio.fc, method);
278    return bfd->pio.fo && bfd->pio.fr && bfd->pio.fc;
279 }
280
281 int my_python_open(BFILE *bfd, const char *fname, int flags, mode_t mode)
282 {
283    return -1;
284 }
285
286 int my_python_close(BFILE *bfd) 
287 {
288    return 0;
289 }
290
291 ssize_t my_python_read(BFILE *bfd, void *buf, size_t count)
292 {
293    return -1;
294 }
295
296 #else
297
298 /* Dummy if Python not configured */
299 int generate_job_event(JCR *jcr, const char *event)
300 { return 1; }
301
302
303 #endif /* HAVE_PYTHON */