-/*
- * Use Device command from Director
- * He tells is what Device Name to use, the Media Type,
- * the Pool Name, and the Pool Type.
- *
- * Ensure that the device exists and is opened, then store
- * the media and pool info in the JCR.
- */
-class DIRSTORE {
-public:
- alist *device;
- char name[MAX_NAME_LENGTH];
- char media_type[MAX_NAME_LENGTH];
- char pool_name[MAX_NAME_LENGTH];
- char pool_type[MAX_NAME_LENGTH];
-};
-
-static int search_res_for_device(JCR *jcr, DIRSTORE *store, char *device_name, int append);
-
-static bool use_storage_cmd(JCR *jcr)
-{
- POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
- BSOCK *dir = jcr->dir_bsock;
- int append;
- bool ok;
- int Copy, Stripe;
- alist *dirstore;
- DIRSTORE *store;
- char *device_name;
- DCR *dcr = NULL;
- /*
- * If there are multiple devices, the director sends us
- * use_device for each device that it wants to use.
- */
- Dmsg1(100, "<dird: %s", dir->msg);
- dirstore = New(alist(10, not_owned_by_alist));
- do {
- ok = sscanf(dir->msg, use_storage, store_name.c_str(),
- media_type.c_str(), pool_name.c_str(),
- pool_type.c_str(), &append, &Copy, &Stripe) == 7;
- if (!ok) {
- break;
- }
- unbash_spaces(store_name);
- unbash_spaces(media_type);
- unbash_spaces(pool_name);
- unbash_spaces(pool_type);
- store = new DIRSTORE;
- dirstore->append(store);
- memset(store, 0, sizeof(DIRSTORE));
- store->device = New(alist(10));
- bstrncpy(store->name, store_name, sizeof(store->name));
- bstrncpy(store->media_type, media_type, sizeof(store->media_type));
- bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
- bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
-
- /* Now get all devices */
- while (bnet_recv(dir) >= 0) {
- ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
- if (!ok) {
- break;
- }
- unbash_spaces(dev_name);
- store->device->append(bstrdup(dev_name.c_str()));
- }
- } while (ok && bnet_recv(dir) >= 0);
-
-#ifdef DEVELOPER
- /* This loop is debug code and can be removed */
- /* ***FIXME**** remove after 1.38 release */
- foreach_alist(store, dirstore) {
- Dmsg4(100, "Storage=%s media_type=%s pool=%s pool_type=%s\n",
- store->name, store->media_type, store->pool_name,
- store->pool_type);
- foreach_alist(device_name, store->device) {
- Dmsg1(100, " Device=%s\n", device_name);
- }
- }
-#endif
-
- /*
- * At this point, we have a list of all the Director's Storage
- * resources indicated for this Job, which include Pool, PoolType,
- * storage name, and Media type.
- * Then for each of the Storage resources, we have a list of
- * device names that were given.
- *
- * Wiffle through them and find one that can do the backup.
- */
- if (ok) {
- store = (DIRSTORE *)dirstore->first();
- foreach_alist(device_name, store->device) {
- if (search_res_for_device(jcr, store, device_name, append) == 1) {
- dcr = jcr->dcr;
- dcr->Copy = Copy;
- dcr->Stripe = Stripe;
- ok = true;
- goto done;
- }
- }
- if (verbose) {
- unbash_spaces(dir->msg);
- pm_strcpy(jcr->errmsg, dir->msg);
- Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
- }
- Jmsg(jcr, M_FATAL, 0, _("\n"
- " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
- dev_name.c_str(), media_type.c_str());
- bnet_fsend(dir, NO_device, dev_name.c_str());
- Dmsg1(100, ">dird: %s\n", dir->msg);
- ok = false;
- } else {
- unbash_spaces(dir->msg);
- pm_strcpy(jcr->errmsg, dir->msg);
- if (verbose) {
- Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
- }
- Jmsg(jcr, M_FATAL, 0, _("Bad Use Device command: %s\n"), jcr->errmsg);
- bnet_fsend(dir, BAD_use, jcr->errmsg);
- Dmsg1(100, ">dird: %s\n", dir->msg);
- ok = false;
- }
-
-done:
- foreach_alist(store, dirstore) {
- delete store->device;
- delete store;
- }
- delete dirstore;
- if (!ok && dcr) {
- free_dcr(dcr);
- }
- return ok;
-}
-
-/*
- * Returns: 1 -- OK, have DCR
- * 0 -- must wait
- * -1 -- fatal error
- */
-static int search_res_for_device(JCR *jcr, DIRSTORE *store, char *device_name, int append)
-{
- DEVRES *device;
- AUTOCHANGER *changer;
- BSOCK *dir = jcr->dir_bsock;
- bool ok;
- DCR *dcr;
-
- Dmsg1(100, "Search res for %s\n", device_name);
- foreach_res(device, R_DEVICE) {
- Dmsg1(100, "Try res=%s\n", device->hdr.name);
- /* Find resource, and make sure we were able to open it */
- if (fnmatch(device_name, device->hdr.name, 0) == 0 &&
- strcmp(device->media_type, store->media_type) == 0) {
- const int name_len = MAX_NAME_LENGTH;
- if (!device->dev) {
- device->dev = init_dev(jcr, NULL, device);
- }
- if (!device->dev) {
- Jmsg(jcr, M_WARNING, 0, _("\n"
- " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
- device_name);
- bnet_fsend(dir, NOT_open, device_name);
- Dmsg1(100, ">dird: %s\n", dir->msg);
- return -1;
- }
- Dmsg1(100, "Found device %s\n", device->hdr.name);
- dcr = new_dcr(jcr, device->dev);
- if (!dcr) {
- bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), device_name);
- Dmsg1(100, ">dird: %s\n", dir->msg);
- return -1;
- }
- jcr->dcr = dcr;
- bstrncpy(dcr->pool_name, store->pool_name, name_len);
- bstrncpy(dcr->pool_type, store->pool_type, name_len);
- bstrncpy(dcr->media_type, store->media_type, name_len);
- bstrncpy(dcr->dev_name, device_name, name_len);
- if (append == SD_APPEND) {
- ok = reserve_device_for_append(dcr);
- } else {
- ok = reserve_device_for_read(dcr);
- }
- if (!ok) {
- bnet_fsend(dir, _("3927 Could not reserve device: %s\n"), device_name);
- Dmsg1(100, ">dird: %s\n", dir->msg);
- free_dcr(jcr->dcr);
- return 0;
- }
- Dmsg1(220, "Got: %s", dir->msg);
- bash_spaces(device_name);
- ok = bnet_fsend(dir, OK_device, device_name);
- Dmsg1(100, ">dird: %s\n", dir->msg);
- return ok;
- }
- }
- foreach_res(changer, R_AUTOCHANGER) {
- Dmsg1(100, "Try changer res=%s\n", changer->hdr.name);
- /* Find resource, and make sure we were able to open it */
- if (fnmatch(device_name, changer->hdr.name, 0) == 0) {
- const int name_len = MAX_NAME_LENGTH;
- /* Try each device in this AutoChanger */
- foreach_alist(device, changer->device) {
- Dmsg1(100, "Try changer device %s\n", device->hdr.name);
- if (!device->dev) {
- device->dev = init_dev(jcr, NULL, device);
- }
- if (!device->dev) {
- Dmsg1(100, "Device %s could not be opened. Skipped\n", device_name);
- Jmsg(jcr, M_WARNING, 0, _("\n"
- " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
- device->hdr.name, device_name);
- continue;
- }
- if (!device->dev->autoselect) {
- continue; /* device is not available */
- }
- dcr = new_dcr(jcr, device->dev);
- if (!dcr) {
- bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), device_name);
- Dmsg1(100, ">dird: %s\n", dir->msg);
- return -1;
- }
- Dmsg1(100, "Found changer device %s\n", device->hdr.name);
- bstrncpy(dcr->pool_name, store->pool_name, name_len);
- bstrncpy(dcr->pool_type, store->pool_type, name_len);
- bstrncpy(dcr->media_type, store->media_type, name_len);
- bstrncpy(dcr->dev_name, device_name, name_len);
- jcr->dcr = dcr;
- if (append == SD_APPEND) {
- ok = reserve_device_for_append(dcr);
- } else {
- ok = reserve_device_for_read(dcr);
- }
- if (!ok) {
- Jmsg(jcr, M_WARNING, 0, _("Could not reserve device: %s\n"), device_name);
- free_dcr(jcr->dcr);
- continue;
- }
- POOL_MEM dev_name;
- Dmsg1(100, "Device %s opened.\n", device_name);
- pm_strcpy(dev_name, device->hdr.name);
- bash_spaces(dev_name);
- ok = bnet_fsend(dir, OK_device, dev_name.c_str()); /* Return real device name */
- Dmsg1(100, ">dird: %s\n", dir->msg);
- return ok;
- }
- }
- }
- return 0;
-}
-
-