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 /* External variables */
29 extern const char *list_pool; /* in sql_cmds.c */
31 /* Imported functions */
32 void update_slots(UAContext *ua);
36 /* Forward referenced functions */
37 static int update_volume(UAContext *ua);
38 static int update_pool(UAContext *ua);
41 * Update a Pool Record in the database.
42 * It is always updated from the Resource record.
44 * update pool=<pool-name>
45 * updates pool from Pool resource
46 * update media pool=<pool-name> volume=<volume-name>
47 * changes pool info for volume
48 * update slots [scan=...]
49 * updates autochanger slots
51 int update_cmd(UAContext *ua, const char *cmd)
53 static const char *kw[] = {
55 NT_("volume"), /* 1 */
64 switch (find_arg_keyword(ua, kw)) {
79 start_prompt(ua, _("Update choice:\n"));
80 add_prompt(ua, _("Volume parameters"));
81 add_prompt(ua, _("Pool from resource"));
82 add_prompt(ua, _("Slots from autochanger"));
83 switch (do_prompt(ua, _("item"), _("Choose catalog item to update"), NULL, 0)) {
99 static void update_volstatus(UAContext *ua, const char *val, MEDIA_DBR *mr)
101 POOL_MEM query(PM_MESSAGE);
115 for (i=0; kw[i]; i++) {
116 if (strcasecmp(val, kw[i]) == 0) {
122 bsendmsg(ua, _("Invalid VolStatus specified: %s\n"), val);
125 bstrncpy(mr->VolStatus, kw[i], sizeof(mr->VolStatus));
126 Mmsg(query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%s",
127 mr->VolStatus, edit_int64(mr->MediaId,ed1));
128 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
129 bsendmsg(ua, "%s", db_strerror(ua->db));
131 bsendmsg(ua, _("New Volume status is: %s\n"), mr->VolStatus);
136 static void update_volretention(UAContext *ua, char *val, MEDIA_DBR *mr)
138 char ed1[150], ed2[50];
139 POOL_MEM query(PM_MESSAGE);
140 if (!duration_to_utime(val, &mr->VolRetention)) {
141 bsendmsg(ua, _("Invalid retention period specified: %s\n"), val);
144 Mmsg(query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%s",
145 edit_uint64(mr->VolRetention, ed1), edit_int64(mr->MediaId,ed2));
146 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
147 bsendmsg(ua, "%s", db_strerror(ua->db));
149 bsendmsg(ua, _("New retention period is: %s\n"),
150 edit_utime(mr->VolRetention, ed1, sizeof(ed1)));
154 static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr)
156 char ed1[150], ed2[50];
157 POOL_MEM query(PM_MESSAGE);
159 if (!duration_to_utime(val, &mr->VolUseDuration)) {
160 bsendmsg(ua, _("Invalid use duration specified: %s\n"), val);
163 Mmsg(query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%s",
164 edit_uint64(mr->VolUseDuration, ed1), edit_int64(mr->MediaId,ed2));
165 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
166 bsendmsg(ua, "%s", db_strerror(ua->db));
168 bsendmsg(ua, _("New use duration is: %s\n"),
169 edit_utime(mr->VolUseDuration, ed1, sizeof(ed1)));
173 static void update_volmaxjobs(UAContext *ua, char *val, MEDIA_DBR *mr)
175 POOL_MEM query(PM_MESSAGE);
177 Mmsg(query, "UPDATE Media SET MaxVolJobs=%s WHERE MediaId=%s",
178 val, edit_int64(mr->MediaId,ed1));
179 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
180 bsendmsg(ua, "%s", db_strerror(ua->db));
182 bsendmsg(ua, _("New max jobs is: %s\n"), val);
186 static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr)
188 POOL_MEM query(PM_MESSAGE);
190 Mmsg(query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%s",
191 val, edit_int64(mr->MediaId, ed1));
192 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
193 bsendmsg(ua, "%s", db_strerror(ua->db));
195 bsendmsg(ua, _("New max files is: %s\n"), val);
199 static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr)
202 char ed1[50], ed2[50];
203 POOL_MEM query(PM_MESSAGE);
205 if (!size_to_uint64(val, strlen(val), &maxbytes)) {
206 bsendmsg(ua, _("Invalid max. bytes specification: %s\n"), val);
209 Mmsg(query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%s",
210 edit_uint64(maxbytes, ed1), edit_int64(mr->MediaId, ed2));
211 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
212 bsendmsg(ua, "%s", db_strerror(ua->db));
214 bsendmsg(ua, _("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1));
218 static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr)
223 POOL_MEM query(PM_MESSAGE);
224 if (!is_yesno(val, &recycle)) {
225 bsendmsg(ua, _("Invalid value. It must be yes or no.\n"));
228 Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%s",
229 recycle, edit_int64(mr->MediaId, ed1));
230 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
231 bsendmsg(ua, "%s", db_strerror(ua->db));
233 bsendmsg(ua, _("New Recycle flag is: %s\n"),
234 mr->Recycle==1?_("yes"):_("no"));
238 static void update_volinchanger(UAContext *ua, char *val, MEDIA_DBR *mr)
243 POOL_MEM query(PM_MESSAGE);
244 if (!is_yesno(val, &InChanger)) {
245 bsendmsg(ua, _("Invalid value. It must be yes or no.\n"));
248 Mmsg(query, "UPDATE Media SET InChanger=%d WHERE MediaId=%s",
249 InChanger, edit_int64(mr->MediaId, ed1));
250 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
251 bsendmsg(ua, "%s", db_strerror(ua->db));
253 bsendmsg(ua, _("New InChanger flag is: %s\n"),
254 mr->InChanger==1?_("yes"):_("no"));
259 static void update_volslot(UAContext *ua, char *val, MEDIA_DBR *mr)
263 memset(&pr, 0, sizeof(POOL_DBR));
264 pr.PoolId = mr->PoolId;
265 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
266 bsendmsg(ua, "%s", db_strerror(ua->db));
269 mr->Slot = atoi(val);
270 if (pr.MaxVols > 0 && mr->Slot > (int)pr.MaxVols) {
271 bsendmsg(ua, _("Invalid slot, it must be between 0 and MaxVols=%d\n"),
276 * Make sure to use db_update... rather than doing this directly,
277 * so that any Slot is handled correctly.
279 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
280 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
282 bsendmsg(ua, _("New Slot is: %d\n"), mr->Slot);
286 /* Modify the Pool in which this Volume is located */
287 static void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr)
291 char ed1[50], ed2[50];
293 memset(&pr, 0, sizeof(pr));
294 bstrncpy(pr.Name, val, sizeof(pr.Name));
295 if (!get_pool_dbr(ua, &pr)) {
298 mr->PoolId = pr.PoolId; /* set new PoolId */
301 query = get_pool_memory(PM_MESSAGE);
303 Mmsg(query, "UPDATE Media SET PoolId=%s WHERE MediaId=%s",
304 edit_int64(mr->PoolId, ed1),
305 edit_int64(mr->MediaId, ed2));
306 if (!db_sql_query(ua->db, query, NULL, NULL)) {
307 bsendmsg(ua, "%s", db_strerror(ua->db));
309 bsendmsg(ua, _("New Pool is: %s\n"), pr.Name);
311 if (!db_update_pool_record(ua->jcr, ua->db, opr)) {
312 bsendmsg(ua, "%s", db_strerror(ua->db));
315 if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
316 bsendmsg(ua, "%s", db_strerror(ua->db));
320 free_pool_memory(query);
324 * Refresh the Volume information from the Pool record
326 static void update_vol_from_pool(UAContext *ua, MEDIA_DBR *mr)
330 memset(&pr, 0, sizeof(pr));
331 pr.PoolId = mr->PoolId;
332 if (!db_get_pool_record(ua->jcr, ua->db, &pr) ||
333 !acl_access_ok(ua, Pool_ACL, pr.Name)) {
336 set_pool_dbr_defaults_in_media_dbr(mr, &pr);
337 if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
338 bsendmsg(ua, _("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
340 bsendmsg(ua, _("Volume defaults updated from \"%s\" Pool record.\n"),
346 * Refresh the Volume information from the Pool record
349 static void update_all_vols_from_pool(UAContext *ua)
354 memset(&pr, 0, sizeof(pr));
355 memset(&mr, 0, sizeof(mr));
356 if (!get_pool_dbr(ua, &pr)) {
359 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
360 mr.PoolId = pr.PoolId;
361 if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
362 bsendmsg(ua, _("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
364 bsendmsg(ua, _("All Volume defaults updated from Pool record.\n"));
368 static void update_volenabled(UAContext *ua, char *val, MEDIA_DBR *mr)
370 if (strcasecmp(val, "yes") == 0 || strcasecmp(val, "true") == 0) {
372 } else if (strcasecmp(val, "no") == 0 || strcasecmp(val, "false") == 0) {
374 } else if (strcasecmp(val, "archived") == 0) {
377 mr->Enabled = atoi(val);
379 if (mr->Enabled < 0 || mr->Enabled > 2) {
380 bsendmsg(ua, _("Invalid Enabled, it must be 0, 1, or 2\n"));
383 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
384 bsendmsg(ua, _("Error updating media record Enabled: ERR=%s"), db_strerror(ua->db));
386 bsendmsg(ua, _("New Enabled is: %d\n"), mr->Enabled);
393 * Update a media record -- allows you to change the
394 * Volume status. E.g. if you want Bacula to stop
395 * writing on the volume, set it to anything other
398 static int update_volume(UAContext *ua)
407 _("VolStatus"), /* 0 */
408 _("VolRetention"), /* 1 */
410 _("MaxVolJobs"), /* 3 */
411 _("MaxVolFiles"), /* 4 */
412 _("MaxVolBytes"), /* 5 */
413 _("Recycle"), /* 6 */
414 _("InChanger"), /* 7 */
417 _("FromPool"), /* 10 */
418 _("AllFromPool"), /* 11 !!! see below !!! */
419 _("Enabled"), /* 12 */
422 #define AllFromPool 11 /* keep this updated with above */
424 for (i=0; kw[i]; i++) {
427 if ((j=find_arg_with_value(ua, kw[i])) > 0) {
428 /* If all from pool don't select a media record */
429 if (i != AllFromPool && !select_media_dbr(ua, &mr)) {
434 update_volstatus(ua, ua->argv[j], &mr);
437 update_volretention(ua, ua->argv[j], &mr);
440 update_voluseduration(ua, ua->argv[j], &mr);
443 update_volmaxjobs(ua, ua->argv[j], &mr);
446 update_volmaxfiles(ua, ua->argv[j], &mr);
449 update_volmaxbytes(ua, ua->argv[j], &mr);
452 update_volrecycle(ua, ua->argv[j], &mr);
455 update_volinchanger(ua, ua->argv[j], &mr);
458 update_volslot(ua, ua->argv[j], &mr);
461 memset(&pr, 0, sizeof(POOL_DBR));
462 pr.PoolId = mr.PoolId;
463 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
464 bsendmsg(ua, "%s", db_strerror(ua->db));
467 update_vol_pool(ua, ua->argv[j], &mr, &pr);
470 update_vol_from_pool(ua, &mr);
473 update_all_vols_from_pool(ua);
476 update_volenabled(ua, ua->argv[j], &mr);
484 start_prompt(ua, _("Parameters to modify:\n"));
485 add_prompt(ua, _("Volume Status")); /* 0 */
486 add_prompt(ua, _("Volume Retention Period")); /* 1 */
487 add_prompt(ua, _("Volume Use Duration")); /* 2 */
488 add_prompt(ua, _("Maximum Volume Jobs")); /* 3 */
489 add_prompt(ua, _("Maximum Volume Files")); /* 4 */
490 add_prompt(ua, _("Maximum Volume Bytes")); /* 5 */
491 add_prompt(ua, _("Recycle Flag")); /* 6 */
492 add_prompt(ua, _("Slot")); /* 7 */
493 add_prompt(ua, _("InChanger Flag")); /* 8 */
494 add_prompt(ua, _("Volume Files")); /* 9 */
495 add_prompt(ua, _("Pool")); /* 10 */
496 add_prompt(ua, _("Volume from Pool")); /* 11 */
497 add_prompt(ua, _("All Volumes from Pool")); /* 12 */
498 add_prompt(ua, _("Enabled")), /* 13 */
499 add_prompt(ua, _("Done")); /* 14 */
500 i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);
502 /* For All Volumes from Pool and Done, we don't need a Volume record */
503 if (i != 12 && i != 14) {
504 if (!select_media_dbr(ua, &mr)) { /* Get Volume record */
507 bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName);
510 case 0: /* Volume Status */
511 /* Modify Volume Status */
512 bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus);
513 start_prompt(ua, _("Possible Values are:\n"));
514 add_prompt(ua, NT_("Append"));
515 add_prompt(ua, NT_("Archive"));
516 add_prompt(ua, NT_("Disabled"));
517 add_prompt(ua, NT_("Full"));
518 add_prompt(ua, NT_("Used"));
519 add_prompt(ua, NT_("Cleaning"));
520 if (strcmp(mr.VolStatus, NT_("Purged")) == 0) {
521 add_prompt(ua, NT_("Recycle"));
523 add_prompt(ua, NT_("Read-Only"));
524 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
527 update_volstatus(ua, ua->cmd, &mr);
529 case 1: /* Retention */
530 bsendmsg(ua, _("Current retention period is: %s\n"),
531 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
532 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
535 update_volretention(ua, ua->cmd, &mr);
538 case 2: /* Use Duration */
539 bsendmsg(ua, _("Current use duration is: %s\n"),
540 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
541 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
544 update_voluseduration(ua, ua->cmd, &mr);
547 case 3: /* Max Jobs */
548 bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs);
549 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
552 update_volmaxjobs(ua, ua->cmd, &mr);
555 case 4: /* Max Files */
556 bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles);
557 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
560 update_volmaxfiles(ua, ua->cmd, &mr);
563 case 5: /* Max Bytes */
564 bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
565 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
568 update_volmaxbytes(ua, ua->cmd, &mr);
572 case 6: /* Recycle */
573 bsendmsg(ua, _("Current recycle flag is: %s\n"),
574 mr.Recycle==1?_("yes"):_("no"));
575 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
578 update_volrecycle(ua, ua->cmd, &mr);
582 bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot);
583 if (!get_pint(ua, _("Enter new Slot: "))) {
586 update_volslot(ua, ua->cmd, &mr);
589 case 8: /* InChanger */
590 bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger);
591 if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) {
594 mr.InChanger = ua->pint32_val;
596 * Make sure to use db_update... rather than doing this directly,
597 * so that any Slot is handled correctly.
599 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
600 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
602 bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger);
607 case 9: /* Volume Files */
609 bsendmsg(ua, _("Warning changing Volume Files can result\n"
610 "in loss of data on your Volume\n\n"));
611 bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles);
612 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
615 VolFiles = ua->pint32_val;
616 if (VolFiles != (int)(mr.VolFiles + 1)) {
617 bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n"));
618 if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) {
622 query = get_pool_memory(PM_MESSAGE);
623 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
624 VolFiles, edit_int64(mr.MediaId, ed1));
625 if (!db_sql_query(ua->db, query, NULL, NULL)) {
626 bsendmsg(ua, "%s", db_strerror(ua->db));
628 bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles);
630 free_pool_memory(query);
633 case 10: /* Volume's Pool */
634 memset(&pr, 0, sizeof(POOL_DBR));
635 pr.PoolId = mr.PoolId;
636 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
637 bsendmsg(ua, "%s", db_strerror(ua->db));
640 bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name);
641 if (!get_cmd(ua, _("Enter new Pool name: "))) {
644 update_vol_pool(ua, ua->cmd, &mr, &pr);
648 update_vol_from_pool(ua, &mr);
651 update_all_vols_from_pool(ua);
655 bsendmsg(ua, _("Current Enabled is: %d\n"), mr.Enabled);
656 if (!get_cmd(ua, _("Enter new Enabled: "))) {
659 if (strcasecmp(ua->cmd, "yes") == 0 || strcasecmp(ua->cmd, "true") == 0) {
661 } else if (strcasecmp(ua->cmd, "no") == 0 || strcasecmp(ua->cmd, "false") == 0) {
663 } else if (strcasecmp(ua->cmd, "archived") == 0) {
666 mr.Enabled = atoi(ua->cmd);
668 update_volenabled(ua, ua->cmd, &mr);
671 default: /* Done or error */
672 bsendmsg(ua, _("Selection terminated.\n"));
680 * Update pool record -- pull info from current POOL resource
682 static int update_pool(UAContext *ua)
690 pool = get_pool_resource(ua);
695 memset(&pr, 0, sizeof(pr));
696 bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name));
697 if (!get_pool_dbr(ua, &pr)) {
701 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
703 id = db_update_pool_record(ua->jcr, ua->db, &pr);
705 bsendmsg(ua, _("db_update_pool_record returned %d. ERR=%s\n"),
706 id, db_strerror(ua->db));
708 query = get_pool_memory(PM_MESSAGE);
709 Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
710 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
711 free_pool_memory(query);
712 bsendmsg(ua, _("Pool DB record updated from resource.\n"));