natgateway.go 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  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 huawei
  15. import (
  16. "net/url"
  17. "strings"
  18. "time"
  19. "yunion.io/x/jsonutils"
  20. "yunion.io/x/pkg/errors"
  21. billing_api "yunion.io/x/cloudmux/pkg/apis/billing"
  22. api "yunion.io/x/cloudmux/pkg/apis/compute"
  23. "yunion.io/x/cloudmux/pkg/cloudprovider"
  24. "yunion.io/x/cloudmux/pkg/multicloud"
  25. )
  26. type SNatGateway struct {
  27. multicloud.SNatGatewayBase
  28. 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_INTRANET
  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. ports, err := gateway.region.GetPorts(gateway.ID)
  96. if err != nil {
  97. return nil, errors.Wrapf(err, "GetPorts(%s)", gateway.ID)
  98. }
  99. ret := []cloudprovider.ICloudEIP{}
  100. for i := range ports {
  101. eips, err := gateway.region.GetEips(ports[i].ID, nil)
  102. if err != nil {
  103. return nil, err
  104. }
  105. for i := range eips {
  106. eips[i].region = gateway.region
  107. ret = append(ret, &eips[i])
  108. }
  109. }
  110. return ret, nil
  111. }
  112. func (gateway *SNatGateway) GetINatDTable() ([]cloudprovider.ICloudNatDEntry, error) {
  113. dNatTable, err := gateway.region.GetNatDEntries(gateway.ID)
  114. if err != nil {
  115. return nil, errors.Wrapf(err, `get dnat table of nat gateway %q`, gateway.GetId())
  116. }
  117. ret := make([]cloudprovider.ICloudNatDEntry, len(dNatTable))
  118. for i := range dNatTable {
  119. dNatTable[i].gateway = gateway
  120. ret[i] = &dNatTable[i]
  121. }
  122. return ret, nil
  123. }
  124. func (gateway *SNatGateway) GetINatSTable() ([]cloudprovider.ICloudNatSEntry, error) {
  125. sNatTable, err := gateway.region.GetNatSEntries(gateway.ID)
  126. if err != nil {
  127. return nil, errors.Wrapf(err, `get dnat table of nat gateway %q`, gateway.GetId())
  128. }
  129. ret := make([]cloudprovider.ICloudNatSEntry, len(sNatTable))
  130. for i := range sNatTable {
  131. sNatTable[i].gateway = gateway
  132. ret[i] = &sNatTable[i]
  133. }
  134. return ret, nil
  135. }
  136. func (gateway *SNatGateway) CreateINatDEntry(rule cloudprovider.SNatDRule) (cloudprovider.ICloudNatDEntry, error) {
  137. dnat, err := gateway.region.CreateNatDEntry(rule, gateway.GetId())
  138. if err != nil {
  139. return nil, err
  140. }
  141. dnat.gateway = gateway
  142. return dnat, nil
  143. }
  144. func (gateway *SNatGateway) CreateINatSEntry(rule cloudprovider.SNatSRule) (cloudprovider.ICloudNatSEntry, error) {
  145. snat, err := gateway.region.CreateNatSEntry(rule, gateway.GetId())
  146. if err != nil {
  147. return nil, err
  148. }
  149. snat.gateway = gateway
  150. return snat, nil
  151. }
  152. func (gateway *SNatGateway) GetINatDEntryById(id string) (cloudprovider.ICloudNatDEntry, error) {
  153. dnat, err := gateway.region.GetNatDEntryByID(id)
  154. if err != nil {
  155. return nil, err
  156. }
  157. dnat.gateway = gateway
  158. return dnat, nil
  159. }
  160. func (gateway *SNatGateway) GetINatSEntryById(id string) (cloudprovider.ICloudNatSEntry, error) {
  161. snat, err := gateway.region.GetNatSEntryByID(id)
  162. if err != nil {
  163. return nil, err
  164. }
  165. snat.gateway = gateway
  166. return snat, nil
  167. }
  168. func (region *SRegion) GetNatGateways(vpcId, id string) ([]SNatGateway, error) {
  169. query := url.Values{}
  170. if len(id) != 0 {
  171. query.Set("id", id)
  172. }
  173. if len(vpcId) != 0 {
  174. query.Set("vpc_id", vpcId)
  175. }
  176. ret := []SNatGateway{}
  177. for {
  178. resp, err := region.list(SERVICE_NAT, "private-nat/gateways", query)
  179. if err != nil {
  180. return nil, err
  181. }
  182. part := struct {
  183. Gateways []SNatGateway
  184. PageInfo sPageInfo
  185. }{}
  186. err = resp.Unmarshal(&part)
  187. if err != nil {
  188. return nil, err
  189. }
  190. ret = append(ret, part.Gateways...)
  191. if len(part.PageInfo.NextMarker) == 0 || len(part.Gateways) == 0 {
  192. break
  193. }
  194. query.Set("marker", part.PageInfo.NextMarker)
  195. }
  196. return ret, nil
  197. }
  198. func (region *SRegion) CreateNatDEntry(rule cloudprovider.SNatDRule, gatewayID string) (*SNatDEntry, error) {
  199. params := make(map[string]interface{})
  200. params["gateway_id"] = gatewayID
  201. params["private_ip"] = rule.InternalIP
  202. params["internal_service_port"] = rule.InternalPort
  203. params["floating_ip_id"] = rule.ExternalIPID
  204. params["external_service_port"] = rule.ExternalPort
  205. params["protocol"] = rule.Protocol
  206. resp, err := region.post(SERVICE_NAT, "private-nat/dnat-rules", map[string]interface{}{"dnat_rule": params})
  207. if err != nil {
  208. return nil, errors.Wrapf(err, "create dnat")
  209. }
  210. ret := &SNatDEntry{}
  211. err = resp.Unmarshal(ret, "dnat_rule")
  212. if err != nil {
  213. return nil, err
  214. }
  215. return ret, nil
  216. }
  217. func (region *SRegion) CreateNatSEntry(rule cloudprovider.SNatSRule, gatewayId string) (*SNatSEntry, error) {
  218. params := make(map[string]interface{})
  219. params["gateway_id"] = gatewayId
  220. if len(rule.NetworkID) != 0 {
  221. params["network_id"] = rule.NetworkID
  222. }
  223. if len(rule.SourceCIDR) != 0 {
  224. params["cidr"] = rule.SourceCIDR
  225. }
  226. params["floating_ip_id"] = rule.ExternalIPID
  227. resp, err := region.post(SERVICE_NAT, "private-nat/snat-rules", map[string]interface{}{"snat_rule": params})
  228. if err != nil {
  229. return nil, errors.Wrapf(err, "create snat")
  230. }
  231. ret := &SNatSEntry{}
  232. err = resp.Unmarshal(ret, "snat_rule")
  233. if err != nil {
  234. return nil, err
  235. }
  236. return ret, nil
  237. }
  238. func (region *SRegion) GetNatDEntryByID(id string) (*SNatDEntry, error) {
  239. resp, err := region.list(SERVICE_NAT, "private-nat/dnat-rules/"+id, nil)
  240. if err != nil {
  241. return nil, err
  242. }
  243. ret := &SNatDEntry{}
  244. err = resp.Unmarshal(ret, "dnat_rule")
  245. if err != nil {
  246. return nil, err
  247. }
  248. return ret, nil
  249. }
  250. func (region *SRegion) GetNatSEntryByID(id string) (*SNatSEntry, error) {
  251. resp, err := region.list(SERVICE_NAT, "private-nat/snat-rules/"+id, nil)
  252. if err != nil {
  253. return nil, err
  254. }
  255. ret := &SNatSEntry{}
  256. err = resp.Unmarshal(ret, "snat_rule")
  257. if err != nil {
  258. return nil, err
  259. }
  260. return ret, nil
  261. }
  262. func NatResouceStatusTransfer(status string) string {
  263. // In Huawei Cloud, there are isx resource status of Nat, "ACTIVE", "PENDING_CREATE",
  264. // "PENDING_UPDATE", "PENDING_DELETE", "EIP_FREEZED", "INACTIVE".
  265. switch status {
  266. case "ACTIVE":
  267. return api.NAT_STAUTS_AVAILABLE
  268. case "PENDING_CREATE":
  269. return api.NAT_STATUS_ALLOCATE
  270. case "PENDING_UPDATE", "PENDING_DELETE":
  271. return api.NAT_STATUS_DEPLOYING
  272. default:
  273. return api.NAT_STATUS_UNKNOWN
  274. }
  275. }
  276. func (self *SRegion) GetNatGateway(id string) (*SNatGateway, error) {
  277. resp, err := self.list(SERVICE_NAT, "private-nat/gateways/"+id, nil)
  278. if err != nil {
  279. return nil, err
  280. }
  281. nat := &SNatGateway{region: self}
  282. err = resp.Unmarshal(nat, "gateway")
  283. if err != nil {
  284. return nil, err
  285. }
  286. return nat, nil
  287. }
  288. func (self *SVpc) CreateINatGateway(opts *cloudprovider.NatGatewayCreateOptions) (cloudprovider.ICloudNatGateway, error) {
  289. nat, err := self.region.CreateNatGateway(opts)
  290. if err != nil {
  291. return nil, errors.Wrapf(err, "CreateNatGateway")
  292. }
  293. return nat, nil
  294. }
  295. func (self *SRegion) CreateNatGateway(opts *cloudprovider.NatGatewayCreateOptions) (*SNatGateway, error) {
  296. spec := ""
  297. switch strings.ToLower(opts.NatSpec) {
  298. case api.NAT_SPEC_SMALL:
  299. spec = "1"
  300. case api.NAT_SPEC_MIDDLE:
  301. spec = "2"
  302. case api.NAT_SPEC_LARGE:
  303. spec = "3"
  304. case api.NAT_SPEC_XLARGE:
  305. spec = "4"
  306. }
  307. params := map[string]interface{}{
  308. "nat_gateway": map[string]interface{}{
  309. "name": opts.Name,
  310. "description": opts.Desc,
  311. "router_id": opts.VpcId,
  312. "internal_network_id": opts.NetworkId,
  313. "spec": spec,
  314. },
  315. }
  316. resp, err := self.post(SERVICE_NAT, "private-nat/gateways", params)
  317. if err != nil {
  318. return nil, errors.Wrap(err, "create nat")
  319. }
  320. nat := &SNatGateway{region: self}
  321. err = resp.Unmarshal(nat, "gateway")
  322. if err != nil {
  323. return nil, errors.Wrapf(err, "resp.Unmarshal")
  324. }
  325. return nat, nil
  326. }
  327. func (self *SRegion) DeleteNatGateway(id string) error {
  328. _, err := self.delete(SERVICE_NAT, "private-nat/gateways/"+id)
  329. return err
  330. }