]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/pythondir.c
Start Python documentation
[bacula/bacula] / bacula / src / dird / pythondir.c
1 /*
2  *
3  * Bacula interface to Python for the Director
4  *
5  * Kern Sibbald, November MMIV
6  *
7  *   Version $Id$
8  *
9  */
10
11 /*
12    Copyright (C) 2004-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 "dird.h"
33
34 #ifdef HAVE_PYTHON
35 #undef _POSIX_C_SOURCE
36 #include <Python.h>
37
38 extern JCR *get_jcr_from_PyObject(PyObject *self);
39 extern PyObject *find_method(PyObject *eventsObject, PyObject *method, 
40          const char *name);
41
42
43 static int set_job_events(PyObject *self, PyObject *arg);
44 static int job_run(PyObject *self, PyObject *arg);
45
46 #ifdef needed
47 static PyObject *set_bacula_job_events(PyObject *self, PyObject *arg)
48 {
49    Dmsg2(000, "In set_bacula_job_events self=%p arg=%p\n",
50       self, arg);
51    Py_INCREF(Py_None);
52    return Py_None;
53 }
54 PyMethodDef JobMethods[] = {
55     {"set_events", set_bacula_job_events, METH_VARARGS, "Define Bacula events."},
56     {NULL, NULL, 0, NULL}             /* last item */
57 };
58 #endif
59  
60
61 struct s_vars {
62    const char *name;
63    char *fmt;
64 };
65
66 /* Read-only variables */
67 static struct s_vars getvars[] = {
68    { N_("Job"),        "s"},
69    { N_("DirName"),    "s"},
70    { N_("Level"),      "s"},
71    { N_("Type"),       "s"},
72    { N_("JobId"),      "i"},
73    { N_("Client"),     "s"},
74    { N_("NumVols"),    "i"},
75    { N_("Pool"),       "s"},
76    { N_("Storage"),    "s"},
77    { N_("Catalog"),    "s"},
78    { N_("MediaType"),  "s"},
79    { N_("JobName"),    "s"},
80    { N_("JobStatus"),  "s"},
81
82    { NULL,             NULL}
83 };
84
85 /* Writable variables */
86 static struct s_vars setvars[] = {
87    { N_("set_events"), NULL},
88    { N_("run"),        NULL},
89    { N_("JobReport"),   "s"},
90    { N_("write"),       "s"},
91    { N_("VolumeName") , "s"},
92
93    { NULL,             NULL}
94 };
95
96
97 /* Return Job variables */
98 /* Returns:  NULL if error
99  *           PyObject * return value if OK
100  */
101 PyObject *job_getattr(PyObject *self, char *attrname)
102 {
103    JCR *jcr;
104    bool found = false;
105    int i;
106    char buf[10];
107    char errmsg[200];
108
109    Dmsg0(100, "In job_getattr.\n");
110    jcr = get_jcr_from_PyObject(self);
111    if (!jcr) {
112       bstrncpy(errmsg, "Job pointer not found.", sizeof(errmsg));
113       goto bail_out;
114    }
115    for (i=0; getvars[i].name; i++) {
116       if (strcmp(getvars[i].name, attrname) == 0) {
117          found = true;
118          break;
119       }
120    }
121    if (!found) {
122       goto not_found;
123    }
124    switch (i) {
125    case 0:                            /* Job */
126       return Py_BuildValue(getvars[i].fmt, jcr->job->hdr.name);
127    case 1:                            /* Director's name */
128       return Py_BuildValue(getvars[i].fmt, my_name);
129    case 2:                            /* level */
130       return Py_BuildValue(getvars[i].fmt, job_level_to_str(jcr->JobLevel));
131    case 3:                            /* type */
132       return Py_BuildValue(getvars[i].fmt, job_type_to_str(jcr->JobType));
133    case 4:                            /* JobId */
134       return Py_BuildValue(getvars[i].fmt, jcr->JobId);
135    case 5:                            /* Client */
136       return Py_BuildValue(getvars[i].fmt, jcr->client->hdr.name);
137    case 6:                            /* NumVols */
138       return Py_BuildValue(getvars[i].fmt, jcr->NumVols);
139    case 7:                            /* Pool */
140       return Py_BuildValue(getvars[i].fmt, jcr->pool->hdr.name);
141    case 8:                            /* Storage */
142       return Py_BuildValue(getvars[i].fmt, jcr->store->hdr.name);
143    case 9:
144       return Py_BuildValue(getvars[i].fmt, jcr->catalog->hdr.name);
145    case 10:                           /* MediaType */
146       return Py_BuildValue(getvars[i].fmt, jcr->store->media_type);
147    case 11:                           /* JobName */
148       return Py_BuildValue(getvars[i].fmt, jcr->Job);
149    case 12:                           /* JobStatus */
150       buf[1] = 0;
151       buf[0] = jcr->JobStatus;
152       return Py_BuildValue(getvars[i].fmt, buf);
153    }
154 not_found:
155    bsnprintf(errmsg, sizeof(errmsg), "Attribute %s not found.", attrname);
156 bail_out:
157    PyErr_SetString(PyExc_AttributeError, errmsg);
158    return NULL;
159 }
160
161
162 /* Set Job variables */
163 /*  Returns:   0 for OK
164  *            -1 for error
165  */
166 int job_setattr(PyObject *self, char *attrname, PyObject *value)
167 {
168    JCR *jcr;
169    bool found = false;
170    char *strval = NULL;
171    int i;
172
173    Dmsg2(100, "In job_setattr=%s val=%p.\n", attrname, value);
174    if (value == NULL) {                /* Cannot delete variables */
175        goto bail_out;
176    }
177    jcr = get_jcr_from_PyObject(self);
178    if (!jcr) {
179       goto bail_out;
180    }
181
182    /* Find attribute name in list */
183    for (i=0; setvars[i].name; i++) {
184       if (strcmp(setvars[i].name, attrname) == 0) {
185          found = true;
186          break;
187       }
188    }
189    if (!found) {
190       goto bail_out;
191    }
192    /* Get argument value ***FIXME*** handle other formats */
193    if (setvars[i].fmt != NULL) {
194       if (!PyArg_Parse(value, setvars[i].fmt, &strval)) {
195          PyErr_SetString(PyExc_TypeError, "Read-only attribute");
196          return -1;
197       }
198    }   
199    switch (i) {
200    case 0:                            /* set_events */
201       return set_job_events(self, value);
202    case 1:                            /* run */
203       return job_run(self, value);
204    case 2:                            /* JobReport */
205    case 3:                            /* write */
206       Jmsg(jcr, M_INFO, 0, "%s", strval);
207       return 0;
208    case 4:                            /* VolumeName */
209       /* Make sure VolumeName is valid and we are in VolumeName event */
210       if (strcmp("NewVolume", jcr->event) == 0 &&
211           is_volume_name_legal(NULL, strval)) {
212          pm_strcpy(jcr->VolumeName, strval);
213          Dmsg1(100, "Set Vol=%s\n", strval);
214          return 0;
215       } else {
216          jcr->VolumeName[0] = 0;
217       }
218    }
219 bail_out:
220    PyErr_SetString(PyExc_AttributeError, attrname);
221    return -1;
222 }
223
224 #ifdef needed
225 static PyObject *set_bacula_job_events(PyObject *self, PyObject *arg)
226 {
227    Dmsg2(000, "In set_bacula_job_events self=%p arg=%p\n",
228       self, arg);
229    Py_INCREF(Py_None);
230    return Py_None;
231 }
232 #endif
233
234
235 static int set_job_events(PyObject *self, PyObject *arg)
236 {
237    PyObject *eObject;
238    JCR *jcr;
239
240    Dmsg0(100, "In set_job_events.\n");
241    if (!PyArg_Parse(arg, "O", &eObject)) {
242       return -1;
243    }
244    jcr = get_jcr_from_PyObject(self);
245    Py_XDECREF((PyObject *)jcr->Python_events);
246    Py_INCREF(eObject);
247    jcr->Python_events = (void *)eObject;
248    return 0;                    /* good return */
249 }
250
251 /* Run a Bacula command */
252 static int job_run(PyObject *self, PyObject *arg)
253 {
254    JCR *jcr;
255    char *item;
256    int stat;
257
258    if (!PyArg_Parse(arg, "s", &item)) {
259       return -1;
260    }
261    jcr = get_jcr_from_PyObject(self);
262    UAContext *ua = new_ua_context(jcr);
263    ua->batch = true;
264    pm_strcpy(ua->cmd, item);          /* copy command */
265    parse_ua_args(ua);                 /* parse command */
266    stat = run_cmd(ua, ua->cmd);
267    free_ua_context(ua);
268    /* ***FIXME*** check stat */
269    return 0;
270 }
271
272
273 int generate_job_event(JCR *jcr, const char *event)
274 {
275    PyObject *method = NULL;
276    PyObject *Job = (PyObject *)jcr->Python_job;
277    PyObject *result = NULL;
278    int stat = 0;
279
280    if (!Job) {
281       return 0;
282    }
283
284    PyEval_AcquireLock();
285
286    PyObject *events = (PyObject *)jcr->Python_events;
287    method = find_method(events, method, event);
288    if (!method) {
289       goto bail_out;
290    }
291
292    bstrncpy(jcr->event, event, sizeof(jcr->event));
293    result = PyObject_CallFunction(method, "O", Job);
294    jcr->event[0] = 0;             /* no event in progress */
295    if (result == NULL) {
296       if (PyErr_Occurred()) {
297          PyErr_Print();
298          Dmsg1(000, "Error in Python method %s\n", event);
299       }
300    } else {
301       stat = 1;
302    }
303    Py_XDECREF(result);
304
305 bail_out:
306    PyEval_ReleaseLock();
307    return stat;
308 }
309
310 bool python_set_prog(JCR*, char const*) { return false; }
311
312 #else
313
314 /* Dummy if Python not configured */
315 int generate_job_event(JCR *jcr, const char *event) { return 1; }
316    
317
318 #endif /* HAVE_PYTHON */