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)
222 POOL_MEM query(PM_MESSAGE);
223 if (strcasecmp(val, _("yes")) == 0) {
225 } else if (strcasecmp(val, _("no")) == 0) {
228 bsendmsg(ua, _("Invalid value. It must be yes or no.\n"));
231 Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%s",
232 recycle, edit_int64(mr->MediaId, ed1));
233 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
234 bsendmsg(ua, "%s", db_strerror(ua->db));
236 bsendmsg(ua, _("New Recycle flag is: %s\n"),
237 mr->Recycle==1?_("yes"):_("no"));
241 static void update_volinchanger(UAContext *ua, char *val, MEDIA_DBR *mr)
246 POOL_MEM query(PM_MESSAGE);
247 if (strcasecmp(val, _("yes")) == 0) {
249 } else if (strcasecmp(val, _("no")) == 0) {
252 bsendmsg(ua, _("Invalid value. It must be yes or no.\n"));
255 Mmsg(query, "UPDATE Media SET InChanger=%d WHERE MediaId=%s",
256 InChanger, edit_int64(mr->MediaId, ed1));
257 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
258 bsendmsg(ua, "%s", db_strerror(ua->db));
260 bsendmsg(ua, _("New InChanger flag is: %s\n"),
261 mr->InChanger==1?_("yes"):_("no"));
266 static void update_volslot(UAContext *ua, char *val, MEDIA_DBR *mr)
270 memset(&pr, 0, sizeof(POOL_DBR));
271 pr.PoolId = mr->PoolId;
272 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
273 bsendmsg(ua, "%s", db_strerror(ua->db));
276 mr->Slot = atoi(val);
277 if (pr.MaxVols > 0 && mr->Slot > (int)pr.MaxVols) {
278 bsendmsg(ua, _("Invalid slot, it must be between 0 and MaxVols=%d\n"),
283 * Make sure to use db_update... rather than doing this directly,
284 * so that any Slot is handled correctly.
286 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
287 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
289 bsendmsg(ua, _("New Slot is: %d\n"), mr->Slot);
293 /* Modify the Pool in which this Volume is located */
294 static void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr)
298 char ed1[50], ed2[50];
300 memset(&pr, 0, sizeof(pr));
301 bstrncpy(pr.Name, val, sizeof(pr.Name));
302 if (!get_pool_dbr(ua, &pr)) {
305 mr->PoolId = pr.PoolId; /* set new PoolId */
308 query = get_pool_memory(PM_MESSAGE);
310 Mmsg(query, "UPDATE Media SET PoolId=%s WHERE MediaId=%s",
311 edit_int64(mr->PoolId, ed1),
312 edit_int64(mr->MediaId, ed2));
313 if (!db_sql_query(ua->db, query, NULL, NULL)) {
314 bsendmsg(ua, "%s", db_strerror(ua->db));
316 bsendmsg(ua, _("New Pool is: %s\n"), pr.Name);
318 if (!db_update_pool_record(ua->jcr, ua->db, opr)) {
319 bsendmsg(ua, "%s", db_strerror(ua->db));
322 if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
323 bsendmsg(ua, "%s", db_strerror(ua->db));
327 free_pool_memory(query);
331 * Refresh the Volume information from the Pool record
333 static void update_vol_from_pool(UAContext *ua, MEDIA_DBR *mr)
337 memset(&pr, 0, sizeof(pr));
338 pr.PoolId = mr->PoolId;
339 if (!db_get_pool_record(ua->jcr, ua->db, &pr) ||
340 !acl_access_ok(ua, Pool_ACL, pr.Name)) {
343 set_pool_dbr_defaults_in_media_dbr(mr, &pr);
344 if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
345 bsendmsg(ua, _("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
347 bsendmsg(ua, _("Volume defaults updated from \"%s\" Pool record.\n"),
353 * Refresh the Volume information from the Pool record
356 static void update_all_vols_from_pool(UAContext *ua)
361 memset(&pr, 0, sizeof(pr));
362 memset(&mr, 0, sizeof(mr));
363 if (!get_pool_dbr(ua, &pr)) {
366 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
367 mr.PoolId = pr.PoolId;
368 if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
369 bsendmsg(ua, _("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
371 bsendmsg(ua, _("All Volume defaults updated from Pool record.\n"));
377 * Update a media record -- allows you to change the
378 * Volume status. E.g. if you want Bacula to stop
379 * writing on the volume, set it to anything other
382 static int update_volume(UAContext *ua)
391 _("VolStatus"), /* 0 */
392 _("VolRetention"), /* 1 */
394 _("MaxVolJobs"), /* 3 */
395 _("MaxVolFiles"), /* 4 */
396 _("MaxVolBytes"), /* 5 */
397 _("Recycle"), /* 6 */
398 _("InChanger"), /* 7 */
401 _("FromPool"), /* 10 */
402 _("AllFromPool"), /* 11 !!! see below !!! */
405 #define AllFromPool 11 /* keep this updated with above */
407 for (i=0; kw[i]; i++) {
410 if ((j=find_arg_with_value(ua, kw[i])) > 0) {
411 if (i != AllFromPool && !select_media_dbr(ua, &mr)) {
416 update_volstatus(ua, ua->argv[j], &mr);
419 update_volretention(ua, ua->argv[j], &mr);
422 update_voluseduration(ua, ua->argv[j], &mr);
425 update_volmaxjobs(ua, ua->argv[j], &mr);
428 update_volmaxfiles(ua, ua->argv[j], &mr);
431 update_volmaxbytes(ua, ua->argv[j], &mr);
434 update_volrecycle(ua, ua->argv[j], &mr);
437 update_volinchanger(ua, ua->argv[j], &mr);
440 update_volslot(ua, ua->argv[j], &mr);
443 memset(&pr, 0, sizeof(POOL_DBR));
444 pr.PoolId = mr.PoolId;
445 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
446 bsendmsg(ua, "%s", db_strerror(ua->db));
449 update_vol_pool(ua, ua->argv[j], &mr, &pr);
452 update_vol_from_pool(ua, &mr);
455 update_all_vols_from_pool(ua);
463 start_prompt(ua, _("Parameters to modify:\n"));
464 add_prompt(ua, _("Volume Status")); /* 0 */
465 add_prompt(ua, _("Volume Retention Period")); /* 1 */
466 add_prompt(ua, _("Volume Use Duration")); /* 2 */
467 add_prompt(ua, _("Maximum Volume Jobs")); /* 3 */
468 add_prompt(ua, _("Maximum Volume Files")); /* 4 */
469 add_prompt(ua, _("Maximum Volume Bytes")); /* 5 */
470 add_prompt(ua, _("Recycle Flag")); /* 6 */
471 add_prompt(ua, _("Slot")); /* 7 */
472 add_prompt(ua, _("InChanger Flag")); /* 8 */
473 add_prompt(ua, _("Volume Files")); /* 9 */
474 add_prompt(ua, _("Pool")); /* 10 */
475 add_prompt(ua, _("Volume from Pool")); /* 11 */
476 add_prompt(ua, _("All Volumes from Pool")); /* 12 */
477 add_prompt(ua, _("Done")); /* 13 */
478 i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);
480 /* For All Volumes from Pool we don't need a Volume record */
481 if (i != 12 && i != 13) {
482 if (!select_media_dbr(ua, &mr)) { /* Get Volume record */
485 bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName);
488 case 0: /* Volume Status */
489 /* Modify Volume Status */
490 bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus);
491 start_prompt(ua, _("Possible Values are:\n"));
492 add_prompt(ua, NT_("Append"));
493 add_prompt(ua, NT_("Archive"));
494 add_prompt(ua, NT_("Disabled"));
495 add_prompt(ua, NT_("Full"));
496 add_prompt(ua, NT_("Used"));
497 add_prompt(ua, NT_("Cleaning"));
498 if (strcmp(mr.VolStatus, NT_("Purged")) == 0) {
499 add_prompt(ua, NT_("Recycle"));
501 add_prompt(ua, NT_("Read-Only"));
502 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
505 update_volstatus(ua, ua->cmd, &mr);
507 case 1: /* Retention */
508 bsendmsg(ua, _("Current retention period is: %s\n"),
509 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
510 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
513 update_volretention(ua, ua->cmd, &mr);
516 case 2: /* Use Duration */
517 bsendmsg(ua, _("Current use duration is: %s\n"),
518 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
519 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
522 update_voluseduration(ua, ua->cmd, &mr);
525 case 3: /* Max Jobs */
526 bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs);
527 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
530 update_volmaxjobs(ua, ua->cmd, &mr);
533 case 4: /* Max Files */
534 bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles);
535 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
538 update_volmaxfiles(ua, ua->cmd, &mr);
541 case 5: /* Max Bytes */
542 bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
543 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
546 update_volmaxbytes(ua, ua->cmd, &mr);
550 case 6: /* Recycle */
551 bsendmsg(ua, _("Current recycle flag is: %s\n"),
552 mr.Recycle==1?_("yes"):_("no"));
553 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
556 update_volrecycle(ua, ua->cmd, &mr);
560 bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot);
561 if (!get_pint(ua, _("Enter new Slot: "))) {
564 update_volslot(ua, ua->cmd, &mr);
567 case 8: /* InChanger */
568 bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger);
569 if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) {
572 mr.InChanger = ua->pint32_val;
574 * Make sure to use db_update... rather than doing this directly,
575 * so that any Slot is handled correctly.
577 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
578 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
580 bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger);
585 case 9: /* Volume Files */
587 bsendmsg(ua, _("Warning changing Volume Files can result\n"
588 "in loss of data on your Volume\n\n"));
589 bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles);
590 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
593 VolFiles = ua->pint32_val;
594 if (VolFiles != (int)(mr.VolFiles + 1)) {
595 bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n"));
596 if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) {
600 query = get_pool_memory(PM_MESSAGE);
601 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
602 VolFiles, edit_int64(mr.MediaId, ed1));
603 if (!db_sql_query(ua->db, query, NULL, NULL)) {
604 bsendmsg(ua, "%s", db_strerror(ua->db));
606 bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles);
608 free_pool_memory(query);
611 case 10: /* Volume's Pool */
612 memset(&pr, 0, sizeof(POOL_DBR));
613 pr.PoolId = mr.PoolId;
614 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
615 bsendmsg(ua, "%s", db_strerror(ua->db));
618 bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name);
619 if (!get_cmd(ua, _("Enter new Pool name: "))) {
622 update_vol_pool(ua, ua->cmd, &mr, &pr);
626 update_vol_from_pool(ua, &mr);
629 update_all_vols_from_pool(ua);
631 default: /* Done or error */
632 bsendmsg(ua, _("Selection terminated.\n"));
640 * Update pool record -- pull info from current POOL resource
642 static int update_pool(UAContext *ua)
650 pool = get_pool_resource(ua);
655 memset(&pr, 0, sizeof(pr));
656 bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name));
657 if (!get_pool_dbr(ua, &pr)) {
661 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
663 id = db_update_pool_record(ua->jcr, ua->db, &pr);
665 bsendmsg(ua, _("db_update_pool_record returned %d. ERR=%s\n"),
666 id, db_strerror(ua->db));
668 query = get_pool_memory(PM_MESSAGE);
669 Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
670 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
671 free_pool_memory(query);
672 bsendmsg(ua, _("Pool DB record updated from resource.\n"));