]> git.sur5r.net Git - bacula/bacula/commitdiff
Implement new "purge volume action" command to trigg ActionOnPurge.
authorEric Bollengier <eric@eb.homelinux.org>
Mon, 1 Feb 2010 17:08:06 +0000 (18:08 +0100)
committerEric Bollengier <eric@eb.homelinux.org>
Mon, 2 Aug 2010 14:49:25 +0000 (16:49 +0200)
This command will replace the automatic truncate operation when purging
the volume.

example:
*update volume=xxxx actiononpurge=Truncate
*purge volume=xxxx
*purge volume=xxxx action=all storage=File
*purge volume=xxxx action=truncate
*purge volume action allpools storage=File

bacula/src/dird/ua_cmds.c
bacula/src/dird/ua_purge.c

index 2a8ebec0ef24f3c8040f495b52411afb7d7b13b7..6e93c0267daf6990359a1e60c423b97014b31d7f 100644 (file)
@@ -151,7 +151,7 @@ static struct cmdstruct commands[] = {                                      /* C
  { NT_("prune"),      prunecmd,      _("Prune expired records from catalog"), 
    NT_("files | jobs | pool=<pool> | client=<client-name> | volume=<volume-name> "), true},
 
- { NT_("purge"),      purgecmd,      _("Purge records from catalog"), NT_("volume=<vol>"),  true},
+ { NT_("purge"),      purgecmd,      _("Purge records from catalog"), NT_("files jobs volume=<vol> [action=<action> devicetype=<type> pool=<pool> allpools storage=<st> drive=<num>]"),  true},
  { NT_("python"),     python_cmd,    _("Python control commands"),    NT_(""),              false},
  { NT_("quit"),       quit_cmd,      _("Terminate Bconsole session"), NT_(""),              false},
  { NT_("query"),      querycmd,      _("Query catalog"),              NT_(""),              false},
index c4f0d8ecb07578aabb0beda1092cc8d932cbab38..c78f83a969a3499dbd9928c0976e6854f5341128 100644 (file)
@@ -44,6 +44,7 @@
 /* Forward referenced functions */
 static int purge_files_from_client(UAContext *ua, CLIENT *client);
 static int purge_jobs_from_client(UAContext *ua, CLIENT *client);
+static int aop_cmd(UAContext *ua, const char *cmd);
 
 static const char *select_jobsfiles_from_client =
    "SELECT JobId FROM Job "
@@ -138,6 +139,11 @@ int purgecmd(UAContext *ua, const char *cmd)
       }
    /* Volume */
    case 2:
+      /* Perform ActionOnPurge (action=truncate) */
+      if (find_arg(ua, "action") >= 0) {
+         return aop_cmd(ua, ua->cmd);
+      }
+
       while ((i=find_arg(ua, NT_("volume"))) >= 0) {
          if (select_media_dbr(ua, &mr)) {
             purge_jobs_from_volume(ua, &mr, /*force*/true);
@@ -571,14 +577,13 @@ static BSOCK *open_sd_bsock(UAContext *ua)
    return ua->jcr->store_bsock;
 }
 
-static void do_actions_on_purge(UAContext *ua, MEDIA_DBR *mr)
+static void do_truncate_on_purge(UAContext *ua, MEDIA_DBR *mr, 
+                                 char *pool, char *storage,
+                                 int drive, BSOCK *sd)
 {
-   BSOCK *sd;
-   POOL_DBR pr;
-   bool ok=false;
    int dvd;
+   bool ok=false;
    uint64_t VolBytes = 0;
-   char dev_name[MAX_NAME_LENGTH];
    
    /* TODO: Return if not mr->Recyle ? */
    if (!mr->Recycle) {
@@ -590,59 +595,158 @@ static void do_actions_on_purge(UAContext *ua, MEDIA_DBR *mr)
        * is disabled for the specific device, this will be a no-op.
        */
 
-      if ((sd=open_sd_bsock(ua)) != NULL) {
-         memset(&pr, 0, sizeof(POOL_DBR));
-         
-         pr.PoolId = mr->PoolId;
-         strcpy(pr.Name, "Default"); /* We don't use the Pool in label */
-         bstrncpy(dev_name, ua->jcr->wstore->dev_name(), sizeof(dev_name));
+      /* Protect us from spaces */
+      bash_spaces(mr->VolumeName);
+      bash_spaces(mr->MediaType);
+      bash_spaces(pool);
+      bash_spaces(storage);
          
-         /* Protect us from spaces */
-         bash_spaces(dev_name);
-         bash_spaces(mr->VolumeName);
-         bash_spaces(mr->MediaType);
-         bash_spaces(pr.Name);
-         
-         /* We set drive=-1 to let the storage decides of which drive
-          * to use
-          */
-         sd->fsend("relabel %s OldName=%s NewName=%s PoolName=%s "
-                   "MediaType=%s Slot=%d drive=%d\n",
-                   dev_name,
+      sd->fsend("relabel %s OldName=%s NewName=%s PoolName=%s "
+                "MediaType=%s Slot=%d drive=%d\n",
+                   storage,
                    mr->VolumeName, mr->VolumeName,
-                   pr.Name, mr->MediaType, mr->Slot, -1);
+                   pool, mr->MediaType, mr->Slot, drive);
          
-         unbash_spaces(mr->VolumeName);
-         unbash_spaces(mr->MediaType);
-         while (sd->recv() >= 0) {
-            ua->send_msg("%s", sd->msg);
-            if (sscanf(sd->msg, "3000 OK label. VolBytes=%llu DVD=%d ",
-                       &VolBytes, &dvd) == 2) 
-            {
-               ok = true;
-            }
+      unbash_spaces(mr->VolumeName);
+      unbash_spaces(mr->MediaType);
+      unbash_spaces(pool);
+      unbash_spaces(storage);
+
+      while (sd->recv() >= 0) {
+         ua->send_msg("%s", sd->msg);
+         if (sscanf(sd->msg, "3000 OK label. VolBytes=%llu DVD=%d ",
+                    &VolBytes, &dvd) == 2) 
+         {
+            ok = true;
          }
-         sd->signal(BNET_TERMINATE);
-         sd->close();
-         ua->jcr->store_bsock = NULL;
-         
-      } else {
-         ua->error_msg(_("Could not connect to storage daemon"));
       }
-      
+
       if (ok) {
          mr->VolBytes = VolBytes;
          mr->VolFiles = 0;
          if (!db_update_media_record(ua->jcr, ua->db, mr)) {
             ua->error_msg(_("Can't update volume size in the catalog\n"));
          }
-         ua->send_msg(_("The volume has been truncated\n"));
+         ua->send_msg(_("The volume \"%s\" has been truncated\n"), mr->VolumeName);
       } else {
-         ua->warning_msg(_("Unable to truncate the volume\n"));
+         ua->warning_msg(_("Unable to truncate volume \"%s\"\n"), mr->VolumeName);
       }
    }
 }
 
+/* purge action= pool= volume= storage= devicetype= */
+static int aop_cmd(UAContext *ua, const char *cmd)
+{
+   bool allpools=false;
+   int drive=-1;
+   int nb=0;
+
+   uint32_t *results=NULL;
+   const char *action="all";
+   STORE *store=NULL;
+   POOL *pool=NULL;
+   MEDIA_DBR mr;
+   POOL_DBR pr;
+
+   BSOCK *sd=NULL;
+   
+   memset(&pr, 0, sizeof(pr));
+   memset(&mr, 0, sizeof(mr));
+
+   /* Look arguments */
+   for (int i=1; i<ua->argc; i++) {
+      if (strcasecmp(ua->argk[i], NT_("allpools")) == 0) {
+         allpools = true;
+            
+      } else if (strcasecmp(ua->argk[i], NT_("volume")) == 0 && ua->argv[i]) {
+         bstrncpy(mr.VolumeName, ua->argv[i], sizeof(mr.VolumeName));
+
+      } else if (strcasecmp(ua->argk[i], NT_("devicetype")) == 0 && ua->argv[i]) {
+         bstrncpy(mr.MediaType, ua->argv[i], sizeof(mr.MediaType));
+         
+      } else if (strcasecmp(ua->argk[i], NT_("drive")) == 0 && ua->argv[i]) {
+         drive = atoi(ua->argv[i]);
+
+      } else if (strcasecmp(ua->argk[i], NT_("action")) == 0 && ua->argv[i]) {
+         action=ua->argv[i];
+      }
+   }
+
+   /* Choose storage */
+   ua->jcr->wstore = store =  get_storage_resource(ua, false);
+   if (!store) {
+      goto bail_out;
+   }
+   mr.StorageId = store->StorageId;
+
+   if (!open_db(ua)) {
+      Dmsg0(100, "Can't open db\n");
+      goto bail_out;
+   }
+
+   if (!allpools) {
+      /* force pool selection */
+      pool = get_pool_resource(ua);
+      if (!pool) {
+         Dmsg0(100, "Can't get pool resource\n");
+         goto bail_out;
+      }
+      bstrncpy(pr.Name, pool->name(), sizeof(pr.Name));
+      if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
+         Dmsg0(100, "Can't get pool record\n");
+         goto bail_out;
+      }
+      mr.PoolId = pr.PoolId;
+   }
+
+   mr.Recycle = 1;
+   mr.Enabled = 1;
+   mr.VolBytes = 10000;
+   bstrncpy(mr.VolStatus, "Purged", sizeof(mr.VolStatus));
+
+   if (!db_get_media_ids(ua->jcr, ua->db, &mr, &nb, &results)) {
+      Dmsg0(100, "No results from db_get_media_ids\n");
+      goto bail_out;
+   }
+   
+   if (!nb) {
+      ua->send_msg(_("No volume founds to perform %s action(s)\n"), action);
+      goto bail_out;
+   }
+
+   if ((sd=open_sd_bsock(ua)) == NULL) {
+      Dmsg0(100, "Can't open connection to sd\n");
+      goto bail_out;
+   }
+
+   for (int i=0; i < nb; i++) {
+      memset(&mr, 0, sizeof(mr));
+      mr.MediaId = results[i];
+      if (db_get_media_record(ua->jcr, ua->db, &mr)) {         
+         /* TODO: ask for drive and change Pool */
+         if (!strcasecmp("truncate", action) || !strcasecmp("all", action)) {
+            do_truncate_on_purge(ua, &mr, pr.Name, store->dev_name(), drive, sd);
+         }
+      } else {
+         Dmsg1(0, "Can't find MediaId=%lld\n", (uint64_t) mr.MediaId);
+      }
+   }
+
+bail_out:
+   close_db(ua);
+   if (sd) {
+      sd->signal(BNET_TERMINATE);
+      sd->close();
+      ua->jcr->store_bsock = NULL;
+   }
+   ua->jcr->wstore = NULL;
+   if (results) {
+      free(results);
+   }
+
+   return 1;
+}
+
 /*
  * IF volume status is Append, Full, Used, or Error, mark it Purged
  *   Purged volumes can then be recycled (if enabled).
@@ -686,9 +790,6 @@ bool mark_media_purged(UAContext *ua, MEDIA_DBR *mr)
             ua->error_msg("%s", db_strerror(ua->db));
          }
       }
-      
-      /* Do any ActionOnPurge for this Volume */
-      do_actions_on_purge(ua, mr);
 
       /* Send message to Job report, if it is a *real* job */           
       if (jcr && jcr->JobId > 0) {