mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
Merge pull request #453 in YUNIONIO/onecloud from ~QUXUAN/onecloud:hotfix/qx-guest-attach-disk to release/2.1.0
* commit '89574e954a32a0e02e974b823440aeef4c2f3c18': 挂载磁盘失败时自动解除与虚机的关系
This commit is contained in:
@@ -53,6 +53,10 @@ func (self *SAliyunGuestDriver) GetDetachDiskStatus() ([]string, error) {
|
||||
return []string{models.VM_READY, models.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SAliyunGuestDriver) GetAttachDiskStatus() ([]string, error) {
|
||||
return []string{models.VM_READY, models.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SAliyunGuestDriver) RequestDetachDisk(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
|
||||
return guest.StartSyncTask(ctx, task.GetUserCred(), false, task.GetTaskId())
|
||||
}
|
||||
|
||||
@@ -170,6 +170,10 @@ func (self *SBaremetalGuestDriver) StartGuestDetachdiskTask(ctx context.Context,
|
||||
return fmt.Errorf("Cannot detach disk from a baremetal serer")
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) StartGuestAttachDiskTask(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, params *jsonutils.JSONDict, parentTaskId string) error {
|
||||
return fmt.Errorf("Cannot attach disk from a baremetal serer")
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) StartSuspendTask(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, params *jsonutils.JSONDict, parentTaskId string) error {
|
||||
return fmt.Errorf("Cannot suspend a baremetal serer")
|
||||
}
|
||||
|
||||
@@ -86,6 +86,11 @@ func (self *SBaseGuestDriver) RequestDetachDisk(ctx context.Context, guest *mode
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) RequestAttachDisk(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) RequestGuestCreateAllDisks(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
|
||||
return fmt.Errorf("Not Implement")
|
||||
}
|
||||
@@ -94,6 +99,10 @@ func (self *SBaseGuestDriver) GetDetachDiskStatus() ([]string, error) {
|
||||
return []string{}, fmt.Errorf("This Guest driver dose not implement GetDetachDiskStatus")
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) GetAttachDiskStatus() ([]string, error) {
|
||||
return []string{}, fmt.Errorf("This Guest driver dose not implement GetAttachDiskStatus")
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) RequestDeleteDetachedDisk(ctx context.Context, disk *models.SDisk, task taskman.ITask, isPurge bool) error {
|
||||
return fmt.Errorf("Not Implement")
|
||||
}
|
||||
|
||||
@@ -29,6 +29,10 @@ func (self *SESXiGuestDriver) GetDetachDiskStatus() ([]string, error) {
|
||||
return []string{models.VM_READY}, nil
|
||||
}
|
||||
|
||||
func (self *SESXiGuestDriver) GetAttachDiskStatus() ([]string, error) {
|
||||
return []string{models.VM_READY}, nil
|
||||
}
|
||||
|
||||
func (self *SESXiGuestDriver) CanKeepDetachDisk() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -214,10 +214,18 @@ func (self *SKVMGuestDriver) RequestDetachDisk(ctx context.Context, guest *model
|
||||
return guest.StartSyncTask(ctx, task.GetUserCred(), false, task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) RequestAttachDisk(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
|
||||
return guest.StartSyncTask(ctx, task.GetUserCred(), false, task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) GetDetachDiskStatus() ([]string, error) {
|
||||
return []string{models.VM_READY, models.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) GetAttachDiskStatus() ([]string, error) {
|
||||
return []string{models.VM_READY, models.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) RequestDeleteDetachedDisk(ctx context.Context, disk *models.SDisk, task taskman.ITask, isPurge bool) error {
|
||||
return disk.StartDiskDeleteTask(ctx, task.GetUserCred(), task.GetTaskId(), isPurge)
|
||||
}
|
||||
|
||||
@@ -103,6 +103,14 @@ func (self *SManagedVirtualizedGuestDriver) RequestGuestCreateAllDisks(ctx conte
|
||||
return storageCache.StartImageCacheTask(ctx, task.GetUserCred(), imageId, false, task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizedGuestDriver) RequestDetachDisk(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
|
||||
return guest.StartSyncTask(ctx, task.GetUserCred(), false, task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizedGuestDriver) RequestAttachDisk(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
|
||||
return guest.StartSyncTask(ctx, task.GetUserCred(), false, task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizedGuestDriver) RequestDeployGuestOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, task taskman.ITask) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -186,6 +186,15 @@ func (self *SVirtualizedGuestDriver) StartGuestDetachdiskTask(ctx context.Contex
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SVirtualizedGuestDriver) StartGuestAttachDiskTask(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, params *jsonutils.JSONDict, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "GuestAttachDiskTask", guest, userCred, params, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SVirtualizedGuestDriver) StartSuspendTask(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, params *jsonutils.JSONDict, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "GuestSuspendTask", guest, userCred, params, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
|
||||
@@ -42,6 +42,7 @@ const (
|
||||
DISK_DEALLOC_FAILED = "dealloc_failed"
|
||||
DISK_UNKNOWN = "unknown"
|
||||
DISK_DETACHING = "detaching"
|
||||
DISK_ATTACHING = "attaching"
|
||||
|
||||
DISK_START_SAVE = "start_save"
|
||||
DISK_SAVING = "saving"
|
||||
|
||||
@@ -77,12 +77,15 @@ type IGuestDriver interface {
|
||||
|
||||
GetGuestVncInfo(userCred mcclient.TokenCredential, guest *SGuest, host *SHost) (*jsonutils.JSONDict, error)
|
||||
|
||||
RequestAttachDisk(ctx context.Context, guest *SGuest, task taskman.ITask) error
|
||||
RequestDetachDisk(ctx context.Context, guest *SGuest, task taskman.ITask) error
|
||||
GetDetachDiskStatus() ([]string, error)
|
||||
GetAttachDiskStatus() ([]string, error)
|
||||
CanKeepDetachDisk() bool
|
||||
|
||||
RequestDeleteDetachedDisk(ctx context.Context, disk *SDisk, task taskman.ITask, isPurge bool) error
|
||||
StartGuestDetachdiskTask(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, params *jsonutils.JSONDict, parentTaskId string) error
|
||||
StartGuestAttachDiskTask(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, params *jsonutils.JSONDict, parentTaskId string) error
|
||||
|
||||
StartSuspendTask(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, params *jsonutils.JSONDict, parentTaskId string) error
|
||||
RqeuestSuspendOnHost(ctx context.Context, guest *SGuest, task taskman.ITask) error
|
||||
|
||||
@@ -62,6 +62,9 @@ const (
|
||||
VM_STOPPING = "stopping"
|
||||
VM_STOP_FAILED = "stop_fail" // # = running
|
||||
|
||||
VM_ATTACH_DISK_FAILED = "attach_disk_fail"
|
||||
VM_DETACH_DISK_FAILED = "detach_disk_fail"
|
||||
|
||||
VM_START_SUSPEND = "start_suspend"
|
||||
VM_SUSPENDING = "suspending"
|
||||
VM_SUSPEND = "suspend"
|
||||
@@ -1821,44 +1824,52 @@ func (self *SGuest) ValidateAttachDisk(ctx context.Context, disk *SDisk) error {
|
||||
host := self.GetHost()
|
||||
if provider.Id != host.ManagerId {
|
||||
return httperrors.NewInputParameterError("Disk %s and guest not belong to the same account", disk.Name)
|
||||
} else if storage.ZoneId != host.ZoneId {
|
||||
}
|
||||
if storage.ZoneId != host.ZoneId {
|
||||
return httperrors.NewInputParameterError("Disk %s and guest not belong to the same zone", disk.Name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if disk.isAttached() {
|
||||
return httperrors.NewInputParameterError("Disk %s has been attached", disk.Name)
|
||||
} else if len(disk.GetPathAtHost(self.GetHost())) == 0 {
|
||||
}
|
||||
if len(disk.GetPathAtHost(self.GetHost())) == 0 {
|
||||
return httperrors.NewInputParameterError("Disk %s not belong the guest's host", disk.Name)
|
||||
} else if disk.Status != DISK_READY {
|
||||
}
|
||||
if disk.Status != DISK_READY {
|
||||
return httperrors.NewInputParameterError("Disk in %s not able to attach", disk.Status)
|
||||
} else if !utils.IsInStringArray(self.Status, []string{VM_RUNNING, VM_READY}) {
|
||||
return httperrors.NewInputParameterError("Server in %s not able to attach disk", self.Status)
|
||||
}
|
||||
guestStatus, err := self.GetDriver().GetAttachDiskStatus()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !utils.IsInStringArray(self.Status, guestStatus) {
|
||||
return httperrors.NewInputParameterError("Guest %s not support attach disk in status %s", self.Name, self.Status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) PerformAttachdisk(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if diskId, err := data.GetString("disk_id"); err != nil {
|
||||
diskId, err := data.GetString("disk_id")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disk, err := DiskManager.FetchByIdOrName(userCred.GetProjectId(), diskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if disk == nil {
|
||||
return nil, httperrors.NewResourceNotFoundError("Disk %s not found", diskId)
|
||||
}
|
||||
if err := self.ValidateAttachDisk(ctx, disk.(*SDisk)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
taskData := data.(*jsonutils.JSONDict)
|
||||
taskData.Set("disk_id", jsonutils.NewString(disk.GetId()))
|
||||
|
||||
if err := self.GetDriver().StartGuestAttachDiskTask(ctx, userCred, self, taskData, ""); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
if disk, err := DiskManager.FetchByIdOrName(userCred.GetProjectId(), diskId); err != nil {
|
||||
return nil, err
|
||||
} else if disk == nil {
|
||||
return nil, httperrors.NewResourceNotFoundError("Disk %s not found", diskId)
|
||||
} else if err := self.ValidateAttachDisk(ctx, disk.(*SDisk)); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
driver, _ := data.GetString("driver")
|
||||
cache, _ := data.GetString("cache")
|
||||
mountpoint, _ := data.GetString("mountpoint")
|
||||
if err := self.attach2Disk(disk.(*SDisk), userCred, driver, cache, mountpoint); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
self.StartSyncTask(ctx, userCred, false, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
type GuestAttachDiskTask struct {
|
||||
SGuestBaseTask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(GuestAttachDiskTask{})
|
||||
}
|
||||
|
||||
func (self *GuestAttachDiskTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
diskId, _ := self.Params.GetString("disk_id")
|
||||
objDisk, err := models.DiskManager.FetchById(diskId)
|
||||
if err != nil {
|
||||
self.OnTaskFail(ctx, guest, nil, err)
|
||||
return
|
||||
}
|
||||
disk := objDisk.(*models.SDisk)
|
||||
if disk == nil {
|
||||
self.OnTaskFail(ctx, guest, nil, fmt.Errorf("Connot find disk %s", diskId))
|
||||
return
|
||||
}
|
||||
|
||||
driver, _ := self.Params.GetString("driver")
|
||||
cache, _ := self.Params.GetString("cache")
|
||||
mountpoint, _ := self.Params.GetString("mountpoint")
|
||||
|
||||
err = guest.AttachDisk(disk, self.UserCred, driver, cache, mountpoint)
|
||||
if err != nil {
|
||||
self.OnTaskFail(ctx, guest, nil, err)
|
||||
return
|
||||
}
|
||||
disk.SetStatus(self.UserCred, models.DISK_ATTACHING, "Disk attach")
|
||||
self.SetStage("on_sync_config_complete", nil)
|
||||
guest.GetDriver().RequestAttachDisk(ctx, guest, self)
|
||||
}
|
||||
|
||||
func (self *GuestAttachDiskTask) OnSyncConfigComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
diskId, _ := self.Params.GetString("disk_id")
|
||||
objDisk, err := models.DiskManager.FetchById(diskId)
|
||||
if err != nil {
|
||||
self.OnTaskFail(ctx, guest, nil, err)
|
||||
return
|
||||
}
|
||||
disk := objDisk.(*models.SDisk)
|
||||
if disk == nil {
|
||||
self.OnTaskFail(ctx, guest, nil, fmt.Errorf("Connot find disk %s", diskId))
|
||||
return
|
||||
}
|
||||
disk.SetStatus(self.UserCred, models.DISK_READY, "")
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (self *GuestAttachDiskTask) OnSyncConfigCompleteFailed(ctx context.Context, obj db.IStandaloneModel, resion jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
diskId, _ := self.Params.GetString("disk_id")
|
||||
objDisk, err := models.DiskManager.FetchById(diskId)
|
||||
if err != nil {
|
||||
self.OnTaskFail(ctx, guest, nil, err)
|
||||
return
|
||||
}
|
||||
disk := objDisk.(*models.SDisk)
|
||||
db.OpsLog.LogEvent(disk, db.ACT_ATTACH, resion.String(), self.UserCred)
|
||||
disk.SetStatus(self.UserCred, models.DISK_READY, "")
|
||||
guest.DetachDisk(ctx, disk, self.UserCred)
|
||||
self.OnTaskFail(ctx, guest, disk, fmt.Errorf(resion.String()))
|
||||
}
|
||||
|
||||
func (self *GuestAttachDiskTask) OnTaskFail(ctx context.Context, guest *models.SGuest, disk *models.SDisk, err error) {
|
||||
if disk != nil {
|
||||
disk.SetStatus(self.UserCred, models.DISK_READY, "")
|
||||
}
|
||||
guest.SetStatus(self.UserCred, models.VM_ATTACH_DISK_FAILED, err.Error())
|
||||
self.SetStageFailed(ctx, err.Error())
|
||||
log.Errorf("Guest %s GuestAttachDiskTask failed %s", guest.Name, err.Error())
|
||||
}
|
||||
@@ -131,6 +131,7 @@ func (self *GuestDetachDiskTask) OnTaskFail(ctx context.Context, guest *models.S
|
||||
if disk != nil {
|
||||
disk.SetDiskReady(ctx, self.UserCred, "")
|
||||
}
|
||||
guest.SetStatus(self.UserCred, models.VM_DETACH_DISK_FAILED, err.Error())
|
||||
self.SetStageFailed(ctx, err.Error())
|
||||
log.Errorf("Guest %s GuestDetachDiskTask failed %s", guest.Id, err.Error())
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ func (self *GuestSyncConfTask) OnDiskSyncCompleteFailed(ctx context.Context, obj
|
||||
guest := obj.(*models.SGuest)
|
||||
db.OpsLog.LogEvent(guest, db.ACT_SYNC_CONF_FAIL, data.String(), self.UserCred)
|
||||
log.Errorf("Guest sync config failed: %v", data.String())
|
||||
self.SetStageFailed(ctx, data.String())
|
||||
}
|
||||
|
||||
func (self *GuestSyncConfTask) OnSyncCompleteFailed(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
@@ -62,6 +63,7 @@ func (self *GuestSyncConfTask) OnSyncCompleteFailed(ctx context.Context, obj db.
|
||||
guest.SetStatus(self.GetUserCred(), models.VM_SYNC_FAIL, data.String())
|
||||
log.Errorf("Guest sync config failed: %v", data.String())
|
||||
db.OpsLog.LogEvent(guest, db.ACT_SYNC_CONF_FAIL, data.String(), self.UserCred)
|
||||
self.SetStageFailed(ctx, data.String())
|
||||
}
|
||||
|
||||
func (self *GuestSyncConfTask) OnSyncStatusComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
|
||||
Reference in New Issue
Block a user