mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
Automatic merge from release/2.4.0 -> release/2.5.0
* commit 'f9202677218c02f3f5e7683a7ccab25c1db2d7db': host-list增加mem_cmtbound disk add allowdeleteitem 修正:1. 删除伪删除主机、磁盘需要override-pending-delete参数 2. joint-update支持auto_create参数 3. 删除主机时候detach磁盘,清理安全组
This commit is contained in:
@@ -206,6 +206,11 @@ func (dispatcher *DBJointModelDispatcher) Update(ctx context.Context, id1 string
|
||||
userCred := fetchUserCredential(ctx)
|
||||
master, slave, item, err := fetchJointItem(dispatcher, ctx, userCred, id1, id2, query)
|
||||
if err == sql.ErrNoRows {
|
||||
if jsonutils.QueryBoolean(query, "auto_create", false) {
|
||||
queryDict := query.(*jsonutils.JSONDict)
|
||||
queryDict.Remove("auto_create")
|
||||
return dispatcher.Attach(ctx, id1, id2, query, data)
|
||||
}
|
||||
return nil, httperrors.NewResourceNotFoundError2(dispatcher.modelManager.Keyword(), id1+"-"+id2)
|
||||
} else if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
|
||||
@@ -790,6 +790,19 @@ func (self *SDisk) validateDeleteCondition(ctx context.Context, isPurge bool) er
|
||||
return self.SSharableVirtualResourceBase.ValidateDeleteCondition(ctx)
|
||||
}
|
||||
|
||||
func (self *SDisk) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
overridePendingDelete := false
|
||||
purge := false
|
||||
if query != nil {
|
||||
overridePendingDelete = jsonutils.QueryBoolean(query, "override_pending_delete", false)
|
||||
purge = jsonutils.QueryBoolean(query, "purge", false)
|
||||
}
|
||||
if (overridePendingDelete || purge) && !db.IsAdminAllowDelete(userCred, self) {
|
||||
return false
|
||||
}
|
||||
return self.IsOwner(userCred) || db.IsAdminAllowDelete(userCred, self)
|
||||
}
|
||||
|
||||
func (self *SDisk) GetTemplateId() string {
|
||||
return self.TemplateId
|
||||
}
|
||||
@@ -1615,3 +1628,23 @@ func (self *SDisk) SaveRenewInfo(ctx context.Context, userCred mcclient.TokenCre
|
||||
db.OpsLog.LogEvent(self, db.ACT_RENEW, self.GetShortDesc(ctx), userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SDisk) IsDetachable() bool {
|
||||
storage := self.GetStorage()
|
||||
if storage == nil {
|
||||
return true
|
||||
}
|
||||
if storage.IsLocal() {
|
||||
return false
|
||||
}
|
||||
if self.BillingType == BILLING_TYPE_PREPAID {
|
||||
return false
|
||||
}
|
||||
if utils.IsInStringArray(self.DiskType, []string{DISK_TYPE_SYS, DISK_TYPE_SWAP}) {
|
||||
return false
|
||||
}
|
||||
if self.AutoDelete {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -129,6 +129,9 @@ func (self *SGuest) AllowPerformSync(ctx context.Context, userCred mcclient.Toke
|
||||
}
|
||||
|
||||
func (self *SGuest) PerformSync(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if !utils.IsInStringArray(self.Status, []string{VM_READY, VM_RUNNING}) {
|
||||
return nil, httperrors.NewResourceBusyError("Cannot sync in status %s", self.Status)
|
||||
}
|
||||
if err := self.StartSyncTask(ctx, userCred, false, ""); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -424,9 +427,7 @@ func (self *SGuest) PerformAttachdisk(ctx context.Context, userCred mcclient.Tok
|
||||
}
|
||||
|
||||
func (self *SGuest) StartSyncTask(ctx context.Context, userCred mcclient.TokenCredential, fw_only bool, parentTaskId string) error {
|
||||
if !utils.IsInStringArray(self.Status, []string{VM_READY, VM_RUNNING}) {
|
||||
return httperrors.NewResourceBusyError("Cannot sync in status %s", self.Status)
|
||||
}
|
||||
|
||||
data := jsonutils.NewDict()
|
||||
if fw_only {
|
||||
data.Add(jsonutils.JSONTrue, "fw_only")
|
||||
@@ -848,7 +849,7 @@ func (self *SGuest) PerformSetSecgroup(ctx context.Context, userCred mcclient.To
|
||||
setSecgroupNames = append(setSecgroupNames, secgrp.GetName())
|
||||
}
|
||||
|
||||
if err := self.revokeAllSecgroups(ctx, userCred); err != nil {
|
||||
if err := self.RevokeAllSecgroups(ctx, userCred); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1125,14 +1126,8 @@ func (self *SGuest) PerformDetachdisk(ctx context.Context, userCred mcclient.Tok
|
||||
return nil, httperrors.NewInputParameterError("Cannot keep detached disk")
|
||||
}
|
||||
if utils.IsInStringArray(self.Status, detachDiskStatus) {
|
||||
if disk.Status == DISK_INIT {
|
||||
disk.SetStatus(userCred, DISK_DETACHING, "")
|
||||
}
|
||||
taskData := jsonutils.NewDict()
|
||||
taskData.Add(jsonutils.NewString(disk.Id), "disk_id")
|
||||
taskData.Add(jsonutils.NewBool(keepDisk), "keep_disk")
|
||||
self.GetDriver().StartGuestDetachdiskTask(ctx, userCred, self, taskData, "")
|
||||
return nil, nil
|
||||
err = self.StartGuestDetachdiskTask(ctx, userCred, disk, keepDisk, "")
|
||||
return nil, err
|
||||
} else {
|
||||
return nil, httperrors.NewInvalidStatusError("Server in %s not able to detach disk", self.Status)
|
||||
}
|
||||
@@ -1143,6 +1138,16 @@ func (self *SGuest) PerformDetachdisk(ctx context.Context, userCred mcclient.Tok
|
||||
return nil, httperrors.NewResourceNotFoundError("Disk %s not found", diskId)
|
||||
}
|
||||
|
||||
func (self *SGuest) StartGuestDetachdiskTask(ctx context.Context, userCred mcclient.TokenCredential, disk *SDisk, keepDisk bool, parentTaskId string) error {
|
||||
if disk.Status == DISK_INIT {
|
||||
disk.SetStatus(userCred, DISK_DETACHING, "")
|
||||
}
|
||||
taskData := jsonutils.NewDict()
|
||||
taskData.Add(jsonutils.NewString(disk.Id), "disk_id")
|
||||
taskData.Add(jsonutils.NewBool(keepDisk), "keep_disk")
|
||||
return self.GetDriver().StartGuestDetachdiskTask(ctx, userCred, self, taskData, "")
|
||||
}
|
||||
|
||||
func (self *SGuest) AllowPerformDetachIsolatedDevice(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "detach-isolated-device")
|
||||
}
|
||||
@@ -1528,12 +1533,12 @@ func (self *SGuest) StartChangeConfigTask(ctx context.Context, userCred mcclient
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) revokeAllSecgroups(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
err := self.revokeSecgroup(ctx, userCred, self.getSecgroup())
|
||||
func (self *SGuest) RevokeAllSecgroups(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
err := GuestsecgroupManager.DeleteGuestSecgroup(ctx, userCred, self, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = GuestsecgroupManager.DeleteGuestSecgroup(ctx, userCred, self, nil)
|
||||
err = self.revokeSecgroup(ctx, userCred, self.getSecgroup())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1545,16 +1550,13 @@ func (self *SGuest) DoPendingDelete(ctx context.Context, userCred mcclient.Token
|
||||
if eip != nil {
|
||||
eip.DoPendingDelete(ctx, userCred)
|
||||
}
|
||||
// revoke all secgroups
|
||||
// TODO: sync revoked secgroups to remote cloud
|
||||
self.revokeAllSecgroups(ctx, userCred)
|
||||
// remove detachable disks
|
||||
|
||||
for _, guestdisk := range self.GetDisks() {
|
||||
disk := guestdisk.GetDisk()
|
||||
storage := disk.GetStorage()
|
||||
if storage.IsLocal() || disk.BillingType == BILLING_TYPE_PREPAID || utils.IsInStringArray(disk.DiskType, []string{DISK_TYPE_SYS, DISK_TYPE_SWAP}) || (utils.IsInStringArray(self.Hypervisor, PUBLIC_CLOUD_HYPERVISORS) && disk.AutoDelete) {
|
||||
if !disk.IsDetachable() {
|
||||
disk.DoPendingDelete(ctx, userCred)
|
||||
} else {
|
||||
log.Warningf("detachable disk on pending delete guests!!! should be removed earlier")
|
||||
self.DetachDisk(ctx, disk, userCred)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2638,9 +2638,9 @@ func (self *SGuest) RealDelete(ctx context.Context, userCred mcclient.TokenCrede
|
||||
func (self *SGuest) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
overridePendingDelete := false
|
||||
purge := false
|
||||
if data != nil {
|
||||
overridePendingDelete = jsonutils.QueryBoolean(data, "override_pending_delete", false)
|
||||
purge = jsonutils.QueryBoolean(data, "purge", false)
|
||||
if query != nil {
|
||||
overridePendingDelete = jsonutils.QueryBoolean(query, "override_pending_delete", false)
|
||||
purge = jsonutils.QueryBoolean(query, "purge", false)
|
||||
}
|
||||
if (overridePendingDelete || purge) && !db.IsAdminAllowDelete(userCred, self) {
|
||||
return false
|
||||
|
||||
@@ -140,9 +140,9 @@ type SHost struct {
|
||||
CpuReserved int8 `nullable:"true" default:"0" list:"admin" update:"admin" create:"admin_optional"` // Column(TINYINT, nullable=True, default=0)
|
||||
CpuCmtbound float32 `nullable:"true" default:"8.0" list:"admin" update:"admin" create:"admin_optional"` // = Column(Float, nullable=True)
|
||||
|
||||
MemSize int `nullable:"true" list:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True) # memory size in MB
|
||||
MemReserved int `nullable:"true" default:"0" list:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True, default=0) # memory reserved in MB
|
||||
MemCmtbound float32 `nullable:"true" default:"1.0" update:"admin" create:"admin_optional"` // = Column(Float, nullable=True)
|
||||
MemSize int `nullable:"true" list:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True) # memory size in MB
|
||||
MemReserved int `nullable:"true" default:"0" list:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True, default=0) # memory reserved in MB
|
||||
MemCmtbound float32 `nullable:"true" default:"1.0" list:"admin" update:"admin" create:"admin_optional"` // = Column(Float, nullable=True)
|
||||
|
||||
StorageSize int `nullable:"true" list:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True) # storage size in MB
|
||||
StorageType string `width:"20" charset:"ascii" nullable:"true" list:"admin" update:"admin" create:"admin_optional"` // Column(VARCHAR(20, charset='ascii'), nullable=True)
|
||||
|
||||
@@ -29,7 +29,14 @@ func (self *DiskDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel,
|
||||
db.OpsLog.LogEvent(disk, db.ACT_DELOCATE_FAIL, reason, self.UserCred)
|
||||
return
|
||||
}
|
||||
if options.Options.EnablePendingDelete && !disk.PendingDeleted && !jsonutils.QueryBoolean(self.Params, "purge", false) && !jsonutils.QueryBoolean(self.Params, "override_pending_delete", false) {
|
||||
|
||||
isPurge := jsonutils.QueryBoolean(self.Params, "purge", false)
|
||||
overridePendingDelete := jsonutils.QueryBoolean(self.Params, "override_pending_delete", false)
|
||||
if options.Options.EnablePendingDelete && !isPurge && !overridePendingDelete {
|
||||
if disk.PendingDeleted {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
return
|
||||
}
|
||||
self.startPendingDeleteDisk(ctx, disk)
|
||||
} else {
|
||||
self.startDeleteDisk(ctx, disk)
|
||||
|
||||
@@ -80,20 +80,69 @@ func (self *GuestDeleteTask) OnGuestStopComplete(ctx context.Context, obj db.ISt
|
||||
}
|
||||
}
|
||||
|
||||
func (self *GuestDeleteTask) OnGuestStopCompleteFailed(ctx context.Context, obj db.IStandaloneModel, err jsonutils.JSONObject) {
|
||||
self.OnGuestStopComplete(ctx, obj, err) // ignore stop error
|
||||
}
|
||||
|
||||
func (self *GuestDeleteTask) OnEipDissociateCompleteFailed(ctx context.Context, obj db.IStandaloneModel, err jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
self.OnFailed(ctx, guest, err)
|
||||
}
|
||||
|
||||
func (self *GuestDeleteTask) OnEipDissociateComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
self.SetStage("OnDiskDetachComplete", nil)
|
||||
self.OnDiskDetachComplete(ctx, obj, data)
|
||||
}
|
||||
|
||||
// remove detachable disks
|
||||
func (self *GuestDeleteTask) OnDiskDetachComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
log.Debugf("OnDiskDetachComplete")
|
||||
guest := obj.(*models.SGuest)
|
||||
|
||||
if options.Options.EnablePendingDelete && !guest.PendingDeleted &&
|
||||
!jsonutils.QueryBoolean(self.Params, "purge", false) &&
|
||||
!jsonutils.QueryBoolean(self.Params, "override_pending_delete", false) {
|
||||
guestdisks := guest.GetDisks()
|
||||
if len(guestdisks) == 0 {
|
||||
self.doClearSecurityGroupComplete(ctx, guest)
|
||||
return
|
||||
}
|
||||
lastDisk := guestdisks[len(guestdisks)-1].GetDisk() // remove last detachable disk
|
||||
log.Debugf("lastDisk IsDetachable?? %v", lastDisk.IsDetachable())
|
||||
if !lastDisk.IsDetachable() {
|
||||
self.doClearSecurityGroupComplete(ctx, guest)
|
||||
return
|
||||
}
|
||||
guest.StartGuestDetachdiskTask(ctx, self.UserCred, lastDisk, true, self.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *GuestDeleteTask) OnDiskDetachCompleteFailed(ctx context.Context, obj db.IStandaloneModel, err jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
self.OnFailed(ctx, guest, err)
|
||||
}
|
||||
|
||||
// revoke all secgroups
|
||||
func (self *GuestDeleteTask) doClearSecurityGroupComplete(ctx context.Context, guest *models.SGuest) {
|
||||
log.Debugf("doClearSecurityGroupComplete")
|
||||
models.IsolatedDeviceManager.ReleaseDevicesOfGuest(ctx, guest, self.UserCred)
|
||||
guest.RevokeAllSecgroups(ctx, self.UserCred)
|
||||
// sync revoked secgroups to remote cloud
|
||||
self.SetStage("OnSyncConfigComplete", nil)
|
||||
guest.StartSyncTask(ctx, self.UserCred, false, self.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *GuestDeleteTask) OnSyncConfigComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
|
||||
isPurge := jsonutils.QueryBoolean(self.Params, "purge", false)
|
||||
overridePendingDelete := jsonutils.QueryBoolean(self.Params, "override_pending_delete", false)
|
||||
|
||||
if options.Options.EnablePendingDelete && !isPurge && !overridePendingDelete {
|
||||
if guest.PendingDeleted {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
return
|
||||
}
|
||||
log.Debugf("XXXXXXX Do guest pending delete... XXXXXXX")
|
||||
guestStatus, _ := self.Params.GetString("guest_status")
|
||||
if !utils.IsInStringArray(guestStatus, []string{models.VM_SCHEDULE_FAILED, models.VM_NETWORK_FAILED, models.VM_DISK_FAILED,
|
||||
if !utils.IsInStringArray(guestStatus, []string{
|
||||
models.VM_SCHEDULE_FAILED, models.VM_NETWORK_FAILED, models.VM_DISK_FAILED,
|
||||
models.VM_CREATE_FAILED, models.VM_DEVICE_FAILED}) {
|
||||
self.StartPendingDeleteGuest(ctx, guest)
|
||||
return
|
||||
@@ -103,8 +152,9 @@ func (self *GuestDeleteTask) OnEipDissociateComplete(ctx context.Context, obj db
|
||||
self.doStartDeleteGuest(ctx, guest)
|
||||
}
|
||||
|
||||
func (self *GuestDeleteTask) OnGuestStopCompleteFailed(ctx context.Context, obj db.IStandaloneModel, err jsonutils.JSONObject) {
|
||||
self.OnGuestStopComplete(ctx, obj, err) // ignore stop error
|
||||
func (self *GuestDeleteTask) OnSyncConfigCompleteFailed(ctx context.Context, obj db.IStandaloneModel, err jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
self.OnFailed(ctx, guest, err)
|
||||
}
|
||||
|
||||
func (self *GuestDeleteTask) OnGuestDeleteFailed(ctx context.Context, obj db.IStandaloneModel, err jsonutils.JSONObject) {
|
||||
@@ -121,7 +171,6 @@ func (self *GuestDeleteTask) doStartDeleteGuest(ctx context.Context, obj db.ISta
|
||||
|
||||
func (self *GuestDeleteTask) StartPendingDeleteGuest(ctx context.Context, guest *models.SGuest) {
|
||||
guest.DoPendingDelete(ctx, self.UserCred)
|
||||
models.IsolatedDeviceManager.ReleaseDevicesOfGuest(ctx, guest, self.UserCred)
|
||||
self.SetStage("on_pending_delete_complete", nil)
|
||||
guest.StartSyncstatus(ctx, self.UserCred, self.GetTaskId())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user