Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions netdiff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
from .parsers.bmx6 import Bmx6Parser # noqa
from .parsers.netjson import NetJsonParser # noqa
from .parsers.cnml import CnmlParser # noqa
from .parsers.openvpn import OpenvpnParser #noqa
from .utils import diff # noqa
58 changes: 58 additions & 0 deletions netdiff/parsers/openvpn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import networkx
from openvpn_status import ParsingError, parse_status

from ..exceptions import ConversionException, ParserError
from .base import BaseParser


class OpenvpnParser(BaseParser):
""" OpenVPN status log parser """
protocol = 'openvpn'
server_address = '127.0.0.1' # Testing purposes
version = '1'
metric = '0'

def to_python(self, data):
status = parse_status(data)
nodes = []
for i in status.client_list:
node = status.client_list[i]
nodes.append({
'commonName': node.common_name,
'bytesSent': node.bytes_sent,
'bytesReceived': node.bytes_received,
'connectedSince': node.connected_since,
'realAddress': str(node.real_address)
})

return {
'type': 'OpenVPN',
'nodes': nodes,
'updated_at': status.updated_at,
'server': self.server_address
}

def parse(self, data):
"""
Converts a OpenVPN JSON to a NetworkX Graph object
which is then returned.
"""
# initialize graph and list of aggregated nodes
graph = networkx.Graph()
if 'type' not in data or data['type'] != 'OpenVPN':
raise ParserError('Parse Error, not a OpenVPN object')
required_keys = ['nodes', 'server']
for key in required_keys:
if key not in data:
raise ParserError('Parse Error, "%s" key not found' % key)

graph.add_node(data['server'])
for link in data['nodes']:
try:
source = data['server']
target = link['realAddress']
except KeyError as e:
raise ParserError('Parse Error, "%s" key not found' % key)
graph.add_node(target)
graph.add_edge(source, target, weight=1)
return graph
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ networkx<2.0
requests<3.0
six
libcnml<0.10.0
openvpn-status<0.2
12 changes: 12 additions & 0 deletions tests/static/openvpn-2-links.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
OpenVPN CLIENT LIST
Updated,Thu Jun 18 08:12:15 2015
Common Name,Real Address,Bytes Received,Bytes Sent,Connected Since
foo@example.com,10.10.10.10:49502,334948,1973012,Thu Jun 18 04:23:03 2015
bar@example.com,10.10.10.10:64169,1817262,28981224,Thu Jun 18 04:08:39 2015
ROUTING TABLE
Virtual Address,Common Name,Real Address,Last Ref
192.168.255.134,foo@example.com,10.10.10.10:49502,Thu Jun 18 08:12:09 2015
192.168.255.126,bar@example.com,10.10.10.10:64169,Thu Jun 18 08:11:55 2015
GLOBAL STATS
Max bcast/mcast queue length,0
END
33 changes: 33 additions & 0 deletions tests/test_openvpn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import os

import networkx
import six
from netdiff import OpenvpnParser
from netdiff.exceptions import ParserError, TopologyRetrievalError
from netdiff.tests import TestCase

CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
links2 = open('{0}/static/openvpn-2-links.txt'.format(CURRENT_DIR)).read()


class TestOpenvpnParser(TestCase):

def test_parse(self):
p = OpenvpnParser(links2)
self.assertIsInstance(p.graph, networkx.Graph)
self.assertEqual(p.version, '1')
self.assertEqual(p.metric, '0')

def test_json_dict(self):
p = OpenvpnParser(links2)
data = p.json(dict=True)
self.assertIsInstance(data, dict)
self.assertEqual(data['type'], 'NetworkGraph')
self.assertEqual(data['protocol'], 'openvpn')
self.assertEqual(data['version'], '1')
self.assertEqual(data['revision'], None)
self.assertEqual(data['metric'], '0')
self.assertIsInstance(data['nodes'], list)
self.assertIsInstance(data['links'], list)
self.assertEqual(len(data['nodes']), 3)
self.assertEqual(len(data['links']), 2)