diff --git a/pkg/apis/notify/event.go b/pkg/apis/notify/event.go index 34cdc5b551..ffc8278337 100644 --- a/pkg/apis/notify/event.go +++ b/pkg/apis/notify/event.go @@ -53,13 +53,18 @@ var ( ActionLock SAction = "lock" - ActionExceedCount SAction = "exceed_count" - ActionPasswordExpireSoon SAction = "password_expire_soon" - ActionWorkerBlock SAction = "woker_block" - ActionNetOutOfSync SAction = "net_out_of_sync" - ActionMysqlOutOfSync SAction = "mysql_out_of_sync" - ActionServiceAbnormal SAction = "service_abnormal" - ActionServerPanicked SAction = "server_panicked" + ActionExceedCount SAction = "exceed_count" + ActionPasswordExpireSoon SAction = "password_expire_soon" + ActionWorkerBlock SAction = "woker_block" + ActionNetOutOfSync SAction = "net_out_of_sync" + ActionMysqlOutOfSync SAction = "mysql_out_of_sync" + ActionServiceAbnormal SAction = "service_abnormal" + ActionServerPanicked SAction = "server_panicked" + ActionAttach SAction = "attach" + ActionDetach SAction = "detach" + ActionIsolatedDeviceCreate SAction = "isolated_device_create" + ActionIsolatedDeviceUpdate SAction = "isolated_device_update" + ActionIsolatedDeviceDelete SAction = "isolated_device_delete" ResultFailed SResult = "failed" ResultSucceed SResult = "succeed" diff --git a/pkg/apis/notify/template.go b/pkg/apis/notify/template.go index 6aee08d27a..bec1dbef01 100644 --- a/pkg/apis/notify/template.go +++ b/pkg/apis/notify/template.go @@ -502,3 +502,16 @@ const ( WORK_BLOCK_CONTENT_EN = `{{- $d := .resource_details -}} The service: {{ d.service_name}} worker has been block 30 minutes.Please verify the service in time.` ) + +// TODO +// 资源挂载\卸载通知 +const ( +// ACTION_ATTACH_TITLE_CN = `{{- $d := .resource_details -}} +// 操作日志超出设置数量{{ $d.exceed_count }}条,当前{{ $d.current_count }}条` +// ACTION_ATTACH_TITLE_EN = `{{- $d := .resource_details -}} +// Action logs excced expected count {{ $d.exceed_count }}, current count is {{ $d.current_count }}` +// ACTION_ATTACH_CONTENT_CN = `{{- $d := .resource_details.action -}} +// 当前日志 ID: {{ $d.id }}` +// ACTION_ATTACH_CONTENT_EN = `{{- $d := .resource_details.action -}} +// Current log ID: {{ $d.id }}` +) diff --git a/pkg/cloudcommon/db/db_joint_dispatcher.go b/pkg/cloudcommon/db/db_joint_dispatcher.go index e949576d99..a5cca6a52f 100644 --- a/pkg/cloudcommon/db/db_joint_dispatcher.go +++ b/pkg/cloudcommon/db/db_joint_dispatcher.go @@ -191,6 +191,7 @@ func attachItems( item.PostCreate(ctx, userCred, nil, query, data) OpsLog.LogAttachEvent(ctx, master, slave, userCred, jsonutils.Marshal(item)) dispatcher.manager.OnCreateComplete(ctx, []IModel{item}, userCred, nil, query, []jsonutils.JSONObject{data}) + return getItemDetails(dispatcher.JointModelManager(), item, ctx, userCred, query) } @@ -223,7 +224,11 @@ func (dispatcher *DBJointModelDispatcher) Attach(ctx context.Context, id1 string lockman.LockJointObject(ctx, master, slave) defer lockman.ReleaseJointObject(ctx, master, slave) - return attachItems(dispatcher, master.(IStandaloneModel), slave.(IStandaloneModel), ctx, userCred, query, data) + resp, err := attachItems(dispatcher, master.(IStandaloneModel), slave.(IStandaloneModel), ctx, userCred, query, data) + if err == nil { + CallCustomizeNotifyHook(ctx, userCred, ACT_ATTACH, master, slave.GetShortDesc(ctx)) + } + return resp, err } func (dispatcher *DBJointModelDispatcher) Update(ctx context.Context, id1 string, id2 string, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { @@ -281,6 +286,7 @@ func (dispatcher *DBJointModelDispatcher) Detach(ctx context.Context, id1 string obj, err := deleteItem(dispatcher.JointModelManager(), item, ctx, userCred, query, data) if err == nil { + CallCustomizeNotifyHook(ctx, userCred, ACT_DETACH, master, slave.GetShortDesc(ctx)) OpsLog.LogDetachEvent(ctx, JointMaster(item), JointSlave(item), userCred, jsonutils.Marshal(item)) } return obj, err diff --git a/pkg/cloudcommon/db/notify_hook.go b/pkg/cloudcommon/db/notify_hook.go index a31eadece1..bfe810353e 100644 --- a/pkg/cloudcommon/db/notify_hook.go +++ b/pkg/cloudcommon/db/notify_hook.go @@ -17,14 +17,18 @@ package db import ( "context" + "yunion.io/x/jsonutils" + "yunion.io/x/onecloud/pkg/mcclient" ) var ( - updateNotifyHook updateNotifyHookFunc + updateNotifyHook updateNotifyHookFunc + customizeNotifyHook customizeNotifyHookFunc ) type updateNotifyHookFunc func(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) +type customizeNotifyHookFunc func(ctx context.Context, userCred mcclient.TokenCredential, action string, obj IModel, moreDetails jsonutils.JSONObject) func SetUpdateNotifyHook(f updateNotifyHookFunc) { if updateNotifyHook != nil { @@ -39,3 +43,17 @@ func CallUpdateNotifyHook(ctx context.Context, userCred mcclient.TokenCredential } updateNotifyHook(ctx, userCred, obj) } + +func SetCustomizeNotifyHook(f customizeNotifyHookFunc) { + if customizeNotifyHook != nil { + panic("updateNotifyHook already set") + } + customizeNotifyHook = f +} + +func CallCustomizeNotifyHook(ctx context.Context, userCred mcclient.TokenCredential, action string, obj IModel, customizeDetails jsonutils.JSONObject) { + if customizeNotifyHook == nil { + return + } + customizeNotifyHook(ctx, userCred, action, obj, customizeDetails) +} diff --git a/pkg/cloudcommon/notifyclient/events.go b/pkg/cloudcommon/notifyclient/events.go index 7a641d9bf2..40f1523a54 100644 --- a/pkg/cloudcommon/notifyclient/events.go +++ b/pkg/cloudcommon/notifyclient/events.go @@ -63,10 +63,13 @@ var ( ActionPendingDelete = api.ActionPendingDelete - ActionSyncCreate = api.ActionSyncCreate - ActionSyncUpdate = api.ActionSyncUpdate - ActionSyncDelete = api.ActionSyncDelete - ActionSyncAccountStatus = api.ActionSyncAccountStatus + ActionSyncCreate = api.ActionSyncCreate + ActionSyncUpdate = api.ActionSyncUpdate + ActionSyncDelete = api.ActionSyncDelete + ActionSyncAccountStatus = api.ActionSyncAccountStatus + ActionIsolatedDeviceCreate = api.ActionIsolatedDeviceCreate + ActionIsolatedDeviceUpdate = api.ActionIsolatedDeviceUpdate + ActionIsolatedDeviceDelete = api.ActionIsolatedDeviceDelete ) type SEvent struct { diff --git a/pkg/cloudcommon/notifyclient/notify.go b/pkg/cloudcommon/notifyclient/notify.go index b0841940a1..60a720a2eb 100644 --- a/pkg/cloudcommon/notifyclient/notify.go +++ b/pkg/cloudcommon/notifyclient/notify.go @@ -55,6 +55,20 @@ func init() { Action: ActionUpdate, }) }) + + db.SetCustomizeNotifyHook(func(ctx context.Context, userCred mcclient.TokenCredential, action string, obj db.IModel, moreDetails jsonutils.JSONObject) { + _, ok := notifyDBHookResources.Load(obj.KeywordPlural()) + if !ok { + return + } + EventNotify(ctx, userCred, SEventNotifyParam{ + Obj: obj, + Action: api.SAction(action), + ObjDetailsDecorator: func(ctx context.Context, details *jsonutils.JSONDict) { + details.Set("customize_details", details) + }, + }) + }) } func AddNotifyDBHookResources(keywordPlurals ...string) { diff --git a/pkg/compute/models/hosts.go b/pkg/compute/models/hosts.go index 1523a42219..4258d50c1e 100644 --- a/pkg/compute/models/hosts.go +++ b/pkg/compute/models/hosts.go @@ -5152,6 +5152,7 @@ func (hh *SHost) PerformEnable( return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.PerformEnable") } hh.SyncAttachedStorageStatus() + hh.updateNotify(ctx, userCred) } return nil, nil } @@ -5163,6 +5164,7 @@ func (hh *SHost) PerformDisable(ctx context.Context, userCred mcclient.TokenCred return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.PerformDisable") } hh.SyncAttachedStorageStatus() + hh.updateNotify(ctx, userCred) } return nil, nil } @@ -6552,3 +6554,10 @@ func (hh *SHost) IsAttach2Wire(wireId string) bool { netifs := hh.getNetifsOnWire(wireId) return len(netifs) > 0 } + +func (h *SHost) updateNotify(ctx context.Context, userCred mcclient.TokenCredential) { + notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{ + Action: notifyclient.ActionUpdate, + Obj: h, + }) +} diff --git a/pkg/compute/models/isolated_devices.go b/pkg/compute/models/isolated_devices.go index d74d6bbe03..5a54431557 100644 --- a/pkg/compute/models/isolated_devices.go +++ b/pkg/compute/models/isolated_devices.go @@ -31,8 +31,10 @@ import ( "yunion.io/x/sqlchemy" api "yunion.io/x/onecloud/pkg/apis/compute" + "yunion.io/x/onecloud/pkg/apis/notify" "yunion.io/x/onecloud/pkg/cloudcommon/consts" "yunion.io/x/onecloud/pkg/cloudcommon/db" + "yunion.io/x/onecloud/pkg/cloudcommon/notifyclient" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" "yunion.io/x/onecloud/pkg/util/rbacutils" @@ -248,8 +250,34 @@ func (self *SIsolatedDevice) ValidateUpdateData( return input, nil } -func (self *SIsolatedDevice) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) { - HostManager.ClearSchedDescCache(self.HostId) +func (device *SIsolatedDevice) isolateDeviceNotifyForHost(ctx context.Context, userCred mcclient.TokenCredential, action notify.SAction) { + model, err := HostManager.FetchById(device.HostId) + if err != nil { + return + } + host := model.(*SHost) + notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{ + Action: action, + Obj: host, + ObjDetailsDecorator: func(ctx context.Context, details *jsonutils.JSONDict) { + details.Set("customize_details", jsonutils.Marshal(device)) + }, + }) +} + +func (device *SIsolatedDevice) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) { + device.SStandaloneResourceBase.PostCreate(ctx, userCred, ownerId, query, data) + device.isolateDeviceNotifyForHost(ctx, userCred, notify.ActionIsolatedDeviceCreate) +} + +func (device *SIsolatedDevice) PostDelete(ctx context.Context, userCred mcclient.TokenCredential) { + device.SStandaloneResourceBase.PostDelete(ctx, userCred) + device.isolateDeviceNotifyForHost(ctx, userCred, notify.ActionIsolatedDeviceDelete) +} + +func (device *SIsolatedDevice) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) { + HostManager.ClearSchedDescCache(device.HostId) + device.isolateDeviceNotifyForHost(ctx, userCred, notify.ActionIsolatedDeviceUpdate) } // 直通设备(GPU等)列表 diff --git a/pkg/compute/tasks/instance_backup_create_task.go b/pkg/compute/tasks/instance_backup_create_task.go index 5332109f35..dd28b3dea3 100644 --- a/pkg/compute/tasks/instance_backup_create_task.go +++ b/pkg/compute/tasks/instance_backup_create_task.go @@ -24,6 +24,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/logclient" ) @@ -46,10 +47,14 @@ func (self *InstanceBackupCreateTask) taskFailed(ctx context.Context, ib *models self.SetStageFailed(ctx, reason) } -func (self *InstanceBackupCreateTask) taskSuccess(ctx context.Context, ib *models.SInstanceBackup) { +func (self *InstanceBackupCreateTask) taskSuccess(ctx context.Context, ib *models.SInstanceBackup, guest *models.SGuest) { ib.SetStatus(self.UserCred, compute.INSTANCE_BACKUP_STATUS_READY, "") logclient.AddActionLogWithStartable(self, ib, logclient.ACT_CREATE, nil, self.UserCred, true) self.SetStageComplete(ctx, nil) + notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{ + Obj: guest, + Action: notifyclient.ActionCreateBackupServer, + }) } func (self *InstanceBackupCreateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) { @@ -129,7 +134,8 @@ func (self *InstanceBackupCreateTask) OnInstanceBackup(ctx context.Context, ib * ib.SizeMb = sizeMb return nil }) - self.taskSuccess(ctx, ib) + guest := models.GuestManager.FetchGuestById(ib.GuestId) + self.taskSuccess(ctx, ib, guest) } func (self *InstanceBackupCreateTask) OnInstanceBackupFailed(ctx context.Context, ib *models.SInstanceBackup, data jsonutils.JSONObject) { diff --git a/pkg/notify/models/topic.go b/pkg/notify/models/topic.go index 919a4d2249..998b952699 100644 --- a/pkg/notify/models/topic.go +++ b/pkg/notify/models/topic.go @@ -88,30 +88,33 @@ type STopic struct { } 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" - DefaultResourceReleaseDue30Day = "resource release due 30 day" - DefaultResourceRelease = "resource release" - DefaultScheduledTaskExecute = "scheduled task execute" - DefaultScalingPolicyExecute = "scaling policy execute" - DefaultSnapshotPolicyExecute = "snapshot policy execute" - DefaultResourceOperationFailed = "resource operation failed" - DefaultResourceSync = "resource sync" - DefaultSystemExceptionEvent = "system exception event" - DefaultChecksumTestFailed = "checksum test failed" - DefaultUserLock = "user lock" - DefaultActionLogExceedCount = "action log exceed count" - DefaultSyncAccountStatus = "cloud account sync status" - DefaultPasswordExpireDue1Day = "password expire due 1 day" - DefaultPasswordExpireDue7Day = "password expire due 7 day" - DefaultPasswordExpire = "password expire" - DefaultNetOutOfSync = "net out of sync" - DefaultMysqlOutOfSync = "mysql out of sync" - DefaultServiceAbnormal = "service abnormal" - DefaultServerPanicked = "server panicked" + DefaultResourceCreateDelete = "resource create or delete" + DefaultResourceChangeConfig = "resource change config" + DefaultResourceUpdate = "resource update" + DefaultResourceReleaseDue1Day = "resource release due 1 day" + DefaultResourceReleaseDue3Day = "resource release due 3 day" + DefaultResourceReleaseDue30Day = "resource release due 30 day" + DefaultResourceRelease = "resource release" + DefaultScheduledTaskExecute = "scheduled task execute" + DefaultScalingPolicyExecute = "scaling policy execute" + DefaultSnapshotPolicyExecute = "snapshot policy execute" + DefaultResourceOperationFailed = "resource operation failed" + DefaultResourceOperationSuccessed = "resource operation successed" + DefaultResourceSync = "resource sync" + DefaultSystemExceptionEvent = "system exception event" + DefaultChecksumTestFailed = "checksum test failed" + DefaultUserLock = "user lock" + DefaultActionLogExceedCount = "action log exceed count" + DefaultSyncAccountStatus = "cloud account sync status" + DefaultPasswordExpireDue1Day = "password expire due 1 day" + DefaultPasswordExpireDue7Day = "password expire due 7 day" + DefaultPasswordExpire = "password expire" + DefaultNetOutOfSync = "net out of sync" + DefaultMysqlOutOfSync = "mysql out of sync" + DefaultServiceAbnormal = "service abnormal" + DefaultServerPanicked = "server panicked" + DefaultAttachOrDetach = "resource attach or detach" + DefaultIsolatedDeviceChanged = "isolated device changed" ) func (sm *STopicManager) InitializeData() error { @@ -279,6 +282,14 @@ func (sm *STopicManager) InitializeData() error { ) t.Type = notify.TOPIC_TYPE_RESOURCE t.Results = tristate.False + case DefaultResourceOperationSuccessed: + t.addResources( + notify.TOPIC_RESOURCE_SERVER, + ) + t.addAction( + notify.ActionCreateBackupServer, + ) + t.Type = notify.TOPIC_TYPE_RESOURCE case DefaultResourceSync: t.addResources( notify.TOPIC_RESOURCE_SERVER, @@ -483,6 +494,27 @@ func (sm *STopicManager) InitializeData() error { t.ContentEn = api.EXPIRED_RELEASE_CONTENT_EN t.TitleCn = api.EXPIRED_RELEASE_TITLE_CN t.TitleEn = api.EXPIRED_RELEASE_TITLE_EN + case DefaultAttachOrDetach: + t.addResources( + notify.TOPIC_RESOURCE_HOST, + ) + t.addAction( + notify.ActionAttach, + notify.ActionDetach, + ) + t.Type = notify.TOPIC_TYPE_RESOURCE + t.Results = tristate.True + case DefaultIsolatedDeviceChanged: + t.addResources( + notify.TOPIC_RESOURCE_HOST, + ) + t.addAction( + notify.ActionIsolatedDeviceCreate, + notify.ActionIsolatedDeviceUpdate, + notify.ActionIsolatedDeviceDelete, + ) + t.Type = notify.TOPIC_TYPE_RESOURCE + t.Results = tristate.True } if topic == nil {