3 * Bacula Director -- Update command processing
4 * Split from ua_cmds.c March 2005
6 * Kern Sibbald, September MM
11 Copyright (C) 2000-2006 Kern Sibbald
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License
15 version 2 as amended with additional clauses defined in the
16 file LICENSE in the main source directory.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 the file LICENSE for additional details.
28 /* Imported functions */
29 void update_slots(UAContext *ua);
33 /* Forward referenced functions */
34 static int update_volume(UAContext *ua);
35 static int update_pool(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
48 int update_cmd(UAContext *ua, const char *cmd)
50 static const char *kw[] = {
52 NT_("volume"), /* 1 */
61 switch (find_arg_keyword(ua, kw)) {
76 start_prompt(ua, _("Update choice:\n"));
77 add_prompt(ua, _("Volume parameters"));
78 add_prompt(ua, _("Pool from resource"));
79 add_prompt(ua, _("Slots from autochanger"));
80 switch (do_prompt(ua, _("item"), _("Choose catalog item to update"), NULL, 0)) {
96 static void update_volstatus(UAContext *ua, const char *val, MEDIA_DBR *mr)
98 POOL_MEM query(PM_MESSAGE);
112 for (i=0; kw[i]; i++) {
113 if (strcasecmp(val, kw[i]) == 0) {
119 bsendmsg(ua, _("Invalid VolStatus specified: %s\n"), val);
122 bstrncpy(mr->VolStatus, kw[i], sizeof(mr->VolStatus));
123 Mmsg(query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%s",
124 mr->VolStatus, edit_int64(mr->MediaId,ed1));
125 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
126 bsendmsg(ua, "%s", db_strerror(ua->db));
128 bsendmsg(ua, _("New Volume status is: %s\n"), mr->VolStatus);
133 static void update_volretention(UAContext *ua, char *val, MEDIA_DBR *mr)
135 char ed1[150], ed2[50];
136 POOL_MEM query(PM_MESSAGE);
137 if (!duration_to_utime(val, &mr->VolRetention)) {
138 bsendmsg(ua, _("Invalid retention period specified: %s\n"), val);
141 Mmsg(query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%s",
142 edit_uint64(mr->VolRetention, ed1), edit_int64(mr->MediaId,ed2));
143 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
144 bsendmsg(ua, "%s", db_strerror(ua->db));
146 bsendmsg(ua, _("New retention period is: %s\n"),
147 edit_utime(mr->VolRetention, ed1, sizeof(ed1)));
151 static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr)
153 char ed1[150], ed2[50];
154 POOL_MEM query(PM_MESSAGE);
156 if (!duration_to_utime(val, &mr->VolUseDuration)) {
157 bsendmsg(ua, _("Invalid use duration specified: %s\n"), val);
160 Mmsg(query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%s",
161 edit_uint64(mr->VolUseDuration, ed1), edit_int64(mr->MediaId,ed2));
162 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
163 bsendmsg(ua, "%s", db_strerror(ua->db));
165 bsendmsg(ua, _("New use duration is: %s\n"),
166 edit_utime(mr->VolUseDuration, ed1, sizeof(ed1)));
170 static void update_volmaxjobs(UAContext *ua, char *val, MEDIA_DBR *mr)
172 POOL_MEM query(PM_MESSAGE);
174 Mmsg(query, "UPDATE Media SET MaxVolJobs=%s WHERE MediaId=%s",
175 val, edit_int64(mr->MediaId,ed1));
176 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
177 bsendmsg(ua, "%s", db_strerror(ua->db));
179 bsendmsg(ua, _("New max jobs is: %s\n"), val);
183 static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr)
185 POOL_MEM query(PM_MESSAGE);
187 Mmsg(query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%s",
188 val, edit_int64(mr->MediaId, ed1));
189 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
190 bsendmsg(ua, "%s", db_strerror(ua->db));
192 bsendmsg(ua, _("New max files is: %s\n"), val);
196 static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr)
199 char ed1[50], ed2[50];
200 POOL_MEM query(PM_MESSAGE);
202 if (!size_to_uint64(val, strlen(val), &maxbytes)) {
203 bsendmsg(ua, _("Invalid max. bytes specification: %s\n"), val);
206 Mmsg(query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%s",
207 edit_uint64(maxbytes, ed1), edit_int64(mr->MediaId, ed2));
208 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
209 bsendmsg(ua, "%s", db_strerror(ua->db));
211 bsendmsg(ua, _("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1));
215 static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr)
220 POOL_MEM query(PM_MESSAGE);
221 if (!is_yesno(val, &recycle)) {
222 bsendmsg(ua, _("Invalid value. It must be yes or no.\n"));
225 Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%s",
226 recycle, edit_int64(mr->MediaId, ed1));
227 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
228 bsendmsg(ua, "%s", db_strerror(ua->db));
230 bsendmsg(ua, _("New Recycle flag is: %s\n"),
231 mr->Recycle==1?_("yes"):_("no"));
235 static void update_volinchanger(UAContext *ua, char *val, MEDIA_DBR *mr)
240 POOL_MEM query(PM_MESSAGE);
241 if (!is_yesno(val, &InChanger)) {
242 bsendmsg(ua, _("Invalid value. It must be yes or no.\n"));
245 Mmsg(query, "UPDATE Media SET InChanger=%d WHERE MediaId=%s",
246 InChanger, edit_int64(mr->MediaId, ed1));
247 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
248 bsendmsg(ua, "%s", db_strerror(ua->db));
250 bsendmsg(ua, _("New InChanger flag is: %s\n"),
251 mr->InChanger==1?_("yes"):_("no"));
256 static void update_volslot(UAContext *ua, char *val, MEDIA_DBR *mr)
260 memset(&pr, 0, sizeof(POOL_DBR));
261 pr.PoolId = mr->PoolId;
262 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
263 bsendmsg(ua, "%s", db_strerror(ua->db));
266 mr->Slot = atoi(val);
267 if (pr.MaxVols > 0 && mr->Slot > (int)pr.MaxVols) {
268 bsendmsg(ua, _("Invalid slot, it must be between 0 and MaxVols=%d\n"),
273 * Make sure to use db_update... rather than doing this directly,
274 * so that any Slot is handled correctly.
276 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
277 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
279 bsendmsg(ua, _("New Slot is: %d\n"), mr->Slot);
283 /* Modify the Pool in which this Volume is located */
284 static void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr)
288 char ed1[50], ed2[50];
290 memset(&pr, 0, sizeof(pr));
291 bstrncpy(pr.Name, val, sizeof(pr.Name));
292 if (!get_pool_dbr(ua, &pr)) {
295 mr->PoolId = pr.PoolId; /* set new PoolId */
298 query = get_pool_memory(PM_MESSAGE);
300 Mmsg(query, "UPDATE Media SET PoolId=%s WHERE MediaId=%s",
301 edit_int64(mr->PoolId, ed1),
302 edit_int64(mr->MediaId, ed2));
303 if (!db_sql_query(ua->db, query, NULL, NULL)) {
304 bsendmsg(ua, "%s", db_strerror(ua->db));
306 bsendmsg(ua, _("New Pool is: %s\n"), pr.Name);
308 if (!db_update_pool_record(ua->jcr, ua->db, opr)) {
309 bsendmsg(ua, "%s", db_strerror(ua->db));
312 if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
313 bsendmsg(ua, "%s", db_strerror(ua->db));
317 free_pool_memory(query);
321 * Refresh the Volume information from the Pool record
323 static void update_vol_from_pool(UAContext *ua, MEDIA_DBR *mr)
327 memset(&pr, 0, sizeof(pr));
328 pr.PoolId = mr->PoolId;
329 if (!db_get_pool_record(ua->jcr, ua->db, &pr) ||
330 !acl_access_ok(ua, Pool_ACL, pr.Name)) {
333 set_pool_dbr_defaults_in_media_dbr(mr, &pr);
334 if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
335 bsendmsg(ua, _("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
337 bsendmsg(ua, _("Volume defaults updated from \"%s\" Pool record.\n"),
343 * Refresh the Volume information from the Pool record
346 static void update_all_vols_from_pool(UAContext *ua)
351 memset(&pr, 0, sizeof(pr));
352 memset(&mr, 0, sizeof(mr));
353 if (!get_pool_dbr(ua, &pr)) {
356 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
357 mr.PoolId = pr.PoolId;
358 if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
359 bsendmsg(ua, _("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
361 bsendmsg(ua, _("All Volume defaults updated from Pool record.\n"));
365 static void update_volenabled(UAContext *ua, char *val, MEDIA_DBR *mr)
367 if (strcasecmp(val, "yes") == 0 || strcasecmp(val, "true") == 0) {
369 } else if (strcasecmp(val, "no") == 0 || strcasecmp(val, "false") == 0) {
371 } else if (strcasecmp(val, "archived") == 0) {
374 mr->Enabled = atoi(val);
376 if (mr->Enabled < 0 || mr->Enabled > 2) {
377 bsendmsg(ua, _("Invalid Enabled, it must be 0, 1, or 2\n"));
380 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
381 bsendmsg(ua, _("Error updating media record Enabled: ERR=%s"), db_strerror(ua->db));
383 bsendmsg(ua, _("New Enabled is: %d\n"), mr->Enabled);
390 * Update a media record -- allows you to change the
391 * Volume status. E.g. if you want Bacula to stop
392 * writing on the volume, set it to anything other
395 static int update_volume(UAContext *ua)
404 _("VolStatus"), /* 0 */
405 _("VolRetention"), /* 1 */
407 _("MaxVolJobs"), /* 3 */
408 _("MaxVolFiles"), /* 4 */
409 _("MaxVolBytes"), /* 5 */
410 _("Recycle"), /* 6 */
411 _("InChanger"), /* 7 */
414 _("FromPool"), /* 10 */
415 _("AllFromPool"), /* 11 !!! see below !!! */
416 _("Enabled"), /* 12 */
419 #define AllFromPool 11 /* keep this updated with above */
421 for (i=0; kw[i]; i++) {
424 if ((j=find_arg_with_value(ua, kw[i])) > 0) {
425 /* If all from pool don't select a media record */
426 if (i != AllFromPool && !select_media_dbr(ua, &mr)) {
431 update_volstatus(ua, ua->argv[j], &mr);
434 update_volretention(ua, ua->argv[j], &mr);
437 update_voluseduration(ua, ua->argv[j], &mr);
440 update_volmaxjobs(ua, ua->argv[j], &mr);
443 update_volmaxfiles(ua, ua->argv[j], &mr);
446 update_volmaxbytes(ua, ua->argv[j], &mr);
449 update_volrecycle(ua, ua->argv[j], &mr);
452 update_volinchanger(ua, ua->argv[j], &mr);
455 update_volslot(ua, ua->argv[j], &mr);
458 memset(&pr, 0, sizeof(POOL_DBR));
459 pr.PoolId = mr.PoolId;
460 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
461 bsendmsg(ua, "%s", db_strerror(ua->db));
464 update_vol_pool(ua, ua->argv[j], &mr, &pr);
467 update_vol_from_pool(ua, &mr);
470 update_all_vols_from_pool(ua);
473 update_volenabled(ua, ua->argv[j], &mr);
481 start_prompt(ua, _("Parameters to modify:\n"));
482 add_prompt(ua, _("Volume Status")); /* 0 */
483 add_prompt(ua, _("Volume Retention Period")); /* 1 */
484 add_prompt(ua, _("Volume Use Duration")); /* 2 */
485 add_prompt(ua, _("Maximum Volume Jobs")); /* 3 */
486 add_prompt(ua, _("Maximum Volume Files")); /* 4 */
487 add_prompt(ua, _("Maximum Volume Bytes")); /* 5 */
488 add_prompt(ua, _("Recycle Flag")); /* 6 */
489 add_prompt(ua, _("Slot")); /* 7 */
490 add_prompt(ua, _("InChanger Flag")); /* 8 */
491 add_prompt(ua, _("Volume Files")); /* 9 */
492 add_prompt(ua, _("Pool")); /* 10 */
493 add_prompt(ua, _("Volume from Pool")); /* 11 */
494 add_prompt(ua, _("All Volumes from Pool")); /* 12 */
495 add_prompt(ua, _("Enabled")), /* 13 */
496 add_prompt(ua, _("Done")); /* 14 */
497 i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);
499 /* For All Volumes from Pool and Done, we don't need a Volume record */
500 if (i != 12 && i != 14) {
501 if (!select_media_dbr(ua, &mr)) { /* Get Volume record */
504 bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName);
507 case 0: /* Volume Status */
508 /* Modify Volume Status */
509 bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus);
510 start_prompt(ua, _("Possible Values are:\n"));
511 add_prompt(ua, NT_("Append"));
512 add_prompt(ua, NT_("Archive"));
513 add_prompt(ua, NT_("Disabled"));
514 add_prompt(ua, NT_("Full"));
515 add_prompt(ua, NT_("Used"));
516 add_prompt(ua, NT_("Cleaning"));
517 if (strcmp(mr.VolStatus, NT_("Purged")) == 0) {
518 add_prompt(ua, NT_("Recycle"));
520 add_prompt(ua, NT_("Read-Only"));
521 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
524 update_volstatus(ua, ua->cmd, &mr);
526 case 1: /* Retention */
527 bsendmsg(ua, _("Current retention period is: %s\n"),
528 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
529 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
532 update_volretention(ua, ua->cmd, &mr);
535 case 2: /* Use Duration */
536 bsendmsg(ua, _("Current use duration is: %s\n"),
537 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
538 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
541 update_voluseduration(ua, ua->cmd, &mr);
544 case 3: /* Max Jobs */
545 bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs);
546 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
549 update_volmaxjobs(ua, ua->cmd, &mr);
552 case 4: /* Max Files */
553 bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles);
554 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
557 update_volmaxfiles(ua, ua->cmd, &mr);
560 case 5: /* Max Bytes */
561 bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
562 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
565 update_volmaxbytes(ua, ua->cmd, &mr);
569 case 6: /* Recycle */
570 bsendmsg(ua, _("Current recycle flag is: %s\n"),
571 mr.Recycle==1?_("yes"):_("no"));
572 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
575 update_volrecycle(ua, ua->cmd, &mr);
579 bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot);
580 if (!get_pint(ua, _("Enter new Slot: "))) {
583 update_volslot(ua, ua->cmd, &mr);
586 case 8: /* InChanger */
587 bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger);
588 if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) {
591 mr.InChanger = ua->pint32_val;
593 * Make sure to use db_update... rather than doing this directly,
594 * so that any Slot is handled correctly.
596 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
597 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
599 bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger);
604 case 9: /* Volume Files */
606 bsendmsg(ua, _("Warning changing Volume Files can result\n"
607 "in loss of data on your Volume\n\n"));
608 bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles);
609 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
612 VolFiles = ua->pint32_val;
613 if (VolFiles != (int)(mr.VolFiles + 1)) {
614 bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n"));
615 if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) {
619 query = get_pool_memory(PM_MESSAGE);
620 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
621 VolFiles, edit_int64(mr.MediaId, ed1));
622 if (!db_sql_query(ua->db, query, NULL, NULL)) {
623 bsendmsg(ua, "%s", db_strerror(ua->db));
625 bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles);
627 free_pool_memory(query);
630 case 10: /* Volume's Pool */
631 memset(&pr, 0, sizeof(POOL_DBR));
632 pr.PoolId = mr.PoolId;
633 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
634 bsendmsg(ua, "%s", db_strerror(ua->db));
637 bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name);
638 if (!get_cmd(ua, _("Enter new Pool name: "))) {
641 update_vol_pool(ua, ua->cmd, &mr, &pr);
645 update_vol_from_pool(ua, &mr);
648 update_all_vols_from_pool(ua);
652 bsendmsg(ua, _("Current Enabled is: %d\n"), mr.Enabled);
653 if (!get_cmd(ua, _("Enter new Enabled: "))) {
656 if (strcasecmp(ua->cmd, "yes") == 0 || strcasecmp(ua->cmd, "true") == 0) {
658 } else if (strcasecmp(ua->cmd, "no") == 0 || strcasecmp(ua->cmd, "false") == 0) {
660 } else if (strcasecmp(ua->cmd, "archived") == 0) {
663 mr.Enabled = atoi(ua->cmd);
665 update_volenabled(ua, ua->cmd, &mr);
668 default: /* Done or error */
669 bsendmsg(ua, _("Selection terminated.\n"));
677 * Update pool record -- pull info from current POOL resource
679 static int update_pool(UAContext *ua)
687 pool = get_pool_resource(ua);
692 memset(&pr, 0, sizeof(pr));
693 bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name));
694 if (!get_pool_dbr(ua, &pr)) {
698 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
700 id = db_update_pool_record(ua->jcr, ua->db, &pr);
702 bsendmsg(ua, _("db_update_pool_record returned %d. ERR=%s\n"),
703 id, db_strerror(ua->db));
705 query = get_pool_memory(PM_MESSAGE);
706 Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
707 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
708 free_pool_memory(query);
709 bsendmsg(ua, _("Pool DB record updated from resource.\n"));