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:
邱剑
2019-01-04 13:16:49 +08:00
7 changed files with 131 additions and 35 deletions
@@ -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)
+33
View File
@@ -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
}
+23 -21
View File
@@ -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)
}
}
+3 -3
View File
@@ -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
+3 -3
View File
@@ -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)
+8 -1
View File
@@ -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)
+56 -7
View File
@@ -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())
}