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 /* Forward referenced functions */
29 static int update_volume(UAContext *ua);
30 static bool update_pool(UAContext *ua);
33 * Update a Pool Record in the database.
34 * It is always updated from the Resource record.
36 * update pool=<pool-name>
37 * updates pool from Pool resource
38 * update media pool=<pool-name> volume=<volume-name>
39 * changes pool info for volume
40 * update slots [scan=...]
41 * updates autochanger slots
43 int update_cmd(UAContext *ua, const char *cmd)
45 static const char *kw[] = {
47 NT_("volume"), /* 1 */
56 switch (find_arg_keyword(ua, kw)) {
71 start_prompt(ua, _("Update choice:\n"));
72 add_prompt(ua, _("Volume parameters"));
73 add_prompt(ua, _("Pool from resource"));
74 add_prompt(ua, _("Slots from autochanger"));
75 switch (do_prompt(ua, _("item"), _("Choose catalog item to update"), NULL, 0)) {
91 static void update_volstatus(UAContext *ua, const char *val, MEDIA_DBR *mr)
93 POOL_MEM query(PM_MESSAGE);
107 for (i=0; kw[i]; i++) {
108 if (strcasecmp(val, kw[i]) == 0) {
114 bsendmsg(ua, _("Invalid VolStatus specified: %s\n"), val);
117 bstrncpy(mr->VolStatus, kw[i], sizeof(mr->VolStatus));
118 Mmsg(query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%s",
119 mr->VolStatus, edit_int64(mr->MediaId,ed1));
120 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
121 bsendmsg(ua, "%s", db_strerror(ua->db));
123 bsendmsg(ua, _("New Volume status is: %s\n"), mr->VolStatus);
128 static void update_volretention(UAContext *ua, char *val, MEDIA_DBR *mr)
130 char ed1[150], ed2[50];
131 POOL_MEM query(PM_MESSAGE);
132 if (!duration_to_utime(val, &mr->VolRetention)) {
133 bsendmsg(ua, _("Invalid retention period specified: %s\n"), val);
136 Mmsg(query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%s",
137 edit_uint64(mr->VolRetention, ed1), edit_int64(mr->MediaId,ed2));
138 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
139 bsendmsg(ua, "%s", db_strerror(ua->db));
141 bsendmsg(ua, _("New retention period is: %s\n"),
142 edit_utime(mr->VolRetention, ed1, sizeof(ed1)));
146 static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr)
148 char ed1[150], ed2[50];
149 POOL_MEM query(PM_MESSAGE);
151 if (!duration_to_utime(val, &mr->VolUseDuration)) {
152 bsendmsg(ua, _("Invalid use duration specified: %s\n"), val);
155 Mmsg(query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%s",
156 edit_uint64(mr->VolUseDuration, ed1), edit_int64(mr->MediaId,ed2));
157 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
158 bsendmsg(ua, "%s", db_strerror(ua->db));
160 bsendmsg(ua, _("New use duration is: %s\n"),
161 edit_utime(mr->VolUseDuration, ed1, sizeof(ed1)));
165 static void update_volmaxjobs(UAContext *ua, char *val, MEDIA_DBR *mr)
167 POOL_MEM query(PM_MESSAGE);
169 Mmsg(query, "UPDATE Media SET MaxVolJobs=%s WHERE MediaId=%s",
170 val, edit_int64(mr->MediaId,ed1));
171 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
172 bsendmsg(ua, "%s", db_strerror(ua->db));
174 bsendmsg(ua, _("New max jobs is: %s\n"), val);
178 static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr)
180 POOL_MEM query(PM_MESSAGE);
182 Mmsg(query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%s",
183 val, edit_int64(mr->MediaId, ed1));
184 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
185 bsendmsg(ua, "%s", db_strerror(ua->db));
187 bsendmsg(ua, _("New max files is: %s\n"), val);
191 static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr)
194 char ed1[50], ed2[50];
195 POOL_MEM query(PM_MESSAGE);
197 if (!size_to_uint64(val, strlen(val), &maxbytes)) {
198 bsendmsg(ua, _("Invalid max. bytes specification: %s\n"), val);
201 Mmsg(query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%s",
202 edit_uint64(maxbytes, ed1), edit_int64(mr->MediaId, ed2));
203 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
204 bsendmsg(ua, "%s", db_strerror(ua->db));
206 bsendmsg(ua, _("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1));
210 static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr)
215 POOL_MEM query(PM_MESSAGE);
216 if (!is_yesno(val, &recycle)) {
217 bsendmsg(ua, _("Invalid value. It must be yes or no.\n"));
220 Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%s",
221 recycle, edit_int64(mr->MediaId, ed1));
222 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
223 bsendmsg(ua, "%s", db_strerror(ua->db));
225 bsendmsg(ua, _("New Recycle flag is: %s\n"),
226 mr->Recycle==1?_("yes"):_("no"));
230 static void update_volinchanger(UAContext *ua, char *val, MEDIA_DBR *mr)
235 POOL_MEM query(PM_MESSAGE);
236 if (!is_yesno(val, &InChanger)) {
237 bsendmsg(ua, _("Invalid value. It must be yes or no.\n"));
240 Mmsg(query, "UPDATE Media SET InChanger=%d WHERE MediaId=%s",
241 InChanger, edit_int64(mr->MediaId, ed1));
242 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
243 bsendmsg(ua, "%s", db_strerror(ua->db));
245 bsendmsg(ua, _("New InChanger flag is: %s\n"),
246 mr->InChanger==1?_("yes"):_("no"));
251 static void update_volslot(UAContext *ua, char *val, MEDIA_DBR *mr)
255 memset(&pr, 0, sizeof(POOL_DBR));
256 pr.PoolId = mr->PoolId;
257 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
258 bsendmsg(ua, "%s", db_strerror(ua->db));
261 mr->Slot = atoi(val);
262 if (pr.MaxVols > 0 && mr->Slot > (int)pr.MaxVols) {
263 bsendmsg(ua, _("Invalid slot, it must be between 0 and MaxVols=%d\n"),
268 * Make sure to use db_update... rather than doing this directly,
269 * so that any Slot is handled correctly.
271 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
272 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
274 bsendmsg(ua, _("New Slot is: %d\n"), mr->Slot);
278 /* Modify the Pool in which this Volume is located */
279 static void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr)
283 char ed1[50], ed2[50];
285 memset(&pr, 0, sizeof(pr));
286 bstrncpy(pr.Name, val, sizeof(pr.Name));
287 if (!get_pool_dbr(ua, &pr)) {
290 mr->PoolId = pr.PoolId; /* set new PoolId */
293 query = get_pool_memory(PM_MESSAGE);
295 Mmsg(query, "UPDATE Media SET PoolId=%s WHERE MediaId=%s",
296 edit_int64(mr->PoolId, ed1),
297 edit_int64(mr->MediaId, ed2));
298 if (!db_sql_query(ua->db, query, NULL, NULL)) {
299 bsendmsg(ua, "%s", db_strerror(ua->db));
301 bsendmsg(ua, _("New Pool is: %s\n"), pr.Name);
303 if (!db_update_pool_record(ua->jcr, ua->db, opr)) {
304 bsendmsg(ua, "%s", db_strerror(ua->db));
307 if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
308 bsendmsg(ua, "%s", db_strerror(ua->db));
312 free_pool_memory(query);
316 * Refresh the Volume information from the Pool record
318 static void update_vol_from_pool(UAContext *ua, MEDIA_DBR *mr)
322 memset(&pr, 0, sizeof(pr));
323 pr.PoolId = mr->PoolId;
324 if (!db_get_pool_record(ua->jcr, ua->db, &pr) ||
325 !acl_access_ok(ua, Pool_ACL, pr.Name)) {
328 set_pool_dbr_defaults_in_media_dbr(mr, &pr);
329 if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
330 bsendmsg(ua, _("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
332 bsendmsg(ua, _("Volume defaults updated from \"%s\" Pool record.\n"),
338 * Refresh the Volume information from the Pool record
341 static void update_all_vols_from_pool(UAContext *ua)
346 memset(&pr, 0, sizeof(pr));
347 memset(&mr, 0, sizeof(mr));
348 if (!get_pool_dbr(ua, &pr)) {
351 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
352 mr.PoolId = pr.PoolId;
353 if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
354 bsendmsg(ua, _("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
356 bsendmsg(ua, _("All Volume defaults updated from Pool record.\n"));
360 static void update_volenabled(UAContext *ua, char *val, MEDIA_DBR *mr)
362 mr->Enabled = get_enabled(ua, val);
363 if (mr->Enabled < 0) {
366 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
367 bsendmsg(ua, _("Error updating media record Enabled: ERR=%s"), db_strerror(ua->db));
369 bsendmsg(ua, _("New Enabled is: %d\n"), mr->Enabled);
376 * Update a media record -- allows you to change the
377 * Volume status. E.g. if you want Bacula to stop
378 * writing on the volume, set it to anything other
381 static int update_volume(UAContext *ua)
390 _("VolStatus"), /* 0 */
391 _("VolRetention"), /* 1 */
393 _("MaxVolJobs"), /* 3 */
394 _("MaxVolFiles"), /* 4 */
395 _("MaxVolBytes"), /* 5 */
396 _("Recycle"), /* 6 */
397 _("InChanger"), /* 7 */
400 _("FromPool"), /* 10 */
401 _("AllFromPool"), /* 11 !!! see below !!! */
402 _("Enabled"), /* 12 */
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 all from pool don't select a media record */
412 if (i != AllFromPool && !select_media_dbr(ua, &mr)) {
417 update_volstatus(ua, ua->argv[j], &mr);
420 update_volretention(ua, ua->argv[j], &mr);
423 update_voluseduration(ua, ua->argv[j], &mr);
426 update_volmaxjobs(ua, ua->argv[j], &mr);
429 update_volmaxfiles(ua, ua->argv[j], &mr);
432 update_volmaxbytes(ua, ua->argv[j], &mr);
435 update_volrecycle(ua, ua->argv[j], &mr);
438 update_volinchanger(ua, ua->argv[j], &mr);
441 update_volslot(ua, ua->argv[j], &mr);
444 memset(&pr, 0, sizeof(POOL_DBR));
445 pr.PoolId = mr.PoolId;
446 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
447 bsendmsg(ua, "%s", db_strerror(ua->db));
450 update_vol_pool(ua, ua->argv[j], &mr, &pr);
453 update_vol_from_pool(ua, &mr);
456 update_all_vols_from_pool(ua);
459 update_volenabled(ua, ua->argv[j], &mr);
467 start_prompt(ua, _("Parameters to modify:\n"));
468 add_prompt(ua, _("Volume Status")); /* 0 */
469 add_prompt(ua, _("Volume Retention Period")); /* 1 */
470 add_prompt(ua, _("Volume Use Duration")); /* 2 */
471 add_prompt(ua, _("Maximum Volume Jobs")); /* 3 */
472 add_prompt(ua, _("Maximum Volume Files")); /* 4 */
473 add_prompt(ua, _("Maximum Volume Bytes")); /* 5 */
474 add_prompt(ua, _("Recycle Flag")); /* 6 */
475 add_prompt(ua, _("Slot")); /* 7 */
476 add_prompt(ua, _("InChanger Flag")); /* 8 */
477 add_prompt(ua, _("Volume Files")); /* 9 */
478 add_prompt(ua, _("Pool")); /* 10 */
479 add_prompt(ua, _("Volume from Pool")); /* 11 */
480 add_prompt(ua, _("All Volumes from Pool")); /* 12 */
481 add_prompt(ua, _("Enabled")), /* 13 */
482 add_prompt(ua, _("Done")); /* 14 */
483 i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);
485 /* For All Volumes from Pool and Done, we don't need a Volume record */
486 if (i != 12 && i != 14) {
487 if (!select_media_dbr(ua, &mr)) { /* Get Volume record */
490 bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName);
493 case 0: /* Volume Status */
494 /* Modify Volume Status */
495 bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus);
496 start_prompt(ua, _("Possible Values are:\n"));
497 add_prompt(ua, NT_("Append"));
498 add_prompt(ua, NT_("Archive"));
499 add_prompt(ua, NT_("Disabled"));
500 add_prompt(ua, NT_("Full"));
501 add_prompt(ua, NT_("Used"));
502 add_prompt(ua, NT_("Cleaning"));
503 if (strcmp(mr.VolStatus, NT_("Purged")) == 0) {
504 add_prompt(ua, NT_("Recycle"));
506 add_prompt(ua, NT_("Read-Only"));
507 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
510 update_volstatus(ua, ua->cmd, &mr);
512 case 1: /* Retention */
513 bsendmsg(ua, _("Current retention period is: %s\n"),
514 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
515 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
518 update_volretention(ua, ua->cmd, &mr);
521 case 2: /* Use Duration */
522 bsendmsg(ua, _("Current use duration is: %s\n"),
523 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
524 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
527 update_voluseduration(ua, ua->cmd, &mr);
530 case 3: /* Max Jobs */
531 bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs);
532 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
535 update_volmaxjobs(ua, ua->cmd, &mr);
538 case 4: /* Max Files */
539 bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles);
540 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
543 update_volmaxfiles(ua, ua->cmd, &mr);
546 case 5: /* Max Bytes */
547 bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
548 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
551 update_volmaxbytes(ua, ua->cmd, &mr);
555 case 6: /* Recycle */
556 bsendmsg(ua, _("Current recycle flag is: %s\n"),
557 mr.Recycle==1?_("yes"):_("no"));
558 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
561 update_volrecycle(ua, ua->cmd, &mr);
565 bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot);
566 if (!get_pint(ua, _("Enter new Slot: "))) {
569 update_volslot(ua, ua->cmd, &mr);
572 case 8: /* InChanger */
573 bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger);
574 if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) {
577 mr.InChanger = ua->pint32_val;
579 * Make sure to use db_update... rather than doing this directly,
580 * so that any Slot is handled correctly.
582 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
583 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
585 bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger);
590 case 9: /* Volume Files */
592 bsendmsg(ua, _("Warning changing Volume Files can result\n"
593 "in loss of data on your Volume\n\n"));
594 bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles);
595 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
598 VolFiles = ua->pint32_val;
599 if (VolFiles != (int)(mr.VolFiles + 1)) {
600 bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n"));
601 if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) {
605 query = get_pool_memory(PM_MESSAGE);
606 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
607 VolFiles, edit_int64(mr.MediaId, ed1));
608 if (!db_sql_query(ua->db, query, NULL, NULL)) {
609 bsendmsg(ua, "%s", db_strerror(ua->db));
611 bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles);
613 free_pool_memory(query);
616 case 10: /* Volume's Pool */
617 memset(&pr, 0, sizeof(POOL_DBR));
618 pr.PoolId = mr.PoolId;
619 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
620 bsendmsg(ua, "%s", db_strerror(ua->db));
623 bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name);
624 if (!get_cmd(ua, _("Enter new Pool name: "))) {
627 update_vol_pool(ua, ua->cmd, &mr, &pr);
631 update_vol_from_pool(ua, &mr);
634 update_all_vols_from_pool(ua);
638 bsendmsg(ua, _("Current Enabled is: %d\n"), mr.Enabled);
639 if (!get_cmd(ua, _("Enter new Enabled: "))) {
642 if (strcasecmp(ua->cmd, "yes") == 0 || strcasecmp(ua->cmd, "true") == 0) {
644 } else if (strcasecmp(ua->cmd, "no") == 0 || strcasecmp(ua->cmd, "false") == 0) {
646 } else if (strcasecmp(ua->cmd, "archived") == 0) {
649 mr.Enabled = atoi(ua->cmd);
651 update_volenabled(ua, ua->cmd, &mr);
654 default: /* Done or error */
655 bsendmsg(ua, _("Selection terminated.\n"));
663 * Update pool record -- pull info from current POOL resource
665 static bool update_pool(UAContext *ua)
673 pool = get_pool_resource(ua);
678 memset(&pr, 0, sizeof(pr));
679 bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name));
680 if (!get_pool_dbr(ua, &pr)) {
684 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
686 id = db_update_pool_record(ua->jcr, ua->db, &pr);
688 bsendmsg(ua, _("db_update_pool_record returned %d. ERR=%s\n"),
689 id, db_strerror(ua->db));
691 query = get_pool_memory(PM_MESSAGE);
692 Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
693 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
694 free_pool_memory(query);
695 bsendmsg(ua, _("Pool DB record updated from resource.\n"));