vpc.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  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. "yunion.io/x/jsonutils"
  19. "yunion.io/x/log"
  20. "yunion.io/x/pkg/errors"
  21. "yunion.io/x/pkg/utils"
  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 SUserCIDRs struct {
  27. UserCidr []string
  28. }
  29. type SVpc struct {
  30. multicloud.SVpc
  31. AwsTags
  32. region *SRegion
  33. VpcId string `xml:"vpcId"`
  34. CidrBlock string `xml:"cidrBlock"`
  35. CidrBlockAssociationSet []struct {
  36. CidrBlock string `xml:"cidrBlock"`
  37. AssociationId string `xml:"associationId"`
  38. CidrBlockState struct {
  39. State string `xml:"state"`
  40. } `xml:"cidrBlockState"`
  41. } `xml:"cidrBlockAssociationSet>item"`
  42. IPv6CidrBlockAssociationSet []struct {
  43. IPv6CidrBlock string `xml:"ipv6CidrBlock"`
  44. } `xml:"ipv6CidrBlockAssociationSet>item"`
  45. IsDefault bool `xml:"isDefault"`
  46. Status string `xml:"state"`
  47. InstanceTenancy string `xml:"instanceTenancy"`
  48. }
  49. func (self *SVpc) GetId() string {
  50. return self.VpcId
  51. }
  52. func (self *SVpc) GetName() string {
  53. name := self.AwsTags.GetName()
  54. if len(name) > 0 {
  55. return name
  56. }
  57. return self.VpcId
  58. }
  59. func (self *SVpc) GetGlobalId() string {
  60. return self.VpcId
  61. }
  62. func (self *SVpc) GetStatus() string {
  63. // 目前不支持专用主机
  64. if self.InstanceTenancy == "dedicated" {
  65. return api.VPC_STATUS_UNAVAILABLE
  66. }
  67. // pending | available
  68. return strings.ToLower(self.Status)
  69. }
  70. func (self *SVpc) Refresh() error {
  71. new, err := self.region.getVpc(self.VpcId)
  72. if err != nil {
  73. return err
  74. }
  75. return jsonutils.Update(self, new)
  76. }
  77. func (self *SVpc) GetRegion() cloudprovider.ICloudRegion {
  78. return self.region
  79. }
  80. func (self *SVpc) GetIsDefault() bool {
  81. return self.IsDefault
  82. }
  83. func (self *SVpc) GetCidrBlock() string {
  84. cidr := []string{self.CidrBlock}
  85. for _, ip := range self.CidrBlockAssociationSet {
  86. if !utils.IsInStringArray(ip.CidrBlock, cidr) {
  87. cidr = append(cidr, ip.CidrBlock)
  88. }
  89. }
  90. return strings.Join(cidr, ",")
  91. }
  92. func (self *SVpc) GetCidrBlock6() string {
  93. ret := []string{}
  94. for _, cidr := range self.IPv6CidrBlockAssociationSet {
  95. if len(cidr.IPv6CidrBlock) > 0 {
  96. ret = append(ret, cidr.IPv6CidrBlock)
  97. }
  98. }
  99. return strings.Join(ret, ",")
  100. }
  101. func (self *SVpc) GetIWires() ([]cloudprovider.ICloudWire, error) {
  102. zones, err := self.region.GetZones("")
  103. if err != nil {
  104. return nil, err
  105. }
  106. ret := []cloudprovider.ICloudWire{}
  107. for i := range zones {
  108. zones[i].region = self.region
  109. ret = append(ret, &SWire{zone: &zones[i], vpc: self})
  110. }
  111. return ret, nil
  112. }
  113. func (self *SVpc) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, error) {
  114. secgroups, err := self.region.GetSecurityGroups(self.VpcId, "", "")
  115. if err != nil {
  116. return nil, errors.Wrap(err, "GetSecurityGroups")
  117. }
  118. ret := []cloudprovider.ICloudSecurityGroup{}
  119. for i := range secgroups {
  120. secgroups[i].region = self.region
  121. ret = append(ret, &secgroups[i])
  122. }
  123. return ret, nil
  124. }
  125. func (self *SVpc) GetIRouteTables() ([]cloudprovider.ICloudRouteTable, error) {
  126. tables, err := self.region.GetRouteTables(self.GetId(), "", "", "", false)
  127. if err != nil {
  128. return nil, errors.Wrap(err, "SVpc.GetIRouteTables")
  129. }
  130. itables := make([]cloudprovider.ICloudRouteTable, len(tables))
  131. for i := range tables {
  132. tables[i].vpc = self
  133. itables[i] = &tables[i]
  134. }
  135. return itables, nil
  136. }
  137. func (self *SVpc) GetIRouteTableById(routeTableId string) (cloudprovider.ICloudRouteTable, error) {
  138. routeTable, err := self.region.GetRouteTable(routeTableId)
  139. if err != nil {
  140. return nil, errors.Wrapf(err, "self.region.GetRouteTable(routeTableId:%s)", routeTableId)
  141. }
  142. routeTable.vpc = self
  143. return routeTable, nil
  144. }
  145. /*
  146. Deletes the specified VPC. You must detach or delete all gateways and resources that are associated with
  147. the VPC before you can delete it. For example, you must terminate all instances running in the VPC,
  148. delete all security groups associated with the VPC (except the default one),
  149. delete all route tables associated with the VPC (except the default one), and so on.
  150. */
  151. func (self *SVpc) Delete() error {
  152. err := self.DeleteInternetGateways()
  153. if err != nil {
  154. return errors.Wrap(err, "DeleteInternetGateways")
  155. }
  156. // 删除路由表. todo: 3.7版本路由表开放之后,需要同步状态到平台
  157. rts, err := self.GetIRouteTables()
  158. if err != nil {
  159. return errors.Wrap(err, "GetIRouteTables")
  160. }
  161. for i := range rts {
  162. // 主路由表不允许删除
  163. rt := rts[i].(*SRouteTable)
  164. if len(rt.Associations) > 0 {
  165. if rt.Associations[0].Main {
  166. log.Debugf("Delete.RouteTable skipped main route table %s(%s)", rt.GetName(), rt.GetId())
  167. continue
  168. }
  169. }
  170. err = self.region.DeleteRouteTable(rts[i].GetId())
  171. if err != nil {
  172. return errors.Wrap(err, "DeleteRouteTable")
  173. }
  174. }
  175. return self.region.DeleteVpc(self.VpcId)
  176. }
  177. func (self *SVpc) GetIWireById(wireId string) (cloudprovider.ICloudWire, error) {
  178. wires, err := self.GetIWires()
  179. if err != nil {
  180. return nil, err
  181. }
  182. for i := range wires {
  183. if wires[i].GetGlobalId() == wireId {
  184. return wires[i], nil
  185. }
  186. }
  187. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", wireId)
  188. }
  189. func (self *SVpc) GetICloudVpcPeeringConnections() ([]cloudprovider.ICloudVpcPeeringConnection, error) {
  190. peers, err := self.region.DescribeVpcPeeringConnections("", self.VpcId, "")
  191. if err != nil {
  192. return nil, err
  193. }
  194. ret := []cloudprovider.ICloudVpcPeeringConnection{}
  195. for i := range peers {
  196. peers[i].vpc = self
  197. ret = append(ret, &peers[i])
  198. }
  199. return ret, nil
  200. }
  201. func (self *SVpc) GetICloudAccepterVpcPeeringConnections() ([]cloudprovider.ICloudVpcPeeringConnection, error) {
  202. peers, err := self.region.DescribeVpcPeeringConnections("", "", self.VpcId)
  203. if err != nil {
  204. return nil, err
  205. }
  206. ret := []cloudprovider.ICloudVpcPeeringConnection{}
  207. for i := range peers {
  208. peers[i].vpc = self
  209. ret = append(ret, &peers[i])
  210. }
  211. return ret, nil
  212. }
  213. func (self *SVpc) GetICloudVpcPeeringConnectionById(id string) (cloudprovider.ICloudVpcPeeringConnection, error) {
  214. peer, err := self.region.GetVpcPeeringConnectionById(id)
  215. if err != nil {
  216. return nil, err
  217. }
  218. peer.vpc = self
  219. return peer, nil
  220. }
  221. func (self *SVpc) CreateICloudVpcPeeringConnection(opts *cloudprovider.VpcPeeringConnectionCreateOptions) (cloudprovider.ICloudVpcPeeringConnection, error) {
  222. peer, err := self.region.CreateVpcPeeringConnection(self.VpcId, opts)
  223. if err != nil {
  224. return nil, errors.Wrapf(err, "CreateVpcPeeringConnection")
  225. }
  226. peer.vpc = self
  227. return peer, nil
  228. }
  229. func (self *SVpc) AcceptICloudVpcPeeringConnection(id string) error {
  230. _, err := self.region.AcceptVpcPeeringConnection(id)
  231. return errors.Wrapf(err, "AcceptVpcPeeringConnection")
  232. }
  233. func (self *SVpc) GetAuthorityOwnerId() string {
  234. identity, err := self.region.client.GetCallerIdentity()
  235. if err != nil {
  236. log.Errorf("GetCallerIdentity error: %v", err)
  237. return ""
  238. }
  239. return identity.Account
  240. }
  241. func (self *SVpc) IsSupportSetExternalAccess() bool {
  242. return true
  243. }
  244. func (self *SVpc) GetExternalAccessMode() string {
  245. igws, err := self.region.GetInternetGateways(self.GetId())
  246. if err != nil {
  247. log.Errorf("GetExternalAccessMode.GetInternetGateways %s", err)
  248. }
  249. if len(igws) > 0 {
  250. return api.VPC_EXTERNAL_ACCESS_MODE_EIP
  251. }
  252. return api.VPC_EXTERNAL_ACCESS_MODE_NONE
  253. }
  254. func (self *SVpc) AttachInternetGateway(igwId string) error {
  255. params := map[string]string{
  256. "InternetGatewayId": igwId,
  257. "VpcId": self.VpcId,
  258. }
  259. ret := struct{}{}
  260. err := self.region.ec2Request("AttachInternetGateway", params, &ret)
  261. if err != nil {
  262. return errors.Wrapf(err, "AttachInternetGateway")
  263. }
  264. return self.AddDefaultInternetGatewayRoute(igwId)
  265. }
  266. func (self *SVpc) AddDefaultInternetGatewayRoute(igwId string) error {
  267. rt, err := self.GetMainRouteTable()
  268. if err != nil {
  269. return errors.Wrap(err, "GetMainRouteTable")
  270. }
  271. return self.region.CreateRoute(rt.RouteTableId, "0.0.0.0/0", igwId)
  272. }
  273. func (self *SVpc) GetMainRouteTable() (*SRouteTable, error) {
  274. rt, err := self.region.GetRouteTables(self.GetId(), "", "", "", true)
  275. if err != nil {
  276. return nil, errors.Wrap(err, "GetRouteTables")
  277. }
  278. if len(rt) == 0 {
  279. return nil, errors.Wrap(cloudprovider.ErrNotSupported, "GetMainRouteTable")
  280. }
  281. return &rt[0], nil
  282. }
  283. func (self *SVpc) DetachInternetGateways() error {
  284. igws, err := self.region.GetInternetGateways(self.GetId())
  285. if err != nil {
  286. return errors.Wrap(err, "GetInternetGateways")
  287. }
  288. if len(igws) > 0 {
  289. for i := range igws {
  290. err = self.region.DetachInternetGateway(self.VpcId, igws[i].GetId())
  291. if err != nil {
  292. return errors.Wrap(err, "DetachInternetGateway")
  293. }
  294. }
  295. }
  296. return nil
  297. }
  298. func (self *SRegion) DetachInternetGateway(vpcId, igwId string) error {
  299. params := map[string]string{
  300. "InternetGatewayId": igwId,
  301. "VpcId": vpcId,
  302. }
  303. ret := struct{}{}
  304. return self.ec2Request("DetachInternetGateway", params, &ret)
  305. }
  306. func (self *SRegion) DeleteInternetGateway(id string) error {
  307. params := map[string]string{
  308. "InternetGatewayId": id,
  309. }
  310. ret := struct{}{}
  311. return self.ec2Request("DeleteInternetGateway", params, &ret)
  312. }
  313. func (self *SVpc) DeleteInternetGateways() error {
  314. igws, err := self.region.GetInternetGateways(self.GetId())
  315. if err != nil {
  316. return errors.Wrap(err, "GetInternetGateways")
  317. }
  318. for i := range igws {
  319. err = self.region.DetachInternetGateway(self.VpcId, igws[i].GetId())
  320. if err != nil {
  321. return errors.Wrap(err, "DetachInternetGateway")
  322. }
  323. err = self.region.DeleteInternetGateway(igws[i].GetId())
  324. if err != nil {
  325. return errors.Wrap(err, "DeleteInternetGateway")
  326. }
  327. }
  328. return nil
  329. }
  330. func (self *SRegion) getVpc(vpcId string) (*SVpc, error) {
  331. vpcs, err := self.GetVpcs([]string{vpcId})
  332. if err != nil {
  333. return nil, errors.Wrap(err, "GetVpcs")
  334. }
  335. for i := range vpcs {
  336. if vpcs[i].VpcId == vpcId {
  337. vpcs[i].region = self
  338. return &vpcs[i], nil
  339. }
  340. }
  341. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", vpcId)
  342. }
  343. func (self *SRegion) assignSecurityGroups(secgroupIds []string, instanceId string) error {
  344. instance, err := self.GetInstance(instanceId)
  345. if err != nil {
  346. return errors.Wrap(err, "GetInstance")
  347. }
  348. for _, eth := range instance.NetworkInterfaces {
  349. params := map[string]string{
  350. "NetworkInterfaceId": eth.NetworkInterfaceId,
  351. }
  352. for i, groupId := range secgroupIds {
  353. params[fmt.Sprintf("SecurityGroupId.%d", i+1)] = groupId
  354. }
  355. ret := struct{}{}
  356. err = self.ec2Request("ModifyNetworkInterfaceAttribute", params, &ret)
  357. if err != nil {
  358. return errors.Wrapf(err, "ModifyNetworkInterfaceAttribute")
  359. }
  360. }
  361. return nil
  362. }
  363. func (self *SRegion) DeleteSecurityGroup(id string) error {
  364. params := map[string]string{
  365. "GroupId": id,
  366. }
  367. ret := struct{}{}
  368. return self.ec2Request("DeleteSecurityGroup", params, &ret)
  369. }
  370. func (self *SRegion) DeleteVpc(vpcId string) error {
  371. params := map[string]string{
  372. "VpcId": vpcId,
  373. }
  374. ret := struct{}{}
  375. return self.ec2Request("DeleteVpc", params, &ret)
  376. }
  377. func (self *SRegion) GetVpcs(vpcIds []string) ([]SVpc, error) {
  378. params := map[string]string{}
  379. for i, id := range vpcIds {
  380. params[fmt.Sprintf("VpcId.%d", i+1)] = id
  381. }
  382. ret := []SVpc{}
  383. for {
  384. part := struct {
  385. NextToken string `xml:"nextToken"`
  386. VpcSet []SVpc `xml:"vpcSet>item"`
  387. }{}
  388. err := self.ec2Request("DescribeVpcs", params, &part)
  389. if err != nil {
  390. return nil, err
  391. }
  392. ret = append(ret, part.VpcSet...)
  393. if len(part.NextToken) == 0 || len(part.VpcSet) == 0 {
  394. break
  395. }
  396. params["NextToken"] = part.NextToken
  397. }
  398. return ret, nil
  399. }
  400. func (self *SRegion) GetInternetGateways(vpcId string) ([]SInternetGateway, error) {
  401. params := map[string]string{}
  402. idx := 1
  403. if len(vpcId) > 0 {
  404. params[fmt.Sprintf("Filter.%d.Name", idx)] = "attachment.vpc-id"
  405. params[fmt.Sprintf("Filter.%d.Value", idx)] = vpcId
  406. idx++
  407. }
  408. ret := []SInternetGateway{}
  409. for {
  410. part := struct {
  411. NextToken string `xml:"nextToken"`
  412. InternetGatewaySet []SInternetGateway `xml:"internetGatewaySet>item"`
  413. }{}
  414. err := self.ec2Request("DescribeInternetGateways", params, &part)
  415. if err != nil {
  416. return nil, errors.Wrapf(err, "DescribeInternetGateways")
  417. }
  418. ret = append(ret, part.InternetGatewaySet...)
  419. if len(part.NextToken) == 0 || len(part.InternetGatewaySet) == 0 {
  420. break
  421. }
  422. params["NextToken"] = part.NextToken
  423. }
  424. return ret, nil
  425. }