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:
parent
5a18c8ebf0
commit
18a3103170
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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."),
|
||||
]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue