Example #1
0
    def setUp(self):
        self.switch = RemoteSwitch(SwitchDescriptor(
            model="juniper", hostname="toto", username="******",
            password="******", port=1234, netman_server=self.netman_url))

        self.requests_mock = flexmock()
        self.switch.requests = self.requests_mock
        self.headers = {
            'Netman-Port': "1234",
            'Netman-Model': 'juniper',
            'Netman-Password': '******',
            'Netman-Username': '******',
            'Netman-Max-Version': "2",
            'Netman-Verbose-Errors': 'yes',
        }
Example #2
0
class RemoteSwitchARPRoutingTest(unittest.TestCase):
    netman_url = 'http://netman.example.org:1234'

    def setUp(self):
        self.switch = RemoteSwitch(SwitchDescriptor(
            model="juniper", hostname="toto", username="******",
            password="******", port=1234, netman_server=self.netman_url))

        self.requests_mock = flexmock()
        self.switch.requests = self.requests_mock
        self.headers = {
            'Netman-Port': "1234",
            'Netman-Model': 'juniper',
            'Netman-Password': '******',
            'Netman-Username': '******',
            'Netman-Max-Version': "2",
            'Netman-Verbose-Errors': 'yes',
        }

    def tearDown(self):
        flexmock_teardown()

    def test_set_vlan_arp_routing_state_OFF_should_send_false(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/vlans/2000/arp-routing',
            headers=self.headers,
            data='false'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.set_vlan_arp_routing_state(2000, OFF)

    def test_set_vlan_arp_routing_state_ON_should_send_true(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/vlans/2000/arp-routing',
            headers=self.headers,
            data='true'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.set_vlan_arp_routing_state(2000, ON)
Example #3
0
class RemoteSwitchUnicastRpfTest(unittest.TestCase):
    netman_url = 'http://netman.example.org:1234'

    def setUp(self):
        self.switch = RemoteSwitch(SwitchDescriptor(
            model="juniper", hostname="toto", username="******",
            password="******", port=1234, netman_server=self.netman_url))

        self.requests_mock = flexmock()
        self.switch.requests = self.requests_mock
        self.headers = {
            'Netman-Port': "1234",
            'Netman-Model': 'juniper',
            'Netman-Password': '******',
            'Netman-Username': '******',
            'Netman-Max-Version': "2",
            'Netman-Verbose-Errors': 'yes',
        }

    def tearDown(self):
        flexmock_teardown()

    def test_set_vlan_unicast_rpf_mode_strict_should_send_true(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/vlans/2000/unicast-rpf-mode',
            headers=self.headers,
            data=str(STRICT)
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.set_vlan_unicast_rpf_mode(2000, STRICT)

    def test_unset_vlan_unicast_rpf_mode_should_send_true(self):
        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches/toto/vlans/2000/unicast-rpf-mode',
            headers=self.headers,
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.unset_vlan_unicast_rpf_mode(2000)
Example #4
0
    def setUp(self):
        self.switch = RemoteSwitch(SwitchDescriptor(
            model="juniper", hostname="toto", username="******",
            password="******", port=1234, netman_server=self.netman_url))

        self.requests_mock = flexmock()
        self.switch.requests = self.requests_mock
        self.headers = {
            'Netman-Port': 1234,
            'Netman-Model': 'juniper',
            'Netman-Password': '******',
            'Netman-Username': '******',
            'Netman-Verbose-Errors': 'yes',
        }
Example #5
0
    def test_remote_sessions_can_continue_on_a_different_netman(self):
        with NetmanTestApp() as partial_client1, NetmanTestApp() as partial_client2:
            switch_descriptor = get_available_switch("juniper")

            client1 = partial_client1(switch_descriptor)
            first_netman_url = "{}:{}".format(client1.host, client1.port)

            client2 = partial_client2(switch_descriptor)
            second_netman_url = "{}:{}".format(client2.host, client2.port)

            remote_switch = RemoteSwitch(switch_descriptor)
            remote_switch._proxy = first_netman_url
            switch = FlowControlSwitch(remote_switch, ThreadingLockFactory().new_lock())

            with switch.transaction():
                switch.add_vlan(1498, "one")

                remote_switch._proxy = second_netman_url

                switch.add_vlan(1499, "two")

            assert_that(client1.get("/switches/{hostname}/vlans/1498").json()["name"], is_("one"))
            assert_that(client1.get("/switches/{hostname}/vlans/1499").json()["name"], is_("two"))
Example #6
0
    def test_multi_proxy_few(self, m_uuid):
        self.switch = RemoteSwitch(SwitchDescriptor(
            model="juniper", hostname="toto", username="******",
            password="******", port=1234, netman_server=[self.netman_url, "1.2.3.4", "5.6.7.8"]))

        self.requests_mock = flexmock()
        self.switch.requests = self.requests_mock

        m_uuid.return_value = '0123456789'
        self.requests_mock.should_receive("post").once().ordered().with_args(
            url=self.netman_url+'/switches-sessions/0123456789',
            headers={
                'Netman-Port': 1234,
                'Netman-Model': 'juniper',
                'Netman-Password': '******',
                'Netman-Username': '******',
                'Netman-Verbose-Errors': 'yes',
                'Netman-Proxy-Server': '1.2.3.4,5.6.7.8',
                'Netman-Max-Version': 2,
                'Netman-Session-Id': '0123456789'
            },
            data=JsonData(hostname="toto")
        ).and_return(
            Reply(
                content=json.dumps({'session_id': '0123456789'}),
                status_code=201))

        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches-sessions/0123456789',
            headers={'Netman-Verbose-Errors': "yes",
                     'Netman-Max-Version': 2,
                     'Netman-Session-Id': '0123456789'}
        ).and_return(
            Reply(
                content="",
                status_code=204))

        self.switch.start_transaction()
        self.switch.end_transaction()
        self.setUp()
        self.test_add_bond()
Example #7
0
    def setUp(self):
        if self.switch_specs is not None:
            specs = type(self).switch_specs
        else:
            specs = next(s for s in available_models
                         if s["switch_descriptor"].model == self._dev_sample)

        self.switch_descriptor = specs["switch_descriptor"]
        self.test_port = specs["test_port_name"]
        self.test_ports = specs["ports"]
        self.test_vrrp_track_id = specs.get("test_vrrp_track_id")

        self.switch_descriptor.netman_server = ''
        self.remote_switch = RemoteSwitch(self.switch_descriptor)
        self.remote_switch.requests = FlaskRequest(app.test_client())

        self.client = ValidatingCachedSwitch(self.remote_switch)
        self.try_to = ExceptionIgnoringProxy(self.client,
                                             [NotImplementedError])
        self.janitor = ExceptionIgnoringProxy(
            self.client, [NotImplementedError, NetmanException])

        self.client.connect()
        self.client.start_transaction()
Example #8
0
class RemoteSwitchTest(unittest.TestCase):
    netman_url = 'http://netman.example.org:1234'

    def setUp(self):
        self.switch = RemoteSwitch(SwitchDescriptor(
            model="juniper", hostname="toto", username="******",
            password="******", port=1234, netman_server=self.netman_url))

        self.requests_mock = flexmock()
        self.switch.requests = self.requests_mock
        self.headers = {
            'Netman-Port': 1234,
            'Netman-Model': 'juniper',
            'Netman-Password': '******',
            'Netman-Username': '******',
            'Netman-Verbose-Errors': 'yes',
        }

    def tearDown(self):
        flexmock_teardown()

    def test_switch_has_a_logger_configured_with_the_switch_name(self):
        assert_that(self.switch.logger.name, is_(RemoteSwitch.__module__ + ".toto"))

    @mock.patch('uuid.uuid4')
    def test_start_then_commit_returns_to_normal_behavior(self, m_uuid):
        m_uuid.return_value = '0123456789'
        self.headers['Netman-Session-Id'] = '0123456789'
        self.requests_mock.should_receive("post").once().with_args(
            url=self.netman_url+'/switches-sessions/0123456789',
            headers=self.headers,
            data=JsonData(hostname="toto")
        ).and_return(
            Reply(
                content=json.dumps({'session_id': '0123456789'}),
                status_code=201))

        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches-sessions/0123456789',
            headers={'Netman-Verbose-Errors': "yes",
                     'Netman-Session-Id': '0123456789'}
        ).and_return(
            Reply(
                content="",
                status_code=204))

        self.switch.start_transaction()
        self.switch.end_transaction()
        self.setUp()
        self.test_add_bond()

    @mock.patch('uuid.uuid4')
    def test_start_transaction_fails_to_obtain_a_session(self, m_uuid):
        m_uuid.return_value = '0123456789'
        self.headers['Netman-Session-Id'] = '0123456789'
        self.requests_mock.should_receive("post").once().with_args(
            url=self.netman_url+'/switches-sessions/0123456789',
            headers=self.headers,
            data=JsonData(hostname="toto")
        ).and_return(
            Reply(
                content=json.dumps({
                    "error": "",
                    "error-module": AnException.__module__,
                    "error-class": AnException.__name__
                }),
                status_code=500))

        with self.assertRaises(AnException):
            self.switch.start_transaction()

    @mock.patch('uuid.uuid4')
    def test_end_session_fails_returns_to_normal_behavior(self, m_uuid):
        m_uuid.return_value = '0123456789'
        self.headers['Netman-Session-Id'] = '0123456789'
        self.requests_mock.should_receive("post").once().with_args(
            url=self.netman_url+'/switches-sessions/0123456789',
            headers=self.headers,
            data=JsonData(hostname="toto")
        ).and_return(
            Reply(
                content=json.dumps({'session_id': '0123456789'}),
                status_code=201))

        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches-sessions/0123456789',
            headers={'Netman-Verbose-Errors': "yes",
                     'Netman-Session-Id': '0123456789'}
        ).and_return(
            Reply(
                content=json.dumps({
                    "error": "",
                    "error-module": AnException.__module__,
                    "error-class": AnException.__name__
                }),
                status_code=500))

        self.switch.start_transaction()
        with self.assertRaises(AnException):
            self.switch.end_transaction()
        self.setUp()
        self.test_add_bond()

    @mock.patch('uuid.uuid4')
    def test_session_is_used_when_we_are_in_a_transaction(self, m_uuid):
        m_uuid.return_value = '0123456789'
        self.headers['Netman-Session-Id'] = '0123456789'
        self.requests_mock.should_receive("post").once().with_args(
            url=self.netman_url+'/switches-sessions/0123456789',
            headers=self.headers,
            data=JsonData(hostname="toto")
        ).and_return(
            Reply(
                content=json.dumps({'session_id': '0123456789'}),
                status_code=201))

        self.requests_mock.should_receive("post").once().with_args(
            url=self.netman_url+'/switches-sessions/0123456789/bonds',
            headers=self.headers,
            data=JsonData(number=6)
        ).and_return(
            Reply(
                content='',
                status_code=201))

        self.switch.start_transaction()
        self.switch.add_bond(6)

    @mock.patch('uuid.uuid4')
    def test_commit_transaction(self, m_uuid):
        m_uuid.return_value = '0123456789'

        self.headers['Netman-Session-Id'] = '0123456789'
        self.requests_mock.should_receive("post").once().with_args(
            url=self.netman_url+'/switches-sessions/0123456789',
            headers=self.headers,
            data=JsonData(hostname="toto")
        ).and_return(
            Reply(
                content=json.dumps({'session_id': '0123456789'}),
                status_code=201))

        self.requests_mock.should_receive("post").once().with_args(
            url=self.netman_url+'/switches-sessions/0123456789/actions',
            data='commit',
            headers={'Netman-Verbose-Errors': "yes",
                     'Netman-Session-Id': '0123456789'}
        ).and_return(
            Reply(
                content=json.dumps({
                    "error": "",
                    "error-module": AnException.__module__,
                    "error-class": AnException.__name__
                }),
                status_code=500))

        self.switch.start_transaction()
        with self.assertRaises(AnException):
            self.switch.commit_transaction()

    @mock.patch('uuid.uuid4')
    def test_rollback_transaction(self, m_uuid):
        m_uuid.return_value = '0123456789'
        self.headers['Netman-Session-Id'] = '0123456789'
        self.requests_mock.should_receive("post").once().ordered().with_args(
            url=self.netman_url+'/switches-sessions/0123456789',
            headers=self.headers,
            data=JsonData(hostname="toto")
        ).and_return(
            Reply(
                content=json.dumps({'session_id': '0123456789'}),
                status_code=201))

        self.requests_mock.should_receive("post").once().ordered().with_args(
            url=self.netman_url+'/switches-sessions/0123456789/actions',
            data='rollback',
            headers={'Netman-Verbose-Errors': "yes",
                     'Netman-Session-Id': '0123456789'}
        ).and_return(
            Reply(
                content=json.dumps({
                    "error": "",
                    "error-module": AnException.__module__,
                    "error-class": AnException.__name__
                }),
                status_code=500))

        self.switch.start_transaction()
        with self.assertRaises(AnException):
            self.switch.rollback_transaction()

    def test_get_vlans(self):
        self.requests_mock.should_receive("get").once().with_args(
            url=self.netman_url+'/switches/toto/vlans',
            headers=self.headers
        ).and_return(
            Reply(
                content=open_fixture('get_switch_hostname_vlans.json').read(),
                status_code=200))

        vlan_1, vlan_2 = self.switch.get_vlans()

        assert_that(vlan_1.number, is_(1))
        assert_that(vlan_1.name, is_('One'))
        assert_that(vlan_1.ips, is_([IPNetwork('1.1.1.1/24')]))
        assert_that(vlan_1.vrf_forwarding, is_("MY_VRF"))
        assert_that(vlan_1.access_groups[IN], is_("Blah_blah"))

        assert_that(vlan_2.number, is_(2))
        assert_that(vlan_2.name, is_(''))
        assert_that(vlan_2.ips, is_([IPNetwork('2.2.2.2/24'), IPNetwork('3.3.3.3/24')]))

    def test_get_interfaces(self):
        self.requests_mock.should_receive("get").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces',
            headers=self.headers
        ).and_return(
            Reply(
                content=open_fixture('get_switch_hostname_interfaces.json').read(),
                status_code=200))

        if1, if2, if3, if4 = self.switch.get_interfaces()

        assert_that(if1.name, equal_to("ethernet 1/4"))
        assert_that(if1.shutdown, equal_to(False))
        assert_that(if1.port_mode, equal_to(TRUNK))
        assert_that(if1.access_vlan, equal_to(None))
        assert_that(if1.trunk_native_vlan, equal_to(2999))
        assert_that(if1.trunk_vlans, equal_to([3000, 3001, 3002]))

        assert_that(if2.name, equal_to("FastEthernet0/3"))
        assert_that(if2.shutdown, equal_to(True))
        assert_that(if2.port_mode, equal_to(ACCESS))
        assert_that(if2.access_vlan, equal_to(1999))
        assert_that(if2.trunk_native_vlan, equal_to(None))
        assert_that(if2.trunk_vlans, equal_to([]))

        assert_that(if3.name, equal_to("GigabitEthernet0/6"))
        assert_that(if3.port_mode, equal_to(DYNAMIC))
        assert_that(if3.access_vlan, equal_to(1999))
        assert_that(if3.trunk_native_vlan, equal_to(2999))
        assert_that(if3.trunk_vlans, equal_to([3000, 3001, 3002]))

        assert_that(if4.name, equal_to("GigabitEthernet0/8"))
        assert_that(if4.shutdown, equal_to(False))
        assert_that(if4.bond_master, equal_to(12))

    def test_get_bond(self):
        self.requests_mock.should_receive("get").once().with_args(
            url=self.netman_url+'/switches/toto/bonds/3',
            headers=self.headers
        ).and_return(
            Reply(
                content=open_fixture('get_switch_hostname_bond.json').read(),
                status_code=200))

        if1 = self.switch.get_bond(3)

        assert_that(if1.number, equal_to(3))
        assert_that(if1.link_speed, equal_to('1g'))
        assert_that(if1.interface.name, equal_to("ae3"))
        assert_that(if1.interface.shutdown, equal_to(True))
        assert_that(if1.interface.port_mode, equal_to(ACCESS))
        assert_that(if1.interface.access_vlan, equal_to(1999))
        assert_that(if1.interface.trunk_native_vlan, equal_to(None))
        assert_that(if1.interface.trunk_vlans, equal_to([]))
        assert_that(if1.members, equal_to(None))

    def test_get_bonds(self):
        self.requests_mock.should_receive("get").once().with_args(
            url=self.netman_url+'/switches/toto/bonds',
            headers=self.headers
        ).and_return(
            Reply(
                content=open_fixture('get_switch_hostname_bonds.json').read(),
                status_code=200))

        if1, if2, if3 = self.switch.get_bonds()

        assert_that(if1.number, equal_to(3))
        assert_that(if1.link_speed, equal_to('1g'))
        assert_that(if1.interface.name, equal_to("ae3"))
        assert_that(if1.interface.shutdown, equal_to(True))
        assert_that(if1.interface.port_mode, equal_to(ACCESS))
        assert_that(if1.interface.access_vlan, equal_to(1999))
        assert_that(if1.interface.trunk_native_vlan, equal_to(None))
        assert_that(if1.interface.trunk_vlans, equal_to([]))
        assert_that(if1.members, equal_to(None))

        assert_that(if2.number, equal_to(4))
        assert_that(if2.members, equal_to(["ge-0/0/1", "ge-1/0/1"]))
        assert_that(if2.interface.name, equal_to("ae4"))
        assert_that(if2.interface.shutdown, equal_to(False))
        assert_that(if2.interface.port_mode, equal_to(TRUNK))
        assert_that(if2.interface.access_vlan, equal_to(None))
        assert_that(if2.interface.trunk_native_vlan, equal_to(2999))
        assert_that(if2.interface.trunk_vlans, equal_to([3000, 3001, 3002]))
        assert_that(if2.members, equal_to(['ge-0/0/1', 'ge-1/0/1']))

        assert_that(if3.number, equal_to(6))
        assert_that(if3.link_speed, equal_to('10g'))
        assert_that(if3.interface.name, equal_to("ae6"))
        assert_that(if2.interface.shutdown, equal_to(False))
        assert_that(if3.interface.port_mode, equal_to(DYNAMIC))
        assert_that(if3.interface.access_vlan, equal_to(1999))
        assert_that(if3.interface.trunk_native_vlan, equal_to(2999))
        assert_that(if3.interface.trunk_vlans, equal_to([3000, 3001, 3002]))
        assert_that(if3.members, equal_to(None))

    def test_add_vlan(self):
        self.requests_mock.should_receive("post").once().with_args(
            url=self.netman_url+'/switches/toto/vlans',
            headers=self.headers,
            data=JsonData(number=2000, name="deux-milles")
        ).and_return(
            Reply(
                content='',
                status_code=201))

        self.switch.add_vlan(2000, name="deux-milles")

    def test_add_vlan_without_a_name(self):
        self.requests_mock.should_receive("post").once().with_args(
            url=self.netman_url+'/switches/toto/vlans',
            headers=self.headers,
            data=JsonData(number=2000)
        ).and_return(
            Reply(
                content='',
                status_code=201))

        self.switch.add_vlan(2000)

    def test_add_vlan_already_exist(self):
        self.requests_mock.should_receive("post").once().with_args(
            url=self.netman_url+'/switches/toto/vlans',
            headers=self.headers,
            data=JsonData(number=2000, name="deux-milles")
        ).and_return(
            Reply(
                content=json.dumps({
                    "error": "Vlan 2000 already exists",
                    "error-module": VlanAlreadyExist.__module__,
                    "error-class": VlanAlreadyExist.__name__
                }),
                status_code=409))

        with self.assertRaises(VlanAlreadyExist) as expect:
            self.switch.add_vlan(2000, name="deux-milles")

        assert_that(str(expect.exception), equal_to("Vlan 2000 already exists"))

    def test_remove_vlan(self):
        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches/toto/vlans/2000',
            headers=self.headers,
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.remove_vlan(2000)

    def test_put_access_groups_in(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/vlans/2500/access-groups/in',
            headers=self.headers,
            data='spaceless-string'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.set_vlan_access_group(2500, IN, "spaceless-string")

    def test_put_access_groups_out(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/vlans/2500/access-groups/out',
            headers=self.headers,
            data='spaceless-string'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.set_vlan_access_group(2500, OUT, "spaceless-string")

    def test_remove_access_groups_in(self):
        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches/toto/vlans/2500/access-groups/in',
            headers=self.headers
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.remove_vlan_access_group(2500, IN)

    def test_remove_access_groups_out(self):
        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches/toto/vlans/2500/access-groups/out',
            headers=self.headers
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.remove_vlan_access_group(2500, OUT)

    def test_add_ip_to_vlan(self):
        self.requests_mock.should_receive("post").once().with_args(
            url=self.netman_url+'/switches/toto/vlans/2500/ips',
            headers=self.headers,
            data="1.2.3.4/25"
        ).and_return(
            Reply(
                content='',
                status_code=201))

        self.switch.add_ip_to_vlan(2500, IPNetwork("1.2.3.4/25"))

    def test_remove_ip(self):
        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches/toto/vlans/2500/ips/1.2.3.4/25',
            headers=self.headers
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.remove_ip_from_vlan(2500, IPNetwork("1.2.3.4/25"))

    def test_set_vlan_vrf(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/vlans/2500/vrf-forwarding',
            headers=self.headers,
            data="DEFAULT_LAN"
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.set_vlan_vrf(2500, "DEFAULT_LAN")

    def test_remove_vlan_vrf(self):
        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches/toto/vlans/2500/vrf-forwarding',
            headers=self.headers
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.remove_vlan_vrf(2500)

    def test_port_mode_access(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces/ge-0/0/6/port-mode',
            headers=self.headers,
            data='access'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.set_access_mode("ge-0/0/6")

    def test_port_mode_trunk(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces/ge-0/0/6/port-mode',
            headers=self.headers,
            data='trunk'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.set_trunk_mode("ge-0/0/6")

    def test_bond_port_mode_access(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/bonds/123/port-mode',
            headers=self.headers,
            data='access'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.set_bond_access_mode(123)

    def test_bond_port_mode_trunk(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/bonds/123/port-mode',
            headers=self.headers,
            data='trunk'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.set_bond_trunk_mode(123)

    def test_set_access_vlan(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces/ge-0/0/6/access-vlan',
            headers=self.headers,
            data='1000'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.set_access_vlan("ge-0/0/6", 1000)

    def test_remove_access_vlan(self):
        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces/ge-0/0/6/access-vlan',
            headers=self.headers
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.remove_access_vlan("ge-0/0/6")

    def test_set_native_vlan(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces/ge-0/0/6/trunk-native-vlan',
            headers=self.headers,
            data='1000'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.configure_native_vlan("ge-0/0/6", 1000)

    def test_remove_native_vlan(self):
        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces/ge-0/0/6/trunk-native-vlan',
            headers=self.headers,
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.remove_native_vlan("ge-0/0/6")

    def test_set_bond_native_vlan(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/bonds/123/trunk-native-vlan',
            headers=self.headers,
            data='1000'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.configure_bond_native_vlan(123, 1000)

    def test_remove_bond_native_vlan(self):
        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches/toto/bonds/123/trunk-native-vlan',
            headers=self.headers,
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.remove_bond_native_vlan(123)

    def test_add_trunk_vlan(self):
        self.requests_mock.should_receive("post").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces/ge-0/0/6/trunk-vlans',
            headers=self.headers,
            data='1000'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.add_trunk_vlan("ge-0/0/6", 1000)

    def test_remove_trunk_vlan(self):
        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces/ge-0/0/6/trunk-vlans/1000',
            headers=self.headers
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.remove_trunk_vlan("ge-0/0/6", 1000)

    def test_add_bond_trunk_vlan(self):
        self.requests_mock.should_receive("post").once().with_args(
            url=self.netman_url+'/switches/toto/bonds/123/trunk-vlans',
            headers=self.headers,
            data='1000'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.add_bond_trunk_vlan(123, 1000)

    def test_remove_bond_trunk_vlan(self):
        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches/toto/bonds/123/trunk-vlans/1000',
            headers=self.headers
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.remove_bond_trunk_vlan(123, 1000)

    def test_set_interface_description(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces/ge-0/0/6/description',
            headers=self.headers,
            data='Resistance is futile'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.set_interface_description("ge-0/0/6", "Resistance is futile")

    def test_remove_interface_description(self):
        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces/ge-0/0/6/description',
            headers=self.headers
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.remove_interface_description("ge-0/0/6")

    def test_set_bond_description(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/bonds/123/description',
            headers=self.headers,
            data='Resistance is futile'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.set_bond_description(123, "Resistance is futile")

    def test_remove_bond_description(self):
        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches/toto/bonds/123/description',
            headers=self.headers
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.remove_bond_description(123)

    def test_edit_interface_spanning_tree_succeeds(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces/ge-0/0/6/spanning-tree',
            headers=self.headers,
            data=json.dumps({"edge": True})
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.edit_interface_spanning_tree("ge-0/0/6", edge=True)

    def test_edit_interface_spanning_tree_optional_params(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces/ge-0/0/6/spanning-tree',
            headers=self.headers,
            data=json.dumps({})
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.edit_interface_spanning_tree("ge-0/0/6")

    def test_enable_interface(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces/ge-0/0/6/shutdown',
            headers=self.headers,
            data='false'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.openup_interface("ge-0/0/6")

    def test_disable_interface(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces/ge-0/0/6/shutdown',
            headers=self.headers,
            data='true'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.shutdown_interface("ge-0/0/6")

    def test_add_bond(self):
        self.requests_mock.should_receive("post").once().with_args(
            url=self.netman_url+'/switches/toto/bonds',
            headers=self.headers,
            data=JsonData(number=6)
        ).and_return(
            Reply(
                content='',
                status_code=201))

        self.switch.add_bond(6)

    def test_remove(self):
        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches/toto/bonds/6',
            headers=self.headers
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.remove_bond(6)

    def test_add_interface_to_bond(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces/ge-0/0/6/bond-master',
            headers=self.headers,
            data='10'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.add_interface_to_bond('ge-0/0/6', 10)

    def test_remove_interface_from_bond(self):
        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces/ge-0/0/6/bond-master',
            headers=self.headers
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.remove_interface_from_bond('ge-0/0/6')

    def test_edit_bond_spanning_tree(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/bonds/5/spanning-tree',
            headers=self.headers,
            data=json.dumps({"edge": True})
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.edit_bond_spanning_tree(5, edge=True)

    def edit_bond_spanning_tree_optional_params(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/bonds/5/spanning-tree',
            headers=self.headers,
            data=json.dumps({})
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.edit_bond_spanning_tree(5)

    def test_change_bond_speed(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/bonds/10/link-speed',
            headers=self.headers,
            data='1g'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.set_bond_link_speed(10, '1g')

    def test_change_bond_speed_missing_bond(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/bonds/10/link-speed',
            headers=self.headers,
            data='1g'
        ).and_return(
            Reply(
                content=json.dumps({
                    "error": "Bond 10 not found",
                    "error-module": UnknownBond.__module__,
                    "error-class": UnknownBond.__name__
                }),
                status_code=404))

        with self.assertRaises(UnknownBond) as expect:
            self.switch.set_bond_link_speed(10, '1g')

        assert_that(str(expect.exception), equal_to("Bond 10 not found"))

    def test_change_bond_speed_wrong_value(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/bonds/10/link-speed',
            headers=self.headers,
            data='1z'
        ).and_return(
            Reply(
                content=json.dumps({
                    "error": "Malformed bond link speed",
                    "error-module": BadBondLinkSpeed.__module__,
                    "error-class": BadBondLinkSpeed.__name__
                }),
                status_code=400))

        with self.assertRaises(BadBondLinkSpeed) as expect:
            self.switch.set_bond_link_speed(10, '1z')

        assert_that(str(expect.exception), equal_to("Malformed bond link speed"))

    def test_change_bond_speed_switch_locked(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/bonds/10/link-speed',
            headers=self.headers,
            data='1z'
        ).and_return(
            Reply(
                content=json.dumps({
                    "error": "Switch is locked and can't be modified",
                    "error-module": LockedSwitch.__module__,
                    "error-class": LockedSwitch.__name__
                }),
                status_code=423))

        with self.assertRaises(LockedSwitch) as expect:
            self.switch.set_bond_link_speed(10, '1z')

        assert_that(str(expect.exception), equal_to("Switch is locked and can't be modified"))

    def test_add_vrrp_group(self):
        self.requests_mock.should_receive("post").once().with_args(
            url=self.netman_url+'/switches/toto/vlans/2000/vrrp-groups',
            headers=self.headers,
            data=JsonData(id=1,
                          priority=2,
                          ips=['1.2.3.4/32'],
                          hello_interval=5,
                          dead_interval=15,
                          track_id="101",
                          track_decrement=50)
        ).and_return(
            Reply(
                content='',
                status_code=201))

        self.switch.add_vrrp_group(2000, group_id=1, priority=2, ips=[IPNetwork('1.2.3.4')], hello_interval=5,
                                   dead_interval=15, track_id='101', track_decrement=50)

    def test_remove_vrrp_group(self):
        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches/toto/vlans/2000/vrrp-groups/123',
            headers=self.headers
        ).and_return(
            Reply(
                content='',
                status_code=201))

        self.switch.remove_vrrp_group(2000, group_id=123)

    def test_add_dhcp_relay_server(self):
        self.requests_mock.should_receive("post").once().with_args(
            url=self.netman_url+'/switches/toto/vlans/2000/dhcp-relay-server',
            headers=self.headers,
            data='1.2.3.4'
        ).and_return(
            Reply(
                content='',
                status_code=201))

        self.switch.add_dhcp_relay_server(2000, '1.2.3.4')

    def test_remove_dhcp_relay_server(self):
        self.requests_mock.should_receive("delete").once().with_args(
            url=self.netman_url+'/switches/toto/vlans/2000/dhcp-relay-server/1.2.3.4',
            headers=self.headers
        ).and_return(
            Reply(
                content='',
                status_code=201))

        self.switch.remove_dhcp_relay_server(2000, '1.2.3.4')

    def test_enable_lldp(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces/ge-0/0/6/lldp',
            headers=self.headers,
            data='true'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.enable_lldp("ge-0/0/6", True)

    def test_disable_lldp(self):
        self.requests_mock.should_receive("put").once().with_args(
            url=self.netman_url+'/switches/toto/interfaces/ge-0/0/6/lldp',
            headers=self.headers,
            data='false'
        ).and_return(
            Reply(
                content='',
                status_code=204))

        self.switch.enable_lldp("ge-0/0/6", False)

    def test_unformatted_exceptions_are_handled(self):
        self.requests_mock.should_receive("put").once().and_return(Reply(
            content='Oops an unexpected excepton occured',
            status_code=500
        ))

        with self.assertRaises(Exception) as expect:
            self.switch.set_bond_link_speed(10, '1z')

        assert_that(str(expect.exception), equal_to("500: Oops an unexpected excepton occured"))

    def test_native_exceptions_are_handled(self):
        self.requests_mock.should_receive("put").once().and_return(Reply(
            content=json.dumps({
                "error": "Oops an unexpected excepton occured",
                "error-class": "Exception"
            }),
            status_code=500
        ))

        with self.assertRaises(Exception) as expect:
            self.switch.set_bond_link_speed(10, '1z')

        assert_that(str(expect.exception), equal_to("Oops an unexpected excepton occured"))

    def test_exceptions_missing_error_classes_work(self):
        self.requests_mock.should_receive("put").once().and_return(Reply(
            content=json.dumps({
                "error": "Oops an unexpected excepton occured"
            }),
            status_code=500
        ))

        with self.assertRaises(Exception) as expect:
            self.switch.set_bond_link_speed(10, '1z')

        assert_that(str(expect.exception), equal_to("Oops an unexpected excepton occured"))

    def test_exceptions_bad_init_works(self):
        self.requests_mock.should_receive("put").once().and_return(Reply(
            content=json.dumps({
                "error": "Switch is locked and can't be modified",
                "error-module": RPCError.__module__,
                "error-class": RPCError.__name__
            }),
            status_code=400
        ))

        with self.assertRaises(NetmanException) as expect:
            self.switch.set_bond_link_speed(10, '1z')

        assert_that(
            str(expect.exception),
            equal_to("ncclient.operations.rpc.RPCError: Switch is locked and can't be modified"))
Example #9
0
 def get_switch_by_descriptor(self, switch_descriptor):
     if switch_descriptor.netman_server:
         return RemoteSwitch(switch_descriptor)
     return factories[switch_descriptor.model](switch_descriptor)