Add Magnum tests (#515)
- Add Heat domain-setup action as a setup configuration option which can be used in other charms - test_100_domain_setup is being deprecated if the new configuration option is being used - Add Magnum tests - test create magnum cluster template - test create magnum cluster - test config changes - test pause and resume - TEST_MAGNUM_QCOW2_IMAGE_URL environment variable is required in the CI - The value of this variable should be a link to a fedora-coreos QCOW2 image
This commit is contained in:
@@ -36,6 +36,7 @@ python-glanceclient
|
||||
python-heatclient
|
||||
python-ironicclient
|
||||
python-keystoneclient
|
||||
python-magnumclient
|
||||
python-manilaclient
|
||||
python-neutronclient
|
||||
python-novaclient
|
||||
|
||||
1
setup.py
1
setup.py
@@ -53,6 +53,7 @@ install_require = [
|
||||
'python-ironicclient',
|
||||
'python-glanceclient<3.0.0',
|
||||
'python-keystoneclient<3.22.0',
|
||||
'python-magnumclient',
|
||||
'python-manilaclient<2.0.0',
|
||||
'python-novaclient<16.0.0',
|
||||
'python-neutronclient<7.0.0',
|
||||
|
||||
31
zaza/openstack/charm_tests/heat/setup.py
Normal file
31
zaza/openstack/charm_tests/heat/setup.py
Normal file
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright 2021 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 configuring heat."""
|
||||
|
||||
import logging
|
||||
import zaza.model
|
||||
|
||||
|
||||
def domain_setup(application_name='heat'):
|
||||
"""Run required action for a working Heat application."""
|
||||
# Action is REQUIRED to run for a functioning heat deployment
|
||||
logging.info('Running domain-setup action on heat unit...')
|
||||
zaza.model.block_until_wl_status_info_starts_with(application_name,
|
||||
"Unit is ready")
|
||||
zaza.model.run_action_on_leader(application_name, "domain-setup")
|
||||
zaza.model.block_until_wl_status_info_starts_with(application_name,
|
||||
"Unit is ready")
|
||||
@@ -62,6 +62,8 @@ class HeatBasicDeployment(test_utils.OpenStackBaseTest):
|
||||
services = ['heat-api', 'heat-api-cfn', 'heat-engine']
|
||||
return services
|
||||
|
||||
# TODO: Deprecate this function
|
||||
# domain-setup action has been added as a setup configuration option
|
||||
def test_100_domain_setup(self):
|
||||
"""Run required action for a working Heat unit."""
|
||||
# Action is REQUIRED to run for a functioning heat deployment
|
||||
|
||||
17
zaza/openstack/charm_tests/magnum/__init__.py
Normal file
17
zaza/openstack/charm_tests/magnum/__init__.py
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright 2021 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 magnum."""
|
||||
64
zaza/openstack/charm_tests/magnum/setup.py
Normal file
64
zaza/openstack/charm_tests/magnum/setup.py
Normal file
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright 2021 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 configuring magnum."""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import tenacity
|
||||
|
||||
import zaza.model
|
||||
import zaza.openstack.utilities.openstack as openstack_utils
|
||||
|
||||
IMAGE_NAME = 'fedora-coreos'
|
||||
|
||||
|
||||
def domain_setup(application_name='magnum'):
|
||||
"""Run required action for a working Magnum application."""
|
||||
# Action is REQUIRED to run for a functioning magnum deployment
|
||||
logging.info('Running domain-setup action on magnum unit...')
|
||||
zaza.model.block_until_wl_status_info_starts_with(application_name,
|
||||
"Unit is ready")
|
||||
zaza.model.run_action_on_leader(application_name, "domain-setup")
|
||||
zaza.model.block_until_wl_status_info_starts_with(application_name,
|
||||
"Unit is ready")
|
||||
|
||||
|
||||
def add_image(image_url=None):
|
||||
"""Upload Magnum image.
|
||||
|
||||
Upload the operating system images built for Kubernetes deployments.
|
||||
Fedora CoreOS image was tested by Magnum team.
|
||||
|
||||
:param image_url: URL where the image resides
|
||||
: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")
|
||||
for attempt in tenacity.Retrying(
|
||||
stop=tenacity.stop_after_attempt(3),
|
||||
reraise=True):
|
||||
with attempt:
|
||||
keystone_session = openstack_utils.get_overcloud_keystone_session()
|
||||
glance_client = openstack_utils.get_glance_session_client(
|
||||
keystone_session)
|
||||
image_properties = {
|
||||
'os_distro': IMAGE_NAME
|
||||
}
|
||||
openstack_utils.create_image(glance_client, image_url, IMAGE_NAME,
|
||||
properties=image_properties)
|
||||
157
zaza/openstack/charm_tests/magnum/tests.py
Normal file
157
zaza/openstack/charm_tests/magnum/tests.py
Normal file
@@ -0,0 +1,157 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright 2021 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.
|
||||
|
||||
"""Encapsulate magnum testing."""
|
||||
|
||||
import logging
|
||||
import urllib
|
||||
|
||||
import zaza.openstack.charm_tests.test_utils as test_utils
|
||||
import zaza.openstack.utilities.openstack as openstack_utils
|
||||
import zaza.openstack.utilities.generic as generic_utils
|
||||
|
||||
from zaza.openstack.charm_tests.magnum.setup import IMAGE_NAME
|
||||
|
||||
# Resource and name constants
|
||||
CLUSTER_NAME = 'test-kubernetes'
|
||||
TEMPLATE_NAME = 'test-kubernetes-template'
|
||||
FLAVOR_NAME = 'm1.small'
|
||||
|
||||
|
||||
class MagnumBasicDeployment(test_utils.OpenStackBaseTest):
|
||||
"""Encapsulate Magnum tests."""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""Run class setup for running magnum tests."""
|
||||
super(MagnumBasicDeployment, cls).setUpClass()
|
||||
cls.keystone_session = openstack_utils.get_overcloud_keystone_session()
|
||||
cls.magnum_client = openstack_utils.get_magnum_session_client(
|
||||
cls.keystone_session)
|
||||
cls.glance_client = openstack_utils.get_glance_session_client(
|
||||
cls.keystone_session)
|
||||
|
||||
@property
|
||||
def services(self):
|
||||
"""Return a list services for the selected OpenStack release.
|
||||
|
||||
:returns: List of services
|
||||
:rtype: [str]
|
||||
"""
|
||||
services = ['magnum-api', 'magnum-conductor']
|
||||
return services
|
||||
|
||||
def test_410_magnum_cluster_create_delete(self):
|
||||
"""Create cluster, confirm nova compute resource, delete cluster."""
|
||||
# Verify new image name
|
||||
images_list = list(self.glance_client.images.list())
|
||||
self.assertEqual(images_list[0].name, IMAGE_NAME,
|
||||
"Magnum image not found")
|
||||
|
||||
# Create magnum template
|
||||
template_fields = {
|
||||
'name': TEMPLATE_NAME,
|
||||
'image_id': IMAGE_NAME,
|
||||
'external_network_id': 'ext_net',
|
||||
'dns_nameserver': '1.1.1.1',
|
||||
'master_flavor_id': FLAVOR_NAME,
|
||||
'flavor_id': FLAVOR_NAME,
|
||||
'coe': 'kubernetes'
|
||||
}
|
||||
|
||||
logging.info('Creating magnum cluster template...')
|
||||
|
||||
template = self.magnum_client.cluster_templates.create(
|
||||
**template_fields)
|
||||
logging.info('Cluster template data: {}'.format(template))
|
||||
|
||||
# Create a magnum cluster from a magnum template, verify its status
|
||||
logging.info('Creating magnum cluster...')
|
||||
# Create the cluster
|
||||
cluster_fields = {
|
||||
'name': CLUSTER_NAME,
|
||||
'cluster_template_id': template.uuid,
|
||||
'master_count': 1,
|
||||
'node_count': 1,
|
||||
'keypair': 'zaza'
|
||||
}
|
||||
|
||||
cluster = self.magnum_client.clusters.create(**cluster_fields)
|
||||
logging.info('Cluster data: {}'.format(cluster))
|
||||
|
||||
# Confirm stack reaches COMPLETE status.
|
||||
openstack_utils.resource_reaches_status(
|
||||
self.magnum_client.clusters,
|
||||
cluster.uuid,
|
||||
expected_status="CREATE_COMPLETE",
|
||||
msg="Cluster status wait",
|
||||
stop_after_attempt=20,
|
||||
wait_iteration_max_time=600,
|
||||
wait_exponential_multiplier=2)
|
||||
|
||||
# List cluster
|
||||
clusters = list(self.magnum_client.clusters.list())
|
||||
logging.info('All clusters: {}'.format(clusters))
|
||||
|
||||
# Get cluster information
|
||||
cluster = self.magnum_client.clusters.get(CLUSTER_NAME)
|
||||
|
||||
# Check Kubernetes api address
|
||||
api_address = urllib.parse.urlparse(cluster.api_address)
|
||||
api_status = generic_utils.is_port_open(api_address.port,
|
||||
api_address.hostname)
|
||||
self.assertTrue(api_status, 'Kubernetes API is unavailable')
|
||||
|
||||
# Delete cluster
|
||||
logging.info('Deleting magnum cluster...')
|
||||
openstack_utils.delete_resource(self.magnum_client.clusters,
|
||||
CLUSTER_NAME, msg="magnum cluster")
|
||||
|
||||
# Delete template
|
||||
logging.info('Deleting magnum cluster template...')
|
||||
openstack_utils.delete_resource(self.magnum_client.cluster_templates,
|
||||
TEMPLATE_NAME,
|
||||
msg="magnum cluster template")
|
||||
|
||||
def test_900_magnum_restart_on_config_change(self):
|
||||
"""Verify the specified services are restarted when config changes."""
|
||||
logging.info('Testing restart on configuration change')
|
||||
|
||||
# Expected default and alternate values
|
||||
set_default = {'cert-manager-type': 'barbican'}
|
||||
set_alternate = {'cert-manager-type': 'x509keypair'}
|
||||
|
||||
# Config file affected by juju set config change
|
||||
conf_file = '/etc/magnum/magnum.conf'
|
||||
|
||||
# Make config change, check for service restarts
|
||||
logging.info('Making configuration change')
|
||||
self.restart_on_changed(
|
||||
conf_file,
|
||||
set_default,
|
||||
set_alternate,
|
||||
None,
|
||||
None,
|
||||
self.services)
|
||||
|
||||
def test_910_pause_and_resume(self):
|
||||
"""Run services pause and resume tests."""
|
||||
logging.info('Checking pause and resume actions...')
|
||||
|
||||
logging.info('Skipping pause resume test LP: #1886202...')
|
||||
return
|
||||
with self.pause_resume(self.services):
|
||||
logging.info("Testing pause resume")
|
||||
@@ -50,6 +50,7 @@ from openstack import connection
|
||||
from aodhclient.v2 import client as aodh_client
|
||||
from cinderclient import client as cinderclient
|
||||
from heatclient import client as heatclient
|
||||
from magnumclient import client as magnumclient
|
||||
from glanceclient import Client as GlanceClient
|
||||
from designateclient.client import Client as DesignateClient
|
||||
|
||||
@@ -407,6 +408,19 @@ def get_heat_session_client(session, version=1):
|
||||
return heatclient.Client(session=session, version=version)
|
||||
|
||||
|
||||
def get_magnum_session_client(session, version='1'):
|
||||
"""Return magnumclient authenticated by keystone session.
|
||||
|
||||
:param session: Keystone session object
|
||||
:type session: keystoneauth1.session.Session object
|
||||
:param version: Magnum API version
|
||||
:type version: string
|
||||
:returns: Authenticated magnumclient
|
||||
:rtype: magnumclient.Client object
|
||||
"""
|
||||
return magnumclient.Client(version, session=session)
|
||||
|
||||
|
||||
def get_cinder_session_client(session, version=3):
|
||||
"""Return cinderclient authenticated by keystone session.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user