diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..3cff252 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,23 @@ +# Copyright 2019 John-Mark Gurney. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. diff --git a/Makefile b/Makefile index 8aa4d8c..6586823 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ -MODULES=vlanmang.py +MODULES=vlanmang test: - (echo $(MODULES) | entr sh -c 'python -m coverage run -m unittest $(basename $(MODULES)) && coverage report --omit=p/\* -m -i') + (ls $(MODULES)/*.py | entr sh -c 'python -m coverage run -m unittest $(basename $(MODULES)) && coverage report --omit=p/\* -m -i') env: (virtualenv p && . ./p/bin/activate && pip install -r requirements.txt) diff --git a/requirements.txt b/requirements.txt index 4e53704..c518e6b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ -pysnmp -coverage -mock +# use setup.py for dependancy info +-e . + +-e .[dev] diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..fba3aed --- /dev/null +++ b/setup.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python + +from setuptools import setup + +setup(name='vlanmang', + version='0.1.0', + description='A utility to use SNMP to configure switch VLANs', + author='John-Mark Gurney', + author_email='jmg@funkthat.com', + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Environment :: Console', + 'Intended Audience :: Information Technology', + 'Intended Audience :: System Administrators', + 'License :: OSI Approved :: BSD License', + 'Topic :: Security', + 'Topic :: System :: Networking', + 'Topic :: Utilities', + ], + url='https://www.funkthat.com/gitea/jmg/vlanmang', + packages=[ 'vlanmang', ], + install_requires=[ + 'pysnmp', + 'pysnmp-mibs', + 'mock', + ], + extras_require = { + 'dev': [ 'coverage' ], + }, + entry_points={ + 'console_scripts': [ + 'vlanmang = vlanmang.__main__:main', + ] + } +) diff --git a/vlanmang.py b/vlanmang/__init__.py similarity index 93% rename from vlanmang.py rename to vlanmang/__init__.py index 1671528..aa737a9 100644 --- a/vlanmang.py +++ b/vlanmang/__init__.py @@ -1,7 +1,33 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +# +# Copyright 2019 John-Mark Gurney. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# from pysnmp.hlapi import * +from pysnmp.proto.rfc1905 import NoSuchInstance from pysnmp.smi.builder import MibBuilder from pysnmp.smi.view import MibViewController @@ -11,11 +37,19 @@ import mock import random import unittest +__author__ = 'John-Mark Gurney' +__copyright__ = 'Copyright 2019 John-Mark Gurney. All rights reserved.' +__license__ = '2-clause BSD license' +__version__ = '0.1.0' +__all__ = [ + 'SwitchConfig', + 'checkchanges', + 'SNMPSwitch', +] + _mbuilder = MibBuilder() _mvc = MibViewController(_mbuilder) -#import data - # received packages # pvid: dot1qPvid # @@ -359,8 +393,12 @@ class SNMPSwitch(object): def _get(self, oid): varBinds = self._getmany(oid) - varBind = varBinds[0] - return varBind[1] + var = varBinds[0][1] + + if isinstance(var, NoSuchInstance): + raise ValueError(repr(var)) + + return var def _set(self, oid, value): oid = ObjectIdentity(*oid) @@ -557,7 +595,6 @@ class _TestMisc(unittest.TestCase): def setUp(self): import test_data - self.skipTest('foo') self._test_data = test_data def test_intstobits(self): @@ -809,9 +846,6 @@ class _TestMisc(unittest.TestCase): self.assertEqual(set(res), set(validres)) class _TestSNMPSwitch(unittest.TestCase): - def setUp(self): - self.skipTest('foo') - @mock.patch('vlanmang.SNMPSwitch._getmany') def test_get(self, gm): # that a switch @@ -872,9 +906,11 @@ class _TestSwitch(unittest.TestCase): _skipSwitchTests: # pragma: no cover self.skipTest('Need a GS108T switch to run these tests') - host, authkey, privkey = open('test.creds').read().split() - self.switch = SNMPSwitch(host, authKey=authkey, - privKey=privkey, privProtocol=usmDESPrivProtocol) + with open('test.creds') as fp: + host, username, authkey, privkey = fp.read().split() + self.switch = SNMPSwitch(host, username=username, + authKey=authkey, privKey=privkey, + privProtocol=usmDESPrivProtocol) self.switchmodel = self.switch._get(('ENTITY-MIB', 'entPhysicalModelName', 1)) @@ -896,32 +932,6 @@ class _TestSwitch(unittest.TestCase): self.assertEqual(switch.getportmapping(), resp) - def test_egress(self): - switch = self.switch - - egress = switch.getegress(1, 2, 3) - - checkegress = { - 1: '1' * 8 + '0' * 5 + '1' * 4 + '0' * 23, - 2: '0' * 8 * 5, - 3: '0' * 8 * 5, - } - - self.assertEqual(egress, checkegress) - - def test_untagged(self): - switch = self.switch - - untagged = switch.getuntagged(1, 2, 3) - - checkuntagged = { - 1: '1' * 8 * 5, - 2: '1' * 8 * 5, - 3: '1' * 8 * 5, - } - - self.assertEqual(untagged, checkuntagged) - def test_vlan(self): switch = self.switch @@ -939,7 +949,14 @@ class _TestSwitch(unittest.TestCase): pvidres = { x: 1 for x in xrange(1, 9) } pvidres.update({ x: 1 for x in xrange(14, 18) }) - self.assertEqual(switch.getpvid(), pvidres) + + rpvidres = switch.getpvid() + + # private config + del pvidres[7] + del rpvidres[7] + + self.assertEqual(rpvidres, pvidres) testname = 'Sometestname' diff --git a/vlanmang/__main__.py b/vlanmang/__main__.py new file mode 100644 index 0000000..6eaa5aa --- /dev/null +++ b/vlanmang/__main__.py @@ -0,0 +1,4 @@ +from . import main + +if __name__ == '__main__': + main()