3 * Bacula Director -- Update command processing
4 * Split from ua_cmds.c March 2005
6 * Kern Sibbald, September MM
12 Copyright (C) 2000-2005 Kern Sibbald
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of
17 the License, or (at your option) any later version.
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
24 You should have received a copy of the GNU General Public
25 License along with this program; if not, write to the Free
26 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
34 /* External variables */
35 extern char *list_pool; /* in sql_cmds.c */
37 /* Imported functions */
38 void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op);
39 int update_slots(UAContext *ua);
42 /* Forward referenced functions */
43 static int update_volume(UAContext *ua);
44 static int update_pool(UAContext *ua);
47 * Update a Pool Record in the database.
48 * It is always updated from the Resource record.
50 * update pool=<pool-name>
51 * updates pool from Pool resource
52 * update media pool=<pool-name> volume=<volume-name>
53 * changes pool info for volume
54 * update slots [scan=...]
55 * updates autochanger slots
57 int update_cmd(UAContext *ua, const char *cmd)
59 static const char *kw[] = {
70 switch (find_arg_keyword(ua, kw)) {
85 start_prompt(ua, _("Update choice:\n"));
86 add_prompt(ua, _("Volume parameters"));
87 add_prompt(ua, _("Pool from resource"));
88 add_prompt(ua, _("Slots from autochanger"));
89 switch (do_prompt(ua, _("item"), _("Choose catalog item to update"), NULL, 0)) {
105 static void update_volstatus(UAContext *ua, const char *val, MEDIA_DBR *mr)
107 POOLMEM *query = get_pool_memory(PM_MESSAGE);
121 for (i=0; kw[i]; i++) {
122 if (strcasecmp(val, kw[i]) == 0) {
128 bsendmsg(ua, _("Invalid VolStatus specified: %s\n"), val);
131 bstrncpy(mr->VolStatus, kw[i], sizeof(mr->VolStatus));
132 Mmsg(query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%s",
133 mr->VolStatus, edit_int64(mr->MediaId,ed1));
134 if (!db_sql_query(ua->db, query, NULL, NULL)) {
135 bsendmsg(ua, "%s", db_strerror(ua->db));
137 bsendmsg(ua, _("New Volume status is: %s\n"), mr->VolStatus);
140 free_pool_memory(query);
143 static void update_volretention(UAContext *ua, char *val, MEDIA_DBR *mr)
145 char ed1[150], ed2[50];
147 if (!duration_to_utime(val, &mr->VolRetention)) {
148 bsendmsg(ua, _("Invalid retention period specified: %s\n"), val);
151 query = get_pool_memory(PM_MESSAGE);
152 Mmsg(query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%s",
153 edit_uint64(mr->VolRetention, ed1), edit_int64(mr->MediaId,ed2));
154 if (!db_sql_query(ua->db, query, NULL, NULL)) {
155 bsendmsg(ua, "%s", db_strerror(ua->db));
157 bsendmsg(ua, _("New retention period is: %s\n"),
158 edit_utime(mr->VolRetention, ed1, sizeof(ed1)));
160 free_pool_memory(query);
163 static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr)
165 char ed1[150], ed2[50];
168 if (!duration_to_utime(val, &mr->VolUseDuration)) {
169 bsendmsg(ua, _("Invalid use duration specified: %s\n"), val);
172 query = get_pool_memory(PM_MESSAGE);
173 Mmsg(query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%s",
174 edit_uint64(mr->VolUseDuration, ed1), edit_int64(mr->MediaId,ed2));
175 if (!db_sql_query(ua->db, query, NULL, NULL)) {
176 bsendmsg(ua, "%s", db_strerror(ua->db));
178 bsendmsg(ua, _("New use duration is: %s\n"),
179 edit_utime(mr->VolUseDuration, ed1, sizeof(ed1)));
181 free_pool_memory(query);
184 static void update_volmaxjobs(UAContext *ua, char *val, MEDIA_DBR *mr)
186 POOLMEM *query = get_pool_memory(PM_MESSAGE);
188 Mmsg(query, "UPDATE Media SET MaxVolJobs=%s WHERE MediaId=%s",
189 val, edit_int64(mr->MediaId,ed1));
190 if (!db_sql_query(ua->db, query, NULL, NULL)) {
191 bsendmsg(ua, "%s", db_strerror(ua->db));
193 bsendmsg(ua, _("New max jobs is: %s\n"), val);
195 free_pool_memory(query);
198 static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr)
200 POOLMEM *query = get_pool_memory(PM_MESSAGE);
202 Mmsg(query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%s",
203 val, edit_int64(mr->MediaId, ed1));
204 if (!db_sql_query(ua->db, query, NULL, NULL)) {
205 bsendmsg(ua, "%s", db_strerror(ua->db));
207 bsendmsg(ua, _("New max files is: %s\n"), val);
209 free_pool_memory(query);
212 static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr)
215 char ed1[50], ed2[50];
218 if (!size_to_uint64(val, strlen(val), &maxbytes)) {
219 bsendmsg(ua, _("Invalid max. bytes specification: %s\n"), val);
222 query = get_pool_memory(PM_MESSAGE);
223 Mmsg(query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%s",
224 edit_uint64(maxbytes, ed1), edit_int64(mr->MediaId, ed2));
225 if (!db_sql_query(ua->db, query, NULL, NULL)) {
226 bsendmsg(ua, "%s", db_strerror(ua->db));
228 bsendmsg(ua, _("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1));
230 free_pool_memory(query);
233 static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr)
238 if (strcasecmp(val, _("yes")) == 0) {
240 } else if (strcasecmp(val, _("no")) == 0) {
243 bsendmsg(ua, _("Invalid value. It must by yes or no.\n"));
246 query = get_pool_memory(PM_MESSAGE);
247 Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%s",
248 recycle, edit_int64(mr->MediaId, ed1));
249 if (!db_sql_query(ua->db, query, NULL, NULL)) {
250 bsendmsg(ua, "%s", db_strerror(ua->db));
252 bsendmsg(ua, _("New Recycle flag is: %s\n"),
253 mr->Recycle==1?_("yes"):_("no"));
255 free_pool_memory(query);
258 /* Modify the Pool in which this Volume is located */
259 static void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr)
265 memset(&pr, 0, sizeof(pr));
266 bstrncpy(pr.Name, val, sizeof(pr.Name));
267 if (!get_pool_dbr(ua, &pr)) {
270 mr->PoolId = pr.PoolId; /* set new PoolId */
273 query = get_pool_memory(PM_MESSAGE);
275 Mmsg(query, "UPDATE Media SET PoolId=%d WHERE MediaId=%s",
276 mr->PoolId, edit_int64(mr->MediaId, ed1));
277 if (!db_sql_query(ua->db, query, NULL, NULL)) {
278 bsendmsg(ua, "%s", db_strerror(ua->db));
280 bsendmsg(ua, _("New Pool is: %s\n"), pr.Name);
282 if (!db_update_pool_record(ua->jcr, ua->db, opr)) {
283 bsendmsg(ua, "%s", db_strerror(ua->db));
286 if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
287 bsendmsg(ua, "%s", db_strerror(ua->db));
291 free_pool_memory(query);
295 * Refresh the Volume information from the Pool record
297 static void update_volfrompool(UAContext *ua, MEDIA_DBR *mr)
301 memset(&pr, 0, sizeof(pr));
302 pr.PoolId = mr->PoolId;
303 if (!db_get_pool_record(ua->jcr, ua->db, &pr) ||
304 !acl_access_ok(ua, Pool_ACL, pr.Name)) {
307 set_pool_dbr_defaults_in_media_dbr(mr, &pr);
308 if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
309 bsendmsg(ua, _("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
311 bsendmsg(ua, _("Volume defaults updated from \"%s\" Pool record.\n"),
317 * Refresh the Volume information from the Pool record
320 static void update_all_vols_from_pool(UAContext *ua)
325 memset(&pr, 0, sizeof(pr));
326 memset(&mr, 0, sizeof(mr));
327 if (!get_pool_dbr(ua, &pr)) {
330 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
331 mr.PoolId = pr.PoolId;
332 if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
333 bsendmsg(ua, _("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
335 bsendmsg(ua, _("All Volume defaults updated from Pool record.\n"));
341 * Update a media record -- allows you to change the
342 * Volume status. E.g. if you want Bacula to stop
343 * writing on the volume, set it to anything other
346 static int update_volume(UAContext *ua)
354 N_("VolStatus"), /* 0 */
355 N_("VolRetention"), /* 1 */
356 N_("VolUse"), /* 2 */
357 N_("MaxVolJobs"), /* 3 */
358 N_("MaxVolFiles"), /* 4 */
359 N_("MaxVolBytes"), /* 5 */
360 N_("Recycle"), /* 6 */
362 N_("FromPool"), /* 8 */
363 N_("AllFromPool"), /* 9 */
366 for (int i=0; kw[i]; i++) {
369 if ((j=find_arg_with_value(ua, kw[i])) > 0) {
370 if (i != 9 && !select_media_dbr(ua, &mr)) {
375 update_volstatus(ua, ua->argv[j], &mr);
378 update_volretention(ua, ua->argv[j], &mr);
381 update_voluseduration(ua, ua->argv[j], &mr);
384 update_volmaxjobs(ua, ua->argv[j], &mr);
387 update_volmaxfiles(ua, ua->argv[j], &mr);
390 update_volmaxbytes(ua, ua->argv[j], &mr);
393 update_volrecycle(ua, ua->argv[j], &mr);
396 memset(&pr, 0, sizeof(POOL_DBR));
397 pr.PoolId = mr.PoolId;
398 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
399 bsendmsg(ua, "%s", db_strerror(ua->db));
402 update_vol_pool(ua, ua->argv[j], &mr, &pr);
405 update_volfrompool(ua, &mr);
408 update_all_vols_from_pool(ua);
416 if (!select_media_dbr(ua, &mr)) {
419 bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName);
420 start_prompt(ua, _("Parameters to modify:\n"));
421 add_prompt(ua, _("Volume Status"));
422 add_prompt(ua, _("Volume Retention Period"));
423 add_prompt(ua, _("Volume Use Duration"));
424 add_prompt(ua, _("Maximum Volume Jobs"));
425 add_prompt(ua, _("Maximum Volume Files"));
426 add_prompt(ua, _("Maximum Volume Bytes"));
427 add_prompt(ua, _("Recycle Flag"));
428 add_prompt(ua, _("Slot"));
429 add_prompt(ua, _("InChanger Flag"));
430 add_prompt(ua, _("Volume Files"));
431 add_prompt(ua, _("Pool"));
432 add_prompt(ua, _("Volume from Pool"));
433 add_prompt(ua, _("All Volumes from Pool"));
434 add_prompt(ua, _("Done"));
435 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
436 case 0: /* Volume Status */
437 /* Modify Volume Status */
438 bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus);
439 start_prompt(ua, _("Possible Values are:\n"));
440 add_prompt(ua, "Append"); /* Better not translate these as */
441 add_prompt(ua, "Archive"); /* They are known in the database code */
442 add_prompt(ua, "Disabled");
443 add_prompt(ua, "Full");
444 add_prompt(ua, "Used");
445 add_prompt(ua, "Cleaning");
446 if (strcmp(mr.VolStatus, "Purged") == 0) {
447 add_prompt(ua, "Recycle");
449 add_prompt(ua, "Read-Only");
450 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
453 update_volstatus(ua, ua->cmd, &mr);
455 case 1: /* Retention */
456 bsendmsg(ua, _("Current retention period is: %s\n"),
457 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
458 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
461 update_volretention(ua, ua->cmd, &mr);
464 case 2: /* Use Duration */
465 bsendmsg(ua, _("Current use duration is: %s\n"),
466 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
467 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
470 update_voluseduration(ua, ua->cmd, &mr);
473 case 3: /* Max Jobs */
474 bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs);
475 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
478 update_volmaxjobs(ua, ua->cmd, &mr);
481 case 4: /* Max Files */
482 bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles);
483 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
486 update_volmaxfiles(ua, ua->cmd, &mr);
489 case 5: /* Max Bytes */
490 bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
491 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
494 update_volmaxbytes(ua, ua->cmd, &mr);
498 case 6: /* Recycle */
499 bsendmsg(ua, _("Current recycle flag is: %s\n"),
500 mr.Recycle==1?_("yes"):_("no"));
501 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
504 update_volrecycle(ua, ua->cmd, &mr);
510 memset(&pr, 0, sizeof(POOL_DBR));
511 pr.PoolId = mr.PoolId;
512 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
513 bsendmsg(ua, "%s", db_strerror(ua->db));
516 bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot);
517 if (!get_pint(ua, _("Enter new Slot: "))) {
520 Slot = ua->pint32_val;
521 if (pr.MaxVols > 0 && Slot > (int)pr.MaxVols) {
522 bsendmsg(ua, _("Invalid slot, it must be between 0 and %d\n"),
528 * Make sure to use db_update... rather than doing this directly,
529 * so that any Slot is handled correctly.
531 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
532 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
534 bsendmsg(ua, _("New Slot is: %d\n"), mr.Slot);
538 case 8: /* InChanger */
539 bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger);
540 if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) {
543 mr.InChanger = ua->pint32_val;
545 * Make sure to use db_update... rather than doing this directly,
546 * so that any Slot is handled correctly.
548 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
549 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
551 bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger);
556 case 9: /* Volume Files */
558 bsendmsg(ua, _("Warning changing Volume Files can result\n"
559 "in loss of data on your Volume\n\n"));
560 bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles);
561 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
564 VolFiles = ua->pint32_val;
565 if (VolFiles != (int)(mr.VolFiles + 1)) {
566 bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n"));
567 if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) {
571 query = get_pool_memory(PM_MESSAGE);
572 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
573 VolFiles, edit_int64(mr.MediaId, ed1));
574 if (!db_sql_query(ua->db, query, NULL, NULL)) {
575 bsendmsg(ua, "%s", db_strerror(ua->db));
577 bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles);
579 free_pool_memory(query);
582 case 10: /* Volume's Pool */
583 memset(&pr, 0, sizeof(POOL_DBR));
584 pr.PoolId = mr.PoolId;
585 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
586 bsendmsg(ua, "%s", db_strerror(ua->db));
589 bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name);
590 if (!get_cmd(ua, _("Enter new Pool name: "))) {
593 update_vol_pool(ua, ua->cmd, &mr, &pr);
597 update_volfrompool(ua, &mr);
600 update_all_vols_from_pool(ua);
602 default: /* Done or error */
603 bsendmsg(ua, "Selection done.\n");
611 * Update pool record -- pull info from current POOL resource
613 static int update_pool(UAContext *ua)
620 pool = get_pool_resource(ua);
625 memset(&pr, 0, sizeof(pr));
626 bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name));
627 if (!get_pool_dbr(ua, &pr)) {
631 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
633 id = db_update_pool_record(ua->jcr, ua->db, &pr);
635 bsendmsg(ua, _("db_update_pool_record returned %d. ERR=%s\n"),
636 id, db_strerror(ua->db));
638 query = get_pool_memory(PM_MESSAGE);
639 Mmsg(query, list_pool, pr.PoolId);
640 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
641 free_pool_memory(query);
642 bsendmsg(ua, _("Pool DB record updated from resource.\n"));