--- /dev/null
+
+ This patch add a new protocol between storage and director
+ to be able to guess device organisation.
+
+
+Index: src/dird/ua_cmds.c
+===================================================================
+--- src/dird/ua_cmds.c (révision 8483)
++++ src/dird/ua_cmds.c (copie de travail)
+@@ -98,6 +98,7 @@
+ static int var_cmd(UAContext *ua, const char *cmd);
+ static int version_cmd(UAContext *ua, const char *cmd);
+ static int wait_cmd(UAContext *ua, const char *cmd);
++static int devicegroup_cmd(UAContext *ua, const char *command);
+
+ static void do_job_delete(UAContext *ua, JobId_t JobId);
+ static void delete_job_id_range(UAContext *ua, char *tok);
+@@ -154,6 +155,7 @@
+ { NT_("var"), var_cmd, _("does variable expansion"), false},
+ { NT_("version"), version_cmd, _("print Director version"), true},
+ { NT_("wait"), wait_cmd, _("wait [<jobname=name> | <jobid=nnn> | <ujobid=complete_name>] -- wait until no jobs are running"), false},
++ { NT_("dg"), devicegroup_cmd, _(""), false}
+ };
+ #define comsize (sizeof(commands)/sizeof(struct cmdstruct))
+
+@@ -1557,6 +1559,65 @@
+ jcr->store_bsock = NULL;
+ }
+
++
++static int devicegroup_cmd(UAContext *ua, const char *command)
++{
++ USTORE store;
++ BSOCK *sd;
++ JCR *jcr = ua->jcr;
++ char dev_name[MAX_NAME_LENGTH];
++ POOL_MEM devname;
++ STORE *storage;
++ DEVICE *dev;
++
++ if (!open_client_db(ua)) {
++ return 1;
++ }
++ Dmsg2(120, "%s: %s\n", command, ua->UA_sock->msg);
++
++ store.store = get_storage_resource(ua, true/*arg is storage*/);
++ if (!store.store) {
++ return 1;
++ }
++ pm_strcpy(store.store_source, _("unknown source"));
++ set_wstorage(jcr, &store);
++
++ if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
++ ua->error_msg(_("Failed to connect to Storage daemon.\n"));
++ return 1;
++ }
++ sd = jcr->store_bsock;
++ bstrncpy(dev_name, store.store->dev_name(), sizeof(dev_name));
++ bash_spaces(dev_name);
++ bnet_fsend(sd, "devicegroup storage=%s", dev_name);
++
++ /* can construct a list of device name */
++ while (bnet_recv(sd) >= 0) {
++ if (sscanf(sd->msg, "dev=%127s", devname.c_str()) == 1) {
++ unbash_spaces(devname);
++
++ /* get the device name from the storage resource */
++ foreach_res(storage, R_STORAGE) {
++ /* check that this resource is on the same storage */
++ if (bstrcmp(store.store->address, storage->address) &&
++ store.store->SDport == storage->SDport)
++ {
++
++ foreach_alist(dev, storage->device) {
++ if (bstrcmp(dev->name(), devname.c_str())) {
++ ua->send_msg("%s\n", storage->name());
++ }
++ }
++ }
++ }
++ }
++ }
++ bnet_sig(sd, BNET_TERMINATE);
++ bnet_close(sd);
++ jcr->store_bsock = NULL;
++ return 1;
++}
++
+ /*
+ * mount [storage=<name>] [drive=nn] [slot=mm]
+ */
+Index: src/stored/dircmd.c
+===================================================================
+--- src/stored/dircmd.c (révision 8483)
++++ src/stored/dircmd.c (copie de travail)
+@@ -91,6 +91,7 @@
+ int Slot, int relabel);
+ static bool try_autoload_device(JCR *jcr, DCR *dcr, int slot, const char *VolName);
+ static void send_dir_busy_message(BSOCK *dir, DEVICE *dev);
++static bool devicegroup_cmd(JCR *jcr);
+
+ struct s_cmds {
+ const char *cmd;
+@@ -118,6 +119,7 @@
+ {"unmount", unmount_cmd, 0},
+ {"use storage=", use_cmd, 0},
+ {"run", run_cmd, 0},
++ {"devicegroup", devicegroup_cmd, 0},
+ // {"query", query_cmd, 0},
+ {NULL, NULL} /* list terminator */
+ };
+@@ -629,6 +631,45 @@
+
+
+ /*
++ * devicegroup storage=<name>
++ */
++static bool devicegroup_cmd(JCR *jcr)
++{
++ POOL_MEM devname, result;
++ BSOCK *dir = jcr->dir_bsock;
++ AUTOCHANGER *ach;
++ DEVRES *dev;
++ DCR *dcr;
++
++ bool ok = sscanf(dir->msg, "devicegroup storage=%127s", devname.c_str()) == 1;
++ if (ok) {
++ dcr = find_device(jcr, devname, -1);
++ if (dcr) {
++ ach = dcr->device->changer_res;
++ if (ach) {
++ /* Send the autochanger name as device*/
++ pm_strcpy(devname, ach->hdr.name);
++ bash_spaces(devname);
++ dir->fsend("dev=%s\n", devname.c_str());
++
++ /* Send all autochanger devices */
++ foreach_alist(dev, ach->device) {
++ pm_strcpy(devname, dev->hdr.name);
++ bash_spaces(devname);
++ dir->fsend("dev=%s\n", devname.c_str());
++ }
++ } else { /* if it's not an autochanger, just return it */
++ pm_strcpy(devname, dcr->device->hdr.name);
++ bash_spaces(devname);
++ dir->fsend("dev=%s\n", devname.c_str());
++ }
++ }
++ }
++ dir->signal(BNET_EOD);
++ return true;
++}
++
++/*
+ * Mount command from Director
+ */
+ static bool mount_cmd(JCR *jcr)