2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
30 * Bacula Director -- Update command processing
31 * Split from ua_cmds.c March 2005
33 * Kern Sibbald, September MM
41 /* Forward referenced functions */
42 static int update_volume(UAContext *ua);
43 static bool update_pool(UAContext *ua);
44 static bool update_job(UAContext *ua);
47 * Update a Pool Record in the database.
48 * It is always updated from the Resource record.
50 * update pool=<pool-name>
51 * updates pool from Pool resource
52 * update media pool=<pool-name> volume=<volume-name>
53 * changes pool info for volume
54 * update slots [scan=...]
55 * updates autochanger slots
57 int update_cmd(UAContext *ua, const char *cmd)
59 static const char *kw[] = {
61 NT_("volume"), /* 1 */
67 if (!open_client_db(ua)) {
71 switch (find_arg_keyword(ua, kw)) {
89 start_prompt(ua, _("Update choice:\n"));
90 add_prompt(ua, _("Volume parameters"));
91 add_prompt(ua, _("Pool from resource"));
92 add_prompt(ua, _("Slots from autochanger"));
93 switch (do_prompt(ua, _("item"), _("Choose catalog item to update"), NULL, 0)) {
109 static void update_volstatus(UAContext *ua, const char *val, MEDIA_DBR *mr)
111 POOL_MEM query(PM_MESSAGE);
126 for (i=0; kw[i]; i++) {
127 if (strcasecmp(val, kw[i]) == 0) {
133 ua->error_msg(_("Invalid VolStatus specified: %s\n"), val);
136 bstrncpy(mr->VolStatus, kw[i], sizeof(mr->VolStatus));
137 Mmsg(query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%s",
138 mr->VolStatus, edit_int64(mr->MediaId,ed1));
139 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
140 ua->error_msg("%s", db_strerror(ua->db));
142 ua->info_msg(_("New Volume status is: %s\n"), mr->VolStatus);
147 static void update_volretention(UAContext *ua, char *val, MEDIA_DBR *mr)
149 char ed1[150], ed2[50];
150 POOL_MEM query(PM_MESSAGE);
151 if (!duration_to_utime(val, &mr->VolRetention)) {
152 ua->error_msg(_("Invalid retention period specified: %s\n"), val);
155 Mmsg(query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%s",
156 edit_uint64(mr->VolRetention, ed1), edit_int64(mr->MediaId,ed2));
157 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
158 ua->error_msg("%s", db_strerror(ua->db));
160 ua->info_msg(_("New retention period is: %s\n"),
161 edit_utime(mr->VolRetention, ed1, sizeof(ed1)));
165 static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr)
167 char ed1[150], ed2[50];
168 POOL_MEM query(PM_MESSAGE);
170 if (!duration_to_utime(val, &mr->VolUseDuration)) {
171 ua->error_msg(_("Invalid use duration specified: %s\n"), val);
174 Mmsg(query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%s",
175 edit_uint64(mr->VolUseDuration, ed1), edit_int64(mr->MediaId,ed2));
176 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
177 ua->error_msg("%s", db_strerror(ua->db));
179 ua->info_msg(_("New use duration is: %s\n"),
180 edit_utime(mr->VolUseDuration, ed1, sizeof(ed1)));
184 static void update_volmaxjobs(UAContext *ua, char *val, MEDIA_DBR *mr)
186 POOL_MEM query(PM_MESSAGE);
188 Mmsg(query, "UPDATE Media SET MaxVolJobs=%s WHERE MediaId=%s",
189 val, edit_int64(mr->MediaId,ed1));
190 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
191 ua->error_msg("%s", db_strerror(ua->db));
193 ua->info_msg(_("New max jobs is: %s\n"), val);
197 static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr)
199 POOL_MEM query(PM_MESSAGE);
201 Mmsg(query, "UPDATE Media SET MaxVolFiles=%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 files is: %s\n"), val);
210 static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr)
213 char ed1[50], ed2[50];
214 POOL_MEM query(PM_MESSAGE);
216 if (!size_to_uint64(val, strlen(val), &maxbytes)) {
217 ua->error_msg(_("Invalid max. bytes specification: %s\n"), val);
220 Mmsg(query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%s",
221 edit_uint64(maxbytes, ed1), edit_int64(mr->MediaId, ed2));
222 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
223 ua->error_msg("%s", db_strerror(ua->db));
225 ua->info_msg(_("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1));
229 static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr)
234 POOL_MEM query(PM_MESSAGE);
235 if (!is_yesno(val, &recycle)) {
236 ua->error_msg(_("Invalid value. It must be yes or no.\n"));
239 Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%s",
240 recycle, edit_int64(mr->MediaId, ed1));
241 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
242 ua->error_msg("%s", db_strerror(ua->db));
244 ua->info_msg(_("New Recycle flag is: %s\n"),
245 recycle==1?_("yes"):_("no"));
249 static void update_volinchanger(UAContext *ua, char *val, MEDIA_DBR *mr)
254 POOL_MEM query(PM_MESSAGE);
255 if (!is_yesno(val, &InChanger)) {
256 ua->error_msg(_("Invalid value. It must be yes or no.\n"));
259 Mmsg(query, "UPDATE Media SET InChanger=%d WHERE MediaId=%s",
260 InChanger, edit_int64(mr->MediaId, ed1));
261 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
262 ua->error_msg("%s", db_strerror(ua->db));
264 ua->info_msg(_("New InChanger flag is: %s\n"),
265 InChanger==1?_("yes"):_("no"));
270 static void update_volslot(UAContext *ua, char *val, MEDIA_DBR *mr)
274 memset(&pr, 0, sizeof(POOL_DBR));
275 pr.PoolId = mr->PoolId;
276 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
277 ua->error_msg("%s", db_strerror(ua->db));
280 mr->Slot = atoi(val);
281 if (pr.MaxVols > 0 && mr->Slot > (int)pr.MaxVols) {
282 ua->error_msg(_("Invalid slot, it must be between 0 and MaxVols=%d\n"),
287 * Make sure to use db_update... rather than doing this directly,
288 * so that any Slot is handled correctly.
290 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
291 ua->error_msg(_("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
293 ua->info_msg(_("New Slot is: %d\n"), mr->Slot);
297 /* Modify the Pool in which this Volume is located */
298 void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr)
301 POOL_MEM query(PM_MESSAGE);
302 char ed1[50], ed2[50];
304 memset(&pr, 0, sizeof(pr));
305 bstrncpy(pr.Name, val, sizeof(pr.Name));
306 if (!get_pool_dbr(ua, &pr)) {
309 mr->PoolId = pr.PoolId; /* set new PoolId */
313 Mmsg(query, "UPDATE Media SET PoolId=%s WHERE MediaId=%s",
314 edit_int64(mr->PoolId, ed1), edit_int64(mr->MediaId, ed2));
315 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
316 ua->error_msg("%s", db_strerror(ua->db));
318 ua->info_msg(_("New Pool is: %s\n"), pr.Name);
320 if (!db_update_pool_record(ua->jcr, ua->db, opr)) {
321 ua->error_msg("%s", db_strerror(ua->db));
324 if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
325 ua->error_msg("%s", db_strerror(ua->db));
331 /* Modify the RecyclePool of a Volume */
332 void update_vol_recyclepool(UAContext *ua, char *val, MEDIA_DBR *mr)
335 POOL_MEM query(PM_MESSAGE);
336 char ed1[50], ed2[50];
338 memset(&pr, 0, sizeof(pr));
339 bstrncpy(pr.Name, val, sizeof(pr.Name));
340 if (!get_pool_dbr(ua, &pr, NT_("recyclepool"))) {
343 /* pool = select_pool_resource(ua); */
344 mr->RecyclePoolId = pr.PoolId; /* get the PoolId */
347 Mmsg(query, "UPDATE Media SET RecyclePoolId=%s WHERE MediaId=%s",
348 edit_int64(mr->RecyclePoolId, ed1), edit_int64(mr->MediaId, ed2));
349 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
350 ua->error_msg("%s", db_strerror(ua->db));
352 ua->info_msg(_("New RecyclePool is: %s\n"), pr.Name);
358 * Refresh the Volume information from the Pool record
360 static void update_vol_from_pool(UAContext *ua, MEDIA_DBR *mr)
364 memset(&pr, 0, sizeof(pr));
365 pr.PoolId = mr->PoolId;
366 if (!db_get_pool_record(ua->jcr, ua->db, &pr) ||
367 !acl_access_ok(ua, Pool_ACL, pr.Name)) {
370 set_pool_dbr_defaults_in_media_dbr(mr, &pr);
371 if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
372 ua->error_msg(_("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
374 ua->info_msg(_("Volume defaults updated from \"%s\" Pool record.\n"),
380 * Refresh the Volume information from the Pool record
383 static void update_all_vols_from_pool(UAContext *ua, const char *pool_name)
388 memset(&pr, 0, sizeof(pr));
389 memset(&mr, 0, sizeof(mr));
391 bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
392 if (!get_pool_dbr(ua, &pr)) {
395 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
396 mr.PoolId = pr.PoolId;
397 if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
398 ua->error_msg(_("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
400 ua->info_msg(_("All Volume defaults updated from \"%s\" Pool record.\n"),
405 static void update_all_vols(UAContext *ua)
412 memset(&pr, 0, sizeof(pr));
413 memset(&mr, 0, sizeof(mr));
415 if (!db_get_pool_ids(ua->jcr, ua->db, &num_pools, &ids)) {
416 ua->error_msg(_("Error obtaining pool ids. ERR=%s\n"), db_strerror(ua->db));
420 for (i=0; i<num_pools; i++) {
422 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { /* ***FIXME*** use acl? */
423 ua->warning_msg(_("Updating all pools, but skipped PoolId=%d. ERR=%s\n"), db_strerror(ua->db));
427 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
428 mr.PoolId = pr.PoolId;
430 if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
431 ua->error_msg(_("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
433 ua->info_msg(_("All Volume defaults updated from \"%s\" Pool record.\n"),
441 static void update_volenabled(UAContext *ua, char *val, MEDIA_DBR *mr)
443 mr->Enabled = get_enabled(ua, val);
444 if (mr->Enabled < 0) {
447 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
448 ua->error_msg(_("Error updating media record Enabled: ERR=%s"), db_strerror(ua->db));
450 ua->info_msg(_("New Enabled is: %d\n"), mr->Enabled);
457 * Update a media record -- allows you to change the
458 * Volume status. E.g. if you want Bacula to stop
459 * writing on the volume, set it to anything other
462 static int update_volume(UAContext *ua)
473 NT_("VolStatus"), /* 0 */
474 NT_("VolRetention"), /* 1 */
475 NT_("VolUse"), /* 2 */
476 NT_("MaxVolJobs"), /* 3 */
477 NT_("MaxVolFiles"), /* 4 */
478 NT_("MaxVolBytes"), /* 5 */
479 NT_("Recycle"), /* 6 */
480 NT_("InChanger"), /* 7 */
483 NT_("FromPool"), /* 10 */
484 NT_("AllFromPool"), /* 11 !!! see below !!! */
485 NT_("Enabled"), /* 12 */
486 NT_("RecyclePool"), /* 13 */
489 #define AllFromPool 11 /* keep this updated with above */
491 for (i=0; kw[i]; i++) {
495 if ((j=find_arg_with_value(ua, kw[i])) > 0) {
496 /* If all from pool don't select a media record */
497 if (i != AllFromPool && !select_media_dbr(ua, &mr)) {
502 update_volstatus(ua, ua->argv[j], &mr);
505 update_volretention(ua, ua->argv[j], &mr);
508 update_voluseduration(ua, ua->argv[j], &mr);
511 update_volmaxjobs(ua, ua->argv[j], &mr);
514 update_volmaxfiles(ua, ua->argv[j], &mr);
517 update_volmaxbytes(ua, ua->argv[j], &mr);
520 update_volrecycle(ua, ua->argv[j], &mr);
523 update_volinchanger(ua, ua->argv[j], &mr);
526 update_volslot(ua, ua->argv[j], &mr);
529 memset(&pr, 0, sizeof(POOL_DBR));
530 pr.PoolId = mr.PoolId;
531 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
532 ua->error_msg("%s", db_strerror(ua->db));
535 update_vol_pool(ua, ua->argv[j], &mr, &pr);
538 update_vol_from_pool(ua, &mr);
541 update_all_vols_from_pool(ua, ua->argv[j]);
544 update_volenabled(ua, ua->argv[j], &mr);
547 update_vol_recyclepool(ua, ua->argv[j], &mr);
554 /* Allow user to simply update all volumes */
555 if (find_arg(ua, NT_("fromallpools")) > 0) {
561 start_prompt(ua, _("Parameters to modify:\n"));
562 add_prompt(ua, _("Volume Status")); /* 0 */
563 add_prompt(ua, _("Volume Retention Period")); /* 1 */
564 add_prompt(ua, _("Volume Use Duration")); /* 2 */
565 add_prompt(ua, _("Maximum Volume Jobs")); /* 3 */
566 add_prompt(ua, _("Maximum Volume Files")); /* 4 */
567 add_prompt(ua, _("Maximum Volume Bytes")); /* 5 */
568 add_prompt(ua, _("Recycle Flag")); /* 6 */
569 add_prompt(ua, _("Slot")); /* 7 */
570 add_prompt(ua, _("InChanger Flag")); /* 8 */
571 add_prompt(ua, _("Volume Files")); /* 9 */
572 add_prompt(ua, _("Pool")); /* 10 */
573 add_prompt(ua, _("Volume from Pool")); /* 11 */
574 add_prompt(ua, _("All Volumes from Pool")); /* 12 */
575 add_prompt(ua, _("All Volumes from all Pools")); /* 13 */
576 add_prompt(ua, _("Enabled")), /* 14 */
577 add_prompt(ua, _("RecyclePool")), /* 15 */
578 add_prompt(ua, _("Done")); /* 16 */
579 i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);
581 /* For All Volumes, All Volumes from Pool, and Done, we don't need
583 if ( i != 12 && i != 13 && i != 16) {
584 if (!select_media_dbr(ua, &mr)) { /* Get Volume record */
587 ua->info_msg(_("Updating Volume \"%s\"\n"), mr.VolumeName);
590 case 0: /* Volume Status */
591 /* Modify Volume Status */
592 ua->info_msg(_("Current Volume status is: %s\n"), mr.VolStatus);
593 start_prompt(ua, _("Possible Values are:\n"));
594 add_prompt(ua, NT_("Append"));
595 add_prompt(ua, NT_("Archive"));
596 add_prompt(ua, NT_("Disabled"));
597 add_prompt(ua, NT_("Full"));
598 add_prompt(ua, NT_("Used"));
599 add_prompt(ua, NT_("Cleaning"));
600 if (strcmp(mr.VolStatus, NT_("Purged")) == 0) {
601 add_prompt(ua, NT_("Recycle"));
603 add_prompt(ua, NT_("Read-Only"));
604 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
607 update_volstatus(ua, ua->cmd, &mr);
609 case 1: /* Retention */
610 ua->info_msg(_("Current retention period is: %s\n"),
611 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
612 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
615 update_volretention(ua, ua->cmd, &mr);
618 case 2: /* Use Duration */
619 ua->info_msg(_("Current use duration is: %s\n"),
620 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
621 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
624 update_voluseduration(ua, ua->cmd, &mr);
627 case 3: /* Max Jobs */
628 ua->info_msg(_("Current max jobs is: %u\n"), mr.MaxVolJobs);
629 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
632 update_volmaxjobs(ua, ua->cmd, &mr);
635 case 4: /* Max Files */
636 ua->info_msg(_("Current max files is: %u\n"), mr.MaxVolFiles);
637 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
640 update_volmaxfiles(ua, ua->cmd, &mr);
643 case 5: /* Max Bytes */
644 ua->info_msg(_("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
645 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
648 update_volmaxbytes(ua, ua->cmd, &mr);
652 case 6: /* Recycle */
653 ua->info_msg(_("Current recycle flag is: %s\n"),
654 mr.Recycle==1?_("yes"):_("no"));
655 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
658 update_volrecycle(ua, ua->cmd, &mr);
662 ua->info_msg(_("Current Slot is: %d\n"), mr.Slot);
663 if (!get_pint(ua, _("Enter new Slot: "))) {
666 update_volslot(ua, ua->cmd, &mr);
669 case 8: /* InChanger */
670 ua->info_msg(_("Current InChanger flag is: %d\n"), mr.InChanger);
671 bsnprintf(buf, sizeof(buf), _("Set InChanger flag for Volume \"%s\": yes/no: "),
673 if (!get_yesno(ua, buf)) {
676 mr.InChanger = ua->pint32_val;
678 * Make sure to use db_update... rather than doing this directly,
679 * so that any Slot is handled correctly.
681 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
682 ua->error_msg(_("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
684 ua->info_msg(_("New InChanger flag is: %d\n"), mr.InChanger);
689 case 9: /* Volume Files */
691 ua->warning_msg(_("Warning changing Volume Files can result\n"
692 "in loss of data on your Volume\n\n"));
693 ua->info_msg(_("Current Volume Files is: %u\n"), mr.VolFiles);
694 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
697 VolFiles = ua->pint32_val;
698 if (VolFiles != (int)(mr.VolFiles + 1)) {
699 ua->warning_msg(_("Normally, you should only increase Volume Files by one!\n"));
700 if (!get_yesno(ua, _("Increase Volume Files? (yes/no): ")) || ua->pint32_val == 0) {
704 query = get_pool_memory(PM_MESSAGE);
705 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
706 VolFiles, edit_int64(mr.MediaId, ed1));
707 if (!db_sql_query(ua->db, query, NULL, NULL)) {
708 ua->error_msg("%s", db_strerror(ua->db));
710 ua->info_msg(_("New Volume Files is: %u\n"), VolFiles);
712 free_pool_memory(query);
715 case 10: /* Volume's Pool */
716 memset(&pr, 0, sizeof(POOL_DBR));
717 pr.PoolId = mr.PoolId;
718 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
719 ua->error_msg("%s", db_strerror(ua->db));
722 ua->info_msg(_("Current Pool is: %s\n"), pr.Name);
723 if (!get_cmd(ua, _("Enter new Pool name: "))) {
726 update_vol_pool(ua, ua->cmd, &mr, &pr);
730 update_vol_from_pool(ua, &mr);
733 pool = select_pool_resource(ua);
735 update_all_vols_from_pool(ua, pool->name());
744 ua->info_msg(_("Current Enabled is: %d\n"), mr.Enabled);
745 if (!get_cmd(ua, _("Enter new Enabled: "))) {
748 if (strcasecmp(ua->cmd, "yes") == 0 || strcasecmp(ua->cmd, "true") == 0) {
750 } else if (strcasecmp(ua->cmd, "no") == 0 || strcasecmp(ua->cmd, "false") == 0) {
752 } else if (strcasecmp(ua->cmd, "archived") == 0) {
755 mr.Enabled = atoi(ua->cmd);
757 update_volenabled(ua, ua->cmd, &mr);
761 memset(&pr, 0, sizeof(POOL_DBR));
762 pr.PoolId = mr.RecyclePoolId;
763 if (db_get_pool_record(ua->jcr, ua->db, &pr)) {
764 ua->info_msg(_("Current RecyclePool is: %s\n"), pr.Name);
766 ua->warning_msg(_("No current RecyclePool\n"));
768 if (!get_cmd(ua, _("Enter new RecyclePool name: "))) {
771 update_vol_recyclepool(ua, ua->cmd, &mr);
774 default: /* Done or error */
775 ua->info_msg(_("Selection terminated.\n"));
783 * Update pool record -- pull info from current POOL resource
785 static bool update_pool(UAContext *ua)
793 pool = get_pool_resource(ua);
798 memset(&pr, 0, sizeof(pr));
799 bstrncpy(pr.Name, pool->name(), sizeof(pr.Name));
800 if (!get_pool_dbr(ua, &pr)) {
804 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
805 set_pooldbr_recyclepoolid(ua->jcr, ua->db, &pr, pool);
807 id = db_update_pool_record(ua->jcr, ua->db, &pr);
809 ua->error_msg(_("db_update_pool_record returned %d. ERR=%s\n"),
810 id, db_strerror(ua->db));
812 query = get_pool_memory(PM_MESSAGE);
813 Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
814 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
815 free_pool_memory(query);
816 ua->info_msg(_("Pool DB record updated from resource.\n"));
821 * Update a Job record -- allows you to change the
822 * date fields in a Job record. This helps when
823 * providing migration from other vendors.
825 static bool update_job(UAContext *ua)
828 char ed1[50], ed2[50];
829 POOL_MEM cmd(PM_MESSAGE);
833 char *client_name = NULL;
834 char *start_time = NULL;
836 NT_("starttime"), /* 0 */
837 NT_("client"), /* 1 */
840 Dmsg1(200, "cmd=%s\n", ua->cmd);
841 i = find_arg_with_value(ua, NT_("jobid"));
843 ua->error_msg(_("Expect JobId keyword, not found.\n"));
846 memset(&jr, 0, sizeof(jr));
847 memset(&cr, 0, sizeof(cr));
848 jr.JobId = str_to_int64(ua->argv[i]);
849 if (!db_get_job_record(ua->jcr, ua->db, &jr)) {
850 ua->error_msg("%s", db_strerror(ua->db));
854 for (i=0; kw[i]; i++) {
856 if ((j=find_arg_with_value(ua, kw[i])) >= 0) {
858 case 0: /* start time */
859 start_time = ua->argv[j];
861 case 1: /* Client name */
862 client_name = ua->argv[j];
867 if (!client_name && !start_time) {
868 ua->error_msg(_("Neither Client nor StartTime specified.\n"));
872 if (!get_client_dbr(ua, &cr)) {
875 jr.ClientId = cr.ClientId;
880 StartTime = str_to_utime(start_time);
881 if (StartTime == 0) {
882 ua->error_msg(_("Improper date format: %s\n"), ua->argv[i]);
885 delta_start = StartTime - jr.StartTime;
886 Dmsg3(200, "ST=%d jr.ST=%d delta=%d\n", (time_t)StartTime,
887 (time_t)jr.StartTime, (time_t)delta_start);
888 jr.StartTime = (time_t)StartTime;
889 jr.SchedTime += (time_t)delta_start;
890 jr.EndTime += (time_t)delta_start;
891 jr.JobTDate += delta_start;
892 /* Convert to DB times */
893 bstrutime(jr.cStartTime, sizeof(jr.cStartTime), jr.StartTime);
894 bstrutime(jr.cSchedTime, sizeof(jr.cSchedTime), jr.SchedTime);
895 bstrutime(jr.cEndTime, sizeof(jr.cEndTime), jr.EndTime);
897 Mmsg(cmd, "UPDATE Job SET ClientId=%s,StartTime='%s',SchedTime='%s',"
898 "EndTime='%s',JobTDate=%s WHERE JobId=%s",
899 edit_int64(jr.ClientId, ed1),
903 edit_uint64(jr.JobTDate, ed1),
904 edit_int64(jr.JobId, ed2));
905 if (!db_sql_query(ua->db, cmd.c_str(), NULL, NULL)) {
906 ua->error_msg("%s", db_strerror(ua->db));