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 }