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 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 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 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 POOLMEM *query = get_pool_memory(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, NULL, NULL)) {
180 bsendmsg(ua, "%s", db_strerror(ua->db));
182 bsendmsg(ua, _("New max jobs is: %s\n"), val);
184 free_pool_memory(query);
187 static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr)
189 POOLMEM *query = get_pool_memory(PM_MESSAGE);
191 Mmsg(query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%s",
192 val, edit_int64(mr->MediaId, ed1));
193 if (!db_sql_query(ua->db, query, NULL, NULL)) {
194 bsendmsg(ua, "%s", db_strerror(ua->db));
196 bsendmsg(ua, _("New max files is: %s\n"), val);
198 free_pool_memory(query);
201 static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr)
204 char ed1[50], ed2[50];
207 if (!size_to_uint64(val, strlen(val), &maxbytes)) {
208 bsendmsg(ua, _("Invalid max. bytes specification: %s\n"), val);
211 query = get_pool_memory(PM_MESSAGE);
212 Mmsg(query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%s",
213 edit_uint64(maxbytes, ed1), edit_int64(mr->MediaId, ed2));
214 if (!db_sql_query(ua->db, query, NULL, NULL)) {
215 bsendmsg(ua, "%s", db_strerror(ua->db));
217 bsendmsg(ua, _("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1));
219 free_pool_memory(query);
222 static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr)
227 if (strcasecmp(val, _("yes")) == 0) {
229 } else if (strcasecmp(val, _("no")) == 0) {
232 bsendmsg(ua, _("Invalid value. It must by yes or no.\n"));
235 query = get_pool_memory(PM_MESSAGE);
236 Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%s",
237 recycle, edit_int64(mr->MediaId, ed1));
238 if (!db_sql_query(ua->db, query, NULL, NULL)) {
239 bsendmsg(ua, "%s", db_strerror(ua->db));
241 bsendmsg(ua, _("New Recycle flag is: %s\n"),
242 mr->Recycle==1?_("yes"):_("no"));
244 free_pool_memory(query);
247 /* Modify the Pool in which this Volume is located */
248 static void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr)
252 char ed1[50], ed2[50];
254 memset(&pr, 0, sizeof(pr));
255 bstrncpy(pr.Name, val, sizeof(pr.Name));
256 if (!get_pool_dbr(ua, &pr)) {
259 mr->PoolId = pr.PoolId; /* set new PoolId */
262 query = get_pool_memory(PM_MESSAGE);
264 Mmsg(query, "UPDATE Media SET PoolId=%s WHERE MediaId=%s",
265 edit_int64(mr->PoolId, ed1),
266 edit_int64(mr->MediaId, ed2));
267 if (!db_sql_query(ua->db, query, NULL, NULL)) {
268 bsendmsg(ua, "%s", db_strerror(ua->db));
270 bsendmsg(ua, _("New Pool is: %s\n"), pr.Name);
272 if (!db_update_pool_record(ua->jcr, ua->db, opr)) {
273 bsendmsg(ua, "%s", db_strerror(ua->db));
276 if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
277 bsendmsg(ua, "%s", db_strerror(ua->db));
281 free_pool_memory(query);
285 * Refresh the Volume information from the Pool record
287 static void update_vol_from_pool(UAContext *ua, MEDIA_DBR *mr)
291 memset(&pr, 0, sizeof(pr));
292 pr.PoolId = mr->PoolId;
293 if (!db_get_pool_record(ua->jcr, ua->db, &pr) ||
294 !acl_access_ok(ua, Pool_ACL, pr.Name)) {
297 set_pool_dbr_defaults_in_media_dbr(mr, &pr);
298 if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
299 bsendmsg(ua, _("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
301 bsendmsg(ua, _("Volume defaults updated from \"%s\" Pool record.\n"),
307 * Refresh the Volume information from the Pool record
310 static void update_all_vols_from_pool(UAContext *ua)
315 memset(&pr, 0, sizeof(pr));
316 memset(&mr, 0, sizeof(mr));
317 if (!get_pool_dbr(ua, &pr)) {
320 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
321 mr.PoolId = pr.PoolId;
322 if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
323 bsendmsg(ua, _("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
325 bsendmsg(ua, _("All Volume defaults updated from Pool record.\n"));
331 * Update a media record -- allows you to change the
332 * Volume status. E.g. if you want Bacula to stop
333 * writing on the volume, set it to anything other
336 static int update_volume(UAContext *ua)
344 _("VolStatus"), /* 0 */
345 _("VolRetention"), /* 1 */
347 _("MaxVolJobs"), /* 3 */
348 _("MaxVolFiles"), /* 4 */
349 _("MaxVolBytes"), /* 5 */
350 _("Recycle"), /* 6 */
352 _("FromPool"), /* 8 */
353 _("AllFromPool"), /* 9 */
356 for (int i=0; kw[i]; i++) {
359 if ((j=find_arg_with_value(ua, kw[i])) > 0) {
360 if (i != 9 && !select_media_dbr(ua, &mr)) {
365 update_volstatus(ua, ua->argv[j], &mr);
368 update_volretention(ua, ua->argv[j], &mr);
371 update_voluseduration(ua, ua->argv[j], &mr);
374 update_volmaxjobs(ua, ua->argv[j], &mr);
377 update_volmaxfiles(ua, ua->argv[j], &mr);
380 update_volmaxbytes(ua, ua->argv[j], &mr);
383 update_volrecycle(ua, ua->argv[j], &mr);
386 memset(&pr, 0, sizeof(POOL_DBR));
387 pr.PoolId = mr.PoolId;
388 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
389 bsendmsg(ua, "%s", db_strerror(ua->db));
392 update_vol_pool(ua, ua->argv[j], &mr, &pr);
395 update_vol_from_pool(ua, &mr);
398 update_all_vols_from_pool(ua);
406 if (!select_media_dbr(ua, &mr)) {
409 bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName);
410 start_prompt(ua, _("Parameters to modify:\n"));
411 add_prompt(ua, _("Volume Status"));
412 add_prompt(ua, _("Volume Retention Period"));
413 add_prompt(ua, _("Volume Use Duration"));
414 add_prompt(ua, _("Maximum Volume Jobs"));
415 add_prompt(ua, _("Maximum Volume Files"));
416 add_prompt(ua, _("Maximum Volume Bytes"));
417 add_prompt(ua, _("Recycle Flag"));
418 add_prompt(ua, _("Slot"));
419 add_prompt(ua, _("InChanger Flag"));
420 add_prompt(ua, _("Volume Files"));
421 add_prompt(ua, _("Pool"));
422 add_prompt(ua, _("Volume from Pool"));
423 add_prompt(ua, _("All Volumes from Pool"));
424 add_prompt(ua, _("Done"));
425 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
426 case 0: /* Volume Status */
427 /* Modify Volume Status */
428 bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus);
429 start_prompt(ua, _("Possible Values are:\n"));
430 add_prompt(ua, N_("Append"));
431 add_prompt(ua, N_("Archive"));
432 add_prompt(ua, N_("Disabled"));
433 add_prompt(ua, N_("Full"));
434 add_prompt(ua, N_("Used"));
435 add_prompt(ua, N_("Cleaning"));
436 if (strcmp(mr.VolStatus, N_("Purged")) == 0) {
437 add_prompt(ua, N_("Recycle"));
439 add_prompt(ua, N_("Read-Only"));
440 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
443 update_volstatus(ua, ua->cmd, &mr);
445 case 1: /* Retention */
446 bsendmsg(ua, _("Current retention period is: %s\n"),
447 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
448 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
451 update_volretention(ua, ua->cmd, &mr);
454 case 2: /* Use Duration */
455 bsendmsg(ua, _("Current use duration is: %s\n"),
456 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
457 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
460 update_voluseduration(ua, ua->cmd, &mr);
463 case 3: /* Max Jobs */
464 bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs);
465 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
468 update_volmaxjobs(ua, ua->cmd, &mr);
471 case 4: /* Max Files */
472 bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles);
473 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
476 update_volmaxfiles(ua, ua->cmd, &mr);
479 case 5: /* Max Bytes */
480 bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
481 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
484 update_volmaxbytes(ua, ua->cmd, &mr);
488 case 6: /* Recycle */
489 bsendmsg(ua, _("Current recycle flag is: %s\n"),
490 mr.Recycle==1?_("yes"):_("no"));
491 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
494 update_volrecycle(ua, ua->cmd, &mr);
500 memset(&pr, 0, sizeof(POOL_DBR));
501 pr.PoolId = mr.PoolId;
502 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
503 bsendmsg(ua, "%s", db_strerror(ua->db));
506 bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot);
507 if (!get_pint(ua, _("Enter new Slot: "))) {
510 Slot = ua->pint32_val;
511 if (pr.MaxVols > 0 && Slot > (int)pr.MaxVols) {
512 bsendmsg(ua, _("Invalid slot, it must be between 0 and %d\n"),
518 * Make sure to use db_update... rather than doing this directly,
519 * so that any Slot is handled correctly.
521 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
522 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
524 bsendmsg(ua, _("New Slot is: %d\n"), mr.Slot);
528 case 8: /* InChanger */
529 bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger);
530 if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) {
533 mr.InChanger = ua->pint32_val;
535 * Make sure to use db_update... rather than doing this directly,
536 * so that any Slot is handled correctly.
538 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
539 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
541 bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger);
546 case 9: /* Volume Files */
548 bsendmsg(ua, _("Warning changing Volume Files can result\n"
549 "in loss of data on your Volume\n\n"));
550 bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles);
551 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
554 VolFiles = ua->pint32_val;
555 if (VolFiles != (int)(mr.VolFiles + 1)) {
556 bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n"));
557 if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) {
561 query = get_pool_memory(PM_MESSAGE);
562 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
563 VolFiles, edit_int64(mr.MediaId, ed1));
564 if (!db_sql_query(ua->db, query, NULL, NULL)) {
565 bsendmsg(ua, "%s", db_strerror(ua->db));
567 bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles);
569 free_pool_memory(query);
572 case 10: /* Volume's Pool */
573 memset(&pr, 0, sizeof(POOL_DBR));
574 pr.PoolId = mr.PoolId;
575 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
576 bsendmsg(ua, "%s", db_strerror(ua->db));
579 bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name);
580 if (!get_cmd(ua, _("Enter new Pool name: "))) {
583 update_vol_pool(ua, ua->cmd, &mr, &pr);
587 update_vol_from_pool(ua, &mr);
590 update_all_vols_from_pool(ua);
592 default: /* Done or error */
593 bsendmsg(ua, _("Selection done.\n"));
601 * Update pool record -- pull info from current POOL resource
603 static int update_pool(UAContext *ua)
611 pool = get_pool_resource(ua);
616 memset(&pr, 0, sizeof(pr));
617 bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name));
618 if (!get_pool_dbr(ua, &pr)) {
622 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
624 id = db_update_pool_record(ua->jcr, ua->db, &pr);
626 bsendmsg(ua, _("db_update_pool_record returned %d. ERR=%s\n"),
627 id, db_strerror(ua->db));
629 query = get_pool_memory(PM_MESSAGE);
630 Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
631 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
632 free_pool_memory(query);
633 bsendmsg(ua, _("Pool DB record updated from resource.\n"));