2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
21 * Bacula Director -- Update command processing
22 * Split from ua_cmds.c March 2005
24 * Kern Sibbald, September MM
31 /* Forward referenced functions */
32 static int update_volume(UAContext *ua);
33 static bool update_pool(UAContext *ua);
34 static bool update_job(UAContext *ua);
35 static bool update_stats(UAContext *ua);
38 * Update a Pool Record in the database.
39 * It is always updated from the Resource record.
41 * update pool=<pool-name>
42 * updates pool from Pool resource
43 * update media pool=<pool-name> volume=<volume-name>
44 * changes pool info for volume
45 * update slots [scan=...]
46 * updates autochanger slots
47 * update stats [days=...]
48 * updates long term statistics
50 int update_cmd(UAContext *ua, const char *cmd)
52 static const char *kw[] = {
54 NT_("volume"), /* 1 */
61 NT_("snapshot"),/* 8 */
64 if (!open_client_db(ua)) {
68 switch (find_arg_keyword(ua, kw)) {
94 start_prompt(ua, _("Update choice:\n"));
95 add_prompt(ua, _("Volume parameters"));
96 add_prompt(ua, _("Pool from resource"));
97 add_prompt(ua, _("Slots from autochanger"));
98 add_prompt(ua, _("Long term statistics"));
99 add_prompt(ua, _("Snapshot parameters"));
100 switch (do_prompt(ua, _("item"), _("Choose catalog item to update"), NULL, 0)) {
122 static void update_volstatus(UAContext *ua, const char *val, MEDIA_DBR *mr)
124 POOL_MEM query(PM_MESSAGE);
139 for (i=0; kw[i]; i++) {
140 if (strcasecmp(val, kw[i]) == 0) {
146 ua->error_msg(_("Invalid VolStatus specified: %s\n"), val);
149 bstrncpy(mr->VolStatus, kw[i], sizeof(mr->VolStatus));
150 Mmsg(query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%s",
151 mr->VolStatus, edit_int64(mr->MediaId,ed1));
152 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
153 ua->error_msg("%s", db_strerror(ua->db));
155 ua->info_msg(_("New Volume status is: %s\n"), mr->VolStatus);
160 static void update_volretention(UAContext *ua, char *val, MEDIA_DBR *mr)
162 char ed1[150], ed2[50];
163 POOL_MEM query(PM_MESSAGE);
164 if (!duration_to_utime(val, &mr->VolRetention)) {
165 ua->error_msg(_("Invalid retention period specified: %s\n"), val);
168 Mmsg(query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%s",
169 edit_uint64(mr->VolRetention, ed1), edit_int64(mr->MediaId,ed2));
170 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
171 ua->error_msg("%s", db_strerror(ua->db));
173 ua->info_msg(_("New retention period is: %s\n"),
174 edit_utime(mr->VolRetention, ed1, sizeof(ed1)));
178 static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr)
180 char ed1[150], ed2[50];
181 POOL_MEM query(PM_MESSAGE);
183 if (!duration_to_utime(val, &mr->VolUseDuration)) {
184 ua->error_msg(_("Invalid use duration specified: %s\n"), val);
187 Mmsg(query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%s",
188 edit_uint64(mr->VolUseDuration, ed1), edit_int64(mr->MediaId,ed2));
189 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
190 ua->error_msg("%s", db_strerror(ua->db));
192 ua->info_msg(_("New use duration is: %s\n"),
193 edit_utime(mr->VolUseDuration, ed1, sizeof(ed1)));
197 static void update_volmaxjobs(UAContext *ua, char *val, MEDIA_DBR *mr)
199 POOL_MEM query(PM_MESSAGE);
201 Mmsg(query, "UPDATE Media SET MaxVolJobs=%s WHERE MediaId=%s",
202 val, edit_int64(mr->MediaId,ed1));
203 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
204 ua->error_msg("%s", db_strerror(ua->db));
206 ua->info_msg(_("New max jobs is: %s\n"), val);
210 static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr)
212 POOL_MEM query(PM_MESSAGE);
214 Mmsg(query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%s",
215 val, edit_int64(mr->MediaId, ed1));
216 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
217 ua->error_msg("%s", db_strerror(ua->db));
219 ua->info_msg(_("New max files is: %s\n"), val);
223 static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr)
226 char ed1[50], ed2[50];
227 POOL_MEM query(PM_MESSAGE);
229 if (!size_to_uint64(val, strlen(val), &maxbytes)) {
230 ua->error_msg(_("Invalid max. bytes specification: %s\n"), val);
233 Mmsg(query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%s",
234 edit_uint64(maxbytes, ed1), edit_int64(mr->MediaId, ed2));
235 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
236 ua->error_msg("%s", db_strerror(ua->db));
238 ua->info_msg(_("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1));
242 static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr)
247 POOL_MEM query(PM_MESSAGE);
248 if (!is_yesno(val, &recycle)) {
249 ua->error_msg(_("Invalid value. It must be yes or no.\n"));
252 Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%s",
253 recycle, edit_int64(mr->MediaId, ed1));
254 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
255 ua->error_msg("%s", db_strerror(ua->db));
257 ua->info_msg(_("New Recycle flag is: %s\n"),
258 recycle==1?_("yes"):_("no"));
262 static void update_volinchanger(UAContext *ua, char *val, MEDIA_DBR *mr)
267 POOL_MEM query(PM_MESSAGE);
268 if (!is_yesno(val, &InChanger)) {
269 ua->error_msg(_("Invalid value. It must be yes or no.\n"));
272 Mmsg(query, "UPDATE Media SET InChanger=%d WHERE MediaId=%s",
273 InChanger, edit_int64(mr->MediaId, ed1));
274 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
275 ua->error_msg("%s", db_strerror(ua->db));
277 ua->info_msg(_("New InChanger flag is: %s\n"),
278 InChanger==1?_("yes"):_("no"));
283 static void update_volslot(UAContext *ua, char *val, MEDIA_DBR *mr)
287 memset(&pr, 0, sizeof(POOL_DBR));
288 pr.PoolId = mr->PoolId;
289 if (!db_get_pool_numvols(ua->jcr, ua->db, &pr)) {
290 ua->error_msg("%s", db_strerror(ua->db));
293 mr->Slot = atoi(val);
295 ua->error_msg(_("Invalid slot, it must be greater than zero\n"));
299 * Make sure to use db_update... rather than doing this directly,
300 * so that any Slot is handled correctly.
302 set_storageid_in_mr(NULL, mr);
303 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
304 ua->error_msg(_("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
306 ua->info_msg(_("New Slot is: %d\n"), mr->Slot);
310 /* Modify the Pool in which this Volume is located */
311 void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr)
314 POOL_MEM query(PM_MESSAGE);
315 char ed1[50], ed2[50];
317 memset(&pr, 0, sizeof(pr));
318 bstrncpy(pr.Name, val, sizeof(pr.Name));
319 if (!get_pool_dbr(ua, &pr)) {
322 mr->PoolId = pr.PoolId; /* set new PoolId */
326 Mmsg(query, "UPDATE Media SET PoolId=%s WHERE MediaId=%s",
327 edit_int64(mr->PoolId, ed1), edit_int64(mr->MediaId, ed2));
328 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
329 ua->error_msg("%s", db_strerror(ua->db));
331 ua->info_msg(_("New Pool is: %s\n"), pr.Name);
333 if (!db_update_pool_record(ua->jcr, ua->db, opr)) {
334 ua->error_msg("%s", db_strerror(ua->db));
337 if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
338 ua->error_msg("%s", db_strerror(ua->db));
344 /* Modify the RecyclePool of a Volume */
345 void update_vol_recyclepool(UAContext *ua, char *val, MEDIA_DBR *mr)
348 POOL_MEM query(PM_MESSAGE);
349 char ed1[50], ed2[50], *poolname;
351 if(val && *val) { /* update volume recyclepool="Scratch" */
352 /* If a pool name is given, look up the PoolId */
353 memset(&pr, 0, sizeof(pr));
354 bstrncpy(pr.Name, val, sizeof(pr.Name));
355 if (!get_pool_dbr(ua, &pr, NT_("recyclepool"))) {
358 /* pool = select_pool_resource(ua); */
359 mr->RecyclePoolId = pr.PoolId; /* get the PoolId */
362 } else { /* update volume recyclepool="" */
363 /* If no pool name is given, set the PoolId to 0 (the default) */
364 mr->RecyclePoolId = 0;
365 poolname = _("*None*");
369 Mmsg(query, "UPDATE Media SET RecyclePoolId=%s WHERE MediaId=%s",
370 edit_int64(mr->RecyclePoolId, ed1), edit_int64(mr->MediaId, ed2));
371 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
372 ua->error_msg("%s", db_strerror(ua->db));
374 ua->info_msg(_("New RecyclePool is: %s\n"), poolname);
380 * Refresh the Volume information from the Pool record
382 static void update_vol_from_pool(UAContext *ua, MEDIA_DBR *mr)
386 memset(&pr, 0, sizeof(pr));
387 pr.PoolId = mr->PoolId;
388 if (!db_get_pool_numvols(ua->jcr, ua->db, &pr) ||
389 !acl_access_ok(ua, Pool_ACL, pr.Name)) {
392 set_pool_dbr_defaults_in_media_dbr(mr, &pr);
393 if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
394 ua->error_msg(_("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
396 ua->info_msg(_("Volume defaults updated from \"%s\" Pool record.\n"),
402 * Refresh the Volume information from the Pool record
405 static void update_all_vols_from_pool(UAContext *ua, const char *pool_name)
410 memset(&pr, 0, sizeof(pr));
412 bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
413 if (!get_pool_dbr(ua, &pr)) {
416 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
417 mr.PoolId = pr.PoolId;
418 if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
419 ua->error_msg(_("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
421 ua->info_msg(_("All Volume defaults updated from \"%s\" Pool record.\n"),
426 static void update_all_vols(UAContext *ua)
433 memset(&pr, 0, sizeof(pr));
435 if (!db_get_pool_ids(ua->jcr, ua->db, &num_pools, &ids)) {
436 ua->error_msg(_("Error obtaining pool ids. ERR=%s\n"), db_strerror(ua->db));
440 for (i=0; i<num_pools; i++) {
442 if (!db_get_pool_numvols(ua->jcr, ua->db, &pr)) { /* ***FIXME*** use acl? */
443 ua->warning_msg(_("Updating all pools, but skipped PoolId=%d. ERR=%s\n"), db_strerror(ua->db));
447 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
448 mr.PoolId = pr.PoolId;
450 if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
451 ua->error_msg(_("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
453 ua->info_msg(_("All Volume defaults updated from \"%s\" Pool record.\n"),
461 static void update_volenabled(UAContext *ua, char *val, MEDIA_DBR *mr)
463 mr->Enabled = get_enabled(ua, val);
464 if (mr->Enabled < 0) {
467 set_storageid_in_mr(NULL, mr);
468 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
469 ua->error_msg(_("Error updating media record Enabled: ERR=%s"),
470 db_strerror(ua->db));
472 ua->info_msg(_("New Enabled is: %d\n"), mr->Enabled);
476 static void update_vol_actiononpurge(UAContext *ua, char *val, MEDIA_DBR *mr)
479 if (strcasecmp(val, "truncate") == 0) {
480 mr->ActionOnPurge = ON_PURGE_TRUNCATE;
482 mr->ActionOnPurge = 0;
485 set_storageid_in_mr(NULL, mr);
486 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
487 ua->error_msg(_("Error updating media record ActionOnPurge: ERR=%s"),
488 db_strerror(ua->db));
490 ua->info_msg(_("New ActionOnPurge is: %s\n"),
491 action_on_purge_to_string(mr->ActionOnPurge, ret));
496 * Update a media record -- allows you to change the
497 * Volume status. E.g. if you want Bacula to stop
498 * writing on the volume, set it to anything other
501 static int update_volume(UAContext *ua)
513 NT_("VolStatus"), /* 0 */
514 NT_("VolRetention"), /* 1 */
515 NT_("VolUse"), /* 2 */
516 NT_("MaxVolJobs"), /* 3 */
517 NT_("MaxVolFiles"), /* 4 */
518 NT_("MaxVolBytes"), /* 5 */
519 NT_("Recycle"), /* 6 */
520 NT_("InChanger"), /* 7 */
523 NT_("FromPool"), /* 10 */
524 NT_("AllFromPool"), /* 11 !!! see below !!! */
525 NT_("Enabled"), /* 12 */
526 NT_("RecyclePool"), /* 13 */
527 NT_("ActionOnPurge"), /* 14 */
530 #define AllFromPool 11 /* keep this updated with above */
532 for (i=0; kw[i]; i++) {
536 if ((j=find_arg_with_value(ua, kw[i])) > 0) {
537 /* If all from pool don't select a media record */
538 if (i != AllFromPool && !select_media_dbr(ua, &mr)) {
543 update_volstatus(ua, ua->argv[j], &mr);
546 update_volretention(ua, ua->argv[j], &mr);
549 update_voluseduration(ua, ua->argv[j], &mr);
552 update_volmaxjobs(ua, ua->argv[j], &mr);
555 update_volmaxfiles(ua, ua->argv[j], &mr);
558 update_volmaxbytes(ua, ua->argv[j], &mr);
561 update_volrecycle(ua, ua->argv[j], &mr);
564 update_volinchanger(ua, ua->argv[j], &mr);
567 update_volslot(ua, ua->argv[j], &mr);
570 memset(&pr, 0, sizeof(POOL_DBR));
571 pr.PoolId = mr.PoolId;
572 if (!db_get_pool_numvols(ua->jcr, ua->db, &pr)) {
573 ua->error_msg("%s", db_strerror(ua->db));
576 update_vol_pool(ua, ua->argv[j], &mr, &pr);
579 update_vol_from_pool(ua, &mr);
582 update_all_vols_from_pool(ua, ua->argv[j]);
585 update_volenabled(ua, ua->argv[j], &mr);
588 update_vol_recyclepool(ua, ua->argv[j], &mr);
591 update_vol_actiononpurge(ua, ua->argv[j], &mr);
598 /* Allow user to simply update all volumes */
599 if (find_arg(ua, NT_("fromallpools")) > 0) {
605 start_prompt(ua, _("Parameters to modify:\n"));
606 add_prompt(ua, _("Volume Status")); /* 0 */
607 add_prompt(ua, _("Volume Retention Period")); /* 1 */
608 add_prompt(ua, _("Volume Use Duration")); /* 2 */
609 add_prompt(ua, _("Maximum Volume Jobs")); /* 3 */
610 add_prompt(ua, _("Maximum Volume Files")); /* 4 */
611 add_prompt(ua, _("Maximum Volume Bytes")); /* 5 */
612 add_prompt(ua, _("Recycle Flag")); /* 6 */
613 add_prompt(ua, _("Slot")); /* 7 */
614 add_prompt(ua, _("InChanger Flag")); /* 8 */
615 add_prompt(ua, _("Volume Files")); /* 9 */
616 add_prompt(ua, _("Pool")); /* 10 */
617 add_prompt(ua, _("Volume from Pool")); /* 11 */
618 add_prompt(ua, _("All Volumes from Pool")); /* 12 */
619 add_prompt(ua, _("All Volumes from all Pools")); /* 13 */
620 add_prompt(ua, _("Enabled")), /* 14 */
621 add_prompt(ua, _("RecyclePool")), /* 15 */
622 add_prompt(ua, _("Action On Purge")), /* 16 */
623 add_prompt(ua, _("Done")); /* 17 */
624 i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);
626 /* For All Volumes, All Volumes from Pool, and Done, we don't need
628 if ( i != 12 && i != 13 && i != 17) {
629 if (!select_media_dbr(ua, &mr)) { /* Get Volume record */
632 ua->info_msg(_("Updating Volume \"%s\"\n"), mr.VolumeName);
635 case 0: /* Volume Status */
636 /* Modify Volume Status */
637 ua->info_msg(_("Current Volume status is: %s\n"), mr.VolStatus);
638 start_prompt(ua, _("Possible Values are:\n"));
639 add_prompt(ua, NT_("Append"));
640 add_prompt(ua, NT_("Archive"));
641 add_prompt(ua, NT_("Disabled"));
642 add_prompt(ua, NT_("Full"));
643 add_prompt(ua, NT_("Used"));
644 add_prompt(ua, NT_("Cleaning"));
645 if (strcmp(mr.VolStatus, NT_("Purged")) == 0) {
646 add_prompt(ua, NT_("Recycle"));
648 add_prompt(ua, NT_("Read-Only"));
649 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
652 update_volstatus(ua, ua->cmd, &mr);
654 case 1: /* Retention */
655 ua->info_msg(_("Current retention period is: %s\n"),
656 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
657 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
660 update_volretention(ua, ua->cmd, &mr);
663 case 2: /* Use Duration */
664 ua->info_msg(_("Current use duration is: %s\n"),
665 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
666 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
669 update_voluseduration(ua, ua->cmd, &mr);
672 case 3: /* Max Jobs */
673 ua->info_msg(_("Current max jobs is: %u\n"), mr.MaxVolJobs);
674 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
677 update_volmaxjobs(ua, ua->cmd, &mr);
680 case 4: /* Max Files */
681 ua->info_msg(_("Current max files is: %u\n"), mr.MaxVolFiles);
682 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
685 update_volmaxfiles(ua, ua->cmd, &mr);
688 case 5: /* Max Bytes */
689 ua->info_msg(_("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
690 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
693 update_volmaxbytes(ua, ua->cmd, &mr);
697 case 6: /* Recycle */
698 ua->info_msg(_("Current recycle flag is: %s\n"),
699 mr.Recycle==1?_("yes"):_("no"));
700 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
703 update_volrecycle(ua, ua->cmd, &mr);
707 ua->info_msg(_("Current Slot is: %d\n"), mr.Slot);
708 if (!get_pint(ua, _("Enter new Slot: "))) {
711 update_volslot(ua, ua->cmd, &mr);
714 case 8: /* InChanger */
715 ua->info_msg(_("Current InChanger flag is: %d\n"), mr.InChanger);
716 bsnprintf(buf, sizeof(buf), _("Set InChanger flag for Volume \"%s\": yes/no: "),
718 if (!get_yesno(ua, buf)) {
721 mr.InChanger = ua->pint32_val;
723 * Make sure to use db_update... rather than doing this directly,
724 * so that any Slot is handled correctly.
726 set_storageid_in_mr(NULL, &mr);
727 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
728 ua->error_msg(_("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
730 ua->info_msg(_("New InChanger flag is: %d\n"), mr.InChanger);
735 case 9: /* Volume Files */
737 ua->warning_msg(_("Warning changing Volume Files can result\n"
738 "in loss of data on your Volume\n\n"));
739 ua->info_msg(_("Current Volume Files is: %u\n"), mr.VolFiles);
740 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
743 VolFiles = ua->pint32_val;
744 if (VolFiles != (int)(mr.VolFiles + 1)) {
745 ua->warning_msg(_("Normally, you should only increase Volume Files by one!\n"));
746 if (!get_yesno(ua, _("Increase Volume Files? (yes/no): ")) || ua->pint32_val == 0) {
750 query = get_pool_memory(PM_MESSAGE);
751 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
752 VolFiles, edit_int64(mr.MediaId, ed1));
753 if (!db_sql_query(ua->db, query, NULL, NULL)) {
754 ua->error_msg("%s", db_strerror(ua->db));
756 ua->info_msg(_("New Volume Files is: %u\n"), VolFiles);
758 free_pool_memory(query);
761 case 10: /* Volume's Pool */
762 memset(&pr, 0, sizeof(POOL_DBR));
763 pr.PoolId = mr.PoolId;
764 if (!db_get_pool_numvols(ua->jcr, ua->db, &pr)) {
765 ua->error_msg("%s", db_strerror(ua->db));
768 ua->info_msg(_("Current Pool is: %s\n"), pr.Name);
769 if (!get_cmd(ua, _("Enter new Pool name: "))) {
772 update_vol_pool(ua, ua->cmd, &mr, &pr);
776 update_vol_from_pool(ua, &mr);
779 pool = select_pool_resource(ua);
781 update_all_vols_from_pool(ua, pool->name());
790 ua->info_msg(_("Current Enabled is: %d\n"), mr.Enabled);
791 if (!get_cmd(ua, _("Enter new Enabled: "))) {
794 update_volenabled(ua, ua->cmd, &mr);
798 memset(&pr, 0, sizeof(POOL_DBR));
799 pr.PoolId = mr.RecyclePoolId;
800 if (db_get_pool_numvols(ua->jcr, ua->db, &pr)) {
801 ua->info_msg(_("Current RecyclePool is: %s\n"), pr.Name);
803 ua->info_msg(_("No current RecyclePool\n"));
805 if (!select_pool_dbr(ua, &pr, NT_("recyclepool"))) {
808 update_vol_recyclepool(ua, pr.Name, &mr);
813 ua->info_msg(_("Current ActionOnPurge is: %s\n"),
814 action_on_purge_to_string(mr.ActionOnPurge, ret));
815 if (!get_cmd(ua, _("Enter new ActionOnPurge (one of: Truncate, None): "))) {
819 update_vol_actiononpurge(ua, ua->cmd, &mr);
822 default: /* Done or error */
823 ua->info_msg(_("Selection terminated.\n"));
831 * Update long term statistics
833 static bool update_stats(UAContext *ua)
835 int i = find_arg_with_value(ua, NT_("days"));
839 since = atoi(ua->argv[i]) * 24*60*60;
842 int nb = db_update_stats(ua->jcr, ua->db, since);
843 ua->info_msg(_("Updating %i job(s).\n"), nb);
849 * Update pool record -- pull info from current POOL resource
851 static bool update_pool(UAContext *ua)
859 pool = get_pool_resource(ua);
864 memset(&pr, 0, sizeof(pr));
865 bstrncpy(pr.Name, pool->name(), sizeof(pr.Name));
866 if (!get_pool_dbr(ua, &pr)) {
870 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
871 set_pooldbr_references(ua->jcr, ua->db, &pr, pool);
873 id = db_update_pool_record(ua->jcr, ua->db, &pr);
875 ua->error_msg(_("db_update_pool_record returned %d. ERR=%s\n"),
876 id, db_strerror(ua->db));
878 query = get_pool_memory(PM_MESSAGE);
879 Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
880 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
881 free_pool_memory(query);
882 ua->info_msg(_("Pool DB record updated from resource.\n"));
887 * Update a Job record -- allows you to change the
888 * date fields in a Job record. This helps when
889 * providing migration from other vendors.
891 static bool update_job(UAContext *ua)
894 char ed1[50], ed2[50];
895 POOL_MEM cmd(PM_MESSAGE);
899 char *client_name = NULL;
900 char *start_time = NULL;
902 NT_("starttime"), /* 0 */
903 NT_("client"), /* 1 */
906 Dmsg1(200, "cmd=%s\n", ua->cmd);
907 i = find_arg_with_value(ua, NT_("jobid"));
909 ua->error_msg(_("Expect JobId keyword, not found.\n"));
912 memset(&jr, 0, sizeof(jr));
913 memset(&cr, 0, sizeof(cr));
914 jr.JobId = str_to_int64(ua->argv[i]);
915 if (!db_get_job_record(ua->jcr, ua->db, &jr)) {
916 ua->error_msg("%s", db_strerror(ua->db));
920 for (i=0; kw[i]; i++) {
922 if ((j=find_arg_with_value(ua, kw[i])) >= 0) {
924 case 0: /* start time */
925 start_time = ua->argv[j];
927 case 1: /* Client name */
928 client_name = ua->argv[j];
933 if (!client_name && !start_time) {
934 ua->error_msg(_("Neither Client nor StartTime specified.\n"));
938 if (!get_client_dbr(ua, &cr)) {
941 jr.ClientId = cr.ClientId;
946 StartTime = str_to_utime(start_time);
947 if (StartTime == 0) {
948 ua->error_msg(_("Improper date format: %s\n"), ua->argv[i]);
951 delta_start = StartTime - jr.StartTime;
952 Dmsg3(200, "ST=%lld jr.ST=%lld delta=%lld\n", StartTime,
953 (utime_t)jr.StartTime, delta_start);
954 jr.StartTime = (time_t)StartTime;
955 jr.SchedTime += (time_t)delta_start;
956 jr.EndTime += (time_t)delta_start;
957 jr.JobTDate += delta_start;
958 /* Convert to DB times */
959 bstrutime(jr.cStartTime, sizeof(jr.cStartTime), jr.StartTime);
960 bstrutime(jr.cSchedTime, sizeof(jr.cSchedTime), jr.SchedTime);
961 bstrutime(jr.cEndTime, sizeof(jr.cEndTime), jr.EndTime);
963 Mmsg(cmd, "UPDATE Job SET ClientId=%s,StartTime='%s',SchedTime='%s',"
964 "EndTime='%s',JobTDate=%s WHERE JobId=%s",
965 edit_int64(jr.ClientId, ed1),
969 edit_uint64(jr.JobTDate, ed1),
970 edit_int64(jr.JobId, ed2));
971 if (!db_sql_query(ua->db, cmd.c_str(), NULL, NULL)) {
972 ua->error_msg("%s", db_strerror(ua->db));