mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
Merge pull request #722 in YUNIONIO/onecloud from ~TANGBIN/onecloud:feature/tb-skus-support-private-cloud to release/2.4.0
* commit '779a588bcf9da4dc6482d89c525bb1938151afa7': make fmt name bugfix skus list bugfix update skus climc update sku create & update & list method update sku create & update & list method
This commit is contained in:
+8
-13
@@ -11,7 +11,7 @@ import (
|
||||
func init() {
|
||||
type ServerSkusListOptions struct {
|
||||
options.BaseListOptions
|
||||
Provider string `help:"provider" choices:"all|kvm|esxi|xen|hyperv|aliyun|azure|aws|qcloud|huawei"`
|
||||
Provider string `help:"provider" choices:"all|aliyun|azure|aws|qcloud|huawei" default:""`
|
||||
Region string `help:"region Id or name"`
|
||||
Zone string `help:"zone Id or name"`
|
||||
Cpu int `help:"Cpu core count"`
|
||||
@@ -50,14 +50,11 @@ func init() {
|
||||
})
|
||||
|
||||
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"`
|
||||
Provider string `help:"Provider name" choices:"kvm|esxi"`
|
||||
CpuCoreCount int `help:"Cpu Count" required:"true" positional:"true"`
|
||||
MemorySizeMB int `help:"Memory MB" required:"true" positional:"true"`
|
||||
|
||||
OsName *string `help:"OS name/type" choices:"Linux|Windows|Any" default:"Any"`
|
||||
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"`
|
||||
OsName *string `help:"OS name/type" choices:"Linux|Windows|Any" default:"Any"`
|
||||
InstanceTypeCategory *string `help:"instance type category" choices:"general_purpose|compute_optimized|memory_optimized|storage_optimized|hardware_accelerated|high_memory|high_storage"`
|
||||
|
||||
SysDiskResizable *bool `help:"system disk is resizable"`
|
||||
SysDiskType *string `help:"system disk type" default:"local" choices:"local"`
|
||||
@@ -95,12 +92,10 @@ func init() {
|
||||
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"`
|
||||
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"`
|
||||
InstanceTypeCategory *string `help:"instance type 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"`
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
)
|
||||
|
||||
type SCapabilities struct {
|
||||
Hypervisors []string `json:",allowempty"`
|
||||
StorageTypes []string `json:",allowempty"`
|
||||
GPUModels []string `json:",allowempty"`
|
||||
Hypervisors []string `json:",allowempty"`
|
||||
StorageTypes []string `json:",allowempty"`
|
||||
GPUModels []string `json:",allowempty"`
|
||||
MinNicCount int
|
||||
MaxNicCount int
|
||||
MinDataDiskCount int
|
||||
|
||||
+158
-25
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
@@ -25,6 +26,17 @@ const (
|
||||
SkuCategoryHighMemory = "high_memory" // 高内存型
|
||||
)
|
||||
|
||||
var InstanceFamilies map[string]string = map[string]string{
|
||||
SkuCategoryGeneralPurpose: "g1",
|
||||
SkuCategoryBurstable: "t1",
|
||||
SkuCategoryComputeOptimized: "c1",
|
||||
SkuCategoryMemoryOptimized: "r1",
|
||||
SkuCategoryStorageIOOptimized: "i1",
|
||||
SkuCategoryHardwareAccelerated: "",
|
||||
SkuCategoryHighStorage: "hc1",
|
||||
SkuCategoryHighMemory: "hr1",
|
||||
}
|
||||
|
||||
type SServerSkuManager struct {
|
||||
db.SStandaloneResourceBaseManager
|
||||
}
|
||||
@@ -54,10 +66,10 @@ type SServerSku struct {
|
||||
CpuCoreCount int `nullable:"false" list:"user" create:"admin_required" update:"admin"`
|
||||
MemorySizeMB int `nullable:"false" list:"user" create:"admin_required" update:"admin"`
|
||||
|
||||
OsName string `width:"32" charset:"ascii" nullable:"false" list:"user" create:"admin_required" update:"admin" default:"Any"` // Windows|Linux|Any
|
||||
OsName string `width:"32" charset:"ascii" nullable:"false" list:"user" create:"admin_optional" update:"admin" default:"Any"` // Windows|Linux|Any
|
||||
|
||||
SysDiskResizable bool `default:"true" nullable:"false" list:"user" create:"admin_optional" update:"admin"`
|
||||
SysDiskType string `width:"32" charset:"ascii" nullable:"false" list:"user" create:"admin_required" update:"admin"`
|
||||
SysDiskType string `width:"32" charset:"ascii" nullable:"false" list:"user" create:"admin_optional" update:"admin"`
|
||||
SysDiskMinSizeGB int `nullable:"false" list:"user" create:"admin_optional" update:"admin"` // not required。 windows比较新的版本都是50G左右。
|
||||
SysDiskMaxSizeGB int `nullable:"false" list:"user" create:"admin_optional" update:"admin"` // not required
|
||||
|
||||
@@ -82,18 +94,26 @@ type SServerSku struct {
|
||||
}
|
||||
|
||||
func inWhiteList(provider string) bool {
|
||||
// 只有为true的hypervisor才进行创建和更新操作
|
||||
// provider 字段为空时表示私有云套餐
|
||||
if len(provider) == 0 {
|
||||
return true
|
||||
}
|
||||
switch provider {
|
||||
case HYPERVISOR_ESXI, HYPERVISOR_KVM:
|
||||
return true
|
||||
default:
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func genInstanceType(family string, cpu, mem_mb int64) (string, error) {
|
||||
if cpu <= 0 {
|
||||
return "", fmt.Errorf("cpu_core_count should great than zero")
|
||||
}
|
||||
|
||||
if mem_mb <= 0 || mem_mb%1024 != 0 {
|
||||
return "", fmt.Errorf("memory_size_mb should great than zero. and should be integral multiple of 1024")
|
||||
}
|
||||
|
||||
return fmt.Sprintf("ecs.%s.c%dm%d", family, cpu, mem_mb/1024), nil
|
||||
}
|
||||
|
||||
func (self *SServerSkuManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return true
|
||||
}
|
||||
@@ -119,6 +139,8 @@ func (self *SServerSkuManager) ValidateCreateData(ctx context.Context,
|
||||
return nil, httperrors.NewForbiddenError("can not create instance_type for public cloud %s", provider)
|
||||
}
|
||||
|
||||
data.Remove("provider")
|
||||
|
||||
regionStr := jsonutils.GetAnyString(data, []string{"region", "region_id", "cloudregion", "cloudregion_id"})
|
||||
if len(regionStr) > 0 {
|
||||
regionObj, err := CloudregionManager.FetchByIdOrName(userCred, regionStr)
|
||||
@@ -143,6 +165,47 @@ func (self *SServerSkuManager) ValidateCreateData(ctx context.Context,
|
||||
}
|
||||
data.Add(jsonutils.NewString(zoneObj.GetId()), "zone_id")
|
||||
}
|
||||
|
||||
// name 由服务器端生成
|
||||
cpu, err := data.Int("cpu_core_count")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("cpu_core_count should not be empty")
|
||||
} else {
|
||||
data.Set("cpu_core_count", jsonutils.NewInt(cpu))
|
||||
}
|
||||
|
||||
mem, err := data.Int("memory_size_mb")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("memory_size_mb should not be empty")
|
||||
} else {
|
||||
data.Set("memory_size_mb", jsonutils.NewInt(mem))
|
||||
}
|
||||
|
||||
category, _ := data.GetString("instance_type_category")
|
||||
family, exists := InstanceFamilies[category]
|
||||
if !exists {
|
||||
return nil, httperrors.NewInputParameterError("instance_type_category %s is invalid", category)
|
||||
}
|
||||
|
||||
data.Set("instance_type_family", jsonutils.NewString(family))
|
||||
// 格式 ecs.g1.c1m1
|
||||
name, err := genInstanceType(family, cpu, mem)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError(err.Error())
|
||||
}
|
||||
|
||||
data.Set("name", jsonutils.NewString(name))
|
||||
|
||||
q := self.Query()
|
||||
q = q.Equals("name", name).Filter(sqlchemy.OR(
|
||||
sqlchemy.IsNull(q.Field("provider")),
|
||||
sqlchemy.IsEmpty(q.Field("provider")),
|
||||
))
|
||||
|
||||
if q.Count() > 0 {
|
||||
return nil, httperrors.NewDuplicateResourceError("Duplicate sku %s", name)
|
||||
}
|
||||
|
||||
return self.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data)
|
||||
}
|
||||
|
||||
@@ -182,17 +245,38 @@ func (self *SServerSkuManager) AllowGetPropertyInstanceSpecs(ctx context.Context
|
||||
|
||||
func (self *SServerSkuManager) GetPropertyInstanceSpecs(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
q := self.Query()
|
||||
zone, err := query.GetString("zone")
|
||||
if err == nil && len(zone) > 0 {
|
||||
q = q.Equals("zone_id", zone)
|
||||
provider, _ := query.GetString("provider")
|
||||
if inWhiteList(provider) {
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.IsNull(q.Field("provider")),
|
||||
sqlchemy.IsEmpty(q.Field("provider")),
|
||||
))
|
||||
} else {
|
||||
return nil, httperrors.NewMissingParameterError("zone")
|
||||
q = q.Equals("provider", provider)
|
||||
}
|
||||
|
||||
// 如果是查询私有云需要忽略zone参数
|
||||
zone := jsonutils.GetAnyString(query, []string{"zone", "zone_id"})
|
||||
if !inWhiteList(provider) {
|
||||
if len(zone) > 0 {
|
||||
zoneObj, err := ZoneManager.FetchByIdOrName(userCred, zone)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError2(ZoneManager.Keyword(), zone)
|
||||
}
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
|
||||
q = q.Equals("zone_id", zoneObj.GetId())
|
||||
} else {
|
||||
return nil, httperrors.NewMissingParameterError("zone")
|
||||
}
|
||||
}
|
||||
|
||||
skus := make([]SServerSku, 0)
|
||||
q = q.GroupBy(q.Field("cpu_core_count"), q.Field("memory_size_mb"))
|
||||
q = q.Asc(q.Field("cpu_core_count"), q.Field("memory_size_mb"))
|
||||
err = q.All(&skus)
|
||||
err := q.All(&skus)
|
||||
if err != nil {
|
||||
log.Errorf("%s", err)
|
||||
return nil, httperrors.NewBadRequestError("instance specs list query error")
|
||||
@@ -255,13 +339,14 @@ func (self *SServerSku) ValidateUpdateData(
|
||||
data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
|
||||
if !inWhiteList(self.Provider) {
|
||||
return nil, httperrors.NewForbiddenError("can not create instance_type for public cloud %s", self.Provider)
|
||||
return nil, httperrors.NewForbiddenError("can not update instance_type for public cloud %s", self.Provider)
|
||||
}
|
||||
|
||||
provider, err := data.GetString("provider")
|
||||
if err == nil && !inWhiteList(provider) {
|
||||
return nil, httperrors.NewForbiddenError("can not create instance_type for public cloud %s", provider)
|
||||
return nil, httperrors.NewForbiddenError("can not update instance_type for public cloud %s", provider)
|
||||
}
|
||||
data.Remove("provider")
|
||||
|
||||
zoneStr := jsonutils.GetAnyString(data, []string{"zone", "zone_id"})
|
||||
if len(zoneStr) > 0 {
|
||||
@@ -274,6 +359,52 @@ func (self *SServerSku) ValidateUpdateData(
|
||||
}
|
||||
data.Add(jsonutils.NewString(zoneObj.GetId()), "zone_id")
|
||||
}
|
||||
|
||||
// name 由服务器端生成
|
||||
cpu, err := data.Int("cpu_core_count")
|
||||
if err != nil {
|
||||
cpu = int64(self.CpuCoreCount)
|
||||
}
|
||||
data.Set("cpu_core_count", jsonutils.NewInt(cpu))
|
||||
|
||||
mem, err := data.Int("memory_size_mb")
|
||||
if err != nil {
|
||||
mem = int64(self.MemorySizeMB)
|
||||
}
|
||||
data.Set("memory_size_mb", jsonutils.NewInt(mem))
|
||||
|
||||
category, err := data.GetString("instance_type_category")
|
||||
family := ""
|
||||
if err != nil {
|
||||
family = self.InstanceTypeFamily
|
||||
} else {
|
||||
f, exists := InstanceFamilies[category]
|
||||
if !exists {
|
||||
return nil, httperrors.NewInputParameterError("instance_type_category %s is invalid", category)
|
||||
}
|
||||
|
||||
family = f
|
||||
}
|
||||
|
||||
data.Set("instance_type_family", jsonutils.NewString(family))
|
||||
// 格式 ecs.g1.c1m1
|
||||
name, err := genInstanceType(family, cpu, mem)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError(err.Error())
|
||||
}
|
||||
|
||||
data.Set("name", jsonutils.NewString(name))
|
||||
|
||||
q := self.GetModelManager().Query()
|
||||
q = q.Equals("name", name).Filter(sqlchemy.OR(
|
||||
sqlchemy.IsNull(q.Field("provider")),
|
||||
sqlchemy.IsEmpty(q.Field("provider")),
|
||||
))
|
||||
|
||||
if q.Count() > 0 {
|
||||
return nil, httperrors.NewDuplicateResourceError("sku cpu %d mem %d(Mb) already exists", cpu, mem)
|
||||
}
|
||||
|
||||
return self.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
}
|
||||
|
||||
@@ -303,20 +434,18 @@ func (self *SServerSku) GetZoneExternalId() (string, error) {
|
||||
}
|
||||
|
||||
func (manager *SServerSkuManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
|
||||
queryDict := query.(*jsonutils.JSONDict)
|
||||
|
||||
provider := jsonutils.GetAnyString(query, []string{"provider"})
|
||||
if len(provider) > 0 {
|
||||
if provider != "all" {
|
||||
q = q.Equals("provider", provider)
|
||||
}
|
||||
|
||||
queryDict.Remove("provider")
|
||||
} else {
|
||||
queryDict := query.(*jsonutils.JSONDict)
|
||||
if provider == "" {
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.IsNull(q.Field("provider")),
|
||||
sqlchemy.IsEmpty(q.Field("provider")),
|
||||
))
|
||||
} else if provider == "all" {
|
||||
// provider 参数为all时。表示查询所有instance type.
|
||||
queryDict.Remove("provider")
|
||||
} else {
|
||||
q = q.Equals("provider", provider)
|
||||
}
|
||||
|
||||
q, err := manager.SStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
|
||||
@@ -336,8 +465,9 @@ func (manager *SServerSkuManager) ListItemFilter(ctx context.Context, q *sqlchem
|
||||
q = q.Equals("cloudregion_id", regionObj.GetId())
|
||||
}
|
||||
|
||||
// 当查询私有云时,需要忽略zone参数
|
||||
zoneStr := jsonutils.GetAnyString(query, []string{"zone", "zone_id"})
|
||||
if len(zoneStr) > 0 {
|
||||
if !inWhiteList(provider) && len(zoneStr) > 0 {
|
||||
zoneObj, err := ZoneManager.FetchByIdOrName(nil, zoneStr)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
@@ -346,6 +476,9 @@ func (manager *SServerSkuManager) ListItemFilter(ctx context.Context, q *sqlchem
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
q = q.Equals("zone_id", zoneObj.GetId())
|
||||
} else {
|
||||
queryDict.Remove("zone")
|
||||
queryDict.Remove("zone_id")
|
||||
}
|
||||
|
||||
return q, err
|
||||
|
||||
Reference in New Issue
Block a user