jobid = job.JobId
      client = job.Client 
      numvol = job.NumVols;
+     print job.CatalogRes
      job.JobReport = "JobId=%d Client=%s NumVols=%d" % (jobid, client, numvol)
      job.JobReport="Python before New Volume set for Job.\n"
-     job.VolumeName="TestA-001"
+     Vol = "TestA-%d" % numvol
+     job.JobReport = "Exists=%d TestA-%d" % (job.DoesVolumeExist(Vol), numvol)
+     job.VolumeName="TestA-%d" % numvol 
      job.JobReport="Python after New Volume set for Job.\n"  
      return 1
 
 
 
 General:
 
+Changes to 1.37.27:
+27Jun05
+- Add Database vendor to CatalogRes tuple for Python.
+- Update doc
+- Implement DoesVolumeExist(Vol) for Python.
+- Prevent python command from seg faulting if no arg given.
+
 Changes to 1.37.26:
 26Jun05
 - Add set_mode method in DEVICE.
 
 int db_get_job_volume_names(JCR *jcr, B_DB *mdb, JobId_t JobId, POOLMEM **VolumeNames);
 int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, FILE_DBR *fdbr);
 int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr);
-int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr);
+bool db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr);
 int db_get_num_media_records(JCR *jcr, B_DB *mdb);
 int db_get_num_pool_records(JCR *jcr, B_DB *mdb);
 int db_get_pool_ids(JCR *jcr, B_DB *mdb, int *num_ids, DBId_t **ids);
 int db_get_client_ids(JCR *jcr, B_DB *mdb, int *num_ids, DBId_t **ids);
-int db_get_media_ids(JCR *jcr, B_DB *mdb, DBId_t PoolId, int *num_ids, uint32_t **ids);
+bool db_get_media_ids(JCR *jcr, B_DB *mdb, DBId_t PoolId, int *num_ids, uint32_t **ids);
 int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, JobId_t JobId, VOL_PARAMS **VolParams);
 int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr);
 int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr);
 
  *     the current Pool.
  *  The caller must free ids if non-NULL.
  *
- *  Returns 0: on failure
- *          1: on success
+ *  Returns false: on failure
+ *          true:  on success
  */
-int db_get_media_ids(JCR *jcr, B_DB *mdb, uint32_t PoolId, int *num_ids, uint32_t *ids[])
+bool db_get_media_ids(JCR *jcr, B_DB *mdb, uint32_t PoolId, int *num_ids, uint32_t *ids[])
 {
    SQL_ROW row;
-   int stat = 0;
    int i = 0;
    uint32_t *id;
    char ed1[50];
+   bool ok = false;
 
    db_lock(mdb);
    *ids = NULL;
          *ids = id;
       }
       sql_free_result(mdb);
-      stat = 1;
+      ok = true;
    } else {
       Mmsg(mdb->errmsg, _("Media id select failed: ERR=%s\n"), sql_strerror(mdb));
       Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
-      stat = 0;
+      ok = false;
    }
    db_unlock(mdb);
-   return stat;
+   return ok;
 }
 
 
 /* Get Media Record
  *
- * Returns: 0 on failure
- *          id on success
+ * Returns: false: on failure
+ *          true:  on success
  */
-int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
+bool db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
 {
    SQL_ROW row;
-   int stat = 0;
    char ed1[50];
+   bool ok = false;
 
    db_lock(mdb);
    if (mr->MediaId == 0 && mr->VolumeName[0] == 0) {
       Mmsg(mdb->cmd, "SELECT count(*) from Media");
       mr->MediaId = get_sql_record_max(jcr, mdb);
       db_unlock(mdb);
-      return 1;
+      return true;
    }
    if (mr->MediaId != 0) {               /* find by id */
       Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
             bstrncpy(mr->cLabelDate, row[27]!=NULL?row[27]:"", sizeof(mr->cLabelDate));
             mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate);
             mr->StorageId = str_to_int64(row[28]);
-            stat = mr->MediaId;
+            ok = true;
          }
       } else {
          if (mr->MediaId != 0) {
             mr->VolumeName);
    }   }
    db_unlock(mdb);
-   return stat;
+   return ok;
 }
 
 
 
 static PyObject *job_run(PyObject *self, PyObject *arg);
 static PyObject *job_write(PyObject *self, PyObject *arg);
 static PyObject *job_cancel(PyObject *self, PyObject *arg);
+static PyObject *job_does_vol_exist(PyObject *self, PyObject *arg);
 
 PyMethodDef JobMethods[] = {
     {"set_events", set_job_events, METH_VARARGS, "Set Job events"},
     {"run", job_run, METH_VARARGS, "Run a Job"},
     {"write", job_write, METH_VARARGS, "Write to output"},
     {"cancel", job_cancel, METH_VARARGS, "Cancel a Job"},
+    {"DoesVolumeExist", job_does_vol_exist, METH_VARARGS, "Does Volume Exist"},
     {NULL, NULL, 0, NULL}             /* last item */
 };
  
    { N_("Version"),    "(ss)"},
    { N_("ConfigFile"), "s"},
    { N_("WorkingDir"), "s"},
-   { N_("CatalogRes"), "(sssssi)"},
+   { N_("CatalogRes"), "(sssssis)"},
 
    { NULL,             NULL}
 };
    case 5:                            /* Client */
       return Py_BuildValue(getvars[i].fmt, jcr->client->hdr.name);
    case 6:                            /* NumVols */
-      return Py_BuildValue(getvars[i].fmt, jcr->NumVols);
+      POOL_DBR pr;
+      memset(&pr, 0, sizeof(pr));
+      bstrncpy(pr.Name, jcr->pool->hdr.name, sizeof(pr.Name));
+      if (db_get_pool_record(jcr, jcr->db, &pr)) {
+         jcr->NumVols = pr.NumVols;
+         return Py_BuildValue(getvars[i].fmt, jcr->NumVols);
+      } else {
+         bsnprintf(errmsg, sizeof(errmsg), "Pool record not found.");
+         goto bail_out;
+      }
    case 7:                            /* Pool */
       return Py_BuildValue(getvars[i].fmt, jcr->pool->hdr.name);
    case 8:                            /* Storage */
       return Py_BuildValue(getvars[i].fmt,
          jcr->catalog->db_name, jcr->catalog->db_address, 
          jcr->catalog->db_user, jcr->catalog->db_password,
-         jcr->catalog->db_socket, jcr->catalog->db_port);
+         jcr->catalog->db_socket, jcr->catalog->db_port,
+         catalog_db);
 
    }
    bsnprintf(errmsg, sizeof(errmsg), "Attribute %s not found.", attrname);
       return NULL;
    }
    if (text) {
-      Jmsg(NULL, M_INFO, 0, "%s", text);
+      JCR *jcr = get_jcr_from_PyObject(self);
+      Jmsg(jcr, M_INFO, 0, "%s", text);
+   }
+   Py_INCREF(Py_None);
+   return Py_None;
+}
+
+static PyObject *job_does_vol_exist(PyObject *self, PyObject *args)
+{
+   char *VolName = NULL;
+
+   if (!PyArg_ParseTuple(args, "s:does_volume_exist", &VolName)) {
+      Dmsg0(000, "Parse tuple error in job_does_vol_exist\n");
+      return NULL;
+   }
+   if (VolName) {
+      MEDIA_DBR mr;
+      int ok;
+      JCR *jcr = get_jcr_from_PyObject(self);
+      memset(&mr, 0, sizeof(mr));
+      bstrncpy(mr.VolumeName, VolName, sizeof(mr.VolumeName));
+      ok = db_get_media_record(jcr, jcr->db, &mr);
+      return Py_BuildValue("i", ok);
    }
    Py_INCREF(Py_None);
    return Py_None;
 }
 
+
 static PyObject *job_cancel(PyObject *self, PyObject *args)
 {
    JobId_t JobId = 0;
 
  */
 static int python_cmd(UAContext *ua, const char *cmd)
 {
-   if (strcasecmp(ua->argk[1], _("restart")) == 0) {
+   if (ua->argc >= 1 && strcasecmp(ua->argk[1], _("restart")) == 0) {
       term_python_interpreter();
       init_python_interpreter(director->hdr.name, 
          director->scripts_directory, "DirStartUp");
 
    }
 
 bail_out:
-   Py_XDECREF((PyObject *)jcr->Python_job);
-   jcr->Python_job = NULL;
-   Py_XDECREF((PyObject *)jcr->Python_events);
-   jcr->Python_events = NULL;
+   if (jcr) {
+      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);