}
return;
}
+
+/**
+ * Open the bootstrap file and find the first Storage=
+ * Returns ok if able to open
+ * It fills the storage name (should be the first line)
+ * and the file descriptor to the bootstrap file,
+ * it should be used for next operations, and need to be closed
+ * at the end.
+ */
+bool open_bootstrap_file(JCR *jcr, bootstrap_info &info)
+{
+ FILE *bs;
+ UAContext *ua;
+ info.bs = NULL;
+ info.ua = NULL;
+
+ if (!jcr->RestoreBootstrap) {
+ return false;
+ }
+ bstrncpy(info.storage, jcr->store_mngr->get_rstore()->name(), MAX_NAME_LENGTH);
+
+ bs = bfopen(jcr->RestoreBootstrap, "rb");
+ if (!bs) {
+ berrno be;
+ Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
+ jcr->RestoreBootstrap, be.bstrerror());
+ jcr->setJobStatus(JS_ErrorTerminated);
+ return false;
+ }
+
+ ua = new_ua_context(jcr);
+ while (bfgets(ua->cmd, bs)) {
+ parse_ua_args(ua);
+ if (ua->argc != 1) {
+ continue;
+ }
+ if (!strcasecmp(ua->argk[0], "Storage")) {
+ bstrncpy(info.storage, ua->argv[0], MAX_NAME_LENGTH);
+ break;
+ }
+ }
+ info.bs = bs;
+ info.ua = ua;
+ fseek(bs, 0, SEEK_SET); /* return to the top of the file */
+ return true;
+}
+
+/*
+ * Clean the bootstrap_info struct
+ */
+void close_bootstrap_file(bootstrap_info &info)
+{
+ if (info.bs) {
+ fclose(info.bs);
+ info.bs = NULL;
+ }
+ if (info.ua) {
+ free_ua_context(info.ua);
+ info.ua = NULL;
+ }
+}
* Kern Sibbald, July MMII
*/
-
+#ifndef BSR_H
+#define BSR_H
/* FileIndex entry in restore bootstrap record */
struct RBSR_FINDEX {
/* If we extend an existing fi, keep the memory for the next insert */
RBSR_FINDEX *m_fi;
};
+
+
+class UAContext;
+/* Structure used to quickly scan the BSR file and find
+ * the right storage daemon to connect to
+ */
+struct bootstrap_info
+{
+ FILE *bs;
+ UAContext *ua;
+ char storage[MAX_NAME_LENGTH+1];
+};
+bool open_bootstrap_file(JCR *jcr, bootstrap_info &info);
+void close_bootstrap_file(bootstrap_info &info);
+
+#endif
BSOCK *sd, *wsd;
JCR *wjcr = jcr->wjcr; /* newly migrated job */
bool ok = false;
- STORE *store;
+ STORE *store, *bsr_store;
char *store_address;
uint32_t store_port;
STORE *rstore = NULL;
jcr->setJobStatus(JS_WaitSD);
wjcr->setJobStatus(JS_WaitSD);
+ if (jcr->store_mngr->get_rstore_list()->size() > 1) {
+ POOL_MEM src;
+ /* To help the user, we can check if the selected storage is compatible
+ * with what we have in the BSR
+ */
+ bootstrap_info info;
+ if (!open_bootstrap_file(jcr, info)) { // We get the first Storage=
+ goto bail_out;
+ }
+ close_bootstrap_file(info);
+
+ /* Keep the source of the information */
+ pm_strcpy(src, jcr->store_mngr->get_rsource());
+
+ /* If we have a Storage Group defined, we can look into it
+ * TODO: Like for Backup, we can also check for the different algorithms
+ * (least used, round robbin)
+ */
+ bsr_store = (STORE *)GetResWithName(R_STORAGE, info.storage);
+ if (bsr_store) {
+ bool found=false;
+ foreach_alist(store, jcr->store_mngr->get_rstore_list()) {
+ /* At least the Address and the Port should match */
+ if (strcmp(store->address, bsr_store->address) == 0 && store->SDport == bsr_store->SDport) {
+ /* The storage is ok, it will select it */
+ jcr->store_mngr->set_rstore(store, src.c_str());
+ found=true;
+ break;
+ }
+ }
+ if (!found) {
+ /* Maybe we can find a storage with the right name. Should not happen */
+ foreach_alist(store, jcr->store_mngr->get_rstore_list()) {
+ if (strcmp(store->hdr.name, info.storage) == 0) {
+ jcr->store_mngr->set_rstore(store, src.c_str());
+ found=true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ /* Let's try with the MediaType */
+ foreach_alist(store, jcr->store_mngr->get_rstore_list()) {
+ if (strcmp(store->media_type, bsr_store->media_type) == 0) {
+ /* The Media type is the same, it will select it */
+ jcr->store_mngr->set_rstore(store, src.c_str());
+ break;
+ }
+ }
+ }
+ /* TODO: It is possible to iterate on the global list of Storage
+ * resource and pick the original one, it would solve automatically
+ * any configuration issues.
+ */
+ if (!found) {
+ Jmsg(jcr, M_WARNING, 0, _("Could not find a compatible Storage to read volumes in the %s Job definition (%s/%s)\n"),
+ jcr->job->name(), bsr_store->hdr.name, bsr_store->media_type);
+ }
+
+ } else {
+ Dmsg1(50, "Unable to find the Storage resource \"%s\" in the configuration\n", info.storage);
+ }
+ }
+
/*
* Start conversation with write Storage daemon
*/
unbash_spaces(where.c_str());
}
-struct bootstrap_info
-{
- FILE *bs;
- UAContext *ua;
- char storage[MAX_NAME_LENGTH+1];
-};
-
-#define UA_CMD_SIZE 1000
-
-/**
- * Open the bootstrap file and find the first Storage=
- * Returns ok if able to open
- * It fills the storage name (should be the first line)
- * and the file descriptor to the bootstrap file,
- * it should be used for next operations, and need to be closed
- * at the end.
- */
-static bool open_bootstrap_file(JCR *jcr, bootstrap_info &info)
-{
- FILE *bs;
- UAContext *ua;
- info.bs = NULL;
- info.ua = NULL;
-
- if (!jcr->RestoreBootstrap) {
- return false;
- }
- bstrncpy(info.storage, jcr->store_mngr->get_rstore()->name(), MAX_NAME_LENGTH);
-
- bs = bfopen(jcr->RestoreBootstrap, "rb");
- if (!bs) {
- berrno be;
- Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
- jcr->RestoreBootstrap, be.bstrerror());
- jcr->setJobStatus(JS_ErrorTerminated);
- return false;
- }
-
- ua = new_ua_context(jcr);
- ua->cmd = check_pool_memory_size(ua->cmd, UA_CMD_SIZE+1);
- while (!fgets(ua->cmd, UA_CMD_SIZE, bs)) {
- parse_ua_args(ua);
- if (ua->argc != 1) {
- continue;
- }
- if (!strcasecmp(ua->argk[0], "Storage")) {
- bstrncpy(info.storage, ua->argv[0], MAX_NAME_LENGTH);
- break;
- }
- }
- info.bs = bs;
- info.ua = ua;
- fseek(bs, 0, SEEK_SET); /* return to the top of the file */
- return true;
-}
-
/**
* This function compare the given storage name with the
* the current one. We compare the name and the address:port.
}
sock->fsend(bootstrap);
pos = ftello(bs);
- while(fgets(ua->cmd, UA_CMD_SIZE, bs)) {
+ while(bfgets(ua->cmd, bs)) {
if (check_for_new_storage(jcr, info)) {
/* Otherwise, we need to contact another storage daemon.
* Reset bs to the beginning of the current segment.
return false;
}
-/*
- * Clean the bootstrap_info struct
- */
-static void close_bootstrap_file(bootstrap_info &info)
-{
- if (info.bs) {
- fclose(info.bs);
- }
- if (info.ua) {
- free_ua_context(info.ua);
- }
-}
-
/**
* The bootstrap is stored in a file, so open the file, and loop
* through it processing each storage device in turn. If the