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.
995 lines
40 KiB
995 lines
40 KiB
# Copyright (c) 2013 OpenStack Foundation |
|
# |
|
# 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 |
|
from mock import patch |
|
from neutron_lib import constants as n_const |
|
from oslo_config import cfg |
|
import six |
|
|
|
from neutron.tests import base |
|
from neutron.tests.unit import testlib_api |
|
|
|
from networking_arista.common import constants |
|
from networking_arista.common import db_lib |
|
from networking_arista.common import exceptions as arista_exc |
|
from networking_arista.ml2.rpc import arista_eapi |
|
from networking_arista.tests.unit.ml2.test_arista_mechanism_driver import \ |
|
FakePortBindingLevel |
|
import networking_arista.tests.unit.ml2.utils as utils |
|
|
|
|
|
EAPI_SEND_FUNC = ('networking_arista.ml2.rpc.arista_eapi.AristaRPCWrapperEapi' |
|
'._send_eapi_req') |
|
|
|
|
|
def setup_valid_config(): |
|
utils.setup_arista_wrapper_config(cfg) |
|
|
|
|
|
class PositiveRPCWrapperValidConfigTestCase(testlib_api.SqlTestCase): |
|
"""Test cases to test the RPC between Arista Driver and EOS. |
|
|
|
Tests all methods used to send commands between Arista Driver and EOS |
|
""" |
|
|
|
def setUp(self): |
|
super(PositiveRPCWrapperValidConfigTestCase, self).setUp() |
|
setup_valid_config() |
|
ndb = db_lib.NeutronNets() |
|
self.drv = arista_eapi.AristaRPCWrapperEapi(ndb) |
|
self.drv._server_ip = "10.11.12.13" |
|
self.region = 'RegionOne' |
|
|
|
def _get_exit_mode_cmds(self, modes): |
|
return ['exit'] * len(modes) |
|
|
|
def _verify_send_eapi_request_calls(self, mock_send_eapi_req, cmds, |
|
commands_to_log=None): |
|
calls = [] |
|
calls.extend( |
|
mock.call(cmds=cmd, commands_to_log=log_cmd) |
|
for cmd, log_cmd in six.moves.zip(cmds, commands_to_log or cmds)) |
|
mock_send_eapi_req.assert_has_calls(calls) |
|
|
|
def test_no_exception_on_correct_configuration(self): |
|
self.assertIsNotNone(self.drv) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_plug_host_into_network(self, mock_send_eapi_req): |
|
tenant_id = 'ten-1' |
|
vm_id = 'vm-1' |
|
port_id = 123 |
|
network_id = 'net-id' |
|
host = 'host' |
|
port_name = '123-port' |
|
segment_id = 'segment_id_1' |
|
segments = [{'network_type': 'vlan', 'physical_network': 'default', |
|
'segmentation_id': 1234, 'id': segment_id}] |
|
|
|
self.drv.plug_host_into_network(vm_id, host, port_id, |
|
network_id, tenant_id, segments, |
|
port_name) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', 'configure', 'cvx', 'service openstack', |
|
'region RegionOne', |
|
'tenant ten-1', 'vm id vm-1 hostid host', |
|
'port id 123 name "123-port" network-id net-id', |
|
] |
|
for level, segment in enumerate(segments): |
|
cmd2.append('segment level %s id %s' % (level, segment['id'])) |
|
|
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_plug_dhcp_port_into_network(self, mock_send_eapi_req): |
|
tenant_id = 'ten-1' |
|
vm_id = 'vm-1' |
|
port_id = 123 |
|
network_id = 'net-id' |
|
host = 'host' |
|
port_name = '123-port' |
|
segments = [] |
|
|
|
self.drv.plug_port_into_network(vm_id, host, port_id, network_id, |
|
tenant_id, port_name, |
|
n_const.DEVICE_OWNER_DHCP, None, None, |
|
None, segments) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', 'configure', 'cvx', 'service openstack', |
|
'region RegionOne', |
|
'tenant ten-1', 'network id net-id', |
|
'dhcp id vm-1 hostid host port-id 123 name "123-port"', |
|
] |
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_plug_baremetal_into_network(self, mock_send_eapi_req): |
|
tenant_id = 'ten-1' |
|
network_id = 'net-id-1' |
|
bm_id = 'bm-1' |
|
port_id = 'p1' |
|
host = 'host' |
|
port_name = 'name_p1' |
|
device_owner = 'compute:None' |
|
|
|
segments = [{'segmentation_id': 1001, |
|
'id': 'segment_id_1', |
|
'network_type': 'vlan', |
|
'is_dynamic': False}] |
|
|
|
switch_bindings = {'local_link_information': [ |
|
{'port_id': 'Eth1', 'switch_id': 'switch-id-1', |
|
'switch_info': 'switch-1'}]} |
|
bindings = switch_bindings['local_link_information'] |
|
|
|
self.drv.bm_and_dvr_supported = mock.MagicMock(return_value=True) |
|
|
|
self.drv.plug_baremetal_into_network(bm_id, host, port_id, |
|
network_id, tenant_id, |
|
segments, port_name, |
|
device_owner, |
|
None, None, 'baremetal', |
|
bindings) |
|
|
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', 'configure', 'cvx', 'service openstack', |
|
'region RegionOne', |
|
'tenant ten-1', |
|
'instance id bm-1 hostid host type baremetal', |
|
'port id p1 name "name_p1" network-id net-id-1 ' |
|
'type native switch-id switch-id-1 switchport Eth1', |
|
] |
|
for level, segment in enumerate(segments): |
|
cmd2.append('segment level %s id %s' % (level, segment['id'])) |
|
cmd2.append('exit') |
|
|
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_unplug_baremetal_from_network(self, mock_send_eapi_req): |
|
tenant_id = 'ten-1' |
|
network_id = 'net-id-1' |
|
bm_id = 'bm-1' |
|
port_id = 111 |
|
host = 'host' |
|
switch_bindings = {'local_link_information': [ |
|
{'port_id': 'Eth1', 'switch_id': 'switch-id-1', |
|
'switch_info': 'switch-1'}]} |
|
bindings = switch_bindings['local_link_information'] |
|
self.drv.bm_and_dvr_supported = mock.MagicMock(return_value=True) |
|
self.drv.unplug_baremetal_from_network(bm_id, host, port_id, |
|
network_id, tenant_id, |
|
None, 'baremetal', |
|
bindings) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', 'configure', 'cvx', 'service openstack', |
|
'region RegionOne', |
|
'tenant ten-1', |
|
'instance id bm-1 hostid host type baremetal', |
|
'no port id 111', |
|
] |
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_unplug_host_from_network(self, mock_send_eapi_req): |
|
tenant_id = 'ten-1' |
|
vm_id = 'vm-1' |
|
port_id = 123 |
|
network_id = 'net-id' |
|
host = 'host' |
|
self.drv.unplug_host_from_network(vm_id, host, port_id, |
|
network_id, tenant_id) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', 'configure', 'cvx', 'service openstack', |
|
'region RegionOne', |
|
'tenant ten-1', 'vm id vm-1 hostid host', |
|
'no port id 123', |
|
] |
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_unplug_dhcp_port_from_network(self, mock_send_eapi_req): |
|
tenant_id = 'ten-1' |
|
vm_id = 'vm-1' |
|
port_id = 123 |
|
network_id = 'net-id' |
|
host = 'host' |
|
|
|
self.drv.unplug_dhcp_port_from_network(vm_id, host, port_id, |
|
network_id, tenant_id) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', 'configure', 'cvx', 'service openstack', |
|
'region RegionOne', |
|
'tenant ten-1', 'network id net-id', |
|
'no dhcp id vm-1 port-id 123', |
|
] |
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_create_network(self, mock_send_eapi_req): |
|
tenant_id = 'ten-1' |
|
self.drv.cli_commands['features'] = {'hierarchical-port-binding': 1} |
|
network = { |
|
'network_id': 'net-id', |
|
'network_name': 'net-name', |
|
'segments': [{'segmentation_id': 123, |
|
'physical_network': 'default', |
|
'network_type': 'vlan', |
|
'id': 'segment_id_1'}], |
|
'shared': False, |
|
} |
|
self.drv.create_network(tenant_id, network) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', 'configure', 'cvx', 'service openstack', |
|
'region RegionOne', |
|
'tenant ten-1', 'network id net-id name "net-name"', |
|
] |
|
for seg in network['segments']: |
|
is_dynamic = seg.get('is_dynamic', False) |
|
cmd2.append('segment %s type %s id %d %s' % (seg['id'], |
|
seg['network_type'], seg['segmentation_id'], |
|
'dynamic' if is_dynamic else 'static')) |
|
cmd2.append('no shared') |
|
|
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_create_shared_network(self, mock_send_eapi_req): |
|
tenant_id = 'ten-1' |
|
segment_id = 'abcd-cccc' |
|
segmentation_id = 123 |
|
network_type = 'vlan' |
|
segments = [{'segmentation_id': segmentation_id, |
|
'id': segment_id, |
|
'network_type': network_type}] |
|
network = { |
|
'network_id': 'net-id', |
|
'network_name': 'net-name', |
|
'segments': segments, |
|
'shared': True} |
|
self.drv.cli_commands['features'] = {'hierarchical-port-binding': 1} |
|
self.drv.create_network(tenant_id, network) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', 'configure', 'cvx', 'service openstack', |
|
'region RegionOne', |
|
'tenant ten-1', 'network id net-id name "net-name"', |
|
'segment %s type %s id %d %s' % (segment_id, network_type, |
|
segmentation_id, 'static'), |
|
'shared', |
|
] |
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_create_network_bulk(self, mock_send_eapi_req): |
|
tenant_id = 'ten-2' |
|
num_networks = 10 |
|
network_type = 'vlan' |
|
segment_id = 'abcd-eeee-%s' |
|
self.drv.cli_commands['features'] = {'hierarchical-port-binding': 1} |
|
networks = [{ |
|
'network_id': 'net-id-%d' % net_id, |
|
'network_name': 'net-name-%d' % net_id, |
|
'segments': [{'segmentation_id': net_id, |
|
'network_type': 'vlan', |
|
'id': segment_id % net_id}], |
|
'shared': True, |
|
} for net_id in range(1, num_networks) |
|
] |
|
|
|
self.drv.create_network_bulk(tenant_id, networks) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', |
|
'configure', |
|
'cvx', |
|
'service openstack', |
|
'region RegionOne', |
|
'tenant ten-2'] |
|
for net_id in range(1, num_networks): |
|
cmd2.append('network id net-id-%d name "net-name-%d"' % |
|
(net_id, net_id)) |
|
cmd2.append('segment %s type %s id %d %s' % ( |
|
segment_id % net_id, network_type, net_id, 'static')) |
|
cmd2.append('shared') |
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_delete_network(self, mock_send_eapi_req): |
|
tenant_id = 'ten-1' |
|
network_id = 'net-id' |
|
segments = [{'segmentation_id': 101, |
|
'physical_network': 'default', |
|
'id': 'segment_id_1', |
|
'network_type': 'vlan'}] |
|
self.drv.delete_network(tenant_id, network_id, segments) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', 'configure', 'cvx', 'service openstack', |
|
'region RegionOne', |
|
'tenant ten-1', |
|
'network id net-id', |
|
'no segment segment_id_1', |
|
] |
|
cmd3 = ['enable', 'configure', 'cvx', 'service openstack', |
|
'region RegionOne', |
|
'tenant ten-1', |
|
'no network id net-id', |
|
] |
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, |
|
[cmd1, cmd2, cmd1, cmd3]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_delete_network_bulk(self, mock_send_eapi_req): |
|
tenant_id = 'ten-2' |
|
num_networks = 10 |
|
|
|
networks = ['net-id-%d' % net_id for net_id in range(1, num_networks)] |
|
self.drv.delete_network_bulk(tenant_id, networks) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', |
|
'configure', |
|
'cvx', |
|
'service openstack', |
|
'region RegionOne', |
|
'tenant ten-2'] |
|
for net_id in range(1, num_networks): |
|
cmd2.append('no network id net-id-%d' % net_id) |
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_delete_vm(self, mock_send_eapi_req): |
|
tenant_id = 'ten-1' |
|
vm_id = 'vm-id' |
|
self.drv.delete_vm(tenant_id, vm_id) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', 'configure', 'cvx', 'service openstack', |
|
'region RegionOne', |
|
'tenant ten-1', 'no vm id vm-id', |
|
] |
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_delete_vm_bulk(self, mock_send_eapi_req): |
|
tenant_id = 'ten-2' |
|
num_vms = 10 |
|
vm_ids = ['vm-id-%d' % vm_id for vm_id in range(1, num_vms)] |
|
self.drv.delete_vm_bulk(tenant_id, vm_ids) |
|
|
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', |
|
'configure', |
|
'cvx', |
|
'service openstack', |
|
'region RegionOne', |
|
'tenant ten-2'] |
|
|
|
for vm_id in range(1, num_vms): |
|
cmd2.append('no vm id vm-id-%d' % vm_id) |
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_create_port_bulk(self, mock_send_eapi_req): |
|
tenant_id = 'ten-3' |
|
num_devices = 10 |
|
num_ports_per_device = 2 |
|
|
|
device_count = 0 |
|
devices = {} |
|
for device_id in range(1, num_devices): |
|
device_count += 1 |
|
dev_id = 'dev-id-%d' % device_id |
|
devices[dev_id] = {'vmId': dev_id, |
|
'baremetal_instance': False, |
|
'ports': [] |
|
} |
|
for port_id in range(1, num_ports_per_device): |
|
port_id = 'port-id-%d-%d' % (device_id, port_id) |
|
port = { |
|
'device_id': 'dev-id-%d' % device_id, |
|
'hosts': ['host_%d' % (device_count)], |
|
'portId': port_id |
|
} |
|
devices[dev_id]['ports'].append(port) |
|
|
|
device_owners = [n_const.DEVICE_OWNER_DHCP, 'compute', |
|
n_const.DEVICE_OWNER_DVR_INTERFACE] |
|
port_list = [] |
|
|
|
net_count = 1 |
|
for device_id in range(1, num_devices): |
|
for port_id in range(1, num_ports_per_device): |
|
port = { |
|
'portId': 'port-id-%d-%d' % (device_id, port_id), |
|
'device_id': 'dev-id-%d' % device_id, |
|
'device_owner': device_owners[(device_id + port_id) % 3], |
|
'network_id': 'network-id-%d' % net_count, |
|
'name': 'port-%d-%d' % (device_id, port_id), |
|
'tenant_id': tenant_id |
|
} |
|
port_list.append(port) |
|
net_count += 1 |
|
|
|
create_ports = {} |
|
port_profiles = {} |
|
for port in port_list: |
|
create_ports.update(utils.port_dict_representation(port)) |
|
port_profiles[port['portId']] = {'vnic_type': 'normal'} |
|
|
|
self.drv.cli_commands[constants.CMD_INSTANCE] = 'instance' |
|
self.drv.create_instance_bulk(tenant_id, create_ports, devices, |
|
port_profiles=port_profiles) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', |
|
'configure', |
|
'cvx', |
|
'service openstack', |
|
'region RegionOne', |
|
'tenant ten-3'] |
|
|
|
for device in devices.values(): |
|
for v_port in device['ports']: |
|
port_id = v_port['portId'] |
|
port = create_ports[port_id] |
|
host = v_port['hosts'][0] |
|
device_owner = port['device_owner'] |
|
port_name = port['name'] |
|
network_id = port['network_id'] |
|
device_id = port['device_id'] |
|
if device_owner == 'network:dhcp': |
|
cmd2.append('network id %s' % network_id) |
|
cmd2.append('dhcp id %s hostid %s port-id %s name "%s"' % ( |
|
device_id, host, port_id, port_name)) |
|
elif device_owner == 'compute': |
|
cmd2.append('vm id %s hostid %s' % (device_id, host)) |
|
cmd2.append('port id %s name "%s" network-id %s' % ( |
|
port_id, port_name, network_id)) |
|
elif device_owner == n_const.DEVICE_OWNER_DVR_INTERFACE: |
|
cmd2.append('instance id %s type router' % device_id) |
|
cmd2.append('port id %s network-id %s hostid %s' % ( |
|
port_id, network_id, host)) |
|
net_count += 1 |
|
|
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_delete_tenant(self, mock_send_eapi_req): |
|
tenant_id = 'ten-1' |
|
self.drv.delete_tenant(tenant_id) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', 'configure', 'cvx', 'service openstack', |
|
'region RegionOne', 'no tenant ten-1', |
|
] |
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_delete_tenant_bulk(self, mock_send_eapi_req): |
|
num_tenants = 10 |
|
tenant_list = ['ten-%d' % t_id for t_id in range(1, num_tenants)] |
|
self.drv.delete_tenant_bulk(tenant_list) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', |
|
'configure', |
|
'cvx', |
|
'service openstack', |
|
'region RegionOne'] |
|
for ten_id in range(1, num_tenants): |
|
cmd2.append('no tenant ten-%d' % ten_id) |
|
|
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
def test_get_network_info_returns_none_when_no_such_net(self): |
|
expected = [] |
|
self.drv.get_tenants = mock.MagicMock() |
|
self.drv.get_tenants.return_value = [] |
|
|
|
net_info = self.drv.get_tenants() |
|
|
|
self.drv.get_tenants.assert_called_once_with() |
|
self.assertEqual(net_info, expected, ('Network info must be "None"' |
|
'for unknown network')) |
|
|
|
def test_get_network_info_returns_info_for_available_net(self): |
|
valid_network_id = '12345' |
|
valid_net_info = {'network_id': valid_network_id, |
|
'some_info': 'net info'} |
|
known_nets = valid_net_info |
|
|
|
self.drv.get_tenants = mock.MagicMock() |
|
self.drv.get_tenants.return_value = known_nets |
|
|
|
net_info = self.drv.get_tenants() |
|
self.assertEqual(net_info, valid_net_info, |
|
('Must return network info for a valid net')) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_check_supported_features(self, mock_send_eapi_req): |
|
self.drv._get_random_name = mock.MagicMock() |
|
self.drv._get_random_name.return_value = 'RegionOne' |
|
|
|
self.drv.check_supported_features() |
|
|
|
get_eos_master_cmd = ['show openstack agent uuid'] |
|
instance_command = ['show openstack instances'] |
|
cmds = [get_eos_master_cmd, instance_command] |
|
|
|
calls = [] |
|
calls.extend(mock.call(cmds=cmd, commands_to_log=cmd) for cmd in cmds) |
|
mock_send_eapi_req.assert_has_calls(calls) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_register_with_eos(self, mock_send_eapi_req): |
|
self.drv.register_with_eos() |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', |
|
'configure', |
|
'cvx', |
|
'service openstack', |
|
'region %s' % self.region, |
|
'sync interval %d' % cfg.CONF.ml2_arista.sync_interval, |
|
] |
|
self._verify_send_eapi_request_calls( |
|
mock_send_eapi_req, |
|
[cmd1, cmd2], |
|
commands_to_log=[cmd1, cmd2]) |
|
|
|
def _enable_sync_cmds(self): |
|
self.drv.cli_commands[ |
|
constants.CMD_REGION_SYNC] = 'region RegionOne sync' |
|
self.drv.cli_commands[constants.CMD_SYNC_HEARTBEAT] = 'sync heartbeat' |
|
self.drv.cli_commands['baremetal'] = '' |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_create_network_bulk_during_sync(self, mock_send_eapi_req): |
|
self._enable_sync_cmds() |
|
self.drv.cli_commands['features'] = {'hierarchical-port-binding': 1} |
|
tenant_id = 'ten-10' |
|
num_networks = 101 |
|
segments = [{'segmentation_id': 101, |
|
'physical_network': 'default', |
|
'id': 'segment_id_1', |
|
'network_type': 'vlan'}] |
|
networks = [{ |
|
'network_id': 'net-id-%d' % net_id, |
|
'network_name': 'net-name-%d' % net_id, |
|
'segments': segments, |
|
'shared': True, |
|
} for net_id in range(1, num_networks + 1) |
|
] |
|
|
|
self.drv.create_network_bulk(tenant_id, networks, sync=True) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', |
|
'configure', |
|
'cvx', |
|
'service openstack', |
|
'region RegionOne sync', |
|
'tenant ten-10'] |
|
|
|
# Send 100 create network commands |
|
for net_id in range(1, 101): |
|
cmd2.append('network id net-id-%d name "net-name-%d"' % |
|
(net_id, net_id)) |
|
for seg in segments: |
|
is_dynamic = seg.get('is_dynamic', False) |
|
cmd2.append('segment %s type %s id %d %s' % (seg['id'], |
|
seg['network_type'], seg['segmentation_id'], |
|
'dynamic' if is_dynamic else 'static')) |
|
cmd2.append('shared') |
|
|
|
# Send heartbeat |
|
cmd2.append('sync heartbeat') |
|
# Send the remaining network |
|
cmd2.append('network id net-id-101 name "net-name-101"') |
|
for seg in segments: |
|
is_dynamic = seg.get('is_dynamic', False) |
|
cmd2.append('segment %s type %s id %d %s' % (seg['id'], |
|
seg['network_type'], seg['segmentation_id'], |
|
'dynamic' if is_dynamic else 'static')) |
|
cmd2.append('shared') |
|
# Send the final heartbeat |
|
cmd2.append('sync heartbeat') |
|
|
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_delete_network_bulk_during_sync(self, mock_send_eapi_req): |
|
self._enable_sync_cmds() |
|
tenant_id = 'ten-10' |
|
num_networks = 101 |
|
networks = ['nid-%d' % net_id for net_id in range(1, num_networks + 1)] |
|
|
|
self.drv.delete_network_bulk(tenant_id, networks, sync=True) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', |
|
'configure', |
|
'cvx', |
|
'service openstack', |
|
'region RegionOne sync', |
|
'tenant ten-10'] |
|
|
|
# Send 100 create network commands |
|
for net_id in range(1, 101): |
|
cmd2.append('no network id nid-%d' % (net_id)) |
|
|
|
# Send heartbeat |
|
cmd2.append('sync heartbeat') |
|
# Send the remaining network |
|
cmd2.append('no network id nid-101') |
|
# Send the final heartbeat |
|
cmd2.append('sync heartbeat') |
|
|
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_delete_vm_bulk_during_sync(self, mock_send_eapi_req): |
|
self._enable_sync_cmds() |
|
tenant_id = 'ten-2' |
|
num_vms = 101 |
|
vm_ids = ['vm-id-%d' % vm_id for vm_id in range(1, num_vms + 1)] |
|
self.drv.delete_vm_bulk(tenant_id, vm_ids, sync=True) |
|
|
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', |
|
'configure', |
|
'cvx', |
|
'service openstack', |
|
'region RegionOne sync', |
|
'tenant ten-2'] |
|
|
|
for vm_id in range(1, 101): |
|
cmd2.append('no vm id vm-id-%d' % vm_id) |
|
|
|
# Send heartbeat |
|
cmd2.append('sync heartbeat') |
|
# Send the remaining vm |
|
cmd2.append('no vm id vm-id-101') |
|
# Send the final heartbeat |
|
cmd2.append('sync heartbeat') |
|
|
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_create_port_bulk_during_sync(self, mock_send_eapi_req): |
|
self._enable_sync_cmds() |
|
tenant_id = 'ten-3' |
|
num_devices = 101 |
|
num_ports_per_device = 2 |
|
|
|
device_count = 0 |
|
devices = {} |
|
for device_id in range(1, num_devices): |
|
device_count += 1 |
|
dev_id = 'dev-id-%d' % device_id |
|
devices[dev_id] = {'vmId': dev_id, |
|
'baremetal_instance': False, |
|
'ports': [] |
|
} |
|
for port_id in range(1, num_ports_per_device + 1): |
|
port_id = 'port-id-%d-%d' % (device_id, port_id) |
|
port = { |
|
'device_id': 'dev-id-%d' % device_id, |
|
'hosts': ['host_%d' % (device_count)], |
|
'portId': port_id |
|
} |
|
devices[dev_id]['ports'].append(port) |
|
|
|
device_owners = [n_const.DEVICE_OWNER_DHCP, 'compute', |
|
n_const.DEVICE_OWNER_DVR_INTERFACE] |
|
|
|
port_list = [] |
|
net_count = 1 |
|
for device_id in range(1, num_devices): |
|
for port_id in range(1, num_ports_per_device + 1): |
|
port = { |
|
'portId': 'port-id-%d-%d' % (device_id, port_id), |
|
'device_id': 'dev-id-%d' % device_id, |
|
'device_owner': device_owners[(device_id + port_id) % 3], |
|
'network_id': 'network-id-%d' % net_count, |
|
'name': 'port-%d-%d' % (device_id, port_id), |
|
'tenant_id': tenant_id |
|
} |
|
port_list.append(port) |
|
net_count += 1 |
|
|
|
create_ports = {} |
|
port_profiles = {} |
|
for port in port_list: |
|
create_ports.update(utils.port_dict_representation(port)) |
|
port_profiles[port['portId']] = {'vnic_type': 'normal'} |
|
|
|
self.drv.cli_commands[constants.CMD_INSTANCE] = 'instance' |
|
self.drv.create_instance_bulk(tenant_id, create_ports, devices, |
|
port_profiles=port_profiles, sync=True) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', |
|
'configure', |
|
'cvx', |
|
'service openstack', |
|
'region RegionOne sync', |
|
'tenant ten-3'] |
|
|
|
for count, device in enumerate(devices.values(), 1): |
|
for v_port in device['ports']: |
|
port_id = v_port['portId'] |
|
port = create_ports[port_id] |
|
host = v_port['hosts'][0] |
|
vm_id = device['vmId'] |
|
port_name = port['name'] |
|
network_id = port['network_id'] |
|
device_owner = port['device_owner'] |
|
device_id = port['device_id'] |
|
|
|
if device_owner == n_const.DEVICE_OWNER_DHCP: |
|
cmd2.append('network id %s' % network_id) |
|
cmd2.append('dhcp id %s hostid %s port-id %s name "%s"' % ( |
|
vm_id, host, port_id, port_name)) |
|
elif device_owner == 'compute': |
|
cmd2.append('vm id %s hostid %s' % (vm_id, host)) |
|
cmd2.append('port id %s name "%s" network-id %s' % ( |
|
port_id, port_name, network_id)) |
|
elif device_owner == n_const.DEVICE_OWNER_DVR_INTERFACE: |
|
cmd2.append('instance id %s type router' % device_id) |
|
cmd2.append('port id %s network-id %s hostid %s' % ( |
|
port_id, network_id, host)) |
|
if count == (num_devices - 1): |
|
# Send heartbeat |
|
cmd2.append('sync heartbeat') |
|
|
|
# Send the final heartbeat |
|
cmd2.append('sync heartbeat') |
|
|
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_delete_tenant_bulk_during_sync(self, mock_send_eapi_req): |
|
self._enable_sync_cmds() |
|
num_tenants = 101 |
|
tenant_list = ['ten-%d' % t_id for t_id in range(1, num_tenants + 1)] |
|
self.drv.delete_tenant_bulk(tenant_list, sync=True) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', |
|
'configure', |
|
'cvx', |
|
'service openstack', |
|
'region RegionOne sync'] |
|
for ten_id in range(1, num_tenants + 1): |
|
cmd2.append('no tenant ten-%d' % ten_id) |
|
|
|
cmd2.append('sync heartbeat') |
|
|
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
|
|
class AristaRPCWrapperInvalidConfigTestCase(base.BaseTestCase): |
|
"""Negative test cases to test the Arista Driver configuration.""" |
|
|
|
def setUp(self): |
|
super(AristaRPCWrapperInvalidConfigTestCase, self).setUp() |
|
self.setup_invalid_config() # Invalid config, required options not set |
|
|
|
def setup_invalid_config(self): |
|
utils.setup_arista_wrapper_config(cfg, host='', user='') |
|
|
|
def test_raises_exception_on_wrong_configuration(self): |
|
ndb = db_lib.NeutronNets() |
|
self.assertRaises(arista_exc.AristaConfigError, |
|
arista_eapi.AristaRPCWrapperEapi, ndb) |
|
|
|
|
|
class NegativeRPCWrapperTestCase(testlib_api.SqlTestCase): |
|
"""Negative test cases to test the RPC between Arista Driver and EOS.""" |
|
|
|
def setUp(self): |
|
super(NegativeRPCWrapperTestCase, self).setUp() |
|
setup_valid_config() |
|
|
|
def test_exception_is_raised_on_json_server_error(self): |
|
ndb = db_lib.NeutronNets() |
|
drv = arista_eapi.AristaRPCWrapperEapi(ndb) |
|
|
|
drv._send_api_request = mock.MagicMock( |
|
side_effect=Exception('server error') |
|
) |
|
with mock.patch.object(arista_eapi.LOG, 'error') as log_err: |
|
self.assertRaises(arista_exc.AristaRpcError, drv.get_tenants) |
|
log_err.assert_called_once_with(mock.ANY) |
|
|
|
|
|
class RPCWrapperEapiValidConfigTrunkTestCase(testlib_api.SqlTestCase): |
|
"""Test cases to test plug trunk port into network.""" |
|
|
|
def setUp(self): |
|
super(RPCWrapperEapiValidConfigTrunkTestCase, self).setUp() |
|
setup_valid_config() |
|
ndb = mock.MagicMock() |
|
self.drv = arista_eapi.AristaRPCWrapperEapi(ndb) |
|
self.drv._server_ip = "10.11.12.13" |
|
self.region = 'RegionOne' |
|
arista_eapi.db_lib = mock.MagicMock() |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_plug_host_into_network(self, mock_send_eapi_req): |
|
tenant_id = 'ten-1' |
|
network_id = 'net-id-1' |
|
vm_id = 'vm-1' |
|
port_id = 111 |
|
host = 'host' |
|
port_name = '111-port' |
|
sub_segment_id = 'sub_segment_id_1' |
|
sub_segmentation_id = 1002 |
|
sub_network_id = 'subnet-id' |
|
subport_id = 222 |
|
segment_id = 'segment_id_1' |
|
segments = [{'network_type': 'vlan', 'physical_network': 'default', |
|
'segmentation_id': 1234, 'id': segment_id}] |
|
binding_level = FakePortBindingLevel(subport_id, 0, 'vendor-1', |
|
sub_segment_id) |
|
subport_segments = [binding_level] |
|
trunk_details = {'sub_ports': [{'mac_address': 'mac_address', |
|
'port_id': subport_id, |
|
'segmentation_id': sub_segmentation_id, |
|
'segmentation_type': 'vlan'}], |
|
'trunk_id': 'trunk_id'} |
|
self.drv._ndb.get_network_id_from_port_id.return_value = sub_network_id |
|
arista_eapi.db_lib.get_port_binding_level.return_value = \ |
|
subport_segments |
|
|
|
self.drv.plug_host_into_network(vm_id, host, port_id, |
|
network_id, tenant_id, segments, |
|
port_name, trunk_details=trunk_details) |
|
|
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', 'configure', 'cvx', 'service openstack', |
|
'region RegionOne', |
|
'tenant ten-1', 'vm id vm-1 hostid host', |
|
'port id 111 name "111-port" network-id net-id-1', |
|
] |
|
for level, segment in enumerate(segments): |
|
cmd2.append('segment level %s id %s' % (level, segment['id'])) |
|
cmd2.append('port id 222 network-id subnet-id') |
|
for segment in subport_segments: |
|
cmd2.append('segment level %s id %s' % (segment.level, |
|
segment.segment_id)) |
|
|
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_plug_baremetal_into_network(self, mock_send_eapi_req): |
|
tenant_id = 'ten-2' |
|
network_id = 'net-id-1' |
|
bm_id = 'bm-1' |
|
port_id = 'p1' |
|
host = 'host' |
|
port_name = 'name_p1' |
|
device_owner = 'compute:None' |
|
subport_id = 222 |
|
sub_segment_id = 'sub_segment_id_1' |
|
|
|
segments = [{'segmentation_id': 1001, |
|
'id': 'segment_id_1', |
|
'network_type': 'vlan', |
|
'is_dynamic': False}] |
|
|
|
subport_net_id = 'net-id-2' |
|
binding_level = FakePortBindingLevel(subport_id, 0, 'vendor-1', |
|
sub_segment_id) |
|
subport_segments = [binding_level] |
|
|
|
trunk_details = {'sub_ports': [{'mac_address': 'mac_address', |
|
'port_id': 'p2', |
|
'segmentation_id': 1002, |
|
'segmentation_type': 'vlan'}], |
|
'trunk_id': 'trunk_id'} |
|
switch_bindings = {'local_link_information': [ |
|
{'port_id': 'Eth1', 'switch_id': 'switch-id-1', |
|
'switch_info': 'switch-1'}]} |
|
bindings = switch_bindings['local_link_information'] |
|
self.drv._ndb.get_network_id_from_port_id.return_value = subport_net_id |
|
arista_eapi.db_lib.get_port_binding_level.return_value = \ |
|
subport_segments |
|
|
|
self.drv.bm_and_dvr_supported = mock.MagicMock(return_value=True) |
|
|
|
self.drv.plug_baremetal_into_network(bm_id, host, port_id, |
|
network_id, tenant_id, |
|
segments, port_name, |
|
device_owner, |
|
None, None, 'baremetal', |
|
bindings, trunk_details) |
|
|
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', 'configure', 'cvx', 'service openstack', |
|
'region RegionOne', |
|
'tenant ten-2', |
|
'instance id bm-1 hostid host type baremetal', |
|
'port id p1 name "name_p1" network-id net-id-1 ' |
|
'type native switch-id switch-id-1 switchport Eth1', |
|
] |
|
for level, segment in enumerate(segments): |
|
cmd2.append('segment level %s id %s' % (level, segment['id'])) |
|
cmd2.append('port id p2 network-id net-id-2 ' |
|
'type allowed switch-id switch-id-1 switchport Eth1', ) |
|
for segment in subport_segments: |
|
cmd2.append('segment level %s id %s' % (segment.level, |
|
segment.segment_id)) |
|
cmd2.append('exit') |
|
|
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_unplug_host_from_network(self, mock_send_eapi_req): |
|
tenant_id = 'ten-2' |
|
network_id = 'net-id-1' |
|
vm_id = 'vm-2' |
|
port_id = 111 |
|
host = 'host' |
|
subport_id = 222 |
|
|
|
trunk_details = {'sub_ports': [{'mac_address': 'mac_address', |
|
'port_id': subport_id, |
|
'segmentation_id': 123, |
|
'segmentation_type': 'vlan'}], |
|
'trunk_id': 'trunk_id'} |
|
self.drv.unplug_host_from_network(vm_id, host, port_id, |
|
network_id, tenant_id, |
|
trunk_details) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', 'configure', 'cvx', 'service openstack', |
|
'region RegionOne', |
|
'tenant ten-2', 'vm id vm-2 hostid host', |
|
'no port id 222', |
|
'no port id 111', |
|
] |
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
@patch(EAPI_SEND_FUNC) |
|
def test_unplug_baremetal_from_network(self, mock_send_eapi_req): |
|
tenant_id = 'ten-2' |
|
network_id = 'net-id-1' |
|
bm_id = 'bm-2' |
|
port_id = 111 |
|
host = 'host' |
|
subport_id = 222 |
|
|
|
trunk_details = {'sub_ports': [{'mac_address': 'mac_address', |
|
'port_id': subport_id, |
|
'segmentation_id': 123, |
|
'segmentation_type': 'vlan'}], |
|
'trunk_id': 'trunk_id'} |
|
switch_bindings = {'local_link_information': [ |
|
{'port_id': 'Eth1', 'switch_id': 'switch-id-1', |
|
'switch_info': 'switch-1'}]} |
|
bindings = switch_bindings['local_link_information'] |
|
self.drv.bm_and_dvr_supported = mock.MagicMock(return_value=True) |
|
self.drv.unplug_baremetal_from_network(bm_id, host, port_id, |
|
network_id, tenant_id, |
|
None, 'baremetal', |
|
bindings, trunk_details) |
|
cmd1 = ['show openstack agent uuid'] |
|
cmd2 = ['enable', 'configure', 'cvx', 'service openstack', |
|
'region RegionOne', |
|
'tenant ten-2', |
|
'instance id bm-2 hostid host type baremetal', |
|
'no port id 222', |
|
'no port id 111', |
|
] |
|
self._verify_send_eapi_request_calls(mock_send_eapi_req, [cmd1, cmd2]) |
|
|
|
def _verify_send_eapi_request_calls(self, mock_send_eapi_req, cmds, |
|
commands_to_log=None): |
|
calls = [] |
|
calls.extend( |
|
mock.call(cmds=cmd, commands_to_log=log_cmd) |
|
for cmd, log_cmd in six.moves.zip(cmds, commands_to_log or cmds)) |
|
mock_send_eapi_req.assert_has_calls(calls)
|
|
|