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 bool 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 mr->Enabled = get_enabled(ua, val);
368 if (mr->Enabled < 0) {
371 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
372 bsendmsg(ua, _("Error updating media record Enabled: ERR=%s"), db_strerror(ua->db));
374 bsendmsg(ua, _("New Enabled is: %d\n"), mr->Enabled);
381 * Update a media record -- allows you to change the
382 * Volume status. E.g. if you want Bacula to stop
383 * writing on the volume, set it to anything other
386 static int update_volume(UAContext *ua)
395 _("VolStatus"), /* 0 */
396 _("VolRetention"), /* 1 */
398 _("MaxVolJobs"), /* 3 */
399 _("MaxVolFiles"), /* 4 */
400 _("MaxVolBytes"), /* 5 */
401 _("Recycle"), /* 6 */
402 _("InChanger"), /* 7 */
405 _("FromPool"), /* 10 */
406 _("AllFromPool"), /* 11 !!! see below !!! */
407 _("Enabled"), /* 12 */
410 #define AllFromPool 11 /* keep this updated with above */
412 for (i=0; kw[i]; i++) {
415 if ((j=find_arg_with_value(ua, kw[i])) > 0) {
416 /* If all from pool don't select a media record */
417 if (i != AllFromPool && !select_media_dbr(ua, &mr)) {
422 update_volstatus(ua, ua->argv[j], &mr);
425 update_volretention(ua, ua->argv[j], &mr);
428 update_voluseduration(ua, ua->argv[j], &mr);
431 update_volmaxjobs(ua, ua->argv[j], &mr);
434 update_volmaxfiles(ua, ua->argv[j], &mr);
437 update_volmaxbytes(ua, ua->argv[j], &mr);
440 update_volrecycle(ua, ua->argv[j], &mr);
443 update_volinchanger(ua, ua->argv[j], &mr);
446 update_volslot(ua, ua->argv[j], &mr);
449 memset(&pr, 0, sizeof(POOL_DBR));
450 pr.PoolId = mr.PoolId;
451 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
452 bsendmsg(ua, "%s", db_strerror(ua->db));
455 update_vol_pool(ua, ua->argv[j], &mr, &pr);
458 update_vol_from_pool(ua, &mr);
461 update_all_vols_from_pool(ua);
464 update_volenabled(ua, ua->argv[j], &mr);
472 start_prompt(ua, _("Parameters to modify:\n"));
473 add_prompt(ua, _("Volume Status")); /* 0 */
474 add_prompt(ua, _("Volume Retention Period")); /* 1 */
475 add_prompt(ua, _("Volume Use Duration")); /* 2 */
476 add_prompt(ua, _("Maximum Volume Jobs")); /* 3 */
477 add_prompt(ua, _("Maximum Volume Files")); /* 4 */
478 add_prompt(ua, _("Maximum Volume Bytes")); /* 5 */
479 add_prompt(ua, _("Recycle Flag")); /* 6 */
480 add_prompt(ua, _("Slot")); /* 7 */
481 add_prompt(ua, _("InChanger Flag")); /* 8 */
482 add_prompt(ua, _("Volume Files")); /* 9 */
483 add_prompt(ua, _("Pool")); /* 10 */
484 add_prompt(ua, _("Volume from Pool")); /* 11 */
485 add_prompt(ua, _("All Volumes from Pool")); /* 12 */
486 add_prompt(ua, _("Enabled")), /* 13 */
487 add_prompt(ua, _("Done")); /* 14 */
488 i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);
490 /* For All Volumes from Pool and Done, we don't need a Volume record */
491 if (i != 12 && i != 14) {
492 if (!select_media_dbr(ua, &mr)) { /* Get Volume record */
495 bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName);
498 case 0: /* Volume Status */
499 /* Modify Volume Status */
500 bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus);
501 start_prompt(ua, _("Possible Values are:\n"));
502 add_prompt(ua, NT_("Append"));
503 add_prompt(ua, NT_("Archive"));
504 add_prompt(ua, NT_("Disabled"));
505 add_prompt(ua, NT_("Full"));
506 add_prompt(ua, NT_("Used"));
507 add_prompt(ua, NT_("Cleaning"));
508 if (strcmp(mr.VolStatus, NT_("Purged")) == 0) {
509 add_prompt(ua, NT_("Recycle"));
511 add_prompt(ua, NT_("Read-Only"));
512 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
515 update_volstatus(ua, ua->cmd, &mr);
517 case 1: /* Retention */
518 bsendmsg(ua, _("Current retention period is: %s\n"),
519 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
520 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
523 update_volretention(ua, ua->cmd, &mr);
526 case 2: /* Use Duration */
527 bsendmsg(ua, _("Current use duration is: %s\n"),
528 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
529 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
532 update_voluseduration(ua, ua->cmd, &mr);
535 case 3: /* Max Jobs */
536 bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs);
537 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
540 update_volmaxjobs(ua, ua->cmd, &mr);
543 case 4: /* Max Files */
544 bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles);
545 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
548 update_volmaxfiles(ua, ua->cmd, &mr);
551 case 5: /* Max Bytes */
552 bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
553 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
556 update_volmaxbytes(ua, ua->cmd, &mr);
560 case 6: /* Recycle */
561 bsendmsg(ua, _("Current recycle flag is: %s\n"),
562 mr.Recycle==1?_("yes"):_("no"));
563 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
566 update_volrecycle(ua, ua->cmd, &mr);
570 bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot);
571 if (!get_pint(ua, _("Enter new Slot: "))) {
574 update_volslot(ua, ua->cmd, &mr);
577 case 8: /* InChanger */
578 bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger);
579 if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) {
582 mr.InChanger = ua->pint32_val;
584 * Make sure to use db_update... rather than doing this directly,
585 * so that any Slot is handled correctly.
587 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
588 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
590 bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger);
595 case 9: /* Volume Files */
597 bsendmsg(ua, _("Warning changing Volume Files can result\n"
598 "in loss of data on your Volume\n\n"));
599 bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles);
600 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
603 VolFiles = ua->pint32_val;
604 if (VolFiles != (int)(mr.VolFiles + 1)) {
605 bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n"));
606 if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) {
610 query = get_pool_memory(PM_MESSAGE);
611 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
612 VolFiles, edit_int64(mr.MediaId, ed1));
613 if (!db_sql_query(ua->db, query, NULL, NULL)) {
614 bsendmsg(ua, "%s", db_strerror(ua->db));
616 bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles);
618 free_pool_memory(query);
621 case 10: /* Volume's Pool */
622 memset(&pr, 0, sizeof(POOL_DBR));
623 pr.PoolId = mr.PoolId;
624 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
625 bsendmsg(ua, "%s", db_strerror(ua->db));
628 bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name);
629 if (!get_cmd(ua, _("Enter new Pool name: "))) {
632 update_vol_pool(ua, ua->cmd, &mr, &pr);
636 update_vol_from_pool(ua, &mr);
639 update_all_vols_from_pool(ua);
643 bsendmsg(ua, _("Current Enabled is: %d\n"), mr.Enabled);
644 if (!get_cmd(ua, _("Enter new Enabled: "))) {
647 if (strcasecmp(ua->cmd, "yes") == 0 || strcasecmp(ua->cmd, "true") == 0) {
649 } else if (strcasecmp(ua->cmd, "no") == 0 || strcasecmp(ua->cmd, "false") == 0) {
651 } else if (strcasecmp(ua->cmd, "archived") == 0) {
654 mr.Enabled = atoi(ua->cmd);
656 update_volenabled(ua, ua->cmd, &mr);
659 default: /* Done or error */
660 bsendmsg(ua, _("Selection terminated.\n"));
668 * Update pool record -- pull info from current POOL resource
670 static bool update_pool(UAContext *ua)
678 pool = get_pool_resource(ua);
683 memset(&pr, 0, sizeof(pr));
684 bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name));
685 if (!get_pool_dbr(ua, &pr)) {
689 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
691 id = db_update_pool_record(ua->jcr, ua->db, &pr);
693 bsendmsg(ua, _("db_update_pool_record returned %d. ERR=%s\n"),
694 id, db_strerror(ua->db));
696 query = get_pool_memory(PM_MESSAGE);
697 Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
698 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
699 free_pool_memory(query);
700 bsendmsg(ua, _("Pool DB record updated from resource.\n"));