mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-10-28 03:23:25 +08:00
feat(notify,region): improvement of news subscription
This commit is contained in:
@@ -3,4 +3,7 @@
|
||||
{{- if $d.brand -}}
|
||||
{{ $d.brand }}平台
|
||||
{{- end -}}
|
||||
{{ .resource_type_display }}{{ $d.name }}已经成功{{ .action_display }}
|
||||
{{ .resource_type_display }}{{ $d.name }}已经{{ .action_display }}{{.result_display}}
|
||||
{{- if eq .result "failed" -}}
|
||||
,请尽快前往控制台进行处理
|
||||
{{- end -}}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
{{- $d := .resource_details -}}
|
||||
您在{{ $d.project }}项目的
|
||||
{{- if $d.brand -}}
|
||||
{{ $d.brand }}平台
|
||||
{{- end -}}
|
||||
|
||||
{{- if $d.private_dns -}}
|
||||
,内网地址为{{ $d.private_dns }}:{{ $d.private_connect_port }}
|
||||
{{- end -}}
|
||||
|
||||
{{- if $d.public_dns -}}
|
||||
,外网地址为{{ $d.public_dns }}:{{ $d.public_connect_port }}
|
||||
{{- end -}}
|
||||
|
||||
{{- if $d.ips -}}
|
||||
,IP地址为{{ $d.ips }}
|
||||
{{- end -}}
|
||||
|
||||
{{- if $d.ip_addr -}}
|
||||
,IP地址为{{ $d.ip_addr }}
|
||||
{{- end -}}
|
||||
{{ .resource_type_display }}{{ $d.name }}已经删除成功。
|
||||
@@ -1,2 +1,5 @@
|
||||
{{- $d := .resource_details -}}
|
||||
Your {{ if $d.brand -}} {{ $d.brand }} {{ end -}} {{ .resource_type_display }} {{ $d.name }} {{ if $d.project -}} in project {{ $d.project }} {{ end -}} has been {{ .action_display }} successfully
|
||||
Your {{ if $d.brand -}} {{ $d.brand }} {{ end -}} {{ .resource_type_display }} {{ $d.name }} {{ if $d.project -}} in project {{ $d.project }} {{ end -}} has been {{ .action_display }} {{ .result_display }}
|
||||
{{- if eq .result "failed" -}}
|
||||
. And please go to the console as soon as possible to process.
|
||||
{{- end -}}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
{{- $d := .resource_details -}}
|
||||
Your {{ if $d.brand -}} {{ $d.brand }} {{ end -}} {{ .resource_type_display }} {{ $d.name }}
|
||||
{{ if $d.project -}} in project {{ $d.project }} {{ end -}} has been deleted successfully
|
||||
{{- if $d.private_dns -}}
|
||||
, the intranet address is {{ $d.private_dns }}:{{ $d.private_connect_port }}
|
||||
{{- end -}}
|
||||
|
||||
{{- if $d.public_dns -}}
|
||||
, the internet address is {{ $d.public_dns }}:{{ $d.public_connect_port }}
|
||||
{{- end -}}
|
||||
|
||||
{{- if and $d.address_type $d.address -}}
|
||||
, the service address is {{ $d.address_type }}{{ $d.address }}
|
||||
{{- end -}}
|
||||
|
||||
{{- if $d.ips -}}
|
||||
, the IP address is {{ $d.ips }}
|
||||
{{- end -}}
|
||||
|
||||
{{- if $d.ip_addr -}}
|
||||
, the IP address is {{ $d.ip_addr }}
|
||||
{{- end -}}
|
||||
@@ -2,4 +2,4 @@
|
||||
{{- if $d.project -}}
|
||||
{{ $d.project }}项目的
|
||||
{{- end -}}
|
||||
{{ .resource_type_display }}{{ $d.name }}{{ .action_display }}成功
|
||||
{{ .resource_type_display }}{{ $d.name }}{{ .action_display }}{{ .result_display }}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
{{- $d := .resource_details -}}
|
||||
The {{ .resource_type_display }} {{ .Name }} {{ if $d.project }} in poject {{ $d.project }} {{ end -}} {{ .action_display }} successfully
|
||||
The {{ .resource_type_display }} {{ .Name }} {{ if $d.project }} in poject {{ $d.project }} {{ end -}} {{ .action_display }} {{ .result_display }}
|
||||
|
||||
@@ -31,6 +31,7 @@ func init() {
|
||||
cmd.Perform("disable", new(options.ReceiverOptions))
|
||||
cmd.Perform("trigger-verify", new(options.ReceiverTriggerVerifyOptions))
|
||||
cmd.Perform("verify", new(options.ReceiverVerifyOptions))
|
||||
cmd.Perform("enable-contact-type", new(options.ReceiverEnableContactTypeInput))
|
||||
cmd.PerformClass("intellij-get", new(options.ReceiverIntellijGetOptions))
|
||||
cmd.PerformClass("get-types", new(options.ReceiverGetTypeOptions))
|
||||
}
|
||||
|
||||
@@ -21,12 +21,12 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.NotifyRobot).WithKeyword("notify-robot")
|
||||
cmd.List(new(options.RobotListOptions))
|
||||
cmd.Create(new(options.RobotCreateOptions))
|
||||
cmd.Update(new(options.RobotUpdateOptions))
|
||||
cmd.Show(new(options.RobotOptions))
|
||||
cmd.Delete(new(options.RobotOptions))
|
||||
cmd.Perform("enable", new(options.RobotOptions))
|
||||
cmd.Perform("disable", new(options.RobotOptions))
|
||||
cmd := shell.NewResourceCmd(&modules.NotifyRobot).WithKeyword("notify-robot")
|
||||
cmd.List(new(options.RobotListOptions))
|
||||
cmd.Create(new(options.RobotCreateOptions))
|
||||
cmd.Update(new(options.RobotUpdateOptions))
|
||||
cmd.Show(new(options.RobotOptions))
|
||||
cmd.Delete(new(options.RobotOptions))
|
||||
cmd.Perform("enable", new(options.RobotOptions))
|
||||
cmd.Perform("disable", new(options.RobotOptions))
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ func init() {
|
||||
cmd1.Create(new(notify.SubscriberCreateOptions))
|
||||
cmd1.Show(new(notify.SubscriberOptions))
|
||||
cmd1.Delete(new(notify.SubscriberOptions))
|
||||
cmd1.Perform("set-receiver", new(notify.SubscriberSetReceiverOptions))
|
||||
cmd1.Perform("change", new(notify.SubscriberChangeOptions))
|
||||
cmd1.Perform("enable", new(notify.SubscriberOptions))
|
||||
cmd1.Perform("disable", new(notify.SubscriberOptions))
|
||||
}
|
||||
|
||||
@@ -105,6 +105,7 @@ const (
|
||||
TOPIC_RESOURCE_DBINSTANCE = "dbinstance"
|
||||
TOPIC_RESOURCE_ELASTICCACHE = "elasticcache"
|
||||
TOPIC_RESOURCE_SCHEDULEDTASK = "scheduledtask"
|
||||
TOPIC_RESOURCE_BAREMETAL = "baremetal"
|
||||
|
||||
SUBSCRIBER_TYPE_ROLE = "role"
|
||||
SUBSCRIBER_TYPE_ROBOT = "robot"
|
||||
|
||||
@@ -33,6 +33,15 @@ var (
|
||||
ActionExpiredRelease SAction = "expired_release"
|
||||
ActionExecute SAction = "execute"
|
||||
ActionChangeIpaddr SAction = "change_ipaddr"
|
||||
ActionSyncStatus SAction = "sync_status"
|
||||
ActionCleanData SAction = "clean_data"
|
||||
ActionMigrate SAction = "migrate"
|
||||
|
||||
ActionCreateBackupServer SAction = "add_backup_server"
|
||||
ActionDelBackupServer SAction = "delete_backup_server"
|
||||
|
||||
ResultFailed SResult = "failed"
|
||||
ResultSucceed SResult = "succeed"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -41,9 +50,12 @@ const (
|
||||
|
||||
type SAction string
|
||||
|
||||
type SResult string
|
||||
|
||||
type SEvent struct {
|
||||
resourceType string
|
||||
action SAction
|
||||
result SResult
|
||||
}
|
||||
|
||||
func (se SEvent) WithResourceType(rt string) SEvent {
|
||||
@@ -56,6 +68,11 @@ func (se SEvent) WithAction(a SAction) SEvent {
|
||||
return se
|
||||
}
|
||||
|
||||
func (se SEvent) WithResult(r SResult) SEvent {
|
||||
se.result = r
|
||||
return se
|
||||
}
|
||||
|
||||
func (se SEvent) ResourceType() string {
|
||||
return se.resourceType
|
||||
}
|
||||
@@ -64,6 +81,29 @@ func (se SEvent) Action() SAction {
|
||||
return se.action
|
||||
}
|
||||
|
||||
func (se SEvent) ActionWithResult(delimiter string) string {
|
||||
ar := string(se.action)
|
||||
if len(se.result) > 0 {
|
||||
ar += delimiter + string(se.result)
|
||||
}
|
||||
return strings.ToUpper(ar)
|
||||
}
|
||||
|
||||
func (se SEvent) Result() SResult {
|
||||
if se.result == "" {
|
||||
return ResultSucceed
|
||||
}
|
||||
return se.result
|
||||
}
|
||||
|
||||
func (se SEvent) String() string {
|
||||
return strings.ToUpper(fmt.Sprintf("%s%s%s", se.ResourceType(), DelimiterInEvent, se.Action()))
|
||||
return se.StringWithDeli(DelimiterInEvent)
|
||||
}
|
||||
|
||||
func (se SEvent) StringWithDeli(delimiter string) string {
|
||||
str := strings.ToUpper(fmt.Sprintf("%s%s%s", se.ResourceType(), delimiter, se.Action()))
|
||||
if se.result != "" {
|
||||
str += delimiter + strings.ToUpper(string(se.result))
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
@@ -32,9 +32,9 @@ type NotificationCreateInput struct {
|
||||
// description: direct contact, admin privileges required
|
||||
// required: false
|
||||
Contacts []string `json:"contacts"`
|
||||
// description: robots
|
||||
// example: feishu robot
|
||||
Robots []string `json:"robots"`
|
||||
// description: robots
|
||||
// example: feishu robot
|
||||
Robots []string `json:"robots"`
|
||||
// description: contact type
|
||||
// required: ture
|
||||
// example: email
|
||||
@@ -87,14 +87,19 @@ type NotificationListInput struct {
|
||||
Tag string
|
||||
}
|
||||
|
||||
type SContact struct {
|
||||
Contact string `json:"contact"`
|
||||
ContactType string `json:"contact_type"`
|
||||
}
|
||||
|
||||
type NotificationManagerEventNotifyInput struct {
|
||||
// description: ids or names of receiver
|
||||
// required: false
|
||||
// example: {"adfb720ccdd34c638346ea4fa7a713a8", "zhangsan"}
|
||||
Receivers []string `json:"receivers"`
|
||||
// example: {"adfb720ccdd34c638346ea4fa7a713a8"}
|
||||
ReceiverIds []string `json:"receiver_ids"`
|
||||
// description: direct contact, admin privileges required
|
||||
// required: false
|
||||
Contacts []string `json:"contacts"`
|
||||
Contacts []SContact `json:"contacts"`
|
||||
// description: contact types
|
||||
// required: false
|
||||
// example: email
|
||||
|
||||
@@ -162,3 +162,7 @@ type ReceiverIntellijGetInput struct {
|
||||
// required: true
|
||||
Scope string `json:"scope"`
|
||||
}
|
||||
|
||||
type ReceiverEnableContactTypeInput struct {
|
||||
EnabledContactTypes []string `json:"enabled_contact_types"`
|
||||
}
|
||||
|
||||
+28
-28
@@ -3,41 +3,41 @@ package notify
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
type RobotCreateInput struct {
|
||||
apis.SharableVirtualResourceCreateInput
|
||||
// description: robot type
|
||||
// enum: feishu,dingtalk,workwx,webhook
|
||||
// example: webhook
|
||||
Type string `json:"type"`
|
||||
// description: address
|
||||
// example: http://helloworld.io/test/webhook
|
||||
Address string `json:"address"`
|
||||
// description: Language preference
|
||||
// example: zh_CN
|
||||
Lang string `json:"lang"`
|
||||
apis.SharableVirtualResourceCreateInput
|
||||
// description: robot type
|
||||
// enum: feishu,dingtalk,workwx,webhook
|
||||
// example: webhook
|
||||
Type string `json:"type"`
|
||||
// description: address
|
||||
// example: http://helloworld.io/test/webhook
|
||||
Address string `json:"address"`
|
||||
// description: Language preference
|
||||
// example: zh_CN
|
||||
Lang string `json:"lang"`
|
||||
}
|
||||
|
||||
type RobotDetails struct {
|
||||
apis.SharableVirtualResourceDetails
|
||||
apis.SharableVirtualResourceDetails
|
||||
}
|
||||
|
||||
type RobotListInput struct {
|
||||
apis.SharableVirtualResourceListInput
|
||||
apis.EnabledResourceBaseListInput
|
||||
// description: robot type
|
||||
// enum: feishu,dingtalk,workwx,webhook
|
||||
// example: webhook
|
||||
Type string `json:"type"`
|
||||
// description: Language preference
|
||||
// example: en
|
||||
Lang string `json:"lang"`
|
||||
apis.SharableVirtualResourceListInput
|
||||
apis.EnabledResourceBaseListInput
|
||||
// description: robot type
|
||||
// enum: feishu,dingtalk,workwx,webhook
|
||||
// example: webhook
|
||||
Type string `json:"type"`
|
||||
// description: Language preference
|
||||
// example: en
|
||||
Lang string `json:"lang"`
|
||||
}
|
||||
|
||||
type RobotUpdateInput struct {
|
||||
apis.SharableVirtualResourceBaseUpdateInput
|
||||
// description: address
|
||||
// example: http://helloworld.io/test/webhook
|
||||
Address string `json:"address"`
|
||||
// description: Language preference
|
||||
// example: en
|
||||
Lang string `json:"lang"`
|
||||
apis.SharableVirtualResourceBaseUpdateInput
|
||||
// description: address
|
||||
// example: http://helloworld.io/test/webhook
|
||||
Address string `json:"address"`
|
||||
// description: Language preference
|
||||
// example: en
|
||||
Lang string `json:"lang"`
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ package notify
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
type SubscriberCreateInput struct {
|
||||
apis.VirtualResourceCreateInput
|
||||
apis.StandaloneAnonResourceCreateInput
|
||||
|
||||
// description: Id of Topic
|
||||
// required
|
||||
@@ -27,6 +27,14 @@ type SubscriberCreateInput struct {
|
||||
// enum: system,domain,project
|
||||
ResourceScope string
|
||||
|
||||
// description: project id or domain id of resource
|
||||
// example: 1e3824756bac4ac084e784ed297ec652
|
||||
ResourceAttributionId string
|
||||
|
||||
// description: domain id of resource
|
||||
// example: 1e3824756bac4ac084e784ed297ec652
|
||||
DomainId string
|
||||
|
||||
// description: Type of subscriber
|
||||
// enum: receiver,robot,role
|
||||
Type string
|
||||
@@ -43,10 +51,29 @@ type SubscriberCreateInput struct {
|
||||
|
||||
// description: Robot(Id or Name) which is required when the type is 'robot' will Subscribe TopicID
|
||||
Robot string
|
||||
|
||||
// description: scope
|
||||
// enum: system,domain
|
||||
Scope string
|
||||
}
|
||||
|
||||
type SubscriberChangeInput struct {
|
||||
// description: receivers which is required when the type is 'receiver' will Subscribe TopicID
|
||||
Receivers []string
|
||||
|
||||
// description: Role(Id or Name) which is required when the type is 'role' will Subscribe TopicID
|
||||
Role string
|
||||
|
||||
// description: The scope of role subscribers
|
||||
// enum: system,domain,project
|
||||
RoleScope string
|
||||
|
||||
// description: Robot(Id or Name) which is required when the type is 'robot' will Subscribe TopicID
|
||||
Robot string
|
||||
}
|
||||
|
||||
type SubscriberListInput struct {
|
||||
apis.VirtualResourceListInput
|
||||
apis.StandaloneAnonResourceListInput
|
||||
apis.EnabledResourceBaseListInput
|
||||
|
||||
// description: topic id
|
||||
@@ -59,6 +86,10 @@ type SubscriberListInput struct {
|
||||
// description: type
|
||||
// enum: receiver,robot,role
|
||||
Type string
|
||||
|
||||
// description: scope
|
||||
// enum: system,domain
|
||||
Scope string
|
||||
}
|
||||
|
||||
type Identification struct {
|
||||
@@ -69,7 +100,7 @@ type Identification struct {
|
||||
}
|
||||
|
||||
type SubscriberDetails struct {
|
||||
apis.VirtualResourceDetails
|
||||
apis.StandaloneAnonResourceDetails
|
||||
SSubscriber
|
||||
|
||||
// description: receivers
|
||||
|
||||
@@ -28,3 +28,9 @@ type TopicDetails struct {
|
||||
// example: ["server", "eip", "disk"]
|
||||
Resources []string `json:"resource_types"`
|
||||
}
|
||||
|
||||
type PerformEnableInput struct {
|
||||
}
|
||||
|
||||
type PerformDisableInput struct {
|
||||
}
|
||||
|
||||
@@ -197,6 +197,7 @@ func mergeQueryParams(params map[string]string, query jsonutils.JSONObject, excl
|
||||
}
|
||||
|
||||
func listHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
||||
log.Infof("start list handler")
|
||||
manager, params, query, _ := fetchEnv(ctx, w, r)
|
||||
handleList(ctx, w, manager, nil, mergeQueryParams(params, query))
|
||||
}
|
||||
|
||||
@@ -1155,6 +1155,9 @@ func FetchModelObjects(modelManager IModelManager, query *sqlchemy.SQuery, targe
|
||||
|
||||
targetsValue := reflect.Indirect(reflect.ValueOf(targets))
|
||||
for rows.Next() {
|
||||
if modelManager.Keyword() == "server" {
|
||||
log.Infof("one guest")
|
||||
}
|
||||
m, err := NewModelObject(modelManager)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -52,6 +52,11 @@ var (
|
||||
ActionExpiredRelease = api.ActionExpiredRelease
|
||||
ActionExecute = api.ActionExecute
|
||||
|
||||
ActionMigrate = api.ActionMigrate
|
||||
ActionCreateBackupServer = api.ActionCreateBackupServer
|
||||
ActionDelBackupServer = api.ActionDelBackupServer
|
||||
ActionSyncStatus = api.ActionSyncStatus
|
||||
|
||||
ActionPendingDelete = api.ActionPendingDelete
|
||||
)
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ func NotifyAllWithoutRobotWithCtx(ctx context.Context, recipientId []string, isG
|
||||
|
||||
// NotifyRobot will send messages via all robot contact type such as dingtalk-robot.
|
||||
func NotifyRobot(robotIds []string, priority npk.TNotifyPriority, event string, data jsonutils.JSONObject) error {
|
||||
return NotifyRobotWithCtx(context.Background(), robotIds, priority, event, data)
|
||||
return NotifyRobotWithCtx(context.Background(), robotIds, priority, event, data)
|
||||
}
|
||||
|
||||
// NotifyRobot will send messages via all robot contact type such as dingtalk-robot.
|
||||
@@ -141,7 +141,7 @@ func NotifyRobotWithCtx(ctx context.Context, robotIds []string, priority npk.TNo
|
||||
event: event,
|
||||
data: data,
|
||||
})
|
||||
return nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func SystemNotify(priority npk.TNotifyPriority, event string, data jsonutils.JSONObject) {
|
||||
@@ -221,7 +221,9 @@ type SEventMessage struct {
|
||||
|
||||
type SEventNotifyParam struct {
|
||||
Obj db.IModel
|
||||
ResourceType string
|
||||
Action api.SAction
|
||||
IsFail bool
|
||||
ObjDetailsDecorator func(context.Context, *jsonutils.JSONDict)
|
||||
AdvanceDays int
|
||||
}
|
||||
@@ -247,9 +249,6 @@ func (t *eventTask) Run() {
|
||||
}
|
||||
|
||||
func EventNotify(ctx context.Context, userCred mcclient.TokenCredential, ep SEventNotifyParam) {
|
||||
// disable EventNotify for now
|
||||
return
|
||||
|
||||
ret, err := db.FetchCustomizeColumns(ep.Obj.GetModelManager(), ctx, userCred, jsonutils.NewDict(), []interface{}{ep.Obj}, stringutils2.SSortedStrings{}, false)
|
||||
if err != nil {
|
||||
log.Errorf("unable to FetchCustomizeColumns: %v", err)
|
||||
@@ -263,7 +262,14 @@ func EventNotify(ctx context.Context, userCred mcclient.TokenCredential, ep SEve
|
||||
if ep.ObjDetailsDecorator != nil {
|
||||
ep.ObjDetailsDecorator(ctx, objDetails)
|
||||
}
|
||||
event := api.Event.WithAction(ep.Action).WithResourceType(ep.Obj.GetModelManager().Keyword())
|
||||
rt := ep.ResourceType
|
||||
if len(rt) == 0 {
|
||||
rt = ep.Obj.GetModelManager().Keyword()
|
||||
}
|
||||
event := api.Event.WithAction(ep.Action).WithResourceType(rt)
|
||||
if ep.IsFail {
|
||||
event = event.WithResult(api.ResultFailed)
|
||||
}
|
||||
var (
|
||||
projectId string
|
||||
projectDomainId string
|
||||
@@ -274,6 +280,7 @@ func EventNotify(ctx context.Context, userCred mcclient.TokenCredential, ep SEve
|
||||
projectDomainId = ownerId.GetProjectDomainId()
|
||||
}
|
||||
params := api.NotificationManagerEventNotifyInput{
|
||||
ReceiverIds: []string{userCred.GetUserId()},
|
||||
ResourceDetails: objDetails,
|
||||
Event: event.String(),
|
||||
AdvanceDays: ep.AdvanceDays,
|
||||
|
||||
@@ -212,7 +212,7 @@ func genMsgViaLang(ctx context.Context, p sNotifyParams) ([]npk.SNotifyMessage,
|
||||
var langMap map[language.Tag]*sTarget
|
||||
|
||||
if p.channel == npk.NotifyByRobot {
|
||||
langMap, err = langRobot(ctx, p.robots)
|
||||
langMap, err = langRobot(ctx, p.robots)
|
||||
} else {
|
||||
langMap, err = lang(ctx, p.channel, reIds, p.contacts)
|
||||
if err != nil {
|
||||
@@ -226,7 +226,7 @@ func genMsgViaLang(ctx context.Context, p sNotifyParams) ([]npk.SNotifyMessage,
|
||||
msg := npk.SNotifyMessage{}
|
||||
msg.Uid = t.reIds
|
||||
msg.Priority = p.priority
|
||||
msg.Robots = p.robots
|
||||
msg.Robots = p.robots
|
||||
msg.Contacts = t.contacts
|
||||
msg.ContactType = p.channel
|
||||
topic, _ := getContent(langSuffix, p.event, "title", p.channel, p.data)
|
||||
|
||||
@@ -65,26 +65,26 @@ func getUserLang(uids []string) (map[string]string, error) {
|
||||
}
|
||||
|
||||
func getRobotLang(robots []string) (map[string]string, error) {
|
||||
s, err := AdminSessionGenerator(context.Background(), consts.GetRegion(), "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
robotLang := make(map[string]string)
|
||||
if len(robots) > 0 {
|
||||
params := jsonutils.NewDict()
|
||||
s, err := AdminSessionGenerator(context.Background(), consts.GetRegion(), "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
robotLang := make(map[string]string)
|
||||
if len(robots) > 0 {
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("filter", jsonutils.NewString(fmt.Sprintf("id.in(%s)", strings.Join(robots, ","))))
|
||||
params.Set("scope", jsonutils.NewString("system"))
|
||||
ret, err := modules.NotifyRobot.List(s, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range ret.Data {
|
||||
id, _ := ret.Data[i].GetString("id")
|
||||
langStr, _ := ret.Data[i].GetString("lang")
|
||||
robotLang[id] = langStr
|
||||
}
|
||||
}
|
||||
return robotLang, nil
|
||||
ret, err := modules.NotifyRobot.List(s, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range ret.Data {
|
||||
id, _ := ret.Data[i].GetString("id")
|
||||
langStr, _ := ret.Data[i].GetString("lang")
|
||||
robotLang[id] = langStr
|
||||
}
|
||||
}
|
||||
return robotLang, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -16,13 +16,17 @@ package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
api "yunion.io/x/onecloud/pkg/apis/billing"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
@@ -204,3 +208,83 @@ func ParseBillingCycleInput(billingBase *SBillingResourceBase, input apis.Postpa
|
||||
|
||||
return &bc, nil
|
||||
}
|
||||
|
||||
type SBillingResourceCheckManager struct {
|
||||
db.SResourceBaseManager
|
||||
}
|
||||
|
||||
type SBillingResourceCheck struct {
|
||||
db.SResourceBase
|
||||
ResourceId string `width:"128" charset:"ascii" index:"true"`
|
||||
ResourceType string `width:"36" charset:"ascii" index:"true"`
|
||||
AdvanceDays int
|
||||
LastCheck time.Time
|
||||
}
|
||||
|
||||
var BillingResourceCheckManager *SBillingResourceCheckManager
|
||||
|
||||
func init() {
|
||||
BillingResourceCheckManager = &SBillingResourceCheckManager{
|
||||
SResourceBaseManager: db.NewResourceBaseManager(
|
||||
SBillingResourceCheck{},
|
||||
"billingresourcecheck_tbl",
|
||||
"billingresourcecheck",
|
||||
"billingresourcechecks",
|
||||
),
|
||||
}
|
||||
BillingResourceCheckManager.SetVirtualObject(BillingResourceCheckManager)
|
||||
}
|
||||
|
||||
func (bm *SBillingResourceCheckManager) Create(ctx context.Context, resourceId, resourceType string, advanceDays int) error {
|
||||
bc := SBillingResourceCheck{
|
||||
ResourceId: resourceId,
|
||||
ResourceType: resourceType,
|
||||
AdvanceDays: advanceDays,
|
||||
LastCheck: time.Now(),
|
||||
}
|
||||
return bm.TableSpec().Insert(ctx, &bc)
|
||||
}
|
||||
|
||||
var advanceDays []int = []int{1, 3}
|
||||
|
||||
func CheckBillingResourceExpireAt(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
|
||||
billingResourceManagers := []db.IModelManager{
|
||||
GuestManager,
|
||||
DBInstanceManager,
|
||||
ElasticcacheManager,
|
||||
}
|
||||
for _, advanceDay := range advanceDays {
|
||||
for _, manager := range billingResourceManagers {
|
||||
upLimit := time.Now().AddDate(0, 0, advanceDay)
|
||||
downLimit := time.Now().AddDate(0, 0, advanceDay-1)
|
||||
v := reflect.MakeSlice(reflect.SliceOf(manager.TableSpec().DataType()), 0, 0)
|
||||
q := manager.Query().LE("expired_at", upLimit).GE("expired_at", downLimit)
|
||||
|
||||
bq := BillingResourceCheckManager.Query("resource_id").Equals("resource_type", manager.Keyword()).Equals("advance_days", advanceDay).SubQuery()
|
||||
q = q.LeftJoin(bq, sqlchemy.Equals(q.Field("id"), bq.Field("resource_id")))
|
||||
q = q.IsNull("resource_id")
|
||||
|
||||
vp := reflect.New(v.Type())
|
||||
vp.Elem().Set(v)
|
||||
err := db.FetchModelObjects(manager, q, vp.Interface())
|
||||
if err != nil {
|
||||
log.Errorf("unable to list %s: %v", manager.KeywordPlural(), err)
|
||||
}
|
||||
|
||||
v = vp.Elem()
|
||||
log.Debugf("%s length of v: %d", manager.Alias(), v.Len())
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
m := v.Index(i).Addr().Interface().(db.IModel)
|
||||
notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{
|
||||
Obj: m,
|
||||
Action: notifyclient.ActionExpiredRelease,
|
||||
AdvanceDays: advanceDay,
|
||||
})
|
||||
err := BillingResourceCheckManager.Create(ctx, m.GetId(), manager.Keyword(), advanceDay)
|
||||
if err != nil {
|
||||
log.Errorf("unable to create billingresourcecheck for resource %s %s", manager.Keyword(), m.GetId())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -973,8 +973,13 @@ func (self *SGuest) EventNotify(ctx context.Context, userCred mcclient.TokenCred
|
||||
}
|
||||
}
|
||||
}
|
||||
var resourceType string
|
||||
if self.Hypervisor == api.HYPERVISOR_BAREMETAL {
|
||||
resourceType = noapi.TOPIC_RESOURCE_BAREMETAL
|
||||
}
|
||||
notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{
|
||||
Obj: self,
|
||||
ResourceType: resourceType,
|
||||
Action: action,
|
||||
ObjDetailsDecorator: detailsDecro,
|
||||
AdvanceDays: 0,
|
||||
|
||||
@@ -91,6 +91,7 @@ func init() {
|
||||
"servers",
|
||||
),
|
||||
}
|
||||
log.Infof("init GuestManager")
|
||||
GuestManager.SetVirtualObject(GuestManager)
|
||||
GuestManager.SetAlias("guest", "guests")
|
||||
}
|
||||
|
||||
@@ -95,6 +95,7 @@ func InitHandlers(app *appsrv.Application) {
|
||||
models.CloudimageManager,
|
||||
|
||||
models.WafRuleStatementManager,
|
||||
models.BillingResourceCheckManager,
|
||||
} {
|
||||
db.RegisterModelManager(manager)
|
||||
}
|
||||
|
||||
@@ -165,6 +165,8 @@ func StartService() {
|
||||
cron.AddJobEveryFewHour("InspectAllTemplate", 1, 0, 0, models.GuestTemplateManager.InspectAllTemplate, true)
|
||||
|
||||
cron.AddJobAtIntervalsWithStartRun("ScheduledTaskCheck", time.Duration(60)*time.Second, models.ScheduledTaskManager.Timer, true)
|
||||
|
||||
cron.AddJobEveryFewHour("CheckBillingResourceExpireAt", 1, 0, 0, models.CheckBillingResourceExpireAt, true)
|
||||
go cron.Start2(ctx, electObj)
|
||||
|
||||
// init auto scaling controller
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
@@ -53,6 +54,10 @@ func (task *BucketCreateTask) OnInit(ctx context.Context, obj db.IStandaloneMode
|
||||
}
|
||||
|
||||
bucket.SetStatus(task.UserCred, api.BUCKET_STATUS_READY, "BucketCreateTask")
|
||||
notifyclient.EventNotify(ctx, task.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: bucket,
|
||||
Action: notifyclient.ActionCreate,
|
||||
})
|
||||
logclient.AddActionLogWithStartable(task, bucket, logclient.ACT_ALLOCATE, nil, task.UserCred, true)
|
||||
task.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
@@ -52,6 +53,10 @@ func (task *BucketDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneMode
|
||||
return
|
||||
}
|
||||
|
||||
notifyclient.EventNotify(ctx, task.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: bucket,
|
||||
Action: notifyclient.ActionDelete,
|
||||
})
|
||||
logclient.AddActionLogWithStartable(task, bucket, logclient.ACT_DELETE, nil, task.UserCred, true)
|
||||
task.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
@@ -73,7 +74,20 @@ func (self *DBInstanceAccountResetPasswordTask) OnInit(ctx context.Context, obj
|
||||
}
|
||||
}
|
||||
|
||||
self.resetPasswdNotify(ctx, instance, account, password)
|
||||
account.SetStatus(self.UserCred, api.DBINSTANCE_USER_AVAILABLE, "")
|
||||
logclient.AddActionLogWithStartable(self, account, logclient.ACT_RESET_PASSWORD, nil, self.UserCred, true)
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (self *DBInstanceAccountResetPasswordTask) resetPasswdNotify(ctx context.Context, rds *models.SDBInstance, account *models.SDBInstanceAccount, password string) {
|
||||
detailsDecro := func(ctx context.Context, details *jsonutils.JSONDict) {
|
||||
details.Set("account", jsonutils.NewString(account.GetName()))
|
||||
details.Set("password", jsonutils.NewString(password))
|
||||
}
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: rds,
|
||||
Action: notifyclient.ActionResetPassword,
|
||||
ObjDetailsDecorator: detailsDecro,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -41,6 +41,11 @@ func (self *DBInstanceChangeConfigTask) taskFailed(ctx context.Context, dbinstan
|
||||
dbinstance.SetStatus(self.UserCred, api.DBINSTANCE_CHANGE_CONFIG_FAILED, err.Error())
|
||||
db.OpsLog.LogEvent(dbinstance, db.ACT_CHANGE_CONFIG, err, self.GetUserCred())
|
||||
logclient.AddActionLogWithStartable(self, dbinstance, logclient.ACT_CHANGE_CONFIG, err, self.UserCred, false)
|
||||
notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{
|
||||
Obj: dbinstance,
|
||||
Action: notifyclient.ActionChangeConfig,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
@@ -64,7 +69,10 @@ func (self *DBInstanceChangeConfigTask) OnInit(ctx context.Context, obj db.IStan
|
||||
func (self *DBInstanceChangeConfigTask) OnDBInstanceChangeConfigComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
dbinstance := obj.(*models.SDBInstance)
|
||||
logclient.AddActionLogWithStartable(self, dbinstance, logclient.ACT_CHANGE_CONFIG, nil, self.UserCred, true)
|
||||
notifyclient.NotifyWebhook(ctx, self.UserCred, dbinstance, notifyclient.ActionChangeConfig)
|
||||
notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{
|
||||
Obj: dbinstance,
|
||||
Action: notifyclient.ActionChangeConfig,
|
||||
})
|
||||
self.SetStage("OnSyncDBInstanceStatusComplete", nil)
|
||||
models.StartResourceSyncStatusTask(ctx, self.UserCred, dbinstance, "DBInstanceSyncStatusTask", self.GetTaskId())
|
||||
}
|
||||
|
||||
@@ -40,6 +40,11 @@ func (self *DBInstanceCreateTask) taskFailed(ctx context.Context, dbinstance *mo
|
||||
dbinstance.SetStatus(self.UserCred, api.DBINSTANCE_CREATE_FAILED, err.Error())
|
||||
db.OpsLog.LogEvent(dbinstance, db.ACT_CREATE, err, self.GetUserCred())
|
||||
logclient.AddActionLogWithStartable(self, dbinstance, logclient.ACT_CREATE, err, self.UserCred, false)
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: dbinstance,
|
||||
Action: notifyclient.ActionCreate,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
@@ -77,7 +82,11 @@ func (self *DBInstanceCreateTask) OnCreateDBInstanceCompleteFailed(ctx context.C
|
||||
|
||||
func (self *DBInstanceCreateTask) OnSyncDBInstanceStatusComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
dbinstance := obj.(*models.SDBInstance)
|
||||
notifyclient.NotifyWebhook(ctx, self.UserCred, dbinstance, notifyclient.ActionCreate)
|
||||
//notifyclient.NotifyWebhook(ctx, self.UserCred, dbinstance, notifyclient.ActionCreate)
|
||||
notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{
|
||||
Obj: dbinstance,
|
||||
Action: notifyclient.ActionCreate,
|
||||
})
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,11 @@ func (self *DBInstanceDeleteTask) taskFailed(ctx context.Context, dbinstance *mo
|
||||
dbinstance.SetStatus(self.UserCred, api.DBINSTANCE_DELETE_FAILED, err.Error())
|
||||
db.OpsLog.LogEvent(dbinstance, db.ACT_DELETE, err, self.GetUserCred())
|
||||
logclient.AddActionLogWithStartable(self, dbinstance, logclient.ACT_DELETE, err, self.UserCred, false)
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: dbinstance,
|
||||
Action: notifyclient.ActionDelete,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
@@ -83,13 +88,21 @@ func (self *DBInstanceDeleteTask) DeleteDBInstanceComplete(ctx context.Context,
|
||||
self.taskFailed(ctx, dbinstance, errors.Wrap(err, "dbinstance.Purge"))
|
||||
return
|
||||
}
|
||||
notifyclient.NotifyWebhook(ctx, self.UserCred, dbinstance, notifyclient.ActionDelete)
|
||||
//notifyclient.NotifyWebhook(ctx, self.UserCred, dbinstance, notifyclient.ActionDelete)
|
||||
notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{
|
||||
Obj: dbinstance,
|
||||
Action: notifyclient.ActionDelete,
|
||||
})
|
||||
self.SetStageComplete(ctx, nil)
|
||||
return
|
||||
}
|
||||
|
||||
self.DeleteBackups(ctx, dbinstance, nil)
|
||||
notifyclient.NotifyWebhook(ctx, self.UserCred, dbinstance, notifyclient.ActionDelete)
|
||||
//notifyclient.NotifyWebhook(ctx, self.UserCred, dbinstance, notifyclient.ActionDelete)
|
||||
notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{
|
||||
Obj: dbinstance,
|
||||
Action: notifyclient.ActionDelete,
|
||||
})
|
||||
}
|
||||
|
||||
func (self *DBInstanceDeleteTask) DeleteBackups(ctx context.Context, instance *models.SDBInstance, data jsonutils.JSONObject) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
@@ -39,6 +40,11 @@ func (self *DBInstanceSyncStatusTask) taskFailed(ctx context.Context, dbinstance
|
||||
dbinstance.SetStatus(self.UserCred, api.DBINSTANCE_UNKNOWN, err.Error())
|
||||
db.OpsLog.LogEvent(dbinstance, db.ACT_SYNC_STATUS, err, self.GetUserCred())
|
||||
logclient.AddActionLogWithStartable(self, dbinstance, logclient.ACT_SYNC_STATUS, err, self.UserCred, false)
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: dbinstance,
|
||||
Action: notifyclient.ActionSyncStatus,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,11 @@ func init() {
|
||||
func (self *EipAllocateTask) onFailed(ctx context.Context, eip *models.SElasticip, reason jsonutils.JSONObject) {
|
||||
eip.SetStatus(self.UserCred, api.EIP_STATUS_ALLOCATE_FAIL, reason.String())
|
||||
self.setGuestAllocateEipFailed(eip, reason)
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: eip,
|
||||
Action: notifyclient.ActionCreate,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, reason)
|
||||
}
|
||||
|
||||
@@ -159,6 +164,10 @@ func (self *EipAllocateTask) OnInit(ctx context.Context, obj db.IStandaloneModel
|
||||
}
|
||||
} else {
|
||||
logclient.AddActionLogWithStartable(self, eip, logclient.ACT_ALLOCATE, nil, self.UserCred, true)
|
||||
notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{
|
||||
Obj: eip,
|
||||
Action: notifyclient.ActionCreate,
|
||||
})
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
}
|
||||
@@ -166,10 +175,6 @@ func (self *EipAllocateTask) OnInit(ctx context.Context, obj db.IStandaloneModel
|
||||
func (self *EipAllocateTask) OnEipAssociateComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
eip := obj.(*models.SElasticip)
|
||||
logclient.AddActionLogWithStartable(self, eip, logclient.ACT_ALLOCATE, nil, self.UserCred, true)
|
||||
notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{
|
||||
Obj: eip,
|
||||
Action: notifyclient.ActionCreate,
|
||||
})
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,11 @@ func (self *EipDeallocateTask) taskFail(ctx context.Context, eip *models.SElasti
|
||||
eip.SetStatus(self.UserCred, api.EIP_STATUS_DEALLOCATE_FAIL, msg.String())
|
||||
db.OpsLog.LogEvent(eip, db.ACT_DELOCATE, msg, self.GetUserCred())
|
||||
logclient.AddActionLogWithStartable(self, eip, logclient.ACT_DELETE, msg, self.UserCred, false)
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: eip,
|
||||
Action: notifyclient.ActionDelete,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -68,7 +68,21 @@ func (self *ElasticcacheAccountResetPasswordTask) OnInit(ctx context.Context, ob
|
||||
ec.(*models.SElasticcache).SetStatus(self.GetUserCred(), api.ELASTIC_CACHE_STATUS_RUNNING, "")
|
||||
logclient.AddActionLogWithStartable(self, ec, logclient.ACT_RESET_PASSWORD, "", self.UserCred, true)
|
||||
}
|
||||
password, _ := self.GetParams().GetString("password")
|
||||
self.resetPasswordNotify(ctx, ec.(*models.SElasticcache), ea, password)
|
||||
logclient.AddActionLogWithStartable(self, ea, logclient.ACT_RESET_PASSWORD, "", self.UserCred, true)
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *ElasticcacheAccountResetPasswordTask) resetPasswordNotify(ctx context.Context, ec *models.SElasticcache, account *models.SElasticcacheAccount, password string) {
|
||||
detailDecro := func(ctx context.Context, details *jsonutils.JSONDict) {
|
||||
details.Set("account", jsonutils.NewString(account.GetName()))
|
||||
details.Set("password", jsonutils.NewString(password))
|
||||
}
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: ec,
|
||||
Action: notifyclient.ActionResetPassword,
|
||||
ObjDetailsDecorator: detailDecro,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -40,7 +40,11 @@ func (self *ElasticcacheChangeSpecTask) taskFail(ctx context.Context, ec *models
|
||||
ec.SetStatus(self.GetUserCred(), api.ELASTIC_CACHE_STATUS_CHANGE_FAILED, reason.String())
|
||||
db.OpsLog.LogEvent(ec, db.ACT_CHANGE_FLAVOR, reason, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, ec, logclient.ACT_VM_CHANGE_FLAVOR, reason, self.UserCred, false)
|
||||
notifyclient.NotifySystemErrorWithCtx(ctx, ec.Id, ec.Name, api.ELASTIC_CACHE_STATUS_CHANGE_FAILED, reason.String())
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: ec,
|
||||
Action: notifyclient.ActionChangeConfig,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, reason)
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,11 @@ func (self *ElasticcacheCreateTask) taskFail(ctx context.Context, elasticcache *
|
||||
elasticcache.SetStatus(self.GetUserCred(), api.ELASTIC_CACHE_STATUS_CREATE_FAILED, reason.String())
|
||||
db.OpsLog.LogEvent(elasticcache, db.ACT_ALLOCATE_FAIL, reason, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, elasticcache, logclient.ACT_CREATE, reason, self.UserCred, false)
|
||||
notifyclient.NotifySystemErrorWithCtx(ctx, elasticcache.Id, elasticcache.Name, api.ELASTIC_CACHE_STATUS_CREATE_FAILED, reason.String())
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: elasticcache,
|
||||
Action: notifyclient.ActionCreate,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, reason)
|
||||
}
|
||||
|
||||
@@ -95,7 +99,11 @@ func (self *ElasticcacheCreateTask) OnSyncSecurityGroupCompleteFailed(ctx contex
|
||||
func (self *ElasticcacheCreateTask) OnElasticcacheCreateComplete(ctx context.Context, elasticcache *models.SElasticcache, data jsonutils.JSONObject) {
|
||||
elasticcache.SetStatus(self.GetUserCred(), api.ELASTIC_CACHE_STATUS_RUNNING, "")
|
||||
logclient.AddActionLogWithStartable(self, elasticcache, logclient.ACT_CREATE, "", self.UserCred, true)
|
||||
notifyclient.NotifyWebhook(ctx, self.UserCred, elasticcache, notifyclient.ActionCreate)
|
||||
// notifyclient.NotifyWebhook(ctx, self.UserCred, elasticcache, notifyclient.ActionCreate)
|
||||
notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{
|
||||
Obj: elasticcache,
|
||||
Action: notifyclient.ActionCreate,
|
||||
})
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,11 @@ func (self *ElasticcacheDeleteTask) taskFail(ctx context.Context, elasticcache *
|
||||
elasticcache.SetStatus(self.GetUserCred(), api.ELASTIC_CACHE_STATUS_RELEASE_FAILED, reason.String())
|
||||
db.OpsLog.LogEvent(elasticcache, db.ACT_DELOCATE_FAIL, reason, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, elasticcache, logclient.ACT_DELETE, reason, self.UserCred, false)
|
||||
notifyclient.NotifySystemErrorWithCtx(ctx, elasticcache.Id, elasticcache.Name, api.ELASTIC_CACHE_STATUS_RELEASE_FAILED, reason.String())
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: elasticcache,
|
||||
Action: notifyclient.ActionDelete,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, reason)
|
||||
}
|
||||
|
||||
@@ -62,7 +66,10 @@ func (self *ElasticcacheDeleteTask) OnInit(ctx context.Context, obj db.IStandalo
|
||||
ec.DeleteSubResources(ctx, self.UserCred)
|
||||
ec.SVirtualResourceBase.Delete(ctx, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, ec, logclient.ACT_DELETE, "", self.UserCred, true)
|
||||
notifyclient.NotifyWebhook(ctx, self.UserCred, ec, notifyclient.ActionDelete)
|
||||
notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{
|
||||
Obj: ec,
|
||||
Action: notifyclient.ActionDelete,
|
||||
})
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
@@ -40,6 +41,11 @@ func (self *ElasticcacheSyncstatusTask) taskFailed(ctx context.Context, cache *m
|
||||
self.SetStageFailed(ctx, err)
|
||||
db.OpsLog.LogEvent(cache, db.ACT_SYNC_STATUS, cache.GetShortDesc(ctx), self.GetUserCred())
|
||||
logclient.AddActionLogWithContext(ctx, cache, logclient.ACT_SYNC_STATUS, err, self.UserCred, false)
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: cache,
|
||||
Action: notifyclient.ActionSyncStatus,
|
||||
IsFail: true,
|
||||
})
|
||||
}
|
||||
|
||||
func (self *ElasticcacheSyncstatusTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
|
||||
@@ -296,7 +296,11 @@ func (self *GuestBatchCreateTask) SaveScheduleResult(ctx context.Context, obj IS
|
||||
self.clearPendingUsage(ctx, guest)
|
||||
db.OpsLog.LogEvent(guest, db.ACT_ALLOCATE_FAIL, err, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, obj, logclient.ACT_ALLOCATE, err, self.GetUserCred(), false)
|
||||
notifyclient.NotifySystemErrorWithCtx(ctx, guest.Id, guest.Name, api.VM_CREATE_FAILED, err.Error())
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: guest,
|
||||
Action: notifyclient.ActionCreateBackupServer,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +335,6 @@ func (self *GuestChangeConfigTask) OnGuestChangeCpuMemSpecCompleteFailed(ctx con
|
||||
func (self *GuestChangeConfigTask) OnGuestChangeCpuMemSpecFinish(ctx context.Context, guest *models.SGuest) {
|
||||
models.HostManager.ClearSchedDescCache(guest.HostId)
|
||||
self.SetStage("OnSyncConfigComplete", nil)
|
||||
notifyclient.NotifyWebhook(ctx, self.UserCred, guest, notifyclient.ActionChangeConfig)
|
||||
err := guest.StartSyncTaskWithoutSyncstatus(ctx, self.UserCred, false, self.GetTaskId())
|
||||
if err != nil {
|
||||
self.markStageFailed(ctx, guest, jsonutils.NewString(fmt.Sprintf("StartSyncstatus fail %s", err)))
|
||||
@@ -383,7 +382,11 @@ func (self *GuestChangeConfigTask) markStageFailed(ctx context.Context, guest *m
|
||||
guest.SetStatus(self.UserCred, api.VM_CHANGE_FLAVOR_FAIL, reason.String())
|
||||
db.OpsLog.LogEvent(guest, db.ACT_CHANGE_FLAVOR_FAIL, reason, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_CHANGE_FLAVOR, reason, self.UserCred, false)
|
||||
notifyclient.NotifyError(ctx, self.UserCred, guest.GetId(), guest.GetName(), logclient.ACT_VM_CHANGE_FLAVOR, reason.String())
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: guest,
|
||||
Action: notifyclient.ActionChangeConfig,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, reason)
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules/notify"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
@@ -70,7 +69,12 @@ func (self *GuestCreateTask) OnDiskPreparedFailed(ctx context.Context, obj db.IS
|
||||
guest.SetStatus(self.UserCred, api.VM_DISK_FAILED, "allocation failed")
|
||||
db.OpsLog.LogEvent(guest, db.ACT_ALLOCATE_FAIL, data, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, guest, logclient.ACT_ALLOCATE, data, self.UserCred, false)
|
||||
notifyclient.NotifySystemErrorWithCtx(ctx, guest.Id, guest.Name, api.VM_DISK_FAILED, data.String())
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: guest,
|
||||
Action: notifyclient.ActionCreate,
|
||||
IsFail: true,
|
||||
})
|
||||
|
||||
self.SetStageFailed(ctx, data)
|
||||
}
|
||||
|
||||
@@ -99,7 +103,11 @@ func (self *GuestCreateTask) OnCdromPreparedFailed(ctx context.Context, obj db.I
|
||||
guest.SetStatus(self.UserCred, api.VM_DISK_FAILED, "")
|
||||
db.OpsLog.LogEvent(guest, db.ACT_ALLOCATE_FAIL, data, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, guest, logclient.ACT_ALLOCATE, data, self.UserCred, false)
|
||||
notifyclient.NotifySystemErrorWithCtx(ctx, guest.Id, guest.Name, api.VM_DISK_FAILED, fmt.Sprintf("cdrom_failed %s", data))
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: guest,
|
||||
Action: notifyclient.ActionCreate,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, data)
|
||||
}
|
||||
|
||||
@@ -160,21 +168,18 @@ func (self *GuestCreateTask) OnDeployGuestDescComplete(ctx context.Context, obj
|
||||
}
|
||||
|
||||
func (self *GuestCreateTask) notifyServerCreated(ctx context.Context, guest *models.SGuest) {
|
||||
notifyclient.NotifyWebhook(ctx, self.UserCred, guest, notifyclient.ActionCreate)
|
||||
guest.NotifyServerEvent(
|
||||
ctx, self.UserCred, notifyclient.SERVER_CREATED,
|
||||
notify.NotifyPriorityImportant, true, nil, false,
|
||||
)
|
||||
guest.NotifyAdminServerEvent(ctx, notifyclient.SERVER_CREATED_ADMIN, notify.NotifyPriorityImportant)
|
||||
// guest.EventNotify(ctx, self.UserCred, notifyclient.ActionCreate)
|
||||
guest.EventNotify(ctx, self.UserCred, notifyclient.ActionCreate)
|
||||
}
|
||||
|
||||
func (self *GuestCreateTask) OnDeployGuestDescCompleteFailed(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
guest.SetStatus(self.UserCred, api.VM_DEPLOY_FAILED, "deploy_failed")
|
||||
db.OpsLog.LogEvent(guest, db.ACT_ALLOCATE_FAIL, data, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, guest, logclient.ACT_ALLOCATE, data, self.UserCred, false)
|
||||
notifyclient.NotifySystemErrorWithCtx(ctx, guest.Id, guest.Name, api.VM_DEPLOY_FAILED, data.String())
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: guest,
|
||||
Action: notifyclient.ActionCreate,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, data)
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/httputils"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
@@ -40,6 +41,11 @@ func (self *GuestDeleteBackupTask) OnFail(ctx context.Context, guest *models.SGu
|
||||
logclient.AddActionLogWithContext(ctx, guest, logclient.ACT_DELETE_BACKUP, reason, self.UserCred, false)
|
||||
db.OpsLog.LogEvent(guest, db.ACT_DELETE_BACKUP_FAILED, reason, self.UserCred)
|
||||
guest.SetStatus(self.UserCred, compute.VM_BACKUP_DELETE_FAILED, reason.String())
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: guest,
|
||||
Action: notifyclient.ActionDelBackupServer,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, reason)
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules/notify"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
@@ -307,6 +306,11 @@ func (self *GuestDeleteTask) OnFailed(ctx context.Context, guest *models.SGuest,
|
||||
guest.SetStatus(self.UserCred, api.VM_DELETE_FAIL, err.String())
|
||||
db.OpsLog.LogEvent(guest, db.ACT_DELOCATE_FAIL, err, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, guest, logclient.ACT_DELOCATE, err, self.UserCred, false)
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: guest,
|
||||
Action: notifyclient.ActionDelete,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, err)
|
||||
}
|
||||
|
||||
@@ -354,14 +358,5 @@ func (self *GuestDeleteTask) DeleteGuest(ctx context.Context, guest *models.SGue
|
||||
}
|
||||
|
||||
func (self *GuestDeleteTask) NotifyServerDeleted(ctx context.Context, guest *models.SGuest) {
|
||||
notifyclient.NotifyWebhook(ctx, self.UserCred, guest, notifyclient.ActionPendingDelete)
|
||||
guest.NotifyServerEvent(
|
||||
ctx,
|
||||
self.UserCred,
|
||||
notifyclient.SERVER_DELETED,
|
||||
notify.NotifyPriorityImportant,
|
||||
false, nil, false,
|
||||
)
|
||||
guest.NotifyAdminServerEvent(ctx, notifyclient.SERVER_DELETED_ADMIN, notify.NotifyPriorityImportant)
|
||||
// guest.EventNotify(ctx, self.UserCred, notifyclient.ActionPendingDelete)
|
||||
guest.EventNotify(ctx, self.UserCred, notifyclient.ActionPendingDelete)
|
||||
}
|
||||
|
||||
@@ -470,6 +470,11 @@ func (self *GuestMigrateTask) TaskFailed(ctx context.Context, guest *models.SGue
|
||||
logclient.AddActionLogWithContext(ctx, guest, logclient.ACT_MIGRATE, reason, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, reason)
|
||||
notifyclient.NotifySystemErrorWithCtx(ctx, guest.Id, guest.Name, api.VM_MIGRATE_FAILED, reason.String())
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: guest,
|
||||
Action: notifyclient.ActionMigrate,
|
||||
IsFail: true,
|
||||
})
|
||||
}
|
||||
|
||||
//ManagedGuestMigrateTask
|
||||
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules/notify"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
@@ -59,6 +58,11 @@ func (self *GuestRebuildRootTask) markFailed(ctx context.Context, guest *models.
|
||||
logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_REBUILD, reason, self.UserCred, false)
|
||||
guest.SetStatus(self.GetUserCred(), api.VM_REBUILD_ROOT_FAIL, reason.String())
|
||||
self.SGuestBaseTask.SetStageFailed(ctx, reason)
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: guest,
|
||||
Action: notifyclient.ActionRebuildRoot,
|
||||
IsFail: true,
|
||||
})
|
||||
gds := guest.CategorizeDisks()
|
||||
imageId, _ := self.Params.GetString("origin_image_id")
|
||||
_, err := db.Update(gds.Root, func() error {
|
||||
@@ -176,15 +180,7 @@ func (self *GuestRebuildRootTask) OnRebuildAllDisksComplete(ctx context.Context,
|
||||
}
|
||||
}
|
||||
db.OpsLog.LogEvent(guest, db.ACT_REBUILD_ROOT, "", self.UserCred)
|
||||
notifyclient.NotifyWebhook(ctx, self.UserCred, guest, notifyclient.ActionRebuildRoot)
|
||||
guest.NotifyServerEvent(
|
||||
ctx,
|
||||
self.UserCred,
|
||||
notifyclient.SERVER_REBUILD_ROOT,
|
||||
notify.NotifyPriorityImportant,
|
||||
true, nil, false,
|
||||
)
|
||||
// guest.EventNotify(ctx, self.UserCred, notifyclient.ActionRebuildRoot)
|
||||
guest.EventNotify(ctx, self.UserCred, notifyclient.ActionRebuildRoot)
|
||||
self.SetStage("OnSyncStatusComplete", nil)
|
||||
guest.StartSyncstatus(ctx, self.UserCred, self.GetTaskId())
|
||||
}
|
||||
|
||||
@@ -41,6 +41,11 @@ func (self *LoadbalancerCreateTask) taskFail(ctx context.Context, lb *models.SLo
|
||||
db.OpsLog.LogEvent(lb, db.ACT_ALLOCATE_FAIL, reason, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, lb, logclient.ACT_CREATE, reason, self.UserCred, false)
|
||||
notifyclient.NotifySystemErrorWithCtx(ctx, lb.Id, lb.Name, api.LB_CREATE_FAILED, reason.String())
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: lb,
|
||||
Action: notifyclient.ActionCreate,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, reason)
|
||||
}
|
||||
|
||||
@@ -71,7 +76,10 @@ func (self *LoadbalancerCreateTask) OnLoadbalancerCreateCompleteFailed(ctx conte
|
||||
|
||||
func (self *LoadbalancerCreateTask) OnLoadbalancerStartComplete(ctx context.Context, lb *models.SLoadbalancer, data jsonutils.JSONObject) {
|
||||
lb.SetStatus(self.GetUserCred(), api.LB_STATUS_ENABLED, "")
|
||||
notifyclient.NotifyWebhook(ctx, self.UserCred, lb, notifyclient.ActionCreate)
|
||||
notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{
|
||||
Obj: lb,
|
||||
Action: notifyclient.ActionCreate,
|
||||
})
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,11 @@ func (self *LoadbalancerDeleteTask) taskFail(ctx context.Context, lb *models.SLo
|
||||
lb.SetStatus(self.GetUserCred(), api.LB_STATUS_DELETE_FAILED, reason.String())
|
||||
db.OpsLog.LogEvent(lb, db.ACT_DELOCATE_FAIL, reason, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, lb, logclient.ACT_DELOCATE, reason, self.UserCred, false)
|
||||
notifyclient.NotifySystemErrorWithCtx(ctx, lb.Id, lb.Name, api.LB_STATUS_DELETE_FAILED, reason.String())
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: lb,
|
||||
Action: notifyclient.ActionDelete,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, reason)
|
||||
}
|
||||
|
||||
@@ -60,7 +64,11 @@ func (self *LoadbalancerDeleteTask) OnInit(ctx context.Context, obj db.IStandalo
|
||||
func (self *LoadbalancerDeleteTask) OnLoadbalancerDeleteComplete(ctx context.Context, lb *models.SLoadbalancer, data jsonutils.JSONObject) {
|
||||
db.OpsLog.LogEvent(lb, db.ACT_DELETE, lb.GetShortDesc(ctx), self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, lb, logclient.ACT_DELOCATE, nil, self.UserCred, true)
|
||||
notifyclient.NotifyWebhook(ctx, self.UserCred, lb, notifyclient.ActionDelete)
|
||||
// notifyclient.NotifyWebhook(ctx, self.UserCred, lb, notifyclient.ActionDelete)
|
||||
notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{
|
||||
Obj: lb,
|
||||
Action: notifyclient.ActionDelete,
|
||||
})
|
||||
lb.DeleteEip(ctx, self.UserCred)
|
||||
lb.LBPendingDelete(ctx, self.GetUserCred())
|
||||
self.SetStageComplete(ctx, nil)
|
||||
|
||||
@@ -159,7 +159,11 @@ func (self *LoadbalancerListenerCreateTask) taskFail(ctx context.Context, lblis
|
||||
lblis.SetStatus(self.GetUserCred(), api.LB_CREATE_FAILED, reason.String())
|
||||
db.OpsLog.LogEvent(lblis, db.ACT_ALLOCATE_FAIL, reason, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, lblis, logclient.ACT_CREATE, reason, self.UserCred, false)
|
||||
notifyclient.NotifySystemErrorWithCtx(ctx, lblis.Id, lblis.Name, api.LB_CREATE_FAILED, reason.String())
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: lblis,
|
||||
Action: notifyclient.ActionCreate,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, reason)
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,11 @@ func (self *LoadbalancerListenerDeleteTask) taskFail(ctx context.Context, lblis
|
||||
lblis.SetStatus(self.GetUserCred(), api.LB_STATUS_DELETE_FAILED, reason.String())
|
||||
db.OpsLog.LogEvent(lblis, db.ACT_DELOCATE_FAIL, reason, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, lblis, logclient.ACT_DELOCATE, reason, self.UserCred, false)
|
||||
notifyclient.NotifySystemErrorWithCtx(ctx, lblis.Id, lblis.Name, api.LB_STATUS_DELETE_FAILED, reason.String())
|
||||
notifyclient.EventNotify(ctx, self.GetUserCred(), notifyclient.SEventNotifyParam{
|
||||
Obj: lblis,
|
||||
Action: notifyclient.ActionDelete,
|
||||
IsFail: true,
|
||||
})
|
||||
self.SetStageFailed(ctx, reason)
|
||||
}
|
||||
|
||||
|
||||
@@ -101,6 +101,19 @@ func (rv *ReceiverVerifyOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(rv.SreceiverVerifyOptions), nil
|
||||
}
|
||||
|
||||
type ReceiverEnableContactTypeInput struct {
|
||||
ReceiverOptions
|
||||
SreceiverEnableContactTypeInput
|
||||
}
|
||||
|
||||
func (re *ReceiverEnableContactTypeInput) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(re.SreceiverEnableContactTypeInput), nil
|
||||
}
|
||||
|
||||
type SreceiverEnableContactTypeInput struct {
|
||||
EnabledContactTypes []string `help:"Enabled contact types"`
|
||||
}
|
||||
|
||||
type ReceiverIntellijGetOptions struct {
|
||||
USERID string `help:"user id in keystone" json:"user_id"`
|
||||
CreateIfNo *bool `help:"create if receiver with UserId does not exist"`
|
||||
|
||||
@@ -40,14 +40,15 @@ func (so *TopicOptions) Params() (jsonutils.JSONObject, error) {
|
||||
}
|
||||
|
||||
type SubscriberCreateOptions struct {
|
||||
Name string `positional:"true"`
|
||||
TopicId string `positional:"true"`
|
||||
ResourceScope string `positional:"true" choices:"system|domain|project"`
|
||||
Type string `positional:"true" choices:"receiver|robot|role"`
|
||||
Receivers []string `help:"required if type is 'receiver'"`
|
||||
Role string `help:"required if type is 'role'"`
|
||||
RoleScope string `help:"required if type if 'role'"`
|
||||
Robot string `help:"required if type if 'robot'"`
|
||||
TopicId string `positional:"true"`
|
||||
ResourceScope string `positional:"true" choices:"system|domain|project"`
|
||||
ResourceAttributionId string `help:"project id or domain id of resource"`
|
||||
Type string `positional:"true" choices:"receiver|robot|role"`
|
||||
Receivers []string `help:"required if type is 'receiver'"`
|
||||
Role string `help:"required if type is 'role'"`
|
||||
RoleScope string `help:"required if type is 'role'"`
|
||||
Robot string `help:"required if type is 'robot'"`
|
||||
Scope string `positional:"true"`
|
||||
}
|
||||
|
||||
func (sc *SubscriberCreateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
@@ -59,6 +60,7 @@ type SubscriberListOptions struct {
|
||||
TopicId string
|
||||
ResourceScope string `choices:"system|domain|project"`
|
||||
Type string `choices:"receiver|robot|role"`
|
||||
SCOPE string `choices:"system|domain"`
|
||||
}
|
||||
|
||||
func (sl *SubscriberListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
@@ -77,13 +79,16 @@ func (s *SubscriberOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type SubscriberSetReceiverOptions struct {
|
||||
type SubscriberChangeOptions struct {
|
||||
SubscriberOptions
|
||||
Receivers []string
|
||||
Role string
|
||||
RoleScope string
|
||||
Robot string
|
||||
}
|
||||
|
||||
func (ssr *SubscriberSetReceiverOptions) Params() (jsonutils.JSONObject, error) {
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("receivers", jsonutils.NewStringArray(ssr.Receivers))
|
||||
func (ssr *SubscriberChangeOptions) Params() (jsonutils.JSONObject, error) {
|
||||
params := jsonutils.Marshal(ssr)
|
||||
params.(*jsonutils.JSONDict).Remove("id")
|
||||
return params, nil
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
notify_apis "yunion.io/x/onecloud/pkg/apis/notify"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/notify/rpc/apis"
|
||||
)
|
||||
@@ -59,15 +60,15 @@ type IServiceConfigStore interface {
|
||||
GetConfigs(service string) ([]SConfig, error)
|
||||
GetConfig(service, domainId string) (SConfig, error)
|
||||
SetConfig(service string, config SConfig) error
|
||||
HasSystemConfig(service string) (bool, error)
|
||||
BatchCheckConfig(service string, domainIds []string) ([]bool, error)
|
||||
HasSystemConfig(service string) (bool, error)
|
||||
BatchCheckConfig(service string, domainIds []string) ([]bool, error)
|
||||
}
|
||||
|
||||
type SNotification struct {
|
||||
ContactType string
|
||||
Topic string
|
||||
Message string
|
||||
Event string
|
||||
Event notify_apis.SEvent
|
||||
AdvanceDays int
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,6 @@ func (cm *SConfigManager) ValidateCreateData(ctx context.Context, userCred mccli
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
log.Infof("input: %s", jsonutils.Marshal(input))
|
||||
if len(input.ProjectDomainId) > 0 {
|
||||
_, input.DomainizedResourceInput, err = db.ValidateDomainizedResourceInput(ctx, input.DomainizedResourceInput)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
)
|
||||
|
||||
type SEventManager struct {
|
||||
db.SStandaloneAnonResourceBaseManager
|
||||
}
|
||||
|
||||
var EventManager *SEventManager
|
||||
|
||||
func init() {
|
||||
EventManager = &SEventManager{
|
||||
SStandaloneAnonResourceBaseManager: db.NewStandaloneAnonResourceBaseManager(
|
||||
SEvent{},
|
||||
"events_tbl",
|
||||
"notifyevent",
|
||||
"notifyevents",
|
||||
),
|
||||
}
|
||||
EventManager.SetVirtualObject(EventManager)
|
||||
}
|
||||
|
||||
type SEvent struct {
|
||||
db.SStandaloneAnonResourceBase
|
||||
|
||||
Message string
|
||||
Event string `width:"32" nullable:"true"`
|
||||
AdvanceDays int
|
||||
}
|
||||
|
||||
func (e *SEventManager) CreateEvent(ctx context.Context, event, message string, advanceDays int) (*SEvent, error) {
|
||||
eve := &SEvent{
|
||||
Message: message,
|
||||
Event: event,
|
||||
AdvanceDays: advanceDays,
|
||||
}
|
||||
err := e.TableSpec().Insert(ctx, eve)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return eve, nil
|
||||
}
|
||||
|
||||
func (e *SEventManager) GetEvent(id string) (*SEvent, error) {
|
||||
model, err := e.FetchById(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return model.(*SEvent), nil
|
||||
}
|
||||
@@ -79,12 +79,8 @@ func (lt *SLocalTemplateManager) detailsDisplay(resourceType string, details *js
|
||||
}
|
||||
|
||||
func (lt *SLocalTemplateManager) FillWithTemplate(ctx context.Context, lang string, no notifyv2.SNotification) (params rpcapi.SendParams, err error) {
|
||||
out := rpcapi.SendParams{}
|
||||
event, err := parseEvent(no.Event)
|
||||
if err != nil {
|
||||
return out, errors.Wrapf(err, "unable to parse event %q", no.Event)
|
||||
}
|
||||
rtStr, aStr := event.ResourceType(), string(event.Action())
|
||||
out, event := rpcapi.SendParams{}, no.Event
|
||||
rtStr, aStr, resultStr := event.ResourceType(), string(event.Action()), string(event.Result())
|
||||
dict, err := jsonutils.ParseString(no.Message)
|
||||
if err != nil {
|
||||
return out, errors.Wrapf(err, "unable to parse json from %q", no.Message)
|
||||
@@ -92,10 +88,11 @@ func (lt *SLocalTemplateManager) FillWithTemplate(ctx context.Context, lang stri
|
||||
webhookMsg := jsonutils.NewDict()
|
||||
webhookMsg.Set("resource_type", jsonutils.NewString(rtStr))
|
||||
webhookMsg.Set("action", jsonutils.NewString(aStr))
|
||||
webhookMsg.Set("result", jsonutils.NewString(resultStr))
|
||||
webhookMsg.Set("resource_details", dict)
|
||||
if no.ContactType == api.WEBHOOK {
|
||||
return rpcapi.SendParams{
|
||||
Title: no.Topic,
|
||||
Title: no.Event.StringWithDeli("_"),
|
||||
Message: webhookMsg.String(),
|
||||
}, nil
|
||||
}
|
||||
@@ -113,6 +110,10 @@ func (lt *SLocalTemplateManager) FillWithTemplate(ctx context.Context, lang stri
|
||||
if len(aDis) == 0 {
|
||||
aDis = aStr
|
||||
}
|
||||
resultDis := notifyclientI18nTable.LookupByLang(tag, resultStr)
|
||||
if len(resultDis) == 0 {
|
||||
resultDis = resultStr
|
||||
}
|
||||
|
||||
lt.detailsDisplay(rtStr, dict.(*jsonutils.JSONDict), tag)
|
||||
|
||||
@@ -120,6 +121,7 @@ func (lt *SLocalTemplateManager) FillWithTemplate(ctx context.Context, lang stri
|
||||
templateParams.Set("advance_days", jsonutils.NewInt(int64(no.AdvanceDays)))
|
||||
templateParams.Set("resource_type_display", jsonutils.NewString(rtDis))
|
||||
templateParams.Set("action_display", jsonutils.NewString(aDis))
|
||||
templateParams.Set("result_display", jsonutils.NewString(resultDis))
|
||||
|
||||
// get title
|
||||
title, err := lt.fillWithTemplate(ctx, "title", no.ContactType, lang, event, templateParams)
|
||||
@@ -148,6 +150,19 @@ func (lt *SLocalTemplateManager) FillWithTemplate(ctx context.Context, lang stri
|
||||
|
||||
var action2Topic = make(map[string]string, 0)
|
||||
|
||||
func specTopic(event api.SEvent) string {
|
||||
switch event.Action() {
|
||||
case api.ActionRebuildRoot, api.ActionChangeIpaddr, api.ActionResetPassword:
|
||||
return string(api.ActionUpdate)
|
||||
case api.ActionDelete:
|
||||
switch event.ResourceType() {
|
||||
case api.TOPIC_RESOURCE_BAREMETAL, api.TOPIC_RESOURCE_SERVER, api.TOPIC_RESOURCE_LOADBALANCER, api.TOPIC_RESOURCE_DBINSTANCE, api.TOPIC_RESOURCE_ELASTICCACHE:
|
||||
return "DELETE_WITH_IP"
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
action2Topic[string(api.ActionRebuildRoot)] = string(api.ActionUpdate)
|
||||
action2Topic[string(api.ActionResetPassword)] = string(api.ActionUpdate)
|
||||
@@ -159,8 +174,11 @@ func (lt *SLocalTemplateManager) fillWithTemplate(ctx context.Context, titleOrCo
|
||||
tmpl *template.Template
|
||||
err error
|
||||
)
|
||||
actionStr := string(event.Action())
|
||||
for _, topic := range []string{event.String(), actionStr, action2Topic[actionStr], "common"} {
|
||||
actionResultStr := event.ActionWithResult("_")
|
||||
for _, topic := range []string{specTopic(event), event.StringWithDeli("_"), actionResultStr, "common"} {
|
||||
if topic == "" {
|
||||
continue
|
||||
}
|
||||
tmpl, err = lt.getTemplate(ctx, titleOrContent, contactType, topic, lang)
|
||||
if errors.Cause(err) == errors.ErrNotFound {
|
||||
continue
|
||||
@@ -392,6 +410,11 @@ func init() {
|
||||
"scheduled task",
|
||||
"定时任务",
|
||||
},
|
||||
sI18nElme{
|
||||
api.TOPIC_RESOURCE_BAREMETAL,
|
||||
"baremetal",
|
||||
"裸金属",
|
||||
},
|
||||
sI18nElme{
|
||||
string(api.ActionCreate),
|
||||
"created",
|
||||
@@ -437,5 +460,15 @@ func init() {
|
||||
"added to the recycle bin",
|
||||
"加入回收站",
|
||||
},
|
||||
sI18nElme{
|
||||
string(api.ResultFailed),
|
||||
"failed",
|
||||
"失败",
|
||||
},
|
||||
sI18nElme{
|
||||
string(api.ResultSucceed),
|
||||
"successfully",
|
||||
"成功",
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -67,12 +67,11 @@ type SNotification struct {
|
||||
Topic string `width:"128" nullable:"true" create:"required" search:"user"`
|
||||
Priority string `width:"16" nullable:"true" create:"optional" list:"user" get:"user"`
|
||||
// swagger:ignore
|
||||
Message string `create:"required"`
|
||||
ReceivedAt time.Time `nullable:"true" list:"user" get:"user"`
|
||||
Event string `width:"32" nullable:"true" create:"optional"`
|
||||
AdvanceDays int
|
||||
SendTimes int
|
||||
Tag string `width:"16" nullable:"true" index:"true" create:"optional"`
|
||||
Message string `create:"required"`
|
||||
ReceivedAt time.Time `nullable:"true" list:"user" get:"user"`
|
||||
EventId string `width:"128" nullable:"true"`
|
||||
SendTimes int
|
||||
Tag string `width:"16" nullable:"true" index:"true" create:"optional"`
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -220,7 +219,13 @@ func (nm *SNotificationManager) AllowPerformEventNotify(ctx context.Context, use
|
||||
|
||||
// TODO: support project and domain
|
||||
func (nm *SNotificationManager) PerformEventNotify(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.NotificationManagerEventNotifyInput) (api.NotificationManagerEventNotifyOutput, error) {
|
||||
log.Infof("default receiverIds: %s", input.ReceiverIds)
|
||||
var output api.NotificationManagerEventNotifyOutput
|
||||
// check event
|
||||
_, err := parseEvent(input.Event)
|
||||
if err != nil {
|
||||
return output, httperrors.NewInputParameterError("unable to parse event %q", input.Event)
|
||||
}
|
||||
// contact type
|
||||
contactTypes := input.ContactTypes
|
||||
cts, err := ConfigManager.allContactType()
|
||||
@@ -245,10 +250,9 @@ func (nm *SNotificationManager) PerformEventNotify(ctx context.Context, userCred
|
||||
if err != nil {
|
||||
return output, errors.Wrap(err, "unable to get receive")
|
||||
}
|
||||
log.Infof("receiver for topic: %s", receiverIds1)
|
||||
receiverIds = append(receiverIds, receiverIds1...)
|
||||
}
|
||||
// deduplication
|
||||
receiverIds = sets.NewString(receiverIds...).UnsortedList()
|
||||
|
||||
// robot
|
||||
var robots []string
|
||||
@@ -262,19 +266,33 @@ func (nm *SNotificationManager) PerformEventNotify(ctx context.Context, userCred
|
||||
robots = append(robots, _robots...)
|
||||
}
|
||||
}
|
||||
robots = intersection(robots, intersection(cts, RobotContactTypes))
|
||||
var webhookRobots []string
|
||||
if len(robots) > 0 {
|
||||
robots = sets.NewString(robots...).UnsortedList()
|
||||
rs, err := RobotManager.FetchByIdOrNames(ctx, robots...)
|
||||
if err != nil {
|
||||
return output, errors.Wrap(err, "unable to get robots")
|
||||
}
|
||||
robots, webhookRobots = make([]string, 0, len(rs)), make([]string, 0, 1)
|
||||
for i := range rs {
|
||||
if rs[i].Type == api.ROBOT_TYPE_WEBHOOK {
|
||||
webhookRobots = append(webhookRobots, rs[i].Id)
|
||||
} else {
|
||||
robots = append(robots, rs[i].Id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
message := jsonutils.Marshal(input.ResourceDetails).String()
|
||||
|
||||
// append default receiver
|
||||
receiverIds = append(receiverIds, input.ReceiverIds...)
|
||||
// fillter non-existed receiver
|
||||
receivers, err := ReceiverManager.FetchByIdOrNames(ctx, receiverIds...)
|
||||
if err != nil {
|
||||
return output, errors.Wrap(err, "unable to fetch receivers by ids")
|
||||
}
|
||||
webconsoleContacts := make([]string, 0)
|
||||
webconsoleContacts := sets.NewString()
|
||||
idSet := sets.NewString()
|
||||
for i := range receivers {
|
||||
idSet.Insert(receivers[i].Id)
|
||||
@@ -283,12 +301,18 @@ func (nm *SNotificationManager) PerformEventNotify(ctx context.Context, userCred
|
||||
if idSet.Has(re) {
|
||||
continue
|
||||
}
|
||||
webconsoleContacts = append(webconsoleContacts, re)
|
||||
webconsoleContacts.Insert(re)
|
||||
}
|
||||
receiverIds = idSet.UnsortedList()
|
||||
|
||||
// create event
|
||||
event, err := EventManager.CreateEvent(ctx, input.Event, message, input.AdvanceDays)
|
||||
if err != nil {
|
||||
return output, errors.Wrap(err, "unable to create Event")
|
||||
}
|
||||
|
||||
// webconsole
|
||||
err = nm.create(ctx, userCred, api.WEBCONSOLE, receiverIds, webconsoleContacts, input.Priority, "", message, input.Event, input.AdvanceDays)
|
||||
err = nm.create(ctx, userCred, api.WEBCONSOLE, receiverIds, webconsoleContacts.UnsortedList(), input.Priority, event.Id)
|
||||
if err != nil {
|
||||
output.FailedList = append(output.FailedList, api.FailedElem{
|
||||
ContactType: api.WEBCONSOLE,
|
||||
@@ -297,7 +321,10 @@ func (nm *SNotificationManager) PerformEventNotify(ctx context.Context, userCred
|
||||
}
|
||||
// normal contact type
|
||||
for _, ct := range contactTypes {
|
||||
err := nm.create(ctx, userCred, ct, receiverIds, nil, input.Priority, "", message, input.Event, input.AdvanceDays)
|
||||
if ct == api.MOBILE {
|
||||
continue
|
||||
}
|
||||
err := nm.create(ctx, userCred, ct, receiverIds, nil, input.Priority, event.Id)
|
||||
if err != nil {
|
||||
output.FailedList = append(output.FailedList, api.FailedElem{
|
||||
ContactType: ct,
|
||||
@@ -305,26 +332,64 @@ func (nm *SNotificationManager) PerformEventNotify(ctx context.Context, userCred
|
||||
})
|
||||
}
|
||||
}
|
||||
err = nm.createWithWebhookRobots(ctx, userCred, webhookRobots, input.Priority, event.Id)
|
||||
if err != nil {
|
||||
output.FailedList = append(output.FailedList, api.FailedElem{
|
||||
ContactType: api.WEBHOOK,
|
||||
Reason: err.Error(),
|
||||
})
|
||||
}
|
||||
// robot
|
||||
err = nm.createWithRobots(ctx, userCred, robots, input.Priority, "", message, input.Event, input.AdvanceDays)
|
||||
output.FailedList = append(output.FailedList, api.FailedElem{
|
||||
ContactType: api.ROBOT,
|
||||
Reason: err.Error(),
|
||||
})
|
||||
err = nm.createWithRobots(ctx, userCred, robots, input.Priority, event.Id)
|
||||
if err != nil {
|
||||
output.FailedList = append(output.FailedList, api.FailedElem{
|
||||
ContactType: api.ROBOT,
|
||||
Reason: err.Error(),
|
||||
})
|
||||
}
|
||||
return output, nil
|
||||
}
|
||||
|
||||
func (nm *SNotificationManager) createWithRobots(ctx context.Context, userCred mcclient.TokenCredential, robotIds []string, priority, topic, message, event string, advanceDays int) error {
|
||||
func (nm *SNotificationManager) createWithWebhookRobots(ctx context.Context, userCred mcclient.TokenCredential, webhookRobotIds []string, priority, eventId string) error {
|
||||
if len(webhookRobotIds) == 0 {
|
||||
return nil
|
||||
}
|
||||
n := &SNotification{
|
||||
ContactType: api.WEBHOOK,
|
||||
Priority: priority,
|
||||
ReceivedAt: time.Now(),
|
||||
EventId: eventId,
|
||||
}
|
||||
n.Id = db.DefaultUUIDGenerator()
|
||||
for i := range webhookRobotIds {
|
||||
_, err := ReceiverNotificationManager.CreateRobot(ctx, userCred, webhookRobotIds[i], n.Id)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "ReceiverNotificationManager.CreateRobot")
|
||||
}
|
||||
}
|
||||
err := nm.TableSpec().Insert(ctx, n)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to insert Notification")
|
||||
}
|
||||
n.SetModelManager(nm, n)
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "NotificationSendTask", n, userCred, nil, "", "")
|
||||
if err != nil {
|
||||
log.Errorf("NotificationSendTask newTask error %v", err)
|
||||
} else {
|
||||
task.ScheduleRun(nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nm *SNotificationManager) createWithRobots(ctx context.Context, userCred mcclient.TokenCredential, robotIds []string, priority, eventId string) error {
|
||||
if len(robotIds) == 0 {
|
||||
return nil
|
||||
}
|
||||
n := &SNotification{
|
||||
ContactType: api.ROBOT,
|
||||
Message: message,
|
||||
Priority: priority,
|
||||
ReceivedAt: time.Now(),
|
||||
Event: event,
|
||||
AdvanceDays: advanceDays,
|
||||
EventId: eventId,
|
||||
}
|
||||
n.Id = db.DefaultUUIDGenerator()
|
||||
for i := range robotIds {
|
||||
@@ -347,7 +412,7 @@ func (nm *SNotificationManager) createWithRobots(ctx context.Context, userCred m
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nm *SNotificationManager) create(ctx context.Context, userCred mcclient.TokenCredential, contactType string, receiverIds, contacts []string, priority, topic, message, event string, advanceDays int) error {
|
||||
func (nm *SNotificationManager) create(ctx context.Context, userCred mcclient.TokenCredential, contactType string, receiverIds, contacts []string, priority, eventId string) error {
|
||||
if len(receiverIds)+len(contacts) == 0 {
|
||||
log.Infof("%s: no send", contactType)
|
||||
return nil
|
||||
@@ -355,11 +420,9 @@ func (nm *SNotificationManager) create(ctx context.Context, userCred mcclient.To
|
||||
|
||||
n := &SNotification{
|
||||
ContactType: contactType,
|
||||
Message: message,
|
||||
Priority: priority,
|
||||
ReceivedAt: time.Now(),
|
||||
Event: event,
|
||||
AdvanceDays: advanceDays,
|
||||
EventId: eventId,
|
||||
}
|
||||
n.Id = db.DefaultUUIDGenerator()
|
||||
err := nm.TableSpec().Insert(ctx, n)
|
||||
@@ -454,6 +517,7 @@ func (n *SNotification) ReceiveDetails(userCred mcclient.TokenCredential, scope
|
||||
q.AppendField(subRQ.Field("name", "receiver_name"))
|
||||
q = q.Join(subRQ, sqlchemy.OR(sqlchemy.Equals(q.Field("receiver_id"), subRQ.Field("id")), sqlchemy.Equals(q.Field("contact"), subRQ.Field("id"))))
|
||||
}
|
||||
q.DebugQuery()
|
||||
ret := make([]api.ReceiveDetail, 0, 2)
|
||||
err := q.All(&ret)
|
||||
if err != nil && errors.Cause(err) != sql.ErrNoRows {
|
||||
@@ -466,7 +530,11 @@ func (n *SNotification) ReceiveDetails(userCred mcclient.TokenCredential, scope
|
||||
func (n *SNotification) getMoreDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, out api.NotificationDetails) (api.NotificationDetails, error) {
|
||||
// get title adn content
|
||||
lang := getLangSuffix(ctx)
|
||||
p, err := n.TemplateStore().FillWithTemplate(ctx, lang, n.Notification())
|
||||
nn, err := n.Notification()
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
p, err := n.TemplateStore().FillWithTemplate(ctx, lang, nn)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
@@ -482,14 +550,26 @@ func (n *SNotification) getMoreDetails(ctx context.Context, userCred mcclient.To
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (n *SNotification) Notification() notifyv2.SNotification {
|
||||
func (n *SNotification) Notification() (notifyv2.SNotification, error) {
|
||||
if n.EventId == "" {
|
||||
return notifyv2.SNotification{
|
||||
ContactType: n.ContactType,
|
||||
Topic: n.Topic,
|
||||
Message: n.Message,
|
||||
}, nil
|
||||
}
|
||||
event, err := EventManager.GetEvent(n.EventId)
|
||||
if err != nil {
|
||||
return notifyv2.SNotification{}, err
|
||||
}
|
||||
e, _ := parseEvent(event.Event)
|
||||
return notifyv2.SNotification{
|
||||
ContactType: n.ContactType,
|
||||
Topic: n.Topic,
|
||||
Message: n.Message,
|
||||
Event: n.Event,
|
||||
AdvanceDays: n.AdvanceDays,
|
||||
}
|
||||
Message: event.Message,
|
||||
Event: e,
|
||||
AdvanceDays: event.AdvanceDays,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (nm *SNotificationManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
@@ -738,7 +818,7 @@ func (nm *SNotificationManager) ReSend(ctx context.Context, userCred mcclient.To
|
||||
}
|
||||
|
||||
func (n *SNotification) TemplateStore() notifyv2.ITemplateStore {
|
||||
if len(n.Event) == 0 || n.ContactType == api.MOBILE {
|
||||
if len(n.EventId) == 0 || n.ContactType == api.MOBILE {
|
||||
return TemplateManager
|
||||
}
|
||||
return LocalTemplateManager
|
||||
|
||||
@@ -1294,3 +1294,28 @@ func (r *SReceiver) GetContact(cType string) (string, error) {
|
||||
func (r *SReceiver) GetDomainId() string {
|
||||
return r.DomainId
|
||||
}
|
||||
|
||||
func (r *SReceiver) AllowPerformEnableContactType(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return r.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, r, "enable-contact-type")
|
||||
}
|
||||
|
||||
func (r *SReceiver) PerformEnableContactType(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.ReceiverEnableContactTypeInput) (jsonutils.JSONObject, error) {
|
||||
err := r.PullCache(false)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to pull cache")
|
||||
}
|
||||
err = r.SetEnabledContactTypes(input.EnabledContactTypes)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to set enabled contact types")
|
||||
}
|
||||
err = r.PushCache(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to push cache")
|
||||
}
|
||||
r.SetStatus(userCred, api.RECEIVER_STATUS_PULLING, "")
|
||||
err = r.StartSubcontactPullTask(ctx, userCred, nil, "")
|
||||
if err != nil {
|
||||
log.Errorf("unable to StartSubcontactPullTask: %v", err)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/notify"
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
@@ -95,6 +97,13 @@ func (rnm *SReceiverNotificationManager) CreateContact(ctx context.Context, user
|
||||
return rn, rnm.TableSpec().Insert(ctx, rn)
|
||||
}
|
||||
|
||||
func (rnm *SReceiverNotificationManager) SetHandlerProcessTimeout(info *appsrv.SHandlerInfo, r *http.Request) time.Duration {
|
||||
if r.Method == http.MethodGet && len(r.URL.Query().Get("export_keys")) > 0 {
|
||||
return time.Hour * 2
|
||||
}
|
||||
return -time.Second
|
||||
}
|
||||
|
||||
// func (rn *SReceiverNotification) Receiver() (*SReceiver, error) {
|
||||
// q := ReceiverManager.Query().Equals("id", rn.ReceiverID)
|
||||
// var receiver SReceiver
|
||||
@@ -118,30 +127,30 @@ func (rn *SReceiverNotification) receiver() (*SReceiver, error) {
|
||||
}
|
||||
|
||||
func (rn *SReceiverNotification) robot() (*SRobot, error) {
|
||||
q := RobotManager.Query().Equals("id", rn.ReceiverID)
|
||||
var robot SRobot
|
||||
err := q.First(&robot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
robot.SetModelManager(RobotManager, &robot)
|
||||
return &robot, nil
|
||||
q := RobotManager.Query().Equals("id", rn.ReceiverID)
|
||||
var robot SRobot
|
||||
err := q.First(&robot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
robot.SetModelManager(RobotManager, &robot)
|
||||
return &robot, nil
|
||||
}
|
||||
|
||||
func (rn *SReceiverNotification) Receiver() (IReceiver, error) {
|
||||
switch rn.ReceiverType {
|
||||
case api.RECEIVER_TYPE_USER:
|
||||
return rn.receiver()
|
||||
return rn.receiver()
|
||||
case api.RECEIVER_TYPE_CONTACT:
|
||||
return &SContact{contact: rn.Contact}, nil
|
||||
case api.RECEIVER_TYPE_ROBOT:
|
||||
return rn.robot()
|
||||
return rn.robot()
|
||||
default:
|
||||
// compatible
|
||||
if rn.ReceiverID != "" && rn.ReceiverID != ReceiverIdDefault {
|
||||
return rn.receiver()
|
||||
}
|
||||
return &SContact{contact: rn.Contact}, nil
|
||||
if rn.ReceiverID != "" && rn.ReceiverID != ReceiverIdDefault {
|
||||
return rn.receiver()
|
||||
}
|
||||
return &SContact{contact: rn.Contact}, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +181,7 @@ func (rn *SReceiverNotification) AfterSend(ctx context.Context, success bool, re
|
||||
|
||||
type IReceiver interface {
|
||||
IsEnabled() bool
|
||||
GetDomainId() string
|
||||
GetDomainId() string
|
||||
IsEnabledContactType(string) (bool, error)
|
||||
IsVerifiedContactType(string) (bool, error)
|
||||
GetContact(string) (string, error)
|
||||
@@ -187,7 +196,7 @@ func (s SReceiverBase) IsEnabled() bool {
|
||||
}
|
||||
|
||||
func (s SReceiverBase) GetDomainId() string {
|
||||
return ""
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s SReceiverBase) IsEnabledContactType(_ string) (bool, error) {
|
||||
|
||||
@@ -4,10 +4,12 @@ import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/tristate"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
@@ -211,6 +213,11 @@ func (r *SRobot) ValidateUpdateData(ctx context.Context, userCred mcclient.Token
|
||||
}
|
||||
|
||||
func (r *SRobot) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
err := r.SSharableVirtualResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Enabled = tristate.True
|
||||
r.Status = api.ROBOT_STATUS_READY
|
||||
return nil
|
||||
}
|
||||
@@ -234,11 +241,11 @@ func (r *SRobot) IsEnabled() bool {
|
||||
}
|
||||
|
||||
func (r *SRobot) IsEnabledContactType(ctype string) (bool, error) {
|
||||
return ctype == api.ROBOT, nil
|
||||
return ctype == api.ROBOT || ctype == api.WEBHOOK, nil
|
||||
}
|
||||
|
||||
func (r *SRobot) IsVerifiedContactType(ctype string) (bool, error) {
|
||||
return ctype == api.ROBOT, nil
|
||||
return ctype == api.ROBOT || ctype == api.WEBHOOK, nil
|
||||
}
|
||||
|
||||
func (r *SRobot) GetContact(ctype string) (string, error) {
|
||||
|
||||
+142
-21
@@ -25,6 +25,7 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/tristate"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
@@ -34,6 +35,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
@@ -41,7 +43,7 @@ var SubscriberManager *SSubscriberManager
|
||||
|
||||
func init() {
|
||||
SubscriberManager = &SSubscriberManager{
|
||||
SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(
|
||||
SStandaloneAnonResourceBaseManager: db.NewStandaloneAnonResourceBaseManager(
|
||||
SSubscriber{},
|
||||
"subscriber_tbl",
|
||||
"subscriber",
|
||||
@@ -52,19 +54,22 @@ func init() {
|
||||
}
|
||||
|
||||
type SSubscriberManager struct {
|
||||
db.SVirtualResourceBaseManager
|
||||
db.SStandaloneAnonResourceBaseManager
|
||||
db.SEnabledResourceBaseManager
|
||||
}
|
||||
|
||||
type SSubscriber struct {
|
||||
db.SVirtualResourceBase
|
||||
db.SStandaloneAnonResourceBase
|
||||
db.SEnabledResourceBase
|
||||
|
||||
TopicID string `width:"128" charset:"ascii" nullable:"false" index:"true" get:"user" list:"user"`
|
||||
Type string `width:"16" charset:"ascii" nullable:"false" index:"true" get:"user" list:"user"`
|
||||
Identification string `width:"128" charset:"ascii" nullable:"false" index:"true"`
|
||||
RoleScope string `width:"8" charset:"ascii" nullable:"false" get:"user" list:"user"`
|
||||
ResourceScope string `width:"8" charset:"ascii" nullable:"false" get:"user" list:"user"`
|
||||
TopicID string `width:"128" charset:"ascii" nullable:"false" index:"true" get:"user" list:"user" create:"required"`
|
||||
Type string `width:"16" charset:"ascii" nullable:"false" index:"true" get:"user" list:"user" create:"required"`
|
||||
Identification string `width:"128" charset:"ascii" nullable:"false" index:"true"`
|
||||
RoleScope string `width:"8" charset:"ascii" nullable:"false" get:"user" list:"user" create:"optional"`
|
||||
ResourceScope string `width:"8" charset:"ascii" nullable:"false" get:"user" list:"user" create:"required"`
|
||||
ResourceAttributionId string `width:"128" charset:"ascii" nullable:"false" get:"user" list:"user" create:"optional"`
|
||||
Scope string `width:"128" charset:"ascii" nullable:"false" create:"required"`
|
||||
DomainId string `width:"128" charset:"ascii" nullable:"false" create:"optional"`
|
||||
}
|
||||
|
||||
func (sm *SSubscriberManager) validateReceivers(ctx context.Context, receivers []string) ([]string, error) {
|
||||
@@ -86,8 +91,25 @@ func (sm *SSubscriberManager) validateReceivers(ctx context.Context, receivers [
|
||||
}
|
||||
|
||||
func (sm *SSubscriberManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.SubscriberCreateInput) (api.SubscriberCreateInput, error) {
|
||||
log.Infof("before deal: %s", jsonutils.Marshal(input))
|
||||
var err error
|
||||
input.VirtualResourceCreateInput, err = sm.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.VirtualResourceCreateInput)
|
||||
// permission check
|
||||
sSystem, sDomain := string(rbacutils.ScopeSystem), string(rbacutils.ScopeDomain)
|
||||
switch input.Scope {
|
||||
case sSystem:
|
||||
allow := db.IsAdminAllowCreate(userCred, sm)
|
||||
if !allow {
|
||||
return input, httperrors.NewForbiddenError("The scope %s and the role of the operator do not match", input.Scope)
|
||||
}
|
||||
case sDomain:
|
||||
allow := db.IsDomainAllowCreate(userCred, sm)
|
||||
if !allow {
|
||||
return input, httperrors.NewForbiddenError("The scope %s and the role of the operator do not match", input.Scope)
|
||||
}
|
||||
default:
|
||||
return input, httperrors.NewInputParameterError("unknown scope %s", input.Scope)
|
||||
}
|
||||
input.StandaloneAnonResourceCreateInput, err = sm.SStandaloneAnonResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StandaloneAnonResourceCreateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SVirtualResourceBaseManager.ValidateCreateData")
|
||||
}
|
||||
@@ -100,6 +122,32 @@ func (sm *SSubscriberManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
if !utils.IsInStringArray(input.ResourceScope, []string{api.SUBSCRIBER_SCOPE_SYSTEM, api.SUBSCRIBER_SCOPE_DOMAIN, api.SUBSCRIBER_SCOPE_PROJECT}) {
|
||||
return input, httperrors.NewInputParameterError("unknown resource_scope %q", input.ResourceScope)
|
||||
}
|
||||
// resource Attribution Id
|
||||
var domainId string
|
||||
switch input.ResourceScope {
|
||||
case api.SUBSCRIBER_SCOPE_SYSTEM:
|
||||
input.ResourceAttributionId = ""
|
||||
input.DomainId = ""
|
||||
case api.SUBSCRIBER_SCOPE_PROJECT:
|
||||
tenant, err := db.TenantCacheManager.FetchTenantByIdOrName(ctx, input.ResourceAttributionId)
|
||||
if err != nil {
|
||||
return input, errors.Wrapf(err, "unable to fetch project %s", input.ResourceAttributionId)
|
||||
}
|
||||
domainId = tenant.DomainId
|
||||
input.DomainId = domainId
|
||||
input.ResourceAttributionId = tenant.GetId()
|
||||
case api.SUBSCRIBER_SCOPE_DOMAIN:
|
||||
tenant, err := db.TenantCacheManager.FetchDomainByIdOrName(ctx, input.ResourceAttributionId)
|
||||
if err != nil {
|
||||
return input, errors.Wrapf(err, "unable to fetch domain %s", input.ResourceAttributionId)
|
||||
}
|
||||
domainId = tenant.DomainId
|
||||
input.DomainId = domainId
|
||||
input.ResourceAttributionId = tenant.DomainId
|
||||
}
|
||||
if input.Scope == sDomain && domainId != userCred.GetDomainId() {
|
||||
return input, httperrors.NewForbiddenError("domain %s admin can't create subscriber for domain %s", userCred.GetDomainId(), domainId)
|
||||
}
|
||||
input.TopicID = t.GetId()
|
||||
switch input.Type {
|
||||
case api.SUBSCRIBER_TYPE_RECEIVER:
|
||||
@@ -129,11 +177,12 @@ func (sm *SSubscriberManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
default:
|
||||
return input, httperrors.NewInputParameterError("unkown type %q", input.Type)
|
||||
}
|
||||
log.Infof("after deal input: %s", jsonutils.Marshal(input))
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (s *SSubscriber) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
err := s.SVirtualResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
|
||||
err := s.SStandaloneAnonResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "SVirtualResourceBase.CustomizeCreate")
|
||||
}
|
||||
@@ -150,12 +199,44 @@ func (s *SSubscriber) CustomizeCreate(ctx context.Context, userCred mcclient.Tok
|
||||
case api.SUBSCRIBER_TYPE_ROLE:
|
||||
s.Identification = input.Role
|
||||
}
|
||||
s.Enabled = tristate.True
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SSubscriber) AllowPerformChange(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *SSubscriber) PerformChange(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.SubscriberChangeInput) (jsonutils.JSONObject, error) {
|
||||
if s.Scope == string(rbacutils.ScopeSystem) {
|
||||
if !db.IsAdminAllowUpdate(userCred, s) {
|
||||
return nil, httperrors.NewForbiddenError("")
|
||||
}
|
||||
} else {
|
||||
if !db.IsDomainAllowUpdate(userCred, s) {
|
||||
return nil, httperrors.NewForbiddenError("")
|
||||
}
|
||||
if s.DomainId != userCred.GetDomainId() {
|
||||
return nil, httperrors.NewForbiddenError("")
|
||||
}
|
||||
}
|
||||
switch s.Type {
|
||||
case api.SUBSCRIBER_TYPE_RECEIVER:
|
||||
err := s.SetReceivers(ctx, input.Receivers)
|
||||
if err != nil {
|
||||
log.Errorf("unable to set receivers %s", input.Receivers)
|
||||
}
|
||||
case api.SUBSCRIBER_TYPE_ROBOT:
|
||||
s.Identification = input.Robot
|
||||
case api.SUBSCRIBER_TYPE_ROLE:
|
||||
s.Identification = input.Role
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (sm *SSubscriberManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, input api.SubscriberListInput) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = sm.SVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, input.VirtualResourceListInput)
|
||||
q, err = sm.SStandaloneAnonResourceBaseManager.ListItemFilter(ctx, q, userCred, input.StandaloneAnonResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SVirtualResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
@@ -163,6 +244,25 @@ func (sm *SSubscriberManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SEnabledResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
sSystem, sDomain := string(rbacutils.ScopeSystem), string(rbacutils.ScopeDomain)
|
||||
if input.Scope == "" {
|
||||
input.Scope = sSystem
|
||||
}
|
||||
switch input.Scope {
|
||||
case sSystem:
|
||||
allow := db.IsAdminAllowList(userCred, sm)
|
||||
if !allow {
|
||||
return nil, httperrors.NewForbiddenError("")
|
||||
}
|
||||
case sDomain:
|
||||
allow := db.IsAdminAllowList(userCred, sm)
|
||||
if !allow {
|
||||
return nil, httperrors.NewForbiddenError("")
|
||||
}
|
||||
q = q.Equals("domain_id", userCred.GetDomainId())
|
||||
default:
|
||||
return nil, httperrors.NewInputParameterError("unkown scope %s", input.Scope)
|
||||
}
|
||||
if input.TopicID != "" {
|
||||
q = q.Equals("topic_id", input.TopicID)
|
||||
}
|
||||
@@ -177,10 +277,10 @@ func (sm *SSubscriberManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
|
||||
|
||||
func (sm *SSubscriberManager) FetchCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, objs []interface{}, fields stringutils2.SSortedStrings, isList bool) []api.SubscriberDetails {
|
||||
var err error
|
||||
vRows := sm.SVirtualResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
vRows := sm.SStandaloneAnonResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
rows := make([]api.SubscriberDetails, len(objs))
|
||||
for i := range rows {
|
||||
rows[i].VirtualResourceDetails = vRows[i]
|
||||
rows[i].StandaloneAnonResourceDetails = vRows[i]
|
||||
s := objs[i].(*SSubscriber)
|
||||
switch s.Type {
|
||||
case api.SUBSCRIBER_TYPE_RECEIVER:
|
||||
@@ -203,6 +303,26 @@ func (sm *SSubscriberManager) FetchCustomizeColumns(ctx context.Context, userCre
|
||||
return rows
|
||||
}
|
||||
|
||||
func (s *SSubscriber) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
err := s.SStandaloneAnonResourceBase.CustomizeDelete(ctx, userCred, query, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if s.Scope == string(rbacutils.ScopeSystem) {
|
||||
if !db.IsAdminAllowDelete(userCred, s) {
|
||||
return httperrors.NewForbiddenError("")
|
||||
}
|
||||
} else {
|
||||
if !db.IsDomainAllowDelete(userCred, s) {
|
||||
return httperrors.NewForbiddenError("")
|
||||
}
|
||||
if s.DomainId != userCred.GetDomainId() {
|
||||
return httperrors.NewForbiddenError("")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SSubscriber) receiverIdentifications() ([]api.Identification, error) {
|
||||
srSubq := SubscriberReceiverManager.Query().Equals("subscription_id", s.Id).SubQuery()
|
||||
rq := ReceiverManager.Query("id", "name")
|
||||
@@ -248,17 +368,17 @@ func (srm *SSubscriberManager) robot(tid, projectDomainId, projectId string) ([]
|
||||
}
|
||||
|
||||
func (srm *SSubscriberManager) findSuitableOnes(tid, projectDomainId, projectId string, types ...string) ([]SSubscriber, error) {
|
||||
q := srm.Query().Equals("subscription_id", tid)
|
||||
q := srm.Query().Equals("topic_id", tid).IsTrue("enabled")
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.AND(
|
||||
sqlchemy.Equals(q.Field("resource_type"), api.SUBSCRIBER_SCOPE_PROJECT),
|
||||
sqlchemy.Equals(q.Field("project_id"), projectId),
|
||||
sqlchemy.Equals(q.Field("resource_scope"), api.SUBSCRIBER_SCOPE_PROJECT),
|
||||
sqlchemy.Equals(q.Field("resource_attribution_id"), projectId),
|
||||
),
|
||||
sqlchemy.AND(
|
||||
sqlchemy.Equals(q.Field("resource_type"), api.SUBSCRIBER_SCOPE_DOMAIN),
|
||||
sqlchemy.Equals(q.Field("domain_id"), projectDomainId),
|
||||
sqlchemy.Equals(q.Field("resource_scope"), api.SUBSCRIBER_SCOPE_DOMAIN),
|
||||
sqlchemy.Equals(q.Field("resource_attribution_id"), projectDomainId),
|
||||
),
|
||||
sqlchemy.Equals(q.Field("resource_type"), api.SUBSCRIBER_SCOPE_SYSTEM),
|
||||
sqlchemy.Equals(q.Field("resource_scope"), api.SUBSCRIBER_SCOPE_SYSTEM),
|
||||
))
|
||||
switch len(types) {
|
||||
case 0:
|
||||
@@ -267,6 +387,7 @@ func (srm *SSubscriberManager) findSuitableOnes(tid, projectDomainId, projectId
|
||||
default:
|
||||
q = q.In("type", types)
|
||||
}
|
||||
q.DebugQuery()
|
||||
srs := make([]SSubscriber, 0, 1)
|
||||
err := db.FetchModelObjects(srm, q, &srs)
|
||||
if err != nil {
|
||||
@@ -291,7 +412,7 @@ func (srm *SSubscriberManager) getReceiversSent(ctx context.Context, tid string,
|
||||
return nil, errors.Wrap(err, "unable to get receivers")
|
||||
}
|
||||
receivers = append(receivers, rIds...)
|
||||
} else if sr.Type == api.SUBSCRIBER_TYPE_ROBOT {
|
||||
} else if sr.Type == api.SUBSCRIBER_TYPE_ROLE {
|
||||
roleMap[sr.RoleScope] = append(roleMap[sr.RoleScope], sr.Identification)
|
||||
receivermap[sr.RoleScope] = &[]string{}
|
||||
}
|
||||
@@ -407,7 +528,7 @@ func (sr *SSubscriber) SetReceivers(ctx context.Context, receiverIds []string) e
|
||||
}
|
||||
|
||||
func (s *SSubscriber) AllowPerformSetReceiver(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return s.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, s, "set-receiver")
|
||||
return db.IsAdminAllowPerform(userCred, s, "set-receiver")
|
||||
}
|
||||
|
||||
func (s *SSubscriber) PerformSetReceiver(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.SubscriberSetReceiverInput) (jsonutils.JSONObject, error) {
|
||||
|
||||
+170
-66
@@ -18,8 +18,10 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/tristate"
|
||||
"yunion.io/x/pkg/util/sets"
|
||||
@@ -34,11 +36,16 @@ import (
|
||||
)
|
||||
|
||||
func parseEvent(es string) (notify.SEvent, error) {
|
||||
es = strings.ToLower(es)
|
||||
ess := strings.Split(es, notify.DelimiterInEvent)
|
||||
if len(ess) != 2 {
|
||||
if len(ess) != 2 && len(ess) != 3 {
|
||||
return notify.SEvent{}, fmt.Errorf("invalid event string %q", es)
|
||||
}
|
||||
return notify.Event.WithResourceType(ess[0]).WithAction(notify.SAction(ess[1])), nil
|
||||
event := notify.Event.WithResourceType(ess[0]).WithAction(notify.SAction(ess[1]))
|
||||
if len(ess) == 3 {
|
||||
event = event.WithResult(notify.SResult(ess[2]))
|
||||
}
|
||||
return event, nil
|
||||
}
|
||||
|
||||
type STopicManager struct {
|
||||
@@ -67,18 +74,20 @@ type STopic struct {
|
||||
Type string `width:"20" nullable:"false" create:"required" update:"user" list:"user"`
|
||||
Resources uint64 `nullable:"false"`
|
||||
Actions uint32 `nullable:"false"`
|
||||
Results uint8 `nullable:"false"`
|
||||
AdvanceDays int `nullable:"false"`
|
||||
}
|
||||
|
||||
const (
|
||||
DefaultResourceCreateDelete = "resource create or delete"
|
||||
DefaultResourceChangeConfig = "resource change config"
|
||||
DefaultResourceUpdate = "resource update"
|
||||
DefaultResourceReleaseDue1Day = "resource release due 1 day"
|
||||
DefaultResourceReleaseDue3Day = "resource release due 3 day"
|
||||
DefaultScheduledTaskExecute = "scheduled task execute"
|
||||
DefaultScalingPolicyExecute = "scaling policy execute"
|
||||
DefaultSnapshotPolicyExecute = "snapshot policy execute"
|
||||
DefaultResourceCreateDelete = "resource create or delete"
|
||||
DefaultResourceChangeConfig = "resource change config"
|
||||
DefaultResourceUpdate = "resource update"
|
||||
DefaultResourceReleaseDue1Day = "resource release due 1 day"
|
||||
DefaultResourceReleaseDue3Day = "resource release due 3 day"
|
||||
DefaultScheduledTaskExecute = "scheduled task execute"
|
||||
DefaultScalingPolicyExecute = "scaling policy execute"
|
||||
DefaultSnapshotPolicyExecute = "snapshot policy execute"
|
||||
DefaultResourceOperationFailed = "resource operation failed"
|
||||
)
|
||||
|
||||
func (sm *STopicManager) InitializeData() error {
|
||||
@@ -91,6 +100,7 @@ func (sm *STopicManager) InitializeData() error {
|
||||
DefaultScheduledTaskExecute,
|
||||
DefaultScalingPolicyExecute,
|
||||
DefaultSnapshotPolicyExecute,
|
||||
DefaultResourceOperationFailed,
|
||||
)
|
||||
q := sm.Query()
|
||||
topics := make([]STopic, 0, initSNames.Len())
|
||||
@@ -125,6 +135,7 @@ func (sm *STopicManager) InitializeData() error {
|
||||
notify.TOPIC_RESOURCE_BUCKET,
|
||||
notify.TOPIC_RESOURCE_DBINSTANCE,
|
||||
notify.TOPIC_RESOURCE_ELASTICCACHE,
|
||||
notify.TOPIC_RESOURCE_BAREMETAL,
|
||||
)
|
||||
t.addAction(
|
||||
notify.ActionCreate,
|
||||
@@ -189,6 +200,24 @@ func (sm *STopicManager) InitializeData() error {
|
||||
t.addResources(notify.TOPIC_RESOURCE_SNAPSHOTPOLICY)
|
||||
t.addAction(notify.ActionExecute)
|
||||
t.Type = notify.TOPIC_TYPE_AUTOMATED_PROCESS
|
||||
case DefaultResourceOperationFailed:
|
||||
t.addResources(
|
||||
notify.TOPIC_RESOURCE_SERVER,
|
||||
notify.TOPIC_RESOURCE_EIP,
|
||||
notify.TOPIC_RESOURCE_LOADBALANCER,
|
||||
notify.TOPIC_RESOURCE_DBINSTANCE,
|
||||
notify.TOPIC_RESOURCE_ELASTICCACHE,
|
||||
)
|
||||
t.addAction(
|
||||
notify.ActionCreate,
|
||||
notify.ActionSyncStatus,
|
||||
notify.ActionRebuildRoot,
|
||||
notify.ActionChangeConfig,
|
||||
notify.ActionCreateBackupServer,
|
||||
notify.ActionDelBackupServer,
|
||||
notify.ActionMigrate,
|
||||
)
|
||||
t.Type = notify.TOPIC_TYPE_RESOURCE
|
||||
}
|
||||
err := sm.TableSpec().Insert(ctx, t)
|
||||
if err != nil {
|
||||
@@ -293,7 +322,15 @@ func (sm *STopicManager) TopicsByEvent(eventStr string, advanceDays int) ([]STop
|
||||
return nil, errors.Wrapf(err, "unable to parse event %q", event)
|
||||
}
|
||||
resourceV := converter.resourceValue(event.ResourceType())
|
||||
if resourceV < 0 {
|
||||
log.Warningf("unknown resource type: %s", event.ResourceType())
|
||||
return nil, nil
|
||||
}
|
||||
actionV := converter.actionValue(event.Action())
|
||||
if actionV < 0 {
|
||||
log.Warningf("unknown action type: %s", event.Action())
|
||||
return nil, nil
|
||||
}
|
||||
q := sm.Query().Equals("advance_days", advanceDays)
|
||||
q = q.Filter(sqlchemy.GT(sqlchemy.AND_Val("", q.Field("resources"), 1<<resourceV), 0))
|
||||
q = q.Filter(sqlchemy.GT(sqlchemy.AND_Val("", q.Field("actions"), 1<<actionV), 0))
|
||||
@@ -306,102 +343,169 @@ func (sm *STopicManager) TopicsByEvent(eventStr string, advanceDays int) ([]STop
|
||||
return topics, nil
|
||||
}
|
||||
|
||||
func (t *STopic) AllowPerformEnable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input notify.PerformEnableInput) bool {
|
||||
return db.IsAdminAllowPerform(userCred, t, "enable")
|
||||
}
|
||||
|
||||
func (t *STopic) PreCheckPerformAction(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
action string, query jsonutils.JSONObject, data jsonutils.JSONObject,
|
||||
) error {
|
||||
if err := t.SStandaloneResourceBase.PreCheckPerformAction(ctx, userCred, action, query, data); err != nil {
|
||||
return err
|
||||
}
|
||||
if action == "enable" || action == "disable" {
|
||||
if !db.IsAdminAllowPerform(userCred, t, action) {
|
||||
return httperrors.NewForbiddenError("only allow admin to perform enable operations")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *STopic) PerformEnable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input notify.PerformEnableInput) (jsonutils.JSONObject, error) {
|
||||
err := db.EnabledPerformEnable(t, ctx, userCred, true)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "EnabledPerformEnable")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (t *STopic) AllowPerformDisable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input notify.PerformDisableInput) bool {
|
||||
return db.IsAdminAllowPerform(userCred, t, "disable")
|
||||
}
|
||||
|
||||
func (t *STopic) PerformDisable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input notify.PerformDisableInput) (jsonutils.JSONObject, error) {
|
||||
err := db.EnabledPerformEnable(t, ctx, userCred, false)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "EnabledPerformEnable")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
converter = &sConverter{
|
||||
resourceValueMap: make(map[string]int, 5),
|
||||
resourceList: make([]string, 0, 5),
|
||||
actionList: make([]notify.SAction, 0, 5),
|
||||
actionValueMap: make(map[notify.SAction]int, 5),
|
||||
resource2Value: &sync.Map{},
|
||||
value2Resource: &sync.Map{},
|
||||
action2Value: &sync.Map{},
|
||||
value2Action: &sync.Map{},
|
||||
}
|
||||
converter.registerResource(
|
||||
notify.TOPIC_RESOURCE_SERVER,
|
||||
notify.TOPIC_RESOURCE_SCALINGGROUP,
|
||||
notify.TOPIC_RESOURCE_SCALINGPOLICY,
|
||||
notify.TOPIC_RESOURCE_IMAGE,
|
||||
notify.TOPIC_RESOURCE_DISK,
|
||||
notify.TOPIC_RESOURCE_SNAPSHOT,
|
||||
notify.TOPIC_RESOURCE_INSTANCESNAPSHOT,
|
||||
notify.TOPIC_RESOURCE_SNAPSHOTPOLICY,
|
||||
notify.TOPIC_RESOURCE_NETWORK,
|
||||
notify.TOPIC_RESOURCE_EIP,
|
||||
notify.TOPIC_RESOURCE_SECGROUP,
|
||||
notify.TOPIC_RESOURCE_LOADBALANCER,
|
||||
notify.TOPIC_RESOURCE_LOADBALANCERACL,
|
||||
notify.TOPIC_RESOURCE_LOADBALANCERCERTIFICATE,
|
||||
notify.TOPIC_RESOURCE_BUCKET,
|
||||
notify.TOPIC_RESOURCE_DBINSTANCE,
|
||||
notify.TOPIC_RESOURCE_ELASTICCACHE,
|
||||
notify.TOPIC_RESOURCE_SCHEDULEDTASK,
|
||||
map[string]int{
|
||||
notify.TOPIC_RESOURCE_SERVER: 0,
|
||||
notify.TOPIC_RESOURCE_SCALINGGROUP: 1,
|
||||
notify.TOPIC_RESOURCE_SCALINGPOLICY: 2,
|
||||
notify.TOPIC_RESOURCE_IMAGE: 3,
|
||||
notify.TOPIC_RESOURCE_DISK: 4,
|
||||
notify.TOPIC_RESOURCE_SNAPSHOT: 5,
|
||||
notify.TOPIC_RESOURCE_INSTANCESNAPSHOT: 6,
|
||||
notify.TOPIC_RESOURCE_SNAPSHOTPOLICY: 7,
|
||||
notify.TOPIC_RESOURCE_NETWORK: 8,
|
||||
notify.TOPIC_RESOURCE_EIP: 9,
|
||||
notify.TOPIC_RESOURCE_SECGROUP: 10,
|
||||
notify.TOPIC_RESOURCE_LOADBALANCER: 11,
|
||||
notify.TOPIC_RESOURCE_LOADBALANCERACL: 12,
|
||||
notify.TOPIC_RESOURCE_LOADBALANCERCERTIFICATE: 13,
|
||||
notify.TOPIC_RESOURCE_BUCKET: 14,
|
||||
notify.TOPIC_RESOURCE_DBINSTANCE: 15,
|
||||
notify.TOPIC_RESOURCE_ELASTICCACHE: 16,
|
||||
notify.TOPIC_RESOURCE_SCHEDULEDTASK: 17,
|
||||
notify.TOPIC_RESOURCE_BAREMETAL: 18,
|
||||
},
|
||||
)
|
||||
converter.registerAction(
|
||||
notify.ActionCreate,
|
||||
notify.ActionDelete,
|
||||
notify.ActionPendingDelete,
|
||||
notify.ActionUpdate,
|
||||
notify.ActionRebuildRoot,
|
||||
notify.ActionResetPassword,
|
||||
notify.ActionChangeConfig,
|
||||
notify.ActionExpiredRelease,
|
||||
notify.ActionExecute,
|
||||
notify.ActionChangeIpaddr,
|
||||
map[notify.SAction]int{
|
||||
notify.ActionCreate: 0,
|
||||
notify.ActionDelete: 1,
|
||||
notify.ActionPendingDelete: 2,
|
||||
notify.ActionUpdate: 3,
|
||||
notify.ActionRebuildRoot: 4,
|
||||
notify.ActionResetPassword: 5,
|
||||
notify.ActionChangeConfig: 6,
|
||||
notify.ActionExpiredRelease: 7,
|
||||
notify.ActionExecute: 8,
|
||||
notify.ActionChangeIpaddr: 9,
|
||||
notify.ActionSyncStatus: 10,
|
||||
notify.ActionCleanData: 11,
|
||||
notify.ActionMigrate: 12,
|
||||
notify.ActionCreateBackupServer: 13,
|
||||
notify.ActionDelBackupServer: 14,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
var converter *sConverter
|
||||
|
||||
type sConverter struct {
|
||||
resourceValueMap map[string]int
|
||||
resourceList []string
|
||||
actionValueMap map[notify.SAction]int
|
||||
actionList []notify.SAction
|
||||
resource2Value *sync.Map
|
||||
value2Resource *sync.Map
|
||||
action2Value *sync.Map
|
||||
value2Action *sync.Map
|
||||
}
|
||||
|
||||
func (rc *sConverter) registerResource(resources ...string) {
|
||||
for _, resource := range resources {
|
||||
if _, ok := rc.resourceValueMap[resource]; ok {
|
||||
return
|
||||
type sResourceValue struct {
|
||||
resource string
|
||||
value int
|
||||
}
|
||||
|
||||
type sActionValue struct {
|
||||
action string
|
||||
value int
|
||||
}
|
||||
|
||||
func (rc *sConverter) registerResource(resourceValues map[string]int) {
|
||||
for resource, value := range resourceValues {
|
||||
if v, ok := rc.resource2Value.Load(resource); ok && v.(int) != value {
|
||||
log.Fatalf("resource '%s' has been mapped to value '%d', and it is not allowed to map to another value '%d'", resource, v, value)
|
||||
}
|
||||
rc.resourceList = append(rc.resourceList, resource)
|
||||
rc.resourceValueMap[resource] = len(rc.resourceList) - 1
|
||||
if r, ok := rc.value2Resource.Load(value); ok && r.(string) != resource {
|
||||
log.Fatalf("value '%d' has been mapped to resource '%s', and it is not allowed to map to another resource '%s'", value, r, resource)
|
||||
}
|
||||
rc.resource2Value.Store(resource, value)
|
||||
rc.value2Resource.Store(value, resource)
|
||||
}
|
||||
}
|
||||
|
||||
func (rc *sConverter) registerAction(actions ...notify.SAction) {
|
||||
for _, action := range actions {
|
||||
if _, ok := rc.actionValueMap[action]; ok {
|
||||
return
|
||||
func (rc *sConverter) registerAction(actionValues map[notify.SAction]int) {
|
||||
for action, value := range actionValues {
|
||||
if v, ok := rc.action2Value.Load(action); ok && v.(int) != value {
|
||||
log.Fatalf("action '%s' has been mapped to value '%d', and it is not allowed to map to another value '%d'", action, v, value)
|
||||
}
|
||||
rc.actionList = append(rc.actionList, action)
|
||||
rc.actionValueMap[action] = len(rc.actionList) - 1
|
||||
if a, ok := rc.value2Action.Load(value); ok && a.(notify.SAction) != action {
|
||||
log.Fatalf("value '%d' has been mapped to action '%s', and it is not allowed to map to another action '%s'", value, a, action)
|
||||
}
|
||||
rc.action2Value.Store(action, value)
|
||||
rc.value2Action.Store(value, action)
|
||||
}
|
||||
}
|
||||
|
||||
func (rc *sConverter) resourceValue(resource string) int {
|
||||
v, ok := rc.resourceValueMap[resource]
|
||||
v, ok := rc.resource2Value.Load(resource)
|
||||
if !ok {
|
||||
return -1
|
||||
}
|
||||
return v
|
||||
return v.(int)
|
||||
}
|
||||
|
||||
func (rc *sConverter) resource(resourceValue int) string {
|
||||
if resourceValue < 0 || resourceValue >= len(rc.resourceList) {
|
||||
r, ok := rc.value2Resource.Load(resourceValue)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return rc.resourceList[resourceValue]
|
||||
return r.(string)
|
||||
}
|
||||
|
||||
func (rc *sConverter) actionValue(action notify.SAction) int {
|
||||
v, ok := rc.actionValueMap[action]
|
||||
v, ok := rc.action2Value.Load(action)
|
||||
if !ok {
|
||||
return -1
|
||||
}
|
||||
return v
|
||||
return v.(int)
|
||||
}
|
||||
|
||||
func (rc *sConverter) action(actionValue int) notify.SAction {
|
||||
if actionValue < 0 || actionValue >= len(rc.actionList) {
|
||||
a, ok := rc.value2Action.Load(actionValue)
|
||||
if !ok {
|
||||
return notify.SAction("")
|
||||
}
|
||||
return rc.actionList[actionValue]
|
||||
return a.(notify.SAction)
|
||||
}
|
||||
|
||||
@@ -42,15 +42,15 @@ func (c *SendNotificationClient) Send(ctx context.Context, in *SendParams, opts
|
||||
}
|
||||
|
||||
func (c *SendNotificationClient) AddConfig(ctx context.Context, in *AddConfigInput, opts ...grpc.CallOption) (*Empty, error) {
|
||||
ctx, cancel := context.WithTimeout(ctx, c.CallTimeout)
|
||||
defer cancel()
|
||||
return c.sendAgentClient.AddConfig(ctx, in, opts...)
|
||||
ctx, cancel := context.WithTimeout(ctx, c.CallTimeout)
|
||||
defer cancel()
|
||||
return c.sendAgentClient.AddConfig(ctx, in, opts...)
|
||||
}
|
||||
|
||||
func (c *SendNotificationClient) DeleteConfig(ctx context.Context, in *DeleteConfigInput, opts ...grpc.CallOption) (*Empty, error) {
|
||||
ctx, cancel := context.WithTimeout(ctx, c.CallTimeout)
|
||||
defer cancel()
|
||||
return c.sendAgentClient.DeleteConfig(ctx, in, opts...)
|
||||
ctx, cancel := context.WithTimeout(ctx, c.CallTimeout)
|
||||
defer cancel()
|
||||
return c.sendAgentClient.DeleteConfig(ctx, in, opts...)
|
||||
}
|
||||
|
||||
func (c *SendNotificationClient) UpdateConfig(ctx context.Context, in *UpdateConfigInput, opts ...grpc.CallOption) (*Empty, error) {
|
||||
@@ -60,9 +60,9 @@ func (c *SendNotificationClient) UpdateConfig(ctx context.Context, in *UpdateCon
|
||||
}
|
||||
|
||||
func (c *SendNotificationClient) CompleteConfig(ctx context.Context, in *CompleteConfigInput, opts ...grpc.CallOption) (*Empty, error) {
|
||||
ctx, cancel := context.WithTimeout(ctx, c.CallTimeout)
|
||||
defer cancel()
|
||||
return c.sendAgentClient.CompleteConfig(ctx, in, opts...)
|
||||
ctx, cancel := context.WithTimeout(ctx, c.CallTimeout)
|
||||
defer cancel()
|
||||
return c.sendAgentClient.CompleteConfig(ctx, in, opts...)
|
||||
}
|
||||
|
||||
func (c *SendNotificationClient) ValidateConfig(ctx context.Context, in *ValidateConfigInput, opts ...grpc.CallOption) (*ValidateConfigReply, error) {
|
||||
@@ -78,9 +78,9 @@ func (c *SendNotificationClient) UseridByMobile(ctx context.Context, in *UseridB
|
||||
}
|
||||
|
||||
func (c *SendNotificationClient) Ready(ctx context.Context, in *ReadyInput, opts ...grpc.CallOption) (*ReadyOutput, error) {
|
||||
ctx, cancel := context.WithTimeout(ctx, c.CallTimeout)
|
||||
defer cancel()
|
||||
return c.sendAgentClient.Ready(ctx, in, opts...)
|
||||
ctx, cancel := context.WithTimeout(ctx, c.CallTimeout)
|
||||
defer cancel()
|
||||
return c.sendAgentClient.Ready(ctx, in, opts...)
|
||||
}
|
||||
|
||||
func (c *SendNotificationClient) BatchSend(ctx context.Context, in *BatchSendParams, opts ...grpc.CallOption) (*BatchSendReply, error) {
|
||||
|
||||
@@ -6,11 +6,12 @@ package apis
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
math "math"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
||||
@@ -257,7 +257,7 @@ func (self *SRpcService) ContactByMobile(ctx context.Context, mobile, serviceNam
|
||||
if s.Code() == codes.NotFound {
|
||||
return "", errors.Wrap(notifyv2.ErrNoSuchMobile, s.Message())
|
||||
}
|
||||
if s.Code() == codes.PermissionDenied {
|
||||
if s.Code() == codes.FailedPrecondition {
|
||||
return "", errors.Wrap(notifyv2.ErrIncompleteConfig, s.Message())
|
||||
}
|
||||
return "", err
|
||||
|
||||
@@ -39,6 +39,7 @@ func InitHandlers(app *appsrv.Application) {
|
||||
models.SubContactManager,
|
||||
db.SharedResourceManager,
|
||||
models.VerificationManager,
|
||||
models.EventManager,
|
||||
} {
|
||||
db.RegisterModelManager(manager)
|
||||
}
|
||||
|
||||
@@ -145,7 +145,11 @@ func (self *NotificationSendTask) OnInit(ctx context.Context, obj db.IStandalone
|
||||
}
|
||||
|
||||
// send
|
||||
p, err := notification.TemplateStore().FillWithTemplate(ctx, lang, notification.Notification())
|
||||
nn, err := notification.Notification()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, notification, err.Error(), false)
|
||||
}
|
||||
p, err := notification.TemplateStore().FillWithTemplate(ctx, lang, nn)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, notification, err.Error(), false)
|
||||
}
|
||||
@@ -199,7 +203,7 @@ type FailedReceiverSpec struct {
|
||||
|
||||
func (self *NotificationSendTask) batchSend(ctx context.Context, contactType string, receivers []ReceiverSpec, params rpcapi.SendParams) (fails []FailedReceiverSpec, err error) {
|
||||
log.Infof("contactType: %s, receivers: %s, params: %s", contactType, receivers, jsonutils.Marshal(params))
|
||||
if contactType != apis.ROBOT {
|
||||
if contactType != apis.ROBOT && contactType != apis.WEBHOOK {
|
||||
return self._batchSend(ctx, contactType, receivers, func(res []*rpcapi.SReceiver) ([]*rpcapi.FailedRecord, error) {
|
||||
return models.NotifyService.BatchSend(ctx, contactType, rpcapi.BatchSendParams{
|
||||
Receivers: res,
|
||||
|
||||
@@ -24,11 +24,11 @@ import (
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/notify"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/notify/models"
|
||||
"yunion.io/x/onecloud/pkg/apis/notify"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
@@ -62,13 +62,13 @@ func (self *RepullSuncontactTask) OnInit(ctx context.Context, obj db.IStandalone
|
||||
}
|
||||
subq := models.SubContactManager.Query("receiver_id").Equals("type", config.Type).SubQuery()
|
||||
q := models.ReceiverManager.Query()
|
||||
if config.Attribution == notify.CONFIG_ATTRIBUTION_DOMAIN {
|
||||
q = q.Equals("domain_id", config.DomainId)
|
||||
} else {
|
||||
// The system-level config update should not affect the receiver under the domain with config
|
||||
configq := models.ConfigManager.Query("domain_id").Equals("attribution", notify.CONFIG_ATTRIBUTION_DOMAIN).SubQuery()
|
||||
q = q.Join(configq, sqlchemy.NotEquals(q.Field("domain_id"), configq.Field("domain_id")))
|
||||
}
|
||||
if config.Attribution == notify.CONFIG_ATTRIBUTION_DOMAIN {
|
||||
q = q.Equals("domain_id", config.DomainId)
|
||||
} else {
|
||||
// The system-level config update should not affect the receiver under the domain with config
|
||||
configq := models.ConfigManager.Query("domain_id").Equals("attribution", notify.CONFIG_ATTRIBUTION_DOMAIN).SubQuery()
|
||||
q = q.Join(configq, sqlchemy.NotEquals(q.Field("domain_id"), configq.Field("domain_id")))
|
||||
}
|
||||
q.Join(subq, sqlchemy.Equals(q.Field("id"), subq.Field("receiver_id")))
|
||||
rs := make([]models.SReceiver, 0)
|
||||
err := db.FetchModelObjects(models.ReceiverManager, q, &rs)
|
||||
|
||||
@@ -82,10 +82,10 @@ func (self *VerificationSendTask) OnInit(ctx context.Context, obj db.IStandalone
|
||||
self.taskFailed(ctx, receiver, err.Error())
|
||||
return
|
||||
}
|
||||
param.Receiver = &apis.SReceiver{
|
||||
Contact: contact,
|
||||
DomainId: receiver.DomainId,
|
||||
}
|
||||
param.Receiver = &apis.SReceiver{
|
||||
Contact: contact,
|
||||
DomainId: receiver.DomainId,
|
||||
}
|
||||
err = models.NotifyService.Send(ctx, contactType, param)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, receiver, err.Error())
|
||||
|
||||
Reference in New Issue
Block a user