fix: validate VM vdi,vga,machine input

This commit is contained in:
Qiu Jian
2021-11-08 21:27:27 +08:00
parent 83da0272e7
commit bd57ee406e
6 changed files with 120 additions and 64 deletions

View File

@@ -183,6 +183,15 @@ const (
const (
VM_MACHINE_TYPE_PC = "pc"
VM_MACHINE_TYPE_Q35 = "q35"
VM_MACHINE_TYPE_ARM_VIRT = "virt"
VM_VDI_PROTOCOL_VNC = "vnc"
VM_VDI_PROTOCOL_SPICE = "spice"
VM_VIDEO_STANDARD = "std"
VM_VIDEO_QXL = "qxl"
VM_VIDEO_VIRTIO = "virtio"
)
var VM_RUNNING_STATUS = []string{VM_START_START, VM_STARTING, VM_RUNNING, VM_BLOCK_STREAM, VM_BLOCK_STREAM_FAIL}

View File

@@ -411,8 +411,12 @@ func (self *SBaseGuestDriver) RequestLiveMigrate(ctx context.Context, guest *mod
return fmt.Errorf("Not Implement RequestLiveMigrate")
}
func (self *SBaseGuestDriver) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, input api.ServerUpdateInput) error {
return nil
func (self *SVirtualizedGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
return input, nil
}
func (self *SBaseGuestDriver) ValidateUpdateData(ctx context.Context, guest *models.SGuest, userCred mcclient.TokenCredential, input api.ServerUpdateInput) (api.ServerUpdateInput, error) {
return input, nil
}
func (self *SBaseGuestDriver) RequestRemoteUpdate(ctx context.Context, guest *models.SGuest, userCred mcclient.TokenCredential, replaceTags bool) error {

View File

@@ -816,3 +816,102 @@ func (self *SKVMGuestDriver) RequestChangeDiskStorage(ctx context.Context, userC
_, _, err = httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, body, false)
return err
}
func (self *SKVMGuestDriver) validateVdiProtocol(vdi string) error {
if !utils.IsInStringArray(vdi, []string{api.VM_VDI_PROTOCOL_VNC, api.VM_VDI_PROTOCOL_SPICE}) {
return httperrors.NewInputParameterError("unsupported vdi protocol")
}
return nil
}
func (self *SKVMGuestDriver) validateVGA(ovdi, ovga string, nvdi, nvga *string) (vdi, vga string) {
vdi = ovdi
if nvdi != nil {
vdi = *nvdi
}
if vdi != api.VM_VDI_PROTOCOL_VNC && vdi != api.VM_VDI_PROTOCOL_SPICE {
vdi = api.VM_VDI_PROTOCOL_VNC
}
var candidateVga []string
switch vdi {
case api.VM_VDI_PROTOCOL_VNC:
candidateVga = []string{api.VM_VIDEO_STANDARD, api.VM_VIDEO_QXL, api.VM_VIDEO_VIRTIO}
case api.VM_VDI_PROTOCOL_SPICE:
candidateVga = []string{api.VM_VIDEO_QXL, api.VM_VIDEO_VIRTIO}
}
vga = ovga
if nvga != nil {
vga = *nvga
}
if !utils.IsInStringArray(vga, candidateVga) {
vga = candidateVga[0]
}
return
}
func (self *SKVMGuestDriver) validateMachineType(machine string, osArch string) error {
var candidate []string
switch osArch {
case apis.OS_ARCH_AARCH64:
candidate = []string{api.VM_MACHINE_TYPE_ARM_VIRT}
default:
candidate = []string{api.VM_MACHINE_TYPE_PC, api.VM_MACHINE_TYPE_Q35}
}
if !utils.IsInStringArray(machine, candidate) {
return httperrors.NewInputParameterError("Invalid machine type %s", machine)
}
return nil
}
func (self *SKVMGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
input, err := self.SVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, input)
if err != nil {
return input, errors.Wrap(err, "SVirtualizedGuestDriver.ValidateCreateData")
}
if input.Vdi != "" {
err = self.validateVdiProtocol(input.Vdi)
if err != nil {
return nil, errors.Wrap(err, "validateVdiProtocol")
}
}
if input.Vdi != "" || input.Vga != "" {
input.Vdi, input.Vga = self.validateVGA("", "", &input.Vdi, &input.Vga)
}
if input.Machine != "" {
if err := self.validateMachineType(input.Machine, input.OsArch); err != nil {
return nil, errors.Wrap(err, "validateMachineType")
}
}
return input, nil
}
func (self *SKVMGuestDriver) ValidateUpdateData(ctx context.Context, guest *models.SGuest, userCred mcclient.TokenCredential, input api.ServerUpdateInput) (api.ServerUpdateInput, error) {
input, err := self.SVirtualizedGuestDriver.ValidateUpdateData(ctx, guest, userCred, input)
if err != nil {
return input, errors.Wrap(err, "SVirtualizedGuestDriver.ValidateUpdateData")
}
if input.Vdi != nil {
err = self.validateVdiProtocol(*input.Vdi)
if err != nil {
return input, errors.Wrap(err, "validateVdiProtocol")
}
}
if input.Vga != nil || input.Vdi != nil {
vdi, vga := self.validateVGA(guest.Vdi, guest.Vga, input.Vdi, input.Vga)
input.Vdi = &vdi
input.Vga = &vga
}
if input.Machine != nil {
err := self.validateMachineType(*input.Machine, guest.OsArch)
if err != nil {
return input, errors.Wrap(err, "ValidateMachineType")
}
}
return input, nil
}

View File

@@ -265,31 +265,6 @@ func (self *SVirtualizedGuestDriver) RequestStopGuestForDelete(ctx context.Conte
return nil
}
func (self *SVirtualizedGuestDriver) ValidateMachineType(machine string) error {
if !utils.IsInStringArray(machine, []string{api.VM_MACHINE_TYPE_PC, api.VM_MACHINE_TYPE_Q35}) {
return httperrors.NewBadRequestError("Invalid machine %q", machine)
}
return nil
}
func (self *SVirtualizedGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
if input.Machine != "" {
if err := self.ValidateMachineType(input.Machine); err != nil {
return nil, err
}
}
return input, nil
}
func (self *SVirtualizedGuestDriver) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, input api.ServerUpdateInput) error {
if input.Machine != nil {
if err := self.ValidateMachineType(*input.Machine); err != nil {
return err
}
}
return nil
}
func (self *SVirtualizedGuestDriver) ValidateCreateDataOnHost(ctx context.Context, userCred mcclient.TokenCredential, bmName string, host *models.SHost, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
if host.HostStatus != api.HOST_ONLINE {
return nil, httperrors.NewInvalidStatusError("Host %s is not online", bmName)

View File

@@ -205,7 +205,7 @@ type IGuestDriver interface {
RequestMigrate(ctx context.Context, guest *SGuest, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, task taskman.ITask) error
RequestLiveMigrate(ctx context.Context, guest *SGuest, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, task taskman.ITask) error
ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, input api.ServerUpdateInput) error
ValidateUpdateData(ctx context.Context, guest *SGuest, userCred mcclient.TokenCredential, input api.ServerUpdateInput) (api.ServerUpdateInput, error)
RequestRemoteUpdate(ctx context.Context, guest *SGuest, userCred mcclient.TokenCredential, replaceTags bool) error
RequestOpenForward(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, req *guestdriver_types.OpenForwardRequest) (*guestdriver_types.OpenForwardResponse, error)

View File

@@ -985,43 +985,12 @@ func (self *SGuest) ValidateUpdateData(ctx context.Context, userCred mcclient.To
return input, httperrors.NewInputParameterError("name is too short")
}
if input.Vdi != nil {
if !utils.IsInStringArray(*input.Vdi, []string{"vnc", "spice"}) {
return input, httperrors.NewInputParameterError("unsupported vdi protocol")
}
}
if input.Vga != nil || input.Vdi != nil {
vdi := self.Vdi
if input.Vdi != nil {
vdi = *input.Vdi
}
if vdi != "vnc" && vdi != "spice" {
vdi = "vnc"
input.Vdi = &vdi
}
var candidateVga []string
switch vdi {
case "vnc":
candidateVga = []string{"std", "qxl", "virtio"}
case "spice":
candidateVga = []string{"qxl", "virtio"}
}
vga := self.Vga
if input.Vga != nil {
vga = *input.Vga
}
if !utils.IsInStringArray(vga, candidateVga) {
vga = candidateVga[0]
input.Vga = &vga
}
}
if err := self.GetDriver().ValidateUpdateData(ctx, userCred, input); err != nil {
return input, err
}
var err error
input, err = self.GetDriver().ValidateUpdateData(ctx, self, userCred, input)
if err != nil {
return input, errors.Wrap(err, "GetDriver().ValidateUpdateData")
}
input.VirtualResourceBaseUpdateInput, err = self.SVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, input.VirtualResourceBaseUpdateInput)
if err != nil {
return input, errors.Wrap(err, "SVirtualResourceBase.ValidateUpdateData")