fix(region,host): rescue mode update initramfs, vnc login no passwd (#19478)

This commit is contained in:
wanyaoqi
2024-02-10 16:29:05 +08:00
committed by GitHub
parent c36ba88ae8
commit 710d5ac2cc
13 changed files with 41 additions and 327 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
FROM registry.cn-beijing.aliyuncs.com/yunionio/host-deployer-base:1.4.4
FROM registry.cn-beijing.aliyuncs.com/yunionio/host-deployer-base:1.4.6
MAINTAINER "Yaoqi Wan wanyaoqi@yunionyun.com"
+2 -9
View File
@@ -16,13 +16,6 @@ package compute
// Rescue constants are used for rescue mode
const (
GUEST_RESCUE_RELATIVE_PATH = "rescue" // serverxxx/rescue
GUEST_RESCUE_INITRAMFS = "initramfs"
GUEST_RESCUE_KERNEL = "kernel"
GUEST_RESCUE_INITRAMFS_ARM64 = "initramfs_aarch64"
GUEST_RESCUE_KERNEL_ARM64 = "kernel_aarch64"
GUEST_RESCUE_SYS_DISK_NAME = "sys_img"
GUEST_RESCUE_SYS_DISK_SIZE = 500 // MB
GUEST_RESCUE_INITRAMFS = "initramfs"
GUEST_RESCUE_KERNEL = "kernel"
)
-4
View File
@@ -557,10 +557,6 @@ func (self *SBaseGuestDriver) RequestStartRescue(ctx context.Context, task taskm
return httperrors.ErrNotImplemented
}
func (self *SBaseGuestDriver) RequestStopRescue(ctx context.Context, task taskman.ITask, body jsonutils.JSONObject, host *models.SHost, guest *models.SGuest) error {
return httperrors.ErrNotImplemented
}
func (base *SBaseGuestDriver) ValidateGuestChangeConfigInput(ctx context.Context, guest *models.SGuest, input api.ServerChangeConfigInput) (*api.ServerChangeConfigSettings, error) {
confs := api.ServerChangeConfigSettings{}
-12
View File
@@ -1195,18 +1195,6 @@ func (self *SKVMGuestDriver) RequestStartRescue(ctx context.Context, task taskma
return nil
}
func (self *SKVMGuestDriver) RequestStopRescue(ctx context.Context, task taskman.ITask, body jsonutils.JSONObject, host *models.SHost, guest *models.SGuest) error {
header := self.getTaskRequestHeader(task)
client := httputils.GetDefaultClient()
url := fmt.Sprintf("%s/servers/%s/stop-rescue", host.ManagerUri, guest.Id)
_, _, err := httputils.JSONRequest(client, ctx, "POST", url, header, body, false)
if err != nil {
return err
}
return nil
}
func (self *SKVMGuestDriver) ValidateSyncOSInfo(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest) error {
if !utils.IsInStringArray(guest.Status, []string{api.VM_RUNNING, api.VM_READY}) {
return httperrors.NewBadRequestError("can't sync guest os info in status %s", guest.Status)
+5 -20
View File
@@ -30,31 +30,16 @@ import (
func (self *SGuest) PerformStartRescue(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject,
data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if self.Hypervisor != api.HYPERVISOR_KVM {
return nil, httperrors.NewBadRequestError("Cannot rescue guest hypervisor %s", self.Hypervisor)
}
if !utils.IsInStringArray(self.Status, []string{api.VM_READY, api.VM_RUNNING}) {
return nil, httperrors.NewInvalidStatusError("guest status must be ready or running")
}
// Check vmem size, need to be greater than 2G
if self.VmemSize < 2048 {
return nil, httperrors.NewInvalidStatusError("vmem size must be greater than 2G")
}
// Get baremetal agent
host, err := self.GetHost()
if err != nil {
return nil, httperrors.NewInvalidStatusError("guest.GetHost: %s", err.Error())
}
bmAgent := BaremetalagentManager.GetAgent(api.AgentTypeBaremetal, host.ZoneId)
if bmAgent == nil {
return nil, httperrors.NewInvalidStatusError("BaremetalagentManager.GetAgent: %s", "Baremetal agent not found")
}
// Set available baremetal agent managerURi to data
dataDict := data.(*jsonutils.JSONDict)
dataDict.Add(jsonutils.NewString(bmAgent.ManagerUri), "manager_uri")
// Start rescue vm task
err = self.StartRescueTask(ctx, userCred, dataDict, "")
err := self.StartRescueTask(ctx, userCred, jsonutils.NewDict(), "")
if err != nil {
return nil, httperrors.NewInvalidStatusError("guest.StartGuestRescueTask: %s", err.Error())
}
-1
View File
@@ -251,7 +251,6 @@ type IGuestDriver interface {
ValidateSetOSInfo(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, input *api.ServerSetOSInfoInput) error
ValidateSyncOSInfo(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest) error
RequestStartRescue(ctx context.Context, task taskman.ITask, body jsonutils.JSONObject, host *SHost, guest *SGuest) error
RequestStopRescue(ctx context.Context, task taskman.ITask, body jsonutils.JSONObject, host *SHost, guest *SGuest) error
}
var guestDrivers map[string]IGuestDriver
+7 -11
View File
@@ -69,14 +69,14 @@ func (self *StartRescueTask) OnServerStopCompleteFailed(ctx context.Context, gue
func (self *StartRescueTask) PrepareRescue(ctx context.Context, guest *models.SGuest) {
db.OpsLog.LogEvent(guest, db.ACT_START_RESCUE, nil, self.UserCred)
guest.SetStatus(ctx, self.UserCred, api.VM_START_RESCUE, "PrepareRescue")
self.SetStage("OnRescuePrepareComplete", nil)
host, _ := guest.GetHost()
err := guest.GetDriver().RequestStartRescue(ctx, self, self.GetParams(), host, guest)
err := guest.GetDriver().RequestStartRescue(ctx, self, jsonutils.NewDict(), host, guest)
if err != nil {
self.OnRescuePrepareCompleteFailed(ctx, guest, jsonutils.NewString(err.Error()))
return
}
self.OnRescuePrepareComplete(ctx, guest, nil)
}
func (self *StartRescueTask) OnRescuePrepareComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
@@ -166,20 +166,16 @@ func (self *StopRescueTask) OnServerStopCompleteFailed(ctx context.Context, gues
func (self *StopRescueTask) ClearRescue(ctx context.Context, guest *models.SGuest) {
db.OpsLog.LogEvent(guest, db.ACT_STOP_RESCUE, nil, self.UserCred)
guest.SetStatus(ctx, self.UserCred, api.VM_STOP_RESCUE, "ClearRescue")
self.SetStage("OnRescueClearComplete", nil)
host, _ := guest.GetHost()
err := guest.GetDriver().RequestStopRescue(ctx, self, nil, host, guest)
if err != nil {
self.OnRescueClearCompleteFailed(ctx, guest, jsonutils.NewString(err.Error()))
return
}
self.OnRescueClearComplete(ctx, guest, nil)
}
func (self *StopRescueTask) OnRescueClearComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
db.OpsLog.LogEvent(guest, db.ACT_STOP_RESCUE, guest.GetShortDesc(ctx), self.UserCred)
logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_STOP_RESCUE, guest.GetShortDesc(ctx), self.UserCred, true)
guest.UpdateRescueMode(false)
if err := guest.UpdateRescueMode(false); err != nil {
self.OnRescueClearCompleteFailed(ctx, guest, jsonutils.NewString(err.Error()))
return
}
self.RescueStartServer(ctx, guest)
}
@@ -106,7 +106,6 @@ func AddGuestTaskHandler(prefix string, app *appsrv.Application) {
"qga-set-network": qgaSetNetwork,
"qga-get-os-info": qgaGetOsInfo,
"start-rescue": guestStartRescue,
"stop-rescue": guestStopRescue,
} {
app.AddHandler("POST",
fmt.Sprintf("%s/%s/<sid>/%s", prefix, keyWord, action),
@@ -950,14 +949,7 @@ func qgaGetOsInfo(ctx context.Context, userCred mcclient.TokenCredential, sid st
return gm.QgaGetOsInfo(sid)
}
// guestStartRescue prepare rescue files
// prepare rescue files
func guestStartRescue(ctx context.Context, userCred mcclient.TokenCredential, sid string, body jsonutils.JSONObject) (interface{}, error) {
// Start rescue guest
return guestman.GetGuestManager().GuestStartRescue(ctx, userCred, sid, body)
}
// guestStopRescue clear rescue files
func guestStopRescue(ctx context.Context, userCred mcclient.TokenCredential, sid string, body jsonutils.JSONObject) (interface{}, error) {
// Stop rescue guest
return guestman.GetGuestManager().GuestStopRescue(ctx, userCred, sid, body)
}
+7 -14
View File
@@ -911,21 +911,14 @@ func (m *SGuestManager) GuestStop(ctx context.Context, sid string, timeout int64
}
func (m *SGuestManager) GuestStartRescue(ctx context.Context, userCred mcclient.TokenCredential, sid string, body jsonutils.JSONObject) (jsonutils.JSONObject, error) {
baremetalManagerUri, err := body.GetString("manager_uri")
if err != nil {
return nil, httperrors.NewInputParameterError("manager_uri required")
}
if guest, ok := m.GetServer(sid); ok {
guest.ExecStartRescueTask(ctx, baremetalManagerUri)
return nil, nil
} else {
return nil, httperrors.NewNotFoundError("Guest %s not found", sid)
}
}
func (m *SGuestManager) GuestStopRescue(ctx context.Context, userCred mcclient.TokenCredential, sid string, body jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if guest, ok := m.GetServer(sid); ok {
guest.ExecStopRescueTask(ctx, body)
// initrd and kernel should be prepared by host-deployer
if !fileutils2.Exists(guest.getRescueInitrdPath()) {
return nil, httperrors.NewInternalServerError("guest initrd not ready")
}
if !fileutils2.Exists(guest.getRescueKernelPath()) {
return nil, httperrors.NewInternalServerError("guest kernel not ready")
}
return nil, nil
} else {
return nil, httperrors.NewNotFoundError("Guest %s not found", sid)
-48
View File
@@ -102,54 +102,6 @@ func (s *SGuestStopTask) CheckGuestRunningLater() {
s.checkGuestRunning()
}
// SGuestStartRescueTask Start a rescue vm
type SGuestStartRescueTask struct {
*SKVMGuestInstance
ctx context.Context
BaremetalManagerUri string
}
func NewGuestStartRescueTask(guest *SKVMGuestInstance, ctx context.Context, baremetalManagerUri string) *SGuestStartRescueTask {
return &SGuestStartRescueTask{
SKVMGuestInstance: guest,
ctx: ctx,
BaremetalManagerUri: baremetalManagerUri,
}
}
func (s *SGuestStartRescueTask) Start() {
if err := s.prepareRescue(s.ctx, s.BaremetalManagerUri); err != nil {
log.Errorf("prepareRescue fail %s", err)
hostutils.TaskFailed(s.ctx, err.Error())
return
}
hostutils.TaskComplete(s.ctx, nil)
}
// SGuestStopRescueTask Stop a rescue vm, clean rescue files
type SGuestStopRescueTask struct {
*SKVMGuestInstance
ctx context.Context
}
func NewGuestStopRescueTask(guest *SKVMGuestInstance, ctx context.Context) *SGuestStopRescueTask {
return &SGuestStopRescueTask{
SKVMGuestInstance: guest,
ctx: ctx,
}
}
func (s *SGuestStopRescueTask) Start() {
if err := s.clearRescue(s.ctx); err != nil {
log.Errorf("clearRescue fail %s", err)
hostutils.TaskFailed(s.ctx, err.Error())
return
}
hostutils.TaskComplete(s.ctx, nil)
}
type SGuestSuspendTask struct {
*SKVMGuestInstance
ctx context.Context
+4 -181
View File
@@ -17,9 +17,7 @@ package guestman
import (
"context"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"path"
"path/filepath"
@@ -34,8 +32,6 @@ import (
"yunion.io/x/log"
"yunion.io/x/pkg/appctx"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/httputils"
"yunion.io/x/pkg/util/qemuimgfmt"
"yunion.io/x/pkg/util/regutils"
"yunion.io/x/pkg/util/seclib"
"yunion.io/x/pkg/util/version"
@@ -395,19 +391,11 @@ func (s *SKVMGuestInstance) GetSourceDescFilePath() string {
}
func (s *SKVMGuestInstance) GetRescueDirPath() string {
return path.Join(s.HomeDir(), api.GUEST_RESCUE_RELATIVE_PATH)
}
func (s *SKVMGuestInstance) CreateRescueDirPath() (string, error) {
rescueDir := path.Join(s.HomeDir(), api.GUEST_RESCUE_RELATIVE_PATH)
// Check if rescue dir exists
output, err := procutils.NewCommand("mkdir", "-p", rescueDir).Output()
if err != nil {
return "", errors.Wrapf(err, "mkdir %s failed: %s", s.HomeDir(), output)
if s.manager.host.IsAarch64() {
return path.Join("/opt/cloud/host-deployer/yunionos/aarch64")
} else {
return path.Join("/opt/cloud/host-deployer/yunionos/x86_64")
}
return rescueDir, nil
}
func (s *SKVMGuestInstance) LoadDesc() error {
@@ -2013,19 +2001,6 @@ func (s *SKVMGuestInstance) ExecStopTask(ctx context.Context, params interface{}
return nil, nil
}
func (s *SKVMGuestInstance) ExecStartRescueTask(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
baremetalManagerUri, ok := params.(string)
if !ok {
return nil, hostutils.ParamsError
}
NewGuestStartRescueTask(s, ctx, baremetalManagerUri).Start()
return nil, nil
}
func (s *SKVMGuestInstance) ExecStopRescueTask(ctx context.Context, params interface{}) {
NewGuestStopRescueTask(s, ctx).Start()
}
func (s *SKVMGuestInstance) ExecSuspendTask(ctx context.Context) {
NewGuestSuspendTask(s, ctx, nil).Start()
}
@@ -3176,155 +3151,3 @@ func (s *SKVMGuestInstance) CPUSetRemove(ctx context.Context) error {
}
return nil
}
func (s *SKVMGuestInstance) clearRescue(ctx context.Context) error {
rescueDir := s.GetRescueDirPath()
if err := fileutils2.Cleandir(rescueDir, false); err != nil {
return errors.Wrap(err, "clear rescue dir failed")
}
return nil
}
func (s *SKVMGuestInstance) prepareRescue(ctx context.Context, baremetalManagerUri string) error {
files := []string{
api.GUEST_RESCUE_INITRAMFS,
api.GUEST_RESCUE_KERNEL,
}
// Support arm64
if s.manager.host.IsAarch64() {
files = []string{
api.GUEST_RESCUE_INITRAMFS_ARM64,
api.GUEST_RESCUE_KERNEL_ARM64,
}
}
// Prepare files
for _, file := range files {
err := s.downloadFromBaremetal(file, baremetalManagerUri)
if err != nil {
return errors.Wrapf(err, "download %s from baremetal failed", file)
}
}
// Create disk
diskPath := path.Join(s.GetRescueDirPath(), api.GUEST_RESCUE_SYS_DISK_NAME)
err := s.createTempDisk(diskPath, api.GUEST_RESCUE_SYS_DISK_SIZE, qemuimgfmt.QCOW2.String(), nil, "")
if err != nil {
return errors.Wrapf(err, "create disk %s failed", diskPath)
}
return nil
}
func (s *SKVMGuestInstance) downloadFromBaremetal(filename, baremetalManagerUri string) error {
rescueDir, err := s.CreateRescueDirPath()
if err != nil {
return errors.Wrap(err, "SKVMGuestInstance.GetRescueDirPath")
}
// Check file is exist
filePath := path.Join(rescueDir, filename)
if fileutils2.Exists(filePath) {
// File already exist
log.Debugf("File %s already exist", filePath)
return nil
}
// Create file
file, err := os.Create(filePath)
if err != nil {
return errors.Wrapf(err, "create file %s failed", filePath)
}
defer file.Close()
// Get filepath
fileURL, err := s.getTftpFileUrl(filename, baremetalManagerUri)
if err != nil {
return errors.Wrapf(err, "getTftpFileUrl")
}
// Request for file
resp, err := httputils.Request(
httputils.GetDefaultClient(),
context.Background(),
"GET",
fileURL,
nil,
nil,
false)
if err != nil || resp.StatusCode != http.StatusOK {
return errors.Wrapf(err, "request %s failed", fileURL)
}
// Write file
if _, err := io.Copy(file, resp.Body); err != nil {
return errors.Wrapf(err, "write file %s failed", filePath)
}
return nil
}
func (s *SKVMGuestInstance) createTempDisk(path string, sizeMB int, diskFormat string, encryptInfo *apis.SEncryptInfo, back string) error {
if fileutils2.Exists(path) {
os.Remove(path)
}
img, err := qemuimg.NewQemuImage(path)
if err != nil {
log.Errorln(err)
return err
}
switch diskFormat {
case "qcow2":
if encryptInfo != nil {
err = img.CreateQcow2(sizeMB, false, back, encryptInfo.Key, qemuimg.EncryptFormatLuks, encryptInfo.Alg)
} else {
err = img.CreateQcow2(sizeMB, false, back, "", "", "")
}
case "vmdk":
err = img.CreateVmdk(sizeMB, false)
default:
err = img.CreateRaw(sizeMB)
}
if err != nil {
return errors.Wrapf(err, "create_raw: Fail to create disk")
}
return nil
}
func (s *SKVMGuestInstance) getTftpFileUrl(filename, baremetalManagerUri string) (string, error) {
endpoint, err := s.getTftpEndpoint(baremetalManagerUri)
if err != nil {
log.Errorf("Get http file server endpoint: %v", err)
return filename, err
}
return fmt.Sprintf("http://%s/tftp/%s", endpoint, filename), nil
}
func (s *SKVMGuestInstance) getTftpEndpoint(baremetalManagerUri string) (string, error) {
// Split with :
addrs := strings.Split(baremetalManagerUri, "//")
if len(addrs) < 2 {
return "", errors.Errorf("baremetal manager uri is invalid")
}
endpoints := strings.Split(addrs[1], ":")
if len(endpoints) < 2 {
return "", errors.Errorf("baremetal manager uri is invalid")
}
// Plus baremetal agent port with 1000
port, err := strconv.Atoi(endpoints[1])
if err != nil {
return "", errors.Wrapf(err, "convert port failed")
}
// Concat new endpoint url
endpoint := fmt.Sprintf("%s:%d", endpoints[0], port+1000)
return endpoint, nil
}
-6
View File
@@ -577,16 +577,10 @@ function nic_mtu() {
}
func (s *SKVMGuestInstance) getRescueInitrdPath() string {
if s.manager.GetHost().IsAarch64() {
return path.Join(s.GetRescueDirPath(), api.GUEST_RESCUE_INITRAMFS_ARM64)
}
return path.Join(s.GetRescueDirPath(), api.GUEST_RESCUE_INITRAMFS)
}
func (s *SKVMGuestInstance) getRescueKernelPath() string {
if s.manager.GetHost().IsAarch64() {
return path.Join(s.GetRescueDirPath(), api.GUEST_RESCUE_KERNEL_ARM64)
}
return path.Join(s.GetRescueDirPath(), api.GUEST_RESCUE_KERNEL)
}
+14 -11
View File
@@ -223,6 +223,7 @@ func generateInitrdOptions(drvOpt QemuOptions, initrdPath, kernel string) []stri
opts := make([]string, 0)
opts = append(opts, drvOpt.Initrd(initrdPath))
opts = append(opts, drvOpt.Kernel(kernel))
opts = append(opts, "-append yn_rescue_mode=true")
return opts
}
@@ -795,20 +796,22 @@ func GenerateStartOptions(
}
opts = append(opts, nicOpts...)
if input.QemuArch == Arch_aarch64 {
if input.GuestDesc.Usb != nil {
opts = append(opts, generatePCIDeviceOption(input.GuestDesc.Usb.PCIDevice))
if !input.GuestDesc.LightMode {
if input.QemuArch == Arch_aarch64 {
if input.GuestDesc.Usb != nil {
opts = append(opts, generatePCIDeviceOption(input.GuestDesc.Usb.PCIDevice))
for _, device := range input.Devices {
opts = append(opts, drvOpt.Device(device))
}
}
} else {
opts = append(opts, drvOpt.USB())
for _, device := range input.Devices {
opts = append(opts, drvOpt.Device(device))
}
}
} else {
opts = append(opts, drvOpt.USB())
for _, device := range input.Devices {
opts = append(opts, drvOpt.Device(device))
}
if input.GuestDesc.Usb != nil {
opts = append(opts, generatePCIDeviceOption(input.GuestDesc.Usb.PCIDevice))
if input.GuestDesc.Usb != nil {
opts = append(opts, generatePCIDeviceOption(input.GuestDesc.Usb.PCIDevice))
}
}
}