3 * Bacula Director -- Update command processing
4 * Split from ua_cmds.c March 2005
6 * Kern Sibbald, September MM
11 Copyright (C) 2000-2005 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 ammended 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 set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op);
33 int 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[] = {
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 POOLMEM *query = get_pool_memory(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, NULL, NULL)) {
129 bsendmsg(ua, "%s", db_strerror(ua->db));
131 bsendmsg(ua, _("New Volume status is: %s\n"), mr->VolStatus);
134 free_pool_memory(query);
137 static void update_volretention(UAContext *ua, char *val, MEDIA_DBR *mr)
139 char ed1[150], ed2[50];
141 if (!duration_to_utime(val, &mr->VolRetention)) {
142 bsendmsg(ua, _("Invalid retention period specified: %s\n"), val);
145 query = get_pool_memory(PM_MESSAGE);
146 Mmsg(query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%s",
147 edit_uint64(mr->VolRetention, ed1), edit_int64(mr->MediaId,ed2));
148 if (!db_sql_query(ua->db, query, NULL, NULL)) {
149 bsendmsg(ua, "%s", db_strerror(ua->db));
151 bsendmsg(ua, _("New retention period is: %s\n"),
152 edit_utime(mr->VolRetention, ed1, sizeof(ed1)));
154 free_pool_memory(query);
157 static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr)
159 char ed1[150], ed2[50];
162 if (!duration_to_utime(val, &mr->VolUseDuration)) {
163 bsendmsg(ua, _("Invalid use duration specified: %s\n"), val);
166 query = get_pool_memory(PM_MESSAGE);
167 Mmsg(query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%s",
168 edit_uint64(mr->VolUseDuration, ed1), edit_int64(mr->MediaId,ed2));
169 if (!db_sql_query(ua->db, query, NULL, NULL)) {
170 bsendmsg(ua, "%s", db_strerror(ua->db));
172 bsendmsg(ua, _("New use duration is: %s\n"),
173 edit_utime(mr->VolUseDuration, ed1, sizeof(ed1)));
175 free_pool_memory(query);
178 static void update_volmaxjobs(UAContext *ua, char *val, MEDIA_DBR *mr)
180 POOLMEM *query = get_pool_memory(PM_MESSAGE);
182 Mmsg(query, "UPDATE Media SET MaxVolJobs=%s WHERE MediaId=%s",
183 val, edit_int64(mr->MediaId,ed1));
184 if (!db_sql_query(ua->db, query, NULL, NULL)) {
185 bsendmsg(ua, "%s", db_strerror(ua->db));
187 bsendmsg(ua, _("New max jobs is: %s\n"), val);
189 free_pool_memory(query);
192 static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr)
194 POOLMEM *query = get_pool_memory(PM_MESSAGE);
196 Mmsg(query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%s",
197 val, edit_int64(mr->MediaId, ed1));
198 if (!db_sql_query(ua->db, query, NULL, NULL)) {
199 bsendmsg(ua, "%s", db_strerror(ua->db));
201 bsendmsg(ua, _("New max files is: %s\n"), val);
203 free_pool_memory(query);
206 static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr)
209 char ed1[50], ed2[50];
212 if (!size_to_uint64(val, strlen(val), &maxbytes)) {
213 bsendmsg(ua, _("Invalid max. bytes specification: %s\n"), val);
216 query = get_pool_memory(PM_MESSAGE);
217 Mmsg(query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%s",
218 edit_uint64(maxbytes, ed1), edit_int64(mr->MediaId, ed2));
219 if (!db_sql_query(ua->db, query, NULL, NULL)) {
220 bsendmsg(ua, "%s", db_strerror(ua->db));
222 bsendmsg(ua, _("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1));
224 free_pool_memory(query);
227 static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr)
232 if (strcasecmp(val, _("yes")) == 0) {
234 } else if (strcasecmp(val, _("no")) == 0) {
237 bsendmsg(ua, _("Invalid value. It must by yes or no.\n"));
240 query = get_pool_memory(PM_MESSAGE);
241 Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%s",
242 recycle, edit_int64(mr->MediaId, ed1));
243 if (!db_sql_query(ua->db, query, NULL, NULL)) {
244 bsendmsg(ua, "%s", db_strerror(ua->db));
246 bsendmsg(ua, _("New Recycle flag is: %s\n"),
247 mr->Recycle==1?_("yes"):_("no"));
249 free_pool_memory(query);
252 /* Modify the Pool in which this Volume is located */
253 static void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr)
257 char ed1[50], ed2[50];
259 memset(&pr, 0, sizeof(pr));
260 bstrncpy(pr.Name, val, sizeof(pr.Name));
261 if (!get_pool_dbr(ua, &pr)) {
264 mr->PoolId = pr.PoolId; /* set new PoolId */
267 query = get_pool_memory(PM_MESSAGE);
269 Mmsg(query, "UPDATE Media SET PoolId=%s WHERE MediaId=%s",
270 edit_int64(mr->PoolId, ed1),
271 edit_int64(mr->MediaId, ed2));
272 if (!db_sql_query(ua->db, query, NULL, NULL)) {
273 bsendmsg(ua, "%s", db_strerror(ua->db));
275 bsendmsg(ua, _("New Pool is: %s\n"), pr.Name);
277 if (!db_update_pool_record(ua->jcr, ua->db, opr)) {
278 bsendmsg(ua, "%s", db_strerror(ua->db));
281 if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
282 bsendmsg(ua, "%s", db_strerror(ua->db));
286 free_pool_memory(query);
290 * Refresh the Volume information from the Pool record
292 static void update_volfrompool(UAContext *ua, MEDIA_DBR *mr)
296 memset(&pr, 0, sizeof(pr));
297 pr.PoolId = mr->PoolId;
298 if (!db_get_pool_record(ua->jcr, ua->db, &pr) ||
299 !acl_access_ok(ua, Pool_ACL, pr.Name)) {
302 set_pool_dbr_defaults_in_media_dbr(mr, &pr);
303 if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
304 bsendmsg(ua, _("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
306 bsendmsg(ua, _("Volume defaults updated from \"%s\" Pool record.\n"),
312 * Refresh the Volume information from the Pool record
315 static void update_all_vols_from_pool(UAContext *ua)
320 memset(&pr, 0, sizeof(pr));
321 memset(&mr, 0, sizeof(mr));
322 if (!get_pool_dbr(ua, &pr)) {
325 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
326 mr.PoolId = pr.PoolId;
327 if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
328 bsendmsg(ua, _("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
330 bsendmsg(ua, _("All Volume defaults updated from Pool record.\n"));
336 * Update a media record -- allows you to change the
337 * Volume status. E.g. if you want Bacula to stop
338 * writing on the volume, set it to anything other
341 static int update_volume(UAContext *ua)
349 N_("VolStatus"), /* 0 */
350 N_("VolRetention"), /* 1 */
351 N_("VolUse"), /* 2 */
352 N_("MaxVolJobs"), /* 3 */
353 N_("MaxVolFiles"), /* 4 */
354 N_("MaxVolBytes"), /* 5 */
355 N_("Recycle"), /* 6 */
357 N_("FromPool"), /* 8 */
358 N_("AllFromPool"), /* 9 */
361 for (int i=0; kw[i]; i++) {
364 if ((j=find_arg_with_value(ua, kw[i])) > 0) {
365 if (i != 9 && !select_media_dbr(ua, &mr)) {
370 update_volstatus(ua, ua->argv[j], &mr);
373 update_volretention(ua, ua->argv[j], &mr);
376 update_voluseduration(ua, ua->argv[j], &mr);
379 update_volmaxjobs(ua, ua->argv[j], &mr);
382 update_volmaxfiles(ua, ua->argv[j], &mr);
385 update_volmaxbytes(ua, ua->argv[j], &mr);
388 update_volrecycle(ua, ua->argv[j], &mr);
391 memset(&pr, 0, sizeof(POOL_DBR));
392 pr.PoolId = mr.PoolId;
393 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
394 bsendmsg(ua, "%s", db_strerror(ua->db));
397 update_vol_pool(ua, ua->argv[j], &mr, &pr);
400 update_volfrompool(ua, &mr);
403 update_all_vols_from_pool(ua);
411 if (!select_media_dbr(ua, &mr)) {
414 bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName);
415 start_prompt(ua, _("Parameters to modify:\n"));
416 add_prompt(ua, _("Volume Status"));
417 add_prompt(ua, _("Volume Retention Period"));
418 add_prompt(ua, _("Volume Use Duration"));
419 add_prompt(ua, _("Maximum Volume Jobs"));
420 add_prompt(ua, _("Maximum Volume Files"));
421 add_prompt(ua, _("Maximum Volume Bytes"));
422 add_prompt(ua, _("Recycle Flag"));
423 add_prompt(ua, _("Slot"));
424 add_prompt(ua, _("InChanger Flag"));
425 add_prompt(ua, _("Volume Files"));
426 add_prompt(ua, _("Pool"));
427 add_prompt(ua, _("Volume from Pool"));
428 add_prompt(ua, _("All Volumes from Pool"));
429 add_prompt(ua, _("Done"));
430 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
431 case 0: /* Volume Status */
432 /* Modify Volume Status */
433 bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus);
434 start_prompt(ua, _("Possible Values are:\n"));
435 add_prompt(ua, "Append"); /* Better not translate these as */
436 add_prompt(ua, "Archive"); /* They are known in the database code */
437 add_prompt(ua, "Disabled");
438 add_prompt(ua, "Full");
439 add_prompt(ua, "Used");
440 add_prompt(ua, "Cleaning");
441 if (strcmp(mr.VolStatus, "Purged") == 0) {
442 add_prompt(ua, "Recycle");
444 add_prompt(ua, "Read-Only");
445 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
448 update_volstatus(ua, ua->cmd, &mr);
450 case 1: /* Retention */
451 bsendmsg(ua, _("Current retention period is: %s\n"),
452 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
453 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
456 update_volretention(ua, ua->cmd, &mr);
459 case 2: /* Use Duration */
460 bsendmsg(ua, _("Current use duration is: %s\n"),
461 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
462 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
465 update_voluseduration(ua, ua->cmd, &mr);
468 case 3: /* Max Jobs */
469 bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs);
470 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
473 update_volmaxjobs(ua, ua->cmd, &mr);
476 case 4: /* Max Files */
477 bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles);
478 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
481 update_volmaxfiles(ua, ua->cmd, &mr);
484 case 5: /* Max Bytes */
485 bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
486 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
489 update_volmaxbytes(ua, ua->cmd, &mr);
493 case 6: /* Recycle */
494 bsendmsg(ua, _("Current recycle flag is: %s\n"),
495 mr.Recycle==1?_("yes"):_("no"));
496 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
499 update_volrecycle(ua, ua->cmd, &mr);
505 memset(&pr, 0, sizeof(POOL_DBR));
506 pr.PoolId = mr.PoolId;
507 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
508 bsendmsg(ua, "%s", db_strerror(ua->db));
511 bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot);
512 if (!get_pint(ua, _("Enter new Slot: "))) {
515 Slot = ua->pint32_val;
516 if (pr.MaxVols > 0 && Slot > (int)pr.MaxVols) {
517 bsendmsg(ua, _("Invalid slot, it must be between 0 and %d\n"),
523 * Make sure to use db_update... rather than doing this directly,
524 * so that any Slot is handled correctly.
526 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
527 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
529 bsendmsg(ua, _("New Slot is: %d\n"), mr.Slot);
533 case 8: /* InChanger */
534 bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger);
535 if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) {
538 mr.InChanger = ua->pint32_val;
540 * Make sure to use db_update... rather than doing this directly,
541 * so that any Slot is handled correctly.
543 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
544 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
546 bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger);
551 case 9: /* Volume Files */
553 bsendmsg(ua, _("Warning changing Volume Files can result\n"
554 "in loss of data on your Volume\n\n"));
555 bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles);
556 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
559 VolFiles = ua->pint32_val;
560 if (VolFiles != (int)(mr.VolFiles + 1)) {
561 bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n"));
562 if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) {
566 query = get_pool_memory(PM_MESSAGE);
567 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
568 VolFiles, edit_int64(mr.MediaId, ed1));
569 if (!db_sql_query(ua->db, query, NULL, NULL)) {
570 bsendmsg(ua, "%s", db_strerror(ua->db));
572 bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles);
574 free_pool_memory(query);
577 case 10: /* Volume's Pool */
578 memset(&pr, 0, sizeof(POOL_DBR));
579 pr.PoolId = mr.PoolId;
580 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
581 bsendmsg(ua, "%s", db_strerror(ua->db));
584 bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name);
585 if (!get_cmd(ua, _("Enter new Pool name: "))) {
588 update_vol_pool(ua, ua->cmd, &mr, &pr);
592 update_volfrompool(ua, &mr);
595 update_all_vols_from_pool(ua);
597 default: /* Done or error */
598 bsendmsg(ua, "Selection done.\n");
606 * Update pool record -- pull info from current POOL resource
608 static int update_pool(UAContext *ua)
616 pool = get_pool_resource(ua);
621 memset(&pr, 0, sizeof(pr));
622 bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name));
623 if (!get_pool_dbr(ua, &pr)) {
627 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
629 id = db_update_pool_record(ua->jcr, ua->db, &pr);
631 bsendmsg(ua, _("db_update_pool_record returned %d. ERR=%s\n"),
632 id, db_strerror(ua->db));
634 query = get_pool_memory(PM_MESSAGE);
635 Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
636 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
637 free_pool_memory(query);
638 bsendmsg(ua, _("Pool DB record updated from resource.\n"));