From 81b6208dda833a1bbcca39a0788da2088a679334 Mon Sep 17 00:00:00 2001 From: TangBin Date: Wed, 8 May 2019 11:18:56 +0800 Subject: [PATCH 1/3] sku provider filter by zone --- pkg/compute/models/skus.go | 28 +------------ pkg/compute/models/zones.go | 83 +++++++++++++++++++------------------ 2 files changed, 45 insertions(+), 66 deletions(-) diff --git a/pkg/compute/models/skus.go b/pkg/compute/models/skus.go index ac2a2ed6ff..9b51e54598 100644 --- a/pkg/compute/models/skus.go +++ b/pkg/compute/models/skus.go @@ -496,32 +496,8 @@ func providerFilter(q *sqlchemy.SQuery, provider string, public_cloud bool) *sql } // 过滤出network usable的sku - providers := CloudproviderManager.Query().SubQuery() - networks := NetworkManager.Query().SubQuery() - wires := WireManager.Query().SubQuery() - vpcs := VpcManager.Query().SubQuery() - - sq := vpcs.Query(sqlchemy.DISTINCT("cloudregion_id", vpcs.Field("cloudregion_id"))) - sq = sq.Join(wires, sqlchemy.Equals(vpcs.Field("id"), wires.Field("vpc_id"))) - sq = sq.Join(networks, sqlchemy.Equals(wires.Field("id"), networks.Field("wire_id"))) - sq = sq.Join(providers, sqlchemy.Equals(vpcs.Field("manager_id"), providers.Field("id"))) - sq = sq.Filter(sqlchemy.Equals(networks.Field("status"), api.NETWORK_STATUS_AVAILABLE)) - sq = sq.Filter(sqlchemy.IsTrue(providers.Field("enabled"))) - sq = sq.Filter(sqlchemy.In(providers.Field("status"), api.CLOUD_PROVIDER_VALID_STATUS)) - sq = sq.Filter(sqlchemy.Equals(providers.Field("health_status"), api.CLOUD_PROVIDER_HEALTH_NORMAL)) - sq = sq.Filter(sqlchemy.Equals(vpcs.Field("status"), api.VPC_STATUS_AVAILABLE)) - - sq2 := vpcs.Query(sqlchemy.DISTINCT("cloudregion_id", vpcs.Field("cloudregion_id"))) - sq2 = sq2.Join(wires, sqlchemy.Equals(vpcs.Field("id"), wires.Field("vpc_id"))) - sq2 = sq2.Join(networks, sqlchemy.Equals(wires.Field("id"), networks.Field("wire_id"))) - sq2 = sq2.Filter(sqlchemy.Equals(networks.Field("status"), api.NETWORK_STATUS_AVAILABLE)) - sq2 = sq2.Filter(sqlchemy.IsNullOrEmpty(vpcs.Field("manager_id"))) - sq2 = sq2.Filter(sqlchemy.Equals(vpcs.Field("status"), api.VPC_STATUS_AVAILABLE)) - - q = q.Filter(sqlchemy.OR( - sqlchemy.In(q.Field("cloudregion_id"), sq.SubQuery()), - sqlchemy.In(q.Field("cloudregion_id"), sq2.SubQuery()), - )) + iconditions := NetworkUsableZoneQueries(q.Field("zone_id"), true, true) + q = q.Filter(sqlchemy.OR(iconditions...)) if provider == "all" { // provider 参数为all时。表示查询所有instance type. diff --git a/pkg/compute/models/zones.go b/pkg/compute/models/zones.go index 08e609743f..f4137c870d 100644 --- a/pkg/compute/models/zones.go +++ b/pkg/compute/models/zones.go @@ -415,7 +415,7 @@ func (manager *SZoneManager) InitializeData() error { Query 1: vpc.manager_id is not empty && wire.zone_id is not empty */ -func (manager *SZoneManager) usableZoneQ1(providers, vpcs, wires, networks *sqlchemy.SSubQuery, usableNet, usableVpc bool) *sqlchemy.SSubQuery { +func usableZoneQ1(providers, vpcs, wires, networks *sqlchemy.SSubQuery, usableNet, usableVpc bool) *sqlchemy.SSubQuery { // join tables sq := wires.Query(sqlchemy.DISTINCT("zone_id", wires.Field("zone_id"))) if usableNet { @@ -443,7 +443,7 @@ func (manager *SZoneManager) usableZoneQ1(providers, vpcs, wires, networks *sqlc Query 2: vpc.manager_id is empty && wire.zone_id is not empty */ -func (manager *SZoneManager) usableZoneQ2(vpcs, wires, networks *sqlchemy.SSubQuery, usableNet, usableVpc bool) *sqlchemy.SSubQuery { +func usableZoneQ2(vpcs, wires, networks *sqlchemy.SSubQuery, usableNet, usableVpc bool) *sqlchemy.SSubQuery { // join tables sq := wires.Query(sqlchemy.DISTINCT("zone_id", wires.Field("zone_id"))) if usableNet { @@ -470,7 +470,7 @@ vpc.manager_id is not empty && wire.zone_id is empty 2019.01.17 目前华为云子网在整个region 可用。wire中zone_id留空。 */ -func (manager *SZoneManager) usableZoneQ3(providers, vpcs, wires, networks, zones *sqlchemy.SSubQuery, usableNet, usableVpc bool) *sqlchemy.SSubQuery { +func usableZoneQ3(providers, vpcs, wires, networks, zones *sqlchemy.SSubQuery, usableNet, usableVpc bool) *sqlchemy.SSubQuery { // join tables sq := zones.Query(sqlchemy.DISTINCT("zone_id", zones.Field("id"))) sq = sq.Join(vpcs, sqlchemy.Equals(zones.Field("cloudregion_id"), vpcs.Field("cloudregion_id"))) @@ -501,7 +501,7 @@ vpc.manager_id is empty && wire.zone_id is empty 2019.01.17 目前华为云子网在整个region 可用。wire中zone_id留空。 */ -func (manager *SZoneManager) usableZoneQ4(vpcs, wires, networks, zones *sqlchemy.SSubQuery, usableNet, usableVpc bool) *sqlchemy.SSubQuery { +func usableZoneQ4(vpcs, wires, networks, zones *sqlchemy.SSubQuery, usableNet, usableVpc bool) *sqlchemy.SSubQuery { // join tables sq := zones.Query(sqlchemy.DISTINCT("zone_id", zones.Field("id"))) sq = sq.Join(vpcs, sqlchemy.Equals(zones.Field("cloudregion_id"), vpcs.Field("cloudregion_id"))) @@ -523,6 +523,41 @@ func (manager *SZoneManager) usableZoneQ4(vpcs, wires, networks, zones *sqlchemy return sq.SubQuery() } +func networkUsableZoneQueries(usableNet, usableVpc bool) []*sqlchemy.SSubQuery { + queries := make([]*sqlchemy.SSubQuery, 4) + queries[0] = usableZoneQ1(CloudproviderManager.Query().SubQuery(), + VpcManager.Query().SubQuery(), + WireManager.Query().SubQuery(), + NetworkManager.Query().SubQuery(), + usableNet, usableVpc) + queries[1] = usableZoneQ2(VpcManager.Query().SubQuery(), + WireManager.Query().SubQuery(), + NetworkManager.Query().SubQuery(), + usableNet, usableVpc) + queries[2] = usableZoneQ3(CloudproviderManager.Query().SubQuery(), + VpcManager.Query().SubQuery(), + WireManager.Query().SubQuery(), + NetworkManager.Query().SubQuery(), + ZoneManager.Query().SubQuery(), + usableNet, usableVpc) + queries[3] = usableZoneQ4(VpcManager.Query().SubQuery(), + WireManager.Query().SubQuery(), + NetworkManager.Query().SubQuery(), + ZoneManager.Query().SubQuery(), + usableNet, usableVpc) + return queries +} + +func NetworkUsableZoneQueries(field sqlchemy.IQueryField, usableNet, usableVpc bool) []sqlchemy.ICondition { + queries := networkUsableZoneQueries(usableNet, usableVpc) + iconditions := make([]sqlchemy.ICondition, 0) + for i := range queries { + iconditions = append(iconditions, sqlchemy.In(field, queries[i])) + } + + return iconditions +} + func (manager *SZoneManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) { q, err := manager.SStatusStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query) if err != nil { @@ -567,42 +602,10 @@ func (manager *SZoneManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQu if jsonutils.QueryBoolean(query, "usable", false) || jsonutils.QueryBoolean(query, "usable_vpc", false) { usableNet := jsonutils.QueryBoolean(query, "usable", false) - usableVpc := jsonutils.QueryBoolean(query, "usable_vpc", false) - - sq1 := manager.usableZoneQ1( - CloudproviderManager.Query().SubQuery(), - VpcManager.Query().SubQuery(), - WireManager.Query().SubQuery(), - NetworkManager.Query().SubQuery(), - usableNet, usableVpc) - - sq2 := manager.usableZoneQ2( - VpcManager.Query().SubQuery(), - WireManager.Query().SubQuery(), - NetworkManager.Query().SubQuery(), - usableNet, usableVpc) - - sq3 := manager.usableZoneQ3( - CloudproviderManager.Query().SubQuery(), - VpcManager.Query().SubQuery(), - WireManager.Query().SubQuery(), - NetworkManager.Query().SubQuery(), - ZoneManager.Query().SubQuery(), - usableNet, usableVpc) - - sq4 := manager.usableZoneQ4( - VpcManager.Query().SubQuery(), - WireManager.Query().SubQuery(), - NetworkManager.Query().SubQuery(), - ZoneManager.Query().SubQuery(), - usableNet, usableVpc) - - q = q.Filter(sqlchemy.OR( - sqlchemy.In(q.Field("id"), sq1), - sqlchemy.In(q.Field("id"), sq2), - sqlchemy.In(q.Field("id"), sq3), - sqlchemy.In(q.Field("id"), sq4), - )) + usableVpc := jsonutils.QueryBoolean(query, "usable_vpc", + false) + iconditions := NetworkUsableZoneQueries(q.Field("id"), usableNet, usableVpc) + q = q.Filter(sqlchemy.OR(iconditions...)) q = q.Equals("status", api.ZONE_ENABLE) } From 78d059ac11f3626731e6d99acc754f032c129016 Mon Sep 17 00:00:00 2001 From: TangBin Date: Wed, 8 May 2019 11:38:43 +0800 Subject: [PATCH 2/3] sku provider filter by region --- pkg/compute/models/skus.go | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/pkg/compute/models/skus.go b/pkg/compute/models/skus.go index 9b51e54598..336ff82a49 100644 --- a/pkg/compute/models/skus.go +++ b/pkg/compute/models/skus.go @@ -481,6 +481,35 @@ func normalizeProvider(provider string) string { return provider } +func networkUsableRegionQueries(f sqlchemy.IQueryField) []sqlchemy.ICondition { + iconditions := make([]sqlchemy.ICondition, 0) + providers := CloudproviderManager.Query().SubQuery() + networks := NetworkManager.Query().SubQuery() + wires := WireManager.Query().SubQuery() + vpcs := VpcManager.Query().SubQuery() + + sq := vpcs.Query(sqlchemy.DISTINCT("cloudregion_id", vpcs.Field("cloudregion_id"))) + sq = sq.Join(wires, sqlchemy.Equals(vpcs.Field("id"), wires.Field("vpc_id"))) + sq = sq.Join(networks, sqlchemy.Equals(wires.Field("id"), networks.Field("wire_id"))) + sq = sq.Join(providers, sqlchemy.Equals(vpcs.Field("manager_id"), providers.Field("id"))) + sq = sq.Filter(sqlchemy.Equals(networks.Field("status"), api.NETWORK_STATUS_AVAILABLE)) + sq = sq.Filter(sqlchemy.IsTrue(providers.Field("enabled"))) + sq = sq.Filter(sqlchemy.In(providers.Field("status"), api.CLOUD_PROVIDER_VALID_STATUS)) + sq = sq.Filter(sqlchemy.Equals(providers.Field("health_status"), api.CLOUD_PROVIDER_HEALTH_NORMAL)) + sq = sq.Filter(sqlchemy.Equals(vpcs.Field("status"), api.VPC_STATUS_AVAILABLE)) + + sq2 := vpcs.Query(sqlchemy.DISTINCT("cloudregion_id", vpcs.Field("cloudregion_id"))) + sq2 = sq2.Join(wires, sqlchemy.Equals(vpcs.Field("id"), wires.Field("vpc_id"))) + sq2 = sq2.Join(networks, sqlchemy.Equals(wires.Field("id"), networks.Field("wire_id"))) + sq2 = sq2.Filter(sqlchemy.Equals(networks.Field("status"), api.NETWORK_STATUS_AVAILABLE)) + sq2 = sq2.Filter(sqlchemy.IsNullOrEmpty(vpcs.Field("manager_id"))) + sq2 = sq2.Filter(sqlchemy.Equals(vpcs.Field("status"), api.VPC_STATUS_AVAILABLE)) + + iconditions = append(iconditions, sqlchemy.In(f, sq.SubQuery())) + iconditions = append(iconditions, sqlchemy.In(f, sq2.SubQuery())) + return iconditions +} + func providerFilter(q *sqlchemy.SQuery, provider string, public_cloud bool) *sqlchemy.SQuery { // 过滤出公有云provider状态健康的sku if public_cloud { @@ -496,8 +525,13 @@ func providerFilter(q *sqlchemy.SQuery, provider string, public_cloud bool) *sql } // 过滤出network usable的sku - iconditions := NetworkUsableZoneQueries(q.Field("zone_id"), true, true) - q = q.Filter(sqlchemy.OR(iconditions...)) + if public_cloud { + iconditions := NetworkUsableZoneQueries(q.Field("zone_id"), true, true) + q = q.Filter(sqlchemy.OR(iconditions...)) + } else { + iconditions := networkUsableRegionQueries(q.Field("cloudregion_id")) + q = q.Filter(sqlchemy.OR(iconditions...)) + } if provider == "all" { // provider 参数为all时。表示查询所有instance type. From afd596f45878301fd1a1ac1ebf1f49efc91e2e3c Mon Sep 17 00:00:00 2001 From: TangBin Date: Thu, 9 May 2019 16:54:37 +0800 Subject: [PATCH 3/3] sku providerFilter add more comment --- pkg/compute/models/skus.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/compute/models/skus.go b/pkg/compute/models/skus.go index 336ff82a49..89ae41ffa0 100644 --- a/pkg/compute/models/skus.go +++ b/pkg/compute/models/skus.go @@ -529,6 +529,7 @@ func providerFilter(q *sqlchemy.SQuery, provider string, public_cloud bool) *sql iconditions := NetworkUsableZoneQueries(q.Field("zone_id"), true, true) q = q.Filter(sqlchemy.OR(iconditions...)) } else { + // 私有云sku 只定义到region层级, zone id 为空.因此只能按region查询 iconditions := networkUsableRegionQueries(q.Field("cloudregion_id")) q = q.Filter(sqlchemy.OR(iconditions...)) }