region.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842
  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. "context"
  17. "fmt"
  18. "strings"
  19. "sync"
  20. "github.com/aws/aws-sdk-go-v2/service/s3"
  21. "github.com/aws/aws-sdk-go-v2/service/s3/types"
  22. "github.com/aws/aws-sdk-go/aws/session"
  23. "github.com/aws/aws-sdk-go/service/organizations"
  24. "github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
  25. "github.com/aws/aws-sdk-go/service/wafv2"
  26. "yunion.io/x/log"
  27. "yunion.io/x/pkg/errors"
  28. "yunion.io/x/pkg/gotypes"
  29. api "yunion.io/x/cloudmux/pkg/apis/compute"
  30. "yunion.io/x/cloudmux/pkg/cloudprovider"
  31. "yunion.io/x/cloudmux/pkg/multicloud"
  32. )
  33. var (
  34. lock sync.RWMutex
  35. )
  36. var RegionLocations = map[string]string{
  37. "us-east-2": "美国东部(俄亥俄州)",
  38. "us-east-1": "美国东部(弗吉尼亚北部)",
  39. "us-west-1": "美国西部(加利福尼亚北部)",
  40. "us-west-2": "美国西部(俄勒冈)",
  41. "ap-east-1": "亚太区域(香港)",
  42. "ap-south-1": "亚太区域(孟买)",
  43. "ap-northeast-3": "亚太区域(大阪-本地)",
  44. "ap-northeast-2": "亚太区域(首尔)",
  45. "ap-southeast-1": "亚太区域(新加坡)",
  46. "ap-southeast-2": "亚太区域(悉尼)",
  47. "ap-northeast-1": "亚太区域(东京)",
  48. "ca-central-1": "加拿大(中部)",
  49. "cn-north-1": "中国(北京)",
  50. "cn-northwest-1": "中国(宁夏)",
  51. "eu-central-1": "欧洲(法兰克福)",
  52. "eu-west-1": "欧洲(爱尔兰)",
  53. "eu-west-2": "欧洲(伦敦)",
  54. "eu-south-1": "欧洲(米兰)",
  55. "eu-west-3": "欧洲(巴黎)",
  56. "eu-north-1": "欧洲(斯德哥尔摩)",
  57. "me-south-1": "中东(巴林)",
  58. "sa-east-1": "南美洲(圣保罗)",
  59. "us-gov-west-1": "AWS GovCloud(美国西部)",
  60. "us-gov-east-1": "AWS GovCloud(美国东部)",
  61. "af-south-1": "非洲(开普敦)",
  62. "ap-southeast-4": "亚太地区(墨尔本)",
  63. "ap-south-2": "亚太地区(德拉巴)",
  64. "eu-south-2": "欧洲(西班牙)",
  65. "eu-central-2": "欧洲(苏黎世)",
  66. "me-central-1": "中东(阿联酋)",
  67. "ap-southeast-3": "亚太地区(雅加达)",
  68. "il-central-1": "以色列(特拉维夫)",
  69. "ap-southeast-6": "亚太地区(新西兰)",
  70. "ap-east-2": "亚太地区(台北)",
  71. "mx-central-1": "北美地区(墨西哥)",
  72. "ap-southeast-7": "亚太地区(泰国)",
  73. "ap-southeast-5": "亚太地区(马来西亚)",
  74. "ca-west-1": "加拿大(卡尔加里)",
  75. }
  76. // https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html
  77. var RegionLocationsEN = map[string]string{
  78. "us-east-1": "US East (N. Virginia)",
  79. "us-east-2": "US East (Ohio)",
  80. "us-west-1": "US West (N. California)",
  81. "us-west-2": "US West (Oregon)",
  82. "af-south-1": "Africa (Cape Town)",
  83. "ap-east-1": "Asia Pacific (Hong Kong)",
  84. "ap-south-1": "Asia Pacific (Mumbai)",
  85. "ap-northeast-3": "Asia Pacific (Osaka)",
  86. "ap-northeast-2": "Asia Pacific (Seoul)",
  87. "ap-southeast-1": "Asia Pacific (Singapore)",
  88. "ap-southeast-2": "Asia Pacific (Sydney)",
  89. "ap-northeast-1": "Asia Pacific (Tokyo)",
  90. "ca-central-1": "Canada (Central)",
  91. "eu-central-1": "Europe (Frankfurt)",
  92. "eu-west-1": "Europe (Ireland)",
  93. "eu-west-2": "Europe (London)",
  94. "eu-south-1": "Europe (Milan)",
  95. "eu-west-3": "Europe (Paris)",
  96. "eu-north-1": "Europe (Stockholm)",
  97. "me-south-1": "Middle East (Bahrain)",
  98. "sa-east-1": "South America (São Paulo)",
  99. "cn-north-1": "China (Beijing)",
  100. "cn-northwest-1": "China (Ninxia)",
  101. "us-gov-west-1": "AWS GovCloud(US West)",
  102. "us-gov-east-1": "AWS GovCloud(US East)",
  103. "ap-southeast-4": "Asia Pacific (Melbourne)",
  104. "ap-south-2": "Asia Pacific (Hyderabad)",
  105. "eu-south-2": "Europe (Spain)",
  106. "eu-central-2": "Europe (Zurich)",
  107. "me-central-1": "Middle East (UAE)",
  108. "ap-southeast-3": "Asia Pacific (Jakarta)",
  109. "il-central-1": "Israel (Tel Aviv)",
  110. "ap-southeast-6": "Asia Pacific (New Zealand)",
  111. "ap-east-2": "Asia Pacific (Taipei)",
  112. "mx-central-1": "North America (Mexico)",
  113. "ap-southeast-7": "Asia Pacific (Thailand)",
  114. "ap-southeast-5": "Asia Pacific (Malaysia)",
  115. "ca-west-1": "Canada (Calgary)",
  116. }
  117. const (
  118. RDS_SERVICE_NAME = "rds"
  119. RDS_SERVICE_ID = "RDS"
  120. EC2_SERVICE_NAME = "ec2"
  121. EC2_SERVICE_ID = "EC2"
  122. IAM_SERVICE_NAME = "iam"
  123. IAM_SERVICE_ID = "IAM"
  124. STS_SERVICE_NAME = "sts"
  125. STS_SERVICE_ID = "STS"
  126. CLOUDWATCH_SERVICE_NAME = "monitoring"
  127. CLOUDWATCH_SERVICE_ID = "CloudWatch"
  128. CLOUD_TRAIL_SERVICE_NAME = "CloudTrail"
  129. CLOUD_TRAIL_SERVICE_ID = "cloudtrail"
  130. ROUTE53_SERVICE_NAME = "route53"
  131. ROUTE53_SERVICE_ID = "Route 53"
  132. ELASTICACHE_SERVICE_NAME = "elasticache"
  133. ELASTICACHE_SERVICE_ID = "ElastiCache"
  134. ELB_SERVICE_NAME = "elasticloadbalancing"
  135. ELB_SERVICE_ID = "Elastic Load Balancing v2"
  136. EKS_SERVICE_NAME = "eks"
  137. EKS_SERVICE_ID = "EKS"
  138. PRICING_SERVICE_NAME = "api.pricing"
  139. PRICING_SERVICE_ID = "Pricing"
  140. CDN_SERVICE_NAME = "cloudfront"
  141. CDN_SERVICE_ID = "CloudFront"
  142. ECS_SERVICE_NAME = "ecs"
  143. ECS_SERVICE_ID = "ECS"
  144. LAMBDA_SERVICE_NAME = "lambda"
  145. LAMBDA_SERVICE_ID = "Lambda"
  146. KINESIS_SERVICE_NAME = "kinesis"
  147. KINESIS_SERVICE_ID = "Kinesis"
  148. DYNAMODB_SERVICE_NAME = "dynamodb"
  149. DYNAMODB_SERVICE_ID = "DynamoDB"
  150. )
  151. type SRegion struct {
  152. multicloud.SRegion
  153. client *SAwsClient
  154. s3Client *s3.Client
  155. wafClient *wafv2.WAFV2
  156. organizationClient *organizations.Organizations
  157. resourceGroupTagClient *resourcegroupstaggingapi.ResourceGroupsTaggingAPI
  158. RegionEndpoint string `xml:"regionEndpoint"`
  159. RegionId string `xml:"regionName"`
  160. OptInStatus string `xml:"optInStatus"`
  161. }
  162. /////////////////////////////////////////////////////////////////////////////
  163. /* 请不要使用这个client(AWS_DEFAULT_REGION)跨region查信息.有可能导致查询返回的信息为空。比如DescribeAvailabilityZones*/
  164. func (self *SRegion) GetClient() *SAwsClient {
  165. return self.client
  166. }
  167. func (self *SRegion) getAwsSession() (*session.Session, error) {
  168. return self.client.getAwsSession(self.RegionId, true)
  169. }
  170. func (self *SRegion) getWafClient() (*wafv2.WAFV2, error) {
  171. if self.wafClient == nil {
  172. s, err := self.getAwsSession()
  173. if err != nil {
  174. return nil, errors.Wrapf(err, "getAwsSession")
  175. }
  176. self.wafClient = wafv2.New(s)
  177. }
  178. return self.wafClient, nil
  179. }
  180. func (self *SRegion) getResourceGroupTagClient() (*resourcegroupstaggingapi.ResourceGroupsTaggingAPI, error) {
  181. if self.resourceGroupTagClient == nil {
  182. s, err := self.getAwsSession()
  183. if err != nil {
  184. return nil, errors.Wrap(err, "getAwsSession")
  185. }
  186. self.resourceGroupTagClient = resourcegroupstaggingapi.New(s)
  187. }
  188. return self.resourceGroupTagClient, nil
  189. }
  190. func (self *SRegion) elbRequest(apiName string, params map[string]string, retval interface{}) error {
  191. return self.client.request(self.RegionId, ELB_SERVICE_NAME, ELB_SERVICE_ID, "2015-12-01", apiName, params, retval, true)
  192. }
  193. func (self *SRegion) rdsRequest(apiName string, params map[string]string, retval interface{}) error {
  194. return self.client.request(self.RegionId, RDS_SERVICE_NAME, RDS_SERVICE_ID, "2014-10-31", apiName, params, retval, true)
  195. }
  196. func (self *SRegion) ecRequest(apiName string, params map[string]string, retval interface{}) error {
  197. return self.client.request(self.RegionId, ELASTICACHE_SERVICE_NAME, ELASTICACHE_SERVICE_ID, "2015-02-02", apiName, params, retval, true)
  198. }
  199. func (self *SRegion) ec2Request(apiName string, params map[string]string, retval interface{}) error {
  200. return self.client.ec2Request(self.RegionId, apiName, params, retval, true)
  201. }
  202. func (self *SAwsClient) monitorRequest(regionId, apiName string, params map[string]string, retval interface{}) error {
  203. return self.request(regionId, CLOUDWATCH_SERVICE_NAME, CLOUDWATCH_SERVICE_ID, "2010-08-01", apiName, params, retval, true)
  204. }
  205. // Amazon Elastic Container Service
  206. func (self *SRegion) ecsRequest(apiName string, params map[string]interface{}, retval interface{}) error {
  207. return self.client.ecsRequest(self.RegionId, apiName, params, retval, true)
  208. }
  209. func (self *SRegion) lambdaRequest(apiName, path string, params map[string]interface{}, retval interface{}) error {
  210. return self.client.lambdaRequest(self.RegionId, apiName, path, params, retval, true)
  211. }
  212. func (self *SRegion) kinesisRequest(apiName, path string, params map[string]interface{}, retval interface{}) error {
  213. return self.client.kinesisRequest(self.RegionId, apiName, path, params, retval, true)
  214. }
  215. func (self *SRegion) dynamodbRequest(apiName string, params map[string]interface{}, retval interface{}) error {
  216. return self.client.invoke(self.RegionId, DYNAMODB_SERVICE_NAME, DYNAMODB_SERVICE_ID, "2012-08-10", apiName, "", params, retval, true)
  217. }
  218. func (self *SRegion) eksRequest(apiName, path string, params map[string]interface{}, retval interface{}) error {
  219. return self.client.invoke(self.RegionId, EKS_SERVICE_NAME, EKS_SERVICE_ID, "2017-11-01", apiName, path, params, retval, true)
  220. }
  221. // ///////////////////////////////////////////////////////////////////////////
  222. func (self *SRegion) GetZones(id string) ([]SZone, error) {
  223. params := map[string]string{
  224. "Filter.1.Name": "region-name",
  225. "Filter.1.Value.1": self.RegionId,
  226. }
  227. if len(id) > 0 {
  228. params["Filter.2.Name"] = "zone-id"
  229. params["Filter.2.Value.1"] = id
  230. }
  231. ret := struct {
  232. AvailabilityZoneInfo []SZone `xml:"availabilityZoneInfo>item"`
  233. }{}
  234. err := self.ec2Request("DescribeAvailabilityZones", params, &ret)
  235. if err != nil {
  236. return nil, err
  237. }
  238. return ret.AvailabilityZoneInfo, nil
  239. }
  240. func (self *SRegion) GetId() string {
  241. return self.RegionId
  242. }
  243. func (self *SRegion) GetName() string {
  244. if localName, ok := RegionLocations[self.RegionId]; ok {
  245. return fmt.Sprintf("%s %s", CLOUD_PROVIDER_AWS_CN, localName)
  246. }
  247. return fmt.Sprintf("%s %s", CLOUD_PROVIDER_AWS_CN, self.RegionId)
  248. }
  249. func (self *SRegion) GetI18n() cloudprovider.SModelI18nTable {
  250. var en string
  251. if localName, ok := RegionLocationsEN[self.RegionId]; ok {
  252. en = fmt.Sprintf("%s %s", CLOUD_PROVIDER_AWS_EN, localName)
  253. } else {
  254. en = fmt.Sprintf("%s %s", CLOUD_PROVIDER_AWS_EN, self.RegionId)
  255. }
  256. table := cloudprovider.SModelI18nTable{}
  257. table["name"] = cloudprovider.NewSModelI18nEntry(self.GetName()).CN(self.GetName()).EN(en)
  258. return table
  259. }
  260. func (self *SRegion) GetGlobalId() string {
  261. return fmt.Sprintf("%s/%s", self.client.GetAccessEnv(), self.RegionId)
  262. }
  263. func (self *SRegion) GetStatus() string {
  264. return api.CLOUD_REGION_STATUS_INSERVER
  265. }
  266. func (self *SRegion) Refresh() error {
  267. return nil
  268. }
  269. func (self *SRegion) IsEmulated() bool {
  270. return false
  271. }
  272. func (self *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo {
  273. if info, ok := LatitudeAndLongitude[self.RegionId]; ok {
  274. return info
  275. }
  276. return cloudprovider.SGeographicInfo{}
  277. }
  278. func (self *SRegion) GetIZones() ([]cloudprovider.ICloudZone, error) {
  279. zones, err := self.GetZones("")
  280. if err != nil {
  281. return nil, errors.Wrapf(err, "GetZones")
  282. }
  283. ret := []cloudprovider.ICloudZone{}
  284. for i := range zones {
  285. zones[i].region = self
  286. ret = append(ret, &zones[i])
  287. }
  288. return ret, nil
  289. }
  290. func (self *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) {
  291. vpcs, err := self.GetVpcs(nil)
  292. if err != nil {
  293. return nil, errors.Wrapf(err, "GetVpcs")
  294. }
  295. ret := []cloudprovider.ICloudVpc{}
  296. for i := range vpcs {
  297. vpcs[i].region = self
  298. ret = append(ret, &vpcs[i])
  299. }
  300. return ret, nil
  301. }
  302. func (self *SRegion) GetIVMById(id string) (cloudprovider.ICloudVM, error) {
  303. return self.GetInstance(id)
  304. }
  305. func (self *SRegion) GetIDiskById(id string) (cloudprovider.ICloudDisk, error) {
  306. return self.GetDisk(id)
  307. }
  308. func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
  309. eips, err := self.GetEips("", "", "")
  310. if err != nil {
  311. return nil, errors.Wrap(err, "GetEips")
  312. }
  313. ret := []cloudprovider.ICloudEIP{}
  314. for i := range eips {
  315. eips[i].region = self
  316. ret = append(ret, &eips[i])
  317. }
  318. return ret, nil
  319. }
  320. func (self *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
  321. snapshots, err := self.GetSnapshots("", "", []string{})
  322. if err != nil {
  323. return nil, errors.Wrap(err, "GetSnapshots")
  324. }
  325. ret := []cloudprovider.ICloudSnapshot{}
  326. for i := 0; i < len(snapshots); i += 1 {
  327. snapshots[i].region = self
  328. ret = append(ret, &snapshots[i])
  329. }
  330. return ret, nil
  331. }
  332. func (self *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) {
  333. zones, err := self.GetZones("")
  334. if err != nil {
  335. return nil, errors.Wrap(err, "GetZones")
  336. }
  337. for i := range zones {
  338. zones[i].region = self
  339. if zones[i].GetId() == id || zones[i].GetGlobalId() == id {
  340. return &zones[i], nil
  341. }
  342. }
  343. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", id)
  344. }
  345. func (self *SRegion) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) {
  346. vpcs, err := self.GetVpcs([]string{id})
  347. if err != nil {
  348. return nil, errors.Wrap(err, "GetIVpcs")
  349. }
  350. for i := range vpcs {
  351. vpcs[i].region = self
  352. if vpcs[i].GetGlobalId() == id {
  353. return &vpcs[i], nil
  354. }
  355. }
  356. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "GetIVpcById %s", id)
  357. }
  358. func (self *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
  359. izones, err := self.GetIZones()
  360. if err != nil {
  361. return nil, errors.Wrap(err, "GetIZones")
  362. }
  363. for i := 0; i < len(izones); i += 1 {
  364. ihost, err := izones[i].GetIHostById(id)
  365. if err != nil && errors.Cause(err) != cloudprovider.ErrNotFound {
  366. return nil, err
  367. }
  368. if !gotypes.IsNil(ihost) {
  369. return ihost, nil
  370. }
  371. }
  372. return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetIHostById")
  373. }
  374. func (self *SRegion) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
  375. izones, err := self.GetIZones()
  376. if err != nil {
  377. return nil, errors.Wrap(err, "GetIZones")
  378. }
  379. for i := 0; i < len(izones); i += 1 {
  380. istore, err := izones[i].GetIStorageById(id)
  381. if err != nil && errors.Cause(err) != cloudprovider.ErrNotFound {
  382. return nil, err
  383. }
  384. if !gotypes.IsNil(istore) {
  385. return istore, nil
  386. }
  387. }
  388. return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetIStorageById")
  389. }
  390. func (self *SRegion) GetIHosts() ([]cloudprovider.ICloudHost, error) {
  391. iHosts := make([]cloudprovider.ICloudHost, 0)
  392. izones, err := self.GetIZones()
  393. if err != nil {
  394. return nil, errors.Wrap(err, "GetIZones")
  395. }
  396. for i := 0; i < len(izones); i += 1 {
  397. iZoneHost, err := izones[i].GetIHosts()
  398. if err != nil {
  399. return nil, errors.Wrap(err, "GetIHosts")
  400. }
  401. iHosts = append(iHosts, iZoneHost...)
  402. }
  403. return iHosts, nil
  404. }
  405. func (self *SRegion) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
  406. iStores := make([]cloudprovider.ICloudStorage, 0)
  407. izones, err := self.GetIZones()
  408. if err != nil {
  409. return nil, errors.Wrap(err, "GetIZones")
  410. }
  411. for i := 0; i < len(izones); i += 1 {
  412. iZoneStores, err := izones[i].GetIStorages()
  413. if err != nil {
  414. return nil, errors.Wrap(err, "GetIStorages")
  415. }
  416. iStores = append(iStores, iZoneStores...)
  417. }
  418. return iStores, nil
  419. }
  420. func (self *SRegion) getStorageCache() *SStoragecache {
  421. return &SStoragecache{region: self}
  422. }
  423. func (self *SRegion) GetIStoragecacheById(id string) (cloudprovider.ICloudStoragecache, error) {
  424. caches, err := self.GetIStoragecaches()
  425. if err != nil {
  426. return nil, err
  427. }
  428. for i := range caches {
  429. if caches[i].GetGlobalId() == id {
  430. return caches[i], nil
  431. }
  432. }
  433. return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetIStoragecacheById")
  434. }
  435. func (self *SRegion) CreateIVpc(opts *cloudprovider.VpcCreateOptions) (cloudprovider.ICloudVpc, error) {
  436. vpc, err := self.CreateVpc(opts)
  437. if err != nil {
  438. return nil, errors.Wrapf(err, "CreateVpc")
  439. }
  440. return vpc, nil
  441. }
  442. func (self *SRegion) CreateVpc(opts *cloudprovider.VpcCreateOptions) (*SVpc, error) {
  443. params := map[string]string{
  444. "CidrBlock": opts.CIDR,
  445. }
  446. tagIdx := 1
  447. if len(opts.NAME) > 0 {
  448. params["TagSpecification.1.ResourceType"] = "vpc"
  449. params[fmt.Sprintf("TagSpecification.%d.Tag.1.Key", tagIdx)] = "Name"
  450. params[fmt.Sprintf("TagSpecification.%d.Tag.1.Value", tagIdx)] = opts.NAME
  451. if len(opts.Desc) > 0 {
  452. params[fmt.Sprintf("TagSpecification.%d.Tag.2.Key", tagIdx)] = "Description"
  453. params[fmt.Sprintf("TagSpecification.%d.Tag.2.Value", tagIdx)] = opts.Desc
  454. }
  455. tagIdx++
  456. }
  457. ret := struct {
  458. Vpc SVpc `xml:"vpc"`
  459. }{}
  460. err := self.ec2Request("CreateVpc", params, &ret)
  461. if err != nil {
  462. return nil, err
  463. }
  464. ret.Vpc.region = self
  465. return &ret.Vpc, nil
  466. }
  467. func (self *SRegion) GetIEipById(id string) (cloudprovider.ICloudEIP, error) {
  468. eip, err := self.GetEip(id)
  469. if err != nil {
  470. return nil, errors.Wrap(err, "GetEip")
  471. }
  472. return eip, nil
  473. }
  474. func (self *SRegion) GetProvider() string {
  475. return CLOUD_PROVIDER_AWS
  476. }
  477. func (self *SRegion) GetCloudEnv() string {
  478. return self.client.accessUrl
  479. }
  480. func (self *SRegion) GetILoadBalancers() ([]cloudprovider.ICloudLoadbalancer, error) {
  481. ret := []cloudprovider.ICloudLoadbalancer{}
  482. marker := ""
  483. for {
  484. part, marker, err := self.GetLoadbalancers("", marker)
  485. if err != nil {
  486. return nil, errors.Wrapf(err, "GetLoadbalancers")
  487. }
  488. for i := range part {
  489. part[i].region = self
  490. ret = append(ret, &part[i])
  491. }
  492. if len(marker) == 0 || len(part) == 0 {
  493. break
  494. }
  495. }
  496. return ret, nil
  497. }
  498. func (self *SRegion) GetLoadBalancer(id string) (*SElb, error) {
  499. part, _, err := self.GetLoadbalancers(id, "")
  500. if err != nil {
  501. return nil, errors.Wrapf(err, "GetLoadbalancers")
  502. }
  503. for i := range part {
  504. if part[i].GetGlobalId() == id {
  505. part[i].region = self
  506. return &part[i], nil
  507. }
  508. }
  509. return nil, errors.Wrap(cloudprovider.ErrNotFound, id)
  510. }
  511. func (self *SRegion) GetILoadBalancerById(id string) (cloudprovider.ICloudLoadbalancer, error) {
  512. lb, err := self.GetLoadBalancer(id)
  513. if err != nil {
  514. return nil, err
  515. }
  516. return lb, nil
  517. }
  518. func (self *SRegion) GetElbAttributes(id string) (map[string]string, error) {
  519. ret := struct {
  520. Attributes []struct {
  521. Key string
  522. Value string
  523. } `xml:"Attributes>member"`
  524. }{}
  525. params := map[string]string{"LoadBalancerArn": id}
  526. err := self.elbRequest("DescribeLoadBalancerAttributes", params, &ret)
  527. if err != nil {
  528. return nil, err
  529. }
  530. result := map[string]string{}
  531. for _, attr := range ret.Attributes {
  532. result[attr.Key] = attr.Value
  533. }
  534. return result, nil
  535. }
  536. func (self *SRegion) GetILoadBalancerAclById(aclId string) (cloudprovider.ICloudLoadbalancerAcl, error) {
  537. return nil, cloudprovider.ErrNotSupported
  538. }
  539. func (self *SRegion) GetILoadBalancerCertificateById(certId string) (cloudprovider.ICloudLoadbalancerCertificate, error) {
  540. certs, err := self.GetILoadBalancerCertificates()
  541. if err != nil {
  542. return nil, errors.Wrap(err, "GetILoadBalancerCertificates")
  543. }
  544. for i := range certs {
  545. if certs[i].GetId() == certId {
  546. return certs[i], nil
  547. }
  548. }
  549. return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetILoadBalancerCertificateById")
  550. }
  551. func (self *SRegion) GetILoadBalancerAcls() ([]cloudprovider.ICloudLoadbalancerAcl, error) {
  552. return nil, cloudprovider.ErrNotSupported
  553. }
  554. func (self *SRegion) GetILoadBalancerCertificates() ([]cloudprovider.ICloudLoadbalancerCertificate, error) {
  555. certs, err := self.ListServerCertificates()
  556. if err != nil {
  557. return nil, err
  558. }
  559. ret := []cloudprovider.ICloudLoadbalancerCertificate{}
  560. for i := range certs {
  561. certs[i].region = self
  562. ret = append(ret, &certs[i])
  563. }
  564. return ret, nil
  565. }
  566. func (self *SRegion) CreateILoadBalancer(opts *cloudprovider.SLoadbalancerCreateOptions) (cloudprovider.ICloudLoadbalancer, error) {
  567. lb, err := self.CreateLoadbalancer(opts)
  568. if err != nil {
  569. return nil, errors.Wrapf(err, "CreateLoadbalancer")
  570. }
  571. return lb, nil
  572. }
  573. func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) {
  574. iBuckets, err := region.client.getIBuckets()
  575. if err != nil {
  576. return nil, errors.Wrap(err, "getIBuckets")
  577. }
  578. ret := make([]cloudprovider.ICloudBucket, 0)
  579. for i := range iBuckets {
  580. if iBuckets[i].GetLocation() != region.GetId() {
  581. continue
  582. }
  583. ret = append(ret, iBuckets[i])
  584. }
  585. return ret, nil
  586. }
  587. func (region *SRegion) CreateIBucket(name string, storageClassStr string, acl string) error {
  588. s3cli, err := region.GetS3Client()
  589. if err != nil {
  590. return errors.Wrap(err, "GetS3Client")
  591. }
  592. input := &s3.CreateBucketInput{}
  593. input.Bucket = &name
  594. if region.GetId() != DEFAULT_S3_REGION_ID {
  595. location := region.GetId()
  596. input.CreateBucketConfiguration = &types.CreateBucketConfiguration{
  597. LocationConstraint: types.BucketLocationConstraint(location),
  598. }
  599. }
  600. _, err = s3cli.CreateBucket(context.Background(), input)
  601. if err != nil {
  602. return errors.Wrap(err, "CreateBucket")
  603. }
  604. region.client.invalidateIBuckets()
  605. // if *output.Location != region.GetId() {
  606. // log.Warningf("Request location %s != got locaiton %s", region.GetId(), *output.Location)
  607. // }
  608. return nil
  609. }
  610. func (region *SRegion) DeleteIBucket(name string) error {
  611. s3cli, err := region.GetS3Client()
  612. if err != nil {
  613. return errors.Wrap(err, "GetS3Client")
  614. }
  615. input := &s3.DeleteBucketInput{}
  616. input.Bucket = &name
  617. _, err = s3cli.DeleteBucket(context.Background(), input)
  618. if err != nil {
  619. if region.client.debug {
  620. log.Debugf("%#v %s", err, err)
  621. }
  622. if strings.Index(err.Error(), "NoSuchBucket:") >= 0 {
  623. return nil
  624. }
  625. return errors.Wrap(err, "DeleteBucket")
  626. }
  627. region.client.invalidateIBuckets()
  628. return nil
  629. }
  630. func (region *SRegion) IBucketExist(name string) (bool, error) {
  631. s3cli, err := region.GetS3Client()
  632. if err != nil {
  633. return false, errors.Wrap(err, "GetS3Client")
  634. }
  635. input := &s3.HeadBucketInput{}
  636. input.Bucket = &name
  637. _, err = s3cli.HeadBucket(context.Background(), input)
  638. if err != nil {
  639. if region.client.debug {
  640. log.Debugf("%#v %s", err, err)
  641. }
  642. if strings.Index(err.Error(), "NotFound:") >= 0 {
  643. return false, nil
  644. }
  645. return false, errors.Wrap(err, "IsBucketExist")
  646. }
  647. return true, nil
  648. }
  649. func (region *SRegion) GetIBucketById(name string) (cloudprovider.ICloudBucket, error) {
  650. return cloudprovider.GetIBucketById(region, name)
  651. }
  652. func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) {
  653. return region.GetIBucketById(name)
  654. }
  655. func (region *SRegion) getBaseEndpoint() string {
  656. if len(region.RegionEndpoint) > 4 {
  657. return region.RegionEndpoint[4:]
  658. }
  659. return ""
  660. }
  661. func (region *SRegion) getS3Endpoint() string {
  662. base := region.getBaseEndpoint()
  663. if len(base) > 0 {
  664. return "s3." + base
  665. }
  666. return ""
  667. }
  668. func (region *SRegion) getS3WebsiteEndpoint() string {
  669. base := region.getBaseEndpoint()
  670. if len(base) > 0 {
  671. return "s3-website." + base
  672. }
  673. return ""
  674. }
  675. func (region *SRegion) getEc2Endpoint() string {
  676. return region.RegionEndpoint
  677. }
  678. func (self *SRegion) CreateILoadBalancerAcl(acl *cloudprovider.SLoadbalancerAccessControlList) (cloudprovider.ICloudLoadbalancerAcl, error) {
  679. return nil, cloudprovider.ErrNotSupported
  680. }
  681. func (self *SRegion) GetSkus(zoneId string) ([]cloudprovider.ICloudSku, error) {
  682. return nil, cloudprovider.ErrNotImplemented
  683. }
  684. func (self *SRegion) GetISecurityGroupById(id string) (cloudprovider.ICloudSecurityGroup, error) {
  685. ret, err := self.GetSecurityGroup(id)
  686. if err != nil {
  687. return nil, errors.Wrap(err, "GetSecurityGroups")
  688. }
  689. return ret, nil
  690. }
  691. func (self *SRegion) CreateISecurityGroup(opts *cloudprovider.SecurityGroupCreateInput) (cloudprovider.ICloudSecurityGroup, error) {
  692. groupId, err := self.CreateSecurityGroup(opts)
  693. if err != nil {
  694. return nil, errors.Wrap(err, "CreateSecurityGroup")
  695. }
  696. return self.GetISecurityGroupById(groupId)
  697. }
  698. func (region *SRegion) GetCapabilities() []string {
  699. return region.client.GetCapabilities()
  700. }
  701. func (self *SRegion) CreateIgw() (*SInternetGateway, error) {
  702. params := map[string]string{}
  703. ret := struct {
  704. InternetGateway SInternetGateway `xml:"internetGateway"`
  705. }{}
  706. err := self.ec2Request("CreateInternetGateway", params, &ret)
  707. if err != nil {
  708. return nil, errors.Wrapf(err, "CreateInternetGateway")
  709. }
  710. ret.InternetGateway.region = self
  711. return &ret.InternetGateway, nil
  712. }
  713. func (region *SRegion) CreateInternetGateway() (cloudprovider.ICloudInternetGateway, error) {
  714. igw, err := region.CreateIgw()
  715. if err != nil {
  716. return nil, err
  717. }
  718. return igw, nil
  719. }
  720. func (region *SRegion) GetIVMs() ([]cloudprovider.ICloudVM, error) {
  721. vms, err := region.GetInstances("", "", nil)
  722. if err != nil {
  723. return nil, errors.Wrap(err, "GetInstances")
  724. }
  725. ivms := make([]cloudprovider.ICloudVM, len(vms))
  726. for i := 0; i < len(vms); i += 1 {
  727. ivms[i] = &vms[i]
  728. }
  729. return ivms, nil
  730. }