mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-01 15:07:17 +08:00
zone list timeout fix
This commit is contained in:
@@ -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))
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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")))
|
||||
|
||||
|
||||
@@ -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
@@ -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")
|
||||
}
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user