yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aws/network.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  	"fmt"
    19  	"strconv"
    20  	"strings"
    21  	"time"
    22  
    23  	"github.com/aws/aws-sdk-go/service/ec2"
    24  
    25  	"yunion.io/x/jsonutils"
    26  	"yunion.io/x/log"
    27  	"yunion.io/x/pkg/errors"
    28  	"yunion.io/x/pkg/util/netutils"
    29  
    30  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    31  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    32  	"yunion.io/x/cloudmux/pkg/multicloud"
    33  	"yunion.io/x/onecloud/pkg/util/rbacutils"
    34  )
    35  
    36  type SNetwork struct {
    37  	multicloud.SResourceBase
    38  	AwsTags
    39  	wire *SWire
    40  
    41  	AvailableIpAddressCount int
    42  	CidrBlock               string
    43  	CreationTime            time.Time
    44  	Description             string
    45  	IsDefault               bool
    46  	Status                  string
    47  	NetworkId               string
    48  	NetworkName             string
    49  	VpcId                   string
    50  	ZoneId                  string
    51  }
    52  
    53  func (self *SNetwork) GetId() string {
    54  	return self.NetworkId
    55  }
    56  
    57  func (self *SNetwork) GetName() string {
    58  	if len(self.NetworkName) == 0 {
    59  		return self.NetworkId
    60  	}
    61  
    62  	return self.NetworkName
    63  }
    64  
    65  func (self *SNetwork) GetGlobalId() string {
    66  	return self.NetworkId
    67  }
    68  
    69  func (self *SNetwork) GetStatus() string {
    70  	if self.wire != nil && self.wire.vpc != nil && self.wire.vpc.InstanceTenancy == "dedicated" {
    71  		return api.NETWORK_STATUS_UNAVAILABLE
    72  	}
    73  
    74  	return strings.ToLower(self.Status)
    75  }
    76  
    77  func (self *SNetwork) Refresh() error {
    78  	new, err := self.wire.zone.region.getNetwork(self.NetworkId)
    79  	if err != nil {
    80  		return err
    81  	}
    82  	return jsonutils.Update(self, new)
    83  }
    84  
    85  func (self *SNetwork) IsEmulated() bool {
    86  	return false
    87  }
    88  
    89  func (self *SNetwork) GetSysTags() map[string]string {
    90  	data := map[string]string{}
    91  	routes, _ := self.wire.vpc.region.GetRouteTablesByNetworkId(self.GetId())
    92  	if len(routes) == 0 {
    93  		routes, _ = self.wire.vpc.region.GetRouteTables(self.VpcId, true)
    94  	}
    95  
    96  	support_eip := false
    97  	if len(routes) >= 1 {
    98  		for i := range routes[0].Routes {
    99  			route := routes[0].Routes[i]
   100  			if route.GetNextHopType() == api.NEXT_HOP_TYPE_INTERNET {
   101  				support_eip = true
   102  			}
   103  		}
   104  	}
   105  	data["support_eip"] = strconv.FormatBool(support_eip)
   106  	return data
   107  }
   108  
   109  func (self *SNetwork) GetIWire() cloudprovider.ICloudWire {
   110  	return self.wire
   111  }
   112  
   113  // 每个子网 CIDR 块中的前四个 IP 地址和最后一个 IP 地址无法使用
   114  func (self *SNetwork) GetIpStart() string {
   115  	pref, _ := netutils.NewIPV4Prefix(self.CidrBlock)
   116  	startIp := pref.Address.NetAddr(pref.MaskLen) // 0
   117  	startIp = startIp.StepUp()                    // 1
   118  	startIp = startIp.StepUp()                    // 2
   119  	startIp = startIp.StepUp()                    // 3
   120  	startIp = startIp.StepUp()                    // 4
   121  	return startIp.String()
   122  }
   123  
   124  func (self *SNetwork) GetIpEnd() string {
   125  	pref, _ := netutils.NewIPV4Prefix(self.CidrBlock)
   126  	endIp := pref.Address.BroadcastAddr(pref.MaskLen) // 255
   127  	endIp = endIp.StepDown()                          // 254
   128  	return endIp.String()
   129  }
   130  
   131  func (self *SNetwork) GetIpMask() int8 {
   132  	pref, _ := netutils.NewIPV4Prefix(self.CidrBlock)
   133  	return pref.MaskLen
   134  }
   135  
   136  func (self *SNetwork) GetGateway() string {
   137  	pref, _ := netutils.NewIPV4Prefix(self.CidrBlock)
   138  	endIp := pref.Address.BroadcastAddr(pref.MaskLen) // 255
   139  	endIp = endIp.StepDown()                          // 254
   140  	return endIp.String()
   141  }
   142  
   143  func (self *SNetwork) GetServerType() string {
   144  	return api.NETWORK_TYPE_GUEST
   145  }
   146  
   147  func (self *SNetwork) GetIsPublic() bool {
   148  	return true
   149  }
   150  
   151  func (self *SNetwork) GetPublicScope() rbacutils.TRbacScope {
   152  	return rbacutils.ScopeDomain
   153  }
   154  
   155  func (self *SNetwork) Delete() error {
   156  	return self.wire.zone.region.deleteNetwork(self.NetworkId)
   157  }
   158  
   159  func (self *SNetwork) GetAllocTimeoutSeconds() int {
   160  	return 120 // 2 minutes
   161  }
   162  
   163  func (self *SRegion) createNetwork(zoneId string, vpcId string, name string, cidr string, desc string) (string, error) {
   164  	params := &ec2.CreateSubnetInput{}
   165  	params.SetAvailabilityZone(zoneId)
   166  	params.SetVpcId(vpcId)
   167  	params.SetCidrBlock(cidr)
   168  
   169  	ec2Client, err := self.getEc2Client()
   170  	if err != nil {
   171  		return "", errors.Wrap(err, "getEc2Client")
   172  	}
   173  	ret, err := ec2Client.CreateSubnet(params)
   174  	if err != nil {
   175  		return "", err
   176  	} else {
   177  		paramsTags := &ec2.CreateTagsInput{}
   178  		tagspec := TagSpec{ResourceType: "subnet"}
   179  		tagspec.SetNameTag(name)
   180  		tagspec.SetDescTag(desc)
   181  		ec2Tag, _ := tagspec.GetTagSpecifications()
   182  		paramsTags.SetResources([]*string{ret.Subnet.SubnetId})
   183  		paramsTags.SetTags(ec2Tag.Tags)
   184  		_, err := ec2Client.CreateTags(paramsTags)
   185  		if err != nil {
   186  			log.Infof("createNetwork write tags failed:%s", err)
   187  		}
   188  		return *ret.Subnet.SubnetId, nil
   189  	}
   190  }
   191  
   192  func (self *SRegion) getNetwork(networkId string) (*SNetwork, error) {
   193  	if len(networkId) == 0 {
   194  		return nil, fmt.Errorf("GetNetwork networkId should not be empty.")
   195  	}
   196  	networks, err := self.GetNetwroks([]string{networkId}, "")
   197  	if err != nil {
   198  		return nil, errors.Wrap(err, "GetNetwroks")
   199  	}
   200  	if len(networks) != 1 {
   201  		return nil, errors.Wrap(cloudprovider.ErrNotFound, "getNetwork")
   202  	}
   203  	return &networks[0], nil
   204  }
   205  
   206  func (self *SRegion) deleteNetwork(networkId string) error {
   207  	params := &ec2.DeleteSubnetInput{}
   208  	params.SetSubnetId(networkId)
   209  	ec2Client, err := self.getEc2Client()
   210  	if err != nil {
   211  		return errors.Wrap(err, "getEc2Client")
   212  	}
   213  	_, err = ec2Client.DeleteSubnet(params)
   214  	return errors.Wrap(err, "DeleteSubnet")
   215  }
   216  
   217  func (self *SRegion) GetNetwroks(ids []string, vpcId string) ([]SNetwork, error) {
   218  	params := &ec2.DescribeSubnetsInput{}
   219  	if len(ids) > 0 {
   220  		_ids := make([]*string, len(ids))
   221  		for _, id := range ids {
   222  			_ids = append(_ids, &id)
   223  		}
   224  		params.SetSubnetIds(_ids)
   225  	}
   226  
   227  	if len(vpcId) > 0 {
   228  		filters := make([]*ec2.Filter, 1)
   229  		vpcFilter := &ec2.Filter{}
   230  		vpcFilter.SetName("vpc-id")
   231  		vpcFilter.SetValues([]*string{&vpcId})
   232  		filters = append(filters, vpcFilter)
   233  		params.SetFilters(filters)
   234  	}
   235  
   236  	ec2Client, err := self.getEc2Client()
   237  	if err != nil {
   238  		return nil, errors.Wrap(err, "getEc2Client")
   239  	}
   240  
   241  	ret, err := ec2Client.DescribeSubnets(params)
   242  	err = parseNotFoundError(err)
   243  	if err != nil {
   244  		return nil, err
   245  	}
   246  
   247  	subnets := []SNetwork{}
   248  	for i := range ret.Subnets {
   249  		item := ret.Subnets[i]
   250  		if err := FillZero(item); err != nil {
   251  			return nil, err
   252  		}
   253  
   254  		tagspec := TagSpec{ResourceType: "subnet"}
   255  		tagspec.LoadingEc2Tags(item.Tags)
   256  
   257  		subnet := SNetwork{}
   258  		subnet.CidrBlock = *item.CidrBlock
   259  		subnet.VpcId = *item.VpcId
   260  		subnet.Status = *item.State
   261  		subnet.ZoneId = *item.AvailabilityZone
   262  		subnet.IsDefault = *item.DefaultForAz
   263  		subnet.NetworkId = *item.SubnetId
   264  		subnet.NetworkName = tagspec.GetNameTag()
   265  		jsonutils.Update(&subnet.AwsTags.TagSet, item.Tags)
   266  		subnets = append(subnets, subnet)
   267  	}
   268  	return subnets, nil
   269  }
   270  
   271  func (self *SNetwork) GetProjectId() string {
   272  	return ""
   273  }