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 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 bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName);
464 start_prompt(ua, _("Parameters to modify:\n"));
465 add_prompt(ua, _("Volume Status"));
466 add_prompt(ua, _("Volume Retention Period"));
467 add_prompt(ua, _("Volume Use Duration"));
468 add_prompt(ua, _("Maximum Volume Jobs"));
469 add_prompt(ua, _("Maximum Volume Files"));
470 add_prompt(ua, _("Maximum Volume Bytes"));
471 add_prompt(ua, _("Recycle Flag"));
472 add_prompt(ua, _("Slot"));
473 add_prompt(ua, _("InChanger Flag"));
474 add_prompt(ua, _("Volume Files"));
475 add_prompt(ua, _("Pool"));
476 add_prompt(ua, _("Volume from Pool"));
477 add_prompt(ua, _("All Volumes from Pool"));
478 add_prompt(ua, _("Done"));
479 i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);
480 /* For All Volumes from Pool we don't need a Volume record */
482 if (!select_media_dbr(ua, &mr)) { /* Get Volume record */
487 case 0: /* Volume Status */
488 /* Modify Volume Status */
489 bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus);
490 start_prompt(ua, _("Possible Values are:\n"));
491 add_prompt(ua, NT_("Append"));
492 add_prompt(ua, NT_("Archive"));
493 add_prompt(ua, NT_("Disabled"));
494 add_prompt(ua, NT_("Full"));
495 add_prompt(ua, NT_("Used"));
496 add_prompt(ua, NT_("Cleaning"));
497 if (strcmp(mr.VolStatus, NT_("Purged")) == 0) {
498 add_prompt(ua, NT_("Recycle"));
500 add_prompt(ua, NT_("Read-Only"));
501 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
504 update_volstatus(ua, ua->cmd, &mr);
506 case 1: /* Retention */
507 bsendmsg(ua, _("Current retention period is: %s\n"),
508 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
509 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
512 update_volretention(ua, ua->cmd, &mr);
515 case 2: /* Use Duration */
516 bsendmsg(ua, _("Current use duration is: %s\n"),
517 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
518 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
521 update_voluseduration(ua, ua->cmd, &mr);
524 case 3: /* Max Jobs */
525 bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs);
526 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
529 update_volmaxjobs(ua, ua->cmd, &mr);
532 case 4: /* Max Files */
533 bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles);
534 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
537 update_volmaxfiles(ua, ua->cmd, &mr);
540 case 5: /* Max Bytes */
541 bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
542 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
545 update_volmaxbytes(ua, ua->cmd, &mr);
549 case 6: /* Recycle */
550 bsendmsg(ua, _("Current recycle flag is: %s\n"),
551 mr.Recycle==1?_("yes"):_("no"));
552 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
555 update_volrecycle(ua, ua->cmd, &mr);
559 bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot);
560 if (!get_pint(ua, _("Enter new Slot: "))) {
563 update_volslot(ua, ua->cmd, &mr);
566 case 8: /* InChanger */
567 bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger);
568 if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) {
571 mr.InChanger = ua->pint32_val;
573 * Make sure to use db_update... rather than doing this directly,
574 * so that any Slot is handled correctly.
576 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
577 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
579 bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger);
584 case 9: /* Volume Files */
586 bsendmsg(ua, _("Warning changing Volume Files can result\n"
587 "in loss of data on your Volume\n\n"));
588 bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles);
589 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
592 VolFiles = ua->pint32_val;
593 if (VolFiles != (int)(mr.VolFiles + 1)) {
594 bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n"));
595 if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) {
599 query = get_pool_memory(PM_MESSAGE);
600 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
601 VolFiles, edit_int64(mr.MediaId, ed1));
602 if (!db_sql_query(ua->db, query, NULL, NULL)) {
603 bsendmsg(ua, "%s", db_strerror(ua->db));
605 bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles);
607 free_pool_memory(query);
610 case 10: /* Volume's Pool */
611 memset(&pr, 0, sizeof(POOL_DBR));
612 pr.PoolId = mr.PoolId;
613 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
614 bsendmsg(ua, "%s", db_strerror(ua->db));
617 bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name);
618 if (!get_cmd(ua, _("Enter new Pool name: "))) {
621 update_vol_pool(ua, ua->cmd, &mr, &pr);
625 update_vol_from_pool(ua, &mr);
628 update_all_vols_from_pool(ua);
630 default: /* Done or error */
631 bsendmsg(ua, _("Selection terminated.\n"));
639 * Update pool record -- pull info from current POOL resource
641 static int update_pool(UAContext *ua)
649 pool = get_pool_resource(ua);
654 memset(&pr, 0, sizeof(pr));
655 bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name));
656 if (!get_pool_dbr(ua, &pr)) {
660 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
662 id = db_update_pool_record(ua->jcr, ua->db, &pr);
664 bsendmsg(ua, _("db_update_pool_record returned %d. ERR=%s\n"),
665 id, db_strerror(ua->db));
667 query = get_pool_memory(PM_MESSAGE);
668 Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
669 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
670 free_pool_memory(query);
671 bsendmsg(ua, _("Pool DB record updated from resource.\n"));