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 /* External variables */
29 extern char *list_pool; /* in sql_cmds.c */
31 /* Imported functions */
32 void 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)
345 _("VolStatus"), /* 0 */
346 _("VolRetention"), /* 1 */
348 _("MaxVolJobs"), /* 3 */
349 _("MaxVolFiles"), /* 4 */
350 _("MaxVolBytes"), /* 5 */
351 _("Recycle"), /* 6 */
353 _("FromPool"), /* 8 */
354 _("AllFromPool"), /* 9 */
357 for (i=0; kw[i]; i++) {
360 if ((j=find_arg_with_value(ua, kw[i])) > 0) {
361 if (i != 9 && !select_media_dbr(ua, &mr)) {
366 update_volstatus(ua, ua->argv[j], &mr);
369 update_volretention(ua, ua->argv[j], &mr);
372 update_voluseduration(ua, ua->argv[j], &mr);
375 update_volmaxjobs(ua, ua->argv[j], &mr);
378 update_volmaxfiles(ua, ua->argv[j], &mr);
381 update_volmaxbytes(ua, ua->argv[j], &mr);
384 update_volrecycle(ua, ua->argv[j], &mr);
387 memset(&pr, 0, sizeof(POOL_DBR));
388 pr.PoolId = mr.PoolId;
389 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
390 bsendmsg(ua, "%s", db_strerror(ua->db));
393 update_vol_pool(ua, ua->argv[j], &mr, &pr);
396 update_vol_from_pool(ua, &mr);
399 update_all_vols_from_pool(ua);
407 bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName);
408 start_prompt(ua, _("Parameters to modify:\n"));
409 add_prompt(ua, _("Volume Status"));
410 add_prompt(ua, _("Volume Retention Period"));
411 add_prompt(ua, _("Volume Use Duration"));
412 add_prompt(ua, _("Maximum Volume Jobs"));
413 add_prompt(ua, _("Maximum Volume Files"));
414 add_prompt(ua, _("Maximum Volume Bytes"));
415 add_prompt(ua, _("Recycle Flag"));
416 add_prompt(ua, _("Slot"));
417 add_prompt(ua, _("InChanger Flag"));
418 add_prompt(ua, _("Volume Files"));
419 add_prompt(ua, _("Pool"));
420 add_prompt(ua, _("Volume from Pool"));
421 add_prompt(ua, _("All Volumes from Pool"));
422 add_prompt(ua, _("Done"));
423 i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);
424 /* For All Volumes from Pool we don't need a Volume record */
426 if (!select_media_dbr(ua, &mr)) { /* Get Volume record */
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, N_("Append"));
436 add_prompt(ua, N_("Archive"));
437 add_prompt(ua, N_("Disabled"));
438 add_prompt(ua, N_("Full"));
439 add_prompt(ua, N_("Used"));
440 add_prompt(ua, N_("Cleaning"));
441 if (strcmp(mr.VolStatus, N_("Purged")) == 0) {
442 add_prompt(ua, N_("Recycle"));
444 add_prompt(ua, N_("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 MaxVols=%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_vol_from_pool(ua, &mr);
595 update_all_vols_from_pool(ua);
597 default: /* Done or error */
598 bsendmsg(ua, _("Selection terminated.\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"));