]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/ua_cmds.c
- Fix the block listing bug pointed out by Arno.
[bacula/bacula] / bacula / src / dird / ua_cmds.c
index 77aedf191e52bb695ac934abd40d0620f93e6667..1ecc80c8193ae11af06a331d56e2b02be8bcbade 100644 (file)
@@ -6,24 +6,18 @@
  *
  *   Version $Id$
  */
-
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 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.
+   modify it under the terms of the GNU General Public License
+   version 2 as amended with additional clauses defined in the
+   file LICENSE in the main source directory.
 
    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.
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
+   the file LICENSE for additional details.
 
  */
 
@@ -62,6 +56,8 @@ extern int update_cmd(UAContext *ua, const char *cmd);
 static int add_cmd(UAContext *ua, const char *cmd);
 static int create_cmd(UAContext *ua, const char *cmd);
 static int cancel_cmd(UAContext *ua, const char *cmd);
+static int enable_cmd(UAContext *ua, const char *cmd);
+static int disable_cmd(UAContext *ua, const char *cmd);
 static int setdebug_cmd(UAContext *ua, const char *cmd);
 static int trace_cmd(UAContext *ua, const char *cmd);
 static int var_cmd(UAContext *ua, const char *cmd);
@@ -97,6 +93,8 @@ static struct cmdstruct commands[] = {
  { N_("cancel"),     cancel_cmd,    _("cancel [<jobid=nnn> | <job=name>] -- cancel a job")},
  { N_("create"),     create_cmd,    _("create DB Pool from resource")},
  { N_("delete"),     delete_cmd,    _("delete [pool=<pool-name> | media volume=<volume-name>]")},
+ { N_("disable"),    disable_cmd,   _("disable <job=name> -- disable a job")},
+ { N_("enable"),     enable_cmd,    _("enable <job=name> -- enable a job")},
  { N_("estimate"),   estimate_cmd,  _("performs FileSet estimate, listing gives full listing")},
  { N_("exit"),       quit_cmd,      _("exit = quit")},
  { N_("gui"),        gui_cmd,       _("gui [on|off] -- non-interactive gui mode")},
@@ -149,10 +147,16 @@ int do_a_command(UAContext *ua, const char *cmd)
       return 1;
    }
 
+   while (ua->jcr->storage->size()) {
+      ua->jcr->storage->remove(0);
+   }
+
    len = strlen(ua->argk[0]);
    for (i=0; i<comsize; i++) {     /* search for command */
       if (strncasecmp(ua->argk[0],  _(commands[i].key), len) == 0) {
-         if (!acl_access_ok(ua, Command_ACL, ua->argk[0], len)) {
+         /* Check if command permitted, but "quit" is always OK */
+         if (strcmp(ua->argk[0], "quit") != 0 &&
+             !acl_access_ok(ua, Command_ACL, ua->argk[0], len)) {
             break;
          }
          stat = (*commands[i].func)(ua, cmd);   /* go execute command */
@@ -218,7 +222,7 @@ static int add_cmd(UAContext *ua, const char *cmd)
       pr.MaxVols, pr.PoolType);
 
    while (pr.MaxVols > 0 && pr.NumVols >= pr.MaxVols) {
-      bsendmsg(ua, _("Pool already has maximum volumes = %d\n"), pr.MaxVols);
+      bsendmsg(ua, _("Pool already has maximum volumes=%d\n"), pr.MaxVols);
       for (;;) {
          if (!get_pint(ua, _("Enter new maximum (zero for unlimited): "))) {
             return 1;
@@ -228,7 +232,7 @@ static int add_cmd(UAContext *ua, const char *cmd)
    }
 
    /* Get media type */
-   if ((store = get_storage_resource(ua, 0)) != NULL) {
+   if ((store = get_storage_resource(ua, false/*no default*/)) != NULL) {
       bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
    } else if (!get_media_type(ua, mr.MediaType, sizeof(mr.MediaType))) {
       return 1;
@@ -378,7 +382,7 @@ static int cancel_cmd(UAContext *ua, const char *cmd)
          }
          JobId = str_to_int64(ua->argv[i]);
          if (!(jcr=get_jcr_by_id(JobId))) {
-            bsendmsg(ua, _("JobId %d is not running.\n"),  JobId);
+            bsendmsg(ua, _("JobId %s is not running. Use Job name to cancel inactive jobs.\n"),  ua->argv[i]);
             return 1;
          }
          break;
@@ -387,8 +391,9 @@ static int cancel_cmd(UAContext *ua, const char *cmd)
             break;
          }
          if (!(jcr=get_jcr_by_partial_name(ua->argv[i]))) {
-            bsendmsg(ua, _("Job %s is not running.\n"), ua->argv[i]);
-            return 1;
+            bsendmsg(ua, _("Warning Job %s is not running. Continuing anyway ...\n"), ua->argv[i]);
+            jcr = new_jcr(sizeof(JCR), dird_free_jcr);
+            bstrncpy(jcr->Job, ua->argv[i], sizeof(jcr->Job));
          }
          break;
       }
@@ -399,33 +404,28 @@ static int cancel_cmd(UAContext *ua, const char *cmd)
    if (!jcr) {
       char buf[1000];
       /* Count Jobs running */
-      lock_jcr_chain();
       foreach_jcr(jcr) {
          if (jcr->JobId == 0) {      /* this is us */
-            free_locked_jcr(jcr);
             continue;
          }
-         free_locked_jcr(jcr);
          njobs++;
       }
-      unlock_jcr_chain();
+      endeach_jcr(jcr);
 
       if (njobs == 0) {
          bsendmsg(ua, _("No Jobs running.\n"));
          return 1;
       }
       start_prompt(ua, _("Select Job:\n"));
-      lock_jcr_chain();
       foreach_jcr(jcr) {
+         char ed1[50];
          if (jcr->JobId == 0) {      /* this is us */
-            free_locked_jcr(jcr);
             continue;
          }
-         bsnprintf(buf, sizeof(buf), "JobId=%d Job=%s", jcr->JobId, jcr->Job);
+         bsnprintf(buf, sizeof(buf), _("JobId=%s Job=%s"), edit_int64(jcr->JobId, ed1), jcr->Job);
          add_prompt(ua, buf);
-         free_locked_jcr(jcr);
       }
-      unlock_jcr_chain();
+      endeach_jcr(jcr);
 
       if (do_prompt(ua, _("Job"),  _("Choose Job to cancel"), buf, sizeof(buf)) < 0) {
          return 1;
@@ -446,7 +446,6 @@ static int cancel_cmd(UAContext *ua, const char *cmd)
 
    ret = cancel_job(ua, jcr);
    free_jcr(jcr);
-
    return ret;
 }
 
@@ -569,7 +568,7 @@ extern DIRRES *director;
  */
 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");
@@ -615,6 +614,49 @@ get_out:
 }
 
 
+static void do_en_disable_cmd(UAContext *ua, bool setting)
+{
+   JOB *job;
+   int i;
+
+   i = find_arg_with_value(ua, N_("job")); 
+   if (i < 0) { 
+      job = select_job_resource(ua);
+      if (!job) {
+         return;
+      }
+   } else {
+      LockRes();
+      job = (JOB *)GetResWithName(R_JOB, ua->argv[i]);
+      UnlockRes();
+   } 
+   if (!job) {
+      bsendmsg(ua, _("Job \"%s\" not found.\n"), ua->argv[i]);
+      return;
+   }
+
+   if (!acl_access_ok(ua, Job_ACL, job->hdr.name)) {
+      bsendmsg(ua, _("Illegal command from this console.\n"));
+      return;
+   }
+   job->enabled = setting;
+   bsendmsg(ua, _("Job \"%s\" %sabled\n"), job->hdr.name, setting?"en":"dis");
+   return;
+}
+
+static int enable_cmd(UAContext *ua, const char *cmd)
+{
+   do_en_disable_cmd(ua, true);
+   return 1;
+}
+
+static int disable_cmd(UAContext *ua, const char *cmd)
+{
+   do_en_disable_cmd(ua, false);
+   return 1;
+}
+
+
 static void do_storage_setdebug(UAContext *ua, STORE *store, int level, int trace_flag)
 {
    BSOCK *sd;
@@ -762,7 +804,7 @@ static int setdebug_cmd(UAContext *ua, const char *cmd)
    Dmsg1(120, "setdebug:%s:\n", cmd);
 
    level = -1;
-   i = find_arg_with_value(ua, _("level"));
+   i = find_arg_with_value(ua, "level");
    if (i >= 0) {
       level = atoi(ua->argv[i]);
    }
@@ -774,7 +816,7 @@ static int setdebug_cmd(UAContext *ua, const char *cmd)
    }
 
    /* Look for trace flag. -1 => not change */
-   i = find_arg_with_value(ua, _("trace"));
+   i = find_arg_with_value(ua, "trace");
    if (i >= 0) {
       trace_flag = atoi(ua->argv[i]);
       if (trace_flag > 0) {
@@ -784,18 +826,18 @@ static int setdebug_cmd(UAContext *ua, const char *cmd)
 
    /* General debug? */
    for (i=1; i<ua->argc; i++) {
-      if (strcasecmp(ua->argk[i], _("all")) == 0) {
+      if (strcasecmp(ua->argk[i], "all") == 0) {
          do_all_setdebug(ua, level, trace_flag);
          return 1;
       }
-      if (strcasecmp(ua->argk[i], _("dir")) == 0 ||
-          strcasecmp(ua->argk[i], _("director")) == 0) {
+      if (strcasecmp(ua->argk[i], "dir") == 0 ||
+          strcasecmp(ua->argk[i], "director") == 0) {
          debug_level = level;
          set_trace(trace_flag);
          return 1;
       }
-      if (strcasecmp(ua->argk[i], _("client")) == 0 ||
-          strcasecmp(ua->argk[i], _("fd")) == 0) {
+      if (strcasecmp(ua->argk[i], "client") == 0 ||
+          strcasecmp(ua->argk[i], "fd") == 0) {
          client = NULL;
          if (ua->argv[i]) {
             client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
@@ -811,9 +853,9 @@ static int setdebug_cmd(UAContext *ua, const char *cmd)
          }
       }
 
-      if (strcasecmp(ua->argk[i], _("store")) == 0 ||
-          strcasecmp(ua->argk[i], _("storage")) == 0 ||
-          strcasecmp(ua->argk[i], _("sd")) == 0) {
+      if (strcasecmp(ua->argk[i], "store") == 0 ||
+          strcasecmp(ua->argk[i], "storage") == 0 ||
+          strcasecmp(ua->argk[i], "sd") == 0) {
          store = NULL;
          if (ua->argv[i]) {
             store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]);
@@ -822,7 +864,7 @@ static int setdebug_cmd(UAContext *ua, const char *cmd)
                return 1;
             }
          }
-         store = get_storage_resource(ua, 0);
+         store = get_storage_resource(ua, false/*no default*/);
          if (store) {
             do_storage_setdebug(ua, store, level, trace_flag);
             return 1;
@@ -834,17 +876,17 @@ static int setdebug_cmd(UAContext *ua, const char *cmd)
     * prompt the user.
     */
    start_prompt(ua, _("Available daemons are: \n"));
-   add_prompt(ua, _("Director"));
-   add_prompt(ua, _("Storage"));
-   add_prompt(ua, _("Client"));
-   add_prompt(ua, _("All"));
+   add_prompt(ua, "Director");
+   add_prompt(ua, "Storage");
+   add_prompt(ua, "Client");
+   add_prompt(ua, "All");
    switch(do_prompt(ua, "", _("Select daemon type to set debug level"), NULL, 0)) {
    case 0:                         /* Director */
       debug_level = level;
       set_trace(trace_flag);
       break;
    case 1:
-      store = get_storage_resource(ua, 0);
+      store = get_storage_resource(ua, false/*no default*/);
       if (store) {
          do_storage_setdebug(ua, store, level, trace_flag);
       }
@@ -911,37 +953,36 @@ static int estimate_cmd(UAContext *ua, const char *cmd)
    JOB *job = NULL;
    CLIENT *client = NULL;
    FILESET *fileset = NULL;
-   FILESET_DBR fsr;
    int listing = 0;
    char since[MAXSTRING];
    JCR *jcr = ua->jcr;
 
    jcr->JobLevel = L_FULL;
    for (int i=1; i<ua->argc; i++) {
-      if (strcasecmp(ua->argk[i], _("client")) == 0 ||
-          strcasecmp(ua->argk[i], _("fd")) == 0) {
+      if (strcasecmp(ua->argk[i], "client") == 0 ||
+          strcasecmp(ua->argk[i], "fd") == 0) {
          if (ua->argv[i]) {
             client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
             continue;
          }
       }
-      if (strcasecmp(ua->argk[i], _("job")) == 0) {
+      if (strcasecmp(ua->argk[i], "job") == 0) {
          if (ua->argv[i]) {
             job = (JOB *)GetResWithName(R_JOB, ua->argv[i]);
             continue;
          }
       }
-      if (strcasecmp(ua->argk[i], _("fileset")) == 0) {
+      if (strcasecmp(ua->argk[i], "fileset") == 0) {
          if (ua->argv[i]) {
             fileset = (FILESET *)GetResWithName(R_FILESET, ua->argv[i]);
             continue;
          }
       }
-      if (strcasecmp(ua->argk[i], _("listing")) == 0) {
+      if (strcasecmp(ua->argk[i], "listing") == 0) {
          listing = 1;
          continue;
       }
-      if (strcasecmp(ua->argk[i], _("level")) == 0) {
+      if (strcasecmp(ua->argk[i], "level") == 0) {
          if (!get_level_from_name(ua->jcr, ua->argv[i])) {
             bsendmsg(ua, _("Level %s not valid.\n"), ua->argv[i]);
          }
@@ -982,7 +1023,7 @@ static int estimate_cmd(UAContext *ua, const char *cmd)
    if (!get_or_create_client_record(jcr)) {
       return 1;
    }
-   if (!get_or_create_fileset_record(jcr, &fsr)) {
+   if (!get_or_create_fileset_record(jcr)) {
       return 1;
    }
 
@@ -1077,7 +1118,7 @@ static int delete_cmd(UAContext *ua, const char *cmd)
       return 1;
    case 2:
       int i;
-      while ((i=find_arg(ua, _("jobid"))) > 0) {
+      while ((i=find_arg(ua, "jobid")) > 0) {
          delete_job(ua);
          *ua->argk[i] = 0;         /* zap keyword already visited */
       }
@@ -1111,7 +1152,7 @@ static int delete_cmd(UAContext *ua, const char *cmd)
 /*
  * delete_job has been modified to parse JobID lists like the
  * following:
- * delete job JobID=3,4,6,7-11,14
+ * delete JobID=3,4,6,7-11,14
  *
  * Thanks to Phil Stracchino for the above addition.
  */
@@ -1121,7 +1162,7 @@ static void delete_job(UAContext *ua)
    JobId_t JobId;
    char *s,*sep,*tok;
 
-   int i = find_arg_with_value(ua, _("jobid"));
+   int i = find_arg_with_value(ua, N_("jobid"));
    if (i >= 0) {
       if (strchr(ua->argv[i], ',') != NULL || strchr(ua->argv[i], '-') != NULL) {
         s = bstrdup(ua->argv[i]);
@@ -1196,9 +1237,11 @@ static void do_job_delete(UAContext *ua, JobId_t JobId)
 
    Mmsg(query, "DELETE FROM Job WHERE JobId=%s", edit_int64(JobId, ed1));
    db_sql_query(ua->db, query, NULL, (void *)NULL);
-   Mmsg(query, "DELETE FROM File WHERE JobId=%s", edit_int64(JobId, ed1));
+   Mmsg(query, "DELETE FROM MAC WHERE JobId=%s", ed1);
    db_sql_query(ua->db, query, NULL, (void *)NULL);
-   Mmsg(query, "DELETE FROM JobMedia WHERE JobId=%s", edit_int64(JobId, ed1));
+   Mmsg(query, "DELETE FROM File WHERE JobId=%s", ed1);
+   db_sql_query(ua->db, query, NULL, (void *)NULL);
+   Mmsg(query, "DELETE FROM JobMedia WHERE JobId=%s", ed1);
    db_sql_query(ua->db, query, NULL, (void *)NULL);
    free_pool_memory(query);
    bsendmsg(ua, _("Job %s and associated records deleted from the catalog.\n"), edit_int64(JobId, ed1));
@@ -1255,21 +1298,23 @@ static void do_mount_cmd(UAContext *ua, const char *command)
    BSOCK *sd;
    JCR *jcr = ua->jcr;
    char dev_name[MAX_NAME_LENGTH];
+   int drive;
 
    if (!open_db(ua)) {
       return;
    }
    Dmsg2(120, "%s: %s\n", command, ua->UA_sock->msg);
 
-   store = get_storage_resource(ua, 1);
+   store = get_storage_resource(ua, true/*arg is storage*/);
    if (!store) {
       return;
    }
+   set_storage(jcr, store);
+   drive = get_storage_drive(ua, store);
 
-   Dmsg2(120, "Found storage, MediaType=%s DevName=%s\n",
-      store->media_type, store->dev_name());
+   Dmsg3(120, "Found storage, MediaType=%s DevName=%s drive=%d\n",
+      store->media_type, store->dev_name(), drive);
 
-   set_storage(jcr, store);
    if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
       bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
       return;
@@ -1277,7 +1322,7 @@ static void do_mount_cmd(UAContext *ua, const char *command)
    sd = jcr->store_bsock;
    bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
    bash_spaces(dev_name);
-   bnet_fsend(sd, "%s %s", command, dev_name);
+   bnet_fsend(sd, "%s %s drive=%d", command, dev_name, drive);
    while (bnet_recv(sd) >= 0) {
       bsendmsg(ua, "%s", sd->msg);
    }
@@ -1287,7 +1332,7 @@ static void do_mount_cmd(UAContext *ua, const char *command)
 }
 
 /*
- * mount [storage | device] <name>
+ * mount [storage=<name>] [drive=nn]
  */
 static int mount_cmd(UAContext *ua, const char *cmd)
 {
@@ -1297,7 +1342,7 @@ static int mount_cmd(UAContext *ua, const char *cmd)
 
 
 /*
- * unmount [storage | device] <name>
+ * unmount [storage=<name>] [drive=nn]
  */
 static int unmount_cmd(UAContext *ua, const char *cmd)
 {
@@ -1307,7 +1352,7 @@ static int unmount_cmd(UAContext *ua, const char *cmd)
 
 
 /*
- * release [storage | device] <name>
+ * release [storage=<name>] [drive=nn]
  */
 static int release_cmd(UAContext *ua, const char *cmd)
 {
@@ -1355,16 +1400,14 @@ int wait_cmd(UAContext *ua, const char *cmd)
    bmicrosleep(0, 200000);            /* let job actually start */
    for (bool running=true; running; ) {
       running = false;
-      lock_jcr_chain();
       foreach_jcr(jcr) {
          if (jcr->JobId != 0) {
             running = true;
-            free_locked_jcr(jcr);
             break;
          }
-         free_locked_jcr(jcr);
       }
-      unlock_jcr_chain();
+      endeach_jcr(jcr);
+
       if (running) {
          bmicrosleep(1, 0);
       }
@@ -1390,14 +1433,14 @@ int qhelp_cmd(UAContext *ua, const char *cmd)
    unsigned int i;
 
    for (i=0; i<comsize; i++) {
-      bsendmsg(ua, _("%s %s\n"), _(commands[i].key), _(commands[i].help));
+      bsendmsg(ua, "%s %s\n", _(commands[i].key), _(commands[i].help));
    }
    return 1;
 }
 
 static int version_cmd(UAContext *ua, const char *cmd)
 {
-   bsendmsg(ua, "%s Version: " VERSION " (" BDATE ")\n", my_name);
+   bsendmsg(ua, _("%s Version: %s (%s)\n"), my_name, VERSION, BDATE);
    return 1;
 }
 
@@ -1406,10 +1449,10 @@ static int version_cmd(UAContext *ua, const char *cmd)
  * a "use catalog xxx" command, we simply find the first
  * catalog resource and open it.
  */
-int open_db(UAContext *ua)
+bool open_db(UAContext *ua)
 {
    if (ua->db) {
-      return 1;
+      return true;
    }
    if (!ua->catalog) {
       LockRes();
@@ -1417,7 +1460,11 @@ int open_db(UAContext *ua)
       UnlockRes();
       if (!ua->catalog) {
          bsendmsg(ua, _("Could not find a Catalog resource\n"));
-         return 0;
+         return false;
+      } else if (!acl_access_ok(ua, Catalog_ACL, ua->catalog->hdr.name)) {
+         bsendmsg(ua, _("You must specify a \"use <catalog-name>\" command before continuing.\n"));
+         ua->catalog = NULL;
+         return false;
       } else {
          bsendmsg(ua, _("Using default Catalog name=%s DB=%s\n"),
             ua->catalog->hdr.name, ua->catalog->db_name);
@@ -1438,11 +1485,11 @@ int open_db(UAContext *ua)
          bsendmsg(ua, "%s", db_strerror(ua->db));
       }
       close_db(ua);
-      return 0;
+      return false;
    }
    ua->jcr->db = ua->db;
    Dmsg1(150, "DB %s opened\n", ua->catalog->db_name);
-   return 1;
+   return true;
 }
 
 void close_db(UAContext *ua)