func getVolumeStatusForLogging(volume *v1.PersistentVolume) string { boundByController := v1.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 := v1.HasAnnotation(claim.ObjectMeta, annBindCompleted) boundByController := v1.HasAnnotation(claim.ObjectMeta, annBoundByController) return fmt.Sprintf("phase: %s, bound to: %q, bindCompleted: %v, boundByController: %v", claim.Status.Phase, claim.Spec.VolumeName, bound, boundByController) }
// 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 v1.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 }