修复初次同步云账号内存为空的问题

This commit is contained in:
TangBin
2018-12-26 14:42:23 +08:00
parent bebde40ad0
commit dc8086ed90
6 changed files with 148 additions and 67 deletions
+94 -39
View File
@@ -26,6 +26,11 @@ const (
SkuCategoryHighMemory = "high_memory" // 高内存型
)
const (
SkuStatusAvailable = "available"
SkuStatusSoldout = "soldout"
)
var InstanceFamilies = map[string]string{
SkuCategoryGeneralPurpose: "g1",
SkuCategoryBurstable: "t1",
@@ -63,6 +68,9 @@ type SServerSku struct {
InstanceTypeFamily string `width:"32" charset:"ascii" nullable:"false" list:"user" create:"admin_optional" update:"admin"` // x2
InstanceTypeCategory string `width:"32" charset:"utf8" nullable:"false" list:"user" create:"admin_optional" update:"admin"` // 通用型
PrepaidStatus string `width:"32" charset:"utf8" nullable:"false" list:"user" create:"admin_optional" update:"admin" default:"available"` // 预付费资源状态 available|soldout
PostpaidStatus string `width:"32" charset:"utf8" nullable:"false" list:"user" create:"admin_optional" update:"admin" default:"available"` // 按需付费资源状态 available|soldout
CpuCoreCount int `nullable:"false" list:"user" create:"admin_required" update:"admin"`
MemorySizeMB int `nullable:"false" list:"user" create:"admin_required" update:"admin"`
@@ -351,50 +359,70 @@ 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)
// 可用资源状态
if postpaid, err := data.GetString("postpaid_status"); err != nil {
if postpaid == SkuStatusSoldout {
data.Set("postpaid_status", jsonutils.NewString(SkuStatusSoldout))
} else {
data.Set("postpaid_status", jsonutils.NewString(SkuStatusAvailable))
}
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())
prepaid, _ := data.GetString("prepaid_status")
if prepaid == SkuStatusSoldout {
data.Set("prepaid_status", jsonutils.NewString(SkuStatusSoldout))
} else {
data.Set("prepaid_status", jsonutils.NewString(SkuStatusAvailable))
}
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)
}
// 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))
// 暂时不允许修改CPU、MEM值
data.Remove("cpu_core_count")
data.Remove("memory_size_mb")
data.Remove("name")
// 暂时不允许修改CPU、MEM值
// 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)
}
@@ -404,6 +432,11 @@ func (self *SServerSku) AllowDeleteItem(ctx context.Context, userCred mcclient.T
}
func (self *SServerSku) ValidateDeleteCondition(ctx context.Context) error {
serverCount := GuestManager.Query().Equals("instance_type", self.Id).Limit(1).Count()
if serverCount > 0 {
return httperrors.NewForbiddenError("now allow to delete inuse instance_type.please remove related server: %s", self.Name)
}
if !inWhiteList(self.Provider) {
return httperrors.NewForbiddenError("not allow to delete public cloud instance_type: %s", self.Name)
}
@@ -456,6 +489,17 @@ func (manager *SServerSkuManager) ListItemFilter(ctx context.Context, q *sqlchem
q = q.Equals("cloudregion_id", regionObj.GetId())
}
// 可用资源状态
postpaid, _ := query.GetString("postpaid_status")
if len(postpaid) > 0 {
q.Equals("postpaid_status", postpaid)
}
prepaid, _ := query.GetString("prepaid_status")
if len(prepaid) > 0 {
q.Equals("prepaid_status", postpaid)
}
// 当查询私有云时,需要忽略zone参数
zoneStr := jsonutils.GetAnyString(query, []string{"zone", "zone_id"})
if !inWhiteList(provider) && len(zoneStr) > 0 {
@@ -530,6 +574,17 @@ func (manager *SServerSkuManager) GetSkuCountByProvider(provider string) int {
return q.Count()
}
func (manager *SServerSkuManager) GetSkuCountByRegion(regionId string) int {
q := manager.Query()
if len(regionId) == 0 {
q = q.IsNotEmpty("cloudregion_id")
} else {
q = q.Equals("cloudregion_id", regionId)
}
return q.Count()
}
// 删除表中zone not found的记录
func (manager *SServerSkuManager) PendingDeleteInvalidSku() error {
sq := ZoneManager.Query("id").Distinct().SubQuery()
+25 -8
View File
@@ -74,11 +74,7 @@ func processSkuData(ndata jsonutils.JSONObject) jsonutils.JSONObject {
}
// 处理os name
os_name, err := ndata.GetString("os_name")
if err != nil {
log.Debugf("no os name %s", ndata)
}
os_name, _ := ndata.GetString("os_name")
os_name = strings.ToLower(os_name)
if strings.Contains(os_name, "any") || strings.Contains(os_name, "na") || os_name == "" {
data.Set("os_name", jsonutils.NewString("Any"))
@@ -186,13 +182,11 @@ func (self *SkusZone) SyncToLocalDB() error {
log.Debugf("SyncToLocalDB zone %s name %s : %s", self.ZoneId, name, err.Error())
return err
}
data := models.SServerSku{}
if e := sku.Unmarshal(&data); e != nil {
log.Debugf("sku Unmarshal failed: %s, %s", sku, e.Error())
return e
}
if err := self.doCreate(data); err != nil {
return err
}
@@ -273,10 +267,14 @@ func (self *SkusZoneList) Refresh(providerIds *[]string) error {
}
}
self.refresh()
return nil
}
func (self *SkusZoneList) refresh() {
self.total = len(self.Data)
self.scuccesed = 0
self.failed = 0
return nil
}
func (self *SkusZoneList) SyncToLocalDB() error {
@@ -341,3 +339,22 @@ func SyncSkusByProviderIds(providerIds []string) error {
return nil
}
// 同步指定zone sku列表
func SyncSkusByRegion(region *models.SCloudregion) error {
skus := SkusZoneList{}
zones, err := models.ZoneManager.GetZonesByRegion(region)
if err != nil {
return err
}
log.Debugf("SyncSkusByRegion %s", region.GetName())
skus.initData(region.Provider, *region, zones)
skus.refresh()
if e := skus.SyncToLocalDB(); e != nil {
return fmt.Errorf("SyncSkus sync to local db failed, %s", e.Error())
}
return nil
}
@@ -7,7 +7,6 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/compute/skus"
)
type CloudAccountSyncInfoTask struct {
@@ -83,20 +82,6 @@ func (self *CloudAccountSyncInfoTask) OnCloudaccountSyncComplete(ctx context.Con
if account != nil {
account.SetStatus(self.UserCred, models.CLOUD_PROVIDER_CONNECTED, "")
}
if models.ServerSkuManager.GetSkuCountByProvider(cloudprovider.Provider) == 0 {
// sync skus
self.SetStage("OnSyncServerSkuComplete", nil)
taskman.LocalTaskRun(self, func() (jsonutils.JSONObject, error) {
err := skus.SyncSkusByProviderIds([]string{cloudprovider.Provider})
return nil, err
})
return
}
}
self.SetStageComplete(ctx, nil)
}
func (self *CloudAccountSyncInfoTask) OnSyncServerSkuComplete(ctx context.Context, items []db.IStandaloneModel, data jsonutils.JSONObject) {
self.SetStageComplete(ctx, nil)
}
@@ -10,6 +10,7 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/compute/skus"
"yunion.io/x/onecloud/pkg/util/logclient"
"yunion.io/x/pkg/utils"
)
@@ -124,6 +125,7 @@ func syncPublicCloudProviderInfo(ctx context.Context, provider *models.SCloudpro
localZones, remoteZones := syncRegionZones(ctx, provider, task, &localRegions[i], remoteRegions[i])
syncRegionSkus(ctx, provider, task, &localRegions[i])
syncRegionVPCs(ctx, provider, task, &localRegions[i], remoteRegions[i], syncRange)
if localZones != nil && remoteZones != nil {
@@ -140,6 +142,25 @@ func syncPublicCloudProviderInfo(ctx context.Context, provider *models.SCloudpro
}
}
func syncRegionSkus(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localRegion *models.SCloudregion) {
if localRegion == nil {
log.Debugf("local region is nil skipped.")
return
}
regionId := localRegion.GetId()
if len(regionId) > 0 && models.ServerSkuManager.GetSkuCountByRegion(regionId) == 0 {
// 提前同步instance type.如果同步失败可能导致vm 内存显示为0
if err := skus.SyncSkusByRegion(localRegion); err != nil {
msg := fmt.Sprintf("Get Skus for region %s failed %s", localRegion.GetName(), err)
log.Errorf(msg)
// 暂时不终止同步
// logSyncFailed(provider, task, msg)
return
}
}
}
func syncRegionSnapshots(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localRegion *models.SCloudregion, remoteRegion cloudprovider.ICloudRegion, syncRange *models.SSyncRange) {
snapshots, err := remoteRegion.GetISnapshots()
if err != nil {