func (ad *attacherDetacher) generateAttachVolumeFunc( volumeToAttach cache.VolumeToAttach, actualStateOfWorld cache.ActualStateOfWorld) (func() error, error) { // Get attacher plugin attachableVolumePlugin, err := ad.volumePluginMgr.FindAttachablePluginBySpec(volumeToAttach.VolumeSpec) if err != nil || attachableVolumePlugin == nil { return nil, fmt.Errorf( "failed to get AttachablePlugin from volumeSpec for volume %q err=%v", volumeToAttach.VolumeSpec.Name(), err) } volumeAttacher, newAttacherErr := attachableVolumePlugin.NewAttacher() if newAttacherErr != nil { return nil, fmt.Errorf( "failed to get NewAttacher from volumeSpec for volume %q err=%v", volumeToAttach.VolumeSpec.Name(), newAttacherErr) } return func() error { // Execute attach attachErr := volumeAttacher.Attach(volumeToAttach.VolumeSpec, volumeToAttach.NodeName) if attachErr != nil { // On failure, just log and exit. The controller will retry glog.Errorf( "Attach operation for device %q to node %q failed with: %v", volumeToAttach.VolumeName, volumeToAttach.NodeName, attachErr) return attachErr } glog.Infof( "Successfully attached device %q to node %q. Will update actual state of world.", volumeToAttach.VolumeName, volumeToAttach.NodeName) // Update actual state of world _, addVolumeNodeErr := actualStateOfWorld.AddVolumeNode(volumeToAttach.VolumeSpec, volumeToAttach.NodeName) if addVolumeNodeErr != nil { // On failure, just log and exit. The controller will retry glog.Errorf( "Attach operation for device %q to node %q succeeded, but updating actualStateOfWorld failed with: %v", volumeToAttach.VolumeName, volumeToAttach.NodeName, addVolumeNodeErr) return addVolumeNodeErr } return nil }, nil }