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:
Davidzkeng
2022-09-27 21:15:52 +08:00
committed by GitHub
co-authored by huangzekeng
parent 3a9f2de4ee
commit bbaaf2da7e
35 changed files with 1052 additions and 125 deletions
+5 -1
View File
@@ -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
}
+12
View File
@@ -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")
}
+4
View File
@@ -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
}
+4
View File
@@ -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
}
+16
View File
@@ -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 {
+1 -1
View File
@@ -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 {
+135 -18
View File
@@ -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 {
+32 -5
View File
@@ -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
}
+4 -1
View File
@@ -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,
+5
View File
@@ -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
View 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
}
+109 -10
View File
@@ -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
+2 -1
View File
@@ -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)
+1
View File
@@ -63,6 +63,7 @@ func InitHandlers(app *appsrv.Application) {
db.SharedResourceManager,
db.I18nManager,
models.GuestcdromManager,
models.GuestFloppyManager,
models.NetInterfaceManager,
models.QuotaManager,
+1 -1
View File
@@ -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) {
+2 -1
View File
@@ -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
+2 -1
View File
@@ -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
View 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)
}
+9 -5
View File
@@ -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
View 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)
}