From 6702b5681314400cc59c516f4aa7b1d1bb27bba4 Mon Sep 17 00:00:00 2001 From: "Ladue, David (dl3158)" Date: Thu, 29 Mar 2018 15:00:54 -0400 Subject: more pytest coverage Change-Id: I665b032f4789ff7a3089d727f36c8e8500963497 Issue-ID: DCAEGEN2-271 Signed-off-by: Ladue, David (dl3158) --- etc/snmptrapd.json | 8 +- snmptrap/mod/trapd_io.py | 24 ++--- snmptrap/mod/trapd_logging.py | 199 ---------------------------------------- snmptrap/snmptrapd.py | 54 ++--------- snmptrap/snmptrapd.sh | 9 +- tests/conftest.py | 12 --- tests/test_snmptrapd.py | 73 ++++++++++++++- tests/test_trapd_io.py | 139 ++++++++++++++++++++++++++++ tests/test_trapd_runtime_pid.py | 2 + tests/test_trapd_settings.py | 1 - 10 files changed, 238 insertions(+), 283 deletions(-) delete mode 100644 snmptrap/mod/trapd_logging.py delete mode 100644 tests/conftest.py create mode 100644 tests/test_trapd_io.py diff --git a/etc/snmptrapd.json b/etc/snmptrapd.json index 570ed82..837bc0a 100644 --- a/etc/snmptrapd.json +++ b/etc/snmptrapd.json @@ -3,9 +3,9 @@ "snmptrap.title": "ONAP SNMP Trap Receiver" , "protocols.transport": "udp", "protocols.ipv4_interface": "0.0.0.0", -"protocols.ipv4_port": 162, +"protocols.ipv4_port": 6162, "protocols.ipv6_interface": "::1", -"protocols.ipv6_port": 162, +"protocols.ipv6_port": 6162, "cache.dns_cache_ttl_seconds": 60, "publisher.http_timeout_milliseconds": 1500, "publisher.http_retries": 3, @@ -54,9 +54,9 @@ "files.roll_frequency": "hour", "files.minimum_severity_to_log": 2, "trap_def.1.trap_oid" : ".1.3.6.1.4.1.74.2.46.12.1.1", -"trap_def.1.trap_category": "DCAE-SNMP-TRAPS", +"trap_def.1.trap_category": "ONAP-COLLECTOR-SNMPTRAP", "trap_def.2.trap_oid" : "*", -"trap_def.2.trap_category": "DCAE-SNMP-TRAPS", +"trap_def.2.trap_category": "ONAP-COLLECTOR-SNMPTRAP", "stormwatch.1.stormwatch_oid" : ".1.3.6.1.4.1.74.2.46.12.1.1", "stormwatch.1.low_water_rearm_per_minute" : "5", "stormwatch.1.high_water_arm_per_minute" : "100", diff --git a/snmptrap/mod/trapd_io.py b/snmptrap/mod/trapd_io.py index 8667750..351174f 100644 --- a/snmptrap/mod/trapd_io.py +++ b/snmptrap/mod/trapd_io.py @@ -175,13 +175,16 @@ def roll_file(_loc_file_name): if os.path.isfile(_loc_file_name): try: os.rename(_loc_file_name, _loc_file_name_bak) + return True except Exception as e: _msg = ("ERROR: Unable to rename %s to %s" % (_loc_file_name, _loc_file_name_bak)) ecomp_logger(tds.LOG_TYPE_ERROR, tds.SEV_CRIT, tds.CODE_GENERAL, _msg) + return False + return False # # # # # # # # # # # # # # fx: open_log_file @@ -304,16 +307,12 @@ def ecomp_logger(_log_type, _sev, _error_code, _msg): unused = "" - # ct = time.time() - # lt = time.localtime(ct) - # t_hman = time.strftime(DateFmt, lt) - # t_ms = (ct - int(ct)) * 1000 # above were various attempts at setting time string found in other # libs; instead, let's keep it real: t_out = datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S,%f")[:-3] calling_fx = inspect.stack()[1][3] - # FIXME: this entire module is a hack to override concept of prog logging + # DLFM: this entire module is a hack to override concept of prog logging # written across multiple files (???), making diagnostics IMPOSSIBLE! # Hoping to leverage ONAP logging libraries & standards when available @@ -321,7 +320,7 @@ def ecomp_logger(_log_type, _sev, _error_code, _msg): if _log_type < 1 or _log_type > 5: msg = ("INVALID log type: %s " % _log_type) _out_rec = ("%s|%s|%s|%s|%s|%s|%s|%s|%s" - % ((calling_fx, "snmptrapd", unused, unused, unused, tds.SEV_TYPES[_sev], _error_code, unused, (msg + _msg)))) + % (calling_fx, "snmptrapd", unused, unused, unused, tds.SEV_TYPES[_sev], _error_code, unused, (msg + _msg))) try: tds.eelf_error_fd.write('%s|%s\n' % (t_out, str(_out_rec))) except Exception as e: @@ -333,7 +332,7 @@ def ecomp_logger(_log_type, _sev, _error_code, _msg): # log to appropriate eelf log (different files ??) if _log_type == tds.LOG_TYPE_ERROR: _out_rec = ('%s|%s|%s|%s|%s|%s|%s|%s|%s' - % ((calling_fx, "snmptrapd", unused, unused, unused, tds.SEV_TYPES[_sev], _error_code, unused, _msg))) + % (calling_fx, "snmptrapd", unused, unused, unused, tds.SEV_TYPES[_sev], _error_code, unused, _msg)) try: tds.eelf_error_fd.write('%s|%s\n' % (t_out, str(_out_rec))) except Exception as e: @@ -341,7 +340,7 @@ def ecomp_logger(_log_type, _sev, _error_code, _msg): elif _log_type == tds.LOG_TYPE_AUDIT: # log message in AUDIT format _out_rec = ('%s|%s|%s|%s|%s|%s|%s|%s|%s' - % ((calling_fx, "snmptrapd", unused, unused, unused, tds.SEV_TYPES[_sev], _error_code, unused, _msg))) + % (calling_fx, "snmptrapd", unused, unused, unused, tds.SEV_TYPES[_sev], _error_code, unused, _msg)) try: tds.eelf_audit_fd.write('%s|%s\n' % (t_out, str(_out_rec))) except Exception as e: @@ -349,20 +348,18 @@ def ecomp_logger(_log_type, _sev, _error_code, _msg): elif _log_type == tds.LOG_TYPE_METRICS: # log message in METRICS format _out_rec = ('%s|%s|%s|%s|%s|%s|%s|%s|%s' - % ((calling_fx, "snmptrapd", unused, unused, unused, tds.SEV_TYPES[_sev], _error_code, unused, _msg))) + % (calling_fx, "snmptrapd", unused, unused, unused, tds.SEV_TYPES[_sev], _error_code, unused, _msg)) try: tds.eelf_metrics_fd.write('%s|%s\n' % (t_out, str(_out_rec))) except Exception as e: stdout_logger(str(_out_rec)) # DEBUG *AND* others - there *MUST BE* a single time-sequenced log for diagnostics! - # FIXME: too much I/O !!! + # DLFM: too much I/O !!! # always write to debug; we need ONE logfile that has time-sequence full view !!! - # if (_log_type == tds.LOG_TYPE_DEBUG and _sev >= tds.current_min_sev_log_level) or (_log_type != tds.LOG_TYPE_DEBUG): - # log message in DEBUG format _out_rec = ("%s|%s|%s|%s|%s|%s|%s|%s|%s" - % ((calling_fx, "snmptrapd", unused, unused, unused, tds.SEV_TYPES[_sev], _error_code, unused, _msg))) + % (calling_fx, "snmptrapd", unused, unused, unused, tds.SEV_TYPES[_sev], _error_code, unused, _msg)) try: tds.eelf_debug_fd.write('%s|%s\n' % (t_out, str(_out_rec))) except Exception as e: @@ -391,6 +388,5 @@ def stdout_logger(_msg): """ t_out = datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S,%f")[:-3] - # calling_fx = inspect.stack()[1][3] print('%s %s' % (t_out, _msg)) diff --git a/snmptrap/mod/trapd_logging.py b/snmptrap/mod/trapd_logging.py deleted file mode 100644 index ae5a1a0..0000000 --- a/snmptrap/mod/trapd_logging.py +++ /dev/null @@ -1,199 +0,0 @@ -# ============LICENSE_START=======================================================) -# org.onap.dcae -# ================================================================================ -# Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. -# ================================================================================ -# 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. -# ============LICENSE_END========================================================= -# -# ECOMP is a trademark and service mark of AT&T Intellectual Property. -# -""" -""" - -__docformat__ = 'restructuredtext' - -# basics -import datetime -import errno -import inspect -import json -import logging -import logging.handlers -import os -import sys -import string -import time -import traceback -import unicodedata - -import trapd_settings as tds - -prog_name = os.path.basename(__file__) - - -# # # # # # # # # # # # # # # # # # # -# fx: ecomp_logger -> log in eelf format until standard -# is released for python via LOG-161 -# # # # # # # # # # ## # # # # # # # - -def ecomp_logger(_log_type, _sev, _error_code, _msg): - """ - Log to ecomp-style logfiles. Logs include: - - Note: this will be updated when https://jira.onap.org/browse/LOG-161 - is closed/available; until then, we resort to a generic format with - valuable info in "extra=" field (?) - - :Parameters: - _msg - - :Exceptions: - none - :Keywords: - eelf logging - :Log Styles: - - :error.log: - - if CommonLogger.verbose: print("using CommonLogger.ErrorFile") - self._logger.log(50, '%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' \ - % (requestID, threadID, serviceName, partnerName, targetEntity, targetServiceName, - errorCategory, errorCode, errorDescription, detailMessage)) - - error.log example: - - 2018-02-20T07:21:34,007+00:00||MainThread|snmp_log_monitor||||FATAL|900||Tue Feb 20 07:21:11 UTC 2018 CRITICAL: [a0cae74e-160e-11e8-8f9f-0242ac110002] ALL publish attempts failed to DMAPP server: dcae-mrtr-zltcrdm5bdce1.1dff83.rdm5b.tci.att.com, topic: DCAE-COLLECTOR-UCSNMP, 339 trap(s) not published in epoch_serno range: 15191112530000 - 15191112620010 - - :debug.log: - - if CommonLogger.verbose: print("using CommonLogger.DebugFile") - self._logger.log(50, '%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' \ - % (requestID, threadID, serverName, serviceName, instanceUUID, upperLogLevel, - severity, serverIPAddress, server, IPAddress, className, timer, detailMessage)) - - debug.log example: - - none available - - :audit.log: - - if CommonLogger.verbose: print("using CommonLogger.AuditFile") - endAuditTime, endAuditMsec = self._getTime() - if self._begTime is not None: - d = {'begtime': self._begTime, 'begmsecs': self._begMsec, 'endtime': endAuditTime, - 'endmsecs': endAuditMsec} - else: - d = {'begtime': endAuditTime, 'begmsecs': endAuditMsec, 'endtime': endAuditTime, - 'endmsecs': endAuditMsec} - - self._logger.log(50, '%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' \ - % (requestID, serviceInstanceID, threadID, serverName, serviceName, partnerName, - statusCode, responseCode, responseDescription, instanceUUID, upperLogLevel, - severity, serverIPAddress, timer, server, IPAddress, className, unused, - processKey, customField1, customField2, customField3, customField4, - detailMessage), extra=d) - - - :metrics.log: - - self._logger.log(50,'%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' \ - % (requestID, serviceInstanceID, threadID, serverName, serviceName, partnerName, - targetEntity, targetServiceName, statusCode, responseCode, responseDescription, - instanceUUID, upperLogLevel, severity, serverIPAddress, timer, server, - IPAddress, - className, unused, processKey, targetVirtualEntity, customField1, customField2, - customField3, customField4, detailMessage), extra=d) - - metrics.log example: - - none available - - - """ - - unused = "" - - # ct = time.time() - # lt = time.localtime(ct) - # t_hman = time.strftime(DateFmt, lt) - # t_ms = (ct - int(ct)) * 1000 - # above were various attempts at setting time string found in other - # libs; instead, let's keep it real: - t_out = datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S,%f")[:-3] - calling_fx = inspect.stack()[1][3] - - # FIXME: this entire module is a hack to override concept of prog logging - # written across multiple files (???), making diagnostics IMPOSSIBLE! - # Hoping to leverage ONAP logging libraries & standards when available - - # catch invalid log type - if _log_type < 1 or _log_type > 5: - msg = ("INVALID log type: %s " % _log_type) - _out_rec = ("%s|%s|%s|%s|%s|%s|%s|%s|%s|%s" - % ((t_out, calling_fx, "snmptrapd", unused, unused, unused, tds.SEV_TYPES[_sev], _error_code, unused, (msg + _msg)))) - tds.eelf_error_fd.write('%s\n' % str(_out_rec)) - return False - - if _sev >= tds.minimum_severity_to_log: - # log to appropriate eelf log (different files ??) - if _log_type == tds.LOG_TYPE_ERROR: - _out_rec = ('%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' - % ((t_out, calling_fx, "snmptrapd", unused, unused, unused, tds.SEV_TYPES[_sev], _error_code, unused, _msg))) - tds.eelf_error_fd.write('%s\n' % str(_out_rec)) - elif _log_type == tds.LOG_TYPE_AUDIT: - # log message in AUDIT format - _out_rec = ('%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' - % ((t_out, calling_fx, "snmptrapd", unused, unused, unused, tds.SEV_TYPES[_sev], _error_code, unused, _msg))) - tds.eelf_audit_fd.write('%s\n' % str(_out_rec)) - elif _log_type == tds.LOG_TYPE_METRICS: - # log message in METRICS format - _out_rec = ('%s|%s|%s|%s|%s|%s|%s|%s|%s|%s' - % ((t_out, calling_fx, "snmptrapd", unused, unused, unused, tds.SEV_TYPES[_sev], _error_code, unused, _msg))) - tds.eelf_metrics_fd.write('%s\n' % str(_out_rec)) - - # DEBUG *AND* others - there *MUST BE* a single time-sequenced log for diagnostics! - # FIXME: too much I/O !!! - # always write to debug; we need ONE logfile that has time-sequence full view !!! - # if (_log_type == tds.LOG_TYPE_DEBUG and _sev >= tds.current_min_sev_log_level) or (_log_type != tds.LOG_TYPE_DEBUG): - - # log message in DEBUG format - _out_rec = ("%s|%s|%s|%s|%s|%s|%s|%s|%s|%s" - % ((t_out, calling_fx, "snmptrapd", unused, unused, unused, tds.SEV_TYPES[_sev], _error_code, unused, _msg))) - tds.eelf_debug_fd.write('%s\n' % str(_out_rec)) - - return True - -# # # # # # # # # # # # # -# fx: stdout_logger -# # # # # # # # # # # # # - - -def stdout_logger(_msg): - """ - Log info/errors to stdout. This is done: - - for critical runtime issues - - :Parameters: - _msg - message to print - :Exceptions: - none - :Keywords: - log stdout - :Variables: - """ - - t_out = datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S,%f")[:-3] - # calling_fx = inspect.stack()[1][3] - - print('%s %s' % (t_out, _msg)) diff --git a/snmptrap/snmptrapd.py b/snmptrap/snmptrapd.py index 9cf828c..f435c30 100644 --- a/snmptrap/snmptrapd.py +++ b/snmptrap/snmptrapd.py @@ -218,7 +218,7 @@ def log_all_arriving_traps(): def log_published_messages(_post_data_enclosed): - # FIXME: should keep data dictionary of Fd's open, and reference those vs. + # FMDL: should keep data dictionary of Fd's open, and reference those vs. # repeatedly opening append-mode msg = "adding trap UUID %s to json log" % tds.trap_dict["uuid"] @@ -295,7 +295,6 @@ def post_dmaap(): timeout=tds.timeout_seconds) if http_resp.status_code == requests.codes.ok: - # msg = "%d trap(s) : %s successfully published - response from %s: %d %s" % (traps_since_last_publish, trap_uuids_in_buffer, ((c_config['streams_publishes']['sec_fault_unsecure']['dmaap_info']['topic_url']).split('/')[2][:-5]) ,http_resp.status_code, http_resp.text) msg = "%d trap(s) successfully published: %s" % ( tds.traps_since_last_publish, tds.trap_uuids_in_buffer) ecomp_logger(tds.LOG_TYPE_METRICS, tds.SEV_INFO, @@ -338,7 +337,7 @@ def post_dmaap(): % (tds.trap_uuids_in_buffer, tds.c_config['streams_publishes']['sec_fault_unsecure']['dmaap_info']['topic_url']) ecomp_logger(tds.LOG_TYPE_ERROR, tds.SEV_CRIT, tds.CODE_GENERAL, msg) - # FIXME: This currently tries, then logs error and trashes buffer if all dmaap attempts fail. Better way? + # FMDL: This currently tries, then logs error and trashes buffer if all dmaap attempts fail. Better way? tds.traps_since_last_publish = 0 tds.trap_uuids_in_buffer = "" tds.all_traps_str = "" @@ -353,9 +352,6 @@ def comm_string_rewrite_observer(snmpEngine, execpoint, variables, cbCtx): # match ALL community strings if re.match('.*', str(variables['communityName'])): - # msg = "Rewriting communityName '%s' from %s into 'public'" % (variables['communityName'], ':'.join([str(x) for x in - # variables['transportInformation'][1]])) - # ecomp_logger(eelf_debug_fd, eelf_debug_fd, tds.LOG_TYPE_DEBUG, tds.SEV_INFO, tds.CODE_GENERAL, msg) variables['communityName'] = variables['communityName'].clone('public') # # # # # # # # # # # # # # # # # # # @@ -428,7 +424,7 @@ def snmp_engine_observer_cb(snmp_engine, execpoint, variables, cbCtx): tds.trap_dict["community"] = "" tds.trap_dict["community len"] = 0 - # FIXME.CHECK_WITH_DOWNSTREAM_CONSUMERS: get rid of round for millisecond val + # FMDL.CHECK_WITH_DOWNSTREAM_CONSUMERS: get rid of round for millisecond val # epoch_second = int(round(time.time())) epoch_msecond = time.time() epoch_second = int(round(epoch_msecond)) @@ -465,6 +461,7 @@ def snmp_engine_observer_cb(snmp_engine, execpoint, variables, cbCtx): tds.trap_dict['trap category'] = ( tds.c_config['streams_publishes']['sec_fault_unsecure']['dmaap_info']['topic_url']).split('/')[-1] + return True # # # # # # # # # # # # # # # # # # # # fx: request_observer for community string rewrite @@ -505,8 +502,6 @@ def add_varbind_to_json(vb_idx, vb_oid, vb_type, vb_val): tds.all_vb_json_str = ', \"varbinds\": [' tds.first_varbind = False else: - # all_vb_json_str = ''.join([all_vb_json_str, ' ,']) - # all_vb_json_str = "%s ," % all_vb_json_str tds.all_vb_json_str = tds.all_vb_json_str + " ," _individual_vb_dict.clear() @@ -516,8 +511,6 @@ def add_varbind_to_json(vb_idx, vb_oid, vb_type, vb_val): _individual_vb_json_str = json.dumps(_individual_vb_dict) - # all_vb_json_str = "%s%s" % (all_vb_json_str, individual_vb_json_str) - # all_vb_json_str = ''.join([all_vb_json_str, individual_vb_json_str]) tds.all_vb_json_str = tds.all_vb_json_str + _individual_vb_json_str return True @@ -548,19 +541,9 @@ def notif_receiver_cb(snmp_engine, stateReference, contextEngineId, contextName, msg = "processing varbinds for %s" % (tds.trap_dict["uuid"]) ecomp_logger(tds.LOG_TYPE_DEBUG, tds.SEV_DETAILED, tds.CODE_GENERAL, msg) - # FIXME update reset location when batching publishes + # FMDL update reset location when batching publishes vb_idx = 0 - # For reference: - # - # print('\nvarBinds ==> %s' % (varBinds)) - # - # varBinds ==> [(ObjectName('1.3.6.1.2.1.1.3.0'), TimeTicks(1243175676)), - # (ObjectName('1.3.6.1.6.3.1.1.4.1.0'), ObjectIdentifier('1.3.6.1.4.1.74.2.46.12.1.1')), - # (ObjectName('1.3.6.1.4.1.74.2.46.12.1.1.1'), OctetString(b'ucsnmp heartbeat - ignore')), - # (ObjectName('1.3.6.1.4.1.74.2.46.12.1.1.2'), OctetString(b'Fri Aug 11 17:46:01 EDT 2017'))] - # - tds.all_vb_json_str = "" vb_idx = 0 tds.first_varbind = True @@ -570,29 +553,21 @@ def notif_receiver_cb(snmp_engine, stateReference, contextEngineId, contextName, add_varbind_to_json(vb_idx, vb_oid, vb_val.__class__.__name__, vb_val) vb_idx += 1 - # FIXME: DL back out first 2 varbinds for v2c notifs prior to publishing varbind count - # trap_dict["varbind count"] = vb_idx curr_trap_json_str = json.dumps(tds.trap_dict) # now have everything except varbinds in "curr_trap_json_str" # if varbinds present - which will almost always be the case - add all_vb_json_str to trap_json_message if vb_idx != 0: # close out vb array - # all_vb_json_str += "]" - # all_vb_json_str = ''.join([all_vb_json_str, ']']) tds.all_vb_json_str = tds.all_vb_json_str + ']' # remove last close bracket from curr_trap_json_str curr_trap_json_str = curr_trap_json_str[:-1] # add vb_json_str to payload - # curr_trap_json_str += all_vb_json_str - # curr_trap_json_str = ''.join([curr_trap_json_str, all_vb_json_str]) curr_trap_json_str = curr_trap_json_str + tds.all_vb_json_str # add last close brace back in - # curr_trap_json_str += "}" - # curr_trap_json_str = ''.join([curr_trap_json_str, '}']) curr_trap_json_str = curr_trap_json_str + '}' msg = "trap %s : %s" % (tds.trap_dict["uuid"], curr_trap_json_str) @@ -667,13 +642,6 @@ if __name__ == "__main__": prog_name, tds.c_config['snmptrap.title'], tds.c_config['snmptrap.version']) stdout_logger(msg) - # Avoid this unless needed for testing; it prints sensitive data to log - # - # msg = "Running config: " - # stdout_logger(msg) - # msg = json.dumps(c_config, sort_keys=False, indent=4) - # stdout_logger(msg) - # open various ecomp logs open_eelf_logs() @@ -722,7 +690,7 @@ if __name__ == "__main__": # # # # # # # # # # # # # UDP over IPv4 - # FIXME: add check for presense of ipv4_interface prior to attempting add OR just put entire thing in try/except clause + # FMDL: add check for presense of ipv4_interface prior to attempting add OR just put entire thing in try/except clause try: ipv4_interface = tds.c_config['protocols.ipv4_interface'] ipv4_port = tds.c_config['protocols.ipv4_port'] @@ -747,16 +715,8 @@ if __name__ == "__main__": ecomp_logger(tds.LOG_TYPE_ERROR, tds.SEV_WARN, tds.CODE_GENERAL, msg) - # UDP over IPv4, second listening interface/port example if you don't want to listen on all - # config.addTransport( - # snmp_engine, - # udp.domainName + (2,), - # udp.UdpTransport().openServerMode(('127.0.0.1', 2162)) - # ) - - # UDP over IPv6 - # FIXME: add check for presense of ipv6_interface prior to attempting add OR just put entire thing in try/except clause + # FMDL: add check for presense of ipv6_interface prior to attempting add OR just put entire thing in try/except clause try: ipv6_interface = tds.c_config['protocols.ipv6_interface'] ipv6_port = tds.c_config['protocols.ipv6_port'] diff --git a/snmptrap/snmptrapd.sh b/snmptrap/snmptrapd.sh index c4712f6..e8ef93e 100644 --- a/snmptrap/snmptrapd.sh +++ b/snmptrap/snmptrapd.sh @@ -21,7 +21,6 @@ # ECOMP is a trademark and service mark of AT&T Intellectual Property. # - # get to where we are supposed to be for startup cd /opt/app/snmptrap/bin @@ -37,8 +36,6 @@ export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-bundle.crt # PYTHONUNBUFFERED: # set PYTHONUNBUFFERED to a non-empty string to avoid output buffering; # comment out for runtime environments/better performance! -# FIXME: This does *NOT* appear to work as desired, so -# we've added "-u" to command line below # export PYTHONUNBUFFERED="True" # set location of config broker server overrride IF NEEDED @@ -47,8 +44,12 @@ export CBS_SIM_JSON=../etc/snmptrapd.json # want tracing? Use this: # python -m trace --trackcalls snmptrapd.py -v + # want verbose logging? Use this: -# python -u snmptrapd.py -v +# python snmptrapd.py -v + # standard startup? Use this: # python snmptrapd.py + +# unbuffered io for logs and verbose logging? Use this: python -u snmptrapd.py -v diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index d78ed5e..0000000 --- a/tests/conftest.py +++ /dev/null @@ -1,12 +0,0 @@ -import pytest - -@pytest.fixture - -def test_var(_var_name): - - try: - _var_name - except NameError: - return False - else: - return True diff --git a/tests/test_snmptrapd.py b/tests/test_snmptrapd.py index a361bfc..d02b4f7 100644 --- a/tests/test_snmptrapd.py +++ b/tests/test_snmptrapd.py @@ -8,7 +8,6 @@ import trapd_settings as tds import trapd_http_session import trapd_runtime_pid import trapd_io -import trapd_logging import trapd_get_cbs_config class test_snmptrapd(unittest.TestCase): @@ -52,6 +51,23 @@ class test_snmptrapd(unittest.TestCase): result = snmptrapd.load_all_configs(0, 1) self.assertEqual(result, True) + def test_load_all_configs_signal(self): + """ + Test load of all configs via runtime signal + """ + + # init vars + tds.init() + + # request load of CBS data + os.environ.update(CBS_SIM_JSON='/tmp/opt/app/snmptrap/etc/snmptrapd.json') + result = trapd_get_cbs_config.get_cbs_config() + self.assertEqual(result, True) + + # request load of CBS data + result = snmptrapd.load_all_configs(1, 1) + self.assertEqual(result, True) + def test_log_all_arriving_traps(self): """ Test logging of traps @@ -85,12 +101,65 @@ class test_snmptrapd(unittest.TestCase): tds.json_traps_fd = trapd_io.open_file(tds.json_traps_filename) msg = ("published traps logged to: %s" % tds.json_traps_filename) trapd_io.stdout_logger(msg) - trapd_logging.ecomp_logger(tds.LOG_TYPE_DEBUG, tds.SEV_INFO, tds.CODE_GENERAL, msg) + trapd_io.ecomp_logger(tds.LOG_TYPE_DEBUG, tds.SEV_INFO, tds.CODE_GENERAL, msg) # don't open files, but try to log - should raise exception with pytest.raises(Exception) as pytest_wrapped_exception: result = snmptrapd.log_all_arriving_traps() assert pytest_wrapped_exception.type == AttributeError + def test_log_all_incorrect_log_type(self): + """ + Test logging of traps + """ + + # init vars + tds.init() + + # request load of CBS data + os.environ.update(CBS_SIM_JSON='/tmp/opt/app/snmptrap/etc/snmptrapd.json') + trapd_get_cbs_config.get_cbs_config() + + # open eelf logs + trapd_io.open_eelf_logs() + + def test_post_dmaap(self): + """ + Test publish of traps + """ + + # init vars + tds.init() + + # request load of CBS data + os.environ.update(CBS_SIM_JSON='/tmp/opt/app/snmptrap/etc/snmptrapd.json') + result = trapd_get_cbs_config.get_cbs_config() + + # set last day to current + tds.last_day = datetime.datetime.now().day + + # trap dict for publish + tds.trap_dict = {'uuid': '06f6e91c-3236-11e8-9953-005056865aac', 'agent address': '1.2.3.4', 'agent name': 'test-agent.nodomain.com', 'cambria.partition': 'test-agent.nodomain.com', 'community': '', 'community len': 0, 'epoch_serno': 15222068260000, 'protocol version': 'v2c', 'time received': 1522206826.2938566, 'trap category': 'ONAP-COLLECTOR-SNMPTRAP', 'sysUptime': '218567736', 'notify OID': '1.3.6.1.4.1.9999.9.9.999', 'notify OID len': 10} + + # open eelf logs + trapd_io.open_eelf_logs() + + # open trap logs + tds.arriving_traps_filename = tds.c_config['files.runtime_base_dir'] + "/" + \ + tds.c_config['files.log_dir'] + "/" + \ + (tds.c_config['files.arriving_traps_log']) + tds.arriving_traps_fd = trapd_io.open_file(tds.arriving_traps_filename) + + # name and open json trap log + tds.json_traps_filename = tds.c_config['files.runtime_base_dir'] + "/" + tds.c_config['files.log_dir'] + "/" + "DMAAP_" + ( + tds.c_config['streams_publishes']['sec_fault_unsecure']['dmaap_info']['topic_url'].split('/')[-1]) + ".json" + tds.json_traps_fd = trapd_io.open_file(tds.json_traps_filename) + msg = ("published traps logged to: %s" % tds.json_traps_filename) + trapd_io.stdout_logger(msg) + trapd_io.ecomp_logger(tds.LOG_TYPE_DEBUG, tds.SEV_INFO, tds.CODE_GENERAL, msg) + + result = snmptrapd.post_dmaap() + print("result from post_dmaap -> %s" % result) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_trapd_io.py b/tests/test_trapd_io.py new file mode 100644 index 0000000..cf45730 --- /dev/null +++ b/tests/test_trapd_io.py @@ -0,0 +1,139 @@ +import os +import pytest +import unittest +import snmptrapd +import datetime +import json +import trapd_settings as tds +import trapd_runtime_pid +import trapd_io + +class test_trapd_io(unittest.TestCase): + """ + Test the save_pid mod + """ + tds.c_config = json.loads("{ \"snmptrap.version\": \"1.3.0\", \"snmptrap.title\": \"ONAP SNMP Trap Receiver\" , \"protocols.transport\": \"udp\", \"protocols.ipv4_interface\": \"0.0.0.0\", \"protocols.ipv4_port\": 6164, \"protocols.ipv6_interface\": \"::1\", \"protocols.ipv6_port\": 6164, \"cache.dns_cache_ttl_seconds\": 60, \"publisher.http_timeout_milliseconds\": 1500, \"publisher.http_retries\": 3, \"publisher.http_milliseconds_between_retries\": 750, \"publisher.http_primary_publisher\": \"true\", \"publisher.http_peer_publisher\": \"unavailable\", \"publisher.max_traps_between_publishes\": 10, \"publisher.max_milliseconds_between_publishes\": 10000, \"streams_publishes\": { \"sec_measurement\": { \"type\": \"message_router\", \"aaf_password\": \"aaf_password\", \"dmaap_info\": { \"location\": \"mtl5\", \"client_id\": \"111111\", \"client_role\": \"com.att.dcae.member\", \"topic_url\": null }, \"aaf_username\": \"aaf_username\" }, \"sec_fault_unsecure\": { \"type\": \"message_router\", \"aaf_password\": null, \"dmaap_info\": { \"location\": \"mtl5\", \"client_id\": null, \"client_role\": null, \"topic_url\": \"http://uebsb93kcdc.it.att.com:3904/events/ONAP-COLLECTOR-SNMPTRAP\" }, \"aaf_username\": null } }, \"files.runtime_base_dir\": \"/tmp/opt/app/snmptrap\", \"files.log_dir\": \"logs\", \"files.data_dir\": \"data\", \"files.pid_dir\": \"/tmp/opt/app/snmptrap/tmp\", \"files.arriving_traps_log\": \"snmptrapd_arriving_traps.log\", \"files.snmptrapd_diag\": \"snmptrapd_prog_diag.log\", \"files.traps_stats_log\": \"snmptrapd_stats.csv\", \"files.perm_status_file\": \"snmptrapd_status.log\", \"files.eelf_base_dir\": \"/tmp/opt/app/snmptrap/logs\", \"files.eelf_error\": \"error.log\", \"files.eelf_debug\": \"debug.log\", \"files.eelf_audit\": \"audit.log\", \"files.eelf_metrics\": \"metrics.log\", \"files.roll_frequency\": \"hour\", \"files.minimum_severity_to_log\": 2, \"trap_def.1.trap_oid\" : \".1.3.6.1.4.1.74.2.46.12.1.1\", \"trap_def.1.trap_category\": \"DCAE-SNMP-TRAPS\", \"trap_def.2.trap_oid\" : \"*\", \"trap_def.2.trap_category\": \"DCAE-SNMP-TRAPS\", \"stormwatch.1.stormwatch_oid\" : \".1.3.6.1.4.1.74.2.46.12.1.1\", \"stormwatch.1.low_water_rearm_per_minute\" : \"5\", \"stormwatch.1.high_water_arm_per_minute\" : \"100\", \"stormwatch.2.stormwatch_oid\" : \".1.3.6.1.4.1.74.2.46.12.1.2\", \"stormwatch.2.low_water_rearm_per_minute\" : \"2\", \"stormwatch.2.high_water_arm_per_minute\" : \"200\", \"stormwatch.3.stormwatch_oid\" : \".1.3.6.1.4.1.74.2.46.12.1.2\", \"stormwatch.3.low_water_rearm_per_minute\" : \"2\", \"stormwatch.3.high_water_arm_per_minute\" : \"200\" }") + + + def test_open_eelf_error_file(self): + """ + Test bad error file location + """ + + # open eelf error logs + tds.c_config['files.eelf_error']="/bad_dir/error.log" + + # try to open file in non-existent dir + with pytest.raises(SystemExit) as pytest_wrapped_exception: + result = trapd_io.open_eelf_logs() + assert pytest_wrapped_exception.type == SystemExit + + def test_open_eelf_debug_file(self): + """ + Test bad debug file location + """ + + # open eelf debug logs + tds.c_config['files.eelf_debug']="/bad_dir/debug.log" + + # try to open file in non-existent dir + with pytest.raises(SystemExit) as pytest_wrapped_exception: + result = trapd_io.open_eelf_logs() + assert pytest_wrapped_exception.type == SystemExit + + def test_open_eelf_audit_file(self): + """ + Test bad audit file location + """ + + # open eelf debug logs + tds.c_config['files.eelf_audit']="/bad_dir/audit.log" + + # try to open file in non-existent dir + with pytest.raises(SystemExit) as pytest_wrapped_exception: + result = trapd_io.open_eelf_logs() + assert pytest_wrapped_exception.type == SystemExit + + def test_open_eelf_metrics_file(self): + """ + Test bad metrics file location + """ + + # open eelf debug logs + tds.c_config['files.eelf_metrics']="/bad_dir/metrics.log" + + # try to open file in non-existent dir + with pytest.raises(SystemExit) as pytest_wrapped_exception: + result = trapd_io.open_eelf_logs() + assert pytest_wrapped_exception.type == SystemExit + + def test_roll_all_logs(self): + """ + Test roll of logs when not open + """ + + # try to roll logs when not open + with pytest.raises(SystemExit) as pytest_wrapped_exception: + result = trapd_io.roll_all_logs() + assert pytest_wrapped_exception.type == SystemExit + + def test_roll_file(self): + """ + Test roll of individual file when not present + """ + + # try to roll logs when not open + result = trapd_io.roll_file("/file/not/present") + self.assertEqual(result, False) + + def test_open_file_exists(self): + """ + Test file open in directory present + """ + + # create copy of snmptrapd.json for pytest + test_file = "/tmp/snmptrap_pytest" + + # try to roll logs when not open + result = trapd_io.open_file(test_file) + compare = str(result).startswith("<_io.TextIOWrapper name=") + self.assertEqual(compare, True) + + def test_open_file_exists_does_not_exist(self): + """ + Test file open in directory present + """ + + # create copy of snmptrapd.json for pytest + test_file = "/tmp/no_such_dir/snmptrap_pytest" + + # try to open file when dir not present + with pytest.raises(SystemExit) as pytest_wrapped_exception: + result = trapd_io.open_file(test_file) + assert pytest_wrapped_exception.type == SystemExit + + def test_close_file_exists(self): + """ + Test closing a file that's present + """ + + # create copy of snmptrapd.json for pytest + test_file_name = "/tmp/snmptrap_pytest" + test_file = trapd_io.open_file(test_file_name) + + # close active file + result = trapd_io.close_file(test_file, test_file_name) + self.assertEqual(result, True) + + def test_close_file_does_not_exists(self): + """ + Test closing non-existent file + """ + + # try to roll logs when not open + result = trapd_io.close_file(None, None) + self.assertEqual(result, False) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_trapd_runtime_pid.py b/tests/test_trapd_runtime_pid.py index c48ef34..b9010e1 100644 --- a/tests/test_trapd_runtime_pid.py +++ b/tests/test_trapd_runtime_pid.py @@ -1,6 +1,7 @@ import pytest import unittest import trapd_runtime_pid +import trapd_io class test_save_pid(unittest.TestCase): """ @@ -43,5 +44,6 @@ class test_rm_pid(unittest.TestCase): result = trapd_runtime_pid.rm_pid('/tmp/snmptrap_test_pid_file_9999') self.assertEqual(result, False) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_trapd_settings.py b/tests/test_trapd_settings.py index ab64426..17b20a8 100644 --- a/tests/test_trapd_settings.py +++ b/tests/test_trapd_settings.py @@ -6,7 +6,6 @@ pid_file="/tmp/test_pid_file" pid_file_dne="/tmp/test_pid_file_NOT" import trapd_settings as tds -from conftest import test_var class test_cleanup_and_exit(unittest.TestCase): """ -- cgit 1.2.3-korg