natgateway.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  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 aliyun
  15. import (
  16. "fmt"
  17. "strings"
  18. "time"
  19. "yunion.io/x/jsonutils"
  20. "yunion.io/x/log"
  21. "yunion.io/x/pkg/errors"
  22. "yunion.io/x/pkg/utils"
  23. api "yunion.io/x/cloudmux/pkg/apis/compute"
  24. "yunion.io/x/cloudmux/pkg/cloudprovider"
  25. "yunion.io/x/cloudmux/pkg/multicloud"
  26. )
  27. type SBandwidthPackageIds struct {
  28. BandwidthPackageId []string
  29. }
  30. type SForwardTableIds struct {
  31. ForwardTableId []string
  32. }
  33. type SSnatTableIds struct {
  34. SnatTableId []string
  35. }
  36. type NatGatewayPrivateInfo struct {
  37. EniInstanceId string
  38. IzNo string
  39. MaxBandwidth int
  40. PrivateIpAddress string
  41. VswitchId string
  42. }
  43. type SNatGateway struct {
  44. multicloud.SNatGatewayBase
  45. AliyunTags
  46. vpc *SVpc
  47. BandwidthPackageIds SBandwidthPackageIds
  48. BusinessStatus string
  49. CreationTime time.Time
  50. ExpiredTime time.Time
  51. Description string
  52. ForwardTableIds SForwardTableIds
  53. NetworkType string
  54. SnatTableIds SSnatTableIds
  55. InstanceChargeType TChargeType
  56. Name string
  57. NatGatewayId string
  58. RegionId string
  59. Spec string
  60. Status string
  61. VpcId string
  62. NatGatewayPrivateInfo NatGatewayPrivateInfo
  63. }
  64. func (nat *SNatGateway) GetId() string {
  65. return nat.NatGatewayId
  66. }
  67. func (nat *SNatGateway) GetGlobalId() string {
  68. return nat.NatGatewayId
  69. }
  70. func (nat *SNatGateway) GetName() string {
  71. if len(nat.Name) > 0 {
  72. return nat.Name
  73. }
  74. return nat.NatGatewayId
  75. }
  76. func (nat *SNatGateway) GetStatus() string {
  77. switch nat.Status {
  78. case "Initiating":
  79. return api.NAT_STATUS_ALLOCATE
  80. case "Available":
  81. return api.NAT_STAUTS_AVAILABLE
  82. case "Pending":
  83. return api.NAT_STATUS_DEPLOYING
  84. default:
  85. return api.NAT_STATUS_UNKNOWN
  86. }
  87. }
  88. func (self *SNatGateway) GetINetworkId() string {
  89. return self.NatGatewayPrivateInfo.VswitchId
  90. }
  91. func (self *SNatGateway) GetNetworkType() string {
  92. return self.NetworkType
  93. }
  94. func (self *SNatGateway) GetIpAddr() string {
  95. return self.NatGatewayPrivateInfo.PrivateIpAddress
  96. }
  97. func (self *SNatGateway) GetBandwidthMb() int {
  98. return self.NatGatewayPrivateInfo.MaxBandwidth
  99. }
  100. func (self *SNatGateway) Delete() error {
  101. return self.vpc.region.DeleteNatGateway(self.NatGatewayId, false)
  102. }
  103. func (nat *SNatGateway) GetBillingType() string {
  104. return convertChargeType(nat.InstanceChargeType)
  105. }
  106. func (nat *SNatGateway) GetNatSpec() string {
  107. if len(nat.Spec) == 0 {
  108. return api.ALIYUN_NAT_SKU_DEFAULT
  109. }
  110. return nat.Spec
  111. }
  112. func (self *SNatGateway) Refresh() error {
  113. nat, total, err := self.vpc.region.GetNatGateways("", self.NatGatewayId, 0, 1)
  114. if err != nil {
  115. return errors.Wrapf(err, "GetNatGateways")
  116. }
  117. if total > 1 {
  118. return errors.Wrapf(cloudprovider.ErrDuplicateId, "get %d natgateways by id %s", total, self.NatGatewayId)
  119. }
  120. if total == 0 {
  121. return errors.Wrapf(cloudprovider.ErrNotFound, "%s", self.NatGatewayId)
  122. }
  123. return jsonutils.Update(self, nat[0])
  124. }
  125. func (nat *SNatGateway) GetCreatedAt() time.Time {
  126. return nat.CreationTime
  127. }
  128. func (nat *SNatGateway) GetExpiredAt() time.Time {
  129. return nat.ExpiredTime
  130. }
  131. func (nat *SNatGateway) GetIEips() ([]cloudprovider.ICloudEIP, error) {
  132. eips, err := nat.vpc.region.GetEips("", nat.NatGatewayId, "")
  133. if err != nil {
  134. return nil, err
  135. }
  136. ret := []cloudprovider.ICloudEIP{}
  137. for i := range eips {
  138. eips[i].region = nat.vpc.region
  139. ret = append(ret, &eips[i])
  140. }
  141. return ret, nil
  142. }
  143. func (nat *SNatGateway) GetINatDTable() ([]cloudprovider.ICloudNatDEntry, error) {
  144. itables := []cloudprovider.ICloudNatDEntry{}
  145. for _, dtableId := range nat.ForwardTableIds.ForwardTableId {
  146. dtables, err := nat.vpc.region.GetAllDTables(dtableId)
  147. if err != nil {
  148. return nil, err
  149. }
  150. for i := 0; i < len(dtables); i++ {
  151. dtables[i].nat = nat
  152. itables = append(itables, &dtables[i])
  153. }
  154. }
  155. return itables, nil
  156. }
  157. func (nat *SNatGateway) GetINatSTable() ([]cloudprovider.ICloudNatSEntry, error) {
  158. stables, err := nat.getSnatEntries()
  159. if err != nil {
  160. return nil, err
  161. }
  162. itables := []cloudprovider.ICloudNatSEntry{}
  163. for i := 0; i < len(stables); i++ {
  164. stables[i].nat = nat
  165. itables = append(itables, &stables[i])
  166. }
  167. return itables, nil
  168. }
  169. func (nat *SNatGateway) GetINatDEntryById(id string) (cloudprovider.ICloudNatDEntry, error) {
  170. dNATEntry, err := nat.vpc.region.GetForwardTableEntry(nat.ForwardTableIds.ForwardTableId[0], id)
  171. if err != nil {
  172. return nil, cloudprovider.ErrNotFound
  173. }
  174. dNATEntry.nat = nat
  175. return &dNATEntry, nil
  176. }
  177. func (nat *SNatGateway) GetINatSEntryById(id string) (cloudprovider.ICloudNatSEntry, error) {
  178. sNATEntry, err := nat.vpc.region.GetSNATEntry(nat.SnatTableIds.SnatTableId[0], id)
  179. if err != nil {
  180. return nil, cloudprovider.ErrNotFound
  181. }
  182. sNATEntry.nat = nat
  183. return &sNATEntry, nil
  184. }
  185. func (nat *SNatGateway) CreateINatDEntry(rule cloudprovider.SNatDRule) (cloudprovider.ICloudNatDEntry, error) {
  186. entryID, err := nat.vpc.region.CreateForwardTableEntry(rule, nat.ForwardTableIds.ForwardTableId[0])
  187. if err != nil {
  188. return nil, errors.Wrapf(err, `create dnat rule for nat gateway %q`, nat.GetId())
  189. }
  190. return nat.GetINatDEntryById(entryID)
  191. }
  192. func (nat *SNatGateway) CreateINatSEntry(rule cloudprovider.SNatSRule) (cloudprovider.ICloudNatSEntry, error) {
  193. entryID, err := nat.vpc.region.CreateSNATTableEntry(rule, nat.SnatTableIds.SnatTableId[0])
  194. if err != nil {
  195. return nil, errors.Wrapf(err, `create snat rule for nat gateway %q`, nat.GetId())
  196. }
  197. return nat.GetINatSEntryById(entryID)
  198. }
  199. func (self *SRegion) GetNatGateways(vpcId string, natGwId string, offset, limit int) ([]SNatGateway, int, error) {
  200. if limit > 50 || limit <= 0 {
  201. limit = 50
  202. }
  203. params := make(map[string]string)
  204. params["RegionId"] = self.RegionId
  205. params["PageSize"] = fmt.Sprintf("%d", limit)
  206. params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
  207. if len(vpcId) > 0 {
  208. params["VpcId"] = vpcId
  209. }
  210. if len(natGwId) > 0 {
  211. params["NatGatewayId"] = natGwId
  212. }
  213. body, err := self.vpcRequest("DescribeNatGateways", params)
  214. if err != nil {
  215. return nil, 0, errors.Wrapf(err, "DescribeNatGateways")
  216. }
  217. if self.client.debug {
  218. log.Debugf("%s", body.PrettyString())
  219. }
  220. gateways := make([]SNatGateway, 0)
  221. err = body.Unmarshal(&gateways, "NatGateways", "NatGateway")
  222. if err != nil {
  223. return nil, 0, errors.Wrapf(err, "body.Unmarshal")
  224. }
  225. total, _ := body.Int("TotalCount")
  226. return gateways, int(total), nil
  227. }
  228. func (self *SVpc) CreateINatGateway(opts *cloudprovider.NatGatewayCreateOptions) (cloudprovider.ICloudNatGateway, error) {
  229. nat, err := self.region.CreateNatGateway(opts)
  230. if err != nil {
  231. return nil, errors.Wrapf(err, "CreateNatGateway")
  232. }
  233. nat.vpc = self
  234. return nat, nil
  235. }
  236. func (self *SRegion) CreateNatGateway(opts *cloudprovider.NatGatewayCreateOptions) (*SNatGateway, error) {
  237. params := map[string]string{
  238. "RegionId": self.RegionId,
  239. "VpcId": opts.VpcId,
  240. "VSwitchId": opts.NetworkId,
  241. "NatType": "Enhanced",
  242. "Name": opts.Name,
  243. "Description": opts.Desc,
  244. "ClientToken": utils.GenRequestId(20),
  245. "InstanceChargeType": "PostPaid",
  246. "InternetChargeType": "PayBySpec",
  247. }
  248. if len(opts.NatSpec) == 0 || opts.NatSpec == api.ALIYUN_NAT_SKU_DEFAULT {
  249. params["InternetChargeType"] = "PayByLcu"
  250. } else {
  251. params["Spec"] = opts.NatSpec
  252. }
  253. if opts.BillingCycle != nil {
  254. params["InstanceChargeType"] = "PrePaid"
  255. params["PricingCycle"] = "Month"
  256. params["AutoPay"] = "false"
  257. if opts.BillingCycle.GetYears() > 0 {
  258. params["PricingCycle"] = "Year"
  259. params["Duration"] = fmt.Sprintf("%d", opts.BillingCycle.GetYears())
  260. } else if opts.BillingCycle.GetMonths() > 0 {
  261. params["PricingCycle"] = "Year"
  262. params["Duration"] = fmt.Sprintf("%d", opts.BillingCycle.GetMonths())
  263. }
  264. if opts.BillingCycle.AutoRenew {
  265. params["AutoPay"] = "true"
  266. }
  267. }
  268. resp, err := self.vpcRequest("CreateNatGateway", params)
  269. if err != nil {
  270. return nil, errors.Wrapf(err, "CreateNatGateway")
  271. }
  272. natId, err := resp.GetString("NatGatewayId")
  273. if err != nil {
  274. return nil, errors.Wrapf(err, "resp.Get(NatGatewayId)")
  275. }
  276. if len(natId) == 0 {
  277. return nil, errors.Errorf("empty NatGatewayId after created")
  278. }
  279. var nat *SNatGateway = nil
  280. err = cloudprovider.Wait(time.Second*5, time.Minute*15, func() (bool, error) {
  281. nats, total, err := self.GetNatGateways("", natId, 0, 1)
  282. if err != nil {
  283. return false, errors.Wrapf(err, "GetNatGateways(%s)", natId)
  284. }
  285. if total > 1 {
  286. return false, errors.Wrapf(cloudprovider.ErrDuplicateId, "get %d nats", total)
  287. }
  288. if total == 0 {
  289. return false, errors.Wrapf(cloudprovider.ErrNotFound, "search %s after %s created", opts.Name, natId)
  290. }
  291. nat = &nats[0]
  292. return true, nil
  293. })
  294. if err != nil {
  295. return nil, errors.Wrapf(err, "cloudprovider.Wait")
  296. }
  297. return nat, nil
  298. }
  299. func (self *SRegion) DeleteNatGateway(natId string, isForce bool) error {
  300. params := map[string]string{
  301. "RegionId": self.RegionId,
  302. "NatGatewayId": natId,
  303. }
  304. if isForce {
  305. params["Force"] = "true"
  306. }
  307. _, err := self.vpcRequest("DeleteNatGateway", params)
  308. return errors.Wrapf(err, "DeleteNatGateway")
  309. }
  310. func (self *SNatGateway) GetTags() (map[string]string, error) {
  311. _, tags, err := self.vpc.region.ListSysAndUserTags(ALIYUN_SERVICE_VPC, "NATGATEWAY", self.NatGatewayId)
  312. if err != nil {
  313. return nil, errors.Wrapf(err, "ListTags")
  314. }
  315. tagMaps := map[string]string{}
  316. for k, v := range tags {
  317. tagMaps[strings.ToLower(k)] = v
  318. }
  319. return tagMaps, nil
  320. }
  321. func (self *SNatGateway) GetSysTags() map[string]string {
  322. tags, _, err := self.vpc.region.ListSysAndUserTags(ALIYUN_SERVICE_VPC, "NATGATEWAY", self.NatGatewayId)
  323. if err != nil {
  324. return nil
  325. }
  326. tagMaps := map[string]string{}
  327. for k, v := range tags {
  328. tagMaps[strings.ToLower(k)] = v
  329. }
  330. return tagMaps
  331. }
  332. func (self *SNatGateway) SetTags(tags map[string]string, replace bool) error {
  333. return self.vpc.region.SetResourceTags(ALIYUN_SERVICE_VPC, "NATGATEWAY", self.GetId(), tags, replace)
  334. }