natgateway.go 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  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 hcso
  15. import (
  16. "strings"
  17. "time"
  18. "yunion.io/x/jsonutils"
  19. "yunion.io/x/pkg/errors"
  20. billing_api "yunion.io/x/cloudmux/pkg/apis/billing"
  21. api "yunion.io/x/cloudmux/pkg/apis/compute"
  22. "yunion.io/x/cloudmux/pkg/cloudprovider"
  23. "yunion.io/x/cloudmux/pkg/multicloud"
  24. "yunion.io/x/cloudmux/pkg/multicloud/huawei"
  25. )
  26. type SNatGateway struct {
  27. multicloud.SNatGatewayBase
  28. huawei.HuaweiTags
  29. region *SRegion
  30. ID string
  31. Name string
  32. Description string
  33. Spec string
  34. Status string
  35. InternalNetworkId string
  36. CreatedTime string `json:"created_at"`
  37. }
  38. func (gateway *SNatGateway) GetId() string {
  39. return gateway.ID
  40. }
  41. func (gateway *SNatGateway) GetName() string {
  42. return gateway.Name
  43. }
  44. func (gateway *SNatGateway) GetGlobalId() string {
  45. return gateway.GetId()
  46. }
  47. func (gateway *SNatGateway) GetStatus() string {
  48. return NatResouceStatusTransfer(gateway.Status)
  49. }
  50. func (self *SNatGateway) Delete() error {
  51. return self.region.DeleteNatGateway(self.ID)
  52. }
  53. func (self *SNatGateway) Refresh() error {
  54. nat, err := self.region.GetNatGateway(self.ID)
  55. if err != nil {
  56. return errors.Wrapf(err, "GetNatGateway(%s)", self.ID)
  57. }
  58. return jsonutils.Update(self, nat)
  59. }
  60. func (self *SNatGateway) GetINetworkId() string {
  61. return self.InternalNetworkId
  62. }
  63. func (self *SNatGateway) GetNetworkType() string {
  64. return api.NAT_NETWORK_TYPE_INTERNET
  65. }
  66. func (gateway *SNatGateway) GetNatSpec() string {
  67. switch gateway.Spec {
  68. case "1":
  69. return api.NAT_SPEC_SMALL
  70. case "2":
  71. return api.NAT_SPEC_MIDDLE
  72. case "3":
  73. return api.NAT_SPEC_LARGE
  74. case "4":
  75. return api.NAT_SPEC_XLARGE
  76. }
  77. return gateway.Spec
  78. }
  79. func (gateway *SNatGateway) GetDescription() string {
  80. return gateway.Description
  81. }
  82. func (gateway *SNatGateway) GetBillingType() string {
  83. // Up to 2019.07.17, only support post pay
  84. return billing_api.BILLING_TYPE_POSTPAID
  85. }
  86. func (gateway *SNatGateway) GetCreatedAt() time.Time {
  87. t, _ := time.Parse("2006-01-02 15:04:05.000000", gateway.CreatedTime)
  88. return t
  89. }
  90. func (gateway *SNatGateway) GetExpiredAt() time.Time {
  91. // no support for expired time
  92. return time.Time{}
  93. }
  94. func (gateway *SNatGateway) GetIEips() ([]cloudprovider.ICloudEIP, error) {
  95. IEips, err := gateway.region.GetIEips()
  96. if err != nil {
  97. return nil, errors.Wrapf(err, `get all Eips of region %q error`, gateway.region.GetId())
  98. }
  99. dNatTables, err := gateway.GetINatDTable()
  100. if err != nil {
  101. return nil, errors.Wrapf(err, `get all DNatTable of gateway %q error`, gateway.GetId())
  102. }
  103. sNatTables, err := gateway.GetINatSTable()
  104. if err != nil {
  105. return nil, errors.Wrapf(err, `get all SNatTable of gateway %q error`, gateway.GetId())
  106. }
  107. // Get natIPSet of nat rules
  108. natIPSet := make(map[string]struct{})
  109. for _, snat := range sNatTables {
  110. natIPSet[snat.GetIP()] = struct{}{}
  111. }
  112. for _, dnat := range dNatTables {
  113. natIPSet[dnat.GetExternalIp()] = struct{}{}
  114. }
  115. // Add Eip whose GetIpAddr() in natIPSet to ret
  116. ret := make([]cloudprovider.ICloudEIP, 0, 2)
  117. for i := range IEips {
  118. if _, ok := natIPSet[IEips[i].GetIpAddr()]; ok {
  119. ret = append(ret, IEips[i])
  120. }
  121. }
  122. return ret, nil
  123. }
  124. func (gateway *SNatGateway) GetINatDTable() ([]cloudprovider.ICloudNatDEntry, error) {
  125. dNatTable, err := gateway.getNatDTable()
  126. if err != nil {
  127. return nil, errors.Wrapf(err, `get dnat table of nat gateway %q`, gateway.GetId())
  128. }
  129. ret := make([]cloudprovider.ICloudNatDEntry, len(dNatTable))
  130. for i := range dNatTable {
  131. ret[i] = &dNatTable[i]
  132. }
  133. return ret, nil
  134. }
  135. func (gateway *SNatGateway) GetINatSTable() ([]cloudprovider.ICloudNatSEntry, error) {
  136. sNatTable, err := gateway.getNatSTable()
  137. if err != nil {
  138. return nil, errors.Wrapf(err, `get dnat table of nat gateway %q`, gateway.GetId())
  139. }
  140. ret := make([]cloudprovider.ICloudNatSEntry, len(sNatTable))
  141. for i := range sNatTable {
  142. ret[i] = &sNatTable[i]
  143. }
  144. return ret, nil
  145. }
  146. func (gateway *SNatGateway) CreateINatDEntry(rule cloudprovider.SNatDRule) (cloudprovider.ICloudNatDEntry, error) {
  147. dnat, err := gateway.region.CreateNatDEntry(rule, gateway.GetId())
  148. if err != nil {
  149. return nil, err
  150. }
  151. dnat.gateway = gateway
  152. return &dnat, nil
  153. }
  154. func (gateway *SNatGateway) CreateINatSEntry(rule cloudprovider.SNatSRule) (cloudprovider.ICloudNatSEntry, error) {
  155. snat, err := gateway.region.CreateNatSEntry(rule, gateway.GetId())
  156. if err != nil {
  157. return nil, err
  158. }
  159. snat.gateway = gateway
  160. return &snat, nil
  161. }
  162. func (gateway *SNatGateway) GetINatDEntryById(id string) (cloudprovider.ICloudNatDEntry, error) {
  163. dnat, err := gateway.region.GetNatDEntryByID(id)
  164. if err != nil {
  165. return nil, err
  166. }
  167. dnat.gateway = gateway
  168. return &dnat, nil
  169. }
  170. func (gateway *SNatGateway) GetINatSEntryById(id string) (cloudprovider.ICloudNatSEntry, error) {
  171. snat, err := gateway.region.GetNatSEntryByID(id)
  172. if err != nil {
  173. return nil, err
  174. }
  175. snat.gateway = gateway
  176. return &snat, nil
  177. }
  178. func (region *SRegion) GetNatGateways(vpcID, natGatewayID string) ([]SNatGateway, error) {
  179. queues := make(map[string]string)
  180. if len(natGatewayID) != 0 {
  181. queues["id"] = natGatewayID
  182. }
  183. if len(vpcID) != 0 {
  184. queues["router_id"] = vpcID
  185. }
  186. natGateways := make([]SNatGateway, 0, 2)
  187. err := doListAllWithMarker(region.ecsClient.NatGateways.List, queues, &natGateways)
  188. if err != nil {
  189. return nil, errors.Wrapf(err, "get nat gateways error by natgatewayid")
  190. }
  191. for i := range natGateways {
  192. natGateways[i].region = region
  193. }
  194. return natGateways, nil
  195. }
  196. func (region *SRegion) CreateNatDEntry(rule cloudprovider.SNatDRule, gatewayID string) (SNatDEntry, error) {
  197. params := make(map[string]interface{})
  198. params["nat_gateway_id"] = gatewayID
  199. params["private_ip"] = rule.InternalIP
  200. params["internal_service_port"] = rule.InternalPort
  201. params["floating_ip_id"] = rule.ExternalIPID
  202. params["external_service_port"] = rule.ExternalPort
  203. params["protocol"] = rule.Protocol
  204. packParams := map[string]map[string]interface{}{
  205. "dnat_rule": params,
  206. }
  207. ret := SNatDEntry{}
  208. err := DoCreate(region.ecsClient.DNatRules.Create, jsonutils.Marshal(packParams), &ret)
  209. if err != nil {
  210. return SNatDEntry{}, errors.Wrapf(err, `create dnat rule of nat gateway %q failed`, gatewayID)
  211. }
  212. return ret, nil
  213. }
  214. func (region *SRegion) CreateNatSEntry(rule cloudprovider.SNatSRule, gatewayID string) (SNatSEntry, error) {
  215. params := make(map[string]interface{})
  216. params["nat_gateway_id"] = gatewayID
  217. if len(rule.NetworkID) != 0 {
  218. params["network_id"] = rule.NetworkID
  219. }
  220. if len(rule.SourceCIDR) != 0 {
  221. params["cidr"] = rule.SourceCIDR
  222. }
  223. params["floating_ip_id"] = rule.ExternalIPID
  224. packParams := map[string]map[string]interface{}{
  225. "snat_rule": params,
  226. }
  227. ret := SNatSEntry{}
  228. err := DoCreate(region.ecsClient.SNatRules.Create, jsonutils.Marshal(packParams), &ret)
  229. if err != nil {
  230. return SNatSEntry{}, errors.Wrapf(err, `create snat rule of nat gateway %q failed`, gatewayID)
  231. }
  232. return ret, nil
  233. }
  234. func (region *SRegion) GetNatDEntryByID(id string) (SNatDEntry, error) {
  235. dnat := SNatDEntry{}
  236. err := DoGet(region.ecsClient.DNatRules.Get, id, map[string]string{}, &dnat)
  237. if err != nil {
  238. return SNatDEntry{}, err
  239. }
  240. return dnat, nil
  241. }
  242. func (region *SRegion) GetNatSEntryByID(id string) (SNatSEntry, error) {
  243. snat := SNatSEntry{}
  244. err := DoGet(region.ecsClient.SNatRules.Get, id, map[string]string{}, &snat)
  245. if err != nil {
  246. return SNatSEntry{}, cloudprovider.ErrNotFound
  247. }
  248. return snat, nil
  249. }
  250. func NatResouceStatusTransfer(status string) string {
  251. // In Huawei Cloud, there are isx resource status of Nat, "ACTIVE", "PENDING_CREATE",
  252. // "PENDING_UPDATE", "PENDING_DELETE", "EIP_FREEZED", "INACTIVE".
  253. switch status {
  254. case "ACTIVE":
  255. return api.NAT_STAUTS_AVAILABLE
  256. case "PENDING_CREATE":
  257. return api.NAT_STATUS_ALLOCATE
  258. case "PENDING_UPDATE", "PENDING_DELETE":
  259. return api.NAT_STATUS_DEPLOYING
  260. default:
  261. return api.NAT_STATUS_UNKNOWN
  262. }
  263. }
  264. func (self *SRegion) GetNatGateway(id string) (*SNatGateway, error) {
  265. resp, err := self.ecsClient.NatGateways.Get(id, nil)
  266. if err != nil {
  267. return nil, errors.Wrapf(err, "NatGateways.Get(%s)", id)
  268. }
  269. nat := &SNatGateway{region: self}
  270. err = resp.Unmarshal(nat)
  271. return nat, errors.Wrap(err, "resp.Unmarshal")
  272. }
  273. func (self *SVpc) CreateINatGateway(opts *cloudprovider.NatGatewayCreateOptions) (cloudprovider.ICloudNatGateway, error) {
  274. nat, err := self.region.CreateNatGateway(opts)
  275. if err != nil {
  276. return nil, errors.Wrapf(err, "CreateNatGateway")
  277. }
  278. return nat, nil
  279. }
  280. func (self *SRegion) CreateNatGateway(opts *cloudprovider.NatGatewayCreateOptions) (*SNatGateway, error) {
  281. spec := ""
  282. switch strings.ToLower(opts.NatSpec) {
  283. case api.NAT_SPEC_SMALL:
  284. spec = "1"
  285. case api.NAT_SPEC_MIDDLE:
  286. spec = "2"
  287. case api.NAT_SPEC_LARGE:
  288. spec = "3"
  289. case api.NAT_SPEC_XLARGE:
  290. spec = "4"
  291. }
  292. params := jsonutils.Marshal(map[string]map[string]interface{}{
  293. "nat_gateway": map[string]interface{}{
  294. "name": opts.Name,
  295. "description": opts.Desc,
  296. "router_id": opts.VpcId,
  297. "internal_network_id": opts.NetworkId,
  298. "spec": spec,
  299. },
  300. })
  301. resp, err := self.ecsClient.NatGateways.Create(params)
  302. if err != nil {
  303. return nil, errors.Wrap(err, "AsyncCreate")
  304. }
  305. nat := &SNatGateway{region: self}
  306. err = resp.Unmarshal(nat)
  307. if err != nil {
  308. return nil, errors.Wrapf(err, "resp.Unmarshal")
  309. }
  310. return nat, nil
  311. }
  312. func (self *SRegion) DeleteNatGateway(id string) error {
  313. _, err := self.ecsClient.NatGateways.Delete(id, nil)
  314. return errors.Wrapf(err, "NatGateways.Delete(%s)", id)
  315. }