Support to run cluster test using existing cluster template

- This fix is primarily focused on using existing cluster template
  use case.
- Rename 'keypair_id' to 'keypair_name' in the magnum tempest config.
- Add 'cluster_template_id' and 'cluster_creation_timeout' config
  options.
- Move the cluster template and keypair to the class-scoped resources.

Change-Id: Ib5260757e373ce545ca6900acf8871b6d96dcfb8
This commit is contained in:
Lingxian Kong 2019-04-08 18:42:12 +12:00
parent 5a18c8ebf0
commit 18a3103170
6 changed files with 126 additions and 103 deletions

View File

@ -102,10 +102,10 @@ class Config(object):
cls.nic_id = CONF.magnum.nic_id
@classmethod
def set_keypair_id(cls, config):
if 'keypair_id' not in CONF.magnum:
raise Exception('config missing keypair_id key')
cls.keypair_id = CONF.magnum.keypair_id
def set_keypair_name(cls, config):
if 'keypair_name' not in CONF.magnum:
raise Exception('config missing keypair_name key')
cls.keypair_name = CONF.magnum.keypair_name
@classmethod
def set_flavor_id(cls, config):
@ -149,6 +149,14 @@ class Config(object):
def set_network_driver(cls, config):
cls.network_driver = CONF.magnum.network_driver
@classmethod
def set_cluster_template_id(cls, config):
cls.cluster_template_id = CONF.magnum.cluster_template_id
@classmethod
def set_cluster_creation_timeout(cls, config):
cls.cluster_creation_timeout = CONF.magnum.cluster_creation_timeout
@classmethod
def setUp(cls):
cls.set_admin_creds(config)
@ -161,7 +169,7 @@ class Config(object):
cls.set_region(config)
cls.set_image_id(config)
cls.set_nic_id(config)
cls.set_keypair_id(config)
cls.set_keypair_name(config)
cls.set_flavor_id(config)
cls.set_magnum_url(config)
cls.set_master_flavor_id(config)
@ -170,3 +178,5 @@ class Config(object):
cls.set_copy_logs(config)
cls.set_coe(config)
cls.set_network_driver(config)
cls.set_cluster_template_id(config)
cls.set_cluster_creation_timeout(config)

View File

@ -161,7 +161,7 @@ def baymodel_data_with_valid_keypair_image_flavor():
:returns: BayModelEntity with generated data
"""
return baymodel_data(keypair_id=config.Config.keypair_id,
return baymodel_data(keypair_id=config.Config.keypair_name,
image_id=config.Config.image_id,
flavor_id=config.Config.flavor_id,
master_flavor_id=config.Config.master_flavor_id)
@ -173,7 +173,7 @@ def baymodel_data_with_missing_image():
:returns: BayModelEntity with generated data
"""
return baymodel_data(keypair_id=config.Config.keypair_id,
return baymodel_data(keypair_id=config.Config.keypair_name,
flavor_id=config.Config.flavor_id,
master_flavor_id=config.Config.master_flavor_id)
@ -184,7 +184,7 @@ def baymodel_data_with_missing_flavor():
:returns: BayModelEntity with generated data
"""
return baymodel_data(keypair_id=config.Config.keypair_id,
return baymodel_data(keypair_id=config.Config.keypair_name,
image_id=config.Config.image_id)
@ -206,7 +206,7 @@ def baymodel_valid_data_with_specific_coe(coe):
:returns: BayModelEntity with generated data
"""
return baymodel_data(keypair_id=config.Config.keypair_id,
return baymodel_data(keypair_id=config.Config.keypair_name,
image_id=config.Config.image_id, coe=coe)
@ -220,7 +220,8 @@ def valid_swarm_mode_baymodel(is_public=False):
flavor_id=config.Config.flavor_id, public=is_public,
dns_nameserver=config.Config.dns_nameserver,
master_flavor_id=config.Config.master_flavor_id,
keypair_id=config.Config.keypair_id, coe="swarm-mode",
keypair_id=config.Config.keypair_name,
coe="swarm-mode",
cluster_distro=None,
external_network_id=config.Config.nic_id,
http_proxy=None, https_proxy=None, no_proxy=None,
@ -436,7 +437,7 @@ def cluster_template_data_with_valid_keypair_image_flavor():
:returns: ClusterTemplateEntity with generated data
"""
master_flavor = config.Config.master_flavor_id
return cluster_template_data(keypair_id=config.Config.keypair_id,
return cluster_template_data(keypair_id=config.Config.keypair_name,
image_id=config.Config.image_id,
flavor_id=config.Config.flavor_id,
master_flavor_id=master_flavor)
@ -449,7 +450,7 @@ def cluster_template_data_with_missing_image():
"""
return cluster_template_data(
keypair_id=config.Config.keypair_id,
keypair_id=config.Config.keypair_name,
flavor_id=config.Config.flavor_id,
master_flavor_id=config.Config.master_flavor_id)
@ -460,7 +461,7 @@ def cluster_template_data_with_missing_flavor():
:returns: ClusterTemplateEntity with generated data
"""
return cluster_template_data(keypair_id=config.Config.keypair_id,
return cluster_template_data(keypair_id=config.Config.keypair_name,
image_id=config.Config.image_id)
@ -483,7 +484,7 @@ def cluster_template_valid_data_with_specific_coe(coe):
:returns: ClusterTemplateEntity with generated data
"""
return cluster_template_data(keypair_id=config.Config.keypair_id,
return cluster_template_data(keypair_id=config.Config.keypair_name,
image_id=config.Config.image_id, coe=coe)
@ -512,7 +513,7 @@ def valid_cluster_template(is_public=False):
def cluster_data(name=data_utils.rand_name('cluster'),
cluster_template_id=data_utils.rand_uuid(),
node_count=random_int(1, 5), discovery_url=gen_random_ip(),
create_timeout=random_int(1, 30),
create_timeout=None,
master_count=random_int(1, 5)):
"""Generates random cluster data
@ -529,13 +530,15 @@ def cluster_data(name=data_utils.rand_name('cluster'),
:returns: ClusterEntity with generated data
"""
timeout = create_timeout or config.Config.cluster_creation_timeout
data = {
"name": name,
"cluster_template_id": cluster_template_id,
"keypair": config.Config.keypair_id,
"keypair": config.Config.keypair_name,
"node_count": node_count,
"discovery_url": None,
"create_timeout": create_timeout,
"create_timeout": timeout,
"master_count": master_count
}
model = cluster_model.ClusterEntity.from_dict(data)

View File

@ -30,48 +30,44 @@ magnum_group = cfg.OptGroup(name="magnum", title="Magnum Options")
MagnumGroup = [
cfg.StrOpt("docker_storage_driver",
help="Docker storage driver. Supported: devicemapper, overlay"),
cfg.StrOpt("image_id",
default="fedora-atomic-latest",
help="Image id to be used for ClusterTemplate."),
cfg.StrOpt("nic_id",
default="public",
help="NIC id."),
cfg.StrOpt("keypair_id",
default="default",
help="Keypair id to use to log into nova instances."),
cfg.StrOpt("keypair_name",
default="magnum-test",
help="Keypair name to use to log into nova instances, the "
"keypair is created automatically if not exist."),
cfg.StrOpt("flavor_id",
default="s1.magnum",
help="Flavor id to use for ClusterTemplate."),
cfg.StrOpt("magnum_url",
help="Bypass URL for Magnum to skip service catalog lookup"),
cfg.StrOpt("master_flavor_id",
default="m1.magnum",
help="Master flavor id to use for ClusterTemplate."),
cfg.StrOpt("csr_location",
default="/opt/stack/new/magnum/default.csr",
deprecated_for_removal=True,
help="CSR location for certificates. This option is no "
"longer used for anything."),
cfg.StrOpt("dns_nameserver",
default="8.8.8.8",
help="DNS nameserver to use for ClusterTemplate."),
cfg.BoolOpt("copy_logs",
default=True,
help="Specify whether to copy nova server logs on failure."),
cfg.StrOpt("coe",
default="swarm-mode",
help="Container Orchestration Engine"),
cfg.StrOpt("network_driver",
help="Network Driver"),
cfg.StrOpt("cluster_template_id",
help="UUID of cluster template used for the test."),
cfg.IntOpt("cluster_creation_timeout",
default=30,
help="Timeout(in minutes) to wait for the cluster creation "
"finished."),
]

View File

@ -97,17 +97,23 @@ class BaseTempestTest(base.BaseMagnumTest):
else:
creds = ic.self.get_credentials(type_of_creds)
_, keypairs_client = cls.get_clients(
creds, type_of_creds, 'keypair_setup')
keypair = None
try:
keypairs_client.show_keypair(config.Config.keypair_id)
except Exception:
keypair_body = keypairs_client.create_keypair(
name=config.Config.keypair_id)
cls.LOG.debug("Keypair body: %s", keypair_body)
keypair = keypair_body['keypair']['private_key']
if config.Config.keypair_name:
_, keypairs_client = cls.get_clients(creds, type_of_creds,
'keypair_setup')
try:
keypairs_client.delete_keypair(config.Config.keypair_name)
except Exception:
cls.LOG.debug("Creating keypair %s",
config.Config.keypair_name)
keypair_body = keypairs_client.create_keypair(
name=config.Config.keypair_name
)
cls.LOG.debug("Keypair body: %s", keypair_body)
keypair = keypair_body['keypair']['private_key']
return (creds, keypair)
@classmethod

View File

@ -113,18 +113,19 @@ class ClusterClient(client.MagnumClient):
def wait_for_cluster_to_delete(self, cluster_id):
utils.wait_for_condition(
lambda: self.does_cluster_not_exist(cluster_id), 10, 600)
lambda: self.does_cluster_not_exist(cluster_id), 10, 300)
def wait_for_created_cluster(self, cluster_id, delete_on_error=True):
def wait_for_created_cluster(self, cluster_id, delete_on_error=True,
timeout=3600):
try:
utils.wait_for_condition(
lambda: self.does_cluster_exist(cluster_id), 10, 3600)
lambda: self.does_cluster_exist(cluster_id), 10, timeout)
except Exception:
# In error state. Clean up the cluster id if desired
self.LOG.error('Cluster %s entered an exception state.',
cluster_id)
if delete_on_error:
self.LOG.error('We will attempt to delete clusters now.')
self.LOG.warning('We will attempt to delete clusters now.')
self.delete_cluster(cluster_id)
self.wait_for_cluster_to_delete(cluster_id)
raise

View File

@ -33,46 +33,64 @@ class ClusterTest(base.BaseTempestTest):
"""Tests for cluster CRUD."""
LOG = logging.getLogger(__name__)
delete_template = False
def __init__(self, *args, **kwargs):
super(ClusterTest, self).__init__(*args, **kwargs)
self.clusters = []
self.creds = None
self.keypair = None
self.cluster_template = None
self.cluster_template_client = None
self.keypairs_client = None
self.cluster_client = None
self.cert_client = None
@classmethod
def setUpClass(cls):
super(ClusterTest, cls).setUpClass()
try:
(cls.creds, cls.keypair) = cls.get_credentials_with_keypair(
type_of_creds='default'
)
(cls.cluster_template_client,
cls.keypairs_client) = cls.get_clients_with_existing_creds(
creds=cls.creds,
type_of_creds='default',
request_type='cluster_template'
)
(cls.cluster_client, _) = cls.get_clients_with_existing_creds(
creds=cls.creds,
type_of_creds='default',
request_type='cluster'
)
(cls.cert_client, _) = cls.get_clients_with_existing_creds(
creds=cls.creds,
type_of_creds='default',
request_type='cert'
)
if config.Config.cluster_template_id:
_, cls.cluster_template = cls.cluster_template_client.\
get_cluster_template(config.Config.cluster_template_id)
else:
model = datagen.valid_cluster_template()
_, cls.cluster_template = cls._create_cluster_template(model)
cls.delete_template = True
except Exception:
raise
@classmethod
def tearDownClass(cls):
if cls.delete_template:
cls._delete_cluster_template(cls.cluster_template.uuid)
if config.Config.keypair_name:
cls.keypairs_client.delete_keypair(config.Config.keypair_name)
super(ClusterTest, cls).tearDownClass()
def setUp(self):
try:
super(ClusterTest, self).setUp()
(self.creds, self.keypair) = self.get_credentials_with_keypair(
type_of_creds='default')
(self.cluster_template_client,
self.keypairs_client) = self.get_clients_with_existing_creds(
creds=self.creds,
type_of_creds='default',
request_type='cluster_template')
(self.cluster_client, _) = self.get_clients_with_existing_creds(
creds=self.creds,
type_of_creds='default',
request_type='cluster')
(self.cert_client, _) = self.get_clients_with_existing_creds(
creds=self.creds,
type_of_creds='default',
request_type='cert')
model = datagen.valid_cluster_template()
_, self.cluster_template = self._create_cluster_template(model)
super(ClusterTest, self).setUp()
# NOTE (dimtruck) by default tempest sets timeout to 20 mins.
# We need more time.
test_timeout = 3600
self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
except Exception:
self.tearDown()
raise
# NOTE (dimtruck) by default tempest sets timeout to 20 mins.
# We need more time.
test_timeout = 3600
self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
def tearDown(self):
try:
@ -80,20 +98,20 @@ class ClusterTest(base.BaseTempestTest):
for cluster_id in cluster_list:
self._delete_cluster(cluster_id)
self.clusters.remove(cluster_id)
if self.cluster_template:
self._delete_cluster_template(self.cluster_template.uuid)
finally:
super(ClusterTest, self).tearDown()
def _create_cluster_template(self, cm_model):
self.LOG.debug('We will create a clustertemplate for %s', cm_model)
resp, model = self.cluster_template_client.post_cluster_template(
@classmethod
def _create_cluster_template(cls, cm_model):
cls.LOG.debug('We will create a clustertemplate for %s', cm_model)
resp, model = cls.cluster_template_client.post_cluster_template(
cm_model)
return resp, model
def _delete_cluster_template(self, cm_id):
self.LOG.debug('We will delete a clustertemplate for %s', cm_id)
resp, model = self.cluster_template_client.delete_cluster_template(
@classmethod
def _delete_cluster_template(cls, cm_id):
cls.LOG.debug('We will delete a clustertemplate for %s', cm_id)
resp, model = cls.cluster_template_client.delete_cluster_template(
cm_id)
return resp, model
@ -113,15 +131,20 @@ class ClusterTest(base.BaseTempestTest):
self._get_cluster_by_id(model.uuid)[1].node_addresses]),
self.cluster_template.coe,
self.keypair))
timeout = config.Config.cluster_creation_timeout * 60
self.cluster_client.wait_for_created_cluster(model.uuid,
delete_on_error=False)
delete_on_error=False,
timeout=timeout)
return resp, model
def _delete_cluster(self, cluster_id):
self.LOG.debug('We will delete a cluster for %s', cluster_id)
resp, model = self.cluster_client.delete_cluster(cluster_id)
self.assertEqual(204, resp.status)
self.cluster_client.wait_for_cluster_to_delete(cluster_id)
self.assertRaises(exceptions.NotFound, self.cert_client.get_cert,
cluster_id, headers=HEADERS)
return resp, model
@ -150,13 +173,6 @@ class ClusterTest(base.BaseTempestTest):
cluster_model.uuid, list([x['uuid']
for x in cluster_list_model.clusters]))
# test invalid cluster update
patch_model = datagen.cluster_name_patch_data()
self.assertRaises(
exceptions.BadRequest,
self.cluster_client.patch_cluster,
cluster_model.uuid, patch_model)
# test ca show
resp, cert_model = self.cert_client.get_cert(
cluster_model.uuid, headers=HEADERS)
@ -168,7 +184,6 @@ class ClusterTest(base.BaseTempestTest):
self.assertIn('-----END CERTIFICATE-----', cert_model.pem)
# test ca sign
csr_sample = """-----BEGIN CERTIFICATE REQUEST-----
MIIByjCCATMCAQAwgYkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh
MRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgSW5jMR8w
@ -194,14 +209,6 @@ Q0uA0aVog3f5iJxCa3Hp5gxbJQ6zV6kJ0TEsuaaOhEko9sdpCoPOnRBm2i/XRD2D
self.assertIn('-----BEGIN CERTIFICATE-----', cert_model.pem)
self.assertIn('-----END CERTIFICATE-----', cert_model.pem)
# test ca sign invalid
cert_data_model = datagen.cert_data(cluster_model.uuid,
csr_data="invalid_csr")
self.assertRaises(
exceptions.BadRequest,
self.cert_client.post_cert,
cert_data_model, headers=HEADERS)
# test cluster delete
self._delete_cluster(cluster_model.uuid)
self.clusters.remove(cluster_model.uuid)