-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
issue:3563885:UFM Enterprise network reports #123
Open
Abeer-Moghrabi
wants to merge
7
commits into
Mellanox:main
Choose a base branch
from
Abeer-Moghrabi:3563885-events-histroy
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,198
−0
Open
Changes from 1 commit
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
7839f2b
issue:3572586: create events history plugin basic structure
Abeer-Moghrabi 98af278
issue:3574823: create event basic structure (event, event resource an…
Abeer-Moghrabi f3b4073
issue:3083189: add missing copyrights
Abeer-Moghrabi c410dc4
issue:3576752: Create a collection for each supported event and add t…
Abeer-Moghrabi 2b812ec
issue:3572590: add file watcher to watch event.log on file modified
Abeer-Moghrabi 04e1ce7
issue:3572590: add value to PLUGIN_NAME in Dockerfile
Abeer-Moghrabi 0df4b84
issue:3572590: replace python3.9 with python3 which is usually symlin…
Abeer-Moghrabi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 74 additions & 0 deletions
74
plugins/events_history_plugin/src/events_history/mgr/events_history_files_watcher.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
from utils.filewatch.abstract_file_watcher import AbstractFileWatcher | ||
import pyinotify | ||
from utils.logger import Logger, LOG_LEVELS | ||
from mgr.events_history_mgr import EventsHistoryMgr | ||
from constants.events_constants import EventsConstants | ||
import os | ||
|
||
|
||
class EventsHistoryListener(): | ||
""" | ||
Listen for changes in files | ||
""" | ||
# The last_position is used to read only the newly added lines in the log file by updating the pointer to that | ||
# position each time the file is read. | ||
|
||
def __init__(self): | ||
self.last_position = self._get_last_position() | ||
self.event_mgr = EventsHistoryMgr.getInstance() | ||
|
||
def onChange(self, event): | ||
""" | ||
Called whenever a modification has been monitored by the watcher | ||
:param event: the data of the event that occurred(file name, mask name,..). | ||
:return: | ||
""" | ||
with open(event.pathname) as log_file: | ||
log_file.seek(self.last_position) | ||
new_lines = log_file.readlines() | ||
self.last_position = log_file.tell() # Update last position | ||
|
||
for line in new_lines: | ||
# Process each new line here | ||
self.event_mgr.create_event(line) | ||
|
||
def _get_last_position(self): | ||
file_path = os.path.join(EventsConstants.EVENT_LOGS_DIRECTORY, EventsConstants.EVENT_LOG) | ||
try: | ||
with open(file_path, 'r', encoding='utf-8') as f: | ||
new_lines = f.readlines() | ||
return f.tell() | ||
except Exception as e: | ||
Logger.log_message(f"Error while getting the last opsition in {file_path}: {e}", LOG_LEVELS.ERROR) | ||
|
||
|
||
class EventsHistoryFilesWatcher(AbstractFileWatcher): | ||
""" | ||
This class is responsible for monitoring which files have been modified by listening to the IN_MODIFY events | ||
provided by the pyinotify library. | ||
""" | ||
def __init__(self, files_list, read_freq=0): | ||
""" | ||
:param files_list: list, is the list of files that we want to listen to when a change | ||
:param read_freq: int, is the interval between every time we request for the files that have been modified | ||
""" | ||
events_list = [pyinotify.IN_MODIFY] | ||
super(EventsHistoryFilesWatcher, self).__init__(files_list, events_list, read_freq=read_freq) | ||
|
||
def notifyListeners(self, event): | ||
""" | ||
This function is designed notify the listeners that a file has been modified | ||
:param event: the data of the event that occurred(file name, mask name,..). | ||
:return: | ||
""" | ||
for listener in self._listener_dict.values(): | ||
listener.onChange(event) | ||
|
||
def process_IN_MODIFY(self, event): | ||
""" | ||
Notify listeners that a file has been modified. | ||
This function will be called when the event of a file modification (IN_MODIFY event) occurs | ||
:param event: the event that occurred. | ||
""" | ||
Logger.log_message(f"event: {event}", LOG_LEVELS.DEBUG) | ||
self.notifyListeners(event) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# | ||
# Copyright © 2013-2022 NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED. | ||
# | ||
# This software product is a proprietary product of Nvidia Corporation and its affiliates | ||
# (the "Company") and all right, title, and interest in and to the software | ||
# product, including all associated intellectual property rights, are and | ||
# shall remain exclusively with the Company. | ||
# | ||
# This software product is governed by the End User License Agreement | ||
# provided with the software product. | ||
# @author: Abeer Moghrabi | ||
# @date: Aug 15, 2023 | ||
# | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
# | ||
# Copyright © 2013-2022 NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED. | ||
# | ||
# This software product is a proprietary product of Nvidia Corporation and its affiliates | ||
# (the "Company") and all right, title, and interest in and to the software | ||
# product, including all associated intellectual property rights, are and | ||
# shall remain exclusively with the Company. | ||
# | ||
# This software product is governed by the End User License Agreement | ||
# provided with the software product. | ||
# @author: Abeer Moghrabi | ||
# @date: Aug 15, 2023 | ||
# | ||
|
||
import os | ||
from threading import Lock | ||
import pyinotify | ||
from utils.singleton import Singleton | ||
from utils.logger import Logger, LOG_LEVELS | ||
|
||
|
||
class AbstractFileWatcher(Singleton): | ||
""" | ||
Base class for File Watching , | ||
This Class should be extended and not used directly! | ||
Each derived class should can watch one or more files. | ||
|
||
Example of subclass can be found in infra.filewatch in file gvWatcher.py | ||
Note: this class was copied from UFM project | ||
""" | ||
|
||
def __init__(self, file_list, events, read_freq=300): | ||
""" | ||
:param file_list: list, list of paths to files the watcher will listen on | ||
:param events: list, list of events on the files that the watcher listens on taken from Events class (below this class) | ||
:param read_freq: int, is the interval between every time we request for the files that have been modified | ||
@ivar _watchedFileList: the list of files we want to watch | ||
@ivar _watchedDirs: the list of directories we want to watch | ||
@ivar _listener_list: the list of listeners to inform on file events | ||
@ivar _listener_id_counter: the id that the next listener will get | ||
@ivar _listener_data_lock: the lock being locked when adding/removing listeners | ||
""" | ||
self._watchedFileList = set([os.path.abspath(f) for f in file_list]) | ||
self._watchedDirs = set([os.path.dirname(f) for f in self._watchedFileList]) | ||
self._listener_dict = {} | ||
self._listener_id_counter = 0 | ||
self._listener_data_lock = Lock() | ||
self._startWatching(events, read_freq=read_freq) | ||
|
||
def _startWatching(self, events, read_freq): | ||
""" | ||
Start file watching by the watch manager | ||
:param events: list of events on the files that the watcher listens on taken from Events class (below this class) | ||
""" | ||
# initialize bitmask with all zeros (no events). | ||
mask = 0x00000000 | ||
# Iterate through the list of events and add each event to the bitmask. | ||
# The '|' operator is used to perform a bitwise OR operation to combine event masks. | ||
for event in events: | ||
mask = mask | event | ||
try : | ||
wm = pyinotify.WatchManager() | ||
eh = EventHandler(self) | ||
self._notifier = pyinotify.ThreadedNotifier(wm, eh, read_freq=read_freq) | ||
|
||
for path in self._watchedDirs: | ||
wm.add_watch(path, mask) | ||
|
||
self._notifier.daemon = True | ||
self._notifier.start() | ||
|
||
except Exception as e: | ||
Logger.log_message("FileWatcher: Was NOT able to start, %s is NOT watched, the reason is : %s" % (self._watchedFileList, e), LOG_LEVELS.ERROR) | ||
return | ||
Logger.log_message("FileWatcher: %s is being watched " % self._watchedFileList, LOG_LEVELS.INFO) | ||
|
||
def __del__(self): | ||
""" | ||
Stop file watching by the watch manager | ||
""" | ||
if hasattr(self, '_notifier'): | ||
self._notifier.stop() | ||
Logger.log_message("FileWatcher: %s is NO LONGER being watched" % self._watchedFileList, LOG_LEVELS.INFO) | ||
|
||
def addListener(self, listener): | ||
""" | ||
adds listener to the file watcher | ||
:param listener: the listener to add to the listeners list | ||
:return: the listener id | ||
""" | ||
self._listener_data_lock.acquire() | ||
id = self._listener_id_counter | ||
self._listener_dict[id] = listener | ||
self._listener_id_counter += 1 | ||
self._listener_data_lock.release() | ||
return id | ||
|
||
def removeListener(self, id): | ||
""" | ||
removes listener from the file watcher by id given | ||
:param id: the id of the listener to remove | ||
:return: True if the listener was removed and false if no listener with the given id was found | ||
""" | ||
try : | ||
self._listener_dict.pop(id) | ||
|
||
except : | ||
return False | ||
|
||
return True | ||
|
||
def handleEvent(self, event): | ||
if event.pathname in self._watchedFileList: | ||
#print "==> ", event.maskname, ": ", event.pathname | ||
# Invokes process_MASKNAME | ||
meth = getattr(self, 'process_' + event.maskname, None) | ||
if meth is not None: | ||
meth(event) | ||
|
||
""" | ||
The methods below should be implemented by subclasses, each method deals with different event type (on files). | ||
for example, in this methods is where you will notify the listeners on the files of the event that happened. | ||
** If you are watching more then one file, you can use the event object to get the file that caused the event. ** | ||
""" | ||
|
||
def process_IN_ACCESS(self, event): | ||
pass | ||
|
||
def process_IN_MODIFY(self, event): | ||
pass | ||
|
||
def process_IN_ATTRIB(self, event): | ||
pass | ||
|
||
def process_IN_CLOSE_WRITE(self, event): | ||
pass | ||
|
||
def process_IN_CLOSE_NOWRITE(self, event): | ||
pass | ||
|
||
def process_IN_OPEN(self, event): | ||
pass | ||
|
||
def process_IN_MOVED_FROM(self, event): | ||
pass | ||
|
||
def process_IN_MOVED_TO(self, event): | ||
pass | ||
|
||
def process_IN_CREATE(self, event): | ||
pass | ||
|
||
def process_IN_DELETE(self, event): | ||
pass | ||
|
||
def process_IN_DELETE_SELF(self, event): | ||
pass | ||
|
||
def process_IN_MOVE_SELF(self, event): | ||
pass | ||
|
||
def process_default(self, event): | ||
pass | ||
|
||
|
||
class EventHandler(pyinotify.ProcessEvent): | ||
""" | ||
This class handle specific actions when filesystem events occur. | ||
It's responsible for processing events such as file modifications, access, attribute changes, and more | ||
!!! This class should not be touched !!! | ||
""" | ||
|
||
def __init__(self, fileWatcher): | ||
""" | ||
@ivar _fw : | ||
The instance of the fileWatcher | ||
""" | ||
self._fw = fileWatcher | ||
|
||
def process_default(self, event): | ||
""" | ||
when an event type that doesn't have a specific method override is encountered. In other words, it serves | ||
as a catch-all method that gets called for any event type that doesn't have its own dedicated method defined | ||
in your custom event handler class. | ||
:param event: the data of the event that occurred(file name, mask name,..). | ||
:return: | ||
""" | ||
self._fw.handleEvent(event) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How will you get last position if file was replaced by logrotate?