增加server sku资源,还需要和创建资源流程,以及公有云接口改造支持

This commit is contained in:
Qiu Jian
2018-11-07 15:47:46 +08:00
parent 223a126793
commit 4d43fcd39c
11 changed files with 464 additions and 19 deletions
+131
View File
@@ -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
})
}
+2
View File
@@ -74,6 +74,8 @@ func InitHandlers(app *appsrv.Application) {
models.SchedpolicyManager,
models.DynamicschedtagManager,
models.ServerSkuManager,
} {
db.RegisterModelManager(manager)
handler := db.NewModelHandler(manager)
+8 -6
View File
@@ -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"
+2
View File
@@ -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 {
+132
View File
@@ -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)
}
+8 -6
View File
@@ -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
+17
View File
@@ -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)
}
+2
View File
@@ -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
+7 -4
View File
@@ -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
}
+145
View File
@@ -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
}
+10 -3
View File
@@ -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"`