@@ -44,6 +44,18 @@ const (
44
44
configDriveUserdataPath = "/openstack/latest/user_data"
45
45
)
46
46
47
+ var (
48
+ metadataServiceUrlIPv4 = url.URL {
49
+ Scheme : "http" ,
50
+ Host : "169.254.169.254" ,
51
+ Path : "openstack/latest/user_data" ,
52
+ }
53
+ metadataServiceUrlIPv6 = url.URL {
54
+ Scheme : "http" ,
55
+ Path : "openstack/latest/user_data" ,
56
+ }
57
+ )
58
+
47
59
func init () {
48
60
platform .Register (platform.Provider {
49
61
Name : "openstack" ,
@@ -159,86 +171,94 @@ func fetchConfigFromDevice(logger *log.Logger, ctx context.Context, path string)
159
171
return os .ReadFile (filepath .Join (mnt , configDriveUserdataPath ))
160
172
}
161
173
162
- func FindIPv6InterfaceName () (string , error ) {
174
+ // Checks if an IP is an IPv6 address
175
+ func isIPv6Address (ip net.IP ) bool {
176
+ isIPv6 := ip .To4 () == nil
177
+ fmt .Printf ("Verificando se o IP é IPv6: %s, resultado: %v\n " , ip .String (), isIPv6 )
178
+ return isIPv6
179
+ }
180
+
181
+ // Finds the name of an active network interface
182
+ func findZoneID () (string , error ) {
183
+ fmt .Println ("Fetching zone id..." )
163
184
interfaces , err := net .Interfaces ()
164
185
if err != nil {
165
- return "" , err
186
+ return "" , fmt . Errorf ( "error fetching zone id: %v" , err )
166
187
}
167
188
168
189
for _ , iface := range interfaces {
169
- // Check if the interface is up and not loopback
170
- if iface .Flags & net .FlagUp != 0 && iface .Flags & net .FlagLoopback == 0 {
171
- addrs , err := iface .Addrs ()
172
- if err != nil {
173
- continue
174
- }
190
+ fmt .Printf ("Checking interface: %s\n " , iface .Name )
175
191
176
- for _ , addr := range addrs {
177
- // Check if the address is an IPv6
178
- if ipnet , ok := addr .(* net.IPNet ); ok && ipnet .IP .To4 () == nil && ! ipnet .IP .IsLinkLocalUnicast () {
179
- return iface .Name , nil
180
- }
192
+ // Skip inactive or loopback interfaces
193
+ if iface .Flags & net .FlagUp == 0 || iface .Flags & net .FlagLoopback != 0 {
194
+ continue
195
+ }
196
+
197
+ addrs , err := iface .Addrs ()
198
+ if err != nil {
199
+ fmt .Printf ("Error fetching addresses for interface %s: %v\n " , iface .Name , err )
200
+ continue
201
+ }
202
+
203
+ for _ , addr := range addrs {
204
+ if ipnet , ok := addr .(* net.IPNet ); ok && isIPv6Address (ipnet .IP ) {
205
+ fmt .Printf ("Active interface found: %s\n " , iface .Name )
206
+ return iface .Name , nil
181
207
}
182
208
}
183
209
}
184
-
185
- return "" , fmt .Errorf ("no IPv6 interface name found" )
210
+ return "" , fmt .Errorf ("no active IPv6 network interface found" )
186
211
}
187
212
213
+ // Fetches configuration from both IPv4 and IPv6 metadata services
188
214
func fetchConfigFromMetadataService (f * resource.Fetcher ) ([]byte , error ) {
189
-
190
- // Find IPv6 name
191
- iface , err := FindIPv6InterfaceName ()
192
- if err != nil {
193
- return nil , err
194
- }
195
-
196
- // Construct URL
197
- var (
198
- ipv4MetadataServiceUrl = url.URL {
199
- Scheme : "http" ,
200
- Host : "169.254.169.254" ,
201
- Path : "openstack/latest/user_data" ,
202
- }
203
- ipv6MetadataServiceUrl = url.URL {
204
- Scheme : "http" ,
205
- Host : fmt .Sprintf ("[fe80::a9fe:a9fe%%%s]" , url .PathEscape (iface )),
206
- Path : "openstack/latest/user_data" ,
215
+ var ipv4Res , ipv6Res []byte
216
+ var ipv4Err , ipv6Err error
217
+
218
+ // Attempt to fetch from IPv4
219
+ fmt .Println ("Fetching from IPv4 metadata service..." )
220
+ ipv4Res , ipv4Err = f .FetchToBuffer (metadataServiceUrlIPv4 , resource.FetchOptions {})
221
+ if ipv4Err == nil {
222
+ fmt .Println ("Successfully fetched configuration from IPv4." )
223
+
224
+ // If IPv4 succeeds, attempt to fetch from IPv6 as well
225
+ fmt .Println ("Fetching IPv6 address for metadata service..." )
226
+ interfaceName , err := findZoneID ()
227
+ if err != nil {
228
+ fmt .Printf ("IPv6 metadata service lookup failed: %v\n " , err )
229
+ return ipv4Res , fmt .Errorf ("IPv6 lookup failed, returning IPv4 result" )
207
230
}
208
- )
209
231
210
- var resIPv4 , resIPv6 []byte
211
- var errIPv4 , errIPv6 error
232
+ metadataServiceUrlIPv6 .Host = fmt .Sprintf ("fe80::a9fe:a9fe%%%s" , interfaceName )
233
+ fmt .Printf ("Fetching from IPv6 metadata service at %s...\n " , metadataServiceUrlIPv6 .String ())
234
+ ipv6Res , ipv6Err = f .FetchToBuffer (metadataServiceUrlIPv6 , resource.FetchOptions {})
212
235
213
- // Try IPv4 endpoint
214
- resIPv4 , errIPv4 = f .FetchToBuffer (ipv4MetadataServiceUrl , resource.FetchOptions {})
215
- if errIPv4 != nil && errIPv4 != resource .ErrNotFound {
216
- f .Logger .Err ("Failed to fetch config from IPv4: %v" , errIPv4 )
236
+ if ipv6Err != nil {
237
+ fmt .Printf ("IPv6 metadata service failed: %v\n " , ipv6Err )
238
+ return ipv4Res , fmt .Errorf ("IPv4 succeeded, but IPv6 failed: %v" , ipv6Err )
239
+ }
240
+ fmt .Println ("Successfully fetched configuration from both IPv4 and IPv6." )
241
+ return append (ipv4Res , ipv6Res ... ), nil
217
242
}
218
243
219
- // Try IPv6 endpoint
220
- resIPv6 , errIPv6 = f .FetchToBuffer (ipv6MetadataServiceUrl , resource.FetchOptions {})
221
- if errIPv6 != nil && errIPv6 != resource .ErrNotFound {
222
- f .Logger .Err ("Failed to fetch config from IPv6: %v" , errIPv6 )
223
- }
244
+ // If IPv4 fails, attempt to fetch from IPv6
245
+ fmt .Printf ("IPv4 metadata service failed: %v\n " , ipv4Err )
246
+ fmt .Println ("Trying to fetch from IPv6 metadata service..." )
224
247
225
- // If both IPv4 and IPv6 have valid data, combine them
226
- if resIPv4 != nil && resIPv6 != nil {
227
- return append (resIPv4 , resIPv6 ... ), nil
228
- } else if resIPv4 != nil {
229
- return resIPv4 , nil
230
- } else if resIPv6 != nil {
231
- return resIPv6 , nil
248
+ interfaceName , err := findZoneID ()
249
+ if err != nil {
250
+ fmt .Printf ("IPv6 metadata service lookup failed: %v\n " , err )
251
+ return nil , fmt .Errorf ("both IPv4 and IPv6 lookup failed" )
232
252
}
233
253
234
- // If both endpoints fail, return the appropriate error
235
- if errIPv4 != nil {
236
- return nil , errIPv4
237
- }
238
- if errIPv6 != nil {
239
- return nil , errIPv6
254
+ metadataServiceUrlIPv6 . Host = fmt . Sprintf ( "fe80::a9fe:a9fe%%%s" , interfaceName )
255
+ fmt . Printf ( "Fetching from IPv6 metadata service at %s... \n " , metadataServiceUrlIPv6 . String ())
256
+ ipv6Res , ipv6Err = f . FetchToBuffer ( metadataServiceUrlIPv6 , resource. FetchOptions {})
257
+ if ipv6Err != nil {
258
+ fmt . Printf ( "IPv6 metadata service failed: %v \n " , ipv6Err )
259
+ return nil , fmt . Errorf ( "both IPv4 and IPv6 services failed" )
240
260
}
241
261
242
- // If both endpoints return ErrNotFound
243
- return nil , nil
262
+ fmt . Println ( "Successfully fetched configuration from IPv6 metadata service." )
263
+ return ipv6Res , fmt . Errorf ( "IPv4 failed, returning IPv6 result" )
244
264
}
0 commit comments