diff --git a/cmd/climc/shell/skus.go b/cmd/climc/shell/skus.go new file mode 100644 index 0000000000..57b135e78f --- /dev/null +++ b/cmd/climc/shell/skus.go @@ -0,0 +1,131 @@ +package shell + +import ( + "yunion.io/x/onecloud/pkg/mcclient" + "yunion.io/x/onecloud/pkg/mcclient/modules" + "yunion.io/x/onecloud/pkg/mcclient/options" +) + +func init() { + type ServerSkusListOptions struct { + options.BaseListOptions + } + R(&ServerSkusListOptions{}, "server-sku-list", "List all avaiable Server SKU", func(s *mcclient.ClientSession, args *ServerSkusListOptions) error { + params, err := options.ListStructToParams(args) + if err != nil { + return err + } + results, err := modules.ServerSkus.List(s, params) + if err != nil { + return err + } + printList(results, modules.ServerSkus.GetColumns(s)) + return nil + }) + + type ServerSkusShowOptions struct { + ID string `help:"ID or Name of SKU to show"` + } + R(&ServerSkusShowOptions{}, "server-sku-show", "show details of a avaiable Server SKU", func(s *mcclient.ClientSession, args *ServerSkusShowOptions) error { + result, err := modules.ServerSkus.Get(s, args.ID, nil) + if err != nil { + return err + } + printObject(result) + return nil + }) + + type ServerSkusCreateOptions struct { + Name string `help:"Name ID of SKU" required:"true" positional:"true"` + CpuCoreCount int `help:"Cpu Count" required:"true" positional:"true"` + MemorySizeMB int `help:"Memory MB" required:"true" positional:"true"` + + SkuFamily *string `help:"sku family"` + SkuCategory *string `help:"sku category" choices:"general_purpose|compute_optimized|memory_optimized|storage_optimized|hardware_accelerated|high_memory|high_storage"` + + SysDiskResizable *bool `help:"system disk is resizable"` + SysDiskMaxSizeGB *int `help:"system disk maximal size in gb"` + + AttachedDiskType *string `help:"attached data disk type"` + AttachedDiskSizeGB *int `help:"attached data disk size in GB"` + AttachedDiskCount *int `help:"attached data disk count"` + + MaxDataDiskCount *int `help:"maximal allowed data disk count"` + + NicType *string `help:"nic type"` + MaxNicCount *int `help:"maximal nic count"` + + GPUSpec *string `help:"GPU spec"` + GPUCount *int `help:"GPU count"` + GPUAttachable *bool `help:"Allow attach GPU"` + + Zone *string `help:"Zone ID or name"` + Region *string `help:"Region ID or name"` + } + R(&ServerSkusCreateOptions{}, "server-sku-create", "Create a server sku record", func(s *mcclient.ClientSession, args *ServerSkusCreateOptions) error { + params, err := options.StructToParams(args) + if err != nil { + return err + } + result, err := modules.ServerSkus.Create(s, params) + if err != nil { + return err + } + printObject(result) + return nil + }) + + type ServerSkusUpdateOptions struct { + ID string `help:"Name or ID of SKU" json:"-"` + + Name *string `help:"new name of SKU"` + CpuCoreCount *int `help:"Cpu Count"` + MemorySizeMB *int `help:"Memory MB"` + + SkuFamily *string `help:"sku family"` + SkuCategory *string `help:"sku category" choices:"general_purpose|compute_optimized|memory_optimized|storage_optimized|hardware_accelerated|high_memory|high_storage"` + + SysDiskResizable *bool `help:"system disk is resizable"` + SysDiskMaxSizeGB *int `help:"system disk maximal size in gb"` + + AttachedDiskType *string `help:"attached data disk type"` + AttachedDiskSizeGB *int `help:"attached data disk size in GB"` + AttachedDiskCount *int `help:"attached data disk count"` + + MaxDataDiskCount *int `help:"maximal allowed data disk count"` + + NicType *string `help:"nic type"` + MaxNicCount *int `help:"maximal nic count"` + + GPUSpec *string `help:"GPU spec"` + GPUCount *int `help:"GPU count"` + GPUAttachable *bool `help:"Allow attach GPU"` + + Zone *string `help:"Zone ID or name"` + Region *string `help:"Region ID or name"` + } + R(&ServerSkusUpdateOptions{}, "server-sku-update", "Update server sku attributes", func(s *mcclient.ClientSession, args *ServerSkusUpdateOptions) error { + params, err := options.StructToParams(args) + if err != nil { + return err + } + result, err := modules.ServerSkus.Update(s, args.ID, params) + if err != nil { + return err + } + printObject(result) + return nil + }) + + type ServerSkusDeleteOptions struct { + ID string `help:"Id or name of server sku"` + } + R(&ServerSkusDeleteOptions{}, "server-sku-delete", "Delete a server sku", func(s *mcclient.ClientSession, args *ServerSkusDeleteOptions) error { + result, err := modules.ServerSkus.Delete(s, args.ID, nil) + if err != nil { + return err + } + printObject(result) + return nil + }) +} diff --git a/pkg/compute/handlers.go b/pkg/compute/handlers.go index 22550bf00e..6d7ed755f0 100644 --- a/pkg/compute/handlers.go +++ b/pkg/compute/handlers.go @@ -74,6 +74,8 @@ func InitHandlers(app *appsrv.Application) { models.SchedpolicyManager, models.DynamicschedtagManager, + + models.ServerSkuManager, } { db.RegisterModelManager(manager) handler := db.NewModelHandler(manager) diff --git a/pkg/compute/models/cloudregions.go b/pkg/compute/models/cloudregions.go index 3e4c931cc8..bf2fcd1eb3 100644 --- a/pkg/compute/models/cloudregions.go +++ b/pkg/compute/models/cloudregions.go @@ -19,6 +19,8 @@ import ( const ( CLOUD_REGION_STATUS_INSERVER = "inservice" CLOUD_REGION_STATUS_OUTOFSERVICE = "outofservice" + + DEFAULT_REGION_ID = "default" ) type SCloudregionManager struct { @@ -64,7 +66,7 @@ func (self *SCloudregion) ValidateDeleteCondition(ctx context.Context) error { if self.GetZoneCount() > 0 || self.GetVpcCount() > 0 { return httperrors.NewNotEmptyError("not empty cloud region") } - if self.Id == "default" { + if self.Id == DEFAULT_REGION_ID { return httperrors.NewProtectedResourceError("not allow to delete default cloud region") } return self.SEnabledStatusStandaloneResourceBase.ValidateDeleteCondition(ctx) @@ -72,7 +74,7 @@ func (self *SCloudregion) ValidateDeleteCondition(ctx context.Context) error { func (self *SCloudregion) GetZoneCount() int { zones := ZoneManager.Query() - if self.Id == "default" { + if self.Id == DEFAULT_REGION_ID { return zones.Filter(sqlchemy.OR(sqlchemy.IsNull(zones.Field("cloudregion_id")), sqlchemy.IsEmpty(zones.Field("cloudregion_id")), sqlchemy.Equals(zones.Field("cloudregion_id"), self.Id))).Count() @@ -83,7 +85,7 @@ func (self *SCloudregion) GetZoneCount() int { func (self *SCloudregion) GetGuestCount(increment bool) int { zoneTable := ZoneManager.Query("id") - if self.Id == "default" { + if self.Id == DEFAULT_REGION_ID { zoneTable = zoneTable.Filter(sqlchemy.OR(sqlchemy.IsNull(zoneTable.Field("cloudregion_id")), sqlchemy.IsEmpty(zoneTable.Field("cloudregion_id")), sqlchemy.Equals(zoneTable.Field("cloudregion_id"), self.Id))) @@ -102,7 +104,7 @@ func (self *SCloudregion) GetGuestCount(increment bool) int { func (self *SCloudregion) GetVpcCount() int { vpcs := VpcManager.Query() - if self.Id == "default" { + if self.Id == DEFAULT_REGION_ID { return vpcs.Filter(sqlchemy.OR(sqlchemy.IsNull(vpcs.Field("cloudregion_id")), sqlchemy.IsEmpty(vpcs.Field("cloudregion_id")), sqlchemy.Equals(vpcs.Field("cloudregion_id"), self.Id))).Count() @@ -294,11 +296,11 @@ func (manager *SCloudregionManager) FetchRegionById(id string) *SCloudregion { func (manager *SCloudregionManager) InitializeData() error { // check if default region exists - _, err := manager.FetchById("default") + _, err := manager.FetchById(DEFAULT_REGION_ID) if err != nil { if err == sql.ErrNoRows { defRegion := SCloudregion{} - defRegion.Id = "default" + defRegion.Id = DEFAULT_REGION_ID defRegion.Name = "Default" defRegion.Enabled = true defRegion.Description = "Default Region" diff --git a/pkg/compute/models/guests.go b/pkg/compute/models/guests.go index df16410468..21115e52d6 100644 --- a/pkg/compute/models/guests.go +++ b/pkg/compute/models/guests.go @@ -201,6 +201,8 @@ type SGuest struct { AdminSecgrpId string `width:"36" charset:"ascii" nullable:"true" get:"admin"` // Column(VARCHAR(36, charset='ascii'), nullable=True) Hypervisor string `width:"16" charset:"ascii" nullable:"false" default:"kvm" list:"user" create:"required"` // Column(VARCHAR(16, charset='ascii'), nullable=False, default=HYPERVISOR_DEFAULT) + + SkuId string `width:"64" charset:"ascii" nullable:"true" list:"user" create:"optional"` } func (manager *SGuestManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool { diff --git a/pkg/compute/models/skus.go b/pkg/compute/models/skus.go new file mode 100644 index 0000000000..56f30fbd18 --- /dev/null +++ b/pkg/compute/models/skus.go @@ -0,0 +1,132 @@ +package models + +import ( + "context" + + "database/sql" + "yunion.io/x/jsonutils" + "yunion.io/x/onecloud/pkg/cloudcommon/db" + "yunion.io/x/onecloud/pkg/httperrors" + "yunion.io/x/onecloud/pkg/mcclient" +) + +const ( + SkuCategoryGeneralPurpose = "general_purpose" // 通用型 + SkuCategoryBurstable = "burstable" // 突发性能型 + SkuCategoryComputeOptimized = "compute_optimized" // 计算优化型 + SkuCategoryMemoryOptimized = "memory_optimized" // 内存优化型 + SkuCategoryStorageIOOptimized = "storage_optimized" // 存储IO优化型 + SkuCategoryHardwareAccelerated = "hardware_accelerated" // 硬件加速型 + SkuCategoryHighStorage = "high_storage" // 高存储型 + SkuCategoryHighMemory = "high_memory" // 高内存型 +) + +type SServerSkuManager struct { + db.SStandaloneResourceBaseManager + SInfrastructureManager +} + +var ServerSkuManager *SServerSkuManager + +func init() { + ServerSkuManager = &SServerSkuManager{ + SStandaloneResourceBaseManager: db.NewStandaloneResourceBaseManager( + SServerSku{}, + "serverskus_tbl", + "serversku", + "serverskus", + ), + } + ServerSkuManager.NameRequireAscii = false +} + +type SServerSku struct { + db.SStandaloneResourceBase + SInfrastructure + + // SkuId string `width:"64" charset:"ascii" nullable:"false" list:"user" create:"admin_required"` + SkuFamily string `width:"32" charset:"ascii" nullable:"false" list:"user" create:"admin_optional" update:"admin"` + SkuCategory string `width:"32" charset:"ascii" nullable:"false" list:"user" create:"admin_optional" update:"admin"` + + CpuCoreCount int `nullable:"false" list:"user" create:"admin_required" update:"admin"` + MemorySizeMB int `nullable:"false" list:"user" create:"admin_required" update:"admin"` + + SysDiskResizable bool `default:"true" nullable:"false" list:"user" create:"admin_optional" update:"admin"` + SysDiskMaxSizeGB int `nullable:"false" list:"user" create:"admin_optional" update:"admin"` + + AttachedDiskType string `nullable:"false" list:"user" create:"admin_optional" update:"admin"` + AttachedDiskSizeGB int `nullable:"false" list:"user" create:"admin_optional" update:"admin"` + AttachedDiskCount int `nullable:"false" list:"user" create:"admin_optional" update:"admin"` + + MaxDataDiskCount int `nullable:"false" list:"user" create:"admin_optional" update:"admin"` + + NicType string `nullable:"false" list:"user" create:"admin_optional" update:"admin"` + MaxNicCount int `default:"1" nullable:"false" list:"user" create:"admin_optional" update:"admin"` + + GpuAttachable bool `default:"true" nullable:"false" list:"user" create:"admin_optional" update:"admin"` + GpuSpec string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"admin_optional" update:"admin"` + GpuCount int `nullable:"false" list:"user" create:"admin_optional" update:"admin"` + + CloudregionId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"admin_required" update:"admin"` + ZoneId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"admin_optional" update:"admin"` +} + +func (self *SServerSkuManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool { + return true +} + +func (self *SServerSku) AllowGetDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool { + return true +} + +func (self *SServerSkuManager) ValidateCreateData(ctx context.Context, + userCred mcclient.TokenCredential, + ownerProjId string, + query jsonutils.JSONObject, + data *jsonutils.JSONDict, +) (*jsonutils.JSONDict, error) { + regionStr := jsonutils.GetAnyString(data, []string{"region", "region_id", "cloudregion", "cloudregion_id"}) + if len(regionStr) > 0 { + regionObj, err := CloudregionManager.FetchByIdOrName(userCred, regionStr) + if err != nil { + if err == sql.ErrNoRows { + return nil, httperrors.NewResourceNotFoundError("region %s not found", regionStr) + } + return nil, httperrors.NewGeneralError(err) + } + data.Add(jsonutils.NewString(regionObj.GetId()), "cloudregion_id") + } else { + data.Add(jsonutils.NewString(DEFAULT_REGION_ID), "cloudregion_id") + } + zoneStr := jsonutils.GetAnyString(data, []string{"zone", "zone_id"}) + if len(zoneStr) > 0 { + zoneObj, err := ZoneManager.FetchByIdOrName(userCred, zoneStr) + if err != nil { + if err == sql.ErrNoRows { + return nil, httperrors.NewResourceNotFoundError("zone %s not found", zoneStr) + } + return nil, httperrors.NewGeneralError(err) + } + data.Add(jsonutils.NewString(zoneObj.GetId()), "zone_id") + } + return self.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data) +} + +func (self *SServerSku) ValidateUpdateData( + ctx context.Context, + userCred mcclient.TokenCredential, + query jsonutils.JSONObject, + data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { + zoneStr := jsonutils.GetAnyString(data, []string{"zone", "zone_id"}) + if len(zoneStr) > 0 { + zoneObj, err := ZoneManager.FetchByIdOrName(userCred, zoneStr) + if err != nil { + if err == sql.ErrNoRows { + return nil, httperrors.NewResourceNotFoundError("zone %s not found", zoneStr) + } + return nil, httperrors.NewGeneralError(err) + } + data.Add(jsonutils.NewString(zoneObj.GetId()), "zone_id") + } + return self.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data) +} diff --git a/pkg/compute/models/vpcs.go b/pkg/compute/models/vpcs.go index 6bc2ffca33..27b38f3545 100644 --- a/pkg/compute/models/vpcs.go +++ b/pkg/compute/models/vpcs.go @@ -29,6 +29,8 @@ const ( VPC_STATUS_UNKNOWN = "unknown" MAX_VPC_PER_REGION = 3 + + DEFAULT_VPC_ID = "default" ) type SVpcManager struct { @@ -67,7 +69,7 @@ func (manager *SVpcManager) GetContextManager() []db.IModelManager { func (self *SVpc) GetCloudRegionId() string { if len(self.CloudregionId) == 0 { - return "default" + return DEFAULT_REGION_ID } else { return self.CloudregionId } @@ -85,7 +87,7 @@ func (self *SVpc) ValidateDeleteCondition(ctx context.Context) error { if self.GetNetworkCount() > 0 { return httperrors.NewNotEmptyError("VPC not empty") } - if self.Id == "default" { + if self.Id == DEFAULT_VPC_ID { return httperrors.NewProtectedResourceError("not allow to delete default vpc") } return self.SEnabledStatusStandaloneResourceBase.ValidateDeleteCondition(ctx) @@ -93,7 +95,7 @@ func (self *SVpc) ValidateDeleteCondition(ctx context.Context) error { func (self *SVpc) getWireQuery() *sqlchemy.SQuery { wires := WireManager.Query() - if self.Id == "default" { + if self.Id == DEFAULT_VPC_ID { return wires.Filter(sqlchemy.OR(sqlchemy.IsNull(wires.Field("vpc_id")), sqlchemy.IsEmpty(wires.Field("vpc_id")), sqlchemy.Equals(wires.Field("vpc_id"), self.Id))) @@ -308,15 +310,15 @@ func (self *SVpc) markAllNetworksUnknown(userCred mcclient.TokenCredential) erro } func (manager *SVpcManager) InitializeData() error { - vpcObj, err := manager.FetchById("default") + vpcObj, err := manager.FetchById(DEFAULT_VPC_ID) if err != nil { if err == sql.ErrNoRows { defVpc := SVpc{} defVpc.SetModelManager(VpcManager) - defVpc.Id = "default" + defVpc.Id = DEFAULT_VPC_ID defVpc.Name = "Default" - defVpc.CloudregionId = "default" + defVpc.CloudregionId = DEFAULT_REGION_ID defVpc.Description = "Default VPC" defVpc.Status = VPC_STATUS_AVAILABLE defVpc.IsDefault = true diff --git a/pkg/mcclient/modules/mod_skus.go b/pkg/mcclient/modules/mod_skus.go new file mode 100644 index 0000000000..bb381cab1a --- /dev/null +++ b/pkg/mcclient/modules/mod_skus.go @@ -0,0 +1,17 @@ +package modules + +var ( + ServerSkus ResourceManager +) + +func init() { + ServerSkus = NewComputeManager("serversku", + "serverskus", + []string{"id", "name", "sku_id", + "sku_family", "cpu_core_count", "memory_size_mb", + "cloudregion_id", "zone_id", + }, + []string{}) + + registerComputeV2(&ServerSkus) +} diff --git a/pkg/util/aliyun/instancetype.go b/pkg/util/aliyun/instancetype.go index 49b4a1c3ad..75b730725d 100644 --- a/pkg/util/aliyun/instancetype.go +++ b/pkg/util/aliyun/instancetype.go @@ -9,12 +9,14 @@ import ( // InstanceBandwidthRx":26214400,"InstanceBandwidthTx":26214400,"InstancePpsRx":4500000,"InstancePpsTx":4500000 type SInstanceType struct { + BaselineCredit int CpuCoreCount int MemorySize float32 EniQuantity int // 实例规格支持网卡数量 GPUAmount int GPUSpec string InstanceTypeFamily string + InstanceFamilyLevel string InstanceTypeId string LocalStorageCategory string LocalStorageAmount int diff --git a/pkg/util/azure/region.go b/pkg/util/azure/region.go index 20b018f4a4..ff634bdb8c 100644 --- a/pkg/util/azure/region.go +++ b/pkg/util/azure/region.go @@ -46,8 +46,11 @@ func (self *SRegion) GetClient() *SAzureClient { return self.client } -func (self *SRegion) GetVMSize() (map[string]SVMSize, error) { - body, err := self.client.ListVmSizes(self.Name) +func (self *SRegion) GetVMSize(location string) (map[string]SVMSize, error) { + if len(location) == 0 { + location = self.Name + } + body, err := self.client.ListVmSizes(location) if err != nil { return nil, err } @@ -64,7 +67,7 @@ func (self *SRegion) GetVMSize() (map[string]SVMSize, error) { } func (self *SRegion) getHardwareProfile(cpu, memMB int) []string { - if vmSizes, err := self.GetVMSize(); err != nil { + if vmSizes, err := self.GetVMSize(""); err != nil { return []string{} } else { profiles := make([]string, 0) @@ -78,7 +81,7 @@ func (self *SRegion) getHardwareProfile(cpu, memMB int) []string { } func (self *SRegion) getVMSize(size string) (*SVMSize, error) { - vmSizes, err := self.GetVMSize() + vmSizes, err := self.GetVMSize("") if err != nil { return nil, err } diff --git a/pkg/util/azure/resourcesku.go b/pkg/util/azure/resourcesku.go new file mode 100644 index 0000000000..b26207fe74 --- /dev/null +++ b/pkg/util/azure/resourcesku.go @@ -0,0 +1,145 @@ +package azure + +import ( + "fmt" + "yunion.io/x/pkg/utils" +) + +/* +{ + "capabilities":[ + {"name":"MaxResourceVolumeMB","value":"286720"}, + {"name":"OSVhdSizeMB","value":"1047552"}, + {"name":"vCPUs","value":"20"}, + {"name":"MemoryGB","value":"140"}, + {"name":"MaxDataDiskCount","value":"64"}, + {"name":"LowPriorityCapable","value":"True"}, + {"name":"PremiumIO","value":"True"}, + {"name":"EphemeralOSDiskSupported","value":"True"} + ], + "family":"standardDSv2Family", + "locations":["CentralUSEUAP"], + "name":"Standard_DS15_v2", + "resourceType":"virtualMachines", + "restrictions":[], + "size":"DS15_v2", + "tier":"Standard" +} +*/ + +type SResourceSkuCapability struct { + Name string + Value string +} + +type TResourceSkuCapacityScaleType string + +const ( + ResourceSkuCapacityScaleTypeAutomatic = TResourceSkuCapacityScaleType("Automatic") + ResourceSkuCapacityScaleTypeManual = TResourceSkuCapacityScaleType("Manual") + ResourceSkuCapacityScaleTypeNone = TResourceSkuCapacityScaleType("None") +) + +type SResourceSkuCapacity struct { + Default int + Maximum int + Minimum int + ScaleType TResourceSkuCapacityScaleType +} + +type SResourceSkuLocationInfo struct { + Location string + Zones []string +} + +type TResourceSkuRestrictionsType string + +const ( + ResourceSkuRestrictionsTypeLocation = TResourceSkuRestrictionsType("Location") + ResourceSkuRestrictionsTypeZone = TResourceSkuRestrictionsType("Zone") +) + +type TResourceSkuRestrictionsReasonCode string + +const ( + ResourceSkuRestrictionsReasonCodeNotAvailable = TResourceSkuRestrictionsReasonCode("NotAvailableForSubscription") + ResourceSkuRestrictionsReasonCodeQuotaId = TResourceSkuRestrictionsReasonCode("QuotaId") +) + +type SResourceSkuRestrictionInfo struct { + Locations []string + Zones []string +} + +type SResourceSkuRestrictions struct { + ReasonCode TResourceSkuRestrictionsReasonCode + RestrictionInfo SResourceSkuRestrictionInfo + Type TResourceSkuRestrictionsType + Values []string +} + +type SResourceSku struct { + Capabilities []SResourceSkuCapability + Capacity *SResourceSkuCapacity + Family string + Kind string + LocationInfo []SResourceSkuLocationInfo + Locations []string + Name string + ResourceType string + Restrictions []SResourceSkuRestrictions + Size string + Tier string +} + +type SResourceSkusResult struct { + NextLink string + Value []SResourceSku +} + +func (self *SAzureClient) ListResourceSkus() ([]SResourceSku, error) { + cli, err := self.getDefaultClient() + if err != nil { + return nil, err + } + if len(self.subscriptionId) == 0 { + return nil, fmt.Errorf("need subscription id") + } + url := fmt.Sprintf("/subscriptions/%s/providers/Microsoft.Compute/skus?api-version=2017-09-01", self.subscriptionId) + skus := make([]SResourceSku, 0) + for { + body, err := jsonRequest(cli, "GET", self.domain, url, "") + if err != nil { + return nil, err + } + result := SResourceSkusResult{} + err = body.Unmarshal(&result) + if err != nil { + return nil, err + } + skus = append(skus, result.Value...) + if len(result.NextLink) > 0 { + url = result.NextLink + } else { + break + } + } + return skus, nil +} + +func (self *SRegion) GetResourceSkus(location string) ([]SResourceSku, error) { + skus, err := self.client.ListResourceSkus() + if err != nil { + return nil, err + } + if len(location) == 0 { + return skus, nil + } + ret := make([]SResourceSku, 0) + for i := 0; i < len(skus); i += 1 { + if utils.IsInStringArray(location, skus[i].Locations) { + ret = append(ret, skus[i]) + } + } + return ret, nil +} diff --git a/pkg/util/azure/shell/instance.go b/pkg/util/azure/shell/instance.go index a5e5f6987a..9013ae394a 100644 --- a/pkg/util/azure/shell/instance.go +++ b/pkg/util/azure/shell/instance.go @@ -39,18 +39,25 @@ func init() { }) type InstanceSizeListOptions struct { - Limit int `help:"page size"` - Offset int `help:"page offset"` + Location string } shellutils.R(&InstanceSizeListOptions{}, "instance-size-list", "List intances", func(cli *azure.SRegion, args *InstanceSizeListOptions) error { - if vmSize, err := cli.GetVMSize(); err != nil { + if vmSize, err := cli.GetVMSize(args.Location); err != nil { return err } else { printObject(vmSize) return nil } }) + shellutils.R(&InstanceSizeListOptions{}, "resource-sku-list", "List resource sku", func(cli *azure.SRegion, args *InstanceSizeListOptions) error { + skus, err := cli.GetResourceSkus(args.Location) + if err != nil { + return err + } + printList(skus, len(skus), 0, 0, []string{}) + return nil + }) type InstanceCrateOptions struct { NAME string `help:"name of instance"`