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 set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op);
33 void update_slots(UAContext *ua);
37 /* Forward referenced functions */
38 static int update_volume(UAContext *ua);
39 static int update_pool(UAContext *ua);
42 * Update a Pool Record in the database.
43 * It is always updated from the Resource record.
45 * update pool=<pool-name>
46 * updates pool from Pool resource
47 * update media pool=<pool-name> volume=<volume-name>
48 * changes pool info for volume
49 * update slots [scan=...]
50 * updates autochanger slots
52 int update_cmd(UAContext *ua, const char *cmd)
54 static const char *kw[] = {
65 switch (find_arg_keyword(ua, kw)) {
80 start_prompt(ua, _("Update choice:\n"));
81 add_prompt(ua, _("Volume parameters"));
82 add_prompt(ua, _("Pool from resource"));
83 add_prompt(ua, _("Slots from autochanger"));
84 switch (do_prompt(ua, _("item"), _("Choose catalog item to update"), NULL, 0)) {
100 static void update_volstatus(UAContext *ua, const char *val, MEDIA_DBR *mr)
102 POOL_MEM query(PM_MESSAGE);
116 for (i=0; kw[i]; i++) {
117 if (strcasecmp(val, kw[i]) == 0) {
123 bsendmsg(ua, _("Invalid VolStatus specified: %s\n"), val);
126 bstrncpy(mr->VolStatus, kw[i], sizeof(mr->VolStatus));
127 Mmsg(query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%s",
128 mr->VolStatus, edit_int64(mr->MediaId,ed1));
129 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
130 bsendmsg(ua, "%s", db_strerror(ua->db));
132 bsendmsg(ua, _("New Volume status is: %s\n"), mr->VolStatus);
137 static void update_volretention(UAContext *ua, char *val, MEDIA_DBR *mr)
139 char ed1[150], ed2[50];
140 POOL_MEM query(PM_MESSAGE);
141 if (!duration_to_utime(val, &mr->VolRetention)) {
142 bsendmsg(ua, _("Invalid retention period specified: %s\n"), val);
145 Mmsg(query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%s",
146 edit_uint64(mr->VolRetention, ed1), edit_int64(mr->MediaId,ed2));
147 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
148 bsendmsg(ua, "%s", db_strerror(ua->db));
150 bsendmsg(ua, _("New retention period is: %s\n"),
151 edit_utime(mr->VolRetention, ed1, sizeof(ed1)));
155 static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr)
157 char ed1[150], ed2[50];
158 POOL_MEM query(PM_MESSAGE);
160 if (!duration_to_utime(val, &mr->VolUseDuration)) {
161 bsendmsg(ua, _("Invalid use duration specified: %s\n"), val);
164 Mmsg(query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%s",
165 edit_uint64(mr->VolUseDuration, ed1), edit_int64(mr->MediaId,ed2));
166 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
167 bsendmsg(ua, "%s", db_strerror(ua->db));
169 bsendmsg(ua, _("New use duration is: %s\n"),
170 edit_utime(mr->VolUseDuration, ed1, sizeof(ed1)));
174 static void update_volmaxjobs(UAContext *ua, char *val, MEDIA_DBR *mr)
176 POOLMEM *query = get_pool_memory(PM_MESSAGE);
178 Mmsg(query, "UPDATE Media SET MaxVolJobs=%s WHERE MediaId=%s",
179 val, edit_int64(mr->MediaId,ed1));
180 if (!db_sql_query(ua->db, query, NULL, NULL)) {
181 bsendmsg(ua, "%s", db_strerror(ua->db));
183 bsendmsg(ua, _("New max jobs is: %s\n"), val);
185 free_pool_memory(query);
188 static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr)
190 POOLMEM *query = get_pool_memory(PM_MESSAGE);
192 Mmsg(query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%s",
193 val, edit_int64(mr->MediaId, ed1));
194 if (!db_sql_query(ua->db, query, NULL, NULL)) {
195 bsendmsg(ua, "%s", db_strerror(ua->db));
197 bsendmsg(ua, _("New max files is: %s\n"), val);
199 free_pool_memory(query);
202 static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr)
205 char ed1[50], ed2[50];
208 if (!size_to_uint64(val, strlen(val), &maxbytes)) {
209 bsendmsg(ua, _("Invalid max. bytes specification: %s\n"), val);
212 query = get_pool_memory(PM_MESSAGE);
213 Mmsg(query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%s",
214 edit_uint64(maxbytes, ed1), edit_int64(mr->MediaId, ed2));
215 if (!db_sql_query(ua->db, query, NULL, NULL)) {
216 bsendmsg(ua, "%s", db_strerror(ua->db));
218 bsendmsg(ua, _("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1));
220 free_pool_memory(query);
223 static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr)
228 if (strcasecmp(val, _("yes")) == 0) {
230 } else if (strcasecmp(val, _("no")) == 0) {
233 bsendmsg(ua, _("Invalid value. It must by yes or no.\n"));
236 query = get_pool_memory(PM_MESSAGE);
237 Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%s",
238 recycle, edit_int64(mr->MediaId, ed1));
239 if (!db_sql_query(ua->db, query, NULL, NULL)) {
240 bsendmsg(ua, "%s", db_strerror(ua->db));
242 bsendmsg(ua, _("New Recycle flag is: %s\n"),
243 mr->Recycle==1?_("yes"):_("no"));
245 free_pool_memory(query);
248 /* Modify the Pool in which this Volume is located */
249 static void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr)
253 char ed1[50], ed2[50];
255 memset(&pr, 0, sizeof(pr));
256 bstrncpy(pr.Name, val, sizeof(pr.Name));
257 if (!get_pool_dbr(ua, &pr)) {
260 mr->PoolId = pr.PoolId; /* set new PoolId */
263 query = get_pool_memory(PM_MESSAGE);
265 Mmsg(query, "UPDATE Media SET PoolId=%s WHERE MediaId=%s",
266 edit_int64(mr->PoolId, ed1),
267 edit_int64(mr->MediaId, ed2));
268 if (!db_sql_query(ua->db, query, NULL, NULL)) {
269 bsendmsg(ua, "%s", db_strerror(ua->db));
271 bsendmsg(ua, _("New Pool is: %s\n"), pr.Name);
273 if (!db_update_pool_record(ua->jcr, ua->db, opr)) {
274 bsendmsg(ua, "%s", db_strerror(ua->db));
277 if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
278 bsendmsg(ua, "%s", db_strerror(ua->db));
282 free_pool_memory(query);
286 * Refresh the Volume information from the Pool record
288 static void update_vol_from_pool(UAContext *ua, MEDIA_DBR *mr)
292 memset(&pr, 0, sizeof(pr));
293 pr.PoolId = mr->PoolId;
294 if (!db_get_pool_record(ua->jcr, ua->db, &pr) ||
295 !acl_access_ok(ua, Pool_ACL, pr.Name)) {
298 set_pool_dbr_defaults_in_media_dbr(mr, &pr);
299 if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
300 bsendmsg(ua, _("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
302 bsendmsg(ua, _("Volume defaults updated from \"%s\" Pool record.\n"),
308 * Refresh the Volume information from the Pool record
311 static void update_all_vols_from_pool(UAContext *ua)
316 memset(&pr, 0, sizeof(pr));
317 memset(&mr, 0, sizeof(mr));
318 if (!get_pool_dbr(ua, &pr)) {
321 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
322 mr.PoolId = pr.PoolId;
323 if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
324 bsendmsg(ua, _("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
326 bsendmsg(ua, _("All Volume defaults updated from Pool record.\n"));
332 * Update a media record -- allows you to change the
333 * Volume status. E.g. if you want Bacula to stop
334 * writing on the volume, set it to anything other
337 static int update_volume(UAContext *ua)
346 _("VolStatus"), /* 0 */
347 _("VolRetention"), /* 1 */
349 _("MaxVolJobs"), /* 3 */
350 _("MaxVolFiles"), /* 4 */
351 _("MaxVolBytes"), /* 5 */
352 _("Recycle"), /* 6 */
354 _("FromPool"), /* 8 */
355 _("AllFromPool"), /* 9 */
358 for (i=0; kw[i]; i++) {
361 if ((j=find_arg_with_value(ua, kw[i])) > 0) {
362 if (i != 9 && !select_media_dbr(ua, &mr)) {
367 update_volstatus(ua, ua->argv[j], &mr);
370 update_volretention(ua, ua->argv[j], &mr);
373 update_voluseduration(ua, ua->argv[j], &mr);
376 update_volmaxjobs(ua, ua->argv[j], &mr);
379 update_volmaxfiles(ua, ua->argv[j], &mr);
382 update_volmaxbytes(ua, ua->argv[j], &mr);
385 update_volrecycle(ua, ua->argv[j], &mr);
388 memset(&pr, 0, sizeof(POOL_DBR));
389 pr.PoolId = mr.PoolId;
390 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
391 bsendmsg(ua, "%s", db_strerror(ua->db));
394 update_vol_pool(ua, ua->argv[j], &mr, &pr);
397 update_vol_from_pool(ua, &mr);
400 update_all_vols_from_pool(ua);
408 bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName);
409 start_prompt(ua, _("Parameters to modify:\n"));
410 add_prompt(ua, _("Volume Status"));
411 add_prompt(ua, _("Volume Retention Period"));
412 add_prompt(ua, _("Volume Use Duration"));
413 add_prompt(ua, _("Maximum Volume Jobs"));
414 add_prompt(ua, _("Maximum Volume Files"));
415 add_prompt(ua, _("Maximum Volume Bytes"));
416 add_prompt(ua, _("Recycle Flag"));
417 add_prompt(ua, _("Slot"));
418 add_prompt(ua, _("InChanger Flag"));
419 add_prompt(ua, _("Volume Files"));
420 add_prompt(ua, _("Pool"));
421 add_prompt(ua, _("Volume from Pool"));
422 add_prompt(ua, _("All Volumes from Pool"));
423 add_prompt(ua, _("Done"));
424 i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);
425 /* For All Volumes from Pool we don't need a Volume record */
427 if (!select_media_dbr(ua, &mr)) { /* Get Volume record */
432 case 0: /* Volume Status */
433 /* Modify Volume Status */
434 bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus);
435 start_prompt(ua, _("Possible Values are:\n"));
436 add_prompt(ua, N_("Append"));
437 add_prompt(ua, N_("Archive"));
438 add_prompt(ua, N_("Disabled"));
439 add_prompt(ua, N_("Full"));
440 add_prompt(ua, N_("Used"));
441 add_prompt(ua, N_("Cleaning"));
442 if (strcmp(mr.VolStatus, N_("Purged")) == 0) {
443 add_prompt(ua, N_("Recycle"));
445 add_prompt(ua, N_("Read-Only"));
446 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
449 update_volstatus(ua, ua->cmd, &mr);
451 case 1: /* Retention */
452 bsendmsg(ua, _("Current retention period is: %s\n"),
453 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
454 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
457 update_volretention(ua, ua->cmd, &mr);
460 case 2: /* Use Duration */
461 bsendmsg(ua, _("Current use duration is: %s\n"),
462 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
463 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
466 update_voluseduration(ua, ua->cmd, &mr);
469 case 3: /* Max Jobs */
470 bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs);
471 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
474 update_volmaxjobs(ua, ua->cmd, &mr);
477 case 4: /* Max Files */
478 bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles);
479 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
482 update_volmaxfiles(ua, ua->cmd, &mr);
485 case 5: /* Max Bytes */
486 bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
487 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
490 update_volmaxbytes(ua, ua->cmd, &mr);
494 case 6: /* Recycle */
495 bsendmsg(ua, _("Current recycle flag is: %s\n"),
496 mr.Recycle==1?_("yes"):_("no"));
497 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
500 update_volrecycle(ua, ua->cmd, &mr);
506 memset(&pr, 0, sizeof(POOL_DBR));
507 pr.PoolId = mr.PoolId;
508 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
509 bsendmsg(ua, "%s", db_strerror(ua->db));
512 bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot);
513 if (!get_pint(ua, _("Enter new Slot: "))) {
516 Slot = ua->pint32_val;
517 if (pr.MaxVols > 0 && Slot > (int)pr.MaxVols) {
518 bsendmsg(ua, _("Invalid slot, it must be between 0 and %d\n"),
524 * Make sure to use db_update... rather than doing this directly,
525 * so that any Slot is handled correctly.
527 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
528 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
530 bsendmsg(ua, _("New Slot is: %d\n"), mr.Slot);
534 case 8: /* InChanger */
535 bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger);
536 if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) {
539 mr.InChanger = ua->pint32_val;
541 * Make sure to use db_update... rather than doing this directly,
542 * so that any Slot is handled correctly.
544 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
545 bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
547 bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger);
552 case 9: /* Volume Files */
554 bsendmsg(ua, _("Warning changing Volume Files can result\n"
555 "in loss of data on your Volume\n\n"));
556 bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles);
557 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
560 VolFiles = ua->pint32_val;
561 if (VolFiles != (int)(mr.VolFiles + 1)) {
562 bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n"));
563 if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) {
567 query = get_pool_memory(PM_MESSAGE);
568 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
569 VolFiles, edit_int64(mr.MediaId, ed1));
570 if (!db_sql_query(ua->db, query, NULL, NULL)) {
571 bsendmsg(ua, "%s", db_strerror(ua->db));
573 bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles);
575 free_pool_memory(query);
578 case 10: /* Volume's Pool */
579 memset(&pr, 0, sizeof(POOL_DBR));
580 pr.PoolId = mr.PoolId;
581 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
582 bsendmsg(ua, "%s", db_strerror(ua->db));
585 bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name);
586 if (!get_cmd(ua, _("Enter new Pool name: "))) {
589 update_vol_pool(ua, ua->cmd, &mr, &pr);
593 update_vol_from_pool(ua, &mr);
596 update_all_vols_from_pool(ua);
598 default: /* Done or error */
599 bsendmsg(ua, _("Selection terminated.\n"));
607 * Update pool record -- pull info from current POOL resource
609 static int update_pool(UAContext *ua)
617 pool = get_pool_resource(ua);
622 memset(&pr, 0, sizeof(pr));
623 bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name));
624 if (!get_pool_dbr(ua, &pr)) {
628 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
630 id = db_update_pool_record(ua->jcr, ua->db, &pr);
632 bsendmsg(ua, _("db_update_pool_record returned %d. ERR=%s\n"),
633 id, db_strerror(ua->db));
635 query = get_pool_memory(PM_MESSAGE);
636 Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
637 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
638 free_pool_memory(query);
639 bsendmsg(ua, _("Pool DB record updated from resource.\n"));