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