]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
Fix #10004 Use VolRetention if greater than MinimumVolumeRetention when setting volum...
authorEric Bollengier <eric@baculasystems.com>
Thu, 30 Mar 2023 14:44:13 +0000 (16:44 +0200)
committerEric Bollengier <eric@baculasystems.com>
Thu, 14 Sep 2023 11:57:01 +0000 (13:57 +0200)
bacula/src/dird/catreq.c
bacula/src/dird/ua_update.c
bacula/src/stored/askdir.c
bacula/src/stored/block_util.c
bacula/src/stored/dev.h
bacula/src/stored/dircmd.c

index e798f11bb363286c3bd68a2d18e8becec5b0f6ed..a2a81f4928d5f57f92a8270624622bbf6ed3bf25 100644 (file)
@@ -68,7 +68,7 @@ static char OK_media[] = "1000 OK VolName=%s VolJobs=%u VolFiles=%u"
    " VolWriteTime=%s EndFile=%u EndBlock=%u VolType=%u LabelType=%d"
    " MediaId=%s ScratchPoolId=%s VolParts=%d VolCloudParts=%d"
    " LastPartBytes=%lld Enabled=%d MaxPoolBytes=%s PoolBytes=%s Recycle=%d"
-   " Protected=%d UseProtect=%d VolEncrypted=%d\n";
+   " Protected=%d UseProtect=%d VolEncrypted=%d VolRetention=%u\n";
 
 static char OK_create[] = "1000 OK CreateJobMedia\n";
 
@@ -121,7 +121,7 @@ static int send_volume_info_to_storage_daemon(JCR *jcr, BSOCK *sd, MEDIA_DBR *mr
       mr->Enabled,
       edit_uint64(pr.MaxPoolBytes, ed11),
       edit_uint64(pr.PoolBytes, ed12),
-      mr->Recycle, mr->Protected, mr->UseProtect, mr->VolEncrypted);
+      mr->Recycle, mr->Protected, mr->UseProtect, mr->VolEncrypted, mr->VolRetention);
    unbash_spaces(mr->VolumeName);
    Dmsg2(100, "Vol Info for %s: %s", jcr->Job, sd->msg);
    return stat;
index 08bea43f2d32444651d5492d42c726fc891c5207..b942f3757a8dc8ffba978ef373ae5b7016e97da5 100644 (file)
@@ -1116,6 +1116,7 @@ struct media_protect {
    char volname[MAX_NAME_LENGTH];
    char storage[MAX_NAME_LENGTH];
    char mediatype[MAX_NAME_LENGTH];
+   uint32_t retention;
 };
 
 /* 
@@ -1125,12 +1126,13 @@ static int media_protect_list_handler(void *ctx, int num_fields, char **row)
 { 
    alist *val = (alist *)ctx; 
  
-   if (row[0] && row[1] && row[2] && row[3]) {
+   if (row[0] && row[1] && row[2] && row[3] && row[4]) {
       struct media_protect *a = (struct media_protect *)malloc(sizeof(struct media_protect));
       a->id = str_to_uint64(row[0]);
       bstrncpy(a->mediatype, row[1], sizeof(a->mediatype));
       bstrncpy(a->volname, row[2], sizeof(a->volname));
       bstrncpy(a->storage, row[3], sizeof(a->storage));
+      a->retention = str_to_uint64(row[4]);
       val->append(a); 
    }
  
@@ -1194,10 +1196,14 @@ static int update_volumeprotect_cmd(UAContext *ua)
       return 0;
    }
 
-   Mmsg(tmp, "SELECT Media.MediaId, Media.MediaType, Media.VolumeName, Storage.Name "
-               "FROM Media JOIN Storage USING (StorageId) JOIN Pool USING (PoolId) "
-              "WHERE UseProtect=1 AND Protected=0 AND VolStatus IN ('Used', 'Full') %s "
-           "ORDER BY Storage.Name", filter.c_str());
+   db_lock(ua->db);
+   const char *where_pool = ua->db->get_acls(DB_ACL_BIT(DB_ACL_POOL), false);
+   /* We use DISTINCT because when looking with JobId, we can get multiple time the same record */
+   Mmsg(tmp, "SELECT DISTINCT Media.MediaId, Media.MediaType, Media.VolumeName, Storage.Name, Media.VolRetention "
+               "FROM Media JOIN Storage USING (StorageId) JOIN Pool USING (PoolId) %s "
+              "WHERE UseProtect=1 AND Protected=0 AND VolStatus IN ('Used', 'Full') %s %s "
+           "ORDER BY Storage.Name", join_job, filter.c_str(), where_pool);
+   db_unlock(ua->db);
 
    db_sql_query(ua->db, tmp.c_str(),
                 media_protect_list_handler, &list);
@@ -1254,8 +1260,8 @@ static int update_volumeprotect_cmd(UAContext *ua)
       bash_spaces(selected_dev_name);
       bash_spaces(elt->volname);
 
-      sd->fsend("volumeprotect mediatype=%s device=%s volume=%s drive=%d\n",
-                elt->mediatype, selected_dev_name, elt->volname, drive);
+      sd->fsend("volumeprotect mediatype=%s device=%s volume=%s drive=%d retention=%u\n",
+                elt->mediatype, selected_dev_name, elt->volname, drive, elt->retention);
 
       unbash_spaces(elt->mediatype);
       unbash_spaces(selected_dev_name);
index 3476fa0f5f41f66f4b1fdf54d83bbd53a0bbf016..47ee2c4a72d44d45bfc6f3379d12376e726ea32b 100644 (file)
@@ -51,7 +51,7 @@ static char OK_media[] = "1000 OK VolName=%127s VolJobs=%u VolFiles=%lu"
    " VolReadTime=%lld VolWriteTime=%lld EndFile=%lu EndBlock=%lu"
    " VolType=%lu LabelType=%ld MediaId=%lld ScratchPoolId=%lld"
    " VolParts=%d VolCloudParts=%d LastPartBytes=%lld Enabled=%d MaxPoolBytes=%lld PoolBytes=%lld Recycle=%d"
-   " Protected=%d UseProtect=%d VolEncrypted=%d\n";
+   " Protected=%d UseProtect=%d VolEncrypted=%d VolRetention=%u\n";
 
 
 static char OK_create[] = "1000 OK CreateJobMedia\n";
@@ -223,9 +223,9 @@ static bool do_get_volume_info(DCR *dcr)
                &vol.LabelType, &vol.VolMediaId, &vol.VolScratchPoolId,
                &vol.VolCatParts, &vol.VolCatCloudParts,
                &vol.VolLastPartBytes, &Enabled, &vol.MaxPoolBytes,
-               &vol.PoolBytes, &Recycle, &Protected, &UseProtect, &VolEncrypted);
+               &vol.PoolBytes, &Recycle, &Protected, &UseProtect, &VolEncrypted, &vol.VolRetention);
     Dmsg2(dbglvl, "<dird n=%d %s", n, dir->msg);
-    if (n != 36) {
+    if (n != 37) {
        Dmsg1(dbglvl, "get_volume_info failed: ERR=%s", dir->msg);
        /*
         * Note, we can get an error here either because there is
index 378efa2b1d0e5a7b11c5f0f03721252554c34f75..a1fc5eccd5133c881382eabe2adee3801101d27c 100644 (file)
@@ -683,28 +683,11 @@ bool is_user_volume_size_reached(DCR *dcr, bool quiet)
             dev->getVolCatName());
       }
 
-      if (dev->device->set_vol_immutable) {
-         dev->VolCatInfo.UseProtect = 1;
-         /* Set volume as immutable */
-         if (!dev->set_immutable(dev->getVolCatName(), &dev->errmsg)) {
-            /* We may proceed with that but warn the user */
-            Jmsg(dcr->jcr, M_WARNING, 0, _("Failed to set the volume %s on device %s as immutable, ERR=%s.\n"),
-                 dev->getVolCatName(), dev->print_name(), dev->errmsg);
-         } else {
-            if (!quiet) {
-               Jmsg(dcr->jcr, M_INFO, 0, _("Marking Volume \"%s\" as immutable\n"),
-                    dev->getVolCatName());
-            }
-            events_send_msg(dcr->jcr, "SJ0003", EVENTS_TYPE_VOLUME, me->hdr.name, (intptr_t)dcr->jcr,
-                            "Mark Volume \"%s\" as immutable", dev->getVolCatName());;
-            dev->VolCatInfo.Protected = 1;
-         }
-      }
-
       if (dev->device->set_vol_read_only) {
+         uint32_t when = MAX(dev->device->min_volume_protection_time, dev->VolCatInfo.VolRetention);
          dev->VolCatInfo.UseProtect = 1;
          /* Set volume as immutable/read only */
-         if (dev->set_atime(dev->m_fd, dev->getVolCatName(), time(NULL) + dev->device->min_volume_protection_time) < 0) {
+         if (dev->set_atime(dev->m_fd, dev->getVolCatName(), time(NULL) + when) < 0) {
             Jmsg(dcr->jcr, M_WARNING, 0, _("Failed to set the volume %s on device %s in atime retention, ERR=%s.\n"),
                  dev->getVolCatName(), dev->print_name(), dev->errmsg);
          }
@@ -714,16 +697,35 @@ bool is_user_volume_size_reached(DCR *dcr, bool quiet)
             Jmsg(dcr->jcr, M_WARNING, 0, _("Failed to set the volume %s on device %s in read-only, ERR=%s.\n"),
                  dev->getVolCatName(), dev->print_name(), be.bstrerror());
          } else {
+            char buf[128];
+            edit_utime(when, buf, sizeof(buf));
             if (!quiet) {
-               Jmsg(dcr->jcr, M_INFO, 0, _("Marking Volume \"%s\" as read-only\n"),
+               Jmsg(dcr->jcr, M_INFO, 0, _("Marking Volume \"%s\" as read-only. Retention set to %s.\n"), buf,
                     dev->getVolCatName());
             }
             dev->VolCatInfo.Protected = 1;
             events_send_msg(dcr->jcr, "SJ0003", EVENTS_TYPE_VOLUME, me->hdr.name, (intptr_t)dcr->jcr,
-                            "Mark Volume \"%s\" as read-only", dev->getVolCatName());;
+                            "Mark Volume \"%s\" as read-only. retention %s.", dev->getVolCatName(), buf);;
          }
       }
 
+      if (dev->device->set_vol_immutable) {
+         dev->VolCatInfo.UseProtect = 1;
+         /* Set volume as immutable */
+         if (!dev->set_immutable(dev->getVolCatName(), &dev->errmsg)) {
+            /* We may proceed with that but warn the user */
+            Jmsg(dcr->jcr, M_WARNING, 0, _("Failed to set the volume %s on device %s as immutable, ERR=%s.\n"),
+                 dev->getVolCatName(), dev->print_name(), dev->errmsg);
+         } else {
+            if (!quiet) {
+               Jmsg(dcr->jcr, M_INFO, 0, _("Marking Volume \"%s\" as immutable\n"),
+                    dev->getVolCatName());
+            }
+            events_send_msg(dcr->jcr, "SJ0003", EVENTS_TYPE_VOLUME, me->hdr.name, (intptr_t)dcr->jcr,
+                            "Mark Volume \"%s\" as immutable", dev->getVolCatName());;
+            dev->VolCatInfo.Protected = 1;
+         }
+      }
       Dmsg4(100, "Maximum volume size %s exceeded Vol=%s device=%s.\n"
          "Marking Volume \"%s\" as Full.\n",
          edit_uint64_with_commas(max_size, ed1), dev->getVolCatName(),
index 0b5ddadc02265d65c950a674795ca5e5e50b4eb3..5eab150673f5d24b1ba0b143bff50755765dc402 100644 (file)
@@ -215,7 +215,8 @@ struct VOLUME_CAT_INFO {
    uint32_t VolCatRecycles;           /* Number of recycles this volume */
    uint32_t EndFile;                  /* Last file number */
    uint32_t EndBlock;                 /* Last block number */
-
+   uint32_t VolRetention;             /* Volume Retention */
+   
    int32_t  LabelType;                /* Bacula/ANSI/IBM */
    int32_t  Slot;                     /* >0=Slot loaded, 0=nothing, -1=unknown */
    uint32_t VolCatMaxJobs;            /* Maximum Jobs to write to volume */
index eff14c7f1ed8a13d6d376adc1ef628381c30bece..cee028dd6d46ddf44166e99cfccc668a94840a48 100644 (file)
@@ -1340,11 +1340,12 @@ static bool volumeprotect_cmd(JCR *jcr)
    char mediatype[MAX_NAME_LENGTH];
    char volume[MAX_NAME_LENGTH];
    POOL_MEM device, tmp;
+   uint32_t retention;
    int32_t drive;
    bool ok;
 
-   ok = sscanf(dir->msg, "volumeprotect mediatype=%127s device=%127s volume=%127s drive=%d",
-               mediatype, device.c_str(), volume, &drive) == 4;
+   ok = sscanf(dir->msg, "volumeprotect mediatype=%127s device=%127s volume=%127s drive=%d retention=%u",
+               mediatype, device.c_str(), volume, &drive, &retention) == 5;
    if (ok) {
       unbash_spaces(mediatype);
       unbash_spaces(device.c_str());
@@ -1374,7 +1375,8 @@ static bool volumeprotect_cmd(JCR *jcr)
          } else if (dev->device->set_vol_read_only) {
             /* Set volume as immutable/read only */
             pm_strcpy(tmp, "");
-            if (dev->set_atime(-1, volume, time(NULL) + dev->device->min_volume_protection_time) < 0) {
+            uint32_t when = MAX(dev->device->min_volume_protection_time, retention);
+            if (dev->set_atime(-1, volume, time(NULL) + when) < 0) {
                berrno be;
                Mmsg(tmp, _(" Failed to set the volume %s on device %s in atime retention, ERR=%s.\n"),
                     volume, dev->print_name(), be.bstrerror());
@@ -1385,9 +1387,11 @@ static bool volumeprotect_cmd(JCR *jcr)
                dir->fsend(_("3900 Failed to set the volume %s on device %s in read-only, ERR=%s.%s\n"),
                           volume, dev->print_name(), be.bstrerror(), tmp.c_str());
             } else {
-               dir->fsend(_("3000 Marking volume \"%s\" as read-only.\n"), volume);
+               char buf[128];
+               dir->fsend(_("3000 Marking volume \"%s\" as read-only. Retention set to %s.\n"),
+                          volume, edit_utime(when, buf, sizeof(buf)));
                events_send_msg(jcr, "SJ0003", EVENTS_TYPE_VOLUME, me->hdr.name, (intptr_t)jcr,
-                               "Mark volume \"%s\" as read-only", volume);
+                               "Mark volume \"%s\" as read-only, retention %s", volume, buf);
             }
          } else {
             dir->fsend(_("3900 Device %s not configured for ReadOnly or Immutable\n"), dev->device->hdr.name);