예제 #1
0
func (client *cinderClient) getConnectionInfo(id string, copts *volumeactions.ConnectorOpts) (map[string]interface{}, error) {
	connectionInfo, err := volumeactions.InitializeConnection(client.cinder, id, copts).Extract()
	if err != nil && err.Error() != "EOF" {
		return nil, err
	}

	return connectionInfo["connection_info"].(map[string]interface{}), nil
}
예제 #2
0
func TestVolumeConns(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)

	connOpts := &volumeactions.ConnectorOpts{
		IP:        "127.0.0.1",
		Host:      "stack",
		Initiator: "iqn.1994-05.com.redhat:17cf566367d2",
		Multipath: false,
		Platform:  "x86_64",
		OSType:    "linux2",
	}

	t.Logf("Initializing connection")
	_, err = volumeactions.InitializeConnection(client, cv.ID, connOpts).Extract()
	th.AssertNoErr(t, err)

	t.Logf("Terminating connection")
	err = volumeactions.TerminateConnection(client, cv.ID, connOpts).ExtractErr()
	th.AssertNoErr(t, err)
}
예제 #3
0
func (d CinderDriver) Mount(r volume.Request) volume.Response {
	d.Mutex.Lock()
	defer d.Mutex.Unlock()

	hostname, _ := os.Hostname()
	log.Infof("Mounting volume %+v on %s", r, hostname)
	vol, err := d.getByName(r.Name)
	if err != nil {
		log.Errorf("Failed to retrieve volume named: ", r.Name, "during Mount operation", err)
		return volume.Response{Err: err.Error()}
	}
	if vol.ID == "" {
		log.Error("Volume Not Found!")
		err := errors.New("Volume Not Found")
		return volume.Response{Err: err.Error()}
	}
	if vol.Status == "creating" {
		// NOTE(jdg):  This may be a successive call after a create which from
		// the docker volume api can be quite speedy.  Take a short pause and
		// check the status again before proceeding
		time.Sleep(time.Second * 5)
		vol, err = d.getByName(r.Name)
	}

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

	if vol.Status != "available" {
		log.Debugf("Volume info: %+v\n", vol)
		log.Errorf("Invalid volume status for Mount request, volume is: %s but must be available", vol.Status)
		err := errors.New("Invalid volume status for Mount request")
		return volume.Response{Err: err.Error()}
	}
	volumeactions.Reserve(d.Client, vol.ID)

	iface := d.Conf.InitiatorIFace
	netDev, _ := net.InterfaceByName(iface)
	IPs, _ := net.InterfaceAddrs()
	log.Debugf("iface: %+v\n Addrs: %+v", netDev, IPs)

	log.Debug("Gather up initiator IQNs...")
	initiator, err := GetInitiatorIqns()
	if err != nil {
		log.Error("Failed to retrieve Initiator name!")
		return volume.Response{Err: err.Error()}
	}
	// TODO(ebalduf): Change assumption that we have only one Initiator defined
	log.Debugf("Value of IPs is=%+v\n", IPs)
	connectorOpts := volumeactions.ConnectorOpts{
		IP:        d.Conf.InitiatorIP,
		Host:      hostname,
		Initiator: initiator[0],
		Wwpns:     []string{},
		Wwnns:     "",
		Multipath: false,
		Platform:  "x86",
		OSType:    "linux",
	}
	log.Debug("Issue InitializeConnection...")
	response := volumeactions.InitializeConnection(d.Client, vol.ID, &connectorOpts)
	log.Debugf("Response from InitializeConnection: %+v\n", response)
	data := response.Body.(map[string]interface{})["connection_info"].(map[string]interface{})["data"]
	var con ConnectorInfo
	mapstructure.Decode(data, &con)
	path, device, err := attachVolume(&con, "default")
	log.Debug("iSCSI connection done")
	if path == "" || device == "" && err == nil {
		log.Error("Missing path or device, but err not set?")
		log.Debug("Path: ", path, " ,Device: ", device)
		return volume.Response{Err: err.Error()}

	}
	if err != nil {
		log.Errorf("Failed to perform iscsi attach of volume %s: %v", r.Name, err)
		return volume.Response{Err: err.Error()}
	}

	if GetFSType(device) == "" {
		//TODO(jdg): Enable selection of *other* fs types
		log.Debugf("Formatting device")
		err := FormatVolume(device, "ext4")
		if err != nil {
			err := errors.New("Failed to format device")
			log.Error(err)
			return volume.Response{Err: err.Error()}
		}
	}
	if mountErr := Mount(device, d.Conf.MountPoint+"/"+r.Name); mountErr != nil {
		err := errors.New("Problem mounting docker volume ")
		log.Error(err)
		return volume.Response{Err: err.Error()}
	}

	path = filepath.Join(d.Conf.MountPoint, r.Name)
	// NOTE(jdg): Cinder will barf if you provide both Instance and HostName
	// which is kinda silly... but it is what it is
	attachOpts := volumeactions.AttachOpts{
		MountPoint:   path,
		InstanceUUID: d.Conf.HostUUID,
		HostName:     "",
		Mode:         "rw"}
	log.Debug("Call gophercloud Attach...")
	attRes := volumeactions.Attach(d.Client, vol.ID, &attachOpts)
	log.Debugf("Attach results: %+v", attRes)
	return volume.Response{Mountpoint: d.Conf.MountPoint + "/" + r.Name}
}