...

Source file src/k8s.io/kubernetes/pkg/kubelet/volumemanager/cache/actual_state_of_world.go

Documentation: k8s.io/kubernetes/pkg/kubelet/volumemanager/cache

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

View as plain text