// DetachDisk detaches a disk
323643
func (gce *Cloud) DetachDisk(devicePath string, nodeName types.NodeName) error {
	instanceName := mapNodeNameToInstanceName(nodeName)
	inst, err := gce.getInstanceByName(instanceName)
	if err != nil {
		if err == cloudprovider.ErrInstanceNotFound {
			// If instance no longer exists, safe to assume volume is not attached.
			glog.Warningf(
				"Instance %q does not exist. DetachDisk will assume PD %q is not attached to it.",
				instanceName,
				devicePath)
			return nil
		}

		return fmt.Errorf("error getting instance %q", instanceName)
	}

	detachOp, err := gce.service.Instances.DetachDisk(gce.projectID, inst.Zone, inst.Name, devicePath).Do()
	if err != nil {
		return err
	}

	return gce.waitForZoneOp(detachOp, inst.Zone)
}
1075051
func (m *MockAgentClient) RemovePersistentDisk(arg0 string) error {
	ret := m.ctrl.Call(m, "RemovePersistentDisk", arg0)
	ret0, _ := ret[0].(error)
	return ret0
}
391166
func (vm *VirtualMachine) DetachDisk(ctx context.Context, vmDiskPath string) error {
	vmDiskPath = RemoveStorageClusterORFolderNameFromVDiskPath(vmDiskPath)
	device, err := vm.getVirtualDeviceByPath(ctx, vmDiskPath)
	if err != nil {
		klog.Errorf("Disk ID not found for VM: %q with diskPath: %q", vm.InventoryPath, vmDiskPath)
		return err
	}
	if device == nil {
		klog.Errorf("No virtual device found with diskPath: %q on VM: %q", vmDiskPath, vm.InventoryPath)
		return fmt.Errorf("No virtual device found with diskPath: %q on VM: %q", vmDiskPath, vm.InventoryPath)
	}
	// Detach disk from VM
	requestTime := time.Now()
	err = vm.RemoveDevice(ctx, true, device)
	RecordvSphereMetric(APIDetachVolume, requestTime, err)
	if err != nil {
		klog.Errorf("Error occurred while removing disk device for VM: %q. err: %v", vm.InventoryPath, err)
		return err
	}
	return nil
}
1288890
func (v *volumeSource) DetachVolumes(ctx context.ProviderCallContext, attachParams []storage.VolumeAttachmentParams) ([]error, error) {
	// noop
	return make([]error, len(attachParams)), nil
}
754431
func (d *detacherDefaults) Detach(volumeName string, hostName types.NodeName) error {
	klog.Warning(logPrefix(d.plugin.flexVolumePlugin), "using default Detach for volume ", volumeName, ", host ", hostName)
	return nil
}
1010866
func (os *OpenStack) AttachDisk(instanceID, volumeID string) (string, error) {
	volume, err := os.getVolume(volumeID)
	if err != nil {
		return "", err
	}
	if volume.Status != VolumeAvailableStatus {
		errmsg := fmt.Sprintf("volume %s status is %s, not %s, can not be attached to instance %s.", volume.Name, volume.Status, VolumeAvailableStatus, instanceID)
		glog.Error(errmsg)
		return "", errors.New(errmsg)
	}
	cClient, err := os.NewComputeV2()
	if err != nil {
		return "", err
	}

	if volume.AttachedServerID != "" {
		if instanceID == volume.AttachedServerID {
			glog.V(4).Infof("Disk %s is already attached to instance %s", volumeID, instanceID)
			return volume.ID, nil
		}
		glog.V(2).Infof("Disk %s is attached to a different instance (%s), detaching", volumeID, volume.AttachedServerID)
		err = os.DetachDisk(volume.AttachedServerID, volumeID)
		if err != nil {
			return "", err
		}
	}

	// add read only flag here if possible spothanis
	_, err = volumeattach.Create(cClient, instanceID, &volumeattach.CreateOpts{
		VolumeID: volume.ID,
	}).Extract()
	if err != nil {
		glog.Errorf("Failed to attach %s volume to %s compute: %v", volumeID, instanceID, err)
		return "", err
	}
	glog.V(2).Infof("Successfully attached %s volume to %s compute", volumeID, instanceID)
	return volume.ID, nil
}
632255
func (ga *openstackStorageAdapter) DetachVolume(serverId, attachmentId string) error {
	if err := ga.novaClient.DetachVolume(serverId, attachmentId); err != nil {
		if gooseerrors.IsNotFound(err) {
			return errors.NewNotFound(nil,
				fmt.Sprintf("volume %q is not attached to server %q",
					attachmentId, serverId,
				),
			)
		}
		return err
	}
	return nil
}
1190642
func (f *FlatReactor) Detach(rm Reactor) {
	f.enders.Disable(rm)
	f.branches.Disable(rm)
}
582222
func Detach(id string, params *stripe.SourceObjectDetachParams) (*stripe.Source, error) {
	return getC().Detach(id, params)
}
571169
func (s *noopFilesystemSource) DetachFilesystems(ctx environscontext.ProviderCallContext, args []storage.FilesystemAttachmentParams) ([]error, error) {
	return make([]error, len(args)), nil
}
955880
func (util *fcUtil) DetachDisk(c fcDiskUnmounter, devicePath string) error {
	var devices []string
	// devicePath might be like /dev/mapper/mpathX. Find destination.
	dstPath, err := c.io.EvalSymlinks(devicePath)
	if err != nil {
		return err
	}
	// Find slave
	if strings.HasPrefix(dstPath, "/dev/dm-") {
		devices = c.deviceUtil.FindSlaveDevicesOnMultipath(dstPath)
	} else {
		// Add single devicepath to devices
		devices = append(devices, dstPath)
	}
	klog.V(4).Infof("fc: DetachDisk devicePath: %v, dstPath: %v, devices: %v", devicePath, dstPath, devices)
	var lastErr error
	for _, device := range devices {
		err := util.detachFCDisk(c.io, device)
		if err != nil {
			klog.Errorf("fc: detachFCDisk failed. device: %v err: %v", device, err)
			lastErr = fmt.Errorf("fc: detachFCDisk failed. device: %v err: %v", device, err)
		}
	}
	if lastErr != nil {
		klog.Errorf("fc: last error occurred during detach disk:\n%v", lastErr)
		return lastErr
	}
	return nil
}
1013740
func (s *awsService) Detach(ctx context.Context, groupID string, instanceIDs []string) error {
	input := &aws.DetachGroupInput{
		GroupID:                       fi.String(groupID),
		InstanceIDs:                   instanceIDs,
		ShouldDecrementTargetCapacity: fi.Bool(false),
		ShouldTerminateInstances:      fi.Bool(true),
	}

	_, err := s.svc.Detach(ctx, input)
	return err
}
1245538
func (s *VolumeServer) Detach(
	ctx context.Context,
	req *api.SdkVolumeDetachRequest,
) (*api.SdkVolumeDetachResponse, error) {
	if s.cluster() == nil || s.driver(ctx) == nil {
		return nil, status.Error(codes.Unavailable, "Resource has not been initialized")
	}

	if len(req.GetVolumeId()) == 0 {
		return nil, status.Error(codes.InvalidArgument, "Must supply volume id")
	}

	// Get access rights
	err := s.checkAccessForVolumeId(ctx, req.GetVolumeId(), api.Ownership_Write)
	if err != nil && !IsErrorNotFound(err) {
		return nil, err
	}

	// Check options
	options := req.GetDriverOptions()
	if options == nil {
		options = make(map[string]string)
	}
	options[mountattachoptions.OptionsRedirectDetach] = "true"
	if req.GetOptions() != nil {
		options[mountattachoptions.OptionsForceDetach] = fmt.Sprint(req.GetOptions().GetForce())
		options[mountattachoptions.OptionsUnmountBeforeDetach] = fmt.Sprint(req.GetOptions().GetUnmountBeforeDetach())
	}

	err = s.driver(ctx).Detach(req.GetVolumeId(), options)
	if err != nil && !IsErrorNotFound(err) {
		return nil, status.Errorf(
			codes.Internal,
			"Failed to detach volume %s: %v",
			req.GetVolumeId(),
			err)
	}

	return &api.SdkVolumeDetachResponse{}, nil
}
986148
func (p *Process) Detach(kill bool) error {
	if kill && !p.exited {
		err := p.conn.kill()
		if err != nil {
			if _, exited := err.(proc.ErrProcessExited); !exited {
				return err
			}
			p.exited = true
		}
	}
	if !p.exited {
		if err := p.conn.detach(); err != nil {
			return err
		}
	}
	if p.process != nil {
		p.process.Kill()
		<-p.waitChan
		p.process = nil
	}
	p.detached = true
	return p.bi.Close()
}
670821
func (ec2i *FakeEC2Impl) DetachVolume(request *ec2.DetachVolumeInput) (resp *ec2.VolumeAttachment, err error) {
	panic("Not implemented")
}
454610
func (util *ISCSIUtil) DetachDisk(c iscsiDiskUnmounter, mntPath string) error {
	if pathExists, pathErr := mount.PathExists(mntPath); pathErr != nil {
		return fmt.Errorf("Error checking if path exists: %v", pathErr)
	} else if !pathExists {
		klog.Warningf("Warning: Unmount skipped because path does not exist: %v", mntPath)
		return nil
	}

	notMnt, err := c.mounter.IsLikelyNotMountPoint(mntPath)
	if err != nil {
		return err
	}
	if !notMnt {
		if err := c.mounter.Unmount(mntPath); err != nil {
			klog.Errorf("iscsi detach disk: failed to unmount: %s\nError: %v", mntPath, err)
			return err
		}
	}

	// if device is no longer used, see if need to logout the target
	device, prefix, err := extractDeviceAndPrefix(mntPath)
	if err != nil {
		return err
	}

	var bkpPortal []string
	var volName, iqn, iface, initiatorName string
	found := true

	// load iscsi disk config from json file
	if err := util.loadISCSI(c.iscsiDisk, mntPath); err == nil {
		bkpPortal, iqn, iface, volName = c.iscsiDisk.Portals, c.iscsiDisk.Iqn, c.iscsiDisk.Iface, c.iscsiDisk.VolName
		initiatorName = c.iscsiDisk.InitiatorName
	} else {
		// If the iscsi disk config is not found, fall back to the original behavior.
		// This portal/iqn/iface is no longer referenced, log out.
		// Extract the portal and iqn from device path.
		bkpPortal = make([]string, 1)
		bkpPortal[0], iqn, err = extractPortalAndIqn(device)
		if err != nil {
			return err
		}
		// Extract the iface from the mountPath and use it to log out. If the iface
		// is not found, maintain the previous behavior to facilitate kubelet upgrade.
		// Logout may fail as no session may exist for the portal/IQN on the specified interface.
		iface, found = extractIface(mntPath)
	}

	// Delete all the scsi devices and any multipath devices after unmounting
	if err = deleteDevices(c); err != nil {
		klog.Warningf("iscsi detach disk: failed to delete devices\nError: %v", err)
		// Fall through -- even if deleting fails, a logout may fix problems
	}

	// Lock the target while we determine if we can safely log out or not
	c.plugin.targetLocks.LockKey(iqn)
	defer c.plugin.targetLocks.UnlockKey(iqn)

	// if device is no longer used, see if need to logout the target
	refCount, err := getDevicePrefixRefCount(c.mounter, prefix)
	if err != nil || refCount != 0 {
		return nil
	}

	portals := removeDuplicate(bkpPortal)
	if len(portals) == 0 {
		return fmt.Errorf("iscsi detach disk: failed to detach iscsi disk. Couldn't get connected portals from configurations")
	}

	err = util.detachISCSIDisk(c.exec, portals, iqn, iface, volName, initiatorName, found)
	if err != nil {
		return fmt.Errorf("failed to finish detachISCSIDisk, err: %v", err)
	}
	return nil
}
179195
func (util *RBDUtil) DetachDisk(plugin *rbdPlugin, deviceMountPath string, device string) error {
	if len(device) == 0 {
		return fmt.Errorf("DetachDisk failed , device is empty")
	}

	exec := plugin.host.GetExec(plugin.GetPluginName())

	var rbdCmd string

	// Unlike map, we cannot fallthrough for unmap
	// the tool to unmap is based on device type
	if strings.HasPrefix(device, "/dev/nbd") {
		rbdCmd = "rbd-nbd"
	} else {
		rbdCmd = "rbd"
	}

	// rbd unmap
	output, err := exec.Run(rbdCmd, "unmap", device)
	if err != nil {
		return rbdErrors(err, fmt.Errorf("rbd: failed to unmap device %s, error %v, rbd output: %v", device, err, output))
	}
	klog.V(3).Infof("rbd: successfully unmap device %s", device)

	// Currently, we don't persist rbd info on the disk, but for backward
	// compatbility, we need to clean it if found.
	rbdFile := filepath.Join(deviceMountPath, "rbd.json")
	exists, err := utilpath.Exists(utilpath.CheckFollowSymlink, rbdFile)
	if err != nil {
		return err
	}
	if exists {
		klog.V(3).Infof("rbd: old rbd.json is found under %s, cleaning it", deviceMountPath)
		err = util.cleanOldRBDFile(plugin, rbdFile)
		if err != nil {
			klog.Errorf("rbd: failed to clean %s", rbdFile)
			return err
		}
		klog.V(3).Infof("rbd: successfully remove %s", rbdFile)
	}
	return nil
}