vpcs.go 66 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110
  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 models
  15. import (
  16. "context"
  17. "database/sql"
  18. "fmt"
  19. "sort"
  20. "strings"
  21. "yunion.io/x/cloudmux/pkg/cloudprovider"
  22. "yunion.io/x/jsonutils"
  23. "yunion.io/x/log"
  24. "yunion.io/x/pkg/errors"
  25. "yunion.io/x/pkg/gotypes"
  26. "yunion.io/x/pkg/tristate"
  27. "yunion.io/x/pkg/util/compare"
  28. "yunion.io/x/pkg/util/netutils"
  29. "yunion.io/x/pkg/util/rbacscope"
  30. "yunion.io/x/pkg/utils"
  31. "yunion.io/x/sqlchemy"
  32. "yunion.io/x/onecloud/pkg/apis"
  33. api "yunion.io/x/onecloud/pkg/apis/compute"
  34. identityapi "yunion.io/x/onecloud/pkg/apis/identity"
  35. "yunion.io/x/onecloud/pkg/cloudcommon/consts"
  36. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  37. "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
  38. "yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
  39. "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
  40. "yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
  41. "yunion.io/x/onecloud/pkg/cloudcommon/validators"
  42. "yunion.io/x/onecloud/pkg/compute/options"
  43. "yunion.io/x/onecloud/pkg/httperrors"
  44. "yunion.io/x/onecloud/pkg/mcclient"
  45. "yunion.io/x/onecloud/pkg/util/stringutils2"
  46. )
  47. type SVpcManager struct {
  48. db.SEnabledStatusInfrasResourceBaseManager
  49. db.SExternalizedResourceBaseManager
  50. SManagedResourceBaseManager
  51. SCloudregionResourceBaseManager
  52. SGlobalVpcResourceBaseManager
  53. }
  54. var VpcManager *SVpcManager
  55. func init() {
  56. VpcManager = &SVpcManager{
  57. SEnabledStatusInfrasResourceBaseManager: db.NewEnabledStatusInfrasResourceBaseManager(
  58. SVpc{},
  59. "vpcs_tbl",
  60. "vpc",
  61. "vpcs",
  62. ),
  63. }
  64. VpcManager.SetVirtualObject(VpcManager)
  65. }
  66. type SVpc struct {
  67. db.SEnabledStatusInfrasResourceBase
  68. db.SExternalizedResourceBase
  69. SManagedResourceBase
  70. SCloudregionResourceBase `width:"36" charset:"ascii" nullable:"false" list:"domain" create:"domain_required" default:"default"`
  71. SGlobalVpcResourceBase `width:"36" charset:"ascii" list:"user" json:"globalvpc_id"`
  72. // 是否是默认VPC
  73. // example: true
  74. IsDefault bool `default:"false" list:"domain" create:"domain_optional"`
  75. // CIDR地址段
  76. // example: 192.168.222.0/24
  77. CidrBlock string `charset:"ascii" nullable:"true" list:"domain" create:"domain_optional" update:"domain"`
  78. // CIDR for IPv6
  79. CidrBlock6 string `charset:"ascii" nullable:"true" list:"domain" create:"domain_optional" update:"domain"`
  80. // Vpc外网访问模式
  81. ExternalAccessMode string `width:"16" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"`
  82. // Can it be connected directly
  83. Direct bool `default:"false" list:"user" update:"user"`
  84. }
  85. func (manager *SVpcManager) GetContextManagers() [][]db.IModelManager {
  86. return [][]db.IModelManager{
  87. {CloudregionManager},
  88. {GlobalVpcManager},
  89. }
  90. }
  91. func (svpc *SVpc) GetCloudRegionId() string {
  92. if len(svpc.CloudregionId) == 0 {
  93. return api.DEFAULT_REGION_ID
  94. } else {
  95. return svpc.CloudregionId
  96. }
  97. }
  98. func (svpc *SVpc) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
  99. idstr, _ := data.GetString("id")
  100. if len(idstr) > 0 {
  101. svpc.Id = idstr
  102. }
  103. return svpc.SEnabledStatusInfrasResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
  104. }
  105. func (svpc *SVpc) getNatgatewayQuery() *sqlchemy.SQuery {
  106. return NatGatewayManager.Query().Equals("vpc_id", svpc.Id)
  107. }
  108. func (svpc *SVpc) GetNatgatewayCount() (int, error) {
  109. return svpc.getNatgatewayQuery().CountWithError()
  110. }
  111. func (svpc *SVpc) GetDnsZones() ([]SDnsZone, error) {
  112. sq := DnsZoneVpcManager.Query("dns_zone_id").Equals("vpc_id", svpc.Id)
  113. q := DnsZoneManager.Query().In("id", sq.SubQuery())
  114. dnsZones := []SDnsZone{}
  115. err := db.FetchModelObjects(DnsZoneManager, q, &dnsZones)
  116. if err != nil {
  117. return nil, errors.Wrapf(err, "db.FetchModelObjects")
  118. }
  119. return dnsZones, nil
  120. }
  121. func (svpc *SVpc) GetInterVpcNetworks() ([]SInterVpcNetwork, error) {
  122. sq := InterVpcNetworkVpcManager.Query("inter_vpc_network_id").Equals("vpc_id", svpc.Id)
  123. q := InterVpcNetworkManager.Query().In("id", sq.SubQuery())
  124. vpcNetworks := []SInterVpcNetwork{}
  125. err := db.FetchModelObjects(InterVpcNetworkManager, q, &vpcNetworks)
  126. if err != nil {
  127. return nil, errors.Wrapf(err, "db.FetchModelObjects")
  128. }
  129. return vpcNetworks, nil
  130. }
  131. func (svpc *SVpc) GetDnsZoneCount() (int, error) {
  132. sq := DnsZoneVpcManager.Query("dns_zone_id").Equals("vpc_id", svpc.Id)
  133. q := DnsZoneManager.Query().In("id", sq.SubQuery())
  134. return q.CountWithError()
  135. }
  136. func (svpc *SVpc) GetNatgateways() ([]SNatGateway, error) {
  137. nats := []SNatGateway{}
  138. err := db.FetchModelObjects(NatGatewayManager, svpc.getNatgatewayQuery(), &nats)
  139. if err != nil {
  140. return nil, err
  141. }
  142. return nats, nil
  143. }
  144. func (svpc *SVpc) getRequesterVpcPeeringConnectionQuery() *sqlchemy.SQuery {
  145. return VpcPeeringConnectionManager.Query().Equals("vpc_id", svpc.Id)
  146. }
  147. func (svpc *SVpc) getAccepterVpcPeeringConnectionQuery() *sqlchemy.SQuery {
  148. return VpcPeeringConnectionManager.Query().Equals("peer_vpc_id", svpc.Id)
  149. }
  150. func (svpc *SVpc) GetRequesterVpcPeeringConnections() ([]SVpcPeeringConnection, error) {
  151. vpcPC := []SVpcPeeringConnection{}
  152. err := db.FetchModelObjects(VpcPeeringConnectionManager, svpc.getRequesterVpcPeeringConnectionQuery(), &vpcPC)
  153. if err != nil {
  154. return nil, err
  155. }
  156. return vpcPC, nil
  157. }
  158. func (svpc *SVpc) GetAccepterVpcPeeringConnections() ([]SVpcPeeringConnection, error) {
  159. vpcPC := []SVpcPeeringConnection{}
  160. err := db.FetchModelObjects(VpcPeeringConnectionManager, svpc.getAccepterVpcPeeringConnectionQuery(), &vpcPC)
  161. if err != nil {
  162. return nil, err
  163. }
  164. return vpcPC, nil
  165. }
  166. func (svpc *SVpc) GetVpcPeeringConnectionCount() (int, error) {
  167. q := svpc.getRequesterVpcPeeringConnectionQuery()
  168. requesterPeerCount, err := q.CountWithError()
  169. if err != nil {
  170. return 0, err
  171. }
  172. q = svpc.getRequesterVpcPeeringConnectionQuery()
  173. accepterPeerCount, err := q.CountWithError()
  174. if err != nil {
  175. return 0, err
  176. }
  177. return requesterPeerCount + accepterPeerCount, nil
  178. }
  179. func (svpc *SVpc) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.VpcUpdateInput) (api.VpcUpdateInput, error) {
  180. var err error
  181. if input.ExternalAccessMode != "" {
  182. if !utils.IsInArray(input.ExternalAccessMode, api.VPC_EXTERNAL_ACCESS_MODES) {
  183. return input, httperrors.NewInputParameterError("invalid external_access_mode %q, want %s",
  184. input.ExternalAccessMode, api.VPC_EXTERNAL_ACCESS_MODES)
  185. }
  186. }
  187. if len(input.CidrBlock) > 0 {
  188. input.CidrBlock, err = validateCidrBlock(input.CidrBlock)
  189. if err != nil {
  190. return input, httperrors.NewInputParameterError("invalid cidr_block %s", err)
  191. }
  192. }
  193. if len(input.CidrBlock6) > 0 {
  194. input.CidrBlock6, err = validateCidrBlock6(input.CidrBlock6)
  195. if err != nil {
  196. return input, httperrors.NewInputParameterError("invalid ipv6 cidr_block %s", err)
  197. }
  198. }
  199. if _, err = svpc.SEnabledStatusInfrasResourceBase.ValidateUpdateData(ctx, userCred, query, input.EnabledStatusInfrasResourceBaseUpdateInput); err != nil {
  200. return input, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.ValidateUpdateData")
  201. }
  202. return input, nil
  203. }
  204. func (svpc *SVpc) ValidateDeleteCondition(ctx context.Context, info *api.VpcDetails) error {
  205. if svpc.Id == api.DEFAULT_VPC_ID {
  206. return httperrors.NewProtectedResourceError("not allow to delete default vpc")
  207. }
  208. if gotypes.IsNil(info) {
  209. info = &api.VpcDetails{}
  210. usage, err := VpcManager.TotalResourceCount([]string{svpc.Id})
  211. if err != nil {
  212. return err
  213. }
  214. info.VpcUsage, _ = usage[svpc.Id]
  215. }
  216. if info.NetworkCount > 0 {
  217. return httperrors.NewNotEmptyError("VPC not empty, please delete network first")
  218. }
  219. if info.NatgatewayCount > 0 {
  220. return httperrors.NewNotEmptyError("VPC not empty, please delete nat gateway first")
  221. }
  222. if info.RequestVpcPeerCount > 0 {
  223. return httperrors.NewNotEmptyError("VPC not empty, please delete vpc peering first")
  224. }
  225. return svpc.SEnabledStatusInfrasResourceBase.ValidateDeleteCondition(ctx, nil)
  226. }
  227. func (svpc *SVpc) getWireQuery() *sqlchemy.SQuery {
  228. wires := WireManager.Query()
  229. if svpc.Id == api.DEFAULT_VPC_ID {
  230. return wires.Filter(sqlchemy.OR(sqlchemy.IsNull(wires.Field("vpc_id")),
  231. sqlchemy.IsEmpty(wires.Field("vpc_id")),
  232. sqlchemy.Equals(wires.Field("vpc_id"), svpc.Id)))
  233. } else {
  234. return wires.Equals("vpc_id", svpc.Id)
  235. }
  236. }
  237. func (svpc *SVpc) GetWireCount() (int, error) {
  238. q := svpc.getWireQuery()
  239. return q.CountWithError()
  240. }
  241. func (svpc *SVpc) GetWires() ([]SWire, error) {
  242. wires := make([]SWire, 0)
  243. q := svpc.getWireQuery()
  244. err := db.FetchModelObjects(WireManager, q, &wires)
  245. if err != nil {
  246. return nil, errors.Wrapf(err, "db.FetchModelObjects")
  247. }
  248. return wires, nil
  249. }
  250. func (manager *SVpcManager) getVpcExternalIdForClassicNetwork(regionId, cloudproviderId string) string {
  251. return fmt.Sprintf("%s-%s", regionId, cloudproviderId)
  252. }
  253. func (manager *SVpcManager) GetOrCreateVpcForClassicNetwork(ctx context.Context, cloudprovider *SCloudprovider, region *SCloudregion) (*SVpc, error) {
  254. externalId := manager.getVpcExternalIdForClassicNetwork(region.Id, cloudprovider.Id)
  255. _vpc, err := db.FetchByExternalIdAndManagerId(manager, externalId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  256. return q.Equals("manager_id", cloudprovider.Id)
  257. })
  258. if err == nil {
  259. return _vpc.(*SVpc), nil
  260. }
  261. if errors.Cause(err) != sql.ErrNoRows {
  262. return nil, errors.Wrapf(err, "db.FetchByExternalId %s", externalId)
  263. }
  264. vpc := &SVpc{}
  265. vpc.IsDefault = false
  266. vpc.CloudregionId = region.Id
  267. vpc.SetModelManager(manager, vpc)
  268. vpc.Name = api.CLASSIC_VPC_NAME
  269. vpc.IsEmulated = true
  270. vpc.SetEnabled(false)
  271. vpc.Status = api.VPC_STATUS_UNAVAILABLE
  272. vpc.ExternalId = externalId
  273. vpc.ManagerId = cloudprovider.Id
  274. err = manager.TableSpec().Insert(ctx, vpc)
  275. if err != nil {
  276. return nil, errors.Wrap(err, "Insert vpc for classic network")
  277. }
  278. return vpc, nil
  279. }
  280. func (svpc *SVpc) getNetworkQuery() *sqlchemy.SQuery {
  281. q := NetworkManager.Query()
  282. wireQ := svpc.getWireQuery().SubQuery()
  283. q = q.In("wire_id", wireQ.Query(wireQ.Field("id")).SubQuery())
  284. return q
  285. }
  286. func (svpc *SVpc) GetNetworks() ([]SNetwork, error) {
  287. q := svpc.getNetworkQuery()
  288. nets := make([]SNetwork, 0, 5)
  289. err := db.FetchModelObjects(NetworkManager, q, &nets)
  290. if err != nil {
  291. return nil, errors.Wrap(err, "db.FetchModelObjects")
  292. }
  293. return nets, nil
  294. }
  295. func (svpc *SVpc) GetNetworksByProvider(provider string) ([]SNetwork, error) {
  296. q := NetworkManager.Query()
  297. wireQ := svpc.getWireQuery()
  298. if provider == api.CLOUD_PROVIDER_ONECLOUD {
  299. wireQ = wireQ.IsNullOrEmpty("manager_id")
  300. } else {
  301. account := CloudaccountManager.Query().SubQuery()
  302. providers := CloudproviderManager.Query().SubQuery()
  303. subq := providers.Query(providers.Field("id"))
  304. subq = subq.Join(account, sqlchemy.Equals(
  305. account.Field("id"), providers.Field("cloudaccount_id"),
  306. ))
  307. subq = subq.Filter(sqlchemy.Equals(account.Field("provider"), provider))
  308. wireQ = wireQ.Filter(sqlchemy.In(wireQ.Field("manager_id"), subq.SubQuery()))
  309. }
  310. wireSubQ := wireQ.SubQuery()
  311. q = q.In("wire_id", wireSubQ.Query(wireSubQ.Field("id")).SubQuery())
  312. nets := make([]SNetwork, 0, 5)
  313. err := db.FetchModelObjects(NetworkManager, q, &nets)
  314. if err != nil {
  315. return nil, errors.Wrap(err, "db.FetchModelObjects")
  316. }
  317. return nets, nil
  318. }
  319. func (svpc *SVpc) GetNetworkByExtId(extId string) (*SNetwork, error) {
  320. network, err := db.FetchByExternalIdAndManagerId(NetworkManager, extId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  321. wireQ := svpc.getWireQuery().SubQuery()
  322. q = q.In("wire_id", wireQ.Query(wireQ.Field("id")).SubQuery())
  323. return q
  324. })
  325. if err != nil {
  326. return nil, errors.Wrapf(err, "GetNetworkByExtId(%s)", extId)
  327. }
  328. return network.(*SNetwork), nil
  329. }
  330. func (svpc *SVpc) GetNetworkCount() (int, error) {
  331. q := svpc.getNetworkQuery()
  332. return q.CountWithError()
  333. }
  334. func (svpc *SVpc) GetRouteTableQuery() *sqlchemy.SQuery {
  335. return RouteTableManager.Query().Equals("vpc_id", svpc.Id)
  336. }
  337. func (svpc *SVpc) GetRouteTables() []SRouteTable {
  338. q := svpc.GetRouteTableQuery()
  339. routes := []SRouteTable{}
  340. db.FetchModelObjects(RouteTableManager, q, &routes)
  341. return routes
  342. }
  343. func (svpc *SVpc) GetRouteTableCount() (int, error) {
  344. return svpc.GetRouteTableQuery().CountWithError()
  345. }
  346. /*func (svpc *SVpc) getCloudProviderInfo() SCloudProviderInfo {
  347. region, _ := svpc.GetRegion()
  348. provider := svpc.GetCloudprovider()
  349. return MakeCloudProviderInfo(region, nil, provider)
  350. }*/
  351. func (svpc *SVpc) GetRegion() (*SCloudregion, error) {
  352. region, err := CloudregionManager.FetchById(svpc.CloudregionId)
  353. if err != nil {
  354. return nil, errors.Wrap(err, "CloudregionManager.FetchById")
  355. }
  356. return region.(*SCloudregion), nil
  357. }
  358. func (svpc *SVpc) getZoneByExternalId(externalId string) (*SZone, error) {
  359. region, err := svpc.GetRegion()
  360. if err != nil {
  361. return nil, errors.Wrapf(err, "getZoneByExternalId.GetRegion")
  362. }
  363. zones := []SZone{}
  364. q := ZoneManager.Query().Equals("cloudregion_id", region.Id).Equals("external_id", externalId)
  365. err = db.FetchModelObjects(ZoneManager, q, &zones)
  366. if err != nil {
  367. return nil, errors.Wrapf(err, "getZoneByExternalId.FetchModelObjects")
  368. }
  369. if len(zones) == 1 {
  370. return &zones[0], nil
  371. }
  372. if len(zones) == 0 {
  373. return nil, fmt.Errorf("failed to found zone by externalId %s in cloudregion %s(%s)", externalId, region.Name, region.Id)
  374. }
  375. return nil, fmt.Errorf("found %d duplicate zones by externalId %s in cloudregion %s(%s)", len(zones), externalId, region.Name, region.Id)
  376. }
  377. type SVpcUsageCount struct {
  378. Id string
  379. api.VpcUsage
  380. }
  381. func (nm *SVpcManager) query(manager db.IModelManager, field string, netIds []string, filter func(*sqlchemy.SQuery) *sqlchemy.SQuery) *sqlchemy.SSubQuery {
  382. q := manager.Query()
  383. if filter != nil {
  384. q = filter(q)
  385. }
  386. sq := q.SubQuery()
  387. return sq.Query(
  388. sq.Field("vpc_id"),
  389. sqlchemy.COUNT(field),
  390. ).In("vpc_id", netIds).GroupBy(sq.Field("vpc_id")).SubQuery()
  391. }
  392. func (manager *SVpcManager) TotalResourceCount(vpcIds []string) (map[string]api.VpcUsage, error) {
  393. // wire
  394. wireSQ := manager.query(WireManager, "wire_cnt", vpcIds, nil)
  395. // network
  396. networkSQ := manager.query(NetworkManager, "network_cnt", vpcIds, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  397. wires := WireManager.Query().SubQuery()
  398. sq := q.SubQuery()
  399. return sq.Query(
  400. sq.Field("id").Label("network_id"),
  401. sq.Field("wire_id").Label("wire_id"),
  402. wires.Field("vpc_id").Label("vpc_id"),
  403. ).LeftJoin(wires, sqlchemy.Equals(sq.Field("wire_id"), wires.Field("id")))
  404. })
  405. // routetable
  406. rtbSQ := manager.query(RouteTableManager, "routetable_cnt", vpcIds, nil)
  407. // nat
  408. natSQ := manager.query(NatGatewayManager, "natgateway_cnt", vpcIds, nil)
  409. // dns
  410. dnsSQ := manager.query(DnsZoneManager, "dns_zone_cnt", vpcIds, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  411. dv := DnsZoneVpcManager.Query().SubQuery()
  412. sq := q.SubQuery()
  413. return sq.Query(
  414. sq.Field("id"),
  415. dv.Field("vpc_id").Label("vpc_id"),
  416. ).LeftJoin(dv, sqlchemy.Equals(sq.Field("id"), dv.Field("dns_zone_id")))
  417. })
  418. // dns
  419. rvpSQ := manager.query(VpcPeeringConnectionManager, "request_vpc_peer_cnt", vpcIds, nil)
  420. avpSQ := manager.query(VpcPeeringConnectionManager, "accept_vpc_peer_cnt", vpcIds, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  421. sq := q.SubQuery()
  422. return sq.Query(
  423. sq.Field("id"),
  424. sq.Field("peer_vpc_id").Label("vpc_id"),
  425. )
  426. })
  427. vpcs := manager.Query().SubQuery()
  428. vpcQ := vpcs.Query(
  429. sqlchemy.SUM("wire_count", wireSQ.Field("wire_cnt")),
  430. sqlchemy.SUM("network_count", networkSQ.Field("network_cnt")),
  431. sqlchemy.SUM("routetable_count", rtbSQ.Field("routetable_cnt")),
  432. sqlchemy.SUM("natgateway_count", natSQ.Field("natgateway_cnt")),
  433. sqlchemy.SUM("dns_zone_count", dnsSQ.Field("dns_zone_cnt")),
  434. sqlchemy.SUM("request_vpc_peer_count", rvpSQ.Field("request_vpc_peer_cnt")),
  435. sqlchemy.SUM("accept_vpc_peer_count", avpSQ.Field("accept_vpc_peer_cnt")),
  436. )
  437. vpcQ.AppendField(vpcQ.Field("id"))
  438. vpcQ = vpcQ.LeftJoin(wireSQ, sqlchemy.Equals(vpcQ.Field("id"), wireSQ.Field("vpc_id")))
  439. vpcQ = vpcQ.LeftJoin(networkSQ, sqlchemy.Equals(vpcQ.Field("id"), networkSQ.Field("vpc_id")))
  440. vpcQ = vpcQ.LeftJoin(rtbSQ, sqlchemy.Equals(vpcQ.Field("id"), rtbSQ.Field("vpc_id")))
  441. vpcQ = vpcQ.LeftJoin(natSQ, sqlchemy.Equals(vpcQ.Field("id"), natSQ.Field("vpc_id")))
  442. vpcQ = vpcQ.LeftJoin(dnsSQ, sqlchemy.Equals(vpcQ.Field("id"), dnsSQ.Field("vpc_id")))
  443. vpcQ = vpcQ.LeftJoin(rvpSQ, sqlchemy.Equals(vpcQ.Field("id"), rvpSQ.Field("vpc_id")))
  444. vpcQ = vpcQ.LeftJoin(avpSQ, sqlchemy.Equals(vpcQ.Field("id"), avpSQ.Field("vpc_id")))
  445. vpcQ = vpcQ.Filter(sqlchemy.In(vpcQ.Field("id"), vpcIds)).GroupBy(vpcQ.Field("id"))
  446. vpcCount := []SVpcUsageCount{}
  447. err := vpcQ.All(&vpcCount)
  448. if err != nil {
  449. return nil, errors.Wrapf(err, "vpcQ.All")
  450. }
  451. result := map[string]api.VpcUsage{}
  452. for i := range vpcCount {
  453. result[vpcCount[i].Id] = vpcCount[i].VpcUsage
  454. }
  455. return result, nil
  456. }
  457. func (manager *SVpcManager) FetchCustomizeColumns(
  458. ctx context.Context,
  459. userCred mcclient.TokenCredential,
  460. query jsonutils.JSONObject,
  461. objs []interface{},
  462. fields stringutils2.SSortedStrings,
  463. isList bool,
  464. ) []api.VpcDetails {
  465. rows := make([]api.VpcDetails, len(objs))
  466. stdRows := manager.SEnabledStatusInfrasResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  467. managerRows := manager.SManagedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  468. regionRows := manager.SCloudregionResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  469. globalVpcRows := manager.SGlobalVpcResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  470. vpcIds := make([]string, len(objs))
  471. for i := range rows {
  472. rows[i] = api.VpcDetails{
  473. EnabledStatusInfrasResourceBaseDetails: stdRows[i],
  474. ManagedResourceInfo: managerRows[i],
  475. CloudregionResourceInfo: regionRows[i],
  476. GlobalVpcResourceInfo: globalVpcRows[i],
  477. }
  478. vpc := objs[i].(*SVpc)
  479. vpcIds[i] = vpc.Id
  480. }
  481. usage, err := manager.TotalResourceCount(vpcIds)
  482. if err != nil {
  483. log.Errorf("TotalResourceCount error: %v", err)
  484. return rows
  485. }
  486. for i := range rows {
  487. rows[i].VpcUsage, _ = usage[vpcIds[i]]
  488. }
  489. return rows
  490. }
  491. func (svpc *SVpc) setDefault(def bool) error {
  492. var err error
  493. if svpc.IsDefault != def {
  494. _, err = db.Update(svpc, func() error {
  495. svpc.IsDefault = def
  496. return nil
  497. })
  498. }
  499. return err
  500. }
  501. func (manager *SVpcManager) SyncVPCs(
  502. ctx context.Context,
  503. userCred mcclient.TokenCredential,
  504. provider *SCloudprovider,
  505. region *SCloudregion,
  506. vpcs []cloudprovider.ICloudVpc,
  507. xor bool,
  508. ) ([]SVpc, []cloudprovider.ICloudVpc, compare.SyncResult) {
  509. lockman.LockRawObject(ctx, manager.Keyword(), fmt.Sprintf("%s-%s", provider.Id, region.Id))
  510. defer lockman.ReleaseRawObject(ctx, manager.Keyword(), fmt.Sprintf("%s-%s", provider.Id, region.Id))
  511. localVPCs := make([]SVpc, 0)
  512. remoteVPCs := make([]cloudprovider.ICloudVpc, 0)
  513. syncResult := compare.SyncResult{}
  514. dbVPCs, err := region.GetCloudproviderVpcs(provider.Id)
  515. if err != nil {
  516. syncResult.Error(err)
  517. return nil, nil, syncResult
  518. }
  519. for i := range dbVPCs {
  520. if taskman.TaskManager.IsInTask(&dbVPCs[i]) {
  521. syncResult.Error(fmt.Errorf("object in task"))
  522. return nil, nil, syncResult
  523. }
  524. }
  525. removed := make([]SVpc, 0)
  526. commondb := make([]SVpc, 0)
  527. commonext := make([]cloudprovider.ICloudVpc, 0)
  528. added := make([]cloudprovider.ICloudVpc, 0)
  529. err = compare.CompareSets(dbVPCs, vpcs, &removed, &commondb, &commonext, &added)
  530. if err != nil {
  531. syncResult.Error(err)
  532. return nil, nil, syncResult
  533. }
  534. for i := 0; i < len(removed); i += 1 {
  535. err = removed[i].syncRemoveCloudVpc(ctx, userCred)
  536. if err != nil {
  537. syncResult.DeleteError(err)
  538. } else {
  539. syncResult.Delete()
  540. }
  541. }
  542. for i := 0; i < len(commondb); i += 1 {
  543. if !xor {
  544. err = commondb[i].SyncWithCloudVpc(ctx, userCred, commonext[i], provider)
  545. if err != nil {
  546. syncResult.UpdateError(err)
  547. continue
  548. }
  549. }
  550. localVPCs = append(localVPCs, commondb[i])
  551. remoteVPCs = append(remoteVPCs, commonext[i])
  552. syncResult.Update()
  553. }
  554. for i := 0; i < len(added); i += 1 {
  555. newVpc, err := manager.newFromCloudVpc(ctx, userCred, added[i], provider, region)
  556. if err != nil {
  557. syncResult.AddError(err)
  558. continue
  559. }
  560. localVPCs = append(localVPCs, *newVpc)
  561. remoteVPCs = append(remoteVPCs, added[i])
  562. syncResult.Add()
  563. }
  564. return localVPCs, remoteVPCs, syncResult
  565. }
  566. func (svpc *SVpc) syncRemoveCloudVpc(ctx context.Context, userCred mcclient.TokenCredential) error {
  567. lockman.LockObject(ctx, svpc)
  568. defer lockman.ReleaseObject(ctx, svpc)
  569. if VpcManager.getVpcExternalIdForClassicNetwork(svpc.CloudregionId, svpc.ManagerId) == svpc.ExternalId { //为经典网络虚拟的vpc
  570. return nil
  571. }
  572. err := svpc.purge(ctx, userCred)
  573. if err == nil {
  574. notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{
  575. Obj: svpc,
  576. Action: notifyclient.ActionSyncDelete,
  577. })
  578. }
  579. return err
  580. }
  581. func (svpc *SVpc) SyncWithCloudVpc(ctx context.Context, userCred mcclient.TokenCredential, extVPC cloudprovider.ICloudVpc, provider *SCloudprovider) error {
  582. diff, err := db.UpdateWithLock(ctx, svpc, func() error {
  583. if options.Options.EnableSyncName {
  584. newName, _ := db.GenerateAlterName(svpc, extVPC.GetName())
  585. if len(newName) > 0 {
  586. svpc.Name = newName
  587. }
  588. }
  589. svpc.Status = extVPC.GetStatus()
  590. svpc.CidrBlock = extVPC.GetCidrBlock()
  591. svpc.CidrBlock6 = extVPC.GetCidrBlock6()
  592. svpc.IsDefault = extVPC.GetIsDefault()
  593. svpc.ExternalId = extVPC.GetGlobalId()
  594. svpc.IsEmulated = extVPC.IsEmulated()
  595. svpc.ExternalAccessMode = extVPC.GetExternalAccessMode()
  596. if len(svpc.Description) == 0 {
  597. svpc.Description = extVPC.GetDescription()
  598. }
  599. if createdAt := extVPC.GetCreatedAt(); !createdAt.IsZero() {
  600. svpc.CreatedAt = createdAt
  601. }
  602. if gId := extVPC.GetGlobalVpcId(); len(gId) > 0 {
  603. gVpc, err := db.FetchByExternalIdAndManagerId(GlobalVpcManager, gId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  604. return q.Equals("manager_id", svpc.ManagerId)
  605. })
  606. if err != nil {
  607. log.Errorf("FetchGlobalVpc %s error: %v", gId, err)
  608. } else {
  609. svpc.GlobalvpcId = gVpc.GetId()
  610. }
  611. }
  612. return nil
  613. })
  614. if err != nil {
  615. return err
  616. }
  617. //syncMetadata(ctx, userCred, svpc, extVPC)
  618. if provider != nil {
  619. SyncCloudDomain(userCred, svpc, provider.GetOwnerId())
  620. svpc.SyncShareState(ctx, userCred, provider.getAccountShareInfo())
  621. }
  622. db.OpsLog.LogSyncUpdate(svpc, diff, userCred)
  623. return nil
  624. }
  625. func (manager *SVpcManager) newFromCloudVpc(ctx context.Context, userCred mcclient.TokenCredential, extVPC cloudprovider.ICloudVpc, provider *SCloudprovider, region *SCloudregion) (*SVpc, error) {
  626. vpc := SVpc{}
  627. vpc.SetModelManager(manager, &vpc)
  628. vpc.Status = extVPC.GetStatus()
  629. vpc.Description = extVPC.GetDescription()
  630. vpc.ExternalId = extVPC.GetGlobalId()
  631. vpc.IsDefault = extVPC.GetIsDefault()
  632. vpc.CidrBlock = extVPC.GetCidrBlock()
  633. vpc.ExternalAccessMode = extVPC.GetExternalAccessMode()
  634. vpc.CloudregionId = region.Id
  635. vpc.ManagerId = provider.Id
  636. if createdAt := extVPC.GetCreatedAt(); !createdAt.IsZero() {
  637. vpc.CreatedAt = createdAt
  638. }
  639. if gId := extVPC.GetGlobalVpcId(); len(gId) > 0 {
  640. gVpc, err := db.FetchByExternalIdAndManagerId(GlobalVpcManager, gId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  641. return q.Equals("manager_id", provider.Id)
  642. })
  643. if err != nil {
  644. log.Errorf("FetchGlobalVpc %s error: %v", gId, err)
  645. } else {
  646. vpc.GlobalvpcId = gVpc.GetId()
  647. }
  648. }
  649. vpc.IsEmulated = extVPC.IsEmulated()
  650. var err = func() error {
  651. lockman.LockRawObject(ctx, manager.Keyword(), "name")
  652. defer lockman.ReleaseRawObject(ctx, manager.Keyword(), "name")
  653. newName, err := db.GenerateName(ctx, manager, userCred, extVPC.GetName())
  654. if err != nil {
  655. return err
  656. }
  657. vpc.Name = newName
  658. return manager.TableSpec().Insert(ctx, &vpc)
  659. }()
  660. if err != nil {
  661. return nil, errors.Wrapf(err, "Insert")
  662. }
  663. syncMetadata(ctx, userCred, &vpc, extVPC, false)
  664. SyncCloudDomain(userCred, &vpc, provider.GetOwnerId())
  665. if provider != nil {
  666. vpc.SyncShareState(ctx, userCred, provider.getAccountShareInfo())
  667. }
  668. db.OpsLog.LogEvent(&vpc, db.ACT_CREATE, vpc.GetShortDesc(ctx), userCred)
  669. return &vpc, nil
  670. }
  671. func (svpc *SVpc) markAllNetworksUnknown(ctx context.Context, userCred mcclient.TokenCredential) error {
  672. wires, _ := svpc.GetWires()
  673. if wires == nil || len(wires) == 0 {
  674. return nil
  675. }
  676. for i := 0; i < len(wires); i += 1 {
  677. wires[i].markNetworkUnknown(ctx, userCred)
  678. }
  679. return nil
  680. }
  681. func (svpc *SVpc) SyncRouteTables(ctx context.Context, userCred mcclient.TokenCredential) error {
  682. ivpc, err := svpc.GetIVpc(ctx)
  683. if err != nil {
  684. return errors.Wrap(err, "svpc.GetIVpc()")
  685. }
  686. routeTables, err := ivpc.GetIRouteTables()
  687. if err != nil {
  688. return errors.Wrapf(err, "GetIRouteTables for vpc %s failed", ivpc.GetId())
  689. }
  690. _, _, result := RouteTableManager.SyncRouteTables(ctx, userCred, svpc, routeTables, svpc.GetCloudprovider(), false)
  691. if result.IsError() {
  692. return errors.Wrapf(result.AllError(), "RouteTableManager.SyncRouteTables(%s,%s)", jsonutils.Marshal(svpc).String(), jsonutils.Marshal(routeTables).String())
  693. }
  694. return nil
  695. }
  696. func (manager *SVpcManager) InitializeData() error {
  697. if vpcObj, err := manager.FetchById(api.DEFAULT_VPC_ID); err != nil {
  698. if err == sql.ErrNoRows {
  699. defVpc := SVpc{}
  700. defVpc.SetModelManager(VpcManager, &defVpc)
  701. defVpc.Id = api.DEFAULT_VPC_ID
  702. defVpc.Name = "Default"
  703. defVpc.CloudregionId = api.DEFAULT_REGION_ID
  704. defVpc.Description = "Default VPC"
  705. defVpc.Status = api.VPC_STATUS_AVAILABLE
  706. defVpc.IsDefault = true
  707. defVpc.IsPublic = true
  708. defVpc.PublicScope = string(rbacscope.ScopeSystem)
  709. defVpc.DomainId = identityapi.DEFAULT_DOMAIN_ID
  710. err = manager.TableSpec().Insert(context.TODO(), &defVpc)
  711. if err != nil {
  712. log.Errorf("Insert default vpc fail: %s", err)
  713. }
  714. return err
  715. } else {
  716. return err
  717. }
  718. } else {
  719. vpc := vpcObj.(*SVpc)
  720. if vpc.Status != api.VPC_STATUS_AVAILABLE || (vpc.PublicScope == string(rbacscope.ScopeSystem) && !vpc.IsPublic) {
  721. _, err = db.Update(vpc, func() error {
  722. vpc.Status = api.VPC_STATUS_AVAILABLE
  723. vpc.IsPublic = true
  724. return nil
  725. })
  726. return err
  727. }
  728. }
  729. if defaultMode := options.Options.DefaultVpcExternalAccessMode; defaultMode == "" {
  730. options.Options.DefaultVpcExternalAccessMode = api.VPC_EXTERNAL_ACCESS_MODE_EIP_DISTGW
  731. } else if !utils.IsInStringArray(defaultMode, api.VPC_EXTERNAL_ACCESS_MODES) {
  732. return errors.Errorf("invalid DefaultVpcExternalAccessMode, got %s, want %s", defaultMode, api.VPC_EXTERNAL_ACCESS_MODES)
  733. }
  734. {
  735. // initialize default external_access_mode for onecloud vpc
  736. var vpcs []SVpc
  737. q := manager.Query().
  738. IsNullOrEmpty("manager_id").
  739. IsNullOrEmpty("external_id").
  740. IsNullOrEmpty("external_access_mode")
  741. if err := db.FetchModelObjects(manager, q, &vpcs); err != nil {
  742. return errors.Wrap(err, "fetch onecloud vpc with external_access_mode not set")
  743. }
  744. for i := range vpcs {
  745. vpc := &vpcs[i]
  746. if _, err := db.Update(vpc, func() error {
  747. vpc.ExternalAccessMode = options.Options.DefaultVpcExternalAccessMode
  748. return nil
  749. }); err != nil {
  750. return errors.Wrap(err, "db set default external_access_mode")
  751. }
  752. }
  753. }
  754. {
  755. // initialize default external access mode for public cloud
  756. var vpcs []SVpc
  757. q := manager.Query().
  758. IsNotEmpty("manager_id").
  759. IsNotEmpty("external_id").
  760. IsNullOrEmpty("external_access_mode")
  761. if err := db.FetchModelObjects(manager, q, &vpcs); err != nil {
  762. return errors.Wrap(err, "fetch public cloud vpc with external_access_mode not set")
  763. }
  764. for i := range vpcs {
  765. vpc := &vpcs[i]
  766. if _, err := db.Update(vpc, func() error {
  767. vpc.ExternalAccessMode = api.VPC_EXTERNAL_ACCESS_MODE_EIP
  768. return nil
  769. }); err != nil {
  770. return errors.Wrap(err, "db set default external_access_mode")
  771. }
  772. }
  773. }
  774. {
  775. vpcs := []SVpc{}
  776. q := manager.Query().IsTrue("is_emulated").IsNotEmpty("external_id").NotEquals("name", "-")
  777. err := db.FetchModelObjects(manager, q, &vpcs)
  778. if err != nil {
  779. return errors.Wrapf(err, "db.FetchModelObjects")
  780. }
  781. for i := range vpcs {
  782. if vpcs[i].ExternalId == manager.getVpcExternalIdForClassicNetwork(vpcs[i].CloudregionId, vpcs[i].ManagerId) {
  783. _, err = db.Update(&vpcs[i], func() error {
  784. vpcs[i].Name = "-"
  785. return nil
  786. })
  787. if err != nil {
  788. return errors.Wrapf(err, "db.Update class vpc name")
  789. }
  790. }
  791. }
  792. }
  793. return nil
  794. }
  795. func validateCidrBlock(blocks string) (string, error) {
  796. var errs []error
  797. cidrStrs := strings.Split(blocks, ",")
  798. cidrList4 := make([]string, 0)
  799. for _, cidrStr := range cidrStrs {
  800. cidr4, err := netutils.NewIPV4Prefix(cidrStr)
  801. if err != nil {
  802. errs = append(errs, errors.Wrap(err, cidrStr))
  803. } else {
  804. cidrList4 = append(cidrList4, cidr4.String())
  805. }
  806. }
  807. if len(errs) > 0 {
  808. return "", errors.NewAggregate(errs)
  809. }
  810. sort.Strings(cidrList4)
  811. return strings.Join(cidrList4, ","), nil
  812. }
  813. func validateCidrBlock6(block6 string) (string, error) {
  814. var errs []error
  815. cidrStrs := strings.Split(block6, ",")
  816. cidrList6 := make([]string, 0)
  817. for _, cidrStr := range cidrStrs {
  818. cidr6, err := netutils.NewIPV6Prefix(cidrStr)
  819. if err != nil {
  820. errs = append(errs, errors.Wrap(err, cidrStr))
  821. } else {
  822. cidrList6 = append(cidrList6, cidr6.String())
  823. }
  824. }
  825. if len(errs) > 0 {
  826. return "", errors.NewAggregate(errs)
  827. }
  828. sort.Strings(cidrList6)
  829. return strings.Join(cidrList6, ","), nil
  830. }
  831. func (manager *SVpcManager) ValidateCreateData(
  832. ctx context.Context,
  833. userCred mcclient.TokenCredential,
  834. ownerId mcclient.IIdentityProvider,
  835. query jsonutils.JSONObject,
  836. input api.VpcCreateInput,
  837. ) (api.VpcCreateInput, error) {
  838. regionObj, err := validators.ValidateModel(ctx, userCred, CloudregionManager, &input.CloudregionId)
  839. if err != nil {
  840. return input, err
  841. }
  842. region := regionObj.(*SCloudregion)
  843. if region.isManaged() {
  844. _, err := validators.ValidateModel(ctx, userCred, CloudproviderManager, &input.CloudproviderId)
  845. if err != nil {
  846. return input, err
  847. }
  848. if input.ExternalAccessMode == "" {
  849. input.ExternalAccessMode = api.VPC_EXTERNAL_ACCESS_MODE_EIP
  850. }
  851. } else {
  852. input.Status = api.VPC_STATUS_AVAILABLE
  853. if input.ExternalAccessMode == "" {
  854. input.ExternalAccessMode = options.Options.DefaultVpcExternalAccessMode
  855. }
  856. }
  857. // check external access mode
  858. if !utils.IsInStringArray(input.ExternalAccessMode, api.VPC_EXTERNAL_ACCESS_MODES) {
  859. return input, httperrors.NewInputParameterError("invalid external_access_mode %q, want %s",
  860. input.Status, api.VPC_EXTERNAL_ACCESS_MODES)
  861. }
  862. if len(input.CidrBlock) > 0 {
  863. input.CidrBlock, err = validateCidrBlock(input.CidrBlock)
  864. if err != nil {
  865. return input, httperrors.NewInputParameterError("invalid cidr_block %s", err)
  866. }
  867. }
  868. if len(input.CidrBlock6) > 0 {
  869. input.CidrBlock6, err = validateCidrBlock6(input.CidrBlock6)
  870. if err != nil {
  871. return input, httperrors.NewInputParameterError("invalid ipv6 cidr_block %s", err)
  872. }
  873. }
  874. input.EnabledStatusInfrasResourceBaseCreateInput, err = manager.SEnabledStatusInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.EnabledStatusInfrasResourceBaseCreateInput)
  875. if err != nil {
  876. return input, err
  877. }
  878. input, err = region.GetDriver().ValidateCreateVpcData(ctx, userCred, input)
  879. if err != nil {
  880. return input, err
  881. }
  882. if region.GetDriver().IsVpcCreateNeedInputCidr() && len(input.CidrBlock) == 0 && len(input.CidrBlock6) == 0 {
  883. return input, httperrors.NewMissingParameterError("cidr_block or cidr_block6")
  884. }
  885. keys := GetVpcQuotaKeysFromCreateInput(ownerId, input)
  886. quota := &SInfrasQuota{Vpc: 1}
  887. quota.SetKeys(keys)
  888. err = quotas.CheckSetPendingQuota(ctx, userCred, quota)
  889. if err != nil {
  890. return input, errors.Wrap(err, "quotas.CheckSetPendingQuota")
  891. }
  892. return input, nil
  893. }
  894. func (svpc *SVpc) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
  895. input := api.VpcCreateInput{}
  896. data.Unmarshal(&input)
  897. pendingUsage := &SInfrasQuota{Vpc: 1}
  898. keys := GetVpcQuotaKeysFromCreateInput(ownerId, input)
  899. pendingUsage.SetKeys(keys)
  900. quotas.CancelPendingUsage(ctx, userCred, pendingUsage, pendingUsage, true)
  901. defer func() {
  902. svpc.SEnabledStatusInfrasResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
  903. }()
  904. if len(svpc.ManagerId) == 0 {
  905. notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{
  906. Obj: svpc,
  907. Action: notifyclient.ActionCreate,
  908. })
  909. return
  910. }
  911. task, err := taskman.TaskManager.NewTask(ctx, "VpcCreateTask", svpc, userCred, nil, "", "", nil)
  912. if err != nil {
  913. svpc.SetStatus(ctx, userCred, api.VPC_STATUS_FAILED, errors.Wrapf(err, "NewTask").Error())
  914. return
  915. }
  916. task.ScheduleRun(nil)
  917. }
  918. func (svpc *SVpc) GetIRegion(ctx context.Context) (cloudprovider.ICloudRegion, error) {
  919. region, err := svpc.GetRegion()
  920. if err != nil {
  921. return nil, errors.Wrap(err, "GetRegion")
  922. }
  923. provider, err := svpc.GetDriver(ctx)
  924. if err != nil {
  925. return nil, err
  926. }
  927. return provider.GetIRegionById(region.GetExternalId())
  928. }
  929. func (svpc *SVpc) GetIVpc(ctx context.Context) (cloudprovider.ICloudVpc, error) {
  930. if len(svpc.ExternalId) == 0 {
  931. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "empty external id")
  932. }
  933. provider, err := svpc.GetDriver(ctx)
  934. if err != nil {
  935. return nil, errors.Wrapf(err, "vpc.GetDriver")
  936. }
  937. var iregion cloudprovider.ICloudRegion
  938. if provider.GetFactory().IsOnPremise() {
  939. iregion, err = provider.GetOnPremiseIRegion()
  940. } else {
  941. region, err := svpc.GetRegion()
  942. if err != nil {
  943. return nil, err
  944. }
  945. iregion, err = provider.GetIRegionById(region.ExternalId)
  946. }
  947. if err != nil {
  948. return nil, errors.Wrapf(err, "find iregion")
  949. }
  950. ivpc, err := iregion.GetIVpcById(svpc.ExternalId)
  951. if err != nil {
  952. return nil, errors.Wrapf(err, "GetIVpcById")
  953. }
  954. return ivpc, nil
  955. }
  956. func (svpc *SVpc) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
  957. log.Infof("SVpc delete do nothing")
  958. svpc.SetStatus(ctx, userCred, api.VPC_STATUS_START_DELETE, "")
  959. return nil
  960. }
  961. func (svpc *SVpc) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
  962. if svpc.Id != api.DEFAULT_VPC_ID {
  963. return svpc.StartDeleteVpcTask(ctx, userCred)
  964. } else {
  965. return svpc.RealDelete(ctx, userCred)
  966. }
  967. }
  968. func (svpc *SVpc) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
  969. db.OpsLog.LogEvent(svpc, db.ACT_DELOCATE, svpc.GetShortDesc(ctx), userCred)
  970. svpc.SetStatus(ctx, userCred, api.VPC_STATUS_DELETED, "real delete")
  971. return svpc.purge(ctx, userCred)
  972. }
  973. func (svpc *SVpc) StartDeleteVpcTask(ctx context.Context, userCred mcclient.TokenCredential) error {
  974. task, err := taskman.TaskManager.NewTask(ctx, "VpcDeleteTask", svpc, userCred, nil, "", "", nil)
  975. if err != nil {
  976. log.Errorf("Start vpcdeleteTask fail %s", err)
  977. return err
  978. }
  979. task.ScheduleRun(nil)
  980. return nil
  981. }
  982. func (svpc *SVpc) getPrefix() []netutils.IPV4Prefix {
  983. if len(svpc.CidrBlock) > 0 {
  984. ret := []netutils.IPV4Prefix{}
  985. blocks := strings.Split(svpc.CidrBlock, ",")
  986. for _, block := range blocks {
  987. prefix, _ := netutils.NewIPV4Prefix(block)
  988. ret = append(ret, prefix)
  989. }
  990. return ret
  991. }
  992. return []netutils.IPV4Prefix{{}}
  993. }
  994. func (svpc *SVpc) getPrefix6() []netutils.IPV6Prefix {
  995. if len(svpc.CidrBlock6) > 0 {
  996. ret := []netutils.IPV6Prefix{}
  997. blocks := strings.Split(svpc.CidrBlock6, ",")
  998. for _, block := range blocks {
  999. prefix, _ := netutils.NewIPV6Prefix(block)
  1000. ret = append(ret, prefix)
  1001. }
  1002. return ret
  1003. }
  1004. return []netutils.IPV6Prefix{{}}
  1005. }
  1006. func (svpc *SVpc) getIPRanges() []netutils.IPV4AddrRange {
  1007. ret := []netutils.IPV4AddrRange{}
  1008. prefs := svpc.getPrefix()
  1009. for _, pref := range prefs {
  1010. ret = append(ret, pref.ToIPRange())
  1011. }
  1012. return ret
  1013. }
  1014. func (svpc *SVpc) getIP6Ranges() []netutils.IPV6AddrRange {
  1015. ret := []netutils.IPV6AddrRange{}
  1016. prefs := svpc.getPrefix6()
  1017. for _, pref := range prefs {
  1018. ret = append(ret, pref.ToIPRange())
  1019. }
  1020. return ret
  1021. }
  1022. func (svpc *SVpc) containsIPV4Range(a netutils.IPV4AddrRange) bool {
  1023. ranges := svpc.getIPRanges()
  1024. for i := range ranges {
  1025. if ranges[i].ContainsRange(a) {
  1026. return true
  1027. }
  1028. }
  1029. return false
  1030. }
  1031. func (svpc *SVpc) containsIPV6Range(a netutils.IPV6AddrRange) bool {
  1032. ranges := svpc.getIP6Ranges()
  1033. for i := range ranges {
  1034. if ranges[i].ContainsRange(a) {
  1035. return true
  1036. }
  1037. }
  1038. return false
  1039. }
  1040. func (svpc *SVpc) PerformPurge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  1041. err := svpc.ValidateDeleteCondition(ctx, nil)
  1042. if err != nil {
  1043. return nil, err
  1044. }
  1045. provider := svpc.GetCloudprovider()
  1046. if provider != nil {
  1047. if provider.GetEnabled() {
  1048. return nil, httperrors.NewInvalidStatusError("Cannot purge vpc on enabled cloud provider")
  1049. }
  1050. }
  1051. err = svpc.RealDelete(ctx, userCred)
  1052. return nil, err
  1053. }
  1054. // 列出VPC
  1055. func (manager *SVpcManager) ListItemFilter(
  1056. ctx context.Context,
  1057. q *sqlchemy.SQuery,
  1058. userCred mcclient.TokenCredential,
  1059. query api.VpcListInput,
  1060. ) (*sqlchemy.SQuery, error) {
  1061. var err error
  1062. q, err = manager.SEnabledStatusInfrasResourceBaseManager.ListItemFilter(ctx, q, userCred, query.EnabledStatusInfrasResourceBaseListInput)
  1063. if err != nil {
  1064. return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager.ListItemFilter")
  1065. }
  1066. q, err = manager.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
  1067. if err != nil {
  1068. return nil, errors.Wrap(err, "SExternalizedResourceBaseManager.ListItemFilter")
  1069. }
  1070. q, err = manager.SManagedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ManagedResourceListInput)
  1071. if err != nil {
  1072. return nil, errors.Wrap(err, "SManagedResourceBaseManager.ListItemFilter")
  1073. }
  1074. q, err = manager.SCloudregionResourceBaseManager.ListItemFilter(ctx, q, userCred, query.RegionalFilterListInput)
  1075. if err != nil {
  1076. return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.ListItemFilter")
  1077. }
  1078. q, err = manager.SGlobalVpcResourceBaseManager.ListItemFilter(ctx, q, userCred, query.GlobalVpcResourceListInput)
  1079. if err != nil {
  1080. return nil, errors.Wrap(err, "SGlobalVpcResourceBaseManager.ListItemFilter")
  1081. }
  1082. if len(query.ExternalAccessMode) > 0 {
  1083. q = q.Equals("external_access_mode", query.ExternalAccessMode)
  1084. }
  1085. if len(query.DnsZoneId) > 0 {
  1086. dnsZone, err := DnsZoneManager.FetchByIdOrName(ctx, userCred, query.DnsZoneId)
  1087. if err != nil {
  1088. if errors.Cause(err) == sql.ErrNoRows {
  1089. return nil, httperrors.NewResourceNotFoundError2("dns_zone", query.DnsZoneId)
  1090. }
  1091. return nil, httperrors.NewGeneralError(err)
  1092. }
  1093. sq := DnsZoneVpcManager.Query("vpc_id").Equals("dns_zone_id", dnsZone.GetId())
  1094. q = q.In("id", sq.SubQuery())
  1095. }
  1096. if len(query.UsableForInterVpcNetworkId) > 0 {
  1097. _interVpc, err := validators.ValidateModel(ctx, userCred, InterVpcNetworkManager, &query.UsableForInterVpcNetworkId)
  1098. if err != nil {
  1099. return nil, err
  1100. }
  1101. interVpc := _interVpc.(*SInterVpcNetwork)
  1102. sq := InterVpcNetworkVpcManager.Query("vpc_id").Equals("inter_vpc_network_id", interVpc.GetId())
  1103. q = q.NotIn("id", sq.SubQuery())
  1104. account := interVpc.GetCloudaccount()
  1105. if account == nil {
  1106. return nil, httperrors.NewNotSupportedError("not supported for inter vpc network %s", interVpc.Name)
  1107. }
  1108. vpcs := VpcManager.Query().SubQuery()
  1109. managers := CloudproviderManager.Query().SubQuery()
  1110. accounts := CloudaccountManager.Query().SubQuery()
  1111. accUrl := sqlchemy.Equals(accounts.Field("access_url"), account.AccessUrl)
  1112. if len(account.AccessUrl) == 0 {
  1113. accUrl = sqlchemy.IsNullOrEmpty(accounts.Field("access_url"))
  1114. }
  1115. vpcSQ := vpcs.Query(vpcs.Field("id")).Join(managers, sqlchemy.Equals(vpcs.Field("manager_id"), managers.Field("id"))).Join(accounts, sqlchemy.Equals(managers.Field("cloudaccount_id"), accounts.Field("id"))).Filter(
  1116. sqlchemy.AND(
  1117. sqlchemy.Equals(accounts.Field("provider"), account.Provider),
  1118. accUrl,
  1119. ),
  1120. )
  1121. q = q.In("id", vpcSQ.SubQuery())
  1122. }
  1123. if len(query.InterVpcNetworkId) > 0 {
  1124. vpcNetwork, err := InterVpcNetworkManager.FetchByIdOrName(ctx, userCred, query.InterVpcNetworkId)
  1125. if err != nil {
  1126. if errors.Cause(err) == sql.ErrNoRows {
  1127. return nil, httperrors.NewResourceNotFoundError2("inter_vpc_network", query.InterVpcNetworkId)
  1128. }
  1129. return nil, httperrors.NewGeneralError(err)
  1130. }
  1131. sq := InterVpcNetworkVpcManager.Query("vpc_id").Equals("inter_vpc_network_id", vpcNetwork.GetId())
  1132. q = q.In("id", sq.SubQuery())
  1133. }
  1134. usable := (query.Usable != nil && *query.Usable)
  1135. vpcUsable := (query.UsableVpc != nil && *query.UsableVpc)
  1136. if vpcUsable || usable {
  1137. regions := CloudregionManager.Query().SubQuery()
  1138. providerSQ := usableCloudProviders().SubQuery()
  1139. q = q.Join(regions, sqlchemy.Equals(q.Field("cloudregion_id"), regions.Field("id"))).Filter(
  1140. sqlchemy.AND(
  1141. sqlchemy.Equals(regions.Field("status"), api.CLOUD_REGION_STATUS_INSERVER),
  1142. sqlchemy.OR(
  1143. sqlchemy.In(q.Field("manager_id"), providerSQ),
  1144. sqlchemy.IsNullOrEmpty(q.Field("manager_id")),
  1145. ),
  1146. ),
  1147. )
  1148. if vpcUsable || usable {
  1149. q = q.Equals("status", api.VPC_STATUS_AVAILABLE)
  1150. }
  1151. if usable {
  1152. wires := WireManager.Query().SubQuery()
  1153. networks := NetworkManager.Query().SubQuery()
  1154. sq := wires.Query(wires.Field("vpc_id")).Join(networks, sqlchemy.Equals(wires.Field("id"), networks.Field("wire_id"))).Filter(
  1155. sqlchemy.Equals(networks.Field("status"), api.NETWORK_STATUS_AVAILABLE),
  1156. )
  1157. q = q.In("id", sq.SubQuery())
  1158. }
  1159. }
  1160. if len(query.ZoneId) > 0 {
  1161. zoneObj, err := validators.ValidateModel(ctx, userCred, ZoneManager, &query.ZoneId)
  1162. if err != nil {
  1163. return nil, err
  1164. }
  1165. region, err := zoneObj.(*SZone).GetRegion()
  1166. if err != nil {
  1167. return nil, errors.Wrapf(err, "get zone %s region", zoneObj.GetName())
  1168. }
  1169. q = q.Equals("cloudregion_id", region.Id)
  1170. wires := WireManager.Query().SubQuery()
  1171. networks := NetworkManager.Query().SubQuery()
  1172. sq := wires.Query(wires.Field("vpc_id")).Join(networks, sqlchemy.Equals(wires.Field("id"), networks.Field("wire_id"))).Filter(
  1173. sqlchemy.OR(
  1174. sqlchemy.Equals(wires.Field("zone_id"), query.ZoneId),
  1175. sqlchemy.IsNullOrEmpty(wires.Field("zone_id")),
  1176. ),
  1177. )
  1178. q = q.In("id", sq.SubQuery())
  1179. }
  1180. if query.IsDefault != nil {
  1181. if *query.IsDefault {
  1182. q = q.IsTrue("is_default")
  1183. } else {
  1184. q = q.IsFalse("is_default")
  1185. }
  1186. }
  1187. if len(query.CidrBlock) > 0 {
  1188. q = q.In("cidr_block", query.CidrBlock)
  1189. }
  1190. if len(query.CidrBlock6) > 0 {
  1191. q = q.In("cidr_block6", query.CidrBlock6)
  1192. }
  1193. return q, nil
  1194. }
  1195. func (manager *SVpcManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
  1196. switch field {
  1197. case "vpc":
  1198. q = q.AppendField(q.Field("name").Label("vpc")).Distinct()
  1199. return q, nil
  1200. default:
  1201. var err error
  1202. q, err = manager.SEnabledStatusInfrasResourceBaseManager.QueryDistinctExtraField(q, field)
  1203. if err == nil {
  1204. return q, nil
  1205. }
  1206. q, err = manager.SManagedResourceBaseManager.QueryDistinctExtraField(q, field)
  1207. if err == nil {
  1208. return q, nil
  1209. }
  1210. q, err = manager.SCloudregionResourceBaseManager.QueryDistinctExtraField(q, field)
  1211. if err == nil {
  1212. return q, nil
  1213. }
  1214. q, err = manager.SGlobalVpcResourceBaseManager.QueryDistinctExtraField(q, field)
  1215. if err == nil {
  1216. return q, nil
  1217. }
  1218. }
  1219. return q, httperrors.ErrNotFound
  1220. }
  1221. func (manager *SVpcManager) QueryDistinctExtraFields(q *sqlchemy.SQuery, resource string, fields []string) (*sqlchemy.SQuery, error) {
  1222. var err error
  1223. q, err = manager.SManagedResourceBaseManager.QueryDistinctExtraFields(q, resource, fields)
  1224. if err == nil {
  1225. return q, nil
  1226. }
  1227. return q, httperrors.ErrNotFound
  1228. }
  1229. func (manager *SVpcManager) OrderByExtraFields(
  1230. ctx context.Context,
  1231. q *sqlchemy.SQuery,
  1232. userCred mcclient.TokenCredential,
  1233. query api.VpcListInput,
  1234. ) (*sqlchemy.SQuery, error) {
  1235. q, err := manager.SEnabledStatusInfrasResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.EnabledStatusInfrasResourceBaseListInput)
  1236. if err != nil {
  1237. return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager.OrderByExtraFields")
  1238. }
  1239. q, err = manager.SManagedResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.ManagedResourceListInput)
  1240. if err != nil {
  1241. return nil, errors.Wrap(err, "SManagedResourceBaseManager.OrderByExtraFields")
  1242. }
  1243. q, err = manager.SCloudregionResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.RegionalFilterListInput)
  1244. if err != nil {
  1245. return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.OrderByExtraFields")
  1246. }
  1247. q, err = manager.SGlobalVpcResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.GlobalVpcResourceListInput)
  1248. if err != nil {
  1249. return nil, errors.Wrap(err, "SGlobalVpcResourceBaseManager.OrderByExtraFields")
  1250. }
  1251. if db.NeedOrderQuery([]string{query.OrderByNetworkCount}) {
  1252. var (
  1253. wireq = WireManager.Query().SubQuery()
  1254. netq = NetworkManager.Query().SubQuery()
  1255. vpcq = VpcManager.Query().SubQuery()
  1256. )
  1257. countq := vpcq.Query(
  1258. vpcq.Field("id"),
  1259. sqlchemy.COUNT("network_count", netq.Field("id")),
  1260. )
  1261. countq = countq.Join(wireq, sqlchemy.OR(
  1262. sqlchemy.Equals(countq.Field("id"), wireq.Field("vpc_id")),
  1263. sqlchemy.AND(
  1264. sqlchemy.Equals(countq.Field("id"), api.DEFAULT_VPC_ID),
  1265. sqlchemy.IsNullOrEmpty(wireq.Field("vpc_id")),
  1266. ),
  1267. ))
  1268. countq = countq.Join(netq, sqlchemy.Equals(
  1269. netq.Field("wire_id"), wireq.Field("id"),
  1270. ))
  1271. countq = countq.GroupBy(vpcq.Field("id"))
  1272. countSubq := countq.SubQuery()
  1273. q = q.LeftJoin(countSubq, sqlchemy.Equals(
  1274. q.Field("id"), countSubq.Field("id"),
  1275. ))
  1276. q.AppendField(q.QueryFields()...)
  1277. q = q.AppendField(countSubq.Field("network_count"))
  1278. q = db.OrderByFields(q,
  1279. []string{
  1280. query.OrderByNetworkCount,
  1281. },
  1282. []sqlchemy.IQueryField{
  1283. countSubq.Field("network_count"),
  1284. },
  1285. )
  1286. }
  1287. if db.NeedOrderQuery([]string{query.OrderByWireCount}) {
  1288. wireQ := WireManager.Query()
  1289. wireQ = wireQ.AppendField(wireQ.Field("vpc_id"), sqlchemy.COUNT("wire_count"))
  1290. wireQ = wireQ.GroupBy(wireQ.Field("vpc_id"))
  1291. wireSQ := wireQ.SubQuery()
  1292. q = q.LeftJoin(wireSQ, sqlchemy.Equals(wireSQ.Field("vpc_id"), q.Field("id")))
  1293. q = q.AppendField(q.QueryFields()...)
  1294. q = q.AppendField(wireSQ.Field("wire_count"))
  1295. q = db.OrderByFields(q, []string{query.OrderByWireCount}, []sqlchemy.IQueryField{q.Field("wire_count")})
  1296. }
  1297. return q, nil
  1298. }
  1299. func (svpc *SVpc) SyncRemoteWires(ctx context.Context, userCred mcclient.TokenCredential) error {
  1300. ivpc, err := svpc.GetIVpc(ctx)
  1301. if err != nil {
  1302. return errors.Wrap(err, "GetIVpc")
  1303. }
  1304. provider := CloudproviderManager.FetchCloudproviderById(svpc.ManagerId)
  1305. syncVpcWires(ctx, userCred, nil, provider, svpc, ivpc, nil, &SSyncRange{})
  1306. hosts := HostManager.GetHostsByManagerAndRegion(provider.Id, svpc.CloudregionId)
  1307. for i := 0; i < len(hosts); i += 1 {
  1308. ihost, err := hosts[i].GetIHost(ctx)
  1309. if err != nil {
  1310. return err
  1311. }
  1312. syncHostNics(ctx, userCred, nil, provider, &hosts[i], ihost)
  1313. }
  1314. return nil
  1315. }
  1316. // 同步VPC状态
  1317. func (vpc *SVpc) PerformSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.VpcSyncstatusInput) (jsonutils.JSONObject, error) {
  1318. return vpc.PerformSync(ctx, userCred, query, input)
  1319. }
  1320. func (vpc *SVpc) PerformSync(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.VpcSyncstatusInput) (jsonutils.JSONObject, error) {
  1321. if vpc.IsManaged() {
  1322. return nil, StartResourceSyncStatusTask(ctx, userCred, vpc, "VpcSyncstatusTask", "")
  1323. }
  1324. return nil, httperrors.NewUnsupportOperationError("on-premise vpc cannot sync status")
  1325. }
  1326. func (svpc *SVpc) initWire(ctx context.Context, zone *SZone, externalId string) (*SWire, error) {
  1327. wire := &SWire{
  1328. Bandwidth: 10000,
  1329. Mtu: options.Options.OvnUnderlayMtu,
  1330. }
  1331. wire.VpcId = svpc.Id
  1332. wire.ZoneId = zone.Id
  1333. wire.IsEmulated = true
  1334. wire.ExternalId = externalId
  1335. wire.Name = fmt.Sprintf("vpc-%s", svpc.Name)
  1336. wire.DomainId = svpc.DomainId
  1337. wire.IsPublic = svpc.IsPublic
  1338. wire.PublicScope = svpc.PublicScope
  1339. wire.ManagerId = svpc.ManagerId
  1340. wire.SetModelManager(WireManager, wire)
  1341. err := WireManager.TableSpec().Insert(ctx, wire)
  1342. if err != nil {
  1343. return nil, err
  1344. }
  1345. return wire, nil
  1346. }
  1347. func GetVpcQuotaKeysFromCreateInput(owner mcclient.IIdentityProvider, input api.VpcCreateInput) quotas.SDomainRegionalCloudResourceKeys {
  1348. ownerId := &db.SOwnerId{DomainId: owner.GetProjectDomainId()}
  1349. var region *SCloudregion
  1350. if len(input.CloudregionId) > 0 {
  1351. region = CloudregionManager.FetchRegionById(input.CloudregionId)
  1352. }
  1353. var provider *SCloudprovider
  1354. if len(input.CloudproviderId) > 0 {
  1355. provider = CloudproviderManager.FetchCloudproviderById(input.CloudproviderId)
  1356. }
  1357. regionKeys := fetchRegionalQuotaKeys(rbacscope.ScopeDomain, ownerId, region, provider)
  1358. keys := quotas.SDomainRegionalCloudResourceKeys{}
  1359. keys.SBaseDomainQuotaKeys = regionKeys.SBaseDomainQuotaKeys
  1360. keys.SRegionalBaseKeys = regionKeys.SRegionalBaseKeys
  1361. keys.SCloudResourceBaseKeys = regionKeys.SCloudResourceBaseKeys
  1362. return keys
  1363. }
  1364. func (vpc *SVpc) GetQuotaKeys() quotas.SDomainRegionalCloudResourceKeys {
  1365. region, _ := vpc.GetRegion()
  1366. manager := vpc.GetCloudprovider()
  1367. ownerId := vpc.GetOwnerId()
  1368. regionKeys := fetchRegionalQuotaKeys(rbacscope.ScopeDomain, ownerId, region, manager)
  1369. keys := quotas.SDomainRegionalCloudResourceKeys{}
  1370. keys.SBaseDomainQuotaKeys = regionKeys.SBaseDomainQuotaKeys
  1371. keys.SRegionalBaseKeys = regionKeys.SRegionalBaseKeys
  1372. keys.SCloudResourceBaseKeys = regionKeys.SCloudResourceBaseKeys
  1373. return keys
  1374. }
  1375. func (vpc *SVpc) GetUsages() []db.IUsage {
  1376. if vpc.Deleted {
  1377. return nil
  1378. }
  1379. usage := SInfrasQuota{Vpc: 1}
  1380. keys := vpc.GetQuotaKeys()
  1381. usage.SetKeys(keys)
  1382. return []db.IUsage{
  1383. &usage,
  1384. }
  1385. }
  1386. func (manager *SVpcManager) totalCount(
  1387. ctx context.Context,
  1388. ownerId mcclient.IIdentityProvider,
  1389. scope rbacscope.TRbacScope,
  1390. rangeObjs []db.IStandaloneModel,
  1391. providers []string,
  1392. brands []string,
  1393. cloudEnv string,
  1394. ) int {
  1395. q := VpcManager.Query()
  1396. if scope != rbacscope.ScopeSystem && ownerId != nil {
  1397. q = q.Equals("domain_id", ownerId.GetProjectDomainId())
  1398. }
  1399. q = CloudProviderFilter(q, q.Field("manager_id"), providers, brands, cloudEnv)
  1400. q = RangeObjectsFilter(q, rangeObjs, q.Field("cloudregion_id"), nil, q.Field("manager_id"), nil, nil)
  1401. cnt, _ := q.CountWithError()
  1402. return cnt
  1403. }
  1404. func (vpc *SVpc) GetChangeOwnerCandidateDomainIds() []string {
  1405. candidates := [][]string{
  1406. vpc.SManagedResourceBase.GetChangeOwnerCandidateDomainIds(),
  1407. }
  1408. globalVpc, _ := vpc.GetGlobalVpc()
  1409. if globalVpc != nil {
  1410. candidates = append(candidates, db.ISharableChangeOwnerCandidateDomainIds(globalVpc))
  1411. }
  1412. log.Debugf("Candidate: %s", candidates)
  1413. return db.ISharableMergeChangeOwnerCandidateDomainIds(vpc, candidates...)
  1414. }
  1415. func (vpc *SVpc) GetChangeOwnerRequiredDomainIds() []string {
  1416. requires := stringutils2.SSortedStrings{}
  1417. wires, _ := vpc.GetWires()
  1418. for i := range wires {
  1419. requires = stringutils2.Append(requires, wires[i].DomainId)
  1420. }
  1421. return requires
  1422. }
  1423. func (vpc *SVpc) GetRequiredSharedDomainIds() []string {
  1424. wires, _ := vpc.GetWires()
  1425. if len(wires) == 0 {
  1426. return vpc.SEnabledStatusInfrasResourceBase.GetRequiredSharedDomainIds()
  1427. }
  1428. requires := make([][]string, len(wires))
  1429. for i := range wires {
  1430. requires[i] = db.ISharableChangeOwnerCandidateDomainIds(&wires[i])
  1431. }
  1432. return db.ISharableMergeShareRequireDomainIds(requires...)
  1433. }
  1434. func (manager *SVpcManager) ListItemExportKeys(ctx context.Context,
  1435. q *sqlchemy.SQuery,
  1436. userCred mcclient.TokenCredential,
  1437. keys stringutils2.SSortedStrings,
  1438. ) (*sqlchemy.SQuery, error) {
  1439. q, err := manager.SEnabledStatusInfrasResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  1440. if err != nil {
  1441. return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager.ListItemExportKeys")
  1442. }
  1443. if keys.ContainsAny(manager.SCloudregionResourceBaseManager.GetExportKeys()...) {
  1444. q, err = manager.SCloudregionResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  1445. if err != nil {
  1446. return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.ListItemExportKeys")
  1447. }
  1448. }
  1449. if keys.ContainsAny(manager.SManagedResourceBaseManager.GetExportKeys()...) {
  1450. q, err = manager.SManagedResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  1451. if err != nil {
  1452. return nil, errors.Wrap(err, "SManagedResourceBaseManager.ListItemExportKeys")
  1453. }
  1454. }
  1455. if keys.ContainsAny(manager.SGlobalVpcResourceBaseManager.GetExportKeys()...) {
  1456. q, err = manager.SGlobalVpcResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  1457. if err != nil {
  1458. return nil, errors.Wrap(err, "SGlobalVpcResourceBaseManager.ListItemExportKeys")
  1459. }
  1460. }
  1461. if keys.Contains("wire_count") {
  1462. wires := WireManager.Query("vpc_id").SubQuery()
  1463. subq := wires.Query(sqlchemy.COUNT("wire_count"), wires.Field("vpc_id")).GroupBy(wires.Field("vpc_id")).SubQuery()
  1464. q = q.LeftJoin(subq, sqlchemy.Equals(q.Field("id"), subq.Field("vpc_id")))
  1465. q = q.AppendField(subq.Field("wire_count"))
  1466. }
  1467. if keys.Contains("network_count") {
  1468. wires := WireManager.Query("id", "vpc_id").SubQuery()
  1469. networks := NetworkManager.Query("wire_id").SubQuery()
  1470. subq := networks.Query(sqlchemy.COUNT("network_count"), wires.Field("vpc_id"))
  1471. subq = subq.LeftJoin(wires, sqlchemy.Equals(networks.Field("wire_id"), wires.Field("id")))
  1472. subq = subq.GroupBy(wires.Field("vpc_id"))
  1473. subqQ := subq.SubQuery()
  1474. q = q.LeftJoin(subqQ, sqlchemy.Equals(q.Field("id"), subqQ.Field("vpc_id")))
  1475. q = q.AppendField(subqQ.Field("network_count"))
  1476. }
  1477. return q, nil
  1478. }
  1479. func (vpc *SVpc) PerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPublicDomainInput) (jsonutils.JSONObject, error) {
  1480. if vpc.Id == api.DEFAULT_VPC_ID && rbacscope.String2ScopeDefault(input.Scope, rbacscope.ScopeSystem) != rbacscope.ScopeSystem {
  1481. return nil, httperrors.NewForbiddenError("For default vpc, only system level sharing can be set")
  1482. }
  1483. _, err := vpc.SEnabledStatusInfrasResourceBase.PerformPublic(ctx, userCred, query, input)
  1484. if err != nil {
  1485. return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.PerformPublic")
  1486. }
  1487. // perform public for all emulated wires
  1488. wires, _ := vpc.GetWires()
  1489. for i := range wires {
  1490. if wires[i].IsEmulated {
  1491. _, err := wires[i].PerformPublic(ctx, userCred, query, input)
  1492. if err != nil {
  1493. return nil, errors.Wrap(err, "wire.PerformPublic")
  1494. }
  1495. }
  1496. }
  1497. nats, err := vpc.GetNatgateways()
  1498. if err != nil {
  1499. return nil, errors.Wrapf(err, "vpc.GetNatgateways")
  1500. }
  1501. for i := range nats {
  1502. _, err = nats[i].PerformPublic(ctx, userCred, query, input)
  1503. if err != nil {
  1504. return nil, errors.Wrapf(err, "nat.PerformPublic")
  1505. }
  1506. }
  1507. return nil, nil
  1508. }
  1509. func (vpc *SVpc) PerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPrivateInput) (jsonutils.JSONObject, error) {
  1510. if vpc.Id == "default" {
  1511. return nil, httperrors.NewForbiddenError("Prohibit making default vpc private")
  1512. }
  1513. nats, err := vpc.GetNatgateways()
  1514. if err != nil {
  1515. return nil, errors.Wrapf(err, "vpc.GetNatgateways")
  1516. }
  1517. for i := range nats {
  1518. _, err = nats[i].PerformPrivate(ctx, userCred, query, input)
  1519. if err != nil {
  1520. return nil, errors.Wrapf(err, "nat.PerformPrivate")
  1521. }
  1522. }
  1523. // perform private for all emulated wires
  1524. emptyNets := true
  1525. wires, _ := vpc.GetWires()
  1526. for i := range wires {
  1527. if wires[i].DomainId == vpc.DomainId {
  1528. nets, _ := wires[i].getNetworks(ctx, nil, nil, rbacscope.ScopeNone)
  1529. for j := range nets {
  1530. if nets[j].DomainId != vpc.DomainId {
  1531. emptyNets = false
  1532. break
  1533. }
  1534. }
  1535. if !emptyNets {
  1536. break
  1537. }
  1538. } else {
  1539. emptyNets = false
  1540. break
  1541. }
  1542. }
  1543. if emptyNets {
  1544. for i := range wires {
  1545. nets, _ := wires[i].getNetworks(ctx, nil, nil, rbacscope.ScopeNone)
  1546. netfail := false
  1547. for j := range nets {
  1548. if nets[j].IsPublic && nets[j].GetPublicScope().HigherEqual(rbacscope.ScopeDomain) {
  1549. var err error
  1550. if consts.GetNonDefaultDomainProjects() {
  1551. netinput := apis.PerformPublicProjectInput{}
  1552. netinput.Scope = string(rbacscope.ScopeDomain)
  1553. _, err = nets[j].PerformPublic(ctx, userCred, nil, netinput)
  1554. } else {
  1555. _, err = nets[j].PerformPrivate(ctx, userCred, nil, input)
  1556. }
  1557. if err != nil {
  1558. log.Errorf("nets[j].PerformPublic fail %s", err)
  1559. netfail = true
  1560. break
  1561. }
  1562. }
  1563. }
  1564. if netfail {
  1565. break
  1566. }
  1567. _, err := wires[i].PerformPrivate(ctx, userCred, query, input)
  1568. if err != nil {
  1569. log.Errorf("wires[i].PerformPrivate fail %s", err)
  1570. break
  1571. }
  1572. }
  1573. }
  1574. return vpc.SEnabledStatusInfrasResourceBase.PerformPrivate(ctx, userCred, query, input)
  1575. }
  1576. func (vpc *SVpc) PerformChangeOwner(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformChangeDomainOwnerInput) (jsonutils.JSONObject, error) {
  1577. _, err := vpc.SEnabledStatusInfrasResourceBase.PerformChangeOwner(ctx, userCred, query, input)
  1578. if err != nil {
  1579. return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.PerformChangeOwner")
  1580. }
  1581. wires, _ := vpc.GetWires()
  1582. for i := range wires {
  1583. if wires[i].IsEmulated {
  1584. _, err := wires[i].PerformChangeOwner(ctx, userCred, query, input)
  1585. if err != nil {
  1586. return nil, errors.Wrap(err, "wires[i].PerformChangeOwner")
  1587. }
  1588. }
  1589. }
  1590. return nil, nil
  1591. }
  1592. func (svpc *SVpc) GetVpcPeeringConnections() ([]SVpcPeeringConnection, error) {
  1593. q := VpcPeeringConnectionManager.Query().Equals("vpc_id", svpc.Id)
  1594. peers := []SVpcPeeringConnection{}
  1595. err := db.FetchModelObjects(VpcPeeringConnectionManager, q, &peers)
  1596. if err != nil {
  1597. return nil, errors.Wrapf(err, "db.FetchModelObjects")
  1598. }
  1599. return peers, nil
  1600. }
  1601. func (svpc *SVpc) GetVpcPeeringConnectionByExtId(extId string) (*SVpcPeeringConnection, error) {
  1602. peer, err := db.FetchByExternalIdAndManagerId(VpcPeeringConnectionManager, extId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  1603. return q.Equals("vpc_id", svpc.Id)
  1604. })
  1605. if err != nil {
  1606. return nil, errors.Wrapf(err, "FetchByExternalIdAndManagerId %s", extId)
  1607. }
  1608. return peer.(*SVpcPeeringConnection), nil
  1609. }
  1610. func (svpc *SVpc) GetAccepterVpcPeeringConnectionByExtId(extId string) (*SVpcPeeringConnection, error) {
  1611. peer, err := db.FetchByExternalIdAndManagerId(VpcPeeringConnectionManager, extId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  1612. return q.Equals("peer_vpc_id", svpc.Id)
  1613. })
  1614. if err != nil {
  1615. return nil, errors.Wrapf(err, "FetchByExternalIdAndManagerId %s", extId)
  1616. }
  1617. return peer.(*SVpcPeeringConnection), nil
  1618. }
  1619. func (svpc *SVpc) BackSycVpcPeeringConnectionsVpc(exts []cloudprovider.ICloudVpcPeeringConnection) compare.SyncResult {
  1620. result := compare.SyncResult{}
  1621. for i := range exts {
  1622. Peering, err := svpc.GetAccepterVpcPeeringConnectionByExtId(exts[i].GetId())
  1623. if err != nil {
  1624. if errors.Cause(err) != errors.ErrNotFound {
  1625. result.Error(err)
  1626. }
  1627. break
  1628. }
  1629. if len(Peering.PeerVpcId) == 0 {
  1630. _, err := db.Update(Peering, func() error {
  1631. Peering.PeerVpcId = svpc.GetId()
  1632. return nil
  1633. })
  1634. if err != nil {
  1635. result.Error(err)
  1636. break
  1637. }
  1638. }
  1639. }
  1640. return result
  1641. }
  1642. func (svpc *SVpc) SyncVpcPeeringConnections(
  1643. ctx context.Context,
  1644. userCred mcclient.TokenCredential,
  1645. exts []cloudprovider.ICloudVpcPeeringConnection,
  1646. xor bool,
  1647. ) compare.SyncResult {
  1648. result := compare.SyncResult{}
  1649. dbPeers, err := svpc.GetVpcPeeringConnections()
  1650. if err != nil {
  1651. result.Error(errors.Wrapf(err, "GetVpcPeeringConnections"))
  1652. return result
  1653. }
  1654. provider := svpc.GetCloudprovider()
  1655. removed := make([]SVpcPeeringConnection, 0)
  1656. commondb := make([]SVpcPeeringConnection, 0)
  1657. commonext := make([]cloudprovider.ICloudVpcPeeringConnection, 0)
  1658. added := make([]cloudprovider.ICloudVpcPeeringConnection, 0)
  1659. err = compare.CompareSets(dbPeers, exts, &removed, &commondb, &commonext, &added)
  1660. if err != nil {
  1661. result.Error(err)
  1662. return result
  1663. }
  1664. for i := 0; i < len(removed); i += 1 {
  1665. if len(removed[i].ExternalId) > 0 {
  1666. err = removed[i].syncRemove(ctx, userCred)
  1667. if err != nil {
  1668. result.DeleteError(err)
  1669. continue
  1670. }
  1671. result.Delete()
  1672. }
  1673. }
  1674. if !xor {
  1675. for i := 0; i < len(commondb); i += 1 {
  1676. err = commondb[i].SyncWithCloudPeerConnection(ctx, userCred, commonext[i])
  1677. if err != nil {
  1678. result.UpdateError(err)
  1679. continue
  1680. }
  1681. result.Update()
  1682. }
  1683. }
  1684. for i := 0; i < len(added); i += 1 {
  1685. _, err := svpc.newFromCloudPeerConnection(ctx, userCred, added[i], provider)
  1686. if err != nil {
  1687. result.AddError(errors.Wrapf(err, "newFromCloudPeerConnection"))
  1688. continue
  1689. }
  1690. result.Add()
  1691. }
  1692. return result
  1693. }
  1694. func (svpc *SVpc) newFromCloudPeerConnection(ctx context.Context, userCred mcclient.TokenCredential, ext cloudprovider.ICloudVpcPeeringConnection, provider *SCloudprovider) (*SVpcPeeringConnection, error) {
  1695. peer := &SVpcPeeringConnection{}
  1696. peer.SetModelManager(VpcPeeringConnectionManager, peer)
  1697. peer.ExternalId = ext.GetGlobalId()
  1698. peer.Status = ext.GetStatus()
  1699. peer.VpcId = svpc.Id
  1700. peer.Enabled = tristate.True
  1701. peer.ExtPeerVpcId = ext.GetPeerVpcId()
  1702. manager := svpc.GetCloudprovider()
  1703. peerVpc, _ := db.FetchByExternalIdAndManagerId(VpcManager, peer.ExtPeerVpcId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  1704. managerQ := CloudproviderManager.Query("id").Equals("provider", manager.Provider)
  1705. return q.In("manager_id", managerQ.SubQuery())
  1706. })
  1707. if peerVpc != nil {
  1708. peer.PeerVpcId = peerVpc.GetId()
  1709. }
  1710. peer.ExtPeerAccountId = ext.GetPeerAccountId()
  1711. var err = func() error {
  1712. lockman.LockClass(ctx, VpcPeeringConnectionManager, "name")
  1713. defer lockman.ReleaseClass(ctx, VpcPeeringConnectionManager, "name")
  1714. var err error
  1715. peer.Name, err = db.GenerateName(ctx, VpcPeeringConnectionManager, provider.GetOwnerId(), ext.GetName())
  1716. if err != nil {
  1717. return errors.Wrapf(err, "db.GenerateName")
  1718. }
  1719. return VpcPeeringConnectionManager.TableSpec().Insert(ctx, peer)
  1720. }()
  1721. if err != nil {
  1722. return nil, errors.Wrapf(err, "Insert")
  1723. }
  1724. if provider != nil {
  1725. SyncCloudDomain(userCred, peer, provider.GetOwnerId())
  1726. peer.SyncShareState(ctx, userCred, provider.getAccountShareInfo())
  1727. }
  1728. db.OpsLog.LogEvent(peer, db.ACT_CREATE, peer.GetShortDesc(ctx), userCred)
  1729. return peer, nil
  1730. }
  1731. func (svpc *SVpc) IsSupportAssociateEip() bool {
  1732. if utils.IsInStringArray(svpc.ExternalAccessMode, []string{api.VPC_EXTERNAL_ACCESS_MODE_EIP_DISTGW, api.VPC_EXTERNAL_ACCESS_MODE_EIP}) {
  1733. return true
  1734. }
  1735. return false
  1736. }
  1737. func (svpc *SVpc) GetDetailsTopology(ctx context.Context, userCred mcclient.TokenCredential, input *api.VpcTopologyInput) (*api.VpcTopologyOutput, error) {
  1738. ret := &api.VpcTopologyOutput{
  1739. Name: svpc.Name,
  1740. Status: svpc.Status,
  1741. Wires: []api.WireTopologyOutput{},
  1742. }
  1743. wires, err := svpc.GetWires()
  1744. if err != nil {
  1745. return ret, errors.Wrapf(err, "GetWires")
  1746. }
  1747. for i := range wires {
  1748. wire := api.WireTopologyOutput{
  1749. Name: wires[i].Name,
  1750. Status: wires[i].Status,
  1751. Bandwidth: wires[i].Bandwidth,
  1752. Networks: []api.NetworkTopologyOutput{},
  1753. Hosts: []api.HostTopologyOutput{},
  1754. }
  1755. if len(wires[i].ZoneId) > 0 {
  1756. zone, _ := wires[i].GetZone()
  1757. if zone != nil {
  1758. wire.Zone = zone.Name
  1759. }
  1760. }
  1761. hosts, err := wires[i].GetHosts()
  1762. if err != nil {
  1763. return nil, errors.Wrapf(err, "GetHosts for wire %s", wires[i].Id)
  1764. }
  1765. for i := range hosts {
  1766. hns := hosts[i].GetBaremetalnetworks()
  1767. hss := hosts[i]._getAttachedStorages(tristate.None, tristate.None, nil)
  1768. host := api.HostTopologyOutput{
  1769. Name: hosts[i].Name,
  1770. Id: hosts[i].Id,
  1771. Status: hosts[i].Status,
  1772. HostStatus: hosts[i].HostStatus,
  1773. HostType: hosts[i].HostType,
  1774. Networks: []api.HostnetworkTopologyOutput{},
  1775. Storages: []api.StorageShortDesc{},
  1776. Schedtags: GetSchedtagsDetailsToResourceV2(&hosts[i], ctx),
  1777. }
  1778. for j := range hns {
  1779. host.Networks = append(host.Networks, api.HostnetworkTopologyOutput{
  1780. IpAddr: hns[j].IpAddr,
  1781. Ip6Addr: hns[j].Ip6Addr,
  1782. MacAddr: hns[j].MacAddr,
  1783. })
  1784. }
  1785. for j := range hss {
  1786. host.Storages = append(host.Storages, api.StorageShortDesc{
  1787. Name: hss[j].Name,
  1788. Id: hss[j].Id,
  1789. Status: hss[j].Status,
  1790. Enabled: hss[j].Enabled.Bool(),
  1791. StorageType: hss[j].StorageType,
  1792. CapacityMb: hss[j].Capacity,
  1793. })
  1794. }
  1795. wire.Hosts = append(wire.Hosts, host)
  1796. }
  1797. networks, err := wires[i].GetNetworks(ctx, nil, nil, rbacscope.ScopeSystem)
  1798. if err != nil {
  1799. return nil, errors.Wrapf(err, "GetNetworks")
  1800. }
  1801. for j := range networks {
  1802. network := api.NetworkTopologyOutput{
  1803. Name: networks[j].Name,
  1804. Status: networks[j].Status,
  1805. GuestIpStart: networks[j].GuestIpStart,
  1806. GuestIpEnd: networks[j].GuestIpEnd,
  1807. GuestIpMask: networks[j].GuestIpMask,
  1808. ServerType: networks[j].ServerType,
  1809. VlanId: networks[j].VlanId,
  1810. // Address: []api.SNetworkUsedAddress{},
  1811. }
  1812. network.GetNetworkAddressesOutput, err = networks[j].fetchAddressDetails(ctx, userCred, userCred, rbacscope.ScopeSystem)
  1813. if err != nil {
  1814. return nil, errors.Wrapf(err, "fetchAddressDetails")
  1815. }
  1816. wire.Networks = append(wire.Networks, network)
  1817. }
  1818. ret.Wires = append(ret.Wires, wire)
  1819. }
  1820. return ret, nil
  1821. }
  1822. func (self *SVpc) CheckSecurityGroupConsistent(secgroup *SSecurityGroup) error {
  1823. if secgroup.Status != api.SECGROUP_STATUS_READY {
  1824. return httperrors.NewInvalidStatusError("security group %s status is not ready", secgroup.Name)
  1825. }
  1826. if len(self.ExternalId) > 0 && len(secgroup.ExternalId) == 0 {
  1827. return httperrors.NewInvalidStatusError("The security group %s does not have an external id", secgroup.Name)
  1828. }
  1829. if len(secgroup.VpcId) > 0 {
  1830. if secgroup.VpcId != self.Id {
  1831. return httperrors.NewInvalidStatusError("The security group does not belong to the vpc")
  1832. }
  1833. } else if len(secgroup.GlobalvpcId) > 0 {
  1834. if secgroup.GlobalvpcId != self.GlobalvpcId {
  1835. return httperrors.NewInvalidStatusError("The security group and vpc are in different global vpc")
  1836. }
  1837. } else if len(secgroup.CloudregionId) > 0 {
  1838. if secgroup.CloudregionId != self.CloudregionId {
  1839. return httperrors.NewInvalidStatusError("The security group and vpc are in different areas")
  1840. }
  1841. }
  1842. return nil
  1843. }
  1844. func (self *SVpc) GetSecurityGroups() ([]SSecurityGroup, error) {
  1845. q := SecurityGroupManager.Query().Equals("vpc_id", self.Id)
  1846. ret := []SSecurityGroup{}
  1847. err := db.FetchModelObjects(SecurityGroupManager, q, &ret)
  1848. if err != nil {
  1849. return nil, err
  1850. }
  1851. return ret, nil
  1852. }
  1853. func (self *SVpc) GetDefaultSecurityGroup(ownerId mcclient.IIdentityProvider, filter func(q *sqlchemy.SQuery) *sqlchemy.SQuery) (*SSecurityGroup, error) {
  1854. q := SecurityGroupManager.Query().Equals("status", api.SECGROUP_STATUS_READY).Like("name", "%"+"default"+"%")
  1855. q = filter(q)
  1856. q = q.Filter(
  1857. sqlchemy.OR(
  1858. sqlchemy.AND(
  1859. sqlchemy.Equals(q.Field("public_scope"), "system"),
  1860. sqlchemy.Equals(q.Field("is_public"), true),
  1861. ),
  1862. sqlchemy.AND(
  1863. sqlchemy.Equals(q.Field("tenant_id"), ownerId.GetProjectId()),
  1864. sqlchemy.Equals(q.Field("domain_id"), ownerId.GetProjectDomainId()),
  1865. ),
  1866. ),
  1867. )
  1868. ret := &SSecurityGroup{}
  1869. ret.SetModelManager(SecurityGroupManager, ret)
  1870. err := q.First(ret)
  1871. if err != nil {
  1872. return nil, err
  1873. }
  1874. return ret, nil
  1875. }
  1876. func (manager *SVpcManager) FetchVpcById(id string) *SVpc {
  1877. obj, err := manager.FetchById(id)
  1878. if err != nil {
  1879. log.Errorf("region %s %s", id, err)
  1880. return nil
  1881. }
  1882. return obj.(*SVpc)
  1883. }
  1884. func (manager *SVpcManager) FetchDefaultVpc() *SVpc {
  1885. return manager.FetchVpcById(api.DEFAULT_VPC_ID)
  1886. }