mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
fix: missing instance type for cloned server
This commit is contained in:
+23
-13
@@ -765,19 +765,29 @@ func (o ServerDelExtraOptionInput) Validate() error {
|
||||
}
|
||||
|
||||
type ServerSnapshotAndCloneInput struct {
|
||||
Name string
|
||||
GenerateName string
|
||||
Count int
|
||||
AutoStart bool
|
||||
AutoDeleteInstanceSnapshot bool
|
||||
ServerCreateSnapshotParams
|
||||
|
||||
// number of cloned servers
|
||||
// 数量
|
||||
Count *int `json:"count"`
|
||||
|
||||
// Whether auto start the cloned server
|
||||
// 是否自动启动
|
||||
AutoStart *bool `json:"auto_start"`
|
||||
|
||||
// Whether delete instance snapshot automatically
|
||||
// 是否自动删除主机快照
|
||||
AutoDeleteInstanceSnapshot *bool `json:"auto_delete_instance_snapshot"`
|
||||
|
||||
// ignore
|
||||
InstanceSnapshotId string `json:"instance_snapshot_id"`
|
||||
}
|
||||
|
||||
func (o *ServerSnapshotAndCloneInput) Validate() error {
|
||||
if len(o.Name) == 0 {
|
||||
return httperrors.NewMissingParameterError("name")
|
||||
}
|
||||
if o.Count <= 1 {
|
||||
o.Count = 1
|
||||
}
|
||||
return nil
|
||||
type ServerInstanceSnapshot struct {
|
||||
ServerCreateSnapshotParams
|
||||
}
|
||||
|
||||
type ServerCreateSnapshotParams struct {
|
||||
Name string `json:"name"`
|
||||
GenerateName string `json:"generate_name"`
|
||||
}
|
||||
|
||||
+17
-11
@@ -1737,16 +1737,20 @@ func parseDiskInfo(ctx context.Context, userCred mcclient.TokenCredential, info
|
||||
return nil, errors.Wrap(err, "fillDiskConfigBySnapshot")
|
||||
}
|
||||
}
|
||||
if info.ImageId != "" {
|
||||
if err := fillDiskConfigByImage(ctx, userCred, info, info.ImageId); err != nil {
|
||||
return nil, errors.Wrap(err, "fillDiskConfigByImage")
|
||||
}
|
||||
}
|
||||
if info.BackupId != "" {
|
||||
if err := fillDiskConfigByBackup(ctx, userCred, info, info.BackupId); err != nil {
|
||||
return nil, errors.Wrap(err, "fillDiskConfigByBackup")
|
||||
}
|
||||
}
|
||||
if info.ImageId != "" {
|
||||
if err := fillDiskConfigByImage(ctx, userCred, info, info.ImageId); err != nil {
|
||||
if len(info.SnapshotId) == 0 && len(info.BackupId) == 0 {
|
||||
// return error only if no valid snapshotId and backId
|
||||
// otherwise, the disk was crated by snapshot or backup, not depends on vald image info
|
||||
return nil, errors.Wrap(err, "fillDiskConfigByImage")
|
||||
}
|
||||
}
|
||||
}
|
||||
// XXX: do not set default disk size here, set it by each hypervisor driver
|
||||
// if len(diskConfig.ImageId) > 0 && diskConfig.SizeMb == 0 {
|
||||
// diskConfig.SizeMb = options.Options.DefaultDiskSize // MB
|
||||
@@ -1914,6 +1918,14 @@ func parseIsoInfo(ctx context.Context, userCred mcclient.TokenCredential, imageI
|
||||
}
|
||||
|
||||
func (self *SDisk) fetchDiskInfo(diskConfig *api.DiskConfig) {
|
||||
if len(diskConfig.SnapshotId) > 0 {
|
||||
self.SnapshotId = diskConfig.SnapshotId
|
||||
self.DiskType = diskConfig.DiskType
|
||||
}
|
||||
if len(diskConfig.BackupId) > 0 {
|
||||
self.BackupId = diskConfig.BackupId
|
||||
self.DiskType = diskConfig.DiskType
|
||||
}
|
||||
if len(diskConfig.ImageId) > 0 {
|
||||
self.TemplateId = diskConfig.ImageId
|
||||
// support for create vm from guest image
|
||||
@@ -1922,12 +1934,6 @@ func (self *SDisk) fetchDiskInfo(diskConfig *api.DiskConfig) {
|
||||
} else {
|
||||
self.DiskType = diskConfig.DiskType
|
||||
}
|
||||
} else if len(diskConfig.SnapshotId) > 0 {
|
||||
self.SnapshotId = diskConfig.SnapshotId
|
||||
self.DiskType = diskConfig.DiskType
|
||||
} else if len(diskConfig.BackupId) > 0 {
|
||||
self.BackupId = diskConfig.BackupId
|
||||
self.DiskType = diskConfig.DiskType
|
||||
}
|
||||
if len(diskConfig.Fs) > 0 {
|
||||
self.FsFormat = diskConfig.Fs
|
||||
|
||||
@@ -4569,38 +4569,37 @@ func (self *SGuest) validateCreateInstanceSnapshot(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
data jsonutils.JSONObject,
|
||||
) (*SRegionQuota, error) {
|
||||
input api.ServerCreateSnapshotParams,
|
||||
) (*SRegionQuota, api.ServerCreateSnapshotParams, error) {
|
||||
|
||||
if !utils.IsInStringArray(self.Hypervisor, supportInstanceSnapshotHypervisors) {
|
||||
return nil, httperrors.NewBadRequestError("guest hypervisor %s can't create instance snapshot", self.Hypervisor)
|
||||
return nil, input, httperrors.NewBadRequestError("guest hypervisor %s can't create instance snapshot", self.Hypervisor)
|
||||
}
|
||||
|
||||
if len(self.BackupHostId) > 0 {
|
||||
return nil, httperrors.NewBadRequestError("Can't do instance snapshot with backup guest")
|
||||
return nil, input, httperrors.NewBadRequestError("Can't do instance snapshot with backup guest")
|
||||
}
|
||||
|
||||
if !utils.IsInStringArray(self.Status, []string{api.VM_RUNNING, api.VM_READY}) {
|
||||
return nil, httperrors.NewInvalidStatusError("guest can't do snapshot in status %s", self.Status)
|
||||
return nil, input, httperrors.NewInvalidStatusError("guest can't do snapshot in status %s", self.Status)
|
||||
}
|
||||
|
||||
var name string
|
||||
ownerId := self.GetOwnerId()
|
||||
dataDict := data.(*jsonutils.JSONDict)
|
||||
nameHint, err := dataDict.GetString("generate_name")
|
||||
if err == nil {
|
||||
name, err = db.GenerateName(ctx, InstanceSnapshotManager, ownerId, nameHint)
|
||||
// dataDict := data.(*jsonutils.JSONDict)
|
||||
// nameHint, err := dataDict.GetString("generate_name")
|
||||
if len(input.GenerateName) > 0 {
|
||||
name, err := db.GenerateName(ctx, InstanceSnapshotManager, ownerId, input.GenerateName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, input, errors.Wrap(err, "GenerateName")
|
||||
}
|
||||
dataDict.Set("name", jsonutils.NewString(name))
|
||||
} else if name, err = dataDict.GetString("name"); err != nil {
|
||||
return nil, httperrors.NewMissingParameterError("name")
|
||||
input.Name = name
|
||||
} else if len(input.Name) == 0 {
|
||||
return nil, input, httperrors.NewMissingParameterError("name")
|
||||
}
|
||||
|
||||
err = db.NewNameValidator(InstanceSnapshotManager, ownerId, name, nil)
|
||||
err := db.NewNameValidator(InstanceSnapshotManager, ownerId, input.Name, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, input, errors.Wrap(err, "NewNameValidator")
|
||||
}
|
||||
|
||||
// construct Quota
|
||||
@@ -4610,16 +4609,16 @@ func (self *SGuest) validateCreateInstanceSnapshot(
|
||||
if utils.IsInStringArray(provider, ProviderHasSubSnapshot) {
|
||||
disks, err := self.GetDisks()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetDisks")
|
||||
return nil, input, errors.Wrapf(err, "GetDisks")
|
||||
}
|
||||
for i := 0; i < len(disks); i++ {
|
||||
if storage, _ := disks[i].GetStorage(); utils.IsInStringArray(storage.StorageType, api.FIEL_STORAGE) {
|
||||
count, err := SnapshotManager.GetDiskManualSnapshotCount(disks[i].Id)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInternalServerError("%v", err)
|
||||
return nil, input, httperrors.NewInternalServerError("%v", err)
|
||||
}
|
||||
if count >= options.Options.DefaultMaxManualSnapshotCount {
|
||||
return nil, httperrors.NewBadRequestError("guests disk %d snapshot full, can't take anymore", i)
|
||||
return nil, input, httperrors.NewBadRequestError("guests disk %d snapshot full, can't take anymore", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4627,14 +4626,14 @@ func (self *SGuest) validateCreateInstanceSnapshot(
|
||||
}
|
||||
keys, err := self.GetRegionalQuotaKeys()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, input, errors.Wrap(err, "GetRegionalQuotaKeys")
|
||||
}
|
||||
pendingUsage.SetKeys(keys)
|
||||
err = quotas.CheckSetPendingQuota(ctx, userCred, pendingUsage)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewOutOfQuotaError("Check set pending quota error %s", err)
|
||||
return nil, input, httperrors.NewOutOfQuotaError("Check set pending quota error %s", err)
|
||||
}
|
||||
return pendingUsage, nil
|
||||
return pendingUsage, input, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) validateCreateInstanceBackup(
|
||||
@@ -4680,16 +4679,16 @@ func (self *SGuest) validateCreateInstanceBackup(
|
||||
// 2. validate every disk manual snapshot count
|
||||
// 3. validate snapshot quota with disk count
|
||||
func (self *SGuest) PerformInstanceSnapshot(
|
||||
ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject,
|
||||
ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.ServerInstanceSnapshot,
|
||||
) (jsonutils.JSONObject, error) {
|
||||
lockman.LockClass(ctx, InstanceSnapshotManager, userCred.GetProjectId())
|
||||
defer lockman.ReleaseClass(ctx, InstanceSnapshotManager, userCred.GetProjectId())
|
||||
pendingUsage, err := self.validateCreateInstanceSnapshot(ctx, userCred, query, data)
|
||||
pendingUsage, params, err := self.validateCreateInstanceSnapshot(ctx, userCred, query, input.ServerCreateSnapshotParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "validateCreateInstanceSnapshot")
|
||||
}
|
||||
name, _ := data.GetString("name")
|
||||
instanceSnapshot, err := InstanceSnapshotManager.CreateInstanceSnapshot(ctx, userCred, self, name, false)
|
||||
input.ServerCreateSnapshotParams = params
|
||||
instanceSnapshot, err := InstanceSnapshotManager.CreateInstanceSnapshot(ctx, userCred, self, input.Name, false)
|
||||
if err != nil {
|
||||
quotas.CancelPendingUsage(
|
||||
ctx, userCred, pendingUsage, pendingUsage, false)
|
||||
@@ -4790,27 +4789,35 @@ func (self *SGuest) StartSnapshotResetTask(ctx context.Context, userCred mcclien
|
||||
}
|
||||
|
||||
func (self *SGuest) PerformSnapshotAndClone(
|
||||
ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input *api.ServerSnapshotAndCloneInput,
|
||||
ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.ServerSnapshotAndCloneInput,
|
||||
) (jsonutils.JSONObject, error) {
|
||||
err := input.Validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
newlyGuestName := input.Name
|
||||
if len(input.Name) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("name")
|
||||
}
|
||||
count := 1
|
||||
if input.Count != nil {
|
||||
count = *input.Count
|
||||
if count <= 0 {
|
||||
return nil, httperrors.NewInputParameterError("count must > 0")
|
||||
}
|
||||
}
|
||||
|
||||
lockman.LockRawObject(ctx, InstanceSnapshotManager.Keyword(), "name")
|
||||
defer lockman.ReleaseRawObject(ctx, InstanceSnapshotManager.Keyword(), "name")
|
||||
|
||||
// validate create instance snapshot and set snapshot pending usage
|
||||
snapshotUsage, err := self.validateCreateInstanceSnapshot(ctx, userCred, query, jsonutils.Marshal(input))
|
||||
snapshotUsage, params, err := self.validateCreateInstanceSnapshot(ctx, userCred, query, input.ServerCreateSnapshotParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "validateCreateInstanceSnapshot")
|
||||
}
|
||||
input.ServerCreateSnapshotParams = params
|
||||
// set guest pending usage
|
||||
pendingUsage, pendingRegionUsage, err := self.getGuestUsage(input.Count)
|
||||
pendingUsage, pendingRegionUsage, err := self.getGuestUsage(count)
|
||||
keys, err := self.GetQuotaKeys()
|
||||
if err != nil {
|
||||
quotas.CancelPendingUsage(ctx, userCred, snapshotUsage, snapshotUsage, false)
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "GetQuotaKeys")
|
||||
}
|
||||
pendingUsage.SetKeys(keys)
|
||||
err = quotas.CheckSetPendingQuota(ctx, userCred, &pendingUsage)
|
||||
@@ -4822,14 +4829,14 @@ func (self *SGuest) PerformSnapshotAndClone(
|
||||
if err != nil {
|
||||
quotas.CancelPendingUsage(ctx, userCred, snapshotUsage, snapshotUsage, false)
|
||||
quotas.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage, false)
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "GetRegionalQuotaKeys")
|
||||
}
|
||||
pendingRegionUsage.SetKeys(regionKeys)
|
||||
err = quotas.CheckSetPendingQuota(ctx, userCred, &pendingRegionUsage)
|
||||
if err != nil {
|
||||
quotas.CancelPendingUsage(ctx, userCred, snapshotUsage, snapshotUsage, false)
|
||||
quotas.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage, false)
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "CheckSetPendingQuota")
|
||||
}
|
||||
// migrate snapshotUsage into regionUsage, then discard snapshotUsage
|
||||
pendingRegionUsage.Snapshot = snapshotUsage.Snapshot
|
||||
@@ -4843,7 +4850,7 @@ func (self *SGuest) PerformSnapshotAndClone(
|
||||
}
|
||||
instanceSnapshot, err := InstanceSnapshotManager.CreateInstanceSnapshot(
|
||||
ctx, userCred, self, instanceSnapshotName,
|
||||
input.AutoDeleteInstanceSnapshot)
|
||||
input.AutoDeleteInstanceSnapshot != nil && *input.AutoDeleteInstanceSnapshot)
|
||||
if err != nil {
|
||||
quotas.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage, false)
|
||||
quotas.CancelPendingUsage(ctx, userCred, &pendingRegionUsage, &pendingRegionUsage, false)
|
||||
@@ -4854,7 +4861,7 @@ func (self *SGuest) PerformSnapshotAndClone(
|
||||
}
|
||||
|
||||
err = self.StartInstanceSnapshotAndCloneTask(
|
||||
ctx, userCred, input.Name, &pendingUsage, &pendingRegionUsage, instanceSnapshot, jsonutils.Marshal(input).(*jsonutils.JSONDict))
|
||||
ctx, userCred, newlyGuestName, &pendingUsage, &pendingRegionUsage, instanceSnapshot, input)
|
||||
if err != nil {
|
||||
quotas.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage, false)
|
||||
quotas.CancelPendingUsage(ctx, userCred, &pendingRegionUsage, &pendingRegionUsage, false)
|
||||
@@ -4865,10 +4872,11 @@ func (self *SGuest) PerformSnapshotAndClone(
|
||||
|
||||
func (self *SGuest) StartInstanceSnapshotAndCloneTask(
|
||||
ctx context.Context, userCred mcclient.TokenCredential, newlyGuestName string,
|
||||
pendingUsage *SQuota, pendingRegionUsage *SRegionQuota, instanceSnapshot *SInstanceSnapshot, data *jsonutils.JSONDict) error {
|
||||
|
||||
pendingUsage *SQuota, pendingRegionUsage *SRegionQuota, instanceSnapshot *SInstanceSnapshot,
|
||||
input api.ServerSnapshotAndCloneInput,
|
||||
) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("guest_params", data)
|
||||
params.Set("guest_params", jsonutils.Marshal(input))
|
||||
if task, err := taskman.TaskManager.NewTask(
|
||||
ctx, "InstanceSnapshotAndCloneTask", instanceSnapshot, userCred, params, "", "", pendingUsage, pendingRegionUsage); err != nil {
|
||||
return err
|
||||
@@ -4880,24 +4888,24 @@ func (self *SGuest) StartInstanceSnapshotAndCloneTask(
|
||||
}
|
||||
|
||||
func (manager *SGuestManager) CreateGuestFromInstanceSnapshot(
|
||||
ctx context.Context, userCred mcclient.TokenCredential, guestParams *jsonutils.JSONDict, isp *SInstanceSnapshot,
|
||||
ctx context.Context, userCred mcclient.TokenCredential, input api.ServerSnapshotAndCloneInput, isp *SInstanceSnapshot,
|
||||
) (*SGuest, *jsonutils.JSONDict, error) {
|
||||
lockman.LockRawObject(ctx, manager.Keyword(), "name")
|
||||
defer lockman.ReleaseRawObject(ctx, manager.Keyword(), "name")
|
||||
|
||||
guestName, err := guestParams.GetString("name")
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("No new guest name provider")
|
||||
}
|
||||
if guestName, err = db.GenerateName(ctx, manager, isp.GetOwnerId(), guestName); err != nil {
|
||||
return nil, nil, err
|
||||
if guestName, err := db.GenerateName(ctx, manager, isp.GetOwnerId(), input.Name); err != nil {
|
||||
return nil, nil, errors.Wrap(err, "db.GenerateName")
|
||||
} else {
|
||||
input.Name = guestName
|
||||
}
|
||||
|
||||
guestParams.Set("name", jsonutils.NewString(guestName))
|
||||
guestParams.Set("instance_snapshot_id", jsonutils.NewString(isp.Id))
|
||||
iGuest, err := db.DoCreate(manager, ctx, userCred, nil, guestParams, isp.GetOwnerId())
|
||||
input.InstanceSnapshotId = isp.Id
|
||||
|
||||
params := jsonutils.Marshal(input).(*jsonutils.JSONDict)
|
||||
|
||||
iGuest, err := db.DoCreate(manager, ctx, userCred, nil, params, isp.GetOwnerId())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, errors.Wrap(err, "db.DoCreate")
|
||||
}
|
||||
guest := iGuest.(*SGuest)
|
||||
notes := map[string]string{
|
||||
@@ -4910,10 +4918,10 @@ func (manager *SGuestManager) CreateGuestFromInstanceSnapshot(
|
||||
lockman.LockObject(ctx, guest)
|
||||
defer lockman.ReleaseObject(ctx, guest)
|
||||
|
||||
guest.PostCreate(ctx, userCred, guest.GetOwnerId(), nil, guestParams)
|
||||
guest.PostCreate(ctx, userCred, guest.GetOwnerId(), nil, params)
|
||||
}()
|
||||
|
||||
return guest, guestParams, nil
|
||||
return guest, params, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) GetDetailsJnlp(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
|
||||
@@ -1178,10 +1178,10 @@ func (manager *SGuestManager) validateCreateData(
|
||||
if inputMem > 0 {
|
||||
input.VcpuCount = inputCpu
|
||||
}
|
||||
input.InstanceType = inputInstaceType
|
||||
}
|
||||
|
||||
if len(input.InstanceBackupId) > 0 {
|
||||
if len(inputInstaceType) > 0 {
|
||||
input.InstanceType = inputInstaceType
|
||||
}
|
||||
} else if len(input.InstanceBackupId) > 0 {
|
||||
inputMem := input.VmemSize
|
||||
inputCpu := input.VcpuCount
|
||||
inputInstaceType := input.InstanceType
|
||||
@@ -1196,7 +1196,9 @@ func (manager *SGuestManager) validateCreateData(
|
||||
if inputMem > 0 {
|
||||
input.VcpuCount = inputCpu
|
||||
}
|
||||
input.InstanceType = inputInstaceType
|
||||
if len(inputInstaceType) > 0 {
|
||||
input.InstanceType = inputInstaceType
|
||||
}
|
||||
}
|
||||
|
||||
resetPassword := true
|
||||
|
||||
@@ -77,6 +77,8 @@ type SInstanceSnapshot struct {
|
||||
InstanceType string `width:"64" charset:"utf8" nullable:"true" list:"user" create:"optional"`
|
||||
// 主机快照磁盘容量和
|
||||
SizeMb int `nullable:"false"`
|
||||
// 镜像ID
|
||||
ImageId string `width:"36" charset:"ascii" nullable:"true" list:"user"`
|
||||
}
|
||||
|
||||
type SInstanceSnapshotManager struct {
|
||||
@@ -291,6 +293,9 @@ func (manager *SInstanceSnapshotManager) fillInstanceSnapshot(ctx context.Contex
|
||||
instanceSnapshot.ProjectId = guest.ProjectId
|
||||
instanceSnapshot.DomainId = guest.DomainId
|
||||
instanceSnapshot.GuestId = guest.Id
|
||||
instanceSnapshot.InstanceType = guest.InstanceType
|
||||
instanceSnapshot.ImageId = guest.GetTemplateId()
|
||||
|
||||
guestSchedInput := guest.ToSchedDesc()
|
||||
|
||||
host, _ := guest.GetHost()
|
||||
@@ -312,7 +317,10 @@ func (manager *SInstanceSnapshotManager) fillInstanceSnapshot(ctx context.Contex
|
||||
}
|
||||
instanceSnapshot.ServerConfig = jsonutils.Marshal(guestSchedInput.ServerConfig)
|
||||
if len(guest.KeypairId) > 0 {
|
||||
instanceSnapshot.KeypairId = guest.KeypairId
|
||||
keypair, _ := KeypairManager.FetchById(guest.KeypairId)
|
||||
if keypair != nil {
|
||||
instanceSnapshot.KeypairId = guest.KeypairId
|
||||
}
|
||||
}
|
||||
serverMetadata := jsonutils.NewDict()
|
||||
if loginAccount := guest.GetMetadata(ctx, "login_account", nil); len(loginAccount) > 0 {
|
||||
@@ -351,7 +359,6 @@ func (manager *SInstanceSnapshotManager) fillInstanceSnapshot(ctx context.Contex
|
||||
instanceSnapshot.OsType = guest.OsType
|
||||
instanceSnapshot.OsArch = guest.OsArch
|
||||
instanceSnapshot.ServerMetadata = serverMetadata
|
||||
instanceSnapshot.InstanceType = guest.InstanceType
|
||||
}
|
||||
|
||||
func (manager *SInstanceSnapshotManager) CreateInstanceSnapshot(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, name string, autoDelete bool) (*SInstanceSnapshot, error) {
|
||||
@@ -397,6 +404,10 @@ func (self *SInstanceSnapshot) ToInstanceCreateInput(
|
||||
index := serverConfig.Disks[i].Index
|
||||
if index < len(isjs) {
|
||||
serverConfig.Disks[i].SnapshotId = isjs[index].SnapshotId
|
||||
if i == 0 && len(self.ImageId) > 0 {
|
||||
// system disk, save ImageId
|
||||
serverConfig.Disks[i].ImageId = self.ImageId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,8 @@ func (self *DiskCreateTask) OnInit(ctx context.Context, obj db.IStandaloneModel,
|
||||
storage, _ := disk.GetStorage()
|
||||
storagecache := storage.GetStoragecache()
|
||||
imageId := disk.GetTemplateId()
|
||||
if len(imageId) > 0 {
|
||||
// use image only if disk not created from snapshot or backup
|
||||
if len(imageId) > 0 && len(disk.SnapshotId) == 0 && len(disk.BackupId) == 0 {
|
||||
self.SetStage("OnStorageCacheImageComplete", nil)
|
||||
input := api.CacheImageInput{
|
||||
ImageId: imageId,
|
||||
|
||||
@@ -93,16 +93,20 @@ func (self *InstanceSnapshotAndCloneTask) OnInit(
|
||||
func (self *InstanceSnapshotAndCloneTask) OnCreateInstanceSnapshot(
|
||||
ctx context.Context, isp *models.SInstanceSnapshot, data jsonutils.JSONObject) {
|
||||
// start create server
|
||||
params, err := self.Params.Get("guest_params")
|
||||
var input compute.ServerSnapshotAndCloneInput
|
||||
err := self.Params.Unmarshal(&input, "guest_params")
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, isp, jsonutils.NewString("Failed get new guest params"))
|
||||
return
|
||||
}
|
||||
count, _ := params.Int("count")
|
||||
count := 0
|
||||
if input.Count != nil {
|
||||
count = *input.Count
|
||||
}
|
||||
if count == 0 {
|
||||
count = 1
|
||||
}
|
||||
err = self.doGuestCreate(ctx, isp, params, int(count))
|
||||
err = self.doGuestCreate(ctx, isp, input, count)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, isp, jsonutils.NewString(err.Error()))
|
||||
return
|
||||
@@ -111,22 +115,21 @@ func (self *InstanceSnapshotAndCloneTask) OnCreateInstanceSnapshot(
|
||||
}
|
||||
|
||||
func (self *InstanceSnapshotAndCloneTask) doGuestCreate(
|
||||
ctx context.Context, isp *models.SInstanceSnapshot, params jsonutils.JSONObject, count int) error {
|
||||
ctx context.Context, isp *models.SInstanceSnapshot, cloneInput compute.ServerSnapshotAndCloneInput, count int) error {
|
||||
|
||||
var (
|
||||
dictParmas = params.(*jsonutils.JSONDict)
|
||||
errStr string
|
||||
errStr string
|
||||
)
|
||||
for i := 0; i < count; i++ {
|
||||
newGuest, input, err := models.GuestManager.CreateGuestFromInstanceSnapshot(
|
||||
ctx, self.UserCred, dictParmas.DeepCopy().(*jsonutils.JSONDict), isp)
|
||||
newGuest, params, err := models.GuestManager.CreateGuestFromInstanceSnapshot(
|
||||
ctx, self.UserCred, cloneInput, isp)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
errStr += err.Error() + "\n"
|
||||
continue
|
||||
}
|
||||
isp.AddRefCount(ctx)
|
||||
models.GuestManager.OnCreateComplete(ctx, []db.IModel{newGuest}, self.UserCred, self.UserCred, nil, input)
|
||||
models.GuestManager.OnCreateComplete(ctx, []db.IModel{newGuest}, self.UserCred, self.UserCred, nil, params)
|
||||
}
|
||||
if len(errStr) > 0 {
|
||||
return fmt.Errorf(errStr)
|
||||
|
||||
Reference in New Issue
Block a user