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);
294 if (pr.MaxVols > 0 && mr->Slot > (int)pr.MaxVols) {
295 ua->error_msg(_("Invalid slot, it must be between 0 and MaxVols=%d\n"),
300 * Make sure to use db_update... rather than doing this directly,
301 * so that any Slot is handled correctly.
303 set_storageid_in_mr(NULL, mr);
304 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
305 ua->error_msg(_("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
307 ua->info_msg(_("New Slot is: %d\n"), mr->Slot);
311 /* Modify the Pool in which this Volume is located */
312 void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr)
315 POOL_MEM query(PM_MESSAGE);
316 char ed1[50], ed2[50];
318 memset(&pr, 0, sizeof(pr));
319 bstrncpy(pr.Name, val, sizeof(pr.Name));
320 if (!get_pool_dbr(ua, &pr)) {
323 mr->PoolId = pr.PoolId; /* set new PoolId */
327 Mmsg(query, "UPDATE Media SET PoolId=%s WHERE MediaId=%s",
328 edit_int64(mr->PoolId, ed1), edit_int64(mr->MediaId, ed2));
329 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
330 ua->error_msg("%s", db_strerror(ua->db));
332 ua->info_msg(_("New Pool is: %s\n"), pr.Name);
334 if (!db_update_pool_record(ua->jcr, ua->db, opr)) {
335 ua->error_msg("%s", db_strerror(ua->db));
338 if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
339 ua->error_msg("%s", db_strerror(ua->db));
345 /* Modify the RecyclePool of a Volume */
346 void update_vol_recyclepool(UAContext *ua, char *val, MEDIA_DBR *mr)
349 POOL_MEM query(PM_MESSAGE);
350 char ed1[50], ed2[50], *poolname;
352 if(val && *val) { /* update volume recyclepool="Scratch" */
353 /* If a pool name is given, look up the PoolId */
354 memset(&pr, 0, sizeof(pr));
355 bstrncpy(pr.Name, val, sizeof(pr.Name));
356 if (!get_pool_dbr(ua, &pr, NT_("recyclepool"))) {
359 /* pool = select_pool_resource(ua); */
360 mr->RecyclePoolId = pr.PoolId; /* get the PoolId */
363 } else { /* update volume recyclepool="" */
364 /* If no pool name is given, set the PoolId to 0 (the default) */
365 mr->RecyclePoolId = 0;
366 poolname = _("*None*");
370 Mmsg(query, "UPDATE Media SET RecyclePoolId=%s WHERE MediaId=%s",
371 edit_int64(mr->RecyclePoolId, ed1), edit_int64(mr->MediaId, ed2));
372 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
373 ua->error_msg("%s", db_strerror(ua->db));
375 ua->info_msg(_("New RecyclePool is: %s\n"), poolname);
381 * Refresh the Volume information from the Pool record
383 static void update_vol_from_pool(UAContext *ua, MEDIA_DBR *mr)
387 memset(&pr, 0, sizeof(pr));
388 pr.PoolId = mr->PoolId;
389 if (!db_get_pool_numvols(ua->jcr, ua->db, &pr) ||
390 !acl_access_ok(ua, Pool_ACL, pr.Name)) {
393 set_pool_dbr_defaults_in_media_dbr(mr, &pr);
394 if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
395 ua->error_msg(_("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
397 ua->info_msg(_("Volume defaults updated from \"%s\" Pool record.\n"),
403 * Refresh the Volume information from the Pool record
406 static void update_all_vols_from_pool(UAContext *ua, const char *pool_name)
411 memset(&pr, 0, sizeof(pr));
413 bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
414 if (!get_pool_dbr(ua, &pr)) {
417 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
418 mr.PoolId = pr.PoolId;
419 if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
420 ua->error_msg(_("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
422 ua->info_msg(_("All Volume defaults updated from \"%s\" Pool record.\n"),
427 static void update_all_vols(UAContext *ua)
434 memset(&pr, 0, sizeof(pr));
436 if (!db_get_pool_ids(ua->jcr, ua->db, &num_pools, &ids)) {
437 ua->error_msg(_("Error obtaining pool ids. ERR=%s\n"), db_strerror(ua->db));
441 for (i=0; i<num_pools; i++) {
443 if (!db_get_pool_numvols(ua->jcr, ua->db, &pr)) { /* ***FIXME*** use acl? */
444 ua->warning_msg(_("Updating all pools, but skipped PoolId=%d. ERR=%s\n"), db_strerror(ua->db));
448 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
449 mr.PoolId = pr.PoolId;
451 if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
452 ua->error_msg(_("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
454 ua->info_msg(_("All Volume defaults updated from \"%s\" Pool record.\n"),
462 static void update_volenabled(UAContext *ua, char *val, MEDIA_DBR *mr)
464 mr->Enabled = get_enabled(ua, val);
465 if (mr->Enabled < 0) {
468 set_storageid_in_mr(NULL, mr);
469 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
470 ua->error_msg(_("Error updating media record Enabled: ERR=%s"),
471 db_strerror(ua->db));
473 ua->info_msg(_("New Enabled is: %d\n"), mr->Enabled);
477 static void update_vol_actiononpurge(UAContext *ua, char *val, MEDIA_DBR *mr)
480 if (strcasecmp(val, "truncate") == 0) {
481 mr->ActionOnPurge = ON_PURGE_TRUNCATE;
483 mr->ActionOnPurge = 0;
486 set_storageid_in_mr(NULL, mr);
487 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
488 ua->error_msg(_("Error updating media record ActionOnPurge: ERR=%s"),
489 db_strerror(ua->db));
491 ua->info_msg(_("New ActionOnPurge is: %s\n"),
492 action_on_purge_to_string(mr->ActionOnPurge, ret));
497 * Update a media record -- allows you to change the
498 * Volume status. E.g. if you want Bacula to stop
499 * writing on the volume, set it to anything other
502 static int update_volume(UAContext *ua)
514 NT_("VolStatus"), /* 0 */
515 NT_("VolRetention"), /* 1 */
516 NT_("VolUse"), /* 2 */
517 NT_("MaxVolJobs"), /* 3 */
518 NT_("MaxVolFiles"), /* 4 */
519 NT_("MaxVolBytes"), /* 5 */
520 NT_("Recycle"), /* 6 */
521 NT_("InChanger"), /* 7 */
524 NT_("FromPool"), /* 10 */
525 NT_("AllFromPool"), /* 11 !!! see below !!! */
526 NT_("Enabled"), /* 12 */
527 NT_("RecyclePool"), /* 13 */
528 NT_("ActionOnPurge"), /* 14 */
531 #define AllFromPool 11 /* keep this updated with above */
533 for (i=0; kw[i]; i++) {
537 if ((j=find_arg_with_value(ua, kw[i])) > 0) {
538 /* If all from pool don't select a media record */
539 if (i != AllFromPool && !select_media_dbr(ua, &mr)) {
544 update_volstatus(ua, ua->argv[j], &mr);
547 update_volretention(ua, ua->argv[j], &mr);
550 update_voluseduration(ua, ua->argv[j], &mr);
553 update_volmaxjobs(ua, ua->argv[j], &mr);
556 update_volmaxfiles(ua, ua->argv[j], &mr);
559 update_volmaxbytes(ua, ua->argv[j], &mr);
562 update_volrecycle(ua, ua->argv[j], &mr);
565 update_volinchanger(ua, ua->argv[j], &mr);
568 update_volslot(ua, ua->argv[j], &mr);
571 memset(&pr, 0, sizeof(POOL_DBR));
572 pr.PoolId = mr.PoolId;
573 if (!db_get_pool_numvols(ua->jcr, ua->db, &pr)) {
574 ua->error_msg("%s", db_strerror(ua->db));
577 update_vol_pool(ua, ua->argv[j], &mr, &pr);
580 update_vol_from_pool(ua, &mr);
583 update_all_vols_from_pool(ua, ua->argv[j]);
586 update_volenabled(ua, ua->argv[j], &mr);
589 update_vol_recyclepool(ua, ua->argv[j], &mr);
592 update_vol_actiononpurge(ua, ua->argv[j], &mr);
599 /* Allow user to simply update all volumes */
600 if (find_arg(ua, NT_("fromallpools")) > 0) {
606 start_prompt(ua, _("Parameters to modify:\n"));
607 add_prompt(ua, _("Volume Status")); /* 0 */
608 add_prompt(ua, _("Volume Retention Period")); /* 1 */
609 add_prompt(ua, _("Volume Use Duration")); /* 2 */
610 add_prompt(ua, _("Maximum Volume Jobs")); /* 3 */
611 add_prompt(ua, _("Maximum Volume Files")); /* 4 */
612 add_prompt(ua, _("Maximum Volume Bytes")); /* 5 */
613 add_prompt(ua, _("Recycle Flag")); /* 6 */
614 add_prompt(ua, _("Slot")); /* 7 */
615 add_prompt(ua, _("InChanger Flag")); /* 8 */
616 add_prompt(ua, _("Volume Files")); /* 9 */
617 add_prompt(ua, _("Pool")); /* 10 */
618 add_prompt(ua, _("Volume from Pool")); /* 11 */
619 add_prompt(ua, _("All Volumes from Pool")); /* 12 */
620 add_prompt(ua, _("All Volumes from all Pools")); /* 13 */
621 add_prompt(ua, _("Enabled")), /* 14 */
622 add_prompt(ua, _("RecyclePool")), /* 15 */
623 add_prompt(ua, _("Action On Purge")), /* 16 */
624 add_prompt(ua, _("Done")); /* 17 */
625 i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);
627 /* For All Volumes, All Volumes from Pool, and Done, we don't need
629 if ( i != 12 && i != 13 && i != 17) {
630 if (!select_media_dbr(ua, &mr)) { /* Get Volume record */
633 ua->info_msg(_("Updating Volume \"%s\"\n"), mr.VolumeName);
636 case 0: /* Volume Status */
637 /* Modify Volume Status */
638 ua->info_msg(_("Current Volume status is: %s\n"), mr.VolStatus);
639 start_prompt(ua, _("Possible Values are:\n"));
640 add_prompt(ua, NT_("Append"));
641 add_prompt(ua, NT_("Archive"));
642 add_prompt(ua, NT_("Disabled"));
643 add_prompt(ua, NT_("Full"));
644 add_prompt(ua, NT_("Used"));
645 add_prompt(ua, NT_("Cleaning"));
646 if (strcmp(mr.VolStatus, NT_("Purged")) == 0) {
647 add_prompt(ua, NT_("Recycle"));
649 add_prompt(ua, NT_("Read-Only"));
650 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
653 update_volstatus(ua, ua->cmd, &mr);
655 case 1: /* Retention */
656 ua->info_msg(_("Current retention period is: %s\n"),
657 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
658 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
661 update_volretention(ua, ua->cmd, &mr);
664 case 2: /* Use Duration */
665 ua->info_msg(_("Current use duration is: %s\n"),
666 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
667 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
670 update_voluseduration(ua, ua->cmd, &mr);
673 case 3: /* Max Jobs */
674 ua->info_msg(_("Current max jobs is: %u\n"), mr.MaxVolJobs);
675 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
678 update_volmaxjobs(ua, ua->cmd, &mr);
681 case 4: /* Max Files */
682 ua->info_msg(_("Current max files is: %u\n"), mr.MaxVolFiles);
683 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
686 update_volmaxfiles(ua, ua->cmd, &mr);
689 case 5: /* Max Bytes */
690 ua->info_msg(_("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
691 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
694 update_volmaxbytes(ua, ua->cmd, &mr);
698 case 6: /* Recycle */
699 ua->info_msg(_("Current recycle flag is: %s\n"),
700 mr.Recycle==1?_("yes"):_("no"));
701 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
704 update_volrecycle(ua, ua->cmd, &mr);
708 ua->info_msg(_("Current Slot is: %d\n"), mr.Slot);
709 if (!get_pint(ua, _("Enter new Slot: "))) {
712 update_volslot(ua, ua->cmd, &mr);
715 case 8: /* InChanger */
716 ua->info_msg(_("Current InChanger flag is: %d\n"), mr.InChanger);
717 bsnprintf(buf, sizeof(buf), _("Set InChanger flag for Volume \"%s\": yes/no: "),
719 if (!get_yesno(ua, buf)) {
722 mr.InChanger = ua->pint32_val;
724 * Make sure to use db_update... rather than doing this directly,
725 * so that any Slot is handled correctly.
727 set_storageid_in_mr(NULL, &mr);
728 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
729 ua->error_msg(_("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
731 ua->info_msg(_("New InChanger flag is: %d\n"), mr.InChanger);
736 case 9: /* Volume Files */
738 ua->warning_msg(_("Warning changing Volume Files can result\n"
739 "in loss of data on your Volume\n\n"));
740 ua->info_msg(_("Current Volume Files is: %u\n"), mr.VolFiles);
741 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
744 VolFiles = ua->pint32_val;
745 if (VolFiles != (int)(mr.VolFiles + 1)) {
746 ua->warning_msg(_("Normally, you should only increase Volume Files by one!\n"));
747 if (!get_yesno(ua, _("Increase Volume Files? (yes/no): ")) || ua->pint32_val == 0) {
751 query = get_pool_memory(PM_MESSAGE);
752 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
753 VolFiles, edit_int64(mr.MediaId, ed1));
754 if (!db_sql_query(ua->db, query, NULL, NULL)) {
755 ua->error_msg("%s", db_strerror(ua->db));
757 ua->info_msg(_("New Volume Files is: %u\n"), VolFiles);
759 free_pool_memory(query);
762 case 10: /* Volume's Pool */
763 memset(&pr, 0, sizeof(POOL_DBR));
764 pr.PoolId = mr.PoolId;
765 if (!db_get_pool_numvols(ua->jcr, ua->db, &pr)) {
766 ua->error_msg("%s", db_strerror(ua->db));
769 ua->info_msg(_("Current Pool is: %s\n"), pr.Name);
770 if (!get_cmd(ua, _("Enter new Pool name: "))) {
773 update_vol_pool(ua, ua->cmd, &mr, &pr);
777 update_vol_from_pool(ua, &mr);
780 pool = select_pool_resource(ua);
782 update_all_vols_from_pool(ua, pool->name());
791 ua->info_msg(_("Current Enabled is: %d\n"), mr.Enabled);
792 if (!get_cmd(ua, _("Enter new Enabled: "))) {
795 update_volenabled(ua, ua->cmd, &mr);
799 memset(&pr, 0, sizeof(POOL_DBR));
800 pr.PoolId = mr.RecyclePoolId;
801 if (db_get_pool_numvols(ua->jcr, ua->db, &pr)) {
802 ua->info_msg(_("Current RecyclePool is: %s\n"), pr.Name);
804 ua->info_msg(_("No current RecyclePool\n"));
806 if (!select_pool_dbr(ua, &pr, NT_("recyclepool"))) {
809 update_vol_recyclepool(ua, pr.Name, &mr);
814 ua->info_msg(_("Current ActionOnPurge is: %s\n"),
815 action_on_purge_to_string(mr.ActionOnPurge, ret));
816 if (!get_cmd(ua, _("Enter new ActionOnPurge (one of: Truncate, None): "))) {
820 update_vol_actiononpurge(ua, ua->cmd, &mr);
823 default: /* Done or error */
824 ua->info_msg(_("Selection terminated.\n"));
832 * Update long term statistics
834 static bool update_stats(UAContext *ua)
836 int i = find_arg_with_value(ua, NT_("days"));
840 since = atoi(ua->argv[i]) * 24*60*60;
843 int nb = db_update_stats(ua->jcr, ua->db, since);
844 ua->info_msg(_("Updating %i job(s).\n"), nb);
850 * Update pool record -- pull info from current POOL resource
852 static bool update_pool(UAContext *ua)
860 pool = get_pool_resource(ua);
865 memset(&pr, 0, sizeof(pr));
866 bstrncpy(pr.Name, pool->name(), sizeof(pr.Name));
867 if (!get_pool_dbr(ua, &pr)) {
871 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
872 set_pooldbr_references(ua->jcr, ua->db, &pr, pool);
874 id = db_update_pool_record(ua->jcr, ua->db, &pr);
876 ua->error_msg(_("db_update_pool_record returned %d. ERR=%s\n"),
877 id, db_strerror(ua->db));
879 query = get_pool_memory(PM_MESSAGE);
880 Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
881 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
882 free_pool_memory(query);
883 ua->info_msg(_("Pool DB record updated from resource.\n"));
888 * Update a Job record -- allows you to change the
889 * date fields in a Job record. This helps when
890 * providing migration from other vendors.
892 static bool update_job(UAContext *ua)
895 char ed1[50], ed2[50];
896 POOL_MEM cmd(PM_MESSAGE);
900 char *client_name = NULL;
901 char *start_time = NULL;
903 NT_("starttime"), /* 0 */
904 NT_("client"), /* 1 */
907 Dmsg1(200, "cmd=%s\n", ua->cmd);
908 i = find_arg_with_value(ua, NT_("jobid"));
910 ua->error_msg(_("Expect JobId keyword, not found.\n"));
913 memset(&jr, 0, sizeof(jr));
914 memset(&cr, 0, sizeof(cr));
915 jr.JobId = str_to_int64(ua->argv[i]);
916 if (!db_get_job_record(ua->jcr, ua->db, &jr)) {
917 ua->error_msg("%s", db_strerror(ua->db));
921 for (i=0; kw[i]; i++) {
923 if ((j=find_arg_with_value(ua, kw[i])) >= 0) {
925 case 0: /* start time */
926 start_time = ua->argv[j];
928 case 1: /* Client name */
929 client_name = ua->argv[j];
934 if (!client_name && !start_time) {
935 ua->error_msg(_("Neither Client nor StartTime specified.\n"));
939 if (!get_client_dbr(ua, &cr)) {
942 jr.ClientId = cr.ClientId;
947 StartTime = str_to_utime(start_time);
948 if (StartTime == 0) {
949 ua->error_msg(_("Improper date format: %s\n"), ua->argv[i]);
952 delta_start = StartTime - jr.StartTime;
953 Dmsg3(200, "ST=%lld jr.ST=%lld delta=%lld\n", StartTime,
954 (utime_t)jr.StartTime, delta_start);
955 jr.StartTime = (time_t)StartTime;
956 jr.SchedTime += (time_t)delta_start;
957 jr.EndTime += (time_t)delta_start;
958 jr.JobTDate += delta_start;
959 /* Convert to DB times */
960 bstrutime(jr.cStartTime, sizeof(jr.cStartTime), jr.StartTime);
961 bstrutime(jr.cSchedTime, sizeof(jr.cSchedTime), jr.SchedTime);
962 bstrutime(jr.cEndTime, sizeof(jr.cEndTime), jr.EndTime);
964 Mmsg(cmd, "UPDATE Job SET ClientId=%s,StartTime='%s',SchedTime='%s',"
965 "EndTime='%s',JobTDate=%s WHERE JobId=%s",
966 edit_int64(jr.ClientId, ed1),
970 edit_uint64(jr.JobTDate, ed1),
971 edit_int64(jr.JobId, ed2));
972 if (!db_sql_query(ua->db, cmd.c_str(), NULL, NULL)) {
973 ua->error_msg("%s", db_strerror(ua->db));