Merge "Sync latest log module from oslo-incubator"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 9323750..13ee8fe 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -260,7 +260,8 @@
# The endpoint type to use for the compute service. (string value)
#endpoint_type = publicURL
-# Visible fixed network name (string value)
+# Name of the fixed network that is visible to all test tenants.
+# (string value)
#fixed_network_name = private
# Valid primary flavor to use in tests. (string value)
@@ -270,7 +271,8 @@
#flavor_ref_alt = 2
# Unallocated floating IP range, which will be used to test the
-# floating IP bulk feature for CRUD operation. (string value)
+# floating IP bulk feature for CRUD operation. This block must not
+# overlap an existing floating IP pool. (string value)
#floating_ip_range = 10.0.0.0/29
# Password used to authenticate to an instance using the alternate
@@ -299,7 +301,8 @@
# IP version used for SSH connections. (integer value)
#ip_version_for_ssh = 4
-# Network used for SSH connections. (string value)
+# Network used for SSH connections. Ignored if
+# use_floatingip_for_ssh=true or run_ssh=false. (string value)
#network_for_ssh = public
# Path to a private key file for SSH access to remote hosts (string
@@ -629,6 +632,9 @@
# (boolean value)
#trust = true
+# If false, skip all identity api tests with xml (boolean value)
+#xml_api = false
+
[image]
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions.py b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
index ba66ab9..3bb7d19 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
@@ -130,7 +130,8 @@
# Make sure no longer associated with old server
self.assertRaises((exceptions.NotFound,
- exceptions.UnprocessableEntity),
+ exceptions.UnprocessableEntity,
+ exceptions.Conflict),
self.client.disassociate_floating_ip_from_server,
self.floating_ip, self.server_id)
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 1e4973b..244323e 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -31,6 +31,9 @@
@classmethod
def resource_setup(cls):
super(BaseIdentityAdminTest, cls).resource_setup()
+ if getattr(cls, '_interface', None) == 'xml':
+ if not CONF.identity_feature_enabled.xml_api:
+ raise cls.skipException('XML API is not enabled')
cls.os_adm = clients.AdminManager(interface=cls._interface)
cls.os = clients.Manager(interface=cls._interface)
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index cd04ef7..4b5f107 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -65,6 +65,8 @@
if getattr(cls, '_interface', None) == 'xml':
if not CONF.network_feature_enabled.xml_api:
raise cls.skipException('XML API is not enabled')
+ if cls._ip_version == 6 and not CONF.network_feature_enabled.ipv6:
+ raise cls.skipException("IPv6 Tests are disabled.")
os = cls.get_client_manager()
@@ -313,9 +315,11 @@
return vip
@classmethod
- def create_member(cls, protocol_port, pool):
+ def create_member(cls, protocol_port, pool, ip_version=None):
"""Wrapper utility that returns a test member."""
- resp, body = cls.client.create_member(address="10.0.9.46",
+ ip_version = ip_version if ip_version is not None else cls._ip_version
+ member_address = "fd00::abcd" if ip_version == 6 else "10.0.9.46"
+ resp, body = cls.client.create_member(address=member_address,
protocol_port=protocol_port,
pool_id=pool['id'])
member = body['member']
diff --git a/tempest/api/network/test_allowed_address_pair.py b/tempest/api/network/test_allowed_address_pair.py
index 6a772f1..a1166c8 100644
--- a/tempest/api/network/test_allowed_address_pair.py
+++ b/tempest/api/network/test_allowed_address_pair.py
@@ -127,5 +127,9 @@
self.assertEqual(mac_address, self.mac_address)
+class AllowedAddressPairIpV6TestJSON(AllowedAddressPairTestJSON):
+ _ip_version = 6
+
+
class AllowedAddressPairTestXML(AllowedAddressPairTestJSON):
_interface = 'xml'
diff --git a/tempest/api/network/test_extra_dhcp_options.py b/tempest/api/network/test_extra_dhcp_options.py
index 86da9b7..6d083b3 100644
--- a/tempest/api/network/test_extra_dhcp_options.py
+++ b/tempest/api/network/test_extra_dhcp_options.py
@@ -44,17 +44,22 @@
cls.network = cls.create_network()
cls.subnet = cls.create_subnet(cls.network)
cls.port = cls.create_port(cls.network)
+ cls.ip_tftp = ('123.123.123.123' if cls._ip_version == 4
+ else '2015::dead')
+ cls.ip_server = ('123.123.123.45' if cls._ip_version == 4
+ else '2015::badd')
+ cls.extra_dhcp_opts = [
+ {'opt_value': 'pxelinux.0', 'opt_name': 'bootfile-name'},
+ {'opt_value': cls.ip_tftp, 'opt_name': 'tftp-server'},
+ {'opt_value': cls.ip_server, 'opt_name': 'server-ip-address'}
+ ]
@test.attr(type='smoke')
def test_create_list_port_with_extra_dhcp_options(self):
# Create a port with Extra DHCP Options
- extra_dhcp_opts = [
- {'opt_value': 'pxelinux.0', 'opt_name': 'bootfile-name'},
- {'opt_value': '123.123.123.123', 'opt_name': 'tftp-server'},
- {'opt_value': '123.123.123.45', 'opt_name': 'server-ip-address'}
- ]
- _, body = self.client.create_port(network_id=self.network['id'],
- extra_dhcp_opts=extra_dhcp_opts)
+ _, body = self.client.create_port(
+ network_id=self.network['id'],
+ extra_dhcp_opts=self.extra_dhcp_opts)
port_id = body['port']['id']
self.addCleanup(self.client.delete_port, port_id)
@@ -63,23 +68,19 @@
ports = body['ports']
port = [p for p in ports if p['id'] == port_id]
self.assertTrue(port)
- self._confirm_extra_dhcp_options(port[0], extra_dhcp_opts)
+ self._confirm_extra_dhcp_options(port[0], self.extra_dhcp_opts)
@test.attr(type='smoke')
def test_update_show_port_with_extra_dhcp_options(self):
# Update port with extra dhcp options
- extra_dhcp_opts = [
- {'opt_value': 'pxelinux.0', 'opt_name': 'bootfile-name'},
- {'opt_value': '123.123.123.123', 'opt_name': 'tftp-server'},
- {'opt_value': '123.123.123.45', 'opt_name': 'server-ip-address'}
- ]
name = data_utils.rand_name('new-port-name')
- _, body = self.client.update_port(self.port['id'], name=name,
- extra_dhcp_opts=extra_dhcp_opts)
-
+ _, body = self.client.update_port(
+ self.port['id'],
+ name=name,
+ extra_dhcp_opts=self.extra_dhcp_opts)
# Confirm extra dhcp options were added to the port
_, body = self.client.show_port(self.port['id'])
- self._confirm_extra_dhcp_options(body['port'], extra_dhcp_opts)
+ self._confirm_extra_dhcp_options(body['port'], self.extra_dhcp_opts)
def _confirm_extra_dhcp_options(self, port, extra_dhcp_opts):
retrieved = port['extra_dhcp_opts']
@@ -92,3 +93,7 @@
else:
self.fail('Extra DHCP option not found in port %s' %
str(retrieved_option))
+
+
+class ExtraDHCPOptionsIpV6TestJSON(ExtraDHCPOptionsTestJSON):
+ _ip_version = 6
diff --git a/tempest/api/network/test_load_balancer.py b/tempest/api/network/test_load_balancer.py
index baa8cad..8b8e3b1 100644
--- a/tempest/api/network/test_load_balancer.py
+++ b/tempest/api/network/test_load_balancer.py
@@ -55,7 +55,9 @@
protocol_port=80,
subnet=cls.subnet,
pool=cls.pool)
- cls.member = cls.create_member(80, cls.pool)
+ cls.member = cls.create_member(80, cls.pool, cls._ip_version)
+ cls.member_address = ("10.0.9.47" if cls._ip_version == 4
+ else "2015::beef")
cls.health_monitor = cls.create_health_monitor(delay=4,
max_retries=3,
Type="TCP",
@@ -213,13 +215,14 @@
def test_list_members_with_filters(self):
attr_exceptions = ['status', 'status_description']
self._check_list_with_filter('member', attr_exceptions,
- address="10.0.9.47", protocol_port=80,
+ address=self.member_address,
+ protocol_port=80,
pool_id=self.pool['id'])
@test.attr(type='smoke')
def test_create_update_delete_member(self):
# Creates a member
- _, body = self.client.create_member(address="10.0.9.47",
+ _, body = self.client.create_member(address=self.member_address,
protocol_port=80,
pool_id=self.pool['id'])
member = body['member']
@@ -419,5 +422,9 @@
self.assertEqual(2, member['weight'])
+class LoadBalancerIpV6TestJSON(LoadBalancerTestJSON):
+ _ip_version = 6
+
+
class LoadBalancerTestXML(LoadBalancerTestJSON):
_interface = 'xml'
diff --git a/tempest/api/network/test_metering_extensions.py b/tempest/api/network/test_metering_extensions.py
index 2cfb841..07ebd8c 100644
--- a/tempest/api/network/test_metering_extensions.py
+++ b/tempest/api/network/test_metering_extensions.py
@@ -43,7 +43,8 @@
description = "metering label created by tempest"
name = data_utils.rand_name("metering-label")
cls.metering_label = cls.create_metering_label(name, description)
- remote_ip_prefix = "10.0.0.0/24"
+ remote_ip_prefix = ("10.0.0.0/24" if cls._ip_version == 4
+ else "fd02::/64")
direction = "ingress"
cls.metering_label_rule = cls.create_metering_label_rule(
remote_ip_prefix, direction,
@@ -112,8 +113,10 @@
@test.attr(type='smoke')
def test_create_delete_metering_label_rule_with_filters(self):
# Creates a rule
+ remote_ip_prefix = ("10.0.1.0/24" if self._ip_version == 4
+ else "fd03::/64")
_, body = (self.admin_client.create_metering_label_rule(
- remote_ip_prefix="10.0.1.0/24",
+ remote_ip_prefix=remote_ip_prefix,
direction="ingress",
metering_label_id=self.metering_label['id']))
metering_label_rule = body['metering_label_rule']
@@ -142,5 +145,9 @@
self.assertFalse(metering_label_rule['excluded'])
+class MeteringIpV6JSON(MeteringJSON):
+ _ip_version = 6
+
+
class MeteringXML(MeteringJSON):
interface = 'xml'
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index b9086cc..be23a82 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -502,13 +502,6 @@
class NetworksIpV6TestJSON(NetworksTestJSON):
_ip_version = 6
- @classmethod
- def resource_setup(cls):
- if not CONF.network_feature_enabled.ipv6:
- skip_msg = "IPv6 Tests are disabled."
- raise cls.skipException(skip_msg)
- super(NetworksIpV6TestJSON, cls).resource_setup()
-
@test.attr(type='smoke')
def test_create_delete_subnet_with_gw(self):
net = netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr)
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index d6db64d..7c5bdfe 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -276,13 +276,6 @@
_tenant_network_cidr = CONF.network.tenant_network_v6_cidr
_tenant_network_mask_bits = CONF.network.tenant_network_v6_mask_bits
- @classmethod
- def resource_setup(cls):
- super(PortsIpV6TestJSON, cls).resource_setup()
- if not CONF.network_feature_enabled.ipv6:
- skip_msg = "IPv6 Tests are disabled."
- raise cls.skipException(skip_msg)
-
class PortsIpV6TestXML(PortsIpV6TestJSON):
_interface = 'xml'
@@ -293,13 +286,6 @@
_tenant_network_cidr = CONF.network.tenant_network_v6_cidr
_tenant_network_mask_bits = CONF.network.tenant_network_v6_mask_bits
- @classmethod
- def resource_setup(cls):
- if not CONF.network_feature_enabled.ipv6:
- skip_msg = "IPv6 Tests are disabled."
- raise cls.skipException(skip_msg)
- super(PortsAdminExtendedAttrsIpV6TestJSON, cls).resource_setup()
-
class PortsAdminExtendedAttrsIpV6TestXML(PortsAdminExtendedAttrsIpV6TestJSON):
_interface = 'xml'
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index f3f25ac..2b4e60a 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -35,6 +35,9 @@
raise cls.skipException(msg)
admin_manager = clients.AdminManager()
cls.identity_admin_client = admin_manager.identity_client
+ cls.tenant_cidr = (CONF.network.tenant_network_cidr
+ if cls._ip_version == 4 else
+ CONF.network.tenant_network_v6_cidr)
def _cleanup_router(self, router):
self.delete_router(router)
@@ -319,7 +322,7 @@
network02 = self.create_network(
network_name=data_utils.rand_name('router-network02-'))
subnet01 = self.create_subnet(network01)
- sub02_cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr).next()
+ sub02_cidr = netaddr.IPNetwork(self.tenant_cidr).next()
subnet02 = self.create_subnet(network02, cidr=sub02_cidr)
router = self._create_router(data_utils.rand_name('router-'))
interface01 = self._add_router_interface_with_subnet_id(router['id'],
@@ -337,3 +340,7 @@
self.assertEqual(router_id, interface_port['device_id'])
self.assertEqual(subnet_id,
interface_port['fixed_ips'][0]['subnet_id'])
+
+
+class RoutersIpV6Test(RoutersTest):
+ _ip_version = 6
diff --git a/tempest/api/network/test_routers_negative.py b/tempest/api/network/test_routers_negative.py
index 4c226af..88aa3c9 100644
--- a/tempest/api/network/test_routers_negative.py
+++ b/tempest/api/network/test_routers_negative.py
@@ -36,6 +36,9 @@
cls.router = cls.create_router(data_utils.rand_name('router-'))
cls.network = cls.create_network()
cls.subnet = cls.create_subnet(cls.network)
+ cls.tenant_cidr = (CONF.network.tenant_network_cidr
+ if cls._ip_version == 4 else
+ CONF.network.tenant_network_v6_cidr)
@test.attr(type=['negative', 'smoke'])
def test_router_add_gateway_invalid_network_returns_404(self):
@@ -49,7 +52,7 @@
def test_router_add_gateway_net_not_external_returns_400(self):
alt_network = self.create_network(
network_name=data_utils.rand_name('router-negative-'))
- sub_cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr).next()
+ sub_cidr = netaddr.IPNetwork(self.tenant_cidr).next()
self.create_subnet(alt_network, cidr=sub_cidr)
self.assertRaises(exceptions.BadRequest,
self.client.update_router,
@@ -79,3 +82,7 @@
self.assertRaises(exceptions.Conflict,
self.client.delete_router,
self.router['id'])
+
+
+class RoutersNegativeIpV6Test(RoutersNegativeTest):
+ _ip_version = 6
diff --git a/tempest/api/network/test_security_groups.py b/tempest/api/network/test_security_groups.py
index e20b58e..47f2b52 100644
--- a/tempest/api/network/test_security_groups.py
+++ b/tempest/api/network/test_security_groups.py
@@ -221,13 +221,6 @@
_ip_version = 6
_tenant_network_cidr = CONF.network.tenant_network_v6_cidr
- @classmethod
- def resource_setup(cls):
- if not CONF.network_feature_enabled.ipv6:
- skip_msg = "IPv6 Tests are disabled."
- raise cls.skipException(skip_msg)
- super(SecGroupIPv6Test, cls).resource_setup()
-
class SecGroupIPv6TestXML(SecGroupIPv6Test):
_interface = 'xml'
diff --git a/tempest/api/network/test_security_groups_negative.py b/tempest/api/network/test_security_groups_negative.py
index 97e4cb7..42f7f71 100644
--- a/tempest/api/network/test_security_groups_negative.py
+++ b/tempest/api/network/test_security_groups_negative.py
@@ -197,13 +197,6 @@
_ip_version = 6
_tenant_network_cidr = CONF.network.tenant_network_v6_cidr
- @classmethod
- def resource_setup(cls):
- if not CONF.network_feature_enabled.ipv6:
- skip_msg = "IPv6 Tests are disabled."
- raise cls.skipException(skip_msg)
- super(NegativeSecGroupIPv6Test, cls).resource_setup()
-
class NegativeSecGroupIPv6TestXML(NegativeSecGroupIPv6Test):
_interface = 'xml'
diff --git a/tempest/clients.py b/tempest/clients.py
index a52907e..9546502 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -233,81 +233,18 @@
super(Manager, self).__init__(credentials=credentials)
self._set_compute_clients(self.interface)
+ self._set_identity_clients(self.interface)
+ self._set_volume_clients(self.interface)
if self.interface == 'xml':
- self.backups_client = BackupsClientXML(self.auth_provider)
- self.snapshots_client = SnapshotsClientXML(self.auth_provider)
- self.snapshots_v2_client = SnapshotsV2ClientXML(self.auth_provider)
- self.volumes_client = VolumesClientXML(self.auth_provider)
- self.volumes_v2_client = VolumesV2ClientXML(self.auth_provider)
- self.volume_types_client = VolumeTypesClientXML(
- self.auth_provider)
- self.identity_client = IdentityClientXML(self.auth_provider)
- self.identity_v3_client = IdentityV3ClientXML(
- self.auth_provider)
- self.endpoints_client = EndPointClientXML(self.auth_provider)
- self.service_client = ServiceClientXML(self.auth_provider)
- self.volume_services_client = VolumesServicesClientXML(
- self.auth_provider)
- self.policy_client = PolicyClientXML(self.auth_provider)
- self.region_client = RegionClientXML(self.auth_provider)
self.network_client = NetworkClientXML(self.auth_provider)
- self.credentials_client = CredentialsClientXML(
- self.auth_provider)
- self.volume_hosts_client = VolumeHostsClientXML(
- self.auth_provider)
- self.volume_quotas_client = VolumeQuotasClientXML(
- self.auth_provider)
- self.volumes_extension_client = VolumeExtensionClientXML(
- self.auth_provider)
- self.volumes_v2_extension_client = VolumeV2ExtensionClientXML(
- self.auth_provider)
if CONF.service_available.ceilometer:
self.telemetry_client = TelemetryClientXML(
self.auth_provider)
- self.token_client = TokenClientXML()
- if CONF.identity_feature_enabled.api_v3:
- self.token_v3_client = V3TokenClientXML()
- self.volume_availability_zone_client = \
- VolumeAvailabilityZoneClientXML(self.auth_provider)
- self.volume_v2_availability_zone_client = \
- VolumeV2AvailabilityZoneClientXML(self.auth_provider)
elif self.interface == 'json':
self.baremetal_client = BaremetalClientJSON(self.auth_provider)
- self.backups_client = BackupsClientJSON(self.auth_provider)
- self.snapshots_client = SnapshotsClientJSON(self.auth_provider)
- self.snapshots_v2_client = SnapshotsV2ClientJSON(
- self.auth_provider)
- self.volumes_client = VolumesClientJSON(self.auth_provider)
- self.volumes_v2_client = VolumesV2ClientJSON(self.auth_provider)
- self.volume_types_client = VolumeTypesClientJSON(
- self.auth_provider)
- self.volume_types_v2_client = VolumeTypesV2ClientJSON(
- self.auth_provider)
- self.identity_client = IdentityClientJSON(self.auth_provider)
- self.identity_v3_client = IdentityV3ClientJSON(
- self.auth_provider)
- self.endpoints_client = EndPointClientJSON(self.auth_provider)
- self.service_client = ServiceClientJSON(self.auth_provider)
- self.volume_services_client = VolumesServicesClientJSON(
- self.auth_provider)
- self.policy_client = PolicyClientJSON(self.auth_provider)
- self.region_client = RegionClientJSON(self.auth_provider)
self.network_client = NetworkClientJSON(self.auth_provider)
- self.credentials_client = CredentialsClientJSON(
- self.auth_provider)
- self.volume_hosts_client = VolumeHostsClientJSON(
- self.auth_provider)
- self.volume_hosts_v2_client = VolumeHostsV2ClientJSON(
- self.auth_provider)
- self.volume_quotas_client = VolumeQuotasClientJSON(
- self.auth_provider)
- self.volumes_extension_client = VolumeExtensionClientJSON(
- self.auth_provider)
- self.volumes_v2_extension_client = VolumeV2ExtensionClientJSON(
- self.auth_provider)
-
self.database_flavors_client = DatabaseFlavorsClientJSON(
self.auth_provider)
self.database_versions_client = DatabaseVersionsClientJSON(
@@ -316,16 +253,9 @@
if CONF.service_available.ceilometer:
self.telemetry_client = TelemetryClientJSON(
self.auth_provider)
- self.token_client = TokenClientJSON()
- if CONF.identity_feature_enabled.api_v3:
- self.token_v3_client = V3TokenClientJSON()
self.negative_client = rest_client.NegativeRestClient(
self.auth_provider)
self.negative_client.service = service
- self.volume_availability_zone_client = \
- VolumeAvailabilityZoneClientJSON(self.auth_provider)
- self.volume_v2_availability_zone_client = \
- VolumeV2AvailabilityZoneClientJSON(self.auth_provider)
else:
msg = "Unsupported interface type `%s'" % interface
@@ -354,13 +284,6 @@
AccountClientCustomizedHeader(self.auth_provider)
self.data_processing_client = DataProcessingClient(
self.auth_provider)
- # NOTE : As XML clients are not implemented for Qos-specs.
- # So, setting the qos_client here. Once client are implemented,
- # qos_client would be moved to its respective if/else.
- # Bug : 1312553
- self.volume_qos_client = QosSpecsClientJSON(self.auth_provider)
- self.volume_qos_v2_client = QosSpecsV2ClientJSON(
- self.auth_provider)
def _set_compute_clients(self, type):
if type == 'json':
@@ -446,6 +369,95 @@
self.instance_usages_audit_log_client = \
InstanceUsagesAuditLogClientJSON(self.auth_provider)
+ def _set_identity_clients(self, type):
+ if type == 'json':
+ self._set_identity_json_clients()
+ else:
+ self._set_identity_xml_clients()
+
+ def _set_identity_xml_clients(self):
+ self.identity_client = IdentityClientXML(self.auth_provider)
+ self.identity_v3_client = IdentityV3ClientXML(self.auth_provider)
+ self.endpoints_client = EndPointClientXML(self.auth_provider)
+ self.service_client = ServiceClientXML(self.auth_provider)
+ self.policy_client = PolicyClientXML(self.auth_provider)
+ self.region_client = RegionClientXML(self.auth_provider)
+ self.token_client = TokenClientXML()
+ if CONF.identity_feature_enabled.api_v3:
+ self.token_v3_client = V3TokenClientXML()
+ self.credentials_client = CredentialsClientXML(self.auth_provider)
+
+ def _set_identity_json_clients(self):
+ self.identity_client = IdentityClientJSON(self.auth_provider)
+ self.identity_v3_client = IdentityV3ClientJSON(self.auth_provider)
+ self.endpoints_client = EndPointClientJSON(self.auth_provider)
+ self.service_client = ServiceClientJSON(self.auth_provider)
+ self.policy_client = PolicyClientJSON(self.auth_provider)
+ self.region_client = RegionClientJSON(self.auth_provider)
+ self.token_client = TokenClientJSON()
+ if CONF.identity_feature_enabled.api_v3:
+ self.token_v3_client = V3TokenClientJSON()
+ self.credentials_client = CredentialsClientJSON(self.auth_provider)
+
+ def _set_volume_clients(self, type):
+ if type == 'json':
+ self._set_volume_json_clients()
+ else:
+ self._set_volume_xml_clients()
+
+ # Common volume clients
+ # NOTE : As XML clients are not implemented for Qos-specs.
+ # So, setting the qos_client here. Once client are implemented,
+ # qos_client would be moved to its respective if/else.
+ # Bug : 1312553
+ self.volume_qos_client = QosSpecsClientJSON(self.auth_provider)
+ self.volume_qos_v2_client = QosSpecsV2ClientJSON(
+ self.auth_provider)
+
+ def _set_volume_xml_clients(self):
+ self.backups_client = BackupsClientXML(self.auth_provider)
+ self.snapshots_client = SnapshotsClientXML(self.auth_provider)
+ self.snapshots_v2_client = SnapshotsV2ClientXML(self.auth_provider)
+ self.volumes_client = VolumesClientXML(self.auth_provider)
+ self.volumes_v2_client = VolumesV2ClientXML(self.auth_provider)
+ self.volume_types_client = VolumeTypesClientXML(self.auth_provider)
+ self.volume_services_client = VolumesServicesClientXML(
+ self.auth_provider)
+ self.volume_hosts_client = VolumeHostsClientXML(self.auth_provider)
+ self.volume_quotas_client = VolumeQuotasClientXML(self.auth_provider)
+ self.volumes_extension_client = VolumeExtensionClientXML(
+ self.auth_provider)
+ self.volumes_v2_extension_client = VolumeV2ExtensionClientXML(
+ self.auth_provider)
+ self.volume_availability_zone_client = \
+ VolumeAvailabilityZoneClientXML(self.auth_provider)
+ self.volume_v2_availability_zone_client = \
+ VolumeV2AvailabilityZoneClientXML(self.auth_provider)
+
+ def _set_volume_json_clients(self):
+ self.backups_client = BackupsClientJSON(self.auth_provider)
+ self.snapshots_client = SnapshotsClientJSON(self.auth_provider)
+ self.snapshots_v2_client = SnapshotsV2ClientJSON(self.auth_provider)
+ self.volumes_client = VolumesClientJSON(self.auth_provider)
+ self.volumes_v2_client = VolumesV2ClientJSON(self.auth_provider)
+ self.volume_types_client = VolumeTypesClientJSON(self.auth_provider)
+ self.volume_services_client = VolumesServicesClientJSON(
+ self.auth_provider)
+ self.volume_hosts_client = VolumeHostsClientJSON(self.auth_provider)
+ self.volume_hosts_v2_client = VolumeHostsV2ClientJSON(
+ self.auth_provider)
+ self.volume_quotas_client = VolumeQuotasClientJSON(self.auth_provider)
+ self.volumes_extension_client = VolumeExtensionClientJSON(
+ self.auth_provider)
+ self.volumes_v2_extension_client = VolumeV2ExtensionClientJSON(
+ self.auth_provider)
+ self.volume_availability_zone_client = \
+ VolumeAvailabilityZoneClientJSON(self.auth_provider)
+ self.volume_v2_availability_zone_client = \
+ VolumeV2AvailabilityZoneClientJSON(self.auth_provider)
+ self.volume_types_v2_client = VolumeTypesV2ClientJSON(
+ self.auth_provider)
+
class AdminManager(Manager):
diff --git a/tempest/config.py b/tempest/config.py
index 495de62..616a476 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -143,6 +143,9 @@
cfg.BoolOpt('api_v3',
default=True,
help='Is the v3 identity API enabled'),
+ cfg.BoolOpt('xml_api',
+ default=False,
+ help='If false, skip all identity api tests with xml'),
]
compute_group = cfg.OptGroup(name='compute',
@@ -219,10 +222,12 @@
"channel."),
cfg.StrOpt('fixed_network_name',
default='private',
- help="Visible fixed network name "),
+ help="Name of the fixed network that is visible to all test "
+ "tenants."),
cfg.StrOpt('network_for_ssh',
default='public',
- help="Network used for SSH connections."),
+ help="Network used for SSH connections. Ignored if "
+ "use_floatingip_for_ssh=true or run_ssh=false."),
cfg.IntOpt('ip_version_for_ssh',
default=4,
help="IP version used for SSH connections."),
@@ -263,7 +268,9 @@
cfg.StrOpt('floating_ip_range',
default='10.0.0.0/29',
help='Unallocated floating IP range, which will be used to '
- 'test the floating IP bulk feature for CRUD operation.')
+ 'test the floating IP bulk feature for CRUD operation. '
+ 'This block must not overlap an existing floating IP '
+ 'pool.')
]
compute_features_group = cfg.OptGroup(name='compute-feature-enabled',
@@ -972,7 +979,14 @@
baremetal_group = cfg.OptGroup(name='baremetal',
- title='Baremetal provisioning service options')
+ title='Baremetal provisioning service options',
+ help='When enabling baremetal tests, Nova '
+ 'must be configured to use the Ironic '
+ 'driver. The following paremeters for the '
+ '[compute] section must be disabled: '
+ 'console_output, interface_attach, '
+ 'live_migration, pause, rescue, resize '
+ 'shelve, snapshot, and suspend')
BaremetalGroup = [
cfg.StrOpt('catalog_type',
diff --git a/tempest/scenario/test_swift_telemetry_middleware.py b/tempest/scenario/test_swift_telemetry_middleware.py
new file mode 100644
index 0000000..e8eb45c
--- /dev/null
+++ b/tempest/scenario/test_swift_telemetry_middleware.py
@@ -0,0 +1,103 @@
+#
+# Copyright 2014 Red Hat
+#
+# Author: Chris Dent <chdent@redhat.com>
+# 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 import config
+from tempest.openstack.common import log as logging
+from tempest.scenario import manager
+from tempest import test
+
+CONF = config.CONF
+
+LOG = logging.getLogger(__name__)
+
+# Loop for up to 120 seconds waiting on notifications
+# NOTE(chdent): The choice of 120 seconds is fairly
+# arbitrary: Long enough to give the notifications the
+# chance to travel across a highly latent bus but not
+# so long as to allow excessive latency to never be visible.
+# TODO(chdent): Ideally this value would come from configuration.
+NOTIFICATIONS_WAIT = 120
+NOTIFICATIONS_SLEEP = 1
+
+
+class TestSwiftTelemetry(manager.SwiftScenarioTest):
+ """
+ Test that swift uses the ceilometer middleware.
+ * create container.
+ * upload a file to the created container.
+ * retrieve the file from the created container.
+ * wait for notifications from ceilometer.
+ """
+
+ @classmethod
+ def resource_setup(cls):
+ if not CONF.service_available.ceilometer:
+ skip_msg = ("%s skipped as ceilometer is not available" %
+ cls.__name__)
+ raise cls.skipException(skip_msg)
+ elif CONF.telemetry.too_slow_to_test:
+ skip_msg = "Ceilometer feature for fast work mysql is disabled"
+ raise cls.skipException(skip_msg)
+ super(TestSwiftTelemetry, cls).resource_setup()
+ cls.telemetry_client = cls.manager.telemetry_client
+
+ def _confirm_notifications(self, container_name, obj_name):
+ """
+ Loop seeking for appropriate notifications about the containers
+ and objects sent to swift.
+ """
+
+ def _check_samples():
+ """
+ Return True only if we have notifications about some
+ containers and some objects and the notifications are about
+ the expected containers and objects.
+ Otherwise returning False will case _check_samples to be
+ called again.
+ """
+ _, results = self.telemetry_client.list_samples(
+ 'storage.api.request')
+ LOG.debug('got samples %s', results)
+
+ # Extract container info from samples.
+ containers = [sample['resource_metadata']['container']
+ for sample in results
+ if sample['resource_metadata']['container']
+ != 'None']
+ # Extract object info from samples.
+ objects = [sample['resource_metadata']['object']
+ for sample in results
+ if sample['resource_metadata']['object'] != 'None']
+
+ return (containers
+ and objects
+ and container_name in containers
+ and obj_name in objects)
+
+ self.assertTrue(test.call_until_true(_check_samples,
+ NOTIFICATIONS_WAIT,
+ NOTIFICATIONS_SLEEP),
+ 'Correct notifications were not received after '
+ '%s seconds.' % NOTIFICATIONS_WAIT)
+
+ @test.services('object_storage', 'telemetry')
+ def test_swift_middleware_notifies(self):
+ container_name = self.create_container()
+ obj_name, _ = self.upload_object_to_container(container_name)
+ self._confirm_notifications(container_name, obj_name)
diff --git a/tempest/thirdparty/boto/test_ec2_instance_run.py b/tempest/thirdparty/boto/test_ec2_instance_run.py
index f3f11fd..00b17d9 100644
--- a/tempest/thirdparty/boto/test_ec2_instance_run.py
+++ b/tempest/thirdparty/boto/test_ec2_instance_run.py
@@ -306,8 +306,7 @@
volume.detach()
- self.assertVolumeStatusWait(_volume_state, "available")
- wait.re_search_wait(_volume_state, "available")
+ self.assertVolumeStatusWait(volume, "available")
wait.state_wait(_part_state, 'DECREASE')