vpc.go 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  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. "yunion.io/x/jsonutils"
  18. "yunion.io/x/pkg/errors"
  19. api "yunion.io/x/cloudmux/pkg/apis/compute"
  20. "yunion.io/x/cloudmux/pkg/cloudprovider"
  21. "yunion.io/x/cloudmux/pkg/multicloud"
  22. "yunion.io/x/cloudmux/pkg/multicloud/huawei"
  23. )
  24. // https://support.huaweicloud.com/api-vpc/zh-cn_topic_0020090625.html
  25. type SVpc struct {
  26. multicloud.SVpc
  27. huawei.HuaweiTags
  28. region *SRegion
  29. iwires []cloudprovider.ICloudWire
  30. secgroups []cloudprovider.ICloudSecurityGroup
  31. routeTables []cloudprovider.ICloudRouteTable
  32. ID string `json:"id"`
  33. Name string `json:"name"`
  34. CIDR string `json:"cidr"`
  35. Status string `json:"status"`
  36. EnterpriseProjectID string `json:"enterprise_project_id"`
  37. }
  38. func (self *SVpc) addWire(wire *SWire) {
  39. if self.iwires == nil {
  40. self.iwires = make([]cloudprovider.ICloudWire, 0)
  41. }
  42. self.iwires = append(self.iwires, wire)
  43. }
  44. func (self *SVpc) getWireByRegionId(regionId string) *SWire {
  45. if len(regionId) == 0 {
  46. return nil
  47. }
  48. for i := 0; i < len(self.iwires); i++ {
  49. wire := self.iwires[i].(*SWire)
  50. if wire.region.GetId() == regionId {
  51. return wire
  52. }
  53. }
  54. return nil
  55. }
  56. func (self *SVpc) fetchNetworks() error {
  57. networks, err := self.region.GetNetwroks(self.ID)
  58. if err != nil {
  59. return err
  60. }
  61. // ???????
  62. if len(networks) == 0 {
  63. self.iwires = append(self.iwires, &SWire{region: self.region, vpc: self})
  64. return nil
  65. }
  66. for i := 0; i < len(networks); i += 1 {
  67. wire := self.getWireByRegionId(self.region.GetId())
  68. networks[i].wire = wire
  69. wire.addNetwork(&networks[i])
  70. }
  71. return nil
  72. }
  73. // 华为云安全组可以被同region的VPC使用
  74. func (self *SVpc) fetchSecurityGroups() error {
  75. secgroups, err := self.region.GetSecurityGroups("", "")
  76. if err != nil {
  77. return err
  78. }
  79. self.secgroups = make([]cloudprovider.ICloudSecurityGroup, len(secgroups))
  80. for i := 0; i < len(secgroups); i++ {
  81. self.secgroups[i] = &secgroups[i]
  82. }
  83. return nil
  84. }
  85. func (self *SVpc) GetId() string {
  86. return self.ID
  87. }
  88. func (self *SVpc) GetName() string {
  89. if len(self.Name) > 0 {
  90. return self.Name
  91. }
  92. return self.ID
  93. }
  94. func (self *SVpc) GetGlobalId() string {
  95. return self.ID
  96. }
  97. func (self *SVpc) GetStatus() string {
  98. return api.VPC_STATUS_AVAILABLE
  99. }
  100. func (self *SVpc) Refresh() error {
  101. new, err := self.region.getVpc(self.GetId())
  102. if err != nil {
  103. return err
  104. }
  105. return jsonutils.Update(self, new)
  106. }
  107. func (self *SVpc) IsEmulated() bool {
  108. return false
  109. }
  110. func (self *SVpc) GetRegion() cloudprovider.ICloudRegion {
  111. return self.region
  112. }
  113. func (self *SVpc) GetIsDefault() bool {
  114. // 华为云没有default vpc.
  115. return false
  116. }
  117. func (self *SVpc) GetCidrBlock() string {
  118. return self.CIDR
  119. }
  120. func (self *SVpc) GetIWires() ([]cloudprovider.ICloudWire, error) {
  121. if self.iwires == nil {
  122. err := self.fetchNetworks()
  123. if err != nil {
  124. return nil, err
  125. }
  126. }
  127. return self.iwires, nil
  128. }
  129. func (self *SVpc) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, error) {
  130. if self.secgroups == nil {
  131. err := self.fetchSecurityGroups()
  132. if err != nil {
  133. return nil, err
  134. }
  135. }
  136. return self.secgroups, nil
  137. }
  138. func (self *SVpc) GetIRouteTables() ([]cloudprovider.ICloudRouteTable, error) {
  139. if self.routeTables == nil {
  140. routeTables, err := self.getRouteTables()
  141. if err != nil {
  142. return nil, errors.Wrap(err, "get route table error")
  143. }
  144. defaultRouteTable := NewSRouteTable(self, string(cloudprovider.RouteTableTypeSystem))
  145. for i := range routeTables {
  146. defaultRouteTable.Routes = append(defaultRouteTable.Routes, routeTables[i].Routes...)
  147. }
  148. self.routeTables = []cloudprovider.ICloudRouteTable{&defaultRouteTable}
  149. }
  150. return self.routeTables, nil
  151. }
  152. // 华为云 路由表资源方法 api 暂未支持,只能直接对vpc对象增加,删除 路由
  153. func (self *SVpc) GetIRouteTableById(routeTableId string) (cloudprovider.ICloudRouteTable, error) {
  154. routeTables, err := self.getRouteTables()
  155. if err != nil {
  156. return nil, errors.Wrap(err, "get route table error")
  157. }
  158. defaultRouteTable := NewSRouteTable(self, string(cloudprovider.RouteTableTypeSystem))
  159. for i := range routeTables {
  160. defaultRouteTable.Routes = append(defaultRouteTable.Routes, routeTables[i].Routes...)
  161. }
  162. return &defaultRouteTable, nil
  163. }
  164. func (self *SVpc) Delete() error {
  165. // todo: 确定删除VPC的逻辑
  166. return self.region.DeleteVpc(self.GetId())
  167. }
  168. func (self *SVpc) GetIWireById(wireId string) (cloudprovider.ICloudWire, error) {
  169. if self.iwires == nil {
  170. err := self.fetchNetworks()
  171. if err != nil {
  172. return nil, err
  173. }
  174. }
  175. for i := 0; i < len(self.iwires); i += 1 {
  176. if self.iwires[i].GetGlobalId() == wireId {
  177. return self.iwires[i], nil
  178. }
  179. }
  180. return nil, cloudprovider.ErrNotFound
  181. }
  182. func (self *SVpc) GetINatGateways() ([]cloudprovider.ICloudNatGateway, error) {
  183. nats, err := self.region.GetNatGateways(self.GetId(), "")
  184. if err != nil {
  185. return nil, err
  186. }
  187. ret := make([]cloudprovider.ICloudNatGateway, len(nats))
  188. for i := 0; i < len(nats); i++ {
  189. ret[i] = &nats[i]
  190. }
  191. return ret, nil
  192. }
  193. func (self *SVpc) GetICloudVpcPeeringConnections() ([]cloudprovider.ICloudVpcPeeringConnection, error) {
  194. svpcPCs, err := self.getVpcPeeringConnections()
  195. if err != nil {
  196. return nil, errors.Wrap(err, "self.getVpcPeeringConnections()")
  197. }
  198. ivpcPCs := []cloudprovider.ICloudVpcPeeringConnection{}
  199. for i := range svpcPCs {
  200. ivpcPCs = append(ivpcPCs, &svpcPCs[i])
  201. }
  202. return ivpcPCs, nil
  203. }
  204. func (self *SVpc) GetICloudAccepterVpcPeeringConnections() ([]cloudprovider.ICloudVpcPeeringConnection, error) {
  205. svpcPCs, err := self.getAccepterVpcPeeringConnections()
  206. if err != nil {
  207. return nil, errors.Wrap(err, "self.getAccepterVpcPeeringConnections()")
  208. }
  209. ivpcPCs := []cloudprovider.ICloudVpcPeeringConnection{}
  210. for i := range svpcPCs {
  211. ivpcPCs = append(ivpcPCs, &svpcPCs[i])
  212. }
  213. return ivpcPCs, nil
  214. }
  215. func (self *SVpc) GetICloudVpcPeeringConnectionById(id string) (cloudprovider.ICloudVpcPeeringConnection, error) {
  216. svpcPC, err := self.getVpcPeeringConnectionById(id)
  217. if err != nil {
  218. return nil, errors.Wrapf(err, "self.getVpcPeeringConnectionById(%s)", id)
  219. }
  220. return svpcPC, nil
  221. }
  222. func (self *SVpc) CreateICloudVpcPeeringConnection(opts *cloudprovider.VpcPeeringConnectionCreateOptions) (cloudprovider.ICloudVpcPeeringConnection, error) {
  223. svpcPC, err := self.region.CreateVpcPeering(self.GetId(), opts)
  224. if err != nil {
  225. return nil, errors.Wrapf(err, "self.region.CreateVpcPeering(%s,%s)", self.GetId(), jsonutils.Marshal(opts).String())
  226. }
  227. svpcPC.vpc = self
  228. return svpcPC, nil
  229. }
  230. func (self *SVpc) AcceptICloudVpcPeeringConnection(id string) error {
  231. vpcPC, err := self.getVpcPeeringConnectionById(id)
  232. if err != nil {
  233. return errors.Wrapf(err, "self.getVpcPeeringConnectionById(%s)", id)
  234. }
  235. if vpcPC.GetStatus() == api.VPC_PEERING_CONNECTION_STATUS_ACTIVE {
  236. return nil
  237. }
  238. if vpcPC.GetStatus() == api.VPC_PEERING_CONNECTION_STATUS_UNKNOWN {
  239. return errors.Wrapf(cloudprovider.ErrInvalidStatus, "vpcPC: %s", jsonutils.Marshal(vpcPC).String())
  240. }
  241. err = self.region.AcceptVpcPeering(id)
  242. if err != nil {
  243. return errors.Wrapf(err, "self.region.AcceptVpcPeering(%s)", id)
  244. }
  245. return nil
  246. }
  247. func (self *SVpc) GetAuthorityOwnerId() string {
  248. return self.region.client.projectId
  249. }
  250. func (self *SVpc) getVpcPeeringConnections() ([]SVpcPeering, error) {
  251. svpcPeerings, err := self.region.GetVpcPeerings(self.GetId())
  252. if err != nil {
  253. return nil, errors.Wrapf(err, "self.region.GetVpcPeerings(%s)", self.GetId())
  254. }
  255. vpcPCs := []SVpcPeering{}
  256. for i := range svpcPeerings {
  257. if svpcPeerings[i].GetVpcId() == self.GetId() {
  258. svpcPeerings[i].vpc = self
  259. vpcPCs = append(vpcPCs, svpcPeerings[i])
  260. }
  261. }
  262. return vpcPCs, nil
  263. }
  264. func (self *SVpc) getAccepterVpcPeeringConnections() ([]SVpcPeering, error) {
  265. svpcPeerings, err := self.region.GetVpcPeerings(self.GetId())
  266. if err != nil {
  267. return nil, errors.Wrapf(err, "self.region.GetVpcPeerings(%s)", self.GetId())
  268. }
  269. vpcPCs := []SVpcPeering{}
  270. for i := range svpcPeerings {
  271. if svpcPeerings[i].GetPeerVpcId() == self.GetId() {
  272. svpcPeerings[i].vpc = self
  273. vpcPCs = append(vpcPCs, svpcPeerings[i])
  274. }
  275. }
  276. return vpcPCs, nil
  277. }
  278. func (self *SVpc) getVpcPeeringConnectionById(id string) (*SVpcPeering, error) {
  279. svpcPC, err := self.region.GetVpcPeering(id)
  280. if err != nil {
  281. return nil, errors.Wrapf(err, "self.region.GetVpcPeering(%s)", id)
  282. }
  283. svpcPC.vpc = self
  284. return svpcPC, nil
  285. }
  286. func (self *SRegion) getVpc(vpcId string) (*SVpc, error) {
  287. vpc := SVpc{}
  288. err := DoGet(self.ecsClient.Vpcs.Get, vpcId, nil, &vpc)
  289. if err != nil && strings.Contains(err.Error(), "RouterNotFound") {
  290. return nil, cloudprovider.ErrNotFound
  291. }
  292. vpc.region = self
  293. return &vpc, err
  294. }
  295. func (self *SRegion) DeleteVpc(vpcId string) error {
  296. if vpcId != "default" {
  297. secgroups, err := self.GetSecurityGroups(vpcId, "")
  298. if err != nil {
  299. return errors.Wrap(err, "GetSecurityGroups")
  300. }
  301. for _, secgroup := range secgroups {
  302. err = self.DeleteSecurityGroup(secgroup.ID)
  303. if err != nil {
  304. return errors.Wrapf(err, "DeleteSecurityGroup(%s)", secgroup.ID)
  305. }
  306. }
  307. }
  308. return DoDelete(self.ecsClient.Vpcs.Delete, vpcId, nil, nil)
  309. }
  310. // https://support.huaweicloud.com/api-vpc/zh-cn_topic_0020090625.html
  311. func (self *SRegion) GetVpcs() ([]SVpc, error) {
  312. querys := make(map[string]string)
  313. vpcs := make([]SVpc, 0)
  314. err := doListAllWithMarker(self.ecsClient.Vpcs.List, querys, &vpcs)
  315. if err != nil {
  316. return nil, err
  317. }
  318. for i := range vpcs {
  319. vpcs[i].region = self
  320. }
  321. return vpcs, err
  322. }