vswitch.go 7.0 KB

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