diff --git a/pkg/compute/models/guest_actions.go b/pkg/compute/models/guest_actions.go index 47c07ecf33..b1cae7d671 100644 --- a/pkg/compute/models/guest_actions.go +++ b/pkg/compute/models/guest_actions.go @@ -2254,12 +2254,13 @@ func (self *SGuest) AllowPerformSwitchToBackup(ctx context.Context, userCred mcc } func (self *SGuest) PerformSwitchToBackup(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}) { + if self.Status == VM_BLOCK_STREAM { return nil, httperrors.NewBadRequestError("Cannot swith to backup when guest in status %s", self.Status) } if len(self.BackupHostId) == 0 { return nil, httperrors.NewBadRequestError("Guest no backup host") } + self.SetStatus(userCred, VM_SWITCH_TO_BACKUP, "Switch to backup") if task, err := taskman.TaskManager.NewTask(ctx, "GuestSwitchToBackupTask", self, userCred, nil, "", "", nil); err != nil { log.Errorf(err.Error()) return nil, err diff --git a/pkg/compute/models/guests.go b/pkg/compute/models/guests.go index 878a1dca3f..7788d4d6b1 100644 --- a/pkg/compute/models/guests.go +++ b/pkg/compute/models/guests.go @@ -66,6 +66,8 @@ const ( VM_DEPLOYING_BACKUP_FAILED = "deploging_backup_fail" VM_DELETING_BACKUP = "deleting_backup" VM_BACKUP_DELETE_FAILED = "backup_delete_fail" + VM_SWITCH_TO_BACKUP = "switch_to_backup" + VM_SWITCH_TO_BACKUP_FAILED = "switch_to_backup_fail" VM_ATTACH_DISK_FAILED = "attach_disk_fail" VM_DETACH_DISK_FAILED = "detach_disk_fail" diff --git a/pkg/compute/tasks/guest_backup_tasks.go b/pkg/compute/tasks/guest_backup_tasks.go index 2f6a30b7b8..a8a2267173 100644 --- a/pkg/compute/tasks/guest_backup_tasks.go +++ b/pkg/compute/tasks/guest_backup_tasks.go @@ -8,6 +8,7 @@ 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/util/logclient" "yunion.io/x/pkg/utils" ) @@ -39,7 +40,7 @@ func (self *GuestSwitchToBackupTask) OnEnsureMasterGuestStoped(ctx context.Conte self.SetStage("OnBackupGuestStoped", nil) err := guest.GetDriver().RequestStopOnHost(ctx, guest, backupHost, self) if err != nil { - self.SetStageFailed(ctx, fmt.Sprintf("Stop backup guest error: %s", err)) + self.OnFail(ctx, guest, fmt.Sprintf("Stop backup guest error: %s", err)) } } @@ -55,16 +56,17 @@ func (self *GuestSwitchToBackupTask) OnBackupGuestStoped(ctx context.Context, gu disk.SwitchToBackup() } } - db.OpsLog.LogEvent(guest, db.ACT_SWITCH_FAILED, fmt.Sprintf("Switch to backup disk error: %s", err), self.UserCred) - self.SetStageFailed(ctx, fmt.Sprintf("Switch to backup disk error: %s", err)) + self.OnFail(ctx, guest, fmt.Sprintf("Switch to backup disk error: %s", err)) + return } } err := guest.SwitchToBackup() if err != nil { - db.OpsLog.LogEvent(guest, db.ACT_SWITCH_FAILED, fmt.Sprintf("Switch to backup guest error: %s", err), self.UserCred) - self.SetStageFailed(ctx, fmt.Sprintf("Switch to backup guest error: %s", err)) + self.OnFail(ctx, guest, fmt.Sprintf("Switch to backup guest error: %s", err)) + return } - db.OpsLog.LogEvent(guest, db.ACT_SWITCHED, fmt.Sprintf("Switch to backup guest error: %s", err), self.UserCred) + db.OpsLog.LogEvent(guest, db.ACT_SWITCHED, "Switch to backup", self.UserCred) + logclient.AddActionLogWithContext(ctx, guest, logclient.ACT_SWITCH_TO_BACKUP, "Switch to backup", self.UserCred, true) self.SetStage("OnNewMasterStarted", nil) guest.StartGueststartTask(ctx, self.UserCred, nil, self.GetTaskId()) } @@ -73,6 +75,13 @@ func (self *GuestSwitchToBackupTask) OnNewMasterStarted(ctx context.Context, gue self.SetStageComplete(ctx, nil) } +func (self *GuestSwitchToBackupTask) OnFail(ctx context.Context, guest *models.SGuest, reason string) { + guest.SetStatus(self.UserCred, models.VM_SWITCH_TO_BACKUP_FAILED, reason) + db.OpsLog.LogEvent(guest, db.ACT_SWITCH_FAILED, reason, self.UserCred) + logclient.AddActionLogWithContext(ctx, guest, logclient.ACT_SWITCH_TO_BACKUP, reason, self.UserCred, false) + self.SetStageFailed(ctx, reason) +} + /********************* GuestStartAndSyncToBackupTask *********************/ type GuestStartAndSyncToBackupTask struct { @@ -101,10 +110,21 @@ func (self *GuestStartAndSyncToBackupTask) checkTemplete(ctx context.Context, gu func (self *GuestStartAndSyncToBackupTask) OnCheckTemplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) { self.SetStage("OnStartBackupGuest", nil) host := models.HostManager.FetchHostById(guest.BackupHostId) - guest.GetDriver().RequestStartOnHost(ctx, guest, host, self.UserCred, self) + if _, err := guest.GetDriver().RequestStartOnHost(ctx, guest, host, self.UserCred, self); err != nil { + self.SetStageFailed(ctx, err.Error()) + } } func (self *GuestStartAndSyncToBackupTask) OnStartBackupGuest(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) { + nbdServerPort, err := data.Int("nbd_server_port") + if err != nil { + self.SetStageFailed(ctx, "Start Backup Guest Missing Nbd Port") + return + } + backupHost := models.HostManager.FetchHostById(guest.BackupHostId) + nbdServerUri := fmt.Sprintf("nbd:%s:%d", backupHost.AccessIp, nbdServerPort) + guest.SetMetadata(ctx, "backup_nbd_server_uri", nbdServerUri, self.UserCred) + db.OpsLog.LogEvent(guest, db.ACT_BACKUP_START, "", self.UserCred) if utils.IsInStringArray(guest.Status, models.VM_RUNNING_STATUS) { self.SetStage("OnRequestSyncToBackup", nil) @@ -216,7 +236,7 @@ func (self *GuestCreateBackupTask) OnCreateBackup(ctx context.Context, guest *mo if utils.IsInStringArray(guestStatus, models.VM_RUNNING_STATUS) { self.OnGuestStart(ctx, guest, nil) } else { - self.SetStageComplete(ctx, nil) + self.TaskCompleted(ctx, guest, "") } } @@ -229,12 +249,19 @@ func (self *GuestCreateBackupTask) OnGuestStart(ctx context.Context, guest *mode } func (self *GuestCreateBackupTask) OnSyncToBackup(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) { + self.TaskCompleted(ctx, guest, "") +} + +func (self *GuestCreateBackupTask) TaskCompleted(ctx context.Context, guest *models.SGuest, reason string) { + db.OpsLog.LogEvent(guest, db.ACT_CREATE_BACKUP, reason, self.UserCred) + logclient.AddActionLogWithContext(ctx, guest, logclient.ACT_CREATE_BACKUP, reason, self.UserCred, true) self.SetStageComplete(ctx, nil) } func (self *GuestCreateBackupTask) TaskFailed(ctx context.Context, guest *models.SGuest, reason string) { guest.SetStatus(self.UserCred, models.VM_BACKUP_CREATE_FAILED, reason) db.OpsLog.LogEvent(guest, db.ACT_CREATE_BACKUP_FAILED, reason, self.UserCred) + logclient.AddActionLogWithContext(ctx, guest, logclient.ACT_CREATE_BACKUP, reason, self.UserCred, false) self.SetStageFailed(ctx, reason) } diff --git a/pkg/compute/tasks/guest_detach_disk_task.go b/pkg/compute/tasks/guest_detach_disk_task.go index 2ccf7c97d1..857bae39b6 100644 --- a/pkg/compute/tasks/guest_detach_disk_task.go +++ b/pkg/compute/tasks/guest_detach_disk_task.go @@ -83,7 +83,7 @@ func (self *GuestDetachDiskTask) OnSyncConfigComplete(ctx context.Context, guest purge = true } if !keepDisk && disk.GetGuestDiskCount() == 0 && disk.AutoDelete { - self.SetStage("on_disk_delete_complete", nil) + self.SetStage("OnDiskDeleteComplete", nil) db.OpsLog.LogEvent(disk, db.ACT_DELETE, "", self.UserCred) err := guest.GetDriver().RequestDeleteDetachedDisk(ctx, disk, self, purge) if err != nil { diff --git a/pkg/util/logclient/logclient.go b/pkg/util/logclient/logclient.go index df3852e7a6..0887f1c07c 100644 --- a/pkg/util/logclient/logclient.go +++ b/pkg/util/logclient/logclient.go @@ -70,6 +70,8 @@ const ( ACT_RESET_DISK = "回滚磁盘" ACT_SYNC_STATUS = "同步状态" ACT_SYNC_CONF = "同步配置" + ACT_CREATE_BACKUP = "创建备份机" + ACT_SWITCH_TO_BACKUP = "主备切换" ACT_IMAGE_SAVE = "上传镜像"