Skip to content

Commit

Permalink
debuggers: add some print to debug, will reset this commit later
Browse files Browse the repository at this point in the history
  • Loading branch information
yasminvalim committed Oct 16, 2024
1 parent 6b8a11e commit fa50682
Showing 1 changed file with 80 additions and 60 deletions.
140 changes: 80 additions & 60 deletions internal/providers/openstack/openstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ const (
configDriveUserdataPath = "/openstack/latest/user_data"
)

var (
metadataServiceUrlIPv4 = url.URL{
Scheme: "http",
Host: "169.254.169.254",
Path: "openstack/latest/user_data",
}
metadataServiceUrlIPv6 = url.URL{
Scheme: "http",
Path: "openstack/latest/user_data",
}
)

func init() {
platform.Register(platform.Provider{
Name: "openstack",
Expand Down Expand Up @@ -159,86 +171,94 @@ func fetchConfigFromDevice(logger *log.Logger, ctx context.Context, path string)
return os.ReadFile(filepath.Join(mnt, configDriveUserdataPath))
}

func FindIPv6InterfaceName() (string, error) {
// Checks if an IP is an IPv6 address
func isIPv6Address(ip net.IP) bool {
isIPv6 := ip.To4() == nil
fmt.Printf("Checking if IP is IPv6: %s, result: %v\n", ip.String(), isIPv6)
return isIPv6
}

// Finds the first available IPv6 address on active interfaces
func findIPv6Address() (string, error) {
fmt.Println("Fetching network interfaces...")
interfaces, err := net.Interfaces()
if err != nil {
return "", err
return "", fmt.Errorf("error fetching interfaces: %v", err)
}

for _, iface := range interfaces {
// Check if the interface is up and not loopback
if iface.Flags&net.FlagUp != 0 && iface.Flags&net.FlagLoopback == 0 {
addrs, err := iface.Addrs()
if err != nil {
continue
}
fmt.Printf("Checking interface: %s\n", iface.Name)

for _, addr := range addrs {
// Check if the address is an IPv6
if ipnet, ok := addr.(*net.IPNet); ok && ipnet.IP.To4() == nil && !ipnet.IP.IsLinkLocalUnicast() {
return iface.Name, nil
}
// Skip inactive or loopback interfaces
if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
continue
}

addrs, err := iface.Addrs()
if err != nil {
fmt.Printf("error fetching addresses for interface %s: %v\n", iface.Name, err)
continue
}

for _, addr := range addrs {
if ipnet, ok := addr.(*net.IPNet); ok && isIPv6Address(ipnet.IP) {
ipv6Address := fmt.Sprintf("[%s]", ipnet.IP.String())
fmt.Printf("Found IPv6 address: %s on interface %s\n", ipv6Address, iface.Name)
return ipv6Address, nil
}
}
}

return "", fmt.Errorf("no IPv6 interface name found")
return "", fmt.Errorf("no IPv6 address found")
}

// Fetches configuration from both IPv4 and IPv6 metadata services
func fetchConfigFromMetadataService(f *resource.Fetcher) ([]byte, error) {

// Find IPv6 name
iface, err := FindIPv6InterfaceName()
if err != nil {
return nil, err
}

// Construct URL
var (
ipv4MetadataServiceUrl = url.URL{
Scheme: "http",
Host: "169.254.169.254",
Path: "openstack/latest/user_data",
}
ipv6MetadataServiceUrl = url.URL{
Scheme: "http",
Host: fmt.Sprintf("[fe80::a9fe:a9fe%%%s]", url.PathEscape(iface)),
Path: "openstack/latest/user_data",
var ipv4Res, ipv6Res []byte
var ipv4Err, ipv6Err error

fmt.Println("Fetching from IPv4 metadata service...")
ipv4Res, ipv4Err = f.FetchToBuffer(metadataServiceUrlIPv4, resource.FetchOptions{})
if ipv4Err == nil {
fmt.Println("Successfully fetched configuration from IPv4 metadata service.")

// If IPv4 is successful, attempt to fetch IPv6
fmt.Println("Fetching IPv6 address for metadata service...")
ipv6Address, err := findIPv6Address()
if err != nil {
fmt.Printf("IPv6 metadata service lookup failed: %v\n", err)
return ipv4Res, fmt.Errorf("IPv6 lookup failed, returning only IPv4 result")
}
)

var resIPv4, resIPv6 []byte
var errIPv4, errIPv6 error
metadataServiceUrlIPv6.Host = ipv6Address
fmt.Printf("Fetching from IPv6 metadata service at %s...\n", metadataServiceUrlIPv6.String())
ipv6Res, ipv6Err = f.FetchToBuffer(metadataServiceUrlIPv6, resource.FetchOptions{})

// Try IPv4 endpoint
resIPv4, errIPv4 = f.FetchToBuffer(ipv4MetadataServiceUrl, resource.FetchOptions{})
if errIPv4 != nil && errIPv4 != resource.ErrNotFound {
f.Logger.Err("Failed to fetch config from IPv4: %v", errIPv4)
if ipv6Err != nil {
fmt.Printf("IPv6 metadata service failed: %v\n", ipv6Err)
return ipv4Res, fmt.Errorf("IPv4 succeeded, IPv6 failed: %v", ipv6Err)
}
fmt.Println("Successfully fetched configuration from both IPv4 and IPv6.")
return append(ipv4Res, ipv6Res...), nil
}

// Try IPv6 endpoint
resIPv6, errIPv6 = f.FetchToBuffer(ipv6MetadataServiceUrl, resource.FetchOptions{})
if errIPv6 != nil && errIPv6 != resource.ErrNotFound {
f.Logger.Err("Failed to fetch config from IPv6: %v", errIPv6)
}
// If IPv4 fails, attempt to fetch IPv6
fmt.Printf("IPv4 metadata service failed: %v\n", ipv4Err)
fmt.Println("Trying to fetch from IPv6 metadata service...")

// If both IPv4 and IPv6 have valid data, combine them
if resIPv4 != nil && resIPv6 != nil {
return append(resIPv4, resIPv6...), nil
} else if resIPv4 != nil {
return resIPv4, nil
} else if resIPv6 != nil {
return resIPv6, nil
ipv6Address, err := findIPv6Address()
if err != nil {
fmt.Printf("IPv6 metadata service lookup failed: %v\n", err)
return nil, fmt.Errorf("both IPv4 and IPv6 lookup failed")
}

// If both endpoints fail, return the appropriate error
if errIPv4 != nil {
return nil, errIPv4
}
if errIPv6 != nil {
return nil, errIPv6
metadataServiceUrlIPv6.Host = ipv6Address
fmt.Printf("Fetching from IPv6 metadata service at %s...\n", metadataServiceUrlIPv6.String())
ipv6Res, ipv6Err = f.FetchToBuffer(metadataServiceUrlIPv6, resource.FetchOptions{})
if ipv6Err != nil {
fmt.Printf("IPv6 metadata service failed: %v\n", ipv6Err)
return nil, fmt.Errorf("both IPv4 and IPv6 services failed")
}

// If both endpoints return ErrNotFound
return nil, nil
fmt.Println("Successfully fetched configuration from IPv6 metadata service.")
return ipv6Res, fmt.Errorf("IPv4 failed, returning IPv6 result")
}

0 comments on commit fa50682

Please sign in to comment.