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 !!! see below !!! */
524 NT_("AllFromPool"), /* 11 !!! see below !!! */
525 NT_("Enabled"), /* 12 */
526 NT_("RecyclePool"), /* 13 */
527 NT_("ActionOnPurge"), /* 14 */
528 NT_("FromAllPools"), /* 15 !!! see bellow !!! */
531 #define FromPool 10 /* keep this updated */
532 #define AllFromPool 11 /* keep this updated with above */
533 #define FromAllPools 15 /* keep this updated */
535 for (i=0; kw[i]; i++) {
538 /* No argv with these parameters */
539 if (i == FromPool || i == FromAllPools) {
540 j = find_arg(ua, kw[i]);
543 j = find_arg_with_value(ua, kw[i]);
546 /* If all from pool/from all pools don't select a media record */
547 if (i != AllFromPool && i != FromAllPools && !select_media_dbr(ua, &mr)) {
552 update_volstatus(ua, ua->argv[j], &mr);
555 update_volretention(ua, ua->argv[j], &mr);
558 update_voluseduration(ua, ua->argv[j], &mr);
561 update_volmaxjobs(ua, ua->argv[j], &mr);
564 update_volmaxfiles(ua, ua->argv[j], &mr);
567 update_volmaxbytes(ua, ua->argv[j], &mr);
570 update_volrecycle(ua, ua->argv[j], &mr);
573 update_volinchanger(ua, ua->argv[j], &mr);
576 update_volslot(ua, ua->argv[j], &mr);
579 memset(&pr, 0, sizeof(POOL_DBR));
580 pr.PoolId = mr.PoolId;
581 if (!db_get_pool_numvols(ua->jcr, ua->db, &pr)) {
582 ua->error_msg("%s", db_strerror(ua->db));
585 update_vol_pool(ua, ua->argv[j], &mr, &pr);
588 update_vol_from_pool(ua, &mr);
591 update_all_vols_from_pool(ua, ua->argv[j]);
594 update_volenabled(ua, ua->argv[j], &mr);
597 update_vol_recyclepool(ua, ua->argv[j], &mr);
600 update_vol_actiononpurge(ua, ua->argv[j], &mr);
611 start_prompt(ua, _("Parameters to modify:\n"));
612 add_prompt(ua, _("Volume Status")); /* 0 */
613 add_prompt(ua, _("Volume Retention Period")); /* 1 */
614 add_prompt(ua, _("Volume Use Duration")); /* 2 */
615 add_prompt(ua, _("Maximum Volume Jobs")); /* 3 */
616 add_prompt(ua, _("Maximum Volume Files")); /* 4 */
617 add_prompt(ua, _("Maximum Volume Bytes")); /* 5 */
618 add_prompt(ua, _("Recycle Flag")); /* 6 */
619 add_prompt(ua, _("Slot")); /* 7 */
620 add_prompt(ua, _("InChanger Flag")); /* 8 */
621 add_prompt(ua, _("Volume Files")); /* 9 */
622 add_prompt(ua, _("Pool")); /* 10 */
623 add_prompt(ua, _("Volume from Pool")); /* 11 */
624 add_prompt(ua, _("All Volumes from Pool")); /* 12 */
625 add_prompt(ua, _("All Volumes from all Pools")); /* 13 */
626 add_prompt(ua, _("Enabled")), /* 14 */
627 add_prompt(ua, _("RecyclePool")), /* 15 */
628 add_prompt(ua, _("Action On Purge")), /* 16 */
629 add_prompt(ua, _("Done")); /* 17 */
630 i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);
632 /* For All Volumes, All Volumes from Pool, and Done, we don't need
634 if ( i != 12 && i != 13 && i != 17) {
635 if (!select_media_dbr(ua, &mr)) { /* Get Volume record */
638 ua->info_msg(_("Updating Volume \"%s\"\n"), mr.VolumeName);
641 case 0: /* Volume Status */
642 /* Modify Volume Status */
643 ua->info_msg(_("Current Volume status is: %s\n"), mr.VolStatus);
644 start_prompt(ua, _("Possible Values are:\n"));
645 add_prompt(ua, NT_("Append"));
646 add_prompt(ua, NT_("Archive"));
647 add_prompt(ua, NT_("Disabled"));
648 add_prompt(ua, NT_("Full"));
649 add_prompt(ua, NT_("Used"));
650 add_prompt(ua, NT_("Cleaning"));
651 if (strcmp(mr.VolStatus, NT_("Purged")) == 0) {
652 add_prompt(ua, NT_("Recycle"));
654 add_prompt(ua, NT_("Read-Only"));
655 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
658 update_volstatus(ua, ua->cmd, &mr);
660 case 1: /* Retention */
661 ua->info_msg(_("Current retention period is: %s\n"),
662 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
663 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
666 update_volretention(ua, ua->cmd, &mr);
669 case 2: /* Use Duration */
670 ua->info_msg(_("Current use duration is: %s\n"),
671 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
672 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
675 update_voluseduration(ua, ua->cmd, &mr);
678 case 3: /* Max Jobs */
679 ua->info_msg(_("Current max jobs is: %u\n"), mr.MaxVolJobs);
680 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
683 update_volmaxjobs(ua, ua->cmd, &mr);
686 case 4: /* Max Files */
687 ua->info_msg(_("Current max files is: %u\n"), mr.MaxVolFiles);
688 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
691 update_volmaxfiles(ua, ua->cmd, &mr);
694 case 5: /* Max Bytes */
695 ua->info_msg(_("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
696 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
699 update_volmaxbytes(ua, ua->cmd, &mr);
703 case 6: /* Recycle */
704 ua->info_msg(_("Current recycle flag is: %s\n"),
705 mr.Recycle==1?_("yes"):_("no"));
706 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
709 update_volrecycle(ua, ua->cmd, &mr);
713 ua->info_msg(_("Current Slot is: %d\n"), mr.Slot);
714 if (!get_pint(ua, _("Enter new Slot: "))) {
717 update_volslot(ua, ua->cmd, &mr);
720 case 8: /* InChanger */
721 ua->info_msg(_("Current InChanger flag is: %d\n"), mr.InChanger);
722 bsnprintf(buf, sizeof(buf), _("Set InChanger flag for Volume \"%s\": yes/no: "),
724 if (!get_yesno(ua, buf)) {
727 mr.InChanger = ua->pint32_val;
729 * Make sure to use db_update... rather than doing this directly,
730 * so that any Slot is handled correctly.
732 set_storageid_in_mr(NULL, &mr);
733 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
734 ua->error_msg(_("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
736 ua->info_msg(_("New InChanger flag is: %d\n"), mr.InChanger);
741 case 9: /* Volume Files */
743 ua->warning_msg(_("Warning changing Volume Files can result\n"
744 "in loss of data on your Volume\n\n"));
745 ua->info_msg(_("Current Volume Files is: %u\n"), mr.VolFiles);
746 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
749 VolFiles = ua->pint32_val;
750 if (VolFiles != (int)(mr.VolFiles + 1)) {
751 ua->warning_msg(_("Normally, you should only increase Volume Files by one!\n"));
752 if (!get_yesno(ua, _("Increase Volume Files? (yes/no): ")) || ua->pint32_val == 0) {
756 query = get_pool_memory(PM_MESSAGE);
757 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
758 VolFiles, edit_int64(mr.MediaId, ed1));
759 if (!db_sql_query(ua->db, query, NULL, NULL)) {
760 ua->error_msg("%s", db_strerror(ua->db));
762 ua->info_msg(_("New Volume Files is: %u\n"), VolFiles);
764 free_pool_memory(query);
767 case 10: /* Volume's Pool */
768 memset(&pr, 0, sizeof(POOL_DBR));
769 pr.PoolId = mr.PoolId;
770 if (!db_get_pool_numvols(ua->jcr, ua->db, &pr)) {
771 ua->error_msg("%s", db_strerror(ua->db));
774 ua->info_msg(_("Current Pool is: %s\n"), pr.Name);
775 if (!get_cmd(ua, _("Enter new Pool name: "))) {
778 update_vol_pool(ua, ua->cmd, &mr, &pr);
782 update_vol_from_pool(ua, &mr);
785 pool = select_pool_resource(ua);
787 update_all_vols_from_pool(ua, pool->name());
796 ua->info_msg(_("Current Enabled is: %d\n"), mr.Enabled);
797 if (!get_cmd(ua, _("Enter new Enabled: "))) {
800 update_volenabled(ua, ua->cmd, &mr);
804 memset(&pr, 0, sizeof(POOL_DBR));
805 pr.PoolId = mr.RecyclePoolId;
806 if (db_get_pool_numvols(ua->jcr, ua->db, &pr)) {
807 ua->info_msg(_("Current RecyclePool is: %s\n"), pr.Name);
809 ua->info_msg(_("No current RecyclePool\n"));
811 if (!select_pool_dbr(ua, &pr, NT_("recyclepool"))) {
814 update_vol_recyclepool(ua, pr.Name, &mr);
819 ua->info_msg(_("Current ActionOnPurge is: %s\n"),
820 action_on_purge_to_string(mr.ActionOnPurge, ret));
821 if (!get_cmd(ua, _("Enter new ActionOnPurge (one of: Truncate, None): "))) {
825 update_vol_actiononpurge(ua, ua->cmd, &mr);
828 default: /* Done or error */
829 ua->info_msg(_("Selection terminated.\n"));
837 * Update long term statistics
839 static bool update_stats(UAContext *ua)
841 int i = find_arg_with_value(ua, NT_("days"));
845 since = atoi(ua->argv[i]) * 24*60*60;
848 int nb = db_update_stats(ua->jcr, ua->db, since);
849 ua->info_msg(_("Updating %i job(s).\n"), nb);
855 * Update pool record -- pull info from current POOL resource
857 static bool update_pool(UAContext *ua)
865 pool = get_pool_resource(ua);
870 memset(&pr, 0, sizeof(pr));
871 bstrncpy(pr.Name, pool->name(), sizeof(pr.Name));
872 if (!get_pool_dbr(ua, &pr)) {
876 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
877 set_pooldbr_references(ua->jcr, ua->db, &pr, pool);
879 id = db_update_pool_record(ua->jcr, ua->db, &pr);
881 ua->error_msg(_("db_update_pool_record returned %d. ERR=%s\n"),
882 id, db_strerror(ua->db));
884 query = get_pool_memory(PM_MESSAGE);
885 Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
886 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
887 free_pool_memory(query);
888 ua->info_msg(_("Pool DB record updated from resource.\n"));
893 * Update a Job record -- allows you to change the
894 * date fields in a Job record. This helps when
895 * providing migration from other vendors.
897 static bool update_job(UAContext *ua)
900 char ed1[50], ed2[50];
901 POOL_MEM cmd(PM_MESSAGE);
905 char *client_name = NULL;
906 char *start_time = NULL;
908 NT_("starttime"), /* 0 */
909 NT_("client"), /* 1 */
912 Dmsg1(200, "cmd=%s\n", ua->cmd);
913 i = find_arg_with_value(ua, NT_("jobid"));
915 ua->error_msg(_("Expect JobId keyword, not found.\n"));
918 memset(&jr, 0, sizeof(jr));
919 memset(&cr, 0, sizeof(cr));
920 jr.JobId = str_to_int64(ua->argv[i]);
921 if (!db_get_job_record(ua->jcr, ua->db, &jr)) {
922 ua->error_msg("%s", db_strerror(ua->db));
926 for (i=0; kw[i]; i++) {
928 if ((j=find_arg_with_value(ua, kw[i])) >= 0) {
930 case 0: /* start time */
931 start_time = ua->argv[j];
933 case 1: /* Client name */
934 client_name = ua->argv[j];
939 if (!client_name && !start_time) {
940 ua->error_msg(_("Neither Client nor StartTime specified.\n"));
944 if (!get_client_dbr(ua, &cr)) {
947 jr.ClientId = cr.ClientId;
952 StartTime = str_to_utime(start_time);
953 if (StartTime == 0) {
954 ua->error_msg(_("Improper date format: %s\n"), ua->argv[i]);
957 delta_start = StartTime - jr.StartTime;
958 Dmsg3(200, "ST=%lld jr.ST=%lld delta=%lld\n", StartTime,
959 (utime_t)jr.StartTime, delta_start);
960 jr.StartTime = (time_t)StartTime;
961 jr.SchedTime += (time_t)delta_start;
962 jr.EndTime += (time_t)delta_start;
963 jr.JobTDate += delta_start;
964 /* Convert to DB times */
965 bstrutime(jr.cStartTime, sizeof(jr.cStartTime), jr.StartTime);
966 bstrutime(jr.cSchedTime, sizeof(jr.cSchedTime), jr.SchedTime);
967 bstrutime(jr.cEndTime, sizeof(jr.cEndTime), jr.EndTime);
969 Mmsg(cmd, "UPDATE Job SET ClientId=%s,StartTime='%s',SchedTime='%s',"
970 "EndTime='%s',JobTDate=%s WHERE JobId=%s",
971 edit_int64(jr.ClientId, ed1),
975 edit_uint64(jr.JobTDate, ed1),
976 edit_int64(jr.JobId, ed2));
977 if (!db_sql_query(ua->db, cmd.c_str(), NULL, NULL)) {
978 ua->error_msg("%s", db_strerror(ua->db));