]> git.sur5r.net Git - bacula/bacula/commitdiff
- Fix new Python code to work for Director.
authorKern Sibbald <kern@sibbald.com>
Tue, 19 Apr 2005 16:49:55 +0000 (16:49 +0000)
committerKern Sibbald <kern@sibbald.com>
Tue, 19 Apr 2005 16:49:55 +0000 (16:49 +0000)
- Move lib/python.c to lib/pythonlib.c so that debug output
  is easier to read (can distinguish lib from dird, ...).

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1937 91ce42f0-d328-0410-95d8-f526ca767f89

16 files changed:
bacula/examples/python/DirStartUp.py [new file with mode: 0644]
bacula/examples/python/FDStartUp.py [new file with mode: 0644]
bacula/examples/python/SDStartUp.py [new file with mode: 0644]
bacula/src/dird/dird.c
bacula/src/dird/job.c
bacula/src/dird/python.c
bacula/src/dird/ua_cmds.c
bacula/src/filed/filed.c
bacula/src/filed/python.c
bacula/src/jcr.h
bacula/src/lib/Makefile.in
bacula/src/lib/jcr.c
bacula/src/lib/python.c [deleted file]
bacula/src/lib/pythonlib.c [new file with mode: 0644]
bacula/src/stored/python.c
bacula/src/stored/stored.c

diff --git a/bacula/examples/python/DirStartUp.py b/bacula/examples/python/DirStartUp.py
new file mode 100644 (file)
index 0000000..2a810f4
--- /dev/null
@@ -0,0 +1,90 @@
+#
+# Bacula Python interface script
+#
+
+# You must import both sys and bacula
+import sys, bacula
+
+# This is the list of Bacula daemon events that you
+#  can receive.
+class BaculaEvents:
+  def __init__(self):
+     # Called here when a new Bacula Events class is
+     #  is created. Normally not used 
+     noop = 1
+
+  def JobStart(self, job):
+     """
+       Called here when a new job is started. If you want
+       to do anything with the Job, you must register
+       events you want to receive.
+     """
+     events = JobEvents()         # create instance of Job class
+     events.job = job             # save Bacula's job pointer
+     job.set_events(events)       # register events desired
+     sys.stderr = events          # send error output to Bacula
+     sys.stdout = events          # send stdout to Bacula
+     jobid = job.get("JobId"); client = job.get("Client"); 
+     numvols = job.get("NumVols") 
+     job.set(JobReport="Python StartJob: JobId=%d Client=%s NumVols=%d\n" % (jobid,client,numvols))
+     return 1
+
+  # Bacula Job is going to terminate
+  def JobEnd(self, job):    
+     jobid = job.get("JobId")
+     client = job.get("Client") 
+     job.set(JobReport="Python EndJob output: JobId=%d Client=%s.\n" % (jobid, client))
+     if (jobid < 2) :
+        startid = job.run("run kernsave")
+        print "Python started new Job: jobid=", startid
+     return 1
+
+  # Called here when the Bacula daemon is going to exit
+  def Exit(self, job):
+      print "Daemon exiting."
+     
+bacula.set_events(BaculaEvents()) # register daemon events desired
+
+"""
+  There are the Job events that you can receive.
+"""
+class JobEvents:
+  def __init__(self):
+     # Called here when you instantiate the Job. Not
+     # normally used
+     noop = 1
+
+  def NewVolume(self, job):
+     jobid = job.get("JobId")
+     client = job.get("Client") 
+     numvol = job.get("NumVols");
+     print "JobId=%d Client=%s NumVols=%d" % (jobid, client, numvol)
+     job.set(JobReport="Python before New Volume set for Job.\n") 
+     job.set(VolumeName="TestA-001")
+     job.set(JobReport="Python after New Volume set for Job.\n") 
+     return 1
+
+
+  # Pass output back to Bacula
+  def write(self, text):
+     self.job.write(text)
+
+  # Open file to be backed up. file is the filename
+  def open(self, file):
+     print "Open %s called" % file
+     self.fd = open('m.py', 'rb')
+     jobid = self.job.get("JobId")
+     print "Open: JobId=%d" % jobid
+     print "name=%s" % bacula.name
+
+  # Read file data into Bacula memory buffer (mem)
+  #  return length read. 0 => EOF, -1 => error
+  def read(self, mem):
+     print "Read called\n"
+     len = self.fd.readinto(mem)
+     print "Read %s bytes into mem.\n" % len
+     return len
+
+  # Close file
+  def close(self):
+     self.fd.close()
diff --git a/bacula/examples/python/FDStartUp.py b/bacula/examples/python/FDStartUp.py
new file mode 100644 (file)
index 0000000..2fe0fb2
--- /dev/null
@@ -0,0 +1,92 @@
+#
+# Bacula Python interface script
+#
+
+# You must import both sys and bacula
+import sys, bacula
+
+# This is the list of Bacula daemon events that you
+#  can receive.
+class BaculaEvents:
+  def __init__(self):
+     # Called here when a new Bacula Events class is
+     #  is created. Normally not used 
+     noop = 1
+
+  def JobStart(self, job):
+     """
+       Called here when a new job is started. If you want
+       to do anything with the Job, you must register
+       events you want to receive.
+     """
+     events = JobEvents()         # create instance of Job class
+     events.job = job             # save Bacula's job pointer
+     job.set_events(events)       # register events desired
+     sys.stderr = events          # send error output to Bacula
+     sys.stdout = events          # send stdout to Bacula
+     jobid = job.get("JobId")
+     client = job.get("Client")
+     numvols = job.get("NumVols") 
+     job.set(JobReport="Python StartJob: JobId=%d Client=%s NumVols=%d\n" % (jobid,client,numvols))
+     return 1
+
+  # Bacula Job is going to terminate
+  def JobEnd(self, job):    
+     jobid = job.get("JobId")
+     client = job.get("Client") 
+     job.set(JobReport="Python EndJob output: JobId=%d Client=%s.\n" % (jobid, client))
+     if (jobid < 2) :
+        startid = job.run("run kernsave")
+        print "Python started new Job: jobid=", startid
+     return 1
+
+  # Called here when the Bacula daemon is going to exit
+  def Exit(self, job):
+      noop = 1
+     
+bacula.set_events(BaculaEvents()) # register daemon events desired
+
+"""
+  There are the Job events that you can receive.
+"""
+class JobEvents:
+  def __init__(self):
+     # Called here when you instantiate the Job. Not
+     # normally used
+     noop = 1
+
+  def NewVolume(self, job):
+     jobid = job.get("JobId")
+     print "JobId=", jobid
+     client = job.get("Client") 
+     print "Client=" + client
+     numvol = job.get("NumVols");
+     print "NumVols=", numvol
+     job.set(JobReport="Python New Volume set for Job.\n") 
+     job.set(VolumeName="TestA-001")
+     return 1
+
+
+  # Pass output back to Bacula
+  def write(self, text):
+     self.job.write(text)
+
+  # Open file to be backed up. file is the filename
+  def open(self, file):
+     print "Open %s called" % file
+     self.fd = open('m.py', 'rb')
+     jobid = self.job.get("JobId")
+     print "Open: JobId=%d" % jobid
+     print "name=%s" % bacula.name
+
+  # Read file data into Bacula memory buffer (mem)
+  #  return length read. 0 => EOF, -1 => error
+  def read(self, mem):
+     print "Read called\n"
+     len = self.fd.readinto(mem)
+     print "Read %s bytes into mem.\n" % len
+     return len
+
+  # Close file
+  def close(self):
+     self.fd.close()
diff --git a/bacula/examples/python/SDStartUp.py b/bacula/examples/python/SDStartUp.py
new file mode 100644 (file)
index 0000000..2fe0fb2
--- /dev/null
@@ -0,0 +1,92 @@
+#
+# Bacula Python interface script
+#
+
+# You must import both sys and bacula
+import sys, bacula
+
+# This is the list of Bacula daemon events that you
+#  can receive.
+class BaculaEvents:
+  def __init__(self):
+     # Called here when a new Bacula Events class is
+     #  is created. Normally not used 
+     noop = 1
+
+  def JobStart(self, job):
+     """
+       Called here when a new job is started. If you want
+       to do anything with the Job, you must register
+       events you want to receive.
+     """
+     events = JobEvents()         # create instance of Job class
+     events.job = job             # save Bacula's job pointer
+     job.set_events(events)       # register events desired
+     sys.stderr = events          # send error output to Bacula
+     sys.stdout = events          # send stdout to Bacula
+     jobid = job.get("JobId")
+     client = job.get("Client")
+     numvols = job.get("NumVols") 
+     job.set(JobReport="Python StartJob: JobId=%d Client=%s NumVols=%d\n" % (jobid,client,numvols))
+     return 1
+
+  # Bacula Job is going to terminate
+  def JobEnd(self, job):    
+     jobid = job.get("JobId")
+     client = job.get("Client") 
+     job.set(JobReport="Python EndJob output: JobId=%d Client=%s.\n" % (jobid, client))
+     if (jobid < 2) :
+        startid = job.run("run kernsave")
+        print "Python started new Job: jobid=", startid
+     return 1
+
+  # Called here when the Bacula daemon is going to exit
+  def Exit(self, job):
+      noop = 1
+     
+bacula.set_events(BaculaEvents()) # register daemon events desired
+
+"""
+  There are the Job events that you can receive.
+"""
+class JobEvents:
+  def __init__(self):
+     # Called here when you instantiate the Job. Not
+     # normally used
+     noop = 1
+
+  def NewVolume(self, job):
+     jobid = job.get("JobId")
+     print "JobId=", jobid
+     client = job.get("Client") 
+     print "Client=" + client
+     numvol = job.get("NumVols");
+     print "NumVols=", numvol
+     job.set(JobReport="Python New Volume set for Job.\n") 
+     job.set(VolumeName="TestA-001")
+     return 1
+
+
+  # Pass output back to Bacula
+  def write(self, text):
+     self.job.write(text)
+
+  # Open file to be backed up. file is the filename
+  def open(self, file):
+     print "Open %s called" % file
+     self.fd = open('m.py', 'rb')
+     jobid = self.job.get("JobId")
+     print "Open: JobId=%d" % jobid
+     print "name=%s" % bacula.name
+
+  # Read file data into Bacula memory buffer (mem)
+  #  return length read. 0 => EOF, -1 => error
+  def read(self, mem):
+     print "Read called\n"
+     len = self.fd.readinto(mem)
+     print "Read %s bytes into mem.\n" % len
+     return len
+
+  # Close file
+  def close(self):
+     self.fd.close()
index a6f072d8b7c523e6610a32dcafdc5b65cd76d34d..c1c05479453db6dcf727433a5a32346ea177ce2c 100644 (file)
@@ -222,8 +222,8 @@ int main (int argc, char *argv[])
 
    init_console_msg(working_directory);
 
-   init_python_interpreter(director->hdr.name, director->scripts_directory ?
-      director->scripts_directory : ".", "DirStartUp");
+   init_python_interpreter(director->hdr.name, director->scripts_directory
+       "DirStartUp");
 
    set_thread_concurrency(director->MaxConcurrentJobs * 2 +
       4 /* UA */ + 4 /* sched+watchdog+jobsvr+misc */);
@@ -255,12 +255,13 @@ int main (int argc, char *argv[])
 /* Cleanup and then exit */
 static void terminate_dird(int sig)
 {
-   static int already_here = FALSE;
+   static bool already_here = false;
 
    if (already_here) {                /* avoid recursive temination problems */
       exit(1);
    }
-   already_here = TRUE;
+   already_here = true;
+   generate_daemon_event(NULL, "Exit");
    write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
    delete_pid_file(director->pid_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
 // signal(SIGCHLD, SIG_IGN);          /* don't worry about children now */
index bf9a4ea8e40332686f34f61679fb5f44c98c463c..a42b66bc24f2ed961445a7d69423699abbd5dd1b 100644 (file)
@@ -93,7 +93,6 @@ JobId_t run_job(JCR *jcr)
    }
    jcr->term_wait_inited = true;
 
-   generate_daemon_event(jcr, "StartJob");
 
    /*
     * Open database
@@ -113,6 +112,7 @@ JobId_t run_job(JCR *jcr)
    }
    Dmsg0(50, "DB opened\n");
 
+
    /*
     * Create Job record
     */
@@ -124,10 +124,11 @@ JobId_t run_job(JCR *jcr)
       goto bail_out;
    }
    JobId = jcr->JobId = jcr->jr.JobId;
-
    Dmsg4(100, "Created job record JobId=%d Name=%s Type=%c Level=%c\n",
        jcr->JobId, jcr->Job, jcr->jr.JobType, jcr->jr.JobLevel);
 
+   generate_daemon_event(jcr, "JobStart");
+
    if (!get_or_create_client_record(jcr)) {
       goto bail_out;
    }
index e717b1271e8eee2d6ef629f8380ec8a263599553..f5445366e8228f1581faf6751d78bdcfc87d4db3 100644 (file)
 #include <Python.h>
 
 extern JCR *get_jcr_from_PyObject(PyObject *self);
-extern PyObject *find_method(PyObject *eventsObject, PyObject *method, char *name);
+extern PyObject *find_method(PyObject *eventsObject, PyObject *method, 
+         const char *name);
 
-static PyObject *jcr_get(PyObject *self, PyObject *args);
+static PyObject *job_get(PyObject *self, PyObject *args);
 static PyObject *jcr_write(PyObject *self, PyObject *args);
 static PyObject *jcr_set(PyObject *self, PyObject *args, PyObject *keyw);
-static PyObject *set_jcr_events(PyObject *self, PyObject *args);
+static PyObject *set_job_events(PyObject *self, PyObject *args);
 static PyObject *jcr_run(PyObject *self, PyObject *args);
 
 /* Define Job entry points */
 PyMethodDef JobMethods[] = {
-    {"get", jcr_get, METH_VARARGS, "Get Job variables."},
+    {"get", job_get, METH_VARARGS, "Get Job variables."},
     {"set", (PyCFunction)jcr_set, METH_VARARGS|METH_KEYWORDS,
         "Set Job variables."},
-    {"set_events", set_jcr_events, METH_VARARGS, "Define Job events."},
+    {"set_events", set_job_events, METH_VARARGS, "Define Job events."},
     {"write", jcr_write, METH_VARARGS, "Write output."},
     {"run", (PyCFunction)jcr_run, METH_VARARGS, "Run a Bacula command."},
     {NULL, NULL, 0, NULL}             /* last item */
 };
 
 
-static PyObject *open_method = NULL;
-static PyObject *read_method = NULL;
-static PyObject *close_method = NULL;
-
 struct s_vars {
    const char *name;
    char *fmt;
@@ -85,7 +82,7 @@ static struct s_vars vars[] = {
 };
 
 /* Return Job variables */
-static PyObject *jcr_get(PyObject *self, PyObject *args)
+static PyObject *job_get(PyObject *self, PyObject *args)
 {
    JCR *jcr;
    char *item;
@@ -93,6 +90,7 @@ static PyObject *jcr_get(PyObject *self, PyObject *args)
    int i;
    char buf[10];
 
+   Dmsg0(100, "In jcr_get.\n");
    if (!PyArg_ParseTuple(args, "s:get", &item)) {
       return NULL;
    }
@@ -146,6 +144,8 @@ static PyObject *jcr_set(PyObject *self, PyObject *args, PyObject *keyw)
    char *msg = NULL;
    char *VolumeName = NULL;
    static char *kwlist[] = {"JobReport", "VolumeName", NULL};
+
+   Dmsg0(100, "In jcr_set.\n");
    if (!PyArg_ParseTupleAndKeywords(args, keyw, "|ss:set", kwlist,
         &msg, &VolumeName)) {
       return NULL;
@@ -155,27 +155,39 @@ static PyObject *jcr_set(PyObject *self, PyObject *args, PyObject *keyw)
    if (msg) {
       Jmsg(jcr, M_INFO, 0, "%s", msg);
    }
+
+   if (!VolumeName) {
+      Dmsg1(100, "No VolumeName. Event=%s\n", jcr->event);
+   } else {
+      Dmsg2(100, "Vol=%s Event=%s\n", VolumeName, jcr->event);
+   }
    /* Make sure VolumeName is valid and we are in VolumeName event */
-   if (VolumeName && strcmp("VolumeName", jcr->event) == 0 &&
+   if (VolumeName && strcmp("NewVolume", jcr->event) == 0 &&
        is_volume_name_legal(NULL, VolumeName)) {
       pm_strcpy(jcr->VolumeName, VolumeName);
-   } else {
+      Dmsg1(100, "Set Vol=%s\n", VolumeName);
+   } else if (VolumeName) {
       jcr->VolumeName[0] = 0;
+      Dmsg0(100, "Zap VolumeName.\n");
       return Py_BuildValue("i", 0);  /* invalid volume name */
    }
    return Py_BuildValue("i", 1);
 }
 
-static PyObject *set_jcr_events(PyObject *self, PyObject *args)
+static PyObject *set_job_events(PyObject *self, PyObject *args)
 {
    PyObject *eObject;
+   JCR *jcr;
+
+   Dmsg0(100, "In set_job_events.\n");
    if (!PyArg_ParseTuple(args, "O:set_events_hook", &eObject)) {
       return NULL;
    }
-   Py_XINCREF(eObject);
-   open_method = find_method(eObject, open_method, "open");
-   read_method = find_method(eObject, read_method, "read");
-   close_method = find_method(eObject, close_method, "close");
+   jcr = get_jcr_from_PyObject(self);
+   Py_XDECREF((PyObject *)jcr->Python_events);
+   Py_INCREF(eObject);
+   jcr->Python_events = (void *)eObject;
+
    Py_INCREF(Py_None);
    return Py_None;
 }
@@ -184,6 +196,7 @@ static PyObject *set_jcr_events(PyObject *self, PyObject *args)
 static PyObject *jcr_write(PyObject *self, PyObject *args)
 {
    char *text;
+
    if (!PyArg_ParseTuple(args, "s:write", &text)) {
       return NULL;
    }
@@ -219,22 +232,39 @@ static PyObject *jcr_run(PyObject *self, PyObject *args)
 
 int generate_job_event(JCR *jcr, const char *event)
 {
-#ifdef xxx
-   PyObject *eObject, *method;
+   PyObject *method = NULL;
+   PyObject *Job = (PyObject *)jcr->Python_job;
+   PyObject *result = NULL;
+   int stat = 0;
+
+   if (!Job) {
+      return 0;
+   }
+
    PyEval_AcquireLock();
 
-   method = find_method(eObject, method, event);
+   PyObject *events = (PyObject *)jcr->Python_events;
+   method = find_method(events, method, event);
+   if (!method) {
+      goto bail_out;
+   }
 
-   PyObject *result = PyObject_CallFunction(method, "s", "m.py");
+   bstrncpy(jcr->event, event, sizeof(jcr->event));
+   result = PyObject_CallFunction(method, "O", Job);
+   jcr->event[0] = 0;             /* no event in progress */
    if (result == NULL) {
-      PyErr_Print();
-      PyErr_Clear();
+      if (PyErr_Occurred()) {
+         PyErr_Print();
+         Dmsg1(000, "Error in Python method %s\n", event);
+      }
+   } else {
+      stat = 1;
    }
    Py_XDECREF(result);
 
+bail_out:
    PyEval_ReleaseLock();
-#endif
-   return 1;
+   return stat;
 }
 
 #else
index 7125d4e57f6940cdcb45afc427ce0e4ad1b673fe..5c0da912ada4c87cc7b84e2c0131bf5ca5328653 100644 (file)
@@ -571,8 +571,8 @@ static int python_cmd(UAContext *ua, const char *cmd)
 {
    if (strcasecmp(ua->argk[1], _("restart")) == 0) {
       term_python_interpreter();
-      init_python_interpreter(director->hdr.name, director->scripts_directory ?
-         director->scripts_directory : ".", "DirStartUp");
+      init_python_interpreter(director->hdr.name, 
+         director->scripts_directory, "DirStartUp");
       bsendmsg(ua, _("Python interpreter restarted.\n"));
    } else {
       bsendmsg(ua, _("Nothing done.\n"));
index 9fdd1983f762708191cf46207ae1fa13c3351a4e..bcfa65c5ed6e287b6a8d1d167a5fdabd63505547 100644 (file)
@@ -230,8 +230,7 @@ int main (int argc, char *argv[])
    me += 1000000;
 #endif
 
-   init_python_interpreter(me->hdr.name, me->scripts_directory ?
-         me->scripts_directory : ".", "FDStartUp");
+   init_python_interpreter(me->hdr.name, me->scripts_directory, "FDStartUp");
 
    set_thread_concurrency(10);
 
index ea7c0cdb6dc3a3c25057a6c87c4ef882f032e10f..3af306a47790204bf8a2ca91ff43f989f1061abe 100644 (file)
@@ -36,7 +36,8 @@
 #include <Python.h>
 
 extern JCR *get_jcr_from_PyObject(PyObject *self);
-extern PyObject *find_method(PyObject *eventsObject, PyObject *method, char *name);
+extern PyObject *find_method(PyObject *eventsObject, PyObject *method, 
+          const char *name);
 
 static PyObject *jcr_get(PyObject *self, PyObject *args);
 static PyObject *jcr_write(PyObject *self, PyObject *args);
index 6cccbdcd029bb53473ed7b2c77a90e0d42fd011a..271655b635b67f9f74b3c137b35dd1dd618af27b 100644 (file)
@@ -143,7 +143,8 @@ struct JCR {
    bool prefix_links;                 /* Prefix links with Where path */
    bool gui;                          /* set if gui using console */
    bool authenticated;                /* set when client authenticated */
-   void *Python_jcr;                  /* Python Job Object */
+   void *Python_job;                  /* Python Job Object */
+   void *Python_events;               /* Python Events Object */
 
    /* Daemon specific part of JCR */
    /* This should be empty in the library */
index 47b9c2d2d083c1fd02015ad1c3d77d1cf3628f87..df440b5e9ff7ce39d8f28f0b74e74dfa9c3bce83 100644 (file)
@@ -29,7 +29,7 @@ LIBSRCS = alloc.c attr.c base64.c berrno.c bsys.c bget_msg.c \
          queue.c res.c rwlock.c scan.c serial.c sha1.c \
          semlock.c signal.c smartall.c tree.c \
          util.c var.c watchdog.c workq.c btimers.c \
-         address_conf.c python.c 
+         address_conf.c pythonlib.c 
 
 
 LIBOBJS = alloc.o attr.o base64.o berrno.o bsys.o bget_msg.o \
@@ -41,7 +41,7 @@ LIBOBJS = alloc.o attr.o base64.o berrno.o bsys.o bget_msg.o \
          queue.o res.o rwlock.o scan.o serial.o sha1.o \
          semlock.o signal.o smartall.o tree.o \
          util.o var.o watchdog.o workq.o btimers.o \
-         address_conf.o python.o
+         address_conf.o pythonlib.o
 
 
 EXTRAOBJS = @OBJLIST@
@@ -72,7 +72,7 @@ Makefile: $(srcdir)/Makefile.in $(topdir)/config.status
        cd $(topdir) \
          && CONFIG_FILES=$(thisdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
 
-python.o: python.c
+pythonlib.o: pythonlib.c
        $(CXX) $(DEFS) $(DEBUG) -c $(WCFLAGS) $(CPPFLAGS) $(python) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) $<
 
 rwlock_test:
index 44a0e484883d36404e842fa5a60418374a80c35e..709a30d9b2677405e458c6f1b8ee3343eef3f7f1 100755 (executable)
@@ -354,9 +354,6 @@ void free_jcr(JCR *jcr)
 #endif
 
    dequeue_messages(jcr);
-   if (jcr->JobId != 0) {
-      generate_daemon_event(jcr, "JobEnd");
-   }
    lock_jcr_chain();
    jcr->use_count--;                  /* decrement use count */
    if (jcr->use_count < 0) {
@@ -369,6 +366,14 @@ void free_jcr(JCR *jcr)
       Dmsg2(3400, "free_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
       return;
    }
+
+   /* 
+    * At this point, we are actually releasing the JCR, which
+    *  means that the job is complete.
+    */
+   if (jcr->JobId != 0) {
+      generate_daemon_event(jcr, "JobEnd");
+   }
    remove_jcr(jcr);                   /* remove Jcr from chain */
    unlock_jcr_chain();
 
diff --git a/bacula/src/lib/python.c b/bacula/src/lib/python.c
deleted file mode 100644 (file)
index cfc3ebd..0000000
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- *
- * Bacula common code library interface to Python
- *
- * Kern Sibbald, November MMIV
- *
- *   Version $Id$
- *
- */
-
-/*
-   Copyright (C) 2004-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 "jcr.h"
-
-#ifdef HAVE_PYTHON
-
-#undef _POSIX_C_SOURCE
-#include <Python.h>
-
-static PyObject *bacula_module = NULL;    /* We create this */
-static PyObject *StartUp_module = NULL;   /* We import this */
-
-/* These are the daemon events or methods that are defined */
-static PyObject *JobStart_method = NULL;
-static PyObject *JobEnd_method = NULL;
-static PyObject *Exit_method = NULL;
-
-
-static PyObject *set_bacula_events(PyObject *self, PyObject *args);
-static PyObject *bacula_write(PyObject *self, PyObject *args);
-
-PyObject *find_method(PyObject *eventsObject, PyObject *method, char *name);
-
-/* Define Bacula daemon method entry points */
-static PyMethodDef BaculaMethods[] = {
-    {"set_events", set_bacula_events, METH_VARARGS, "Define Bacula events."},
-    {"write", bacula_write, METH_VARARGS, "Write output."},
-    {NULL, NULL, 0, NULL}             /* last item */
-};
-
-
-/*
- * This is a Bacula Job type as defined in Python. We store a pointer
- *   to the jcr. That is all we need, but the user's script may keep
- *   local data attached to this. 
- */
-typedef struct JCRObject {
-    PyObject_HEAD
-    JCR *jcr;
-} JCRObject;
-
-static PyTypeObject JCRType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
-    "bacula.jcr",              /*tp_name*/
-    sizeof(JCRObject),         /*tp_basicsize*/
-    0,                         /*tp_itemsize*/
-    0,                         /*tp_dealloc*/
-    0,                         /*tp_print*/
-    0,                         /*tp_getattr*/
-    0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
-    0,                         /*tp_repr*/
-    0,                         /*tp_as_number*/
-    0,                         /*tp_as_sequence*/
-    0,                         /*tp_as_mapping*/
-    0,                         /*tp_hash */
-    0,                         /*tp_call*/
-    0,                         /*tp_str*/
-    0,                         /*tp_getattro*/
-    0,                         /*tp_setattro*/
-    0,                         /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT, /*tp_flags*/
-    "JCR objects",             /* tp_doc */
-    0,                         /* tp_traverse */
-    0,                         /* tp_clear */
-    0,                         /* tp_richcompare */
-    0,                         /* tp_weaklistoffset */
-    0,                         /* tp_iter */
-    0,                         /* tp_iternext */
-    0,                         /* tp_methods */
-    0,                         /* tp_members */
-    0,                         /* tp_getset */
-    0,                         /* tp_base */
-    0,                         /* tp_dict */
-    0,                         /* tp_descr_get */
-    0,                         /* tp_descr_set */
-    0,                         /* tp_dictoffset */
-    0,                         /* tp_init */
-    0,                         /* tp_alloc */
-    0,                         /* tp_new */
-};
-
-/* Return the JCR pointer from the JCRObject */
-JCR *get_jcr_from_PyObject(PyObject *self)
-{
-   return ((JCRObject *)self)->jcr;
-}
-
-
-/* Start the interpreter */
-void init_python_interpreter(const char *progname, const char *scripts,
-    const char *module)
-{
-   char buf[MAXSTRING];
-   Py_SetProgramName((char *)progname);
-   Py_Initialize();
-   PyEval_InitThreads();
-   bacula_module = Py_InitModule("bacula", BaculaMethods);
-   if (!bacula_module) {
-      Jmsg(NULL, M_ERROR_TERM, 0, "Could not initialize Python\n");
-   }
-   bsnprintf(buf, sizeof(buf), "import sys\n"
-            "sys.path.append('%s')\n", scripts);
-   if (PyRun_SimpleString(buf) != 0) {
-      Jmsg(NULL, M_ERROR_TERM, 0, "Could not Run Python string %s\n", buf);
-   }   
-   JCRType.tp_methods = BaculaMethods;
-   if(PyType_Ready(&JCRType) != 0) {
-      Jmsg(NULL, M_ERROR_TERM, 0, "Could not initialize Python Job type.\n");
-      PyErr_Print();
-   }   
-   StartUp_module = PyImport_ImportModule((char *)module);
-   if (!StartUp_module) {
-      Jmsg(NULL, M_ERROR_TERM, 0, "Could not import script %s/%s.\n",
-           scripts, module);
-      PyErr_Clear();
-   }
-   PyEval_ReleaseLock();
-}
-
-
-void term_python_interpreter()
-{
-   Py_XDECREF(StartUp_module);
-   Py_Finalize();
-}
-
-static PyObject *set_bacula_events(PyObject *self, PyObject *args)
-{
-   PyObject *eObject;
-   if (!PyArg_ParseTuple(args, "O:set_bacula_events", &eObject)) {
-      return NULL;
-   }
-   JobStart_method = find_method(eObject, JobStart_method, "JobStart");
-   JobEnd_method = find_method(eObject, JobEnd_method, "JobEnd");
-   Exit_method = find_method(eObject, Exit_method, "Exit");
-
-   Py_XINCREF(eObject);
-   Py_INCREF(Py_None);
-   return Py_None;
-}
-
-/* Write text to daemon output */
-static PyObject *bacula_write(PyObject *self, PyObject *args)
-{
-   char *text;
-   if (!PyArg_ParseTuple(args, "s:write", &text)) {
-      return NULL;
-   }
-   if (text) {
-      Jmsg(NULL, M_INFO, 0, "%s", text);
-   }
-   Py_INCREF(Py_None);
-   return Py_None;
-}
-
-
-/*
- * Check that a method exists and is callable.
- */
-PyObject *find_method(PyObject *eventsObject, PyObject *method, char *name)
-{
-   Py_XDECREF(method);             /* release old method if any */
-   method = PyObject_GetAttrString(eventsObject, name);
-   if (method == NULL) {
-       Dmsg1(000, "Python method %s not found\n", name);
-   } else if (PyCallable_Check(method) == 0) {
-       Dmsg1(000, "Python object %s found but not a method.\n", name);
-       Py_XDECREF(method);
-       method = NULL;
-   } else {
-       Dmsg1(000, "Got method %s\n", name);
-   }
-   return method; 
-}
-
-
-/*
- * Generate and process a Bacula event by importing a Python
- *  module and running it.
- *
- *  Returns: 0 if Python not configured or module not found
- *          -1 on Python error
- *           1 OK
- */
-int generate_daemon_event(JCR *jcr, const char *event)
-{
-   PyObject *pJCR;
-   int stat = -1;
-   PyObject *result = NULL;
-
-   PyEval_AcquireLock();
-   if (strcmp(event, "JobStart") == 0) {
-      if (!JobStart_method) {
-         stat = 0;
-         goto bail_out;
-      }
-      /* Create JCR argument to send to function */
-      pJCR = (PyObject *)PyObject_New(JCRObject, &JCRType);
-      if (!pJCR) {
-         Jmsg(jcr, M_ERROR, 0, "Could not create JCR Python Object.\n");
-         goto bail_out;
-      }
-      ((JCRObject *)pJCR)->jcr = jcr;
-      bstrncpy(jcr->event, event, sizeof(jcr->event));
-      result = PyObject_CallFunction(JobStart_method, "O", pJCR);
-      jcr->event[0] = 0;             /* no event in progress */
-      if (result == NULL) {
-         JobStart_method = NULL;
-         if (PyErr_Occurred()) {
-            PyErr_Print();
-         }
-         Jmsg(jcr, M_ERROR, 0, "Python function \"%s\" not found.\n", event);
-         Py_XDECREF(pJCR);
-         goto bail_out;
-      }
-      jcr->Python_jcr = (void *)pJCR;
-      stat = 1;                       /* OK */
-
-   } else if (strcmp(event, "JobEnd") == 0) {
-      if (!JobEnd_method) {
-         Py_XDECREF((PyObject *)jcr->Python_jcr);
-         stat = 0;
-         goto bail_out;
-      }
-      bstrncpy(jcr->event, event, sizeof(jcr->event));
-      result = PyObject_CallFunction(JobEnd_method, "O", jcr->Python_jcr);
-      jcr->event[0] = 0;             /* no event in progress */
-      if (result == NULL) {
-         JobEnd_method = NULL;
-         if (PyErr_Occurred()) {
-            PyErr_Print();
-         }
-         Jmsg(jcr, M_ERROR, 0, "Python function \"%s\" not found.\n", event);
-         Py_XDECREF((PyObject *)jcr->Python_jcr);
-         goto bail_out;
-      }
-      Py_XDECREF((PyObject *)jcr->Python_jcr);
-      stat = 1;                    /* OK */
-   }
-
-bail_out:
-   Py_XDECREF(result);
-   PyEval_ReleaseLock();
-   return stat; 
-}
-
-#ifdef xxx
-   PyObject *pName, *pModule, *pDict, *pFunc;
-   PyObject *pArgs, *pJCR, *pCall;
-   
-   Dmsg1(100, "Generate event %s\n", event);
-   pName = PyString_FromString(event);
-   if (!pName) {
-      Jmsg(jcr, M_ERROR, 0, "Could not convert \"%s\" to Python string.\n", event);
-      return -1;                      /* Could not convert string */
-   }
-
-   pModule = PyImport_Import(pName);
-   Py_DECREF(pName);                  /* release pName */
-
-   if (pModule != NULL) {
-      pDict = PyModule_GetDict(pModule);
-      /* pDict is a borrowed reference */
-
-      pFunc = PyDict_GetItemString(pDict, (char *)event);
-      /* pFun: Borrowed reference */
-
-      if (pFunc && PyCallable_Check(pFunc)) {
-          /* Create JCR argument to send to function */
-          pArgs = PyTuple_New(1);
-          pJCR = (PyObject *)PyObject_New(JCRObject, &JCRType);
-          ((JCRObject *)pJCR)->jcr = jcr;
-          if (!pJCR) {
-             Py_DECREF(pArgs);
-             Py_DECREF(pModule);
-             Jmsg(jcr, M_ERROR, 0, "Could not create JCR Python Object.\n");
-             return -1;
-          }
-          Py_INCREF(pJCR);
-          /* pJCR reference stolen here: */
-          PyTuple_SetItem(pArgs, 0, pJCR);
-
-          /* Finally, we call the module here */
-          bstrncpy(jcr->event, event, sizeof(jcr->event));
-          pCall = PyObject_CallObject(pFunc, pArgs);
-          jcr->event[0] = 0;             /* no event in progress */
-          Py_DECREF(pArgs);
-          Py_DECREF(pJCR);
-          if (pCall != NULL) {
-             Py_DECREF(pCall);
-          } else {
-             Py_DECREF(pModule);
-             PyErr_Print();
-             Jmsg(jcr, M_ERROR, 0, "Error running Python module: %s\n", event);
-             return 0;                /* error running function */
-          }
-          /* pDict and pFunc are borrowed and must not be Py_DECREF-ed */
-      } else {
-         if (PyErr_Occurred()) {
-            PyErr_Print();
-         }
-         Jmsg(jcr, M_ERROR, 0, "Python function \"%s\" not found in module.\n", event);
-         return -1;                   /* function not found */
-      }
-      Py_DECREF(pModule);
-   } else {
-      return 0;                       /* Module not present */
-   }
-   Dmsg0(100, "Generate event OK\n");
-   return 1;
-}
-#endif
-
-#else
-
-/*
- *  No Python configured -- create external entry points and
- *    dummy routines so that library code can call this without
- *    problems even if it is not configured.
- */
-int generate_daemon_event(JCR *jcr, const char *event) { return 0; }
-void init_python_interpreter(const char *progname, const char *scripts,
-         const char *module) { }
-void term_python_interpreter() { }
-
-#endif /* HAVE_PYTHON */
diff --git a/bacula/src/lib/pythonlib.c b/bacula/src/lib/pythonlib.c
new file mode 100644 (file)
index 0000000..7ad1030
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ *
+ * Bacula common code library interface to Python
+ *
+ * Kern Sibbald, November MMIV
+ *
+ *   Version $Id$
+ *
+ */
+
+/*
+   Copyright (C) 2004-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 "jcr.h"
+
+#ifdef HAVE_PYTHON
+
+#undef _POSIX_C_SOURCE
+#include <Python.h>
+
+/* Imported subroutines */
+extern PyMethodDef JobMethods[];
+
+static PyObject *bacula_module = NULL;    /* We create this */
+static PyObject *StartUp_module = NULL;   /* We import this */
+
+/* These are the daemon events or methods that are defined */
+static PyObject *JobStart_method = NULL;
+static PyObject *JobEnd_method = NULL;
+static PyObject *Exit_method = NULL;
+
+static PyObject *set_bacula_events(PyObject *self, PyObject *args);
+static PyObject *bacula_write(PyObject *self, PyObject *args);
+
+PyObject *find_method(PyObject *eventsObject, PyObject *method, const char *name);
+
+/* Define Bacula daemon method entry points */
+static PyMethodDef BaculaMethods[] = {
+    {"set_events", set_bacula_events, METH_VARARGS, "Define Bacula events."},
+    {"write", bacula_write, METH_VARARGS, "Write output."},
+    {NULL, NULL, 0, NULL}             /* last item */
+};
+
+
+/*
+ * This is a Bacula Job type as defined in Python. We store a pointer
+ *   to the jcr. That is all we need, but the user's script may keep
+ *   local data attached to this. 
+ */
+typedef struct s_JobObject {
+    PyObject_HEAD
+    JCR *jcr;
+} JobObject;
+
+static PyTypeObject JobType = {
+    PyObject_HEAD_INIT(NULL)
+    0,                         /*ob_size*/
+    "bacula.jcr",              /*tp_name*/
+    sizeof(JobObject),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    0,                         /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_compare*/
+    0,                         /*tp_repr*/
+    0,                         /*tp_as_number*/
+    0,                         /*tp_as_sequence*/
+    0,                         /*tp_as_mapping*/
+    0,                         /*tp_hash */
+    0,                         /*tp_call*/
+    0,                         /*tp_str*/
+    0,                         /*tp_getattro*/
+    0,                         /*tp_setattro*/
+    0,                         /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT, /*tp_flags*/
+    "Job objects",             /* tp_doc */
+    0,                         /* tp_traverse */
+    0,                         /* tp_clear */
+    0,                         /* tp_richcompare */
+    0,                         /* tp_weaklistoffset */
+    0,                         /* tp_iter */
+    0,                         /* tp_iternext */
+    JobMethods,                /* tp_methods */
+    0,                         /* tp_members */
+    0,                         /* tp_getset */
+    0,                         /* tp_base */
+    0,                         /* tp_dict */
+    0,                         /* tp_descr_get */
+    0,                         /* tp_descr_set */
+    0,                         /* tp_dictoffset */
+    0,                         /* tp_init */
+    0,                         /* tp_alloc */
+    0,                         /* tp_new */
+};
+
+/* Return the JCR pointer from the JobObject */
+JCR *get_jcr_from_PyObject(PyObject *self)
+{
+   return ((JobObject *)self)->jcr;
+}
+
+
+/* Start the interpreter */
+void init_python_interpreter(const char *progname, const char *scripts,
+    const char *module)
+{
+   char buf[MAXSTRING];
+
+   if (!scripts || scripts[0] == 0) {
+      return;
+   }
+
+   Py_SetProgramName((char *)progname);
+   Py_Initialize();
+   PyEval_InitThreads();
+   bacula_module = Py_InitModule("bacula", BaculaMethods);
+   if (!bacula_module) {
+      Jmsg0(NULL, M_ERROR_TERM, 0, "Could not initialize Python\n");
+   }
+   bsnprintf(buf, sizeof(buf), "import sys\n"
+            "sys.path.append('%s')\n", scripts);
+   if (PyRun_SimpleString(buf) != 0) {
+      Jmsg1(NULL, M_ERROR_TERM, 0, "Could not Run Python string %s\n", buf);
+   }   
+   JobType.tp_methods = JobMethods;
+   if(PyType_Ready(&JobType) != 0) {
+      Jmsg0(NULL, M_ERROR_TERM, 0, "Could not initialize Python Job type.\n");
+      PyErr_Print();
+   }   
+   StartUp_module = PyImport_ImportModule((char *)module);
+   if (!StartUp_module) {
+      Emsg2(M_ERROR, 0, "Could not import Python script %s/%s. Python disabled.\n",
+           scripts, module);
+      if (PyErr_Occurred()) {
+         PyErr_Print();
+         Dmsg0(000, "Python Import error.\n");
+      }
+   }
+   PyEval_ReleaseLock();
+}
+
+
+void term_python_interpreter()
+{
+   if (StartUp_module) {
+      Py_XDECREF(StartUp_module);
+      Py_Finalize();
+   }
+}
+
+static PyObject *set_bacula_events(PyObject *self, PyObject *args)
+{
+   PyObject *eObject;
+
+   Dmsg0(100, "In set_bacula_events.\n");
+   if (!PyArg_ParseTuple(args, "O:set_bacula_events", &eObject)) {
+      return NULL;
+   }
+   JobStart_method = find_method(eObject, JobStart_method, "JobStart");
+   JobEnd_method = find_method(eObject, JobEnd_method, "JobEnd");
+   Exit_method = find_method(eObject, Exit_method, "Exit");
+
+   Py_XINCREF(eObject);
+   Py_INCREF(Py_None);
+   return Py_None;
+}
+
+/* Write text to daemon output */
+static PyObject *bacula_write(PyObject *self, PyObject *args)
+{
+   char *text;
+   if (!PyArg_ParseTuple(args, "s:write", &text)) {
+      return NULL;
+   }
+   if (text) {
+      Jmsg(NULL, M_INFO, 0, "%s", text);
+   }
+   Py_INCREF(Py_None);
+   return Py_None;
+}
+
+
+/*
+ * Check that a method exists and is callable.
+ */
+PyObject *find_method(PyObject *eventsObject, PyObject *method, const char *name)
+{
+   Py_XDECREF(method);             /* release old method if any */
+   method = PyObject_GetAttrString(eventsObject, (char *)name);
+   if (method == NULL) {
+       Dmsg1(000, "Python method %s not found\n", name);
+   } else if (PyCallable_Check(method) == 0) {
+       Dmsg1(000, "Python object %s found but not a method.\n", name);
+       Py_XDECREF(method);
+       method = NULL;
+   } else {
+       Dmsg1(100, "Got method %s\n", name);
+   }
+   return method; 
+}
+
+
+/*
+ * Generate and process a Bacula event by importing a Python
+ *  module and running it.
+ *
+ *  Returns: 0 if Python not configured or module not found
+ *          -1 on Python error
+ *           1 OK
+ */
+int generate_daemon_event(JCR *jcr, const char *event)
+{
+   PyObject *pJob;
+   int stat = -1;
+   PyObject *result = NULL;
+
+   if (!StartUp_module) {
+      return 0;
+   }
+
+   PyEval_AcquireLock();
+   if (strcmp(event, "JobStart") == 0) {
+      if (!JobStart_method) {
+         stat = 0;
+         goto bail_out;
+      }
+      /* Create JCR argument to send to function */
+      pJob = (PyObject *)PyObject_New(JobObject, &JobType);
+      if (!pJob) {
+         Jmsg(jcr, M_ERROR, 0, "Could not create Python Job Object.\n");
+         goto bail_out;
+      }
+      ((JobObject *)pJob)->jcr = jcr;
+      bstrncpy(jcr->event, event, sizeof(jcr->event));
+      result = PyObject_CallFunction(JobStart_method, "O", pJob);
+      jcr->event[0] = 0;             /* no event in progress */
+      if (result == NULL) {
+         JobStart_method = NULL;
+         if (PyErr_Occurred()) {
+            PyErr_Print();
+            Dmsg0(000, "Python JobStart error.\n");
+         }
+         Jmsg(jcr, M_ERROR, 0, "Python function \"%s\" not found.\n", event);
+         Py_XDECREF(pJob);
+         goto bail_out;
+      }
+      jcr->Python_job = (void *)pJob;
+      stat = 1;                       /* OK */
+      goto jobstart_ok;
+
+   } else if (strcmp(event, "JobEnd") == 0) {
+      if (!JobEnd_method) {
+         stat = 0;
+         goto bail_out;
+      }
+      bstrncpy(jcr->event, event, sizeof(jcr->event));
+      result = PyObject_CallFunction(JobEnd_method, "O", jcr->Python_job);
+      jcr->event[0] = 0;             /* no event in progress */
+      if (result == NULL) {
+         JobEnd_method = NULL;
+         if (PyErr_Occurred()) {
+            PyErr_Print();
+            Dmsg1(000, "Python JobEnd error. JobId=%d\n", jcr->JobId);
+         }
+         Jmsg(jcr, M_ERROR, 0, "Python function \"%s\" not found.\n", event);
+         goto bail_out;
+      }
+      stat = 1;                    /* OK */
+   } else if (strcmp(event, "Exit") == 0) {
+      if (!Exit_method) {
+         stat = 0;
+         goto bail_out;
+      }
+      result = PyObject_CallFunction(JobEnd_method, NULL);
+      if (result == NULL) {
+         goto bail_out;
+      }
+      stat = 1;                    /* OK */
+   } else {
+      Emsg1(M_ABORT, 0, "Unknown Python daemon event %s\n", event);
+   }
+
+bail_out:
+   Py_XDECREF((PyObject *)jcr->Python_job);
+   jcr->Python_job = NULL;
+   Py_XDECREF((PyObject *)jcr->Python_events);
+   jcr->Python_events = NULL;
+   /* Fall through */
+jobstart_ok:
+   Py_XDECREF(result);
+   PyEval_ReleaseLock();
+   return stat; 
+}
+
+#ifdef xxx
+   PyObject *pName, *pModule, *pDict, *pFunc;
+   PyObject *pArgs, *pJCR, *pCall;
+   
+   Dmsg1(100, "Generate event %s\n", event);
+   pName = PyString_FromString(event);
+   if (!pName) {
+      Jmsg(jcr, M_ERROR, 0, "Could not convert \"%s\" to Python string.\n", event);
+      return -1;                      /* Could not convert string */
+   }
+
+   pModule = PyImport_Import(pName);
+   Py_DECREF(pName);                  /* release pName */
+
+   if (pModule != NULL) {
+      pDict = PyModule_GetDict(pModule);
+      /* pDict is a borrowed reference */
+
+      pFunc = PyDict_GetItemString(pDict, (char *)event);
+      /* pFun: Borrowed reference */
+
+      if (pFunc && PyCallable_Check(pFunc)) {
+          /* Create JCR argument to send to function */
+          pArgs = PyTuple_New(1);
+          pJCR = (PyObject *)PyObject_New(JCRObject, &JCRType);
+          ((JCRObject *)pJCR)->jcr = jcr;
+          if (!pJCR) {
+             Py_DECREF(pArgs);
+             Py_DECREF(pModule);
+             Jmsg0(jcr, M_ERROR, 0, "Could not create JCR Python Object.\n");
+             return -1;
+          }
+          Py_INCREF(pJCR);
+          /* pJCR reference stolen here: */
+          PyTuple_SetItem(pArgs, 0, pJCR);
+
+          /* Finally, we call the module here */
+          bstrncpy(jcr->event, event, sizeof(jcr->event));
+          pCall = PyObject_CallObject(pFunc, pArgs);
+          jcr->event[0] = 0;             /* no event in progress */
+          Py_DECREF(pArgs);
+          Py_DECREF(pJCR);
+          if (pCall != NULL) {
+             Py_DECREF(pCall);
+          } else {
+             Py_DECREF(pModule);
+             PyErr_Print();
+             Jmsg1(jcr, M_ERROR, 0, "Error running Python module: %s\n", event);
+             return 0;                /* error running function */
+          }
+          /* pDict and pFunc are borrowed and must not be Py_DECREF-ed */
+      } else {
+         if (PyErr_Occurred()) {
+            PyErr_Print();
+            Dmsg1(000, "Python event %s function not callable.\n", event);
+         }
+         Jmsg1(jcr, M_ERROR, 0, "Python function \"%s\" not found in module.\n", event);
+         return -1;                   /* function not found */
+      }
+      Py_DECREF(pModule);
+   } else {
+      return 0;                       /* Module not present */
+   }
+   Dmsg0(100, "Generate event OK\n");
+   return 1;
+}
+#endif
+
+#else
+
+/*
+ *  No Python configured -- create external entry points and
+ *    dummy routines so that library code can call this without
+ *    problems even if it is not configured.
+ */
+int generate_daemon_event(JCR *jcr, const char *event) { return 0; }
+void init_python_interpreter(const char *progname, const char *scripts,
+         const char *module) { }
+void term_python_interpreter() { }
+
+#endif /* HAVE_PYTHON */
index 00e95f78ad2c0ee21bf22311a2746e19559c2876..aa9e7e86a1ea64ec40975429e9f5e357e5744bab 100644 (file)
@@ -36,7 +36,8 @@
 #include <Python.h>
 
 extern JCR *get_jcr_from_PyObject(PyObject *self);
-extern PyObject *find_method(PyObject *eventsObject, PyObject *method, char *name);
+extern PyObject *find_method(PyObject *eventsObject, PyObject *method, 
+         const char *name);
 
 static PyObject *jcr_get(PyObject *self, PyObject *args);
 static PyObject *jcr_write(PyObject *self, PyObject *args);
index d45ca8b0d3f99efbc53f3aba9382afa5a865d1b1..0f404349330385f8e160ade0a15c2de14c42f92d 100644 (file)
@@ -208,8 +208,7 @@ int main (int argc, char *argv[])
       Jmsg0(NULL, M_ABORT, 0, _("Volume Session Time is ZERO!\n"));
    }
 
-   init_python_interpreter(me->hdr.name, me->scripts_directory ?
-         me->scripts_directory : ".", "SDStartUp");
+   init_python_interpreter(me->hdr.name, me->scripts_directory, "SDStartUp");
 
    /* Make sure on Solaris we can run concurrent, watch dog + servers + misc */
    set_thread_concurrency(me->max_concurrent_jobs * 2 + 4);