mirror of
https://github.com/vmware-tanzu/velero.git
synced 2026-09-20 15:04:17 +00:00
issue 9343: include PV topology to data mover pod affinities
Signed-off-by: Lyndon-Li <lyonghui@vmware.com>
This commit is contained in:
+17
-22
@@ -230,14 +230,9 @@ func CollectPodLogs(ctx context.Context, podGetter corev1client.CoreV1Interface,
|
||||
return nil
|
||||
}
|
||||
|
||||
func ToSystemAffinity(loadAffinities []*LoadAffinity) *corev1api.Affinity {
|
||||
if len(loadAffinities) == 0 {
|
||||
return nil
|
||||
}
|
||||
nodeSelectorTermList := make([]corev1api.NodeSelectorTerm, 0)
|
||||
|
||||
for _, loadAffinity := range loadAffinities {
|
||||
requirements := []corev1api.NodeSelectorRequirement{}
|
||||
func ToSystemAffinity(loadAffinity *LoadAffinity, volumeTopolpogy *corev1api.NodeSelector) *corev1api.Affinity {
|
||||
requirements := []corev1api.NodeSelectorRequirement{}
|
||||
if loadAffinity != nil {
|
||||
for k, v := range loadAffinity.NodeSelector.MatchLabels {
|
||||
requirements = append(requirements, corev1api.NodeSelectorRequirement{
|
||||
Key: k,
|
||||
@@ -253,25 +248,25 @@ func ToSystemAffinity(loadAffinities []*LoadAffinity) *corev1api.Affinity {
|
||||
Operator: corev1api.NodeSelectorOperator(exp.Operator),
|
||||
})
|
||||
}
|
||||
|
||||
nodeSelectorTermList = append(
|
||||
nodeSelectorTermList,
|
||||
corev1api.NodeSelectorTerm{
|
||||
MatchExpressions: requirements,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
if len(nodeSelectorTermList) > 0 {
|
||||
result := new(corev1api.Affinity)
|
||||
result.NodeAffinity = new(corev1api.NodeAffinity)
|
||||
result.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution = new(corev1api.NodeSelector)
|
||||
result.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms = nodeSelectorTermList
|
||||
result := new(corev1api.Affinity)
|
||||
result.NodeAffinity = new(corev1api.NodeAffinity)
|
||||
result.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution = new(corev1api.NodeSelector)
|
||||
|
||||
return result
|
||||
if volumeTopolpogy != nil {
|
||||
result.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms = append(result.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms, volumeTopolpogy.NodeSelectorTerms...)
|
||||
} else if len(requirements) > 0 {
|
||||
result.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms = make([]corev1api.NodeSelectorTerm, 1)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
for i := range result.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms {
|
||||
result.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[i].MatchExpressions = append(result.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[i].MatchExpressions, requirements...)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func DiagnosePod(pod *corev1api.Pod, events *corev1api.EventList) string {
|
||||
|
||||
+255
-39
@@ -747,24 +747,23 @@ func TestCollectPodLogs(t *testing.T) {
|
||||
func TestToSystemAffinity(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
loadAffinities []*LoadAffinity
|
||||
loadAffinity *LoadAffinity
|
||||
volumeTopology *corev1api.NodeSelector
|
||||
expected *corev1api.Affinity
|
||||
}{
|
||||
{
|
||||
name: "loadAffinity is nil",
|
||||
},
|
||||
{
|
||||
name: "loadAffinity is empty",
|
||||
loadAffinities: []*LoadAffinity{},
|
||||
name: "loadAffinity is empty",
|
||||
loadAffinity: &LoadAffinity{},
|
||||
},
|
||||
{
|
||||
name: "with match label",
|
||||
loadAffinities: []*LoadAffinity{
|
||||
{
|
||||
NodeSelector: metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"key-1": "value-1",
|
||||
},
|
||||
loadAffinity: &LoadAffinity{
|
||||
NodeSelector: metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"key-1": "value-1",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -788,23 +787,21 @@ func TestToSystemAffinity(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "with match expression",
|
||||
loadAffinities: []*LoadAffinity{
|
||||
{
|
||||
NodeSelector: metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"key-2": "value-2",
|
||||
loadAffinity: &LoadAffinity{
|
||||
NodeSelector: metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"key-2": "value-2",
|
||||
},
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
Key: "key-3",
|
||||
Values: []string{"value-3-1", "value-3-2"},
|
||||
Operator: metav1.LabelSelectorOpNotIn,
|
||||
},
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
Key: "key-3",
|
||||
Values: []string{"value-3-1", "value-3-2"},
|
||||
Operator: metav1.LabelSelectorOpNotIn,
|
||||
},
|
||||
{
|
||||
Key: "key-4",
|
||||
Values: []string{"value-4-1", "value-4-2", "value-4-3"},
|
||||
Operator: metav1.LabelSelectorOpDoesNotExist,
|
||||
},
|
||||
{
|
||||
Key: "key-4",
|
||||
Values: []string{"value-4-1", "value-4-2", "value-4-3"},
|
||||
Operator: metav1.LabelSelectorOpDoesNotExist,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -838,19 +835,49 @@ func TestToSystemAffinity(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple load affinities",
|
||||
loadAffinities: []*LoadAffinity{
|
||||
{
|
||||
NodeSelector: metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"key-1": "value-1",
|
||||
name: "with olume topology",
|
||||
volumeTopology: &corev1api.NodeSelector{
|
||||
NodeSelectorTerms: []corev1api.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []corev1api.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "key-5",
|
||||
Values: []string{"value-5-1", "value-5-2", "value-5-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
{
|
||||
Key: "key-6",
|
||||
Values: []string{"value-5-1", "value-5-2", "value-5-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
NodeSelector: metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"key-2": "value-2",
|
||||
{
|
||||
MatchExpressions: []corev1api.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "key-7",
|
||||
Values: []string{"value-7-1", "value-7-2", "value-7-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
{
|
||||
Key: "key-8",
|
||||
Values: []string{"value-8-1", "value-8-2", "value-8-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
MatchFields: []corev1api.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "key-9",
|
||||
Values: []string{"value-9-1", "value-9-2", "value-9-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
{
|
||||
Key: "key-a",
|
||||
Values: []string{"value-a-1", "value-a-2", "value-a-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -862,10 +889,177 @@ func TestToSystemAffinity(t *testing.T) {
|
||||
{
|
||||
MatchExpressions: []corev1api.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "key-1",
|
||||
Values: []string{"value-1"},
|
||||
Key: "key-5",
|
||||
Values: []string{"value-5-1", "value-5-2", "value-5-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
{
|
||||
Key: "key-6",
|
||||
Values: []string{"value-5-1", "value-5-2", "value-5-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
MatchExpressions: []corev1api.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "key-7",
|
||||
Values: []string{"value-7-1", "value-7-2", "value-7-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
{
|
||||
Key: "key-8",
|
||||
Values: []string{"value-8-1", "value-8-2", "value-8-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
MatchFields: []corev1api.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "key-9",
|
||||
Values: []string{"value-9-1", "value-9-2", "value-9-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
{
|
||||
Key: "key-a",
|
||||
Values: []string{"value-a-1", "value-a-2", "value-a-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with match expression and volume topology",
|
||||
loadAffinity: &LoadAffinity{
|
||||
NodeSelector: metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"key-2": "value-2",
|
||||
},
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
Key: "key-3",
|
||||
Values: []string{"value-3-1", "value-3-2"},
|
||||
Operator: metav1.LabelSelectorOpNotIn,
|
||||
},
|
||||
{
|
||||
Key: "key-4",
|
||||
Values: []string{"value-4-1", "value-4-2", "value-4-3"},
|
||||
Operator: metav1.LabelSelectorOpDoesNotExist,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
volumeTopology: &corev1api.NodeSelector{
|
||||
NodeSelectorTerms: []corev1api.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []corev1api.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "key-5",
|
||||
Values: []string{"value-5-1", "value-5-2", "value-5-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
{
|
||||
Key: "key-6",
|
||||
Values: []string{"value-5-1", "value-5-2", "value-5-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
MatchExpressions: []corev1api.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "key-7",
|
||||
Values: []string{"value-7-1", "value-7-2", "value-7-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
{
|
||||
Key: "key-8",
|
||||
Values: []string{"value-8-1", "value-8-2", "value-8-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
MatchFields: []corev1api.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "key-9",
|
||||
Values: []string{"value-9-1", "value-9-2", "value-9-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
{
|
||||
Key: "key-a",
|
||||
Values: []string{"value-a-1", "value-a-2", "value-a-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: &corev1api.Affinity{
|
||||
NodeAffinity: &corev1api.NodeAffinity{
|
||||
RequiredDuringSchedulingIgnoredDuringExecution: &corev1api.NodeSelector{
|
||||
NodeSelectorTerms: []corev1api.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []corev1api.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "key-5",
|
||||
Values: []string{"value-5-1", "value-5-2", "value-5-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
{
|
||||
Key: "key-6",
|
||||
Values: []string{"value-5-1", "value-5-2", "value-5-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
{
|
||||
Key: "key-2",
|
||||
Values: []string{"value-2"},
|
||||
Operator: corev1api.NodeSelectorOpIn,
|
||||
},
|
||||
{
|
||||
Key: "key-3",
|
||||
Values: []string{"value-3-1", "value-3-2"},
|
||||
Operator: corev1api.NodeSelectorOpNotIn,
|
||||
},
|
||||
{
|
||||
Key: "key-4",
|
||||
Values: []string{"value-4-1", "value-4-2", "value-4-3"},
|
||||
Operator: corev1api.NodeSelectorOpDoesNotExist,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
MatchExpressions: []corev1api.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "key-7",
|
||||
Values: []string{"value-7-1", "value-7-2", "value-7-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
{
|
||||
Key: "key-8",
|
||||
Values: []string{"value-8-1", "value-8-2", "value-8-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
{
|
||||
Key: "key-2",
|
||||
Values: []string{"value-2"},
|
||||
Operator: corev1api.NodeSelectorOpIn,
|
||||
},
|
||||
{
|
||||
Key: "key-3",
|
||||
Values: []string{"value-3-1", "value-3-2"},
|
||||
Operator: corev1api.NodeSelectorOpNotIn,
|
||||
},
|
||||
{
|
||||
Key: "key-4",
|
||||
Values: []string{"value-4-1", "value-4-2", "value-4-3"},
|
||||
Operator: corev1api.NodeSelectorOpDoesNotExist,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -875,6 +1069,28 @@ func TestToSystemAffinity(t *testing.T) {
|
||||
Values: []string{"value-2"},
|
||||
Operator: corev1api.NodeSelectorOpIn,
|
||||
},
|
||||
{
|
||||
Key: "key-3",
|
||||
Values: []string{"value-3-1", "value-3-2"},
|
||||
Operator: corev1api.NodeSelectorOpNotIn,
|
||||
},
|
||||
{
|
||||
Key: "key-4",
|
||||
Values: []string{"value-4-1", "value-4-2", "value-4-3"},
|
||||
Operator: corev1api.NodeSelectorOpDoesNotExist,
|
||||
},
|
||||
},
|
||||
MatchFields: []corev1api.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "key-9",
|
||||
Values: []string{"value-9-1", "value-9-2", "value-9-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
{
|
||||
Key: "key-a",
|
||||
Values: []string{"value-a-1", "value-a-2", "value-a-3"},
|
||||
Operator: corev1api.NodeSelectorOpGt,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -886,7 +1102,7 @@ func TestToSystemAffinity(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
affinity := ToSystemAffinity(test.loadAffinities)
|
||||
affinity := ToSystemAffinity(test.loadAffinity, test.volumeTopology)
|
||||
assert.True(t, reflect.DeepEqual(affinity, test.expected))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -580,3 +580,25 @@ func GetPVAttachedNodes(ctx context.Context, pv string, storageClient storagev1.
|
||||
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func GetVolumeTopology(ctx context.Context, volumeClient corev1client.CoreV1Interface, storageClient storagev1.StorageV1Interface, pvName string, scName string) (*corev1api.NodeSelector, error) {
|
||||
sc, err := storageClient.StorageClasses().Get(ctx, scName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error getting storage class %s", scName)
|
||||
}
|
||||
|
||||
if sc.VolumeBindingMode == nil || *sc.VolumeBindingMode != storagev1api.VolumeBindingWaitForFirstConsumer {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
pv, err := volumeClient.PersistentVolumes().Get(ctx, pvName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error getting PV %s", pvName)
|
||||
}
|
||||
|
||||
if pv.Spec.NodeAffinity == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return pv.Spec.NodeAffinity.Required, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user