func (util *ISCSIUtil) DetachDisk(iscsi iscsiDisk, mntPath string) error {
	device, cnt, err := mount.GetDeviceNameFromMount(iscsi.mounter, mntPath)
	if err != nil {
		glog.Errorf("iscsi detach disk: failed to get device from mnt: %s\nError: %v", mntPath, err)
		return err
	}
	if err = iscsi.mounter.Unmount(mntPath, 0); err != nil {
		glog.Errorf("iscsi detach disk: failed to umount: %s\nError: %v", mntPath, err)
		return err
	}
	cnt--
	// if device is no longer used, see if need to logout the target
	if cnt == 0 {
		// strip -lun- from device path
		ind := strings.LastIndex(device, "-lun-")
		prefix := device[:(ind - 1)]
		refCount, err := getDevicePrefixRefCount(iscsi.mounter, prefix)

		if err == nil && refCount == 0 {
			// this portal/iqn are no longer referenced, log out
			// extract portal and iqn from device path
			ind1 := strings.LastIndex(device, "-iscsi-")
			portal := device[(len("/dev/disk/by-path/ip-")):ind1]
			iqn := device[ind1+len("-iscsi-") : ind]

			glog.Infof("iscsi: log out target %s iqn %s", portal, iqn)
			_, err = iscsi.plugin.execCommand("iscsiadm", []string{"-m", "node", "-p", portal, "-T", iqn, "--logout"})
			if err != nil {
				glog.Errorf("iscsi: failed to detach disk Error: %v", err)
			}
		}
	}
	return nil
}
Example #2
0
func (util *RBDUtil) DetachDisk(rbd rbd, mntPath string) error {
	device, cnt, err := mount.GetDeviceNameFromMount(rbd.mounter, mntPath)
	if err != nil {
		return fmt.Errorf("rbd detach disk: failed to get device from mnt: %s\nError: %v", mntPath, err)
	}
	if err = rbd.mounter.Unmount(mntPath); err != nil {
		return fmt.Errorf("rbd detach disk: failed to umount: %s\nError: %v", mntPath, err)
	}
	// if device is no longer used, see if can unmap
	if cnt <= 1 {
		// rbd unmap
		_, err = rbd.plugin.execCommand("rbd", []string{"unmap", device})
		if err != nil {
			return fmt.Errorf("rbd: failed to unmap device %s:Error: %v", device, err)
		}

		// load ceph and image/pool info to remove fencing
		if err := util.loadRBD(&rbd, mntPath); err == nil {
			// remove rbd lock
			util.defencing(rbd)
		}

		glog.Infof("rbd: successfully unmap device %s", device)
	}
	return nil
}
Example #3
0
func TestSafeFormatAndMount(t *testing.T) {
	tests := []struct {
		fstype        string
		mountOptions  []string
		execScripts   []ExecArgs
		mountErrs     []error
		expectedError error
	}{
		{ // Test a read only mount
			fstype:       "ext4",
			mountOptions: []string{"ro"},
		},
		{ // Test a normal mount
			fstype: "ext4",
		},

		{ // Test that 'file' is called and fails
			fstype:    "ext4",
			mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")},
			execScripts: []ExecArgs{
				{"file", []string{"-L", "--special-files", "/dev/foo"}, "ext4 filesystem", nil},
			},
			expectedError: fmt.Errorf("unknown filesystem type '(null)'"),
		},
		{ // Test that 'file' is called and confirms unformatted disk, format fails
			fstype:    "ext4",
			mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")},
			execScripts: []ExecArgs{
				{"file", []string{"-L", "--special-files", "/dev/foo"}, "data", nil},
				{"mkfs.ext4", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", fmt.Errorf("formatting failed")},
			},
			expectedError: fmt.Errorf("formatting failed"),
		},
		{ // Test that 'file' is called and confirms unformatted disk, format passes, second mount fails
			fstype:    "ext4",
			mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), fmt.Errorf("Still cannot mount")},
			execScripts: []ExecArgs{
				{"file", []string{"-L", "--special-files", "/dev/foo"}, "data", nil},
				{"mkfs.ext4", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", nil},
			},
			expectedError: fmt.Errorf("Still cannot mount"),
		},
		{ // Test that 'file' is called and confirms unformatted disk, format passes, second mount passes
			fstype:    "ext4",
			mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
			execScripts: []ExecArgs{
				{"file", []string{"-L", "--special-files", "/dev/foo"}, "data", nil},
				{"mkfs.ext4", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", nil},
			},
			expectedError: nil,
		},
		{ // Test that 'file' is called and confirms unformatted disk, format passes, second mount passes with ext3
			fstype:    "ext3",
			mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
			execScripts: []ExecArgs{
				{"file", []string{"-L", "--special-files", "/dev/foo"}, "data", nil},
				{"mkfs.ext3", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", nil},
			},
			expectedError: nil,
		},
	}

	for _, test := range tests {
		commandScripts := []exec.FakeCommandAction{}
		for _, expected := range test.execScripts {
			ecmd := expected.command
			eargs := expected.args
			output := expected.output
			err := expected.err
			commandScript := func(cmd string, args ...string) exec.Cmd {
				if cmd != ecmd {
					t.Errorf("Unexpected command %s. Expecting %s", cmd, ecmd)
				}

				for j := range args {
					if args[j] != eargs[j] {
						t.Errorf("Unexpected args %v. Expecting %v", args, eargs)
					}
				}
				fake := exec.FakeCmd{
					CombinedOutputScript: []exec.FakeCombinedOutputAction{
						func() ([]byte, error) { return []byte(output), err },
					},
				}
				return exec.InitFakeCmd(&fake, cmd, args...)
			}
			commandScripts = append(commandScripts, commandScript)
		}

		fake := exec.FakeExec{
			CommandScript: commandScripts,
		}

		fakeMounter := ErrorMounter{&mount.FakeMounter{}, 0, test.mountErrs}
		mounter := gceSafeFormatAndMount{
			Interface: &fakeMounter,
			runner:    &fake,
		}

		device := "/dev/foo"
		dest := "/mnt/bar"
		err := mounter.Mount(device, dest, test.fstype, test.mountOptions)
		if test.expectedError == nil {
			if err != nil {
				t.Errorf("unexpected non-error: %v", err)
			}

			// Check that something was mounted on the directory
			isMountPoint, err := fakeMounter.IsMountPoint(dest)
			if err != nil || !isMountPoint {
				t.Errorf("the directory was not mounted")
			}

			//check that the correct device was mounted
			mountedDevice, _, err := mount.GetDeviceNameFromMount(fakeMounter.FakeMounter, dest)
			if err != nil || mountedDevice != device {
				t.Errorf("the correct device was not mounted")
			}
		} else {
			if err == nil || test.expectedError.Error() != err.Error() {
				t.Errorf("unexpected error: %v. Expecting %v", err, test.expectedError)
			}
		}
	}
}