From 852d6ad343e940be1f08145b89be3f6b78a504d4 Mon Sep 17 00:00:00 2001 From: TangBin Date: Tue, 29 Jan 2019 10:20:26 +0800 Subject: [PATCH 1/9] fix rule validate --- pkg/util/huawei/securitygroup.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/util/huawei/securitygroup.go b/pkg/util/huawei/securitygroup.go index ce685575db..ead715c452 100644 --- a/pkg/util/huawei/securitygroup.go +++ b/pkg/util/huawei/securitygroup.go @@ -196,7 +196,7 @@ func (self *SSecurityGroup) GetSecurityRule(ruleId string, withRuleId bool) (sec } // todo: icmp 可能不兼容 rule := secrules.SecurityRule{ - Priority: 0, + Priority: 1, Action: secrules.SecurityRuleAllow, IPNet: ipNet, Protocol: protocol, From 459a358ed100d76ef1a6bc165800558aa662c088 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Wed, 30 Jan 2019 00:40:54 +0800 Subject: [PATCH 2/9] =?UTF-8?q?Feature=EF=BC=9Aadd=20kvm=20online=20resize?= =?UTF-8?q?=20disk=20handlers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../diskhandler.go | 40 ++++++---- .../guesthandler.go | 77 ++++++++++--------- pkg/hostman/guestman/guestman.go | 15 +++- pkg/hostman/guestman/guesttasks.go | 47 +++++++++++ pkg/hostman/guestman/qemu-kvm.go | 5 ++ pkg/hostman/host_services.go | 6 +- pkg/hostman/monitor/hmp.go | 7 +- pkg/hostman/monitor/monitor.go | 4 +- pkg/hostman/monitor/qmp.go | 21 +++-- 9 files changed, 155 insertions(+), 67 deletions(-) rename pkg/hostman/{storageman => diskhandlers}/diskhandler.go (73%) rename pkg/hostman/{guestman => guesthandlers}/guesthandler.go (81%) diff --git a/pkg/hostman/storageman/diskhandler.go b/pkg/hostman/diskhandlers/diskhandler.go similarity index 73% rename from pkg/hostman/storageman/diskhandler.go rename to pkg/hostman/diskhandlers/diskhandler.go index dc4532fd14..dd7369f4e8 100644 --- a/pkg/hostman/storageman/diskhandler.go +++ b/pkg/hostman/diskhandlers/diskhandler.go @@ -1,4 +1,4 @@ -package storageman +package diskhandlers import ( "context" @@ -13,6 +13,8 @@ import ( "yunion.io/x/onecloud/pkg/hostman/hostutils" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient/auth" + "yunion.io/x/onecloud/pkg/hostman/guestman" + "yunion.io/x/onecloud/pkg/hostman/storageman" ) var ( @@ -28,7 +30,7 @@ var ( } ) -type actionFunc func(context.Context, IStorage, string, IDisk, jsonutils.JSONObject) (interface{}, error) +type actionFunc func(context.Context, storageman.IStorage, string, storageman.IDisk, jsonutils.JSONObject) (interface{}, error) func AddDiskHandler(prefix string, app *appsrv.Application) { for _, keyWord := range keyWords { @@ -70,7 +72,7 @@ func performImageCache( httperrors.MissingParameterError(w, "disk") return } - storagecache := storageManager.GetStoragecacheById(scId) + storagecache := storageman.GetManager().GetStoragecacheById(scId) if storagecache == nil { httperrors.NotFoundError(w, "Storagecache %s not found", scId) return @@ -102,7 +104,7 @@ func saveToGlance(ctx context.Context, w http.ResponseWriter, r *http.Request) { storageId = params[""] diskInfo, _ = body.Get("disk") ) - storage := storageManager.GetStorage(storageId) + storage := storageman.GetManager().GetStorage(storageId) if storage == nil { hostutils.Response(ctx, w, httperrors.NewNotFoundError("Storage %s not found", storageId)) return @@ -131,7 +133,7 @@ func perfomrDiskActions(ctx context.Context, w http.ResponseWriter, r *http.Requ hostutils.Response(ctx, w, httperrors.NewNotFoundError("Not found")) return } - storage := storageManager.GetStorage(storageId) + storage := storageman.GetManager().GetStorage(storageId) if storage == nil { hostutils.Response(ctx, w, httperrors.NewNotFoundError("Storage %s not found", storageId)) return @@ -152,17 +154,17 @@ func perfomrDiskActions(ctx context.Context, w http.ResponseWriter, r *http.Requ } } -func diskCreate(ctx context.Context, storage IStorage, diskId string, disk IDisk, body jsonutils.JSONObject) (interface{}, error) { +func diskCreate(ctx context.Context, storage storageman.IStorage, diskId string, disk storageman.IDisk, body jsonutils.JSONObject) (interface{}, error) { diskInfo, err := body.Get("disk") if err != nil { return nil, httperrors.NewMissingParameterError("disk") } hostutils.DelayTask(ctx, storage.CreateDiskByDiskinfo, - &SDiskCreateByDiskinfo{diskId, disk, diskInfo, storage}) + &storageman.SDiskCreateByDiskinfo{diskId, disk, diskInfo, storage}) return nil, nil } -func diskDelete(ctx context.Context, storage IStorage, diskId string, disk IDisk, body jsonutils.JSONObject) (interface{}, error) { +func diskDelete(ctx context.Context, storage storageman.IStorage, diskId string, disk storageman.IDisk, body jsonutils.JSONObject) (interface{}, error) { if disk != nil { hostutils.DelayTask(ctx, disk.Delete, nil) } else { @@ -171,16 +173,22 @@ func diskDelete(ctx context.Context, storage IStorage, diskId string, disk IDisk return nil, nil } -func diskResize(ctx context.Context, storage IStorage, diskId string, disk IDisk, body jsonutils.JSONObject) (interface{}, error) { +func diskResize(ctx context.Context, storage storageman.IStorage, diskId string, disk storageman.IDisk, body jsonutils.JSONObject) (interface{}, error) { diskInfo, err := body.Get("disk") if err != nil { return nil, httperrors.NewMissingParameterError("disk") } - hostutils.DelayTask(ctx, disk.Resize, diskInfo) - return nil, nil + serverId, _ := diskInfo.GetString("server_id") + if len(serverId) > 0 && guestman.GetGuestManager().Status(serverId) == "running" { + sizeMb, _ := diskInfo.Int("size") + return guestman.GetGuestManager().OnlineResizeDisk(ctx, serverId, diskId, sizeMb) + } else { + hostutils.DelayTask(ctx, disk.Resize, diskInfo) + return nil, nil + } } -func diskSavePrepare(ctx context.Context, storage IStorage, diskId string, disk IDisk, body jsonutils.JSONObject) (interface{}, error) { +func diskSavePrepare(ctx context.Context, storage storageman.IStorage, diskId string, disk storageman.IDisk, body jsonutils.JSONObject) (interface{}, error) { diskInfo, err := body.Get("disk") if err != nil { return nil, httperrors.NewMissingParameterError("disk") @@ -189,7 +197,7 @@ func diskSavePrepare(ctx context.Context, storage IStorage, diskId string, disk return nil, nil } -func diskReset(ctx context.Context, storage IStorage, diskId string, disk IDisk, body jsonutils.JSONObject) (interface{}, error) { +func diskReset(ctx context.Context, storage storageman.IStorage, diskId string, disk storageman.IDisk, body jsonutils.JSONObject) (interface{}, error) { snapshotId, err := body.GetString("snapshot_id") if err != nil { return nil, httperrors.NewMissingParameterError("snapshot_id") @@ -198,7 +206,7 @@ func diskReset(ctx context.Context, storage IStorage, diskId string, disk IDisk, if err != nil { return nil, httperrors.NewMissingParameterError("out_of_chain") } - hostutils.DelayTask(ctx, disk.ResetFromSnapshot, &SDiskReset{snapshotId, outOfChain}) + hostutils.DelayTask(ctx, disk.ResetFromSnapshot, &storageman.SDiskReset{snapshotId, outOfChain}) return nil, nil } @@ -211,7 +219,7 @@ func diskReset(ctx context.Context, storage IStorage, diskId string, disk IDisk, // return nil, nil // } -func diskCleanupSnapshots(ctx context.Context, storage IStorage, diskId string, disk IDisk, body jsonutils.JSONObject) (interface{}, error) { +func diskCleanupSnapshots(ctx context.Context, storage storageman.IStorage, diskId string, disk storageman.IDisk, body jsonutils.JSONObject) (interface{}, error) { convertSnapshots, err := body.GetArray("convert_snapshots") if err != nil { return nil, httperrors.NewMissingParameterError("convert_snapshots") @@ -220,6 +228,6 @@ func diskCleanupSnapshots(ctx context.Context, storage IStorage, diskId string, if err != nil { return nil, httperrors.NewMissingParameterError("delete_snapshots") } - hostutils.DelayTask(ctx, disk.CleanupSnapshots, &SDiskCleanupSnapshots{convertSnapshots, deleteSnapshots}) + hostutils.DelayTask(ctx, disk.CleanupSnapshots, &storageman.SDiskCleanupSnapshots{convertSnapshots, deleteSnapshots}) return nil, nil } diff --git a/pkg/hostman/guestman/guesthandler.go b/pkg/hostman/guesthandlers/guesthandler.go similarity index 81% rename from pkg/hostman/guestman/guesthandler.go rename to pkg/hostman/guesthandlers/guesthandler.go index 69bed3f526..338041b7bd 100644 --- a/pkg/hostman/guestman/guesthandler.go +++ b/pkg/hostman/guesthandlers/guesthandler.go @@ -1,4 +1,4 @@ -package guestman +package guesthandlers import ( "context" @@ -13,6 +13,7 @@ import ( "yunion.io/x/onecloud/pkg/hostman/storageman" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient/auth" + "yunion.io/x/onecloud/pkg/hostman/guestman" ) type strDict map[string]string @@ -88,12 +89,12 @@ func guestActions(ctx context.Context, w http.ResponseWriter, r *http.Request) { func getStatus(ctx context.Context, w http.ResponseWriter, r *http.Request) { params, _, _ := appsrv.FetchEnv(ctx, w, r) - var status = guestManger.Status(params[""]) + var status = guestman.GetGuestManager().Status(params[""]) appsrv.SendStruct(w, strDict{"status": status}) } func cpusetBalance(ctx context.Context, w http.ResponseWriter, r *http.Request) { - hostutils.DelayTask(ctx, guestManger.CpusetBalance, nil) + hostutils.DelayTask(ctx, guestman.GetGuestManager().CpusetBalance, nil) hostutils.ResponseOk(ctx, w) } @@ -101,7 +102,7 @@ func deleteGuest(ctx context.Context, w http.ResponseWriter, r *http.Request) { params, _, body := appsrv.FetchEnv(ctx, w, r) var sid = params[""] var migrated = jsonutils.QueryBoolean(body, "migrated", false) - guest, err := guestManger.Delete(sid) + guest, err := guestman.GetGuestManager().Delete(sid) if err != nil { hostutils.Response(ctx, w, err) } else { @@ -111,25 +112,25 @@ func deleteGuest(ctx context.Context, w http.ResponseWriter, r *http.Request) { } func guestCreate(ctx context.Context, sid string, body jsonutils.JSONObject) (interface{}, error) { - err := guestManger.PrepareCreate(sid) + err := guestman.GetGuestManager().PrepareCreate(sid) if err != nil { return nil, err } - hostutils.DelayTask(ctx, guestManger.GuestDeploy, &SGuestDeploy{sid, body, true}) + hostutils.DelayTask(ctx, guestman.GetGuestManager().GuestDeploy, &guestman.SGuestDeploy{sid, body, true}) return nil, nil } func guestDeploy(ctx context.Context, sid string, body jsonutils.JSONObject) (interface{}, error) { - err := guestManger.PrepareDeploy(sid) + err := guestman.GetGuestManager().PrepareDeploy(sid) if err != nil { return nil, err } - hostutils.DelayTask(ctx, guestManger.GuestDeploy, &SGuestDeploy{sid, body, false}) + hostutils.DelayTask(ctx, guestman.GetGuestManager().GuestDeploy, &guestman.SGuestDeploy{sid, body, false}) return nil, nil } func guestStart(ctx context.Context, sid string, body jsonutils.JSONObject) (interface{}, error) { - return guestManger.GuestStart(ctx, sid, body) + return guestman.GetGuestManager().GuestStart(ctx, sid, body) } func guestStop(ctx context.Context, sid string, body jsonutils.JSONObject) (interface{}, error) { @@ -137,11 +138,11 @@ func guestStop(ctx context.Context, sid string, body jsonutils.JSONObject) (inte if err != nil { timeout = 30 } - return nil, guestManger.GuestStop(ctx, sid, timeout) + return nil, guestman.GetGuestManager().GuestStop(ctx, sid, timeout) } func guestMonitor(ctx context.Context, sid string, body jsonutils.JSONObject) (interface{}, error) { - if !guestManger.IsGuestExist(sid) { + if !guestman.GetGuestManager().IsGuestExist(sid) { return nil, httperrors.NewNotFoundError("Guest %s not found", sid) } @@ -151,7 +152,7 @@ func guestMonitor(ctx context.Context, sid string, body jsonutils.JSONObject) (i c <- res } cmd, _ := body.GetString("cmd") - err := guestManger.Monitor(sid, cmd, cb) + err := guestman.GetGuestManager().Monitor(sid, cmd, cb) if err != nil { return nil, err } else { @@ -169,33 +170,33 @@ func guestMonitor(ctx context.Context, sid string, body jsonutils.JSONObject) (i } func guestSync(ctx context.Context, sid string, body jsonutils.JSONObject) (interface{}, error) { - if !guestManger.IsGuestExist(sid) { + if !guestman.GetGuestManager().IsGuestExist(sid) { return nil, httperrors.NewNotFoundError("Guest %s not found", sid) } - hostutils.DelayTask(ctx, guestManger.GuestSync, &SBaseParms{sid, body}) + hostutils.DelayTask(ctx, guestman.GetGuestManager().GuestSync, &guestman.SBaseParms{sid, body}) return nil, nil } func guestSuspend(ctx context.Context, sid string, body jsonutils.JSONObject) (interface{}, error) { - if !guestManger.IsGuestExist(sid) { + if !guestman.GetGuestManager().IsGuestExist(sid) { return nil, httperrors.NewNotFoundError("Guest %s not found", sid) } - hostutils.DelayTaskWithoutReqctx(ctx, guestManger.GuestSuspend, sid) + hostutils.DelayTaskWithoutReqctx(ctx, guestman.GetGuestManager().GuestSuspend, sid) return nil, nil } func guestSrcPrepareMigrate(ctx context.Context, sid string, body jsonutils.JSONObject) (interface{}, error) { - if !guestManger.IsGuestExist(sid) { + if !guestman.GetGuestManager().IsGuestExist(sid) { return nil, httperrors.NewNotFoundError("Guest %s not found", sid) } liveMigrate := jsonutils.QueryBoolean(body, "live_migrate", false) - hostutils.DelayTask(ctx, guestManger.SrcPrepareMigrate, - &SSrcPrepareMigrate{sid, liveMigrate}) + hostutils.DelayTask(ctx, guestman.GetGuestManager().SrcPrepareMigrate, + &guestman.SSrcPrepareMigrate{sid, liveMigrate}) return nil, nil } func guestDestPrepareMigrate(ctx context.Context, sid string, body jsonutils.JSONObject) (interface{}, error) { - if !guestManger.CanMigrate(sid) { + if !guestman.GetGuestManager().CanMigrate(sid) { return nil, httperrors.NewBadRequestError("Guest exist") } desc, err := body.Get("desc") @@ -211,7 +212,7 @@ func guestDestPrepareMigrate(ctx context.Context, sid string, body jsonutils.JSO if err != nil { return nil, httperrors.NewMissingParameterError("is_local_storage") } - var params = &SDestPrepareMigrate{} + var params = &guestman.SDestPrepareMigrate{} params.Sid = sid params.Desc = desc params.QemuVersion = qemuVersion @@ -258,12 +259,12 @@ func guestDestPrepareMigrate(ctx context.Context, sid string, body jsonutils.JSO params.TargetStorageId = targetStorageId } } - hostutils.DelayTask(ctx, guestManger.DestPrepareMigrate, params) + hostutils.DelayTask(ctx, guestman.GetGuestManager().DestPrepareMigrate, params) return nil, nil } func guestLiveMigrate(ctx context.Context, sid string, body jsonutils.JSONObject) (interface{}, error) { - if !guestManger.IsGuestExist(sid) { + if !guestman.GetGuestManager().IsGuestExist(sid) { return nil, httperrors.NewNotFoundError("Guest %s not found", sid) } destPort, err := body.Int("live_migrate_dest_port") @@ -278,18 +279,18 @@ func guestLiveMigrate(ctx context.Context, sid string, body jsonutils.JSONObject if err != nil { return nil, httperrors.NewMissingParameterError("is_local_storage") } - hostutils.DelayTaskWithoutReqctx(ctx, guestManger.LiveMigrate, &SLiveMigrate{ + hostutils.DelayTaskWithoutReqctx(ctx, guestman.GetGuestManager().LiveMigrate, &guestman.SLiveMigrate{ Sid: sid, DestPort: int(destPort), DestIp: destIp, IsLocal: isLocal, }) return nil, nil } func guestResume(ctx context.Context, sid string, body jsonutils.JSONObject) (interface{}, error) { - if !guestManger.IsGuestExist(sid) { + if !guestman.GetGuestManager().IsGuestExist(sid) { return nil, httperrors.NewNotFoundError("Guest %s not found", sid) } isLiveMigrate := jsonutils.QueryBoolean(body, "live_migrate", false) - guestManger.Resume(ctx, sid, isLiveMigrate) + guestman.GetGuestManager().Resume(ctx, sid, isLiveMigrate) return nil, nil } @@ -302,20 +303,20 @@ func guestResume(ctx context.Context, sid string, body jsonutils.JSONObject) (in // } func guestDriveMirror(ctx context.Context, sid string, body jsonutils.JSONObject) (interface{}, error) { - if !guestManger.IsGuestExist(sid) { + if !guestman.GetGuestManager().IsGuestExist(sid) { return nil, httperrors.NewNotFoundError("Guest %s not found", sid) } backupNbdServerUri, err := body.GetString("backup_ndb_server_uri") if err != nil { return nil, httperrors.NewMissingParameterError("backup_ndb_server_uri") } - hostutils.DelayTaskWithoutReqctx(ctx, guestManger.StartDriveMirror, - &SDriverMirror{sid, backupNbdServerUri}) + hostutils.DelayTaskWithoutReqctx(ctx, guestman.GetGuestManager().StartDriveMirror, + &guestman.SDriverMirror{sid, backupNbdServerUri}) return nil, nil } func guestReloadDiskSnapshot(ctx context.Context, sid string, body jsonutils.JSONObject) (interface{}, error) { - if !guestManger.IsGuestExist(sid) { + if !guestman.GetGuestManager().IsGuestExist(sid) { return nil, httperrors.NewNotFoundError("Guest %s not found", sid) } diskId, err := body.GetString("disk_id") @@ -324,7 +325,7 @@ func guestReloadDiskSnapshot(ctx context.Context, sid string, body jsonutils.JSO } var disk storageman.IDisk - guest := guestManger.Servers[sid] + guest := guestman.GetGuestManager().Servers[sid] disks, _ := guest.Desc.GetArray("disks") for _, d := range disks { id, _ := d.GetString("disk_id") @@ -338,12 +339,12 @@ func guestReloadDiskSnapshot(ctx context.Context, sid string, body jsonutils.JSO return nil, httperrors.NewNotFoundError("Disk not found") } - hostutils.DelayTaskWithoutReqctx(ctx, guestManger.ReloadDiskSnapshot, &SReloadDisk{sid, disk}) + hostutils.DelayTaskWithoutReqctx(ctx, guestman.GetGuestManager().ReloadDiskSnapshot, &guestman.SReloadDisk{sid, disk}) return nil, nil } func guestSnapshot(ctx context.Context, sid string, body jsonutils.JSONObject) (interface{}, error) { - if !guestManger.IsGuestExist(sid) { + if !guestman.GetGuestManager().IsGuestExist(sid) { return nil, httperrors.NewNotFoundError("Guest %s not found", sid) } snapshotId, err := body.GetString("snapshot_id") @@ -356,7 +357,7 @@ func guestSnapshot(ctx context.Context, sid string, body jsonutils.JSONObject) ( } var disk storageman.IDisk - guest := guestManger.Servers[sid] + guest := guestman.GetGuestManager().Servers[sid] disks, _ := guest.Desc.GetArray("disks") for _, d := range disks { id, _ := d.GetString("disk_id") @@ -370,7 +371,7 @@ func guestSnapshot(ctx context.Context, sid string, body jsonutils.JSONObject) ( return nil, httperrors.NewNotFoundError("Disk not found") } - hostutils.DelayTask(ctx, guestManger.DoSnapshot, &SDiskSnapshot{sid, snapshotId, disk}) + hostutils.DelayTask(ctx, guestman.GetGuestManager().DoSnapshot, &guestman.SDiskSnapshot{sid, snapshotId, disk}) return nil, nil } @@ -385,7 +386,7 @@ func guestDeleteSnapshot(ctx context.Context, sid string, body jsonutils.JSONObj } var disk storageman.IDisk - guest := guestManger.Servers[sid] + guest := guestman.GetGuestManager().Servers[sid] disks, _ := guest.Desc.GetArray("disks") for _, d := range disks { id, _ := d.GetString("disk_id") @@ -399,7 +400,7 @@ func guestDeleteSnapshot(ctx context.Context, sid string, body jsonutils.JSONObj return nil, httperrors.NewNotFoundError("Disk not found") } - params := &SDeleteDiskSnapshot{ + params := &guestman.SDeleteDiskSnapshot{ Sid: sid, DeleteSnapshot: deleteSnapshot, Disk: disk, @@ -417,6 +418,6 @@ func guestDeleteSnapshot(ctx context.Context, sid string, body jsonutils.JSONObj } params.PendingDelete = pendingDelete } - hostutils.DelayTask(ctx, guestManger.DeleteSnapshot, params) + hostutils.DelayTask(ctx, guestman.GetGuestManager().DeleteSnapshot, params) return nil, nil } diff --git a/pkg/hostman/guestman/guestman.go b/pkg/hostman/guestman/guestman.go index f96e4e5e7a..049e7d5899 100644 --- a/pkg/hostman/guestman/guestman.go +++ b/pkg/hostman/guestman/guestman.go @@ -257,7 +257,7 @@ func (m *SGuestManager) PrepareDeploy(sid string) error { func (m *SGuestManager) Monitor(sid, cmd string, callback func(string)) error { if guest, ok := m.Servers[sid]; ok { if guest.IsRunning() { - guest.Monitor.HumanMonirotCommand(cmd, callback) + guest.Monitor.HumanMonitorCommand(cmd, callback) return nil } else { return httperrors.NewBadRequestError("Server stopped??") @@ -611,6 +611,19 @@ func (m *SGuestManager) Resume(ctx context.Context, sid string, isLiveMigrate bo return nil, nil } +func (m *SGuestManager) OnlineResizeDisk(ctx context.Context, sid string, diskId string, sizeMb int64) (jsonutils.JSONObject, error) { + guest, ok := guestManger.Servers[sid] + if !ok { + return nil, httperrors.NewNotFoundError("guest %s not found", sid) + } + if guest.IsRunning() { + guest.onlineResizeDisk(ctx, diskId, sizeMb) + return nil, nil + } else { + return nil, httperrors.NewInvalidStatusError("guest is not runnign") + } +} + // func (m *SGuestManager) StartNbdServer(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) { // sid, ok := params.(string) // if !ok { diff --git a/pkg/hostman/guestman/guesttasks.go b/pkg/hostman/guestman/guesttasks.go index e34ac0c845..3f42543b1e 100644 --- a/pkg/hostman/guestman/guesttasks.go +++ b/pkg/hostman/guestman/guesttasks.go @@ -954,3 +954,50 @@ func (s *SDriveMirrorTask) startMirror(res string) { } } } + + +/** + * GuestOnlineResizeDiskTask +**/ + +type SGuestOnlineResizeDiskTask struct { + *SKVMGuestInstance + + ctx context.Context + diskId string + sizeMB int64 +} + +func NewGuestOnlineResizeDiskTask( + ctx context.Context, s *SKVMGuestInstance, diskId string, sizeMB int64, +) *SGuestOnlineResizeDiskTask { + return &SGuestOnlineResizeDiskTask{ + SKVMGuestInstance: s, + ctx: ctx, + diskId: diskId, + sizeMB: sizeMB, + } +} + +func (task *SGuestOnlineResizeDiskTask) Start() { + task.Monitor.GetBlocks(task.OnGetBlocksSucc) +} + +func (task *SGuestOnlineResizeDiskTask) OnGetBlocksSucc(results *jsonutils.JSONArray) { + for i := 0; i < results.Size(); i += 1 { + result, _ := results.GetAt(i) + fileStr, _ := result.GetString("inserted", "file") + if len(fileStr) > 0 && strings.HasSuffix(fileStr, task.diskId) { + driveName, _ := result.GetString("device") + task.Monitor.ResizeDisk(driveName, task.sizeMB, task.OnResizeSucc) + return + } + } + hostutils.TaskFailed(task.ctx, fmt.Sprintf("disk %s not found on this guest", task.diskId)) +} + +func (task *SGuestOnlineResizeDiskTask) OnResizeSucc(result string) { + params := jsonutils.NewDict() + params.Add(jsonutils.NewInt(task.sizeMB), "disk_size") + hostutils.TaskComplete(task.ctx, params) +} \ No newline at end of file diff --git a/pkg/hostman/guestman/qemu-kvm.go b/pkg/hostman/guestman/qemu-kvm.go index 329d7e9327..336cf71dac 100644 --- a/pkg/hostman/guestman/qemu-kvm.go +++ b/pkg/hostman/guestman/qemu-kvm.go @@ -1169,3 +1169,8 @@ func (s *SKVMGuestInstance) PrepareMigrate(liveMigrage bool) (*jsonutils.JSONDic } return disksBackFile, nil } + +func (s *SKVMGuestInstance) onlineResizeDisk(ctx context.Context, diskId string, sizeMB int64) { + task := NewGuestOnlineResizeDiskTask(ctx, s, diskId, sizeMB) + task.Start() +} diff --git a/pkg/hostman/host_services.go b/pkg/hostman/host_services.go index ae10671bdc..1b283d546d 100644 --- a/pkg/hostman/host_services.go +++ b/pkg/hostman/host_services.go @@ -17,6 +17,8 @@ import ( "yunion.io/x/onecloud/pkg/hostman/hostutils" "yunion.io/x/onecloud/pkg/hostman/options" "yunion.io/x/onecloud/pkg/hostman/storageman" + "yunion.io/x/onecloud/pkg/hostman/guesthandlers" + "yunion.io/x/onecloud/pkg/hostman/diskhandlers" ) type SHostService struct { @@ -84,9 +86,9 @@ func (host *SHostService) StartService() { } func (host *SHostService) initHandlers(app *appsrv.Application) { - guestman.AddGuestTaskHandler("", app) + guesthandlers.AddGuestTaskHandler("", app) storageman.AddStorageHandler("", app) - storageman.AddDiskHandler("", app) + diskhandlers.AddDiskHandler("", app) downloader.AddDownloadHandler("", app) addKubeAgentHandler("", app) } diff --git a/pkg/hostman/monitor/hmp.go b/pkg/hostman/monitor/hmp.go index 6a38dcbf61..95c1a9b617 100644 --- a/pkg/hostman/monitor/hmp.go +++ b/pkg/hostman/monitor/hmp.go @@ -175,7 +175,7 @@ func (m *HmpMonitor) SimpleCommand(cmd string, callback StringCallback) { m.Query(cmd, callback) } -func (m *HmpMonitor) HumanMonirotCommand(cmd string, callback StringCallback) { +func (m *HmpMonitor) HumanMonitorCommand(cmd string, callback StringCallback) { m.Query(cmd, callback) } @@ -351,3 +351,8 @@ func (m *HmpMonitor) StartNbdServer(port int, exportAllDevice, writable bool, ca cmd += fmt.Sprintf(" 0.0.0.0:%d", port) m.Query(cmd, callback) } + +func (m *HmpMonitor) ResizeDisk(driveName string, sizeMB int64, callback StringCallback) { + cmd := fmt.Sprintf("block_resize %s %d", driveName, sizeMB) + m.Query(cmd, callback) +} \ No newline at end of file diff --git a/pkg/hostman/monitor/monitor.go b/pkg/hostman/monitor/monitor.go index 165edc162b..4573de4d4e 100644 --- a/pkg/hostman/monitor/monitor.go +++ b/pkg/hostman/monitor/monitor.go @@ -19,7 +19,7 @@ type Monitor interface { // The callback function will be called in another goroutine SimpleCommand(cmd string, callback StringCallback) - HumanMonirotCommand(cmd string, callback StringCallback) + HumanMonitorCommand(cmd string, callback StringCallback) QueryStatus(StringCallback) GetVersion(StringCallback) @@ -45,6 +45,8 @@ type Monitor interface { ReloadDiskBlkdev(device, path string, callback StringCallback) SetVncPassword(proto, password string, callback StringCallback) StartNbdServer(port int, exportAllDevice, writable bool, callback StringCallback) + + ResizeDisk(driveName string, sizeMB int64, callback StringCallback) } type MonitorErrorFunc func(error) diff --git a/pkg/hostman/monitor/qmp.go b/pkg/hostman/monitor/qmp.go index 8339a61cf2..07cbec784a 100644 --- a/pkg/hostman/monitor/qmp.go +++ b/pkg/hostman/monitor/qmp.go @@ -297,7 +297,7 @@ func (m *QmpMonitor) SimpleCommand(cmd string, callback StringCallback) { m.Query(c, cb) } -func (m *QmpMonitor) HumanMonirotCommand(cmd string, callback StringCallback) { +func (m *QmpMonitor) HumanMonitorCommand(cmd string, callback StringCallback) { var ( c = &Command{ Execute: "human-monitor-command", @@ -382,7 +382,7 @@ func (m *QmpMonitor) GetBlocks(callback func(*jsonutils.JSONArray)) { } func (m *QmpMonitor) ChangeCdrom(dev string, path string, callback StringCallback) { - m.HumanMonirotCommand(fmt.Sprintf("change %s %s", dev, path), callback) + m.HumanMonitorCommand(fmt.Sprintf("change %s %s", dev, path), callback) // var ( // args = map[string]interface{}{ // "arguments": map[string]interface{}{ @@ -404,7 +404,7 @@ func (m *QmpMonitor) ChangeCdrom(dev string, path string, callback StringCallbac } func (m *QmpMonitor) EjectCdrom(dev string, callback StringCallback) { - m.HumanMonirotCommand(fmt.Sprintf("eject -f %s", dev), callback) + m.HumanMonitorCommand(fmt.Sprintf("eject -f %s", dev), callback) // XXX: 同下 // var ( // args = map[string]interface{}{ @@ -427,7 +427,7 @@ func (m *QmpMonitor) EjectCdrom(dev string, callback StringCallback) { } func (m *QmpMonitor) DriveDel(idstr string, callback StringCallback) { - m.HumanMonirotCommand(fmt.Sprintf("drive_del %s", idstr), callback) + m.HumanMonitorCommand(fmt.Sprintf("drive_del %s", idstr), callback) // XXX: 同下 // var ( // args = map[string]interface{}{ @@ -449,7 +449,7 @@ func (m *QmpMonitor) DriveDel(idstr string, callback StringCallback) { } func (m *QmpMonitor) DeviceDel(idstr string, callback StringCallback) { - m.HumanMonirotCommand(fmt.Sprintf("device_del %s", idstr), callback) + m.HumanMonitorCommand(fmt.Sprintf("device_del %s", idstr), callback) // XXX: 同下 // var ( // args = map[string]interface{}{ @@ -476,7 +476,7 @@ func (m *QmpMonitor) DriveAdd(bus string, params map[string]string, callback Str paramsKvs = append(paramsKvs, fmt.Sprintf("%s=%s", k, v)) } cmd := fmt.Sprintf("drive_add %s %s", bus, strings.Join(paramsKvs, ",")) - m.HumanMonirotCommand(cmd, callback) + m.HumanMonitorCommand(cmd, callback) // XXX: 同下 // var ( // args = map[string]interface{}{ @@ -504,7 +504,7 @@ func (m *QmpMonitor) DeviceAdd(dev string, params map[string]interface{}, callba paramsKvs = append(paramsKvs, fmt.Sprintf("%s=%v", k, v)) } cmd := fmt.Sprintf("device_add %s,%s", dev, strings.Join(paramsKvs, ",")) - m.HumanMonirotCommand(cmd, callback) + m.HumanMonitorCommand(cmd, callback) // XXX: 参数不对,之后再调,先用着hmp的参数 // var ( @@ -696,5 +696,10 @@ func (m *QmpMonitor) StartNbdServer(port int, exportAllDevice, writable bool, ca cmd += " -w" } cmd += fmt.Sprintf(" 0.0.0.0:%d", port) - m.HumanMonirotCommand(cmd, callback) + m.HumanMonitorCommand(cmd, callback) } + +func (m *QmpMonitor) ResizeDisk(driveName string, sizeMB int64, callback StringCallback) { + cmd := fmt.Sprintf("block_resize %s %d", driveName, sizeMB) + m.HumanMonitorCommand(cmd, callback) +} \ No newline at end of file From 24514642bee6c64d050a19d227e736ae3cc8e2e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=88=E8=BD=A9?= Date: Wed, 30 Jan 2019 10:28:51 +0800 Subject: [PATCH 3/9] =?UTF-8?q?=E9=81=BF=E5=85=8D=E6=9C=AA=E4=BC=A0?= =?UTF-8?q?=E9=80=92backend=E6=97=B6,=E9=BB=98=E8=AE=A4=E6=98=AFlocal,?= =?UTF-8?q?=E4=B8=8D=E8=83=BD=E9=80=9A=E8=BF=87=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/compute/guestdrivers/aliyun.go | 2 -- pkg/compute/guestdrivers/qcloud.go | 2 -- 2 files changed, 4 deletions(-) diff --git a/pkg/compute/guestdrivers/aliyun.go b/pkg/compute/guestdrivers/aliyun.go index a743a82714..2c05cf7a88 100644 --- a/pkg/compute/guestdrivers/aliyun.go +++ b/pkg/compute/guestdrivers/aliyun.go @@ -114,8 +114,6 @@ func (self *SAliyunGuestDriver) ValidateCreateData(ctx context.Context, userCred if disk.SizeMb < 5*1024 || disk.SizeMb > 800*1024 { return nil, httperrors.NewInputParameterError("The %s disk size must be in the range of 5GB ~ 800GB", disk.Backend) } - default: - return nil, httperrors.NewInputParameterError("Unkonwn disk type %s", disk.Backend) } } return data, nil diff --git a/pkg/compute/guestdrivers/qcloud.go b/pkg/compute/guestdrivers/qcloud.go index 4442d65ffb..0597b722e8 100644 --- a/pkg/compute/guestdrivers/qcloud.go +++ b/pkg/compute/guestdrivers/qcloud.go @@ -129,8 +129,6 @@ func (self *SQcloudGuestDriver) ValidateCreateData(ctx context.Context, userCred if disk.SizeMb < 100*1024 || disk.SizeMb > 16000*1024 { return nil, httperrors.NewInputParameterError("The %s disk size must be in the range of 100GB ~ 16000GB", disk.Backend) } - default: - return nil, httperrors.NewInputParameterError("Unkonwn disk type %s", disk.Backend) } } return data, nil From d862cd1a16ee51c9d25dbc4bfe7a7abcc1acda44 Mon Sep 17 00:00:00 2001 From: TangBin Date: Wed, 30 Jan 2019 12:16:26 +0800 Subject: [PATCH 4/9] enable batch* interface --- pkg/mcclient/modules/modules.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/mcclient/modules/modules.go b/pkg/mcclient/modules/modules.go index c9414fc946..323420c63f 100644 --- a/pkg/mcclient/modules/modules.go +++ b/pkg/mcclient/modules/modules.go @@ -132,11 +132,11 @@ type JointManager interface { ListDescendent2(s *mcclient.ClientSession, sid string, params jsonutils.JSONObject) (*ListResult, error) ListAscendent(s *mcclient.ClientSession, mid string, params jsonutils.JSONObject) (*ListResult, error) Attach(s *mcclient.ClientSession, mid, sid string, params jsonutils.JSONObject) (jsonutils.JSONObject, error) - // BatchAttach(s *mcclient.ClientSession, mid string, sids []string, params jsonutils.JSONObject) []SubmitResult - // BatchAttach2(s *mcclient.ClientSession, mid string, sids []string, params jsonutils.JSONObject) []SubmitResult + BatchAttach(s *mcclient.ClientSession, mid string, sids []string, params jsonutils.JSONObject) []SubmitResult + BatchAttach2(s *mcclient.ClientSession, mid string, sids []string, params jsonutils.JSONObject) []SubmitResult Detach(s *mcclient.ClientSession, mid, sid string, query jsonutils.JSONObject) (jsonutils.JSONObject, error) - // BatchDetach(s *mcclient.ClientSession, mid string, sids []string) []SubmitResult - // BatchDetach2(s *mcclient.ClientSession, mid string, sids []string) []SubmitResult + BatchDetach(s *mcclient.ClientSession, mid string, sids []string) []SubmitResult + BatchDetach2(s *mcclient.ClientSession, mid string, sids []string) []SubmitResult Update(s *mcclient.ClientSession, mid, sid string, query jsonutils.JSONObject, params jsonutils.JSONObject) (jsonutils.JSONObject, error) Patch(s *mcclient.ClientSession, mid, sid string, query jsonutils.JSONObject, params jsonutils.JSONObject) (jsonutils.JSONObject, error) } From f0d8f543d707a186ad3525dfb4aa8e228b289b47 Mon Sep 17 00:00:00 2001 From: TangBin Date: Wed, 30 Jan 2019 14:27:26 +0800 Subject: [PATCH 5/9] enable batch* interface --- pkg/compute/regiondrivers/doc.go | 1 + pkg/hostman/hostmetrics/doc.go | 1 + pkg/mcclient/modules/joint.go | 8 ++++---- 3 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 pkg/compute/regiondrivers/doc.go create mode 100644 pkg/hostman/hostmetrics/doc.go diff --git a/pkg/compute/regiondrivers/doc.go b/pkg/compute/regiondrivers/doc.go new file mode 100644 index 0000000000..c574159abd --- /dev/null +++ b/pkg/compute/regiondrivers/doc.go @@ -0,0 +1 @@ +package regiondrivers // import "yunion.io/x/onecloud/pkg/compute/regiondrivers" diff --git a/pkg/hostman/hostmetrics/doc.go b/pkg/hostman/hostmetrics/doc.go new file mode 100644 index 0000000000..3ef0d0730f --- /dev/null +++ b/pkg/hostman/hostmetrics/doc.go @@ -0,0 +1 @@ +package hostmetrics // import "yunion.io/x/onecloud/pkg/hostman/hostmetrics" diff --git a/pkg/mcclient/modules/joint.go b/pkg/mcclient/modules/joint.go index 9413ad0005..32c709c3f8 100644 --- a/pkg/mcclient/modules/joint.go +++ b/pkg/mcclient/modules/joint.go @@ -104,7 +104,7 @@ func (this *JointResourceManager) Attach(s *mcclient.ClientSession, mid, sid str return this.filterSingleResult(s, result, nil) } -/*func (this *JointResourceManager) BatchAttach(s *mcclient.ClientSession, mid string, sids []string, params jsonutils.JSONObject) []SubmitResult { +func (this *JointResourceManager) BatchAttach(s *mcclient.ClientSession, mid string, sids []string, params jsonutils.JSONObject) []SubmitResult { return BatchDo(sids, func(sid string) (jsonutils.JSONObject, error) { return this.Attach(s, mid, sid, params) }) @@ -114,7 +114,7 @@ func (this *JointResourceManager) BatchAttach2(s *mcclient.ClientSession, mid st return BatchDo(sids, func(sid string) (jsonutils.JSONObject, error) { return this.Attach(s, sid, mid, params) }) -}*/ +} func (this *JointResourceManager) Detach(s *mcclient.ClientSession, mid, sid string) (jsonutils.JSONObject, error) { path := fmt.Sprintf("/%s/%s/%s/%s", this.Master.KeyString(), url.PathEscape(mid), this.Slave.KeyString(), url.PathEscape(sid)) @@ -125,7 +125,7 @@ func (this *JointResourceManager) Detach(s *mcclient.ClientSession, mid, sid str return this.filterSingleResult(s, result, nil) } -/*func (this *JointResourceManager) BatchDetach(s *mcclient.ClientSession, mid string, sids []string) []SubmitResult { +func (this *JointResourceManager) BatchDetach(s *mcclient.ClientSession, mid string, sids []string) []SubmitResult { return BatchDo(sids, func(sid string) (jsonutils.JSONObject, error) { return this.Detach(s, mid, sid) }) @@ -135,7 +135,7 @@ func (this *JointResourceManager) BatchDetach2(s *mcclient.ClientSession, mid st return BatchDo(sids, func(sid string) (jsonutils.JSONObject, error) { return this.Detach(s, sid, mid) }) -}*/ +} func (this *JointResourceManager) Update(s *mcclient.ClientSession, mid, sid string, query jsonutils.JSONObject, params jsonutils.JSONObject) (jsonutils.JSONObject, error) { path := fmt.Sprintf("/%s/%s/%s/%s", this.Master.KeyString(), url.PathEscape(mid), this.Slave.KeyString(), url.PathEscape(sid)) From 609be1282c3f569804b9685c46fa95a743c04510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=88=E8=BD=A9?= Date: Wed, 30 Jan 2019 18:04:44 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E9=81=BF=E5=85=8D=E8=8E=B7=E5=8F=96region?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E5=AF=BC=E8=87=B4=E5=86=85=E5=AD=98=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E8=AE=BF=E9=97=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/compute/models/loadbalanceracls.go | 1 + pkg/compute/models/loadbalancerbackendgroups.go | 13 +++++++++++-- pkg/compute/models/loadbalancerbackends.go | 14 ++++++++++++-- pkg/compute/models/loadbalancercertificates.go | 7 ++++++- pkg/compute/models/loadbalancerlistenerrules.go | 8 +++++++- pkg/compute/models/loadbalancerlisteners.go | 15 +++++++++++++-- pkg/compute/models/loadbalancers.go | 1 + 7 files changed, 51 insertions(+), 8 deletions(-) diff --git a/pkg/compute/models/loadbalanceracls.go b/pkg/compute/models/loadbalanceracls.go index 86c92ea048..dbd069dbd2 100644 --- a/pkg/compute/models/loadbalanceracls.go +++ b/pkg/compute/models/loadbalanceracls.go @@ -187,6 +187,7 @@ func (lbacl *SLoadbalancerAcl) StartLoadBalancerAclCreateTask(ctx context.Contex func (lbacl *SLoadbalancerAcl) GetRegion() *SCloudregion { region, err := CloudregionManager.FetchById(lbacl.CloudregionId) if err != nil { + log.Errorf("failed to find region for loadbalancer acl %s", lbacl.Name) return nil } return region.(*SCloudregion) diff --git a/pkg/compute/models/loadbalancerbackendgroups.go b/pkg/compute/models/loadbalancerbackendgroups.go index a959dbfa87..a7e7ace419 100644 --- a/pkg/compute/models/loadbalancerbackendgroups.go +++ b/pkg/compute/models/loadbalancerbackendgroups.go @@ -147,12 +147,17 @@ func (man *SLoadbalancerBackendGroupManager) ValidateCreateData(ctx context.Cont } } data.Set("backends", jsonutils.Marshal(backends)) - return lb.GetRegion().GetDriver().ValidateCreateLoadbalancerBackendGroupData(ctx, userCred, data, lb, backends) + region := lb.GetRegion() + if region == nil { + return nil, httperrors.NewResourceNotFoundError("failed to find region for loadbalancer %s", lb.Name) + } + return region.GetDriver().ValidateCreateLoadbalancerBackendGroupData(ctx, userCred, data, lb, backends) } func (lbbg *SLoadbalancerBackendGroup) GetLoadbalancer() *SLoadbalancer { lb, err := LoadbalancerManager.FetchById(lbbg.LoadbalancerId) if err != nil { + fmt.Errorf("failed to find loadbalancer for backendgroup %s", lbbg.Name) return nil } return lb.(*SLoadbalancer) @@ -196,7 +201,11 @@ func (lbbg *SLoadbalancerBackendGroup) ValidateDeleteCondition(ctx context.Conte } } - return lbbg.GetRegion().GetDriver().ValidateDeleteLoadbalancerBackendGroupCondition(ctx, lbbg) + region := lbbg.GetRegion() + if region != nil { + return nil + } + return region.GetDriver().ValidateDeleteLoadbalancerBackendGroupCondition(ctx, lbbg) } func (lbbg *SLoadbalancerBackendGroup) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict { diff --git a/pkg/compute/models/loadbalancerbackends.go b/pkg/compute/models/loadbalancerbackends.go index ac75a66506..291b30f4b0 100644 --- a/pkg/compute/models/loadbalancerbackends.go +++ b/pkg/compute/models/loadbalancerbackends.go @@ -13,6 +13,7 @@ import ( "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" "yunion.io/x/onecloud/pkg/cloudcommon/validators" "yunion.io/x/onecloud/pkg/cloudprovider" + "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" ) @@ -133,7 +134,11 @@ func (man *SLoadbalancerBackendManager) ValidateCreateData(ctx context.Context, if _, err := man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data); err != nil { return nil, err } - return backendGroup.GetLoadbalancer().GetRegion().GetDriver().ValidateCreateLoadbalancerBackendData(ctx, userCred, data, backendType, lb, backendGroup, backendV.Model) + region := lb.GetRegion() + if region == nil { + return nil, httperrors.NewResourceNotFoundError("failed to find region for loadbalancer %s", lb.Name) + } + return region.GetDriver().ValidateCreateLoadbalancerBackendData(ctx, userCred, data, backendType, lb, backendGroup, backendV.Model) } func (lbb *SLoadbalancerBackend) AllowPerformStatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { @@ -143,6 +148,7 @@ func (lbb *SLoadbalancerBackend) AllowPerformStatus(ctx context.Context, userCre func (lbb *SLoadbalancerBackend) GetLoadbalancerBackendGroup() *SLoadbalancerBackendGroup { backendgroup, err := LoadbalancerBackendGroupManager.FetchById(lbb.BackendGroupId) if err != nil { + log.Errorf("failed to find backendgroup for backend %s", lbb.Name) return nil } return backendgroup.(*SLoadbalancerBackendGroup) @@ -255,7 +261,11 @@ func (lbb *SLoadbalancerBackend) ValidateDeleteCondition(ctx context.Context) er if err := lbb.SVirtualResourceBase.ValidateDeleteCondition(ctx); err != nil { return err } - return lbb.GetRegion().GetDriver().ValidateDeleteLoadbalancerBackendCondition(ctx, lbb) + region := lbb.GetRegion() + if region == nil { + return nil + } + return region.GetDriver().ValidateDeleteLoadbalancerBackendCondition(ctx, lbb) } func (man *SLoadbalancerBackendManager) SyncLoadbalancerBackends(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, loadbalancerBackendgroup *SLoadbalancerBackendGroup, lbbs []cloudprovider.ICloudLoadbalancerBackend, syncRange *SSyncRange) compare.SyncResult { diff --git a/pkg/compute/models/loadbalancercertificates.go b/pkg/compute/models/loadbalancercertificates.go index 3c030e7fa9..90ee15fc13 100644 --- a/pkg/compute/models/loadbalancercertificates.go +++ b/pkg/compute/models/loadbalancercertificates.go @@ -194,7 +194,11 @@ func (lbcert *SLoadbalancerCertificate) ValidateUpdateData(ctx context.Context, if _, err := lbcert.SVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, data); err != nil { return nil, err } - return lbcert.GetRegion().GetDriver().ValidateUpdateLoadbalancerCertificateData(ctx, userCred, data) + region := lbcert.GetRegion() + if region == nil { + return nil, httperrors.NewResourceNotFoundError("failed to find region for loadbalancer certificate %s", lbcert.Name) + } + return region.GetDriver().ValidateUpdateLoadbalancerCertificateData(ctx, userCred, data) } func (lbcert *SLoadbalancerCertificate) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, query jsonutils.JSONObject, data jsonutils.JSONObject) { @@ -242,6 +246,7 @@ func (lbcert *SLoadbalancerCertificate) Delete(ctx context.Context, userCred mcc func (lbcert *SLoadbalancerCertificate) GetRegion() *SCloudregion { region, err := CloudregionManager.FetchById(lbcert.CloudregionId) if err != nil { + log.Errorf("failed to find region for loadbalancer certificate %s", lbcert.Name) return nil } return region.(*SCloudregion) diff --git a/pkg/compute/models/loadbalancerlistenerrules.go b/pkg/compute/models/loadbalancerlistenerrules.go index cee456567d..0dae971fac 100644 --- a/pkg/compute/models/loadbalancerlistenerrules.go +++ b/pkg/compute/models/loadbalancerlistenerrules.go @@ -128,7 +128,12 @@ func (man *SLoadbalancerListenerRuleManager) ValidateCreateData(ctx context.Cont if _, err := man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data); err != nil { return nil, err } - return listener.GetRegion().GetDriver().ValidateCreateLoadbalancerListenerRuleData(ctx, userCred, data, backendGroupV.Model) + region := listener.GetRegion() + if region == nil { + return nil, httperrors.NewResourceNotFoundError("failed to find region for loadbalancer listener %s", listener.Name) + } + + return region.GetDriver().ValidateCreateLoadbalancerListenerRuleData(ctx, userCred, data, backendGroupV.Model) } func (lbr *SLoadbalancerListenerRule) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, query jsonutils.JSONObject, data jsonutils.JSONObject) { @@ -229,6 +234,7 @@ func (lbr *SLoadbalancerListenerRule) GetExtraDetails(ctx context.Context, userC func (lbr *SLoadbalancerListenerRule) GetLoadbalancerListener() *SLoadbalancerListener { listener, err := LoadbalancerListenerManager.FetchById(lbr.ListenerId) if err != nil { + log.Errorf("failed to find listener for loadbalancer listener rule %s", lbr.Name) return nil } return listener.(*SLoadbalancerListener) diff --git a/pkg/compute/models/loadbalancerlisteners.go b/pkg/compute/models/loadbalancerlisteners.go index 3e9a47e389..6dc26364f8 100644 --- a/pkg/compute/models/loadbalancerlisteners.go +++ b/pkg/compute/models/loadbalancerlisteners.go @@ -271,7 +271,11 @@ func (man *SLoadbalancerListenerManager) ValidateCreateData(ctx context.Context, if _, err := man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data); err != nil { return nil, err } - return lb.GetRegion().GetDriver().ValidateCreateLoadbalancerListenerData(ctx, userCred, data, backendGroupV.Model) + region := lb.GetRegion() + if region == nil { + return nil, httperrors.NewResourceNotFoundError("failed to find region for loadbalancer %s", lb.Name) + } + return region.GetDriver().ValidateCreateLoadbalancerListenerData(ctx, userCred, data, backendGroupV.Model) } func (man *SLoadbalancerListenerManager) checkTypeV(listenerType string) validators.IValidator { @@ -426,7 +430,13 @@ func (lblis *SLoadbalancerListener) ValidateUpdateData(ctx context.Context, user if _, err := lblis.SVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, data); err != nil { return nil, err } - return lblis.GetRegion().GetDriver().ValidateUpdateLoadbalancerListenerData(ctx, userCred, data, backendGroupV.Model) + + region := lblis.GetRegion() + if region == nil { + return nil, httperrors.NewResourceNotFoundError("failed to find region for loadbalancer listener %s", lblis.Name) + } + + return region.GetDriver().ValidateUpdateLoadbalancerListenerData(ctx, userCred, data, backendGroupV.Model) } func (lblis *SLoadbalancerListener) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) { @@ -621,6 +631,7 @@ func (lblis *SLoadbalancerListener) GetLoadbalancerBackendGroup() *SLoadbalancer func (lblis *SLoadbalancerListener) GetLoadbalancer() *SLoadbalancer { loadbalancer, err := LoadbalancerManager.FetchById(lblis.LoadbalancerId) if err != nil { + log.Errorf("failed to find loadbalancer for loadbalancer listener %s", lblis.Name) return nil } return loadbalancer.(*SLoadbalancer) diff --git a/pkg/compute/models/loadbalancers.go b/pkg/compute/models/loadbalancers.go index d8118b1b96..be072ab187 100644 --- a/pkg/compute/models/loadbalancers.go +++ b/pkg/compute/models/loadbalancers.go @@ -256,6 +256,7 @@ func (lb *SLoadbalancer) GetCloudprovider() *SCloudprovider { func (lb *SLoadbalancer) GetRegion() *SCloudregion { region, err := CloudregionManager.FetchById(lb.CloudregionId) if err != nil { + log.Errorf("failed to find region for loadbalancer %s", lb.Name) return nil } return region.(*SCloudregion) From bbfed827dc0b0fb1756d01fcac49244679720a15 Mon Sep 17 00:00:00 2001 From: wanyaoqi Date: Wed, 30 Jan 2019 17:28:31 +0800 Subject: [PATCH 7/9] - reserve mutli ip; - server-list order by disk --- cmd/climc/shell/reservedips.go | 8 +++---- pkg/compute/models/guests.go | 17 ++++++++++++++ pkg/compute/models/networks.go | 41 +++++++++++++++++++++------------ pkg/mcclient/options/servers.go | 1 + 4 files changed, 48 insertions(+), 19 deletions(-) diff --git a/cmd/climc/shell/reservedips.go b/cmd/climc/shell/reservedips.go index 6ce216ff58..e0603cca34 100644 --- a/cmd/climc/shell/reservedips.go +++ b/cmd/climc/shell/reservedips.go @@ -9,13 +9,13 @@ import ( func init() { type NetworkReserveIPOptions struct { - NETWORK string `help:"IP or name of network"` - IP string `help:"IP to reserve"` - NOTES string `help:"Why reserve this IP"` + NETWORK string `help:"IP or name of network"` + NOTES string `help:"Why reserve this IP"` + IPS []string `help:"IPs to reserve"` } R(&NetworkReserveIPOptions{}, "network-reserve-ip", "Reserve an IP address from pool", func(s *mcclient.ClientSession, args *NetworkReserveIPOptions) error { params := jsonutils.NewDict() - params.Add(jsonutils.NewString(args.IP), "ip") + params.Add(jsonutils.NewStringArray(args.IPS), "ips") params.Add(jsonutils.NewString(args.NOTES), "notes") net, err := modules.Networks.PerformAction(s, args.NETWORK, "reserve-ip", params) if err != nil { diff --git a/pkg/compute/models/guests.go b/pkg/compute/models/guests.go index 709bd99fcf..e91d18c4c6 100644 --- a/pkg/compute/models/guests.go +++ b/pkg/compute/models/guests.go @@ -485,6 +485,23 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ } q = q.Filter(cond(q.Field("id"), sgq)) } + + orderByDisk, _ := queryDict.GetString("order_by_disk") + if orderByDisk == "asc" { + guestdisks := GuestdiskManager.Query().SubQuery() + disks := DiskManager.Query().SubQuery() + q.AppendField(sqlchemy.SUM("disks_size", disks.Field("disk_size"))) + q = q.Join(guestdisks, sqlchemy.Equals(q.Field("id"), guestdisks.Field("guest_id"))). + Join(disks, sqlchemy.Equals(guestdisks.Field("disk_id"), disks.Field("id"))). + Asc(q.Field("disks_size")).GroupBy(q.Field("id")) + } else if orderByDisk == "desc" { + guestdisks := GuestdiskManager.Query().SubQuery() + disks := DiskManager.Query().SubQuery() + q.AppendField(sqlchemy.SUM("disks_size", disks.Field("disk_size"))) + q = q.Join(guestdisks, sqlchemy.Equals(q.Field("id"), guestdisks.Field("guest_id"))). + Join(disks, sqlchemy.Equals(guestdisks.Field("disk_id"), disks.Field("id"))). + Desc(q.Field("disks_size")).GroupBy(q.Field("id")) + } return q, nil } diff --git a/pkg/compute/models/networks.go b/pkg/compute/models/networks.go index c1acfaa0fd..c46708b95e 100644 --- a/pkg/compute/models/networks.go +++ b/pkg/compute/models/networks.go @@ -903,24 +903,35 @@ func (self *SNetwork) AllowPerformReserveIp(ctx context.Context, userCred mcclie } func (self *SNetwork) PerformReserveIp(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { - ipstr, _ := data.GetString("ip") - notes, _ := data.GetString("notes") - if len(ipstr) == 0 || len(notes) == 0 { - return nil, httperrors.NewInputParameterError("both reserved ip and notes should be provided") - } - ipAddr, err := netutils.NewIPV4Addr(ipstr) + ips, err := data.GetArray("ips") if err != nil { - return nil, httperrors.NewInputParameterError("not a valid ip address %s: %s", ipstr, err) + if data.Contains("ip") { + ip, _ := data.Get("ip") + ips = []jsonutils.JSONObject{ip} + } else { + return nil, httperrors.NewMissingParameterError("ips") + } } - if !self.isAddressInRange(ipAddr) { - return nil, httperrors.NewInputParameterError("Address %s not in network", ipstr) - } - if self.isAddressUsed(ipstr) { - return nil, httperrors.NewConflictError("Address %s has been used", ipstr) - } - err = ReservedipManager.ReserveIP(userCred, self, ipstr, notes) + notes, err := data.GetString("notes") if err != nil { - return nil, err + return nil, httperrors.NewMissingParameterError("ips") + } + for _, ip := range ips { + ipstr, _ := ip.GetString() + ipAddr, err := netutils.NewIPV4Addr(ipstr) + if err != nil { + return nil, httperrors.NewInputParameterError("not a valid ip address %s: %s", ipstr, err) + } + if !self.isAddressInRange(ipAddr) { + return nil, httperrors.NewInputParameterError("Address %s not in network", ipstr) + } + if self.isAddressUsed(ipstr) { + return nil, httperrors.NewConflictError("Address %s has been used", ipstr) + } + err = ReservedipManager.ReserveIP(userCred, self, ipstr, notes) + if err != nil { + return nil, err + } } return nil, nil } diff --git a/pkg/mcclient/options/servers.go b/pkg/mcclient/options/servers.go index 8adfdfa9db..0eddc078d9 100644 --- a/pkg/mcclient/options/servers.go +++ b/pkg/mcclient/options/servers.go @@ -23,6 +23,7 @@ type ServerListOptions struct { WithEip *bool `help:"Show Servers with EIP"` WithoutEip *bool `help:"Show Servers without EIP"` OsType string `help:"OS Type" choices:"linux|windows|vmware"` + OrderByDisk string `help:"Order by disk" choices:"asc|desc"` ResourceType string `help:"Resource type" choices:"shared|prepaid|dedicated"` From ddde11f4f93b8d3e2e2e430600bf5d03f1450b9f Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Wed, 30 Jan 2019 20:50:22 +0800 Subject: [PATCH 8/9] 1. network-list add is_private/is_public filter 2. set default image quota to 10 --- cmd/climc/shell/networks.go | 2 ++ pkg/compute/models/networks.go | 18 ++++++++++++++++++ pkg/image/options/options.go | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/cmd/climc/shell/networks.go b/cmd/climc/shell/networks.go index 0ea837eabf..b06da9c57b 100644 --- a/cmd/climc/shell/networks.go +++ b/cmd/climc/shell/networks.go @@ -18,6 +18,8 @@ func init() { Vpc string `help:"search networks belongs to a VPC"` Region string `help:"search networks belongs to a CloudRegion" json:"cloudregion"` ServerType string `help:"search networks belongs to a ServerType"` + Private *bool `help:"show private cloud networks only" json:"is_private"` + Public *bool `help:"show public cloud networks only" json:"is_public"` } R(&NetworkListOptions{}, "network-list", "List networks", func(s *mcclient.ClientSession, opts *NetworkListOptions) error { params, err := options.ListStructToParams(opts) diff --git a/pkg/compute/models/networks.go b/pkg/compute/models/networks.go index def6785461..e3e9120395 100644 --- a/pkg/compute/models/networks.go +++ b/pkg/compute/models/networks.go @@ -1447,6 +1447,24 @@ func (manager *SNetworkManager) ListItemFilter(ctx context.Context, q *sqlchemy. q = q.Filter(sqlchemy.In(q.Field("wire_id"), subq.SubQuery())) } + if query.Contains("is_private") && jsonutils.QueryBoolean(query, "is_private", false) { + wires := WireManager.Query().SubQuery() + vpcs := VpcManager.Query().SubQuery() + subq := wires.Query(wires.Field("id")) + subq = subq.Join(vpcs, sqlchemy.Equals(vpcs.Field("id"), wires.Field("vpc_id"))) + subq = subq.Filter(sqlchemy.IsNullOrEmpty(vpcs.Field("manager_id"))) + q = q.Filter(sqlchemy.In(q.Field("wire_id"), subq.SubQuery())) + } + + if query.Contains("is_public") && jsonutils.QueryBoolean(query, "is_public", false) { + wires := WireManager.Query().SubQuery() + vpcs := VpcManager.Query().SubQuery() + subq := wires.Query(wires.Field("id")) + subq = subq.Join(vpcs, sqlchemy.Equals(vpcs.Field("id"), wires.Field("vpc_id"))) + subq = subq.Filter(sqlchemy.IsNotEmpty(vpcs.Field("manager_id"))) + q = q.Filter(sqlchemy.In(q.Field("wire_id"), subq.SubQuery())) + } + return q, nil } diff --git a/pkg/image/options/options.go b/pkg/image/options/options.go index 7cf2ea593f..edc4fcf17e 100644 --- a/pkg/image/options/options.go +++ b/pkg/image/options/options.go @@ -12,7 +12,7 @@ type SImageOptions struct { pending_delete.SPendingDeleteOptions - DefaultImageQuota int `default:"5" help:"Common image quota per tenant, default 5"` + DefaultImageQuota int `default:"10" help:"Common image quota per tenant, default 10"` PortV2 int `help:"Listening port for region V2"` From 29d0f3cfed65f0051a0376c4462f4ca1ec3dfcdc Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Wed, 30 Jan 2019 20:55:22 +0800 Subject: [PATCH 9/9] fix: baremetal dhcp request filter networks with private cloud ONLY --- pkg/baremetal/pxe/dhcp.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/baremetal/pxe/dhcp.go b/pkg/baremetal/pxe/dhcp.go index 13e5fe5605..fb62ddab51 100644 --- a/pkg/baremetal/pxe/dhcp.go +++ b/pkg/baremetal/pxe/dhcp.go @@ -191,6 +191,7 @@ func (h *DHCPHandler) findNetworkConf(filterUseIp bool) (*types.SNetworkConfig, "filter.1") params.Add(jsonutils.JSONTrue, "filter_any") } + params.Add(jsonutils.JSONTrue, "is_private") session := h.baremetalManager.GetClientSession() ret, err := modules.Networks.List(session, params) if err != nil {