zone list timeout fix

This commit is contained in:
tb365
2021-08-12 19:11:28 +08:00
parent bc653ce7fc
commit cfae948719
11 changed files with 243 additions and 215 deletions
+2 -8
View File
@@ -604,14 +604,11 @@ func (image *SCachedimage) requestRefreshExternalImage(ctx context.Context, user
func (image *SCachedimage) getValidStoragecache() []SStoragecache {
storagecaches := StoragecacheManager.Query().SubQuery()
storagecacheimages := StoragecachedimageManager.Query().SubQuery()
providers := CloudproviderManager.Query().SubQuery()
providers := usableCloudProviders().SubQuery()
q := storagecaches.Query()
q = q.Join(providers, sqlchemy.Equals(providers.Field("id"), storagecaches.Field("manager_id")))
q = q.Join(storagecacheimages, sqlchemy.Equals(storagecaches.Field("id"), storagecacheimages.Field("storagecache_id")))
q = q.Filter(sqlchemy.IsTrue(providers.Field("enabled")))
q = q.Filter(sqlchemy.In(providers.Field("status"), api.CLOUD_PROVIDER_VALID_STATUS))
q = q.Filter(sqlchemy.In(providers.Field("health_status"), api.CLOUD_PROVIDER_VALID_HEALTH_STATUS))
q = q.Filter(sqlchemy.Equals(storagecacheimages.Field("cachedimage_id"), image.Id))
q = q.Filter(sqlchemy.Equals(storagecacheimages.Field("status"), api.CACHED_IMAGE_STATUS_ACTIVE))
@@ -642,16 +639,13 @@ func (image *SCachedimage) GetUsableZoneIds() ([]string, error) {
storages := StorageManager.Query().SubQuery()
storagecaches := StoragecacheManager.Query().SubQuery()
storagecacheimages := StoragecachedimageManager.Query().SubQuery()
providers := CloudproviderManager.Query().SubQuery()
providers := usableCloudProviders().SubQuery()
q := zones.Query(zones.Field("id"))
q = q.Join(storages, sqlchemy.Equals(q.Field("id"), storages.Field("zone_id")))
q = q.Join(storagecaches, sqlchemy.Equals(storages.Field("storagecache_id"), storagecaches.Field("id")))
q = q.Join(providers, sqlchemy.Equals(providers.Field("id"), storagecaches.Field("manager_id")))
q = q.Join(storagecacheimages, sqlchemy.Equals(storagecaches.Field("id"), storagecacheimages.Field("storagecache_id")))
q = q.Filter(sqlchemy.IsTrue(providers.Field("enabled")))
q = q.Filter(sqlchemy.In(providers.Field("status"), api.CLOUD_PROVIDER_VALID_STATUS))
q = q.Filter(sqlchemy.In(providers.Field("health_status"), api.CLOUD_PROVIDER_VALID_HEALTH_STATUS))
q = q.Filter(sqlchemy.Equals(storagecacheimages.Field("cachedimage_id"), image.Id))
q = q.Filter(sqlchemy.Equals(storagecacheimages.Field("status"), api.CACHED_IMAGE_STATUS_ACTIVE))
q = q.Filter(sqlchemy.Equals(q.Field("status"), api.ZONE_ENABLE))
+1 -4
View File
@@ -1177,7 +1177,7 @@ func (manager *SCloudproviderManager) ListItemFilter(
}
if query.Usable != nil && *query.Usable {
providers := CloudproviderManager.Query().SubQuery()
providers := usableCloudProviders().SubQuery()
networks := NetworkManager.Query().SubQuery()
wires := WireManager.Query().SubQuery()
vpcs := VpcManager.Query().SubQuery()
@@ -1188,9 +1188,6 @@ func (manager *SCloudproviderManager) ListItemFilter(
sq = sq.Join(vpcs, sqlchemy.Equals(providerRegions.Field("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.Filter(sqlchemy.IsTrue(providers.Field("enabled")))
sq = sq.Filter(sqlchemy.In(providers.Field("status"), api.CLOUD_PROVIDER_VALID_STATUS))
sq = sq.Filter(sqlchemy.In(providers.Field("health_status"), api.CLOUD_PROVIDER_VALID_HEALTH_STATUS))
sq = sq.Filter(sqlchemy.Equals(vpcs.Field("status"), api.VPC_STATUS_AVAILABLE))
sq = sq.Filter(sqlchemy.Equals(networks.Field("status"), api.NETWORK_STATUS_AVAILABLE))
sq = sq.Filter(sqlchemy.OR(
+1 -4
View File
@@ -793,7 +793,7 @@ func (manager *SCloudregionManager) ListItemFilter(
usableNet := (query.Usable != nil && *query.Usable)
usableVpc := (query.UsableVpc != nil && *query.UsableVpc)
if usableNet || usableVpc {
providers := CloudproviderManager.Query().SubQuery()
providers := usableCloudProviders().SubQuery()
networks := NetworkManager.Query().SubQuery()
wires := WireManager.Query().SubQuery()
vpcs := VpcManager.Query().SubQuery()
@@ -807,9 +807,6 @@ func (manager *SCloudregionManager) ListItemFilter(
if usableNet {
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.In(providers.Field("health_status"), api.CLOUD_PROVIDER_VALID_HEALTH_STATUS))
if usableVpc {
sq = sq.Filter(sqlchemy.Equals(vpcs.Field("status"), api.VPC_STATUS_AVAILABLE))
}
+4 -1
View File
@@ -276,7 +276,10 @@ func (manager *SElasticcacheSkuManager) ListItemFilter(
}
if query.Usable != nil && *query.Usable {
q = usableFilter(q, true)
q, err = usableFilter(q, true)
if err != nil {
return nil, err
}
sq := sqlchemy.OR(sqlchemy.Equals(q.Field("prepaid_status"), api.SkuStatusAvailable), sqlchemy.Equals(q.Field("postpaid_status"), api.SkuStatusAvailable))
q = q.Filter(sq)
}
+1 -4
View File
@@ -317,15 +317,12 @@ func (manager *SHostManager) ListItemFilter(
hosts := HostManager.Query().SubQuery()
hostwires := HostwireManager.Query().SubQuery()
networks := NetworkManager.Query().SubQuery()
providers := CloudproviderManager.Query().SubQuery()
providers := usableCloudProviders().SubQuery()
hostQ1 := hosts.Query(hosts.Field("id"))
hostQ1 = hostQ1.Join(providers, sqlchemy.Equals(hosts.Field("manager_id"), providers.Field("id")))
hostQ1 = hostQ1.Join(hostwires, sqlchemy.Equals(hosts.Field("id"), hostwires.Field("host_id")))
hostQ1 = hostQ1.Join(networks, sqlchemy.Equals(hostwires.Field("wire_id"), networks.Field("wire_id")))
hostQ1 = hostQ1.Filter(sqlchemy.IsTrue(providers.Field("enabled")))
hostQ1 = hostQ1.Filter(sqlchemy.In(providers.Field("status"), api.CLOUD_PROVIDER_VALID_STATUS))
hostQ1 = hostQ1.Filter(sqlchemy.In(providers.Field("health_status"), api.CLOUD_PROVIDER_VALID_HEALTH_STATUS))
hostQ1 = hostQ1.Filter(sqlchemy.Equals(networks.Field("status"), api.NETWORK_STATUS_AVAILABLE))
hostQ1 = hostQ1.Filter(sqlchemy.IsTrue(hosts.Field("enabled")))
+12 -26
View File
@@ -2028,33 +2028,19 @@ func (manager *SNetworkManager) ListItemFilter(
}
if input.Usable != nil && *input.Usable {
wires := WireManager.Query().SubQuery()
zones := ZoneManager.Query().SubQuery()
vpcs := VpcManager.Query().SubQuery()
cloudproviders := CloudproviderManager.Query().SubQuery()
providerSQ := cloudproviders.Query(cloudproviders.Field("id")).Filter(
sqlchemy.AND(
sqlchemy.IsTrue(cloudproviders.Field("enabled")),
sqlchemy.In(cloudproviders.Field("status"), api.CLOUD_PROVIDER_VALID_STATUS),
sqlchemy.In(cloudproviders.Field("health_status"), api.CLOUD_PROVIDER_VALID_HEALTH_STATUS),
),
)
regions := CloudregionManager.Query().SubQuery()
regions := CloudregionManager.Query("id").Equals("status", api.CLOUD_REGION_STATUS_INSERVER)
zones := ZoneManager.Query("id").Equals("status", api.ZONE_ENABLE).In("cloudregion_id", regions)
providerSQ := usableCloudProviders()
_vpcs := VpcManager.Query("id").Equals("status", api.VPC_STATUS_AVAILABLE)
vpcs := _vpcs.Filter(sqlchemy.OR(
sqlchemy.In(_vpcs.Field("manager_id"), providerSQ),
sqlchemy.IsNullOrEmpty(_vpcs.Field("manager_id")),
))
sq := wires.Query(wires.Field("id")).
Join(vpcs, sqlchemy.Equals(wires.Field("vpc_id"), vpcs.Field("id"))).
Join(zones, sqlchemy.OR(sqlchemy.Equals(wires.Field("zone_id"), zones.Field("id")), sqlchemy.IsNullOrEmpty(wires.Field("zone_id")))).
Join(regions, sqlchemy.Equals(zones.Field("cloudregion_id"), regions.Field("id"))).
Filter(sqlchemy.AND(
sqlchemy.Equals(vpcs.Field("status"), api.VPC_STATUS_AVAILABLE),
sqlchemy.Equals(zones.Field("status"), api.ZONE_ENABLE),
sqlchemy.Equals(regions.Field("status"), api.CLOUD_REGION_STATUS_INSERVER),
sqlchemy.OR(
sqlchemy.In(vpcs.Field("manager_id"), providerSQ.SubQuery()),
sqlchemy.IsNullOrEmpty(vpcs.Field("manager_id")),
),
))
q = q.In("wire_id", sq.SubQuery()).Equals("status", api.NETWORK_STATUS_AVAILABLE)
wires := WireManager.Query("id")
wires = wires.In("vpc_id", vpcs).
Filter(sqlchemy.OR(sqlchemy.IsNullOrEmpty(wires.Field("zone_id")), sqlchemy.In(wires.Field("zone_id"), zones)))
q = q.In("wire_id", wires).Equals("status", api.NETWORK_STATUS_AVAILABLE)
}
hostStr := input.HostId
+21 -35
View File
@@ -494,53 +494,36 @@ func normalizeProvider(provider string) string {
}
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()
providers := usableCloudProviders()
networks := NetworkManager.Query("wire_id").Equals("status", api.NETWORK_STATUS_AVAILABLE)
wires := WireManager.Query("vpc_id").In("id", networks)
_vpcs := VpcManager.Query("cloudregion_id").
Equals("status", api.VPC_STATUS_AVAILABLE).
In("id", wires)
filters := sqlchemy.OR(sqlchemy.In(_vpcs.Field("manager_id"), providers), sqlchemy.IsNullOrEmpty(_vpcs.Field("manager_id")))
vpcs := _vpcs.Filter(filters).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.In(providers.Field("health_status"), api.CLOUD_PROVIDER_VALID_HEALTH_STATUS))
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
return []sqlchemy.ICondition{sqlchemy.In(f, sq.SubQuery())}
}
func usableFilter(q *sqlchemy.SQuery, public_cloud bool) *sqlchemy.SQuery {
func usableFilter(q *sqlchemy.SQuery, public_cloud bool) (*sqlchemy.SQuery, error) {
// 过滤出公有云provider状态健康的sku
if public_cloud {
providerTable := CloudproviderManager.Query().SubQuery()
providerTable := usableCloudProviders().SubQuery()
providerRegionTable := CloudproviderRegionManager.Query().SubQuery()
subq := providerRegionTable.Query(sqlchemy.DISTINCT("cloudregion_id", providerRegionTable.Field("cloudregion_id")))
subq = subq.Join(providerTable, sqlchemy.Equals(providerRegionTable.Field("cloudprovider_id"), providerTable.Field("id")))
subq = subq.Filter(sqlchemy.IsTrue(providerTable.Field("enabled")))
subq = subq.Filter(sqlchemy.In(providerTable.Field("status"), api.CLOUD_PROVIDER_VALID_STATUS))
subq = subq.Filter(sqlchemy.In(providerTable.Field("health_status"), api.CLOUD_PROVIDER_VALID_HEALTH_STATUS))
q = q.Filter(sqlchemy.In(q.Field("cloudregion_id"), subq.SubQuery()))
}
// 过滤出network usable的sku
if public_cloud {
iconditions := NetworkUsableZoneQueries(q.Field("zone_id"), true, true)
iconditions = append(iconditions, sqlchemy.IsNullOrEmpty(q.Field("zone_id"))) //Azure的zone_id可能为空
q = q.Filter(sqlchemy.OR(iconditions...))
zoneIds, err := NetworkUsableZoneIds(true, true, nil)
if err != nil {
return nil, errors.Wrap(err, "NetworkUsableZoneIds")
}
q = q.Filter(sqlchemy.OR(sqlchemy.In(q.Field("zone_id"), zoneIds), sqlchemy.IsNullOrEmpty(q.Field("zone_id")))) //Azure的zone_id可能为空
} else {
// 本地IDC sku 只定义到region层级, zone id 为空.因此只能按region查询
iconditions := networkUsableRegionQueries(q.Field("cloudregion_id"))
@@ -549,7 +532,7 @@ func usableFilter(q *sqlchemy.SQuery, public_cloud bool) *sqlchemy.SQuery {
q = q.Filter(sqlchemy.OR(iconditions...))
}
return q
return q, nil
}
func (manager *SServerSkuManager) GetPropertyInstanceSpecs(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
@@ -772,7 +755,10 @@ func (manager *SServerSkuManager) ListItemFilter(
}
if query.Usable != nil && *query.Usable {
q = usableFilter(q, publicCloud)
q, err := usableFilter(q, publicCloud)
if err != nil {
return nil, err
}
q = q.IsTrue("enabled")
}
+2 -5
View File
@@ -1447,13 +1447,10 @@ func (manager *SStorageManager) ListItemFilter(
Filter(sqlchemy.IsTrue(hostTable.Field("enabled"))).
Filter(sqlchemy.IsNullOrEmpty(hostTable.Field("manager_id")))
providerTable := CloudproviderManager.Query().SubQuery()
providerTable := usableCloudProviders().SubQuery()
sq2 := hostStorageTable.Query(hostStorageTable.Field("storage_id")).
Join(hostTable, sqlchemy.Equals(hostTable.Field("id"), hostStorageTable.Field("host_id"))).
Join(providerTable, sqlchemy.Equals(hostTable.Field("manager_id"), providerTable.Field("id"))).
Filter(sqlchemy.IsTrue(providerTable.Field("enabled"))).
Filter(sqlchemy.In(providerTable.Field("status"), api.CLOUD_PROVIDER_VALID_STATUS)).
Filter(sqlchemy.In(providerTable.Field("health_status"), api.CLOUD_PROVIDER_VALID_HEALTH_STATUS))
Join(providerTable, sqlchemy.Equals(hostTable.Field("manager_id"), providerTable.Field("id")))
q = q.Filter(
sqlchemy.OR(
+14
View File
@@ -0,0 +1,14 @@
package models
import (
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/compute"
)
func usableCloudProviders() *sqlchemy.SQuery {
return CloudproviderManager.Query("id").
In("status", api.CLOUD_PROVIDER_VALID_STATUS).
In("health_status", api.CLOUD_PROVIDER_VALID_HEALTH_STATUS).
IsTrue("enabled")
}
+2 -9
View File
@@ -1109,19 +1109,12 @@ func (manager *SVpcManager) ListItemFilter(
vpcUsable := (query.UsableVpc != nil && *query.UsableVpc)
if vpcUsable || usable {
regions := CloudregionManager.Query().SubQuery()
cloudproviders := CloudproviderManager.Query().SubQuery()
providerSQ := cloudproviders.Query(cloudproviders.Field("id")).Filter(
sqlchemy.AND(
sqlchemy.IsTrue(cloudproviders.Field("enabled")),
sqlchemy.In(cloudproviders.Field("status"), api.CLOUD_PROVIDER_VALID_STATUS),
sqlchemy.In(cloudproviders.Field("health_status"), api.CLOUD_PROVIDER_VALID_HEALTH_STATUS),
),
)
providerSQ := usableCloudProviders().SubQuery()
q = q.Join(regions, sqlchemy.Equals(q.Field("cloudregion_id"), regions.Field("id"))).Filter(
sqlchemy.AND(
sqlchemy.Equals(regions.Field("status"), api.CLOUD_REGION_STATUS_INSERVER),
sqlchemy.OR(
sqlchemy.In(q.Field("manager_id"), providerSQ.SubQuery()),
sqlchemy.In(q.Field("manager_id"), providerSQ),
sqlchemy.IsNullOrEmpty(q.Field("manager_id")),
),
),
+183 -119
View File
@@ -367,149 +367,210 @@ func (manager *SZoneManager) InitializeData() error {
/*
Query 1:
vpc.manager_id is not empty && wire.zone_id is not empty
wire.zone_id is not empty
*/
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 {
sq = sq.Join(networks, sqlchemy.Equals(wires.Field("id"), networks.Field("wire_id")))
}
sq = sq.Join(vpcs, sqlchemy.Equals(wires.Field("vpc_id"), vpcs.Field("id")))
sq = sq.Join(providers, sqlchemy.Equals(vpcs.Field("manager_id"), providers.Field("id")))
// add filters
if usableNet {
sq = sq.Filter(sqlchemy.Equals(networks.Field("status"), api.NETWORK_STATUS_AVAILABLE))
}
sq = sq.Filter(sqlchemy.IsNotEmpty(wires.Field("zone_id")))
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.In(providers.Field("health_status"), api.CLOUD_PROVIDER_VALID_HEALTH_STATUS))
if usableVpc {
sq = sq.Filter(sqlchemy.Equals(vpcs.Field("status"), api.VPC_STATUS_AVAILABLE))
func usableZoneQ1(vpcs map[string]map[string]string, usableNet bool) ([]string, error) {
// conditions
vpcIds := make([]string, 0)
for k, _ := range vpcs {
vpcIds = append(vpcIds, k)
}
return sq.SubQuery()
q := zoneWireFilter(usableNet, false, vpcIds)
results, _, err := zoneWireFilterResult(q)
if err != nil {
return nil, errors.Wrap(err, "zoneWireFilterResult")
}
return results, nil
}
/*
Query 2:
vpc.manager_id is empty && wire.zone_id is not empty
*/
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 {
sq = sq.Join(networks, sqlchemy.Equals(wires.Field("id"), networks.Field("wire_id")))
}
sq = sq.Join(vpcs, sqlchemy.Equals(wires.Field("vpc_id"), vpcs.Field("id")))
// add filters
if usableNet {
sq = sq.Filter(sqlchemy.Equals(networks.Field("status"), api.NETWORK_STATUS_AVAILABLE))
}
sq = sq.Filter(sqlchemy.IsNotEmpty(wires.Field("zone_id")))
sq = sq.Filter(sqlchemy.IsNullOrEmpty(vpcs.Field("manager_id")))
if usableVpc {
sq = sq.Filter(sqlchemy.Equals(vpcs.Field("status"), api.VPC_STATUS_AVAILABLE))
}
return sq.SubQuery()
}
/*
Query 3:
vpc.manager_id is not empty && wire.zone_id is empty
wire.zone_id is empty
2019.01.17 目前华为云子网在整个region 可用wire中zone_id留空
*/
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")))
sq = sq.Join(wires, sqlchemy.Equals(wires.Field("vpc_id"), vpcs.Field("id")))
if usableNet {
sq = sq.Join(networks, sqlchemy.Equals(wires.Field("id"), networks.Field("wire_id")))
func usableZoneQ2(vpcs map[string]map[string]string, usableNet bool) ([]string, error) {
// conditions
vpcIds := make([]string, 0)
for k, _ := range vpcs {
vpcIds = append(vpcIds, k)
}
sq = sq.Join(providers, sqlchemy.Equals(vpcs.Field("manager_id"), providers.Field("id")))
// add filters
if usableNet {
sq = sq.Filter(sqlchemy.Equals(networks.Field("status"), api.NETWORK_STATUS_AVAILABLE))
q := zoneWireFilter(usableNet, true, vpcIds)
_, vpcIds, err := zoneWireFilterResult(q)
if err != nil {
return nil, errors.Wrap(err, "zoneWireFilterResult")
}
sq = sq.Filter(sqlchemy.IsNullOrEmpty(wires.Field("zone_id")))
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.In(providers.Field("health_status"), api.CLOUD_PROVIDER_VALID_HEALTH_STATUS))
cloudregionIds := make([]string, 0)
for i := range vpcIds {
if vpc, ok := vpcs[vpcIds[i]]; ok {
if c, ok := vpc["cloudregion_id"]; ok && len(c) > 0 {
cloudregionIds = append(cloudregionIds, c)
}
}
}
return zoneRegionFilter(cloudregionIds)
}
func zoneVpcFilter(usableVpc bool, query *api.ZoneListInput) *sqlchemy.SQuery {
// conditions
q := VpcManager.Query("id", "cloudregion_id")
if usableVpc {
sq = sq.Filter(sqlchemy.Equals(vpcs.Field("status"), api.VPC_STATUS_AVAILABLE))
q = q.Equals("status", api.VPC_STATUS_AVAILABLE)
}
return sq.SubQuery()
if query != nil && len(query.CloudregionId) > 0 {
q.Equals("cloudregion_id", query.CloudregionId)
}
return q
}
/*
Query 4:
vpc.manager_id is empty && wire.zone_id is empty
// vpc.manager_id is empty
func usableVpc1(usableVpc bool, query *api.ZoneListInput) *sqlchemy.SQuery {
// conditions
return zoneVpcFilter(usableVpc, query).IsNullOrEmpty("manager_id")
}
// vpc.manager_id is not empty
func usableVpc2(usableVpc bool, query *api.ZoneListInput) (*sqlchemy.SQuery, error) {
// conditions
q := zoneVpcFilter(usableVpc, query).IsNotEmpty("manager_id")
if query != nil && len(query.CloudproviderId) > 0 {
q.Equals("manager_id", query.CloudproviderId)
} else {
providerIds, err := zoneUsableProviderQuery(query)
if err != nil {
return nil, errors.Wrap(err, "zoneUsableProviderQuery")
}
q.In("manager_id", providerIds)
}
return q, nil
}
func zoneUsableVpc(usableVpc bool, query *api.ZoneListInput) (map[string]map[string]string, error) {
q1 := usableVpc1(usableVpc, query)
q2, err := usableVpc2(usableVpc, query)
if err != nil {
return nil, errors.Wrap(err, "usableVpc2")
}
results := make(map[string]map[string]string, 0)
for _, q := range []*sqlchemy.SQuery{q1, q2} {
rows, err := q.Rows()
if err != nil && err != sql.ErrNoRows {
return nil, errors.Wrap(err, "zoneUsableVpc.rows")
}
for rows.Next() {
var id string
var cloudregion_id string
err := rows.Scan(&id, &cloudregion_id)
if err != nil {
return nil, errors.Wrap(err, "rows.Scan")
}
results[id] = map[string]string{"id": id, "cloudregion_id": cloudregion_id}
}
}
return results, nil
}
func zoneWireFilter(usableNet bool, zoneIdIsEmpty bool, vpcIds []string) *sqlchemy.SQuery {
wireq := WireManager.Query("vpc_id", "zone_id").In("vpc_id", vpcIds)
if zoneIdIsEmpty {
wireq.IsNullOrEmpty("zone_id")
} else {
wireq.IsNotEmpty("zone_id")
}
2019.01.17 目前华为云子网在整个region 可用wire中zone_id留空
*/
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")))
sq = sq.Join(wires, sqlchemy.Equals(wires.Field("vpc_id"), vpcs.Field("id")))
if usableNet {
sq = sq.Join(networks, sqlchemy.Equals(wires.Field("id"), networks.Field("wire_id")))
netq := NetworkManager.Query().Equals("status", api.NETWORK_STATUS_AVAILABLE).SubQuery()
wireq = wireq.Join(netq, sqlchemy.Equals(netq.Field("wire_id"), wireq.Field("id")))
}
// add filters
if usableNet {
sq = sq.Filter(sqlchemy.Equals(networks.Field("status"), api.NETWORK_STATUS_AVAILABLE))
}
sq = sq.Filter(sqlchemy.IsNullOrEmpty(wires.Field("zone_id")))
sq = sq.Filter(sqlchemy.IsNullOrEmpty(vpcs.Field("manager_id")))
if usableVpc {
sq = sq.Filter(sqlchemy.Equals(vpcs.Field("status"), api.VPC_STATUS_AVAILABLE))
}
return sq.SubQuery()
return wireq
}
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]))
func zoneWireFilterResult(q *sqlchemy.SQuery) ([]string, []string, error) {
rows, err := q.Rows()
if err != nil && err != sql.ErrNoRows {
return nil, nil, errors.Wrap(err, "zoneWireFilterResult.rows")
}
defer rows.Close()
zoneIds := make([]string, 0)
vpcIds := make([]string, 0)
for rows.Next() {
var vpcId string
var zoneId string
err := rows.Scan(&vpcId, &zoneId)
if err != nil {
return nil, nil, errors.Wrap(err, "rows.Scan")
}
zoneIds = append(zoneIds, zoneId)
vpcIds = append(vpcIds, vpcId)
}
return iconditions
return zoneIds, vpcIds, nil
}
// avaliable providers
func zoneUsableProviderQuery(query *api.ZoneListInput) ([]string, error) {
q := usableCloudProviders()
if query != nil {
if len(query.CloudproviderId) > 0 {
q = q.Filter(sqlchemy.OR(sqlchemy.Equals(q.Field("id"), query.CloudproviderId), sqlchemy.Equals(q.Field("name"), query.CloudproviderId)))
}
}
return filterResult(q)
}
func zoneRegionFilter(cloudregionIds []string) ([]string, error) {
q := ZoneManager.Query("id").In("cloudregion_id", cloudregionIds)
return filterResult(q)
}
func filterResult(q *sqlchemy.SQuery) ([]string, error) {
rows, err := q.Rows()
if err != nil && err != sql.ErrNoRows {
return nil, errors.Wrap(err, "filterResult.rows")
}
results := make([]string, 0)
for rows.Next() {
var id string
err := rows.Scan(&id)
if err != nil {
return nil, errors.Wrap(err, "filterResult.Scan")
}
results = append(results, id)
}
return results, nil
}
func NetworkUsableZoneIds(usableNet, usableVpc bool, query *api.ZoneListInput) ([]string, error) {
vpcs, err := zoneUsableVpc(usableVpc, query)
if err != nil {
return nil, errors.Wrap(err, "zoneUsableVpc")
}
ret, err := usableZoneQ1(vpcs, usableNet)
if err != nil {
return nil, errors.Wrap(err, "usableZoneQ1")
}
r2, err := usableZoneQ2(vpcs, usableNet)
if err != nil {
return nil, errors.Wrap(err, "usableZoneQ2")
}
ret = append(ret, r2...)
return ret, nil
}
// 可用区列表
@@ -577,8 +638,11 @@ func (manager *SZoneManager) ListItemFilter(
usableNet := (query.Usable != nil && *query.Usable)
usableVpc := (query.UsableVpc != nil && *query.UsableVpc)
if usableNet || usableVpc {
iconditions := NetworkUsableZoneQueries(q.Field("id"), usableNet, usableVpc)
q = q.Filter(sqlchemy.OR(iconditions...))
zoneIds, err := NetworkUsableZoneIds(usableNet, usableVpc, &query)
if err != nil {
return nil, err
}
q = q.In("id", zoneIds)
q = q.Equals("status", api.ZONE_ENABLE)
service := query.Service