Exemplo n.º 1
0
func (ad *attacherDetacher) generateDetachVolumeFunc(
	volumeToDetach cache.AttachedVolume,
	actualStateOfWorld cache.ActualStateOfWorld) (func() error, error) {
	// Get attacher plugin
	attachableVolumePlugin, err := ad.volumePluginMgr.FindAttachablePluginBySpec(volumeToDetach.VolumeSpec)
	if err != nil || attachableVolumePlugin == nil {
		return nil, fmt.Errorf(
			"failed to get AttachablePlugin from volumeSpec for volume %q err=%v",
			volumeToDetach.VolumeSpec.Name(),
			err)
	}

	deviceName, err := attachableVolumePlugin.GetDeviceName(volumeToDetach.VolumeSpec)
	if err != nil {
		return nil, fmt.Errorf(
			"failed to GetDeviceName from AttachablePlugin for volumeSpec %q err=%v",
			volumeToDetach.VolumeSpec.Name(),
			err)
	}

	volumeDetacher, err := attachableVolumePlugin.NewDetacher()
	if err != nil {
		return nil, fmt.Errorf(
			"failed to get NewDetacher from volumeSpec for volume %q err=%v",
			volumeToDetach.VolumeSpec.Name(),
			err)
	}

	return func() error {
		// Execute detach
		detachErr := volumeDetacher.Detach(deviceName, volumeToDetach.NodeName)

		if detachErr != nil {
			// On failure, just log and exit. The controller will retry
			glog.Errorf(
				"Detach operation for device %q from node %q failed with: %v",
				volumeToDetach.VolumeName, volumeToDetach.NodeName, detachErr)
			return detachErr
		}

		glog.Infof(
			"Successfully detached device %q from node %q. Will update actual state of world.",
			volumeToDetach.VolumeName, volumeToDetach.NodeName)

		// Update actual state of world
		actualStateOfWorld.DeleteVolumeNode(volumeToDetach.VolumeName, volumeToDetach.NodeName)

		return nil
	}, nil
}