Merge pull request #51409 from FengyunPan/implement-InstanceExistsByProviderID

Automatic merge from submit-queue (batch tested with PRs 51409, 54616). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Implement InstanceExistsByProviderID() for cloud providers

Fix #51406
If cloud providers(like aws, gce etc...) implement ExternalID()
and support getting instance by ProviderID , they also implement
InstanceExistsByProviderID().

/assign wlan0
/assign @luxas

**Release note**:
```release-note
NONE
```
pull/6/head
Kubernetes Submit Queue 2017-10-27 06:16:20 -07:00 committed by GitHub
commit 55e49ed554
5 changed files with 119 additions and 10 deletions

View File

@ -1152,7 +1152,33 @@ func (c *Cloud) ExternalID(nodeName types.NodeName) (string, error) {
// InstanceExistsByProviderID returns true if the instance with the given provider id still exists and is running.
// If false is returned with no error, the instance will be immediately deleted by the cloud controller manager.
func (c *Cloud) InstanceExistsByProviderID(providerID string) (bool, error) {
return false, cloudprovider.NotImplemented
instanceID, err := kubernetesInstanceID(providerID).mapToAWSInstanceID()
if err != nil {
return false, err
}
request := &ec2.DescribeInstancesInput{
InstanceIds: []*string{instanceID.awsString()},
}
instances, err := c.ec2.DescribeInstances(request)
if err != nil {
return false, err
}
if len(instances) == 0 {
return false, nil
}
if len(instances) > 1 {
return false, fmt.Errorf("multiple instances found for instance: %s", instanceID)
}
state := instances[0].State.Name
if *state != "running" {
glog.Warningf("the instance %s is not running", instanceID)
return false, nil
}
return true, nil
}
// InstanceID returns the cloud provider ID of the node with the specified nodeName.

View File

@ -89,7 +89,20 @@ func (az *Cloud) ExternalID(name types.NodeName) (string, error) {
// InstanceExistsByProviderID returns true if the instance with the given provider id still exists and is running.
// If false is returned with no error, the instance will be immediately deleted by the cloud controller manager.
func (az *Cloud) InstanceExistsByProviderID(providerID string) (bool, error) {
return false, cloudprovider.NotImplemented
name, err := splitProviderID(providerID)
if err != nil {
return false, err
}
_, err = az.InstanceID(name)
if err != nil {
if err == cloudprovider.InstanceNotFound {
return false, nil
}
return false, err
}
return true, nil
}
func (az *Cloud) isCurrentInstance(name types.NodeName) (bool, error) {

View File

@ -116,19 +116,35 @@ func (gce *GCECloud) NodeAddressesByProviderID(providerID string) ([]v1.NodeAddr
return nodeAddresses, nil
}
// instanceByProviderID returns the cloudprovider instance of the node
// with the specified unique providerID
func (gce *GCECloud) instanceByProviderID(providerID string) (*gceInstance, error) {
project, zone, name, err := splitProviderID(providerID)
if err != nil {
return nil, err
}
instance, err := gce.getInstanceFromProjectInZoneByName(project, zone, name)
if err != nil {
if isHTTPErrorCode(err, http.StatusNotFound) {
return nil, cloudprovider.InstanceNotFound
}
return nil, err
}
return instance, nil
}
// InstanceTypeByProviderID returns the cloudprovider instance type of the node
// with the specified unique providerID This method will not be called from the
// node that is requesting this ID. i.e. metadata service and other local
// methods cannot be used here
func (gce *GCECloud) InstanceTypeByProviderID(providerID string) (string, error) {
project, zone, name, err := splitProviderID(providerID)
if err != nil {
return "", err
}
instance, err := gce.getInstanceFromProjectInZoneByName(project, zone, name)
instance, err := gce.instanceByProviderID(providerID)
if err != nil {
return "", err
}
return instance.Type, nil
}
@ -156,7 +172,15 @@ func (gce *GCECloud) ExternalID(nodeName types.NodeName) (string, error) {
// InstanceExistsByProviderID returns true if the instance with the given provider id still exists and is running.
// If false is returned with no error, the instance will be immediately deleted by the cloud controller manager.
func (gce *GCECloud) InstanceExistsByProviderID(providerID string) (bool, error) {
return false, cloudprovider.NotImplemented
_, err := gce.instanceByProviderID(providerID)
if err != nil {
if err == cloudprovider.InstanceNotFound {
return false, nil
}
return false, err
}
return true, nil
}
// InstanceID returns the cloud provider ID of the node with the specified NodeName.

View File

@ -116,7 +116,25 @@ func (i *Instances) ExternalID(name types.NodeName) (string, error) {
// InstanceExistsByProviderID returns true if the instance with the given provider id still exists and is running.
// If false is returned with no error, the instance will be immediately deleted by the cloud controller manager.
func (i *Instances) InstanceExistsByProviderID(providerID string) (bool, error) {
return false, cloudprovider.NotImplemented
instanceID, err := instanceIDFromProviderID(providerID)
if err != nil {
return false, err
}
server, err := servers.Get(i.compute, instanceID).Extract()
if err != nil {
if isNotFound(err) {
return false, nil
}
return false, err
}
if server.Status != "ACTIVE" {
glog.Warningf("the instance %s is not active", instanceID)
return false, nil
}
return true, nil
}
// InstanceID returns the kubelet's cloud provider ID.

View File

@ -380,7 +380,35 @@ func (vs *VSphere) ExternalID(nodeName k8stypes.NodeName) (string, error) {
// InstanceExistsByProviderID returns true if the instance with the given provider id still exists and is running.
// If false is returned with no error, the instance will be immediately deleted by the cloud controller manager.
func (vs *VSphere) InstanceExistsByProviderID(providerID string) (bool, error) {
return false, cloudprovider.NotImplemented
vmName := path.Base(providerID)
nodeName := vmNameToNodeName(vmName)
// Create context
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Ensure client is logged in and session is valid
err := vs.conn.Connect(ctx)
if err != nil {
return false, err
}
vm, err := vs.getVMByName(ctx, nodeName)
if err != nil {
if vclib.IsNotFound(err) {
return false, nil
}
glog.Errorf("Failed to get VM object for node: %q. err: +%v", nodeNameToVMName(nodeName), err)
return false, err
}
isActive, err := vm.IsActive(ctx)
if err != nil {
glog.Errorf("Failed to check whether node %q is active. err: %+v.", nodeNameToVMName(nodeName), err)
return false, err
}
if !isActive {
return false, nil
}
return true, nil
}
// InstanceID returns the cloud provider ID of the node with the specified Name.