natgateway.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  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 aws
  15. import (
  16. "fmt"
  17. "strings"
  18. "time"
  19. "yunion.io/x/jsonutils"
  20. "yunion.io/x/pkg/errors"
  21. api "yunion.io/x/cloudmux/pkg/apis/compute"
  22. "yunion.io/x/cloudmux/pkg/cloudprovider"
  23. "yunion.io/x/cloudmux/pkg/multicloud"
  24. )
  25. type NatGatewayAddress struct {
  26. AllocationId string `xml:"allocationId"`
  27. NetworkInterfaceId string `xml:"networkInterfaceId"`
  28. PrivateIp string `xml:"privateIp"`
  29. PublicIp string `xml:"publicIp"`
  30. }
  31. type ProvisionedBandwidth struct {
  32. ProvisionTime time.Time `xml:"provisionTime"`
  33. Provisioned string `xml:"provisioned"`
  34. RequestTime time.Time `xml:"requestTime"`
  35. Requested string `xml:"requested"`
  36. Status string `xml:"status"`
  37. }
  38. type SNatGateway struct {
  39. multicloud.SNatGatewayBase
  40. AwsTags
  41. region *SRegion
  42. ConnectivityType string `xml:"connectivityType"`
  43. CreateTime time.Time `xml:"createTime"`
  44. DeleteTime time.Time `xml:"deleteTime"`
  45. FailureCode string `xml:"failureCode"`
  46. FailureMessage string `xml:"failureMessage"`
  47. NatGatewayAddresses []NatGatewayAddress `xml:"natGatewayAddressSet>item"`
  48. NatGatewayId string `xml:"natGatewayId"`
  49. ProvisionedBandwidth ProvisionedBandwidth `xml:"provisionedBandwidth"`
  50. // pending | failed | available | deleting | deleted
  51. State string `xml:"state"`
  52. SubnetId string `xml:"subnetId"`
  53. VpcId string `xml:"vpcId"`
  54. }
  55. func (self *SNatGateway) GetName() string {
  56. name := self.AwsTags.GetName()
  57. if len(name) > 0 {
  58. return name
  59. }
  60. return self.NatGatewayId
  61. }
  62. func (self *SNatGateway) GetId() string {
  63. return self.NatGatewayId
  64. }
  65. func (self *SNatGateway) GetGlobalId() string {
  66. return self.NatGatewayId
  67. }
  68. func (self *SNatGateway) GetStatus() string {
  69. switch self.State {
  70. case "pending":
  71. return api.NAT_STATUS_ALLOCATE
  72. case "failed":
  73. return api.NAT_STATUS_CREATE_FAILED
  74. case "available":
  75. return api.NAT_STAUTS_AVAILABLE
  76. case "deleting", "deleted":
  77. return api.NAT_STATUS_DELETING
  78. default:
  79. return api.NAT_STATUS_UNKNOWN
  80. }
  81. }
  82. func (self *SNatGateway) GetNetworkType() string {
  83. if self.ConnectivityType == "public" {
  84. return api.NAT_NETWORK_TYPE_INTERNET
  85. }
  86. return api.NAT_NETWORK_TYPE_INTRANET
  87. }
  88. func (self *SNatGateway) GetNatSpec() string {
  89. return ""
  90. }
  91. func (self *SNatGateway) Refresh() error {
  92. nat, err := self.region.GetNatGateway(self.NatGatewayId)
  93. if err != nil {
  94. return err
  95. }
  96. return jsonutils.Update(self, nat)
  97. }
  98. func (self *SNatGateway) GetIEips() ([]cloudprovider.ICloudEIP, error) {
  99. ret := []cloudprovider.ICloudEIP{}
  100. for _, addr := range self.NatGatewayAddresses {
  101. if len(addr.PublicIp) > 0 {
  102. eip, err := self.region.GetEipByIpAddress(addr.PublicIp)
  103. if err != nil {
  104. return nil, errors.Wrapf(err, "GetEipByIpAddress")
  105. }
  106. ret = append(ret, eip)
  107. }
  108. }
  109. return ret, nil
  110. }
  111. func (self *SNatGateway) GetINatDTable() ([]cloudprovider.ICloudNatDEntry, error) {
  112. return []cloudprovider.ICloudNatDEntry{}, nil
  113. }
  114. func (self *SNatGateway) GetINatSTable() ([]cloudprovider.ICloudNatSEntry, error) {
  115. return []cloudprovider.ICloudNatSEntry{}, nil
  116. }
  117. func (self *SNatGateway) GetINatDEntryById(id string) (cloudprovider.ICloudNatDEntry, error) {
  118. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", id)
  119. }
  120. func (self *SNatGateway) GetINatSEntryById(id string) (cloudprovider.ICloudNatSEntry, error) {
  121. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", id)
  122. }
  123. func (self *SNatGateway) CreateINatDEntry(rule cloudprovider.SNatDRule) (cloudprovider.ICloudNatDEntry, error) {
  124. return nil, cloudprovider.ErrNotImplemented
  125. }
  126. func (self *SNatGateway) CreateINatSEntry(rule cloudprovider.SNatSRule) (cloudprovider.ICloudNatSEntry, error) {
  127. return nil, cloudprovider.ErrNotImplemented
  128. }
  129. func (self *SNatGateway) GetINetworkId() string {
  130. return self.SubnetId
  131. }
  132. func (self *SNatGateway) GetBandwidthMb() int {
  133. return 0
  134. }
  135. func (self *SNatGateway) GetIpAddr() string {
  136. ipAddrs := []string{}
  137. for _, addr := range self.NatGatewayAddresses {
  138. if len(addr.PrivateIp) > 0 {
  139. ipAddrs = append(ipAddrs, addr.PrivateIp)
  140. }
  141. }
  142. return strings.Join(ipAddrs, ",")
  143. }
  144. func (self *SNatGateway) Delete() error {
  145. return self.region.DeleteNatgateway(self.NatGatewayId)
  146. }
  147. func (self *SRegion) DeleteNatgateway(id string) error {
  148. params := map[string]string{
  149. "NatGatewayId": id,
  150. }
  151. return self.ec2Request("DeleteNatGateway", params, nil)
  152. }
  153. func (self *SRegion) GetNatGateways(ids []string, vpcId, subnetId string) ([]SNatGateway, error) {
  154. params := map[string]string{}
  155. for i, id := range ids {
  156. params[fmt.Sprintf("NatGatewayId.%d", i+1)] = id
  157. }
  158. idx := 1
  159. if len(vpcId) > 0 {
  160. params[fmt.Sprintf("Filter.%d.Name", idx)] = "vpc-id"
  161. params[fmt.Sprintf("Filter.%d.Value.1", idx)] = vpcId
  162. idx++
  163. }
  164. if len(subnetId) > 0 {
  165. params[fmt.Sprintf("Filter.%d.Name", idx)] = "subnet-id"
  166. params[fmt.Sprintf("Filter.%d.Value.1", idx)] = subnetId
  167. idx++
  168. }
  169. params[fmt.Sprintf("Filter.%d.Name", idx)] = "state"
  170. for i, state := range []string{
  171. "pending",
  172. "failed",
  173. "available",
  174. "deleting",
  175. } {
  176. params[fmt.Sprintf("Filter.%d.Value.%d", idx, i+1)] = state
  177. }
  178. idx++
  179. ret := []SNatGateway{}
  180. for {
  181. result := struct {
  182. Nats []SNatGateway `xml:"natGatewaySet>item"`
  183. NextToken string `xml:"nextToken"`
  184. }{}
  185. err := self.ec2Request("DescribeNatGateways", params, &result)
  186. if err != nil {
  187. return nil, errors.Wrapf(err, "DescribeNatGateways")
  188. }
  189. ret = append(ret, result.Nats...)
  190. if len(result.NextToken) == 0 || len(result.Nats) == 0 {
  191. break
  192. }
  193. params["NextToken"] = result.NextToken
  194. }
  195. return ret, nil
  196. }
  197. func (self *SRegion) GetNatGateway(id string) (*SNatGateway, error) {
  198. nats, err := self.GetNatGateways([]string{id}, "", "")
  199. if err != nil {
  200. return nil, errors.Wrapf(err, "GetNatGateways")
  201. }
  202. for i := range nats {
  203. if nats[i].GetGlobalId() == id {
  204. nats[i].region = self
  205. return &nats[i], nil
  206. }
  207. }
  208. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", id)
  209. }
  210. func (self *SVpc) GetINatGateways() ([]cloudprovider.ICloudNatGateway, error) {
  211. nats, err := self.region.GetNatGateways(nil, self.VpcId, "")
  212. if err != nil {
  213. return nil, errors.Wrapf(err, "GetINatGateways")
  214. }
  215. ret := []cloudprovider.ICloudNatGateway{}
  216. for i := range nats {
  217. nats[i].region = self.region
  218. ret = append(ret, &nats[i])
  219. }
  220. return ret, nil
  221. }
  222. func (self *SRegion) DescribeTags(resType, instanceId string) (map[string]string, error) {
  223. params := map[string]string{
  224. "Filter.1.Name": "resource-id",
  225. "Filter.1.Value.1": instanceId,
  226. "Filter.2.Name": "resource-type",
  227. "Filter.2.Value.1": resType,
  228. }
  229. ret := struct {
  230. NextToken string
  231. AwsTags
  232. }{}
  233. err := self.ec2Request("DescribeTags", params, &ret)
  234. if err != nil {
  235. return nil, err
  236. }
  237. return ret.GetTags()
  238. }
  239. func (self *SRegion) DeleteTags(instanceId string, tags map[string]string) error {
  240. params := map[string]string{
  241. "ResourceId.1": instanceId,
  242. }
  243. idx := 1
  244. for k, v := range tags {
  245. params[fmt.Sprintf("Tag.%d.Key", idx)] = k
  246. params[fmt.Sprintf("Tag.%d.Value", idx)] = v
  247. idx++
  248. }
  249. ret := struct {
  250. }{}
  251. return self.ec2Request("DeleteTags", params, &ret)
  252. }
  253. func (self *SRegion) CreateTags(instanceId string, tags map[string]string) error {
  254. params := map[string]string{
  255. "ResourceId.1": instanceId,
  256. }
  257. idx := 1
  258. for k, v := range tags {
  259. params[fmt.Sprintf("Tag.%d.Key", idx)] = k
  260. params[fmt.Sprintf("Tag.%d.Value", idx)] = v
  261. idx++
  262. }
  263. ret := struct {
  264. }{}
  265. return self.ec2Request("CreateTags", params, &ret)
  266. }
  267. func (self *SRegion) setTags(resType, resId string, tags map[string]string, replace bool) error {
  268. oldTags, err := self.DescribeTags(resType, resId)
  269. if err != nil {
  270. return errors.Wrapf(err, "DescribeTags")
  271. }
  272. added, removed := map[string]string{}, map[string]string{}
  273. for k, v := range tags {
  274. oldValue, ok := oldTags[k]
  275. if !ok {
  276. added[k] = v
  277. } else if oldValue != v {
  278. removed[k] = oldValue
  279. added[k] = v
  280. }
  281. }
  282. if replace {
  283. for k, v := range oldTags {
  284. newValue, ok := tags[k]
  285. if !ok {
  286. removed[k] = v
  287. } else if v != newValue {
  288. added[k] = newValue
  289. removed[k] = v
  290. }
  291. }
  292. }
  293. if len(removed) > 0 {
  294. err = self.DeleteTags(resId, removed)
  295. if err != nil {
  296. return errors.Wrapf(err, "DeleteTags %s", removed)
  297. }
  298. }
  299. if len(added) > 0 {
  300. return self.CreateTags(resId, added)
  301. }
  302. return nil
  303. }
  304. func (self *SNatGateway) SetTags(tags map[string]string, replace bool) error {
  305. return self.region.setTags("natgateway", self.NatGatewayId, tags, replace)
  306. }