Compare commits

...

31 Commits

Author SHA1 Message Date
Zexi Li
83896cdcc3 Merge pull request #9764 from wanyaoqi/automated-cherry-pick-of-#9762-upstream-release-3.6
Automated cherry pick of #9762: feat(region): stop guest before freeze
2021-01-05 18:33:32 +08:00
wanyaoqi
38914b967d feat(region): stop guest before freeze 2021-01-05 15:19:13 +08:00
Zexi Li
7695eb905c Merge pull request #9758 from zhaoxiangchun/automated-cherry-pick-of-#9757-upstream-release-3.6
Automated cherry pick of #9757: fix(monitor): modify totalrecord query
2021-01-04 15:57:09 +08:00
zhaoxiangchun
562aefda85 fix(monitor): modify totalrecord query
1. influxdb 增加abs function
2. 调整total报警记录接口query
2021-01-04 15:40:57 +08:00
Zexi Li
0143d271e1 Merge pull request #9756 from zhaoxiangchun/automated-cherry-pick-of-#9754-upstream-release-3.6
Automated cherry pick of #9754: feat(monitor): get today alerting resource info
2020-12-31 20:23:52 +08:00
zhaoxiangchun
de2b95cab7 feat(monitor): get today alerting resource info
1.提供接口获取当前时间发生报警的资源统计
2020-12-31 20:09:16 +08:00
Zexi Li
fc5a78c7e3 Merge pull request #9751 from rainzm/automated-cherry-pick-of-#9750-upstream-release-3.6
Automated cherry pick of #9750: feat(region): be compatible with changes in monitor api in scaling group
2020-12-30 21:45:01 +08:00
Zexi Li
3986dbc434 Merge pull request #9740 from zhaoxiangchun/automated-cherry-pick-of-#9735-upstream-release-3.6
Automated cherry pick of #9735: fix(monitor): modify rds,redis,oss field descriptions
2020-12-30 21:43:16 +08:00
Zexi Li
192e03fcd7 Merge pull request #9734 from ioito/automated-cherry-pick-of-#9730-upstream-release-3.6
Automated cherry pick of #9730: fix(cloudevent): cloudevent is domain level resource
2020-12-30 21:42:32 +08:00
Zexi Li
44db018039 Merge pull request #9729 from ioito/automated-cherry-pick-of-#9727-upstream-release-3.6
Automated cherry pick of #9727: fix(region): rds list with secgorups info
2020-12-30 21:41:49 +08:00
Zexi Li
6751d1d3af Merge pull request #9736 from wanyaoqi/automated-cherry-pick-of-#9731-upstream-release-3.6
Automated cherry pick of #9731: fix(region): server start check host memory is enough
2020-12-30 21:40:24 +08:00
Zexi Li
5ea100865d Merge pull request #9746 from rainzm/automated-cherry-pick-of-#9744-upstream-release-3.6
Automated cherry pick of #9744: fix(esxiagent): nicIndex should be incremented
2020-12-30 21:35:56 +08:00
rainzm
987b641bd0 feat(region): be compatible with changes in monitor api in scaling group 2020-12-30 19:16:47 +08:00
rainzm
77e56db095 fix(esxiagent): nicIndex should be incremented 2020-12-30 19:02:54 +08:00
Zexi Li
b7629422f7 Merge pull request #9725 from zhaoxiangchun/automated-cherry-pick-of-#9724-upstream-release-3.6
Automated cherry pick of #9724: feat(suggestion,apigateway): add analysispredict climc
2020-12-30 18:54:41 +08:00
zhaoxiangchun
589daf5063 fix(monitor): modify rds,redis,oss field descriptions
1.修改后端redis,rds,oss desc 信息,和前端索引进行对应
2020-12-30 16:09:17 +08:00
wanyaoqi
a066301ae2 fix(region): server start check host memory is enough 2020-12-30 15:50:52 +08:00
Qu Xuan
7d07b4aa5f fix(cloudevent): cloudevent is domain level resource 2020-12-30 15:48:33 +08:00
Qu Xuan
b96f225274 fix(region): rds list with secgorups info 2020-12-30 14:20:03 +08:00
zhaoxiangchun
40c8b54cba feat(suggestion,apigateway): add analysispredict climc 2020-12-30 14:09:02 +08:00
Zexi Li
93879980f5 Merge pull request #9720 from swordqiu/automated-cherry-pick-of-#9719-upstream-release-3.6
Automated cherry pick of #9719: fix(cloudcommon): splitable may not initialize underlying table
2020-12-29 21:17:17 +08:00
Zexi Li
5bb13e48b7 Merge pull request #9716 from wanyaoqi/automated-cherry-pick-of-#9711-upstream-release-3.6
Automated cherry pick of #9711: fix(region,host,host-deployer): sync status chekc block jobs
2020-12-29 20:43:37 +08:00
Zexi Li
64fcdea2b0 Merge pull request #9712 from rainzm/automated-cherry-pick-of-#9693-upstream-release-3.6
Automated cherry pick of #9693: Solve the permission problem of notify to create receiver
2020-12-29 20:41:44 +08:00
Zexi Li
57fa6361fc Merge pull request #9708 from rainzm/automated-cherry-pick-of-#9706-upstream-release-3.6
Automated cherry pick of #9706: feat(region): multilingual timer description
2020-12-29 20:39:31 +08:00
Qiu Jian
732159137b fix(cloudcommon): splitable may not initialize underlying table 2020-12-29 18:54:26 +08:00
wanyaoqi
d2ec564ccc fix(region,host): sync status check block jobs 2020-12-29 15:31:54 +08:00
wanyaoqi
a4323eab43 fix(host-deployer): add log line on blkid failed 2020-12-29 15:31:54 +08:00
wanyaoqi
7335875ef1 fix(climc): host add netif add params bridge/interface 2020-12-29 15:31:54 +08:00
rainzm
8d98218f06 feat(region): multilingual timer description 2020-12-29 15:23:45 +08:00
rainzm
af274d7ad2 feat(db): progressive inspection when determining the required scope 2020-12-29 15:04:28 +08:00
rainzm
25baa6f509 fix(notify): inject domain info in ReceiverManager.FetchOwnerId 2020-12-29 15:04:28 +08:00
42 changed files with 614 additions and 231 deletions

View File

@@ -34,6 +34,7 @@ import (
_ "yunion.io/x/onecloud/cmd/climc/shell/monitor"
_ "yunion.io/x/onecloud/cmd/climc/shell/notifyv2"
_ "yunion.io/x/onecloud/cmd/climc/shell/servicetree"
_ "yunion.io/x/onecloud/cmd/climc/shell/suggestion"
_ "yunion.io/x/onecloud/cmd/climc/shell/yunionconf"
)

View File

@@ -407,12 +407,14 @@ func init() {
})
type HostAddNetIfOptions struct {
ID string `help:"ID or Name of host"`
WIRE string `help:"ID or Name of wire to attach"`
MAC string `help:"Mac address of NIC"`
INDEX int64 `help:"nic index"`
Type string `help:"Nic type" choices:"admin|ipmi"`
IpAddr string `help:"IP address"`
ID string `help:"ID or Name of host"`
WIRE string `help:"ID or Name of wire to attach"`
MAC string `help:"Mac address of NIC"`
INDEX int64 `help:"nic index"`
Type string `help:"Nic type" choices:"admin|ipmi"`
IpAddr string `help:"IP address"`
Bridge string `help:"Bridge of hostwire"`
Interface string `help:"Interface name, eg:eth0, en0"`
}
R(&HostAddNetIfOptions{}, "host-add-netif", "Host add a NIC", func(s *mcclient.ClientSession, args *HostAddNetIfOptions) error {
params := jsonutils.NewDict()
@@ -426,6 +428,12 @@ func init() {
if len(args.IpAddr) > 0 {
params.Add(jsonutils.NewString(args.IpAddr), "ip_addr")
}
if len(args.Bridge) > 0 {
params.Add(jsonutils.NewString(args.Bridge), "bridge")
}
if len(args.Interface) > 0 {
params.Add(jsonutils.NewString(args.Interface), "interface")
}
result, err := modules.Hosts.PerformAction(s, args.ID, "add-netif", params)
if err != nil {
return err

View File

@@ -10,4 +10,5 @@ func init() {
cmd := shell.NewResourceCmd(modules.AlertRecordManager)
cmd.List(new(options.AlertRecordListOptions))
cmd.Show(new(options.AlertRecordShowOptions))
cmd.Get("", new(options.AlertRecordTotalOptions))
}

View File

@@ -1,67 +0,0 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package monitor
import (
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/modules/monitor"
options "yunion.io/x/onecloud/pkg/mcclient/options/monitor"
)
func init() {
aN := cmdN("suggestsysalert")
R(&options.SuggestSysAlertListOptions{}, aN("list"), "List all suggestsysrules",
func(s *mcclient.ClientSession, args *options.SuggestSysAlertListOptions) error {
params, err := args.Params()
if err != nil {
return err
}
if len(args.Type) > 0 {
params.Add(jsonutils.NewString(args.Type), "type")
}
ret, err := monitor.SuggestSysAlertManager.List(s, params)
if err != nil {
return err
}
printList(ret, monitor.SuggestSysAlertManager.GetColumns(s))
return nil
})
R(&options.SSuggestAlertShowOptions{}, aN("show"), "Show details of a alert rule",
func(s *mcclient.ClientSession, args *options.SSuggestAlertShowOptions) error {
ret, err := monitor.SuggestSysAlertManager.Get(s, args.ID, nil)
if err != nil {
return err
}
printObject(ret)
return nil
})
R(&options.SuggestAlertIgnoreOptions{}, aN("ignore"), "Ignore alert result",
func(s *mcclient.ClientSession, args *options.SuggestAlertIgnoreOptions) error {
params, err := args.Params()
if err != nil {
return err
}
ret, err := monitor.SuggestSysAlertManager.PerformAction(s, args.ID, "ignore", params)
if err != nil {
return err
}
printObject(ret)
return nil
})
}

View File

@@ -0,0 +1,12 @@
package suggestion
import (
"yunion.io/x/onecloud/cmd/climc/shell"
"yunion.io/x/onecloud/pkg/mcclient/modules"
options "yunion.io/x/onecloud/pkg/mcclient/options/suggestion"
)
func init() {
cmd := shell.NewResourceCmd(modules.AnalysisPredictManager)
cmd.Get("", new(options.AnalysisPredictConfigOptions))
}

View File

@@ -0,0 +1,28 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package suggestion
import (
"yunion.io/x/onecloud/cmd/climc/shell"
"yunion.io/x/onecloud/pkg/mcclient/modules/monitor"
options "yunion.io/x/onecloud/pkg/mcclient/options/monitor"
)
func init() {
cmd := shell.NewResourceCmd(monitor.SuggestSysAlertManager)
cmd.List(new(options.SuggestSysAlertListOptions))
cmd.Show(new(options.SSuggestAlertShowOptions))
cmd.Perform("ignore", new(options.SuggestAlertIgnoreOptions))
}

View File

@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package monitor
package suggestion
import (
"yunion.io/x/onecloud/cmd/climc/shell"

View File

@@ -23,7 +23,7 @@ import (
type CloudeventListInput struct {
apis.ModelBaseListInput
apis.ProjectizedResourceListInput
apis.DomainizedResourceListInput
compute.CloudenvResourceListInput
@@ -47,6 +47,6 @@ type CloudeventListInput struct {
type CloudeventDetails struct {
apis.ModelBaseDetails
apis.ProjectizedResourceInfo
apis.DomainizedResourceInfo
SCloudevent
}

View File

@@ -294,6 +294,8 @@ type DBInstanceDetails struct {
SDBInstance
Secgroups []apis.StandaloneShortDesc `json:"secgroups"`
// 安全组名称
// example: Default
Secgroup string `json:"secgroup"`

View File

@@ -23,6 +23,9 @@ import (
type ScheduledTaskDetails struct {
apis.VirtualResourceDetails
SScheduledTask
// 描述
TimerDesc string `json:"timer_desc"`
// 定时方式触发
Timer TimerDetails `json:"timer"`
// 周期方式触发

View File

@@ -2068,7 +2068,6 @@ type SScheduledTask struct {
apis.SEnabledResourceBase
ScheduledType string `json:"scheduled_type"`
STimer
TimerDesc string `json:"timer_desc"`
ResourceType string `json:"resource_type"`
Operation string `json:"operation"`
LabelType string `json:"label_type"`

View File

@@ -205,6 +205,8 @@ type PerformStatusInput struct {
// 更改的目标状态值
// required:true
Status string `json:"status"`
// swagger:ignore
BlockJobsCount int `json:"block_jobs_count"`
// 更改状态的原因描述
// required:false

View File

@@ -47,8 +47,9 @@ const (
ACT_BACKUP_START = "backup_start"
ACT_BACKUP_START_FAILED = "backup_start_fail"
ACT_FREEZE = "freeze"
ACT_UNFREEZE = "unfreeze"
ACT_FREEZE = "freeze"
ACT_FREEZE_FAIL = "freeze_fail"
ACT_UNFREEZE = "unfreeze"
ACT_RESTARING = "restarting"
ACT_RESTART_FAIL = "restart_fail"

View File

@@ -51,6 +51,8 @@ func isObjectRbacAllowed(model IModel, userCred mcclient.TokenCredential, action
case rbacutils.ScopeUser:
if ownerId != nil && objOwnerId != nil && (ownerId.GetUserId() == objOwnerId.GetUserId() || objOwnerId.GetUserId() == "" || (model.IsSharable(ownerId) && action == policy.PolicyActionGet)) {
requireScope = rbacutils.ScopeUser
} else if ownerId != nil && objOwnerId != nil && ownerId.GetProjectDomainId() == objOwnerId.GetProjectDomainId() {
requireScope = rbacutils.ScopeDomain
} else {
requireScope = rbacutils.ScopeSystem
}
@@ -103,6 +105,8 @@ func isClassRbacAllowed(manager IModelManager, userCred mcclient.TokenCredential
case rbacutils.ScopeUser:
if ownerId != nil && ownerId.GetUserId() == objOwnerId.GetUserId() {
requireScope = rbacutils.ScopeUser
} else if ownerId != nil && ownerId.GetProjectDomainId() == objOwnerId.GetProjectDomainId() {
requireScope = rbacutils.ScopeDomain
} else {
requireScope = rbacutils.ScopeSystem
}

View File

@@ -34,7 +34,7 @@ import (
type SCloudeventManager struct {
db.SModelBaseManager
db.SProjectizedResourceBaseManager
db.SDomainizedResourceBaseManager
}
var CloudeventManager *SCloudeventManager
@@ -57,7 +57,7 @@ func init() {
type SCloudevent struct {
db.SModelBase
db.SProjectizedResourceBase
db.SDomainizedResourceBase
EventId int64 `primary:"true" auto_increment:"true" list:"user"`
Name string `width:"128" charset:"utf8" nullable:"false" index:"true" list:"user"`
@@ -76,6 +76,10 @@ type SCloudevent struct {
Brand string `width:"64" charset:"ascii" list:"domain"`
}
func (self *SCloudeventManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return db.IsDomainAllowList(userCred, self)
}
func (self *SCloudeventManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return false
}
@@ -88,6 +92,10 @@ func (self *SCloudevent) AllowUpdateItem(ctx context.Context, userCred mcclient.
return false
}
func (self *SCloudevent) AllowGetDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return db.IsDomainAllowGet(userCred, self)
}
// 云平台操作日志列表
func (manager *SCloudeventManager) ListItemFilter(
ctx context.Context,
@@ -97,7 +105,11 @@ func (manager *SCloudeventManager) ListItemFilter(
) (*sqlchemy.SQuery, error) {
q, err := manager.SModelBaseManager.ListItemFilter(ctx, q, userCred, input.ModelBaseListInput)
if err != nil {
return nil, errors.Wrap(err, "SVirtualResourceBaseManager.ListItemFilter")
return nil, errors.Wrap(err, "SModelBaseManager.ListItemFilter")
}
q, err = manager.SDomainizedResourceBaseManager.ListItemFilter(ctx, q, userCred, input.DomainizedResourceListInput)
if err != nil {
return nil, errors.Wrap(err, "SDomainizedResourceBaseManager.ListItemFilter")
}
if len(input.Providers) > 0 {
@@ -153,37 +165,45 @@ func (manager *SCloudeventManager) FetchCustomizeColumns(
) []api.CloudeventDetails {
rows := make([]api.CloudeventDetails, len(objs))
base := manager.SModelBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
projRows := manager.SProjectizedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
domainRows := manager.SDomainizedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
for i := range rows {
rows[i].ModelBaseDetails = base[i]
rows[i].ProjectizedResourceInfo = projRows[i]
rows[i].DomainizedResourceInfo = domainRows[i]
}
return rows
}
func (self *SCloudevent) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
return self.SModelBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
}
func (manager *SCloudeventManager) NamespaceScope() rbacutils.TRbacScope {
return rbacutils.ScopeDomain
}
func (manager *SCloudeventManager) ResourceScope() rbacutils.TRbacScope {
return rbacutils.ScopeProject
return rbacutils.ScopeDomain
}
func (self *SCloudevent) GetOwnerId() mcclient.IIdentityProvider {
owner := db.SOwnerId{DomainId: self.DomainId, ProjectId: self.ProjectId}
owner := db.SOwnerId{DomainId: self.DomainId}
return &owner
}
func (manager *SCloudeventManager) FilterByOwner(q *sqlchemy.SQuery, owner mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
return manager.SProjectizedResourceBaseManager.FilterByOwner(q, owner, scope)
return manager.SDomainizedResourceBaseManager.FilterByOwner(q, owner, scope)
}
func (manager *SCloudeventManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
return manager.SProjectizedResourceBaseManager.FetchOwnerId(ctx, data)
return manager.SDomainizedResourceBaseManager.FetchOwnerId(ctx, data)
}
func (manager *SCloudeventManager) ListItemExportKeys(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, keys stringutils2.SSortedStrings) (*sqlchemy.SQuery, error) {
return manager.SProjectizedResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
return manager.SDomainizedResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
}
func (manager *SCloudeventManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
return manager.SProjectizedResourceBaseManager.QueryDistinctExtraField(q, field)
return manager.SDomainizedResourceBaseManager.QueryDistinctExtraField(q, field)
}
func (manager *SCloudeventManager) OrderByExtraFields(
@@ -192,7 +212,7 @@ func (manager *SCloudeventManager) OrderByExtraFields(
userCred mcclient.TokenCredential,
query api.CloudeventListInput,
) (*sqlchemy.SQuery, error) {
return manager.SProjectizedResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.ProjectizedResourceListInput)
return manager.SDomainizedResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.DomainizedResourceListInput)
}
func (manager *SCloudeventManager) SyncCloudevent(ctx context.Context, userCred mcclient.TokenCredential, cloudprovider *SCloudprovider, iEvents []cloudprovider.ICloudEvent) int {
@@ -213,7 +233,6 @@ func (manager *SCloudeventManager) SyncCloudevent(ctx context.Context, userCred
CloudproviderId: cloudprovider.Id,
}
event.DomainId = cloudprovider.DomainId
event.ProjectId = cloudprovider.ProjectId
if len(event.Brand) == 0 {
event.Brand = event.Provider
}

View File

@@ -21,8 +21,10 @@ import (
var (
cloudeventSystemResources = []string{}
cloudeventDomainResources = []string{}
cloudeventUserResources = []string{}
cloudeventDomainResources = []string{
"cloudevent",
}
cloudeventUserResources = []string{}
)
func init() {

View File

@@ -38,6 +38,7 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/options"
@@ -537,6 +538,7 @@ func (manager *SDBInstanceManager) FetchCustomizeColumns(
manRows := manager.SManagedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
regRows := manager.SCloudregionResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
rdsIds := make([]string, len(rows))
vpcIds := make([]string, len(rows))
zone1Ids := make([]string, len(rows))
zone2Ids := make([]string, len(rows))
@@ -548,6 +550,7 @@ func (manager *SDBInstanceManager) FetchCustomizeColumns(
CloudregionResourceInfo: regRows[i],
}
instance := objs[i].(*SDBInstance)
rdsIds[i] = instance.Id
vpcIds[i] = instance.VpcId
zone1Ids[i] = instance.Zone1
zone2Ids[i] = instance.Zone2
@@ -569,6 +572,42 @@ func (manager *SDBInstanceManager) FetchCustomizeColumns(
}
}
q := SecurityGroupManager.Query()
ownerId, queryScope, err := db.FetchCheckQueryOwnerScope(ctx, userCred, query, SecurityGroupManager, policy.PolicyActionList, true)
if err != nil {
log.Errorf("FetchCheckQueryOwnerScope error: %v", err)
return rows
}
secgroups := SecurityGroupManager.FilterByOwner(q, ownerId, queryScope).SubQuery()
rdssecgroups := DBInstanceSecgroupManager.Query().SubQuery()
secQ := rdssecgroups.Query(rdssecgroups.Field("dbinstance_id"), rdssecgroups.Field("secgroup_id"), secgroups.Field("name").Label("secgroup_name")).Join(secgroups, sqlchemy.Equals(rdssecgroups.Field("secgroup_id"), secgroups.Field("id"))).Filter(sqlchemy.In(rdssecgroups.Field("dbinstance_id"), rdsIds))
type sRdsSecgroupInfo struct {
DBInstanceId string `json:"dbinstance_id"`
SecgroupName string
SecgroupId string
}
rsgs := []sRdsSecgroupInfo{}
err = secQ.All(&rsgs)
if err != nil {
log.Errorf("secQ.All error: %v", err)
return rows
}
ret := make(map[string][]apis.StandaloneShortDesc)
for i := range rsgs {
rsg, ok := ret[rsgs[i].DBInstanceId]
if !ok {
rsg = make([]apis.StandaloneShortDesc, 0)
}
rsg = append(rsg, apis.StandaloneShortDesc{
Id: rsgs[i].SecgroupId,
Name: rsgs[i].SecgroupName,
})
ret[rsgs[i].DBInstanceId] = rsg
}
zone1, err := db.FetchIdNameMap2(ZoneManager, zone1Ids)
if err != nil {
return rows
@@ -588,6 +627,7 @@ func (manager *SDBInstanceManager) FetchCustomizeColumns(
rows[i].Zone1Name = zone1[zone1Ids[i]]
rows[i].Zone2Name = zone2[zone2Ids[i]]
rows[i].Zone3Name = zone3[zone3Ids[i]]
rows[i].Secgroups, _ = ret[rdsIds[i]]
}
return rows

View File

@@ -805,6 +805,16 @@ func (self *SGuest) AllowPerformStart(ctx context.Context,
func (self *SGuest) PerformStart(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject,
data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if utils.IsInStringArray(self.Status, []string{api.VM_READY, api.VM_START_FAILED, api.VM_SAVE_DISK_FAILED, api.VM_SUSPEND}) {
if !self.guestDisksStorageTypeIsShared() {
host := self.GetHost()
guestsMem, err := host.GetNotReadyGuestsMemorySize()
if err != nil {
return nil, err
}
if float32(guestsMem+self.VmemSize) > host.GetVirtualMemorySize() {
return nil, httperrors.NewInsufficientResourceError("host virtual memory not enough")
}
}
if self.isAllDisksReady() {
var kwargs *jsonutils.JSONDict
if data != nil {
@@ -2726,7 +2736,7 @@ func (self *SGuest) PerformStatus(ctx context.Context, userCred mcclient.TokenCr
}
status := input.Status
if len(self.BackupHostId) > 0 && status == api.VM_RUNNING {
if len(self.BackupHostId) > 0 && status == api.VM_RUNNING && input.BlockJobsCount > 0 {
self.SetMetadata(ctx, api.MIRROR_JOB, api.MIRROR_JOB_READY, userCred)
} else if ispId := self.GetMetadata(api.BASE_INSTANCE_SNAPSHOT_ID, userCred); len(ispId) > 0 {
ispM, err := InstanceSnapshotManager.FetchById(ispId)
@@ -2763,6 +2773,27 @@ func (self *SGuest) PerformStop(ctx context.Context, userCred mcclient.TokenCred
return nil, httperrors.NewInvalidStatusError("Cannot stop server in status %s", self.Status)
}
func (self *SGuest) PerformFreeze(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformFreezeInput) (jsonutils.JSONObject, error) {
if self.Freezed {
return nil, httperrors.NewBadRequestError("virtual resource already freezed")
}
if utils.IsInStringArray(self.Status, []string{api.VM_RUNNING, api.VM_STOP_FAILED}) {
return nil, self.StartGuestStopAndFreezeTask(ctx, userCred)
} else {
return self.SVirtualResourceBase.PerformFreeze(ctx, userCred, query, input)
}
}
func (self *SGuest) StartGuestStopAndFreezeTask(ctx context.Context, userCred mcclient.TokenCredential) error {
self.SetStatus(userCred, api.VM_START_STOP, "")
task, err := taskman.TaskManager.NewTask(ctx, "GuestStopAndFreezeTask", self, userCred, nil, "", "", nil)
if err != nil {
return err
}
task.ScheduleRun(nil)
return nil
}
func (self *SGuest) AllowPerformRestart(ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,

View File

@@ -4784,7 +4784,7 @@ func (self *SGuestManager) switchBackupGuests(ctx context.Context, userCred mccl
log.Errorf("ReconcileBackupGuests failed fetch guests %s", err)
return
}
log.Infof("Guests count %d need reconcile with switch bakcup", len(guests))
log.Debugf("Guests count %d need reconcile with switch backup", len(guests))
for i := 0; i < len(guests); i++ {
val := guests[i].GetMetadataJson("switch_backup", userCred)
t, err := val.GetTime()

View File

@@ -1497,6 +1497,23 @@ func (self *SHost) GetRunningGuestCount() (int, error) {
return q.CountWithError()
}
func (self *SHost) GetNotReadyGuestsMemorySize() (int, error) {
guests := GuestManager.Query().SubQuery()
q := guests.Query(sqlchemy.COUNT("guest_count"),
sqlchemy.SUM("guest_vcpu_count", guests.Field("vcpu_count")),
sqlchemy.SUM("guest_vmem_size", guests.Field("vmem_size")))
cond := sqlchemy.OR(sqlchemy.Equals(q.Field("host_id"), self.Id),
sqlchemy.Equals(q.Field("backup_host_id"), self.Id))
q = q.Filter(cond)
q = q.NotEquals("status", api.VM_READY)
stat := SHostGuestResourceUsage{}
err := q.First(&stat)
if err != nil {
return -1, err
}
return stat.GuestVmemSize, nil
}
func (self *SHost) GetRunningGuestMemorySize() int {
res := self.getGuestsResource(api.VM_RUNNING)
if res != nil {

View File

@@ -18,8 +18,6 @@ import (
"context"
"database/sql"
"fmt"
"strconv"
"strings"
"time"
"yunion.io/x/jsonutils"
@@ -205,17 +203,7 @@ func (st *SScalingTimer) TriggerId() string {
var cstSh, _ = time.LoadLocation("Asia/Shanghai")
func (st *SScalingTimer) TriggerDescription() string {
var detail string
switch st.Type {
case api.TIMER_TYPE_ONCE:
detail = st.EndTime.In(cstSh).Format("2006-01-02 15:04:05")
case api.TIMER_TYPE_DAY:
detail = fmt.Sprintf("%d:%d every day", st.Hour, st.Minute)
case api.TIMER_TYPE_WEEK:
detail = st.WeekDaysDesc()
case api.TIMER_TYPE_MONTH:
detail = st.MonthDaysDesc()
}
detail := st.descEnglish()
name := st.ScalingPolicyId
sp, _ := st.ScalingPolicy()
if sp != nil {
@@ -336,11 +324,14 @@ var indicatorMap = map[string]sTableField{
api.INDICATOR_FLOW_OUT: {"vm_netio", "bps_sent"},
}
var alertConfigUsedBy = "scaling_group"
func (sa *SScalingAlarm) generateAlertConfig(sp *SScalingPolicy) (*monitor.AlertConfig, error) {
config, err := monitor.NewAlertConfig(fmt.Sprintf("sp-%s", sp.Id), fmt.Sprintf("%ds", sa.Cycle), true)
if err != nil {
return nil, err
}
config.UsedBy = alertConfigUsedBy
cond := config.Condition("telegraf", indicatorMap[sa.Indicator].Table).Avg()
log.Debugf("alarm: %#v", sa)
@@ -442,61 +433,3 @@ var units = map[string]string{
api.INDICATOR_FLOW_INTO: "KB/s",
api.INDICATOR_FLOW_OUT: "KB/s",
}
var weekDays = []string{"", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}
func (st *SScalingTimer) WeekDaysDesc() string {
if st.WeekDays == 0 {
return ""
}
var desc strings.Builder
wds := st.GetWeekDays()
i := 0
desc.WriteString(fmt.Sprintf("%d:%d every %s", st.Hour, st.Minute, weekDays[wds[i]]))
for i++; i < len(wds)-1; i++ {
desc.WriteString(", ")
desc.WriteString(weekDays[wds[i]])
}
if i == len(wds)-1 {
desc.WriteString(" and ")
desc.WriteString(weekDays[wds[i]])
}
return desc.String()
}
func (st *SScalingTimer) MonthDaysDesc() string {
if st.MonthDays == 0 {
return ""
}
var desc strings.Builder
mds := st.GetMonthDays()
i := 0
desc.WriteString(fmt.Sprintf("%d:%d on the %d%s", st.Hour, st.Minute, mds[i], dateSuffix(mds[i])))
for i++; i < len(mds)-1; i++ {
desc.WriteString(", ")
desc.WriteString(strconv.Itoa(mds[i]))
desc.WriteString(dateSuffix(mds[i]))
}
if i == len(mds)-1 {
desc.WriteString(" and ")
desc.WriteString(strconv.Itoa(mds[i]))
desc.WriteString(dateSuffix(mds[i]))
}
desc.WriteString(" of each month")
return desc.String()
}
func dateSuffix(date int) string {
var ret string
switch date {
case 1:
ret = "st"
case 2:
ret = "nd"
case 3:
ret = "rd"
default:
ret = "th"
}
return ret
}

View File

@@ -72,7 +72,6 @@ type SScheduledTask struct {
STimer
TimerDesc string `width:"128" charset:"utf8" list:"user" get:"user"`
ResourceType string `width:"32" charset:"ascii" create:"required" list:"user" get:"user"`
Operation string `width:"32" charset:"ascii" create:"required" list:"user" get:"user"`
LabelType string `width:"4" charset:"ascii" create:"required" list:"user" get:"user"`
@@ -139,6 +138,7 @@ func (st *SScheduledTask) getMoreDetails(ctx context.Context, userCred mcclient.
case api.ST_TYPE_CYCLE:
out.CycleTimer = st.STimer.CycleTimerDetails()
}
out.TimerDesc = st.Description(ctx)
// fill label
stLabels, err := st.STLabels()
if err != nil {
@@ -184,36 +184,6 @@ func (stm *SScheduledTaskManager) ValidateCreateData(ctx context.Context, userCr
return input, nil
}
var wdsCN = []string{"", "一", "二", "三", "四", "五", "六", "日"}
var zone = time.FixedZone("GMT", 8*3600)
func (st *SScheduledTask) TimerDescription() string {
format := "2006-01-02 15:04:05"
var prefix string
timer := st.STimer
switch timer.Type {
case api.TIMER_TYPE_ONCE:
return fmt.Sprintf("单次 %s触发", timer.StartTime.In(zone).Format(format))
case api.TIMER_TYPE_DAY:
prefix = "每天"
case api.TIMER_TYPE_WEEK:
wds := timer.GetWeekDays()
weekDays := make([]string, len(wds))
for i := range wds {
weekDays[i] = fmt.Sprintf("星期%s", wdsCN[wds[i]])
}
prefix = fmt.Sprintf("每周 【%s】", strings.Join(weekDays, ""))
case api.TIMER_TYPE_MONTH:
mns := timer.GetMonthDays()
monthDays := make([]string, len(mns))
for i := range mns {
monthDays[i] = fmt.Sprintf("%d号", mns[i])
}
prefix = fmt.Sprintf("每月 【%s】", strings.Join(monthDays, ""))
}
return fmt.Sprintf("%s %02d:%02d触发 有效时间为%s至%s", prefix, timer.Hour, timer.Minute, timer.StartTime.In(zone).Format(format), timer.EndTime.In(zone).Format(format))
}
func (st *SScheduledTask) AllowPerformEnable(ctx context.Context, userCred mcclient.TokenCredential,
query jsonutils.JSONObject, input apis.PerformEnableInput) bool {
return true
@@ -288,7 +258,7 @@ func (st *SScheduledTask) PostCreate(ctx context.Context, userCred mcclient.Toke
st.Update(time.Time{})
st.Status = api.ST_STATUS_READY
st.Enabled = tristate.True
st.TimerDesc = st.TimerDescription()
// st.TimerDesc = st.Description(ctx)
err = st.GetModelManager().TableSpec().InsertOrUpdate(ctx, st)
if err != nil {
createFailed("update itself")

View File

@@ -15,13 +15,17 @@
package models
import (
"context"
"fmt"
"sort"
"strconv"
"strings"
"time"
"yunion.io/x/log"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/i18n"
"yunion.io/x/onecloud/pkg/util/bitmap"
)
@@ -159,6 +163,134 @@ func checkTimerCreateInput(in api.TimerCreateInput) (api.TimerCreateInput, error
return in, nil
}
var (
timerDescTable = i18n.Table{}
TIMERLANG = "timerLang"
)
func init() {
timerDescTable.Set("timerLang", i18n.NewTableEntry().EN("en").CN("cn"))
}
func (st *STimer) Description(ctx context.Context) string {
lang := timerDescTable.Lookup(ctx, TIMERLANG)
switch lang {
case "en":
return st.descEnglish()
case "cn":
return st.descChinese()
}
return ""
}
var (
wdsCN = []string{"", "一", "二", "三", "四", "五", "六", "日"}
wdsEN = []string{"", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}
zone = time.Now().Local().Location()
//zone = time.FixedZone("GMT", 8*3600)
)
func (st *STimer) descChinese() string {
format := "2006-01-02 15:04:05"
var prefix string
switch st.Type {
case api.TIMER_TYPE_ONCE:
return fmt.Sprintf("单次 %s触发", st.StartTime.In(zone).Format(format))
case api.TIMER_TYPE_DAY:
prefix = "每天"
case api.TIMER_TYPE_WEEK:
wds := st.GetWeekDays()
weekDays := make([]string, len(wds))
for i := range wds {
weekDays[i] = fmt.Sprintf("星期%s", wdsCN[wds[i]])
}
prefix = fmt.Sprintf("每周 【%s】", strings.Join(weekDays, ""))
case api.TIMER_TYPE_MONTH:
mns := st.GetMonthDays()
monthDays := make([]string, len(mns))
for i := range mns {
monthDays[i] = fmt.Sprintf("%d号", mns[i])
}
prefix = fmt.Sprintf("每月 【%s】", strings.Join(monthDays, ""))
}
return fmt.Sprintf("%s %02d:%02d触发 有效时间为%s至%s", prefix, st.Hour, st.Minute, st.StartTime.In(zone).Format(format), st.EndTime.In(zone).Format(format))
}
func (st *STimer) descEnglish() string {
var detail string
format := "2006-01-02 15:04:05"
switch st.Type {
case api.TIMER_TYPE_ONCE:
return st.EndTime.In(zone).Format(format)
case api.TIMER_TYPE_DAY:
detail = fmt.Sprintf("%d:%d every day", st.Hour, st.Minute)
case api.TIMER_TYPE_WEEK:
detail = st.weekDaysDesc()
case api.TIMER_TYPE_MONTH:
detail = st.monthDaysDesc()
}
if st.EndTime.IsZero() {
return detail
}
return fmt.Sprintf("%s, from %s to %s", detail, st.StartTime.In(zone).Format(format), st.EndTime.In(zone).Format(format))
}
func (st *STimer) weekDaysDesc() string {
if st.WeekDays == 0 {
return ""
}
var desc strings.Builder
wds := st.GetWeekDays()
i := 0
desc.WriteString(fmt.Sprintf("%d:%d every %s", st.Hour, st.Minute, wdsEN[wds[i]]))
for i++; i < len(wds)-1; i++ {
desc.WriteString(", ")
desc.WriteString(wdsEN[wds[i]])
}
if i == len(wds)-1 {
desc.WriteString(" and ")
desc.WriteString(wdsEN[wds[i]])
}
return desc.String()
}
func (st *STimer) monthDaysDesc() string {
if st.MonthDays == 0 {
return ""
}
var desc strings.Builder
mds := st.GetMonthDays()
i := 0
desc.WriteString(fmt.Sprintf("%d:%d on the %d%s", st.Hour, st.Minute, mds[i], st.dateSuffix(mds[i])))
for i++; i < len(mds)-1; i++ {
desc.WriteString(", ")
desc.WriteString(strconv.Itoa(mds[i]))
desc.WriteString(st.dateSuffix(mds[i]))
}
if i == len(mds)-1 {
desc.WriteString(" and ")
desc.WriteString(strconv.Itoa(mds[i]))
desc.WriteString(st.dateSuffix(mds[i]))
}
desc.WriteString(" of each month")
return desc.String()
}
func (st *STimer) dateSuffix(date int) string {
var ret string
switch date {
case 1:
ret = "st"
case 2:
ret = "nd"
case 3:
ret = "rd"
default:
ret = "th"
}
return ret
}
func checkCycleTimerCreateInput(in api.CycleTimerCreateInput) (api.CycleTimerCreateInput, error) {
now := time.Now()
if in.Minute < 0 || in.Minute > 59 {

View File

@@ -20,6 +20,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
@@ -33,6 +34,7 @@ type GuestStopTask struct {
func init() {
taskman.RegisterTask(GuestStopTask{})
taskman.RegisterTask(GuestStopAndFreezeTask{})
}
func (self *GuestStopTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
@@ -80,3 +82,40 @@ func (self *GuestStopTask) OnGuestStopTaskCompleteFailed(ctx context.Context, gu
self.SetStageFailed(ctx, reason)
logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_STOP, reason.String(), self.UserCred, false)
}
type GuestStopAndFreezeTask struct {
SGuestBaseTask
}
func (self *GuestStopAndFreezeTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
guest := obj.(*models.SGuest)
self.SetStage("OnStopGuest", nil)
err := guest.StartGuestStopTask(ctx, self.UserCred, false, false, self.GetTaskId())
if err != nil {
self.OnStopGuestFailed(ctx, guest, jsonutils.NewString(err.Error()))
}
}
func (self *GuestStopAndFreezeTask) OnStopGuestFailed(ctx context.Context, guest *models.SGuest, reason jsonutils.JSONObject) {
db.OpsLog.LogEvent(guest, db.ACT_FREEZE_FAIL, reason.String(), self.UserCred)
self.SetStageFailed(ctx, reason)
}
func (self *GuestStopAndFreezeTask) OnStopGuest(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
self.SetStage("OnSyncStatus", nil)
guest.StartSyncstatus(ctx, self.UserCred, self.GetTaskId())
}
func (self *GuestStopAndFreezeTask) OnSyncStatus(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
_, err := guest.SVirtualResourceBase.PerformFreeze(ctx, self.UserCred, nil, apis.PerformFreezeInput{})
if err != nil {
self.OnStopGuestFailed(ctx, guest, jsonutils.NewString(err.Error()))
return
}
self.SetStageComplete(ctx, nil)
}
func (self *GuestStopAndFreezeTask) OnSyncStatusFailed(ctx context.Context, guest *models.SGuest, reason jsonutils.JSONObject) {
db.OpsLog.LogEvent(guest, db.ACT_FREEZE_FAIL, reason.String(), self.UserCred)
self.SetStageFailed(ctx, reason)
}

View File

@@ -68,8 +68,13 @@ func (self *GuestSyncstatusTask) OnGetStatusSucc(ctx context.Context, guest *mod
default:
statusStr = api.VM_UNKNOWN
}
blockJobsCount, err := body.Int("block_jobs_count")
if err != nil {
blockJobsCount = -1
}
input := apis.PerformStatusInput{
Status: statusStr,
Status: statusStr,
BlockJobsCount: int(blockJobsCount),
}
guest.PerformStatus(ctx, self.UserCred, nil, input)
self.SetStageComplete(ctx, nil)

View File

@@ -106,8 +106,12 @@ func guestActions(f actionFunc) appsrv.FilterHandler {
func getStatus(ctx context.Context, w http.ResponseWriter, r *http.Request) {
params, _, _ := appsrv.FetchEnv(ctx, w, r)
var status = guestman.GetGuestManager().Status(params["<sid>"])
appsrv.SendStruct(w, strDict{"status": status})
var status, blockJobsCount = guestman.GetGuestManager().StatusWithBlockJobsCount(params["<sid>"])
res := map[string]interface{}{
"status": status,
"block_jobs_count": blockJobsCount,
}
appsrv.SendStruct(w, res)
}
func cpusetBalance(ctx context.Context, w http.ResponseWriter, r *http.Request) {

View File

@@ -477,6 +477,19 @@ func (m *SGuestManager) Status(sid string) string {
return status
}
func (m *SGuestManager) StatusWithBlockJobsCount(sid string) (string, int) {
status := m.GetStatus(sid)
blockJobsCount := 0
if status == GUEST_RUNNING {
guest, _ := m.GetServer(sid)
if guest.Monitor == nil && !guest.IsStopping() {
guest.StartMonitor(context.Background())
}
blockJobsCount = guest.BlockJobsCount()
}
return status, blockJobsCount
}
func (m *SGuestManager) GetStatus(sid string) string {
if guest, ok := m.GetServer(sid); ok {
if guest.IsRunning() && guest.Monitor != nil && guest.IsMaster() {

View File

@@ -0,0 +1,23 @@
package modules
import "yunion.io/x/onecloud/pkg/mcclient/modulebase"
var (
AnalysisPredictManager *SAnalysisPredict
)
func init() {
AnalysisPredictManager = NewAnalysisPredict()
Register(AnalysisPredictManager)
}
type SAnalysisPredict struct {
*modulebase.ResourceManager
}
func NewAnalysisPredict() *SAnalysisPredict {
man := NewSuggestionManager("analysispredict", "analysispredicts", []string{}, []string{})
return &SAnalysisPredict{
ResourceManager: &man,
}
}

View File

@@ -32,6 +32,7 @@ type AlertConfig struct {
conditions []*AlertCondition
execErrorState string
noDataState string
UsedBy string
}
func NewAlertConfig(name string, frequency string, enabled bool) (*AlertConfig, error) {

View File

@@ -29,3 +29,16 @@ func (o *AlertRecordShowOptions) Params() (jsonutils.JSONObject, error) {
func (o *AlertRecordShowOptions) GetId() string {
return o.ID
}
type AlertRecordTotalOptions struct {
ID string `help:"total-alert" json:"-"`
options.BaseListOptions
}
func (o *AlertRecordTotalOptions) Params() (jsonutils.JSONObject, error) {
return options.ListStructToParams(o)
}
func (o *AlertRecordTotalOptions) GetId() string {
return o.ID
}

View File

@@ -25,10 +25,22 @@ type SuggestSysAlertListOptions struct {
Type string `help:"Type of suggest rule" choices:"EIP_UNUSED|"`
}
func (o *SuggestSysAlertListOptions) Params() (jsonutils.JSONObject, error) {
return options.ListStructToParams(o)
}
type SSuggestAlertShowOptions struct {
ID string `help:"ID or name of the alert" json:"-"`
}
func (o *SSuggestAlertShowOptions) Params() (jsonutils.JSONObject, error) {
return options.StructToParams(o)
}
func (o *SSuggestAlertShowOptions) GetId() string {
return o.ID
}
type SuggestAlertIgnoreOptions struct {
ID string `help:"ID or name of the alert" json:"-"`
Scope string `help:"Resource scope" choices:"system|domain|project" default:"project"`
@@ -36,6 +48,10 @@ type SuggestAlertIgnoreOptions struct {
Project string `help:"'Owner project ID or Name" json:"project"`
}
func (opt *SuggestAlertIgnoreOptions) Params() (*jsonutils.JSONDict, error) {
func (opt *SuggestAlertIgnoreOptions) Params() (jsonutils.JSONObject, error) {
return options.StructToParams(opt)
}
func (o *SuggestAlertIgnoreOptions) GetId() string {
return o.ID
}

View File

@@ -0,0 +1,24 @@
package suggestion
import (
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/mcclient/options"
)
type AnalysisPredictConfigOptions struct {
ID string `help:"ID or name of the alert" json:"-"`
options.BaseListOptions
QueryType string `help:"query_type of the analysis" choices:"expense_trend" json:"query_type"`
StartDate string `help:"start_date of the analysis" json:"start_date"`
EndDate string `help:"end_date of the analysis" json:"end_date"`
DataType string `help:"data_type of the analysis" choices:"day|month" json:"data_type"`
}
func (o *AnalysisPredictConfigOptions) Params() (jsonutils.JSONObject, error) {
return options.ListStructToParams(o)
}
func (o *AnalysisPredictConfigOptions) GetId() string {
return o.ID
}

View File

@@ -0,0 +1 @@
package suggestion // import "yunion.io/x/onecloud/pkg/mcclient/options/suggestion"

View File

@@ -193,14 +193,13 @@ func init() {
// rds_cpu
RegistryMetricCreateInput("rds_cpu", "Rds CPU usage", monitor.METRIC_RES_TYPE_RDS,
monitor.METRIC_DATABASE_TELE, 1, []monitor.MetricFieldCreateInput{
newMetricFieldCreateInput("used_percent", "Connection usage", monitor.METRIC_UNIT_PERCENT, 1),
newMetricFieldCreateInput("usage_active", "CPU active state utilization rate", monitor.METRIC_UNIT_PERCENT, 2),
})
// rds_mem
RegistryMetricCreateInput("rds_mem", "Rds memory", monitor.METRIC_RES_TYPE_RDS,
monitor.METRIC_DATABASE_TELE, 2, []monitor.MetricFieldCreateInput{
newMetricFieldCreateInput("used_percent", "Connection usage", monitor.METRIC_UNIT_PERCENT, 1),
newMetricFieldCreateInput("used_percent", "Used memory rate", monitor.METRIC_UNIT_PERCENT, 1),
})
// rds_netio
@@ -219,13 +218,13 @@ func init() {
// dcs_cpu
RegistryMetricCreateInput("dcs_cpu", "Redis CPU usage", monitor.METRIC_RES_TYPE_REDIS,
monitor.METRIC_DATABASE_TELE, 1, []monitor.MetricFieldCreateInput{
newMetricFieldCreateInput("used_percent", "CPU active state utilization rate", monitor.METRIC_UNIT_PERCENT, 1),
newMetricFieldCreateInput("usage_percent", "CPU active state utilization rate", monitor.METRIC_UNIT_PERCENT, 1),
})
// dcs_mem
RegistryMetricCreateInput("dcs_mem", "Redis memory", monitor.METRIC_RES_TYPE_REDIS,
monitor.METRIC_DATABASE_TELE, 2, []monitor.MetricFieldCreateInput{
newMetricFieldCreateInput("used_percent", "memory usage", monitor.METRIC_UNIT_PERCENT, 1),
newMetricFieldCreateInput("used_percent", "Used memory rate", monitor.METRIC_UNIT_PERCENT, 1),
})
// dcs_netio

View File

@@ -297,5 +297,51 @@ func (manager *SAlertRecordManager) DeleteRecordsOfThirtyDaysAgo(ctx context.Con
log.Errorf("delete expire record:%s err:%v", records[i].GetId(), err)
}
}
}
func (manager *SAlertRecordManager) AllowGetPropertyTotalAlert(ctx context.Context, userCred mcclient.TokenCredential,
query jsonutils.JSONObject) bool {
return true
}
func (manager *SAlertRecordManager) GetPropertyTotalAlert(ctx context.Context, userCred mcclient.TokenCredential,
query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
alertRecords, err := manager.getNowAlertingRecord(ctx, userCred, query)
if err != nil {
return nil, errors.Wrap(err, "getNowAlertingRecord error")
}
alertCountMap := jsonutils.NewDict()
for _, record := range alertRecords {
evalMatches, err := record.GetEvalData()
if err != nil {
return nil, errors.Wrapf(err, "get record:%s evalData error", record.GetId())
}
count := int64(len(evalMatches))
if alertCountMap.Contains(record.ResType) {
resTypeCount, _ := alertCountMap.Int(record.ResType)
count = count + resTypeCount
}
alertCountMap.Set(record.ResType, jsonutils.NewInt(count))
}
return alertCountMap, nil
}
func (manager *SAlertRecordManager) getNowAlertingRecord(ctx context.Context, userCred mcclient.TokenCredential,
param jsonutils.JSONObject) ([]SAlertRecord, error) {
now := time.Now()
startTime := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 1, now.Location())
query := manager.Query()
scope, _ := param.GetString("scope")
query = manager.FilterByOwner(query, userCred, rbacutils.String2Scope(scope))
query = query.GE("created_at", startTime.UTC().Format(timeutils.MysqlTimeFormat))
query = query.Equals("state", monitor.AlertStateAlerting)
sQuery := CommonAlertManager.Query("id").Equals("state", monitor.AlertStateAlerting).IsNull("used_by").SubQuery()
query = query.In("alert_id", sQuery).IsNotNull("res_type").IsNotEmpty("res_type").GroupBy("alert_id")
records := make([]SAlertRecord, 0)
err := db.FetchModelObjects(manager, query, &records)
if err != nil {
return nil, err
}
return records, nil
}

View File

@@ -95,6 +95,7 @@ func init() {
renders["last"] = QueryDefinition{Renderer: functionRenderer}
renders["max"] = QueryDefinition{Renderer: functionRenderer}
renders["min"] = QueryDefinition{Renderer: functionRenderer}
renders["abs"] = QueryDefinition{Renderer: functionRenderer}
renders["percentile"] = QueryDefinition{
Renderer: functionRenderer,
Params: []DefinitionParameters{{Name: "nth", Type: "int"}},

View File

@@ -1025,6 +1025,7 @@ func (host *SHost) CloneVM(ctx context.Context, from *SVirtualMachine, snapshot
Device: dev,
})
}
nicIndex += 1
}
}

View File

@@ -533,6 +533,8 @@ func (rm *SReceiverManager) FetchOwnerId(ctx context.Context, data jsonutils.JSO
return nil, errors.Wrap(err, "UserCacheManager.FetchUserByIdOrName")
}
ownerId := db.SOwnerId{
DomainId: u.DomainId,
Domain: u.Domain,
UserDomain: u.Domain,
UserDomainId: u.DomainId,
UserId: u.Id,

View File

@@ -178,6 +178,7 @@ func FileGetContents(file string) (string, error) {
func GetFsFormat(diskPath string) string {
ret, err := procutils.NewCommand("blkid", "-o", "value", "-s", "TYPE", diskPath).Output()
if err != nil {
log.Errorf("failed exec blkid of dev %s: %s, %s", diskPath, err, ret)
return ""
}
var res string

View File

@@ -44,7 +44,7 @@ func (t *SSplitTableSpec) Insert(dt interface{}) error {
newMeta := false
if len(metas) > 0 {
lastMeta := metas[len(metas)-1]
if lastDate.Sub(lastMeta.StartDate) > t.maxDuration {
if !lastMeta.StartDate.IsZero() && lastDate.Sub(lastMeta.StartDate) > t.maxDuration {
lastTable := t.GetTableSpec(lastMeta)
ti := lastTable.Instance()
q := ti.Query(sqlchemy.MAX("last_index", ti.Field(t.indexField)), sqlchemy.MAX("last_date", ti.Field(t.dateField)))
@@ -64,29 +64,49 @@ func (t *SSplitTableSpec) Insert(dt interface{}) error {
}
newMeta = true
} else {
if lastMeta.StartDate.IsZero() {
indexCol := t.tableSpec.ColumnSpec(t.indexField)
_, err = t.metaSpec.Update(&lastMeta, func() error {
lastMeta.Start = indexCol.(*sqlchemy.SIntegerColumn).AutoIncrementOffset
lastMeta.StartDate = lastDate
return nil
})
if err != nil {
return errors.Wrap(err, "Update last meta")
}
}
lastTableSpec = t.GetTableSpec(lastMeta)
}
} else {
newMeta = true
}
if newMeta {
// insert a new metadata
meta := STableMetadata{
Table: fmt.Sprintf("%s_%d", t.tableName, lastDate.Unix()),
Start: lastRecIndex + 1,
StartDate: lastDate,
}
err := t.metaSpec.Insert(&meta)
lastTableSpec, err = t.newTable(lastRecIndex, lastDate)
if err != nil {
return errors.Wrap(err, "insert new meta")
return errors.Wrap(err, "newTable")
}
// create new table
newTable := t.GetTableSpec(meta)
err = newTable.Sync()
if err != nil {
return errors.Wrap(err, "sync new table")
}
lastTableSpec = newTable
}
return lastTableSpec.Insert(dt)
}
func (t *SSplitTableSpec) newTable(lastRecIndex int64, lastDate time.Time) (*sqlchemy.STableSpec, error) {
// insert a new metadata
meta := STableMetadata{
Table: fmt.Sprintf("%s_%d", t.tableName, lastDate.Unix()),
}
if lastRecIndex > 0 {
meta.Start = lastRecIndex + 1
meta.StartDate = lastDate
}
err := t.metaSpec.Insert(&meta)
if err != nil {
return nil, errors.Wrap(err, "insert new meta")
}
// create new table
newTable := t.GetTableSpec(meta)
err = newTable.Sync()
if err != nil {
return nil, errors.Wrap(err, "sync new table")
}
return newTable, nil
}

View File

@@ -140,7 +140,7 @@ func NewSplitTableSpec(s interface{}, name string, indexField string, dateField
metaSpec := sqlchemy.NewTableSpecFromStruct(&STableMetadata{}, fmt.Sprintf("%s_metadata", name))
return &SSplitTableSpec{
sts := &SSplitTableSpec{
indexField: indexField,
dateField: dateField,
tableName: name,
@@ -148,5 +148,7 @@ func NewSplitTableSpec(s interface{}, name string, indexField string, dateField
metaSpec: metaSpec,
maxDuration: maxDuration,
maxSegments: maxSegments,
}, nil
}
return sts, nil
}

View File

@@ -59,6 +59,11 @@ func (spec *SSplitTableSpec) Sync() error {
if err != nil {
return errors.Wrap(err, "insert init metadata")
}
} else {
_, err := spec.newTable(-1, time.Time{})
if err != nil {
return errors.Wrap(err, "spec.newTable")
}
}
} else {
for i := range metas {
@@ -81,11 +86,15 @@ func (spec *SSplitTableSpec) CheckSync() error {
if err != nil {
return errors.Wrap(err, "GetTableMetas")
}
for i := range metas {
subSpec := spec.GetTableSpec(metas[i])
err := subSpec.CheckSync()
if err != nil {
return errors.Wrap(err, "GetTableSpec")
if len(metas) == 0 {
return errors.Wrap(err, "empty metadata")
} else {
for i := range metas {
subSpec := spec.GetTableSpec(metas[i])
err := subSpec.CheckSync()
if err != nil {
return errors.Wrap(err, "GetTableSpec")
}
}
}
return nil
@@ -93,6 +102,8 @@ func (spec *SSplitTableSpec) CheckSync() error {
func (spec *SSplitTableSpec) SyncSQL() []string {
sqls := spec.metaSpec.SyncSQL()
zeroMeta := false
if spec.metaSpec.Exists() {
metas, err := spec.GetTableMetas()
if err != nil {
@@ -105,7 +116,30 @@ func (spec *SSplitTableSpec) SyncSQL() []string {
sqls = append(sqls, nsql...)
}
return sqls
} else { // len(metas) == 0
zeroMeta = true
}
} else {
nsql := spec.metaSpec.SyncSQL()
sqls = append(sqls, nsql...)
zeroMeta = true
}
if zeroMeta {
indexCol := spec.tableSpec.ColumnSpec(spec.indexField)
now := time.Now()
meta := STableMetadata{
Table: fmt.Sprintf("%s_%d", spec.tableName, now.Unix()),
Start: indexCol.(*sqlchemy.SIntegerColumn).AutoIncrementOffset,
}
// insert the first meta
sql := fmt.Sprintf("INSERT INTO `%s`(`table`, `deleted`, `created_at`) VALUES('%s', 0, '%s')", spec.metaSpec.Name(), meta.Table, timeutils.MysqlTime(now))
sqls = append(sqls, sql)
// create the first table
newtable := spec.GetTableSpec(meta)
nsql := newtable.SyncSQL()
sqls = append(sqls, nsql...)
return sqls
}
fakeMeta := STableMetadata{