OpenStack: Return multiple private+public NodeAddresses

Add better support for the new NodeAddresses call.  Note the returned
list may include IPv6 addresses (as strings) on many OpenStack clouds.
This commit is contained in:
Angus Lees 2015-03-16 17:11:36 +11:00
parent 8f5064bfea
commit 1437e6b7ca

View File

@ -271,25 +271,29 @@ func getServerByName(client *gophercloud.ServiceClient, name string) (*servers.S
return &serverList[0], nil return &serverList[0], nil
} }
func firstAddr(netblob interface{}) string { func findAddrs(netblob interface{}) []string {
// Run-time types for the win :( // Run-time types for the win :(
ret := []string{}
list, ok := netblob.([]interface{}) list, ok := netblob.([]interface{})
if !ok || len(list) < 1 {
return ""
}
props, ok := list[0].(map[string]interface{})
if !ok { if !ok {
return "" return ret
}
for _, item := range list {
props, ok := item.(map[string]interface{})
if !ok {
continue
} }
tmp, ok := props["addr"] tmp, ok := props["addr"]
if !ok { if !ok {
return "" continue
} }
addr, ok := tmp.(string) addr, ok := tmp.(string)
if !ok { if !ok {
return "" continue
} }
return addr ret = append(ret, addr)
}
return ret
} }
func getAddressByName(api *gophercloud.ServiceClient, name string) (string, error) { func getAddressByName(api *gophercloud.ServiceClient, name string) (string, error) {
@ -300,10 +304,14 @@ func getAddressByName(api *gophercloud.ServiceClient, name string) (string, erro
var s string var s string
if s == "" { if s == "" {
s = firstAddr(srv.Addresses["private"]) if tmp := findAddrs(srv.Addresses["private"]); len(tmp) >= 1 {
s = tmp[0]
}
} }
if s == "" { if s == "" {
s = firstAddr(srv.Addresses["public"]) if tmp := findAddrs(srv.Addresses["public"]); len(tmp) >= 1 {
s = tmp[0]
}
} }
if s == "" { if s == "" {
s = srv.AccessIPv4 s = srv.AccessIPv4
@ -320,15 +328,41 @@ func getAddressByName(api *gophercloud.ServiceClient, name string) (string, erro
func (i *Instances) NodeAddresses(name string) ([]api.NodeAddress, error) { func (i *Instances) NodeAddresses(name string) ([]api.NodeAddress, error) {
glog.V(4).Infof("NodeAddresses(%v) called", name) glog.V(4).Infof("NodeAddresses(%v) called", name)
ip, err := getAddressByName(i.compute, name) srv, err := getServerByName(i.compute, name)
if err != nil { if err != nil {
return nil, err return nil, err
} }
glog.V(4).Infof("NodeAddresses(%v) => %v", name, ip) addrs := []api.NodeAddress{}
// net.ParseIP().String() is to maintain compatibility with the old code for _, addr := range findAddrs(srv.Addresses["private"]) {
return []api.NodeAddress{{Type: api.NodeLegacyHostIP, Address: net.ParseIP(ip).String()}}, nil addrs = append(addrs, api.NodeAddress{
Type: api.NodeInternalIP,
Address: addr,
})
}
for _, addr := range findAddrs(srv.Addresses["public"]) {
addrs = append(addrs, api.NodeAddress{
Type: api.NodeExternalIP,
Address: addr,
})
}
// AccessIPs are usually duplicates of "public" addresses.
api.AddToNodeAddresses(&addrs,
api.NodeAddress{
Type: api.NodeExternalIP,
Address: srv.AccessIPv6,
},
api.NodeAddress{
Type: api.NodeExternalIP,
Address: srv.AccessIPv4,
},
)
glog.V(4).Infof("NodeAddresses(%v) => %v", name, addrs)
return addrs, nil
} }
// ExternalID returns the cloud provider ID of the specified instance. // ExternalID returns the cloud provider ID of the specified instance.