--- /dev/null
+/*
+ *
+ * Bacula interface to Python for the File Daemon
+ *
+ * Kern Sibbald, March MMV
+ *
+ * Version $Id$
+ *
+ */
+
+/*
+ Copyright (C) 2005 Kern Sibbald
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ */
+
+#include "bacula.h"
+#include "filed.h"
+
+#ifdef HAVE_PYTHON
+#undef _POSIX_C_SOURCE
+#include <Python.h>
+
+PyObject *bacula_get(PyObject *self, PyObject *args);
+PyObject *bacula_set(PyObject *self, PyObject *args, PyObject *keyw);
+
+/* Define Bacula entry points */
+PyMethodDef BaculaMethods[] = {
+ {"get", bacula_get, METH_VARARGS, "Get Bacula FD variables."},
+ {"set", (PyCFunction)bacula_set, METH_VARARGS|METH_KEYWORDS,
+ "Set FD Bacula variables."},
+ {NULL, NULL, 0, NULL} /* last item */
+};
+
+
+struct s_vars {
+ const char *name;
+ char *fmt;
+};
+
+static struct s_vars vars[] = {
+ { N_("FDName"), "s"}, /* 0 */
+ { N_("Level"), "s"}, /* 1 */
+ { N_("Type"), "s"}, /* 2 */
+ { N_("JobId"), "i"}, /* 3 */
+ { N_("Client"), "s"}, /* 4 */
+ { N_("JobName"), "s"}, /* 5 */
+ { N_("JobStatus"), "s"}, /* 6 */
+
+ { NULL, NULL}
+};
+
+/* Return Bacula variables */
+PyObject *bacula_get(PyObject *self, PyObject *args)
+{
+ PyObject *CObject;
+ JCR *jcr;
+ char *item;
+ bool found = false;
+ int i;
+ char buf[10];
+
+ if (!PyArg_ParseTuple(args, "Os:get", &CObject, &item)) {
+ return NULL;
+ }
+ jcr = (JCR *)PyCObject_AsVoidPtr(CObject);
+ for (i=0; vars[i].name; i++) {
+ if (strcmp(vars[i].name, item) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ return NULL;
+ }
+ switch (i) {
+ case 0: /* FD's name */
+ return Py_BuildValue(vars[i].fmt, my_name);
+ case 1: /* level */
+ return Py_BuildValue(vars[i].fmt, job_level_to_str(jcr->JobLevel));
+ case 2: /* type */
+ return Py_BuildValue(vars[i].fmt, job_type_to_str(jcr->JobType));
+ case 3: /* JobId */
+ return Py_BuildValue(vars[i].fmt, jcr->JobId);
+ case 4: /* Client */
+ return Py_BuildValue(vars[i].fmt, jcr->client_name);
+ case 5: /* JobName */
+ return Py_BuildValue(vars[i].fmt, jcr->Job);
+ case 6: /* JobStatus */
+ buf[1] = 0;
+ buf[0] = jcr->JobStatus;
+ return Py_BuildValue(vars[i].fmt, buf);
+ }
+ return NULL;
+}
+
+/* Set Bacula variables */
+PyObject *bacula_set(PyObject *self, PyObject *args, PyObject *keyw)
+{
+ PyObject *CObject;
+ JCR *jcr;
+ char *msg = NULL;
+ static char *kwlist[] = {"jcr", "JobReport", NULL};
+ if (!PyArg_ParseTupleAndKeywords(args, keyw, "O|ss:set", kwlist,
+ &CObject, &msg)) {
+ return NULL;
+ }
+ jcr = (JCR *)PyCObject_AsVoidPtr(CObject);
+
+ if (msg) {
+ Jmsg(jcr, M_INFO, 0, "%s", msg);
+ }
+ return Py_BuildValue("i", 1);
+}
+
+#endif /* HAVE_PYTHON */
{"workingdirectory", store_dir, ITEM(res_store.working_directory), 0, ITEM_REQUIRED, 0},
{"piddirectory", store_dir, ITEM(res_store.pid_directory), 0, ITEM_REQUIRED, 0},
{"subsysdirectory", store_dir, ITEM(res_store.subsys_directory), 0, 0, 0},
+ {"scriptsdirectory", store_dir, ITEM(res_store.scripts_directory), 0, 0, 0},
{"requiressl", store_yesno,ITEM(res_store.require_ssl), 1, ITEM_DEFAULT, 0},
{"maximumconcurrentjobs", store_pint, ITEM(res_store.max_concurrent_jobs), 0, ITEM_DEFAULT, 10},
{"heartbeatinterval", store_time, ITEM(res_store.heartbeat_interval), 0, ITEM_DEFAULT, 0},
{"device", dev_items, R_DEVICE},
{"messages", msgs_items, R_MSGS},
{"autochanger", changer_items, R_AUTOCHANGER},
- {NULL, NULL, 0}
+ {NULL, NULL, 0}
};
return;
}
sendit(sock, "dump_resource type=%d\n", type);
- if (type < 0) { /* no recursion */
+ if (type < 0) { /* no recursion */
type = - type;
recurse = 0;
}
break;
case R_STORAGE:
sendit(sock, "Storage: name=%s SDaddr=%s SDport=%d SDDport=%d HB=%s\n",
- res->res_store.hdr.name,
- NPRT(get_first_address(res->res_store.sdaddrs, buf, sizeof(buf))),
- get_first_port_host_order(res->res_store.sdaddrs),
- get_first_port_host_order(res->res_store.sddaddrs),
- edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf)));
+ res->res_store.hdr.name,
+ NPRT(get_first_address(res->res_store.sdaddrs, buf, sizeof(buf))),
+ get_first_port_host_order(res->res_store.sdaddrs),
+ get_first_port_host_order(res->res_store.sddaddrs),
+ edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf)));
if (res->res_store.sdaddrs) {
- foreach_dlist(p, res->res_store.sdaddrs) {
+ foreach_dlist(p, res->res_store.sdaddrs) {
sendit(sock, " SDaddr=%s SDport=%d\n",
- p->get_address(buf, sizeof(buf)), p->get_port_host_order());
- }
+ p->get_address(buf, sizeof(buf)), p->get_port_host_order());
+ }
}
if (res->res_store.sddaddrs) {
- foreach_dlist(p, res->res_store.sddaddrs) {
+ foreach_dlist(p, res->res_store.sddaddrs) {
sendit(sock, " SDDaddr=%s SDDport=%d\n",
- p->get_address(buf, sizeof(buf)), p->get_port_host_order());
- }
+ p->get_address(buf, sizeof(buf)), p->get_port_host_order());
+ }
}
break;
case R_DEVICE:
sendit(sock, "Device: name=%s MediaType=%s Device=%s LabelType=%d\n",
- res->res_dev.hdr.name,
- res->res_dev.media_type, res->res_dev.device_name,
- res->res_dev.label_type);
+ res->res_dev.hdr.name,
+ res->res_dev.media_type, res->res_dev.device_name,
+ res->res_dev.label_type);
sendit(sock, " rew_wait=%d min_bs=%d max_bs=%d\n",
- res->res_dev.max_rewind_wait, res->res_dev.min_block_size,
- res->res_dev.max_block_size);
+ res->res_dev.max_rewind_wait, res->res_dev.min_block_size,
+ res->res_dev.max_block_size);
sendit(sock, " max_jobs=%d max_files=%" lld " max_size=%" lld "\n",
- res->res_dev.max_volume_jobs, res->res_dev.max_volume_files,
- res->res_dev.max_volume_size);
+ res->res_dev.max_volume_jobs, res->res_dev.max_volume_files,
+ res->res_dev.max_volume_size);
sendit(sock, " max_file_size=%" lld " capacity=%" lld "\n",
- res->res_dev.max_file_size, res->res_dev.volume_capacity);
+ res->res_dev.max_file_size, res->res_dev.volume_capacity);
sendit(sock, " spool_directory=%s\n", NPRT(res->res_dev.spool_directory));
sendit(sock, " max_spool_size=%" lld " max_job_spool_size=%" lld "\n",
- res->res_dev.max_spool_size, res->res_dev.max_job_spool_size);
+ res->res_dev.max_spool_size, res->res_dev.max_job_spool_size);
if (res->res_dev.changer_res) {
sendit(sock, " changer=%p\n", res->res_dev.changer_res);
}
case R_AUTOCHANGER:
DEVRES *dev;
sendit(sock, "Changer: name=%s Changer_devname=%s\n Changer_cmd=%s\n",
- res->res_changer.hdr.name,
- res->res_changer.changer_name, res->res_changer.changer_command);
+ res->res_changer.hdr.name,
+ res->res_changer.changer_name, res->res_changer.changer_command);
foreach_alist(dev, res->res_changer.device) {
sendit(sock, " --->Device: name=%s\n", dev->hdr.name);
}
switch (type) {
case R_DIRECTOR:
if (res->res_dir.password) {
- free(res->res_dir.password);
+ free(res->res_dir.password);
}
if (res->res_dir.address) {
- free(res->res_dir.address);
+ free(res->res_dir.address);
}
break;
case R_AUTOCHANGER:
if (res->res_changer.changer_name) {
- free(res->res_changer.changer_name);
+ free(res->res_changer.changer_name);
}
if (res->res_changer.changer_command) {
- free(res->res_changer.changer_command);
+ free(res->res_changer.changer_command);
}
if (res->res_changer.device) {
- delete res->res_changer.device;
+ delete res->res_changer.device;
}
break;
case R_STORAGE:
if (res->res_store.sdaddrs) {
- free_addresses(res->res_store.sdaddrs);
+ free_addresses(res->res_store.sdaddrs);
}
if (res->res_store.sddaddrs) {
- free_addresses(res->res_store.sddaddrs);
+ free_addresses(res->res_store.sddaddrs);
}
if (res->res_store.working_directory) {
- free(res->res_store.working_directory);
+ free(res->res_store.working_directory);
}
if (res->res_store.pid_directory) {
- free(res->res_store.pid_directory);
+ free(res->res_store.pid_directory);
}
if (res->res_store.subsys_directory) {
- free(res->res_store.subsys_directory);
+ free(res->res_store.subsys_directory);
+ }
+ if (res->res_store.scripts_directory) {
+ free(res->res_store.scripts_directory);
}
break;
case R_DEVICE:
if (res->res_dev.media_type) {
- free(res->res_dev.media_type);
+ free(res->res_dev.media_type);
}
if (res->res_dev.device_name) {
- free(res->res_dev.device_name);
+ free(res->res_dev.device_name);
}
if (res->res_dev.changer_name) {
- free(res->res_dev.changer_name);
+ free(res->res_dev.changer_name);
}
if (res->res_dev.changer_command) {
- free(res->res_dev.changer_command);
+ free(res->res_dev.changer_command);
}
if (res->res_dev.alert_command) {
- free(res->res_dev.alert_command);
+ free(res->res_dev.alert_command);
}
if (res->res_dev.spool_directory) {
- free(res->res_dev.spool_directory);
+ free(res->res_dev.spool_directory);
}
if (res->res_dev.mount_point) {
- free(res->res_dev.mount_point);
+ free(res->res_dev.mount_point);
}
if (res->res_dev.mount_command) {
- free(res->res_dev.mount_command);
+ free(res->res_dev.mount_command);
}
if (res->res_dev.unmount_command) {
- free(res->res_dev.unmount_command);
+ free(res->res_dev.unmount_command);
}
if (res->res_dev.write_part_command) {
- free(res->res_dev.write_part_command);
+ free(res->res_dev.write_part_command);
}
if (res->res_dev.free_space_command) {
- free(res->res_dev.free_space_command);
+ free(res->res_dev.free_space_command);
}
break;
case R_MSGS:
if (res->res_msgs.mail_cmd) {
- free(res->res_msgs.mail_cmd);
+ free(res->res_msgs.mail_cmd);
}
if (res->res_msgs.operator_cmd) {
- free(res->res_msgs.operator_cmd);
+ free(res->res_msgs.operator_cmd);
}
free_msgs_res((MSGS *)res); /* free message resource */
res = NULL;
*/
for (i=0; items[i].name; i++) {
if (items[i].flags & ITEM_REQUIRED) {
- if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
+ if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
Emsg2(M_ERROR_TERM, 0, _("\"%s\" item is required in \"%s\" resource, but not found.\n"),
- items[i].name, resources[rindex]);
- }
+ items[i].name, resources[rindex]);
+ }
}
/* If this triggers, take a look at lib/parse_conf.h */
if (i >= MAX_RES_ITEMS) {
case R_DIRECTOR:
case R_DEVICE:
case R_MSGS:
- break;
+ break;
/* Resources containing a resource or an alist */
case R_STORAGE:
- if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) {
+ if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) {
Emsg1(M_ERROR_TERM, 0, "Cannot find Storage resource \"%s\"\n", res_all.res_dir.hdr.name);
- }
- res->res_store.messages = res_all.res_store.messages;
- break;
+ }
+ res->res_store.messages = res_all.res_store.messages;
+ break;
case R_AUTOCHANGER:
- if ((res = (URES *)GetResWithName(type, res_all.res_changer.hdr.name)) == NULL) {
+ if ((res = (URES *)GetResWithName(type, res_all.res_changer.hdr.name)) == NULL) {
Emsg1(M_ERROR_TERM, 0, "Cannot find AutoChanger resource %s\n",
- res_all.res_changer.hdr.name);
- }
- /* we must explicitly copy the device alist pointer */
- res->res_changer.device = res_all.res_changer.device;
- /*
- * Now update each device in this resource to point back
- * to the changer resource.
- */
- foreach_alist(dev, res->res_changer.device) {
- dev->changer_res = (AUTOCHANGER *)&res->res_changer;
- }
- if ((errstat = pthread_mutex_init(&res->res_changer.changer_mutex, NULL)) != 0) {
- berrno be;
+ res_all.res_changer.hdr.name);
+ }
+ /* we must explicitly copy the device alist pointer */
+ res->res_changer.device = res_all.res_changer.device;
+ /*
+ * Now update each device in this resource to point back
+ * to the changer resource.
+ */
+ foreach_alist(dev, res->res_changer.device) {
+ dev->changer_res = (AUTOCHANGER *)&res->res_changer;
+ }
+ if ((errstat = pthread_mutex_init(&res->res_changer.changer_mutex, NULL)) != 0) {
+ berrno be;
Jmsg1(NULL, M_ERROR_TERM, 0, _("Unable to init mutex: ERR=%s\n"),
- be.strerror(errstat));
- }
- break;
+ be.strerror(errstat));
+ }
+ break;
default:
printf("Unknown resource type %d\n", type);
- error = 1;
- break;
+ error = 1;
+ break;
}
if (res_all.res_dir.hdr.name) {
- free(res_all.res_dir.hdr.name);
- res_all.res_dir.hdr.name = NULL;
+ free(res_all.res_dir.hdr.name);
+ res_all.res_dir.hdr.name = NULL;
}
if (res_all.res_dir.hdr.desc) {
- free(res_all.res_dir.hdr.desc);
- res_all.res_dir.hdr.desc = NULL;
+ free(res_all.res_dir.hdr.desc);
+ res_all.res_dir.hdr.desc = NULL;
}
return;
}
/* The following code is only executed on pass 1 */
switch (type) {
case R_DIRECTOR:
- size = sizeof(DIRRES);
- break;
+ size = sizeof(DIRRES);
+ break;
case R_STORAGE:
- size = sizeof(STORES);
- break;
+ size = sizeof(STORES);
+ break;
case R_DEVICE:
- size = sizeof(DEVRES);
- break;
+ size = sizeof(DEVRES);
+ break;
case R_MSGS:
- size = sizeof(MSGS);
- break;
+ size = sizeof(MSGS);
+ break;
case R_AUTOCHANGER:
- size = sizeof(AUTOCHANGER);
- break;
+ size = sizeof(AUTOCHANGER);
+ break;
default:
printf("Unknown resource type %d\n", type);
- error = 1;
- size = 1;
- break;
+ error = 1;
+ size = 1;
+ break;
}
/* Common */
if (!error) {
res = (URES *)malloc(size);
memcpy(res, &res_all, size);
if (!res_head[rindex]) {
- res_head[rindex] = (RES *)res; /* store first entry */
+ res_head[rindex] = (RES *)res; /* store first entry */
} else {
- RES *next;
- /* Add new res to end of chain */
- for (next=res_head[rindex]; next->next; next=next->next) {
- if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
- Emsg2(M_ERROR_TERM, 0,
+ RES *next;
+ /* Add new res to end of chain */
+ for (next=res_head[rindex]; next->next; next=next->next) {
+ if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
+ Emsg2(M_ERROR_TERM, 0,
_("Attempt to define second \"%s\" resource named \"%s\" is not permitted.\n"),
- resources[rindex].name, res->res_dir.hdr.name);
- }
- }
- next->next = (RES *)res;
+ resources[rindex].name, res->res_dir.hdr.name);
+ }
+ }
+ next->next = (RES *)res;
Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
- res->res_dir.hdr.name);
+ res->res_dir.hdr.name);
}
}
}
R_MSGS,
R_AUTOCHANGER,
R_FIRST = R_DIRECTOR,
- R_LAST = R_AUTOCHANGER /* keep this updated */
+ R_LAST = R_AUTOCHANGER /* keep this updated */
};
enum {
/* Definition of the contents of each Resource */
class DIRRES {
public:
- RES hdr;
+ RES hdr;
- char *password; /* Director password */
- char *address; /* Director IP address or zero */
- int enable_ssl; /* Use SSL with this Director */
- int monitor; /* Have only access to status and .status functions */
+ char *password; /* Director password */
+ char *address; /* Director IP address or zero */
+ int enable_ssl; /* Use SSL with this Director */
+ int monitor; /* Have only access to status and .status functions */
};
/* Storage daemon "global" definitions */
class s_res_store {
public:
- RES hdr;
+ RES hdr;
dlist *sdaddrs;
dlist *sddaddrs;
- char *working_directory; /* working directory for checkpoints */
+ char *working_directory; /* working directory for checkpoints */
char *pid_directory;
char *subsys_directory;
- int require_ssl; /* Require SSL on all connections */
+ char *scripts_directory;
+ int require_ssl; /* Require SSL on all connections */
uint32_t max_concurrent_jobs; /* maximum concurrent jobs to run */
- MSGS *messages; /* Daemon message handler */
- utime_t heartbeat_interval; /* Interval to send hb to FD */
+ MSGS *messages; /* Daemon message handler */
+ utime_t heartbeat_interval; /* Interval to send hb to FD */
};
typedef struct s_res_store STORES;
public:
RES hdr;
alist *device;
- char *changer_name; /* Changer device name */
- char *changer_command; /* Changer command -- external program */
+ char *changer_name; /* Changer device name */
+ char *changer_command; /* Changer command -- external program */
pthread_mutex_t changer_mutex; /* One changer operation at a time */
};
/* Device specific definitions */
class DEVRES {
public:
- RES hdr;
-
- char *media_type; /* User assigned media type */
- char *device_name; /* Archive device name */
- char *changer_name; /* Changer device name */
- char *changer_command; /* Changer command -- external program */
- char *alert_command; /* Alert command -- external program */
- char *spool_directory; /* Spool file directory */
- int label_type; /* label type */
- int autoselect; /* Automatically select from AutoChanger */
- uint32_t drive_index; /* Autochanger drive index */
- uint32_t cap_bits; /* Capabilities of this device */
- uint32_t max_changer_wait; /* Changer timeout */
- uint32_t max_rewind_wait; /* maximum secs to wait for rewind */
- uint32_t max_open_wait; /* maximum secs to wait for open */
- uint32_t max_open_vols; /* maximum simultaneous open volumes */
- uint32_t min_block_size; /* min block size */
- uint32_t max_block_size; /* max block size */
- uint32_t max_volume_jobs; /* max jobs to put on one volume */
+ RES hdr;
+
+ char *media_type; /* User assigned media type */
+ char *device_name; /* Archive device name */
+ char *changer_name; /* Changer device name */
+ char *changer_command; /* Changer command -- external program */
+ char *alert_command; /* Alert command -- external program */
+ char *spool_directory; /* Spool file directory */
+ int label_type; /* label type */
+ int autoselect; /* Automatically select from AutoChanger */
+ uint32_t drive_index; /* Autochanger drive index */
+ uint32_t cap_bits; /* Capabilities of this device */
+ uint32_t max_changer_wait; /* Changer timeout */
+ uint32_t max_rewind_wait; /* maximum secs to wait for rewind */
+ uint32_t max_open_wait; /* maximum secs to wait for open */
+ uint32_t max_open_vols; /* maximum simultaneous open volumes */
+ uint32_t min_block_size; /* min block size */
+ uint32_t max_block_size; /* max block size */
+ uint32_t max_volume_jobs; /* max jobs to put on one volume */
uint32_t max_network_buffer_size; /* max network buf size */
- utime_t vol_poll_interval; /* interval between polling volume during mount */
- int64_t max_volume_files; /* max files to put on one volume */
- int64_t max_volume_size; /* max bytes to put on one volume */
- int64_t max_file_size; /* max file size in bytes */
- int64_t volume_capacity; /* advisory capacity */
- int64_t max_spool_size; /* Max spool size for all jobs */
- int64_t max_job_spool_size; /* Max spool size for any single job */
+ utime_t vol_poll_interval; /* interval between polling volume during mount */
+ int64_t max_volume_files; /* max files to put on one volume */
+ int64_t max_volume_size; /* max bytes to put on one volume */
+ int64_t max_file_size; /* max file size in bytes */
+ int64_t volume_capacity; /* advisory capacity */
+ int64_t max_spool_size; /* Max spool size for all jobs */
+ int64_t max_job_spool_size; /* Max spool size for any single job */
- int64_t max_part_size; /* Max part size */
- char *mount_point; /* Mount point for require mount devices */
- char *mount_command; /* Mount command */
- char *unmount_command; /* Unmount command */
- char *write_part_command; /* Write part command */
- char *free_space_command; /* Free space command */
+ int64_t max_part_size; /* Max part size */
+ char *mount_point; /* Mount point for require mount devices */
+ char *mount_command; /* Mount command */
+ char *unmount_command; /* Unmount command */
+ char *write_part_command; /* Write part command */
+ char *free_space_command; /* Free space command */
/* The following are set at runtime */
- DEVICE *dev; /* Pointer to phyical dev -- set at runtime */
- AUTOCHANGER *changer_res; /* pointer to changer res if any */
+ DEVICE *dev; /* Pointer to phyical dev -- set at runtime */
+ AUTOCHANGER *changer_res; /* pointer to changer res if any */
};
DEVRES res_dev;
MSGS res_msgs;
AUTOCHANGER res_changer;
- RES hdr;
+ RES hdr;
};