Skip to content
This repository was archived by the owner on Dec 17, 2021. It is now read-only.

Commit b646e19

Browse files
fix: new execution of enricher (#163)
* fix: add delay tp snmp_polling * fix: change variable of extract_network_interface_data_from_additional_config * fix: add loggers * fix: change way of adding additional varbinds * fix: add loggers * fix: refactor method to update enricher structure * fix: add loggers * fix: update OID * fix: snmp_pooling function * fix: update enricher to trigger only in case of exisitng IF-MIB * fix: add logs and redesign function * fix: change sequence of enricher check * fix: refactor code * fix: delete unnecessary loggers * fix: refactor variable name for delete_ifmib decorator * fix: adjusting code to PR comments * fix: remove unnecessary boolean cast * fix: add saving InventoryRecord for every host in inventory * fix: change way of requesting walk for IF-MIB
1 parent d69a9c7 commit b646e19

File tree

7 files changed

+425
-1
lines changed

7 files changed

+425
-1
lines changed

splunk_connect_for_snmp_poller/manager/poller.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515
#
16+
import copy
1617
import functools
1718
import logging.config
1819
import threading
@@ -28,6 +29,7 @@
2829
create_poller_scheduler_entry_key,
2930
parse_inventory_file,
3031
return_database_id,
32+
update_enricher_config,
3133
)
3234
from splunk_connect_for_snmp_poller.manager.profile_matching import (
3335
assign_profiles_to_device,
@@ -59,6 +61,7 @@ def __init__(self, args, server_config):
5961
self._unmatched_devices = {}
6062
self._lock = threading.Lock()
6163
self._force_refresh = False
64+
self._old_enricher = {}
6265

6366
def force_inventory_refresh(self):
6467
self._force_refresh = True
@@ -104,6 +107,7 @@ def __check_inventory(self):
104107
# TODO should rethink logic with changed to profiles and oids
105108
inventory_entry_keys = set()
106109
inventory_hosts = set()
110+
inventory_hosts_with_snmp_data = {}
107111
profiles = get_profiles(self._server_config)
108112
for ir in parse_inventory_file(self._args.inventory, profiles):
109113
entry_key = create_poller_scheduler_entry_key(ir.host, ir.profile)
@@ -117,7 +121,9 @@ def __check_inventory(self):
117121
)
118122
continue
119123
inventory_entry_keys.add(entry_key)
120-
inventory_hosts.add(return_database_id(ir.host))
124+
ir_host = return_database_id(ir.host)
125+
inventory_hosts.add(return_database_id(ir_host))
126+
inventory_hosts_with_snmp_data[ir_host] = copy.deepcopy(ir)
121127
if ir.profile == DYNAMIC_PROFILE:
122128
self.delete_all_entries_per_host(ir.host)
123129
self.add_device_for_profile_matching(ir)
@@ -131,8 +137,37 @@ def __check_inventory(self):
131137
else:
132138
self.update_schedule_for_changed_conf(entry_key, ir, profiles)
133139

140+
if server_config_modified:
141+
new_enricher = self._server_config.get("enricher", {})
142+
if new_enricher != self._old_enricher:
143+
self.run_enricher_check(
144+
new_enricher, profiles, inventory_hosts_with_snmp_data
145+
)
134146
self.clean_job_inventory(inventory_entry_keys, inventory_hosts)
135147

148+
def run_enricher_check(
149+
self, new_enricher, profiles, inventory_hosts_with_snmp_data
150+
):
151+
logger.info(
152+
f"Previous enricher: {self._old_enricher} \n New enricher: {new_enricher}"
153+
)
154+
if new_enricher == {}:
155+
logger.debug("Enricher is being deleted from MongoDB")
156+
self._mongo.delete_all_static_data()
157+
self._old_enricher = {}
158+
return
159+
for inventory_host in inventory_hosts_with_snmp_data.keys():
160+
update_enricher_config(
161+
self._old_enricher,
162+
new_enricher,
163+
self._mongo,
164+
profiles,
165+
inventory_hosts_with_snmp_data[inventory_host],
166+
self._server_config,
167+
self.__get_splunk_indexes(),
168+
)
169+
self._old_enricher = new_enricher
170+
136171
def delete_all_entries_per_host(self, host):
137172
for entry_key in list(self._jobs_map.keys()):
138173
if entry_key.split("#")[0] == host:

splunk_connect_for_snmp_poller/manager/poller_utilities.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,20 @@
2727
from splunk_connect_for_snmp_poller.manager.realtime.real_time_data import (
2828
should_redo_walk,
2929
)
30+
from splunk_connect_for_snmp_poller.manager.static.interface_mib_utililities import (
31+
extract_network_interface_data_from_additional_config,
32+
)
3033
from splunk_connect_for_snmp_poller.manager.task_utilities import parse_port
3134
from splunk_connect_for_snmp_poller.manager.tasks import snmp_polling
3235
from splunk_connect_for_snmp_poller.manager.validator.inventory_validator import (
3336
DYNAMIC_PROFILE,
3437
is_valid_inventory_line_from_dict,
3538
should_process_inventory_line,
3639
)
40+
from splunk_connect_for_snmp_poller.manager.variables import (
41+
enricher_if_mib,
42+
enricher_oid_family,
43+
)
3744
from splunk_connect_for_snmp_poller.utilities import OnetimeFlag, multi_key_lookup
3845

3946
logger = logging.getLogger(__name__)
@@ -274,6 +281,88 @@ def automatic_realtime_task(
274281
logger.exception("Error during automatic_realtime_task")
275282

276283

284+
def update_enricher_config(
285+
old_enricher,
286+
new_enricher,
287+
mongo,
288+
profiles,
289+
inventory_host,
290+
server_config,
291+
splunk_indexes,
292+
):
293+
run_ifmib_walk = is_ifmib_different(old_enricher, new_enricher)
294+
if run_ifmib_walk:
295+
_update_enricher_config_with_ifmib(
296+
profiles, inventory_host, server_config, splunk_indexes
297+
)
298+
else:
299+
_update_enricher_config_for_additional_varbinds(
300+
old_enricher, new_enricher, mongo, inventory_host.host, server_config
301+
)
302+
303+
304+
def _update_enricher_config_with_ifmib(
305+
profiles,
306+
inventory_host,
307+
server_config,
308+
splunk_indexes,
309+
):
310+
inventory_host.profile = OidConstant.IF_MIB
311+
snmp_polling.delay(
312+
inventory_host.to_json(),
313+
server_config,
314+
splunk_indexes,
315+
profiles,
316+
)
317+
318+
319+
def _update_enricher_config_for_additional_varbinds(
320+
old_enricher,
321+
new_enricher,
322+
mongo,
323+
inventory_host,
324+
server_config,
325+
):
326+
families_to_delete = deleted_oid_families(old_enricher, new_enricher)
327+
mongo.delete_oidfamilies_from_static_data(inventory_host, families_to_delete)
328+
additional_enricher_varbinds = modified_oid_families(server_config)
329+
mongo.update_static_data_for_one(inventory_host, additional_enricher_varbinds)
330+
331+
332+
def is_ifmib_different(old_enricher, new_enricher):
333+
new_if_mib = multi_key_lookup(new_enricher, (enricher_oid_family, enricher_if_mib))
334+
old_if_mib = multi_key_lookup(old_enricher, (enricher_oid_family, enricher_if_mib))
335+
return new_if_mib != old_if_mib
336+
337+
338+
def delete_ifmib(func):
339+
def function(*args, **kwargs):
340+
set_of_oid_families_to_modify = func(*args, **kwargs)
341+
if "IF-MIB" in set_of_oid_families_to_modify:
342+
if isinstance(set_of_oid_families_to_modify, set):
343+
set_of_oid_families_to_modify.remove("IF-MIB")
344+
if isinstance(set_of_oid_families_to_modify, dict):
345+
set_of_oid_families_to_modify.pop("IF-MIB")
346+
return set_of_oid_families_to_modify
347+
348+
return function
349+
350+
351+
@delete_ifmib
352+
def deleted_oid_families(old_enricher, new_enricher):
353+
old_families = old_enricher.get("oidFamily", {})
354+
new_families = new_enricher.get("oidFamily", {})
355+
return set(old_families.keys()) - set(new_families.keys())
356+
357+
358+
@delete_ifmib
359+
def modified_oid_families(server_config):
360+
additional_enricher_varbinds = (
361+
extract_network_interface_data_from_additional_config(server_config)
362+
)
363+
return additional_enricher_varbinds
364+
365+
277366
def create_poller_scheduler_entry_key(host, profile):
278367
return host + "#" + profile
279368

splunk_connect_for_snmp_poller/manager/realtime/oid_constant.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ class OidConstant:
1919
SYS_UP_TIME_INSTANCE = "1.3.6.1.2.1.1.3.0"
2020
# see https://www.alvestrand.no/objectid/1.3.6.1.html for a better understanding
2121
UNIVERSAL_BASE_OID = "1.3.6.1.*"
22+
IF_MIB = "1.3.6.1.2.1.2.*"

splunk_connect_for_snmp_poller/manager/variables.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@
1616
enricher_existing_varbinds = "existingVarBinds"
1717
enricher_additional_varbinds = "additionalVarBinds"
1818
enricher_oid_family = "oidFamily"
19+
enricher_if_mib = "IF-MIB"

splunk_connect_for_snmp_poller/mongo.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,32 @@ def update_mib_static_data_for(self, host, existing_data, additional_data):
216216
return_document=ReturnDocument.AFTER,
217217
)
218218
return static_data_dictionary[WalkedHostsRepository.MIB_STATIC_DATA]
219+
220+
def update_static_data_for_one(self, host, static_data_dictionary):
221+
logger.info(f"Updating static data for {host} with {static_data_dictionary}")
222+
for oid_family in static_data_dictionary.keys():
223+
index_dict = static_data_dictionary[oid_family]
224+
if index_dict:
225+
self._walked_hosts.update(
226+
{"_id": host},
227+
{
228+
"$set": {
229+
f"MIB-STATIC-DATA.{oid_family}.additionalVarBinds": index_dict
230+
}
231+
},
232+
upsert=True,
233+
)
234+
235+
def delete_oidfamilies_from_static_data(self, host, oid_families):
236+
logger.info(f"Deleting oidfamilies {oid_families} from {host}")
237+
for oid_family in oid_families:
238+
self._walked_hosts.find_one_and_update(
239+
{"_id": host},
240+
{"$unset": {f"MIB-STATIC-DATA.{oid_family}": ""}},
241+
)
242+
243+
def delete_all_static_data(self):
244+
self._walked_hosts.update_many(
245+
{},
246+
{"$unset": {"MIB-STATIC-DATA": ""}},
247+
)

tests/test_poller.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#
2+
# Copyright 2021 Splunk Inc.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
import sys
17+
from unittest import TestCase
18+
from unittest.mock import MagicMock, Mock, patch
19+
20+
sys.modules["splunk_connect_for_snmp_poller.manager.celery_client"] = Mock()
21+
from splunk_connect_for_snmp_poller.manager.poller import Poller # noqa: E402
22+
23+
24+
class TestPollerUtilities(TestCase):
25+
def test_run_enricher_check_when_enricher_is_deleted(self):
26+
server_config = {"mongo": ""}
27+
with patch(
28+
"splunk_connect_for_snmp_poller.mongo.WalkedHostsRepository.__init__"
29+
) as mock:
30+
mock.return_value = None
31+
obj = Poller([], server_config)
32+
obj._old_enricher = {
33+
"IF-MIB": {
34+
"existingVarBinds": [
35+
{"ifIndex": "interface_index"},
36+
{"ifDescr": "interface_desc"},
37+
{"ifPhysAddress": "MAC_address"},
38+
],
39+
"additionalVarBinds": [{"indexNum": "index_number"}],
40+
}
41+
}
42+
with patch(
43+
"splunk_connect_for_snmp_poller.mongo.WalkedHostsRepository.delete_all_static_data"
44+
):
45+
obj.run_enricher_check({}, [], {"127.0.0.1:161": MagicMock()})
46+
self.assertEqual(obj._old_enricher, {})

0 commit comments

Comments
 (0)