-
Notifications
You must be signed in to change notification settings - Fork 128
Reach MetaData service over IPv6 #856
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ import ( | |
| "encoding/json" | ||
| "fmt" | ||
| "io" | ||
| network "net" | ||
| "os" | ||
| "os/exec" | ||
| "path/filepath" | ||
|
|
@@ -26,11 +27,10 @@ const ( | |
| varConfigPath = "/var/config" | ||
| ospMetaDataBaseDir = "/openstack/2018-08-27" | ||
| ospMetaDataDir = varConfigPath + ospMetaDataBaseDir | ||
| ospMetaDataBaseURL = "http://169.254.169.254" + ospMetaDataBaseDir | ||
| ospNetworkDataJSON = "network_data.json" | ||
| ospMetaDataJSON = "meta_data.json" | ||
| ospNetworkDataURL = ospMetaDataBaseURL + "/" + ospNetworkDataJSON | ||
| ospMetaDataURL = ospMetaDataBaseURL + "/" + ospMetaDataJSON | ||
| ospHTTP = "http://" | ||
| ospHTTPS = "https://" | ||
| // Config drive is defined as an iso9660 or vfat (deprecated) drive | ||
| // with the "config-2" label. | ||
| //https://docs.openstack.org/nova/latest/user/config-drive.html | ||
|
|
@@ -40,6 +40,10 @@ const ( | |
| var ( | ||
| ospNetworkDataFile = ospMetaDataDir + "/" + ospNetworkDataJSON | ||
| ospMetaDataFile = ospMetaDataDir + "/" + ospMetaDataJSON | ||
| ospBaseURLS = [2]string{"169.254.169.254", "fe80::a9fe:a9fe"} | ||
| ospNetworkDataURL string | ||
| ospMetaDataURL string | ||
| ospMetaDataBaseURL []string | ||
| ) | ||
|
|
||
| //go:generate ../../../bin/mockgen -destination mock/mock_openstack.go -source openstack.go | ||
|
|
@@ -113,17 +117,85 @@ func New(hostManager host.HostManagerInterface) OpenstackInterface { | |
| } | ||
| } | ||
|
|
||
| func getActiveInterfaceName() (string, error) { | ||
| interfaces, err := network.Interfaces() | ||
| if err != nil { | ||
| return "", err | ||
| } | ||
|
|
||
| for _, intf := range interfaces { | ||
| // Check if the interface is up and not a loopback | ||
| if intf.Flags&network.FlagUp != 0 && intf.Flags&network.FlagLoopback == 0 { | ||
| addrs, err := intf.Addrs() | ||
| if err != nil { | ||
| continue | ||
| } | ||
|
|
||
| // Check if at least one address is an IPv6 address | ||
| for _, addr := range addrs { | ||
| if ipNet, ok := addr.(*network.IPNet); ok && ipNet.IP.To4() == nil { | ||
| return intf.Name, nil | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return "", fmt.Errorf("no active non-loopback interface found with an IPv6 address") | ||
| } | ||
|
|
||
| func constructMetaDataURLs(baseURL, activeInterface string, isIPv6 bool) []string { | ||
| var urls []string | ||
| encodedSign := "%25" | ||
| port := "80" | ||
| if isIPv6 { | ||
| urls = append(urls, ospHTTPS+"["+baseURL+encodedSign+activeInterface+"]:"+port) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi question can you please explain why we need the interface name here? base on this we can just send a request to the ipv6 address and it should be good no? https://specs.openstack.org/openstack/neutron-specs/specs/ussuri/metadata-add-ipv6-support.html
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @SchSeba I am following this documentation.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I get it thanks! |
||
| urls = append(urls, ospHTTP+"["+baseURL+encodedSign+activeInterface+"]:"+port) | ||
| } else { | ||
| urls = append(urls, ospHTTPS+baseURL) | ||
| urls = append(urls, ospHTTP+baseURL) | ||
| } | ||
| return urls | ||
| } | ||
|
|
||
| // GetOpenstackData gets the metadata and network_data | ||
| func getOpenstackData(mountConfigDrive bool) (metaData *OSPMetaData, networkData *OSPNetworkData, err error) { | ||
| metaData, networkData, err = getOpenstackDataFromConfigDrive(mountConfigDrive) | ||
| if err != nil { | ||
| log.Log.Error(err, "GetOpenStackData(): non-fatal error getting OpenStack data from config drive") | ||
| metaData, networkData, err = getOpenstackDataFromMetadataService() | ||
| if err != nil { | ||
| return metaData, networkData, fmt.Errorf("GetOpenStackData(): error getting OpenStack data: %w", err) | ||
| // Attempt to reach MetaData over IPv4 then over IPv6 for both HTTPS and HTTP | ||
| reachedMetaData := false | ||
| for i, baseURL := range ospBaseURLS { | ||
| isIPv6 := i == 1 | ||
| if isIPv6 { | ||
| activeInterface, err := getActiveInterfaceName() | ||
| if err != nil { | ||
| log.Log.Error(err, "GetOpenStackData(): non-fatal error retrieving active network interface") | ||
| continue | ||
| } | ||
| ospMetaDataBaseURL = constructMetaDataURLs(baseURL, activeInterface, true) | ||
| } else { | ||
| ospMetaDataBaseURL = constructMetaDataURLs(baseURL, "", false) | ||
| } | ||
| // Attempt to reach MetaData over HTTPS then over HTTP | ||
| for _, baseMetaURL := range ospMetaDataBaseURL { | ||
| ospNetworkDataURL = baseMetaURL + "/" + ospNetworkDataJSON | ||
| ospMetaDataURL = baseMetaURL + "/" + ospMetaDataJSON | ||
| metaData, networkData, err = getOpenstackDataFromMetadataService() | ||
| if err == nil { | ||
| reachedMetaData = true | ||
| break | ||
| } | ||
| } | ||
|
|
||
| if reachedMetaData { | ||
| break | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if !reachedMetaData { | ||
| return metaData, networkData, fmt.Errorf("GetOpenStackData(): error reaching metadata service both over IPv6 and IPv4: %v", err) | ||
| } | ||
| } | ||
| // We can't rely on the PCI address from the metadata so we will lookup the real PCI address | ||
| // for the NIC that matches the MAC address. | ||
| // | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should check if there is at least one IPv6 address defined in the interface to be used
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay i added this check thanks for the feedback