@@ -383,6 +383,15 @@ type Device struct {
383
383
// +listType=atomic
384
384
// +featureGate=DRADeviceBindingConditions,DRAResourceClaimDeviceStatus
385
385
BindingFailureConditions []string `json:"bindingFailureConditions,omitempty" protobuf:"bytes,11,rep,name=bindingFailureConditions"`
386
+
387
+ // AllowMultipleAllocations marks whether the device is allowed to be allocated to multiple DeviceRequests.
388
+ //
389
+ // If AllowMultipleAllocations is set to true, the device can be allocated more than once,
390
+ // and all of its capacity is consumable, regardless of whether the requestPolicy is defined or not.
391
+ //
392
+ // +optional
393
+ // +featureGate=DRAConsumableCapacity
394
+ AllowMultipleAllocations * bool `json:"allowMultipleAllocations,omitempty" protobuf:"bytes,12,opt,name=allowMultipleAllocations"`
386
395
}
387
396
388
397
// DeviceCounterConsumption defines a set of counters that
@@ -407,13 +416,28 @@ type DeviceCounterConsumption struct {
407
416
408
417
// DeviceCapacity describes a quantity associated with a device.
409
418
type DeviceCapacity struct {
410
- // Value defines how much of a certain device capacity is available.
419
+ // Value defines how much of a certain capacity that device has.
420
+ //
421
+ // This field reflects the fixed total capacity and does not change.
422
+ // The consumed amount is tracked separately by scheduler
423
+ // and does not affect this value.
411
424
//
412
425
// +required
413
426
Value resource.Quantity `json:"value" protobuf:"bytes,1,rep,name=value"`
414
427
415
- // potential future addition: fields which define how to "consume"
416
- // capacity (= share a single device between different consumers).
428
+ // RequestPolicy defines how this DeviceCapacity must be consumed
429
+ // when the device is allowed to be shared by multiple allocations.
430
+ //
431
+ // The Device must have allowMultipleAllocations set to true in order to set a requestPolicy.
432
+ //
433
+ // If unset, capacity requests are unconstrained:
434
+ // requests can consume any amount of capacity, as long as the total consumed
435
+ // across all allocations does not exceed the device's defined capacity.
436
+ // If request is also unset, default is the full capacity value.
437
+ //
438
+ // +optional
439
+ // +featureGate=DRAConsumableCapacity
440
+ RequestPolicy * CapacityRequestPolicy `json:"requestPolicy,omitempty" protobuf:"bytes,2,opt,name=requestPolicy"`
417
441
}
418
442
419
443
// Counter describes a quantity associated with a device.
@@ -424,6 +448,86 @@ type Counter struct {
424
448
Value resource.Quantity `json:"value" protobuf:"bytes,1,rep,name=value"`
425
449
}
426
450
451
+ // CapacityRequestPolicy defines how requests consume device capacity.
452
+ //
453
+ // Must not set more than one ValidRequestValues.
454
+ type CapacityRequestPolicy struct {
455
+ // Default specifies how much of this capacity is consumed by a request
456
+ // that does not contain an entry for it in DeviceRequest's Capacity.
457
+ //
458
+ // +optional
459
+ Default * resource.Quantity `json:"default" protobuf:"bytes,1,opt,name=default"`
460
+
461
+ // ValidValues defines a set of acceptable quantity values in consuming requests.
462
+ //
463
+ // Must not contain more than 10 entries.
464
+ // Must be sorted in ascending order.
465
+ //
466
+ // If this field is set,
467
+ // Default must be defined and it must be included in ValidValues list.
468
+ //
469
+ // If the requested amount does not match any valid value but smaller than some valid values,
470
+ // the scheduler calculates the smallest valid value that is greater than or equal to the request.
471
+ // That is: min(ceil(requestedValue) ∈ validValues), where requestedValue ≤ max(validValues).
472
+ //
473
+ // If the requested amount exceeds all valid values, the request violates the policy,
474
+ // and this device cannot be allocated.
475
+ //
476
+ // +optional
477
+ // +listType=atomic
478
+ // +oneOf=ValidRequestValues
479
+ ValidValues []resource.Quantity `json:"validValues,omitempty" protobuf:"bytes,3,opt,name=validValues"`
480
+
481
+ // ValidRange defines an acceptable quantity value range in consuming requests.
482
+ //
483
+ // If this field is set,
484
+ // Default must be defined and it must fall within the defined ValidRange.
485
+ //
486
+ // If the requested amount does not fall within the defined range, the request violates the policy,
487
+ // and this device cannot be allocated.
488
+ //
489
+ // If the request doesn't contain this capacity entry, Default value is used.
490
+ //
491
+ // +optional
492
+ // +oneOf=ValidRequestValues
493
+ ValidRange * CapacityRequestPolicyRange `json:"validRange,omitempty" protobuf:"bytes,4,opt,name=validRange"`
494
+ }
495
+
496
+ // CapacityRequestPolicyRange defines a valid range for consumable capacity values.
497
+ //
498
+ // - If the requested amount is less than Min, it is rounded up to the Min value.
499
+ // - If Step is set and the requested amount is between Min and Max but not aligned with Step,
500
+ // it will be rounded up to the next value equal to Min + (n * Step).
501
+ // - If Step is not set, the requested amount is used as-is if it falls within the range Min to Max (if set).
502
+ // - If the requested or rounded amount exceeds Max (if set), the request does not satisfy the policy,
503
+ // and the device cannot be allocated.
504
+ type CapacityRequestPolicyRange struct {
505
+ // Min specifies the minimum capacity allowed for a consumption request.
506
+ //
507
+ // Min must be greater than or equal to zero,
508
+ // and less than or equal to the capacity value.
509
+ // requestPolicy.default must be more than or equal to the minimum.
510
+ //
511
+ // +required
512
+ Min * resource.Quantity `json:"min,omitempty" protobuf:"bytes,1,opt,name=min"`
513
+
514
+ // Max defines the upper limit for capacity that can be requested.
515
+ //
516
+ // Max must be less than or equal to the capacity value.
517
+ // Min and requestPolicy.default must be less than or equal to the maximum.
518
+ //
519
+ // +optional
520
+ Max * resource.Quantity `json:"max,omitempty" protobuf:"bytes,2,opt,name=max"`
521
+
522
+ // Step defines the step size between valid capacity amounts within the range.
523
+ //
524
+ // Max (if set) and requestPolicy.default must be a multiple of Step.
525
+ // Min + Step must be less than or equal to the capacity value.
526
+ //
527
+ // +optional
528
+ Step * resource.Quantity `json:"step,omitempty" protobuf:"bytes,3,opt,name=step"`
529
+ }
530
+
427
531
// Limit for the sum of the number of entries in both attributes and capacity.
428
532
const ResourceSliceMaxAttributesAndCapacitiesPerDevice = 32
429
533
@@ -797,6 +901,23 @@ type ExactDeviceRequest struct {
797
901
// +listType=atomic
798
902
// +featureGate=DRADeviceTaints
799
903
Tolerations []DeviceToleration `json:"tolerations,omitempty" protobuf:"bytes,6,opt,name=tolerations"`
904
+
905
+ // Capacity define resource requirements against each capacity.
906
+ //
907
+ // If this field is unset and the device supports multiple allocations,
908
+ // the default value will be applied to each capacity according to requestPolicy.
909
+ // For the capacity that has no requestPolicy, default is the full capacity value.
910
+ //
911
+ // Applies to each device allocation.
912
+ // If Count > 1,
913
+ // the request fails if there aren't enough devices that meet the requirements.
914
+ // If AllocationMode is set to All,
915
+ // the request fails if there are devices that otherwise match the request,
916
+ // and have this capacity, with a value >= the requested amount, but which cannot be allocated to this request.
917
+ //
918
+ // +optional
919
+ // +featureGate=DRAConsumableCapacity
920
+ Capacity * CapacityRequirements `json:"capacity,omitempty" protobuf:"bytes,7,opt,name=capacity"`
800
921
}
801
922
802
923
// DeviceSubRequest describes a request for device provided in the
@@ -891,6 +1012,52 @@ type DeviceSubRequest struct {
891
1012
// +listType=atomic
892
1013
// +featureGate=DRADeviceTaints
893
1014
Tolerations []DeviceToleration `json:"tolerations,omitempty" protobuf:"bytes,6,opt,name=tolerations"`
1015
+
1016
+ // Capacity define resource requirements against each capacity.
1017
+ //
1018
+ // If this field is unset and the device supports multiple allocations,
1019
+ // the default value will be applied to each capacity according to requestPolicy.
1020
+ // For the capacity that has no requestPolicy, default is the full capacity value.
1021
+ //
1022
+ // Applies to each device allocation.
1023
+ // If Count > 1,
1024
+ // the request fails if there aren't enough devices that meet the requirements.
1025
+ // If AllocationMode is set to All,
1026
+ // the request fails if there are devices that otherwise match the request,
1027
+ // and have this capacity, with a value >= the requested amount, but which cannot be allocated to this request.
1028
+ //
1029
+ // +optional
1030
+ // +featureGate=DRAConsumableCapacity
1031
+ Capacity * CapacityRequirements `json:"capacity,omitempty" protobuf:"bytes,7,opt,name=capacity"`
1032
+ }
1033
+
1034
+ // CapacityRequirements defines the capacity requirements for a specific device request.
1035
+ type CapacityRequirements struct {
1036
+ // Requests represent individual device resource requests for distinct resources,
1037
+ // all of which must be provided by the device.
1038
+ //
1039
+ // This value is used as an additional filtering condition against the available capacity on the device.
1040
+ // This is semantically equivalent to a CEL selector with
1041
+ // `device.capacity[<domain>].<name>.compareTo(quantity(<request quantity>)) >= 0`.
1042
+ // For example, device.capacity['test-driver.cdi.k8s.io'].counters.compareTo(quantity('2')) >= 0.
1043
+ //
1044
+ // When a requestPolicy is defined, the requested amount is adjusted upward
1045
+ // to the nearest valid value based on the policy.
1046
+ // If the requested amount cannot be adjusted to a valid value—because it exceeds what the requestPolicy allows—
1047
+ // the device is considered ineligible for allocation.
1048
+ //
1049
+ // For any capacity that is not explicitly requested:
1050
+ // - If no requestPolicy is set, the default consumed capacity is equal to the full device capacity
1051
+ // (i.e., the whole device is claimed).
1052
+ // - If a requestPolicy is set, the default consumed capacity is determined according to that policy.
1053
+ //
1054
+ // If the device allows multiple allocation,
1055
+ // the aggregated amount across all requests must not exceed the capacity value.
1056
+ // The consumed capacity, which may be adjusted based on the requestPolicy if defined,
1057
+ // is recorded in the resource claim’s status.devices[*].consumedCapacity field.
1058
+ //
1059
+ // +optional
1060
+ Requests map [QualifiedName ]resource.Quantity `json:"requests,omitempty" protobuf:"bytes,1,rep,name=requests,castkey=QualifiedName"`
894
1061
}
895
1062
896
1063
const (
@@ -930,6 +1097,8 @@ type CELDeviceSelector struct {
930
1097
// (e.g. device.attributes["dra.example.com"] evaluates to an object with all
931
1098
// of the attributes which were prefixed by "dra.example.com".
932
1099
// - capacity (map[string]object): the device's capacities, grouped by prefix.
1100
+ // - allowMultipleAllocations (bool): the allowMultipleAllocations property of the device
1101
+ // (v1.34+ with the DRAConsumableCapacity feature enabled).
933
1102
//
934
1103
// Example: Consider a device with driver="dra.example.com", which exposes
935
1104
// two attributes named "model" and "ext.example.com/family" and which
@@ -1043,6 +1212,22 @@ type DeviceConstraint struct {
1043
1212
// criteria.
1044
1213
//
1045
1214
// MatchExpression string
1215
+
1216
+ // DistinctAttribute requires that all devices in question have this
1217
+ // attribute and that its type and value are unique across those devices.
1218
+ //
1219
+ // This acts as the inverse of MatchAttribute.
1220
+ //
1221
+ // This constraint is used to avoid allocating multiple requests to the same device
1222
+ // by ensuring attribute-level differentiation.
1223
+ //
1224
+ // This is useful for scenarios where resource requests must be fulfilled by separate physical devices.
1225
+ // For example, a container requests two network interfaces that must be allocated from two different physical NICs.
1226
+ //
1227
+ // +optional
1228
+ // +oneOf=ConstraintType
1229
+ // +featureGate=DRAConsumableCapacity
1230
+ DistinctAttribute * FullyQualifiedName `json:"distinctAttribute,omitempty" protobuf:"bytes,3,opt,name=distinctAttribute"`
1046
1231
}
1047
1232
1048
1233
// DeviceClaimConfiguration is used for configuration parameters in DeviceClaim.
@@ -1204,6 +1389,7 @@ type ResourceClaimStatus struct {
1204
1389
// +listMapKey=driver
1205
1390
// +listMapKey=device
1206
1391
// +listMapKey=pool
1392
+ // +listMapKey=shareID
1207
1393
// +featureGate=DRAResourceClaimDeviceStatus
1208
1394
Devices []AllocatedDeviceStatus `json:"devices,omitempty" protobuf:"bytes,4,opt,name=devices"`
1209
1395
}
@@ -1370,6 +1556,28 @@ type DeviceRequestAllocationResult struct {
1370
1556
// +listType=atomic
1371
1557
// +featureGate=DRADeviceBindingConditions,DRAResourceClaimDeviceStatus
1372
1558
BindingFailureConditions []string `json:"bindingFailureConditions,omitempty" protobuf:"bytes,8,rep,name=bindingFailureConditions"`
1559
+
1560
+ // ShareID uniquely identifies an individual allocation share of the device,
1561
+ // used when the device supports multiple simultaneous allocations.
1562
+ // It serves as an additional map key to differentiate concurrent shares
1563
+ // of the same device.
1564
+ //
1565
+ // +optional
1566
+ // +featureGate=DRAConsumableCapacity
1567
+ ShareID * types.UID `json:"shareID,omitempty" protobuf:"bytes,9,opt,name=shareID"`
1568
+
1569
+ // ConsumedCapacity tracks the amount of capacity consumed per device as part of the claim request.
1570
+ // The consumed amount may differ from the requested amount: it is rounded up to the nearest valid
1571
+ // value based on the device’s requestPolicy if applicable (i.e., may not be less than the requested amount).
1572
+ //
1573
+ // The total consumed capacity for each device must not exceed the DeviceCapacity's Value.
1574
+ //
1575
+ // This field is populated only for devices that allow multiple allocations.
1576
+ // All capacity entries are included, even if the consumed amount is zero.
1577
+ //
1578
+ // +optional
1579
+ // +featureGate=DRAConsumableCapacity
1580
+ ConsumedCapacity map [QualifiedName ]resource.Quantity `json:"consumedCapacity,omitempty" protobuf:"bytes,10,rep,name=consumedCapacity"`
1373
1581
}
1374
1582
1375
1583
// DeviceAllocationConfiguration gets embedded in an AllocationResult.
@@ -1574,6 +1782,9 @@ const (
1574
1782
1575
1783
// AllocatedDeviceStatus contains the status of an allocated device, if the
1576
1784
// driver chooses to report it. This may include driver-specific information.
1785
+ //
1786
+ // The combination of Driver, Pool, Device, and ShareID must match the corresponding key
1787
+ // in Status.Allocation.Devices.
1577
1788
type AllocatedDeviceStatus struct {
1578
1789
// Driver specifies the name of the DRA driver whose kubelet
1579
1790
// plugin should be invoked to process the allocation once the claim is
@@ -1600,6 +1811,12 @@ type AllocatedDeviceStatus struct {
1600
1811
// +required
1601
1812
Device string `json:"device" protobuf:"bytes,3,rep,name=device"`
1602
1813
1814
+ // ShareID uniquely identifies an individual allocation share of the device.
1815
+ //
1816
+ // +optional
1817
+ // +featureGate=DRAConsumableCapacity
1818
+ ShareID * string `json:"shareID,omitempty" protobuf:"bytes,7,opt,name=shareID"`
1819
+
1603
1820
// Conditions contains the latest observation of the device's state.
1604
1821
// If the device has been configured according to the class and claim
1605
1822
// config references, the `Ready` condition should be True.
0 commit comments