Add instance-type label to cloud providers
Fully implemented for AWS and GCE
This commit is contained in:
		@@ -18,3 +18,4 @@ package unversioned
 | 
			
		||||
 | 
			
		||||
const LabelZoneFailureDomain = "failure-domain.alpha.kubernetes.io/zone"
 | 
			
		||||
const LabelZoneRegion = "failure-domain.alpha.kubernetes.io/region"
 | 
			
		||||
const LabelInstanceType = "beta.kubernetes.io/instance-type"
 | 
			
		||||
 
 | 
			
		||||
@@ -108,6 +108,9 @@ type Instances interface {
 | 
			
		||||
	// InstanceID returns the cloud provider ID of the specified instance.
 | 
			
		||||
	// Note that if the instance does not exist or is no longer running, we must return ("", cloudprovider.InstanceNotFound)
 | 
			
		||||
	InstanceID(name string) (string, error)
 | 
			
		||||
	// InstanceType returns the type of the specified instance.
 | 
			
		||||
	// Note that if the instance does not exist or is no longer running, we must return ("", cloudprovider.InstanceNotFound)
 | 
			
		||||
	InstanceType(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)
 | 
			
		||||
	// AddSSHKeyToAllInstances adds an SSH public key as a legal identity for all instances
 | 
			
		||||
 
 | 
			
		||||
@@ -491,6 +491,10 @@ func readAWSCloudConfig(config io.Reader, metadata EC2Metadata) (*AWSCloudConfig
 | 
			
		||||
	return &cfg, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getInstanceType(metadata EC2Metadata) (string, error) {
 | 
			
		||||
	return metadata.GetMetadata("instance-type")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getAvailabilityZone(metadata EC2Metadata) (string, error) {
 | 
			
		||||
	return metadata.GetMetadata("placement/availability-zone")
 | 
			
		||||
}
 | 
			
		||||
@@ -751,6 +755,24 @@ func (aws *AWSCloud) InstanceID(name string) (string, error) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InstanceType returns the type of the specified instance.
 | 
			
		||||
func (aws *AWSCloud) InstanceType(name string) (string, error) {
 | 
			
		||||
	awsInstance, err := aws.getSelfAWSInstance()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if awsInstance.nodeName == name {
 | 
			
		||||
		return awsInstance.instanceType, nil
 | 
			
		||||
	} else {
 | 
			
		||||
		inst, err := aws.getInstanceByNodeName(name)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return "", err
 | 
			
		||||
		}
 | 
			
		||||
		return orEmpty(inst.InstanceType), nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Check if the instance is alive (running or pending)
 | 
			
		||||
// We typically ignore instances that are not alive
 | 
			
		||||
func isAlive(instance *ec2.Instance) bool {
 | 
			
		||||
@@ -873,6 +895,9 @@ type awsInstance struct {
 | 
			
		||||
	// availability zone the instance resides in
 | 
			
		||||
	availabilityZone string
 | 
			
		||||
 | 
			
		||||
	// instance type
 | 
			
		||||
	instanceType string
 | 
			
		||||
 | 
			
		||||
	mutex sync.Mutex
 | 
			
		||||
 | 
			
		||||
	// We must cache because otherwise there is a race condition,
 | 
			
		||||
@@ -880,8 +905,8 @@ type awsInstance struct {
 | 
			
		||||
	deviceMappings map[mountDevice]string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newAWSInstance(ec2 EC2, awsID, nodeName string, availabilityZone string) *awsInstance {
 | 
			
		||||
	self := &awsInstance{ec2: ec2, awsID: awsID, nodeName: nodeName, availabilityZone: availabilityZone}
 | 
			
		||||
func newAWSInstance(ec2 EC2, awsID, nodeName, availabilityZone, instanceType string) *awsInstance {
 | 
			
		||||
	self := &awsInstance{ec2: ec2, awsID: awsID, nodeName: nodeName, availabilityZone: availabilityZone, instanceType: instanceType}
 | 
			
		||||
 | 
			
		||||
	// We lazy-init deviceMappings
 | 
			
		||||
	self.deviceMappings = nil
 | 
			
		||||
@@ -1157,8 +1182,12 @@ func (s *AWSCloud) getSelfAWSInstance() (*awsInstance, error) {
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("error fetching availability zone from ec2 metadata service: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		instanceType, err := getInstanceType(s.metadata)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("error fetching instance type from ec2 metadata service: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		i = newAWSInstance(s.ec2, instanceId, privateDnsName, availabilityZone)
 | 
			
		||||
		i = newAWSInstance(s.ec2, instanceId, privateDnsName, availabilityZone, instanceType)
 | 
			
		||||
		s.selfAWSInstance = i
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -1180,7 +1209,7 @@ func (aws *AWSCloud) getAwsInstance(nodeName string) (*awsInstance, error) {
 | 
			
		||||
			return nil, fmt.Errorf("error finding instance %s: %v", nodeName, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		awsInstance = newAWSInstance(aws.ec2, orEmpty(instance.InstanceId), orEmpty(instance.PrivateDnsName), orEmpty(instance.Placement.AvailabilityZone))
 | 
			
		||||
		awsInstance = newAWSInstance(aws.ec2, orEmpty(instance.InstanceId), orEmpty(instance.PrivateDnsName), orEmpty(instance.Placement.AvailabilityZone), orEmpty(instance.InstanceType))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return awsInstance, nil
 | 
			
		||||
 
 | 
			
		||||
@@ -52,6 +52,7 @@ type FakeCloud struct {
 | 
			
		||||
	Calls         []string
 | 
			
		||||
	Addresses     []api.NodeAddress
 | 
			
		||||
	ExtID         map[string]string
 | 
			
		||||
	InstanceTypes map[string]string
 | 
			
		||||
	Machines      []string
 | 
			
		||||
	NodeResources *api.NodeResources
 | 
			
		||||
	ClusterList   []string
 | 
			
		||||
@@ -189,6 +190,12 @@ func (f *FakeCloud) InstanceID(instance string) (string, error) {
 | 
			
		||||
	return f.ExtID[instance], nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InstanceType returns the type of the specified instance.
 | 
			
		||||
func (f *FakeCloud) InstanceType(instance string) (string, error) {
 | 
			
		||||
	f.addCall("instance-type")
 | 
			
		||||
	return f.InstanceTypes[instance], nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1797,6 +1797,15 @@ func (gce *GCECloud) InstanceID(instanceName string) (string, error) {
 | 
			
		||||
	return gce.projectID + "/" + instance.Zone + "/" + instance.Name, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InstanceType returns the type of the specified instance.
 | 
			
		||||
func (gce *GCECloud) InstanceType(instanceName string) (string, error) {
 | 
			
		||||
	instance, err := gce.getInstanceByName(instanceName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return instance.Type, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// List is an implementation of Instances.List.
 | 
			
		||||
func (gce *GCECloud) List(filter string) ([]string, error) {
 | 
			
		||||
	var instances []string
 | 
			
		||||
@@ -2151,6 +2160,7 @@ type gceInstance struct {
 | 
			
		||||
	Name  string
 | 
			
		||||
	ID    uint64
 | 
			
		||||
	Disks []*compute.AttachedDisk
 | 
			
		||||
	Type  string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type gceDisk struct {
 | 
			
		||||
@@ -2185,7 +2195,7 @@ func (gce *GCECloud) getInstancesByNames(names []string) ([]*gceInstance, error)
 | 
			
		||||
		// Add the filter for hosts
 | 
			
		||||
		listCall = listCall.Filter("name eq (" + strings.Join(remaining, "|") + ")")
 | 
			
		||||
 | 
			
		||||
		listCall = listCall.Fields("items(name,id,disks)")
 | 
			
		||||
		listCall = listCall.Fields("items(name,id,disks,machineType)")
 | 
			
		||||
 | 
			
		||||
		res, err := listCall.Do()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
@@ -2199,6 +2209,7 @@ func (gce *GCECloud) getInstancesByNames(names []string) ([]*gceInstance, error)
 | 
			
		||||
				Name:  name,
 | 
			
		||||
				ID:    i.Id,
 | 
			
		||||
				Disks: i.Disks,
 | 
			
		||||
				Type:  lastComponent(i.MachineType),
 | 
			
		||||
			}
 | 
			
		||||
			instances[name] = instance
 | 
			
		||||
		}
 | 
			
		||||
@@ -2236,6 +2247,7 @@ func (gce *GCECloud) getInstanceByName(name string) (*gceInstance, error) {
 | 
			
		||||
			Name:  res.Name,
 | 
			
		||||
			ID:    res.Id,
 | 
			
		||||
			Disks: res.Disks,
 | 
			
		||||
			Type:  lastComponent(res.MachineType),
 | 
			
		||||
		}, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -216,6 +216,11 @@ func (c *MesosCloud) InstanceID(name string) (string, error) {
 | 
			
		||||
	return "", nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InstanceType returns the type of the specified instance.
 | 
			
		||||
func (c *MesosCloud) InstanceType(name string) (string, error) {
 | 
			
		||||
	return "", nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *MesosCloud) listNodes() (map[string]*slaveNode, error) {
 | 
			
		||||
	//TODO(jdef) use a timeout here? 15s?
 | 
			
		||||
	ctx, cancel := context.WithCancel(context.TODO())
 | 
			
		||||
 
 | 
			
		||||
@@ -480,6 +480,11 @@ func (i *Instances) InstanceID(name string) (string, error) {
 | 
			
		||||
	return "/" + srv.ID, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InstanceType returns the type of the specified instance.
 | 
			
		||||
func (i *Instances) InstanceType(name string) (string, error) {
 | 
			
		||||
	return "", nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (os *OpenStack) Clusters() (cloudprovider.Clusters, bool) {
 | 
			
		||||
	return nil, false
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -193,6 +193,11 @@ func (v *OVirtCloud) InstanceID(name string) (string, error) {
 | 
			
		||||
	return "/" + instance.UUID, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InstanceType returns the type of the specified instance.
 | 
			
		||||
func (v *OVirtCloud) InstanceType(name string) (string, error) {
 | 
			
		||||
	return "", nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getInstancesFromXml(body io.Reader) (OVirtInstanceMap, error) {
 | 
			
		||||
	if body == nil {
 | 
			
		||||
		return nil, fmt.Errorf("ovirt rest-api response body is missing")
 | 
			
		||||
 
 | 
			
		||||
@@ -344,6 +344,11 @@ func (i *Instances) InstanceID(name string) (string, error) {
 | 
			
		||||
	return "", nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InstanceType returns the type of the specified instance.
 | 
			
		||||
func (i *Instances) InstanceType(name string) (string, error) {
 | 
			
		||||
	return "", nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *Instances) AddSSHKeyToAllInstances(user string, keyData []byte) error {
 | 
			
		||||
	return errors.New("unimplemented")
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1040,6 +1040,14 @@ func (kl *Kubelet) initialNodeStatus() (*api.Node, error) {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		instanceType, err := instances.InstanceType(kl.nodeName)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if instanceType != "" {
 | 
			
		||||
			glog.Infof("Adding node label from cloud provider: %s=%s", unversioned.LabelInstanceType, instanceType)
 | 
			
		||||
			node.ObjectMeta.Labels[unversioned.LabelInstanceType] = instanceType
 | 
			
		||||
		}
 | 
			
		||||
		// If the cloud has zone information, label the node with the zone information
 | 
			
		||||
		zones, ok := kl.cloud.Zones()
 | 
			
		||||
		if ok {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user