natgateway.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. // Copyright 2023 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 volcengine
  15. import (
  16. "fmt"
  17. "time"
  18. billing "yunion.io/x/cloudmux/pkg/apis/billing"
  19. api "yunion.io/x/cloudmux/pkg/apis/compute"
  20. "yunion.io/x/cloudmux/pkg/cloudprovider"
  21. "yunion.io/x/cloudmux/pkg/multicloud"
  22. "yunion.io/x/jsonutils"
  23. "yunion.io/x/pkg/errors"
  24. "yunion.io/x/pkg/utils"
  25. )
  26. type SNatGateway struct {
  27. multicloud.SNatGatewayBase
  28. VolcEngineTags
  29. vpc *SVpc
  30. NatGatewayId string
  31. NatGatewayName string
  32. Description string
  33. Spec string
  34. BillingType int
  35. VpcId string
  36. SubnetId string
  37. ZoneId string
  38. NetworkInterfaceId string
  39. ProjectName string
  40. Status string
  41. BusinessStatus string
  42. LockReason string
  43. CreationTime time.Time
  44. UpdatedAt time.Time
  45. ExpiredTime time.Time
  46. OverdueTime time.Time
  47. DeletedTime time.Time
  48. PrivateIP string
  49. }
  50. func (nat *SNatGateway) GetId() string {
  51. return nat.NatGatewayId
  52. }
  53. func (nat *SNatGateway) GetGlobalId() string {
  54. return nat.NatGatewayId
  55. }
  56. func (nat *SNatGateway) GetName() string {
  57. if len(nat.NatGatewayName) > 0 {
  58. return nat.NatGatewayName
  59. }
  60. return nat.NatGatewayId
  61. }
  62. func (nat *SNatGateway) GetStatus() string {
  63. switch nat.Status {
  64. case "Creating":
  65. return api.NAT_STATUS_ALLOCATE
  66. case "Available":
  67. return api.NAT_STAUTS_AVAILABLE
  68. case "Pending":
  69. return api.NAT_STATUS_DEPLOYING
  70. case "Deleteting":
  71. return api.NAT_STATUS_DELETING
  72. default:
  73. return api.NAT_STATUS_UNKNOWN
  74. }
  75. }
  76. func (nat *SNatGateway) GetINetworkId() string {
  77. return nat.SubnetId
  78. }
  79. func (nat *SNatGateway) GetNetworkType() string {
  80. return api.NAT_NETWORK_TYPE_INTERNET
  81. }
  82. func (nat *SNatGateway) GetIpAddr() string {
  83. if len(nat.PrivateIP) > 0 {
  84. return nat.PrivateIP
  85. }
  86. return ""
  87. }
  88. func (nat *SNatGateway) GetBandwidthMb() int {
  89. return 0
  90. }
  91. func (nat *SNatGateway) Delete() error {
  92. return nat.vpc.region.DeleteNatGateway(nat.NatGatewayId, false)
  93. }
  94. func (nat *SNatGateway) GetBillingType() string {
  95. switch nat.BillingType {
  96. case 1:
  97. return billing.BILLING_TYPE_PREPAID
  98. case 2:
  99. return billing.BILLING_TYPE_POSTPAID
  100. default:
  101. return ""
  102. }
  103. }
  104. func (nat *SNatGateway) GetNatSpec() string {
  105. if len(nat.Spec) == 0 {
  106. return "Small"
  107. }
  108. return nat.Spec
  109. }
  110. func (nat *SNatGateway) Refresh() error {
  111. newNat, _, err := nat.vpc.region.GetNatGateways("", nat.NatGatewayId, 1, 1)
  112. if err != nil {
  113. return errors.Wrapf(err, "GetNatGateways")
  114. }
  115. for _, nt := range newNat {
  116. if nt.NatGatewayId == nat.NatGatewayId {
  117. return jsonutils.Update(nat, nt)
  118. }
  119. }
  120. return errors.Wrapf(cloudprovider.ErrNotFound, "%s not found", nat.NatGatewayId)
  121. }
  122. func (nat *SNatGateway) GetCreatedAt() time.Time {
  123. return nat.CreationTime
  124. }
  125. func (nat *SNatGateway) GetExpiredAt() time.Time {
  126. return nat.ExpiredTime
  127. }
  128. func (nat *SNatGateway) GetINatDTable() ([]cloudprovider.ICloudNatDEntry, error) {
  129. stables, err := nat.getDnatEntries()
  130. if err != nil {
  131. return nil, err
  132. }
  133. itables := []cloudprovider.ICloudNatDEntry{}
  134. for i := 0; i < len(stables); i++ {
  135. stables[i].nat = nat
  136. itables = append(itables, &stables[i])
  137. }
  138. return itables, nil
  139. }
  140. func (nat *SNatGateway) GetINatSTable() ([]cloudprovider.ICloudNatSEntry, error) {
  141. stables, err := nat.getSnatEntries()
  142. if err != nil {
  143. return nil, err
  144. }
  145. itables := []cloudprovider.ICloudNatSEntry{}
  146. for i := 0; i < len(stables); i++ {
  147. stables[i].nat = nat
  148. itables = append(itables, &stables[i])
  149. }
  150. return itables, nil
  151. }
  152. func (nat *SNatGateway) GetINatDEntryById(id string) (cloudprovider.ICloudNatDEntry, error) {
  153. dNATEntry, err := nat.vpc.region.GetDnatEntry(nat.NatGatewayId, id)
  154. if err != nil {
  155. return nil, cloudprovider.ErrNotFound
  156. }
  157. dNATEntry.nat = nat
  158. return &dNATEntry, nil
  159. }
  160. func (nat *SNatGateway) GetINatSEntryById(id string) (cloudprovider.ICloudNatSEntry, error) {
  161. sNATEntry, err := nat.vpc.region.GetSnatEntry(nat.NatGatewayId, id)
  162. if err != nil {
  163. return nil, cloudprovider.ErrNotFound
  164. }
  165. sNATEntry.nat = nat
  166. return &sNATEntry, nil
  167. }
  168. func (nat *SNatGateway) CreateINatDEntry(rule cloudprovider.SNatDRule) (cloudprovider.ICloudNatDEntry, error) {
  169. entryID, err := nat.vpc.region.CreateDnatEntry(rule, nat.NatGatewayId)
  170. if err != nil {
  171. return nil, errors.Wrapf(err, `create dnat rule for nat gateway %q`, nat.GetId())
  172. }
  173. return nat.GetINatDEntryById(entryID)
  174. }
  175. func (nat *SNatGateway) CreateINatSEntry(rule cloudprovider.SNatSRule) (cloudprovider.ICloudNatSEntry, error) {
  176. entryID, err := nat.vpc.region.CreateSnatEntry(rule, nat.NatGatewayId)
  177. if err != nil {
  178. return nil, errors.Wrapf(err, `create snat rule for nat gateway %q`, nat.GetId())
  179. }
  180. return nat.GetINatSEntryById(entryID)
  181. }
  182. func (region *SRegion) GetNatGateways(vpcId string, natGatewayId string, pageNumber int, pageSize int) ([]SNatGateway, int, error) {
  183. if pageSize > 100 || pageSize <= 0 {
  184. pageSize = 100
  185. }
  186. params := make(map[string]string)
  187. params["PageSize"] = fmt.Sprintf("%d", pageSize)
  188. params["PageNumber"] = fmt.Sprintf("%d", pageNumber)
  189. if len(vpcId) > 0 {
  190. params["VpcId"] = vpcId
  191. }
  192. if len(natGatewayId) > 0 {
  193. params["NatGatewayId.1"] = natGatewayId
  194. }
  195. body, err := region.natRequest("DescribeNatGateways", params)
  196. if err != nil {
  197. return nil, 0, errors.Wrapf(err, "DescribeNatGateways")
  198. }
  199. gateways := make([]SNatGateway, 0)
  200. err = body.Unmarshal(&gateways, "NatGateways")
  201. if err != nil {
  202. return nil, 0, errors.Wrapf(err, "body.Unmarshal")
  203. }
  204. total, _ := body.Int("TotalCount")
  205. return gateways, int(total), nil
  206. }
  207. func (region *SRegion) CreateNatGateway(opts *cloudprovider.NatGatewayCreateOptions) (*SNatGateway, error) {
  208. params := map[string]string{
  209. "VpcId": opts.VpcId,
  210. "SubnetId": opts.NetworkId,
  211. "NatGatewayName": opts.Name,
  212. "Description": opts.Desc,
  213. "ClientToken": utils.GenRequestId(20),
  214. "BillingType": fmt.Sprintf("%d", 2),
  215. }
  216. if len(opts.NatSpec) != 0 {
  217. params["Spec"] = opts.NatSpec
  218. }
  219. if opts.BillingCycle != nil {
  220. params["BillingType"] = fmt.Sprintf("%d", 1)
  221. params["Period"] = fmt.Sprintf("%d", 1)
  222. params["PeriodUnit"] = "Month"
  223. if opts.BillingCycle.GetYears() > 0 {
  224. params["PeriodUnit"] = "Year"
  225. params["Period"] = fmt.Sprintf("%d", opts.BillingCycle.GetYears())
  226. } else if opts.BillingCycle.GetMonths() > 0 {
  227. params["PeriodUnit"] = "Month"
  228. params["Period"] = fmt.Sprintf("%d", opts.BillingCycle.GetMonths())
  229. }
  230. }
  231. resp, err := region.natRequest("CreateNatGateway", params)
  232. if err != nil {
  233. return nil, errors.Wrapf(err, "CreateNatGateway")
  234. }
  235. natId, err := resp.GetString("NatGatewayId")
  236. if err != nil {
  237. return nil, errors.Wrapf(err, "resp.Get(NatGatewayId)")
  238. }
  239. if len(natId) == 0 {
  240. return nil, errors.Errorf("empty NatGatewayId after created")
  241. }
  242. err = cloudprovider.Wait(time.Second*5, time.Minute*15, func() (bool, error) {
  243. _, _, err := region.GetNatGateways("", natId, 1, 1)
  244. if errors.Cause(err) == cloudprovider.ErrNotFound {
  245. return false, nil
  246. } else {
  247. return true, err
  248. }
  249. })
  250. if err != nil {
  251. return nil, errors.Wrapf(err, "cannot find nat gateway after create")
  252. }
  253. nats, _, err := region.GetNatGateways("", natId, 1, 1)
  254. for _, nat := range nats {
  255. if nat.NatGatewayId == natId {
  256. return &nat, nil
  257. }
  258. }
  259. return nil, errors.Wrapf(err, "%s not found", natId)
  260. }
  261. func (region *SRegion) DeleteNatGateway(natId string, isForce bool) error {
  262. params := make(map[string]string)
  263. params["NatGatewayId"] = natId
  264. _, err := region.natRequest("DeleteNatGateway", params)
  265. return errors.Wrapf(err, "DeleteNatGateway")
  266. }