mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-20 08:03:53 +08:00
Feature/floppy (#15008)
* feat(region,host): add floppy,mult cdrom * fix floppy-device Co-authored-by: huangzekeng <huangzekeng@grgbanking.com>
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
package compute
|
||||
|
||||
type GuestcdromJsonDesc struct {
|
||||
Ordinal int `json:"ordinal"`
|
||||
ImageId string `json:"image_id"`
|
||||
Path string `json:"path"`
|
||||
Name string `json:"name"`
|
||||
|
||||
23
pkg/apis/compute/floppy.go
Normal file
23
pkg/apis/compute/floppy.go
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package compute
|
||||
|
||||
type GuestfloppyJsonDesc struct {
|
||||
Ordinal int `json:"ordinal"`
|
||||
ImageId string `json:"image_id"`
|
||||
Path string `json:"path"`
|
||||
Name string `json:"name"`
|
||||
Size int64 `json:"size"`
|
||||
}
|
||||
@@ -195,6 +195,8 @@ type ServerDetails struct {
|
||||
DiskCount int `json:"disk_count"`
|
||||
// 是否支持ISO启动
|
||||
CdromSupport bool `json:"cdrom_support"`
|
||||
//是否支持Floppy启动
|
||||
FloppySupport bool `json:"floppy_support"`
|
||||
|
||||
// 磁盘大小
|
||||
// example:30720
|
||||
@@ -237,7 +239,10 @@ type ServerDetails struct {
|
||||
IsGpu bool `json:"is_gpu"`
|
||||
|
||||
// Cdrom信息
|
||||
Cdrom string `json:"cdrom,allowempty"`
|
||||
Cdrom []Cdrom `json:"cdrom"`
|
||||
|
||||
//Floppy信息
|
||||
Floppy []Floppy `json:"floppy"`
|
||||
|
||||
// 主机在伸缩组中的状态
|
||||
ScalingStatus string `json:"scaling_status"`
|
||||
@@ -246,6 +251,16 @@ type ServerDetails struct {
|
||||
ScalingGroupId string `json:"scaling_group_id"`
|
||||
}
|
||||
|
||||
type Floppy struct {
|
||||
Ordinal int `json:"ordinal"`
|
||||
Detail string `json:"detail"`
|
||||
}
|
||||
|
||||
type Cdrom struct {
|
||||
Ordinal int `json:"ordinal"`
|
||||
Detail string `json:"detail"`
|
||||
}
|
||||
|
||||
func (self ServerDetails) GetMetricTags() map[string]string {
|
||||
ret := map[string]string{
|
||||
"id": self.Id,
|
||||
@@ -758,7 +773,10 @@ type GuestJsonDesc struct {
|
||||
Nics []*GuestnetworkJsonDesc `json:"nics"`
|
||||
Disks []*GuestdiskJsonDesc `json:"disks"`
|
||||
|
||||
Cdrom *GuestcdromJsonDesc `json:"cdrom"`
|
||||
Cdrom *GuestcdromJsonDesc `json:"cdrom"`
|
||||
Cdroms []*GuestcdromJsonDesc `json:"cdroms"`
|
||||
|
||||
Floppys []*GuestfloppyJsonDesc `json:"floppys"`
|
||||
|
||||
Tenant string `json:"tenant"`
|
||||
TenantId string `json:"tenant_id"`
|
||||
@@ -924,6 +942,16 @@ type ServerSetPasswordInput struct {
|
||||
AutoStart bool
|
||||
}
|
||||
|
||||
type ServerInsertVfdInput struct {
|
||||
FloppyOrdinal int64 `json:"floppy_ordinal"`
|
||||
ImageId string `json:"image_id"`
|
||||
}
|
||||
|
||||
type ServerEjectVfdInput struct {
|
||||
FloppyOrdinal int64 `json:"floppy_ordinal"`
|
||||
ImageId string `json:"image_id"`
|
||||
}
|
||||
|
||||
type ServerSetLiveMigrateParamsInput struct {
|
||||
MaxBandwidthMB *int64
|
||||
DowntimeLimitMS *int64
|
||||
|
||||
@@ -141,6 +141,11 @@ const (
|
||||
ACT_ISO_ATTACH = "iso_attach"
|
||||
ACT_ISO_DETACH = "iso_detach"
|
||||
|
||||
ACT_VFD_PREPARING = "vfd_preparing"
|
||||
ACT_VFD_PREPARE_FAIL = "vfd_prepare_fail"
|
||||
ACT_VFD_ATTACH = "vfd_attach"
|
||||
ACT_VFD_DETACH = "vfd_detach"
|
||||
|
||||
ACT_EIP_ATTACH = "eip_attach"
|
||||
ACT_EIP_DETACH = "eip_detach"
|
||||
|
||||
|
||||
@@ -325,7 +325,7 @@ func (self *SBaremetalGuestDriver) RequestGuestHotRemoveIso(ctx context.Context,
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) RequestGuestCreateInsertIso(ctx context.Context, imageId string, guest *models.SGuest, task taskman.ITask) error {
|
||||
return guest.StartInsertIsoTask(ctx, imageId, true, guest.HostId, task.GetUserCred(), task.GetTaskId())
|
||||
return guest.StartInsertIsoTask(ctx, 0, imageId, true, guest.HostId, task.GetUserCred(), task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) RequestStartOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, userCred mcclient.TokenCredential, task taskman.ITask) error {
|
||||
@@ -611,3 +611,7 @@ func (self *SBaremetalGuestDriver) IsSupportCdrom(guest *models.SGuest) (bool, e
|
||||
}
|
||||
return ipmiInfo.CdromBoot, nil
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) IsSupportFloppy(guest *models.SGuest) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -248,6 +248,18 @@ func (self *SBaseGuestDriver) RequestRebuildRootDisk(ctx context.Context, guest
|
||||
return fmt.Errorf("Not Implement")
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) NeedRequestGuestHotAddVfd(ctx context.Context, guest *models.SGuest) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) RequestGuestHotAddVfd(ctx context.Context, guest *models.SGuest, path string, boot bool, task taskman.ITask) error {
|
||||
return fmt.Errorf("Not Implement")
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) RequestGuestHotRemoveVfd(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
|
||||
return fmt.Errorf("Not Implement")
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) RequestDiskSnapshot(ctx context.Context, guest *models.SGuest, task taskman.ITask, snapshotId, diskId string) error {
|
||||
return fmt.Errorf("Not Implement")
|
||||
}
|
||||
|
||||
@@ -80,6 +80,10 @@ func (self *SCloudpodsGuestDriver) IsSupportCdrom(guest *models.SGuest) (bool, e
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (self *SCloudpodsGuestDriver) IsSupportFloppy(guest *models.SGuest) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (self *SCloudpodsGuestDriver) IsSupportMigrate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -220,3 +220,7 @@ func (self *SContainerDriver) IsSupportGuestClone() bool {
|
||||
func (self *SContainerDriver) IsSupportCdrom(guest *models.SGuest) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (self *SContainerDriver) IsSupportFloppy(guest *models.SGuest) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -651,6 +651,18 @@ func (self *SKVMGuestDriver) RequestGuestHotRemoveIso(ctx context.Context, guest
|
||||
return guest.StartSyncTask(ctx, task.GetUserCred(), false, task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) NeedRequestGuestHotAddVfd(ctx context.Context, guest *models.SGuest) bool {
|
||||
return guest.Status == api.VM_RUNNING
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) RequestGuestHotAddVfd(ctx context.Context, guest *models.SGuest, path string, boot bool, task taskman.ITask) error {
|
||||
return guest.StartSyncTask(ctx, task.GetUserCred(), false, task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) RequestGuestHotRemoveVfd(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
|
||||
return guest.StartSyncTask(ctx, task.GetUserCred(), false, task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) RequestRebuildRootDisk(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
|
||||
subtask, err := taskman.TaskManager.NewTask(ctx, "KVMGuestRebuildRootTask", guest, task.GetUserCred(), task.GetParams(), task.GetTaskId(), "", nil)
|
||||
if err != nil {
|
||||
@@ -714,6 +726,10 @@ func (self *SKVMGuestDriver) IsSupportCdrom(guest *models.SGuest) (bool, error)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) IsSupportFloppy(guest *models.SGuest) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) IsSupportMigrate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -1189,6 +1189,10 @@ func (self *SManagedVirtualizedGuestDriver) IsSupportCdrom(guest *models.SGuest)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizedGuestDriver) IsSupportFloppy(guest *models.SGuest) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func GetCloudVMStatus(vm cloudprovider.ICloudVM) string {
|
||||
status := vm.GetStatus()
|
||||
switch status {
|
||||
|
||||
@@ -220,7 +220,7 @@ func (self *SVirtualizedGuestDriver) ChooseHostStorage(host *models.SHost, guest
|
||||
}
|
||||
|
||||
func (self *SVirtualizedGuestDriver) RequestGuestCreateInsertIso(ctx context.Context, imageId string, guest *models.SGuest, task taskman.ITask) error {
|
||||
return guest.StartInsertIsoTask(ctx, imageId, true, guest.HostId, task.GetUserCred(), task.GetTaskId())
|
||||
return guest.StartInsertIsoTask(ctx, 0, imageId, true, guest.HostId, task.GetUserCred(), task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SVirtualizedGuestDriver) StartGuestStopTask(guest *models.SGuest, ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict, parentTaskId string) error {
|
||||
|
||||
@@ -1139,18 +1139,18 @@ func (self *SGuest) StartGuestStopTask(ctx context.Context, userCred mcclient.To
|
||||
return self.GetDriver().StartGuestStopTask(self, ctx, userCred, params, parentTaskId)
|
||||
}
|
||||
|
||||
func (self *SGuest) insertIso(imageId string) bool {
|
||||
cdrom := self.getCdrom(true)
|
||||
func (self *SGuest) insertIso(imageId string, cdromOrdinal int64) bool {
|
||||
cdrom := self.getCdrom(true, cdromOrdinal)
|
||||
return cdrom.insertIso(imageId)
|
||||
}
|
||||
|
||||
func (self *SGuest) InsertIsoSucc(imageId string, path string, size int64, name string) bool {
|
||||
cdrom := self.getCdrom(false)
|
||||
func (self *SGuest) InsertIsoSucc(cdromOrdinal int64, imageId string, path string, size int64, name string) bool {
|
||||
cdrom := self.getCdrom(false, cdromOrdinal)
|
||||
return cdrom.insertIsoSucc(imageId, path, size, name)
|
||||
}
|
||||
|
||||
func (self *SGuest) GetDetailsIso(userCred mcclient.TokenCredential) jsonutils.JSONObject {
|
||||
cdrom := self.getCdrom(false)
|
||||
func (self *SGuest) GetDetailsIso(cdromOrdinal int64, userCred mcclient.TokenCredential) jsonutils.JSONObject {
|
||||
cdrom := self.getCdrom(false, cdromOrdinal)
|
||||
desc := jsonutils.NewDict()
|
||||
if len(cdrom.ImageId) > 0 {
|
||||
desc.Set("image_id", jsonutils.NewString(cdrom.ImageId))
|
||||
@@ -1168,7 +1168,11 @@ func (self *SGuest) PerformInsertiso(ctx context.Context, userCred mcclient.Toke
|
||||
if !utils.IsInStringArray(self.Hypervisor, []string{api.HYPERVISOR_KVM, api.HYPERVISOR_BAREMETAL}) {
|
||||
return nil, httperrors.NewNotAcceptableError("Not allow for hypervisor %s", self.Hypervisor)
|
||||
}
|
||||
cdrom := self.getCdrom(false)
|
||||
cdromOrdinal, _ := data.Int("cdrom_ordinal")
|
||||
if cdromOrdinal < 0 {
|
||||
return nil, httperrors.NewServerStatusError("invalid cdrom_ordinal: %d", cdromOrdinal)
|
||||
}
|
||||
cdrom := self.getCdrom(false, cdromOrdinal)
|
||||
if cdrom != nil && len(cdrom.ImageId) > 0 {
|
||||
return nil, httperrors.NewBadRequestError("CD-ROM not empty, please eject first")
|
||||
}
|
||||
@@ -1180,7 +1184,7 @@ func (self *SGuest) PerformInsertiso(ctx context.Context, userCred mcclient.Toke
|
||||
}
|
||||
|
||||
if utils.IsInStringArray(self.Status, []string{api.VM_RUNNING, api.VM_READY}) {
|
||||
err = self.StartInsertIsoTask(ctx, image.Id, false, self.HostId, userCred, "")
|
||||
err = self.StartInsertIsoTask(ctx, cdromOrdinal, image.Id, false, self.HostId, userCred, "")
|
||||
return nil, err
|
||||
} else {
|
||||
return nil, httperrors.NewServerStatusError("Insert ISO not allowed in status %s", self.Status)
|
||||
@@ -1191,20 +1195,26 @@ func (self *SGuest) PerformEjectiso(ctx context.Context, userCred mcclient.Token
|
||||
if !utils.IsInStringArray(self.Hypervisor, []string{api.HYPERVISOR_KVM, api.HYPERVISOR_BAREMETAL}) {
|
||||
return nil, httperrors.NewNotAcceptableError("Not allow for hypervisor %s", self.Hypervisor)
|
||||
}
|
||||
cdrom := self.getCdrom(false)
|
||||
cdromOrdinal, _ := data.Int("cdrom_ordinal")
|
||||
if cdromOrdinal < 0 {
|
||||
return nil, httperrors.NewServerStatusError("invalid cdrom_ordinal: %d", cdromOrdinal)
|
||||
}
|
||||
cdrom := self.getCdrom(false, cdromOrdinal)
|
||||
if cdrom == nil || len(cdrom.ImageId) == 0 {
|
||||
return nil, httperrors.NewBadRequestError("No ISO to eject")
|
||||
}
|
||||
if utils.IsInStringArray(self.Status, []string{api.VM_RUNNING, api.VM_READY}) {
|
||||
err := self.StartEjectisoTask(ctx, userCred, "")
|
||||
err := self.StartEjectisoTask(ctx, cdromOrdinal, userCred, "")
|
||||
return nil, err
|
||||
} else {
|
||||
return nil, httperrors.NewServerStatusError("Eject ISO not allowed in status %s", self.Status)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SGuest) StartEjectisoTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "GuestEjectISOTask", self, userCred, nil, parentTaskId, "", nil)
|
||||
func (self *SGuest) StartEjectisoTask(ctx context.Context, cdromOrdinal int64, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
data := jsonutils.NewDict()
|
||||
data.Add(jsonutils.NewInt(cdromOrdinal), "cdrom_ordinal")
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "GuestEjectISOTask", self, userCred, data, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1212,11 +1222,12 @@ func (self *SGuest) StartEjectisoTask(ctx context.Context, userCred mcclient.Tok
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) StartInsertIsoTask(ctx context.Context, imageId string, boot bool, hostId string, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
self.insertIso(imageId)
|
||||
func (self *SGuest) StartInsertIsoTask(ctx context.Context, cdromOrdinal int64, imageId string, boot bool, hostId string, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
self.insertIso(imageId, cdromOrdinal)
|
||||
|
||||
data := jsonutils.NewDict()
|
||||
data.Add(jsonutils.NewString(imageId), "image_id")
|
||||
data.Add(jsonutils.NewInt(cdromOrdinal), "cdrom_ordinal")
|
||||
data.Add(jsonutils.NewString(hostId), "host_id")
|
||||
if boot {
|
||||
data.Add(jsonutils.JSONTrue, "boot")
|
||||
@@ -1233,6 +1244,105 @@ func (self *SGuest) StartInsertIsoTask(ctx context.Context, imageId string, boot
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) insertVfd(imageId string, floppyOrdinal int64) bool {
|
||||
floppy := self.getFloppy(true, floppyOrdinal)
|
||||
return floppy.insertVfd(imageId)
|
||||
}
|
||||
|
||||
func (self *SGuest) InsertVfdSucc(floppyOrdinal int64, imageId string, path string, size int64, name string) bool {
|
||||
floppy := self.getFloppy(true, floppyOrdinal)
|
||||
return floppy.insertVfdSucc(imageId, path, size, name)
|
||||
}
|
||||
|
||||
func (self *SGuest) GetDetailsVfd(floppyOrdinal int64, userCred mcclient.TokenCredential) jsonutils.JSONObject {
|
||||
floppy := self.getFloppy(false, floppyOrdinal)
|
||||
desc := jsonutils.NewDict()
|
||||
if len(floppy.ImageId) > 0 {
|
||||
desc.Set("image_id", jsonutils.NewString(floppy.ImageId))
|
||||
desc.Set("status", jsonutils.NewString("inserting"))
|
||||
}
|
||||
if len(floppy.Path) > 0 {
|
||||
desc.Set("name", jsonutils.NewString(floppy.Name))
|
||||
desc.Set("size", jsonutils.NewInt(int64(floppy.Size)))
|
||||
desc.Set("status", jsonutils.NewString("ready"))
|
||||
}
|
||||
return desc
|
||||
}
|
||||
|
||||
func (self *SGuest) PerformInsertvfd(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data api.ServerInsertVfdInput) (jsonutils.JSONObject, error) {
|
||||
if !utils.IsInStringArray(self.Hypervisor, []string{api.HYPERVISOR_KVM, api.HYPERVISOR_BAREMETAL}) {
|
||||
return nil, httperrors.NewNotAcceptableError("Not allow for hypervisor %s", self.Hypervisor)
|
||||
}
|
||||
if data.FloppyOrdinal < 0 {
|
||||
return nil, httperrors.NewServerStatusError("invalid floppy_ordinal: %d", data.FloppyOrdinal)
|
||||
}
|
||||
floppy := self.getFloppy(false, data.FloppyOrdinal)
|
||||
if floppy != nil && len(floppy.ImageId) > 0 {
|
||||
return nil, httperrors.NewBadRequestError("Floppy not empty, please eject first")
|
||||
}
|
||||
image, err := parseIsoInfo(ctx, userCred, data.ImageId)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if utils.IsInStringArray(self.Status, []string{api.VM_RUNNING, api.VM_READY}) {
|
||||
err = self.StartInsertVfdTask(ctx, data.FloppyOrdinal, image.Id, false, self.HostId, userCred, "")
|
||||
return nil, err
|
||||
} else {
|
||||
return nil, httperrors.NewServerStatusError("Insert ISO not allowed in status %s", self.Status)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SGuest) PerformEjectvfd(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data api.ServerEjectVfdInput) (jsonutils.JSONObject, error) {
|
||||
if !utils.IsInStringArray(self.Hypervisor, []string{api.HYPERVISOR_KVM, api.HYPERVISOR_BAREMETAL}) {
|
||||
return nil, httperrors.NewNotAcceptableError("Not allow for hypervisor %s", self.Hypervisor)
|
||||
}
|
||||
if data.FloppyOrdinal < 0 {
|
||||
return nil, httperrors.NewServerStatusError("invalid floppy_ordinal: %d", data.FloppyOrdinal)
|
||||
}
|
||||
floppy := self.getFloppy(false, data.FloppyOrdinal)
|
||||
if floppy == nil || len(floppy.ImageId) == 0 {
|
||||
return nil, httperrors.NewBadRequestError("No VFD to eject")
|
||||
}
|
||||
if utils.IsInStringArray(self.Status, []string{api.VM_RUNNING, api.VM_READY}) {
|
||||
err := self.StartEjectvfdTask(ctx, userCred, "")
|
||||
return nil, err
|
||||
} else {
|
||||
return nil, httperrors.NewServerStatusError("Eject ISO not allowed in status %s", self.Status)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SGuest) StartEjectvfdTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "GuestEjectVFDTask", self, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) StartInsertVfdTask(ctx context.Context, floppyOrdinal int64, imageId string, boot bool, hostId string, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
self.insertVfd(imageId, floppyOrdinal)
|
||||
|
||||
data := jsonutils.NewDict()
|
||||
data.Add(jsonutils.NewString(imageId), "image_id")
|
||||
data.Add(jsonutils.NewString(hostId), "host_id")
|
||||
if boot {
|
||||
data.Add(jsonutils.JSONTrue, "boot")
|
||||
}
|
||||
taskName := "GuestInsertVfdTask"
|
||||
if self.BackupHostId != "" {
|
||||
taskName = "HaGuestInsertVfdTask"
|
||||
}
|
||||
task, err := taskman.TaskManager.NewTask(ctx, taskName, self, userCred, data, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) StartGueststartTask(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
data *jsonutils.JSONDict, parentTaskId string,
|
||||
@@ -2126,7 +2236,6 @@ func (self *SGuest) attachIsolatedDevice(ctx context.Context, userCred mcclient.
|
||||
return fmt.Errorf("Isolated device already attached to another guest: %s", dev.GuestId)
|
||||
}
|
||||
if dev.HostId !=
|
||||
|
||||
self.HostId {
|
||||
return fmt.Errorf("Isolated device and guest are not located in the same host")
|
||||
}
|
||||
@@ -4631,9 +4740,17 @@ func (self *SGuest) validateForBatchMigrate(ctx context.Context, rescueMode bool
|
||||
return guest, httperrors.NewBadRequestError("guest %s status %s can't migrate", guest.Name, guest.Status)
|
||||
}
|
||||
if guest.Status == api.VM_RUNNING {
|
||||
cdrom := guest.getCdrom(false)
|
||||
if cdrom != nil && len(cdrom.ImageId) > 0 {
|
||||
return guest, httperrors.NewBadRequestError("cannot migrate with cdrom")
|
||||
cdroms, _ := guest.getCdroms()
|
||||
for _, cdrom := range cdroms {
|
||||
if len(cdrom.ImageId) > 0 {
|
||||
return guest, httperrors.NewBadRequestError("cannot migrate with cdrom")
|
||||
}
|
||||
}
|
||||
floppys, _ := guest.getFloppys()
|
||||
for _, floppy := range floppys {
|
||||
if len(floppy.ImageId) > 0 {
|
||||
return guest, httperrors.NewBadRequestError("cannot migrate with floppy")
|
||||
}
|
||||
}
|
||||
} else if guest.Status == api.VM_UNKNOWN {
|
||||
if guest.getDefaultStorageType() == api.STORAGE_LOCAL {
|
||||
|
||||
@@ -222,12 +222,25 @@ func (manager *SGuestManager) FetchCustomizeColumns(
|
||||
gcds := fetchGuestCdroms(guestIds)
|
||||
if gcds != nil {
|
||||
for i := range rows {
|
||||
if gcd, ok := gcds[guestIds[i]]; ok {
|
||||
rows[i].Cdrom = gcd.GetDetails()
|
||||
for _, gcd := range gcds[guestIds[i]] {
|
||||
t := api.Cdrom{Ordinal: gcd.Ordinal, Detail: gcd.GetDetails()}
|
||||
rows[i].Cdrom = append(rows[i].Cdrom, t)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(fields) == 0 || fields.Contains("floppy") {
|
||||
gfloppys := fetchGuestFloppys(guestIds)
|
||||
if gfloppys != nil {
|
||||
for i := range rows {
|
||||
for _, gfl := range gfloppys[guestIds[i]] {
|
||||
t := api.Floppy{Ordinal: gfl.Ordinal, Detail: gfl.GetDetails()}
|
||||
rows[i].Floppy = append(rows[i].Floppy, t)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(fields) == 0 || fields.Contains("scaling_group") {
|
||||
sggs := fetchScalingGroupGuest(guestIds...)
|
||||
if sggs != nil && len(sggs) != 0 {
|
||||
@@ -691,16 +704,30 @@ func fetchGuestIsolatedDevices(guestIds []string) map[string][]api.SIsolatedDevi
|
||||
return ret
|
||||
}
|
||||
|
||||
func fetchGuestCdroms(guestIds []string) map[string]SGuestcdrom {
|
||||
func fetchGuestCdroms(guestIds []string) map[string][]SGuestcdrom {
|
||||
q := GuestcdromManager.Query().In("id", guestIds)
|
||||
gcds := make([]SGuestcdrom, 0)
|
||||
err := q.All(&gcds)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
ret := make(map[string]SGuestcdrom)
|
||||
ret := make(map[string][]SGuestcdrom)
|
||||
for i := range gcds {
|
||||
ret[gcds[i].Id] = gcds[i]
|
||||
ret[gcds[i].Id] = append(ret[gcds[i].Id], gcds[i])
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func fetchGuestFloppys(guestIds []string) map[string][]SGuestfloppy {
|
||||
q := GuestFloppyManager.Query().In("id", guestIds)
|
||||
gfls := make([]SGuestfloppy, 0)
|
||||
err := q.All(&gfls)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
ret := make(map[string][]SGuestfloppy)
|
||||
for i := range gfls {
|
||||
ret[gfls[i].Id] = append(ret[gfls[i].Id], gfls[i])
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -47,7 +47,9 @@ func init() {
|
||||
type SGuestcdrom struct {
|
||||
db.SModelBase
|
||||
|
||||
Id string `width:"36" charset:"ascii" primary:"true"` // = Column(VARCHAR(36, charset='ascii'), primary_key=True)
|
||||
RowId int64 `primary:"true" auto_increment:"true" list:"user"`
|
||||
Ordinal int `nullable:"false" default:"0"` // = Column(Integer, nullable=False, default=0)
|
||||
Id string `width:"36" charset:"ascii"` // = Column(VARCHAR(36, charset='ascii'), primary_key=True)
|
||||
ImageId string `width:"36" charset:"ascii" nullable:"true"` // Column(VARCHAR(36, charset='ascii'), nullable=True)
|
||||
Name string `width:"64" charset:"ascii" nullable:"true"` // Column(VARCHAR(64, charset='ascii'), nullable=True)
|
||||
Path string `width:"256" charset:"ascii" nullable:"true"` // Column(VARCHAR(256, charset='ascii'), nullable=True)
|
||||
@@ -127,6 +129,7 @@ func (self *SGuestcdrom) GetDetails() string {
|
||||
func (self *SGuestcdrom) getJsonDesc() *api.GuestcdromJsonDesc {
|
||||
if len(self.ImageId) > 0 && len(self.Path) > 0 {
|
||||
return &api.GuestcdromJsonDesc{
|
||||
Ordinal: self.Ordinal,
|
||||
ImageId: self.ImageId,
|
||||
Path: self.Path,
|
||||
Name: self.Name,
|
||||
|
||||
@@ -169,6 +169,10 @@ type IGuestDriver interface {
|
||||
RequestGuestHotRemoveIso(ctx context.Context, guest *SGuest, task taskman.ITask) error
|
||||
RequestRebuildRootDisk(ctx context.Context, guest *SGuest, task taskman.ITask) error
|
||||
|
||||
NeedRequestGuestHotAddVfd(ctx context.Context, guest *SGuest) bool
|
||||
RequestGuestHotAddVfd(ctx context.Context, guest *SGuest, path string, boot bool, task taskman.ITask) error
|
||||
RequestGuestHotRemoveVfd(ctx context.Context, guest *SGuest, task taskman.ITask) error
|
||||
|
||||
RequestDiskSnapshot(ctx context.Context, guest *SGuest, task taskman.ITask, snapshotId, diskId string) error
|
||||
RequestDeleteSnapshot(ctx context.Context, guest *SGuest, task taskman.ITask, params *jsonutils.JSONDict) error
|
||||
RequestReloadDiskSnapshot(ctx context.Context, guest *SGuest, task taskman.ITask, params *jsonutils.JSONDict) error
|
||||
@@ -193,6 +197,7 @@ type IGuestDriver interface {
|
||||
CancelExpireTime(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest) error
|
||||
|
||||
IsSupportCdrom(guest *SGuest) (bool, error)
|
||||
IsSupportFloppy(guest *SGuest) (bool, error)
|
||||
IsSupportPublicipToEip() bool
|
||||
RequestConvertPublicipToEip(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, task taskman.ITask) error
|
||||
|
||||
|
||||
140
pkg/compute/models/guestfloppy.go
Normal file
140
pkg/compute/models/guestfloppy.go
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/log"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
)
|
||||
|
||||
// +onecloud:swagger-gen-ignore
|
||||
type SGuestFloppyManager struct {
|
||||
db.SModelBaseManager
|
||||
}
|
||||
|
||||
var GuestFloppyManager *SGuestFloppyManager
|
||||
|
||||
func init() {
|
||||
GuestFloppyManager = &SGuestFloppyManager{
|
||||
SModelBaseManager: db.NewModelBaseManager(
|
||||
SGuestfloppy{},
|
||||
"guestfloppy_tbl",
|
||||
"guestfloppy",
|
||||
"guestfloppys",
|
||||
),
|
||||
}
|
||||
GuestFloppyManager.SetVirtualObject(GuestFloppyManager)
|
||||
}
|
||||
|
||||
// +onecloud:swagger-gen-ignore
|
||||
type SGuestfloppy struct {
|
||||
db.SModelBase
|
||||
|
||||
RowId int64 `primary:"true" auto_increment:"true" list:"user"`
|
||||
Id string `width:"36" charset:"ascii" ` // = Column(VARCHAR(36, charset='ascii'), primary_key=True)
|
||||
Ordinal int `nullable:"false" default:"0"` // = Column(Integer, nullable=False, default=0)
|
||||
ImageId string `width:"36" charset:"ascii" nullable:"true"` // Column(VARCHAR(36, charset='ascii'), nullable=True)
|
||||
Name string `width:"64" charset:"ascii" nullable:"true"` // Column(VARCHAR(64, charset='ascii'), nullable=True)
|
||||
Path string `width:"256" charset:"ascii" nullable:"true"` // Column(VARCHAR(256, charset='ascii'), nullable=True)
|
||||
Size int64 `nullable:"false" default:"0"` // = Column(Integer, nullable=False, default=0)
|
||||
UpdatedAt time.Time `nullable:"false" updated_at:"true" nullable:"false"`
|
||||
UpdateVersion int `default:"0" nullable:"false" auto_version:"true"`
|
||||
}
|
||||
|
||||
func (self *SGuestfloppy) insertVfd(imageId string) bool {
|
||||
if len(self.ImageId) == 0 {
|
||||
_, err := db.Update(self, func() error {
|
||||
self.ImageId = imageId
|
||||
self.Name = ""
|
||||
self.Path = ""
|
||||
self.Size = 0
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("insertVfd saveupdate fail: %s", err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SGuestfloppy) insertVfdSucc(imageId string, path string, size int64, name string) bool {
|
||||
if self.ImageId == imageId {
|
||||
_, err := db.Update(self, func() error {
|
||||
self.Name = name
|
||||
self.Path = path
|
||||
self.Size = size
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("insertIsoSucc saveUpdate fail %s", err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SGuestfloppy) ejectVfd() bool {
|
||||
if len(self.ImageId) > 0 {
|
||||
_, err := db.Update(self, func() error {
|
||||
self.ImageId = ""
|
||||
self.Name = ""
|
||||
self.Path = ""
|
||||
self.Size = 0
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("ejectVfd saveUpdate fail %s", err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SGuestfloppy) GetDetails() string {
|
||||
if len(self.ImageId) > 0 {
|
||||
if self.Size > 0 {
|
||||
return fmt.Sprintf("%s(%s/%dMB)", self.Name, self.ImageId, self.Size)
|
||||
} else {
|
||||
return fmt.Sprintf("%s(inserting)", self.ImageId)
|
||||
}
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SGuestfloppy) getJsonDesc() *api.GuestfloppyJsonDesc {
|
||||
if len(self.ImageId) > 0 && len(self.Path) > 0 {
|
||||
return &api.GuestfloppyJsonDesc{
|
||||
Ordinal: self.Ordinal,
|
||||
ImageId: self.ImageId,
|
||||
Path: self.Path,
|
||||
Name: self.Name,
|
||||
Size: self.Size,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -2227,6 +2227,7 @@ func (self *SGuest) moreExtraInfo(
|
||||
}
|
||||
|
||||
out.CdromSupport, _ = self.GetDriver().IsSupportCdrom(self)
|
||||
out.FloppySupport, _ = self.GetDriver().IsSupportFloppy(self)
|
||||
|
||||
return out
|
||||
}
|
||||
@@ -2336,18 +2337,19 @@ func (self *SGuest) getNetworksDetails() string {
|
||||
}
|
||||
|
||||
func (self *SGuest) GetCdrom() *SGuestcdrom {
|
||||
return self.getCdrom(false)
|
||||
return self.getCdrom(false, 0)
|
||||
}
|
||||
|
||||
func (self *SGuest) getCdrom(create bool) *SGuestcdrom {
|
||||
func (self *SGuest) getCdrom(create bool, ordinal int64) *SGuestcdrom {
|
||||
cdrom := SGuestcdrom{}
|
||||
cdrom.SetModelManager(GuestcdromManager, &cdrom)
|
||||
|
||||
err := GuestcdromManager.Query().Equals("id", self.Id).First(&cdrom)
|
||||
err := GuestcdromManager.Query().Equals("id", self.Id).Equals("ordinal", ordinal).First(&cdrom)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
if create {
|
||||
cdrom.Id = self.Id
|
||||
cdrom.Ordinal = int(ordinal)
|
||||
err = GuestcdromManager.TableSpec().Insert(context.TODO(), &cdrom)
|
||||
if err != nil {
|
||||
log.Errorf("insert cdrom fail %s", err)
|
||||
@@ -2366,6 +2368,54 @@ func (self *SGuest) getCdrom(create bool) *SGuestcdrom {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SGuest) getCdroms() ([]SGuestcdrom, error) {
|
||||
cdroms := make([]SGuestcdrom, 0)
|
||||
q := GuestcdromManager.Query().Equals("id", self.Id)
|
||||
err := db.FetchModelObjects(GuestcdromManager, q, &cdroms)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return cdroms, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) getFloppys() ([]SGuestfloppy, error) {
|
||||
floppys := make([]SGuestfloppy, 0)
|
||||
q := GuestFloppyManager.Query().Equals("id", self.Id)
|
||||
err := db.FetchModelObjects(GuestFloppyManager, q, &floppys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return floppys, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) getFloppy(create bool, ordinal int64) *SGuestfloppy {
|
||||
floppy := SGuestfloppy{}
|
||||
floppy.SetModelManager(GuestFloppyManager, &floppy)
|
||||
|
||||
err := GuestFloppyManager.Query().Equals("id", self.Id).Equals("ordinal", ordinal).First(&floppy)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
if create {
|
||||
floppy.Id = self.Id
|
||||
floppy.Ordinal = int(ordinal)
|
||||
err = GuestFloppyManager.TableSpec().Insert(context.TODO(), &floppy)
|
||||
if err != nil {
|
||||
log.Errorf("insert cdrom fail %s", err)
|
||||
return nil
|
||||
}
|
||||
return &floppy
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
log.Errorf("getFloppy query fail %s", err)
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
return &floppy
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SGuest) getKeypair() *SKeypair {
|
||||
if len(self.KeypairId) > 0 {
|
||||
keypair, _ := KeypairManager.FetchById(self.KeypairId)
|
||||
@@ -4088,8 +4138,8 @@ func (self *SGuest) DetachAllNetworks(ctx context.Context, userCred mcclient.Tok
|
||||
return GuestnetworkManager.DeleteGuestNics(ctx, userCred, gns, false)
|
||||
}
|
||||
|
||||
func (self *SGuest) EjectIso(userCred mcclient.TokenCredential) bool {
|
||||
cdrom := self.getCdrom(false)
|
||||
func (self *SGuest) EjectIso(cdromOrdinal int64, userCred mcclient.TokenCredential) bool {
|
||||
cdrom := self.getCdrom(false, cdromOrdinal)
|
||||
if cdrom != nil && len(cdrom.ImageId) > 0 {
|
||||
imageId := cdrom.ImageId
|
||||
if cdrom.ejectIso() {
|
||||
@@ -4100,6 +4150,48 @@ func (self *SGuest) EjectIso(userCred mcclient.TokenCredential) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SGuest) EjectAllIso(userCred mcclient.TokenCredential) bool {
|
||||
cdroms, _ := self.getCdroms()
|
||||
for _, cdrom := range cdroms {
|
||||
if len(cdrom.ImageId) > 0 {
|
||||
imageId := cdrom.ImageId
|
||||
if cdrom.ejectIso() {
|
||||
db.OpsLog.LogEvent(self, db.ACT_ISO_DETACH, imageId, userCred)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SGuest) EjectVfd(floppyOrdinal int64, userCred mcclient.TokenCredential) bool {
|
||||
floppy := self.getFloppy(false, floppyOrdinal)
|
||||
if floppy != nil && len(floppy.ImageId) > 0 {
|
||||
imageId := floppy.ImageId
|
||||
if floppy.ejectVfd() {
|
||||
db.OpsLog.LogEvent(self, db.ACT_VFD_DETACH, imageId, userCred)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SGuest) EjectAllVfd(userCred mcclient.TokenCredential) bool {
|
||||
floppys, _ := self.getFloppys()
|
||||
for _, floppy := range floppys {
|
||||
if len(floppy.ImageId) > 0 {
|
||||
imageId := floppy.ImageId
|
||||
if floppy.ejectVfd() {
|
||||
db.OpsLog.LogEvent(self, db.ACT_ISO_DETACH, imageId, userCred)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SGuest) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
// self.SVirtualResourceBase.Delete(ctx, userCred)
|
||||
// override
|
||||
@@ -4421,10 +4513,17 @@ func (self *SGuest) GetJsonDescAtHypervisor(ctx context.Context, host *SHost) *a
|
||||
desc.Disks = append(desc.Disks, diskDesc)
|
||||
}
|
||||
|
||||
// cdrom
|
||||
cdrom := self.getCdrom(false)
|
||||
if cdrom != nil {
|
||||
desc.Cdrom = cdrom.getJsonDesc()
|
||||
cdroms, _ := self.getCdroms()
|
||||
for _, cdrom := range cdroms {
|
||||
cdromDesc := cdrom.getJsonDesc()
|
||||
desc.Cdroms = append(desc.Cdroms, cdromDesc)
|
||||
}
|
||||
|
||||
//floppy
|
||||
floppys, _ := self.getFloppys()
|
||||
for _, floppy := range floppys {
|
||||
floppyDesc := floppy.getJsonDesc()
|
||||
desc.Floppys = append(desc.Floppys, floppyDesc)
|
||||
}
|
||||
|
||||
// tenant
|
||||
@@ -5631,7 +5730,7 @@ func (self *SGuest) toCreateInput() *api.ServerCreateInput {
|
||||
r := new(api.ServerCreateInput)
|
||||
r.VmemSize = self.VmemSize
|
||||
r.VcpuCount = int(self.VcpuCount)
|
||||
if guestCdrom := self.getCdrom(false); guestCdrom != nil {
|
||||
if guestCdrom := self.getCdrom(false, 0); guestCdrom != nil {
|
||||
r.Cdrom = guestCdrom.ImageId
|
||||
}
|
||||
r.Vga = self.Vga
|
||||
|
||||
@@ -127,7 +127,8 @@ func (guest *SGuest) purge(ctx context.Context, userCred mcclient.TokenCredentia
|
||||
guest.RevokeAllSecgroups(ctx, userCred)
|
||||
guest.LeaveAllGroups(ctx, userCred)
|
||||
guest.DetachAllNetworks(ctx, userCred)
|
||||
guest.EjectIso(userCred)
|
||||
guest.EjectAllIso(userCred)
|
||||
guest.EjectAllVfd(userCred)
|
||||
guest.DeleteEip(ctx, userCred)
|
||||
guest.purgeInstanceSnapshots(ctx, userCred)
|
||||
guest.DeleteAllDisksInDB(ctx, userCred)
|
||||
|
||||
@@ -63,6 +63,7 @@ func InitHandlers(app *appsrv.Application) {
|
||||
db.SharedResourceManager,
|
||||
db.I18nManager,
|
||||
models.GuestcdromManager,
|
||||
models.GuestFloppyManager,
|
||||
models.NetInterfaceManager,
|
||||
|
||||
models.QuotaManager,
|
||||
|
||||
@@ -359,7 +359,7 @@ func (self *GuestCreateBackupTask) StartCreateBackupDisks(ctx context.Context, g
|
||||
|
||||
func (self *GuestCreateBackupTask) StartInsertIso(ctx context.Context, guest *models.SGuest, imageId string) {
|
||||
self.SetStage("OnInsertIso", nil)
|
||||
guest.StartInsertIsoTask(ctx, imageId, false, guest.BackupHostId, self.UserCred, self.GetTaskId())
|
||||
guest.StartInsertIsoTask(ctx, 0, imageId, false, guest.BackupHostId, self.UserCred, self.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *GuestCreateBackupTask) OnInsertIso(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
|
||||
@@ -332,7 +332,8 @@ func (self *GuestDeleteTask) OnGuestDeleteCompleteFailed(ctx context.Context, ob
|
||||
func (self *GuestDeleteTask) OnGuestDeleteComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
guest.DetachAllNetworks(ctx, self.UserCred)
|
||||
guest.EjectIso(self.UserCred)
|
||||
guest.EjectAllIso(self.UserCred)
|
||||
guest.EjectAllVfd(self.UserCred)
|
||||
guest.DeleteEip(ctx, self.UserCred)
|
||||
guest.GetDriver().OnDeleteGuestFinalCleanup(ctx, guest, self.UserCred)
|
||||
// sync capacity used for storage
|
||||
|
||||
@@ -39,7 +39,8 @@ func (self *GuestEjectISOTask) OnInit(ctx context.Context, obj db.IStandaloneMod
|
||||
|
||||
func (self *GuestEjectISOTask) startEjectIso(ctx context.Context, obj db.IStandaloneModel) {
|
||||
guest := obj.(*models.SGuest)
|
||||
if guest.EjectIso(self.UserCred) && guest.Status == api.VM_RUNNING {
|
||||
cdromOrdinal, _ := self.Params.Int("cdrom_ordinal")
|
||||
if guest.EjectIso(cdromOrdinal, self.UserCred) && guest.Status == api.VM_RUNNING {
|
||||
self.SetStage("OnConfigSyncComplete", nil)
|
||||
guest.GetDriver().RequestGuestHotRemoveIso(ctx, guest, self)
|
||||
} else {
|
||||
|
||||
53
pkg/compute/tasks/guest_eject_vfd_task.go
Normal file
53
pkg/compute/tasks/guest_eject_vfd_task.go
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
type GuestEjectVFDTask struct {
|
||||
SGuestBaseTask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(GuestEjectVFDTask{})
|
||||
}
|
||||
|
||||
func (self *GuestEjectVFDTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
self.startEjectVfd(ctx, obj)
|
||||
}
|
||||
|
||||
func (self *GuestEjectVFDTask) startEjectVfd(ctx context.Context, obj db.IStandaloneModel) {
|
||||
guest := obj.(*models.SGuest)
|
||||
floppyOrdinal, _ := self.Params.Int("floppy_ordinal")
|
||||
if guest.EjectVfd(floppyOrdinal, self.UserCred) && guest.Status == api.VM_RUNNING {
|
||||
self.SetStage("OnConfigSyncComplete", nil)
|
||||
guest.GetDriver().RequestGuestHotRemoveVfd(ctx, guest, self)
|
||||
} else {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *GuestEjectVFDTask) OnConfigSyncComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -41,6 +41,7 @@ func (self *GuestInsertIsoTask) OnInit(ctx context.Context, obj db.IStandaloneMo
|
||||
func (self *GuestInsertIsoTask) prepareIsoImage(ctx context.Context, obj db.IStandaloneModel) {
|
||||
guest := obj.(*models.SGuest)
|
||||
imageId, _ := self.Params.GetString("image_id")
|
||||
cdromOrdinal, _ := self.Params.Int("cdrom_ordinal")
|
||||
db.OpsLog.LogEvent(obj, db.ACT_ISO_PREPARING, imageId, self.UserCred)
|
||||
|
||||
disks, _ := guest.GetGuestDisks()
|
||||
@@ -57,7 +58,7 @@ func (self *GuestInsertIsoTask) prepareIsoImage(ctx context.Context, obj db.ISta
|
||||
}
|
||||
storageCache.StartImageCacheTask(ctx, self.UserCred, input)
|
||||
} else {
|
||||
guest.EjectIso(self.UserCred)
|
||||
guest.EjectIso(cdromOrdinal, self.UserCred)
|
||||
db.OpsLog.LogEvent(obj, db.ACT_ISO_PREPARE_FAIL, imageId, self.UserCred)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString("host no local storage cache"))
|
||||
}
|
||||
@@ -65,14 +66,16 @@ func (self *GuestInsertIsoTask) prepareIsoImage(ctx context.Context, obj db.ISta
|
||||
|
||||
func (self *GuestInsertIsoTask) OnIsoPrepareCompleteFailed(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
imageId, _ := self.Params.GetString("image_id")
|
||||
cdromOrdinal, _ := self.Params.Int("cdrom_ordinal")
|
||||
db.OpsLog.LogEvent(obj, db.ACT_ISO_PREPARE_FAIL, imageId, self.UserCred)
|
||||
guest := obj.(*models.SGuest)
|
||||
guest.EjectIso(self.UserCred)
|
||||
guest.EjectIso(cdromOrdinal, self.UserCred)
|
||||
self.SetStageFailed(ctx, data)
|
||||
}
|
||||
|
||||
func (self *GuestInsertIsoTask) OnIsoPrepareComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
imageId, _ := data.GetString("image_id")
|
||||
cdromOrdinal, _ := self.Params.Int("cdrom_ordinal")
|
||||
size, err := data.Int("size")
|
||||
if err != nil {
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
@@ -81,8 +84,8 @@ func (self *GuestInsertIsoTask) OnIsoPrepareComplete(ctx context.Context, obj db
|
||||
name, _ := data.GetString("name")
|
||||
path, _ := data.GetString("path")
|
||||
guest := obj.(*models.SGuest)
|
||||
if guest.InsertIsoSucc(imageId, path, size, name) {
|
||||
db.OpsLog.LogEvent(guest, db.ACT_ISO_ATTACH, guest.GetDetailsIso(self.UserCred), self.UserCred)
|
||||
if guest.InsertIsoSucc(cdromOrdinal, imageId, path, size, name) {
|
||||
db.OpsLog.LogEvent(guest, db.ACT_ISO_ATTACH, guest.GetDetailsIso(cdromOrdinal, self.UserCred), self.UserCred)
|
||||
if guest.GetDriver().NeedRequestGuestHotAddIso(ctx, guest) {
|
||||
self.SetStage("OnConfigSyncComplete", nil)
|
||||
boot := jsonutils.QueryBoolean(self.Params, "boot", false)
|
||||
@@ -110,6 +113,7 @@ func (self *HaGuestInsertIsoTask) OnInit(ctx context.Context, obj db.IStandalone
|
||||
func (self *HaGuestInsertIsoTask) prepareIsoImage(ctx context.Context, obj db.IStandaloneModel) {
|
||||
guest := obj.(*models.SGuest)
|
||||
imageId, _ := self.Params.GetString("image_id")
|
||||
cdromOrdinal, _ := self.Params.Int("cdrom_ordinal")
|
||||
db.OpsLog.LogEvent(obj, db.ACT_ISO_PREPARING, imageId, self.UserCred)
|
||||
disks, _ := guest.GetGuestDisks()
|
||||
disk := disks[0].GetDisk()
|
||||
@@ -124,7 +128,7 @@ func (self *HaGuestInsertIsoTask) prepareIsoImage(ctx context.Context, obj db.IS
|
||||
}
|
||||
storageCache.StartImageCacheTask(ctx, self.UserCred, input)
|
||||
} else {
|
||||
guest.EjectIso(self.UserCred)
|
||||
guest.EjectIso(cdromOrdinal, self.UserCred)
|
||||
db.OpsLog.LogEvent(obj, db.ACT_ISO_PREPARE_FAIL, imageId, self.UserCred)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString("host no local storage cache"))
|
||||
}
|
||||
|
||||
147
pkg/compute/tasks/guest_insert_vfd_task.go
Normal file
147
pkg/compute/tasks/guest_insert_vfd_task.go
Normal file
@@ -0,0 +1,147 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
type GuestInsertVfdTask struct {
|
||||
SGuestBaseTask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(GuestInsertVfdTask{})
|
||||
taskman.RegisterTask(HaGuestInsertVfdTask{})
|
||||
}
|
||||
|
||||
func (self *GuestInsertVfdTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
self.prepareVfdImage(ctx, obj)
|
||||
}
|
||||
|
||||
func (self *GuestInsertVfdTask) prepareVfdImage(ctx context.Context, obj db.IStandaloneModel) {
|
||||
guest := obj.(*models.SGuest)
|
||||
imageId, _ := self.Params.GetString("image_id")
|
||||
floppyOrdinal, _ := self.Params.Int("floppy_ordinal")
|
||||
db.OpsLog.LogEvent(obj, db.ACT_VFD_PREPARING, imageId, self.UserCred)
|
||||
|
||||
disks, _ := guest.GetGuestDisks()
|
||||
disk := disks[0].GetDisk()
|
||||
storage, _ := disk.GetStorage()
|
||||
storageCache := storage.GetStoragecache()
|
||||
|
||||
if storageCache != nil {
|
||||
self.SetStage("OnVfdPrepareComplete", nil)
|
||||
input := api.CacheImageInput{
|
||||
ImageId: imageId,
|
||||
Format: "raw",
|
||||
ParentTaskId: self.GetTaskId(),
|
||||
}
|
||||
storageCache.StartImageCacheTask(ctx, self.UserCred, input)
|
||||
} else {
|
||||
guest.EjectVfd(floppyOrdinal, self.UserCred)
|
||||
db.OpsLog.LogEvent(obj, db.ACT_VFD_PREPARE_FAIL, imageId, self.UserCred)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString("host no local storage cache"))
|
||||
}
|
||||
}
|
||||
|
||||
func (self *GuestInsertVfdTask) OnVfdPrepareCompleteFailed(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
imageId, _ := self.Params.GetString("image_id")
|
||||
floppyOrdinal, _ := self.Params.Int("floppy_ordinal")
|
||||
db.OpsLog.LogEvent(obj, db.ACT_VFD_PREPARE_FAIL, imageId, self.UserCred)
|
||||
guest := obj.(*models.SGuest)
|
||||
guest.EjectVfd(floppyOrdinal, self.UserCred)
|
||||
self.SetStageFailed(ctx, data)
|
||||
}
|
||||
|
||||
func (self *GuestInsertVfdTask) OnVfdPrepareComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
floppyOrdinal, _ := self.Params.Int("floppy_ordinal")
|
||||
imageId, _ := data.GetString("image_id")
|
||||
size, err := data.Int("size")
|
||||
if err != nil {
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
return
|
||||
}
|
||||
name, _ := data.GetString("name")
|
||||
path, _ := data.GetString("path")
|
||||
guest := obj.(*models.SGuest)
|
||||
if guest.InsertVfdSucc(floppyOrdinal, imageId, path, size, name) {
|
||||
db.OpsLog.LogEvent(guest, db.ACT_VFD_ATTACH, guest.GetDetailsVfd(floppyOrdinal, self.UserCred), self.UserCred)
|
||||
if guest.GetDriver().NeedRequestGuestHotAddVfd(ctx, guest) {
|
||||
self.SetStage("OnConfigSyncComplete", nil)
|
||||
boot := jsonutils.QueryBoolean(self.Params, "boot", false)
|
||||
guest.GetDriver().RequestGuestHotAddVfd(ctx, guest, path, boot, self)
|
||||
} else {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
} else {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *GuestInsertVfdTask) OnConfigSyncComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
type HaGuestInsertVfdTask struct {
|
||||
GuestInsertVfdTask
|
||||
}
|
||||
|
||||
func (self *HaGuestInsertVfdTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
self.prepareVfdImage(ctx, obj)
|
||||
}
|
||||
|
||||
func (self *HaGuestInsertVfdTask) prepareVfdImage(ctx context.Context, obj db.IStandaloneModel) {
|
||||
guest := obj.(*models.SGuest)
|
||||
imageId, _ := self.Params.GetString("image_id")
|
||||
floppyOrdinal, _ := self.Params.Int("floppy_ordinal")
|
||||
db.OpsLog.LogEvent(obj, db.ACT_VFD_PREPARING, imageId, self.UserCred)
|
||||
disks, _ := guest.GetGuestDisks()
|
||||
disk := disks[0].GetDisk()
|
||||
storage := disk.GetBackupStorage()
|
||||
storageCache := storage.GetStoragecache()
|
||||
if storageCache != nil {
|
||||
self.SetStage("OnBackupVfdPrepareComplete", nil)
|
||||
input := api.CacheImageInput{
|
||||
ImageId: imageId,
|
||||
Format: "raw",
|
||||
ParentTaskId: self.GetTaskId(),
|
||||
}
|
||||
storageCache.StartImageCacheTask(ctx, self.UserCred, input)
|
||||
} else {
|
||||
guest.EjectVfd(floppyOrdinal, self.UserCred)
|
||||
db.OpsLog.LogEvent(obj, db.ACT_VFD_PREPARE_FAIL, imageId, self.UserCred)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString("host no local storage cache"))
|
||||
}
|
||||
}
|
||||
|
||||
func (self *HaGuestInsertVfdTask) OnBackupVfdPrepareComplete(
|
||||
ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject,
|
||||
) {
|
||||
self.GuestInsertVfdTask.prepareVfdImage(ctx, guest)
|
||||
}
|
||||
|
||||
func (self *HaGuestInsertVfdTask) OnBackupVfdPrepareCompleteFailed(
|
||||
ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject,
|
||||
) {
|
||||
self.OnVfdPrepareCompleteFailed(ctx, guest, data)
|
||||
}
|
||||
@@ -26,6 +26,7 @@ type Arch interface {
|
||||
GenerateMemDesc() *desc.SGuestMem
|
||||
GenerateMachineDesc(accel string) *desc.SGuestMachine
|
||||
GenerateCdromDesc(osName string, cdrom *desc.SGuestCdrom)
|
||||
GenerateFloppyDesc(osName string, floppy *desc.SGuestFloppy)
|
||||
GenerateQgaDesc(qgaPath string) *desc.SGuestQga
|
||||
GeneratePvpanicDesc() *desc.SGuestPvpanic
|
||||
GenerateIsaSerialDesc() *desc.SGuestIsaSerial
|
||||
|
||||
@@ -47,6 +47,10 @@ func (*ARM) GenerateCdromDesc(osName string, cdrom *desc.SGuestCdrom) {
|
||||
cdrom.Id = "cd0"
|
||||
}
|
||||
|
||||
func (*ARM) GenerateFloppyDesc(osName string, floppy *desc.SGuestFloppy) {
|
||||
|
||||
}
|
||||
|
||||
func (*ARM) GenerateMachineDesc(accel string) *desc.SGuestMachine {
|
||||
gicVersion := "max"
|
||||
return &desc.SGuestMachine{
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
package arch
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestman/desc"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestman/qemu"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
@@ -62,7 +64,7 @@ func (*X86) GenerateCdromDesc(osName string, cdrom *desc.SGuestCdrom) {
|
||||
"snapshot": "on",
|
||||
}
|
||||
default:
|
||||
id = "ide0-cd0"
|
||||
id = fmt.Sprintf("ide%d-cd0", cdrom.Ordinal)
|
||||
devType = "ide-cd"
|
||||
driveOpts = map[string]string{
|
||||
"if": "none",
|
||||
@@ -77,6 +79,27 @@ func (*X86) GenerateCdromDesc(osName string, cdrom *desc.SGuestCdrom) {
|
||||
cdrom.Id = id
|
||||
}
|
||||
|
||||
//-device floppy,drive=floppy0 -drive id=floppy0,if=none
|
||||
func (*X86) GenerateFloppyDesc(osName string, floppy *desc.SGuestFloppy) {
|
||||
var id, devType string
|
||||
var driveOpts map[string]string
|
||||
|
||||
switch osName {
|
||||
case qemu.OS_NAME_WINDOWS:
|
||||
id = fmt.Sprintf("floppy%d", floppy.Ordinal)
|
||||
devType = "floppy"
|
||||
driveOpts = map[string]string{
|
||||
"if": "none",
|
||||
}
|
||||
floppy.Floppy = &desc.FloppyDevice{
|
||||
DevType: devType,
|
||||
}
|
||||
floppy.DriveOptions = driveOpts
|
||||
floppy.Id = id
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (*X86) GenerateMachineDesc(accel string) *desc.SGuestMachine {
|
||||
return &desc.SGuestMachine{
|
||||
Accel: accel,
|
||||
|
||||
@@ -91,7 +91,8 @@ type SGuestHardwareDesc struct {
|
||||
|
||||
VirtioScsi *SGuestVirtioScsi `json:",omitempty"`
|
||||
PvScsi *SGuestPvScsi `json:",omitempty"`
|
||||
Cdrom *SGuestCdrom `json:",omitempty"`
|
||||
Cdroms []*SGuestCdrom `json:"cdroms,omitempty"`
|
||||
Floppys []*SGuestFloppy `json:",omitempty"`
|
||||
Disks []*SGuestDisk `json:",omitempty"`
|
||||
Nics []*SGuestNetwork `json:",omitempty"`
|
||||
NicsStandby []*SGuestNetwork `json:",omitempty"`
|
||||
@@ -167,14 +168,24 @@ type SGuestDisk struct {
|
||||
// -drive id=MacDVD,if=none,snapshot=on,file=%s
|
||||
|
||||
type SGuestCdrom struct {
|
||||
Id string
|
||||
Path string
|
||||
Id string
|
||||
Path string
|
||||
Ordinal int64
|
||||
|
||||
Ide *IDEDevice `json:",omitempty"`
|
||||
Scsi *SCSIDevice `json:",omitempty"`
|
||||
DriveOptions map[string]string `json:",omitempty"`
|
||||
}
|
||||
|
||||
type SGuestFloppy struct {
|
||||
Id string
|
||||
Path string
|
||||
Ordinal int64
|
||||
|
||||
Floppy *FloppyDevice `json:",omitempty"`
|
||||
DriveOptions map[string]string `json:",omitempty"`
|
||||
}
|
||||
|
||||
type SGuestNetwork struct {
|
||||
api.GuestnetworkJsonDesc
|
||||
Pci *PCIDevice `json:",omitempty"`
|
||||
|
||||
@@ -129,6 +129,19 @@ type IDEDevice struct {
|
||||
Options map[string]string `json:",omitempty"`
|
||||
}
|
||||
|
||||
type FloppyAddr struct {
|
||||
Bus uint
|
||||
Controller uint
|
||||
}
|
||||
|
||||
type FloppyDevice struct {
|
||||
*FloppyAddr
|
||||
|
||||
Id string
|
||||
DevType string
|
||||
Options map[string]string `json:",omitempty"`
|
||||
}
|
||||
|
||||
type Object struct {
|
||||
ObjType string
|
||||
Id string
|
||||
|
||||
@@ -221,15 +221,16 @@ type SGuestDiskSyncTask struct {
|
||||
guest *SKVMGuestInstance
|
||||
delDisks []*desc.SGuestDisk
|
||||
addDisks []*desc.SGuestDisk
|
||||
cdrom *string
|
||||
cdroms []*desc.SGuestCdrom
|
||||
floppys []*desc.SGuestFloppy
|
||||
errors []error
|
||||
|
||||
callback func(...error)
|
||||
checkDrivers []string
|
||||
}
|
||||
|
||||
func NewGuestDiskSyncTask(guest *SKVMGuestInstance, delDisks, addDisks []*desc.SGuestDisk, cdrom *string) *SGuestDiskSyncTask {
|
||||
return &SGuestDiskSyncTask{guest, delDisks, addDisks, cdrom, make([]error, 0), nil, nil}
|
||||
func NewGuestDiskSyncTask(guest *SKVMGuestInstance, delDisks, addDisks []*desc.SGuestDisk, cdroms []*desc.SGuestCdrom, floppys []*desc.SGuestFloppy) *SGuestDiskSyncTask {
|
||||
return &SGuestDiskSyncTask{guest, delDisks, addDisks, cdroms, floppys, make([]error, 0), nil, nil}
|
||||
}
|
||||
|
||||
func (d *SGuestDiskSyncTask) Start(callback func(...error)) {
|
||||
@@ -250,9 +251,15 @@ func (d *SGuestDiskSyncTask) syncDisksConf() {
|
||||
d.addDisk(disk)
|
||||
return
|
||||
}
|
||||
if d.cdrom != nil {
|
||||
d.changeCdrom()
|
||||
return
|
||||
if len(d.cdroms) > 0 {
|
||||
cdrom := d.cdroms[len(d.cdroms)-1]
|
||||
d.cdroms = d.cdroms[:len(d.cdroms)-1]
|
||||
d.changeCdrom(cdrom)
|
||||
}
|
||||
if len(d.floppys) > 0 {
|
||||
floppy := d.floppys[len(d.floppys)-1]
|
||||
d.floppys = d.floppys[:len(d.floppys)-1]
|
||||
d.changeFloppy(floppy)
|
||||
}
|
||||
if idxs := d.guest.GetNeedMergeBackingFileDiskIndexs(); len(idxs) > 0 {
|
||||
d.guest.StreamDisks(context.Background(),
|
||||
@@ -262,40 +269,113 @@ func (d *SGuestDiskSyncTask) syncDisksConf() {
|
||||
d.callback(d.errors...)
|
||||
}
|
||||
|
||||
func (d *SGuestDiskSyncTask) changeCdrom() {
|
||||
d.guest.Monitor.GetBlocks(d.onGetBlockInfo)
|
||||
func (d *SGuestDiskSyncTask) changeCdrom(cdrom *desc.SGuestCdrom) {
|
||||
d.guest.Monitor.GetBlocks(func(blocks []monitor.QemuBlock) {
|
||||
var cdName string
|
||||
for _, r := range blocks {
|
||||
if regexp.MustCompile(fmt.Sprintf(`^ide%d-cd\d+$`, cdrom.Ordinal)).MatchString(r.Device) {
|
||||
cdName = r.Device
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(cdName) > 0 {
|
||||
d.changeCdromContent(cdName, cdrom)
|
||||
} else {
|
||||
cdrom.Path = ""
|
||||
d.syncDisksConf()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (d *SGuestDiskSyncTask) onGetBlockInfo(blocks []monitor.QemuBlock) {
|
||||
var cdName string
|
||||
for _, r := range blocks {
|
||||
if regexp.MustCompile(`^ide\d+-cd\d+$`).MatchString(r.Device) {
|
||||
cdName = r.Device
|
||||
break
|
||||
func (d *SGuestDiskSyncTask) changeCdromContent(cdName string, cdrom *desc.SGuestCdrom) {
|
||||
if cdrom.Path == "" {
|
||||
d.guest.Monitor.EjectCdrom(cdName, func(s string) {
|
||||
d.OnEjectCdromContentSucc(cdName)
|
||||
})
|
||||
} else {
|
||||
d.guest.Monitor.ChangeCdrom(cdName, cdrom.Path, func(s string) {
|
||||
d.OnChangeCdromContentSucc(cdrom)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (d *SGuestDiskSyncTask) OnEjectCdromContentSucc(cdName string) {
|
||||
for i, cdrom := range d.guest.Desc.Cdroms {
|
||||
if cdrom.Id == cdName {
|
||||
d.guest.Desc.Cdroms[i].Path = ""
|
||||
}
|
||||
}
|
||||
if len(cdName) > 0 {
|
||||
d.changeCdromContent(cdName)
|
||||
d.syncDisksConf()
|
||||
}
|
||||
|
||||
func (d *SGuestDiskSyncTask) OnChangeCdromContentSucc(cdrom *desc.SGuestCdrom) {
|
||||
if d.guest.Desc.Cdroms == nil {
|
||||
d.guest.Desc.Cdroms = make([]*desc.SGuestCdrom, options.HostOptions.CdromCount)
|
||||
for i := range d.guest.Desc.Cdroms {
|
||||
d.guest.Desc.Cdroms[i] = new(desc.SGuestCdrom)
|
||||
d.guest.Desc.Cdroms[i].Ordinal = int64(i)
|
||||
}
|
||||
}
|
||||
for i := range d.guest.Desc.Cdroms {
|
||||
if cdrom.Ordinal == d.guest.Desc.Cdroms[i].Ordinal {
|
||||
d.guest.Desc.Cdroms[i] = cdrom
|
||||
}
|
||||
}
|
||||
d.syncDisksConf()
|
||||
}
|
||||
|
||||
func (d *SGuestDiskSyncTask) changeFloppy(floppy *desc.SGuestFloppy) {
|
||||
d.guest.Monitor.GetBlocks(func(blocks []monitor.QemuBlock) {
|
||||
var flName string
|
||||
for _, r := range blocks {
|
||||
if regexp.MustCompile(fmt.Sprintf(`^floppy%d$`, floppy.Ordinal)).MatchString(r.Device) {
|
||||
flName = r.Device
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(flName) > 0 {
|
||||
d.changeFloppyContent(flName, floppy)
|
||||
} else {
|
||||
floppy.Path = ""
|
||||
d.syncDisksConf()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (d *SGuestDiskSyncTask) changeFloppyContent(flName string, floppy *desc.SGuestFloppy) {
|
||||
if floppy.Path == "" {
|
||||
d.guest.Monitor.EjectCdrom(flName, func(s string) {
|
||||
d.OnEjectFloppyContentSucc(flName)
|
||||
})
|
||||
} else {
|
||||
d.cdrom = nil
|
||||
d.syncDisksConf()
|
||||
d.guest.Monitor.ChangeCdrom(flName, floppy.Path, func(s string) {
|
||||
d.OnChangeFloppyContentSucc(floppy)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (d *SGuestDiskSyncTask) changeCdromContent(cdName string) {
|
||||
if *d.cdrom == "" {
|
||||
d.guest.Monitor.EjectCdrom(cdName, d.OnChangeCdromContentSucc)
|
||||
} else {
|
||||
d.guest.Monitor.ChangeCdrom(cdName, *d.cdrom, d.OnChangeCdromContentSucc)
|
||||
func (d *SGuestDiskSyncTask) OnEjectFloppyContentSucc(flName string) {
|
||||
for i, floppy := range d.guest.Desc.Floppys {
|
||||
if floppy.Id == flName {
|
||||
d.guest.Desc.Floppys[i].Path = ""
|
||||
}
|
||||
}
|
||||
d.syncDisksConf()
|
||||
}
|
||||
|
||||
func (d *SGuestDiskSyncTask) OnChangeCdromContentSucc(results string) {
|
||||
if d.guest.Desc.Cdrom == nil {
|
||||
d.guest.Desc.Cdrom = new(desc.SGuestCdrom)
|
||||
func (d *SGuestDiskSyncTask) OnChangeFloppyContentSucc(floppy *desc.SGuestFloppy) {
|
||||
if d.guest.Desc.Floppys == nil {
|
||||
d.guest.Desc.Floppys = make([]*desc.SGuestFloppy, options.HostOptions.FloppyCount)
|
||||
for i := range d.guest.Desc.Floppys {
|
||||
d.guest.Desc.Floppys[i] = new(desc.SGuestFloppy)
|
||||
d.guest.Desc.Floppys[i].Ordinal = int64(i)
|
||||
}
|
||||
}
|
||||
for i := range d.guest.Desc.Floppys {
|
||||
if floppy.Ordinal == d.guest.Desc.Floppys[i].Ordinal {
|
||||
d.guest.Desc.Floppys[i] = floppy
|
||||
}
|
||||
}
|
||||
d.guest.Desc.Cdrom.Path = *d.cdrom
|
||||
d.cdrom = nil
|
||||
d.syncDisksConf()
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ func (s *SKVMGuestInstance) initGuestDesc() error {
|
||||
s.initVirtioSerial(pciRoot)
|
||||
s.initGuestVga(pciRoot)
|
||||
s.initCdromDesc()
|
||||
s.initFloppyDesc()
|
||||
s.initGuestDisks(pciRoot, pciBridge)
|
||||
if err = s.initGuestNetworks(pciRoot, pciBridge); err != nil {
|
||||
return errors.Wrap(err, "init guest networks")
|
||||
@@ -327,11 +328,32 @@ func (s *SKVMGuestInstance) initIsolatedDevices(pciRoot, pciBridge *desc.PCICont
|
||||
}
|
||||
|
||||
func (s *SKVMGuestInstance) initCdromDesc() {
|
||||
if s.Desc.Cdrom == nil {
|
||||
s.Desc.Cdrom = new(desc.SGuestCdrom)
|
||||
if s.Desc.Cdroms == nil {
|
||||
s.Desc.Cdroms = make([]*desc.SGuestCdrom, options.HostOptions.CdromCount)
|
||||
for i := range s.Desc.Cdroms {
|
||||
s.Desc.Cdroms[i] = new(desc.SGuestCdrom)
|
||||
s.Desc.Cdroms[i].Ordinal = int64(i)
|
||||
}
|
||||
}
|
||||
for i := range s.Desc.Cdroms {
|
||||
s.archMan.GenerateCdromDesc(s.getOsname(), s.Desc.Cdroms[i])
|
||||
}
|
||||
}
|
||||
|
||||
s.archMan.GenerateCdromDesc(s.getOsname(), s.Desc.Cdrom)
|
||||
func (s *SKVMGuestInstance) initFloppyDesc() {
|
||||
if s.getOsname() != OS_NAME_WINDOWS {
|
||||
return
|
||||
}
|
||||
if s.Desc.Floppys == nil {
|
||||
s.Desc.Floppys = make([]*desc.SGuestFloppy, options.HostOptions.FloppyCount)
|
||||
for i := range s.Desc.Floppys {
|
||||
s.Desc.Floppys[i] = new(desc.SGuestFloppy)
|
||||
s.Desc.Floppys[i].Ordinal = int64(i)
|
||||
}
|
||||
}
|
||||
for i := range s.Desc.Floppys {
|
||||
s.archMan.GenerateFloppyDesc(s.getOsname(), s.Desc.Floppys[i])
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SKVMGuestInstance) initGuestDisks(pciRoot, pciBridge *desc.PCIController) {
|
||||
|
||||
@@ -1688,26 +1688,60 @@ func (s *SKVMGuestInstance) compareDescIsolatedDevices(newDesc *desc.SGuestDesc,
|
||||
return delDevs, addDevs
|
||||
}
|
||||
|
||||
func (s *SKVMGuestInstance) compareDescCdrom(newDesc *desc.SGuestDesc) *string {
|
||||
newCdromIsNil := newDesc.Cdrom == nil || newDesc.Cdrom.Path == ""
|
||||
oldCdromIsNil := s.Desc.Cdrom == nil || s.Desc.Cdrom.Path == ""
|
||||
func (s *SKVMGuestInstance) compareDescCdroms(newDesc *desc.SGuestDesc) []*desc.SGuestCdrom {
|
||||
var changeCdroms []*desc.SGuestCdrom
|
||||
newCdroms := newDesc.Cdroms
|
||||
for i := 0; i < options.HostOptions.CdromCount; i++ {
|
||||
changeCdrom := new(desc.SGuestCdrom)
|
||||
changeCdrom.Ordinal = int64(i)
|
||||
changeCdrom.Path = ""
|
||||
s.archMan.GenerateCdromDesc(s.getOsname(), changeCdrom)
|
||||
changeCdroms = append(changeCdroms, changeCdrom)
|
||||
}
|
||||
|
||||
if oldCdromIsNil && newCdromIsNil {
|
||||
return nil
|
||||
} else if oldCdromIsNil && !newCdromIsNil {
|
||||
cdromPath := newDesc.Cdrom.Path
|
||||
return &cdromPath
|
||||
} else if !oldCdromIsNil && newCdromIsNil {
|
||||
var res = ""
|
||||
return &res
|
||||
} else {
|
||||
if s.Desc.Cdrom.Path == newDesc.Cdrom.Path {
|
||||
return nil
|
||||
} else {
|
||||
cdromPath := newDesc.Cdrom.Path
|
||||
return &cdromPath
|
||||
for _, newCdrom := range newCdroms {
|
||||
ordinal := newCdrom.Ordinal
|
||||
path := newCdrom.Path
|
||||
changeCdrom := new(desc.SGuestCdrom)
|
||||
changeCdrom.Ordinal = ordinal
|
||||
changeCdrom.Path = path
|
||||
s.archMan.GenerateCdromDesc(s.getOsname(), changeCdrom)
|
||||
for i, tmp := range changeCdroms {
|
||||
if tmp.Ordinal == ordinal {
|
||||
changeCdroms[i] = changeCdrom
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return changeCdroms
|
||||
}
|
||||
|
||||
func (s *SKVMGuestInstance) compareDescFloppys(newDesc *desc.SGuestDesc) []*desc.SGuestFloppy {
|
||||
var changeFloppys []*desc.SGuestFloppy
|
||||
newFloppys := newDesc.Floppys
|
||||
for i := 0; i < options.HostOptions.FloppyCount; i++ {
|
||||
changeFloppy := new(desc.SGuestFloppy)
|
||||
changeFloppy.Ordinal = int64(i)
|
||||
changeFloppy.Path = ""
|
||||
s.archMan.GenerateFloppyDesc(s.getOsname(), changeFloppy)
|
||||
changeFloppys = append(changeFloppys, changeFloppy)
|
||||
}
|
||||
|
||||
for _, newFloppy := range newFloppys {
|
||||
ordinal := newFloppy.Ordinal
|
||||
path := newFloppy.Path
|
||||
changeFloppy := new(desc.SGuestFloppy)
|
||||
changeFloppy.Ordinal = ordinal
|
||||
changeFloppy.Path = path
|
||||
s.archMan.GenerateFloppyDesc(s.getOsname(), changeFloppy)
|
||||
for i, tmp := range changeFloppys { //如果新增的跟changeCdrom重叠,则以新增为准
|
||||
if tmp.Ordinal == ordinal {
|
||||
changeFloppys[i] = changeFloppy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return changeFloppys
|
||||
}
|
||||
|
||||
func (s *SKVMGuestInstance) compareDescNetworks(newDesc *desc.SGuestDesc,
|
||||
@@ -1824,7 +1858,8 @@ func (s *SKVMGuestInstance) SyncConfig(
|
||||
var delNetworks, addNetworks []*desc.SGuestNetwork
|
||||
var changedNetworks [][2]*desc.SGuestNetwork
|
||||
var delDevs, addDevs []*desc.SGuestIsolatedDevice
|
||||
var cdrom *string
|
||||
var cdroms []*desc.SGuestCdrom
|
||||
var floppys []*desc.SGuestFloppy
|
||||
|
||||
if err := s.SaveSourceDesc(guestDesc); err != nil {
|
||||
return nil, err
|
||||
@@ -1832,7 +1867,8 @@ func (s *SKVMGuestInstance) SyncConfig(
|
||||
|
||||
if !fwOnly && !s.isImportFromLibvirt() {
|
||||
delDisks, addDisks = s.compareDescDisks(guestDesc)
|
||||
cdrom = s.compareDescCdrom(guestDesc)
|
||||
cdroms = s.compareDescCdroms(guestDesc)
|
||||
floppys = s.compareDescFloppys(guestDesc)
|
||||
delNetworks, addNetworks, changedNetworks = s.compareDescNetworks(guestDesc)
|
||||
delDevs, addDevs = s.compareDescIsolatedDevices(guestDesc)
|
||||
}
|
||||
@@ -1868,8 +1904,8 @@ func (s *SKVMGuestInstance) SyncConfig(
|
||||
var runTaskNames = []jsonutils.JSONObject{}
|
||||
var tasks = []IGuestTasks{}
|
||||
|
||||
if len(delDisks)+len(addDisks) > 0 || cdrom != nil {
|
||||
task := NewGuestDiskSyncTask(s, delDisks, addDisks, cdrom)
|
||||
if len(delDisks)+len(addDisks) > 0 || cdroms != nil || floppys != nil {
|
||||
task := NewGuestDiskSyncTask(s, delDisks, addDisks, cdroms, floppys)
|
||||
runTaskNames = append(runTaskNames, jsonutils.NewString("disksync"))
|
||||
tasks = append(tasks, task)
|
||||
}
|
||||
|
||||
@@ -301,32 +301,58 @@ func getDiskDeviceOption(optDrv QemuOptions, disk *desc.SGuestDisk) string {
|
||||
return optDrv.Device(opt)
|
||||
}
|
||||
|
||||
func generateCdromOptions(optDrv QemuOptions, cdrom *desc.SGuestCdrom) []string {
|
||||
func generateCdromOptions(optDrv QemuOptions, cdroms []*desc.SGuestCdrom) []string {
|
||||
opts := make([]string, 0)
|
||||
|
||||
//cdromDriveId := cdrom
|
||||
driveOpt := fmt.Sprintf("id=%s", cdrom.Id)
|
||||
driveOpt += optionsToString(cdrom.DriveOptions)
|
||||
for _, cdrom := range cdroms {
|
||||
//cdromDriveId := cdrom
|
||||
driveOpt := fmt.Sprintf("id=%s", cdrom.Id)
|
||||
driveOpt += optionsToString(cdrom.DriveOptions)
|
||||
|
||||
var cdromPath = cdrom.Path
|
||||
if len(cdromPath) > 0 {
|
||||
driveOpt += fmt.Sprintf(",file=%s", cdromPath)
|
||||
}
|
||||
|
||||
if cdrom.Ide != nil {
|
||||
opts = append(opts, optDrv.Drive(driveOpt))
|
||||
devOpt := fmt.Sprintf("%s,drive=%s,bus=ide.1",
|
||||
cdrom.Ide.DevType, cdrom.Id)
|
||||
// TODO: ,bus=ide.%d,unit=%d
|
||||
//, cdrom.Ide.Bus, cdrom.Ide.Unit)
|
||||
opts = append(opts, optDrv.Device(devOpt))
|
||||
} else if cdrom.Scsi != nil {
|
||||
var cdromPath = cdrom.Path
|
||||
if len(cdromPath) > 0 {
|
||||
driveOpt += fmt.Sprintf(",file=%s", cdromPath)
|
||||
}
|
||||
|
||||
if cdrom.Ide != nil {
|
||||
opts = append(opts, optDrv.Drive(driveOpt))
|
||||
devOpt := fmt.Sprintf("%s,drive=%s,bus=ide.1",
|
||||
cdrom.Ide.DevType, cdrom.Id)
|
||||
// TODO: ,bus=ide.%d,unit=%d
|
||||
//, cdrom.Ide.Bus, cdrom.Ide.Unit)
|
||||
opts = append(opts, optDrv.Device(devOpt))
|
||||
} else if cdrom.Scsi != nil {
|
||||
if len(cdromPath) > 0 {
|
||||
opts = append(opts, optDrv.Drive(driveOpt))
|
||||
|
||||
devOpt := fmt.Sprintf("%s,drive=%s", cdrom.Scsi.DevType, cdrom.Id)
|
||||
devOpt += optionsToString(cdrom.Scsi.Options)
|
||||
devOpt := fmt.Sprintf("%s,drive=%s", cdrom.Scsi.DevType, cdrom.Id)
|
||||
devOpt += optionsToString(cdrom.Scsi.Options)
|
||||
|
||||
opts = append(opts, optDrv.Device(devOpt))
|
||||
}
|
||||
}
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
func generateFloppyOptions(optDrv QemuOptions, floppys []*desc.SGuestFloppy) []string {
|
||||
opts := make([]string, 0)
|
||||
|
||||
for _, floppy := range floppys {
|
||||
driveOpt := fmt.Sprintf("id=%s", floppy.Id)
|
||||
driveOpt += optionsToString(floppy.DriveOptions)
|
||||
|
||||
var floppyPath = floppy.Path
|
||||
if len(floppyPath) > 0 {
|
||||
driveOpt += fmt.Sprintf(",file=%s", floppyPath)
|
||||
}
|
||||
|
||||
if floppy.Floppy != nil {
|
||||
opts = append(opts, optDrv.Drive(driveOpt))
|
||||
devOpt := fmt.Sprintf("%s,drive=%s",
|
||||
floppy.Floppy.DevType, floppy.Id)
|
||||
// TODO: ,bus=ide.%d,unit=%d
|
||||
//, cdrom.Ide.Bus, cdrom.Ide.Unit)
|
||||
opts = append(opts, optDrv.Device(devOpt))
|
||||
}
|
||||
}
|
||||
@@ -585,9 +611,14 @@ func GenerateStartOptions(
|
||||
|
||||
// bootOrder
|
||||
enableMenu := false
|
||||
if input.GuestDesc.Cdrom != nil && input.GuestDesc.Cdrom.Path != "" {
|
||||
enableMenu = true
|
||||
if len(input.GuestDesc.Cdroms) > 0 {
|
||||
for _, cdrom := range input.GuestDesc.Cdroms {
|
||||
if cdrom.Path != "" {
|
||||
enableMenu = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
opts = append(opts, drvOpt.Boot(input.GuestDesc.BootOrder, enableMenu))
|
||||
|
||||
// bios
|
||||
@@ -641,7 +672,10 @@ func GenerateStartOptions(
|
||||
opts = append(opts, generateDisksOptions(drvOpt, input.GuestDesc.Disks, isEncrypt)...)
|
||||
|
||||
// cdrom
|
||||
opts = append(opts, generateCdromOptions(drvOpt, input.GuestDesc.Cdrom)...)
|
||||
opts = append(opts, generateCdromOptions(drvOpt, input.GuestDesc.Cdroms)...)
|
||||
|
||||
//floppy
|
||||
opts = append(opts, generateFloppyOptions(drvOpt, input.GuestDesc.Floppys)...)
|
||||
|
||||
// generate nics
|
||||
nicOpts, err := generateNicOptions(drvOpt, input)
|
||||
|
||||
@@ -31,6 +31,9 @@ type SHostBaseOptions struct {
|
||||
HostCpuPassthrough bool `default:"true" help:"if it is true, set qemu cpu type as -cpu host, otherwise, qemu64. default is true"`
|
||||
|
||||
DefaultQemuVersion string `help:"Default qemu version" default:"4.2.0"`
|
||||
|
||||
CdromCount int `help:"cdrom count" default:"1"`
|
||||
FloppyCount int `help:"floppy count" default:"1"`
|
||||
}
|
||||
|
||||
type SHostOptions struct {
|
||||
|
||||
Reference in New Issue
Block a user