yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aliyun/vswitch.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 aliyun 16 17 import ( 18 "fmt" 19 "strings" 20 "time" 21 22 "yunion.io/x/jsonutils" 23 "yunion.io/x/log" 24 "yunion.io/x/pkg/util/netutils" 25 "yunion.io/x/pkg/utils" 26 27 api "yunion.io/x/cloudmux/pkg/apis/compute" 28 "yunion.io/x/cloudmux/pkg/cloudprovider" 29 "yunion.io/x/cloudmux/pkg/multicloud" 30 "yunion.io/x/onecloud/pkg/util/rbacutils" 31 ) 32 33 // {"AvailableIpAddressCount":4091,"CidrBlock":"172.31.32.0/20","CreationTime":"2017-03-19T13:37:44Z","Description":"System created default virtual switch.","IsDefault":true,"Status":"Available","VSwitchId":"vsw-j6c3gig5ub4fmi2veyrus","VSwitchName":"","VpcId":"vpc-j6c86z3sh8ufhgsxwme0q","ZoneId":"cn-hongkong-b"} 34 35 const ( 36 VSwitchPending = "Pending" 37 VSwitchAvailable = "Available" 38 ) 39 40 type SCloudResources struct { 41 CloudResourceSetType []string 42 } 43 44 type SVSwitch struct { 45 multicloud.SResourceBase 46 AliyunTags 47 wire *SWire 48 49 AvailableIpAddressCount int 50 51 CidrBlock string 52 Ipv6CidrBlock string 53 CreationTime time.Time 54 Description string 55 IsDefault bool 56 Status string 57 VSwitchId string 58 VSwitchName string 59 VpcId string 60 ZoneId string 61 62 CloudResources SCloudResources 63 ResourceGroupId string 64 RouteTable SRouteTable 65 } 66 67 func (self *SVSwitch) GetId() string { 68 return self.VSwitchId 69 } 70 71 func (self *SVSwitch) GetName() string { 72 if len(self.VSwitchName) > 0 { 73 return self.VSwitchName 74 } 75 return self.VSwitchId 76 } 77 78 func (self *SVSwitch) GetGlobalId() string { 79 return self.VSwitchId 80 } 81 82 func (self *SVSwitch) IsEmulated() bool { 83 return false 84 } 85 86 func (self *SVSwitch) GetStatus() string { 87 return strings.ToLower(self.Status) 88 } 89 90 func (self *SVSwitch) Refresh() error { 91 log.Debugf("vsiwtch refresh %s", self.VSwitchId) 92 new, err := self.wire.zone.region.GetVSwitchAttributes(self.VSwitchId) 93 if err != nil { 94 return err 95 } 96 return jsonutils.Update(self, new) 97 } 98 99 func (self *SVSwitch) GetIWire() cloudprovider.ICloudWire { 100 return self.wire 101 } 102 103 func (self *SVSwitch) GetIpStart() string { 104 pref, _ := netutils.NewIPV4Prefix(self.CidrBlock) 105 startIp := pref.Address.NetAddr(pref.MaskLen) // 0 106 startIp = startIp.StepUp() // 1 107 return startIp.String() 108 } 109 110 func (self *SVSwitch) GetIpEnd() string { 111 pref, _ := netutils.NewIPV4Prefix(self.CidrBlock) 112 endIp := pref.Address.BroadcastAddr(pref.MaskLen) // 255 113 endIp = endIp.StepDown() // 254 114 endIp = endIp.StepDown() // 253 115 endIp = endIp.StepDown() // 252 116 return endIp.String() 117 } 118 119 func (self *SVSwitch) GetIpMask() int8 { 120 pref, _ := netutils.NewIPV4Prefix(self.CidrBlock) 121 return pref.MaskLen 122 } 123 124 func (self *SVSwitch) GetGateway() 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 *SVSwitch) GetServerType() string { 132 return api.NETWORK_TYPE_GUEST 133 } 134 135 func (self *SVSwitch) GetIsPublic() bool { 136 // return self.IsDefault 137 return true 138 } 139 140 func (self *SVSwitch) GetPublicScope() rbacutils.TRbacScope { 141 return rbacutils.ScopeDomain 142 } 143 144 func (self *SRegion) createVSwitch(zoneId string, vpcId string, name string, cidr string, desc string) (string, error) { 145 params := make(map[string]string) 146 params["ZoneId"] = zoneId 147 params["VpcId"] = vpcId 148 params["CidrBlock"] = cidr 149 params["VSwitchName"] = name 150 if len(desc) > 0 { 151 params["Description"] = desc 152 } 153 params["ClientToken"] = utils.GenRequestId(20) 154 155 body, err := self.vpcRequest("CreateVSwitch", params) 156 if err != nil { 157 return "", err 158 } 159 return body.GetString("VSwitchId") 160 } 161 162 func (self *SRegion) DeleteVSwitch(vswitchId string) error { 163 params := make(map[string]string) 164 params["VSwitchId"] = vswitchId 165 166 _, err := self.vpcRequest("DeleteVSwitch", params) 167 return err 168 } 169 170 func (self *SVSwitch) Delete() error { 171 err := self.Refresh() 172 if err != nil { 173 log.Errorf("refresh vswitch fail %s", err) 174 return err 175 } 176 if len(self.RouteTable.RouteTableId) > 0 && !self.RouteTable.IsSystem() { 177 err = self.wire.zone.region.UnassociateRouteTable(self.RouteTable.RouteTableId, self.VSwitchId) 178 if err != nil { 179 log.Errorf("unassociate routetable fail %s", err) 180 return err 181 } 182 } 183 err = self.dissociateWithSNAT() 184 if err != nil { 185 log.Errorf("fail to dissociateWithSNAT") 186 return err 187 } 188 err = cloudprovider.Wait(10*time.Second, 60*time.Second, func() (bool, error) { 189 err := self.wire.zone.region.DeleteVSwitch(self.VSwitchId) 190 if err != nil { 191 // delete network immediately after deleting vm on it 192 // \"Code\":\"DependencyViolation\",\"Message\":\"Specified object has dependent resources.\"} 193 if isError(err, "DependencyViolation") { 194 return false, nil 195 } 196 return false, err 197 } else { 198 return true, nil 199 } 200 }) 201 return err 202 } 203 204 func (self *SVSwitch) GetAllocTimeoutSeconds() int { 205 return 120 // 2 minutes 206 } 207 208 func (self *SRegion) GetVSwitches(ids []string, vpcId string, offset int, limit int) ([]SVSwitch, int, error) { 209 if limit > 50 || limit <= 0 { 210 limit = 50 211 } 212 params := make(map[string]string) 213 params["RegionId"] = self.RegionId 214 params["PageSize"] = fmt.Sprintf("%d", limit) 215 params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1) 216 if ids != nil && len(ids) > 0 { 217 params["VSwitchId"] = strings.Join(ids, ",") 218 } 219 if len(vpcId) > 0 { 220 params["VpcId"] = vpcId 221 } 222 223 body, err := self.vpcRequest("DescribeVSwitches", params) 224 if err != nil { 225 log.Errorf("GetVSwitches fail %s", err) 226 return nil, 0, err 227 } 228 229 switches := make([]SVSwitch, 0) 230 err = body.Unmarshal(&switches, "VSwitches", "VSwitch") 231 if err != nil { 232 log.Errorf("Unmarshal vswitches fail %s", err) 233 return nil, 0, err 234 } 235 total, _ := body.Int("TotalCount") 236 return switches, int(total), nil 237 } 238 239 func (self *SRegion) GetVSwitchAttributes(idstr string) (*SVSwitch, error) { 240 params := make(map[string]string) 241 params["VSwitchId"] = idstr 242 243 body, err := self.vpcRequest("DescribeVSwitchAttributes", params) 244 if err != nil { 245 log.Errorf("DescribeVSwitchAttributes fail %s", err) 246 return nil, err 247 } 248 if self.client.debug { 249 log.Debugf("%s", body.PrettyString()) 250 } 251 switches := SVSwitch{} 252 err = body.Unmarshal(&switches) 253 if err != nil { 254 log.Errorf("Unmarshal vswitches fail %s", err) 255 return nil, err 256 } 257 return &switches, nil 258 } 259 260 func (vsw *SVSwitch) dissociateWithSNAT() error { 261 natgatways, err := vsw.wire.vpc.getNatGateways() 262 if err != nil { 263 return err 264 } 265 for i := range natgatways { 266 err = natgatways[i].dissociateWithVswitch(vsw.VSwitchId) 267 if err != nil { 268 return err 269 } 270 } 271 return nil 272 } 273 274 func (self *SVSwitch) GetProjectId() string { 275 return self.ResourceGroupId 276 }