k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/kubelet/volumemanager/cache/actual_state_of_world.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  /*
    18  Package cache implements data structures used by the kubelet volume manager to
    19  keep track of attached volumes and the pods that mounted them.
    20  */
    21  package cache
    22  
    23  import (
    24  	"fmt"
    25  	"sync"
    26  
    27  	v1 "k8s.io/api/core/v1"
    28  	"k8s.io/apimachinery/pkg/api/resource"
    29  	"k8s.io/apimachinery/pkg/types"
    30  	utilfeature "k8s.io/apiserver/pkg/util/feature"
    31  	"k8s.io/klog/v2"
    32  	"k8s.io/kubernetes/pkg/features"
    33  	"k8s.io/kubernetes/pkg/volume"
    34  	"k8s.io/kubernetes/pkg/volume/util"
    35  	"k8s.io/kubernetes/pkg/volume/util/operationexecutor"
    36  	volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
    37  )
    38  
    39  // ActualStateOfWorld defines a set of thread-safe operations for the kubelet
    40  // volume manager's actual state of the world cache.
    41  // This cache contains volumes->pods i.e. a set of all volumes attached to this
    42  // node and the pods that the manager believes have successfully mounted the
    43  // volume.
    44  // Note: This is distinct from the ActualStateOfWorld implemented by the
    45  // attach/detach controller. They both keep track of different objects. This
    46  // contains kubelet volume manager specific state.
    47  type ActualStateOfWorld interface {
    48  	// ActualStateOfWorld must implement the methods required to allow
    49  	// operationexecutor to interact with it.
    50  	operationexecutor.ActualStateOfWorldMounterUpdater
    51  
    52  	// ActualStateOfWorld must implement the methods required to allow
    53  	// operationexecutor to interact with it.
    54  	operationexecutor.ActualStateOfWorldAttacherUpdater
    55  
    56  	// AddPodToVolume adds the given pod to the given volume in the cache
    57  	// indicating the specified volume has been successfully mounted to the
    58  	// specified pod.
    59  	// If a pod with the same unique name already exists under the specified
    60  	// volume, reset the pod's remountRequired value.
    61  	// If a volume with the name volumeName does not exist in the list of
    62  	// attached volumes, an error is returned.
    63  	AddPodToVolume(operationexecutor.MarkVolumeOpts) error
    64  
    65  	// MarkRemountRequired marks each volume that is successfully attached and
    66  	// mounted for the specified pod as requiring remount (if the plugin for the
    67  	// volume indicates it requires remounting on pod updates). Atomically
    68  	// updating volumes depend on this to update the contents of the volume on
    69  	// pod update.
    70  	MarkRemountRequired(podName volumetypes.UniquePodName)
    71  
    72  	// SetDeviceMountState sets device mount state for the given volume. When deviceMountState is set to DeviceGloballyMounted
    73  	// then device is mounted at a global mount point. When it is set to DeviceMountUncertain then also it means volume
    74  	// MAY be globally mounted at a global mount point. In both cases - the volume must be unmounted from
    75  	// global mount point prior to detach.
    76  	// If a volume with the name volumeName does not exist in the list of
    77  	// attached volumes, an error is returned.
    78  	SetDeviceMountState(volumeName v1.UniqueVolumeName, deviceMountState operationexecutor.DeviceMountState, devicePath, deviceMountPath, seLinuxMountContext string) error
    79  
    80  	// DeletePodFromVolume removes the given pod from the given volume in the
    81  	// cache indicating the volume has been successfully unmounted from the pod.
    82  	// If a pod with the same unique name does not exist under the specified
    83  	// volume, this is a no-op.
    84  	// If a volume with the name volumeName does not exist in the list of
    85  	// attached volumes, an error is returned.
    86  	DeletePodFromVolume(podName volumetypes.UniquePodName, volumeName v1.UniqueVolumeName) error
    87  
    88  	// DeleteVolume removes the given volume from the list of attached volumes
    89  	// in the cache indicating the volume has been successfully detached from
    90  	// this node.
    91  	// If a volume with the name volumeName does not exist in the list of
    92  	// attached volumes, this is a no-op.
    93  	// If a volume with the name volumeName exists and its list of mountedPods
    94  	// is not empty, an error is returned.
    95  	DeleteVolume(volumeName v1.UniqueVolumeName) error
    96  
    97  	// PodExistsInVolume returns true if the given pod exists in the list of
    98  	// mountedPods for the given volume in the cache, indicating that the volume
    99  	// is attached to this node and the pod has successfully mounted it.
   100  	// If a pod with the same unique name does not exist under the specified
   101  	// volume, false is returned.
   102  	// If a volume with the name volumeName does not exist in the list of
   103  	// attached volumes, a volumeNotAttachedError is returned indicating the
   104  	// given volume is not yet attached.
   105  	// If the given volumeName/podName combo exists but the value of
   106  	// remountRequired is true, a remountRequiredError is returned indicating
   107  	// the given volume has been successfully mounted to this pod but should be
   108  	// remounted to reflect changes in the referencing pod. Atomically updating
   109  	// volumes, depend on this to update the contents of the volume.
   110  	// All volume mounting calls should be idempotent so a second mount call for
   111  	// volumes that do not need to update contents should not fail.
   112  	PodExistsInVolume(podName volumetypes.UniquePodName, volumeName v1.UniqueVolumeName, desiredVolumeSize resource.Quantity, seLinuxLabel string) (bool, string, error)
   113  
   114  	// PodRemovedFromVolume returns true if the given pod does not exist in the list of
   115  	// mountedPods for the given volume in the cache, indicating that the pod has
   116  	// fully unmounted it or it was never mounted the volume.
   117  	// If the volume is fully mounted or is in uncertain mount state for the pod, it is
   118  	// considered that the pod still exists in volume manager's actual state of the world
   119  	// and false is returned.
   120  	PodRemovedFromVolume(podName volumetypes.UniquePodName, volumeName v1.UniqueVolumeName) bool
   121  
   122  	// VolumeExistsWithSpecName returns true if the given volume specified with the
   123  	// volume spec name (a.k.a., InnerVolumeSpecName) exists in the list of
   124  	// volumes that should be attached to this node.
   125  	// If a pod with the same name does not exist under the specified
   126  	// volume, false is returned.
   127  	VolumeExistsWithSpecName(podName volumetypes.UniquePodName, volumeSpecName string) bool
   128  
   129  	// VolumeExists returns true if the given volume exists in the list of
   130  	// attached volumes in the cache, indicating the volume is attached to this
   131  	// node.
   132  	VolumeExists(volumeName v1.UniqueVolumeName) bool
   133  
   134  	// GetMountedVolumes generates and returns a list of volumes and the pods
   135  	// they are successfully attached and mounted for based on the current
   136  	// actual state of the world.
   137  	GetMountedVolumes() []MountedVolume
   138  
   139  	// GetAllMountedVolumes returns list of all possibly mounted volumes including
   140  	// those that are in VolumeMounted state and VolumeMountUncertain state.
   141  	GetAllMountedVolumes() []MountedVolume
   142  
   143  	// GetMountedVolumesForPod generates and returns a list of volumes that are
   144  	// successfully attached and mounted for the specified pod based on the
   145  	// current actual state of the world.
   146  	GetMountedVolumesForPod(podName volumetypes.UniquePodName) []MountedVolume
   147  
   148  	// GetPossiblyMountedVolumesForPod generates and returns a list of volumes for
   149  	// the specified pod that either are attached and mounted or are "uncertain",
   150  	// i.e. a volume plugin may be mounting the volume right now.
   151  	GetPossiblyMountedVolumesForPod(podName volumetypes.UniquePodName) []MountedVolume
   152  
   153  	// GetGloballyMountedVolumes generates and returns a list of all attached
   154  	// volumes that are globally mounted. This list can be used to determine
   155  	// which volumes should be reported as "in use" in the node's VolumesInUse
   156  	// status field. Globally mounted here refers to the shared plugin mount
   157  	// point for the attachable volume from which the pod specific mount points
   158  	// are created (via bind mount).
   159  	GetGloballyMountedVolumes() []AttachedVolume
   160  
   161  	// GetUnmountedVolumes generates and returns a list of attached volumes that
   162  	// have no mountedPods. This list can be used to determine which volumes are
   163  	// no longer referenced and may be globally unmounted and detached.
   164  	GetUnmountedVolumes() []AttachedVolume
   165  
   166  	// GetAttachedVolumes returns a list of volumes that is known to be attached
   167  	// to the node. This list can be used to determine volumes that are either in-use
   168  	// or have a mount/unmount operation pending.
   169  	GetAttachedVolumes() []AttachedVolume
   170  
   171  	// Add the specified volume to ASW as uncertainly attached.
   172  	AddAttachUncertainReconstructedVolume(volumeName v1.UniqueVolumeName, volumeSpec *volume.Spec, nodeName types.NodeName, devicePath string) error
   173  
   174  	// UpdateReconstructedDevicePath updates devicePath of a reconstructed volume
   175  	// from Node.Status.VolumesAttached. The ASW is updated only when the volume is still
   176  	// uncertain. If the volume got mounted in the meantime, its devicePath must have
   177  	// been fixed by such an update.
   178  	UpdateReconstructedDevicePath(volumeName v1.UniqueVolumeName, devicePath string)
   179  
   180  	// UpdateReconstructedVolumeAttachability updates volume attachability from the API server.
   181  	UpdateReconstructedVolumeAttachability(volumeName v1.UniqueVolumeName, volumeAttachable bool)
   182  }
   183  
   184  // MountedVolume represents a volume that has successfully been mounted to a pod.
   185  type MountedVolume struct {
   186  	operationexecutor.MountedVolume
   187  }
   188  
   189  // AttachedVolume represents a volume that is attached to a node.
   190  type AttachedVolume struct {
   191  	operationexecutor.AttachedVolume
   192  
   193  	// DeviceMountState indicates if device has been globally mounted or is not.
   194  	DeviceMountState operationexecutor.DeviceMountState
   195  
   196  	// SELinuxMountContext is the context with that the volume is globally mounted
   197  	// (via -o context=XYZ mount option). If empty, the volume is not mounted with
   198  	// "-o context=".
   199  	SELinuxMountContext string
   200  }
   201  
   202  // DeviceMayBeMounted returns true if device is mounted in global path or is in
   203  // uncertain state.
   204  func (av AttachedVolume) DeviceMayBeMounted() bool {
   205  	return av.DeviceMountState == operationexecutor.DeviceGloballyMounted ||
   206  		av.DeviceMountState == operationexecutor.DeviceMountUncertain
   207  }
   208  
   209  // NewActualStateOfWorld returns a new instance of ActualStateOfWorld.
   210  func NewActualStateOfWorld(
   211  	nodeName types.NodeName,
   212  	volumePluginMgr *volume.VolumePluginMgr) ActualStateOfWorld {
   213  	return &actualStateOfWorld{
   214  		nodeName:                  nodeName,
   215  		attachedVolumes:           make(map[v1.UniqueVolumeName]attachedVolume),
   216  		foundDuringReconstruction: make(map[v1.UniqueVolumeName]map[volumetypes.UniquePodName]types.UID),
   217  		volumePluginMgr:           volumePluginMgr,
   218  	}
   219  }
   220  
   221  // IsVolumeNotAttachedError returns true if the specified error is a
   222  // volumeNotAttachedError.
   223  func IsVolumeNotAttachedError(err error) bool {
   224  	_, ok := err.(volumeNotAttachedError)
   225  	return ok
   226  }
   227  
   228  // IsRemountRequiredError returns true if the specified error is a
   229  // remountRequiredError.
   230  func IsRemountRequiredError(err error) bool {
   231  	_, ok := err.(remountRequiredError)
   232  	return ok
   233  }
   234  
   235  type actualStateOfWorld struct {
   236  	// nodeName is the name of this node. This value is passed to Attach/Detach
   237  	nodeName types.NodeName
   238  
   239  	// attachedVolumes is a map containing the set of volumes the kubelet volume
   240  	// manager believes to be successfully attached to this node. Volume types
   241  	// that do not implement an attacher interface are assumed to be in this
   242  	// state by default.
   243  	// The key in this map is the name of the volume and the value is an object
   244  	// containing more information about the attached volume.
   245  	attachedVolumes map[v1.UniqueVolumeName]attachedVolume
   246  	// foundDuringReconstruction is a map of volumes which were discovered
   247  	// from kubelet root directory when kubelet was restarted.
   248  	foundDuringReconstruction map[v1.UniqueVolumeName]map[volumetypes.UniquePodName]types.UID
   249  
   250  	// volumePluginMgr is the volume plugin manager used to create volume
   251  	// plugin objects.
   252  	volumePluginMgr *volume.VolumePluginMgr
   253  	sync.RWMutex
   254  }
   255  
   256  type volumeAttachability string
   257  
   258  const (
   259  	volumeAttachabilityTrue      volumeAttachability = "True"
   260  	volumeAttachabilityFalse     volumeAttachability = "False"
   261  	volumeAttachabilityUncertain volumeAttachability = "Uncertain"
   262  )
   263  
   264  // attachedVolume represents a volume the kubelet volume manager believes to be
   265  // successfully attached to a node it is managing. Volume types that do not
   266  // implement an attacher are assumed to be in this state.
   267  type attachedVolume struct {
   268  	// volumeName contains the unique identifier for this volume.
   269  	volumeName v1.UniqueVolumeName
   270  
   271  	// mountedPods is a map containing the set of pods that this volume has been
   272  	// successfully mounted to. The key in this map is the name of the pod and
   273  	// the value is a mountedPod object containing more information about the
   274  	// pod.
   275  	mountedPods map[volumetypes.UniquePodName]mountedPod
   276  
   277  	// spec is the volume spec containing the specification for this volume.
   278  	// Used to generate the volume plugin object, and passed to plugin methods.
   279  	// In particular, the Unmount method uses spec.Name() as the volumeSpecName
   280  	// in the mount path:
   281  	// /var/lib/kubelet/pods/{podUID}/volumes/{escapeQualifiedPluginName}/{volumeSpecName}/
   282  	spec *volume.Spec
   283  
   284  	// pluginName is the Unescaped Qualified name of the volume plugin used to
   285  	// attach and mount this volume. It is stored separately in case the full
   286  	// volume spec (everything except the name) can not be reconstructed for a
   287  	// volume that should be unmounted (which would be the case for a mount path
   288  	// read from disk without a full volume spec).
   289  	pluginName string
   290  
   291  	// pluginIsAttachable indicates the volume plugin used to attach and mount
   292  	// this volume implements the volume.Attacher interface
   293  	pluginIsAttachable volumeAttachability
   294  
   295  	// deviceMountState stores information that tells us if device is mounted
   296  	// globally or not
   297  	deviceMountState operationexecutor.DeviceMountState
   298  
   299  	// devicePath contains the path on the node where the volume is attached for
   300  	// attachable volumes
   301  	devicePath string
   302  
   303  	// deviceMountPath contains the path on the node where the device should
   304  	// be mounted after it is attached.
   305  	deviceMountPath string
   306  
   307  	// volumeInUseErrorForExpansion indicates volume driver has previously returned volume-in-use error
   308  	// for this volume and volume expansion on this node should not be retried
   309  	volumeInUseErrorForExpansion bool
   310  
   311  	// persistentVolumeSize records size of the volume when pod was started or
   312  	// size after successful completion of volume expansion operation.
   313  	persistentVolumeSize *resource.Quantity
   314  
   315  	// seLinuxMountContext is the context with that the volume is mounted to global directory
   316  	// (via -o context=XYZ mount option). If nil, the volume is not mounted. If "", the volume is
   317  	// mounted without "-o context=".
   318  	seLinuxMountContext *string
   319  }
   320  
   321  // The mountedPod object represents a pod for which the kubelet volume manager
   322  // believes the underlying volume has been successfully been mounted.
   323  type mountedPod struct {
   324  	// the name of the pod
   325  	podName volumetypes.UniquePodName
   326  
   327  	// the UID of the pod
   328  	podUID types.UID
   329  
   330  	// mounter used to mount
   331  	mounter volume.Mounter
   332  
   333  	// mapper used to block volumes support
   334  	blockVolumeMapper volume.BlockVolumeMapper
   335  
   336  	// spec is the volume spec containing the specification for this volume.
   337  	// Used to generate the volume plugin object, and passed to plugin methods.
   338  	// In particular, the Unmount method uses spec.Name() as the volumeSpecName
   339  	// in the mount path:
   340  	// /var/lib/kubelet/pods/{podUID}/volumes/{escapeQualifiedPluginName}/{volumeSpecName}/
   341  	volumeSpec *volume.Spec
   342  
   343  	// outerVolumeSpecName is the volume.Spec.Name() of the volume as referenced
   344  	// directly in the pod. If the volume was referenced through a persistent
   345  	// volume claim, this contains the volume.Spec.Name() of the persistent
   346  	// volume claim
   347  	outerVolumeSpecName string
   348  
   349  	// remountRequired indicates the underlying volume has been successfully
   350  	// mounted to this pod but it should be remounted to reflect changes in the
   351  	// referencing pod.
   352  	// Atomically updating volumes depend on this to update the contents of the
   353  	// volume. All volume mounting calls should be idempotent so a second mount
   354  	// call for volumes that do not need to update contents should not fail.
   355  	remountRequired bool
   356  
   357  	// volumeGidValue contains the value of the GID annotation, if present.
   358  	volumeGidValue string
   359  
   360  	// volumeMountStateForPod stores state of volume mount for the pod. if it is:
   361  	//   - VolumeMounted: means volume for pod has been successfully mounted
   362  	//   - VolumeMountUncertain: means volume for pod may not be mounted, but it must be unmounted
   363  	volumeMountStateForPod operationexecutor.VolumeMountState
   364  
   365  	// seLinuxMountContext is the context with that the volume is mounted to Pod directory
   366  	// (via -o context=XYZ mount option). If nil, the volume is not mounted. If "", the volume is
   367  	// mounted without "-o context=".
   368  	seLinuxMountContext string
   369  }
   370  
   371  func (asw *actualStateOfWorld) MarkVolumeAsAttached(
   372  	logger klog.Logger,
   373  	volumeName v1.UniqueVolumeName, volumeSpec *volume.Spec, _ types.NodeName, devicePath string) error {
   374  
   375  	pluginIsAttachable := volumeAttachabilityFalse
   376  	if attachablePlugin, err := asw.volumePluginMgr.FindAttachablePluginBySpec(volumeSpec); err == nil && attachablePlugin != nil {
   377  		pluginIsAttachable = volumeAttachabilityTrue
   378  	}
   379  
   380  	return asw.addVolume(volumeName, volumeSpec, devicePath, pluginIsAttachable)
   381  }
   382  
   383  func (asw *actualStateOfWorld) AddAttachUncertainReconstructedVolume(
   384  	volumeName v1.UniqueVolumeName, volumeSpec *volume.Spec, _ types.NodeName, devicePath string) error {
   385  
   386  	return asw.addVolume(volumeName, volumeSpec, devicePath, volumeAttachabilityUncertain)
   387  }
   388  
   389  func (asw *actualStateOfWorld) MarkVolumeAsUncertain(
   390  	logger klog.Logger, volumeName v1.UniqueVolumeName, volumeSpec *volume.Spec, _ types.NodeName) error {
   391  	return nil
   392  }
   393  
   394  func (asw *actualStateOfWorld) MarkVolumeAsDetached(
   395  	volumeName v1.UniqueVolumeName, nodeName types.NodeName) {
   396  	asw.DeleteVolume(volumeName)
   397  }
   398  
   399  func (asw *actualStateOfWorld) IsVolumeReconstructed(volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName) bool {
   400  	volumeState := asw.GetVolumeMountState(volumeName, podName)
   401  
   402  	// only uncertain volumes are reconstructed
   403  	if volumeState != operationexecutor.VolumeMountUncertain {
   404  		return false
   405  	}
   406  
   407  	asw.RLock()
   408  	defer asw.RUnlock()
   409  	podMap, ok := asw.foundDuringReconstruction[volumeName]
   410  	if !ok {
   411  		return false
   412  	}
   413  	_, foundPod := podMap[podName]
   414  	return foundPod
   415  }
   416  
   417  func (asw *actualStateOfWorld) IsVolumeDeviceReconstructed(volumeName v1.UniqueVolumeName) bool {
   418  	asw.RLock()
   419  	defer asw.RUnlock()
   420  	_, ok := asw.foundDuringReconstruction[volumeName]
   421  	return ok
   422  }
   423  
   424  func (asw *actualStateOfWorld) CheckAndMarkVolumeAsUncertainViaReconstruction(opts operationexecutor.MarkVolumeOpts) (bool, error) {
   425  	asw.Lock()
   426  	defer asw.Unlock()
   427  
   428  	volumeObj, volumeExists := asw.attachedVolumes[opts.VolumeName]
   429  	if !volumeExists {
   430  		return false, nil
   431  	}
   432  
   433  	podObj, podExists := volumeObj.mountedPods[opts.PodName]
   434  	if podExists {
   435  		// if volume mount was uncertain we should keep trying to unmount the volume
   436  		if podObj.volumeMountStateForPod == operationexecutor.VolumeMountUncertain {
   437  			return false, nil
   438  		}
   439  		if podObj.volumeMountStateForPod == operationexecutor.VolumeMounted {
   440  			return false, nil
   441  		}
   442  	}
   443  
   444  	podName := opts.PodName
   445  	podUID := opts.PodUID
   446  	volumeName := opts.VolumeName
   447  	mounter := opts.Mounter
   448  	blockVolumeMapper := opts.BlockVolumeMapper
   449  	outerVolumeSpecName := opts.OuterVolumeSpecName
   450  	volumeGidValue := opts.VolumeGidVolume
   451  	volumeSpec := opts.VolumeSpec
   452  
   453  	podObj = mountedPod{
   454  		podName:                podName,
   455  		podUID:                 podUID,
   456  		mounter:                mounter,
   457  		blockVolumeMapper:      blockVolumeMapper,
   458  		outerVolumeSpecName:    outerVolumeSpecName,
   459  		volumeGidValue:         volumeGidValue,
   460  		volumeSpec:             volumeSpec,
   461  		remountRequired:        false,
   462  		volumeMountStateForPod: operationexecutor.VolumeMountUncertain,
   463  	}
   464  
   465  	if mounter != nil {
   466  		// The mounter stored in the object may have old information,
   467  		// use the newest one.
   468  		podObj.mounter = mounter
   469  	}
   470  
   471  	asw.attachedVolumes[volumeName].mountedPods[podName] = podObj
   472  
   473  	podMap, ok := asw.foundDuringReconstruction[opts.VolumeName]
   474  	if !ok {
   475  		podMap = map[volumetypes.UniquePodName]types.UID{}
   476  	}
   477  	podMap[opts.PodName] = opts.PodUID
   478  	asw.foundDuringReconstruction[opts.VolumeName] = podMap
   479  	return true, nil
   480  }
   481  
   482  func (asw *actualStateOfWorld) CheckAndMarkDeviceUncertainViaReconstruction(volumeName v1.UniqueVolumeName, deviceMountPath string) bool {
   483  	asw.Lock()
   484  	defer asw.Unlock()
   485  
   486  	volumeObj, volumeExists := asw.attachedVolumes[volumeName]
   487  	// CheckAndMarkDeviceUncertainViaReconstruction requires volume to be marked as attached, so if
   488  	// volume does not exist in ASOW or is in any state other than DeviceNotMounted we should return
   489  	if !volumeExists || volumeObj.deviceMountState != operationexecutor.DeviceNotMounted {
   490  		return false
   491  	}
   492  
   493  	volumeObj.deviceMountState = operationexecutor.DeviceMountUncertain
   494  	// we are only changing deviceMountPath because devicePath at at this stage is
   495  	// determined from node object.
   496  	volumeObj.deviceMountPath = deviceMountPath
   497  	asw.attachedVolumes[volumeName] = volumeObj
   498  	return true
   499  
   500  }
   501  
   502  func (asw *actualStateOfWorld) MarkVolumeAsMounted(markVolumeOpts operationexecutor.MarkVolumeOpts) error {
   503  	return asw.AddPodToVolume(markVolumeOpts)
   504  }
   505  
   506  func (asw *actualStateOfWorld) AddVolumeToReportAsAttached(logger klog.Logger, volumeName v1.UniqueVolumeName, nodeName types.NodeName) {
   507  	// no operation for kubelet side
   508  }
   509  
   510  func (asw *actualStateOfWorld) RemoveVolumeFromReportAsAttached(volumeName v1.UniqueVolumeName, nodeName types.NodeName) error {
   511  	// no operation for kubelet side
   512  	return nil
   513  }
   514  
   515  func (asw *actualStateOfWorld) MarkVolumeAsUnmounted(
   516  	podName volumetypes.UniquePodName, volumeName v1.UniqueVolumeName) error {
   517  	return asw.DeletePodFromVolume(podName, volumeName)
   518  }
   519  
   520  func (asw *actualStateOfWorld) MarkDeviceAsMounted(
   521  	volumeName v1.UniqueVolumeName, devicePath, deviceMountPath, seLinuxMountContext string) error {
   522  	return asw.SetDeviceMountState(volumeName, operationexecutor.DeviceGloballyMounted, devicePath, deviceMountPath, seLinuxMountContext)
   523  }
   524  
   525  func (asw *actualStateOfWorld) MarkDeviceAsUncertain(
   526  	volumeName v1.UniqueVolumeName, devicePath, deviceMountPath, seLinuxMountContext string) error {
   527  	return asw.SetDeviceMountState(volumeName, operationexecutor.DeviceMountUncertain, devicePath, deviceMountPath, seLinuxMountContext)
   528  }
   529  
   530  func (asw *actualStateOfWorld) MarkVolumeMountAsUncertain(markVolumeOpts operationexecutor.MarkVolumeOpts) error {
   531  	markVolumeOpts.VolumeMountState = operationexecutor.VolumeMountUncertain
   532  	return asw.AddPodToVolume(markVolumeOpts)
   533  }
   534  
   535  func (asw *actualStateOfWorld) MarkDeviceAsUnmounted(
   536  	volumeName v1.UniqueVolumeName) error {
   537  	return asw.SetDeviceMountState(volumeName, operationexecutor.DeviceNotMounted, "", "", "")
   538  }
   539  
   540  func (asw *actualStateOfWorld) UpdateReconstructedDevicePath(volumeName v1.UniqueVolumeName, devicePath string) {
   541  	asw.Lock()
   542  	defer asw.Unlock()
   543  
   544  	volumeObj, volumeExists := asw.attachedVolumes[volumeName]
   545  	if !volumeExists {
   546  		return
   547  	}
   548  	if volumeObj.deviceMountState != operationexecutor.DeviceMountUncertain {
   549  		// Reconciler must have updated volume state, i.e. when a pod uses the volume and
   550  		// succeeded mounting the volume. Such update has fixed the device path.
   551  		return
   552  	}
   553  
   554  	volumeObj.devicePath = devicePath
   555  	asw.attachedVolumes[volumeName] = volumeObj
   556  }
   557  
   558  func (asw *actualStateOfWorld) UpdateReconstructedVolumeAttachability(volumeName v1.UniqueVolumeName, attachable bool) {
   559  	asw.Lock()
   560  	defer asw.Unlock()
   561  
   562  	volumeObj, volumeExists := asw.attachedVolumes[volumeName]
   563  	if !volumeExists {
   564  		return
   565  	}
   566  	if volumeObj.pluginIsAttachable != volumeAttachabilityUncertain {
   567  		// Reconciler must have updated volume state, i.e. when a pod uses the volume and
   568  		// succeeded mounting the volume. Such update has fixed the device path.
   569  		return
   570  	}
   571  
   572  	if attachable {
   573  		volumeObj.pluginIsAttachable = volumeAttachabilityTrue
   574  	} else {
   575  		volumeObj.pluginIsAttachable = volumeAttachabilityFalse
   576  	}
   577  	asw.attachedVolumes[volumeName] = volumeObj
   578  }
   579  
   580  func (asw *actualStateOfWorld) GetDeviceMountState(volumeName v1.UniqueVolumeName) operationexecutor.DeviceMountState {
   581  	asw.RLock()
   582  	defer asw.RUnlock()
   583  
   584  	volumeObj, volumeExists := asw.attachedVolumes[volumeName]
   585  	if !volumeExists {
   586  		return operationexecutor.DeviceNotMounted
   587  	}
   588  
   589  	return volumeObj.deviceMountState
   590  }
   591  
   592  func (asw *actualStateOfWorld) MarkForInUseExpansionError(volumeName v1.UniqueVolumeName) {
   593  	asw.Lock()
   594  	defer asw.Unlock()
   595  
   596  	volumeObj, ok := asw.attachedVolumes[volumeName]
   597  	if ok {
   598  		volumeObj.volumeInUseErrorForExpansion = true
   599  		asw.attachedVolumes[volumeName] = volumeObj
   600  	}
   601  }
   602  
   603  func (asw *actualStateOfWorld) GetVolumeMountState(volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName) operationexecutor.VolumeMountState {
   604  	asw.RLock()
   605  	defer asw.RUnlock()
   606  
   607  	volumeObj, volumeExists := asw.attachedVolumes[volumeName]
   608  	if !volumeExists {
   609  		return operationexecutor.VolumeNotMounted
   610  	}
   611  
   612  	podObj, podExists := volumeObj.mountedPods[podName]
   613  	if !podExists {
   614  		return operationexecutor.VolumeNotMounted
   615  	}
   616  	return podObj.volumeMountStateForPod
   617  }
   618  
   619  func (asw *actualStateOfWorld) IsVolumeMountedElsewhere(volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName) bool {
   620  	asw.RLock()
   621  	defer asw.RUnlock()
   622  
   623  	volumeObj, volumeExists := asw.attachedVolumes[volumeName]
   624  	if !volumeExists {
   625  		return false
   626  	}
   627  
   628  	for _, podObj := range volumeObj.mountedPods {
   629  		if podName != podObj.podName {
   630  			// Treat uncertain mount state as mounted until certain.
   631  			if podObj.volumeMountStateForPod != operationexecutor.VolumeNotMounted {
   632  				return true
   633  			}
   634  		}
   635  	}
   636  	return false
   637  }
   638  
   639  // addVolume adds the given volume to the cache indicating the specified
   640  // volume is attached to this node. If no volume name is supplied, a unique
   641  // volume name is generated from the volumeSpec and returned on success. If a
   642  // volume with the same generated name already exists, this is a noop. If no
   643  // volume plugin can support the given volumeSpec or more than one plugin can
   644  // support it, an error is returned.
   645  func (asw *actualStateOfWorld) addVolume(
   646  	volumeName v1.UniqueVolumeName, volumeSpec *volume.Spec, devicePath string, attachability volumeAttachability) error {
   647  	asw.Lock()
   648  	defer asw.Unlock()
   649  
   650  	volumePlugin, err := asw.volumePluginMgr.FindPluginBySpec(volumeSpec)
   651  	if err != nil || volumePlugin == nil {
   652  		return fmt.Errorf(
   653  			"failed to get Plugin from volumeSpec for volume %q err=%v",
   654  			volumeSpec.Name(),
   655  			err)
   656  	}
   657  
   658  	if len(volumeName) == 0 {
   659  		volumeName, err = util.GetUniqueVolumeNameFromSpec(volumePlugin, volumeSpec)
   660  		if err != nil {
   661  			return fmt.Errorf(
   662  				"failed to GetUniqueVolumeNameFromSpec for volumeSpec %q using volume plugin %q err=%v",
   663  				volumeSpec.Name(),
   664  				volumePlugin.GetPluginName(),
   665  				err)
   666  		}
   667  	}
   668  
   669  	volumeObj, volumeExists := asw.attachedVolumes[volumeName]
   670  	if !volumeExists {
   671  		volumeObj = attachedVolume{
   672  			volumeName:         volumeName,
   673  			spec:               volumeSpec,
   674  			mountedPods:        make(map[volumetypes.UniquePodName]mountedPod),
   675  			pluginName:         volumePlugin.GetPluginName(),
   676  			pluginIsAttachable: attachability,
   677  			deviceMountState:   operationexecutor.DeviceNotMounted,
   678  			devicePath:         devicePath,
   679  		}
   680  	} else {
   681  		// If volume object already exists, update the fields such as device path
   682  		volumeObj.devicePath = devicePath
   683  		klog.V(2).InfoS("Volume is already added to attachedVolume list, update device path", "volumeName", volumeName, "path", devicePath)
   684  	}
   685  	asw.attachedVolumes[volumeName] = volumeObj
   686  
   687  	return nil
   688  }
   689  
   690  func (asw *actualStateOfWorld) AddPodToVolume(markVolumeOpts operationexecutor.MarkVolumeOpts) error {
   691  	podName := markVolumeOpts.PodName
   692  	podUID := markVolumeOpts.PodUID
   693  	volumeName := markVolumeOpts.VolumeName
   694  	mounter := markVolumeOpts.Mounter
   695  	blockVolumeMapper := markVolumeOpts.BlockVolumeMapper
   696  	outerVolumeSpecName := markVolumeOpts.OuterVolumeSpecName
   697  	volumeGidValue := markVolumeOpts.VolumeGidVolume
   698  	volumeSpec := markVolumeOpts.VolumeSpec
   699  	asw.Lock()
   700  	defer asw.Unlock()
   701  
   702  	volumeObj, volumeExists := asw.attachedVolumes[volumeName]
   703  	if !volumeExists {
   704  		return fmt.Errorf(
   705  			"no volume with the name %q exists in the list of attached volumes",
   706  			volumeName)
   707  	}
   708  
   709  	podObj, podExists := volumeObj.mountedPods[podName]
   710  
   711  	updateUncertainVolume := false
   712  	if podExists {
   713  		// Update uncertain volumes - the new markVolumeOpts may have updated information.
   714  		// Especially reconstructed volumes (marked as uncertain during reconstruction) need
   715  		// an update.
   716  		updateUncertainVolume = utilfeature.DefaultFeatureGate.Enabled(features.NewVolumeManagerReconstruction) && podObj.volumeMountStateForPod == operationexecutor.VolumeMountUncertain
   717  	}
   718  	if !podExists || updateUncertainVolume {
   719  		// Add new mountedPod or update existing one.
   720  		podObj = mountedPod{
   721  			podName:                podName,
   722  			podUID:                 podUID,
   723  			mounter:                mounter,
   724  			blockVolumeMapper:      blockVolumeMapper,
   725  			outerVolumeSpecName:    outerVolumeSpecName,
   726  			volumeGidValue:         volumeGidValue,
   727  			volumeSpec:             volumeSpec,
   728  			volumeMountStateForPod: markVolumeOpts.VolumeMountState,
   729  			seLinuxMountContext:    markVolumeOpts.SELinuxMountContext,
   730  		}
   731  	}
   732  
   733  	// If pod exists, reset remountRequired value
   734  	podObj.remountRequired = false
   735  	podObj.volumeMountStateForPod = markVolumeOpts.VolumeMountState
   736  
   737  	// if volume is mounted successfully, then it should be removed from foundDuringReconstruction map
   738  	if markVolumeOpts.VolumeMountState == operationexecutor.VolumeMounted {
   739  		delete(asw.foundDuringReconstruction[volumeName], podName)
   740  	}
   741  	if mounter != nil {
   742  		// The mounter stored in the object may have old information,
   743  		// use the newest one.
   744  		podObj.mounter = mounter
   745  	}
   746  	asw.attachedVolumes[volumeName].mountedPods[podName] = podObj
   747  	if utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
   748  		// Store the mount context also in the AttachedVolume to have a global volume context
   749  		// for a quick comparison in PodExistsInVolume.
   750  		if volumeObj.seLinuxMountContext == nil {
   751  			volumeObj.seLinuxMountContext = &markVolumeOpts.SELinuxMountContext
   752  			asw.attachedVolumes[volumeName] = volumeObj
   753  		}
   754  	}
   755  
   756  	return nil
   757  }
   758  
   759  func (asw *actualStateOfWorld) MarkVolumeAsResized(volumeName v1.UniqueVolumeName, claimSize *resource.Quantity) bool {
   760  	asw.Lock()
   761  	defer asw.Unlock()
   762  
   763  	volumeObj, ok := asw.attachedVolumes[volumeName]
   764  	if ok {
   765  		volumeObj.persistentVolumeSize = claimSize
   766  		asw.attachedVolumes[volumeName] = volumeObj
   767  		return true
   768  	}
   769  	return false
   770  }
   771  
   772  func (asw *actualStateOfWorld) MarkRemountRequired(
   773  	podName volumetypes.UniquePodName) {
   774  	asw.Lock()
   775  	defer asw.Unlock()
   776  	for volumeName, volumeObj := range asw.attachedVolumes {
   777  		if podObj, podExists := volumeObj.mountedPods[podName]; podExists {
   778  			volumePlugin, err :=
   779  				asw.volumePluginMgr.FindPluginBySpec(podObj.volumeSpec)
   780  			if err != nil || volumePlugin == nil {
   781  				// Log and continue processing
   782  				klog.ErrorS(nil, "MarkRemountRequired failed to FindPluginBySpec for volume", "uniquePodName", podObj.podName, "podUID", podObj.podUID, "volumeName", volumeName, "volumeSpecName", podObj.volumeSpec.Name())
   783  				continue
   784  			}
   785  
   786  			if volumePlugin.RequiresRemount(podObj.volumeSpec) {
   787  				podObj.remountRequired = true
   788  				asw.attachedVolumes[volumeName].mountedPods[podName] = podObj
   789  			}
   790  		}
   791  	}
   792  }
   793  
   794  func (asw *actualStateOfWorld) SetDeviceMountState(
   795  	volumeName v1.UniqueVolumeName, deviceMountState operationexecutor.DeviceMountState, devicePath, deviceMountPath, seLinuxMountContext string) error {
   796  	asw.Lock()
   797  	defer asw.Unlock()
   798  
   799  	volumeObj, volumeExists := asw.attachedVolumes[volumeName]
   800  	if !volumeExists {
   801  		return fmt.Errorf(
   802  			"no volume with the name %q exists in the list of attached volumes",
   803  			volumeName)
   804  	}
   805  
   806  	volumeObj.deviceMountState = deviceMountState
   807  	volumeObj.deviceMountPath = deviceMountPath
   808  	if devicePath != "" {
   809  		volumeObj.devicePath = devicePath
   810  	}
   811  	if utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
   812  		if seLinuxMountContext != "" {
   813  			volumeObj.seLinuxMountContext = &seLinuxMountContext
   814  		}
   815  	}
   816  
   817  	asw.attachedVolumes[volumeName] = volumeObj
   818  	return nil
   819  }
   820  
   821  func (asw *actualStateOfWorld) InitializeClaimSize(logger klog.Logger, volumeName v1.UniqueVolumeName, claimSize *resource.Quantity) {
   822  	asw.Lock()
   823  	defer asw.Unlock()
   824  
   825  	volumeObj, ok := asw.attachedVolumes[volumeName]
   826  	// only set volume claim size if claimStatusSize is zero
   827  	// this can happen when volume was rebuilt after kubelet startup
   828  	if ok && volumeObj.persistentVolumeSize == nil {
   829  		volumeObj.persistentVolumeSize = claimSize
   830  		asw.attachedVolumes[volumeName] = volumeObj
   831  	}
   832  }
   833  
   834  func (asw *actualStateOfWorld) GetClaimSize(volumeName v1.UniqueVolumeName) *resource.Quantity {
   835  	asw.RLock()
   836  	defer asw.RUnlock()
   837  
   838  	volumeObj, ok := asw.attachedVolumes[volumeName]
   839  	if ok {
   840  		return volumeObj.persistentVolumeSize
   841  	}
   842  	return nil
   843  }
   844  
   845  func (asw *actualStateOfWorld) DeletePodFromVolume(
   846  	podName volumetypes.UniquePodName, volumeName v1.UniqueVolumeName) error {
   847  	asw.Lock()
   848  	defer asw.Unlock()
   849  
   850  	volumeObj, volumeExists := asw.attachedVolumes[volumeName]
   851  	if !volumeExists {
   852  		return fmt.Errorf(
   853  			"no volume with the name %q exists in the list of attached volumes",
   854  			volumeName)
   855  	}
   856  
   857  	_, podExists := volumeObj.mountedPods[podName]
   858  	if podExists {
   859  		delete(asw.attachedVolumes[volumeName].mountedPods, podName)
   860  	}
   861  
   862  	// if there were reconstructed volumes, we should remove them
   863  	_, podExists = asw.foundDuringReconstruction[volumeName]
   864  	if podExists {
   865  		delete(asw.foundDuringReconstruction[volumeName], podName)
   866  	}
   867  
   868  	return nil
   869  }
   870  
   871  func (asw *actualStateOfWorld) DeleteVolume(volumeName v1.UniqueVolumeName) error {
   872  	asw.Lock()
   873  	defer asw.Unlock()
   874  
   875  	volumeObj, volumeExists := asw.attachedVolumes[volumeName]
   876  	if !volumeExists {
   877  		return nil
   878  	}
   879  
   880  	if len(volumeObj.mountedPods) != 0 {
   881  		return fmt.Errorf(
   882  			"failed to DeleteVolume %q, it still has %v mountedPods",
   883  			volumeName,
   884  			len(volumeObj.mountedPods))
   885  	}
   886  
   887  	delete(asw.attachedVolumes, volumeName)
   888  	delete(asw.foundDuringReconstruction, volumeName)
   889  	return nil
   890  }
   891  
   892  func (asw *actualStateOfWorld) PodExistsInVolume(podName volumetypes.UniquePodName, volumeName v1.UniqueVolumeName, desiredVolumeSize resource.Quantity, seLinuxLabel string) (bool, string, error) {
   893  	asw.RLock()
   894  	defer asw.RUnlock()
   895  
   896  	volumeObj, volumeExists := asw.attachedVolumes[volumeName]
   897  	if !volumeExists {
   898  		return false, "", newVolumeNotAttachedError(volumeName)
   899  	}
   900  
   901  	// The volume exists, check its SELinux context mount option
   902  	if utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
   903  		if volumeObj.seLinuxMountContext != nil && *volumeObj.seLinuxMountContext != seLinuxLabel {
   904  			fullErr := newSELinuxMountMismatchError(volumeName)
   905  			return false, volumeObj.devicePath, fullErr
   906  		}
   907  	}
   908  
   909  	podObj, podExists := volumeObj.mountedPods[podName]
   910  	if podExists {
   911  		// if volume mount was uncertain we should keep trying to mount the volume
   912  		if podObj.volumeMountStateForPod == operationexecutor.VolumeMountUncertain {
   913  			return false, volumeObj.devicePath, nil
   914  		}
   915  		if podObj.remountRequired {
   916  			return true, volumeObj.devicePath, newRemountRequiredError(volumeObj.volumeName, podObj.podName)
   917  		}
   918  		if currentSize, expandVolume := asw.volumeNeedsExpansion(volumeObj, desiredVolumeSize); expandVolume {
   919  			return true, volumeObj.devicePath, newFsResizeRequiredError(volumeObj.volumeName, podObj.podName, currentSize)
   920  		}
   921  	}
   922  
   923  	return podExists, volumeObj.devicePath, nil
   924  }
   925  
   926  func (asw *actualStateOfWorld) volumeNeedsExpansion(volumeObj attachedVolume, desiredVolumeSize resource.Quantity) (resource.Quantity, bool) {
   927  	currentSize := resource.Quantity{}
   928  	if volumeObj.persistentVolumeSize != nil {
   929  		currentSize = volumeObj.persistentVolumeSize.DeepCopy()
   930  	}
   931  	if volumeObj.volumeInUseErrorForExpansion {
   932  		return currentSize, false
   933  	}
   934  	if volumeObj.persistentVolumeSize == nil || desiredVolumeSize.IsZero() {
   935  		return currentSize, false
   936  	}
   937  
   938  	if desiredVolumeSize.Cmp(*volumeObj.persistentVolumeSize) > 0 {
   939  		volumePlugin, err := asw.volumePluginMgr.FindNodeExpandablePluginBySpec(volumeObj.spec)
   940  		if err != nil || volumePlugin == nil {
   941  			// Log and continue processing
   942  			klog.InfoS("PodExistsInVolume failed to find expandable plugin",
   943  				"volume", volumeObj.volumeName,
   944  				"volumeSpecName", volumeObj.spec.Name())
   945  			return currentSize, false
   946  		}
   947  		if volumePlugin.RequiresFSResize() {
   948  			return currentSize, true
   949  		}
   950  	}
   951  	return currentSize, false
   952  }
   953  
   954  func (asw *actualStateOfWorld) PodRemovedFromVolume(
   955  	podName volumetypes.UniquePodName,
   956  	volumeName v1.UniqueVolumeName) bool {
   957  	asw.RLock()
   958  	defer asw.RUnlock()
   959  
   960  	volumeObj, volumeExists := asw.attachedVolumes[volumeName]
   961  	if !volumeExists {
   962  		return true
   963  	}
   964  
   965  	podObj, podExists := volumeObj.mountedPods[podName]
   966  	if podExists {
   967  		// if volume mount was uncertain we should keep trying to unmount the volume
   968  		if podObj.volumeMountStateForPod == operationexecutor.VolumeMountUncertain {
   969  			return false
   970  		}
   971  		if podObj.volumeMountStateForPod == operationexecutor.VolumeMounted {
   972  			return false
   973  		}
   974  	}
   975  	return true
   976  }
   977  
   978  func (asw *actualStateOfWorld) VolumeExistsWithSpecName(podName volumetypes.UniquePodName, volumeSpecName string) bool {
   979  	asw.RLock()
   980  	defer asw.RUnlock()
   981  	for _, volumeObj := range asw.attachedVolumes {
   982  		if podObj, podExists := volumeObj.mountedPods[podName]; podExists {
   983  			if podObj.volumeSpec.Name() == volumeSpecName {
   984  				return true
   985  			}
   986  		}
   987  	}
   988  	return false
   989  }
   990  
   991  func (asw *actualStateOfWorld) VolumeExists(
   992  	volumeName v1.UniqueVolumeName) bool {
   993  	asw.RLock()
   994  	defer asw.RUnlock()
   995  
   996  	_, volumeExists := asw.attachedVolumes[volumeName]
   997  	return volumeExists
   998  }
   999  
  1000  func (asw *actualStateOfWorld) GetMountedVolumes() []MountedVolume {
  1001  	asw.RLock()
  1002  	defer asw.RUnlock()
  1003  	mountedVolume := make([]MountedVolume, 0 /* len */, len(asw.attachedVolumes) /* cap */)
  1004  	for _, volumeObj := range asw.attachedVolumes {
  1005  		for _, podObj := range volumeObj.mountedPods {
  1006  			if podObj.volumeMountStateForPod == operationexecutor.VolumeMounted {
  1007  				mountedVolume = append(
  1008  					mountedVolume,
  1009  					getMountedVolume(&podObj, &volumeObj))
  1010  			}
  1011  		}
  1012  	}
  1013  	return mountedVolume
  1014  }
  1015  
  1016  // GetAllMountedVolumes returns all volumes which could be locally mounted for a pod.
  1017  func (asw *actualStateOfWorld) GetAllMountedVolumes() []MountedVolume {
  1018  	asw.RLock()
  1019  	defer asw.RUnlock()
  1020  	mountedVolume := make([]MountedVolume, 0 /* len */, len(asw.attachedVolumes) /* cap */)
  1021  	for _, volumeObj := range asw.attachedVolumes {
  1022  		for _, podObj := range volumeObj.mountedPods {
  1023  			if podObj.volumeMountStateForPod == operationexecutor.VolumeMounted ||
  1024  				podObj.volumeMountStateForPod == operationexecutor.VolumeMountUncertain {
  1025  				mountedVolume = append(
  1026  					mountedVolume,
  1027  					getMountedVolume(&podObj, &volumeObj))
  1028  			}
  1029  		}
  1030  	}
  1031  
  1032  	return mountedVolume
  1033  }
  1034  
  1035  func (asw *actualStateOfWorld) GetMountedVolumesForPod(
  1036  	podName volumetypes.UniquePodName) []MountedVolume {
  1037  	asw.RLock()
  1038  	defer asw.RUnlock()
  1039  	mountedVolume := make([]MountedVolume, 0 /* len */, len(asw.attachedVolumes) /* cap */)
  1040  	for _, volumeObj := range asw.attachedVolumes {
  1041  		for mountedPodName, podObj := range volumeObj.mountedPods {
  1042  			if mountedPodName == podName && podObj.volumeMountStateForPod == operationexecutor.VolumeMounted {
  1043  				mountedVolume = append(
  1044  					mountedVolume,
  1045  					getMountedVolume(&podObj, &volumeObj))
  1046  			}
  1047  		}
  1048  	}
  1049  
  1050  	return mountedVolume
  1051  }
  1052  
  1053  func (asw *actualStateOfWorld) GetPossiblyMountedVolumesForPod(
  1054  	podName volumetypes.UniquePodName) []MountedVolume {
  1055  	asw.RLock()
  1056  	defer asw.RUnlock()
  1057  	mountedVolume := make([]MountedVolume, 0 /* len */, len(asw.attachedVolumes) /* cap */)
  1058  	for _, volumeObj := range asw.attachedVolumes {
  1059  		for mountedPodName, podObj := range volumeObj.mountedPods {
  1060  			if mountedPodName == podName &&
  1061  				(podObj.volumeMountStateForPod == operationexecutor.VolumeMounted ||
  1062  					podObj.volumeMountStateForPod == operationexecutor.VolumeMountUncertain) {
  1063  				mountedVolume = append(
  1064  					mountedVolume,
  1065  					getMountedVolume(&podObj, &volumeObj))
  1066  			}
  1067  		}
  1068  	}
  1069  
  1070  	return mountedVolume
  1071  }
  1072  
  1073  func (asw *actualStateOfWorld) GetGloballyMountedVolumes() []AttachedVolume {
  1074  	asw.RLock()
  1075  	defer asw.RUnlock()
  1076  	globallyMountedVolumes := make(
  1077  		[]AttachedVolume, 0 /* len */, len(asw.attachedVolumes) /* cap */)
  1078  	for _, volumeObj := range asw.attachedVolumes {
  1079  		if volumeObj.deviceMountState == operationexecutor.DeviceGloballyMounted {
  1080  			globallyMountedVolumes = append(
  1081  				globallyMountedVolumes,
  1082  				asw.newAttachedVolume(&volumeObj))
  1083  		}
  1084  	}
  1085  
  1086  	return globallyMountedVolumes
  1087  }
  1088  
  1089  func (asw *actualStateOfWorld) GetAttachedVolumes() []AttachedVolume {
  1090  	asw.RLock()
  1091  	defer asw.RUnlock()
  1092  	allAttachedVolumes := make(
  1093  		[]AttachedVolume, 0 /* len */, len(asw.attachedVolumes) /* cap */)
  1094  	for _, volumeObj := range asw.attachedVolumes {
  1095  		allAttachedVolumes = append(
  1096  			allAttachedVolumes,
  1097  			asw.newAttachedVolume(&volumeObj))
  1098  	}
  1099  
  1100  	return allAttachedVolumes
  1101  }
  1102  
  1103  func (asw *actualStateOfWorld) GetUnmountedVolumes() []AttachedVolume {
  1104  	asw.RLock()
  1105  	defer asw.RUnlock()
  1106  	unmountedVolumes := make([]AttachedVolume, 0 /* len */, len(asw.attachedVolumes) /* cap */)
  1107  	for _, volumeObj := range asw.attachedVolumes {
  1108  		if len(volumeObj.mountedPods) == 0 {
  1109  			unmountedVolumes = append(
  1110  				unmountedVolumes,
  1111  				asw.newAttachedVolume(&volumeObj))
  1112  		}
  1113  	}
  1114  
  1115  	return unmountedVolumes
  1116  }
  1117  
  1118  func (asw *actualStateOfWorld) newAttachedVolume(
  1119  	attachedVolume *attachedVolume) AttachedVolume {
  1120  	seLinuxMountContext := ""
  1121  	if utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
  1122  		if attachedVolume.seLinuxMountContext != nil {
  1123  			seLinuxMountContext = *attachedVolume.seLinuxMountContext
  1124  		}
  1125  	}
  1126  	return AttachedVolume{
  1127  		AttachedVolume: operationexecutor.AttachedVolume{
  1128  			VolumeName:          attachedVolume.volumeName,
  1129  			VolumeSpec:          attachedVolume.spec,
  1130  			NodeName:            asw.nodeName,
  1131  			PluginIsAttachable:  attachedVolume.pluginIsAttachable == volumeAttachabilityTrue,
  1132  			DevicePath:          attachedVolume.devicePath,
  1133  			DeviceMountPath:     attachedVolume.deviceMountPath,
  1134  			PluginName:          attachedVolume.pluginName,
  1135  			SELinuxMountContext: seLinuxMountContext},
  1136  		DeviceMountState:    attachedVolume.deviceMountState,
  1137  		SELinuxMountContext: seLinuxMountContext,
  1138  	}
  1139  }
  1140  
  1141  // Compile-time check to ensure volumeNotAttachedError implements the error interface
  1142  var _ error = volumeNotAttachedError{}
  1143  
  1144  // volumeNotAttachedError is an error returned when PodExistsInVolume() fails to
  1145  // find specified volume in the list of attached volumes.
  1146  type volumeNotAttachedError struct {
  1147  	volumeName v1.UniqueVolumeName
  1148  }
  1149  
  1150  func (err volumeNotAttachedError) Error() string {
  1151  	return fmt.Sprintf(
  1152  		"volumeName %q does not exist in the list of attached volumes",
  1153  		err.volumeName)
  1154  }
  1155  
  1156  func newVolumeNotAttachedError(volumeName v1.UniqueVolumeName) error {
  1157  	return volumeNotAttachedError{
  1158  		volumeName: volumeName,
  1159  	}
  1160  }
  1161  
  1162  // Compile-time check to ensure remountRequiredError implements the error interface
  1163  var _ error = remountRequiredError{}
  1164  
  1165  // remountRequiredError is an error returned when PodExistsInVolume() found
  1166  // volume/pod attached/mounted but remountRequired was true, indicating the
  1167  // given volume should be remounted to the pod to reflect changes in the
  1168  // referencing pod.
  1169  type remountRequiredError struct {
  1170  	volumeName v1.UniqueVolumeName
  1171  	podName    volumetypes.UniquePodName
  1172  }
  1173  
  1174  func (err remountRequiredError) Error() string {
  1175  	return fmt.Sprintf(
  1176  		"volumeName %q is mounted to %q but should be remounted",
  1177  		err.volumeName, err.podName)
  1178  }
  1179  
  1180  func newRemountRequiredError(
  1181  	volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName) error {
  1182  	return remountRequiredError{
  1183  		volumeName: volumeName,
  1184  		podName:    podName,
  1185  	}
  1186  }
  1187  
  1188  // fsResizeRequiredError is an error returned when PodExistsInVolume() found
  1189  // volume/pod attached/mounted but fsResizeRequired was true, indicating the
  1190  // given volume receives an resize request after attached/mounted.
  1191  type FsResizeRequiredError struct {
  1192  	CurrentSize resource.Quantity
  1193  	volumeName  v1.UniqueVolumeName
  1194  	podName     volumetypes.UniquePodName
  1195  }
  1196  
  1197  func (err FsResizeRequiredError) Error() string {
  1198  	return fmt.Sprintf(
  1199  		"volumeName %q mounted to %q needs to resize file system",
  1200  		err.volumeName, err.podName)
  1201  }
  1202  
  1203  func newFsResizeRequiredError(
  1204  	volumeName v1.UniqueVolumeName, podName volumetypes.UniquePodName, currentSize resource.Quantity) error {
  1205  	return FsResizeRequiredError{
  1206  		CurrentSize: currentSize,
  1207  		volumeName:  volumeName,
  1208  		podName:     podName,
  1209  	}
  1210  }
  1211  
  1212  // IsFSResizeRequiredError returns true if the specified error is a
  1213  // fsResizeRequiredError.
  1214  func IsFSResizeRequiredError(err error) bool {
  1215  	_, ok := err.(FsResizeRequiredError)
  1216  	return ok
  1217  }
  1218  
  1219  // getMountedVolume constructs and returns a MountedVolume object from the given
  1220  // mountedPod and attachedVolume objects.
  1221  func getMountedVolume(
  1222  	mountedPod *mountedPod, attachedVolume *attachedVolume) MountedVolume {
  1223  	seLinuxMountContext := ""
  1224  	if attachedVolume.seLinuxMountContext != nil {
  1225  		seLinuxMountContext = *attachedVolume.seLinuxMountContext
  1226  	}
  1227  	return MountedVolume{
  1228  		MountedVolume: operationexecutor.MountedVolume{
  1229  			PodName:             mountedPod.podName,
  1230  			VolumeName:          attachedVolume.volumeName,
  1231  			InnerVolumeSpecName: mountedPod.volumeSpec.Name(),
  1232  			OuterVolumeSpecName: mountedPod.outerVolumeSpecName,
  1233  			PluginName:          attachedVolume.pluginName,
  1234  			PodUID:              mountedPod.podUID,
  1235  			Mounter:             mountedPod.mounter,
  1236  			BlockVolumeMapper:   mountedPod.blockVolumeMapper,
  1237  			VolumeGidValue:      mountedPod.volumeGidValue,
  1238  			VolumeSpec:          mountedPod.volumeSpec,
  1239  			DeviceMountPath:     attachedVolume.deviceMountPath,
  1240  			SELinuxMountContext: seLinuxMountContext}}
  1241  
  1242  }
  1243  
  1244  // seLinuxMountMismatchError is an error returned when PodExistsInVolume() found
  1245  // a volume mounted with a different SELinux label than expected.
  1246  type seLinuxMountMismatchError struct {
  1247  	volumeName v1.UniqueVolumeName
  1248  }
  1249  
  1250  func (err seLinuxMountMismatchError) Error() string {
  1251  	return fmt.Sprintf(
  1252  		"waiting for unmount of volume %q, because it is already mounted to a different pod with a different SELinux label",
  1253  		err.volumeName)
  1254  }
  1255  
  1256  func newSELinuxMountMismatchError(volumeName v1.UniqueVolumeName) error {
  1257  	return seLinuxMountMismatchError{
  1258  		volumeName: volumeName,
  1259  	}
  1260  }
  1261  
  1262  // IsSELinuxMountMismatchError returns true if the specified error is a
  1263  // seLinuxMountMismatchError.
  1264  func IsSELinuxMountMismatchError(err error) bool {
  1265  	_, ok := err.(seLinuxMountMismatchError)
  1266  	return ok
  1267  }