diff options
-rw-r--r-- | Dockerfile | 2 | ||||
-rw-r--r-- | coverage.xml | 695 | ||||
-rw-r--r-- | pom.xml | 3 | ||||
-rw-r--r-- | setup.py | 14 | ||||
-rw-r--r-- | snmptrap/__init__.py | 21 | ||||
-rw-r--r-- | snmptrap/mod/__init__.py | 21 | ||||
-rw-r--r-- | snmptrap/mod/trapd_exit.py (renamed from bin/mod/trapd_exit.py) | 4 | ||||
-rw-r--r-- | snmptrap/mod/trapd_get_cbs_config.py (renamed from bin/mod/trapd_get_cbs_config.py) | 8 | ||||
-rw-r--r-- | snmptrap/mod/trapd_http_session.py (renamed from bin/mod/trapd_http_session.py) | 0 | ||||
-rw-r--r-- | snmptrap/mod/trapd_io.py (renamed from bin/mod/trapd_file_utils.py) | 173 | ||||
-rw-r--r-- | snmptrap/mod/trapd_logging.py (renamed from bin/mod/trapd_logging.py) | 0 | ||||
-rw-r--r-- | snmptrap/mod/trapd_runtime_pid.py (renamed from bin/mod/trapd_runtime_pid.py) | 0 | ||||
-rw-r--r-- | snmptrap/mod/trapd_settings.py (renamed from bin/mod/trapd_settings.py) | 0 | ||||
-rw-r--r-- | snmptrap/snmptrapd.py (renamed from bin/snmptrapd.py) | 355 | ||||
-rw-r--r--[-rwxr-xr-x] | snmptrap/snmptrapd.sh (renamed from bin/snmptrapd.sh) | 0 | ||||
-rw-r--r-- | tests/__init__.py | 21 | ||||
-rw-r--r-- | tests/_test_trapd_get_cbs_config.py | 44 | ||||
-rw-r--r-- | tests/conftest.py | 12 | ||||
-rw-r--r-- | tests/snmp.setup.py (renamed from tests/setup.py) | 0 | ||||
-rw-r--r-- | tests/test_snmptrapd.py | 100 | ||||
-rw-r--r-- | tests/test_trapd_get_cbs_config.py | 61 | ||||
-rw-r--r-- | tests/test_trapd_settings.py | 73 | ||||
-rw-r--r-- | tests/tox.ini | 15 | ||||
-rw-r--r-- | tox.ini | 15 |
24 files changed, 1364 insertions, 273 deletions
@@ -12,7 +12,7 @@ WORKDIR ${APPDIR} EXPOSE 162:162/udp # Copy the current directory contents into the container at ${APPDIR} -COPY ./bin/ ./bin/ +COPY ./snmptrap/ ./bin/ COPY ./etc/ ./etc/ COPY requirements.txt ./ RUN pip install -r requirements.txt diff --git a/coverage.xml b/coverage.xml new file mode 100644 index 0000000..96da2c6 --- /dev/null +++ b/coverage.xml @@ -0,0 +1,695 @@ +<?xml version="1.0" ?> +<coverage branch-rate="0" branches-covered="0" branches-valid="0" complexity="0" line-rate="0.07154" lines-covered="45" lines-valid="629" timestamp="1522110803348" version="4.5.1"> + <!-- Generated by coverage.py: https://coverage.readthedocs.io --> + <!-- Based on https://raw.githubusercontent.com/cobertura/web/master/htdocs/xml/coverage-04.dtd --> + <sources> + <source>C:\Users\vv770d\git\onap\snmptrap\snmptrap</source> + </sources> + <packages> + <package branch-rate="0" complexity="0" line-rate="0" name="."> + <classes> + <class branch-rate="0" complexity="0" filename="__init__.py" line-rate="1" name="__init__.py"> + <methods/> + <lines/> + </class> + <class branch-rate="0" complexity="0" filename="snmptrapd.py" line-rate="0" name="snmptrapd.py"> + <methods/> + <lines> + <line hits="0" number="21"/> + <line hits="0" number="36"/> + <line hits="0" number="39"/> + <line hits="0" number="40"/> + <line hits="0" number="41"/> + <line hits="0" number="42"/> + <line hits="0" number="43"/> + <line hits="0" number="44"/> + <line hits="0" number="45"/> + <line hits="0" number="46"/> + <line hits="0" number="47"/> + <line hits="0" number="48"/> + <line hits="0" number="49"/> + <line hits="0" number="50"/> + <line hits="0" number="51"/> + <line hits="0" number="52"/> + <line hits="0" number="53"/> + <line hits="0" number="54"/> + <line hits="0" number="55"/> + <line hits="0" number="56"/> + <line hits="0" number="57"/> + <line hits="0" number="58"/> + <line hits="0" number="59"/> + <line hits="0" number="60"/> + <line hits="0" number="63"/> + <line hits="0" number="64"/> + <line hits="0" number="66"/> + <line hits="0" number="67"/> + <line hits="0" number="70"/> + <line hits="0" number="71"/> + <line hits="0" number="72"/> + <line hits="0" number="73"/> + <line hits="0" number="74"/> + <line hits="0" number="76"/> + <line hits="0" number="77"/> + <line hits="0" number="79"/> + <line hits="0" number="80"/> + <line hits="0" number="87"/> + <line hits="0" number="98"/> + <line hits="0" number="99"/> + <line hits="0" number="100"/> + <line hits="0" number="108"/> + <line hits="0" number="125"/> + <line hits="0" number="126"/> + <line hits="0" number="128"/> + <line hits="0" number="133"/> + <line hits="0" number="134"/> + <line hits="0" number="136"/> + <line hits="0" number="137"/> + <line hits="0" number="138"/> + <line hits="0" number="139"/> + <line hits="0" number="140"/> + <line hits="0" number="141"/> + <line hits="0" number="145"/> + <line hits="0" number="146"/> + <line hits="0" number="147"/> + <line hits="0" number="148"/> + <line hits="0" number="156"/> + <line hits="0" number="159"/> + <line hits="0" number="160"/> + <line hits="0" number="161"/> + <line hits="0" number="162"/> + <line hits="0" number="163"/> + <line hits="0" number="164"/> + <line hits="0" number="165"/> + <line hits="0" number="166"/> + <line hits="0" number="167"/> + <line hits="0" number="168"/> + <line hits="0" number="171"/> + <line hits="0" number="172"/> + <line hits="0" number="173"/> + <line hits="0" number="174"/> + <line hits="0" number="177"/> + <line hits="0" number="181"/> + <line hits="0" number="198"/> + <line hits="0" number="199"/> + <line hits="0" number="201"/> + <line hits="0" number="209"/> + <line hits="0" number="214"/> + <line hits="0" number="215"/> + <line hits="0" number="217"/> + <line hits="0" number="218"/> + <line hits="0" number="219"/> + <line hits="0" number="221"/> + <line hits="0" number="223"/> + <line hits="0" number="224"/> + <line hits="0" number="226"/> + <line hits="0" number="234"/> + <line hits="0" number="245"/> + <line hits="0" number="247"/> + <line hits="0" number="248"/> + <line hits="0" number="249"/> + <line hits="0" number="251"/> + <line hits="0" number="254"/> + <line hits="0" number="255"/> + <line hits="0" number="258"/> + <line hits="0" number="260"/> + <line hits="0" number="261"/> + <line hits="0" number="263"/> + <line hits="0" number="264"/> + <line hits="0" number="266"/> + <line hits="0" number="267"/> + <line hits="0" number="268"/> + <line hits="0" number="269"/> + <line hits="0" number="271"/> + <line hits="0" number="273"/> + <line hits="0" number="277"/> + <line hits="0" number="279"/> + <line hits="0" number="281"/> + <line hits="0" number="287"/> + <line hits="0" number="289"/> + <line hits="0" number="291"/> + <line hits="0" number="293"/> + <line hits="0" number="294"/> + <line hits="0" number="295"/> + <line hits="0" number="296"/> + <line hits="0" number="298"/> + <line hits="0" number="300"/> + <line hits="0" number="303"/> + <line hits="0" number="304"/> + <line hits="0" number="306"/> + <line hits="0" number="309"/> + <line hits="0" number="310"/> + <line hits="0" number="312"/> + <line hits="0" number="315"/> + <line hits="0" number="317"/> + <line hits="0" number="318"/> + <line hits="0" number="320"/> + <line hits="0" number="322"/> + <line hits="0" number="324"/> + <line hits="0" number="326"/> + <line hits="0" number="327"/> + <line hits="0" number="329"/> + <line hits="0" number="332"/> + <line hits="0" number="333"/> + <line hits="0" number="334"/> + <line hits="0" number="335"/> + <line hits="0" number="342"/> + <line hits="0" number="345"/> + <line hits="0" number="349"/> + <line hits="0" number="357"/> + <line hits="0" number="378"/> + <line hits="0" number="381"/> + <line hits="0" number="384"/> + <line hits="0" number="385"/> + <line hits="0" number="387"/> + <line hits="0" number="389"/> + <line hits="0" number="391"/> + <line hits="0" number="392"/> + <line hits="0" number="393"/> + <line hits="0" number="396"/> + <line hits="0" number="397"/> + <line hits="0" number="398"/> + <line hits="0" number="399"/> + <line hits="0" number="401"/> + <line hits="0" number="402"/> + <line hits="0" number="403"/> + <line hits="0" number="404"/> + <line hits="0" number="406"/> + <line hits="0" number="408"/> + <line hits="0" number="409"/> + <line hits="0" number="411"/> + <line hits="0" number="413"/> + <line hits="0" number="416"/> + <line hits="0" number="418"/> + <line hits="0" number="419"/> + <line hits="0" number="423"/> + <line hits="0" number="424"/> + <line hits="0" number="425"/> + <line hits="0" number="426"/> + <line hits="0" number="428"/> + <line hits="0" number="429"/> + <line hits="0" number="430"/> + <line hits="0" number="431"/> + <line hits="0" number="434"/> + <line hits="0" number="435"/> + <line hits="0" number="436"/> + <line hits="0" number="438"/> + <line hits="0" number="439"/> + <line hits="0" number="441"/> + <line hits="0" number="442"/> + <line hits="0" number="444"/> + <line hits="0" number="446"/> + <line hits="0" number="447"/> + <line hits="0" number="448"/> + <line hits="0" number="449"/> + <line hits="0" number="451"/> + <line hits="0" number="452"/> + <line hits="0" number="454"/> + <line hits="0" number="455"/> + <line hits="0" number="462"/> + <line hits="0" number="480"/> + <line hits="0" number="482"/> + <line hits="0" number="485"/> + <line hits="0" number="486"/> + <line hits="0" number="487"/> + <line hits="0" number="489"/> + <line hits="0" number="490"/> + <line hits="0" number="491"/> + <line hits="0" number="493"/> + <line hits="0" number="494"/> + <line hits="0" number="495"/> + <line hits="0" number="496"/> + <line hits="0" number="500"/> + <line hits="0" number="502"/> + <line hits="0" number="503"/> + <line hits="0" number="504"/> + <line hits="0" number="505"/> + <line hits="0" number="507"/> + <line hits="0" number="511"/> + <line hits="0" number="512"/> + <line hits="0" number="517"/> + <line hits="0" number="538"/> + <line hits="0" number="539"/> + <line hits="0" number="542"/> + <line hits="0" number="554"/> + <line hits="0" number="555"/> + <line hits="0" number="556"/> + <line hits="0" number="559"/> + <line hits="0" number="560"/> + <line hits="0" number="561"/> + <line hits="0" number="565"/> + <line hits="0" number="569"/> + <line hits="0" number="573"/> + <line hits="0" number="576"/> + <line hits="0" number="581"/> + <line hits="0" number="586"/> + <line hits="0" number="588"/> + <line hits="0" number="589"/> + <line hits="0" number="592"/> + <line hits="0" number="593"/> + <line hits="0" number="595"/> + <line hits="0" number="596"/> + <line hits="0" number="597"/> + <line hits="0" number="598"/> + <line hits="0" number="599"/> + <line hits="0" number="600"/> + <line hits="0" number="602"/> + <line hits="0" number="604"/> + <line hits="0" number="607"/> + <line hits="0" number="610"/> + <line hits="0" number="611"/> + <line hits="0" number="613"/> + <line hits="0" number="615"/> + <line hits="0" number="616"/> + <line hits="0" number="617"/> + <line hits="0" number="618"/> + <line hits="0" number="620"/> + <line hits="0" number="627"/> + <line hits="0" number="629"/> + <line hits="0" number="631"/> + <line hits="0" number="635"/> + <line hits="0" number="638"/> + <line hits="0" number="639"/> + <line hits="0" number="642"/> + <line hits="0" number="643"/> + <line hits="0" number="646"/> + <line hits="0" number="649"/> + <line hits="0" number="652"/> + <line hits="0" number="653"/> + <line hits="0" number="655"/> + <line hits="0" number="665"/> + <line hits="0" number="668"/> + <line hits="0" number="669"/> + <line hits="0" number="670"/> + <line hits="0" number="671"/> + <line hits="0" number="674"/> + <line hits="0" number="677"/> + <line hits="0" number="678"/> + <line hits="0" number="679"/> + <line hits="0" number="680"/> + <line hits="0" number="683"/> + <line hits="0" number="685"/> + <line hits="0" number="686"/> + <line hits="0" number="687"/> + <line hits="0" number="688"/> + <line hits="0" number="691"/> + <line hits="0" number="694"/> + <line hits="0" number="696"/> + <line hits="0" number="697"/> + <line hits="0" number="698"/> + <line hits="0" number="701"/> + <line hits="0" number="705"/> + <line hits="0" number="713"/> + <line hits="0" number="714"/> + <line hits="0" number="715"/> + <line hits="0" number="717"/> + <line hits="0" number="718"/> + <line hits="0" number="724"/> + <line hits="0" number="725"/> + <line hits="0" number="727"/> + <line hits="0" number="728"/> + <line hits="0" number="729"/> + <line hits="0" number="731"/> + <line hits="0" number="732"/> + <line hits="0" number="733"/> + <line hits="0" number="734"/> + <line hits="0" number="747"/> + <line hits="0" number="748"/> + <line hits="0" number="749"/> + <line hits="0" number="751"/> + <line hits="0" number="752"/> + <line hits="0" number="758"/> + <line hits="0" number="759"/> + <line hits="0" number="761"/> + <line hits="0" number="762"/> + <line hits="0" number="763"/> + <line hits="0" number="765"/> + <line hits="0" number="766"/> + <line hits="0" number="767"/> + <line hits="0" number="768"/> + <line hits="0" number="778"/> + <line hits="0" number="781"/> + <line hits="0" number="787"/> + <line hits="0" number="794"/> + <line hits="0" number="796"/> + <line hits="0" number="799"/> + <line hits="0" number="800"/> + <line hits="0" number="801"/> + <line hits="0" number="802"/> + <line hits="0" number="803"/> + <line hits="0" number="804"/> + </lines> + </class> + </classes> + </package> + <package branch-rate="0" complexity="0" line-rate="0.1466" name="mod"> + <classes> + <class branch-rate="0" complexity="0" filename="mod/__init__.py" line-rate="1" name="__init__.py"> + <methods/> + <lines/> + </class> + <class branch-rate="0" complexity="0" filename="mod/trapd_exit.py" line-rate="1" name="trapd_exit.py"> + <methods/> + <lines> + <line hits="1" number="21"/> + <line hits="1" number="26"/> + <line hits="1" number="28"/> + <line hits="1" number="29"/> + <line hits="1" number="30"/> + <line hits="1" number="31"/> + <line hits="1" number="33"/> + <line hits="1" number="41"/> + <line hits="1" number="59"/> + <line hits="1" number="61"/> + <line hits="1" number="62"/> + <line hits="1" number="63"/> + </lines> + </class> + <class branch-rate="0" complexity="0" filename="mod/trapd_file_utils.py" line-rate="0" name="trapd_file_utils.py"> + <methods/> + <lines> + <line hits="0" number="21"/> + <line hits="0" number="24"/> + <line hits="0" number="27"/> + <line hits="0" number="28"/> + <line hits="0" number="29"/> + <line hits="0" number="30"/> + <line hits="0" number="31"/> + <line hits="0" number="32"/> + <line hits="0" number="33"/> + <line hits="0" number="34"/> + <line hits="0" number="35"/> + <line hits="0" number="36"/> + <line hits="0" number="37"/> + <line hits="0" number="38"/> + <line hits="0" number="41"/> + <line hits="0" number="42"/> + <line hits="0" number="43"/> + <line hits="0" number="45"/> + <line hits="0" number="53"/> + <line hits="0" number="61"/> + <line hits="0" number="63"/> + <line hits="0" number="65"/> + <line hits="0" number="67"/> + <line hits="0" number="68"/> + <line hits="0" number="69"/> + <line hits="0" number="70"/> + <line hits="0" number="72"/> + <line hits="0" number="73"/> + <line hits="0" number="74"/> + <line hits="0" number="75"/> + <line hits="0" number="77"/> + <line hits="0" number="78"/> + <line hits="0" number="79"/> + <line hits="0" number="80"/> + <line hits="0" number="81"/> + <line hits="0" number="84"/> + <line hits="0" number="86"/> + <line hits="0" number="87"/> + <line hits="0" number="88"/> + <line hits="0" number="89"/> + <line hits="0" number="91"/> + <line hits="0" number="92"/> + <line hits="0" number="95"/> + <line hits="0" number="97"/> + <line hits="0" number="98"/> + <line hits="0" number="99"/> + <line hits="0" number="100"/> + <line hits="0" number="102"/> + <line hits="0" number="103"/> + <line hits="0" number="112"/> + <line hits="0" number="117"/> + <line hits="0" number="120"/> + <line hits="0" number="122"/> + <line hits="0" number="124"/> + <line hits="0" number="125"/> + <line hits="0" number="126"/> + <line hits="0" number="127"/> + <line hits="0" number="129"/> + <line hits="0" number="130"/> + <line hits="0" number="132"/> + <line hits="0" number="134"/> + <line hits="0" number="135"/> + <line hits="0" number="136"/> + <line hits="0" number="137"/> + <line hits="0" number="139"/> + <line hits="0" number="140"/> + <line hits="0" number="142"/> + <line hits="0" number="143"/> + <line hits="0" number="144"/> + <line hits="0" number="145"/> + <line hits="0" number="146"/> + <line hits="0" number="148"/> + <line hits="0" number="149"/> + <line hits="0" number="151"/> + <line hits="0" number="152"/> + <line hits="0" number="153"/> + <line hits="0" number="154"/> + <line hits="0" number="155"/> + <line hits="0" number="157"/> + <line hits="0" number="164"/> + <line hits="0" number="169"/> + <line hits="0" number="173"/> + <line hits="0" number="176"/> + <line hits="0" number="177"/> + <line hits="0" number="178"/> + <line hits="0" number="179"/> + <line hits="0" number="180"/> + <line hits="0" number="183"/> + <line hits="0" number="192"/> + <line hits="0" number="197"/> + <line hits="0" number="200"/> + <line hits="0" number="201"/> + <line hits="0" number="202"/> + <line hits="0" number="203"/> + <line hits="0" number="204"/> + <line hits="0" number="205"/> + <line hits="0" number="211"/> + <line hits="0" number="216"/> + <line hits="0" number="218"/> + <line hits="0" number="219"/> + <line hits="0" number="220"/> + <line hits="0" number="221"/> + <line hits="0" number="222"/> + <line hits="0" number="224"/> + <line hits="0" number="225"/> + </lines> + </class> + <class branch-rate="0" complexity="0" filename="mod/trapd_get_cbs_config.py" line-rate="0" name="trapd_get_cbs_config.py"> + <methods/> + <lines> + <line hits="0" number="21"/> + <line hits="0" number="27"/> + <line hits="0" number="29"/> + <line hits="0" number="30"/> + <line hits="0" number="31"/> + <line hits="0" number="32"/> + <line hits="0" number="33"/> + <line hits="0" number="34"/> + <line hits="0" number="35"/> + <line hits="0" number="37"/> + <line hits="0" number="38"/> + <line hits="0" number="39"/> + <line hits="0" number="40"/> + <line hits="0" number="42"/> + <line hits="0" number="50"/> + <line hits="0" number="58"/> + <line hits="0" number="61"/> + <line hits="0" number="62"/> + <line hits="0" number="63"/> + <line hits="0" number="64"/> + <line hits="0" number="65"/> + <line hits="0" number="68"/> + <line hits="0" number="69"/> + <line hits="0" number="70"/> + <line hits="0" number="72"/> + <line hits="0" number="73"/> + <line hits="0" number="74"/> + <line hits="0" number="75"/> + <line hits="0" number="76"/> + <line hits="0" number="77"/> + <line hits="0" number="79"/> + <line hits="0" number="80"/> + <line hits="0" number="81"/> + <line hits="0" number="82"/> + <line hits="0" number="84"/> + <line hits="0" number="86"/> + <line hits="0" number="87"/> + <line hits="0" number="88"/> + <line hits="0" number="89"/> + <line hits="0" number="90"/> + <line hits="0" number="92"/> + <line hits="0" number="93"/> + <line hits="0" number="96"/> + <line hits="0" number="97"/> + <line hits="0" number="98"/> + <line hits="0" number="99"/> + <line hits="0" number="102"/> + <line hits="0" number="103"/> + <line hits="0" number="104"/> + <line hits="0" number="105"/> + <line hits="0" number="108"/> + <line hits="0" number="109"/> + <line hits="0" number="110"/> + <line hits="0" number="111"/> + <line hits="0" number="113"/> + <line hits="0" number="114"/> + <line hits="0" number="115"/> + <line hits="0" number="116"/> + <line hits="0" number="118"/> + </lines> + </class> + <class branch-rate="0" complexity="0" filename="mod/trapd_http_session.py" line-rate="0.8333" name="trapd_http_session.py"> + <methods/> + <lines> + <line hits="1" number="21"/> + <line hits="1" number="26"/> + <line hits="1" number="28"/> + <line hits="1" number="29"/> + <line hits="1" number="30"/> + <line hits="1" number="32"/> + <line hits="1" number="38"/> + <line hits="1" number="53"/> + <line hits="1" number="54"/> + <line hits="0" number="55"/> + <line hits="0" number="56"/> + <line hits="1" number="58"/> + </lines> + </class> + <class branch-rate="0" complexity="0" filename="mod/trapd_logging.py" line-rate="0" name="trapd_logging.py"> + <methods/> + <lines> + <line hits="0" number="21"/> + <line hits="0" number="24"/> + <line hits="0" number="27"/> + <line hits="0" number="28"/> + <line hits="0" number="29"/> + <line hits="0" number="30"/> + <line hits="0" number="31"/> + <line hits="0" number="32"/> + <line hits="0" number="33"/> + <line hits="0" number="34"/> + <line hits="0" number="35"/> + <line hits="0" number="36"/> + <line hits="0" number="37"/> + <line hits="0" number="38"/> + <line hits="0" number="40"/> + <line hits="0" number="42"/> + <line hits="0" number="50"/> + <line hits="0" number="124"/> + <line hits="0" number="132"/> + <line hits="0" number="133"/> + <line hits="0" number="140"/> + <line hits="0" number="141"/> + <line hits="0" number="142"/> + <line hits="0" number="144"/> + <line hits="0" number="145"/> + <line hits="0" number="147"/> + <line hits="0" number="149"/> + <line hits="0" number="150"/> + <line hits="0" number="152"/> + <line hits="0" number="153"/> + <line hits="0" number="155"/> + <line hits="0" number="157"/> + <line hits="0" number="158"/> + <line hits="0" number="160"/> + <line hits="0" number="162"/> + <line hits="0" number="170"/> + <line hits="0" number="172"/> + <line hits="0" number="174"/> + <line hits="0" number="181"/> + <line hits="0" number="196"/> + <line hits="0" number="199"/> + </lines> + </class> + <class branch-rate="0" complexity="0" filename="mod/trapd_runtime_pid.py" line-rate="0.8846" name="trapd_runtime_pid.py"> + <methods/> + <lines> + <line hits="1" number="21"/> + <line hits="1" number="26"/> + <line hits="1" number="28"/> + <line hits="1" number="29"/> + <line hits="1" number="30"/> + <line hits="1" number="31"/> + <line hits="1" number="32"/> + <line hits="1" number="34"/> + <line hits="1" number="40"/> + <line hits="1" number="54"/> + <line hits="1" number="55"/> + <line hits="1" number="56"/> + <line hits="1" number="57"/> + <line hits="1" number="58"/> + <line hits="1" number="59"/> + <line hits="1" number="60"/> + <line hits="1" number="66"/> + <line hits="1" number="72"/> + <line hits="1" number="85"/> + <line hits="1" number="86"/> + <line hits="1" number="87"/> + <line hits="1" number="88"/> + <line hits="1" number="90"/> + <line hits="0" number="92"/> + <line hits="0" number="93"/> + <line hits="0" number="94"/> + </lines> + </class> + <class branch-rate="0" complexity="0" filename="mod/trapd_settings.py" line-rate="0" name="trapd_settings.py"> + <methods/> + <lines> + <line hits="0" number="21"/> + <line hits="0" number="24"/> + <line hits="0" number="27"/> + <line hits="0" number="32"/> + <line hits="0" number="43"/> + <line hits="0" number="45"/> + <line hits="0" number="50"/> + <line hits="0" number="52"/> + <line hits="0" number="55"/> + <line hits="0" number="57"/> + <line hits="0" number="60"/> + <line hits="0" number="62"/> + <line hits="0" number="65"/> + <line hits="0" number="67"/> + <line hits="0" number="70"/> + <line hits="0" number="72"/> + <line hits="0" number="74"/> + <line hits="0" number="79"/> + <line hits="0" number="81"/> + <line hits="0" number="83"/> + <line hits="0" number="85"/> + <line hits="0" number="87"/> + <line hits="0" number="89"/> + <line hits="0" number="94"/> + <line hits="0" number="96"/> + <line hits="0" number="98"/> + <line hits="0" number="100"/> + <line hits="0" number="102"/> + <line hits="0" number="104"/> + <line hits="0" number="106"/> + <line hits="0" number="108"/> + <line hits="0" number="113"/> + <line hits="0" number="118"/> + <line hits="0" number="120"/> + <line hits="0" number="125"/> + <line hits="0" number="127"/> + <line hits="0" number="132"/> + <line hits="0" number="141"/> + <line hits="0" number="142"/> + <line hits="0" number="143"/> + <line hits="0" number="144"/> + <line hits="0" number="145"/> + <line hits="0" number="146"/> + <line hits="0" number="155"/> + <line hits="0" number="156"/> + <line hits="0" number="157"/> + <line hits="0" number="158"/> + <line hits="0" number="159"/> + <line hits="0" number="160"/> + <line hits="0" number="161"/> + <line hits="0" number="164"/> + <line hits="0" number="167"/> + </lines> + </class> + </classes> + </package> + </packages> +</coverage> @@ -34,7 +34,7 @@ ECOMP is a trademark and service mark of AT&T Intellectual Property. <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <sonar.skip>true</sonar.skip> + <sonar.skip>false</sonar.skip> <sonar.sources>.</sonar.sources> <!-- customize the SONARQUBE URL --> <!-- sonar.host.url>http://localhost:9000</sonar.host.url --> @@ -43,6 +43,7 @@ ECOMP is a trademark and service mark of AT&T Intellectual Property. <sonar.language>py</sonar.language> <sonar.pluginName>Python</sonar.pluginName> <sonar.inclusions>**/*.py</sonar.inclusions> + <sonar.exclusions>target/**,tests/**,setup.py,**/__init__.py</sonar.exclusions> <!-- for JavaScaript --> <!-- <sonar.language>js</sonar.language> @@ -20,19 +20,23 @@ import os import string import sys +import setuptools +from setuptools import setup, find_packages -install_reqs = parse_requirements("requirements.txt", session=PipSession()) -reqs = [str(ir.req) for ir in install_reqs] setup( - name = "dcaegen2-collectors-snmptrap", + name = "snmptrap", description = "snmp trap receiver for ONAP docker image", version = "1.3.0", packages=find_packages(), + install_requires=[ + "pysnmp==4.4.2", + "requests==2.18.3", + "onap_dcae_cbs_docker_client==0.0.3" + ], author = "Dave L", author_email = "dl3158@att.com", license='Apache 2', keywords = "", - url = "", - install_requires=reqs + url = "" ) diff --git a/snmptrap/__init__.py b/snmptrap/__init__.py new file mode 100644 index 0000000..1875bf6 --- /dev/null +++ b/snmptrap/__init__.py @@ -0,0 +1,21 @@ +# ================================================================================ +# 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. + + +# empty __init__.py so that pytest can add correct path to coverage report, -- per pytest +# best practice guideline diff --git a/snmptrap/mod/__init__.py b/snmptrap/mod/__init__.py new file mode 100644 index 0000000..1875bf6 --- /dev/null +++ b/snmptrap/mod/__init__.py @@ -0,0 +1,21 @@ +# ================================================================================ +# 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. + + +# empty __init__.py so that pytest can add correct path to coverage report, -- per pytest +# best practice guideline diff --git a/bin/mod/trapd_exit.py b/snmptrap/mod/trapd_exit.py index a7ffc8a..ef7a2ae 100644 --- a/bin/mod/trapd_exit.py +++ b/snmptrap/mod/trapd_exit.py @@ -56,8 +56,8 @@ def cleanup_and_exit(_loc_exit_code, _pid_file_name): number of parameters passed to module """ - _num_params = len(locals()) + # _num_params = len(locals()) - if _num_params == 2: + if _pid_file_name is not None: rc = rm_pid(_pid_file_name) sys.exit(_loc_exit_code) diff --git a/bin/mod/trapd_get_cbs_config.py b/snmptrap/mod/trapd_get_cbs_config.py index e0f5ca8..524f1c2 100644 --- a/bin/mod/trapd_get_cbs_config.py +++ b/snmptrap/mod/trapd_get_cbs_config.py @@ -37,7 +37,7 @@ import collections import trapd_settings as tds from onap_dcae_cbs_docker_client.client import get_config from trapd_exit import cleanup_and_exit -from trapd_logging import stdout_logger +from trapd_io import stdout_logger prog_name = os.path.basename(__file__) @@ -74,12 +74,12 @@ def get_cbs_config(): except Exception as e: msg = "CBS_SIM_JSON not defined - FATAL ERROR, exiting" stdout_logger(msg) - cleanup_and_exit(1, pid_file_name) + cleanup_and_exit(1,None) if _cbs_sim_json_file == "None": msg = "CBS_SIM_JSON not defined - FATAL ERROR, exiting" stdout_logger(msg) - cleanup_and_exit(1, pid_file_name) + cleanup_and_exit(1,None) else: msg = ("ONAP controller override specified via CBS_SIM_JSON: %s" % _cbs_sim_json_file) @@ -90,7 +90,7 @@ def get_cbs_config(): msg = "Unable to load CBS_SIM_JSON " + _cbs_sim_json_file + \ " (invalid json?) - FATAL ERROR, exiting" stdout_logger(msg) - cleanup_and_exit(1, tds.pid_file_name) + cleanup_and_exit(1,None) # recalc timeout, set default if not present try: diff --git a/bin/mod/trapd_http_session.py b/snmptrap/mod/trapd_http_session.py index b34c19d..b34c19d 100644 --- a/bin/mod/trapd_http_session.py +++ b/snmptrap/mod/trapd_http_session.py diff --git a/bin/mod/trapd_file_utils.py b/snmptrap/mod/trapd_io.py index e62b528..8667750 100644 --- a/bin/mod/trapd_file_utils.py +++ b/snmptrap/mod/trapd_io.py @@ -39,7 +39,6 @@ import unicodedata # dcae_snmptrap import trapd_settings as tds -from trapd_logging import ecomp_logger, stdout_logger from trapd_exit import cleanup_and_exit prog_name = os.path.basename(__file__) @@ -223,3 +222,175 @@ def close_file(_loc_fd, _loc_filename): _loc_filename, str(e)) ecomp_logger(tds.LOG_TYPE_ERROR, tds.SEV_FATAL, tds.CODE_GENERAL, msg) return False + +# # # # # # # # # # # # # # # # # # # +# 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" + % ((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: + stdout_logger(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' + % ((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: + stdout_logger(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' + % ((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: + stdout_logger(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' + % ((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 !!! + # 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))) + try: + tds.eelf_debug_fd.write('%s|%s\n' % (t_out, str(_out_rec))) + except Exception as e: + stdout_logger(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/bin/mod/trapd_logging.py b/snmptrap/mod/trapd_logging.py index ae5a1a0..ae5a1a0 100644 --- a/bin/mod/trapd_logging.py +++ b/snmptrap/mod/trapd_logging.py diff --git a/bin/mod/trapd_runtime_pid.py b/snmptrap/mod/trapd_runtime_pid.py index c6ef76e..c6ef76e 100644 --- a/bin/mod/trapd_runtime_pid.py +++ b/snmptrap/mod/trapd_runtime_pid.py diff --git a/bin/mod/trapd_settings.py b/snmptrap/mod/trapd_settings.py index be87e26..be87e26 100644 --- a/bin/mod/trapd_settings.py +++ b/snmptrap/mod/trapd_settings.py diff --git a/bin/snmptrapd.py b/snmptrap/snmptrapd.py index 3765746..9cf828c 100644 --- a/bin/snmptrapd.py +++ b/snmptrap/snmptrapd.py @@ -73,8 +73,7 @@ from trapd_get_cbs_config import get_cbs_config from trapd_exit import cleanup_and_exit from trapd_http_session import init_session_obj -from trapd_file_utils import roll_all_logs, open_eelf_logs, roll_file, open_file, close_file -from trapd_logging import ecomp_logger, stdout_logger +from trapd_io import roll_all_logs, open_eelf_logs, roll_file, open_file, close_file, ecomp_logger, stdout_logger prog_name = os.path.basename(__file__) verbose = False @@ -146,7 +145,18 @@ def load_all_configs(_signum, _frame): msg = "error (re)loading CBS config - FATAL ERROR, exiting" stdout_logger(msg) cleanup_and_exit(1, tds.pid_file_name) + else: + current_runtime_config_file_name = tds.c_config['files.runtime_base_dir'] + \ + "/tmp/current_config.json" + + msg = "current config logged to : %s" % current_runtime_config_file_name + ecomp_logger(tds.LOG_TYPE_DEBUG, tds.SEV_INFO, tds.CODE_GENERAL, msg) + + with open(current_runtime_config_file_name, 'w') as outfile: + json.dump(tds.c_config, outfile) + # if here, config re-read successfully + return True # # # # # # # # # # # # # # fx: log_all_arriving_traps @@ -624,181 +634,184 @@ def notif_receiver_cb(snmp_engine, stateReference, contextEngineId, contextName, # Main MAIN Main MAIN # # # # # # # # # # # # # # parse command line args -parser = argparse.ArgumentParser(description='Post SNMP traps ' - 'to message bus') -parser.add_argument('-v', action="store_true", dest="verbose", - help="verbose logging") -parser.add_argument('-?', action="store_true", dest="usage_requested", - help="show command line use") - -# parse args -args = parser.parse_args() - -# set vars from args -verbose = args.verbose -usage_requested = args.usage_requested -# if usage, just display and exit -if usage_requested: - usage_err() - -# init vars -tds.init() - -# Set initial startup hour for rolling logfile -tds.last_hour = datetime.datetime.now().hour - -# get config binding service (CBS) values (either broker, or json file override) -load_all_configs(0, 0) -msg = "%s : %s version %s starting" % ( - 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() - -# bump up logging level if overridden at command line -if verbose: - msg = "WARNING: '-v' argument present. All messages will be logged. This can slow things down, use only when needed." - tds.minimum_severity_to_log = 0 +if __name__ == "__main__": + + parser = argparse.ArgumentParser(description='Post SNMP traps ' + 'to message bus') + parser.add_argument('-v', action="store_true", dest="verbose", + help="verbose logging") + parser.add_argument('-?', action="store_true", dest="usage_requested", + help="show command line use") + + # parse args + args = parser.parse_args() + + # set vars from args + verbose = args.verbose + usage_requested = args.usage_requested + + # if usage, just display and exit + if usage_requested: + usage_err() + + # init vars + tds.init() + + # Set initial startup hour for rolling logfile + tds.last_hour = datetime.datetime.now().hour + + # get config binding service (CBS) values (either broker, or json file override) + load_all_configs(0, 0) + msg = "%s : %s version %s starting" % ( + prog_name, tds.c_config['snmptrap.title'], tds.c_config['snmptrap.version']) stdout_logger(msg) - -# name and open arriving trap log -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 = open_file(tds.arriving_traps_filename) -msg = ("arriving traps logged to: %s" % tds.arriving_traps_filename) -stdout_logger(msg) -ecomp_logger(tds.LOG_TYPE_DEBUG, tds.SEV_INFO, tds.CODE_GENERAL, msg) - -# 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 = open_file(tds.json_traps_filename) -msg = ("published traps logged to: %s" % tds.json_traps_filename) -stdout_logger(msg) -ecomp_logger(tds.LOG_TYPE_DEBUG, tds.SEV_INFO, tds.CODE_GENERAL, msg) - -# setup signal handling for config reload -signal.signal(signal.SIGUSR1, load_all_configs) - -# save current PID for future/external reference -tds.pid_file_name = tds.c_config['files.runtime_base_dir'] + \ - '/' + tds.c_config['files.pid_dir'] + '/' + prog_name + ".pid" -msg = "Runtime PID file: %s" % tds.pid_file_name -ecomp_logger(tds.LOG_TYPE_DEBUG, tds.SEV_INFO, tds.CODE_GENERAL, msg) -rc = save_pid(tds.pid_file_name) - -# Get the event loop for this thread -loop = asyncio.get_event_loop() - -# Create SNMP engine with autogenernated engineID pre-bound -# to socket transport dispatcher -snmp_engine = engine.SnmpEngine() - -# # # # # # # # # # # # -# Transport setup -# # # # # # # # # # # # - -# UDP over IPv4 -# FIXME: 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'] - + + # 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() + + # bump up logging level if overridden at command line + if verbose: + msg = "WARNING: '-v' argument present. All diagnostic messages will be logged. This can slow things down, use only when needed." + tds.minimum_severity_to_log = 0 + stdout_logger(msg) + + # name and open arriving trap log + 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 = open_file(tds.arriving_traps_filename) + msg = ("arriving traps logged to: %s" % tds.arriving_traps_filename) + stdout_logger(msg) + ecomp_logger(tds.LOG_TYPE_DEBUG, tds.SEV_INFO, tds.CODE_GENERAL, msg) + + # 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 = open_file(tds.json_traps_filename) + msg = ("published traps logged to: %s" % tds.json_traps_filename) + stdout_logger(msg) + ecomp_logger(tds.LOG_TYPE_DEBUG, tds.SEV_INFO, tds.CODE_GENERAL, msg) + + # setup signal handling for config reload + signal.signal(signal.SIGUSR1, load_all_configs) + + # save current PID for future/external reference + tds.pid_file_name = tds.c_config['files.runtime_base_dir'] + \ + '/' + tds.c_config['files.pid_dir'] + '/' + prog_name + ".pid" + msg = "Runtime PID file: %s" % tds.pid_file_name + ecomp_logger(tds.LOG_TYPE_DEBUG, tds.SEV_INFO, tds.CODE_GENERAL, msg) + rc = save_pid(tds.pid_file_name) + + # Get the event loop for this thread + loop = asyncio.get_event_loop() + + # Create SNMP engine with autogenernated engineID pre-bound + # to socket transport dispatcher + snmp_engine = engine.SnmpEngine() + + # # # # # # # # # # # # + # Transport setup + # # # # # # # # # # # # + + # UDP over IPv4 + # FIXME: add check for presense of ipv4_interface prior to attempting add OR just put entire thing in try/except clause try: - config.addTransport( - snmp_engine, - udp.domainName + (1,), - udp.UdpTransport().openServerMode( - (ipv4_interface, ipv4_port)) - ) + ipv4_interface = tds.c_config['protocols.ipv4_interface'] + ipv4_port = tds.c_config['protocols.ipv4_port'] + + try: + config.addTransport( + snmp_engine, + udp.domainName + (1,), + udp.UdpTransport().openServerMode( + (ipv4_interface, ipv4_port)) + ) + except Exception as e: + msg = "Unable to bind to %s:%s - %s" % ( + ipv4_interface, ipv4_port, str(e)) + ecomp_logger(tds.LOG_TYPE_ERROR, tds.SEV_FATAL, tds.CODE_GENERAL, msg) + stdout_logger(msg) + cleanup_and_exit(1, tds.pid_file_name) + except Exception as e: - msg = "Unable to bind to %s:%s - %s" % ( - ipv4_interface, ipv4_port, str(e)) - ecomp_logger(tds.LOG_TYPE_ERROR, tds.SEV_FATAL, tds.CODE_GENERAL, msg) + msg = "IPv4 interface and/or port not specified in config - not listening for IPv4 traps" stdout_logger(msg) - cleanup_and_exit(1, tds.pid_file_name) - -except Exception as e: - msg = "IPv4 interface and/or port not specified in config - not listening for IPv4 traps" - stdout_logger(msg) - 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 -try: - ipv6_interface = tds.c_config['protocols.ipv6_interface'] - ipv6_port = tds.c_config['protocols.ipv6_port'] - + 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 try: - config.addTransport( - snmp_engine, - udp6.domainName, - udp6.Udp6Transport().openServerMode( - (ipv6_interface, ipv6_port)) - ) + ipv6_interface = tds.c_config['protocols.ipv6_interface'] + ipv6_port = tds.c_config['protocols.ipv6_port'] + + try: + config.addTransport( + snmp_engine, + udp6.domainName, + udp6.Udp6Transport().openServerMode( + (ipv6_interface, ipv6_port)) + ) + except Exception as e: + msg = "Unable to bind to %s:%s - %s" % ( + ipv6_interface, ipv6_port, str(e)) + stdout_logger(msg) + ecomp_logger(tds.LOG_TYPE_ERROR, tds.SEV_FATAL, tds.CODE_GENERAL, msg) + cleanup_and_exit(1, tds.pid_file_name) + except Exception as e: - msg = "Unable to bind to %s:%s - %s" % ( - ipv6_interface, ipv6_port, str(e)) + msg = "IPv6 interface and/or port not specified in config - not listening for IPv6 traps" stdout_logger(msg) - ecomp_logger(tds.LOG_TYPE_ERROR, tds.SEV_FATAL, tds.CODE_GENERAL, msg) + ecomp_logger(tds.LOG_TYPE_ERROR, tds.SEV_WARN, tds.CODE_GENERAL, msg) + + + # # # # # # # # # # # # + # SNMPv1/2c setup + # # # # # # # # # # # # + + # SecurityName <-> CommunityName mapping + # to restrict trap reception to only those with specific community + # strings + config.addV1System(snmp_engine, 'my-area', 'public') + + # register comm_string_rewrite_observer for message arrival + snmp_engine.observer.registerObserver( + comm_string_rewrite_observer, + 'rfc2576.processIncomingMsg:writable' + ) + + # register snmp_engine_observer_cb for message arrival + snmp_engine.observer.registerObserver( + snmp_engine_observer_cb, + 'rfc3412.receiveMessage:request', + 'rfc3412.returnResponsePdu', + ) + + # Register SNMP Application at the SNMP engine + ntfrcv.NotificationReceiver(snmp_engine, notif_receiver_cb) + + snmp_engine.transportDispatcher.jobStarted(1) # loop forever + + # Run I/O dispatcher which will receive traps + try: + snmp_engine.transportDispatcher.runDispatcher() + except Exception as e: + snmp_engine.observer.unregisterObserver() + snmp_engine.transportDispatcher.closeDispatcher() cleanup_and_exit(1, tds.pid_file_name) - -except Exception as e: - msg = "IPv6 interface and/or port not specified in config - not listening for IPv6 traps" - stdout_logger(msg) - ecomp_logger(tds.LOG_TYPE_ERROR, tds.SEV_WARN, tds.CODE_GENERAL, msg) - - -# # # # # # # # # # # # -# SNMPv1/2c setup -# # # # # # # # # # # # - -# SecurityName <-> CommunityName mapping -# to restrict trap reception to only those with specific community -# strings -config.addV1System(snmp_engine, 'my-area', 'public') - -# register comm_string_rewrite_observer for message arrival -snmp_engine.observer.registerObserver( - comm_string_rewrite_observer, - 'rfc2576.processIncomingMsg:writable' -) - -# register snmp_engine_observer_cb for message arrival -snmp_engine.observer.registerObserver( - snmp_engine_observer_cb, - 'rfc3412.receiveMessage:request', - 'rfc3412.returnResponsePdu', -) - -# Register SNMP Application at the SNMP engine -ntfrcv.NotificationReceiver(snmp_engine, notif_receiver_cb) - -snmp_engine.transportDispatcher.jobStarted(1) # loop forever - -# Run I/O dispatcher which will receive traps -try: - snmp_engine.transportDispatcher.runDispatcher() -except Exception as e: - snmp_engine.observer.unregisterObserver() - snmp_engine.transportDispatcher.closeDispatcher() - cleanup_and_exit(1, tds.pid_file_name) diff --git a/bin/snmptrapd.sh b/snmptrap/snmptrapd.sh index c4712f6..c4712f6 100755..100644 --- a/bin/snmptrapd.sh +++ b/snmptrap/snmptrapd.sh diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..1875bf6 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,21 @@ +# ================================================================================ +# 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. + + +# empty __init__.py so that pytest can add correct path to coverage report, -- per pytest +# best practice guideline diff --git a/tests/_test_trapd_get_cbs_config.py b/tests/_test_trapd_get_cbs_config.py deleted file mode 100644 index 5fcfc2a..0000000 --- a/tests/_test_trapd_get_cbs_config.py +++ /dev/null @@ -1,44 +0,0 @@ -import pytest -import unittest -import os -from onap_dcae_cbs_docker_client.client import get_config -from trapd_exit import cleanup_and_exit -from trapd_logging import stdout_logger -import trapd_get_cbs_config - -class test_get_cbs_config(unittest.TestCase): - """ - Test the trapd_get_cbs_config mod - """ - - def test_cbs_env_present(self): - """ - Test that CBS env variable exists and we can get config even - if CONSUL_HOST doesn't provide - """ - os.environ.update(CONSUL_HOST='nosuchhost') - result = trapd_get_cbs_config.trapd_get_cbs_config() - compare = str(result).startswith("{'snmptrap': ") - self.assertEqual(compare, False) - - def test_cbs_fallback_env_present(self): - """ - Test that CBS fallback env variable exists and we can get config - from fallback env var - """ - os.environ.update(CBS_SIM_JSON='../etc/snmptrapd.json') - result = trapd_get_cbs_config.trapd_get_cbs_config() - compare = str(result).startswith("{'snmptrap': ") - self.assertEqual(compare, False) - - def test_cbs_fallback_env_not_present(self): - """ - Test that CBS fallback env variable does not exists fails - """ - os.environ.update(CBS_SIM_JSON='../etc/no_such_file.json') - result = trapd_get_cbs_config.trapd_get_cbs_config() - compare = str(result).startswith("{'snmptrap': ") - self.assertEqual(compare, False) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..d78ed5e --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,12 @@ +import pytest + +@pytest.fixture + +def test_var(_var_name): + + try: + _var_name + except NameError: + return False + else: + return True diff --git a/tests/setup.py b/tests/snmp.setup.py index 5a12f10..5a12f10 100644 --- a/tests/setup.py +++ b/tests/snmp.setup.py diff --git a/tests/test_snmptrapd.py b/tests/test_snmptrapd.py index 2f1783c..2cc11d7 100644 --- a/tests/test_snmptrapd.py +++ b/tests/test_snmptrapd.py @@ -1,46 +1,88 @@ +import os import pytest import unittest +import snmptrapd +import datetime + +import trapd_settings as tds +import trapd_http_session import trapd_runtime_pid - -class test_save_pid(unittest.TestCase): +import trapd_io +import trapd_logging +import trapd_get_cbs_config + +class test_snmptrapd(unittest.TestCase): """ Test the save_pid mod """ - def test_correct_usage(self): + def test_usage_err(self): """ - Test that attempt to create pid file in standard location works + Test usage error """ - result = trapd_runtime_pid.save_pid('/tmp/snmptrap_test_pid_file') - self.assertEqual(result, True) + + with pytest.raises(SystemExit) as pytest_wrapped_sys_exit: + result = snmptrapd.usage_err() + assert pytest_wrapped_sys_exit.type == SystemExit + assert pytest_wrapped_sys_exit.value.code == 1 + - def test_missing_directory(self): + def test_load_all_configs(self): """ - Test that attempt to create pid file in missing dir fails + Test load of all configs """ - result = trapd_runtime_pid.save_pid('/bogus/directory/for/snmptrap_test_pid_file') - self.assertEqual(result, False) - -class test_rm_pid(unittest.TestCase): - """ - Test the rm_pid mod - """ - - def test_correct_usage(self): - """ - Test that attempt to remove pid file in standard location works - """ - # must create it before removing it - result = trapd_runtime_pid.save_pid('/tmp/snmptrap_test_pid_file') - result = trapd_runtime_pid.rm_pid('/tmp/snmptrap_test_pid_file') + + # init vars + tds.init() + + # request load of CBS data + os.environ.update(CBS_SIM_JSON='/opt/app/snmptrap/etc/snmptrapd.json') + result = trapd_get_cbs_config.get_cbs_config() self.assertEqual(result, True) - - def test_missing_file(self): + + # request load of CBS data + result = snmptrapd.load_all_configs(0, 1) + self.assertEqual(result, True) + + def test_log_all_arriving_traps(self): """ - Test that attempt to rm non-existent pid file fails + Test logging of traps """ - result = trapd_runtime_pid.rm_pid('/tmp/snmptrap_test_pid_file_9999') - self.assertEqual(result, False) - + + # init vars + tds.init() + + # request load of CBS data + os.environ.update(CBS_SIM_JSON='/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 logging + 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_logging.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 + if __name__ == '__main__': unittest.main() diff --git a/tests/test_trapd_get_cbs_config.py b/tests/test_trapd_get_cbs_config.py new file mode 100644 index 0000000..415c951 --- /dev/null +++ b/tests/test_trapd_get_cbs_config.py @@ -0,0 +1,61 @@ +import pytest +import unittest +import os + +from onap_dcae_cbs_docker_client.client import get_config +from trapd_exit import cleanup_and_exit +from trapd_io import stdout_logger, ecomp_logger +import trapd_settings as tds +import trapd_get_cbs_config + +class test_get_cbs_config(unittest.TestCase): + """ + Test the trapd_get_cbs_config mod + """ + + def test_cbs_env_present(self): + """ + Test that CBS env variable exists and we can get config even + if CONSUL_HOST doesn't provide + """ + os.environ.update(CONSUL_HOST='nosuchhost') + # result = trapd_get_cbs_config.get_cbs_config() + # print("result: %s" % result) + # compare = str(result).startswith("{'snmptrap': ") + # self.assertEqual(compare, False) + + with pytest.raises(Exception) as pytest_wrapped_sys_exit: + result = trapd_get_cbs_config.get_cbs_config() + assert pytest_wrapped_sys_exit.type == SystemExit + # assert pytest_wrapped_sys_exit.value.code == 1 + + + def test_cbs_override_env_invalid(self): + """ + """ + os.environ.update(CBS_SIM_JSON='/opt/app/snmptrap/etc/nosuchfile.json') + # result = trapd_get_cbs_config.get_cbs_config() + # print("result: %s" % result) + # compare = str(result).startswith("{'snmptrap': ") + # self.assertEqual(compare, False) + + with pytest.raises(SystemExit) as pytest_wrapped_sys_exit: + result = trapd_get_cbs_config.get_cbs_config() + assert pytest_wrapped_sys_exit.type == SystemExit + assert pytest_wrapped_sys_exit.value.code == 1 + + + def test_cbs_fallback_env_present(self): + """ + Test that CBS fallback env variable exists and we can get config + from fallback env var + """ + os.environ.update(CBS_SIM_JSON='/opt/app/snmptrap/etc/snmptrapd.json') + result = trapd_get_cbs_config.get_cbs_config() + print("result: %s" % result) + # compare = str(result).startswith("{'snmptrap': ") + # self.assertEqual(compare, True) + self.assertEqual(result, True) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_trapd_settings.py b/tests/test_trapd_settings.py new file mode 100644 index 0000000..ab64426 --- /dev/null +++ b/tests/test_trapd_settings.py @@ -0,0 +1,73 @@ +import pytest +import unittest +import trapd_exit + +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): + """ + Test for presense of required vars + """ + + + def test_nonexistent_dict(self): + """ + Test nosuch var + """ + tds.init() + try: + tds.no_such_var + result = True + except: + result = False + + self.assertEqual(result, False) + + def test_config_dict(self): + """ + Test config dict + """ + tds.init() + try: + tds.c_config + result = True + except: + result = False + + self.assertEqual(result, True) + + def test_dns_cache_ip_to_name(self): + """ + Test dns cache name dict + """ + + tds.init() + try: + tds.dns_cache_ip_to_name + result = True + except: + result = False + + self.assertEqual(result, True) + + def test_dns_cache_ip_expires(self): + """ + Test dns cache ip expires dict + """ + + tds.init() + try: + tds.dns_cache_ip_expires + result = True + except: + result = False + + self.assertEqual(result, True) + +if __name__ == '__main__': + # tds.init() + unittest.main() diff --git a/tests/tox.ini b/tests/tox.ini deleted file mode 100644 index 3d8e842..0000000 --- a/tests/tox.ini +++ /dev/null @@ -1,15 +0,0 @@ -[tox] -envlist = py36 - -[testenv] -deps = coverage -commands = coverage erase - -[testenv:py36] -deps = coverage pytest -commands = coverage run ../bin/snmptrapd.py & - pytest test_trapd_exit.py - pytest test_trapd_http_session.py - pytest test_trapd_runtime_pid.py - ./test_snmptrapd_send_test_trap.py & - coverage report -m @@ -0,0 +1,15 @@ +# content of: tox.ini , put in same dir as setup.py +[tox] +envlist = py27 + +[testenv] +deps= + -rrequirements.txt + pytest + coverage + pytest-cov +setenv = + PYTHONPATH={toxinidir} +recreate = True +commands= + pytest --cov snmptrap --cov-report=xml --cov-report=term tests --verbose |