func getVolumeStatusForLogging(volume *v1.PersistentVolume) string {
	boundByController := metav1.HasAnnotation(volume.ObjectMeta, annBoundByController)
	claimName := ""
	if volume.Spec.ClaimRef != nil {
		claimName = fmt.Sprintf("%s/%s (uid: %s)", volume.Spec.ClaimRef.Namespace, volume.Spec.ClaimRef.Name, volume.Spec.ClaimRef.UID)
	}
	return fmt.Sprintf("phase: %s, bound to: %q, boundByController: %v", volume.Status.Phase, claimName, boundByController)
}
func getClaimStatusForLogging(claim *v1.PersistentVolumeClaim) string {
	bound := metav1.HasAnnotation(claim.ObjectMeta, annBindCompleted)
	boundByController := metav1.HasAnnotation(claim.ObjectMeta, annBoundByController)

	return fmt.Sprintf("phase: %s, bound to: %q, bindCompleted: %v, boundByController: %v", claim.Status.Phase, claim.Spec.VolumeName, bound, boundByController)
}
Exemple #3
0
// find returns the nearest PV from the ordered list or nil if a match is not found
func (pvIndex *persistentVolumeOrderedIndex) findByClaim(claim *v1.PersistentVolumeClaim, matchPredicate matchPredicate) (*v1.PersistentVolume, error) {
	// PVs are indexed by their access modes to allow easier searching.  Each
	// index is the string representation of a set of access modes. There is a
	// finite number of possible sets and PVs will only be indexed in one of
	// them (whichever index matches the PV's modes).
	//
	// A request for resources will always specify its desired access modes.
	// Any matching PV must have at least that number of access modes, but it
	// can have more.  For example, a user asks for ReadWriteOnce but a GCEPD
	// is available, which is ReadWriteOnce+ReadOnlyMany.
	//
	// Searches are performed against a set of access modes, so we can attempt
	// not only the exact matching modes but also potential matches (the GCEPD
	// example above).
	allPossibleModes := pvIndex.allPossibleMatchingAccessModes(claim.Spec.AccessModes)

	var smallestVolume *v1.PersistentVolume
	var smallestVolumeSize int64
	requestedQty := claim.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
	requestedSize := requestedQty.Value()
	requestedClass := storageutil.GetClaimStorageClass(claim)

	var selector labels.Selector
	if claim.Spec.Selector != nil {
		internalSelector, err := metav1.LabelSelectorAsSelector(claim.Spec.Selector)
		if err != nil {
			// should be unreachable code due to validation
			return nil, fmt.Errorf("error creating internal label selector for claim: %v: %v", claimToClaimKey(claim), err)
		}
		selector = internalSelector
	}

	for _, modes := range allPossibleModes {
		volumes, err := pvIndex.listByAccessModes(modes)
		if err != nil {
			return nil, err
		}

		// Go through all available volumes with two goals:
		// - find a volume that is either pre-bound by user or dynamically
		//   provisioned for this claim. Because of this we need to loop through
		//   all volumes.
		// - find the smallest matching one if there is no volume pre-bound to
		//   the claim.
		for _, volume := range volumes {
			if isVolumeBoundToClaim(volume, claim) {
				// this claim and volume are pre-bound; return
				// the volume if the size request is satisfied,
				// otherwise continue searching for a match
				volumeQty := volume.Spec.Capacity[v1.ResourceStorage]
				volumeSize := volumeQty.Value()
				if volumeSize < requestedSize {
					continue
				}
				return volume, nil
			}

			// In Alpha dynamic provisioning, we do now want not match claims
			// with existing PVs, findByClaim must find only PVs that are
			// pre-bound to the claim (by dynamic provisioning). TODO: remove in
			// 1.5
			if metav1.HasAnnotation(claim.ObjectMeta, storageutil.AlphaStorageClassAnnotation) {
				continue
			}

			// filter out:
			// - volumes bound to another claim
			// - volumes whose labels don't match the claim's selector, if specified
			// - volumes in Class that is not requested
			if volume.Spec.ClaimRef != nil {
				continue
			} else if selector != nil && !selector.Matches(labels.Set(volume.Labels)) {
				continue
			}
			if storageutil.GetVolumeStorageClass(volume) != requestedClass {
				continue
			}

			volumeQty := volume.Spec.Capacity[v1.ResourceStorage]
			volumeSize := volumeQty.Value()
			if volumeSize >= requestedSize {
				if smallestVolume == nil || smallestVolumeSize > volumeSize {
					smallestVolume = volume
					smallestVolumeSize = volumeSize
				}
			}
		}

		if smallestVolume != nil {
			// Found a matching volume
			return smallestVolume, nil
		}
	}
	return nil, nil
}