Merge pull request #996 from freyes/add-tempest-magnum-support

Add tempest magnum support
This commit is contained in:
coreycb
2023-02-14 16:19:17 -05:00
committed by GitHub
11 changed files with 237 additions and 27 deletions

View File

@@ -0,0 +1,72 @@
# Copyright 2023 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.
import os
import unittest
from unittest import mock
import zaza.openstack.charm_tests.magnum.setup as magnum_setup
class TestMagnumSetup(unittest.TestCase):
@mock.patch.object(magnum_setup.openstack_utils,
'get_current_os_release_pair')
def test_get_fedora_coreos_image_url(self, get_current_os_release_pair):
get_current_os_release_pair.return_value = 'focal_ussuri'
self.assertEqual(magnum_setup.FEDORA_COREOS_IMAGE['ussuri'],
magnum_setup.get_fedora_coreos_image_url())
self.assertEqual(magnum_setup.FEDORA_COREOS_IMAGE['xena'],
magnum_setup.get_fedora_coreos_image_url('xena'))
self.assertEqual(magnum_setup.DEFAULT_FEDORA_COREOS_IMAGE_URL,
magnum_setup.get_fedora_coreos_image_url('foobar'))
@mock.patch.object(magnum_setup, 'get_fedora_coreos_image_url')
@mock.patch.object(magnum_setup.openstack_utils,
'get_overcloud_keystone_session')
@mock.patch.object(magnum_setup.openstack_utils,
'get_glance_session_client')
@mock.patch.object(magnum_setup.openstack_utils,
'create_image')
def test_add_image(self, create_image, get_glance_session_client,
get_overcloud_keystone_session,
get_fedora_coreos_image_url):
image_url = 'http://example.com/image.qcow2'
with mock.patch.dict(os.environ,
{'TEST_MAGNUM_QCOW2_IMAGE_URL':
image_url},
clear=True) as environ: # noqa:F841
magnum_setup.add_image()
create_image.assert_called_with(
get_glance_session_client(),
image_url,
magnum_setup.IMAGE_NAME,
properties={'os_distro': magnum_setup.IMAGE_NAME}
)
get_fedora_coreos_image_url.assert_not_called()
image_url = 'http://example.com/fedora-coreos.qcow2'
get_fedora_coreos_image_url.return_value = image_url
with mock.patch.dict(os.environ, {},
clear=True) as environ: # noqa:F841
magnum_setup.add_image()
create_image.assert_called_with(
get_glance_session_client(),
image_url,
magnum_setup.IMAGE_NAME,
properties={'os_distro': magnum_setup.IMAGE_NAME}
)
get_fedora_coreos_image_url.assert_called()

View File

@@ -12,9 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import mock
import os
import unittest
from unittest import mock
import zaza.openstack.charm_tests.tempest.utils as tempest_utils
@@ -61,3 +63,21 @@ class TestTempestUtils(unittest.TestCase):
('Environment variables [TEST_CIDR_EXT, TEST_FIP_RANGE] must '
'all be set to run this test'),
str(context.exception))
@mock.patch.object(tempest_utils, '_add_image_id')
def test_add_magnum_config(self, _add_image_id):
ctxt = {}
keystone_session = mock.MagicMock()
with mock.patch.dict(os.environ,
{'TEST_REGISTRY_PREFIX': '1.2.3.4:5000'},
clear=True) as environ: # noqa:F841
tempest_utils._add_magnum_config(ctxt, keystone_session)
self.assertIn('test_registry_prefix', ctxt)
self.assertEqual(ctxt['test_registry_prefix'], '1.2.3.4:5000')
_add_image_id.assert_called()
ctxt = {}
with mock.patch.dict(os.environ, {},
clear=True) as environ: # noqa:F841
tempest_utils._add_magnum_config(ctxt, keystone_session)
self.assertNotIn('test_registry_prefix', ctxt)

View File

@@ -42,8 +42,8 @@ class TestBaseCharmTest(ut_utils.BaseTestCase):
return self.get_my_tests_options('aKey', 'aDefault')
f = FakeTest()
self.assertEquals(f.method({}), 'aDefault')
self.assertEquals(f.method({
self.assertEqual(f.method({}), 'aDefault')
self.assertEqual(f.method({
'tests_options': {
'unit_tests.charm_tests.test_utils.'
'FakeTest.method.aKey': 'aValue',

View File

@@ -127,7 +127,7 @@ class TestCephUtils(ut_utils.BaseTestCase):
'{"op": "create-pool", "name": "cinder-ceph", '
'"compression-mode": "aggressive"}]}'),
}
self.assertEquals(
self.assertEqual(
ceph_utils.get_pools_from_broker_req(
'anApplication', 'aModelName'),
['cinder-ceph'])

View File

@@ -1322,7 +1322,7 @@ class TestOpenStackUtils(ut_utils.BaseTestCase):
self.patch_object(openstack_utils.juju_utils,
'get_machine_uuids_for_application')
self.get_machine_uuids_for_application.return_value = 'ret'
self.assertEquals(openstack_utils.get_gateway_uuids(), 'ret')
self.assertEqual(openstack_utils.get_gateway_uuids(), 'ret')
self.get_machine_uuids_for_application.assert_called_once_with(
'neutron-gateway')
@@ -1330,7 +1330,7 @@ class TestOpenStackUtils(ut_utils.BaseTestCase):
self.patch_object(openstack_utils.juju_utils,
'get_machine_uuids_for_application')
self.get_machine_uuids_for_application.return_value = 'ret'
self.assertEquals(openstack_utils.get_ovs_uuids(), 'ret')
self.assertEqual(openstack_utils.get_ovs_uuids(), 'ret')
self.get_machine_uuids_for_application.assert_called_once_with(
'neutron-openvswitch')
@@ -1338,8 +1338,8 @@ class TestOpenStackUtils(ut_utils.BaseTestCase):
self.patch_object(openstack_utils.juju_utils,
'get_machine_uuids_for_application')
self.get_machine_uuids_for_application.return_value = ['ret']
self.assertEquals(list(openstack_utils.get_ovn_uuids()),
['ret', 'ret'])
self.assertEqual(list(openstack_utils.get_ovn_uuids()),
['ret', 'ret'])
self.get_machine_uuids_for_application.assert_has_calls([
mock.call('ovn-chassis'),
mock.call('ovn-dedicated-chassis'),
@@ -1387,7 +1387,7 @@ class TestOpenStackUtils(ut_utils.BaseTestCase):
with self.assertRaises(RuntimeError):
openstack_utils.get_charm_networking_data()
self.ngw_present.return_value = True
self.assertEquals(
self.assertEqual(
openstack_utils.get_charm_networking_data(),
openstack_utils.CharmedOpenStackNetworkingData(
openstack_utils.OpenStackNetworkingTopology.ML2_OVS,
@@ -1396,7 +1396,7 @@ class TestOpenStackUtils(ut_utils.BaseTestCase):
'data-port',
{}))
self.dvr_enabled.return_value = True
self.assertEquals(
self.assertEqual(
openstack_utils.get_charm_networking_data(),
openstack_utils.CharmedOpenStackNetworkingData(
openstack_utils.OpenStackNetworkingTopology.ML2_OVS_DVR,
@@ -1405,7 +1405,7 @@ class TestOpenStackUtils(ut_utils.BaseTestCase):
'data-port',
{}))
self.ngw_present.return_value = False
self.assertEquals(
self.assertEqual(
openstack_utils.get_charm_networking_data(),
openstack_utils.CharmedOpenStackNetworkingData(
openstack_utils.OpenStackNetworkingTopology.ML2_OVS_DVR_SNAT,
@@ -1415,7 +1415,7 @@ class TestOpenStackUtils(ut_utils.BaseTestCase):
{}))
self.dvr_enabled.return_value = False
self.ovn_present.return_value = True
self.assertEquals(
self.assertEqual(
openstack_utils.get_charm_networking_data(),
openstack_utils.CharmedOpenStackNetworkingData(
openstack_utils.OpenStackNetworkingTopology.ML2_OVN,
@@ -1424,7 +1424,7 @@ class TestOpenStackUtils(ut_utils.BaseTestCase):
'bridge-interface-mappings',
{'ovn-bridge-mappings': 'physnet1:br-ex'}))
self.get_application.side_effect = None
self.assertEquals(
self.assertEqual(
openstack_utils.get_charm_networking_data(),
openstack_utils.CharmedOpenStackNetworkingData(
openstack_utils.OpenStackNetworkingTopology.ML2_OVN,

View File

@@ -147,7 +147,7 @@ class CephFSTests(unittest.TestCase):
"""
model.set_application_config('ceph-fs', mds_config)
results = _get_conf()
self.assertEquals(
self.assertEqual(
results['mds_cache_memory_limit'],
mds_config['mds-cache-memory-limit'])
self.assertAlmostEqual(

View File

@@ -1323,12 +1323,12 @@ class BlueStoreCompressionCharmOperation(test_utils.BaseCharmTest):
if pd['pool_name'] == pool:
if 'options' in expected_properties:
for k, v in expected_properties['options'].items():
self.assertEquals(pd['options'][k], v)
self.assertEqual(pd['options'][k], v)
log_func("['options']['{}'] == {}".format(k, v))
for k, v in expected_properties.items():
if k == 'options':
continue
self.assertEquals(pd[k], v)
self.assertEqual(pd[k], v)
log_func("{} == {}".format(k, v))
def test_configure_compression(self):

View File

@@ -23,8 +23,30 @@ import tenacity
import zaza.model
import zaza.openstack.utilities.openstack as openstack_utils
TEST_SWIFT_IP = os.environ.get('TEST_SWIFT_IP')
IMAGE_NAME = 'fedora-coreos'
# https://docs.openstack.org/magnum/latest/user/index.html#supported-versions
# List of published image available at:
# https://builds.coreos.fedoraproject.org/browser?stream=stable&arch=x86_64
#
# Source images:
# https://builds.coreos.fedoraproject.org/prod/streams/stable/builds/35.20220424.3.0/x86_64/fedora-coreos-35.20220424.3.0-openstack.x86_64.qcow2.xz # noqa
# https://builds.coreos.fedoraproject.org/prod/streams/stable/builds/31.20200517.3.0/x86_64/fedora-coreos-31.20200517.3.0-openstack.x86_64.qcow2.xz # noqa
# https://builds.coreos.fedoraproject.org/prod/streams/stable/builds/32.20201104.3.0/x86_64/fedora-coreos-32.20201104.3.0-openstack.x86_64.qcow2.xz # noqa
FEDORA_COREOS_31 = 'http://%s/magnum/images/fedora-coreos-31.qcow2' % TEST_SWIFT_IP # noqa
FEDORA_COREOS_32 = 'http://%s/magnum/images/fedora-coreos-32.qcow2' % TEST_SWIFT_IP # noqa
FEDORA_COREOS_35 = 'http://%s/magnum/images/fedora-coreos-35.qcow2' % TEST_SWIFT_IP # noqa
DEFAULT_FEDORA_COREOS_IMAGE_URL = FEDORA_COREOS_35
FEDORA_COREOS_IMAGE = {
'ussuri': FEDORA_COREOS_32,
'victoria': FEDORA_COREOS_31,
'wallaby': FEDORA_COREOS_31,
'xena': FEDORA_COREOS_31,
'yoga': FEDORA_COREOS_35,
'zed': FEDORA_COREOS_35,
}
def domain_setup(application_name='magnum'):
"""Run required action for a working Magnum application."""
@@ -37,6 +59,25 @@ def domain_setup(application_name='magnum'):
"Unit is ready")
def get_fedora_coreos_image_url(os_release: str = None) -> str:
"""Get Fedora CoreOS image url compatible with the Magnum release deployed.
:param os_release: OpenStack release codename (e.g. ussuri).
:returns: url where the image can be GET.
"""
if not os_release:
pair = openstack_utils.get_current_os_release_pair('keystone')
os_release = pair.split('_', 1)[1]
if os_release in FEDORA_COREOS_IMAGE:
return FEDORA_COREOS_IMAGE[os_release]
else:
logging.warning(
'No image found for OpenStack %s, using default image %s',
os_release, DEFAULT_FEDORA_COREOS_IMAGE_URL
)
return DEFAULT_FEDORA_COREOS_IMAGE_URL
def add_image(image_url=None):
"""Upload Magnum image.
@@ -47,9 +88,8 @@ def add_image(image_url=None):
:type image_url: str
"""
image_url = image_url or os.environ.get(
'TEST_MAGNUM_QCOW2_IMAGE_URL', None)
if image_url is None:
raise ValueError("Missing image_url")
'TEST_MAGNUM_QCOW2_IMAGE_URL', None) or get_fedora_coreos_image_url()
for attempt in tenacity.Retrying(
stop=tenacity.stop_after_attempt(3),
reraise=True):

View File

@@ -0,0 +1,16 @@
#!/bin/bash
wget -O - https://builds.coreos.fedoraproject.org/prod/streams/stable/builds/31.20200517.3.0/x86_64/fedora-coreos-31.20200517.3.0-openstack.x86_64.qcow2.xz \
| xzcat > ./fedora-coreos-31.qcow2
openstack object create --name images/fedora-coreos-31.qcow2 magnum ./fedora-coreos-31.qcow2
wget -O - https://builds.coreos.fedoraproject.org/prod/streams/stable/builds/32.20201104.3.0/x86_64/fedora-coreos-32.20201104.3.0-openstack.x86_64.qcow2.xz \
| xzcat > ./fedora-coreos-32.qcow2
openstack object create --name images/fedora-coreos-32.qcow2 magnum ./fedora-coreos-32.qcow2
wget -O - https://builds.coreos.fedoraproject.org/prod/streams/stable/builds/35.20220424.3.0/x86_64/fedora-coreos-35.20220424.3.0-openstack.x86_64.qcow2.xz \
| xzcat > ./fedora-coreos-35.qcow2
openstack object create --name images/fedora-coreos-35.qcow2 magnum ./fedora-coreos-35.qcow2

View File

@@ -122,5 +122,19 @@ test_server_path = {{ workspace_path }}/test_server.bin
provider = amphora
{% endif %}
{%- if 'magnum' in enabled_services %}
[magnum]
nic_id = {{ ext_net }}
image_id = {{ fedora_coreos_id }}
master_flavor_id = {{ flavor_ref }}
flavor_id = {{ flavor_ref }}
dns_nameserver = {{ test_name_server }}
network_driver = flannel
{%- if test_registry_prefix %}
labels = container_infra_prefix:{{ test_registry_prefix }}
insecure_registry = {{ test_registry_prefix }}
{%- endif %}
{%- endif %}
[dns]
nameservers = {{ test_name_server }}

View File

@@ -15,6 +15,7 @@
"""Utility code for working with tempest workspaces."""
import jinja2
import logging
import os
from pathlib import Path
import shutil
@@ -28,6 +29,7 @@ import zaza.utilities.deployment_env as deployment_env
import zaza.openstack.utilities.juju as juju_utils
import zaza.openstack.utilities.openstack as openstack_utils
import zaza.openstack.charm_tests.glance.setup as glance_setup
import zaza.openstack.charm_tests.magnum.setup as magnum_setup
SETUP_ENV_VARS = {
'neutron': ['TEST_GATEWAY', 'TEST_CIDR_EXT', 'TEST_FIP_RANGE',
@@ -156,7 +158,9 @@ def _get_tempest_context(workspace_path, missing_fatal=True):
'neutron': _add_neutron_config,
'glance': _add_glance_config,
'cinder': _add_cinder_config,
'keystone': _add_keystone_config}
'keystone': _add_keystone_config,
'magnum': _add_magnum_config,
}
ctxt['enabled_services'] = _get_service_list(keystone_session)
if set(['cinderv2', 'cinderv3']) \
.intersection(set(ctxt['enabled_services'])):
@@ -284,16 +288,39 @@ def _add_glance_config(ctxt, keystone_session, missing_fatal=True):
:returns: None
:rtype: None
"""
_add_image_id(ctxt, keystone_session,
glance_setup.CIRROS_IMAGE_NAME, 'image_id',
missing_fatal)
_add_image_id(ctxt, keystone_session,
glance_setup.CIRROS_ALT_IMAGE_NAME, 'image_alt_id',
missing_fatal)
def _add_image_id(ctxt, keystone_session, image_name, ctxt_key,
missing_fatal=True):
"""Add an image id to the context.
:param ctxt: Context dictionary
:type ctxt: dict
:param keystone_session: keystoneauth1.session.Session object
:type: keystoneauth1.session.Session
:param image_name: Image's name to search in glance.
:type image_name: str
:param ctxt_key: key to use when adding the image id to the context.
:type ctxt_key: str
:param missing_fatal: Raise an exception if a resource is missing
:type missing_fatal: bool
"""
glance_client = openstack_utils.get_glance_session_client(
keystone_session)
image = openstack_utils.get_images_by_name(
glance_client, glance_setup.CIRROS_IMAGE_NAME)
image_alt = openstack_utils.get_images_by_name(
glance_client, glance_setup.CIRROS_ALT_IMAGE_NAME)
image = openstack_utils.get_images_by_name(glance_client, image_name)
if image:
ctxt['image_id'] = image[0].id
if image_alt:
ctxt['image_alt_id'] = image_alt[0].id
ctxt[ctxt_key] = image[0].id
else:
msg = 'Image %s not found' % image_name
logging.warning(msg)
if missing_fatal:
raise Exception(msg)
def _add_cinder_config(ctxt, keystone_session, missing_fatal=True):
@@ -360,6 +387,27 @@ def _add_octavia_config(ctxt, missing_fatal=True):
])
def _add_magnum_config(ctxt, keystone_session, missing_fatal=True):
"""Add magnum config to context.
:param ctxt: Context dictionary
:type ctxt: dict
:param missing_fatal: Raise an exception if a resource is missing
:type missing_fatal: bool
:returns: None
:rtype: None
:raises: subprocess.CalledProcessError
"""
_add_image_id(ctxt, keystone_session,
magnum_setup.IMAGE_NAME, 'fedora_coreos_id',
missing_fatal)
test_registry_prefix = os.environ.get('TEST_REGISTRY_PREFIX')
if test_registry_prefix:
ctxt['test_registry_prefix'] = test_registry_prefix
else:
logging.warning('Environment variable TEST_REGISTRY_PREFIX not found')
def _add_environment_var_config(ctxt, services, missing_fatal=True):
"""Add environment variable config to context.