diff --git a/cmd/climc/shell/networks.go b/cmd/climc/shell/networks.go index 314046fbc5..a27505e06a 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" choices:"guest|baremetal|container|pxe|ipmi"` + 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/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/baremetal/pxe/dhcp.go b/pkg/baremetal/pxe/dhcp.go index 748c605f21..3bcbac1763 100644 --- a/pkg/baremetal/pxe/dhcp.go +++ b/pkg/baremetal/pxe/dhcp.go @@ -192,6 +192,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 { diff --git a/pkg/compute/guestdrivers/aliyun.go b/pkg/compute/guestdrivers/aliyun.go index 5edd5d4f41..462b782eb8 100644 --- a/pkg/compute/guestdrivers/aliyun.go +++ b/pkg/compute/guestdrivers/aliyun.go @@ -113,8 +113,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 d5eb88398d..6c1928d35f 100644 --- a/pkg/compute/guestdrivers/qcloud.go +++ b/pkg/compute/guestdrivers/qcloud.go @@ -128,8 +128,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 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/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) diff --git a/pkg/compute/models/networks.go b/pkg/compute/models/networks.go index 7e8a9e3a01..1131ae06e3 100644 --- a/pkg/compute/models/networks.go +++ b/pkg/compute/models/networks.go @@ -917,24 +917,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 } @@ -1475,6 +1486,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/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/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..db5304c813 100644 --- a/pkg/hostman/storageman/diskhandler.go +++ b/pkg/hostman/diskhandlers/diskhandler.go @@ -1,4 +1,4 @@ -package storageman +package diskhandlers import ( "context" @@ -10,7 +10,9 @@ import ( "yunion.io/x/onecloud/pkg/appsrv" "yunion.io/x/onecloud/pkg/cloudcommon/workmanager" + "yunion.io/x/onecloud/pkg/hostman/guestman" "yunion.io/x/onecloud/pkg/hostman/hostutils" + "yunion.io/x/onecloud/pkg/hostman/storageman" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient/auth" ) @@ -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..7c7632df20 100644 --- a/pkg/hostman/guestman/guesthandler.go +++ b/pkg/hostman/guesthandlers/guesthandler.go @@ -1,4 +1,4 @@ -package guestman +package guesthandlers import ( "context" @@ -8,7 +8,9 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/log" + "yunion.io/x/onecloud/pkg/appsrv" + "yunion.io/x/onecloud/pkg/hostman/guestman" "yunion.io/x/onecloud/pkg/hostman/hostutils" "yunion.io/x/onecloud/pkg/hostman/storageman" "yunion.io/x/onecloud/pkg/httperrors" @@ -88,12 +90,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 +103,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 +113,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 +139,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 +153,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 +171,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 +213,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 +260,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 +280,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 +304,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 +326,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 +340,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 +358,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 +372,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 +387,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 +401,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 +419,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..2ca49c9734 100644 --- a/pkg/hostman/guestman/guesttasks.go +++ b/pkg/hostman/guestman/guesttasks.go @@ -954,3 +954,49 @@ 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) +} 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..237734a4c2 100644 --- a/pkg/hostman/host_services.go +++ b/pkg/hostman/host_services.go @@ -10,7 +10,9 @@ import ( "yunion.io/x/onecloud/pkg/cloudcommon" "yunion.io/x/onecloud/pkg/cloudcommon/cronman" "yunion.io/x/onecloud/pkg/cloudcommon/service" + "yunion.io/x/onecloud/pkg/hostman/diskhandlers" "yunion.io/x/onecloud/pkg/hostman/downloader" + "yunion.io/x/onecloud/pkg/hostman/guesthandlers" "yunion.io/x/onecloud/pkg/hostman/guestman" "yunion.io/x/onecloud/pkg/hostman/hostinfo" "yunion.io/x/onecloud/pkg/hostman/hostmetrics" @@ -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/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/hostman/monitor/hmp.go b/pkg/hostman/monitor/hmp.go index 6a38dcbf61..ea317f36a5 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) +} 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..83705d2663 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) } 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"` 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)) 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) } 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"` 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,