Brocade plugins/drivers for ML2 and Service Plugins
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
networking-brocade/networking_brocade/vyatta/tests/test_vrouter_driver.py

666 lines
21 KiB

# Copyright 2015 Brocade Communications System, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import mock
import requests
import urllib
from neutron import context
from neutron.db import models_v2
from neutron.tests import base as n_base
from networking_brocade.vyatta.common import utils as vyatta_utils
from networking_brocade.vyatta.vrouter import client as vyatta_client
from networking_brocade.vyatta.vrouter import driver as vrouter_driver
from oslo_utils import uuidutils
_uuid = uuidutils.generate_uuid
def mock_patch(target, new=mock.DEFAULT):
patcher = mock.patch(target, new)
return patcher.start()
def mock_object(target, attribute, new=mock.DEFAULT):
patcher = mock.patch.object(target, attribute, new)
return patcher.start()
class TestVRouterDriver(n_base.BaseTestCase):
def setUp(self):
super(TestVRouterDriver, self).setUp()
# mock_object(
# vrouter_driver.VyattaVRouterDriver,
# '_management_network').return_value = _uuid()
self._nova_client = mock_patch(
'novaclient.v2.client.Client').return_value
self._server = self._create_server()
self._nova_client.servers.create.return_value = self._server
self._nova_client.servers.get.return_value = self._server
self._router_api_mock = mock_object(
vrouter_driver.VyattaVRouterDriver, '_get_router_api')
self._router_api = self._router_api_mock.return_value
self.driver = vrouter_driver.VyattaVRouterDriver()
@staticmethod
def _create_server():
server = mock.Mock()
server.id = _uuid()
server.status = 'ACTIVE'
server.interface_list.return_value = ['mng-iface']
return server
def test_create_router(self):
ctx = context.Context('', 'tenant_id1')
router = self.driver.create_router(ctx)
self.assertEqual(self._server.id, router)
def test_init_router(self):
ctx = context.Context('', 'tenant_id1')
router = {'id': _uuid()}
self.driver.init_router(ctx, router)
self._router_api_mock.assert_called_once_with(mock.ANY, router['id'])
self._router_api.init_router.assert_called_once_with(
mock.ANY, mock.ANY)
def test_delete_router(self):
ctx = context.Context('', 'tenant_id1')
router_id = _uuid()
self.driver.delete_router(ctx, router_id)
self._router_api_mock.assert_called_once_with(mock.ANY, router_id)
self._router_api.disconnect.assert_called_once_with()
self._nova_client.servers.delete.assert_called_once_with(router_id)
def test_attach_interface(self):
ctx = context.Context('', 'tenant_id1')
port_id = _uuid()
self.driver.attach_interface(ctx, self._server.id, port_id)
self._nova_client.servers.get.assert_called_once_with(self._server.id)
self._server.interface_attach.assert_called_once_with(
port_id, mock.ANY, mock.ANY)
def test_detach_interface(self):
ctx = context.Context('', 'tenant_id1')
port_id = _uuid()
self.driver.detach_interface(ctx, self._server.id, port_id)
self._nova_client.servers.get.assert_called_once_with(self._server.id)
self._server.interface_detach.assert_called_once_with(port_id)
def test_configure_interface(self):
ctx = context.Context('', 'tenant_id1')
router_id = _uuid()
interfaces = ['eth0', 'eth1']
self.driver.configure_interface(ctx, router_id, interfaces)
for interface in interfaces:
self._router_api.add_interface_to_router.assert_any_call(interface)
def test_deconfigure_interface(self):
ctx = context.Context('', 'tenant_id1')
router_id = _uuid()
interfaces = ['eth0', 'eth1']
self.driver.deconfigure_interface(ctx, router_id, interfaces)
for interface in interfaces:
self._router_api.remove_interface_from_router.assert_any_call(
interface)
def test_configure_gateway(self):
ctx = context.Context('', 'tenant_id1')
router_id = _uuid()
interfaces = ['eth0']
self.driver.configure_gateway(ctx, router_id, interfaces)
self._router_api.update_router.assert_called_once_with(
external_gateway_info=interfaces[0])
def test_clear_gateway(self):
ctx = context.Context('', 'tenant_id1')
router_id = _uuid()
self.driver.clear_gateway(ctx, router_id)
self._router_api.update_router.assert_called_once_with(
external_gateway_info=None)
def test_assign_floating_ip(self):
ctx = context.Context('', 'tenant_id1')
router_id = _uuid()
floating_ip = '192.168.1.13'
fixed_ip = '10.10.1.13'
self.driver.assign_floating_ip(ctx, router_id, floating_ip, fixed_ip)
self._router_api.assign_floating_ip.assert_called_once_with(
floating_ip, fixed_ip)
def test_unassign_floating_ip(self):
ctx = context.Context('', 'tenant_id1')
router_id = _uuid()
floating_ip = '192.168.1.13'
fixed_ip = '10.10.1.13'
self.driver.unassign_floating_ip(ctx, router_id, floating_ip, fixed_ip)
self._router_api.unassign_floating_ip.assert_called_once_with(
floating_ip, fixed_ip)
def test_update_static_routes(self):
ctx = context.Context('', 'tenant_idl')
router_id = _uuid()
RouteRule = vyatta_utils.RouteRule
routes_to_add = (
RouteRule(dest_cidr='10.1.0.0/24', next_hop='192.168.1.1'),
RouteRule(dest_cidr='10.2.0.0/24', next_hop='192.168.1.1')
)
routes_to_del = (
RouteRule(dest_cidr='10.3.0.0/24', next_hop='192.168.1.1'),
)
self.driver.update_static_routes(ctx, router_id,
routes_to_add, routes_to_del)
self._router_api.update_static_routes.assert_called_once_with(
routes_to_add, routes_to_del)
class TestVRouterDriverApi(n_base.BaseTestCase):
def setUp(self):
super(TestVRouterDriverApi, self).setUp()
self._nova_client = mock_patch(
'novaclient.v2.client.Client').return_value
# self._mock_object(vrouter_driver.VyattaVRouterDriver,
# '_management_network')
self.driver = vrouter_driver.VyattaVRouterDriver()
def _mock_object(self, target, attribute, new=mock.DEFAULT):
patcher = mock.patch.object(target, attribute, new)
return patcher.start()
def test_get_router_api(self):
ctx = mock.Mock()
router_id = _uuid()
router_addr = '172.16.18.10'
server = self._nova_client.servers.get.return_value
server.addresses = {
'external': [
{'addr': router_addr, }
]
}
query = ctx.session.query.return_value
query.filter_by.return_value.one.return_value = models_v2.Network(
name='external')
with mock.patch.object(
vyatta_client.VRouterRestAPIClient, 'connect') as api_connect:
api = self.driver._get_router_api(ctx, router_id)
self.assertIsNotNone(api)
api_connect.assert_called_once_with(router_addr)
SHOW_VERSION_OUTPUT = """
Version: VSE6.6R5X3
Description: Brocade Vyatta 5410 vRouter 6.6 R5X3
Copyright: 2006-2014 Vyatta, Inc.
"""
SHOW_CONFIG_OUTPUT = """
interfaces {
ethernet eth0 {
address 10.10.0.1
description External_Gateway
hw-id 08:00:27:02:b4:67
duplex auto
smp_affinity auto
speed auto
}
loopback lo {
}
}
service {
https {
http-redirect disable
}
lldp {
interface all {
}
snmp {
enable
}
}
snmp {
community public {
authorization ro
}
}
ssh {
port 22
}
}
system {
host-name router1
login {
user vyatta {
authentication {
encrypted-password ****************
}
level admin
}
}
syslog {
global {
facility all {
level debug
}
facility protocols {
level debug
}
}
user all {
facility all {
level emerg
}
}
}
time-zone GMT
}
"""
class VRouterRestAPIClientMixin(object):
def _create_client(self):
self.address = 'example.com'
client = vyatta_client.VRouterRestAPIClient()
client.address = self.address
client._vrouter_model = (
vyatta_client.VRouterRestAPIClient._VROUTER_VR_MODEL)
return client
class TestVRouterRestAPIClient(n_base.BaseTestCase,
VRouterRestAPIClientMixin):
def setUp(self):
super(TestVRouterRestAPIClient, self).setUp()
self._rest_mock = mock_object(
vyatta_client.VRouterRestAPIClient, '_rest_call')
self._rest_mock.side_effect = self._rest_call
m = mock_object(vyatta_client.VRouterRestAPIClient,
'get_ethernet_if_id')
m.return_value = 'eth0'
m = mock_object(
vyatta_client.VRouterRestAPIClient, '_get_admin_state')
m.return_value = False
def _check_cmd(self, cmd, check_type=None, check_cmd=None):
if check_type is not None:
self.assertEqual(cmd.cmd_type, check_type)
if check_cmd is not None:
self.assertEqual(cmd.cmd, check_cmd)
@staticmethod
def _rest_call(method, uri, headers=None, session=None):
response = mock.Mock()
response.status_code = requests.codes.OK
response.reason = 'Ok'
response.text = '{}'
response.headers = {
'Location': 'location'
}
return response
def _check_update_interface(self, action, interface_info):
prefix = '/location/{action}/interfaces/dataplane/eth0'.format(
action=action)
self._rest_mock.assert_any_call(
'PUT', prefix + '/address/' + interface_info['ip_address'])
self._rest_mock.assert_any_call(
'POST', '/location/commit')
self._rest_mock.assert_any_call(
'POST', '/location/save')
def test_init_router(self):
client = self._create_client()
with mock.patch('eventlet.greenthread.sleep'):
client.init_router('router1', True)
self._rest_mock.assert_any_call(
'PUT', '/location/delete/system/ip/disable-forwarding',
)
def test_add_interface_to_router(self):
interface_info = {
'mac_address': '08:00:27:02:b4:67',
'ip_address': '10.10.16.20',
'gateway_ip': '10.10.16.1'
}
client = self._create_client()
client.add_interface_to_router(interface_info)
self._check_update_interface('set', interface_info)
def test_remove_interface_from_router(self):
interface_info = {
'mac_address': '08:00:27:02:b4:67',
'ip_address': '10.10.16.20',
'gateway_ip': '10.10.16.1'
}
client = self._create_client()
client.remove_interface_from_router(interface_info)
self._check_update_interface('delete', interface_info)
def test_assign_floating_ip(self):
client = self._create_client()
client._external_gw_info = vyatta_client.InterfaceInfo(
'eth0', '172.16.18.10', '172.16.18.1')
client.assign_floating_ip('172.16.18.12', '10.10.10.12')
self.assertIn('172.16.18.12.10.10.10.12', client._floating_ip_dict)
client.unassign_floating_ip('172.16.18.12', '10.10.10.12')
self.assertNotIn('172.16.18.12.10.10.10.12', client._floating_ip_dict)
def test_update_static_routes(self):
cmd_batch_mock = mock.Mock()
mock_object(vyatta_client.VRouterRestAPIClient,
'exec_cmd_batch', cmd_batch_mock)
RouteRule = vyatta_utils.RouteRule
routes_to_add = tuple((
RouteRule(dest_cidr='10.1.0.0/24', next_hop='192.168.1.1'),
RouteRule(dest_cidr='10.2.0.0/24', next_hop='192.168.1.1'),
))
routes_to_del = tuple((
RouteRule(dest_cidr='10.3.0.0/24', next_hop='192.168.1.1'),
))
client = self._create_client()
client.update_static_routes(routes_to_add, routes_to_del)
expected_batch = list()
for rule in routes_to_add:
cmd = vyatta_client.SetCmd((
'protocols/static/route/{0}/next-hop/{1}').format(
urllib.quote_plus(rule.dest_cidr),
urllib.quote_plus(rule.next_hop)))
expected_batch.append(cmd)
for rule in routes_to_del:
cmd = vyatta_client.DeleteCmd('protocols/static/route/{0}'.format(
urllib.quote_plus(rule.dest_cidr)))
expected_batch.append(cmd)
cmd_batch_mock.assert_called_once_with(expected_batch)
def test_update_router(self):
client = self._create_client()
gw_info = {
'mac_address': '08:00:27:02:b4:67',
'ip_address': '10.10.16.20',
'gateway_ip': '10.10.16.1'
}
client.update_router('rotuer1', True, gw_info)
self._check_update_interface('set', gw_info)
self._rest_mock.assert_any_call(
'PUT', '/location/set/protocols/static/route/0.0.0.0%2F0/next-hop/'
+ gw_info['gateway_ip'])
self._rest_mock.reset_mock()
client.update_router('rotuer1', True)
self._check_update_interface('delete', gw_info)
self._rest_mock.assert_any_call(
'PUT', '/location/delete/protocols/static/route/0.0.0.0%2F0')
def test_get_nat_cmd(self):
client = self._create_client()
nat_cmd = client._get_nat_cmd()
self.assertEqual(nat_cmd, 'service/nat')
client._vrouter_model = (
vyatta_client.VRouterRestAPIClient._VROUTER_VSE_MODEL)
nat_cmd = client._get_nat_cmd()
self.assertEqual(nat_cmd, 'nat')
def test_add_snat_rule_cmd(self):
client = self._create_client()
cmd_list = []
client._add_snat_rule_cmd(
cmd_list, 2, 'eth1', '10.10.12.1', '192.168.12.1')
prefix = 'service/nat/source/rule/2'
self._check_cmd(cmd_list[0], 'set', prefix)
self._check_cmd(cmd_list[1], 'set',
prefix + '/outbound-interface/eth1')
self._check_cmd(cmd_list[2], 'set',
prefix + '/source/address/10.10.12.1')
self._check_cmd(cmd_list[3], 'set',
prefix + '/translation/address/192.168.12.1')
def test_add_dnat_rule_cmd(self):
client = self._create_client()
cmd_list = []
client._add_dnat_rule_cmd(
cmd_list, 2, 'eth1', '10.10.12.1', '192.168.12.1')
prefix = 'service/nat/destination/rule/2'
self._check_cmd(cmd_list[0], 'set', prefix)
self._check_cmd(cmd_list[1], 'set', prefix + '/inbound-interface/eth1')
self._check_cmd(cmd_list[2], 'set',
prefix + '/destination/address/10.10.12.1')
self._check_cmd(cmd_list[3], 'set',
prefix + '/translation/address/192.168.12.1')
def test_delete_snat_rule_cmd(self):
client = self._create_client()
cmd_list = []
client._delete_snat_rule_cmd(cmd_list, 2)
self._check_cmd(cmd_list[0], 'delete', 'service/nat/source/rule/2')
def test_delete_dnat_rule_cmd(self):
client = self._create_client()
cmd_list = []
client._delete_dnat_rule_cmd(cmd_list, 2)
self._check_cmd(cmd_list[0],
'delete', 'service/nat/destination/rule/2')
def test_set_router_name_cmd(self):
client = self._create_client()
cmd_list = []
client._set_router_name_cmd(cmd_list, 'router1')
self._check_cmd(cmd_list[0], 'set', 'system/host-name/router1')
def test_set_system_gateway_cmd(self):
client = self._create_client()
cmd_list = []
client._set_system_gateway_cmd(cmd_list, '10.10.16.1')
self.assertEqual(len(cmd_list), 1)
self._check_cmd(
cmd_list[0], 'set',
'protocols/static/route/0.0.0.0%2F0/next-hop/10.10.16.1')
def test_delete_system_gateway_cmd(self):
client = self._create_client()
cmd_list = []
# NOTE: Gateway parameter is not used
client._delete_system_gateway_cmd(cmd_list, '10.10.16.1')
self.assertEqual(len(cmd_list), 1)
self._check_cmd(
cmd_list[0], 'delete',
'protocols/static/route/0.0.0.0%2F0')
def test_configure_cmd_batch(self):
client = self._create_client()
cmd_list = [
vyatta_client.SetCmd('cmd1'),
vyatta_client.DeleteCmd('cmd2')
]
client.exec_cmd_batch(cmd_list)
self.assertEqual(
self._rest_mock.call_count, len(cmd_list) + 4)
def test_get_config_cmd(self):
client = self._create_client()
client._get_config_cmd('system/ip/disable-forwarding')
self.assertEqual(self._rest_mock.call_count, 3)
def test_show_cmd(self):
self._rest_mock.side_effect = [
self._make_http_response(201, headers={'Location': '/fake-url'}),
self._make_http_response(200, text=SHOW_VERSION_OUTPUT),
self._make_http_response(410),
self._make_http_response(200)]
client = self._create_client()
client._show_cmd('version')
self.assertEqual(self._rest_mock.call_count, 4)
def test_process_model(self):
client = vyatta_client.VRouterRestAPIClient()
with mock.patch.object(
vyatta_client.VRouterRestAPIClient, '_show_cmd') as show_cmd:
show_cmd.return_value = SHOW_VERSION_OUTPUT
client._process_model()
self.assertEqual(client._vrouter_model, 54)
def test_sync_cache(self):
client = self._create_client()
client._vrouter_model = client._VROUTER_VSE_MODEL
with mock.patch.object(
vyatta_client.VRouterRestAPIClient, '_show_cmd') as show_cmd:
show_cmd.return_value = SHOW_CONFIG_OUTPUT
client._sync_cache()
interface_info = vyatta_client.InterfaceInfo(
'eth0', '10.10.0.1')
self.assertEqual(client._external_gw_info, interface_info)
def _make_http_response(self, status_code, headers=None, text=None):
if headers is None:
headers = {}
response = mock.Mock()
response.status_code = status_code
response.headers = headers
response.text = text
return response
class TestLowLevelRestAPIClient(n_base.BaseTestCase,
VRouterRestAPIClientMixin):
def test_get_admin_state(self):
client = self._create_client()
with mock.patch.object(
vyatta_client.VRouterRestAPIClient,
'_show_cmd') as get_cmd:
get_cmd.return_value = "IP forwarding is on"
state = client._get_admin_state()
self.assertTrue(state)
def test_get_ethernet_if_id(self):
client = self._create_client()
with mock.patch.object(
vyatta_client.VRouterRestAPIClient,
'_get_interfaces') as get_ifs:
get_ifs.return_value = [{'name': 'dp0e5',
'ip_addrs': '192.168.21.3',
'mac_address': '08:00:27:4a:be:12'}]
if_id = client.get_ethernet_if_id('08:00:27:4a:be:12')
self.assertEqual(if_id, 'dp0e5')
def test_rest_call(self):
action = 'GET'
uri = '/show/config'
client = self._create_client()
with mock.patch('requests.request') as request:
client._rest_call(action, uri)
uri = 'https://{0}{1}'.format(self.address, uri)
request.assert_called_once_with(
action, uri, verify=False, auth=mock.ANY,
headers={'Content-Length': 0, 'Accept': 'application/json'})