mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
multicloud: aliyun: instancenic: secondary address management
This commit is contained in:
@@ -337,6 +337,11 @@ type ICloudNic interface {
|
||||
GetDriver() string
|
||||
GetINetwork() ICloudNetwork
|
||||
|
||||
// GetSubAddress returns non-primary/secondary/alias ipv4 addresses of
|
||||
// the network interface
|
||||
//
|
||||
// Implement it when any AssignXx ops methods are implemented
|
||||
GetSubAddress() ([]string, error)
|
||||
AssignNAddress(count int) ([]string, error)
|
||||
AssignAddress(ipAddrs []string) error
|
||||
// UnassignAddress should not return error if the network interface is
|
||||
@@ -355,6 +360,9 @@ func (d DummyICloudNic) GetMAC() string { panic(errors.ErrNotImpleme
|
||||
func (d DummyICloudNic) InClassicNetwork() bool { panic(errors.ErrNotImplemented) }
|
||||
func (d DummyICloudNic) GetDriver() string { panic(errors.ErrNotImplemented) }
|
||||
func (d DummyICloudNic) GetINetwork() ICloudNetwork { panic(errors.ErrNotImplemented) }
|
||||
func (d DummyICloudNic) GetSubAddress() ([]string, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (d DummyICloudNic) AssignNAddress(count int) ([]string, error) {
|
||||
return nil, errors.ErrNotImplemented
|
||||
}
|
||||
|
||||
@@ -15,6 +15,13 @@
|
||||
package aliyun
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
@@ -31,6 +38,13 @@ func (self *SInstanceNic) GetId() string {
|
||||
return self.id
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) mustGetId() string {
|
||||
if self.id == "" {
|
||||
panic("empty network interface id")
|
||||
}
|
||||
return self.id
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) GetIP() string {
|
||||
return self.ipAddr
|
||||
}
|
||||
@@ -62,3 +76,158 @@ func (self *SInstanceNic) GetINetwork() cloudprovider.ICloudNetwork {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) GetSubAddress() ([]string, error) {
|
||||
selfId := self.mustGetId()
|
||||
region := self.instance.host.zone.region
|
||||
params := map[string]string{
|
||||
"RegionId": region.GetId(),
|
||||
"NetworkInterfaceId.1": selfId,
|
||||
}
|
||||
body, err := region.ecsRequest("DescribeNetworkInterfaces", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
type DescribeNetworkInterfacesResponse struct {
|
||||
TotalCount int `json:"TotalCount"`
|
||||
RequestID string `json:"RequestId"`
|
||||
PageSize int `json:"PageSize"`
|
||||
NextToken string `json:"NextToken"`
|
||||
PageNumber int `json:"PageNumber"`
|
||||
NetworkInterfaceSets struct {
|
||||
NetworkInterfaceSet []struct {
|
||||
Status string `json:"Status"`
|
||||
PrivateIPAddress string `json:"PrivateIpAddress"`
|
||||
ZoneID string `json:"ZoneId"`
|
||||
ResourceGroupID string `json:"ResourceGroupId"`
|
||||
InstanceID string `json:"InstanceId"`
|
||||
VSwitchID string `json:"VSwitchId"`
|
||||
NetworkInterfaceID string `json:"NetworkInterfaceId"`
|
||||
MacAddress string `json:"MacAddress"`
|
||||
SecurityGroupIds struct {
|
||||
SecurityGroupID []string `json:"SecurityGroupId"`
|
||||
} `json:"SecurityGroupIds"`
|
||||
Type string `json:"Type"`
|
||||
Ipv6Sets struct {
|
||||
Ipv6Set []struct {
|
||||
Ipv6Address string `json:"Ipv6Address"`
|
||||
} `json:"Ipv6Set"`
|
||||
} `json:"Ipv6Sets"`
|
||||
VpcID string `json:"VpcId"`
|
||||
OwnerID string `json:"OwnerId"`
|
||||
AssociatedPublicIP struct {
|
||||
} `json:"AssociatedPublicIp"`
|
||||
CreationTime time.Time `json:"CreationTime"`
|
||||
Tags struct {
|
||||
Tag []struct {
|
||||
TagKey string `json:"TagKey"`
|
||||
TagValue string `json:"TagValue"`
|
||||
} `json:"Tag"`
|
||||
} `json:"Tags"`
|
||||
PrivateIPSets struct {
|
||||
PrivateIPSet []struct {
|
||||
PrivateIPAddress string `json:"PrivateIpAddress"`
|
||||
AssociatedPublicIP struct {
|
||||
} `json:"AssociatedPublicIp"`
|
||||
Primary bool `json:"Primary"`
|
||||
} `json:"PrivateIpSet"`
|
||||
} `json:"PrivateIpSets"`
|
||||
} `json:"NetworkInterfaceSet"`
|
||||
} `json:"NetworkInterfaceSets"`
|
||||
}
|
||||
var resp DescribeNetworkInterfacesResponse
|
||||
if err := body.Unmarshal(&resp); err != nil {
|
||||
return nil, errors.Wrapf(err, "unmarshal DescribeNetworkInterfacesResponse: %s", body)
|
||||
}
|
||||
if got := len(resp.NetworkInterfaceSets.NetworkInterfaceSet); got != 1 {
|
||||
return nil, errors.Errorf("got %d element(s) in interface set, expect 1", got)
|
||||
}
|
||||
var (
|
||||
ipAddrs []string
|
||||
networkInterface = resp.NetworkInterfaceSets.NetworkInterfaceSet[0]
|
||||
)
|
||||
if got := networkInterface.NetworkInterfaceID; got != selfId {
|
||||
return nil, errors.Errorf("got interface data for %s, expect %s", got, selfId)
|
||||
}
|
||||
for _, privateIP := range networkInterface.PrivateIPSets.PrivateIPSet {
|
||||
if !privateIP.Primary {
|
||||
ipAddrs = append(ipAddrs, privateIP.PrivateIPAddress)
|
||||
}
|
||||
}
|
||||
return ipAddrs, nil
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) ipAddrsParams(ipAddrs []string) map[string]string {
|
||||
region := self.instance.host.zone.region
|
||||
params := map[string]string{
|
||||
"RegionId": region.GetId(),
|
||||
"NetworkInterfaceId": self.mustGetId(),
|
||||
}
|
||||
for i, ipAddr := range ipAddrs {
|
||||
k := fmt.Sprintf("PrivateIpAddress.%d", i+1)
|
||||
params[k] = ipAddr
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) AssignAddress(ipAddrs []string) error {
|
||||
var (
|
||||
selfId = self.mustGetId()
|
||||
instance = self.instance
|
||||
zone = instance.host.zone
|
||||
region = zone.region
|
||||
)
|
||||
ecsClient, err := region.getEcsClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
request := ecs.CreateAssignPrivateIpAddressesRequest()
|
||||
request.Scheme = "https"
|
||||
|
||||
request.NetworkInterfaceId = selfId
|
||||
request.PrivateIpAddress = &ipAddrs
|
||||
resp, err := ecsClient.AssignPrivateIpAddresses(request)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "AssignPrivateIpAddresses")
|
||||
}
|
||||
|
||||
allocated := resp.AssignedPrivateIpAddressesSet.PrivateIpSet.PrivateIpAddress
|
||||
if len(allocated) != len(ipAddrs) {
|
||||
return errors.Errorf("AssignAddress want %d addresses, got %d", len(ipAddrs), len(allocated))
|
||||
}
|
||||
for i := 0; i < len(ipAddrs); i++ {
|
||||
ip0 := ipAddrs[i]
|
||||
ip1 := allocated[i]
|
||||
if ip0 != ip1 {
|
||||
return errors.Errorf("AssignAddress address %d does not match: want %s, got %s", i, ip0, ip1)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) UnassignAddress(ipAddrs []string) error {
|
||||
var (
|
||||
selfId = self.mustGetId()
|
||||
instance = self.instance
|
||||
zone = instance.host.zone
|
||||
region = zone.region
|
||||
)
|
||||
ecsClient, err := region.getEcsClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
request := ecs.CreateUnassignPrivateIpAddressesRequest()
|
||||
request.Scheme = "https"
|
||||
|
||||
request.NetworkInterfaceId = selfId
|
||||
request.PrivateIpAddress = &ipAddrs
|
||||
resp, err := ecsClient.UnassignPrivateIpAddresses(request)
|
||||
if err != nil {
|
||||
if resp.GetHttpStatus() == 404 {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/aliyun/aliyun-oss-go-sdk/oss"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
@@ -83,6 +84,17 @@ func (self *SRegion) getSdkClient() (*sdk.Client, error) {
|
||||
return self.sdkClient, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) getEcsClient() (*ecs.Client, error) {
|
||||
sdkClient, err := self.getSdkClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getSdkClient")
|
||||
}
|
||||
ecsClient := &ecs.Client{
|
||||
Client: *sdkClient,
|
||||
}
|
||||
return ecsClient, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) getOSSExternalDomain() string {
|
||||
return getOSSExternalDomain(self.RegionId)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user