From 302dfead2527aa144413e99c2eab759d63de22ea Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Thu, 10 Mar 2005 16:52:42 +0000 Subject: [PATCH] - Add new ua_update.c file and move update_cmd there. - Modify update slots to obtain actual number of slots. - Tweak autochanger code to handle new slots request. - Modify autochanger code to lock/unlock around slots and update slots code. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1880 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 2 + bacula/src/dird/Makefile.in | 4 +- bacula/src/dird/ua_cmds.c | 610 +----------------------------- bacula/src/dird/ua_label.c | 67 +++- bacula/src/dird/ua_update.c | 644 ++++++++++++++++++++++++++++++++ bacula/src/lib/mem_pool.c | 10 +- bacula/src/lib/watchdog.c | 2 +- bacula/src/stored/autochanger.c | 87 +++-- bacula/src/stored/dircmd.c | 19 +- bacula/src/stored/protos.h | 2 +- bacula/src/version.h | 4 +- 11 files changed, 787 insertions(+), 664 deletions(-) create mode 100644 bacula/src/dird/ua_update.c diff --git a/bacula/kernstodo b/bacula/kernstodo index 19c71756fb..8aa0c23488 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -219,6 +219,8 @@ Why: format string. Then I have the tape labeled automatically with weekday name in the correct language. ========== +- Make output from status use html table tags for nicely + presenting in a browser. - Can one write tapes faster with 8192 byte block sizes? - Specify a single directory to restore. - Document security problems with the same password for everyone in diff --git a/bacula/src/dird/Makefile.in b/bacula/src/dird/Makefile.in index 487913c77e..b5c6d9f1b2 100644 --- a/bacula/src/dird/Makefile.in +++ b/bacula/src/dird/Makefile.in @@ -39,7 +39,7 @@ SVRSRCS = dird.c admin.c authenticate.c \ ua_input.c ua_label.c ua_output.c ua_prune.c \ ua_purge.c ua_restore.c ua_run.c \ ua_select.c ua_server.c \ - ua_status.c ua_tree.c verify.c + ua_status.c ua_tree.c ua_update.c verify.c SVROBJS = dird.o admin.o authenticate.o \ autoprune.o backup.o bsr.o \ catreq.o dird_conf.o expand.o \ @@ -54,7 +54,7 @@ SVROBJS = dird.o admin.o authenticate.o \ ua_input.o ua_label.o ua_output.o ua_prune.o \ ua_purge.o ua_restore.o ua_run.o \ ua_select.o ua_server.o \ - ua_status.o ua_tree.o verify.o + ua_status.o ua_tree.o ua_update.o verify.o # these are the objects that are changed by the .configure process EXTRAOBJS = @OBJLIST@ diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 13e19c9478..d0844f9d10 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -40,8 +40,6 @@ extern char my_name[]; extern jobq_t job_queue; /* job queue */ -extern char *list_pool; - /* Imported functions */ extern int status_cmd(UAContext *ua, const char *cmd); extern int list_cmd(UAContext *ua, const char *cmd); @@ -58,7 +56,7 @@ extern int purgecmd(UAContext *ua, const char *cmd); extern int restore_cmd(UAContext *ua, const char *cmd); extern int label_cmd(UAContext *ua, const char *cmd); extern int relabel_cmd(UAContext *ua, const char *cmd); -extern int update_slots(UAContext *ua); /* ua_label.c */ +extern int update_cmd(UAContext *ua, const char *cmd); /* Forward referenced functions */ static int add_cmd(UAContext *ua, const char *cmd); @@ -76,14 +74,11 @@ static int version_cmd(UAContext *ua, const char *cmd); static int automount_cmd(UAContext *ua, const char *cmd); static int time_cmd(UAContext *ua, const char *cmd); static int reload_cmd(UAContext *ua, const char *cmd); -static int update_volume(UAContext *ua); -static int update_pool(UAContext *ua); static int delete_volume(UAContext *ua); static int delete_pool(UAContext *ua); static void delete_job(UAContext *ua); static int mount_cmd(UAContext *ua, const char *cmd); static int release_cmd(UAContext *ua, const char *cmd); -static int update_cmd(UAContext *ua, const char *cmd); static int wait_cmd(UAContext *ua, const char *cmd); static int setip_cmd(UAContext *ua, const char *cmd); static int python_cmd(UAContext *ua, const char *cmd); @@ -462,7 +457,7 @@ static int cancel_cmd(UAContext *ua, const char *cmd) * depending on if we are creating the Pool or we are * simply bringing it into agreement with the resource (updage). */ -static void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op) +void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op) { bstrncpy(pr->PoolType, pool->pool_type, sizeof(pr->PoolType)); if (op == POOL_OP_CREATE) { @@ -620,607 +615,6 @@ get_out: } -/* - * Update a Pool Record in the database. - * It is always updated from the Resource record. - * - * update pool= - * updates pool from Pool resource - * update media pool= volume= - * changes pool info for volume - * update slots [scan=...] - * updates autochanger slots - */ -static int update_cmd(UAContext *ua, const char *cmd) -{ - static const char *kw[] = { - N_("media"), /* 0 */ - N_("volume"), /* 1 */ - N_("pool"), /* 2 */ - N_("slots"), /* 3 */ - NULL}; - - if (!open_db(ua)) { - return 1; - } - - switch (find_arg_keyword(ua, kw)) { - case 0: - case 1: - update_volume(ua); - return 1; - case 2: - update_pool(ua); - return 1; - case 3: - update_slots(ua); - return 1; - default: - break; - } - - start_prompt(ua, _("Update choice:\n")); - add_prompt(ua, _("Volume parameters")); - add_prompt(ua, _("Pool from resource")); - add_prompt(ua, _("Slots from autochanger")); - switch (do_prompt(ua, _("item"), _("Choose catalog item to update"), NULL, 0)) { - case 0: - update_volume(ua); - break; - case 1: - update_pool(ua); - break; - case 2: - update_slots(ua); - break; - default: - break; - } - return 1; -} - -static void update_volstatus(UAContext *ua, const char *val, MEDIA_DBR *mr) -{ - POOLMEM *query = get_pool_memory(PM_MESSAGE); - const char *kw[] = { - "Append", - "Archive", - "Disabled", - "Full", - "Used", - "Cleaning", - "Recycle", - "Read-Only", - NULL}; - bool found = false; - int i; - - for (i=0; kw[i]; i++) { - if (strcasecmp(val, kw[i]) == 0) { - found = true; - break; - } - } - if (!found) { - bsendmsg(ua, _("Invalid VolStatus specified: %s\n"), val); - } else { - char ed1[50]; - bstrncpy(mr->VolStatus, kw[i], sizeof(mr->VolStatus)); - Mmsg(query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%s", - mr->VolStatus, edit_int64(mr->MediaId,ed1)); - if (!db_sql_query(ua->db, query, NULL, NULL)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); - } else { - bsendmsg(ua, _("New Volume status is: %s\n"), mr->VolStatus); - } - } - free_pool_memory(query); -} - -static void update_volretention(UAContext *ua, char *val, MEDIA_DBR *mr) -{ - char ed1[150], ed2[50]; - POOLMEM *query; - if (!duration_to_utime(val, &mr->VolRetention)) { - bsendmsg(ua, _("Invalid retention period specified: %s\n"), val); - return; - } - query = get_pool_memory(PM_MESSAGE); - Mmsg(query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%s", - edit_uint64(mr->VolRetention, ed1), edit_int64(mr->MediaId,ed2)); - if (!db_sql_query(ua->db, query, NULL, NULL)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); - } else { - bsendmsg(ua, _("New retention period is: %s\n"), - edit_utime(mr->VolRetention, ed1, sizeof(ed1))); - } - free_pool_memory(query); -} - -static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr) -{ - char ed1[150], ed2[50]; - POOLMEM *query; - - if (!duration_to_utime(val, &mr->VolUseDuration)) { - bsendmsg(ua, _("Invalid use duration specified: %s\n"), val); - return; - } - query = get_pool_memory(PM_MESSAGE); - Mmsg(query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%s", - edit_uint64(mr->VolUseDuration, ed1), edit_int64(mr->MediaId,ed2)); - if (!db_sql_query(ua->db, query, NULL, NULL)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); - } else { - bsendmsg(ua, _("New use duration is: %s\n"), - edit_utime(mr->VolUseDuration, ed1, sizeof(ed1))); - } - free_pool_memory(query); -} - -static void update_volmaxjobs(UAContext *ua, char *val, MEDIA_DBR *mr) -{ - POOLMEM *query = get_pool_memory(PM_MESSAGE); - char ed1[50]; - Mmsg(query, "UPDATE Media SET MaxVolJobs=%s WHERE MediaId=%s", - val, edit_int64(mr->MediaId,ed1)); - if (!db_sql_query(ua->db, query, NULL, NULL)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); - } else { - bsendmsg(ua, _("New max jobs is: %s\n"), val); - } - free_pool_memory(query); -} - -static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr) -{ - POOLMEM *query = get_pool_memory(PM_MESSAGE); - char ed1[50]; - Mmsg(query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%s", - val, edit_int64(mr->MediaId, ed1)); - if (!db_sql_query(ua->db, query, NULL, NULL)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); - } else { - bsendmsg(ua, _("New max files is: %s\n"), val); - } - free_pool_memory(query); -} - -static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr) -{ - uint64_t maxbytes; - char ed1[50], ed2[50]; - POOLMEM *query; - - if (!size_to_uint64(val, strlen(val), &maxbytes)) { - bsendmsg(ua, _("Invalid max. bytes specification: %s\n"), val); - return; - } - query = get_pool_memory(PM_MESSAGE); - Mmsg(query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%s", - edit_uint64(maxbytes, ed1), edit_int64(mr->MediaId, ed2)); - if (!db_sql_query(ua->db, query, NULL, NULL)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); - } else { - bsendmsg(ua, _("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1)); - } - free_pool_memory(query); -} - -static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr) -{ - int recycle; - char ed1[50]; - POOLMEM *query; - if (strcasecmp(val, _("yes")) == 0) { - recycle = 1; - } else if (strcasecmp(val, _("no")) == 0) { - recycle = 0; - } else { - bsendmsg(ua, _("Invalid value. It must by yes or no.\n")); - return; - } - query = get_pool_memory(PM_MESSAGE); - Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%s", - recycle, edit_int64(mr->MediaId, ed1)); - if (!db_sql_query(ua->db, query, NULL, NULL)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); - } else { - bsendmsg(ua, _("New Recycle flag is: %s\n"), - mr->Recycle==1?_("yes"):_("no")); - } - free_pool_memory(query); -} - -/* Modify the Pool in which this Volume is located */ -static void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr) -{ - POOL_DBR pr; - POOLMEM *query; - char ed1[50]; - - memset(&pr, 0, sizeof(pr)); - bstrncpy(pr.Name, val, sizeof(pr.Name)); - if (!get_pool_dbr(ua, &pr)) { - return; - } - mr->PoolId = pr.PoolId; /* set new PoolId */ - /* - */ - query = get_pool_memory(PM_MESSAGE); - db_lock(ua->db); - Mmsg(query, "UPDATE Media SET PoolId=%d WHERE MediaId=%s", - mr->PoolId, edit_int64(mr->MediaId, ed1)); - if (!db_sql_query(ua->db, query, NULL, NULL)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); - } else { - bsendmsg(ua, _("New Pool is: %s\n"), pr.Name); - opr->NumVols--; - if (!db_update_pool_record(ua->jcr, ua->db, opr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); - } - pr.NumVols++; - if (!db_update_pool_record(ua->jcr, ua->db, &pr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); - } - } - db_unlock(ua->db); - free_pool_memory(query); -} - -/* - * Refresh the Volume information from the Pool record - */ -static void update_volfrompool(UAContext *ua, MEDIA_DBR *mr) -{ - POOL_DBR pr; - - memset(&pr, 0, sizeof(pr)); - pr.PoolId = mr->PoolId; - if (!db_get_pool_record(ua->jcr, ua->db, &pr) || - !acl_access_ok(ua, Pool_ACL, pr.Name)) { - return; - } - set_pool_dbr_defaults_in_media_dbr(mr, &pr); - if (!db_update_media_defaults(ua->jcr, ua->db, mr)) { - bsendmsg(ua, _("Error updating Volume record: ERR=%s"), db_strerror(ua->db)); - } else { - bsendmsg(ua, _("Volume defaults updated from \"%s\" Pool record.\n"), - pr.Name); - } -} - -/* - * Refresh the Volume information from the Pool record - * for all Volumes - */ -static void update_all_vols_from_pool(UAContext *ua) -{ - POOL_DBR pr; - MEDIA_DBR mr; - - memset(&pr, 0, sizeof(pr)); - memset(&mr, 0, sizeof(mr)); - if (!get_pool_dbr(ua, &pr)) { - return; - } - set_pool_dbr_defaults_in_media_dbr(&mr, &pr); - mr.PoolId = pr.PoolId; - if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, _("Error updating Volume records: ERR=%s"), db_strerror(ua->db)); - } else { - bsendmsg(ua, _("All Volume defaults updated from Pool record.\n")); - } -} - - -/* - * Update a media record -- allows you to change the - * Volume status. E.g. if you want Bacula to stop - * writing on the volume, set it to anything other - * than Append. - */ -static int update_volume(UAContext *ua) -{ - MEDIA_DBR mr; - POOL_DBR pr; - POOLMEM *query; - char ed1[130]; - bool done = false; - const char *kw[] = { - N_("VolStatus"), /* 0 */ - N_("VolRetention"), /* 1 */ - N_("VolUse"), /* 2 */ - N_("MaxVolJobs"), /* 3 */ - N_("MaxVolFiles"), /* 4 */ - N_("MaxVolBytes"), /* 5 */ - N_("Recycle"), /* 6 */ - N_("Pool"), /* 7 */ - N_("FromPool"), /* 8 */ - N_("AllFromPool"), /* 9 */ - NULL }; - - for (int i=0; kw[i]; i++) { - int j; - POOL_DBR pr; - if ((j=find_arg_with_value(ua, kw[i])) > 0) { - if (i != 9 && !select_media_dbr(ua, &mr)) { - return 0; - } - switch (i) { - case 0: - update_volstatus(ua, ua->argv[j], &mr); - break; - case 1: - update_volretention(ua, ua->argv[j], &mr); - break; - case 2: - update_voluseduration(ua, ua->argv[j], &mr); - break; - case 3: - update_volmaxjobs(ua, ua->argv[j], &mr); - break; - case 4: - update_volmaxfiles(ua, ua->argv[j], &mr); - break; - case 5: - update_volmaxbytes(ua, ua->argv[j], &mr); - break; - case 6: - update_volrecycle(ua, ua->argv[j], &mr); - break; - case 7: - memset(&pr, 0, sizeof(POOL_DBR)); - pr.PoolId = mr.PoolId; - if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); - break; - } - update_vol_pool(ua, ua->argv[j], &mr, &pr); - break; - case 8: - update_volfrompool(ua, &mr); - return 1; - case 9: - update_all_vols_from_pool(ua); - return 1; - } - done = true; - } - } - - for ( ; !done; ) { - if (!select_media_dbr(ua, &mr)) { - return 0; - } - bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName); - start_prompt(ua, _("Parameters to modify:\n")); - add_prompt(ua, _("Volume Status")); - add_prompt(ua, _("Volume Retention Period")); - add_prompt(ua, _("Volume Use Duration")); - add_prompt(ua, _("Maximum Volume Jobs")); - add_prompt(ua, _("Maximum Volume Files")); - add_prompt(ua, _("Maximum Volume Bytes")); - add_prompt(ua, _("Recycle Flag")); - add_prompt(ua, _("Slot")); - add_prompt(ua, _("InChanger Flag")); - add_prompt(ua, _("Volume Files")); - add_prompt(ua, _("Pool")); - add_prompt(ua, _("Volume from Pool")); - add_prompt(ua, _("All Volumes from Pool")); - add_prompt(ua, _("Done")); - switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) { - case 0: /* Volume Status */ - /* Modify Volume Status */ - bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus); - start_prompt(ua, _("Possible Values are:\n")); - add_prompt(ua, "Append"); /* Better not translate these as */ - add_prompt(ua, "Archive"); /* They are known in the database code */ - add_prompt(ua, "Disabled"); - add_prompt(ua, "Full"); - add_prompt(ua, "Used"); - add_prompt(ua, "Cleaning"); - if (strcmp(mr.VolStatus, "Purged") == 0) { - add_prompt(ua, "Recycle"); - } - add_prompt(ua, "Read-Only"); - if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) { - return 1; - } - update_volstatus(ua, ua->cmd, &mr); - break; - case 1: /* Retention */ - bsendmsg(ua, _("Current retention period is: %s\n"), - edit_utime(mr.VolRetention, ed1, sizeof(ed1))); - if (!get_cmd(ua, _("Enter Volume Retention period: "))) { - return 0; - } - update_volretention(ua, ua->cmd, &mr); - break; - - case 2: /* Use Duration */ - bsendmsg(ua, _("Current use duration is: %s\n"), - edit_utime(mr.VolUseDuration, ed1, sizeof(ed1))); - if (!get_cmd(ua, _("Enter Volume Use Duration: "))) { - return 0; - } - update_voluseduration(ua, ua->cmd, &mr); - break; - - case 3: /* Max Jobs */ - bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs); - if (!get_pint(ua, _("Enter new Maximum Jobs: "))) { - return 0; - } - update_volmaxjobs(ua, ua->cmd, &mr); - break; - - case 4: /* Max Files */ - bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles); - if (!get_pint(ua, _("Enter new Maximum Files: "))) { - return 0; - } - update_volmaxfiles(ua, ua->cmd, &mr); - break; - - case 5: /* Max Bytes */ - bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1)); - if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) { - return 0; - } - update_volmaxbytes(ua, ua->cmd, &mr); - break; - - - case 6: /* Recycle */ - bsendmsg(ua, _("Current recycle flag is: %s\n"), - mr.Recycle==1?_("yes"):_("no")); - if (!get_yesno(ua, _("Enter new Recycle status: "))) { - return 0; - } - update_volrecycle(ua, ua->cmd, &mr); - break; - - case 7: /* Slot */ - int Slot; - - memset(&pr, 0, sizeof(POOL_DBR)); - pr.PoolId = mr.PoolId; - if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); - return 0; - } - bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot); - if (!get_pint(ua, _("Enter new Slot: "))) { - return 0; - } - Slot = ua->pint32_val; - if (pr.MaxVols > 0 && Slot > (int)pr.MaxVols) { - bsendmsg(ua, _("Invalid slot, it must be between 0 and %d\n"), - pr.MaxVols); - break; - } - mr.Slot = Slot; - /* - * Make sure to use db_update... rather than doing this directly, - * so that any Slot is handled correctly. - */ - if (!db_update_media_record(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db)); - } else { - bsendmsg(ua, _("New Slot is: %d\n"), mr.Slot); - } - break; - - case 8: /* InChanger */ - bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger); - if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) { - return 0; - } - mr.InChanger = ua->pint32_val; - /* - * Make sure to use db_update... rather than doing this directly, - * so that any Slot is handled correctly. - */ - if (!db_update_media_record(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db)); - } else { - bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger); - } - break; - - - case 9: /* Volume Files */ - int32_t VolFiles; - bsendmsg(ua, _("Warning changing Volume Files can result\n" - "in loss of data on your Volume\n\n")); - bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles); - if (!get_pint(ua, _("Enter new number of Files for Volume: "))) { - return 0; - } - VolFiles = ua->pint32_val; - if (VolFiles != (int)(mr.VolFiles + 1)) { - bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n")); - if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) { - break; - } - } - query = get_pool_memory(PM_MESSAGE); - Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s", - VolFiles, edit_int64(mr.MediaId, ed1)); - if (!db_sql_query(ua->db, query, NULL, NULL)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); - } else { - bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles); - } - free_pool_memory(query); - break; - - case 10: /* Volume's Pool */ - memset(&pr, 0, sizeof(POOL_DBR)); - pr.PoolId = mr.PoolId; - if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); - return 0; - } - bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name); - if (!get_cmd(ua, _("Enter new Pool name: "))) { - return 0; - } - update_vol_pool(ua, ua->cmd, &mr, &pr); - return 1; - - case 11: - update_volfrompool(ua, &mr); - return 1; - case 12: - update_all_vols_from_pool(ua); - return 1; - default: /* Done or error */ - bsendmsg(ua, "Selection done.\n"); - return 1; - } - } - return 1; -} - -/* - * Update pool record -- pull info from current POOL resource - */ -static int update_pool(UAContext *ua) -{ - POOL_DBR pr; - int id; - POOL *pool; - POOLMEM *query; - - pool = get_pool_resource(ua); - if (!pool) { - return 0; - } - - memset(&pr, 0, sizeof(pr)); - bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name)); - if (!get_pool_dbr(ua, &pr)) { - return 0; - } - - set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */ - - id = db_update_pool_record(ua->jcr, ua->db, &pr); - if (id <= 0) { - bsendmsg(ua, _("db_update_pool_record returned %d. ERR=%s\n"), - id, db_strerror(ua->db)); - } - query = get_pool_memory(PM_MESSAGE); - Mmsg(query, list_pool, pr.PoolId); - db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST); - free_pool_memory(query); - bsendmsg(ua, _("Pool DB record updated from resource.\n")); - return 1; -} - - static void do_storage_setdebug(UAContext *ua, STORE *store, int level, int trace_flag) { BSOCK *sd; diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index 1fe5dc0647..bea22f84fe 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -49,6 +49,7 @@ static bool is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr); static BSOCK *open_sd_bsock(UAContext *ua); static void close_sd_bsock(UAContext *ua); static char *get_volume_name_from_SD(UAContext *ua, int Slot); +static int get_num_slots_from_SD(UAContext *ua); /* @@ -66,14 +67,12 @@ int relabel_cmd(UAContext *ua, const char *cmd) return do_label(ua, cmd, 1); /* relabel tape */ } -static int const max_slots = 5000; - static bool get_user_slot_list(UAContext *ua, char *slot_list, int num_slots) { int i; const char *msg; - for (int i=0; i= 0; - slot_list = (char *)malloc(max_slots); + max_slots = get_num_slots_from_SD(ua); + if (max_slots <= 0) { + bsendmsg(ua, _("No slots in changer to scan.\n")); + return 1; + } + slot_list = (char *)malloc(max_slots+1); if (!get_user_slot_list(ua, slot_list, max_slots)) { free(slot_list); return 1; @@ -189,8 +195,9 @@ int update_slots(UAContext *ua) /* Walk through the list updating the media records */ for (vl=vol_list; vl; vl=vl->next) { - if (vl->Slot >= max_slots) { - bsendmsg(ua, _("Slot %d larger than max %d ignored.\n")); + if (vl->Slot > max_slots) { + bsendmsg(ua, _("Slot %d larger than max %d ignored.\n"), + vl->Slot, max_slots); continue; } /* Check if user wants us to look at this slot */ @@ -252,7 +259,7 @@ int update_slots(UAContext *ua) mr.InChanger = 1; mr.StorageId = store->StorageId; db_lock(ua->db); - for (int i=1; ijcr->store; + char dev_name[MAX_NAME_LENGTH]; + BSOCK *sd; + int slots = 0; + + + if (!(sd=open_sd_bsock(ua))) { + return 0; + } + + bstrncpy(dev_name, store->dev_name(), sizeof(dev_name)); + bash_spaces(dev_name); + /* Ask for autochanger list of volumes */ + bnet_fsend(sd, _("autochanger slots %s \n"), dev_name); + + while (bnet_recv(sd) >= 0) { + if (sscanf(sd->msg, "slots=%d\n", &slots) == 1) { + break; + } else { + bsendmsg(ua, "%s", sd->msg); + } + } + close_sd_bsock(ua); + bsendmsg(ua, _("Device \"%s\" has %d slots.\n"), store->dev_name(), slots); + return slots; +} + + /* * Check if this is a cleaning tape by comparing the Volume name diff --git a/bacula/src/dird/ua_update.c b/bacula/src/dird/ua_update.c new file mode 100644 index 0000000000..b9a016c70a --- /dev/null +++ b/bacula/src/dird/ua_update.c @@ -0,0 +1,644 @@ +/* + * + * Bacula Director -- Update command processing + * Split from ua_cmds.c March 2005 + * + * Kern Sibbald, September MM + * + * Version $Id$ + */ + +/* + Copyright (C) 2000-2005 Kern Sibbald + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + */ + +#include "bacula.h" +#include "dird.h" + +/* External variables */ +extern char *list_pool; /* in sql_cmds.c */ + +/* Imported functions */ +void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op); +int update_slots(UAContext *ua); + + +/* Forward referenced functions */ +static int update_volume(UAContext *ua); +static int update_pool(UAContext *ua); + +/* + * Update a Pool Record in the database. + * It is always updated from the Resource record. + * + * update pool= + * updates pool from Pool resource + * update media pool= volume= + * changes pool info for volume + * update slots [scan=...] + * updates autochanger slots + */ +int update_cmd(UAContext *ua, const char *cmd) +{ + static const char *kw[] = { + N_("media"), /* 0 */ + N_("volume"), /* 1 */ + N_("pool"), /* 2 */ + N_("slots"), /* 3 */ + NULL}; + + if (!open_db(ua)) { + return 1; + } + + switch (find_arg_keyword(ua, kw)) { + case 0: + case 1: + update_volume(ua); + return 1; + case 2: + update_pool(ua); + return 1; + case 3: + update_slots(ua); + return 1; + default: + break; + } + + start_prompt(ua, _("Update choice:\n")); + add_prompt(ua, _("Volume parameters")); + add_prompt(ua, _("Pool from resource")); + add_prompt(ua, _("Slots from autochanger")); + switch (do_prompt(ua, _("item"), _("Choose catalog item to update"), NULL, 0)) { + case 0: + update_volume(ua); + break; + case 1: + update_pool(ua); + break; + case 2: + update_slots(ua); + break; + default: + break; + } + return 1; +} + +static void update_volstatus(UAContext *ua, const char *val, MEDIA_DBR *mr) +{ + POOLMEM *query = get_pool_memory(PM_MESSAGE); + const char *kw[] = { + "Append", + "Archive", + "Disabled", + "Full", + "Used", + "Cleaning", + "Recycle", + "Read-Only", + NULL}; + bool found = false; + int i; + + for (i=0; kw[i]; i++) { + if (strcasecmp(val, kw[i]) == 0) { + found = true; + break; + } + } + if (!found) { + bsendmsg(ua, _("Invalid VolStatus specified: %s\n"), val); + } else { + char ed1[50]; + bstrncpy(mr->VolStatus, kw[i], sizeof(mr->VolStatus)); + Mmsg(query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%s", + mr->VolStatus, edit_int64(mr->MediaId,ed1)); + if (!db_sql_query(ua->db, query, NULL, NULL)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } else { + bsendmsg(ua, _("New Volume status is: %s\n"), mr->VolStatus); + } + } + free_pool_memory(query); +} + +static void update_volretention(UAContext *ua, char *val, MEDIA_DBR *mr) +{ + char ed1[150], ed2[50]; + POOLMEM *query; + if (!duration_to_utime(val, &mr->VolRetention)) { + bsendmsg(ua, _("Invalid retention period specified: %s\n"), val); + return; + } + query = get_pool_memory(PM_MESSAGE); + Mmsg(query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%s", + edit_uint64(mr->VolRetention, ed1), edit_int64(mr->MediaId,ed2)); + if (!db_sql_query(ua->db, query, NULL, NULL)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } else { + bsendmsg(ua, _("New retention period is: %s\n"), + edit_utime(mr->VolRetention, ed1, sizeof(ed1))); + } + free_pool_memory(query); +} + +static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr) +{ + char ed1[150], ed2[50]; + POOLMEM *query; + + if (!duration_to_utime(val, &mr->VolUseDuration)) { + bsendmsg(ua, _("Invalid use duration specified: %s\n"), val); + return; + } + query = get_pool_memory(PM_MESSAGE); + Mmsg(query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%s", + edit_uint64(mr->VolUseDuration, ed1), edit_int64(mr->MediaId,ed2)); + if (!db_sql_query(ua->db, query, NULL, NULL)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } else { + bsendmsg(ua, _("New use duration is: %s\n"), + edit_utime(mr->VolUseDuration, ed1, sizeof(ed1))); + } + free_pool_memory(query); +} + +static void update_volmaxjobs(UAContext *ua, char *val, MEDIA_DBR *mr) +{ + POOLMEM *query = get_pool_memory(PM_MESSAGE); + char ed1[50]; + Mmsg(query, "UPDATE Media SET MaxVolJobs=%s WHERE MediaId=%s", + val, edit_int64(mr->MediaId,ed1)); + if (!db_sql_query(ua->db, query, NULL, NULL)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } else { + bsendmsg(ua, _("New max jobs is: %s\n"), val); + } + free_pool_memory(query); +} + +static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr) +{ + POOLMEM *query = get_pool_memory(PM_MESSAGE); + char ed1[50]; + Mmsg(query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%s", + val, edit_int64(mr->MediaId, ed1)); + if (!db_sql_query(ua->db, query, NULL, NULL)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } else { + bsendmsg(ua, _("New max files is: %s\n"), val); + } + free_pool_memory(query); +} + +static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr) +{ + uint64_t maxbytes; + char ed1[50], ed2[50]; + POOLMEM *query; + + if (!size_to_uint64(val, strlen(val), &maxbytes)) { + bsendmsg(ua, _("Invalid max. bytes specification: %s\n"), val); + return; + } + query = get_pool_memory(PM_MESSAGE); + Mmsg(query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%s", + edit_uint64(maxbytes, ed1), edit_int64(mr->MediaId, ed2)); + if (!db_sql_query(ua->db, query, NULL, NULL)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } else { + bsendmsg(ua, _("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1)); + } + free_pool_memory(query); +} + +static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr) +{ + int recycle; + char ed1[50]; + POOLMEM *query; + if (strcasecmp(val, _("yes")) == 0) { + recycle = 1; + } else if (strcasecmp(val, _("no")) == 0) { + recycle = 0; + } else { + bsendmsg(ua, _("Invalid value. It must by yes or no.\n")); + return; + } + query = get_pool_memory(PM_MESSAGE); + Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%s", + recycle, edit_int64(mr->MediaId, ed1)); + if (!db_sql_query(ua->db, query, NULL, NULL)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } else { + bsendmsg(ua, _("New Recycle flag is: %s\n"), + mr->Recycle==1?_("yes"):_("no")); + } + free_pool_memory(query); +} + +/* Modify the Pool in which this Volume is located */ +static void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr) +{ + POOL_DBR pr; + POOLMEM *query; + char ed1[50]; + + memset(&pr, 0, sizeof(pr)); + bstrncpy(pr.Name, val, sizeof(pr.Name)); + if (!get_pool_dbr(ua, &pr)) { + return; + } + mr->PoolId = pr.PoolId; /* set new PoolId */ + /* + */ + query = get_pool_memory(PM_MESSAGE); + db_lock(ua->db); + Mmsg(query, "UPDATE Media SET PoolId=%d WHERE MediaId=%s", + mr->PoolId, edit_int64(mr->MediaId, ed1)); + if (!db_sql_query(ua->db, query, NULL, NULL)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } else { + bsendmsg(ua, _("New Pool is: %s\n"), pr.Name); + opr->NumVols--; + if (!db_update_pool_record(ua->jcr, ua->db, opr)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } + pr.NumVols++; + if (!db_update_pool_record(ua->jcr, ua->db, &pr)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } + } + db_unlock(ua->db); + free_pool_memory(query); +} + +/* + * Refresh the Volume information from the Pool record + */ +static void update_volfrompool(UAContext *ua, MEDIA_DBR *mr) +{ + POOL_DBR pr; + + memset(&pr, 0, sizeof(pr)); + pr.PoolId = mr->PoolId; + if (!db_get_pool_record(ua->jcr, ua->db, &pr) || + !acl_access_ok(ua, Pool_ACL, pr.Name)) { + return; + } + set_pool_dbr_defaults_in_media_dbr(mr, &pr); + if (!db_update_media_defaults(ua->jcr, ua->db, mr)) { + bsendmsg(ua, _("Error updating Volume record: ERR=%s"), db_strerror(ua->db)); + } else { + bsendmsg(ua, _("Volume defaults updated from \"%s\" Pool record.\n"), + pr.Name); + } +} + +/* + * Refresh the Volume information from the Pool record + * for all Volumes + */ +static void update_all_vols_from_pool(UAContext *ua) +{ + POOL_DBR pr; + MEDIA_DBR mr; + + memset(&pr, 0, sizeof(pr)); + memset(&mr, 0, sizeof(mr)); + if (!get_pool_dbr(ua, &pr)) { + return; + } + set_pool_dbr_defaults_in_media_dbr(&mr, &pr); + mr.PoolId = pr.PoolId; + if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) { + bsendmsg(ua, _("Error updating Volume records: ERR=%s"), db_strerror(ua->db)); + } else { + bsendmsg(ua, _("All Volume defaults updated from Pool record.\n")); + } +} + + +/* + * Update a media record -- allows you to change the + * Volume status. E.g. if you want Bacula to stop + * writing on the volume, set it to anything other + * than Append. + */ +static int update_volume(UAContext *ua) +{ + MEDIA_DBR mr; + POOL_DBR pr; + POOLMEM *query; + char ed1[130]; + bool done = false; + const char *kw[] = { + N_("VolStatus"), /* 0 */ + N_("VolRetention"), /* 1 */ + N_("VolUse"), /* 2 */ + N_("MaxVolJobs"), /* 3 */ + N_("MaxVolFiles"), /* 4 */ + N_("MaxVolBytes"), /* 5 */ + N_("Recycle"), /* 6 */ + N_("Pool"), /* 7 */ + N_("FromPool"), /* 8 */ + N_("AllFromPool"), /* 9 */ + NULL }; + + for (int i=0; kw[i]; i++) { + int j; + POOL_DBR pr; + if ((j=find_arg_with_value(ua, kw[i])) > 0) { + if (i != 9 && !select_media_dbr(ua, &mr)) { + return 0; + } + switch (i) { + case 0: + update_volstatus(ua, ua->argv[j], &mr); + break; + case 1: + update_volretention(ua, ua->argv[j], &mr); + break; + case 2: + update_voluseduration(ua, ua->argv[j], &mr); + break; + case 3: + update_volmaxjobs(ua, ua->argv[j], &mr); + break; + case 4: + update_volmaxfiles(ua, ua->argv[j], &mr); + break; + case 5: + update_volmaxbytes(ua, ua->argv[j], &mr); + break; + case 6: + update_volrecycle(ua, ua->argv[j], &mr); + break; + case 7: + memset(&pr, 0, sizeof(POOL_DBR)); + pr.PoolId = mr.PoolId; + if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + break; + } + update_vol_pool(ua, ua->argv[j], &mr, &pr); + break; + case 8: + update_volfrompool(ua, &mr); + return 1; + case 9: + update_all_vols_from_pool(ua); + return 1; + } + done = true; + } + } + + for ( ; !done; ) { + if (!select_media_dbr(ua, &mr)) { + return 0; + } + bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName); + start_prompt(ua, _("Parameters to modify:\n")); + add_prompt(ua, _("Volume Status")); + add_prompt(ua, _("Volume Retention Period")); + add_prompt(ua, _("Volume Use Duration")); + add_prompt(ua, _("Maximum Volume Jobs")); + add_prompt(ua, _("Maximum Volume Files")); + add_prompt(ua, _("Maximum Volume Bytes")); + add_prompt(ua, _("Recycle Flag")); + add_prompt(ua, _("Slot")); + add_prompt(ua, _("InChanger Flag")); + add_prompt(ua, _("Volume Files")); + add_prompt(ua, _("Pool")); + add_prompt(ua, _("Volume from Pool")); + add_prompt(ua, _("All Volumes from Pool")); + add_prompt(ua, _("Done")); + switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) { + case 0: /* Volume Status */ + /* Modify Volume Status */ + bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus); + start_prompt(ua, _("Possible Values are:\n")); + add_prompt(ua, "Append"); /* Better not translate these as */ + add_prompt(ua, "Archive"); /* They are known in the database code */ + add_prompt(ua, "Disabled"); + add_prompt(ua, "Full"); + add_prompt(ua, "Used"); + add_prompt(ua, "Cleaning"); + if (strcmp(mr.VolStatus, "Purged") == 0) { + add_prompt(ua, "Recycle"); + } + add_prompt(ua, "Read-Only"); + if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) { + return 1; + } + update_volstatus(ua, ua->cmd, &mr); + break; + case 1: /* Retention */ + bsendmsg(ua, _("Current retention period is: %s\n"), + edit_utime(mr.VolRetention, ed1, sizeof(ed1))); + if (!get_cmd(ua, _("Enter Volume Retention period: "))) { + return 0; + } + update_volretention(ua, ua->cmd, &mr); + break; + + case 2: /* Use Duration */ + bsendmsg(ua, _("Current use duration is: %s\n"), + edit_utime(mr.VolUseDuration, ed1, sizeof(ed1))); + if (!get_cmd(ua, _("Enter Volume Use Duration: "))) { + return 0; + } + update_voluseduration(ua, ua->cmd, &mr); + break; + + case 3: /* Max Jobs */ + bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs); + if (!get_pint(ua, _("Enter new Maximum Jobs: "))) { + return 0; + } + update_volmaxjobs(ua, ua->cmd, &mr); + break; + + case 4: /* Max Files */ + bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles); + if (!get_pint(ua, _("Enter new Maximum Files: "))) { + return 0; + } + update_volmaxfiles(ua, ua->cmd, &mr); + break; + + case 5: /* Max Bytes */ + bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1)); + if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) { + return 0; + } + update_volmaxbytes(ua, ua->cmd, &mr); + break; + + + case 6: /* Recycle */ + bsendmsg(ua, _("Current recycle flag is: %s\n"), + mr.Recycle==1?_("yes"):_("no")); + if (!get_yesno(ua, _("Enter new Recycle status: "))) { + return 0; + } + update_volrecycle(ua, ua->cmd, &mr); + break; + + case 7: /* Slot */ + int Slot; + + memset(&pr, 0, sizeof(POOL_DBR)); + pr.PoolId = mr.PoolId; + if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + return 0; + } + bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot); + if (!get_pint(ua, _("Enter new Slot: "))) { + return 0; + } + Slot = ua->pint32_val; + if (pr.MaxVols > 0 && Slot > (int)pr.MaxVols) { + bsendmsg(ua, _("Invalid slot, it must be between 0 and %d\n"), + pr.MaxVols); + break; + } + mr.Slot = Slot; + /* + * Make sure to use db_update... rather than doing this directly, + * so that any Slot is handled correctly. + */ + if (!db_update_media_record(ua->jcr, ua->db, &mr)) { + bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db)); + } else { + bsendmsg(ua, _("New Slot is: %d\n"), mr.Slot); + } + break; + + case 8: /* InChanger */ + bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger); + if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) { + return 0; + } + mr.InChanger = ua->pint32_val; + /* + * Make sure to use db_update... rather than doing this directly, + * so that any Slot is handled correctly. + */ + if (!db_update_media_record(ua->jcr, ua->db, &mr)) { + bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db)); + } else { + bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger); + } + break; + + + case 9: /* Volume Files */ + int32_t VolFiles; + bsendmsg(ua, _("Warning changing Volume Files can result\n" + "in loss of data on your Volume\n\n")); + bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles); + if (!get_pint(ua, _("Enter new number of Files for Volume: "))) { + return 0; + } + VolFiles = ua->pint32_val; + if (VolFiles != (int)(mr.VolFiles + 1)) { + bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n")); + if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) { + break; + } + } + query = get_pool_memory(PM_MESSAGE); + Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s", + VolFiles, edit_int64(mr.MediaId, ed1)); + if (!db_sql_query(ua->db, query, NULL, NULL)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } else { + bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles); + } + free_pool_memory(query); + break; + + case 10: /* Volume's Pool */ + memset(&pr, 0, sizeof(POOL_DBR)); + pr.PoolId = mr.PoolId; + if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + return 0; + } + bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name); + if (!get_cmd(ua, _("Enter new Pool name: "))) { + return 0; + } + update_vol_pool(ua, ua->cmd, &mr, &pr); + return 1; + + case 11: + update_volfrompool(ua, &mr); + return 1; + case 12: + update_all_vols_from_pool(ua); + return 1; + default: /* Done or error */ + bsendmsg(ua, "Selection done.\n"); + return 1; + } + } + return 1; +} + +/* + * Update pool record -- pull info from current POOL resource + */ +static int update_pool(UAContext *ua) +{ + POOL_DBR pr; + int id; + POOL *pool; + POOLMEM *query; + + pool = get_pool_resource(ua); + if (!pool) { + return 0; + } + + memset(&pr, 0, sizeof(pr)); + bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name)); + if (!get_pool_dbr(ua, &pr)) { + return 0; + } + + set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */ + + id = db_update_pool_record(ua->jcr, ua->db, &pr); + if (id <= 0) { + bsendmsg(ua, _("db_update_pool_record returned %d. ERR=%s\n"), + id, db_strerror(ua->db)); + } + query = get_pool_memory(PM_MESSAGE); + Mmsg(query, list_pool, pr.PoolId); + db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST); + free_pool_memory(query); + bsendmsg(ua, _("Pool DB record updated from resource.\n")); + return 1; +} diff --git a/bacula/src/lib/mem_pool.c b/bacula/src/lib/mem_pool.c index a62b6c50c6..2cef7c32e9 100644 --- a/bacula/src/lib/mem_pool.c +++ b/bacula/src/lib/mem_pool.c @@ -108,7 +108,7 @@ POOLMEM *sm_get_pool_memory(const char *fname, int lineno, int pool) pool_ctl[pool].max_used = pool_ctl[pool].in_use; } V(mutex); - Dmsg3(800, "sm_get_pool_memory reuse %x to %s:%d\n", buf, fname, lineno); + Dmsg3(1800, "sm_get_pool_memory reuse %x to %s:%d\n", buf, fname, lineno); sm_new_owner(fname, lineno, (char *)buf); return (POOLMEM *)((char *)buf+HEAD_SIZE); } @@ -124,7 +124,7 @@ POOLMEM *sm_get_pool_memory(const char *fname, int lineno, int pool) pool_ctl[pool].max_used = pool_ctl[pool].in_use; } V(mutex); - Dmsg3(800, "sm_get_pool_memory give %x to %s:%d\n", buf, fname, lineno); + Dmsg3(1800, "sm_get_pool_memory give %x to %s:%d\n", buf, fname, lineno); return (POOLMEM *)((char *)buf+HEAD_SIZE); } @@ -209,7 +209,7 @@ void sm_free_pool_memory(const char *fname, int lineno, POOLMEM *obuf) /* Don't let him free the same buffer twice */ for (next=pool_ctl[pool].free_buf; next; next=next->next) { if (next == buf) { - Dmsg4(800, "bad free_pool_memory %x pool=%d from %s:%d\n", buf, pool, fname, lineno); + Dmsg4(1800, "bad free_pool_memory %x pool=%d from %s:%d\n", buf, pool, fname, lineno); V(mutex); /* unblock the pool */ ASSERT(next != buf); /* attempt to free twice */ } @@ -218,7 +218,7 @@ void sm_free_pool_memory(const char *fname, int lineno, POOLMEM *obuf) buf->next = pool_ctl[pool].free_buf; pool_ctl[pool].free_buf = buf; } - Dmsg4(800, "free_pool_memory %x pool=%d from %s:%d\n", buf, pool, fname, lineno); + Dmsg4(1800, "free_pool_memory %x pool=%d from %s:%d\n", buf, pool, fname, lineno); V(mutex); } @@ -347,7 +347,7 @@ void free_pool_memory(POOLMEM *obuf) buf->next = pool_ctl[pool].free_buf; pool_ctl[pool].free_buf = buf; } - Dmsg2(800, "free_pool_memory %x pool=%d\n", buf, pool); + Dmsg2(1800, "free_pool_memory %x pool=%d\n", buf, pool); V(mutex); } diff --git a/bacula/src/lib/watchdog.c b/bacula/src/lib/watchdog.c index a08e51ed55..68da73265d 100755 --- a/bacula/src/lib/watchdog.c +++ b/bacula/src/lib/watchdog.c @@ -283,7 +283,7 @@ walk_list: timeout.tv_sec++; } - Dmsg1(900, "pthread_cond_timedwait %d\n", timeout.tv_sec - tv.tv_sec); + Dmsg1(1900, "pthread_cond_timedwait %d\n", timeout.tv_sec - tv.tv_sec); /* Note, this unlocks mutex during the sleep */ P(timer_mutex); pthread_cond_timedwait(&timer, &timer_mutex, &timeout); diff --git a/bacula/src/stored/autochanger.c b/bacula/src/stored/autochanger.c index 71db9dc80a..f127e96fe2 100644 --- a/bacula/src/stored/autochanger.c +++ b/bacula/src/stored/autochanger.c @@ -159,7 +159,7 @@ static int get_autochanger_loaded_slot(DCR *dcr) drive); changer = edit_device_codes(dcr, changer, "loaded"); status = run_program(changer, timeout, results); - Dmsg3(50, "run_prog: %s stat=%d result=%s\n", changer, status, results); + Dmsg3(50, "run_prog: %s stat=%d result=%s", changer, status, results); if (status == 0) { loaded = atoi(results); if (loaded > 0) { @@ -223,7 +223,7 @@ void mark_volume_not_inchanger(DCR *dcr) * with their barcodes. * We assume that it is always the Console that is calling us. */ -bool autochanger_list(DCR *dcr, BSOCK *dir) +bool autochanger_cmd(DCR *dcr, BSOCK *dir, const char *cmd) { DEVICE *dev = dcr->dev; JCR *jcr = dcr->jcr; @@ -232,6 +232,8 @@ bool autochanger_list(DCR *dcr, BSOCK *dir) BPIPE *bpipe; int slot, loaded; int len = sizeof_pool_memory(dir->msg) - 1; + bool ok = false; + int stat; if (!dev_cap(dev, CAP_AUTOCHANGER) || !dcr->device->changer_name || !dcr->device->changer_command) { @@ -240,49 +242,73 @@ bool autochanger_list(DCR *dcr, BSOCK *dir) } changer = get_pool_memory(PM_FNAME); - offline_or_rewind_dev(dev); - /* We are going to load a new tape, so close the device */ - force_close_dev(dev); + /* List command? */ + if (strcmp(cmd, "list") == 0) { + int drive = dev->device->drive_index; + /* Yes, to get a good listing, we unload any volumes */ + offline_or_rewind_dev(dev); + /* We are going to load a new tape, so close the device */ + force_close_dev(dev); - /* First unload any tape */ - loaded = get_autochanger_loaded_slot(dcr); - if (loaded > 0) { - bnet_fsend(dir, _("3305 Issuing autochanger \"unload slot %d\" command.\n"), loaded); - slot = dcr->VolCatInfo.Slot; - dcr->VolCatInfo.Slot = loaded; - changer = edit_device_codes(dcr, changer, "unload"); - int stat = run_program(changer, timeout, NULL); - if (stat != 0) { - berrno be; - be.set_errno(stat); - Jmsg(jcr, M_INFO, 0, _("3995 Bad autochanger \"unload slot %d\" command: ERR=%s.\n"), - loaded, be.strerror()); + /* First unload any tape */ + loaded = get_autochanger_loaded_slot(dcr); + if (loaded > 0) { + bnet_fsend(dir, + _("3305 Issuing autochanger \"unload slot %d, drive %d\" command.\n"), + loaded, drive); + slot = dcr->VolCatInfo.Slot; + dcr->VolCatInfo.Slot = loaded; + changer = edit_device_codes(dcr, changer, "unload"); + lock_changer(dcr); + int stat = run_program(changer, timeout, NULL); + unlock_changer(dcr); + if (stat != 0) { + berrno be; + be.set_errno(stat); + Jmsg(jcr, M_INFO, 0, _("3995 Bad autochanger \"unload slot %d, drive %d\": ERR=%s.\n"), + slot, drive, be.strerror()); + } + dcr->VolCatInfo.Slot = slot; } - dcr->VolCatInfo.Slot = slot; } - /* Now list slots occupied */ - changer = edit_device_codes(dcr, changer, "list"); - bnet_fsend(dir, _("3306 Issuing autochanger \"list\" command.\n")); + /* Now issue the command */ + changer = edit_device_codes(dcr, changer, cmd); + bnet_fsend(dir, _("3306 Issuing autochanger \"%s\" command.\n"), cmd); + lock_changer(dcr); bpipe = open_bpipe(changer, timeout, "r"); if (!bpipe) { + unlock_changer(dcr); bnet_fsend(dir, _("3993 Open bpipe failed.\n")); - free_pool_memory(changer); - return false; + goto bail_out; } - /* Get output from changer */ - while (fgets(dir->msg, len, bpipe->rfd)) { + if (strcmp(cmd, "list") == 0) { + /* Get output from changer */ + while (fgets(dir->msg, len, bpipe->rfd)) { + dir->msglen = strlen(dir->msg); + Dmsg1(100, "msg); + bnet_send(dir); + } + } else { + /* For slots command, read a single line */ + bstrncpy(dir->msg, "slots=", len); + fgets(dir->msg+6, len-6, bpipe->rfd); dir->msglen = strlen(dir->msg); + Dmsg1(100, "msg); bnet_send(dir); } - int stat = close_bpipe(bpipe); + + stat = close_bpipe(bpipe); + unlock_changer(dcr); if (stat != 0) { berrno be; be.set_errno(stat); bnet_fsend(dir, "Autochanger error: ERR=%s\n", be.strerror()); } bnet_sig(dir, BNET_EOD); + ok = true; +bail_out: free_pool_memory(changer); return true; } @@ -315,7 +341,7 @@ char *edit_device_codes(DCR *dcr, char *omsg, const char *cmd) const char *imsg = dcr->device->changer_command; *omsg = 0; - Dmsg1(800, "edit_device_codes: %s\n", imsg); + Dmsg1(1800, "edit_device_codes: %s\n", imsg); for (p=imsg; *p; p++) { if (*p == '%') { switch (*++p) { @@ -365,9 +391,10 @@ char *edit_device_codes(DCR *dcr, char *omsg, const char *cmd) add[1] = 0; str = add; } - Dmsg1(900, "add_str %s\n", str); + Dmsg1(1900, "add_str %s\n", str); pm_strcat(&omsg, (char *)str); - Dmsg1(800, "omsg=%s\n", omsg); + Dmsg1(1800, "omsg=%s\n", omsg); } + Dmsg1(800, "omsg=%s\n", omsg); return omsg; } diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index f4ac283fcf..201d301fb6 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -782,8 +782,17 @@ static bool autochanger_cmd(JCR *jcr) BSOCK *dir = jcr->dir_bsock; DEVICE *dev; DCR *dcr; + const char *cmd; + bool ok = false; if (sscanf(dir->msg, "autochanger list %127s ", devname.c_str()) == 1) { + cmd = "list"; + ok = true; + } else if (sscanf(dir->msg, "autochanger slots %127s ", devname.c_str()) == 1) { + cmd = "slots"; + ok = true; + } + if (ok) { dev = find_device(jcr, devname); dcr = jcr->dcr; if (dev) { @@ -792,17 +801,17 @@ static bool autochanger_cmd(JCR *jcr) bnet_fsend(dir, _("3995 Device %s is not an autochanger.\n"), dev->print_name()); } else if (!dev->is_open()) { - autochanger_list(dcr, dir); + autochanger_cmd(dcr, dir, cmd); /* Under certain "safe" conditions, we can steal the lock */ } else if (dev->dev_blocked && (dev->dev_blocked == BST_UNMOUNTED || dev->dev_blocked == BST_WAITING_FOR_SYSOP || dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP)) { - autochanger_list(dcr, dir); + autochanger_cmd(dcr, dir, cmd); } else if (dev->is_busy()) { send_dir_busy_message(dir, dev); } else { /* device not being used */ - autochanger_list(dcr, dir); + autochanger_cmd(dcr, dir, cmd); } V(dev->mutex); } else { @@ -810,8 +819,8 @@ static bool autochanger_cmd(JCR *jcr) } } else { /* error on scanf */ pm_strcpy(jcr->errmsg, dir->msg); - bnet_fsend(dir, _("3908 Error scanning autocharger list command: %s\n"), - jcr->errmsg); + bnet_fsend(dir, _("3908 Error scanning autocharger %s command: %s\n"), + cmd, jcr->errmsg); } bnet_sig(dir, BNET_EOD); return true; diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 7730845939..6ec0b722ea 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -58,7 +58,7 @@ int authenticate_filed(JCR *jcr); /* From autochanger.c */ int autoload_device(DCR *dcr, int writing, BSOCK *dir); -bool autochanger_list(DCR *dcr, BSOCK *dir); +bool autochanger_cmd(DCR *dcr, BSOCK *dir, const char *cmd); void mark_volume_not_inchanger(DCR *dcr); char *edit_device_codes(DCR *dcr, char *omsg, const char *cmd); diff --git a/bacula/src/version.h b/bacula/src/version.h index 8d7a7f6be6..780da7da63 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #undef VERSION #define VERSION "1.37.6" -#define BDATE "09 March 2005" -#define LSMDATE "09Mar05" +#define BDATE "10 March 2005" +#define LSMDATE "10Mar05" /* Debug flags */ #undef DEBUG -- 2.39.5