diff --git a/cmd/climc/shell/cloudregions.go b/cmd/climc/shell/cloudregions.go index 034ba9d8c0..a788a8c20e 100644 --- a/cmd/climc/shell/cloudregions.go +++ b/cmd/climc/shell/cloudregions.go @@ -158,4 +158,13 @@ func init() { printObject(result) return nil }) + + R(&CloudregionShowOptions{}, "cloud-region-capability", "Show region's capacibilities", func(s *mcclient.ClientSession, args *CloudregionShowOptions) error { + result, err := modules.Cloudregions.GetSpecific(s, args.ID, "capability", nil) + if err != nil { + return err + } + printObject(result) + return nil + }) } diff --git a/cmd/climc/shell/isolatedevices.go b/cmd/climc/shell/isolatedevices.go index 38951b3e7f..59979a4c46 100644 --- a/cmd/climc/shell/isolatedevices.go +++ b/cmd/climc/shell/isolatedevices.go @@ -14,6 +14,7 @@ func init() { Unused bool `help:"Only show unused devices"` Gpu bool `help:"Only show gpu devices"` Host string `help:"Host ID or Name"` + Region string `help:"Cloudregion ID or Name"` Zone string `help:"Zone ID or Name"` } R(&DeviceListOptions{}, "isolated-device-list", "List isolated devices like GPU", func(s *mcclient.ClientSession, args *DeviceListOptions) error { @@ -35,6 +36,9 @@ func init() { if args.Gpu { params.Add(jsonutils.JSONTrue, "gpu") } + if len(args.Region) > 0 { + params.Add(jsonutils.NewString(args.Region), "region") + } if args.Zone != "" { params.Add(jsonutils.NewString(args.Zone), "zone") } diff --git a/pkg/compute/capabilities/handler.go b/pkg/compute/capabilities/handler.go index 8df5482467..0772fc5a50 100644 --- a/pkg/compute/capabilities/handler.go +++ b/pkg/compute/capabilities/handler.go @@ -25,7 +25,7 @@ func capaHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) { httperrors.GeneralServerError(w, err) return } - capa, err := models.GetCapabilities(ctx, userCred, query, nil) + capa, err := models.GetCapabilities(ctx, userCred, query, nil, nil) if err != nil { httperrors.GeneralServerError(w, err) return diff --git a/pkg/compute/models/capabilities.go b/pkg/compute/models/capabilities.go index e95a471649..441dbeed47 100644 --- a/pkg/compute/models/capabilities.go +++ b/pkg/compute/models/capabilities.go @@ -25,23 +25,26 @@ type SCapabilities struct { Specs jsonutils.JSONObject } -func GetCapabilities(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, zone *SZone) (SCapabilities, error) { +func GetCapabilities(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, region *SCloudregion, zone *SZone) (SCapabilities, error) { capa := SCapabilities{} - capa.Hypervisors = getHypervisors(zone) - capa.ResourceTypes = getResourceTypes(zone) - capa.StorageTypes = getStorageTypes(zone, true) - capa.DataStorageTypes = getStorageTypes(zone, false) - capa.GPUModels = getGPUs(zone) - capa.SchedPolicySupport = isSchedPolicySupported(zone) - capa.MinNicCount = getMinNicCount(zone) - capa.MaxNicCount = getMaxNicCount(zone) - capa.MinDataDiskCount = getMinDataDiskCount(zone) - capa.MaxDataDiskCount = getMaxDataDiskCount(zone) - capa.Usable = isUsable(zone) + capa.Hypervisors = getHypervisors(region, zone) + capa.ResourceTypes = getResourceTypes(region, zone) + capa.StorageTypes = getStorageTypes(region, zone, true) + capa.DataStorageTypes = getStorageTypes(region, zone, false) + capa.GPUModels = getGPUs(region, zone) + capa.SchedPolicySupport = isSchedPolicySupported(region, zone) + capa.MinNicCount = getMinNicCount(region, zone) + capa.MaxNicCount = getMaxNicCount(region, zone) + capa.MinDataDiskCount = getMinDataDiskCount(region, zone) + capa.MaxDataDiskCount = getMaxDataDiskCount(region, zone) + capa.Usable = isUsable(region, zone) if query == nil { query = jsonutils.NewDict() } var err error + if region != nil { + query.(*jsonutils.JSONDict).Add(jsonutils.NewString(region.GetId()), "region") + } if zone != nil { query.(*jsonutils.JSONDict).Add(jsonutils.NewString(zone.GetId()), "zone") } @@ -50,8 +53,16 @@ func GetCapabilities(ctx context.Context, userCred mcclient.TokenCredential, que return capa, err } -func getHypervisors(zone *SZone) []string { +func getRegionZoneSubq(region *SCloudregion) *sqlchemy.SSubQuery { + return ZoneManager.Query("id").Equals("cloudregion_id", region.GetId()).SubQuery() +} + +func getHypervisors(region *SCloudregion, zone *SZone) []string { q := HostManager.Query("host_type") + if region != nil { + subq := getRegionZoneSubq(region) + q = q.Filter(sqlchemy.In(q.Field("zone_id"), subq)) + } if zone != nil { q = q.Equals("zone_id", zone.Id) } @@ -75,8 +86,12 @@ func getHypervisors(zone *SZone) []string { return hypervisors } -func getResourceTypes(zone *SZone) []string { +func getResourceTypes(region *SCloudregion, zone *SZone) []string { q := HostManager.Query("resource_type") + if region != nil { + subq := getRegionZoneSubq(region) + q = q.Filter(sqlchemy.In(q.Field("zone_id"), subq)) + } if zone != nil { q = q.Equals("zone_id", zone.Id) } @@ -99,7 +114,7 @@ func getResourceTypes(zone *SZone) []string { return resourceTypes } -func getStorageTypes(zone *SZone, isSysDisk bool) []string { +func getStorageTypes(region *SCloudregion, zone *SZone, isSysDisk bool) []string { storages := StorageManager.Query().SubQuery() hostStorages := HoststorageManager.Query().SubQuery() hosts := HostManager.Query().SubQuery() @@ -113,6 +128,10 @@ func getStorageTypes(zone *SZone, isSysDisk bool) []string { hosts.Field("id"), hostStorages.Field("host_id"), )) + if region != nil { + subq := getRegionZoneSubq(region) + q = q.Filter(sqlchemy.In(storages.Field("zone_id"), subq)) + } if zone != nil { q = q.Filter(sqlchemy.Equals(storages.Field("zone_id"), zone.Id)) } @@ -144,11 +163,16 @@ func getStorageTypes(zone *SZone, isSysDisk bool) []string { return storageTypes } -func getGPUs(zone *SZone) []string { +func getGPUs(region *SCloudregion, zone *SZone) []string { devices := IsolatedDeviceManager.Query().SubQuery() hosts := HostManager.Query().SubQuery() q := devices.Query(devices.Field("model")) + if region != nil { + subq := getRegionZoneSubq(region) + q = q.Join(hosts, sqlchemy.Equals(devices.Field("host_id"), hosts.Field("id"))) + q = q.Filter(sqlchemy.In(hosts.Field("zone_id"), subq)) + } if zone != nil { q = q.Join(hosts, sqlchemy.Equals(devices.Field("host_id"), hosts.Field("id"))) q = q.Filter(sqlchemy.Equals(hosts.Field("zone_id"), zone.Id)) @@ -171,12 +195,17 @@ func getGPUs(zone *SZone) []string { return gpus } -func getNetworkCount(zone *SZone) int { +func getNetworkCount(region *SCloudregion, zone *SZone) int { + wires := WireManager.Query().SubQuery() networks := NetworkManager.Query().SubQuery() q := networks.Query() + if region != nil { + subq := getRegionZoneSubq(region) + q = q.Join(wires, sqlchemy.Equals(networks.Field("wire_id"), wires.Field("id"))) + q = q.Filter(sqlchemy.In(wires.Field("zone_id"), subq)) + } if zone != nil { - wires := WireManager.Query().SubQuery() q = q.Join(wires, sqlchemy.Equals(networks.Field("wire_id"), wires.Field("id"))) q = q.Filter(sqlchemy.Equals(wires.Field("zone_id"), zone.Id)) } @@ -185,44 +214,52 @@ func getNetworkCount(zone *SZone) int { return q.Count() } -func isSchedPolicySupported(zone *SZone) bool { +func isSchedPolicySupported(region *SCloudregion, zone *SZone) bool { return true } -func getMinNicCount(zone *SZone) int { +func getMinNicCount(region *SCloudregion, zone *SZone) int { + if region != nil { + return region.getMinNicCount() + } if zone != nil { return zone.getMinNicCount() - } else { - return 0 } + return 0 } -func getMaxNicCount(zone *SZone) int { +func getMaxNicCount(region *SCloudregion, zone *SZone) int { + if region != nil { + return region.getMaxNicCount() + } if zone != nil { return zone.getMaxNicCount() - } else { - return 0 } + return 0 } -func getMinDataDiskCount(zone *SZone) int { +func getMinDataDiskCount(region *SCloudregion, zone *SZone) int { + if region != nil { + return region.getMinDataDiskCount() + } if zone != nil { return zone.getMinDataDiskCount() - } else { - return 0 } + return 0 } -func getMaxDataDiskCount(zone *SZone) int { +func getMaxDataDiskCount(region *SCloudregion, zone *SZone) int { + if region != nil { + return region.getMaxDataDiskCount() + } if zone != nil { return zone.getMaxDataDiskCount() - } else { - return 0 } + return 0 } -func isUsable(zone *SZone) bool { - if getNetworkCount(zone) > 0 { +func isUsable(region *SCloudregion, zone *SZone) bool { + if getNetworkCount(region, zone) > 0 { return true } else { return false diff --git a/pkg/compute/models/cloudregions.go b/pkg/compute/models/cloudregions.go index b8479df8fe..c30981b700 100644 --- a/pkg/compute/models/cloudregions.go +++ b/pkg/compute/models/cloudregions.go @@ -15,6 +15,7 @@ import ( "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman" "yunion.io/x/onecloud/pkg/cloudprovider" + "yunion.io/x/onecloud/pkg/compute/options" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" ) @@ -511,3 +512,38 @@ func (self *SCloudregion) ValidateUpdateCondition(ctx context.Context) error { } return self.SEnabledStatusStandaloneResourceBase.ValidateUpdateCondition(ctx) } + +func (self *SCloudregion) AllowGetDetailsCapability(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool { + return true +} + +func (self *SCloudregion) GetDetailsCapability(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) { + capa, err := GetCapabilities(ctx, userCred, query, self, nil) + if err != nil { + return nil, err + } + return jsonutils.Marshal(&capa), nil +} + +func (self *SCloudregion) getNetworkCount() int { + return getNetworkCount(self, nil) +} + +func (self *SCloudregion) getMinNicCount() int { + return options.Options.MinNicCount +} + +func (self *SCloudregion) getMaxNicCount() int { + if self.isManaged() { + return options.Options.MaxManagedNicCount + } + return options.Options.MaxNormalNicCount +} + +func (self *SCloudregion) getMinDataDiskCount() int { + return options.Options.MinDataDiskCount +} + +func (self *SCloudregion) getMaxDataDiskCount() int { + return options.Options.MaxDataDiskCount +} diff --git a/pkg/compute/models/isolated_devices.go b/pkg/compute/models/isolated_devices.go index 5120871abb..13221ef09d 100644 --- a/pkg/compute/models/isolated_devices.go +++ b/pkg/compute/models/isolated_devices.go @@ -2,6 +2,7 @@ package models import ( "context" + "database/sql" "fmt" "strings" "time" @@ -139,6 +140,19 @@ func (manager *SIsolatedDeviceManager) ListItemFilter(ctx context.Context, q *sq if jsonutils.QueryBoolean(query, "unused", false) { q = q.IsEmpty("guest_id") } + regionStr := jsonutils.GetAnyString(query, []string{"region", "region_id"}) + if len(regionStr) > 0 { + region, err := CloudregionManager.FetchByIdOrName(nil, regionStr) + if err != nil { + if err == sql.ErrNoRows { + return nil, httperrors.NewResourceNotFoundError2(CloudregionManager.Keyword(), regionStr) + } + return nil, httperrors.NewGeneralError(err) + } + hosts := HostManager.Query().SubQuery() + subq := ZoneManager.Query("id").Equals("cloudregion_id", region.GetId()).SubQuery() + q.Join(hosts, sqlchemy.Equals(q.Field("host_id"), hosts.Field("id"))).Filter(sqlchemy.In(hosts.Field("zone_id"), subq)) + } zoneStr := jsonutils.GetAnyString(query, []string{"zone", "zone_id"}) if len(zoneStr) > 0 { zone, _ := ZoneManager.FetchByIdOrName(nil, zoneStr) diff --git a/pkg/compute/models/zones.go b/pkg/compute/models/zones.go index 746e6a70bd..2bd2772242 100644 --- a/pkg/compute/models/zones.go +++ b/pkg/compute/models/zones.go @@ -205,7 +205,7 @@ func (zone *SZone) getStorageCount() int { } func (zone *SZone) getNetworkCount() int { - return getNetworkCount(zone) + return getNetworkCount(nil, zone) } /*def host_count(self, status=None, host_status=None, enabled=None, host_type=None, is_baremetal=None): @@ -727,7 +727,7 @@ func (self *SZone) AllowGetDetailsCapability(ctx context.Context, userCred mccli } func (self *SZone) GetDetailsCapability(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) { - capa, err := GetCapabilities(ctx, userCred, query, self) + capa, err := GetCapabilities(ctx, userCred, query, nil, self) if err != nil { return nil, err }