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)
263 char ed1[50], ed2[50];
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=%s WHERE MediaId=%s",
276 edit_int64(mr->PoolId, ed1),
277 edit_int64(mr->MediaId, ed2));
278 if (!db_sql_query(ua->db, query, NULL, NULL)) {
279 bsendmsg(ua, "%s", db_strerror(ua->db));
281 bsendmsg(ua, _("New Pool is: %s\n"), pr.Name);
283 if (!db_update_pool_record(ua->jcr, ua->db, opr)) {
284 bsendmsg(ua, "%s", db_strerror(ua->db));
287 if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
288 bsendmsg(ua, "%s", db_strerror(ua->db));
292 free_pool_memory(query);
296 * Refresh the Volume information from the Pool record
298 static void update_volfrompool(UAContext *ua, MEDIA_DBR *mr)
302 memset(&pr, 0, sizeof(pr));
303 pr.PoolId = mr->PoolId;
304 if (!db_get_pool_record(ua->jcr, ua->db, &pr) ||
305 !acl_access_ok(ua, Pool_ACL, pr.Name)) {
308 set_pool_dbr_defaults_in_media_dbr(mr, &pr);
309 if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
310 bsendmsg(ua, _("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
312 bsendmsg(ua, _("Volume defaults updated from \"%s\" Pool record.\n"),
318 * Refresh the Volume information from the Pool record
321 static void update_all_vols_from_pool(UAContext *ua)
326 memset(&pr, 0, sizeof(pr));
327 memset(&mr, 0, sizeof(mr));
328 if (!get_pool_dbr(ua, &pr)) {
331 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
332 mr.PoolId = pr.PoolId;
333 if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
334 bsendmsg(ua, _("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
336 bsendmsg(ua, _("All Volume defaults updated from Pool record.\n"));
342 * Update a media record -- allows you to change the
343 * Volume status. E.g. if you want Bacula to stop
344 * writing on the volume, set it to anything other
347 static int update_volume(UAContext *ua)
355 N_("VolStatus"), /* 0 */
356 N_("VolRetention"), /* 1 */
357 N_("VolUse"), /* 2 */
358 N_("MaxVolJobs"), /* 3 */
359 N_("MaxVolFiles"), /* 4 */
360 N_("MaxVolBytes"), /* 5 */
361 N_("Recycle"), /* 6 */
363 N_("FromPool"), /* 8 */
364 N_("AllFromPool"), /* 9 */
367 for (int i=0; kw[i]; i++) {
370 if ((j=find_arg_with_value(ua, kw[i])) > 0) {
371 if (i != 9 && !select_media_dbr(ua, &mr)) {
376 update_volstatus(ua, ua->argv[j], &mr);
379 update_volretention(ua, ua->argv[j], &mr);
382 update_voluseduration(ua, ua->argv[j], &mr);
385 update_volmaxjobs(ua, ua->argv[j], &mr);
388 update_volmaxfiles(ua, ua->argv[j], &mr);
391 update_volmaxbytes(ua, ua->argv[j], &mr);
394 update_volrecycle(ua, ua->argv[j], &mr);
397 memset(&pr, 0, sizeof(POOL_DBR));
398 pr.PoolId = mr.PoolId;
399 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
400 bsendmsg(ua, "%s", db_strerror(ua->db));
403 update_vol_pool(ua, ua->argv[j], &mr, &pr);
406 update_volfrompool(ua, &mr);
409 update_all_vols_from_pool(ua);
417 if (!select_media_dbr(ua, &mr)) {
420 bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName);
421 start_prompt(ua, _("Parameters to modify:\n"));
422 add_prompt(ua, _("Volume Status"));
423 add_prompt(ua, _("Volume Retention Period"));
424 add_prompt(ua, _("Volume Use Duration"));
425 add_prompt(ua, _("Maximum Volume Jobs"));
426 add_prompt(ua, _("Maximum Volume Files"));
427 add_prompt(ua, _("Maximum Volume Bytes"));
428 add_prompt(ua, _("Recycle Flag"));
429 add_prompt(ua, _("Slot"));
430 add_prompt(ua, _("InChanger Flag"));
431 add_prompt(ua, _("Volume Files"));
432 add_prompt(ua, _("Pool"));
433 add_prompt(ua, _("Volume from Pool"));
434 add_prompt(ua, _("All Volumes from Pool"));
435 add_prompt(ua, _("Done"));
436 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
437 case 0: /* Volume Status */
438 /* Modify Volume Status */
439 bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus);
440 start_prompt(ua, _("Possible Values are:\n"));
441 add_prompt(ua, "Append"); /* Better not translate these as */
442 add_prompt(ua, "Archive"); /* They are known in the database code */
443 add_prompt(ua, "Disabled");
444 add_prompt(ua, "Full");
445 add_prompt(ua, "Used");
446 add_prompt(ua, "Cleaning");
447 if (strcmp(mr.VolStatus, "Purged") == 0) {
448 add_prompt(ua, "Recycle");
450 add_prompt(ua, "Read-Only");
451 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
454 update_volstatus(ua, ua->cmd, &mr);
456 case 1: /* Retention */
457 bsendmsg(ua, _("Current retention period is: %s\n"),
458 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
459 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
462 update_volretention(ua, ua->cmd, &mr);
465 case 2: /* Use Duration */
466 bsendmsg(ua, _("Current use duration is: %s\n"),
467 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
468 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
471 update_voluseduration(ua, ua->cmd, &mr);
474 case 3: /* Max Jobs */
475 bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs);
476 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
479 update_volmaxjobs(ua, ua->cmd, &mr);
482 case 4: /* Max Files */
483 bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles);
484 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
487 update_volmaxfiles(ua, ua->cmd, &mr);
490 case 5: /* Max Bytes */
491 bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
492 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
495 update_volmaxbytes(ua, ua->cmd, &mr);
499 case 6: /* Recycle */
500 bsendmsg(ua, _("Current recycle flag is: %s\n"),
501 mr.Recycle==1?_("yes"):_("no"));
502 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
505 update_volrecycle(ua, ua->cmd, &mr);
511 memset(&pr, 0, sizeof(POOL_DBR));
512 pr.PoolId = mr.PoolId;
513 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
514 bsendmsg(ua, "%s", db_strerror(ua->db));
517 bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot);
518 if (!get_pint(ua, _("Enter new Slot: "))) {
521 Slot = ua->pint32_val;
522 if (pr.MaxVols > 0 && Slot > (int)pr.MaxVols) {
523 bsendmsg(ua, _("Invalid slot, it must be between 0 and %d\n"),
529 * Make sure to use db_update... rather than doing this directly,
530 * so that any Slot is handled correctly.
532 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
533 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
535 bsendmsg(ua, _("New Slot is: %d\n"), mr.Slot);
539 case 8: /* InChanger */
540 bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger);
541 if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) {
544 mr.InChanger = ua->pint32_val;
546 * Make sure to use db_update... rather than doing this directly,
547 * so that any Slot is handled correctly.
549 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
550 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
552 bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger);
557 case 9: /* Volume Files */
559 bsendmsg(ua, _("Warning changing Volume Files can result\n"
560 "in loss of data on your Volume\n\n"));
561 bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles);
562 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
565 VolFiles = ua->pint32_val;
566 if (VolFiles != (int)(mr.VolFiles + 1)) {
567 bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n"));
568 if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) {
572 query = get_pool_memory(PM_MESSAGE);
573 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
574 VolFiles, edit_int64(mr.MediaId, ed1));
575 if (!db_sql_query(ua->db, query, NULL, NULL)) {
576 bsendmsg(ua, "%s", db_strerror(ua->db));
578 bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles);
580 free_pool_memory(query);
583 case 10: /* Volume's Pool */
584 memset(&pr, 0, sizeof(POOL_DBR));
585 pr.PoolId = mr.PoolId;
586 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
587 bsendmsg(ua, "%s", db_strerror(ua->db));
590 bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name);
591 if (!get_cmd(ua, _("Enter new Pool name: "))) {
594 update_vol_pool(ua, ua->cmd, &mr, &pr);
598 update_volfrompool(ua, &mr);
601 update_all_vols_from_pool(ua);
603 default: /* Done or error */
604 bsendmsg(ua, "Selection done.\n");
612 * Update pool record -- pull info from current POOL resource
614 static int update_pool(UAContext *ua)
622 pool = get_pool_resource(ua);
627 memset(&pr, 0, sizeof(pr));
628 bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name));
629 if (!get_pool_dbr(ua, &pr)) {
633 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
635 id = db_update_pool_record(ua->jcr, ua->db, &pr);
637 bsendmsg(ua, _("db_update_pool_record returned %d. ERR=%s\n"),
638 id, db_strerror(ua->db));
640 query = get_pool_memory(PM_MESSAGE);
641 Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
642 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
643 free_pool_memory(query);
644 bsendmsg(ua, _("Pool DB record updated from resource.\n"));