Merge "Only create necessary resources for compute v3 tests"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index b216c5c..bb9a68e 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -439,6 +439,17 @@
#admin_password=pass
+[identity-feature-enabled]
+
+#
+# Options defined in tempest.config
+#
+
+# Does the identity service have delegation and impersonation
+# enabled (boolean value)
+#trust=true
+
+
[image]
#
diff --git a/run_tests.sh b/run_tests.sh
index 285b372..3f00453 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -126,7 +126,7 @@
exit
fi
-if [$coverage -eq 1] ; then
+if [ $coverage -eq 1 ]; then
$testrargs = "--coverage $testrargs"
fi
diff --git a/tempest/api/compute/admin/test_hosts_negative.py b/tempest/api/compute/admin/test_hosts_negative.py
index dbf7967..a1afe0e 100644
--- a/tempest/api/compute/admin/test_hosts_negative.py
+++ b/tempest/api/compute/admin/test_hosts_negative.py
@@ -66,7 +66,9 @@
self.assertRaises(exceptions.Unauthorized,
self.non_admin_client.update_host,
- hostname)
+ hostname,
+ status='enable',
+ maintenance_mode='enable')
@test.skip_because(bug="1261964", interface="xml")
@test.attr(type=['negative', 'gate'])
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index fad947b..d29a5dd 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -278,6 +278,8 @@
cls.extensions_client = cls.os.extensions_v3_client
cls.availability_zone_client = cls.os.availability_zone_v3_client
cls.interfaces_client = cls.os.interfaces_v3_client
+ cls.instance_usages_audit_log_client = \
+ cls.os.instance_usages_audit_log_v3_client
cls.hypervisor_client = cls.os.hypervisor_v3_client
cls.keypairs_client = cls.os.keypairs_v3_client
cls.tenant_usages_client = cls.os.tenant_usages_v3_client
@@ -346,6 +348,8 @@
cls.os_adm = os_adm
cls.servers_admin_client = cls.os_adm.servers_v3_client
+ cls.instance_usages_audit_log_admin_client = \
+ cls.os_adm.instance_usages_audit_log_v3_client
cls.services_admin_client = cls.os_adm.services_v3_client
cls.availability_zone_admin_client = \
cls.os_adm.availability_zone_v3_client
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index 1008670..5048967 100644
--- a/tempest/api/compute/servers/test_server_rescue.py
+++ b/tempest/api/compute/servers/test_server_rescue.py
@@ -70,7 +70,7 @@
cls.rescue_password = resc_server['adminPass']
cls.servers_client.rescue_server(
- cls.rescue_id, cls.rescue_password)
+ cls.rescue_id, adminPass=cls.rescue_password)
cls.servers_client.wait_for_server_status(cls.rescue_id, 'RESCUE')
def setUp(self):
@@ -111,7 +111,7 @@
@attr(type='smoke')
def test_rescue_unrescue_instance(self):
resp, body = self.servers_client.rescue_server(
- self.server_id, self.password)
+ self.server_id, adminPass=self.password)
self.assertEqual(200, resp.status)
self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
resp, body = self.servers_client.unrescue_server(self.server_id)
@@ -152,7 +152,8 @@
@attr(type=['negative', 'gate'])
def test_rescued_vm_attach_volume(self):
# Rescue the server
- self.servers_client.rescue_server(self.server_id, self.password)
+ self.servers_client.rescue_server(self.server_id,
+ adminPass=self.password)
self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
self.addCleanup(self._unrescue, self.server_id)
@@ -173,7 +174,8 @@
self.volume_to_detach['id'], 'in-use')
# Rescue the server
- self.servers_client.rescue_server(self.server_id, self.password)
+ self.servers_client.rescue_server(self.server_id,
+ adminPass=self.password)
self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
# addCleanup is a LIFO queue
self.addCleanup(self._detach, self.server_id,
@@ -190,7 +192,7 @@
def test_rescued_vm_associate_dissociate_floating_ip(self):
# Rescue the server
self.servers_client.rescue_server(
- self.server_id, self.password)
+ self.server_id, adminPass=self.password)
self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
self.addCleanup(self._unrescue, self.server_id)
@@ -210,7 +212,7 @@
def test_rescued_vm_add_remove_security_group(self):
# Rescue the server
self.servers_client.rescue_server(
- self.server_id, self.password)
+ self.server_id, adminPass=self.password)
self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
# Add Security group
diff --git a/tempest/api/compute/v3/admin/test_hosts_negative.py b/tempest/api/compute/v3/admin/test_hosts_negative.py
index 755fa2b..598a1d3 100644
--- a/tempest/api/compute/v3/admin/test_hosts_negative.py
+++ b/tempest/api/compute/v3/admin/test_hosts_negative.py
@@ -66,7 +66,9 @@
self.assertRaises(exceptions.Unauthorized,
self.non_admin_client.update_host,
- hostname)
+ hostname,
+ status='enable',
+ maintenance_mode='enable')
@test.attr(type=['negative', 'gate'])
def test_update_host_with_extra_param(self):
diff --git a/tempest/api/compute/v3/admin/test_instance_usage_audit_log.py b/tempest/api/compute/v3/admin/test_instance_usage_audit_log.py
index cea6e92..d0cfc63 100644
--- a/tempest/api/compute/v3/admin/test_instance_usage_audit_log.py
+++ b/tempest/api/compute/v3/admin/test_instance_usage_audit_log.py
@@ -16,22 +16,22 @@
# under the License.
import datetime
-
-from tempest.api.compute import base
-from tempest.test import attr
import urllib
+from tempest.api.compute import base
+from tempest import test
-class InstanceUsageAuditLogTestJSON(base.BaseV2ComputeAdminTest):
+
+class InstanceUsageAuditLogV3TestJSON(base.BaseV3ComputeAdminTest):
_interface = 'json'
@classmethod
def setUpClass(cls):
- super(InstanceUsageAuditLogTestJSON, cls).setUpClass()
- cls.adm_client = cls.os_adm.instance_usages_audit_log_client
+ super(InstanceUsageAuditLogV3TestJSON, cls).setUpClass()
+ cls.adm_client = cls.instance_usages_audit_log_admin_client
- @attr(type='gate')
+ @test.attr(type='gate')
def test_list_instance_usage_audit_logs(self):
# list instance usage audit logs
resp, body = self.adm_client.list_instance_usage_audit_logs()
@@ -44,12 +44,12 @@
for item in expected_items:
self.assertIn(item, body)
- @attr(type='gate')
- def test_get_instance_usage_audit_log(self):
+ @test.attr(type='gate')
+ def test_list_instance_usage_audit_logs_with_filter_before(self):
# Get instance usage audit log before specified time
- now = datetime.datetime.now()
- resp, body = self.adm_client.get_instance_usage_audit_log(
- urllib.quote(now.strftime("%Y-%m-%d %H:%M:%S")))
+ ending_time = datetime.datetime(2012, 12, 24)
+ resp, body = self.adm_client.list_instance_usage_audit_logs(
+ urllib.quote(ending_time.strftime("%Y-%m-%d %H:%M:%S")))
self.assertEqual(200, resp.status)
expected_items = ['total_errors', 'total_instances', 'log',
@@ -58,7 +58,8 @@
'period_beginning', 'num_hosts_not_run']
for item in expected_items:
self.assertIn(item, body)
+ self.assertEqual(body['period_ending'], "2012-12-23 23:00:00")
-class InstanceUsageAuditLogTestXML(InstanceUsageAuditLogTestJSON):
+class InstanceUsageAuditLogV3TestXML(InstanceUsageAuditLogV3TestJSON):
_interface = 'xml'
diff --git a/tempest/api/compute/v3/admin/test_instance_usage_audit_log_negative.py b/tempest/api/compute/v3/admin/test_instance_usage_audit_log_negative.py
index dcf41c5..6e919c9 100644
--- a/tempest/api/compute/v3/admin/test_instance_usage_audit_log_negative.py
+++ b/tempest/api/compute/v3/admin/test_instance_usage_audit_log_negative.py
@@ -15,42 +15,34 @@
# License for the specific language governing permissions and limitations
# under the License.
-import datetime
-
from tempest.api.compute import base
from tempest import exceptions
-from tempest.test import attr
-import urllib
+from tempest import test
-class InstanceUsageAuditLogNegativeTestJSON(base.BaseV2ComputeAdminTest):
+class InstanceUsageLogNegativeV3TestJSON(base.BaseV3ComputeAdminTest):
_interface = 'json'
@classmethod
def setUpClass(cls):
- super(InstanceUsageAuditLogNegativeTestJSON, cls).setUpClass()
- cls.adm_client = cls.os_adm.instance_usages_audit_log_client
+ super(InstanceUsageLogNegativeV3TestJSON, cls).setUpClass()
+ cls.adm_client = cls.instance_usages_audit_log_admin_client
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_instance_usage_audit_logs_with_nonadmin_user(self):
# the instance_usage_audit_logs API just can be accessed by admin user
self.assertRaises(exceptions.Unauthorized,
self.instance_usages_audit_log_client.
list_instance_usage_audit_logs)
- now = datetime.datetime.now()
- self.assertRaises(exceptions.Unauthorized,
- self.instance_usages_audit_log_client.
- get_instance_usage_audit_log,
- urllib.quote(now.strftime("%Y-%m-%d %H:%M:%S")))
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_get_instance_usage_audit_logs_with_invalid_time(self):
self.assertRaises(exceptions.BadRequest,
- self.adm_client.get_instance_usage_audit_log,
+ self.adm_client.list_instance_usage_audit_logs,
"invalid_time")
-class InstanceUsageAuditLogNegativeTestXML(
- InstanceUsageAuditLogNegativeTestJSON):
+class InstanceUsageLogNegativeV3TestXML(
+ InstanceUsageLogNegativeV3TestJSON):
_interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_server_rescue.py b/tempest/api/compute/v3/servers/test_server_rescue.py
index eebd4d8..387fa88 100644
--- a/tempest/api/compute/v3/servers/test_server_rescue.py
+++ b/tempest/api/compute/v3/servers/test_server_rescue.py
@@ -56,7 +56,7 @@
cls.rescue_password = resc_server['admin_password']
cls.servers_client.rescue_server(
- cls.rescue_id, cls.rescue_password)
+ cls.rescue_id, admin_password=cls.rescue_password)
cls.servers_client.wait_for_server_status(cls.rescue_id, 'RESCUE')
def setUp(self):
@@ -93,7 +93,7 @@
@attr(type='smoke')
def test_rescue_unrescue_instance(self):
resp, body = self.servers_client.rescue_server(
- self.server_id, self.password)
+ self.server_id, admin_password=self.password)
self.assertEqual(202, resp.status)
self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
resp, body = self.servers_client.unrescue_server(self.server_id)
@@ -134,7 +134,8 @@
@attr(type=['negative', 'gate'])
def test_rescued_vm_attach_volume(self):
# Rescue the server
- self.servers_client.rescue_server(self.server_id, self.password)
+ self.servers_client.rescue_server(self.server_id,
+ admin_password=self.password)
self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
self.addCleanup(self._unrescue, self.server_id)
@@ -155,7 +156,8 @@
self.volume_to_detach['id'], 'in-use')
# Rescue the server
- self.servers_client.rescue_server(self.server_id, self.password)
+ self.servers_client.rescue_server(self.server_id,
+ admin_password=self.password)
self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
# addCleanup is a LIFO queue
self.addCleanup(self._detach, self.server_id,
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index d316ae1..98b298e 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -17,16 +17,22 @@
from tempest.api.identity import base
from tempest import clients
from tempest.common.utils.data_utils import rand_name
+from tempest import config
from tempest import exceptions
from tempest.openstack.common import timeutils
from tempest.test import attr
+CONF = config.CONF
+
class BaseTrustsV3Test(base.BaseIdentityAdminTest):
def setUp(self):
super(BaseTrustsV3Test, self).setUp()
# Use alt_username as the trustee
+ if not CONF.identity_feature_enabled.trust:
+ raise self.skipException("Trusts aren't enabled")
+
self.trustee_username = self.config.identity.alt_username
self.trust_id = None
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index 91f725e..b521bce 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -130,7 +130,7 @@
raise cls.skipException(msg)
-class BaseV2MemeberImageTest(BaseImageTest):
+class BaseV2MemeberImageTest(BaseV2ImageTest):
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/network/test_security_groups.py b/tempest/api/network/test_security_groups.py
index 9b0a3de..37b1f2c 100644
--- a/tempest/api/network/test_security_groups.py
+++ b/tempest/api/network/test_security_groups.py
@@ -82,6 +82,36 @@
for rule in rule_list_body['security_group_rules']]
self.assertIn(rule_create_body['security_group_rule']['id'], rule_list)
+ @attr(type='smoke')
+ def test_create_security_group_rule_with_additional_args(self):
+ # Verify creating security group rule with the following
+ # arguments works: "protocol": "tcp", "port_range_max": 77,
+ # "port_range_min": 77, "direction":"ingress".
+ group_create_body, _ = self._create_security_group()
+
+ direction = 'ingress'
+ protocol = 'tcp'
+ port_range_min = 77
+ port_range_max = 77
+ resp, rule_create_body = self.client.create_security_group_rule(
+ group_create_body['security_group']['id'],
+ direction=direction,
+ protocol=protocol,
+ port_range_min=port_range_min,
+ port_range_max=port_range_max
+ )
+
+ self.assertEqual('201', resp['status'])
+ sec_group_rule = rule_create_body['security_group_rule']
+ self.addCleanup(self._delete_security_group_rule,
+ sec_group_rule['id']
+ )
+
+ self.assertEqual(sec_group_rule['direction'], direction)
+ self.assertEqual(sec_group_rule['protocol'], protocol)
+ self.assertEqual(int(sec_group_rule['port_range_min']), port_range_min)
+ self.assertEqual(int(sec_group_rule['port_range_max']), port_range_max)
+
class SecGroupTestXML(SecGroupTest):
_interface = 'xml'
diff --git a/tempest/clients.py b/tempest/clients.py
index 519d191..75f8838 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -64,6 +64,8 @@
from tempest.services.compute.v3.json.hosts_client import HostsV3ClientJSON
from tempest.services.compute.v3.json.hypervisor_client import \
HypervisorV3ClientJSON
+from tempest.services.compute.v3.json.instance_usage_audit_log_client import \
+ InstanceUsagesAuditLogV3ClientJSON
from tempest.services.compute.v3.json.interfaces_client import \
InterfacesV3ClientJSON
from tempest.services.compute.v3.json.keypairs_client import \
@@ -88,6 +90,8 @@
from tempest.services.compute.v3.xml.hosts_client import HostsV3ClientXML
from tempest.services.compute.v3.xml.hypervisor_client import \
HypervisorV3ClientXML
+from tempest.services.compute.v3.xml.instance_usage_audit_log_client import \
+ InstanceUsagesAuditLogV3ClientXML
from tempest.services.compute.v3.xml.interfaces_client import \
InterfacesV3ClientXML
from tempest.services.compute.v3.xml.keypairs_client import KeyPairsV3ClientXML
@@ -284,6 +288,8 @@
self.credentials_client = CredentialsClientXML(*client_args)
self.instance_usages_audit_log_client = \
InstanceUsagesAuditLogClientXML(*client_args)
+ self.instance_usages_audit_log_v3_client = \
+ InstanceUsagesAuditLogV3ClientXML(*client_args)
self.volume_hosts_client = VolumeHostsClientXML(*client_args)
self.volumes_extension_client = VolumeExtensionClientXML(
*client_args)
@@ -347,6 +353,8 @@
self.credentials_client = CredentialsClientJSON(*client_args)
self.instance_usages_audit_log_client = \
InstanceUsagesAuditLogClientJSON(*client_args)
+ self.instance_usages_audit_log_v3_client = \
+ InstanceUsagesAuditLogV3ClientJSON(*client_args)
self.volume_hosts_client = VolumeHostsClientJSON(*client_args)
self.volumes_extension_client = VolumeExtensionClientJSON(
*client_args)
diff --git a/tempest/config.py b/tempest/config.py
index c346aef..3c7241a 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -90,6 +90,16 @@
secret=True),
]
+identity_feature_group = cfg.OptGroup(name='identity-feature-enabled',
+ title='Enabled Identity Features')
+
+IdentityFeatureGroup = [
+ cfg.BoolOpt('trust',
+ default=True,
+ help='Does the identity service have delegation and '
+ 'impersonation enabled')
+]
+
compute_group = cfg.OptGroup(name='compute',
title='Compute Service Options')
@@ -724,6 +734,8 @@
register_opt_group(cfg.CONF, compute_features_group,
ComputeFeaturesGroup)
register_opt_group(cfg.CONF, identity_group, IdentityGroup)
+ register_opt_group(cfg.CONF, identity_feature_group,
+ IdentityFeatureGroup)
register_opt_group(cfg.CONF, image_group, ImageGroup)
register_opt_group(cfg.CONF, image_feature_group, ImageFeaturesGroup)
register_opt_group(cfg.CONF, network_group, NetworkGroup)
@@ -752,6 +764,7 @@
self.compute = cfg.CONF.compute
self.compute_feature_enabled = cfg.CONF['compute-feature-enabled']
self.identity = cfg.CONF.identity
+ self.identity_feature_enabled = cfg.CONF['identity-feature-enabled']
self.images = cfg.CONF.image
self.image_feature_enabled = cfg.CONF['image-feature-enabled']
self.network = cfg.CONF.network
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 2b5a770..ecb55f9 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -528,6 +528,13 @@
private_key = self.keypair.private_key
return RemoteClient(ip, username, pkey=private_key)
+ def _log_console_output(self, servers=None):
+ if not servers:
+ servers = self.compute_client.servers.list()
+ for server in servers:
+ LOG.debug('Console output for %s', server.id)
+ LOG.debug(server.get_console_output())
+
class NetworkScenarioTest(OfficialClientTest):
"""
diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py
new file mode 100644
index 0000000..3ae9567
--- /dev/null
+++ b/tempest/scenario/test_aggregates_basic_ops.py
@@ -0,0 +1,133 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM Corp.
+# All Rights Reserved.
+#
+# 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.
+
+from tempest.common import tempest_fixtures as fixtures
+from tempest.common.utils.data_utils import rand_name
+from tempest.openstack.common import log as logging
+from tempest.scenario import manager
+from tempest import test
+
+
+LOG = logging.getLogger(__name__)
+
+
+class TestAggregatesBasicOps(manager.OfficialClientTest):
+ """
+ Creates an aggregate within an availability zone
+ Adds a host to the aggregate
+ Checks aggregate details
+ Updates aggregate's name
+ Removes host from aggregate
+ Deletes aggregate
+ """
+ @classmethod
+ def credentials(cls):
+ return cls.admin_credentials()
+
+ def _create_aggregate(self, aggregate_name, availability_zone=None):
+ aggregate = self.compute_client.aggregates.create(aggregate_name,
+ availability_zone)
+ self.assertEqual(aggregate.name, aggregate_name)
+ self.assertEqual(aggregate.availability_zone, availability_zone)
+ self.set_resource(aggregate.id, aggregate)
+ LOG.debug("Aggregate %s created." % (aggregate.name))
+ return aggregate
+
+ def _delete_aggregate(self, aggregate):
+ self.compute_client.aggregates.delete(aggregate.id)
+ self.remove_resource(aggregate.id)
+ LOG.debug("Aggregate %s deleted. " % (aggregate.name))
+
+ def _get_host_name(self):
+ hosts = self.compute_client.hosts.list()
+ self.assertTrue(len(hosts) >= 1)
+ hostname = hosts[0].host_name
+ return hostname
+
+ def _add_host(self, aggregate_name, host):
+ aggregate = self.compute_client.aggregates.add_host(aggregate_name,
+ host)
+ self.assertIn(host, aggregate.hosts)
+ LOG.debug("Host %s added to Aggregate %s." % (host, aggregate.name))
+
+ def _remove_host(self, aggregate_name, host):
+ aggregate = self.compute_client.aggregates.remove_host(aggregate_name,
+ host)
+ self.assertNotIn(host, aggregate.hosts)
+ LOG.debug("Host %s removed to Aggregate %s." % (host, aggregate.name))
+
+ def _check_aggregate_details(self, aggregate, aggregate_name, azone,
+ hosts, metadata):
+ aggregate = self.compute_client.aggregates.get(aggregate.id)
+ self.assertEqual(aggregate_name, aggregate.name)
+ self.assertEqual(azone, aggregate.availability_zone)
+ self.assertEqual(aggregate.hosts, hosts)
+ for meta_key in metadata.keys():
+ self.assertIn(meta_key, aggregate.metadata)
+ self.assertEqual(metadata[meta_key], aggregate.metadata[meta_key])
+ LOG.debug("Aggregate %s details match." % aggregate.name)
+
+ def _set_aggregate_metadata(self, aggregate, meta):
+ aggregate = self.compute_client.aggregates.set_metadata(aggregate.id,
+ meta)
+
+ for key, value in meta.items():
+ self.assertEqual(meta[key], aggregate.metadata[key])
+ LOG.debug("Aggregate %s metadata updated successfully." %
+ aggregate.name)
+
+ def _update_aggregate(self, aggregate, aggregate_name,
+ availability_zone):
+ values = {}
+ if aggregate_name:
+ values.update({'name': aggregate_name})
+ if availability_zone:
+ values.update({'availability_zone': availability_zone})
+ if values.keys():
+ aggregate = self.compute_client.aggregates.update(aggregate.id,
+ values)
+ for key, values in values.items():
+ self.assertEqual(getattr(aggregate, key), values)
+ return aggregate
+
+ @test.services('compute')
+ def test_aggregate_basic_ops(self):
+ self.useFixture(fixtures.LockFixture('availability_zone'))
+ az = 'foo_zone'
+ aggregate_name = rand_name('aggregate-scenario')
+ aggregate = self._create_aggregate(aggregate_name, az)
+
+ metadata = {'meta_key': 'meta_value'}
+ self._set_aggregate_metadata(aggregate, metadata)
+
+ host = self._get_host_name()
+ self._add_host(aggregate, host)
+ self._check_aggregate_details(aggregate, aggregate_name, az, [host],
+ metadata)
+
+ aggregate_name = rand_name('renamed-aggregate-scenario')
+ aggregate = self._update_aggregate(aggregate, aggregate_name, None)
+
+ additional_metadata = {'foo': 'bar'}
+ self._set_aggregate_metadata(aggregate, additional_metadata)
+
+ metadata.update(additional_metadata)
+ self._check_aggregate_details(aggregate, aggregate.name, az, [host],
+ metadata)
+
+ self._remove_host(aggregate, host)
+ self._delete_aggregate(aggregate)
diff --git a/tempest/scenario/test_cross_tenant_connectivity.py b/tempest/scenario/test_cross_tenant_connectivity.py
index faba987..a269017 100644
--- a/tempest/scenario/test_cross_tenant_connectivity.py
+++ b/tempest/scenario/test_cross_tenant_connectivity.py
@@ -371,6 +371,7 @@
msg)
except Exception:
debug.log_ip_ns()
+ self._log_console_output(servers=self.servers)
raise
def _test_in_tenant_block(self, tenant):
diff --git a/tempest/scenario/test_dashboard_basic_ops.py b/tempest/scenario/test_dashboard_basic_ops.py
index 1081a3e..9e08bb6 100644
--- a/tempest/scenario/test_dashboard_basic_ops.py
+++ b/tempest/scenario/test_dashboard_basic_ops.py
@@ -34,6 +34,7 @@
@classmethod
def setUpClass(cls):
+ cls.set_network_resources()
super(TestDashboardBasicOps, cls).setUpClass()
if not cls.config.service_available.horizon:
diff --git a/tempest/scenario/test_large_ops.py b/tempest/scenario/test_large_ops.py
index 7f8d3e4..30468fa 100644
--- a/tempest/scenario/test_large_ops.py
+++ b/tempest/scenario/test_large_ops.py
@@ -36,6 +36,11 @@
"""
+ @classmethod
+ def setUpClass(cls):
+ cls.set_network_resources()
+ super(TestLargeOpsScenario, cls).setUpClass()
+
def _wait_for_server_status(self, status):
for server in self.servers:
self.status_timeout(
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 8a51cd1..890d00f 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -131,7 +131,12 @@
self.server.add_floating_ip(self.floating_ip)
def ssh_to_server(self):
- self.linux_client = self.get_remote_client(self.floating_ip.ip)
+ try:
+ self.linux_client = self.get_remote_client(self.floating_ip.ip)
+ except Exception:
+ LOG.exception('ssh to server failed')
+ self._log_console_output()
+ raise
def check_partitions(self):
partitions = self.linux_client.get_partitions()
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 52a36e6..414aae6 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -19,11 +19,9 @@
from tempest.common import debug
from tempest.common.utils import data_utils
from tempest import config
-from tempest.openstack.common import jsonutils
from tempest.openstack.common import log as logging
from tempest.scenario import manager
-import tempest.test
from tempest.test import attr
from tempest.test import services
@@ -31,45 +29,6 @@
LOG = logging.getLogger(__name__)
-class FloatingIPCheckTracker(object):
- """
- Checking VM connectivity through floating IP addresses is bound to fail
- if the floating IP has not actually been associated with the VM yet.
- This helper class facilitates checking for floating IP assignments on
- VMs. It only checks for a given IP address once.
- """
-
- def __init__(self, compute_client, floating_ip_map):
- self.compute_client = compute_client
- self.unchecked = floating_ip_map.copy()
-
- def run_checks(self):
- """Check for any remaining unverified floating IPs
-
- Gets VM details from nova and checks for floating IPs
- within the returned information. Returns true when all
- checks are complete and is suitable for use with
- tempest.test.call_until_true()
- """
- to_delete = []
- loggable_map = {}
- for check_addr, server in self.unchecked.iteritems():
- serverdata = self.compute_client.servers.get(server.id)
- ip_addr = [addr for sublist in serverdata.networks.values() for
- addr in sublist]
- if check_addr.floating_ip_address in ip_addr:
- to_delete.append(check_addr)
- else:
- loggable_map[server.id] = check_addr
-
- for to_del in to_delete:
- del self.unchecked[to_del]
-
- LOG.debug('Unchecked floating IPs: %s',
- jsonutils.dumps(loggable_map))
- return len(self.unchecked) == 0
-
-
class TestNetworkBasicOps(manager.NetworkScenarioTest):
"""
@@ -213,11 +172,6 @@
name = data_utils.rand_name('server-smoke-%d-' % i)
self._create_server(name, network)
- def _log_console_output(self):
- for server, key in self.servers.items():
- LOG.debug('Console output for %s', server.id)
- LOG.debug(server.get_console_output())
-
def _check_tenant_network_connectivity(self):
if not CONF.network.tenant_networks_reachable:
msg = 'Tenant networks not configured to be reachable.'
@@ -234,21 +188,11 @@
key.private_key)
except Exception:
LOG.exception('Tenant connectivity check failed')
- self._log_console_output()
+ self._log_console_output(
+ servers=[server for server, _key in self.servers])
debug.log_ip_ns()
raise
- def _wait_for_floating_ip_association(self):
- ip_tracker = FloatingIPCheckTracker(self.compute_client,
- self.floating_ips)
-
- self.assertTrue(
- tempest.test.call_until_true(
- ip_tracker.run_checks, CONF.compute.build_timeout,
- CONF.compute.build_interval),
- "Timed out while waiting for the floating IP assignments "
- "to propagate")
-
def _create_and_associate_floating_ips(self):
public_network_id = CONF.network.public_network_id
for server in self.servers.keys():
@@ -272,7 +216,8 @@
should_connect=should_connect)
except Exception:
LOG.exception('Public network connectivity check failed')
- self._log_console_output()
+ self._log_console_output(
+ servers=[server for server, _key in self.servers])
debug.log_ip_ns()
raise
@@ -298,11 +243,9 @@
self._check_networks()
self._create_servers()
self._create_and_associate_floating_ips()
- self._wait_for_floating_ip_association()
self._check_tenant_network_connectivity()
self._check_public_network_connectivity(should_connect=True)
self._disassociate_floating_ips()
self._check_public_network_connectivity(should_connect=False)
self._reassociate_floating_ips()
- self._wait_for_floating_ip_association()
self._check_public_network_connectivity(should_connect=True)
diff --git a/tempest/scenario/test_network_quotas.py b/tempest/scenario/test_network_quotas.py
deleted file mode 100644
index cb7aa0b..0000000
--- a/tempest/scenario/test_network_quotas.py
+++ /dev/null
@@ -1,131 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2013 Hewlett-Packard Development Company, L.P.
-# All Rights Reserved.
-#
-# 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.
-
-from neutronclient.common import exceptions as exc
-
-from tempest.scenario.manager import NetworkScenarioTest
-from tempest.test import services
-
-
-class TestNetworkQuotaBasic(NetworkScenarioTest):
- """
- This test suite contains tests that each loop trying to grab a
- particular resource until a quota limit is hit.
- For sanity, there is a maximum number of iterations - if this is hit
- the test fails. Covers network, subnet, port.
- """
-
- @classmethod
- def check_preconditions(cls):
- super(TestNetworkQuotaBasic, cls).check_preconditions()
-
- @classmethod
- def setUpClass(cls):
- super(TestNetworkQuotaBasic, cls).setUpClass()
- cls.check_preconditions()
- cls.networks = []
- cls.subnets = []
- cls.ports = []
-
- @services('network')
- def test_create_network_until_quota_hit(self):
- hit_limit = False
- networknum = self._get_tenant_own_network_num(self.tenant_id)
- max = self._show_quota_network(self.tenant_id) - networknum
- for n in xrange(max):
- try:
- self.networks.append(
- self._create_network(self.tenant_id,
- namestart='network-quotatest-'))
- except exc.NeutronClientException as e:
- if (e.status_code != 409):
- raise
- hit_limit = True
- break
- self.assertFalse(hit_limit, "Failed: Hit quota limit !")
-
- try:
- self.networks.append(
- self._create_network(self.tenant_id,
- namestart='network-quotatest-'))
- except exc.NeutronClientException as e:
- if (e.status_code != 409):
- raise
- hit_limit = True
- self.assertTrue(hit_limit, "Failed: Did not hit quota limit !")
-
- @services('network')
- def test_create_subnet_until_quota_hit(self):
- if not self.networks:
- self.networks.append(
- self._create_network(self.tenant_id,
- namestart='network-quotatest-'))
- hit_limit = False
- subnetnum = self._get_tenant_own_subnet_num(self.tenant_id)
- max = self._show_quota_subnet(self.tenant_id) - subnetnum
- for n in xrange(max):
- try:
- self.subnets.append(
- self._create_subnet(self.networks[0],
- namestart='subnet-quotatest-'))
- except exc.NeutronClientException as e:
- if (e.status_code != 409):
- raise
- hit_limit = True
- break
- self.assertFalse(hit_limit, "Failed: Hit quota limit !")
-
- try:
- self.subnets.append(
- self._create_subnet(self.networks[0],
- namestart='subnet-quotatest-'))
- except exc.NeutronClientException as e:
- if (e.status_code != 409):
- raise
- hit_limit = True
- self.assertTrue(hit_limit, "Failed: Did not hit quota limit !")
-
- @services('network')
- def test_create_ports_until_quota_hit(self):
- if not self.networks:
- self.networks.append(
- self._create_network(self.tenant_id,
- namestart='network-quotatest-'))
- hit_limit = False
- portnum = self._get_tenant_own_port_num(self.tenant_id)
- max = self._show_quota_port(self.tenant_id) - portnum
- for n in xrange(max):
- try:
- self.ports.append(
- self._create_port(self.networks[0],
- namestart='port-quotatest-'))
- except exc.NeutronClientException as e:
- if (e.status_code != 409):
- raise
- hit_limit = True
- break
- self.assertFalse(hit_limit, "Failed: Hit quota limit !")
-
- try:
- self.ports.append(
- self._create_port(self.networks[0],
- namestart='port-quotatest-'))
- except exc.NeutronClientException as e:
- if (e.status_code != 409):
- raise
- hit_limit = True
- self.assertTrue(hit_limit, "Failed: Did not hit quota limit !")
diff --git a/tempest/scenario/test_server_advanced_ops.py b/tempest/scenario/test_server_advanced_ops.py
index 112c8a2..2c9446f 100644
--- a/tempest/scenario/test_server_advanced_ops.py
+++ b/tempest/scenario/test_server_advanced_ops.py
@@ -33,6 +33,7 @@
@classmethod
def setUpClass(cls):
+ cls.set_network_resources()
super(TestServerAdvancedOps, cls).setUpClass()
if not cls.config.compute_feature_enabled.resize:
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index ca3035d..279b80e 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -151,10 +151,15 @@
instance = self.get_resource('instance')
instance.add_floating_ip(floating_ip)
# Check ssh
- self.get_remote_client(
- server_or_ip=floating_ip.ip,
- username=self.image_utils.ssh_user(self.image_ref),
- private_key=self.keypair.private)
+ try:
+ self.get_remote_client(
+ server_or_ip=floating_ip.ip,
+ username=self.image_utils.ssh_user(self.image_ref),
+ private_key=self.keypair.private)
+ except Exception:
+ LOG.exception('ssh to server failed')
+ self._log_console_output()
+ raise
@services('compute', 'network')
def test_server_basicops(self):
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index 00139f0..874bc60 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -15,10 +15,14 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.openstack.common import log
from tempest.scenario import manager
from tempest.test import services
+LOG = log.getLogger(__name__)
+
+
class TestSnapshotPattern(manager.OfficialClientTest):
"""
This test is for snapshotting an instance and booting with it.
@@ -40,7 +44,11 @@
self.keypair = self.create_keypair()
def _ssh_to_server(self, server_or_ip):
- linux_client = self.get_remote_client(server_or_ip)
+ try:
+ linux_client = self.get_remote_client(server_or_ip)
+ except Exception:
+ LOG.exception()
+ self._log_console_output()
return linux_client.ssh_client
def _write_timestamp(self, server_or_ip):
diff --git a/tempest/scenario/test_swift_basic_ops.py b/tempest/scenario/test_swift_basic_ops.py
index 6763503..4ef2aca 100644
--- a/tempest/scenario/test_swift_basic_ops.py
+++ b/tempest/scenario/test_swift_basic_ops.py
@@ -39,6 +39,7 @@
@classmethod
def setUpClass(cls):
+ cls.set_network_resources()
super(TestSwiftBasicOps, cls).setUpClass()
if not cls.config.service_available.swift:
skip_msg = ("%s skipped as swift is not available" %
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index fa9a228..2a2b527 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -13,10 +13,14 @@
# under the License.
from tempest.common.utils import data_utils
+from tempest.openstack.common import log
from tempest.scenario import manager
from tempest.test import services
+LOG = log.getLogger(__name__)
+
+
class TestVolumeBootPattern(manager.OfficialClientTest):
"""
@@ -96,8 +100,14 @@
network_name_for_ssh = self.config.compute.network_for_ssh
ip = server.networks[network_name_for_ssh][0]
- client = self.get_remote_client(ip,
- private_key=keypair.private_key)
+ try:
+ client = self.get_remote_client(
+ ip,
+ private_key=keypair.private_key)
+ except Exception:
+ LOG.exception('ssh to server failed')
+ self._log_console_output()
+ raise
return client.ssh_client
def _get_content(self, ssh_client):
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index eb1a0c3..2eae39c 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -397,9 +397,9 @@
'os-virtual-interfaces']))
return resp, json.loads(body)
- def rescue_server(self, server_id, adminPass=None):
+ def rescue_server(self, server_id, **kwargs):
"""Rescue the provided server."""
- return self.action(server_id, 'rescue', None, adminPass=adminPass)
+ return self.action(server_id, 'rescue', None, **kwargs)
def unrescue_server(self, server_id):
"""Unrescue the provided server."""
diff --git a/tempest/services/compute/v3/json/flavors_client.py b/tempest/services/compute/v3/json/flavors_client.py
index e99ac91..a790c40 100644
--- a/tempest/services/compute/v3/json/flavors_client.py
+++ b/tempest/services/compute/v3/json/flavors_client.py
@@ -61,7 +61,7 @@
'id': flavor_id,
}
if kwargs.get('ephemeral'):
- post_body['OS-FLV-EXT-DATA:ephemeral'] = kwargs.get('ephemeral')
+ post_body['ephemeral'] = kwargs.get('ephemeral')
if kwargs.get('swap'):
post_body['swap'] = kwargs.get('swap')
if kwargs.get('rxtx'):
diff --git a/tempest/services/compute/v3/json/instance_usage_audit_log_client.py b/tempest/services/compute/v3/json/instance_usage_audit_log_client.py
index 07ce1bb..bd73c13 100644
--- a/tempest/services/compute/v3/json/instance_usage_audit_log_client.py
+++ b/tempest/services/compute/v3/json/instance_usage_audit_log_client.py
@@ -20,21 +20,18 @@
from tempest.common.rest_client import RestClient
-class InstanceUsagesAuditLogClientJSON(RestClient):
+class InstanceUsagesAuditLogV3ClientJSON(RestClient):
def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(InstanceUsagesAuditLogClientJSON, self).__init__(
+ super(InstanceUsagesAuditLogV3ClientJSON, self).__init__(
config, username, password, auth_url, tenant_name)
- self.service = self.config.compute.catalog_type
+ self.service = self.config.compute.catalog_v3_type
- def list_instance_usage_audit_logs(self):
- url = 'os-instance_usage_audit_log'
- resp, body = self.get(url)
- body = json.loads(body)
- return resp, body["instance_usage_audit_logs"]
-
- def get_instance_usage_audit_log(self, time_before):
- url = 'os-instance_usage_audit_log/%s' % time_before
+ def list_instance_usage_audit_logs(self, time_before=None):
+ if time_before:
+ url = 'os-instance-usage-audit-log?before=%s' % time_before
+ else:
+ url = 'os-instance-usage-audit-log'
resp, body = self.get(url)
body = json.loads(body)
return resp, body["instance_usage_audit_log"]
diff --git a/tempest/services/compute/v3/json/servers_client.py b/tempest/services/compute/v3/json/servers_client.py
index 3342660..eba3be5 100644
--- a/tempest/services/compute/v3/json/servers_client.py
+++ b/tempest/services/compute/v3/json/servers_client.py
@@ -75,7 +75,7 @@
('metadata', 'meta'),
('os-disk-config:disk_config', 'disk_config'),
('os-multiple-create:return_reservation_id',
- 'return_reservation_id')]:
+ 'return_reservation_id')]:
if isinstance(option, tuple):
post_param = option[0]
key = option[1]
@@ -376,10 +376,9 @@
return self.action(server_id, 'get_console_output', 'output',
length=length)
- def rescue_server(self, server_id, admin_password=None):
+ def rescue_server(self, server_id, **kwargs):
"""Rescue the provided server."""
- return self.action(server_id, 'rescue', None,
- admin_password=admin_password)
+ return self.action(server_id, 'rescue', None, **kwargs)
def unrescue_server(self, server_id):
"""Unrescue the provided server."""
diff --git a/tempest/services/compute/v3/xml/instance_usage_audit_log_client.py b/tempest/services/compute/v3/xml/instance_usage_audit_log_client.py
index 175997b..b8429b2 100644
--- a/tempest/services/compute/v3/xml/instance_usage_audit_log_client.py
+++ b/tempest/services/compute/v3/xml/instance_usage_audit_log_client.py
@@ -21,21 +21,18 @@
from tempest.services.compute.xml.common import xml_to_json
-class InstanceUsagesAuditLogClientXML(RestClientXML):
+class InstanceUsagesAuditLogV3ClientXML(RestClientXML):
def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(InstanceUsagesAuditLogClientXML, self).__init__(
+ super(InstanceUsagesAuditLogV3ClientXML, self).__init__(
config, username, password, auth_url, tenant_name)
- self.service = self.config.compute.catalog_type
+ self.service = self.config.compute.catalog_v3_type
- def list_instance_usage_audit_logs(self):
- url = 'os-instance_usage_audit_log'
+ def list_instance_usage_audit_logs(self, time_before=None):
+ if time_before:
+ url = 'os-instance-usage-audit-log?before=%s' % time_before
+ else:
+ url = 'os-instance-usage-audit-log'
resp, body = self.get(url, self.headers)
instance_usage_audit_logs = xml_to_json(etree.fromstring(body))
return resp, instance_usage_audit_logs
-
- def get_instance_usage_audit_log(self, time_before):
- url = 'os-instance_usage_audit_log/%s' % time_before
- resp, body = self.get(url, self.headers)
- instance_usage_audit_log = xml_to_json(etree.fromstring(body))
- return resp, instance_usage_audit_log
diff --git a/tempest/services/compute/v3/xml/servers_client.py b/tempest/services/compute/v3/xml/servers_client.py
index 5aca7e8..68831cd 100644
--- a/tempest/services/compute/v3/xml/servers_client.py
+++ b/tempest/services/compute/v3/xml/servers_client.py
@@ -620,10 +620,9 @@
return self.action(server_id, 'get_console_output', 'output',
length=length)
- def rescue_server(self, server_id, admin_password=None):
+ def rescue_server(self, server_id, **kwargs):
"""Rescue the provided server."""
- return self.action(server_id, 'rescue', None,
- admin_password=admin_password)
+ return self.action(server_id, 'rescue', None, **kwargs)
def unrescue_server(self, server_id):
"""Unrescue the provided server."""
diff --git a/tempest/services/compute/xml/servers_client.py b/tempest/services/compute/xml/servers_client.py
index 68f6cf0..628c6ee 100644
--- a/tempest/services/compute/xml/servers_client.py
+++ b/tempest/services/compute/xml/servers_client.py
@@ -595,9 +595,9 @@
virt_int = self._parse_xml_virtual_interfaces(etree.fromstring(body))
return resp, virt_int
- def rescue_server(self, server_id, adminPass=None):
+ def rescue_server(self, server_id, **kwargs):
"""Rescue the provided server."""
- return self.action(server_id, 'rescue', None, adminPass=adminPass)
+ return self.action(server_id, 'rescue', None, **kwargs)
def unrescue_server(self, server_id):
"""Unrescue the provided server."""
diff --git a/test-requirements.txt b/test-requirements.txt
index 9486244..d7340f3 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -6,3 +6,4 @@
oslo.sphinx
mox>=0.5.3
mock>=1.0
+coverage>=3.6
diff --git a/tox.ini b/tox.ini
index 6d596e3..88f2537 100644
--- a/tox.ini
+++ b/tox.ini
@@ -25,6 +25,10 @@
setenv = OS_TEST_PATH=./tempest/tests
commands = python setup.py test --slowest --testr-arg='tempest\.tests {posargs}'
+[testenv:cover]
+setenv = OS_TEST_PATH=./tempest/tests
+commands = python setup.py testr --coverage --testr-arg='tempest\.tests {posargs}'
+
[testenv:all]
setenv = VIRTUAL_ENV={envdir}
commands =