Merge pull request #336 from openstack-charmers/lourot/arista
Add functional tests for neutron-arista
This commit is contained in:
@@ -292,36 +292,44 @@ class NeutronCreateNetworkTest(test_utils.OpenStackBaseTest):
|
||||
# set up clients
|
||||
cls.neutron_client = (
|
||||
openstack_utils.get_neutron_session_client(cls.keystone_session))
|
||||
cls.neutron_client.format = 'json'
|
||||
|
||||
_TEST_NET_NAME = 'test_net'
|
||||
|
||||
def test_400_create_network(self):
|
||||
"""Create a network, verify that it exists, and then delete it."""
|
||||
self._assert_test_network_doesnt_exist()
|
||||
self._create_test_network()
|
||||
net_id = self._assert_test_network_exists_and_return_id()
|
||||
self._delete_test_network(net_id)
|
||||
self._assert_test_network_doesnt_exist()
|
||||
|
||||
def _create_test_network(self):
|
||||
logging.debug('Creating neutron network...')
|
||||
self.neutron_client.format = 'json'
|
||||
net_name = 'test_net'
|
||||
|
||||
# Verify that the network doesn't exist
|
||||
networks = self.neutron_client.list_networks(name=net_name)
|
||||
net_count = len(networks['networks'])
|
||||
assert net_count == 0, (
|
||||
"Expected zero networks, found {}".format(net_count))
|
||||
|
||||
# Create a network and verify that it exists
|
||||
network = {'name': net_name}
|
||||
network = {'name': self._TEST_NET_NAME}
|
||||
self.neutron_client.create_network({'network': network})
|
||||
|
||||
networks = self.neutron_client.list_networks(name=net_name)
|
||||
def _delete_test_network(self, net_id):
|
||||
logging.debug('Deleting neutron network...')
|
||||
self.neutron_client.delete_network(net_id)
|
||||
|
||||
def _assert_test_network_exists_and_return_id(self):
|
||||
logging.debug('Confirming new neutron network...')
|
||||
networks = self.neutron_client.list_networks(name=self._TEST_NET_NAME)
|
||||
logging.debug('Networks: {}'.format(networks))
|
||||
net_len = len(networks['networks'])
|
||||
assert net_len == 1, (
|
||||
"Expected 1 network, found {}".format(net_len))
|
||||
|
||||
logging.debug('Confirming new neutron network...')
|
||||
network = networks['networks'][0]
|
||||
assert network['name'] == net_name, "network ext_net not found"
|
||||
assert network['name'] == self._TEST_NET_NAME, \
|
||||
"network {} not found".format(self._TEST_NET_NAME)
|
||||
return network['id']
|
||||
|
||||
# Cleanup
|
||||
logging.debug('Deleting neutron network...')
|
||||
self.neutron_client.delete_network(network['id'])
|
||||
def _assert_test_network_doesnt_exist(self):
|
||||
networks = self.neutron_client.list_networks(name=self._TEST_NET_NAME)
|
||||
net_count = len(networks['networks'])
|
||||
assert net_count == 0, (
|
||||
"Expected zero networks, found {}".format(net_count))
|
||||
|
||||
|
||||
class NeutronApiTest(NeutronCreateNetworkTest):
|
||||
|
||||
15
zaza/openstack/charm_tests/neutron_arista/__init__.py
Normal file
15
zaza/openstack/charm_tests/neutron_arista/__init__.py
Normal file
@@ -0,0 +1,15 @@
|
||||
# Copyright 2020 Canonical Ltd.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Collection of code for setting up and testing neutron-api-plugin-arista."""
|
||||
76
zaza/openstack/charm_tests/neutron_arista/setup.py
Normal file
76
zaza/openstack/charm_tests/neutron_arista/setup.py
Normal file
@@ -0,0 +1,76 @@
|
||||
# Copyright 2020 Canonical Ltd.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Code for setting up neutron-api-plugin-arista."""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import tenacity
|
||||
import zaza
|
||||
import zaza.openstack.charm_tests.neutron_arista.utils as arista_utils
|
||||
import zaza.openstack.utilities.openstack as openstack_utils
|
||||
|
||||
|
||||
def download_arista_image():
|
||||
"""Download arista-cvx-virt-test.qcow2 from a web server.
|
||||
|
||||
The download will happen only if the env var TEST_ARISTA_IMAGE_REMOTE has
|
||||
been set, so you don't have to set it if you already have the image
|
||||
locally.
|
||||
|
||||
If the env var TEST_ARISTA_IMAGE_LOCAL isn't set, it will be set to
|
||||
`/tmp/arista-cvx-virt-test.qcow2`. This is where the image will be
|
||||
downloaded to if TEST_ARISTA_IMAGE_REMOTE has been set.
|
||||
"""
|
||||
try:
|
||||
os.environ['TEST_ARISTA_IMAGE_LOCAL']
|
||||
except KeyError:
|
||||
os.environ['TEST_ARISTA_IMAGE_LOCAL'] = ''
|
||||
if not os.environ['TEST_ARISTA_IMAGE_LOCAL']:
|
||||
os.environ['TEST_ARISTA_IMAGE_LOCAL'] \
|
||||
= '/tmp/arista-cvx-virt-test.qcow2'
|
||||
|
||||
try:
|
||||
if os.environ['TEST_ARISTA_IMAGE_REMOTE']:
|
||||
logging.info('Downloading Arista image from {}'
|
||||
.format(os.environ['TEST_ARISTA_IMAGE_REMOTE']))
|
||||
openstack_utils.download_image(
|
||||
os.environ['TEST_ARISTA_IMAGE_REMOTE'],
|
||||
os.environ['TEST_ARISTA_IMAGE_LOCAL'])
|
||||
except KeyError:
|
||||
# TEST_ARISTA_IMAGE_REMOTE isn't set, which means the image is already
|
||||
# available at TEST_ARISTA_IMAGE_LOCAL
|
||||
pass
|
||||
|
||||
logging.info('Arista image can be found at {}'
|
||||
.format(os.environ['TEST_ARISTA_IMAGE_LOCAL']))
|
||||
|
||||
|
||||
def test_fixture():
|
||||
"""Pass arista-virt-test-fixture's IP address to Neutron."""
|
||||
fixture_ip_addr = arista_utils.fixture_ip_addr()
|
||||
logging.info(
|
||||
"{}'s IP address is '{}'. Passing it to neutron-api-plugin-arista..."
|
||||
.format(arista_utils.FIXTURE_APP_NAME, fixture_ip_addr))
|
||||
zaza.model.set_application_config('neutron-api-plugin-arista',
|
||||
{'eapi-host': fixture_ip_addr})
|
||||
|
||||
logging.info('Waiting for {} to become ready...'.format(
|
||||
arista_utils.FIXTURE_APP_NAME))
|
||||
for attempt in tenacity.Retrying(
|
||||
wait=tenacity.wait_fixed(10), # seconds
|
||||
stop=tenacity.stop_after_attempt(30),
|
||||
reraise=True):
|
||||
with attempt:
|
||||
arista_utils.query_fixture_networks(fixture_ip_addr)
|
||||
53
zaza/openstack/charm_tests/neutron_arista/tests.py
Normal file
53
zaza/openstack/charm_tests/neutron_arista/tests.py
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright 2020 Canonical Ltd.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Encapsulating `neutron-api-plugin-arista` testing."""
|
||||
|
||||
import logging
|
||||
import tenacity
|
||||
import zaza.openstack.charm_tests.neutron.tests as neutron_tests
|
||||
import zaza.openstack.charm_tests.neutron_arista.utils as arista_utils
|
||||
|
||||
|
||||
class NeutronCreateAristaNetworkTest(neutron_tests.NeutronCreateNetworkTest):
|
||||
"""Test creating an Arista Neutron network through the API."""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""Run class setup for running Neutron Arista tests."""
|
||||
super(NeutronCreateAristaNetworkTest, cls).setUpClass()
|
||||
|
||||
logging.info('Waiting for Neutron to become ready...')
|
||||
for attempt in tenacity.Retrying(
|
||||
wait=tenacity.wait_fixed(5), # seconds
|
||||
stop=tenacity.stop_after_attempt(12),
|
||||
reraise=True):
|
||||
with attempt:
|
||||
cls.neutron_client.list_networks()
|
||||
|
||||
def _assert_test_network_exists_and_return_id(self):
|
||||
actual_network_names = arista_utils.query_fixture_networks(
|
||||
arista_utils.fixture_ip_addr())
|
||||
self.assertEqual(actual_network_names, [self._TEST_NET_NAME])
|
||||
return super(NeutronCreateAristaNetworkTest,
|
||||
self)._assert_test_network_exists_and_return_id()
|
||||
|
||||
def _assert_test_network_doesnt_exist(self):
|
||||
actual_network_names = arista_utils.query_fixture_networks(
|
||||
arista_utils.fixture_ip_addr())
|
||||
self.assertEqual(actual_network_names, [])
|
||||
super(NeutronCreateAristaNetworkTest,
|
||||
self)._assert_test_network_doesnt_exist()
|
||||
67
zaza/openstack/charm_tests/neutron_arista/utils.py
Normal file
67
zaza/openstack/charm_tests/neutron_arista/utils.py
Normal file
@@ -0,0 +1,67 @@
|
||||
# Copyright 2020 Canonical Ltd.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Common Arista-related utils."""
|
||||
|
||||
import json
|
||||
import requests
|
||||
import urllib3
|
||||
import zaza
|
||||
|
||||
FIXTURE_APP_NAME = 'arista-virt-test-fixture'
|
||||
|
||||
|
||||
def fixture_ip_addr():
|
||||
"""Return the public IP address of the Arista test fixture."""
|
||||
return zaza.model.get_units(FIXTURE_APP_NAME)[0].public_address
|
||||
|
||||
|
||||
_FIXTURE_LOGIN = 'admin'
|
||||
_FIXTURE_PASSWORD = 'password123'
|
||||
|
||||
|
||||
def query_fixture_networks(ip_addr):
|
||||
"""Query the Arista test fixture's list of networks."""
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
|
||||
session = requests.Session()
|
||||
session.headers['Content-Type'] = 'application/json'
|
||||
session.headers['Accept'] = 'application/json'
|
||||
session.verify = False
|
||||
session.auth = (_FIXTURE_LOGIN, _FIXTURE_PASSWORD)
|
||||
|
||||
data = {
|
||||
'id': 'Zaza neutron-api-plugin-arista tests',
|
||||
'method': 'runCmds',
|
||||
'jsonrpc': '2.0',
|
||||
'params': {
|
||||
'timestamps': False,
|
||||
'format': 'json',
|
||||
'version': 1,
|
||||
'cmds': ['show openstack networks']
|
||||
}
|
||||
}
|
||||
|
||||
response = session.post(
|
||||
'https://{}/command-api/'.format(ip_addr),
|
||||
data=json.dumps(data),
|
||||
timeout=10 # seconds
|
||||
)
|
||||
|
||||
result = []
|
||||
for region in response.json()['result'][0]['regions'].values():
|
||||
for tenant in region['tenants'].values():
|
||||
for network in tenant['tenantNetworks'].values():
|
||||
result.append(network['networkName'])
|
||||
return result
|
||||
Reference in New Issue
Block a user