1
1
/*
2
- Copyright 2021 The Kubernetes Authors.
2
+ Copyright 2021-2025 The Kubernetes Authors.
3
3
4
4
Licensed under the Apache License, Version 2.0 (the "License");
5
5
you may not use this file except in compliance with the License.
@@ -37,6 +37,8 @@ import (
37
37
38
38
vimtypes "github.com/vmware/govmomi/vim25/types"
39
39
"sigs.k8s.io/vsphere-csi-driver/v3/pkg/common/config"
40
+ "sigs.k8s.io/vsphere-csi-driver/v3/pkg/csi/service/common"
41
+ "sigs.k8s.io/vsphere-csi-driver/v3/pkg/csi/service/common/commonco"
40
42
"sigs.k8s.io/vsphere-csi-driver/v3/pkg/csi/service/logger"
41
43
)
42
44
@@ -52,6 +54,12 @@ var networkInfoGVR = schema.GroupVersionResource{
52
54
Resource : "networkinfos" ,
53
55
}
54
56
57
+ var namespaceNetworkInfoGVR = schema.GroupVersionResource {
58
+ Group : "nsx.vmware.com" ,
59
+ Version : "v1alpha1" ,
60
+ Resource : "namespacenetworkinfos" ,
61
+ }
62
+
55
63
const (
56
64
snatIPAnnotation = "ncp/snat_ip"
57
65
// Namespace for system resources.
@@ -113,9 +121,16 @@ func GetTKGVMIP(ctx context.Context, vmOperatorClient client.Client, dc dynamic.
113
121
return "" , err
114
122
}
115
123
124
+ isFileVolumesWithVmServiceVmSupported := commonco .ContainerOrchestratorUtility .IsFSSEnabled (ctx ,
125
+ common .FileVolumesWithVmService )
126
+
116
127
var networkNames []string
117
128
for _ , networkInterface := range virtualMachineInstance .Spec .Network .Interfaces {
118
- networkNames = append (networkNames , networkInterface .Network .Name )
129
+ if ! isFileVolumesWithVmServiceVmSupported {
130
+ networkNames = append (networkNames , networkInterface .Network .Name )
131
+ } else if networkInterface .Network .Name != "" {
132
+ networkNames = append (networkNames , networkInterface .Network .Name )
133
+ }
119
134
}
120
135
log .Debugf ("VirtualMachine %s/%s is configured with networks %v" , vmNamespace , vmName , networkNames )
121
136
@@ -137,8 +152,27 @@ func GetTKGVMIP(ctx context.Context, vmOperatorClient client.Client, dc dynamic.
137
152
}
138
153
}
139
154
if ip == "" {
140
- return "" , fmt .Errorf ("failed to get SNAT IP annotation from VirtualMachine %s/%s" ,
141
- vmNamespace , vmName )
155
+ if ! isFileVolumesWithVmServiceVmSupported {
156
+ return "" , fmt .Errorf ("failed to get SNAT IP annotation from VirtualMachine %s/%s" ,
157
+ vmNamespace , vmName )
158
+ }
159
+ if len (networkNames ) != 0 {
160
+ // If networkNames for VirtualNetwork were found on the VM,
161
+ // then some error happened in getting the SNAT IP from VirtualNetwork CR.
162
+ return "" , fmt .Errorf ("failed to get SNAT IP annotation for VirtualMachine %s/%s " +
163
+ "from VirtualNetwrok" ,
164
+ vmNamespace , vmName )
165
+ }
166
+ // It is likely an NSX setup with VM service VMs.
167
+ // For TKG service VMs, virtual network CR will always be present.
168
+ ip , err = getSnatIpFromNamespaceNetworkInfo (ctx , dc , vmNamespace , vmName )
169
+ if err != nil {
170
+ log .Errorf ("failed to get SNAT IP from NameSpaceNetworkInfo. Err %s" , err )
171
+ return "" , fmt .Errorf ("failed to get SNAT IP from NameSpaceNetworkInfo %s/%s" ,
172
+ vmNamespace , vmName )
173
+ }
174
+ log .Infof ("Obtained SNAT IP %s from NamespaceNetworkInfo for VirtualMachine %s/%s" ,
175
+ ip , vmNamespace , vmName )
142
176
}
143
177
} else if network_provider_type == VDSNetworkProvider {
144
178
ip = virtualMachineInstance .Status .Network .PrimaryIP4
@@ -188,6 +222,35 @@ func GetTKGVMIP(ctx context.Context, vmOperatorClient client.Client, dc dynamic.
188
222
return ip , nil
189
223
}
190
224
225
+ // getSnatIpFromNamespaceNetworkInfo finds VM's SNAT IP from the namespace's default NamespaceNetworkInfo CR.
226
+ func getSnatIpFromNamespaceNetworkInfo (ctx context.Context , dc dynamic.Interface ,
227
+ vmNamespace string , vmName string ) (string , error ) {
228
+ log := logger .GetLogger (ctx )
229
+ log .Infof ("Determining SNAT IP for VM %s in namespace %s via NamespaceNetworkInfo CR" , vmNamespace , vmName )
230
+
231
+ namespaceNetworkInfoInstance , err := dc .Resource (namespaceNetworkInfoGVR ).Namespace (vmNamespace ).Get (ctx ,
232
+ vmNamespace , metav1.GetOptions {})
233
+ if err != nil {
234
+ return "" , err
235
+ }
236
+ log .Debugf ("Got namespaceNetworkInfo instance %s/%s" , vmNamespace , namespaceNetworkInfoInstance .GetName ())
237
+ snatIP , found , err := unstructured .NestedString (namespaceNetworkInfoInstance .Object , "topology" , "defaultEgressIP" )
238
+ if err != nil {
239
+ return "" , fmt .Errorf ("failed to get defaultEgressIP from namespaceNetworkInfo %s/%s with error: %v" ,
240
+ vmNamespace , vmName , err )
241
+
242
+ }
243
+ if ! found {
244
+ return "" , fmt .Errorf ("defaultEgressIP is not found on namespaceNetworkInfo %s/%s" , vmNamespace , vmName )
245
+
246
+ }
247
+ if snatIP == "" {
248
+ return "" , fmt .Errorf ("empty SNAT IP for VM %s on namespaceNetworkInfo instance %s/%s" , vmName , vmNamespace ,
249
+ namespaceNetworkInfoInstance .GetName ())
250
+ }
251
+ return snatIP , nil
252
+ }
253
+
191
254
// GetNetworkProvider reads the network-config configmap in Supervisor cluster.
192
255
// Returns the network provider as NSXT_CONTAINER_PLUGIN for NSX-T, or
193
256
// VSPHERE_NETWORK for VDS. Otherwise, returns an error, if network provider is
0 commit comments