func TestVolumeReserve(t *testing.T) {
	client, err := newClient(t)
	th.AssertNoErr(t, err)

	t.Logf("Creating volume")
	cv, err := volumes.Create(client, &volumes.CreateOpts{
		Size: 1,
		Name: "blockv2-volume",
	}).Extract()
	th.AssertNoErr(t, err)

	defer func() {
		err = volumes.WaitForStatus(client, cv.ID, "available", 60)
		th.AssertNoErr(t, err)

		t.Logf("Deleting volume")
		err = volumes.Delete(client, cv.ID).ExtractErr()
		th.AssertNoErr(t, err)
	}()

	err = volumes.WaitForStatus(client, cv.ID, "available", 60)
	th.AssertNoErr(t, err)

	t.Logf("Reserving volume")
	err = volumeactions.Reserve(client, cv.ID).ExtractErr()
	th.AssertNoErr(t, err)

	err = volumes.WaitForStatus(client, cv.ID, "attaching", 60)
	th.AssertNoErr(t, err)

	t.Logf("Unreserving volume")
	err = volumeactions.Unreserve(client, cv.ID).ExtractErr()
	th.AssertNoErr(t, err)

	err = volumes.WaitForStatus(client, cv.ID, "available", 60)
	th.AssertNoErr(t, err)
}
func (d CinderDriver) Unmount(r volume.Request) volume.Response {
	log.Infof("Unmounting volume: %+v", r)
	d.Mutex.Lock()
	defer d.Mutex.Unlock()
	vol, err := d.getByName(r.Name)
	if vol.ID == "" {
		log.Errorf("Request to Unmount failed because volume `%s` could not be found", r.Name)
		err := errors.New("Volume Not Found")
		return volume.Response{Err: err.Error()}
	}

	if err != nil {
		log.Errorf("Failed to retrieve volume named: `", r.Name, "` during Unmount operation", err)
		return volume.Response{Err: err.Error()}
	}

	if umountErr := Umount(d.Conf.MountPoint + "/" + r.Name); umountErr != nil {
		if umountErr.Error() == "Volume is not mounted" {
			log.Warning("Request to unmount volume, but it's not mounted")
			return volume.Response{}
		} else {
			return volume.Response{Err: umountErr.Error()}
		}
	}
	// NOTE(jdg): So there's a couple issues with how Docker works here.  If
	// you are trying to attach and it fails, it kindly goes through and does
	// an Unmount to clean up anything that went bad, BUT that creates a
	// problem here.  Say for example you try to attach an in-use volume, we
	// don't want to rip that out from under wherever it's currently being used

	// NOTE(jdg): Don't rely on things like `df --output=source mounpoint`
	// that's no good for error situations.

	tgt, portal := getTgtInfo(vol)
	iscsiDetachVolume(tgt, portal)
	log.Debug("Terminate Connection")
	iface := d.Conf.InitiatorIFace
	netDev, _ := net.InterfaceByName(iface)
	IPs, _ := net.InterfaceAddrs()
	log.Debugf("iface: %+v\n Addrs: %+v", netDev, IPs)
	initiators, err := GetInitiatorIqns()
	if err != nil {
		log.Error("Failed to retrieve Initiator name!")
		return volume.Response{Err: err.Error()}
	}
	hostname, _ := os.Hostname()
	// TODO(ebalduf): Change assumption that we have only one Initiator defined
	// TODO(jdg): For now we're only supporting linux, but in the future we'll
	// need to get rid of the hard coded Platform/OSType and fix this up for
	// things like say Windows
	log.Debugf("IPs=%+v\n", IPs)
	connectorOpts := volumeactions.ConnectorOpts{
		IP:        d.Conf.InitiatorIP,
		Host:      hostname,
		Initiator: initiators[0],
		Wwpns:     []string{},
		Wwnns:     "",
		Multipath: false,
		Platform:  "x86",
		OSType:    "linux",
	}
	log.Debugf("Unreserve volume: %s", vol.ID)
	volumeactions.Unreserve(d.Client, vol.ID)
	log.Debugf("Terminate connection for volume: %s", vol.ID)
	volumeactions.TerminateConnection(d.Client, vol.ID, &connectorOpts)
	log.Debugf("Detach volume: %s", vol.ID)
	volumeactions.Detach(d.Client, vol.ID)
	return volume.Response{}
}