yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aws/instancenic.go (about)

     1  // Copyright 2019 Yunion
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package aws
    16  
    17  import (
    18  	"strings"
    19  
    20  	"github.com/aws/aws-sdk-go/aws"
    21  	"github.com/aws/aws-sdk-go/aws/awserr"
    22  	"github.com/aws/aws-sdk-go/service/ec2"
    23  
    24  	"yunion.io/x/pkg/errors"
    25  
    26  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    27  )
    28  
    29  type SInstanceNic struct {
    30  	instance *SInstance
    31  
    32  	id      string
    33  	ipAddr  string
    34  	macAddr string
    35  
    36  	cloudprovider.DummyICloudNic
    37  }
    38  
    39  func (self *SInstanceNic) GetId() string {
    40  	return self.id
    41  }
    42  
    43  func (self *SInstanceNic) GetIP() string {
    44  	return self.ipAddr
    45  }
    46  
    47  func (self *SInstanceNic) GetMAC() string {
    48  	return self.macAddr
    49  }
    50  
    51  func (self *SInstanceNic) InClassicNetwork() bool {
    52  	return false
    53  }
    54  
    55  func (self *SInstanceNic) GetDriver() string {
    56  	return "virtio"
    57  }
    58  
    59  func (self *SInstanceNic) GetINetworkId() string {
    60  	return self.instance.VpcAttributes.NetworkId
    61  }
    62  
    63  func (self *SInstanceNic) getEc2Client() *ec2.EC2 {
    64  	ec2Client, err := self.instance.host.zone.region.getEc2Client()
    65  	if err != nil {
    66  		return nil
    67  	}
    68  	return ec2Client
    69  }
    70  
    71  func (self *SInstanceNic) GetSubAddress() ([]string, error) {
    72  	var (
    73  		ec2Client = self.getEc2Client()
    74  		id        = self.GetId()
    75  		input     = &ec2.DescribeNetworkInterfacesInput{
    76  			NetworkInterfaceIds: []*string{
    77  				aws.String(id),
    78  			},
    79  		}
    80  	)
    81  	output, err := ec2Client.DescribeNetworkInterfaces(input)
    82  	if err != nil {
    83  		return nil, errors.Wrapf(err, "aws ec2 DescribeNetworkInterfaces")
    84  	}
    85  	if got := len(output.NetworkInterfaces); got != 1 {
    86  		return nil, errors.Errorf("got aws %d network interface, want 1", got)
    87  	}
    88  	networkInterface := output.NetworkInterfaces[0]
    89  	if got := aws.StringValue(networkInterface.NetworkInterfaceId); got != id {
    90  		return nil, errors.Errorf("got aws network interface %s, want %s", got, id)
    91  	}
    92  	var ipAddrs []string
    93  	for _, privateIp := range networkInterface.PrivateIpAddresses {
    94  		if !aws.BoolValue(privateIp.Primary) {
    95  			ipAddrs = append(ipAddrs, *privateIp.PrivateIpAddress)
    96  		}
    97  	}
    98  	return ipAddrs, nil
    99  }
   100  
   101  func (self *SInstanceNic) AssignAddress(ipAddrs []string) error {
   102  	var (
   103  		ec2Client = self.getEc2Client()
   104  		id        = self.GetId()
   105  		input     = &ec2.AssignPrivateIpAddressesInput{
   106  			NetworkInterfaceId: aws.String(id),
   107  			PrivateIpAddresses: aws.StringSlice(ipAddrs),
   108  		}
   109  	)
   110  	_, err := ec2Client.AssignPrivateIpAddresses(input)
   111  	if err != nil {
   112  		if aerr, ok := err.(awserr.Error); ok {
   113  			switch aerr.Code() {
   114  			case "PrivateIpAddressLimitExceeded":
   115  				return errors.Wrapf(cloudprovider.ErrAddressCountExceed, "aws ec2 AssignPrivateIpAddresses: %v", err)
   116  			}
   117  		}
   118  		return errors.Wrapf(err, "aws ec2 AssignPrivateIpAddresses")
   119  	}
   120  	return nil
   121  }
   122  
   123  func (self *SInstanceNic) UnassignAddress(ipAddrs []string) error {
   124  	var (
   125  		ec2Client = self.getEc2Client()
   126  		id        = self.GetId()
   127  		input     = &ec2.UnassignPrivateIpAddressesInput{
   128  			NetworkInterfaceId: aws.String(id),
   129  			PrivateIpAddresses: aws.StringSlice(ipAddrs),
   130  		}
   131  	)
   132  	_, err := ec2Client.UnassignPrivateIpAddresses(input)
   133  	if err != nil {
   134  		if aerr, ok := err.(awserr.Error); ok {
   135  			switch aerr.Code() {
   136  			case "InvalidNetworkInterfaceID.NotFound":
   137  				return nil
   138  			case "InvalidParameterValue":
   139  				msg := aerr.Message()
   140  				// "Some of the specified addresses are not assigned to interface eni-xxxxxxxxxxxxxxxxx"
   141  				if strings.Contains(msg, " addresses are not assigned to interface ") {
   142  					return nil
   143  				}
   144  			}
   145  		}
   146  		return errors.Wrapf(err, "aws ec2 UnassignPrivateIpAddresses")
   147  	}
   148  	return nil
   149  }