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"));
370 * Update a media record -- allows you to change the
371 * Volume status. E.g. if you want Bacula to stop
372 * writing on the volume, set it to anything other
375 static int update_volume(UAContext *ua)
384 NT_("VolStatus"), /* 0 */
385 NT_("VolRetention"), /* 1 */
386 NT_("VolUse"), /* 2 */
387 NT_("MaxVolJobs"), /* 3 */
388 NT_("MaxVolFiles"), /* 4 */
389 NT_("MaxVolBytes"), /* 5 */
390 NT_("Recycle"), /* 6 */
391 NT_("InChanger"), /* 7 */
394 NT_("FromPool"), /* 10 */
395 NT_("AllFromPool"), /* 11 !!! see below !!! */
398 #define AllFromPool 11 /* keep this updated with above */
400 for (i=0; kw[i]; i++) {
403 if ((j=find_arg_with_value(ua, kw[i])) > 0) {
404 if (i != AllFromPool && !select_media_dbr(ua, &mr)) {
409 update_volstatus(ua, ua->argv[j], &mr);
412 update_volretention(ua, ua->argv[j], &mr);
415 update_voluseduration(ua, ua->argv[j], &mr);
418 update_volmaxjobs(ua, ua->argv[j], &mr);
421 update_volmaxfiles(ua, ua->argv[j], &mr);
424 update_volmaxbytes(ua, ua->argv[j], &mr);
427 update_volrecycle(ua, ua->argv[j], &mr);
430 update_volinchanger(ua, ua->argv[j], &mr);
433 update_volslot(ua, ua->argv[j], &mr);
436 memset(&pr, 0, sizeof(POOL_DBR));
437 pr.PoolId = mr.PoolId;
438 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
439 bsendmsg(ua, "%s", db_strerror(ua->db));
442 update_vol_pool(ua, ua->argv[j], &mr, &pr);
445 update_vol_from_pool(ua, &mr);
448 update_all_vols_from_pool(ua);
456 start_prompt(ua, _("Parameters to modify:\n"));
457 add_prompt(ua, _("Volume Status")); /* 0 */
458 add_prompt(ua, _("Volume Retention Period")); /* 1 */
459 add_prompt(ua, _("Volume Use Duration")); /* 2 */
460 add_prompt(ua, _("Maximum Volume Jobs")); /* 3 */
461 add_prompt(ua, _("Maximum Volume Files")); /* 4 */
462 add_prompt(ua, _("Maximum Volume Bytes")); /* 5 */
463 add_prompt(ua, _("Recycle Flag")); /* 6 */
464 add_prompt(ua, _("Slot")); /* 7 */
465 add_prompt(ua, _("InChanger Flag")); /* 8 */
466 add_prompt(ua, _("Volume Files")); /* 9 */
467 add_prompt(ua, _("Pool")); /* 10 */
468 add_prompt(ua, _("Volume from Pool")); /* 11 */
469 add_prompt(ua, _("All Volumes from Pool")); /* 12 */
470 add_prompt(ua, _("Done")); /* 13 */
471 i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);
473 /* For All Volumes from Pool we don't need a Volume record */
474 if (i != 12 && i != 13) {
475 if (!select_media_dbr(ua, &mr)) { /* Get Volume record */
478 bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName);
481 case 0: /* Volume Status */
482 /* Modify Volume Status */
483 bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus);
484 start_prompt(ua, _("Possible Values are:\n"));
485 add_prompt(ua, NT_("Append"));
486 add_prompt(ua, NT_("Archive"));
487 add_prompt(ua, NT_("Disabled"));
488 add_prompt(ua, NT_("Full"));
489 add_prompt(ua, NT_("Used"));
490 add_prompt(ua, NT_("Cleaning"));
491 if (strcmp(mr.VolStatus, NT_("Purged")) == 0) {
492 add_prompt(ua, NT_("Recycle"));
494 add_prompt(ua, NT_("Read-Only"));
495 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
498 update_volstatus(ua, ua->cmd, &mr);
500 case 1: /* Retention */
501 bsendmsg(ua, _("Current retention period is: %s\n"),
502 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
503 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
506 update_volretention(ua, ua->cmd, &mr);
509 case 2: /* Use Duration */
510 bsendmsg(ua, _("Current use duration is: %s\n"),
511 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
512 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
515 update_voluseduration(ua, ua->cmd, &mr);
518 case 3: /* Max Jobs */
519 bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs);
520 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
523 update_volmaxjobs(ua, ua->cmd, &mr);
526 case 4: /* Max Files */
527 bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles);
528 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
531 update_volmaxfiles(ua, ua->cmd, &mr);
534 case 5: /* Max Bytes */
535 bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
536 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
539 update_volmaxbytes(ua, ua->cmd, &mr);
543 case 6: /* Recycle */
544 bsendmsg(ua, _("Current recycle flag is: %s\n"),
545 mr.Recycle==1?_("yes"):_("no"));
546 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
549 update_volrecycle(ua, ua->cmd, &mr);
553 bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot);
554 if (!get_pint(ua, _("Enter new Slot: "))) {
557 update_volslot(ua, ua->cmd, &mr);
560 case 8: /* InChanger */
561 bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger);
562 if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) {
565 mr.InChanger = ua->pint32_val;
567 * Make sure to use db_update... rather than doing this directly,
568 * so that any Slot is handled correctly.
570 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
571 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
573 bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger);
578 case 9: /* Volume Files */
580 bsendmsg(ua, _("Warning changing Volume Files can result\n"
581 "in loss of data on your Volume\n\n"));
582 bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles);
583 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
586 VolFiles = ua->pint32_val;
587 if (VolFiles != (int)(mr.VolFiles + 1)) {
588 bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n"));
589 if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) {
593 query = get_pool_memory(PM_MESSAGE);
594 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
595 VolFiles, edit_int64(mr.MediaId, ed1));
596 if (!db_sql_query(ua->db, query, NULL, NULL)) {
597 bsendmsg(ua, "%s", db_strerror(ua->db));
599 bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles);
601 free_pool_memory(query);
604 case 10: /* Volume's Pool */
605 memset(&pr, 0, sizeof(POOL_DBR));
606 pr.PoolId = mr.PoolId;
607 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
608 bsendmsg(ua, "%s", db_strerror(ua->db));
611 bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name);
612 if (!get_cmd(ua, _("Enter new Pool name: "))) {
615 update_vol_pool(ua, ua->cmd, &mr, &pr);
619 update_vol_from_pool(ua, &mr);
622 update_all_vols_from_pool(ua);
624 default: /* Done or error */
625 bsendmsg(ua, _("Selection terminated.\n"));
633 * Update pool record -- pull info from current POOL resource
635 static int update_pool(UAContext *ua)
643 pool = get_pool_resource(ua);
648 memset(&pr, 0, sizeof(pr));
649 bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name));
650 if (!get_pool_dbr(ua, &pr)) {
654 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
656 id = db_update_pool_record(ua->jcr, ua->db, &pr);
658 bsendmsg(ua, _("db_update_pool_record returned %d. ERR=%s\n"),
659 id, db_strerror(ua->db));
661 query = get_pool_memory(PM_MESSAGE);
662 Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
663 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
664 free_pool_memory(query);
665 bsendmsg(ua, _("Pool DB record updated from resource.\n"));