diff --git a/cmd/climc/shell/compute/cloudregions.go b/cmd/climc/shell/compute/cloudregions.go index 5ca0395a75..2900021768 100644 --- a/cmd/climc/shell/compute/cloudregions.go +++ b/cmd/climc/shell/compute/cloudregions.go @@ -130,6 +130,24 @@ func init() { return nil }) + R(&CloudregionCityListOptions{}, "cloud-city-servers", "List cities where cloud region resides", func(s *mcclient.ClientSession, args *CloudregionCityListOptions) error { + params, err := options.StructToParams(args) + if err != nil { + return err + } + results, err := modules.Cloudregions.GetCityServers(s, params) + if err != nil { + return err + } + listResult := modulebase.ListResult{} + listResult.Data, err = results.GetArray() + if err != nil { + return err + } + printList(&listResult, nil) + return nil + }) + type CloudregionCreateOptions struct { Id string `help:"ID of the region"` NAME string `help:"Name of the region"` diff --git a/pkg/mcclient/modules/mod_cloudregions.go b/pkg/mcclient/modules/mod_cloudregions.go index bb99bd6564..1736e0a70c 100644 --- a/pkg/mcclient/modules/mod_cloudregions.go +++ b/pkg/mcclient/modules/mod_cloudregions.go @@ -18,7 +18,9 @@ import ( "sort" "yunion.io/x/jsonutils" + "yunion.io/x/pkg/errors" + "yunion.io/x/onecloud/pkg/cloudprovider" "yunion.io/x/onecloud/pkg/mcclient" "yunion.io/x/onecloud/pkg/mcclient/modulebase" ) @@ -34,6 +36,7 @@ var ( type sNameCounter struct { Name string Count int + cloudprovider.SGeographicInfo } type tNameCounters []sNameCounter @@ -59,25 +62,31 @@ func (this *SCloudregionManager) getRegionAttributeList(session *mcclient.Client return nil, err } - cities := make(map[string]int) + cities := map[string]*sNameCounter{} for i := range listResult.Data { cityStr, _ := listResult.Data[i].GetString(attr) if len(cityStr) == 0 && attr == "city" { cityStr = "Other" } if len(cityStr) > 0 { - if _, ok := cities[cityStr]; ok { - cities[cityStr] += 1 - } else { - cities[cityStr] = 1 + _, ok := cities[cityStr] + if !ok { + cities[cityStr] = &sNameCounter{ + Name: cityStr, + Count: 0, + } + if attr == "city" { + listResult.Data[i].Unmarshal(&cities[cityStr].SGeographicInfo) + } } + cities[cityStr].Count += 1 } } cityList := make([]sNameCounter, len(cities)) i := 0 for k, v := range cities { - cityList[i] = sNameCounter{Name: k, Count: v} + cityList[i] = sNameCounter{Name: k, Count: v.Count, SGeographicInfo: v.SGeographicInfo} i += 1 } @@ -94,6 +103,31 @@ func (this *SCloudregionManager) GetRegionProviders(session *mcclient.ClientSess return this.getRegionAttributeList(session, params, "provider") } +func (this *SCloudregionManager) GetCityServers(session *mcclient.ClientSession, params jsonutils.JSONObject) (jsonutils.JSONObject, error) { + objs, err := this.GetRegionCities(session, params) + if err != nil { + return nil, errors.Wrapf(err, "GetRegionCities") + } + cities := []sNameCounter{} + err = objs.Unmarshal(&cities) + if err != nil { + return nil, errors.Wrapf(err, "objs.Unmarshal") + } + _params := params.(*jsonutils.JSONDict) + _params.Set("limit", jsonutils.NewInt(1)) + _params.Set("details", jsonutils.NewBool(false)) + for i := range cities { + _params.Set("city", jsonutils.NewString(cities[i].Name)) + resp, err := Servers.List(session, _params) + if err != nil { + return nil, errors.Wrapf(err, "Servers.List") + } + cities[i].Count = resp.Total + } + sort.Sort(tNameCounters(cities)) + return jsonutils.Marshal(cities), nil +} + func init() { Cloudregions = SCloudregionManager{ NewComputeManager("cloudregion", "cloudregions",