From 85229cc7faece0792ae6bba248effd2828a4e33e Mon Sep 17 00:00:00 2001 From: Vitaliy Kharechko Date: Tue, 12 Jul 2016 10:52:34 +0300 Subject: [PATCH] Add packet trace handler support (handler, serializer for Monasca, plugin integration, and simulators) Change-Id: I39caaaf8346ec1aeca7fbeff7611151a1f6d57af --- .../handlers/broadviewhandlerbase.py | 2 +- broadview_collector/handlers/bsthandler.py | 1 - broadview_collector/handlers/pthandler.py | 32 + .../plugins/broadviewpublisherbase.py | 9 + broadview_collector/plugins/kafkapublisher.py | 24 +- broadview_collector/plugins/logpublisher.py | 14 +- .../plugins/monascapublisher.py | 20 +- broadview_collector/plugins/stacklight.py | 6 +- .../plugins/syslogpublisher.py | 11 +- .../serializers/pt_to_monasca.py | 1005 +++++++++++++++++ .../tools/pt/pt_drop_counter_report.py | 155 +++ .../tools/pt/pt_drop_reason.py | 94 ++ .../tools/pt/pt_ecmp_resolution.py | 106 ++ .../tools/pt/pt_lag_resolution.py | 95 ++ broadview_collector/tools/pt/pt_profile.py | 134 +++ broadview_collector/tools/pt/pt_sim.py | 51 + 16 files changed, 1734 insertions(+), 25 deletions(-) create mode 100644 broadview_collector/handlers/pthandler.py create mode 100644 broadview_collector/serializers/pt_to_monasca.py create mode 100644 broadview_collector/tools/pt/pt_drop_counter_report.py create mode 100644 broadview_collector/tools/pt/pt_drop_reason.py create mode 100644 broadview_collector/tools/pt/pt_ecmp_resolution.py create mode 100644 broadview_collector/tools/pt/pt_lag_resolution.py create mode 100644 broadview_collector/tools/pt/pt_profile.py create mode 100644 broadview_collector/tools/pt/pt_sim.py diff --git a/broadview_collector/handlers/broadviewhandlerbase.py b/broadview_collector/handlers/broadviewhandlerbase.py index c626163..88241be 100644 --- a/broadview_collector/handlers/broadviewhandlerbase.py +++ b/broadview_collector/handlers/broadviewhandlerbase.py @@ -20,7 +20,7 @@ class BroadViewHandlerBase(object): ''' return a 2-tuple (data, handled) - where data is understandable by a downstream serializer + where data is understandable by a downstream parser (in the case of BST, this would be a bst_parser object), and handled is a boolean, True if the POST was recognized, and False if not. diff --git a/broadview_collector/handlers/bsthandler.py b/broadview_collector/handlers/bsthandler.py index 1e570c3..320400c 100644 --- a/broadview_collector/handlers/bsthandler.py +++ b/broadview_collector/handlers/bsthandler.py @@ -25,7 +25,6 @@ class BroadViewHandler(BroadViewHandlerBase): handled = parser.process(data) except: handled = False - print handled return (parser, handled) def __repr__(self): diff --git a/broadview_collector/handlers/pthandler.py b/broadview_collector/handlers/pthandler.py new file mode 100644 index 0000000..eae1b67 --- /dev/null +++ b/broadview_collector/handlers/pthandler.py @@ -0,0 +1,32 @@ +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + +from broadviewhandlerbase import BroadViewHandlerBase +from broadview_lib.pt.pt_parser import PTParser + +class BroadViewHandler(BroadViewHandlerBase): + def __init__(self): + pass + + def handlePOST(self, path, ctype, length, data): + parser = PTParser() + try: + handled = parser.process(data) + except: + handled = False + return (parser, handled) + + def __repr__(self): + return "PT Handler" + diff --git a/broadview_collector/plugins/broadviewpublisherbase.py b/broadview_collector/plugins/broadviewpublisherbase.py index a6b2673..20c34e1 100644 --- a/broadview_collector/plugins/broadviewpublisherbase.py +++ b/broadview_collector/plugins/broadviewpublisherbase.py @@ -12,6 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +from broadview_lib.pt.pt_parser import PTParser +from broadview_lib.bst.bst_parser import BSTParser + class BroadViewPublisherBase(object): def __init__(self): pass @@ -19,3 +22,9 @@ class BroadViewPublisherBase(object): def publish(self, host, data): raise NotImplementedError + def isBST(self, parser): + return isinstance(parser, BSTParser) + + def isPT(self, parser): + return isinstance(parser, PTParser) + diff --git a/broadview_collector/plugins/kafkapublisher.py b/broadview_collector/plugins/kafkapublisher.py index 6d0168e..707b53d 100644 --- a/broadview_collector/plugins/kafkapublisher.py +++ b/broadview_collector/plugins/kafkapublisher.py @@ -39,16 +39,16 @@ class BroadViewPublisher(BroadViewPublisherBase): def getKafkaProducer(self): try: - self._producer = kafka.KafkaProducer(bootstrap_servers=['{}:{}'.format(self._ip_address, self._port)]) + self._producer = kafka.KafkaProducer(bootstrap_servers=['{}:{}'.format(self._ip_address, self._port)]) except kafka.errors.NoBrokersAvailable as e: LOG.error("BroadViewPublisher: NoBrokersAvailable {}".format(e)) except: LOG.error("Unexpected error: {}".format(sys.exc_info()[0])) def __init__(self): - self._ip_address = "127.0.0.1" - self._port = "9092" - self._topic = "broadview-bst" + self._ip_address = "127.0.0.1" + self._port = "9092" + self._topic = "broadview-bst" self.readConfig() self._producer = None @@ -58,13 +58,21 @@ class BroadViewPublisher(BroadViewPublisherBase): if not self._producer: self.getKafkaProducer() if self._producer: - code = 200 + code = 200 + if self.isBST(data): + self._topic = "broadview-bst" success, sdata = BSTToMonasca().serialize(host, data) - sdata = json.loads(sdata) + elif self.isPT(data): + self._topic = "broadview-pt" + success, sdata = PTToMonasca().serialize(host, data) + else: + success = False + if success: + sdata = json.loads(sdata) if success: - for x in sdata: + for x in sdata: try: - self._producer.send(self._topic, json.dumps(x)) + self._producer.send(self._topic, json.dumps(x)) except: LOG.info('unable to send to kafka topic {}: {}'.format(self._topic, sys.exc_info()[0])) else: diff --git a/broadview_collector/plugins/logpublisher.py b/broadview_collector/plugins/logpublisher.py index 69ba40e..1330270 100644 --- a/broadview_collector/plugins/logpublisher.py +++ b/broadview_collector/plugins/logpublisher.py @@ -18,6 +18,7 @@ from broadviewpublisherbase import BroadViewPublisherBase # so use it. from broadview_collector.serializers.bst_to_monasca import BSTToMonasca +from broadview_collector.serializers.pt_to_monasca import PTToMonasca import json try: from oslo_log import log @@ -40,7 +41,7 @@ class BroadViewPublisher(BroadViewPublisherBase): try: self._f = open(self._logfile, "w+") except: - LOG.info("log publisher: unable to open log file {}".format(self.__logfile)) + LOG.info("log publisher: unable to open log file {}".format(self._logfile)) def __init__(self): LOG.info("log publisher: init") @@ -53,11 +54,16 @@ class BroadViewPublisher(BroadViewPublisherBase): self._f.close() def publish(self, host, data): - LOG.info("log publisher: publish") code = 200 - success, sdata = BSTToMonasca().serialize(host, data) - sdata = json.loads(sdata) + if self.isBST(data): + success, sdata = BSTToMonasca().serialize(host, data) + elif self.isPT(data): + success, sdata = PTToMonasca().serialize(host, data) + else: + LOG.info("log publisher is not PT or BST") + success = False if success: + sdata = json.loads(sdata) for x in sdata: print >>self._f, json.dumps(x) self._f.flush() diff --git a/broadview_collector/plugins/monascapublisher.py b/broadview_collector/plugins/monascapublisher.py index 0251a29..b36593d 100644 --- a/broadview_collector/plugins/monascapublisher.py +++ b/broadview_collector/plugins/monascapublisher.py @@ -16,6 +16,7 @@ from broadviewpublisherbase import BroadViewPublisherBase from monascaclient import client import monascaclient.exc as exc from broadview_collector.serializers.bst_to_monasca import BSTToMonasca +from broadview_collector.serializers.pt_to_monasca import PTToMonasca import json import ConfigParser @@ -45,7 +46,6 @@ class BroadViewPublisher(BroadViewPublisherBase): def __init__(self): self.readConfig() - try: self._auth_kwargs = { 'username': self._username, @@ -65,15 +65,21 @@ class BroadViewPublisher(BroadViewPublisherBase): def publish(self, host, data): code = 500 if self._monasca_client: - code = 200 - success, sdata = BSTToMonasca().serialize(host, data) - sdata = json.loads(sdata) + if self.isBST(data): + success, sdata = BSTToMonasca().serialize(host, data) + elif self.isPT(data): + success, sdata = PTToMonasca().serialize(host, data) + else: + success = False + sdata = None if success: - for x in sdata: + code = 200 + sdata = json.loads(sdata) + for x in sdata: try: resp = self._monasca_client.metrics.create(**x) if not resp.status_code == 200 and not resp.status_code == 204: - code = resp.status_code + code = resp.status_code break except exc.HTTPException as he: LOG.error('HTTPException code=%s message=%s' % (he.code, he.message)) @@ -82,5 +88,5 @@ class BroadViewPublisher(BroadViewPublisherBase): return code def __repr__(self): - return "BroadView Monasca Publisher {_endpoint} {_api_version}".format(**__dict__(self)) + return "BroadView Monasca Publisher {}".format(self.__dict__) diff --git a/broadview_collector/plugins/stacklight.py b/broadview_collector/plugins/stacklight.py index dbdb93b..c3d11f1 100644 --- a/broadview_collector/plugins/stacklight.py +++ b/broadview_collector/plugins/stacklight.py @@ -54,10 +54,12 @@ class BroadViewPublisher(BroadViewPublisherBase): def publish(self, host, data): code = 500 - success, sdata = BSTToStacklight().serialize(host, data) + success = False + if self.isBST(data): + success, sdata = BSTToStacklight().serialize(host, data) if success: sdata = json.loads(sdata) - for x in sdata: + for x in sdata: try: r = requests.post('http://{}:{}'.format(self._ipaddr, self._port), json=sdata, timeout=self._timeout) code = r.status_code diff --git a/broadview_collector/plugins/syslogpublisher.py b/broadview_collector/plugins/syslogpublisher.py index 84e9309..6797b87 100644 --- a/broadview_collector/plugins/syslogpublisher.py +++ b/broadview_collector/plugins/syslogpublisher.py @@ -18,6 +18,7 @@ from broadviewpublisherbase import BroadViewPublisherBase # so use it. from broadview_collector.serializers.bst_to_monasca import BSTToMonasca +from broadview_collector.serializers.pt_to_monasca import PTToMonasca import json import syslog @@ -31,9 +32,15 @@ class BroadViewPublisher(BroadViewPublisherBase): def publish(self, host, data): code = 200 - success, sdata = BSTToMonasca().serialize(host, data) - sdata = json.loads(sdata) + if self.isBST(data): + success, sdata = BSTToMonasca().serialize(host, data) + elif self.isPT(data): + success, sdata = PTToMonasca().serialize(host, data) + else: + success = False if success: + sdata = json.loads(sdata) + for x in sdata: syslog.syslog(json.dumps(x)) else: diff --git a/broadview_collector/serializers/pt_to_monasca.py b/broadview_collector/serializers/pt_to_monasca.py new file mode 100644 index 0000000..f984389 --- /dev/null +++ b/broadview_collector/serializers/pt_to_monasca.py @@ -0,0 +1,1005 @@ +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + +from broadviewserializerbase import BroadViewSerializerBase +from broadview_lib.pt.pt_parser import PTParser, ReportTypes +import json +import unittest +import datetime +import time + + +class PTToMonasca(BroadViewSerializerBase): + ''' + Class that converts Packet Trace object model to OpenStack Monasca metrics. + See broadview-collector/doc/pt_to_monasca_serializer.md for documentation + ''' + + def __init__(self): + pass + + def __serializeToJSON(self, host, data): + ret = [] + try: + timestamp = time.mktime(data.getTimestamp()) * 1000 + except: + timestamp = int(time.mktime(datetime.datetime.utcnow().timetuple())) \ + * 1000 * 1000 + asic = data.getASICId() + + ''' + Note that monasca requires a value field. Where required, but not + obvious value is present in the data, we use 0 and notate that the + value is to be ignored in the metadata + ''' + + d = data.getPacketTraceProfile() + for x in d: + for y in x: + m = {} + m["name"] = "broadview.pt." + repr(x) + m["timestamp"] = timestamp + m["value"] = 0 + m["dimensions"] = {} + m["dimensions"]["asic-id"] = asic + m["dimensions"]["bv-agent"] = host + m["dimensions"]["realm"] = y.getRealm() + m["dimensions"]["port"] = y.getPort() + r = y.getLAGLinkResolution() + if r: + m["dimensions"]["lag-id"] = r.getLAGID() + m["dimensions"]["dst-lag-member"] = r.getDstLAGMember() + m["dimensions"]["lag-members"] = r.getLAGMembers() + m["dimensions"]["ignore-value"] = 1 + ret.append(m) + else: + r = y.getECMPLinkResolution() + for l in r: + m = {} + m["name"] = "broadview.pt." + repr(x) + m["timestamp"] = timestamp + m["value"] = 0 + m["dimensions"] = {} + m["dimensions"]["ignore-value"] = 1 + m["dimensions"]["asic-id"] = asic + m["dimensions"]["bv-agent"] = host + m["dimensions"]["realm"] = y.getRealm() + m["dimensions"]["port"] = y.getPort() + m["dimensions"]["ecmp-group-id"] = l.getECMPGroupID() + m["dimensions"]["ecmp-dst-member"] = l.getECMPDstMember() + m["dimensions"]["ecmp-dst-port"] = l.getECMPDstPort() + m["dimensions"]["ecmp-next-hop-ip"] = l.getECMPNextHopIP() + m["dimensions"]["ecmp-members"] = [] + for mem in l.getECMPMembers(): + member = {} + member["id"] = mem.getId() + member["ip"] = mem.getIP() + member["port"] = mem.getPort() + m["dimensions"]["ecmp-members"].append(member) + ret.append(m) + + d = data.getPacketTraceECMPResolution() + for x in d: + r = x.getECMPLinkResolution() + for l in r: + m = {} + m["name"] = "broadview.pt." + repr(x) + m["timestamp"] = timestamp + m["value"] = 0 + m["dimensions"] = {} + m["dimensions"]["ignore-value"] = 1 + m["dimensions"]["asic-id"] = asic + m["dimensions"]["bv-agent"] = host + m["dimensions"]["port"] = x.getPort() + m["dimensions"]["ecmp-group-id"] = l.getECMPGroupID() + m["dimensions"]["ecmp-dst-member"] = l.getECMPDstMember() + m["dimensions"]["ecmp-dst-port"] = l.getECMPDstPort() + m["dimensions"]["ecmp-next-hop-ip"] = l.getECMPNextHopIP() + m["dimensions"]["ecmp-members"] = [] + for mem in l.getECMPMembers(): + member = {} + member["id"] = mem.getId() + member["ip"] = mem.getIP() + member["port"] = mem.getPort() + m["dimensions"]["ecmp-members"].append(member) + ret.append(m) + + d = data.getPacketTraceLAGResolution() + for x in d: + ll = x.getLAGLinkResolution() + m = {} + m["name"] = "broadview.pt." + repr(x) + m["timestamp"] = timestamp + m["dimensions"] = {} + m["dimensions"]["asic-id"] = asic + m["dimensions"]["bv-agent"] = host + m["dimensions"]["port"] = x.getPort() + m["dimensions"]["lag-id"] = ll.getLAGID() + m["dimensions"]["dst-lag-member"] = ll.getDstLAGMember() + m["dimensions"]["lag-members"] = ll.getLAGMembers() + m["dimensions"]["ignore-value"] = 1 + m["value"] = 0 + ret.append(m) + + d = data.getPacketTraceDropReason() + for x in d: + m = {} + m["name"] = "broadview.pt." + repr(x) + m["timestamp"] = timestamp + m["dimensions"] = {} + m["dimensions"]["asic-id"] = asic + m["dimensions"]["bv-agent"] = host + m["dimensions"]["reason"] = x.getReason() + m["dimensions"]["port-list"] = x.getPortList() + m["dimensions"]["send-dropped-packet"] = x.getSendDroppedPacket() + m["dimensions"]["trace-profile"] = x.getTraceProfile() + m["dimensions"]["packet-threshold"] = x.getPacketThreshold() + m["dimensions"]["ignore-value"] = 0 + m["value"] = x.getPacketCount() + ret.append(m) + + d = data.getPacketTraceDropCounterReport() + for x in d: + for y in x: + m = {} + m["name"] = "broadview.pt." + repr(x) + m["timestamp"] = timestamp + m["dimensions"] = {} + m["dimensions"]["asic-id"] = asic + m["dimensions"]["bv-agent"] = host + m["dimensions"]["realm"] = y.getRealm() + m["dimensions"]["port"] = y.getPort() + m["value"] = y.getCount() + m["dimensions"]["ignore-value"] = 0 + ret.append(m) + + d = data.getPacketTraceSupportedDropReasons() + if d: + m = {} + m["name"] = "broadview.pt." + repr(d) + m["timestamp"] = timestamp + m["dimensions"] = {} + m["dimensions"]["asic-id"] = asic + m["dimensions"]["bv-agent"] = host + m["dimensions"]["reasons"] = d.getReasons() + m["dimensions"]["ignore-value"] = 1 + m["value"] = 0 + ret.append(m) + + return json.dumps(ret) + + def serialize(self, host, data): + # serialize a parsed BST report to Monasca metrics + ret = (False, None) + + s = self.__serializeToJSON(host, data) + + if s: + ret = (True, s) + + return ret + + def __repr__(self): + return "Packet Trace To Monasca Serializer" + +class TestSerializer(unittest.TestCase): + + def setUp(self): + self._host = "127.0.0.1" + self.packet_trace_profile_1 = { + "jsonrpc": "2.0", + "method": "get-packet-trace-profile", + "asic-id": "1", + "version": "1", + "time-stamp": "2014-11-18 - 00:15:04 ", + "report": [ + { + "port": "1", + "trace-profile": [ + { + "realm": "lag-link-resolution", + "data": { + "lag-id": "2", + "lag-members": ["1", "2", "3", "4"], + "dst-lag-member": "4" + } + }, + { + "realm": "ecmp-link-resolution", + "data": + [ + { + "ecmp-group-id": "100256", + "ecmp-members": [["100004", "1.2.2.2", "18"],["100005", "1.6.6.1", "11"]], + "ecmp-dst-member": "100005", + "ecmp-dst-port": "11", + "ecmp-next-hop-ip": "1.6.6.2" + }, + { + "ecmp-group-id": "200100", + "ecmp-members": [["200001", "2.3.3.1", "21"], ["200002", "2.7.7.2", "21"]], + "ecmp-dst-member": "200001", + "ecmp-dst-port": "21", + "ecmp-next-hop-ip": "2.3.3.2" + } + ] + } + ] + }, + { + "port": "2", + "trace-profile": [ + { + "realm": "lag-link-resolution", + "data": { + "lag-id": "2", + "lag-members": ["5", "6", "7", "8"], + "dst-lag-member": "5" + } + }, + { + "realm": "ecmp-link-resolution", + "data": + [ + { + "ecmp-group-id": "300256", + "ecmp-members": [["300004", "3.2.2.2", "38"],["300005", "3.6.6.1", "31"]], + "ecmp-dst-member": "300005", + "ecmp-dst-port": "31", + "ecmp-next-hop-ip": "3.6.6.2" + }, + { + "ecmp-group-id": "400100", + "ecmp-members": [["400001", "4.3.3.1", "48"], ["400002", "4.7.7.2", "41"]], + "ecmp-dst-member": "400001", + "ecmp-dst-port": "41", + "ecmp-next-hop-ip": "4.3.3.2" + } + ] + } + ] + } + ], + "id": 1 + } + self.packet_trace_lag_resolution_1 = { + "jsonrpc": "2.0", + "method": " get-packet-trace-lag-resolution", + "asic-id": "1", + "version": "1", + "time-stamp": "2014-11-18 - 00:15:04 ", + "report": [ + { + "port": "1", + "lag-link-resolution": { + "lag-id": "1", + "lag-members": [ + "1", + "2", + "3", + "4" + ], + "dst-lag-member": "4" + } + }, + { + "port": "2", + "lag-link-resolution": { + "lag-id": "2", + "lag-members": [ + "5", + "6", + "7", + "8" + ], + "dst-lag-member": "7" + } + } + ], + "id": 1 + } + + self.packet_trace_ecmp_resolution_1 = { + "jsonrpc": "2.0", + "method": " get-packet-trace-ecmp-resolution", + "asic-id": "1", + "version": "1", + "time-stamp": "2014-11-18 - 00:15:04 ", + "report": [ + { + "port": "1", + "ecmp-link-resolution": [ + { + "ecmp-group-id": "100256", + "ecmp-members": [["100004", "1.2.2.2", "18"],["100005", "1.6.6.1", "11"]], + "ecmp-dst-member": "100005", + "ecmp-dst-port": "11", + "ecmp-next-hop-ip": "1.6.6.2" + }, + { + "ecmp-group-id": "200100", + "ecmp-members": [["200001", "2.3.3.1", "21"], ["200002", "2.7.7.2", "21"]], + "ecmp-dst-member": "200001", + "ecmp-dst-port": "21", + "ecmp-next-hop-ip": "2.3.3.2" + } + ] + }, + { + "port": "2", + "ecmp-link-resolution": [ + { + "ecmp-group-id": "300100", + "ecmp-members": [["300001", "3.3.3.1", "38"],["300002", "3.7.7.2", "31"]], + "ecmp-dst-member": "300005", + "ecmp-dst-port": "31", + "ecmp-next-hop-ip": "3.6.6.2" + }, + { + "ecmp-group-id": "400100", + "ecmp-members": [["400001", "4.3.3.1", "48"], ["400002", "4.7.7.2", "41"]], + "ecmp-dst-member": "400001", + "ecmp-dst-port": "41", + "ecmp-next-hop-ip": "4.3.3.2" + } + ] + } + ], + "id": 1 + } + + self.packet_trace_drop_reason_1 = { + "jsonrpc": "2.0", + "method": "get-packet-trace-drop-reason", + "asic-id": "1", + "version": "1", + "result": [ + { + "reason": "l2-lookup-failure", + "port-list": [ + "1", + "5", + "6", + "10-15" + ], + "send-dropped-packet": 0, + "trace-profile": 0, + "packet-count": 4, + "packet-threshold": 0 + }, + { + "reason": "vlan-mismatch", + "port-list": [ + "11", + "15", + "16", + "20-25" + ], + "send-dropped-packet": 1, + "trace-profile": 1, + "packet-count": 3, + "packet-threshold": 10 + } + ], + "id": 1 + } + + self.packet_trace_drop_counter_report_1 = { + "jsonrpc": "2.0", + "method": " get-packet-trace-drop-counter-report", + "asic-id": "1", + "version": "1", + "report": [ + { + "realm": "vlan-xlate-miss-drop", + "data": [ + { + "port": "1", + "count": 10 + }, + { + "port": "5", + "count": 20 + }, + { + "port": "6", + "count": 30 + }, + { + "port": "10", + "count": 40 + }, + { + "port": "11", + "count": 50 + }, + { + "port": "12", + "count": 60 + } + ] + }, + { + "realm": "bpdu-drop", + "data": [ + { + "port": "1", + "count": 70 + }, + { + "port": "5", + "count": 20 + }, + { + "port": "6", + "count": 30 + }, + { + "port": "10", + "count": 40 + }, + { + "port": "11", + "count": 80 + }, + { + "port": "12", + "count": 90 + } + ] + }, + { + "realm": "trill-slowpath-drop", + "data": [ + { + "port": "1", + "count": 10 + }, + { + "port": "5", + "count": 20 + }, + { + "port": "6", + "count": 30 + }, + { + "port": "10", + "count": 40 + }, + { + "port": "11", + "count": 50 + }, + { + "port": "12", + "count": 60 + } + ] + } + ] + } + + self.packet_trace_supported_drop_reasons_1 = { + "jsonrpc": "2.0", + "method": "get-packet-trace-supported-drop-reasons", + "asic-id": "1", + "version": "1", + "result": [ + "l2-lookup-failure", + "vlan-mismatch" + ], + "id": 1 + } + + def test_packet_trace_profile_1(self): + rep = PTParser() + rep.process(self.packet_trace_profile_1) + serializer = PTToMonasca() + ret = serializer.serialize(self._host, rep) + self.assertEqual(ret[0], True) + data = json.loads(ret[1]) + self.assertTrue(len(data) == 6) + + self.assertTrue("timestamp" in data[0]) + timestamp = int(data[0]["timestamp"]) / 1000 + self.assertTrue("name" in data[0]) + self.assertTrue("dimensions" in data[0]) + t1 = datetime.datetime.fromtimestamp(timestamp) + t1 = t1.strftime("%Y-%m-%d - %H:%M:%S") + t2 = self.packet_trace_profile_1["time-stamp"].strip() + self.assertEqual(t1, t2) + self.assertEqual(data[0]["name"], "broadview.pt.packet-trace-profile") + dim = data[0]["dimensions"] + self.assertTrue("bv-agent" in dim) + self.assertTrue("asic-id" in dim) + self.assertEqual(dim["asic-id"], self.packet_trace_profile_1["asic-id"]) + self.assertTrue("realm" in dim) + self.assertEqual(dim["realm"], "lag-link-resolution") + self.assertTrue("lag-id" in dim) + self.assertEqual(dim["lag-id"], "2") + self.assertTrue("lag-members" in dim) + self.assertEqual(len(dim["lag-members"]), 4) + self.assertTrue("1" in dim["lag-members"]) + self.assertTrue("2" in dim["lag-members"]) + self.assertTrue("3" in dim["lag-members"]) + self.assertTrue("4" in dim["lag-members"]) + self.assertTrue("port" in dim) + self.assertEqual(dim["port"], "1") + self.assertTrue("dst-lag-member" in dim) + self.assertEqual(dim["dst-lag-member"], "4") + + self.assertTrue("timestamp" in data[1]) + timestamp = int(data[1]["timestamp"]) / 1000 + self.assertTrue("name" in data[1]) + self.assertTrue("dimensions" in data[1]) + t1 = datetime.datetime.fromtimestamp(timestamp) + t1 = t1.strftime("%Y-%m-%d - %H:%M:%S") + t2 = self.packet_trace_profile_1["time-stamp"].strip() + self.assertEqual(t1, t2) + self.assertEqual(data[1]["name"], "broadview.pt.packet-trace-profile") + dim = data[1]["dimensions"] + self.assertTrue("asic-id" in dim) + self.assertEqual(dim["asic-id"], self.packet_trace_profile_1["asic-id"]) + self.assertTrue("realm" in dim) + self.assertEqual(dim["realm"], "ecmp-link-resolution") + self.assertTrue("ecmp-dst-member" in dim) + self.assertEqual(dim["ecmp-dst-member"], "100005") + self.assertTrue("bv-agent" in dim) + self.assertTrue("ecmp-next-hop-ip" in dim) + self.assertEqual(dim["ecmp-next-hop-ip"], "1.6.6.2") + self.assertTrue("ecmp-dst-port" in dim) + self.assertEqual(dim["ecmp-dst-port"], "11") + self.assertTrue("ecmp-members" in dim) + self.assertEqual(len(dim["ecmp-members"]), 2) + mem = dim["ecmp-members"][0] + self.assertTrue("ip" in mem) + self.assertEqual(mem["ip"], "1.2.2.2") + self.assertTrue("id" in mem) + self.assertEqual(mem["id"], "100004") + self.assertTrue("port" in mem) + self.assertEqual(mem["port"], "18") + mem = dim["ecmp-members"][1] + self.assertTrue("ip" in mem) + self.assertEqual(mem["ip"], "1.6.6.1") + self.assertTrue("id" in mem) + self.assertEqual(mem["id"], "100005") + self.assertTrue("port" in mem) + self.assertEqual(mem["port"], "11") + self.assertTrue("ecmp-group-id" in dim) + self.assertEqual(dim["ecmp-group-id"], "100256") + self.assertTrue("port" in dim) + self.assertEqual(dim["port"], "1") + + self.assertTrue("timestamp" in data[2]) + timestamp = int(data[1]["timestamp"]) / 1000 + self.assertTrue("name" in data[2]) + self.assertTrue("dimensions" in data[2]) + t1 = datetime.datetime.fromtimestamp(timestamp) + t1 = t1.strftime("%Y-%m-%d - %H:%M:%S") + t2 = self.packet_trace_profile_1["time-stamp"].strip() + self.assertEqual(t1, t2) + self.assertEqual(data[2]["name"], "broadview.pt.packet-trace-profile") + dim = data[2]["dimensions"] + self.assertTrue("asic-id" in dim) + self.assertEqual(dim["asic-id"], self.packet_trace_profile_1["asic-id"]) + self.assertTrue("realm" in dim) + self.assertEqual(dim["realm"], "ecmp-link-resolution") + self.assertTrue("ecmp-dst-member" in dim) + self.assertEqual(dim["ecmp-dst-member"], "200001") + self.assertTrue("bv-agent" in dim) + self.assertTrue("ecmp-next-hop-ip" in dim) + self.assertEqual(dim["ecmp-next-hop-ip"], "2.3.3.2") + self.assertTrue("ecmp-dst-port" in dim) + self.assertEqual(dim["ecmp-dst-port"], "21") + self.assertTrue("ecmp-members" in dim) + self.assertEqual(len(dim["ecmp-members"]), 2) + mem = dim["ecmp-members"][0] + self.assertTrue("ip" in mem) + self.assertEqual(mem["ip"], "2.3.3.1") + self.assertTrue("id" in mem) + self.assertEqual(mem["id"], "200001") + self.assertTrue("port" in mem) + self.assertEqual(mem["port"], "21") + mem = dim["ecmp-members"][1] + self.assertTrue("ip" in mem) + self.assertEqual(mem["ip"], "2.7.7.2") + self.assertTrue("id" in mem) + self.assertEqual(mem["id"], "200002") + self.assertTrue("port" in mem) + self.assertEqual(mem["port"], "21") + self.assertTrue("ecmp-group-id" in dim) + self.assertEqual(dim["ecmp-group-id"], "200100") + self.assertTrue("port" in dim) + self.assertEqual(dim["port"], "1") + + def test_packet_trace_lag_resolution_1(self): + rep = PTParser() + rep.process(self.packet_trace_lag_resolution_1) + serializer = PTToMonasca() + ret = serializer.serialize(self._host, rep) + self.assertEqual(ret[0], True) + data = json.loads(ret[1]) + self.assertTrue(len(data) == 2) + + self.assertTrue("timestamp" in data[0]) + timestamp = int(data[0]["timestamp"]) / 1000 + self.assertTrue("name" in data[0]) + self.assertTrue("dimensions" in data[0]) + t1 = datetime.datetime.fromtimestamp(timestamp) + t1 = t1.strftime("%Y-%m-%d - %H:%M:%S") + t2 = self.packet_trace_lag_resolution_1["time-stamp"].strip() + self.assertEqual(t1, t2) + self.assertEqual(data[0]["name"], "broadview.pt.packet-trace-lag-resolution") + dim = data[0]["dimensions"] + self.assertTrue("bv-agent" in dim) + self.assertTrue("asic-id" in dim) + self.assertEqual(dim["asic-id"], self.packet_trace_profile_1["asic-id"]) + self.assertTrue("lag-id" in dim) + self.assertEqual(dim["lag-id"], "1") + self.assertTrue("lag-members" in dim) + self.assertEqual(len(dim["lag-members"]), 4) + self.assertTrue("1" in dim["lag-members"]) + self.assertTrue("2" in dim["lag-members"]) + self.assertTrue("3" in dim["lag-members"]) + self.assertTrue("4" in dim["lag-members"]) + self.assertTrue("port" in dim) + self.assertEqual(dim["port"], "1") + self.assertTrue("dst-lag-member" in dim) + self.assertEqual(dim["dst-lag-member"], "4") + + self.assertTrue("timestamp" in data[1]) + timestamp = int(data[0]["timestamp"]) / 1000 + self.assertTrue("name" in data[1]) + self.assertTrue("dimensions" in data[1]) + t1 = datetime.datetime.fromtimestamp(timestamp) + t1 = t1.strftime("%Y-%m-%d - %H:%M:%S") + t2 = self.packet_trace_lag_resolution_1["time-stamp"].strip() + self.assertEqual(t1, t2) + self.assertEqual(data[1]["name"], "broadview.pt.packet-trace-lag-resolution") + dim = data[1]["dimensions"] + self.assertTrue("bv-agent" in dim) + self.assertTrue("asic-id" in dim) + self.assertEqual(dim["asic-id"], self.packet_trace_profile_1["asic-id"]) + self.assertTrue("lag-id" in dim) + self.assertEqual(dim["lag-id"], "2") + self.assertTrue("lag-members" in dim) + self.assertEqual(len(dim["lag-members"]), 4) + self.assertTrue("5" in dim["lag-members"]) + self.assertTrue("6" in dim["lag-members"]) + self.assertTrue("7" in dim["lag-members"]) + self.assertTrue("8" in dim["lag-members"]) + self.assertTrue("port" in dim) + self.assertEqual(dim["port"], "2") + self.assertTrue("dst-lag-member" in dim) + self.assertEqual(dim["dst-lag-member"], "7") + + def test_packet_trace_ecmp_resolution_1(self): + rep = PTParser() + rep.process(self.packet_trace_ecmp_resolution_1) + serializer = PTToMonasca() + ret = serializer.serialize(self._host, rep) + self.assertEqual(ret[0], True) + data = json.loads(ret[1]) + self.assertTrue(len(data) == 4) + + self.assertTrue("timestamp" in data[0]) + timestamp = int(data[0]["timestamp"]) / 1000 + self.assertTrue("name" in data[0]) + self.assertTrue("dimensions" in data[0]) + t1 = datetime.datetime.fromtimestamp(timestamp) + t1 = t1.strftime("%Y-%m-%d - %H:%M:%S") + t2 = self.packet_trace_ecmp_resolution_1["time-stamp"].strip() + self.assertEqual(t1, t2) + self.assertEqual(data[0]["name"], "broadview.pt.packet-trace-ecmp-resolution") + dim = data[0]["dimensions"] + self.assertTrue("asic-id" in dim) + self.assertEqual(dim["asic-id"], self.packet_trace_profile_1["asic-id"]) + self.assertTrue("ecmp-dst-member" in dim) + self.assertEqual(dim["ecmp-dst-member"], "100005") + self.assertTrue("bv-agent" in dim) + self.assertTrue("ecmp-next-hop-ip" in dim) + self.assertEqual(dim["ecmp-next-hop-ip"], "1.6.6.2") + self.assertTrue("ecmp-dst-port" in dim) + self.assertEqual(dim["ecmp-dst-port"], "11") + self.assertTrue("ecmp-members" in dim) + self.assertEqual(len(dim["ecmp-members"]), 2) + mem = dim["ecmp-members"][0] + self.assertTrue("ip" in mem) + self.assertEqual(mem["ip"], "1.2.2.2") + self.assertTrue("id" in mem) + self.assertEqual(mem["id"], "100004") + self.assertTrue("port" in mem) + self.assertEqual(mem["port"], "18") + mem = dim["ecmp-members"][1] + self.assertTrue("ip" in mem) + self.assertEqual(mem["ip"], "1.6.6.1") + self.assertTrue("id" in mem) + self.assertEqual(mem["id"], "100005") + self.assertTrue("port" in mem) + self.assertEqual(mem["port"], "11") + self.assertTrue("ecmp-group-id" in dim) + self.assertEqual(dim["ecmp-group-id"], "100256") + self.assertTrue("port" in dim) + self.assertEqual(dim["port"], "1") + + self.assertTrue("timestamp" in data[1]) + timestamp = int(data[1]["timestamp"]) / 1000 + self.assertTrue("name" in data[1]) + self.assertTrue("dimensions" in data[1]) + t1 = datetime.datetime.fromtimestamp(timestamp) + t1 = t1.strftime("%Y-%m-%d - %H:%M:%S") + t2 = self.packet_trace_ecmp_resolution_1["time-stamp"].strip() + self.assertEqual(t1, t2) + dim = data[1]["dimensions"] + self.assertTrue("asic-id" in dim) + self.assertEqual(dim["asic-id"], self.packet_trace_profile_1["asic-id"]) + self.assertTrue("ecmp-dst-member" in dim) + self.assertEqual(dim["ecmp-dst-member"], "200001") + self.assertTrue("bv-agent" in dim) + self.assertTrue("ecmp-next-hop-ip" in dim) + self.assertEqual(dim["ecmp-next-hop-ip"], "2.3.3.2") + self.assertTrue("ecmp-dst-port" in dim) + self.assertEqual(dim["ecmp-dst-port"], "21") + self.assertTrue("ecmp-members" in dim) + self.assertEqual(len(dim["ecmp-members"]), 2) + mem = dim["ecmp-members"][0] + self.assertTrue("ip" in mem) + self.assertEqual(mem["ip"], "2.3.3.1") + self.assertTrue("id" in mem) + self.assertEqual(mem["id"], "200001") + self.assertTrue("port" in mem) + self.assertEqual(mem["port"], "21") + mem = dim["ecmp-members"][1] + self.assertTrue("ip" in mem) + self.assertEqual(mem["ip"], "2.7.7.2") + self.assertTrue("id" in mem) + self.assertEqual(mem["id"], "200002") + self.assertTrue("port" in mem) + self.assertEqual(mem["port"], "21") + self.assertTrue("ecmp-group-id" in dim) + self.assertEqual(dim["ecmp-group-id"], "200100") + self.assertTrue("port" in dim) + self.assertEqual(dim["port"], "1") + + self.assertTrue("timestamp" in data[2]) + timestamp = int(data[2]["timestamp"]) / 1000 + self.assertTrue("name" in data[2]) + self.assertTrue("dimensions" in data[2]) + t1 = datetime.datetime.fromtimestamp(timestamp) + t1 = t1.strftime("%Y-%m-%d - %H:%M:%S") + t2 = self.packet_trace_ecmp_resolution_1["time-stamp"].strip() + self.assertEqual(t1, t2) + dim = data[2]["dimensions"] + self.assertTrue("asic-id" in dim) + self.assertEqual(dim["asic-id"], self.packet_trace_profile_1["asic-id"]) + self.assertTrue("ecmp-dst-member" in dim) + self.assertEqual(dim["ecmp-dst-member"], "300005") + self.assertTrue("bv-agent" in dim) + self.assertTrue("ecmp-next-hop-ip" in dim) + self.assertEqual(dim["ecmp-next-hop-ip"], "3.6.6.2") + self.assertTrue("ecmp-dst-port" in dim) + self.assertEqual(dim["ecmp-dst-port"], "31") + self.assertTrue("ecmp-members" in dim) + self.assertEqual(len(dim["ecmp-members"]), 2) + mem = dim["ecmp-members"][0] + self.assertTrue("ip" in mem) + self.assertEqual(mem["ip"], "3.3.3.1") + self.assertTrue("id" in mem) + self.assertEqual(mem["id"], "300001") + self.assertTrue("port" in mem) + self.assertEqual(mem["port"], "38") + mem = dim["ecmp-members"][1] + self.assertTrue("ip" in mem) + self.assertEqual(mem["ip"], "3.7.7.2") + self.assertTrue("id" in mem) + self.assertEqual(mem["id"], "300002") + self.assertTrue("port" in mem) + self.assertEqual(mem["port"], "31") + self.assertTrue("ecmp-group-id" in dim) + self.assertEqual(dim["ecmp-group-id"], "300100") + self.assertTrue("port" in dim) + self.assertEqual(dim["port"], "2") + + self.assertTrue("timestamp" in data[3]) + timestamp = int(data[3]["timestamp"]) / 1000 + self.assertTrue("name" in data[3]) + self.assertTrue("dimensions" in data[3]) + t1 = datetime.datetime.fromtimestamp(timestamp) + t1 = t1.strftime("%Y-%m-%d - %H:%M:%S") + t2 = self.packet_trace_ecmp_resolution_1["time-stamp"].strip() + self.assertEqual(t1, t2) + dim = data[3]["dimensions"] + self.assertTrue("asic-id" in dim) + self.assertEqual(dim["asic-id"], self.packet_trace_profile_1["asic-id"]) + self.assertTrue("ecmp-dst-member" in dim) + self.assertEqual(dim["ecmp-dst-member"], "400001") + self.assertTrue("bv-agent" in dim) + self.assertTrue("ecmp-next-hop-ip" in dim) + self.assertEqual(dim["ecmp-next-hop-ip"], "4.3.3.2") + self.assertTrue("ecmp-dst-port" in dim) + self.assertEqual(dim["ecmp-dst-port"], "41") + self.assertTrue("ecmp-members" in dim) + self.assertEqual(len(dim["ecmp-members"]), 2) + mem = dim["ecmp-members"][0] + self.assertTrue("ip" in mem) + self.assertEqual(mem["ip"], "4.3.3.1") + self.assertTrue("id" in mem) + self.assertEqual(mem["id"], "400001") + self.assertTrue("port" in mem) + self.assertEqual(mem["port"], "48") + mem = dim["ecmp-members"][1] + self.assertTrue("ip" in mem) + self.assertEqual(mem["ip"], "4.7.7.2") + self.assertTrue("id" in mem) + self.assertEqual(mem["id"], "400002") + self.assertTrue("port" in mem) + self.assertEqual(mem["port"], "41") + self.assertTrue("ecmp-group-id" in dim) + self.assertEqual(dim["ecmp-group-id"], "400100") + self.assertTrue("port" in dim) + self.assertEqual(dim["port"], "2") + + def test_packet_trace_drop_reason(self): + rep = PTParser() + rep.process(self.packet_trace_drop_reason_1) + serializer = PTToMonasca() + ret = serializer.serialize(self._host, rep) + self.assertEqual(ret[0], True) + data = json.loads(ret[1]) + self.assertTrue(len(data) == 2) + i = 0 + for x in data: + self.assertTrue("timestamp" in x) + self.assertTrue("name" in x) + self.assertTrue("dimensions" in x) + self.assertEqual(x["name"], "broadview.pt.packet-trace-drop-reason") + dim = x["dimensions"] + if i == 0: + self.assertEqual(dim["reason"], "l2-lookup-failure") + l = dim["port-list"] + self.assertEqual(len(l), 4) + self.assertEqual(l[0], "1") + self.assertEqual(l[1], "5") + self.assertEqual(l[2], "6") + self.assertEqual(l[3], "10-15") + self.assertEqual(dim["send-dropped-packet"], 0) + self.assertEqual(dim["trace-profile"], 0) + self.assertEqual(dim["packet-threshold"], 0) + self.assertEqual(x["value"], 4) + else: + self.assertEqual(dim["reason"], "vlan-mismatch") + l = dim["port-list"] + self.assertEqual(len(l), 4) + self.assertEqual(l[0], "11") + self.assertEqual(l[1], "15") + self.assertEqual(l[2], "16") + self.assertEqual(l[3], "20-25") + self.assertEqual(dim["send-dropped-packet"], 1) + self.assertEqual(dim["trace-profile"], 1) + self.assertEqual(dim["packet-threshold"], 10) + self.assertEqual(x["value"], 3) + i = i + 1 + + def test_packet_trace_drop_counter_report(self): + rep = PTParser() + rep.process(self.packet_trace_drop_counter_report_1) + serializer = PTToMonasca() + ret = serializer.serialize(self._host, rep) + self.assertEqual(ret[0], True) + data = json.loads(ret[1]) + self.assertTrue(len(data) == 18) + i = 0 + for x in data: + self.assertTrue("timestamp" in x) + self.assertTrue("name" in x) + self.assertTrue("dimensions" in x) + self.assertEqual(x["name"], "broadview.pt.packet-trace-drop-counter-report") + dim = x["dimensions"] + if i == 0: + self.assertEqual(dim["realm"], "vlan-xlate-miss-drop") + self.assertEqual(dim["port"], "1") + self.assertEqual(x["value"], 10) + elif i == 1: + self.assertEqual(dim["realm"], "vlan-xlate-miss-drop") + self.assertEqual(dim["port"], "5") + self.assertEqual(x["value"], 20) + elif i == 2: + self.assertEqual(dim["realm"], "vlan-xlate-miss-drop") + self.assertEqual(dim["port"], "6") + self.assertEqual(x["value"], 30) + elif i == 3: + self.assertEqual(dim["realm"], "vlan-xlate-miss-drop") + self.assertEqual(dim["port"], "10") + self.assertEqual(x["value"], 40) + elif i == 4: + self.assertEqual(dim["realm"], "vlan-xlate-miss-drop") + self.assertEqual(dim["port"], "11") + self.assertEqual(x["value"], 50) + elif i == 5: + self.assertEqual(dim["realm"], "vlan-xlate-miss-drop") + self.assertEqual(dim["port"], "12") + self.assertEqual(x["value"], 60) + elif i == 6: + self.assertEqual(dim["realm"], "bpdu-drop") + self.assertEqual(dim["port"], "1") + self.assertEqual(x["value"], 70) + elif i == 7: + self.assertEqual(dim["realm"], "bpdu-drop") + self.assertEqual(dim["port"], "5") + self.assertEqual(x["value"], 20) + elif i == 8: + self.assertEqual(dim["realm"], "bpdu-drop") + self.assertEqual(dim["port"], "6") + self.assertEqual(x["value"], 30) + elif i == 9: + self.assertEqual(dim["realm"], "bpdu-drop") + self.assertEqual(dim["port"], "10") + self.assertEqual(x["value"], 40) + elif i == 10: + self.assertEqual(dim["realm"], "bpdu-drop") + self.assertEqual(dim["port"], "11") + self.assertEqual(x["value"], 80) + elif i == 11: + self.assertEqual(dim["realm"], "bpdu-drop") + self.assertEqual(dim["port"], "12") + self.assertEqual(x["value"], 90) + elif i == 12: + self.assertEqual(dim["realm"], "trill-slowpath-drop") + self.assertEqual(dim["port"], "1") + self.assertEqual(x["value"], 10) + elif i == 13: + self.assertEqual(dim["realm"], "trill-slowpath-drop") + self.assertEqual(dim["port"], "5") + self.assertEqual(x["value"], 20) + elif i == 14: + self.assertEqual(dim["realm"], "trill-slowpath-drop") + self.assertEqual(dim["port"], "6") + self.assertEqual(x["value"], 30) + elif i == 15: + self.assertEqual(dim["realm"], "trill-slowpath-drop") + self.assertEqual(dim["port"], "10") + self.assertEqual(x["value"], 40) + elif i == 16: + self.assertEqual(dim["realm"], "trill-slowpath-drop") + self.assertEqual(dim["port"], "11") + self.assertEqual(x["value"], 50) + elif i == 17: + self.assertEqual(dim["realm"], "trill-slowpath-drop") + self.assertEqual(dim["port"], "12") + self.assertEqual(x["value"], 60) + i = i + 1 + + def test_packet_trace_supported_drop_reasons(self): + rep = PTParser() + rep.process(self.packet_trace_supported_drop_reasons_1) + serializer = PTToMonasca() + ret = serializer.serialize(self._host, rep) + self.assertEqual(ret[0], True) + data = json.loads(ret[1]) + self.assertTrue(len(data) == 1) + d = data[0] + self.assertTrue("timestamp" in d) + self.assertTrue("name" in d) + self.assertTrue("dimensions" in d) + self.assertEqual(d["name"], "broadview.pt.packet-trace-supported-drop-reasons") + dim = d["dimensions"] + self.assertTrue("reasons" in dim) + self.assertEqual(len(dim["reasons"]), 2) + self.assertEqual(dim["reasons"][0], "l2-lookup-failure") + self.assertEqual(dim["reasons"][1], "vlan-mismatch") + +if __name__ == "__main__": + unittest.main() + diff --git a/broadview_collector/tools/pt/pt_drop_counter_report.py b/broadview_collector/tools/pt/pt_drop_counter_report.py new file mode 100644 index 0000000..241743a --- /dev/null +++ b/broadview_collector/tools/pt/pt_drop_counter_report.py @@ -0,0 +1,155 @@ +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + +import getopt +import sys +from pt_sim import PTSim + +''' +Program to simulate sending a get-packet-trace-profile message +from a BroadView agent. + +''' + +class PTDropCounterReport(PTSim): + + def __init__(self, host, port): + super(PTDropCounterReport, self).__init__(host, port) + self._data = { + "jsonrpc": "2.0", + "method": " get-packet-trace-drop-counter-report", + "asic-id": "1", + "version": "1", + "report": [ + { + "realm": "vlan-xlate-miss-drop", + "data": [ + { + "port": "1", + "count": 10 + }, + { + "port": "5", + "count": 20 + }, + { + "port": "6", + "count": 30 + }, + { + "port": "10", + "count": 40 + }, + { + "port": "11", + "count": 50 + }, + { + "port": "12", + "count": 60 + } + ] + }, + { + "realm": "bpdu-drop", + "data": [ + { + "port": "11", + "count": 700 + }, + { + "port": "15", + "count": 200 + }, + { + "port": "16", + "count": 300 + }, + { + "port": "20", + "count": 400 + }, + { + "port": "21", + "count": 800 + }, + { + "port": "22", + "count": 900 + } + ] + }, + { + "realm": "trill-slowpath-drop", + "data": [ + { + "port": "51", + "count": 310 + }, + { + "port": "55", + "count": 320 + }, + { + "port": "56", + "count": 330 + }, + { + "port": "60", + "count": 340 + }, + { + "port": "61", + "count": 350 + }, + { + "port": "62", + "count": 360 + } + ] + } + + ] + } + +def usage(): + print "pt_drop_counter_report [-h host] [-p port]" + +def main(): + + host = None + port = None + + try: + opts, args = getopt.getopt(sys.argv[1:], "h:p:") + except getopt.GetoptError as err: + # print help information and exit: + print str(err) # will print something like "option -a not recognized" + usage() + sys.exit(2) + for o, a in opts: + if o == "-h": + host = a + elif o == "-p": + port = a + else: + assert False, "unhandled option" + + x = PTDropCounterReport(host, port) + x.send() + +if __name__ == "__main__": + main() + + diff --git a/broadview_collector/tools/pt/pt_drop_reason.py b/broadview_collector/tools/pt/pt_drop_reason.py new file mode 100644 index 0000000..71c214e --- /dev/null +++ b/broadview_collector/tools/pt/pt_drop_reason.py @@ -0,0 +1,94 @@ +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + +import getopt +import sys +from pt_sim import PTSim + +''' +Program to simulate sending a get-packet-trace-profile message +from a BroadView agent. + +''' + +class PTDropReason(PTSim): + + def __init__(self, host, port): + super(PTDropReason, self).__init__(host, port) + self._data = { + "jsonrpc": "2.0", + "method": "get-packet-trace-drop-reason", + "asic-id": "1", + "version": "1", + "result": [ + { + "reason": "l2-lookup-failure", + "port-list": [ + "1", + "5", + "6", + "10-15" + ], + "send-dropped-packet": 1, + "trace-profile": 0, + "packet-count": 3, + "packet-threshold": 0 + }, + { + "reason": "vlan-mismatch", + "port-list": [ + "2", + "10", + "12", + "20-30" + ], + "send-dropped-packet": 1, + "trace-profile": 1, + "packet-count": 6, + "packet-threshold": 10 + } + ], + "id": 1 + } + +def usage(): + print "pt_drop_reason [-h host] [-p port]" + +def main(): + + host = None + port = None + + try: + opts, args = getopt.getopt(sys.argv[1:], "h:p:") + except getopt.GetoptError as err: + # print help information and exit: + print str(err) # will print something like "option -a not recognized" + usage() + sys.exit(2) + for o, a in opts: + if o == "-h": + host = a + elif o == "-p": + port = a + else: + assert False, "unhandled option" + + x = PTDropReason(host, port) + x.send() + +if __name__ == "__main__": + main() + + diff --git a/broadview_collector/tools/pt/pt_ecmp_resolution.py b/broadview_collector/tools/pt/pt_ecmp_resolution.py new file mode 100644 index 0000000..150a453 --- /dev/null +++ b/broadview_collector/tools/pt/pt_ecmp_resolution.py @@ -0,0 +1,106 @@ +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + +import getopt +import sys +from pt_sim import PTSim + +''' +Program to simulate a get-packet-trace-ecmp-resolution message received +from a BroadView agent. + +''' + +class PTECMPResolution(PTSim): + + def __init__(self, host, port): + super(PTECMPResolution, self).__init__(host, port) + self._data = { + "jsonrpc": "2.0", + "method": " get-packet-trace-ecmp-resolution", + "asic-id": "1", + "version": "1", + "time-stamp": self._timestamp, + "report": [ + { + "port": "1", + "ecmp-link-resolution": [ + { + "ecmp-group-id": "200256", + "ecmp-members": [["100004", "2.2.2.2", "28"],["100005", "6.6.6.1", "41"]], + "ecmp-dst-member": "100005", + "ecmp-dst-port": "41", + "ecmp-next-hop-ip": "6.6.6.2" + }, + { + "ecmp-group-id": "200100", + "ecmp-members": [["100001", "3.3.3.1", "31"], ["100002", "7.7.7.2", "21"]], + "ecmp-dst-member": "100001", + "ecmp-dst-port": "31", + "ecmp-next-hop-ip": "3.3.3.2" + } + ] + }, + { + "port": "2", + "ecmp-link-resolution": [ + { + "ecmp-group-id": "200512", + "ecmp-members": [["100002", "6.3.3.1", "61"], ["100004", "9.9.9.2", "41"]], + "ecmp-dst-member": "100010", + "ecmp-dst-port": "81", + "ecmp-next-hop-ip": "7.6.6.2" + }, + { + "ecmp-group-id": "200200", + "ecmp-members": [["100008", "4.4.4.4", "56"],["100010", "8.8.8.1", "82"]], + "ecmp-dst-member": "100002", + "ecmp-dst-port": "62", + "ecmp-next-hop-ip": "6.5.4.3" + } + ] + } + ], + "id": 1 + } + +def usage(): + print "pt_ecmp_resolution [-h host] [-p port]" + +def main(): + + host = None + port = None + + try: + opts, args = getopt.getopt(sys.argv[1:], "h:p:") + except getopt.GetoptError as err: + print str(err) + usage() + sys.exit(2) + for o, a in opts: + if o == "-h": + host = a + elif o == "-p": + port = a + else: + assert False, "unhandled option" + + x = PTECMPResolution(host, port) + x.send() + +if __name__ == "__main__": + main() + + diff --git a/broadview_collector/tools/pt/pt_lag_resolution.py b/broadview_collector/tools/pt/pt_lag_resolution.py new file mode 100644 index 0000000..7a2d698 --- /dev/null +++ b/broadview_collector/tools/pt/pt_lag_resolution.py @@ -0,0 +1,95 @@ +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + +import getopt +import sys +from pt_sim import PTSim + +''' +Program to simulate sending a get-packet-trace-lag-resolution message +from a BroadView agent. + +''' + +class PTLAGResolution(PTSim): + + def __init__(self, host, port): + super(PTLAGResolution, self).__init__(host, port) + self._data = { + "jsonrpc": "2.0", + "method": " get-packet-trace-lag-resolution", + "asic-id": "1", + "version": "1", + "time-stamp": self._timestamp, + "report": [ + { + "port": "1", + "lag-link-resolution": { + "lag-id": "1", + "lag-members": [ + "1", + "2", + "3", + "4" + ], + "dst-lag-member": "4" + } + }, + { + "port": "2", + "lag-link-resolution": { + "lag-id": "2", + "lag-members": [ + "5", + "6", + "7", + "8" + ], + "dst-lag-member": "7" + } + } + ], + "id": 1 + } + +def usage(): + print "pt_lag_resolution [-h host] [-p port]" + +def main(): + + host = None + port = None + + try: + opts, args = getopt.getopt(sys.argv[1:], "h:p:") + except getopt.GetoptError as err: + # print help information and exit: + print str(err) # will print something like "option -a not recognized" + usage() + sys.exit(2) + for o, a in opts: + if o == "-h": + host = a + elif o == "-p": + port = a + else: + assert False, "unhandled option" + + x = PTLAGResolution(host, port) + x.send() + +if __name__ == "__main__": + main() + + diff --git a/broadview_collector/tools/pt/pt_profile.py b/broadview_collector/tools/pt/pt_profile.py new file mode 100644 index 0000000..f9cf973 --- /dev/null +++ b/broadview_collector/tools/pt/pt_profile.py @@ -0,0 +1,134 @@ +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + +import getopt +import sys +from pt_sim import PTSim + +''' +Program to simulate sending a get-packet-trace-profile message +from a BroadView agent. + +''' + +class PTProfile(PTSim): + + def __init__(self, host, port): + super(PTProfile, self).__init__(host, port) + self._data = { + "jsonrpc": "2.0", + "method": "get-packet-trace-profile", + "asic-id": "1", + "version": "1", + "time-stamp": "2014-11-18 - 00:15:04 ", + "report": [ + { + "port": "1", + "trace-profile": [ + { + "realm": "lag-link-resolution", + "data": { + "lag-id": "2", + "lag-members": ["1", "2", "3", "4"], + "dst-lag-member": "4" + } + }, + { + "realm": "ecmp-link-resolution", + "data": [ + { + "ecmp-group-id": "200256", + "ecmp-members": [["100004", "2.2.2.2", "28"],["100005", "6.6.6.1", "41"]], + "ecmp-dst-member": "100005", + "ecmp-dst-port": "41", + "ecmp-next-hop-ip": "6.6.6.2" + }, + { + "ecmp-group-id": "200100", + "ecmp-members": [["100001", "3.3.3.1", "31"], +["100002", "7.7.7.2", "21"]], + "ecmp-dst-member": "100001", + "ecmp-dst-port": "31", + "ecmp-next-hop-ip": "3.3.3.2" + } + ] + } + ] + }, + { + "port": "2", + "trace-profile": [ + { + "realm": "lag-link-resolution", + "data": { + "lag-id": "3", + "lag-members": ["5","6","7","8"], + "dst-lag-member": "6" + } + }, + { + "realm": "ecmp-link-resolution", + "data": [ + { + "ecmp-group-id": "200512", + "ecmp-members": [["200004", "3.2.2.2", "38"],["100005", "6.6.6.1", "41"]], + "ecmp-dst-member": "100010", + "ecmp-dst-port": "19", + "ecmp-next-hop-ip": "8.8.8.2" + }, + { + "ecmp-group-id": "200200", + "ecmp-members": [["100002", "4.3.3.1", "76"], ["100002", "7.7.7.2", "21"]], + "ecmp-dst-member": "100002", + "ecmp-dst-port": "55", + "ecmp-next-hop-ip": "7.3.3.2" + } + ] + } + ] + } + ], + "id": 1 + } + +def usage(): + print "pt_profile [-h host] [-p port]" + +def main(): + + host = None + port = None + + try: + opts, args = getopt.getopt(sys.argv[1:], "h:p:") + except getopt.GetoptError as err: + # print help information and exit: + print str(err) # will print something like "option -a not recognized" + usage() + sys.exit(2) + for o, a in opts: + if o == "-h": + host = a + elif o == "-p": + port = a + else: + assert False, "unhandled option" + + x = PTProfile(host, port) + x.send() + +if __name__ == "__main__": + main() + + diff --git a/broadview_collector/tools/pt/pt_sim.py b/broadview_collector/tools/pt/pt_sim.py new file mode 100644 index 0000000..3f5a983 --- /dev/null +++ b/broadview_collector/tools/pt/pt_sim.py @@ -0,0 +1,51 @@ +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + +import json +import requests +import datetime +import time + +''' +Base class for packet trace agent simulation classes + +''' + +class PTSim(object): + + def __init__(self, host=None, port=None): + if not host: + self._host = "127.0.0.1" + else: + self._host = host + if not port: + self._port = 8082 + else: + self._port = port + self.setUp() + + def setUp(self): + # convert datetime string to timestamp + + d = str(datetime.datetime.now()).split(" ") + t = d[1].split(".")[0] + self._timestamp = "{} - {}".format(d[0], t) + + # initialize data, overridden by subclass + self._data = None + + def send(self): + j = json.dumps(self._data) + r = requests.post('http://{}:{}'.format(self._host, self._port), json=j) +