cloudprovider: add instance id to NodeSpec

Sometimes for external applications it is important to identify the
cloud instance of the nodes. Until this patch there was no contract
that the node name returned by List was also the unique identifier of
the cloud instance. This new API ensures that an external application
can reliably retrieve the relevant instance id of the nodes.

Signed-off-by: Federico Simoncelli <fsimonce@redhat.com>
This commit is contained in:
Federico Simoncelli 2015-02-11 17:37:27 -05:00
parent 8844c06574
commit a450da4fd0
15 changed files with 58 additions and 0 deletions

View File

@ -781,6 +781,8 @@ type NodeSpec struct {
// PodCIDR represents the pod IP range assigned to the node
// Note: assigning IP ranges to nodes might need to be revisited when we support migratable IPs.
PodCIDR string `json:"cidr,omitempty"`
// External ID of the node assigned by some machine database (e.g. a cloud provider)
ExternalID string `json:"externalID,omitempty"`
}
// NodeStatus is information about the current status of a node.

View File

@ -699,6 +699,7 @@ func init() {
out.HostIP = in.Status.HostIP
out.PodCIDR = in.Spec.PodCIDR
out.ExternalID = in.Spec.ExternalID
return s.Convert(&in.Spec.Capacity, &out.NodeResources.Capacity, 0)
},
func(in *Minion, out *newer.Node, s conversion.Scope) error {
@ -720,6 +721,7 @@ func init() {
out.Status.HostIP = in.HostIP
out.Spec.PodCIDR = in.PodCIDR
out.Spec.ExternalID = in.ExternalID
return s.Convert(&in.NodeResources.Capacity, &out.Spec.Capacity, 0)
},
func(in *newer.LimitRange, out *LimitRange, s conversion.Scope) error {

View File

@ -690,6 +690,8 @@ type Minion struct {
Status NodeStatus `json:"status,omitempty" description:"current status of node"`
// Labels for the node
Labels map[string]string `json:"labels,omitempty" description:"map of string keys and values that can be used to organize and categorize minions; labels of a minion assigned by the scheduler must match the scheduled pod's nodeSelector"`
// External ID of the node
ExternalID string `json:"externalID,omitempty" description:"external id of the node assigned by some machine database (e.g. a cloud provider)"`
}
// MinionList is a list of minions.

View File

@ -619,6 +619,7 @@ func init() {
out.HostIP = in.Status.HostIP
out.PodCIDR = in.Spec.PodCIDR
out.ExternalID = in.Spec.ExternalID
return s.Convert(&in.Spec.Capacity, &out.NodeResources.Capacity, 0)
},
func(in *Minion, out *newer.Node, s conversion.Scope) error {
@ -640,6 +641,7 @@ func init() {
out.Status.HostIP = in.HostIP
out.Spec.PodCIDR = in.PodCIDR
out.Spec.ExternalID = in.ExternalID
return s.Convert(&in.NodeResources.Capacity, &out.Spec.Capacity, 0)
},
func(in *newer.LimitRange, out *LimitRange, s conversion.Scope) error {

View File

@ -654,6 +654,8 @@ type Minion struct {
Status NodeStatus `json:"status,omitempty" description:"current status of node"`
// Labels for the node
Labels map[string]string `json:"labels,omitempty" description:"map of string keys and values that can be used to organize and categorize minions; labels of a minion assigned by the scheduler must match the scheduled pod's nodeSelector"`
// External ID of the node
ExternalID string `json:"externalID,omitempty" description:"external id of the node assigned by some machine database (e.g. a cloud provider)"`
}
// MinionList is a list of minions.

View File

@ -814,6 +814,8 @@ type NodeSpec struct {
Capacity ResourceList `json:"capacity,omitempty"`
// PodCIDR represents the pod IP range assigned to the node
PodCIDR string `json:"cidr,omitempty"`
// External ID of the node assigned by some machine database (e.g. a cloud provider)
ExternalID string `json:"externalID,omitempty"`
}
// NodeStatus is information about the current status of a node.

View File

@ -150,6 +150,11 @@ func (aws *AWSCloud) IPAddress(name string) (net.IP, error) {
return ip, nil
}
// ExternalID returns the cloud provider ID of the specified instance.
func (aws *AWSCloud) ExternalID(name string) (string, error) {
return "", fmt.Errorf("unimplemented")
}
// Return a list of instances matching regex string.
func (aws *AWSCloud) getInstancesByRegex(regex string) ([]string, error) {
resp, err := aws.ec2.Instances(nil, nil)

View File

@ -59,6 +59,8 @@ type TCPLoadBalancer interface {
type Instances interface {
// IPAddress returns an IP address of the specified instance.
IPAddress(name string) (net.IP, error)
// ExternalID returns the cloud provider ID of the specified instance.
ExternalID(name string) (string, error)
// List lists instances that match 'filter' which is a regular expression which must match the entire instance name (fqdn)
List(filter string) ([]string, error)
// GetNodeResources gets the resources for a particular node

View File

@ -231,6 +231,12 @@ func (s *NodeController) PopulateIPs(nodes *api.NodeList) (*api.NodeList, error)
} else {
node.Status.HostIP = hostIP.String()
}
instanceID, err := instances.ExternalID(node.Name)
if err != nil {
glog.Errorf("error getting instance id for %s: %v", node.Name, err)
} else {
node.Spec.ExternalID = instanceID
}
}
} else {
for i := range nodes.Items {

View File

@ -30,6 +30,7 @@ type FakeCloud struct {
Err error
Calls []string
IP net.IP
ExtID string
Machines []string
NodeResources *api.NodeResources
ClusterList []string
@ -110,6 +111,13 @@ func (f *FakeCloud) IPAddress(instance string) (net.IP, error) {
return f.IP, f.Err
}
// ExternalID is a test-spy implementation of Instances.ExternalID.
// It adds an entry "external-id" into the internal method call record.
func (f *FakeCloud) ExternalID(instance string) (string, error) {
f.addCall("external-id")
return f.ExtID, f.Err
}
// List is a test-spy implementation of Instances.List.
// It adds an entry "list" into the internal method call record.
func (f *FakeCloud) List(filter string) ([]string, error) {

View File

@ -294,6 +294,11 @@ func (gce *GCECloud) IPAddress(instance string) (net.IP, error) {
return ip, nil
}
// ExternalID returns the cloud provider ID of the specified instance.
func (gce *GCECloud) ExternalID(instance string) (string, error) {
return "", fmt.Errorf("unimplemented")
}
// fqdnSuffix is hacky function to compute the delta between hostame and hostname -f.
func fqdnSuffix() (string, error) {
fullHostname, err := exec.Command("hostname", "-f").Output()

View File

@ -312,6 +312,11 @@ func (i *Instances) IPAddress(name string) (net.IP, error) {
return net.ParseIP(ip), err
}
// ExternalID returns the cloud provider ID of the specified instance.
func (i *Instances) ExternalID(name string) (string, error) {
return "", fmt.Errorf("unimplemented")
}
func (i *Instances) GetNodeResources(name string) (*api.NodeResources, error) {
glog.V(2).Infof("GetNodeResources(%v) called", name)

View File

@ -153,6 +153,11 @@ func (v *OVirtCloud) IPAddress(name string) (net.IP, error) {
return address, nil
}
// ExternalID returns the cloud provider ID of the specified instance.
func (v *OVirtCloud) ExternalID(name string) (string, error) {
return "", fmt.Errorf("unimplemented")
}
func getInstancesFromXml(body io.Reader) (OVirtInstanceMap, error) {
if body == nil {
return nil, fmt.Errorf("ovirt rest-api response body is missing")

View File

@ -363,6 +363,11 @@ func (i *Instances) IPAddress(name string) (net.IP, error) {
return net.ParseIP(ip), err
}
// ExternalID returns the cloud provider ID of the specified instance.
func (i *Instances) ExternalID(name string) (string, error) {
return "", fmt.Errorf("unimplemented")
}
func (i *Instances) GetNodeResources(name string) (*api.NodeResources, error) {
glog.V(2).Infof("GetNodeResources(%v) called", name)

View File

@ -119,6 +119,11 @@ func (v *VagrantCloud) IPAddress(instance string) (net.IP, error) {
return nil, fmt.Errorf("unable to find IP address for instance: %s", instance)
}
// ExternalID returns the cloud provider ID of the specified instance.
func (v *VagrantCloud) ExternalID(instance string) (string, error) {
return "", fmt.Errorf("unimplemented")
}
// saltMinionsByRole filters a list of minions that have a matching role.
func (v *VagrantCloud) saltMinionsByRole(minions []SaltMinion, role string) []SaltMinion {
var filteredMinions []SaltMinion