k8s.io/kubernetes@v1.29.3/pkg/controller/volume/persistentvolume/pv_controller.go (about)

     1  /*
     2  Copyright 2016 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package persistentvolume
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"reflect"
    23  	"strings"
    24  	"time"
    25  
    26  	utilfeature "k8s.io/apiserver/pkg/util/feature"
    27  	"k8s.io/kubernetes/pkg/features"
    28  	"k8s.io/kubernetes/pkg/util/slice"
    29  
    30  	v1 "k8s.io/api/core/v1"
    31  	storage "k8s.io/api/storage/v1"
    32  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    33  	"k8s.io/apimachinery/pkg/api/resource"
    34  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    35  	"k8s.io/apimachinery/pkg/util/sets"
    36  	clientset "k8s.io/client-go/kubernetes"
    37  	"k8s.io/client-go/kubernetes/scheme"
    38  	corelisters "k8s.io/client-go/listers/core/v1"
    39  	storagelisters "k8s.io/client-go/listers/storage/v1"
    40  	"k8s.io/client-go/tools/cache"
    41  	"k8s.io/client-go/tools/record"
    42  	ref "k8s.io/client-go/tools/reference"
    43  	"k8s.io/client-go/util/workqueue"
    44  	cloudprovider "k8s.io/cloud-provider"
    45  	volerr "k8s.io/cloud-provider/volume/errors"
    46  	storagehelpers "k8s.io/component-helpers/storage/volume"
    47  	"k8s.io/kubernetes/pkg/controller/volume/common"
    48  	"k8s.io/kubernetes/pkg/controller/volume/events"
    49  	"k8s.io/kubernetes/pkg/controller/volume/persistentvolume/metrics"
    50  	"k8s.io/kubernetes/pkg/util/goroutinemap"
    51  	"k8s.io/kubernetes/pkg/util/goroutinemap/exponentialbackoff"
    52  	vol "k8s.io/kubernetes/pkg/volume"
    53  	"k8s.io/kubernetes/pkg/volume/util"
    54  	"k8s.io/kubernetes/pkg/volume/util/recyclerclient"
    55  	volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
    56  
    57  	"k8s.io/klog/v2"
    58  )
    59  
    60  // ==================================================================
    61  // PLEASE DO NOT ATTEMPT TO SIMPLIFY THIS CODE.
    62  // KEEP THE SPACE SHUTTLE FLYING.
    63  // ==================================================================
    64  //
    65  // This controller is intentionally written in a very verbose style. You will
    66  // notice:
    67  //
    68  // 1. Every 'if' statement has a matching 'else' (exception: simple error
    69  //    checks for a client API call)
    70  // 2. Things that may seem obvious are commented explicitly
    71  //
    72  // We call this style 'space shuttle style'. Space shuttle style is meant to
    73  // ensure that every branch and condition is considered and accounted for -
    74  // the same way code is written at NASA for applications like the space
    75  // shuttle.
    76  //
    77  // Originally, the work of this controller was split amongst three
    78  // controllers. This controller is the result a large effort to simplify the
    79  // PV subsystem. During that effort, it became clear that we needed to ensure
    80  // that every single condition was handled and accounted for in the code, even
    81  // if it resulted in no-op code branches.
    82  //
    83  // As a result, the controller code may seem overly verbose, commented, and
    84  // 'branchy'. However, a large amount of business knowledge and context is
    85  // recorded here in order to ensure that future maintainers can correctly
    86  // reason through the complexities of the binding behavior. For that reason,
    87  // changes to this file should preserve and add to the space shuttle style.
    88  //
    89  // ==================================================================
    90  // PLEASE DO NOT ATTEMPT TO SIMPLIFY THIS CODE.
    91  // KEEP THE SPACE SHUTTLE FLYING.
    92  // ==================================================================
    93  
    94  // Design:
    95  //
    96  // The fundamental key to this design is the bi-directional "pointer" between
    97  // PersistentVolumes (PVs) and PersistentVolumeClaims (PVCs), which is
    98  // represented here as pvc.Spec.VolumeName and pv.Spec.ClaimRef. The bi-
    99  // directionality is complicated to manage in a transactionless system, but
   100  // without it we can't ensure sane behavior in the face of different forms of
   101  // trouble. For example, a rogue HA controller instance could end up racing
   102  // and making multiple bindings that are indistinguishable, resulting in
   103  // potential data loss.
   104  //
   105  // This controller is designed to work in active-passive high availability
   106  // mode. It *could* work also in active-active HA mode, all the object
   107  // transitions are designed to cope with this, however performance could be
   108  // lower as these two active controllers will step on each other toes
   109  // frequently.
   110  //
   111  // This controller supports pre-bound (by the creator) objects in both
   112  // directions: a PVC that wants a specific PV or a PV that is reserved for a
   113  // specific PVC.
   114  //
   115  // The binding is two-step process. PV.Spec.ClaimRef is modified first and
   116  // PVC.Spec.VolumeName second. At any point of this transaction, the PV or PVC
   117  // can be modified by user or other controller or completely deleted. Also,
   118  // two (or more) controllers may try to bind different volumes to different
   119  // claims at the same time. The controller must recover from any conflicts
   120  // that may arise from these conditions.
   121  
   122  // CloudVolumeCreatedForClaimNamespaceTag is a name of a tag attached to a real volume in cloud (e.g. AWS EBS or GCE PD)
   123  // with namespace of a persistent volume claim used to create this volume.
   124  const CloudVolumeCreatedForClaimNamespaceTag = "kubernetes.io/created-for/pvc/namespace"
   125  
   126  // CloudVolumeCreatedForClaimNameTag is a name of a tag attached to a real volume in cloud (e.g. AWS EBS or GCE PD)
   127  // with name of a persistent volume claim used to create this volume.
   128  const CloudVolumeCreatedForClaimNameTag = "kubernetes.io/created-for/pvc/name"
   129  
   130  // CloudVolumeCreatedForVolumeNameTag is a name of a tag attached to a real volume in cloud (e.g. AWS EBS or GCE PD)
   131  // with name of appropriate Kubernetes persistent volume .
   132  const CloudVolumeCreatedForVolumeNameTag = "kubernetes.io/created-for/pv/name"
   133  
   134  // Number of retries when we create a PV object for a provisioned volume.
   135  const createProvisionedPVRetryCount = 5
   136  
   137  // Interval between retries when we create a PV object for a provisioned volume.
   138  const createProvisionedPVInterval = 10 * time.Second
   139  
   140  // CSINameTranslator can get the CSI Driver name based on the in-tree plugin name
   141  type CSINameTranslator interface {
   142  	GetCSINameFromInTreeName(pluginName string) (string, error)
   143  }
   144  
   145  // CSIMigratedPluginManager keeps track of CSI migration status of a plugin
   146  type CSIMigratedPluginManager interface {
   147  	IsMigrationEnabledForPlugin(pluginName string) bool
   148  }
   149  
   150  // PersistentVolumeController is a controller that synchronizes
   151  // PersistentVolumeClaims and PersistentVolumes. It starts two
   152  // cache.Controllers that watch PersistentVolume and PersistentVolumeClaim
   153  // changes.
   154  type PersistentVolumeController struct {
   155  	volumeLister       corelisters.PersistentVolumeLister
   156  	volumeListerSynced cache.InformerSynced
   157  	claimLister        corelisters.PersistentVolumeClaimLister
   158  	claimListerSynced  cache.InformerSynced
   159  	classLister        storagelisters.StorageClassLister
   160  	classListerSynced  cache.InformerSynced
   161  	podLister          corelisters.PodLister
   162  	podListerSynced    cache.InformerSynced
   163  	podIndexer         cache.Indexer
   164  	NodeLister         corelisters.NodeLister
   165  	NodeListerSynced   cache.InformerSynced
   166  
   167  	kubeClient                clientset.Interface
   168  	eventBroadcaster          record.EventBroadcaster
   169  	eventRecorder             record.EventRecorder
   170  	cloud                     cloudprovider.Interface
   171  	volumePluginMgr           vol.VolumePluginMgr
   172  	enableDynamicProvisioning bool
   173  	clusterName               string
   174  	resyncPeriod              time.Duration
   175  
   176  	// Cache of the last known version of volumes and claims. This cache is
   177  	// thread safe as long as the volumes/claims there are not modified, they
   178  	// must be cloned before any modification. These caches get updated both by
   179  	// "xxx added/updated/deleted" events from etcd and by the controller when
   180  	// it saves newer version to etcd.
   181  	// Why local cache: binding a volume to a claim generates 4 events, roughly
   182  	// in this order (depends on goroutine ordering):
   183  	// - volume.Spec update
   184  	// - volume.Status update
   185  	// - claim.Spec update
   186  	// - claim.Status update
   187  	// With these caches, the controller can check that it has already saved
   188  	// volume.Status and claim.Spec+Status and does not need to do anything
   189  	// when e.g. volume.Spec update event arrives before all the other events.
   190  	// Without this cache, it would see the old version of volume.Status and
   191  	// claim in the informers (it has not been updated from API server events
   192  	// yet) and it would try to fix these objects to be bound together.
   193  	// Any write to API server would fail with version conflict - these objects
   194  	// have been already written.
   195  	volumes persistentVolumeOrderedIndex
   196  	claims  cache.Store
   197  
   198  	// Work queues of claims and volumes to process. Every queue should have
   199  	// exactly one worker thread, especially syncClaim() is not reentrant.
   200  	// Two syncClaims could bind two different claims to the same volume or one
   201  	// claim to two volumes. The controller would recover from this (due to
   202  	// version errors in API server and other checks in this controller),
   203  	// however overall speed of multi-worker controller would be lower than if
   204  	// it runs single thread only.
   205  	claimQueue  *workqueue.Type
   206  	volumeQueue *workqueue.Type
   207  
   208  	// Map of scheduled/running operations.
   209  	runningOperations goroutinemap.GoRoutineMap
   210  
   211  	// For testing only: hook to call before an asynchronous operation starts.
   212  	// Not used when set to nil.
   213  	preOperationHook func(operationName string)
   214  
   215  	createProvisionedPVRetryCount int
   216  	createProvisionedPVInterval   time.Duration
   217  
   218  	// operationTimestamps caches start timestamp of operations
   219  	// (currently provision + binding/deletion) for metric recording.
   220  	// Detailed lifecycle/key for each operation
   221  	// 1. provision + binding
   222  	//     key:        claimKey
   223  	//     start time: user has NOT provide any volume ref in the claim AND
   224  	//                 there is no existing volume found for the claim,
   225  	//                 "provisionClaim" is called with a valid plugin/external provisioner
   226  	//                 to provision a volume
   227  	//     end time:   after a volume has been provisioned and bound to the claim successfully
   228  	//                 the corresponding timestamp entry will be deleted from cache
   229  	//     abort:      claim has not been bound to a volume yet but a claim deleted event
   230  	//                 has been received from API server
   231  	// 2. deletion
   232  	//     key:        volumeName
   233  	//     start time: when "reclaimVolume" process a volume with reclaim policy
   234  	//                 set to be "PersistentVolumeReclaimDelete"
   235  	//     end time:   after a volume deleted event has been received from API server
   236  	//                 the corresponding timestamp entry will be deleted from cache
   237  	//     abort:      N.A.
   238  	operationTimestamps metrics.OperationStartTimeCache
   239  
   240  	translator               CSINameTranslator
   241  	csiMigratedPluginManager CSIMigratedPluginManager
   242  }
   243  
   244  // syncClaim is the main controller method to decide what to do with a claim.
   245  // It's invoked by appropriate cache.Controller callbacks when a claim is
   246  // created, updated or periodically synced. We do not differentiate between
   247  // these events.
   248  // For easier readability, it was split into syncUnboundClaim and syncBoundClaim
   249  // methods.
   250  func (ctrl *PersistentVolumeController) syncClaim(ctx context.Context, claim *v1.PersistentVolumeClaim) error {
   251  	logger := klog.FromContext(ctx)
   252  	logger.V(4).Info("Synchronizing PersistentVolumeClaim", "PVC", klog.KObj(claim), "claimStatus", getClaimStatusForLogging(claim))
   253  
   254  	// Set correct "migrated-to" annotations on PVC and update in API server if
   255  	// necessary
   256  	newClaim, err := ctrl.updateClaimMigrationAnnotations(ctx, claim)
   257  	if err != nil {
   258  		// Nothing was saved; we will fall back into the same
   259  		// condition in the next call to this method
   260  		return err
   261  	}
   262  	claim = newClaim
   263  
   264  	if !metav1.HasAnnotation(claim.ObjectMeta, storagehelpers.AnnBindCompleted) {
   265  		return ctrl.syncUnboundClaim(ctx, claim)
   266  	} else {
   267  		return ctrl.syncBoundClaim(ctx, claim)
   268  	}
   269  }
   270  
   271  // checkVolumeSatisfyClaim checks if the volume requested by the claim satisfies the requirements of the claim
   272  func checkVolumeSatisfyClaim(volume *v1.PersistentVolume, claim *v1.PersistentVolumeClaim) error {
   273  	requestedQty := claim.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
   274  	requestedSize := requestedQty.Value()
   275  
   276  	// check if PV's DeletionTimeStamp is set, if so, return error.
   277  	if volume.ObjectMeta.DeletionTimestamp != nil {
   278  		return fmt.Errorf("the volume is marked for deletion %q", volume.Name)
   279  	}
   280  
   281  	volumeQty := volume.Spec.Capacity[v1.ResourceStorage]
   282  	volumeSize := volumeQty.Value()
   283  	if volumeSize < requestedSize {
   284  		return fmt.Errorf("requested PV is too small")
   285  	}
   286  
   287  	requestedClass := storagehelpers.GetPersistentVolumeClaimClass(claim)
   288  	if storagehelpers.GetPersistentVolumeClass(volume) != requestedClass {
   289  		return fmt.Errorf("storageClassName does not match")
   290  	}
   291  
   292  	if storagehelpers.CheckVolumeModeMismatches(&claim.Spec, &volume.Spec) {
   293  		return fmt.Errorf("incompatible volumeMode")
   294  	}
   295  
   296  	if !storagehelpers.CheckAccessModes(claim, volume) {
   297  		return fmt.Errorf("incompatible accessMode")
   298  	}
   299  
   300  	return nil
   301  }
   302  
   303  // emitEventForUnboundDelayBindingClaim generates informative event for claim
   304  // if it's in delay binding mode and not bound yet.
   305  func (ctrl *PersistentVolumeController) emitEventForUnboundDelayBindingClaim(claim *v1.PersistentVolumeClaim) error {
   306  	reason := events.WaitForFirstConsumer
   307  	message := "waiting for first consumer to be created before binding"
   308  	podNames, err := ctrl.findNonScheduledPodsByPVC(claim)
   309  	if err != nil {
   310  		return err
   311  	}
   312  	if len(podNames) > 0 {
   313  		reason = events.WaitForPodScheduled
   314  		if len(podNames) > 1 {
   315  			// Although only one pod is taken into account in
   316  			// volume scheduling, more than one pods can reference
   317  			// the PVC at the same time. We can't know which pod is
   318  			// used in scheduling, all pods are included.
   319  			message = fmt.Sprintf("waiting for pods %s to be scheduled", strings.Join(podNames, ","))
   320  		} else {
   321  			message = fmt.Sprintf("waiting for pod %s to be scheduled", podNames[0])
   322  		}
   323  	}
   324  	ctrl.eventRecorder.Event(claim, v1.EventTypeNormal, reason, message)
   325  	return nil
   326  }
   327  
   328  // syncUnboundClaim is the main controller method to decide what to do with an
   329  // unbound claim.
   330  func (ctrl *PersistentVolumeController) syncUnboundClaim(ctx context.Context, claim *v1.PersistentVolumeClaim) error {
   331  	// This is a new PVC that has not completed binding
   332  	// OBSERVATION: pvc is "Pending"
   333  	logger := klog.FromContext(ctx)
   334  	if claim.Spec.VolumeName == "" {
   335  		// User did not care which PV they get.
   336  		delayBinding, err := storagehelpers.IsDelayBindingMode(claim, ctrl.classLister)
   337  		if err != nil {
   338  			return err
   339  		}
   340  
   341  		// [Unit test set 1]
   342  		volume, err := ctrl.volumes.findBestMatchForClaim(claim, delayBinding)
   343  		if err != nil {
   344  			logger.V(2).Info("Synchronizing unbound PersistentVolumeClaim, Error finding PV for claim", "PVC", klog.KObj(claim), "err", err)
   345  			return fmt.Errorf("error finding PV for claim %q: %w", claimToClaimKey(claim), err)
   346  		}
   347  		if volume == nil {
   348  			logger.V(4).Info("Synchronizing unbound PersistentVolumeClaim, no volume found", "PVC", klog.KObj(claim))
   349  			// No PV could be found
   350  			// OBSERVATION: pvc is "Pending", will retry
   351  
   352  			logger.V(4).Info("Attempting to assign storage class to unbound PersistentVolumeClaim", "PVC", klog.KObj(claim))
   353  			updated, err := ctrl.assignDefaultStorageClass(ctx, claim)
   354  			if err != nil {
   355  				metrics.RecordRetroactiveStorageClassMetric(false)
   356  				return fmt.Errorf("can't update PersistentVolumeClaim[%q]: %w", claimToClaimKey(claim), err)
   357  			}
   358  			if updated {
   359  				logger.V(4).Info("PersistentVolumeClaim update successful, restarting claim sync", "PVC", klog.KObj(claim))
   360  				metrics.RecordRetroactiveStorageClassMetric(true)
   361  				return nil
   362  			}
   363  
   364  			switch {
   365  			case delayBinding && !storagehelpers.IsDelayBindingProvisioning(claim):
   366  				if err = ctrl.emitEventForUnboundDelayBindingClaim(claim); err != nil {
   367  					return err
   368  				}
   369  			case storagehelpers.GetPersistentVolumeClaimClass(claim) != "":
   370  				if err = ctrl.provisionClaim(ctx, claim); err != nil {
   371  					return err
   372  				}
   373  				return nil
   374  			default:
   375  				ctrl.eventRecorder.Event(claim, v1.EventTypeNormal, events.FailedBinding, "no persistent volumes available for this claim and no storage class is set")
   376  			}
   377  
   378  			// Mark the claim as Pending and try to find a match in the next
   379  			// periodic syncClaim
   380  			if _, err = ctrl.updateClaimStatus(ctx, claim, v1.ClaimPending, nil); err != nil {
   381  				return err
   382  			}
   383  			return nil
   384  		} else /* pv != nil */ {
   385  			// Found a PV for this claim
   386  			// OBSERVATION: pvc is "Pending", pv is "Available"
   387  			claimKey := claimToClaimKey(claim)
   388  			logger.V(4).Info("Synchronizing unbound PersistentVolumeClaim, volume found", "PVC", klog.KObj(claim), "volumeName", volume.Name, "volumeStatus", getVolumeStatusForLogging(volume))
   389  			if err = ctrl.bind(ctx, volume, claim); err != nil {
   390  				// On any error saving the volume or the claim, subsequent
   391  				// syncClaim will finish the binding.
   392  				// record count error for provision if exists
   393  				// timestamp entry will remain in cache until a success binding has happened
   394  				metrics.RecordMetric(claimKey, &ctrl.operationTimestamps, err)
   395  				return err
   396  			}
   397  			// OBSERVATION: claim is "Bound", pv is "Bound"
   398  			// if exists a timestamp entry in cache, record end to end provision latency and clean up cache
   399  			// End of the provision + binding operation lifecycle, cache will be cleaned by "RecordMetric"
   400  			// [Unit test 12-1, 12-2, 12-4]
   401  			metrics.RecordMetric(claimKey, &ctrl.operationTimestamps, nil)
   402  			return nil
   403  		}
   404  	} else /* pvc.Spec.VolumeName != nil */ {
   405  		// [Unit test set 2]
   406  		// User asked for a specific PV.
   407  		logger.V(4).Info("Synchronizing unbound PersistentVolumeClaim, volume requested", "PVC", klog.KObj(claim), "volumeName", claim.Spec.VolumeName)
   408  		obj, found, err := ctrl.volumes.store.GetByKey(claim.Spec.VolumeName)
   409  		if err != nil {
   410  			return err
   411  		}
   412  		if !found {
   413  			// User asked for a PV that does not exist.
   414  			// OBSERVATION: pvc is "Pending"
   415  			// Retry later.
   416  			logger.V(4).Info("Synchronizing unbound PersistentVolumeClaim, volume requested and not found, will try again next time", "PVC", klog.KObj(claim), "volumeName", claim.Spec.VolumeName)
   417  			if _, err = ctrl.updateClaimStatus(ctx, claim, v1.ClaimPending, nil); err != nil {
   418  				return err
   419  			}
   420  			return nil
   421  		} else {
   422  			volume, ok := obj.(*v1.PersistentVolume)
   423  			if !ok {
   424  				return fmt.Errorf("cannot convert object from volume cache to volume %q!?: %+v", claim.Spec.VolumeName, obj)
   425  			}
   426  			logger.V(4).Info("Synchronizing unbound PersistentVolumeClaim, volume requested and found", "PVC", klog.KObj(claim), "volumeName", claim.Spec.VolumeName, "volumeStatus", getVolumeStatusForLogging(volume))
   427  			if volume.Spec.ClaimRef == nil {
   428  				// User asked for a PV that is not claimed
   429  				// OBSERVATION: pvc is "Pending", pv is "Available"
   430  				logger.V(4).Info("Synchronizing unbound PersistentVolumeClaim, volume is unbound, binding", "PVC", klog.KObj(claim))
   431  				if err = checkVolumeSatisfyClaim(volume, claim); err != nil {
   432  					logger.V(4).Info("Can't bind the claim to volume", "volumeName", volume.Name, "err", err)
   433  					// send an event
   434  					msg := fmt.Sprintf("Cannot bind to requested volume %q: %s", volume.Name, err)
   435  					ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.VolumeMismatch, msg)
   436  					// volume does not satisfy the requirements of the claim
   437  					if _, err = ctrl.updateClaimStatus(ctx, claim, v1.ClaimPending, nil); err != nil {
   438  						return err
   439  					}
   440  				} else if err = ctrl.bind(ctx, volume, claim); err != nil {
   441  					// On any error saving the volume or the claim, subsequent
   442  					// syncClaim will finish the binding.
   443  					return err
   444  				}
   445  				// OBSERVATION: pvc is "Bound", pv is "Bound"
   446  				return nil
   447  			} else if storagehelpers.IsVolumeBoundToClaim(volume, claim) {
   448  				// User asked for a PV that is claimed by this PVC
   449  				// OBSERVATION: pvc is "Pending", pv is "Bound"
   450  				logger.V(4).Info("Synchronizing unbound PersistentVolumeClaim, volume already bound, finishing the binding", "PVC", klog.KObj(claim))
   451  
   452  				// Finish the volume binding by adding claim UID.
   453  				if err = ctrl.bind(ctx, volume, claim); err != nil {
   454  					return err
   455  				}
   456  				// OBSERVATION: pvc is "Bound", pv is "Bound"
   457  				return nil
   458  			} else {
   459  				// User asked for a PV that is claimed by someone else
   460  				// OBSERVATION: pvc is "Pending", pv is "Bound"
   461  				if !metav1.HasAnnotation(claim.ObjectMeta, storagehelpers.AnnBoundByController) {
   462  					logger.V(4).Info("Synchronizing unbound PersistentVolumeClaim, volume already bound to different claim by user, will retry later", "PVC", klog.KObj(claim))
   463  					claimMsg := fmt.Sprintf("volume %q already bound to a different claim.", volume.Name)
   464  					ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.FailedBinding, claimMsg)
   465  					// User asked for a specific PV, retry later
   466  					if _, err = ctrl.updateClaimStatus(ctx, claim, v1.ClaimPending, nil); err != nil {
   467  						return err
   468  					}
   469  					return nil
   470  				} else {
   471  					// This should never happen because someone had to remove
   472  					// AnnBindCompleted annotation on the claim.
   473  					logger.V(4).Info("Synchronizing unbound PersistentVolumeClaim, volume already bound to different claim by controller, THIS SHOULD NEVER HAPPEN", "PVC", klog.KObj(claim), "boundClaim", klog.KRef(volume.Spec.ClaimRef.Namespace, volume.Spec.ClaimRef.Name))
   474  					claimMsg := fmt.Sprintf("volume %q already bound to a different claim.", volume.Name)
   475  					ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.FailedBinding, claimMsg)
   476  
   477  					return fmt.Errorf("invalid binding of claim %q to volume %q: volume already claimed by %q", claimToClaimKey(claim), claim.Spec.VolumeName, claimrefToClaimKey(volume.Spec.ClaimRef))
   478  				}
   479  			}
   480  		}
   481  	}
   482  }
   483  
   484  // syncBoundClaim is the main controller method to decide what to do with a
   485  // bound claim.
   486  func (ctrl *PersistentVolumeController) syncBoundClaim(ctx context.Context, claim *v1.PersistentVolumeClaim) error {
   487  	// HasAnnotation(pvc, storagehelpers.AnnBindCompleted)
   488  	// This PVC has previously been bound
   489  	// OBSERVATION: pvc is not "Pending"
   490  	// [Unit test set 3]
   491  
   492  	logger := klog.FromContext(ctx)
   493  
   494  	if claim.Spec.VolumeName == "" {
   495  		// Claim was bound before but not any more.
   496  		if _, err := ctrl.updateClaimStatusWithEvent(ctx, claim, v1.ClaimLost, nil, v1.EventTypeWarning, "ClaimLost", "Bound claim has lost reference to PersistentVolume. Data on the volume is lost!"); err != nil {
   497  			return err
   498  		}
   499  		return nil
   500  	}
   501  	obj, found, err := ctrl.volumes.store.GetByKey(claim.Spec.VolumeName)
   502  	if err != nil {
   503  		return err
   504  	}
   505  	if !found {
   506  		// Claim is bound to a non-existing volume.
   507  		if _, err = ctrl.updateClaimStatusWithEvent(ctx, claim, v1.ClaimLost, nil, v1.EventTypeWarning, "ClaimLost", "Bound claim has lost its PersistentVolume. Data on the volume is lost!"); err != nil {
   508  			return err
   509  		}
   510  		return nil
   511  	} else {
   512  		volume, ok := obj.(*v1.PersistentVolume)
   513  		if !ok {
   514  			return fmt.Errorf("cannot convert object from volume cache to volume %q!?: %#v", claim.Spec.VolumeName, obj)
   515  		}
   516  
   517  		logger.V(4).Info("Synchronizing bound PersistentVolumeClaim, volume found", "PVC", klog.KObj(claim), "volumeName", claim.Spec.VolumeName, "volumeStatus", getVolumeStatusForLogging(volume))
   518  		if volume.Spec.ClaimRef == nil {
   519  			// Claim is bound but volume has come unbound.
   520  			// Or, a claim was bound and the controller has not received updated
   521  			// volume yet. We can't distinguish these cases.
   522  			// Bind the volume again and set all states to Bound.
   523  			logger.V(4).Info("Synchronizing bound PersistentVolumeClaim, volume is unbound, fixing", "PVC", klog.KObj(claim))
   524  			if err = ctrl.bind(ctx, volume, claim); err != nil {
   525  				// Objects not saved, next syncPV or syncClaim will try again
   526  				return err
   527  			}
   528  			return nil
   529  		} else if volume.Spec.ClaimRef.UID == claim.UID {
   530  			// All is well
   531  			// NOTE: syncPV can handle this so it can be left out.
   532  			// NOTE: bind() call here will do nothing in most cases as
   533  			// everything should be already set.
   534  			logger.V(4).Info("Synchronizing bound PersistentVolumeClaim, claim is already correctly bound", "PVC", klog.KObj(claim))
   535  			if err = ctrl.bind(ctx, volume, claim); err != nil {
   536  				// Objects not saved, next syncPV or syncClaim will try again
   537  				return err
   538  			}
   539  			return nil
   540  		} else {
   541  			// Claim is bound but volume has a different claimant.
   542  			// Set the claim phase to 'Lost', which is a terminal
   543  			// phase.
   544  			if _, err = ctrl.updateClaimStatusWithEvent(ctx, claim, v1.ClaimLost, nil, v1.EventTypeWarning, "ClaimMisbound", "Two claims are bound to the same volume, this one is bound incorrectly"); err != nil {
   545  				return err
   546  			}
   547  			return nil
   548  		}
   549  	}
   550  }
   551  
   552  // syncVolume is the main controller method to decide what to do with a volume.
   553  // It's invoked by appropriate cache.Controller callbacks when a volume is
   554  // created, updated or periodically synced. We do not differentiate between
   555  // these events.
   556  func (ctrl *PersistentVolumeController) syncVolume(ctx context.Context, volume *v1.PersistentVolume) error {
   557  	logger := klog.FromContext(ctx)
   558  	logger.V(4).Info("Synchronizing PersistentVolume", "volumeName", volume.Name, "volumeStatus", getVolumeStatusForLogging(volume))
   559  	// Set correct "migrated-to" annotations and modify finalizers on PV and update in API server if
   560  	// necessary
   561  	newVolume, err := ctrl.updateVolumeMigrationAnnotationsAndFinalizers(ctx, volume)
   562  	if err != nil {
   563  		// Nothing was saved; we will fall back into the same
   564  		// condition in the next call to this method
   565  		return err
   566  	}
   567  	volume = newVolume
   568  
   569  	// [Unit test set 4]
   570  	if volume.Spec.ClaimRef == nil {
   571  		// Volume is unused
   572  		logger.V(4).Info("Synchronizing PersistentVolume, volume is unused", "volumeName", volume.Name)
   573  		if _, err := ctrl.updateVolumePhase(ctx, volume, v1.VolumeAvailable, ""); err != nil {
   574  			// Nothing was saved; we will fall back into the same
   575  			// condition in the next call to this method
   576  			return err
   577  		}
   578  		return nil
   579  	} else /* pv.Spec.ClaimRef != nil */ {
   580  		// Volume is bound to a claim.
   581  		if volume.Spec.ClaimRef.UID == "" {
   582  			// The PV is reserved for a PVC; that PVC has not yet been
   583  			// bound to this PV; the PVC sync will handle it.
   584  			logger.V(4).Info("Synchronizing PersistentVolume, volume is pre-bound to claim", "PVC", klog.KRef(volume.Spec.ClaimRef.Namespace, volume.Spec.ClaimRef.Name), "volumeName", volume.Name)
   585  			if _, err := ctrl.updateVolumePhase(ctx, volume, v1.VolumeAvailable, ""); err != nil {
   586  				// Nothing was saved; we will fall back into the same
   587  				// condition in the next call to this method
   588  				return err
   589  			}
   590  			return nil
   591  		}
   592  		logger.V(4).Info("Synchronizing PersistentVolume, volume is bound to claim", "PVC", klog.KRef(volume.Spec.ClaimRef.Namespace, volume.Spec.ClaimRef.Name), "volumeName", volume.Name)
   593  		// Get the PVC by _name_
   594  		var claim *v1.PersistentVolumeClaim
   595  		claimName := claimrefToClaimKey(volume.Spec.ClaimRef)
   596  		obj, found, err := ctrl.claims.GetByKey(claimName)
   597  		if err != nil {
   598  			return err
   599  		}
   600  		if !found {
   601  			// If the PV was created by an external PV provisioner or
   602  			// bound by external PV binder (e.g. kube-scheduler), it's
   603  			// possible under heavy load that the corresponding PVC is not synced to
   604  			// controller local cache yet. So we need to double-check PVC in
   605  			//   1) informer cache
   606  			//   2) apiserver if not found in informer cache
   607  			// to make sure we will not reclaim a PV wrongly.
   608  			// Note that only non-released and non-failed volumes will be
   609  			// updated to Released state when PVC does not exist.
   610  			if volume.Status.Phase != v1.VolumeReleased && volume.Status.Phase != v1.VolumeFailed {
   611  				obj, err = ctrl.claimLister.PersistentVolumeClaims(volume.Spec.ClaimRef.Namespace).Get(volume.Spec.ClaimRef.Name)
   612  				if err != nil && !apierrors.IsNotFound(err) {
   613  					return err
   614  				}
   615  				found = !apierrors.IsNotFound(err)
   616  				if !found {
   617  					obj, err = ctrl.kubeClient.CoreV1().PersistentVolumeClaims(volume.Spec.ClaimRef.Namespace).Get(ctx, volume.Spec.ClaimRef.Name, metav1.GetOptions{})
   618  					if err != nil && !apierrors.IsNotFound(err) {
   619  						return err
   620  					}
   621  					found = !apierrors.IsNotFound(err)
   622  				}
   623  			}
   624  		}
   625  		if !found {
   626  			logger.V(4).Info("Synchronizing PersistentVolume, claim not found", "PVC", klog.KRef(volume.Spec.ClaimRef.Namespace, volume.Spec.ClaimRef.Name), "volumeName", volume.Name)
   627  			// Fall through with claim = nil
   628  		} else {
   629  			var ok bool
   630  			claim, ok = obj.(*v1.PersistentVolumeClaim)
   631  			if !ok {
   632  				return fmt.Errorf("cannot convert object from volume cache to volume %q!?: %#v", claim.Spec.VolumeName, obj)
   633  			}
   634  			logger.V(4).Info("Synchronizing PersistentVolume, claim found", "PVC", klog.KRef(volume.Spec.ClaimRef.Namespace, volume.Spec.ClaimRef.Name), "claimStatus", getClaimStatusForLogging(claim), "volumeName", volume.Name)
   635  		}
   636  		if claim != nil && claim.UID != volume.Spec.ClaimRef.UID {
   637  			// The claim that the PV was pointing to was deleted, and another
   638  			// with the same name created.
   639  			// in some cases, the cached claim is not the newest, and the volume.Spec.ClaimRef.UID is newer than cached.
   640  			// so we should double check by calling apiserver and get the newest claim, then compare them.
   641  			logger.V(4).Info("Maybe cached claim is not the newest one, we should fetch it from apiserver", "PVC", klog.KRef(volume.Spec.ClaimRef.Namespace, volume.Spec.ClaimRef.Name))
   642  
   643  			claim, err = ctrl.kubeClient.CoreV1().PersistentVolumeClaims(volume.Spec.ClaimRef.Namespace).Get(ctx, volume.Spec.ClaimRef.Name, metav1.GetOptions{})
   644  			if err != nil && !apierrors.IsNotFound(err) {
   645  				return err
   646  			} else if claim != nil {
   647  				// Treat the volume as bound to a missing claim.
   648  				if claim.UID != volume.Spec.ClaimRef.UID {
   649  					logger.V(4).Info("Synchronizing PersistentVolume, claim has a newer UID than pv.ClaimRef, the old one must have been deleted", "PVC", klog.KRef(volume.Spec.ClaimRef.Namespace, volume.Spec.ClaimRef.Name), "volumeName", volume.Name)
   650  					claim = nil
   651  				} else {
   652  					logger.V(4).Info("Synchronizing PersistentVolume, claim has a same UID with pv.ClaimRef", "PVC", klog.KRef(volume.Spec.ClaimRef.Namespace, volume.Spec.ClaimRef.Name), "volumeName", volume.Name)
   653  				}
   654  			}
   655  		}
   656  
   657  		if claim == nil {
   658  			// If we get into this block, the claim must have been deleted;
   659  			// NOTE: reclaimVolume may either release the PV back into the pool or
   660  			// recycle it or do nothing (retain)
   661  
   662  			// Do not overwrite previous Failed state - let the user see that
   663  			// something went wrong, while we still re-try to reclaim the
   664  			// volume.
   665  			if volume.Status.Phase != v1.VolumeReleased && volume.Status.Phase != v1.VolumeFailed {
   666  				// Also, log this only once:
   667  				logger.V(2).Info("Volume is released and reclaim policy will be executed", "volumeName", volume.Name, "reclaimPolicy", volume.Spec.PersistentVolumeReclaimPolicy)
   668  				if volume, err = ctrl.updateVolumePhase(ctx, volume, v1.VolumeReleased, ""); err != nil {
   669  					// Nothing was saved; we will fall back into the same condition
   670  					// in the next call to this method
   671  					return err
   672  				}
   673  			}
   674  			if err = ctrl.reclaimVolume(ctx, volume); err != nil {
   675  				// Release failed, we will fall back into the same condition
   676  				// in the next call to this method
   677  				return err
   678  			}
   679  			if volume.Spec.PersistentVolumeReclaimPolicy == v1.PersistentVolumeReclaimRetain {
   680  				// volume is being retained, it references a claim that does not exist now.
   681  				logger.V(4).Info("PersistentVolume references a claim that is not found", "PVC", klog.KRef(volume.Spec.ClaimRef.Namespace, volume.Spec.ClaimRef.Name), "claimUID", volume.Spec.ClaimRef.UID, "volumeName", volume.Name)
   682  			}
   683  			return nil
   684  		} else if claim.Spec.VolumeName == "" {
   685  			if storagehelpers.CheckVolumeModeMismatches(&claim.Spec, &volume.Spec) {
   686  				// Binding for the volume won't be called in syncUnboundClaim,
   687  				// because findBestMatchForClaim won't return the volume due to volumeMode mismatch.
   688  				volumeMsg := fmt.Sprintf("Cannot bind PersistentVolume to requested PersistentVolumeClaim %q due to incompatible volumeMode.", claim.Name)
   689  				ctrl.eventRecorder.Event(volume, v1.EventTypeWarning, events.VolumeMismatch, volumeMsg)
   690  				claimMsg := fmt.Sprintf("Cannot bind PersistentVolume %q to requested PersistentVolumeClaim due to incompatible volumeMode.", volume.Name)
   691  				ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.VolumeMismatch, claimMsg)
   692  				// Skipping syncClaim
   693  				return nil
   694  			}
   695  
   696  			if metav1.HasAnnotation(volume.ObjectMeta, storagehelpers.AnnBoundByController) {
   697  				// The binding is not completed; let PVC sync handle it
   698  				logger.V(4).Info("Synchronizing PersistentVolume, volume not bound yet, waiting for syncClaim to fix it", "volumeName", volume.Name)
   699  			} else {
   700  				// Dangling PV; try to re-establish the link in the PVC sync
   701  				logger.V(4).Info("Synchronizing PersistentVolume, volume was bound and got unbound (by user?), waiting for syncClaim to fix it", "volumeName", volume.Name)
   702  			}
   703  			// In both cases, the volume is Bound and the claim is Pending.
   704  			// Next syncClaim will fix it. To speed it up, we enqueue the claim
   705  			// into the controller, which results in syncClaim to be called
   706  			// shortly (and in the right worker goroutine).
   707  			// This speeds up binding of provisioned volumes - provisioner saves
   708  			// only the new PV and it expects that next syncClaim will bind the
   709  			// claim to it.
   710  			ctrl.claimQueue.Add(claimToClaimKey(claim))
   711  			return nil
   712  		} else if claim.Spec.VolumeName == volume.Name {
   713  			// Volume is bound to a claim properly, update status if necessary
   714  			logger.V(4).Info("Synchronizing PersistentVolume, all is bound", "volumeName", volume.Name)
   715  			if _, err = ctrl.updateVolumePhase(ctx, volume, v1.VolumeBound, ""); err != nil {
   716  				// Nothing was saved; we will fall back into the same
   717  				// condition in the next call to this method
   718  				return err
   719  			}
   720  			return nil
   721  		} else {
   722  			// Volume is bound to a claim, but the claim is bound elsewhere
   723  			if metav1.HasAnnotation(volume.ObjectMeta, storagehelpers.AnnDynamicallyProvisioned) && volume.Spec.PersistentVolumeReclaimPolicy == v1.PersistentVolumeReclaimDelete {
   724  				// This volume was dynamically provisioned for this claim. The
   725  				// claim got bound elsewhere, and thus this volume is not
   726  				// needed. Delete it.
   727  				// Mark the volume as Released for external deleters and to let
   728  				// the user know. Don't overwrite existing Failed status!
   729  				if volume.Status.Phase != v1.VolumeReleased && volume.Status.Phase != v1.VolumeFailed {
   730  					// Also, log this only once:
   731  					logger.V(2).Info("Dynamically provisioned volume is released and it will be deleted", "volumeName", volume.Name)
   732  					if volume, err = ctrl.updateVolumePhase(ctx, volume, v1.VolumeReleased, ""); err != nil {
   733  						// Nothing was saved; we will fall back into the same condition
   734  						// in the next call to this method
   735  						return err
   736  					}
   737  				}
   738  				if err = ctrl.reclaimVolume(ctx, volume); err != nil {
   739  					// Deletion failed, we will fall back into the same condition
   740  					// in the next call to this method
   741  					return err
   742  				}
   743  				return nil
   744  			} else {
   745  				// Volume is bound to a claim, but the claim is bound elsewhere
   746  				// and it's not dynamically provisioned.
   747  				if metav1.HasAnnotation(volume.ObjectMeta, storagehelpers.AnnBoundByController) {
   748  					// This is part of the normal operation of the controller; the
   749  					// controller tried to use this volume for a claim but the claim
   750  					// was fulfilled by another volume. We did this; fix it.
   751  					logger.V(4).Info("Synchronizing PersistentVolume, volume is bound by controller to a claim that is bound to another volume, unbinding", "volumeName", volume.Name)
   752  					if err = ctrl.unbindVolume(ctx, volume); err != nil {
   753  						return err
   754  					}
   755  					return nil
   756  				} else {
   757  					// The PV must have been created with this ptr; leave it alone.
   758  					logger.V(4).Info("Synchronizing PersistentVolume, volume is bound by user to a claim that is bound to another volume, waiting for the claim to get unbound", "volumeName", volume.Name)
   759  					// This just updates the volume phase and clears
   760  					// volume.Spec.ClaimRef.UID. It leaves the volume pre-bound
   761  					// to the claim.
   762  					if err = ctrl.unbindVolume(ctx, volume); err != nil {
   763  						return err
   764  					}
   765  					return nil
   766  				}
   767  			}
   768  		}
   769  	}
   770  }
   771  
   772  // updateClaimStatus saves new claim.Status to API server.
   773  // Parameters:
   774  //
   775  //	claim - claim to update
   776  //	phase - phase to set
   777  //	volume - volume which Capacity is set into claim.Status.Capacity
   778  func (ctrl *PersistentVolumeController) updateClaimStatus(ctx context.Context, claim *v1.PersistentVolumeClaim, phase v1.PersistentVolumeClaimPhase, volume *v1.PersistentVolume) (*v1.PersistentVolumeClaim, error) {
   779  	logger := klog.FromContext(ctx)
   780  	logger.V(4).Info("Updating PersistentVolumeClaim status", "PVC", klog.KObj(claim), "setPhase", phase)
   781  
   782  	dirty := false
   783  
   784  	claimClone := claim.DeepCopy()
   785  	if claim.Status.Phase != phase {
   786  		claimClone.Status.Phase = phase
   787  		dirty = true
   788  	}
   789  
   790  	if volume == nil {
   791  		// Need to reset AccessModes and Capacity
   792  		if claim.Status.AccessModes != nil {
   793  			claimClone.Status.AccessModes = nil
   794  			dirty = true
   795  		}
   796  		if claim.Status.Capacity != nil {
   797  			claimClone.Status.Capacity = nil
   798  			dirty = true
   799  		}
   800  	} else {
   801  		// Need to update AccessModes and Capacity
   802  		if !reflect.DeepEqual(claim.Status.AccessModes, volume.Spec.AccessModes) {
   803  			claimClone.Status.AccessModes = volume.Spec.AccessModes
   804  			dirty = true
   805  		}
   806  
   807  		// Update Capacity if the claim is becoming Bound, not if it was already.
   808  		// A discrepancy can be intentional to mean that the PVC filesystem size
   809  		// doesn't match the PV block device size, so don't clobber it
   810  		if claim.Status.Phase != phase {
   811  			volumeCap, ok := volume.Spec.Capacity[v1.ResourceStorage]
   812  			if !ok {
   813  				return nil, fmt.Errorf("PersistentVolume %q is without a storage capacity", volume.Name)
   814  			}
   815  			claimCap, ok := claim.Status.Capacity[v1.ResourceStorage]
   816  			// If PV has a resize annotation, set the claim's request capacity
   817  			if metav1.HasAnnotation(volume.ObjectMeta, util.AnnPreResizeCapacity) {
   818  				logger.V(2).Info("Volume requires filesystem resize: setting pvc status capacity", "PVC", klog.KObj(claim), "volumeName", volume.Name, "statusCapacity", volume.ObjectMeta.Annotations[util.AnnPreResizeCapacity])
   819  				preQty, err := resource.ParseQuantity(volume.ObjectMeta.Annotations[util.AnnPreResizeCapacity])
   820  				if err != nil {
   821  					logger.Info("Parsing pre-resize-capacity from PV failed", "volumeName", volume.Name, "err", err)
   822  					preQty = volume.Spec.Capacity[v1.ResourceStorage]
   823  				}
   824  				if claimClone.Status.Capacity == nil {
   825  					claimClone.Status.Capacity = make(map[v1.ResourceName]resource.Quantity)
   826  				}
   827  				claimClone.Status.Capacity[v1.ResourceStorage] = preQty
   828  				dirty = true
   829  			} else if !ok || volumeCap.Cmp(claimCap) != 0 {
   830  				claimClone.Status.Capacity = volume.Spec.Capacity
   831  				dirty = true
   832  			}
   833  		}
   834  	}
   835  
   836  	if !dirty {
   837  		// Nothing to do.
   838  		logger.V(4).Info("Updating PersistentVolumeClaim status, phase already set", "PVC", klog.KObj(claim), "phase", phase)
   839  		return claim, nil
   840  	}
   841  
   842  	newClaim, err := ctrl.kubeClient.CoreV1().PersistentVolumeClaims(claimClone.Namespace).UpdateStatus(ctx, claimClone, metav1.UpdateOptions{})
   843  	if err != nil {
   844  		logger.V(4).Info("Updating PersistentVolumeClaim status, set phase failed", "PVC", klog.KObj(claim), "phase", phase, "err", err)
   845  		return newClaim, err
   846  	}
   847  	_, err = ctrl.storeClaimUpdate(logger, newClaim)
   848  	if err != nil {
   849  		logger.V(4).Info("Updating PersistentVolumeClaim status: cannot update internal cache", "PVC", klog.KObj(claim), "err", err)
   850  		return newClaim, err
   851  	}
   852  	logger.V(2).Info("Claim entered phase", "PVC", klog.KObj(claim), "phase", phase)
   853  	return newClaim, nil
   854  }
   855  
   856  // updateClaimStatusWithEvent saves new claim.Status to API server and emits
   857  // given event on the claim. It saves the status and emits the event only when
   858  // the status has actually changed from the version saved in API server.
   859  // Parameters:
   860  //
   861  //	claim - claim to update
   862  //	phase - phase to set
   863  //	volume - volume which Capacity is set into claim.Status.Capacity
   864  //	eventtype, reason, message - event to send, see EventRecorder.Event()
   865  func (ctrl *PersistentVolumeController) updateClaimStatusWithEvent(ctx context.Context, claim *v1.PersistentVolumeClaim, phase v1.PersistentVolumeClaimPhase, volume *v1.PersistentVolume, eventtype, reason, message string) (*v1.PersistentVolumeClaim, error) {
   866  	logger := klog.FromContext(ctx)
   867  	logger.V(4).Info("Updating updateClaimStatusWithEvent", "PVC", klog.KObj(claim), "setPhase", phase)
   868  	if claim.Status.Phase == phase {
   869  		// Nothing to do.
   870  		logger.V(4).Info("Updating updateClaimStatusWithEvent, phase already set", "PVC", klog.KObj(claim), "phase", phase)
   871  		return claim, nil
   872  	}
   873  
   874  	newClaim, err := ctrl.updateClaimStatus(ctx, claim, phase, volume)
   875  	if err != nil {
   876  		return nil, err
   877  	}
   878  
   879  	// Emit the event only when the status change happens, not every time
   880  	// syncClaim is called.
   881  	logger.V(3).Info("Claim changed status", "PVC", klog.KObj(claim), "phase", phase, "message", message)
   882  	ctrl.eventRecorder.Event(newClaim, eventtype, reason, message)
   883  
   884  	return newClaim, nil
   885  }
   886  
   887  // updateVolumePhase saves new volume phase to API server.
   888  func (ctrl *PersistentVolumeController) updateVolumePhase(ctx context.Context, volume *v1.PersistentVolume, phase v1.PersistentVolumePhase, message string) (*v1.PersistentVolume, error) {
   889  	logger := klog.FromContext(ctx)
   890  	logger.V(4).Info("Updating PersistentVolume", "volumeName", volume.Name, "setPhase", phase)
   891  	if volume.Status.Phase == phase {
   892  		// Nothing to do.
   893  		logger.V(4).Info("Updating PersistentVolume: phase already set", "volumeName", volume.Name, "phase", phase)
   894  		return volume, nil
   895  	}
   896  
   897  	volumeClone := volume.DeepCopy()
   898  	volumeClone.Status.Phase = phase
   899  	volumeClone.Status.Message = message
   900  
   901  	newVol, err := ctrl.kubeClient.CoreV1().PersistentVolumes().UpdateStatus(ctx, volumeClone, metav1.UpdateOptions{})
   902  	if err != nil {
   903  		logger.V(4).Info("Updating PersistentVolume: set phase failed", "volumeName", volume.Name, "phase", phase, "err", err)
   904  		return newVol, err
   905  	}
   906  	_, err = ctrl.storeVolumeUpdate(logger, newVol)
   907  	if err != nil {
   908  		logger.V(4).Info("Updating PersistentVolume: cannot update internal cache", "volumeName", volume.Name, "err", err)
   909  		return newVol, err
   910  	}
   911  	logger.V(2).Info("Volume entered phase", "volumeName", volume.Name, "phase", phase)
   912  	return newVol, err
   913  }
   914  
   915  // updateVolumePhaseWithEvent saves new volume phase to API server and emits
   916  // given event on the volume. It saves the phase and emits the event only when
   917  // the phase has actually changed from the version saved in API server.
   918  func (ctrl *PersistentVolumeController) updateVolumePhaseWithEvent(ctx context.Context, volume *v1.PersistentVolume, phase v1.PersistentVolumePhase, eventtype, reason, message string) (*v1.PersistentVolume, error) {
   919  	logger := klog.FromContext(ctx)
   920  	logger.V(4).Info("Updating updateVolumePhaseWithEvent", "volumeName", volume.Name, "setPhase", phase)
   921  	if volume.Status.Phase == phase {
   922  		// Nothing to do.
   923  		logger.V(4).Info("Updating updateVolumePhaseWithEvent: phase already set", "volumeName", volume.Name, "phase", phase)
   924  		return volume, nil
   925  	}
   926  
   927  	newVol, err := ctrl.updateVolumePhase(ctx, volume, phase, message)
   928  	if err != nil {
   929  		return nil, err
   930  	}
   931  
   932  	// Emit the event only when the status change happens, not every time
   933  	// syncClaim is called.
   934  	logger.V(3).Info("Volume changed status", "volumeName", volume.Name, "changedPhase", phase, "message", message)
   935  	ctrl.eventRecorder.Event(newVol, eventtype, reason, message)
   936  
   937  	return newVol, nil
   938  }
   939  
   940  // assignDefaultStorageClass updates the claim storage class if there is any, the claim is updated to the API server.
   941  // Ignores claims that already have a storage class.
   942  // TODO: if resync is ever changed to a larger period, we might need to change how we set the default class on existing unbound claims
   943  func (ctrl *PersistentVolumeController) assignDefaultStorageClass(ctx context.Context, claim *v1.PersistentVolumeClaim) (bool, error) {
   944  	logger := klog.FromContext(ctx)
   945  
   946  	if storagehelpers.PersistentVolumeClaimHasClass(claim) {
   947  		// The user asked for a class.
   948  		return false, nil
   949  	}
   950  
   951  	class, err := util.GetDefaultClass(ctrl.classLister)
   952  	if err != nil {
   953  		return false, err
   954  	} else if class == nil {
   955  		logger.V(4).Info("Can not assign storage class to PersistentVolumeClaim: default storage class not found", "PVC", klog.KObj(claim))
   956  		return false, nil
   957  	}
   958  
   959  	logger.V(4).Info("Assigning StorageClass to PersistentVolumeClaim", "PVC", klog.KObj(claim), "storageClassName", class.Name)
   960  	claim.Spec.StorageClassName = &class.Name
   961  	_, err = ctrl.kubeClient.CoreV1().PersistentVolumeClaims(claim.GetNamespace()).Update(ctx, claim, metav1.UpdateOptions{})
   962  	if err != nil {
   963  		return false, err
   964  	}
   965  
   966  	logger.V(4).Info("Successfully assigned StorageClass to PersistentVolumeClaim", "PVC", klog.KObj(claim), "storageClassName", class.Name)
   967  	return true, nil
   968  }
   969  
   970  // bindVolumeToClaim modifies given volume to be bound to a claim and saves it to
   971  // API server. The claim is not modified in this method!
   972  func (ctrl *PersistentVolumeController) bindVolumeToClaim(ctx context.Context, volume *v1.PersistentVolume, claim *v1.PersistentVolumeClaim) (*v1.PersistentVolume, error) {
   973  	logger := klog.FromContext(ctx)
   974  	logger.V(4).Info("Updating PersistentVolume: binding to claim", "PVC", klog.KObj(claim), "volumeName", volume.Name)
   975  
   976  	volumeClone, dirty, err := storagehelpers.GetBindVolumeToClaim(volume, claim)
   977  	if err != nil {
   978  		return nil, err
   979  	}
   980  
   981  	// Save the volume only if something was changed
   982  	if dirty {
   983  		return ctrl.updateBindVolumeToClaim(ctx, volumeClone, true)
   984  	}
   985  
   986  	logger.V(4).Info("Updating PersistentVolume: already bound to claim", "PVC", klog.KObj(claim), "volumeName", volume.Name)
   987  	return volume, nil
   988  }
   989  
   990  // updateBindVolumeToClaim modifies given volume to be bound to a claim and saves it to
   991  // API server. The claim is not modified in this method!
   992  func (ctrl *PersistentVolumeController) updateBindVolumeToClaim(ctx context.Context, volumeClone *v1.PersistentVolume, updateCache bool) (*v1.PersistentVolume, error) {
   993  	logger := klog.FromContext(ctx)
   994  	logger.V(2).Info("Claim bound to volume", "PVC", klog.KRef(volumeClone.Spec.ClaimRef.Namespace, volumeClone.Spec.ClaimRef.Name), "volumeName", volumeClone.Name)
   995  	newVol, err := ctrl.kubeClient.CoreV1().PersistentVolumes().Update(ctx, volumeClone, metav1.UpdateOptions{})
   996  	if err != nil {
   997  		logger.V(4).Info("Updating PersistentVolume: binding to claim failed", "PVC", klog.KRef(volumeClone.Spec.ClaimRef.Namespace, volumeClone.Spec.ClaimRef.Name), "volumeName", volumeClone.Name, "err", err)
   998  		return newVol, err
   999  	}
  1000  	if updateCache {
  1001  		_, err = ctrl.storeVolumeUpdate(logger, newVol)
  1002  		if err != nil {
  1003  			logger.V(4).Info("Updating PersistentVolume: cannot update internal cache", "volumeName", volumeClone.Name, "err", err)
  1004  			return newVol, err
  1005  		}
  1006  	}
  1007  	logger.V(4).Info("Updating PersistentVolume: bound to claim", "PVC", klog.KRef(volumeClone.Spec.ClaimRef.Namespace, volumeClone.Spec.ClaimRef.Name), "volumeName", newVol.Name)
  1008  	return newVol, nil
  1009  }
  1010  
  1011  // bindClaimToVolume modifies the given claim to be bound to a volume and
  1012  // saves it to API server. The volume is not modified in this method!
  1013  func (ctrl *PersistentVolumeController) bindClaimToVolume(ctx context.Context, claim *v1.PersistentVolumeClaim, volume *v1.PersistentVolume) (*v1.PersistentVolumeClaim, error) {
  1014  	logger := klog.FromContext(ctx)
  1015  	logger.V(4).Info("Updating PersistentVolumeClaim: binding to volume", "PVC", klog.KObj(claim), "volumeName", volume.Name)
  1016  
  1017  	dirty := false
  1018  
  1019  	// Check if the claim was already bound (either by controller or by user)
  1020  	shouldBind := false
  1021  	if volume.Name != claim.Spec.VolumeName {
  1022  		shouldBind = true
  1023  	}
  1024  
  1025  	// The claim from method args can be pointing to watcher cache. We must not
  1026  	// modify these, therefore create a copy.
  1027  	claimClone := claim.DeepCopy()
  1028  
  1029  	if shouldBind {
  1030  		dirty = true
  1031  		// Bind the claim to the volume
  1032  		claimClone.Spec.VolumeName = volume.Name
  1033  
  1034  		// Set AnnBoundByController if it is not set yet
  1035  		if !metav1.HasAnnotation(claimClone.ObjectMeta, storagehelpers.AnnBoundByController) {
  1036  			metav1.SetMetaDataAnnotation(&claimClone.ObjectMeta, storagehelpers.AnnBoundByController, "yes")
  1037  		}
  1038  	}
  1039  
  1040  	// Set AnnBindCompleted if it is not set yet
  1041  	if !metav1.HasAnnotation(claimClone.ObjectMeta, storagehelpers.AnnBindCompleted) {
  1042  		metav1.SetMetaDataAnnotation(&claimClone.ObjectMeta, storagehelpers.AnnBindCompleted, "yes")
  1043  		dirty = true
  1044  	}
  1045  
  1046  	if dirty {
  1047  		logger.V(2).Info("Volume bound to claim", "PVC", klog.KObj(claim), "volumeName", volume.Name)
  1048  		newClaim, err := ctrl.kubeClient.CoreV1().PersistentVolumeClaims(claim.Namespace).Update(ctx, claimClone, metav1.UpdateOptions{})
  1049  		if err != nil {
  1050  			logger.V(4).Info("Updating PersistentVolumeClaim: binding to volume failed", "PVC", klog.KObj(claim), "volumeName", volume.Name, "err", err)
  1051  			return newClaim, err
  1052  		}
  1053  		_, err = ctrl.storeClaimUpdate(logger, newClaim)
  1054  		if err != nil {
  1055  			logger.V(4).Info("Updating PersistentVolumeClaim: cannot update internal cache", "PVC", klog.KObj(claim), "err", err)
  1056  			return newClaim, err
  1057  		}
  1058  		logger.V(4).Info("Updating PersistentVolumeClaim: bound to volume", "PVC", klog.KObj(claim), "volumeName", volume.Name)
  1059  		return newClaim, nil
  1060  	}
  1061  
  1062  	logger.V(4).Info("Updating PersistentVolumeClaim: already bound to volume", "PVC", klog.KObj(claim), "volumeName", volume.Name)
  1063  	return claim, nil
  1064  }
  1065  
  1066  // bind saves binding information both to the volume and the claim and marks
  1067  // both objects as Bound. Volume is saved first.
  1068  // It returns on first error, it's up to the caller to implement some retry
  1069  // mechanism.
  1070  func (ctrl *PersistentVolumeController) bind(ctx context.Context, volume *v1.PersistentVolume, claim *v1.PersistentVolumeClaim) error {
  1071  	var err error
  1072  	// use updateClaim/updatedVolume to keep the original claim/volume for
  1073  	// logging in error cases.
  1074  	var updatedClaim *v1.PersistentVolumeClaim
  1075  	var updatedVolume *v1.PersistentVolume
  1076  
  1077  	logger := klog.FromContext(ctx)
  1078  	logger.V(4).Info("Binding volume to claim", "PVC", klog.KObj(claim), "volumeName", volume.Name)
  1079  
  1080  	if updatedVolume, err = ctrl.bindVolumeToClaim(ctx, volume, claim); err != nil {
  1081  		logger.V(3).Info("Error binding volume to claim: failed saving the volume", "PVC", klog.KObj(claim), "volumeName", volume.Name, "err", err)
  1082  		return err
  1083  	}
  1084  	volume = updatedVolume
  1085  
  1086  	if updatedVolume, err = ctrl.updateVolumePhase(ctx, volume, v1.VolumeBound, ""); err != nil {
  1087  		logger.V(3).Info("Error binding volume to claim: failed saving the volume status", "PVC", klog.KObj(claim), "volumeName", volume.Name, "err", err)
  1088  		return err
  1089  	}
  1090  	volume = updatedVolume
  1091  
  1092  	if updatedClaim, err = ctrl.bindClaimToVolume(ctx, claim, volume); err != nil {
  1093  		logger.V(3).Info("Error binding volume to claim: failed saving the claim", "PVC", klog.KObj(claim), "volumeName", volume.Name, "err", err)
  1094  		return err
  1095  	}
  1096  	claim = updatedClaim
  1097  
  1098  	if updatedClaim, err = ctrl.updateClaimStatus(ctx, claim, v1.ClaimBound, volume); err != nil {
  1099  		logger.V(3).Info("Error binding volume to claim: failed saving the claim status", "PVC", klog.KObj(claim), "volumeName", volume.Name, "err", err)
  1100  		return err
  1101  	}
  1102  	claim = updatedClaim
  1103  
  1104  	logger.V(4).Info("Volume bound to claim", "PVC", klog.KObj(claim), "volumeName", volume.Name)
  1105  	logger.V(4).Info("Volume status after binding", "volumeName", volume.Name, "volumeStatus", getVolumeStatusForLogging(volume))
  1106  	logger.V(4).Info("Claim status after binding", "PVC", klog.KObj(claim), "claimStatus", getClaimStatusForLogging(claim))
  1107  	return nil
  1108  }
  1109  
  1110  // unbindVolume rolls back previous binding of the volume. This may be necessary
  1111  // when two controllers bound two volumes to single claim - when we detect this,
  1112  // only one binding succeeds and the second one must be rolled back.
  1113  // This method updates both Spec and Status.
  1114  // It returns on first error, it's up to the caller to implement some retry
  1115  // mechanism.
  1116  func (ctrl *PersistentVolumeController) unbindVolume(ctx context.Context, volume *v1.PersistentVolume) error {
  1117  	logger := klog.FromContext(ctx)
  1118  	logger.V(4).Info("Updating PersistentVolume: rolling back binding from claim", "PVC", klog.KRef(volume.Spec.ClaimRef.Namespace, volume.Spec.ClaimRef.Name), "volumeName", volume.Name)
  1119  
  1120  	// Save the PV only when any modification is necessary.
  1121  	volumeClone := volume.DeepCopy()
  1122  
  1123  	if metav1.HasAnnotation(volume.ObjectMeta, storagehelpers.AnnBoundByController) {
  1124  		// The volume was bound by the controller.
  1125  		volumeClone.Spec.ClaimRef = nil
  1126  		delete(volumeClone.Annotations, storagehelpers.AnnBoundByController)
  1127  		if len(volumeClone.Annotations) == 0 {
  1128  			// No annotations look better than empty annotation map (and it's easier
  1129  			// to test).
  1130  			volumeClone.Annotations = nil
  1131  		}
  1132  	} else {
  1133  		// The volume was pre-bound by user. Clear only the binding UID.
  1134  		volumeClone.Spec.ClaimRef.UID = ""
  1135  	}
  1136  
  1137  	newVol, err := ctrl.kubeClient.CoreV1().PersistentVolumes().Update(ctx, volumeClone, metav1.UpdateOptions{})
  1138  	if err != nil {
  1139  		logger.V(4).Info("Updating PersistentVolume: rollback failed", "volumeName", volume.Name, "err", err)
  1140  		return err
  1141  	}
  1142  	_, err = ctrl.storeVolumeUpdate(logger, newVol)
  1143  	if err != nil {
  1144  		logger.V(4).Info("Updating PersistentVolume: cannot update internal cache", "volumeName", volume.Name, "err", err)
  1145  		return err
  1146  	}
  1147  	logger.V(4).Info("Updating PersistentVolume: rolled back", "volumeName", newVol.Name)
  1148  
  1149  	// Update the status
  1150  	_, err = ctrl.updateVolumePhase(ctx, newVol, v1.VolumeAvailable, "")
  1151  	return err
  1152  }
  1153  
  1154  // reclaimVolume implements volume.Spec.PersistentVolumeReclaimPolicy and
  1155  // starts appropriate reclaim action.
  1156  func (ctrl *PersistentVolumeController) reclaimVolume(ctx context.Context, volume *v1.PersistentVolume) error {
  1157  	logger := klog.FromContext(ctx)
  1158  	if migrated := volume.Annotations[storagehelpers.AnnMigratedTo]; len(migrated) > 0 {
  1159  		// PV is Migrated. The PV controller should stand down and the external
  1160  		// provisioner will handle this PV
  1161  		return nil
  1162  	}
  1163  	switch volume.Spec.PersistentVolumeReclaimPolicy {
  1164  	case v1.PersistentVolumeReclaimRetain:
  1165  		logger.V(4).Info("ReclaimVolume: policy is Retain, nothing to do", "volumeName", volume.Name)
  1166  
  1167  	case v1.PersistentVolumeReclaimRecycle:
  1168  		logger.V(4).Info("ReclaimVolume: policy is Recycle", "volumeName", volume.Name)
  1169  		opName := fmt.Sprintf("recycle-%s[%s]", volume.Name, string(volume.UID))
  1170  		ctrl.scheduleOperation(logger, opName, func() error {
  1171  			ctrl.recycleVolumeOperation(ctx, volume)
  1172  			return nil
  1173  		})
  1174  
  1175  	case v1.PersistentVolumeReclaimDelete:
  1176  		logger.V(4).Info("ReclaimVolume: policy is Delete", "volumeName", volume.Name)
  1177  		opName := fmt.Sprintf("delete-%s[%s]", volume.Name, string(volume.UID))
  1178  		// create a start timestamp entry in cache for deletion operation if no one exists with
  1179  		// key = volume.Name, pluginName = provisionerName, operation = "delete"
  1180  		ctrl.operationTimestamps.AddIfNotExist(volume.Name, ctrl.getProvisionerNameFromVolume(volume), "delete")
  1181  		ctrl.scheduleOperation(logger, opName, func() error {
  1182  			_, err := ctrl.deleteVolumeOperation(ctx, volume)
  1183  			if err != nil {
  1184  				// only report error count to "volume_operation_total_errors"
  1185  				// latency reporting will happen when the volume get finally
  1186  				// deleted and a volume deleted event is captured
  1187  				metrics.RecordMetric(volume.Name, &ctrl.operationTimestamps, err)
  1188  			}
  1189  			return err
  1190  		})
  1191  
  1192  	default:
  1193  		// Unknown PersistentVolumeReclaimPolicy
  1194  		if _, err := ctrl.updateVolumePhaseWithEvent(ctx, volume, v1.VolumeFailed, v1.EventTypeWarning, "VolumeUnknownReclaimPolicy", "Volume has unrecognized PersistentVolumeReclaimPolicy"); err != nil {
  1195  			return err
  1196  		}
  1197  	}
  1198  	return nil
  1199  }
  1200  
  1201  // recycleVolumeOperation recycles a volume. This method is running in
  1202  // standalone goroutine and already has all necessary locks.
  1203  func (ctrl *PersistentVolumeController) recycleVolumeOperation(ctx context.Context, volume *v1.PersistentVolume) {
  1204  	logger := klog.FromContext(ctx)
  1205  	logger.V(4).Info("RecycleVolumeOperation started", "volumeName", volume.Name)
  1206  
  1207  	// This method may have been waiting for a volume lock for some time.
  1208  	// Previous recycleVolumeOperation might just have saved an updated version,
  1209  	// so read current volume state now.
  1210  	newVolume, err := ctrl.kubeClient.CoreV1().PersistentVolumes().Get(ctx, volume.Name, metav1.GetOptions{})
  1211  	if err != nil {
  1212  		logger.V(3).Info("Error reading persistent volume", "volumeName", volume.Name, "err", err)
  1213  		return
  1214  	}
  1215  	needsReclaim, err := ctrl.isVolumeReleased(logger, newVolume)
  1216  	if err != nil {
  1217  		logger.V(3).Info("Error reading claim for volume", "volumeName", volume.Name, "err", err)
  1218  		return
  1219  	}
  1220  	if !needsReclaim {
  1221  		logger.V(3).Info("Volume no longer needs recycling, skipping", "volumeName", volume.Name)
  1222  		return
  1223  	}
  1224  	pods, used, err := ctrl.isVolumeUsed(newVolume)
  1225  	if err != nil {
  1226  		logger.V(3).Info("Can't recycle volume", "volumeName", volume.Name, "err", err)
  1227  		return
  1228  	}
  1229  
  1230  	// Verify the claim is in cache: if so, then it is a different PVC with the same name
  1231  	// since the volume is known to be released at this moment. The new (cached) PVC must use
  1232  	// a different PV -- we checked that the PV is unused in isVolumeReleased.
  1233  	// So the old PV is safe to be recycled.
  1234  	claimName := claimrefToClaimKey(volume.Spec.ClaimRef)
  1235  	_, claimCached, err := ctrl.claims.GetByKey(claimName)
  1236  	if err != nil {
  1237  		logger.V(3).Info("Error getting the claim from cache", "PVC", klog.KRef(volume.Spec.ClaimRef.Namespace, volume.Spec.ClaimRef.Name))
  1238  		return
  1239  	}
  1240  
  1241  	if used && !claimCached {
  1242  		msg := fmt.Sprintf("Volume is used by pods: %s", strings.Join(pods, ","))
  1243  		logger.V(3).Info("Can't recycle volume", "volumeName", volume.Name, "msg", msg)
  1244  		ctrl.eventRecorder.Event(volume, v1.EventTypeNormal, events.VolumeFailedRecycle, msg)
  1245  		return
  1246  	}
  1247  
  1248  	// Use the newest volume copy, this will save us from version conflicts on
  1249  	// saving.
  1250  	volume = newVolume
  1251  
  1252  	// Find a plugin.
  1253  	spec := vol.NewSpecFromPersistentVolume(volume, false)
  1254  	plugin, err := ctrl.volumePluginMgr.FindRecyclablePluginBySpec(spec)
  1255  	if err != nil {
  1256  		// No recycler found. Emit an event and mark the volume Failed.
  1257  		if _, err = ctrl.updateVolumePhaseWithEvent(ctx, volume, v1.VolumeFailed, v1.EventTypeWarning, events.VolumeFailedRecycle, "No recycler plugin found for the volume!"); err != nil {
  1258  			logger.V(4).Info("RecycleVolumeOperation: failed to mark volume as failed", "volumeName", volume.Name, "err", err)
  1259  			// Save failed, retry on the next deletion attempt
  1260  			return
  1261  		}
  1262  		// Despite the volume being Failed, the controller will retry recycling
  1263  		// the volume in every syncVolume() call.
  1264  		return
  1265  	}
  1266  
  1267  	// Plugin found
  1268  	recorder := ctrl.newRecyclerEventRecorder(volume)
  1269  
  1270  	if err = plugin.Recycle(volume.Name, spec, recorder); err != nil {
  1271  		// Recycler failed
  1272  		strerr := fmt.Sprintf("Recycle failed: %s", err)
  1273  		if _, err = ctrl.updateVolumePhaseWithEvent(ctx, volume, v1.VolumeFailed, v1.EventTypeWarning, events.VolumeFailedRecycle, strerr); err != nil {
  1274  			logger.V(4).Info("RecycleVolumeOperation: failed to mark volume as failed", "volumeName", volume.Name, "err", err)
  1275  			// Save failed, retry on the next deletion attempt
  1276  			return
  1277  		}
  1278  		// Despite the volume being Failed, the controller will retry recycling
  1279  		// the volume in every syncVolume() call.
  1280  		return
  1281  	}
  1282  
  1283  	logger.V(2).Info("Volume recycled", "volumeName", volume.Name)
  1284  	// Send an event
  1285  	ctrl.eventRecorder.Event(volume, v1.EventTypeNormal, events.VolumeRecycled, "Volume recycled")
  1286  	// Make the volume available again
  1287  	if err = ctrl.unbindVolume(ctx, volume); err != nil {
  1288  		// Oops, could not save the volume and therefore the controller will
  1289  		// recycle the volume again on next update. We _could_ maintain a cache
  1290  		// of "recently recycled volumes" and avoid unnecessary recycling, this
  1291  		// is left out as future optimization.
  1292  		logger.V(3).Info("RecycleVolumeOperation: failed to make recycled volume 'Available', we will recycle the volume again", "volumeName", volume.Name, "err", err)
  1293  		return
  1294  	}
  1295  }
  1296  
  1297  // deleteVolumeOperation deletes a volume. This method is running in standalone
  1298  // goroutine and already has all necessary locks.
  1299  func (ctrl *PersistentVolumeController) deleteVolumeOperation(ctx context.Context, volume *v1.PersistentVolume) (string, error) {
  1300  	logger := klog.FromContext(ctx)
  1301  	logger.V(4).Info("DeleteVolumeOperation started", "volumeName", volume.Name)
  1302  
  1303  	// This method may have been waiting for a volume lock for some time.
  1304  	// Previous deleteVolumeOperation might just have saved an updated version, so
  1305  	// read current volume state now.
  1306  	newVolume, err := ctrl.kubeClient.CoreV1().PersistentVolumes().Get(ctx, volume.Name, metav1.GetOptions{})
  1307  	if err != nil {
  1308  		logger.V(3).Info("Error reading persistent volume", "volumeName", volume.Name, "err", err)
  1309  		return "", nil
  1310  	}
  1311  
  1312  	if !utilfeature.DefaultFeatureGate.Enabled(features.HonorPVReclaimPolicy) {
  1313  		if newVolume.GetDeletionTimestamp() != nil {
  1314  			logger.V(3).Info("Volume is already being deleted", "volumeName", volume.Name)
  1315  			return "", nil
  1316  		}
  1317  	}
  1318  	needsReclaim, err := ctrl.isVolumeReleased(logger, newVolume)
  1319  	if err != nil {
  1320  		logger.V(3).Info("Error reading claim for volume", "volumeName", volume.Name, "err", err)
  1321  		return "", nil
  1322  	}
  1323  	if !needsReclaim {
  1324  		logger.V(3).Info("Volume no longer needs deletion, skipping", "volumeName", volume.Name)
  1325  		return "", nil
  1326  	}
  1327  
  1328  	pluginName, deleted, err := ctrl.doDeleteVolume(ctx, volume)
  1329  	if err != nil {
  1330  		// Delete failed, update the volume and emit an event.
  1331  		logger.V(3).Info("Deletion of volume failed", "volumeName", volume.Name, "err", err)
  1332  		if volerr.IsDeletedVolumeInUse(err) {
  1333  			// The plugin needs more time, don't mark the volume as Failed
  1334  			// and send Normal event only
  1335  			ctrl.eventRecorder.Event(volume, v1.EventTypeNormal, events.VolumeDelete, err.Error())
  1336  		} else {
  1337  			// The plugin failed, mark the volume as Failed and send Warning
  1338  			// event
  1339  			if _, err := ctrl.updateVolumePhaseWithEvent(ctx, volume, v1.VolumeFailed, v1.EventTypeWarning, events.VolumeFailedDelete, err.Error()); err != nil {
  1340  				logger.V(4).Info("DeleteVolumeOperation: failed to mark volume as failed", "volumeName", volume.Name, "err", err)
  1341  				// Save failed, retry on the next deletion attempt
  1342  				return pluginName, err
  1343  			}
  1344  		}
  1345  
  1346  		// Despite the volume being Failed, the controller will retry deleting
  1347  		// the volume in every syncVolume() call.
  1348  		return pluginName, err
  1349  	}
  1350  	if !deleted {
  1351  		// The volume waits for deletion by an external plugin. Do nothing.
  1352  		return pluginName, nil
  1353  	}
  1354  
  1355  	logger.V(4).Info("DeleteVolumeOperation: success", "volumeName", volume.Name)
  1356  	// Delete the volume
  1357  	if err = ctrl.kubeClient.CoreV1().PersistentVolumes().Delete(ctx, volume.Name, metav1.DeleteOptions{}); err != nil {
  1358  		// Oops, could not delete the volume and therefore the controller will
  1359  		// try to delete the volume again on next update. We _could_ maintain a
  1360  		// cache of "recently deleted volumes" and avoid unnecessary deletion,
  1361  		// this is left out as future optimization.
  1362  		logger.V(3).Info("Failed to delete volume from database", "volumeName", volume.Name, "err", err)
  1363  		return pluginName, nil
  1364  	}
  1365  	return pluginName, nil
  1366  }
  1367  
  1368  // isVolumeReleased returns true if given volume is released and can be recycled
  1369  // or deleted, based on its retain policy. I.e. the volume is bound to a claim
  1370  // and the claim does not exist or exists and is bound to different volume.
  1371  func (ctrl *PersistentVolumeController) isVolumeReleased(logger klog.Logger, volume *v1.PersistentVolume) (bool, error) {
  1372  	// A volume needs reclaim if it has ClaimRef and appropriate claim does not
  1373  	// exist.
  1374  	if volume.Spec.ClaimRef == nil {
  1375  		logger.V(4).Info("isVolumeReleased: ClaimRef is nil", "volumeName", volume.Name)
  1376  		return false, nil
  1377  	}
  1378  	if volume.Spec.ClaimRef.UID == "" {
  1379  		// This is a volume bound by user and the controller has not finished
  1380  		// binding to the real claim yet.
  1381  		logger.V(4).Info("isVolumeReleased: ClaimRef is not bound", "volumeName", volume.Name)
  1382  		return false, nil
  1383  	}
  1384  
  1385  	var claim *v1.PersistentVolumeClaim
  1386  	claimName := claimrefToClaimKey(volume.Spec.ClaimRef)
  1387  	obj, found, err := ctrl.claims.GetByKey(claimName)
  1388  	if err != nil {
  1389  		return false, err
  1390  	}
  1391  	if !found {
  1392  		// Fall through with claim = nil
  1393  	} else {
  1394  		var ok bool
  1395  		claim, ok = obj.(*v1.PersistentVolumeClaim)
  1396  		if !ok {
  1397  			return false, fmt.Errorf("cannot convert object from claim cache to claim!?: %#v", obj)
  1398  		}
  1399  	}
  1400  	if claim != nil && claim.UID == volume.Spec.ClaimRef.UID {
  1401  		// the claim still exists and has the right UID
  1402  
  1403  		if len(claim.Spec.VolumeName) > 0 && claim.Spec.VolumeName != volume.Name {
  1404  			// the claim is bound to another PV, this PV *is* released
  1405  			return true, nil
  1406  		}
  1407  
  1408  		logger.V(4).Info("isVolumeReleased: ClaimRef is still valid, volume is not released", "volumeName", volume.Name)
  1409  		return false, nil
  1410  	}
  1411  
  1412  	logger.V(2).Info("isVolumeReleased: volume is released", "volumeName", volume.Name)
  1413  	return true, nil
  1414  }
  1415  
  1416  func (ctrl *PersistentVolumeController) findPodsByPVCKey(key string) ([]*v1.Pod, error) {
  1417  	pods := []*v1.Pod{}
  1418  	objs, err := ctrl.podIndexer.ByIndex(common.PodPVCIndex, key)
  1419  	if err != nil {
  1420  		return pods, err
  1421  	}
  1422  	for _, obj := range objs {
  1423  		pod, ok := obj.(*v1.Pod)
  1424  		if !ok {
  1425  			continue
  1426  		}
  1427  		pods = append(pods, pod)
  1428  	}
  1429  	return pods, err
  1430  }
  1431  
  1432  // isVolumeUsed returns list of active pods that use given PV.
  1433  func (ctrl *PersistentVolumeController) isVolumeUsed(pv *v1.PersistentVolume) ([]string, bool, error) {
  1434  	if pv.Spec.ClaimRef == nil {
  1435  		return nil, false, nil
  1436  	}
  1437  	podNames := sets.NewString()
  1438  	pvcKey := fmt.Sprintf("%s/%s", pv.Spec.ClaimRef.Namespace, pv.Spec.ClaimRef.Name)
  1439  	pods, err := ctrl.findPodsByPVCKey(pvcKey)
  1440  	if err != nil {
  1441  		return nil, false, fmt.Errorf("error finding pods by pvc %q: %s", pvcKey, err)
  1442  	}
  1443  	for _, pod := range pods {
  1444  		if util.IsPodTerminated(pod, pod.Status) {
  1445  			continue
  1446  		}
  1447  		podNames.Insert(pod.Namespace + "/" + pod.Name)
  1448  	}
  1449  	return podNames.List(), podNames.Len() != 0, nil
  1450  }
  1451  
  1452  // findNonScheduledPodsByPVC returns list of non-scheduled active pods that reference given PVC.
  1453  func (ctrl *PersistentVolumeController) findNonScheduledPodsByPVC(pvc *v1.PersistentVolumeClaim) ([]string, error) {
  1454  	pvcKey := fmt.Sprintf("%s/%s", pvc.Namespace, pvc.Name)
  1455  	pods, err := ctrl.findPodsByPVCKey(pvcKey)
  1456  	if err != nil {
  1457  		return nil, err
  1458  	}
  1459  	podNames := []string{}
  1460  	for _, pod := range pods {
  1461  		if util.IsPodTerminated(pod, pod.Status) {
  1462  			continue
  1463  		}
  1464  		if len(pod.Spec.NodeName) == 0 {
  1465  			podNames = append(podNames, pod.Name)
  1466  		}
  1467  	}
  1468  	return podNames, nil
  1469  }
  1470  
  1471  // doDeleteVolume finds appropriate delete plugin and deletes given volume, returning
  1472  // the volume plugin name. Also, it returns 'true', when the volume was deleted and
  1473  // 'false' when the volume cannot be deleted because the deleter is external. No
  1474  // error should be reported in this case.
  1475  func (ctrl *PersistentVolumeController) doDeleteVolume(ctx context.Context, volume *v1.PersistentVolume) (string, bool, error) {
  1476  	logger := klog.FromContext(ctx)
  1477  	logger.V(4).Info("doDeleteVolume", "volumeName", volume.Name)
  1478  	var err error
  1479  
  1480  	plugin, err := ctrl.findDeletablePlugin(volume)
  1481  	if err != nil {
  1482  		return "", false, err
  1483  	}
  1484  	if plugin == nil {
  1485  		// External deleter is requested, do nothing
  1486  		logger.V(3).Info("External deleter for volume requested, ignoring", "volumeName", volume.Name)
  1487  		return "", false, nil
  1488  	}
  1489  
  1490  	// Plugin found
  1491  	pluginName := plugin.GetPluginName()
  1492  	logger.V(5).Info("Found a deleter plugin for volume", "pluginName", pluginName, "volumeName", volume.Name)
  1493  	spec := vol.NewSpecFromPersistentVolume(volume, false)
  1494  	deleter, err := plugin.NewDeleter(logger, spec)
  1495  	if err != nil {
  1496  		// Cannot create deleter
  1497  		return pluginName, false, fmt.Errorf("failed to create deleter for volume %q: %w", volume.Name, err)
  1498  	}
  1499  
  1500  	opComplete := util.OperationCompleteHook(pluginName, "volume_delete")
  1501  	err = deleter.Delete()
  1502  	opComplete(volumetypes.CompleteFuncParam{Err: &err})
  1503  	if err != nil {
  1504  		// Deleter failed
  1505  		return pluginName, false, err
  1506  	}
  1507  	logger.V(2).Info("Volume deleted", "volumeName", volume.Name)
  1508  	// Remove in-tree delete finalizer on the PV as the volume has been deleted from the underlying storage
  1509  	if utilfeature.DefaultFeatureGate.Enabled(features.HonorPVReclaimPolicy) {
  1510  		err = ctrl.removeDeletionProtectionFinalizer(ctx, volume)
  1511  		if err != nil {
  1512  			return pluginName, true, err
  1513  		}
  1514  	}
  1515  	return pluginName, true, nil
  1516  }
  1517  
  1518  func (ctrl *PersistentVolumeController) removeDeletionProtectionFinalizer(ctx context.Context, volume *v1.PersistentVolume) error {
  1519  	var err error
  1520  	pvUpdateNeeded := false
  1521  	// Retrieve latest version
  1522  	logger := klog.FromContext(ctx)
  1523  	newVolume, err := ctrl.kubeClient.CoreV1().PersistentVolumes().Get(ctx, volume.Name, metav1.GetOptions{})
  1524  	if err != nil {
  1525  		logger.Error(err, "Error reading persistent volume", "volumeName", volume.Name)
  1526  		return err
  1527  	}
  1528  	volume = newVolume
  1529  	volumeClone := volume.DeepCopy()
  1530  	pvFinalizers := volumeClone.Finalizers
  1531  	if pvFinalizers != nil && slice.ContainsString(pvFinalizers, storagehelpers.PVDeletionInTreeProtectionFinalizer, nil) {
  1532  		pvUpdateNeeded = true
  1533  		pvFinalizers = slice.RemoveString(pvFinalizers, storagehelpers.PVDeletionInTreeProtectionFinalizer, nil)
  1534  	}
  1535  	if pvUpdateNeeded {
  1536  		volumeClone.SetFinalizers(pvFinalizers)
  1537  		_, err = ctrl.kubeClient.CoreV1().PersistentVolumes().Update(ctx, volumeClone, metav1.UpdateOptions{})
  1538  		if err != nil {
  1539  			return fmt.Errorf("persistent volume controller can't update finalizer: %v", err)
  1540  		}
  1541  		_, err = ctrl.storeVolumeUpdate(logger, volumeClone)
  1542  		if err != nil {
  1543  			return fmt.Errorf("persistent Volume Controller can't anneal migration finalizer: %v", err)
  1544  		}
  1545  		logger.V(2).Info("PV in-tree protection finalizer removed from volume", "volumeName", volume.Name)
  1546  	}
  1547  	return nil
  1548  }
  1549  
  1550  // provisionClaim starts new asynchronous operation to provision a claim if
  1551  // provisioning is enabled.
  1552  func (ctrl *PersistentVolumeController) provisionClaim(ctx context.Context, claim *v1.PersistentVolumeClaim) error {
  1553  	if !ctrl.enableDynamicProvisioning {
  1554  		return nil
  1555  	}
  1556  	logger := klog.FromContext(ctx)
  1557  	logger.V(4).Info("provisionClaim: started", "PVC", klog.KObj(claim))
  1558  	opName := fmt.Sprintf("provision-%s[%s]", claimToClaimKey(claim), string(claim.UID))
  1559  	plugin, storageClass, err := ctrl.findProvisionablePlugin(claim)
  1560  	// findProvisionablePlugin does not return err for external provisioners
  1561  	if err != nil {
  1562  		ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.ProvisioningFailed, err.Error())
  1563  		logger.Error(err, "Error finding provisioning plugin for claim", "PVC", klog.KObj(claim))
  1564  		// failed to find the requested provisioning plugin, directly return err for now.
  1565  		// controller will retry the provisioning in every syncUnboundClaim() call
  1566  		// retain the original behavior of returning nil from provisionClaim call
  1567  		return nil
  1568  	}
  1569  	ctrl.scheduleOperation(logger, opName, func() error {
  1570  		// create a start timestamp entry in cache for provision operation if no one exists with
  1571  		// key = claimKey, pluginName = provisionerName, operation = "provision"
  1572  		claimKey := claimToClaimKey(claim)
  1573  		ctrl.operationTimestamps.AddIfNotExist(claimKey, ctrl.getProvisionerName(plugin, storageClass), "provision")
  1574  		var err error
  1575  		if plugin == nil {
  1576  			_, err = ctrl.provisionClaimOperationExternal(ctx, claim, storageClass)
  1577  		} else {
  1578  			_, err = ctrl.provisionClaimOperation(ctx, claim, plugin, storageClass)
  1579  		}
  1580  		// if error happened, record an error count metric
  1581  		// timestamp entry will remain in cache until a success binding has happened
  1582  		if err != nil {
  1583  			metrics.RecordMetric(claimKey, &ctrl.operationTimestamps, err)
  1584  		}
  1585  		return err
  1586  	})
  1587  	return nil
  1588  }
  1589  
  1590  // provisionClaimOperation provisions a volume. This method is running in
  1591  // standalone goroutine and already has all necessary locks.
  1592  func (ctrl *PersistentVolumeController) provisionClaimOperation(
  1593  	ctx context.Context,
  1594  	claim *v1.PersistentVolumeClaim,
  1595  	plugin vol.ProvisionableVolumePlugin,
  1596  	storageClass *storage.StorageClass) (string, error) {
  1597  	claimClass := storagehelpers.GetPersistentVolumeClaimClass(claim)
  1598  	logger := klog.FromContext(ctx)
  1599  	logger.V(4).Info("provisionClaimOperation started", "PVC", klog.KObj(claim), "storageClassName", claimClass)
  1600  
  1601  	// called from provisionClaim(), in this case, plugin MUST NOT be nil
  1602  	// NOTE: checks on plugin/storageClass has been saved
  1603  	pluginName := plugin.GetPluginName()
  1604  	if pluginName != "kubernetes.io/csi" && claim.Spec.DataSource != nil {
  1605  		// Only CSI plugin can have a DataSource. Fail the operation
  1606  		// if Datasource in Claim is not nil and it is not a CSI plugin,
  1607  		strerr := fmt.Sprintf("plugin %q is not a CSI plugin. Only CSI plugin can provision a claim with a datasource", pluginName)
  1608  		logger.V(2).Info(strerr)
  1609  		ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.ProvisioningFailed, strerr)
  1610  		return pluginName, fmt.Errorf(strerr)
  1611  
  1612  	}
  1613  	provisionerName := storageClass.Provisioner
  1614  	logger.V(4).Info("provisionClaimOperation", "PVC", klog.KObj(claim), "pluginName", pluginName, "provisionerName", provisionerName)
  1615  
  1616  	// Add provisioner annotation to be consistent with external provisioner workflow
  1617  	newClaim, err := ctrl.setClaimProvisioner(ctx, claim, provisionerName)
  1618  	if err != nil {
  1619  		// Save failed, the controller will retry in the next sync
  1620  		logger.V(2).Info("Error saving claim", "PVC", klog.KObj(claim), "err", err)
  1621  		return pluginName, err
  1622  	}
  1623  	claim = newClaim
  1624  
  1625  	// internal provisioning
  1626  
  1627  	//  A previous provisionClaimOperation may just have finished while we were waiting for
  1628  	//  the locks. Check that PV (with deterministic name) hasn't been provisioned
  1629  	//  yet.
  1630  
  1631  	pvName := ctrl.getProvisionedVolumeNameForClaim(claim)
  1632  	volume, err := ctrl.kubeClient.CoreV1().PersistentVolumes().Get(ctx, pvName, metav1.GetOptions{})
  1633  	if err != nil && !apierrors.IsNotFound(err) {
  1634  		logger.V(3).Info("Error reading persistent volume", "PV", klog.KRef("", pvName), "err", err)
  1635  		return pluginName, err
  1636  	}
  1637  	if err == nil && volume != nil {
  1638  		// Volume has been already provisioned, nothing to do.
  1639  		logger.V(4).Info("provisionClaimOperation: volume already exists, skipping", "PVC", klog.KObj(claim))
  1640  		return pluginName, err
  1641  	}
  1642  
  1643  	// Prepare a claimRef to the claim early (to fail before a volume is
  1644  	// provisioned)
  1645  	claimRef, err := ref.GetReference(scheme.Scheme, claim)
  1646  	if err != nil {
  1647  		logger.V(3).Info("Unexpected error getting claim reference", "err", err)
  1648  		return pluginName, err
  1649  	}
  1650  
  1651  	// Gather provisioning options
  1652  	tags := make(map[string]string)
  1653  	tags[CloudVolumeCreatedForClaimNamespaceTag] = claim.Namespace
  1654  	tags[CloudVolumeCreatedForClaimNameTag] = claim.Name
  1655  	tags[CloudVolumeCreatedForVolumeNameTag] = pvName
  1656  
  1657  	options := vol.VolumeOptions{
  1658  		PersistentVolumeReclaimPolicy: *storageClass.ReclaimPolicy,
  1659  		MountOptions:                  storageClass.MountOptions,
  1660  		CloudTags:                     &tags,
  1661  		ClusterName:                   ctrl.clusterName,
  1662  		PVName:                        pvName,
  1663  		PVC:                           claim,
  1664  		Parameters:                    storageClass.Parameters,
  1665  	}
  1666  
  1667  	// Refuse to provision if the plugin doesn't support mount options, creation
  1668  	// of PV would be rejected by validation anyway
  1669  	if !plugin.SupportsMountOption() && len(options.MountOptions) > 0 {
  1670  		strerr := fmt.Sprintf("Mount options are not supported by the provisioner but StorageClass %q has mount options %v", storageClass.Name, options.MountOptions)
  1671  		logger.V(2).Info("Mount options are not supported by the provisioner but claim's StorageClass has mount options", "PVC", klog.KObj(claim), "storageClassName", storageClass.Name, "options", options.MountOptions)
  1672  		ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.ProvisioningFailed, strerr)
  1673  		return pluginName, fmt.Errorf("provisioner %q doesn't support mount options", plugin.GetPluginName())
  1674  	}
  1675  
  1676  	// Provision the volume
  1677  	provisioner, err := plugin.NewProvisioner(logger, options)
  1678  	if err != nil {
  1679  		strerr := fmt.Sprintf("Failed to create provisioner: %v", err)
  1680  		logger.V(2).Info("Failed to create provisioner for claim with StorageClass", "PVC", klog.KObj(claim), "storageClassName", storageClass.Name, "err", err)
  1681  		ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.ProvisioningFailed, strerr)
  1682  		return pluginName, err
  1683  	}
  1684  
  1685  	var selectedNode *v1.Node = nil
  1686  	if nodeName, ok := claim.Annotations[storagehelpers.AnnSelectedNode]; ok {
  1687  		selectedNode, err = ctrl.NodeLister.Get(nodeName)
  1688  		if err != nil {
  1689  			strerr := fmt.Sprintf("Failed to get target node: %v", err)
  1690  			logger.V(3).Info("Unexpected error getting target node for claim", "node", klog.KRef("", nodeName), "PVC", klog.KObj(claim), "err", err)
  1691  			ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.ProvisioningFailed, strerr)
  1692  			return pluginName, err
  1693  		}
  1694  	}
  1695  	allowedTopologies := storageClass.AllowedTopologies
  1696  
  1697  	opComplete := util.OperationCompleteHook(plugin.GetPluginName(), "volume_provision")
  1698  	volume, err = provisioner.Provision(selectedNode, allowedTopologies)
  1699  	opComplete(volumetypes.CompleteFuncParam{Err: &err})
  1700  	if err != nil {
  1701  		// Other places of failure have nothing to do with VolumeScheduling,
  1702  		// so just let controller retry in the next sync. We'll only call func
  1703  		// rescheduleProvisioning here when the underlying provisioning actually failed.
  1704  		ctrl.rescheduleProvisioning(ctx, claim)
  1705  
  1706  		strerr := fmt.Sprintf("Failed to provision volume with StorageClass %q: %v", storageClass.Name, err)
  1707  		logger.V(2).Info("Failed to provision volume for claim with StorageClass", "PVC", klog.KObj(claim), "storageClassName", storageClass.Name, "err", err)
  1708  		ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.ProvisioningFailed, strerr)
  1709  		return pluginName, err
  1710  	}
  1711  
  1712  	logger.V(3).Info("Volume for claim created", "PVC", klog.KObj(claim), "volumeName", volume.Name)
  1713  
  1714  	// Create Kubernetes PV object for the volume.
  1715  	if volume.Name == "" {
  1716  		volume.Name = pvName
  1717  	}
  1718  	// Bind it to the claim
  1719  	volume.Spec.ClaimRef = claimRef
  1720  	volume.Status.Phase = v1.VolumeBound
  1721  	volume.Spec.StorageClassName = claimClass
  1722  
  1723  	// Add AnnBoundByController (used in deleting the volume)
  1724  	metav1.SetMetaDataAnnotation(&volume.ObjectMeta, storagehelpers.AnnBoundByController, "yes")
  1725  	metav1.SetMetaDataAnnotation(&volume.ObjectMeta, storagehelpers.AnnDynamicallyProvisioned, plugin.GetPluginName())
  1726  
  1727  	if utilfeature.DefaultFeatureGate.Enabled(features.HonorPVReclaimPolicy) {
  1728  		if volume.Spec.PersistentVolumeReclaimPolicy == v1.PersistentVolumeReclaimDelete {
  1729  			// Add In-Tree protection finalizer here only when the reclaim policy is `Delete`
  1730  			volume.SetFinalizers([]string{storagehelpers.PVDeletionInTreeProtectionFinalizer})
  1731  		}
  1732  	}
  1733  
  1734  	// Try to create the PV object several times
  1735  	for i := 0; i < ctrl.createProvisionedPVRetryCount; i++ {
  1736  		logger.V(4).Info("provisionClaimOperation: trying to save volume", "PVC", klog.KObj(claim), "volumeName", volume.Name)
  1737  		var newVol *v1.PersistentVolume
  1738  		if newVol, err = ctrl.kubeClient.CoreV1().PersistentVolumes().Create(ctx, volume, metav1.CreateOptions{}); err == nil || apierrors.IsAlreadyExists(err) {
  1739  			// Save succeeded.
  1740  			if err != nil {
  1741  				logger.V(3).Info("Volume for claim already exists, reusing", "PVC", klog.KObj(claim), "volumeName", volume.Name)
  1742  				err = nil
  1743  			} else {
  1744  				logger.V(3).Info("Volume for claim saved", "PVC", klog.KObj(claim), "volumeName", volume.Name)
  1745  
  1746  				_, updateErr := ctrl.storeVolumeUpdate(logger, newVol)
  1747  				if updateErr != nil {
  1748  					// We will get an "volume added" event soon, this is not a big error
  1749  					logger.V(4).Info("provisionClaimOperation: cannot update internal cache", "volumeName", volume.Name, "err", updateErr)
  1750  				}
  1751  			}
  1752  			break
  1753  		}
  1754  		// Save failed, try again after a while.
  1755  		logger.V(3).Info("Failed to save volume for claim", "PVC", klog.KObj(claim), "volumeName", volume.Name, "err", err)
  1756  		time.Sleep(ctrl.createProvisionedPVInterval)
  1757  	}
  1758  
  1759  	if err != nil {
  1760  		// Save failed. Now we have a storage asset outside of Kubernetes,
  1761  		// but we don't have appropriate PV object for it.
  1762  		// Emit some event here and try to delete the storage asset several
  1763  		// times.
  1764  		strerr := fmt.Sprintf("Error creating provisioned PV object for claim %s: %v. Deleting the volume.", claimToClaimKey(claim), err)
  1765  		logger.V(3).Info(strerr)
  1766  		ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.ProvisioningFailed, strerr)
  1767  
  1768  		var deleteErr error
  1769  		var deleted bool
  1770  		for i := 0; i < ctrl.createProvisionedPVRetryCount; i++ {
  1771  			_, deleted, deleteErr = ctrl.doDeleteVolume(ctx, volume)
  1772  			if deleteErr == nil && deleted {
  1773  				// Delete succeeded
  1774  				logger.V(4).Info("provisionClaimOperation: cleaning volume succeeded", "PVC", klog.KObj(claim), "volumeName", volume.Name)
  1775  				break
  1776  			}
  1777  			if !deleted {
  1778  				// This is unreachable code, the volume was provisioned by an
  1779  				// internal plugin and therefore there MUST be an internal
  1780  				// plugin that deletes it.
  1781  				logger.Error(nil, "Error finding internal deleter for volume plugin", "plugin", plugin.GetPluginName())
  1782  				break
  1783  			}
  1784  			// Delete failed, try again after a while.
  1785  			logger.V(3).Info("Failed to delete volume", "volumeName", volume.Name, "err", deleteErr)
  1786  			time.Sleep(ctrl.createProvisionedPVInterval)
  1787  		}
  1788  
  1789  		if deleteErr != nil {
  1790  			// Delete failed several times. There is an orphaned volume and there
  1791  			// is nothing we can do about it.
  1792  			strerr := fmt.Sprintf("Error cleaning provisioned volume for claim %s: %v. Please delete manually.", claimToClaimKey(claim), deleteErr)
  1793  			logger.V(2).Info(strerr)
  1794  			ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.ProvisioningCleanupFailed, strerr)
  1795  		}
  1796  	} else {
  1797  		logger.V(2).Info("Volume provisioned for claim", "PVC", klog.KObj(claim), "volumeName", volume.Name)
  1798  		msg := fmt.Sprintf("Successfully provisioned volume %s using %s", volume.Name, plugin.GetPluginName())
  1799  		ctrl.eventRecorder.Event(claim, v1.EventTypeNormal, events.ProvisioningSucceeded, msg)
  1800  	}
  1801  	return pluginName, nil
  1802  }
  1803  
  1804  // provisionClaimOperationExternal provisions a volume using external provisioner async-ly
  1805  // This method will be running in a standalone go-routine scheduled in "provisionClaim"
  1806  func (ctrl *PersistentVolumeController) provisionClaimOperationExternal(
  1807  	ctx context.Context,
  1808  	claim *v1.PersistentVolumeClaim,
  1809  	storageClass *storage.StorageClass) (string, error) {
  1810  	claimClass := storagehelpers.GetPersistentVolumeClaimClass(claim)
  1811  	logger := klog.FromContext(ctx)
  1812  	logger.V(4).Info("provisionClaimOperationExternal started", "PVC", klog.KObj(claim), "storageClassName", claimClass)
  1813  	// Set provisionerName to external provisioner name by setClaimProvisioner
  1814  	var err error
  1815  	provisionerName := storageClass.Provisioner
  1816  	if ctrl.csiMigratedPluginManager.IsMigrationEnabledForPlugin(storageClass.Provisioner) {
  1817  		// update the provisioner name to use the migrated CSI plugin name
  1818  		provisionerName, err = ctrl.translator.GetCSINameFromInTreeName(storageClass.Provisioner)
  1819  		if err != nil {
  1820  			strerr := fmt.Sprintf("error getting CSI name for In tree plugin %s: %v", storageClass.Provisioner, err)
  1821  			logger.V(2).Info(strerr)
  1822  			ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.ProvisioningFailed, strerr)
  1823  			return provisionerName, err
  1824  		}
  1825  	}
  1826  	// Add provisioner annotation so external provisioners know when to start
  1827  	newClaim, err := ctrl.setClaimProvisioner(ctx, claim, provisionerName)
  1828  	if err != nil {
  1829  		// Save failed, the controller will retry in the next sync
  1830  		strerr := fmt.Sprintf("Error saving claim: %v", err)
  1831  		logger.V(2).Info("Error saving claim", "PVC", klog.KObj(claim), "err", err)
  1832  		ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.ProvisioningFailed, strerr)
  1833  		return provisionerName, err
  1834  	}
  1835  	claim = newClaim
  1836  	msg := fmt.Sprintf("Waiting for a volume to be created either by the external provisioner '%s' "+
  1837  		"or manually by the system administrator. If volume creation is delayed, please verify that "+
  1838  		"the provisioner is running and correctly registered.", provisionerName)
  1839  	// External provisioner has been requested for provisioning the volume
  1840  	// Report an event and wait for external provisioner to finish
  1841  	ctrl.eventRecorder.Event(claim, v1.EventTypeNormal, events.ExternalProvisioning, msg)
  1842  	logger.V(3).Info("provisionClaimOperationExternal provisioning claim", "PVC", klog.KObj(claim), "msg", msg)
  1843  	// return provisioner name here for metric reporting
  1844  	return provisionerName, nil
  1845  }
  1846  
  1847  // rescheduleProvisioning signal back to the scheduler to retry dynamic provisioning
  1848  // by removing the AnnSelectedNode annotation
  1849  func (ctrl *PersistentVolumeController) rescheduleProvisioning(ctx context.Context, claim *v1.PersistentVolumeClaim) {
  1850  	if _, ok := claim.Annotations[storagehelpers.AnnSelectedNode]; !ok {
  1851  		// Provisioning not triggered by the scheduler, skip
  1852  		return
  1853  	}
  1854  
  1855  	// The claim from method args can be pointing to watcher cache. We must not
  1856  	// modify these, therefore create a copy.
  1857  	newClaim := claim.DeepCopy()
  1858  	delete(newClaim.Annotations, storagehelpers.AnnSelectedNode)
  1859  	// Try to update the PVC object
  1860  	logger := klog.FromContext(ctx)
  1861  	if _, err := ctrl.kubeClient.CoreV1().PersistentVolumeClaims(newClaim.Namespace).Update(ctx, newClaim, metav1.UpdateOptions{}); err != nil {
  1862  		logger.V(4).Info("Failed to delete annotation 'storagehelpers.AnnSelectedNode' for PersistentVolumeClaim", "PVC", klog.KObj(newClaim), "err", err)
  1863  		return
  1864  	}
  1865  	if _, err := ctrl.storeClaimUpdate(logger, newClaim); err != nil {
  1866  		// We will get an "claim updated" event soon, this is not a big error
  1867  		logger.V(4).Info("Updating PersistentVolumeClaim: cannot update internal cache", "PVC", klog.KObj(newClaim), "err", err)
  1868  	}
  1869  }
  1870  
  1871  // getProvisionedVolumeNameForClaim returns PV.Name for the provisioned volume.
  1872  // The name must be unique.
  1873  func (ctrl *PersistentVolumeController) getProvisionedVolumeNameForClaim(claim *v1.PersistentVolumeClaim) string {
  1874  	return "pvc-" + string(claim.UID)
  1875  }
  1876  
  1877  // scheduleOperation starts given asynchronous operation on given volume. It
  1878  // makes sure the operation is already not running.
  1879  func (ctrl *PersistentVolumeController) scheduleOperation(logger klog.Logger, operationName string, operation func() error) {
  1880  	logger.V(4).Info("scheduleOperation", "operationName", operationName)
  1881  
  1882  	// Poke test code that an operation is just about to get started.
  1883  	if ctrl.preOperationHook != nil {
  1884  		ctrl.preOperationHook(operationName)
  1885  	}
  1886  
  1887  	err := ctrl.runningOperations.Run(operationName, operation)
  1888  	if err != nil {
  1889  		switch {
  1890  		case goroutinemap.IsAlreadyExists(err):
  1891  			logger.V(4).Info("Operation is already running, skipping", "operationName", operationName)
  1892  		case exponentialbackoff.IsExponentialBackoff(err):
  1893  			logger.V(4).Info("Operation postponed due to exponential backoff", "operationName", operationName)
  1894  		default:
  1895  			logger.Error(err, "Error scheduling operation", "operationName", operationName)
  1896  		}
  1897  	}
  1898  }
  1899  
  1900  // newRecyclerEventRecorder returns a RecycleEventRecorder that sends all events
  1901  // to given volume.
  1902  func (ctrl *PersistentVolumeController) newRecyclerEventRecorder(volume *v1.PersistentVolume) recyclerclient.RecycleEventRecorder {
  1903  	return func(eventtype, message string) {
  1904  		ctrl.eventRecorder.Eventf(volume, eventtype, events.RecyclerPod, "Recycler pod: %s", message)
  1905  	}
  1906  }
  1907  
  1908  // findProvisionablePlugin finds a provisioner plugin for a given claim.
  1909  // It returns either the provisioning plugin or nil when an external
  1910  // provisioner is requested.
  1911  func (ctrl *PersistentVolumeController) findProvisionablePlugin(claim *v1.PersistentVolumeClaim) (vol.ProvisionableVolumePlugin, *storage.StorageClass, error) {
  1912  	// provisionClaim() which leads here is never called with claimClass=="", we
  1913  	// can save some checks.
  1914  	claimClass := storagehelpers.GetPersistentVolumeClaimClass(claim)
  1915  	class, err := ctrl.classLister.Get(claimClass)
  1916  	if err != nil {
  1917  		return nil, nil, err
  1918  	}
  1919  
  1920  	// Find a plugin for the class
  1921  	if ctrl.csiMigratedPluginManager.IsMigrationEnabledForPlugin(class.Provisioner) {
  1922  		// CSI migration scenario - do not depend on in-tree plugin
  1923  		return nil, class, nil
  1924  	}
  1925  	plugin, err := ctrl.volumePluginMgr.FindProvisionablePluginByName(class.Provisioner)
  1926  	if err != nil {
  1927  		if !strings.HasPrefix(class.Provisioner, "kubernetes.io/") {
  1928  			// External provisioner is requested, do not report error
  1929  			return nil, class, nil
  1930  		}
  1931  		return nil, class, err
  1932  	}
  1933  	return plugin, class, nil
  1934  }
  1935  
  1936  // findDeletablePlugin finds a deleter plugin for a given volume. It returns
  1937  // either the deleter plugin or nil when an external deleter is requested.
  1938  func (ctrl *PersistentVolumeController) findDeletablePlugin(volume *v1.PersistentVolume) (vol.DeletableVolumePlugin, error) {
  1939  	// Find a plugin. Try to find the same plugin that provisioned the volume
  1940  	var plugin vol.DeletableVolumePlugin
  1941  	if metav1.HasAnnotation(volume.ObjectMeta, storagehelpers.AnnDynamicallyProvisioned) {
  1942  		provisionPluginName := volume.Annotations[storagehelpers.AnnDynamicallyProvisioned]
  1943  		if provisionPluginName != "" {
  1944  			plugin, err := ctrl.volumePluginMgr.FindDeletablePluginByName(provisionPluginName)
  1945  			if err != nil {
  1946  				if !strings.HasPrefix(provisionPluginName, "kubernetes.io/") {
  1947  					// External provisioner is requested, do not report error
  1948  					return nil, nil
  1949  				}
  1950  				return nil, err
  1951  			}
  1952  			return plugin, nil
  1953  		}
  1954  	}
  1955  
  1956  	// The plugin that provisioned the volume was not found or the volume
  1957  	// was not dynamically provisioned. Try to find a plugin by spec.
  1958  	spec := vol.NewSpecFromPersistentVolume(volume, false)
  1959  	plugin, err := ctrl.volumePluginMgr.FindDeletablePluginBySpec(spec)
  1960  	if err != nil {
  1961  		// No deleter found. Emit an event and mark the volume Failed.
  1962  		return nil, fmt.Errorf("error getting deleter volume plugin for volume %q: %w", volume.Name, err)
  1963  	}
  1964  	return plugin, nil
  1965  }
  1966  
  1967  // obtain provisioner/deleter name for a volume
  1968  func (ctrl *PersistentVolumeController) getProvisionerNameFromVolume(volume *v1.PersistentVolume) string {
  1969  	plugin, err := ctrl.findDeletablePlugin(volume)
  1970  	if err != nil {
  1971  		return "N/A"
  1972  	}
  1973  	if plugin != nil {
  1974  		return plugin.GetPluginName()
  1975  	}
  1976  	// If reached here, Either an external provisioner was used for provisioning
  1977  	// or a plugin has been migrated to CSI.
  1978  	// If an external provisioner was used, i.e., plugin == nil, instead of using
  1979  	// the AnnDynamicallyProvisioned annotation value, use the storageClass's Provisioner
  1980  	// field to avoid explosion of the metric in the cases like local storage provisioner
  1981  	// tagging a volume with arbitrary provisioner names
  1982  	storageClass := storagehelpers.GetPersistentVolumeClass(volume)
  1983  	class, err := ctrl.classLister.Get(storageClass)
  1984  	if err != nil {
  1985  		return "N/A"
  1986  	}
  1987  	if ctrl.csiMigratedPluginManager.IsMigrationEnabledForPlugin(class.Provisioner) {
  1988  		provisionerName, err := ctrl.translator.GetCSINameFromInTreeName(class.Provisioner)
  1989  		if err != nil {
  1990  			return "N/A"
  1991  		}
  1992  		return provisionerName
  1993  	}
  1994  	return class.Provisioner
  1995  }
  1996  
  1997  // obtain plugin/external provisioner name from plugin and storage class for timestamp logging purposes
  1998  func (ctrl *PersistentVolumeController) getProvisionerName(plugin vol.ProvisionableVolumePlugin, storageClass *storage.StorageClass) string {
  1999  	// non CSI-migrated in-tree plugin, returns the plugin's name
  2000  	if plugin != nil {
  2001  		return plugin.GetPluginName()
  2002  	}
  2003  	if ctrl.csiMigratedPluginManager.IsMigrationEnabledForPlugin(storageClass.Provisioner) {
  2004  		// get the name of the CSI plugin that the in-tree storage class
  2005  		// provisioner has migrated to
  2006  		provisionerName, err := ctrl.translator.GetCSINameFromInTreeName(storageClass.Provisioner)
  2007  		if err != nil {
  2008  			return "N/A"
  2009  		}
  2010  		return provisionerName
  2011  	}
  2012  	return storageClass.Provisioner
  2013  }