Merge "Make create_server_group use **kwargs"
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index ec430b7..dd2f56b 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -76,8 +76,9 @@
To enable and use tenant isolation you only need to configure 2 things:
#. A set of admin credentials with permissions to create users and
- tenants/projects. This is specified in the identity section with the
- admin_username, admin_tenant_name, and admin_password options
+ tenants/projects. This is specified in the auth section with the
+ admin_username, admin_tenant_name, admin_domain_name, and admin_password
+ options
#. To enable tenant_isolation in the auth section with the
allow_tenant_isolation option.
@@ -126,6 +127,9 @@
Non-locking test accounts (aka credentials config options)
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+**Starting in the Liberty release this mechanism was deprecated and will be
+removed in a future release**
+
When Tempest was refactored to allow for locking test accounts, the original
non-tenant isolated case was converted to internally work similarly to the
accounts.yaml file. This mechanism was then called the non-locking test accounts
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index 68af81c..2fd7520 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -41,6 +41,7 @@
super(ServersTestJSON, cls).setup_clients()
cls.client = cls.servers_client
cls.network_client = cls.os.network_client
+ cls.networks_client = cls.os.networks_client
@classmethod
def resource_setup(cls):
@@ -69,8 +70,8 @@
def _create_net_subnet_ret_net_from_cidr(self, cidr):
name_net = data_utils.rand_name(self.__class__.__name__)
- net = self.network_client.create_network(name=name_net)
- self.addCleanup(self.network_client.delete_network,
+ net = self.networks_client.create_network(name=name_net)
+ self.addCleanup(self.networks_client.delete_network,
net['network']['id'])
subnet = self.network_client.create_subnet(
diff --git a/tempest/api/identity/v2/test_ec2_credentials.py b/tempest/api/identity/v2/test_ec2_credentials.py
index 17963b8..763d8de 100644
--- a/tempest/api/identity/v2/test_ec2_credentials.py
+++ b/tempest/api/identity/v2/test_ec2_credentials.py
@@ -93,7 +93,7 @@
ec2_creds = self.non_admin_client.show_user_ec2_credentials(
self.creds.credentials.user_id, resp['access']
- )
+ )["credential"]
for key in ['access', 'secret', 'user_id', 'tenant_id']:
self.assertEqual(ec2_creds[key], resp[key])
diff --git a/tempest/api/identity/v2/test_users.py b/tempest/api/identity/v2/test_users.py
index 4e5b41d..3b89b66 100644
--- a/tempest/api/identity/v2/test_users.py
+++ b/tempest/api/identity/v2/test_users.py
@@ -56,7 +56,7 @@
# user updates own password
resp = self.non_admin_client.update_user_own_password(
- user_id=user_id, new_pass=new_pass, old_pass=old_pass)
+ user_id=user_id, new_pass=new_pass, old_pass=old_pass)['access']
# check authorization with new token
self.non_admin_token_client.auth_token(resp['token']['id'])
diff --git a/tempest/api/network/admin/test_external_network_extension.py b/tempest/api/network/admin/test_external_network_extension.py
index d942641..62aa18e 100644
--- a/tempest/api/network/admin/test_external_network_extension.py
+++ b/tempest/api/network/admin/test_external_network_extension.py
@@ -26,9 +26,10 @@
post_body = {'name': data_utils.rand_name('network-')}
if external:
post_body['router:external'] = external
- body = self.admin_client.create_network(**post_body)
+ body = self.admin_networks_client.create_network(**post_body)
network = body['network']
- self.addCleanup(self.admin_client.delete_network, network['id'])
+ self.addCleanup(
+ self.admin_networks_client.delete_network, network['id'])
return network
@test.idempotent_id('462be770-b310-4df9-9c42-773217e4c8b1')
@@ -47,8 +48,8 @@
network = self._create_network(external=False)
self.assertFalse(network.get('router:external', False))
update_body = {'router:external': True}
- body = self.admin_client.update_network(network['id'],
- **update_body)
+ body = self.admin_networks_client.update_network(network['id'],
+ **update_body)
updated_network = body['network']
# Verify that router:external parameter was updated
self.assertTrue(updated_network['router:external'])
@@ -60,7 +61,7 @@
# List networks as a normal user and confirm the external
# network extension attribute is returned for those networks
# that were created as external
- body = self.client.list_networks()
+ body = self.networks_client.list_networks()
networks_list = [net['id'] for net in body['networks']]
self.assertIn(external_network['id'], networks_list)
self.assertIn(self.network['id'], networks_list)
@@ -76,12 +77,12 @@
external_network = self._create_network()
# Show an external network as a normal user and confirm the
# external network extension attribute is returned.
- body = self.client.show_network(external_network['id'])
+ body = self.networks_client.show_network(external_network['id'])
show_ext_net = body['network']
self.assertEqual(external_network['name'], show_ext_net['name'])
self.assertEqual(external_network['id'], show_ext_net['id'])
self.assertTrue(show_ext_net['router:external'])
- body = self.client.show_network(self.network['id'])
+ body = self.networks_client.show_network(self.network['id'])
show_net = body['network']
# Verify with show that router:external is False for network
self.assertEqual(self.network['name'], show_net['name'])
@@ -96,10 +97,11 @@
"""
# Set cls.client to admin to use base.create_subnet()
client = self.admin_client
- body = client.create_network(**{'router:external': True})
+ body = self.admin_networks_client.create_network(
+ **{'router:external': True})
external_network = body['network']
self.addCleanup(self._try_delete_resource,
- client.delete_network,
+ self.admin_networks_client.delete_network,
external_network['id'])
subnet = self.create_subnet(external_network, client=client,
enable_dhcp=False)
@@ -113,7 +115,7 @@
network=external_network['id'])
self.assertIn(created_floating_ip['id'],
(f['id'] for f in floatingip_list['floatingips']))
- client.delete_network(external_network['id'])
+ self.admin_networks_client.delete_network(external_network['id'])
# Verifies floating ip is deleted
floatingip_list = client.list_floatingips()
self.assertNotIn(created_floating_ip['id'],
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index fa6fa33..39bdcff 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -73,6 +73,7 @@
def setup_clients(cls):
super(BaseNetworkTest, cls).setup_clients()
cls.client = cls.os.network_client
+ cls.networks_client = cls.os.networks_client
@classmethod
def resource_setup(cls):
@@ -118,7 +119,7 @@
subnet['id'])
# Clean up networks
for network in cls.networks:
- cls._try_delete_resource(cls.client.delete_network,
+ cls._try_delete_resource(cls.networks_client.delete_network,
network['id'])
super(BaseNetworkTest, cls).resource_cleanup()
@@ -147,7 +148,7 @@
"""Wrapper utility that returns a test network."""
network_name = network_name or data_utils.rand_name('test-network-')
- body = cls.client.create_network(name=network_name)
+ body = cls.networks_client.create_network(name=network_name)
network = body['network']
cls.networks.append(network)
return network
@@ -265,6 +266,7 @@
def setup_clients(cls):
super(BaseAdminNetworkTest, cls).setup_clients()
cls.admin_client = cls.os_adm.network_client
+ cls.admin_networks_client = cls.os_adm.networks_client
@classmethod
def create_metering_label(cls, name, description):
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 1116573..a4ab43a 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -146,7 +146,7 @@
def _delete_network(self, network):
# Deleting network also deletes its subnets if exists
- self.client.delete_network(network['id'])
+ self.networks_client.delete_network(network['id'])
if network in self.networks:
self.networks.remove(network)
for subnet in self.subnets:
@@ -171,7 +171,7 @@
del subnet['dns_nameservers'], compare_args['dns_nameservers']
self._compare_resource_attrs(subnet, compare_args)
- self.client.delete_network(net_id)
+ self.networks_client.delete_network(net_id)
self.networks.pop()
self.subnets.pop()
@@ -186,7 +186,7 @@
self.assertEqual('ACTIVE', network['status'])
# Verify network update
new_name = "New_network"
- body = self.client.update_network(net_id, name=new_name)
+ body = self.networks_client.update_network(net_id, name=new_name)
updated_net = body['network']
self.assertEqual(updated_net['name'], new_name)
# Find a cidr that is not in use yet and create a subnet with it
@@ -202,7 +202,7 @@
@test.idempotent_id('2bf13842-c93f-4a69-83ed-717d2ec3b44e')
def test_show_network(self):
# Verify the details of a network
- body = self.client.show_network(self.network['id'])
+ body = self.networks_client.show_network(self.network['id'])
network = body['network']
for key in ['id', 'name']:
self.assertEqual(network[key], self.network[key])
@@ -211,8 +211,8 @@
def test_show_network_fields(self):
# Verify specific fields of a network
fields = ['id', 'name']
- body = self.client.show_network(self.network['id'],
- fields=fields)
+ body = self.networks_client.show_network(self.network['id'],
+ fields=fields)
network = body['network']
self.assertEqual(sorted(network.keys()), sorted(fields))
for field_name in fields:
@@ -222,7 +222,7 @@
@test.idempotent_id('f7ffdeda-e200-4a7a-bcbe-05716e86bf43')
def test_list_networks(self):
# Verify the network exists in the list of all networks
- body = self.client.list_networks()
+ body = self.networks_client.list_networks()
networks = [network['id'] for network in body['networks']
if network['id'] == self.network['id']]
self.assertNotEmpty(networks, "Created network not found in the list")
@@ -231,7 +231,7 @@
def test_list_networks_fields(self):
# Verify specific fields of the networks
fields = ['id', 'name']
- body = self.client.list_networks(fields=fields)
+ body = self.networks_client.list_networks(fields=fields)
networks = body['networks']
self.assertNotEmpty(networks, "Network list returned is empty")
for network in networks:
@@ -281,7 +281,7 @@
def _try_delete_network(self, net_id):
# delete network, if it exists
try:
- self.client.delete_network(net_id)
+ self.networks_client.delete_network(net_id)
# if network is not found, this means it was deleted in the test
except lib_exc.NotFound:
pass
@@ -290,7 +290,7 @@
def test_delete_network_with_subnet(self):
# Creates a network
name = data_utils.rand_name('network-')
- body = self.client.create_network(name=name)
+ body = self.networks_client.create_network(name=name)
network = body['network']
net_id = network['id']
self.addCleanup(self._try_delete_network, net_id)
@@ -300,7 +300,7 @@
subnet_id = subnet['id']
# Delete network while the subnet still exists
- body = self.client.delete_network(net_id)
+ body = self.networks_client.delete_network(net_id)
# Verify that the subnet got automatically deleted.
self.assertRaises(lib_exc.NotFound, self.client.show_subnet,
@@ -382,7 +382,7 @@
@test.idempotent_id('af774677-42a9-4e4b-bb58-16fe6a5bc1ec')
def test_external_network_visibility(self):
"""Verifies user can see external networks but not subnets."""
- body = self.client.list_networks(**{'router:external': True})
+ body = self.networks_client.list_networks(**{'router:external': True})
networks = [network['id'] for network in body['networks']]
self.assertNotEmpty(networks, "No external networks found")
@@ -426,9 +426,9 @@
def _delete_networks(self, created_networks):
for n in created_networks:
- self.client.delete_network(n['id'])
+ self.networks_client.delete_network(n['id'])
# Asserting that the networks are not found in the list after deletion
- body = self.client.list_networks()
+ body = self.networks_client.list_networks()
networks_list = [network['id'] for network in body['networks']]
for n in created_networks:
self.assertNotIn(n['id'], networks_list)
@@ -461,7 +461,7 @@
created_networks = body['networks']
self.addCleanup(self._delete_networks, created_networks)
# Asserting that the networks are found in the list after creation
- body = self.client.list_networks()
+ body = self.networks_client.list_networks()
networks_list = [network['id'] for network in body['networks']]
for n in created_networks:
self.assertIsNotNone(n['id'])
@@ -630,7 +630,7 @@
self.assertRaisesRegexp(
lib_exc.Conflict,
"There are one or more ports still in use on the network",
- self.client.delete_network,
+ self.networks_client.delete_network,
slaac_network['id'])
@test.idempotent_id('88554555-ebf8-41ef-9300-4926d45e06e9')
diff --git a/tempest/api/network/test_networks_negative.py b/tempest/api/network/test_networks_negative.py
index 94c3f9a..4d1971f 100644
--- a/tempest/api/network/test_networks_negative.py
+++ b/tempest/api/network/test_networks_negative.py
@@ -27,7 +27,7 @@
@test.idempotent_id('9293e937-824d-42d2-8d5b-e985ea67002a')
def test_show_non_existent_network(self):
non_exist_id = data_utils.rand_uuid()
- self.assertRaises(lib_exc.NotFound, self.client.show_network,
+ self.assertRaises(lib_exc.NotFound, self.networks_client.show_network,
non_exist_id)
@test.attr(type=['negative'])
@@ -48,14 +48,16 @@
@test.idempotent_id('98bfe4e3-574e-4012-8b17-b2647063de87')
def test_update_non_existent_network(self):
non_exist_id = data_utils.rand_uuid()
- self.assertRaises(lib_exc.NotFound, self.client.update_network,
- non_exist_id, name="new_name")
+ self.assertRaises(
+ lib_exc.NotFound, self.networks_client.update_network,
+ non_exist_id, name="new_name")
@test.attr(type=['negative'])
@test.idempotent_id('03795047-4a94-4120-a0a1-bd376e36fd4e')
def test_delete_non_existent_network(self):
non_exist_id = data_utils.rand_uuid()
- self.assertRaises(lib_exc.NotFound, self.client.delete_network,
+ self.assertRaises(lib_exc.NotFound,
+ self.networks_client.delete_network,
non_exist_id)
@test.attr(type=['negative'])
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index 6a8fbec..321473c 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -167,17 +167,25 @@
port_list = self.client.list_ports(fixed_ips=fixed_ips)
# Check that we got the desired port
ports = port_list['ports']
- self.assertEqual(len(ports), 1)
- self.assertEqual(ports[0]['id'], port_1['port']['id'])
- self.assertEqual(ports[0]['fixed_ips'][0]['ip_address'],
- port_1_fixed_ip)
- self.assertEqual(ports[0]['network_id'], network['id'])
+ tenant_ids = set([port['tenant_id'] for port in ports])
+ self.assertEqual(len(tenant_ids), 1,
+ 'Ports from multiple tenants are in the list resp')
+ port_ids = [port['id'] for port in ports]
+ fixed_ips = [port['fixed_ips'] for port in ports]
+ port_ips = []
+ for addr in fixed_ips:
+ port_ips.extend([port['ip_address'] for port in addr])
+
+ port_net_ids = [port['network_id'] for port in ports]
+ self.assertIn(port_1['port']['id'], port_ids)
+ self.assertIn(port_1_fixed_ip, port_ips)
+ self.assertIn(network['id'], port_net_ids)
@test.idempotent_id('5ad01ed0-0e6e-4c5d-8194-232801b15c72')
def test_port_list_filter_by_router_id(self):
# Create a router
network = self.create_network()
- self.addCleanup(self.client.delete_network, network['id'])
+ self.addCleanup(self.networks_client.delete_network, network['id'])
subnet = self.create_subnet(network)
self.addCleanup(self.client.delete_subnet, subnet['id'])
router = self.create_router(data_utils.rand_name('router-'))
@@ -210,7 +218,7 @@
def test_create_update_port_with_second_ip(self):
# Create a network with two subnets
network = self.create_network()
- self.addCleanup(self.client.delete_network, network['id'])
+ self.addCleanup(self.networks_client.delete_network, network['id'])
subnet_1 = self.create_subnet(network)
self.addCleanup(self.client.delete_subnet, subnet_1['id'])
subnet_2 = self.create_subnet(network)
@@ -318,7 +326,7 @@
@test.idempotent_id('4179dcb9-1382-4ced-84fe-1b91c54f5735')
def test_create_port_with_no_securitygroups(self):
network = self.create_network()
- self.addCleanup(self.client.delete_network, network['id'])
+ self.addCleanup(self.networks_client.delete_network, network['id'])
subnet = self.create_subnet(network)
self.addCleanup(self.client.delete_subnet, subnet['id'])
port = self.create_port(network, security_groups=[])
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index ca5a868..29855e1 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -188,7 +188,7 @@
gw_port = list_body['ports'][0]
fixed_ips = gw_port['fixed_ips']
self.assertGreaterEqual(len(fixed_ips), 1)
- public_net_body = self.admin_client.show_network(
+ public_net_body = self.admin_networks_client.show_network(
CONF.network.public_network_id)
public_subnet_id = public_net_body['network']['subnets'][0]
self.assertIn(public_subnet_id,
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index f450b0c..4968835 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -50,6 +50,8 @@
cls.servers_client = cls.os.servers_client
cls.keypairs_client = cls.os.keypairs_client
cls.network_client = cls.os.network_client
+ cls.networks_client = cls.os.networks_client
+ cls.volumes_client = cls.os.volumes_client
cls.images_v2_client = cls.os.image_client_v2
if CONF.volume_feature_enabled.api_v2:
diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
index 8f1f0d6..99c2a97 100644
--- a/tempest/api/orchestration/stacks/test_neutron_resources.py
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -118,7 +118,7 @@
def test_created_network(self):
"""Verifies created network."""
network_id = self.test_resources.get('Network')['physical_resource_id']
- body = self.network_client.show_network(network_id)
+ body = self.networks_client.show_network(network_id)
network = body['network']
self.assertIsInstance(network, dict)
self.assertEqual(network_id, network['id'])
diff --git a/tempest/api/telemetry/test_alarming_api_negative.py b/tempest/api/telemetry/test_alarming_api_negative.py
new file mode 100644
index 0000000..7d5a0bf
--- /dev/null
+++ b/tempest/api/telemetry/test_alarming_api_negative.py
@@ -0,0 +1,71 @@
+# Copyright 2015 GlobalLogic. 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.api.telemetry import base
+from tempest.common.utils import data_utils
+from tempest import test
+from tempest_lib import exceptions as lib_exc
+
+import uuid
+
+
+class TelemetryAlarmingNegativeTest(base.BaseTelemetryTest):
+ """here we have negative tests for show_alarm, update_alarm, show_alarm_history
+ Tests
+ ** show non-existent alarm
+ ** show the deleted alarm
+ ** delete deleted alarm
+ ** update deleted alarm
+ """
+
+ @test.attr(type=['negative'])
+ @test.idempotent_id('668743d5-08ad-4480-b2b8-15da34f81e7d')
+ def test_get_non_existent_alarm(self):
+ # get the non-existent alarm
+ non_existent_id = str(uuid.uuid4())
+ self.assertRaises(lib_exc.NotFound, self.telemetry_client.show_alarm,
+ non_existent_id)
+
+ @test.attr(type=['negative'])
+ @test.idempotent_id('ef45000d-0a72-4781-866d-4cb7bf2582ad')
+ def test_get_update_show_history_delete_deleted_alarm(self):
+ # get, update and delete the deleted alarm
+ alarm_name = data_utils.rand_name('telemetry_alarm')
+ rule = {'meter_name': 'cpu',
+ 'comparison_operator': 'eq',
+ 'threshold': 100.0,
+ 'period': 90}
+ body = self.telemetry_client.create_alarm(
+ name=alarm_name,
+ type='threshold',
+ threshold_rule=rule)
+ alarm_id = body['alarm_id']
+ self.telemetry_client.delete_alarm(alarm_id)
+ # get the deleted alarm
+ self.assertRaises(lib_exc.NotFound, self.telemetry_client.show_alarm,
+ alarm_id)
+
+ # update the deleted alarm
+ updated_alarm_name = data_utils.rand_name('telemetry_alarm_updated')
+ updated_rule = {'meter_name': 'cpu_new',
+ 'comparison_operator': 'eq',
+ 'threshold': 70,
+ 'period': 50}
+ self.assertRaises(lib_exc.NotFound, self.telemetry_client.update_alarm,
+ alarm_id, threshold_rule=updated_rule,
+ name=updated_alarm_name,
+ type='threshold')
+ # delete the deleted alarm
+ self.assertRaises(lib_exc.NotFound, self.telemetry_client.delete_alarm,
+ alarm_id)
diff --git a/tempest/clients.py b/tempest/clients.py
index 2756fa8..dd0d145 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -74,8 +74,8 @@
ServerGroupsClient
from tempest.services.compute.json.servers_client import ServersClient
from tempest.services.compute.json.services_client import ServicesClient
-from tempest.services.compute.json.snapshots_extensions_client import \
- SnapshotsExtensionsClient
+from tempest.services.compute.json.snapshots_client import \
+ SnapshotsClient as ComputeSnapshotsClient
from tempest.services.compute.json.tenant_networks_client import \
TenantNetworksClient
from tempest.services.compute.json.tenant_usages_client import \
@@ -108,6 +108,7 @@
from tempest.services.messaging.json.messaging_client import \
MessagingClient
from tempest.services.network.json.network_client import NetworkClient
+from tempest.services.network.json.networks_client import NetworksClient
from tempest.services.object_storage.account_client import AccountClient
from tempest.services.object_storage.container_client import ContainerClient
from tempest.services.object_storage.object_client import ObjectClient
@@ -197,6 +198,14 @@
build_interval=CONF.network.build_interval,
build_timeout=CONF.network.build_timeout,
**self.default_params)
+ self.networks_client = NetworksClient(
+ self.auth_provider,
+ CONF.network.catalog_type,
+ CONF.network.region or CONF.identity.region,
+ endpoint_type=CONF.network.endpoint_type,
+ build_interval=CONF.network.build_interval,
+ build_timeout=CONF.network.build_timeout,
+ **self.default_params)
self.messaging_client = MessagingClient(
self.auth_provider,
CONF.messaging.catalog_type,
@@ -329,7 +338,7 @@
self.auth_provider, **params_volume)
self.compute_versions_client = VersionsClient(self.auth_provider,
**params_volume)
- self.snapshots_extensions_client = SnapshotsExtensionsClient(
+ self.snapshots_extensions_client = ComputeSnapshotsClient(
self.auth_provider, **params_volume)
def _set_database_clients(self):
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index ce7728e..c26df96 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -93,6 +93,7 @@
from tempest import exceptions as exc
from tempest.services.identity.v2.json import identity_client
from tempest.services.network.json import network_client
+from tempest.services.network.json import networks_client
import tempest_lib.auth
from tempest_lib.common.utils import data_utils
import tempest_lib.exceptions
@@ -136,19 +137,29 @@
**params
)
network_admin = None
+ networks_admin = None
+ neutron_iso_networks = False
if (CONF.service_available.neutron and
CONF.auth.create_isolated_networks):
+ neutron_iso_networks = True
network_admin = network_client.NetworkClient(
_auth,
CONF.network.catalog_type,
CONF.network.region or CONF.identity.region,
endpoint_type='adminURL',
**params)
- return identity_admin, network_admin
+ networks_admin = networks_client.NetworksClient(
+ _auth,
+ CONF.network.catalog_type,
+ CONF.network.region or CONF.identity.region,
+ endpoint_type='adminURL',
+ **params)
+ return identity_admin, neutron_iso_networks, network_admin, networks_admin
def create_resources(opts, resources):
- identity_admin, network_admin = get_admin_clients(opts)
+ (identity_admin, neutron_iso_networks,
+ network_admin, networks_admin) = get_admin_clients(opts)
roles = identity_admin.list_roles()
for u in resources['users']:
u['role_ids'] = []
@@ -187,12 +198,11 @@
u['name'] = random_user_name(opts.tag, u['prefix'])
LOG.info('Users created')
- if network_admin:
+ if neutron_iso_networks:
for u in resources['users']:
tenant = identity_admin.get_tenant_by_name(u['tenant'])
- network_name, router_name = create_network_resources(network_admin,
- tenant['id'],
- u['name'])
+ network_name, router_name = create_network_resources(
+ network_admin, networks_admin, tenant['id'], u['name'])
u['network'] = network_name
u['router'] = router_name
LOG.info('Networks created')
@@ -218,10 +228,11 @@
LOG.info('Resources deployed successfully!')
-def create_network_resources(network_admin_client, tenant_id, name):
+def create_network_resources(network_admin_client, networks_admin_client,
+ tenant_id, name):
def _create_network(name):
- resp_body = network_admin_client.create_network(
+ resp_body = networks_admin_client.create_network(
name=name, tenant_id=tenant_id)
return resp_body['network']
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index 6d4e3a9..6c79abc 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -83,7 +83,7 @@
def _get_network_id(net_name, tenant_name):
am = clients.AdminManager()
- net_cl = am.network_client
+ net_cl = am.networks_client
id_cl = am.identity_client
networks = net_cl.list_networks()
@@ -381,6 +381,7 @@
def __init__(self, manager, **kwargs):
super(NetworkService, self).__init__(kwargs)
self.client = manager.network_client
+ self.networks_client = manager.networks_client
def _filter_by_conf_networks(self, item_list):
if not item_list or not all(('network_id' in i for i in item_list)):
@@ -390,7 +391,7 @@
not in CONF_NETWORKS]
def list(self):
- client = self.client
+ client = self.networks_client
networks = client.list_networks(**self.tenant_filter)
networks = networks['networks']
# filter out networks declared in tempest.conf
@@ -401,7 +402,7 @@
return networks
def delete(self):
- client = self.client
+ client = self.networks_client
networks = self.list()
for n in networks:
try:
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index d107ec2..41b0529 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -89,11 +89,14 @@
if volume_backed:
volume_name = data_utils.rand_name('volume')
- volume = clients.volumes_client.create_volume(
+ volumes_client = clients.volumes_v2_client
+ if CONF.volume_feature_enabled.api_v1:
+ volumes_client = clients.volumes_client
+ volume = volumes_client.create_volume(
display_name=volume_name,
imageRef=image_id)
- clients.volumes_client.wait_for_volume_status(volume['volume']['id'],
- 'available')
+ volumes_client.wait_for_volume_status(volume['volume']['id'],
+ 'available')
bd_map_v2 = [{
'uuid': volume['volume']['id'],
diff --git a/tempest/common/cred_provider.py b/tempest/common/cred_provider.py
index 783a5fc..5e80f50 100644
--- a/tempest/common/cred_provider.py
+++ b/tempest/common/cred_provider.py
@@ -26,7 +26,7 @@
# Type of credentials available from configuration
CREDENTIAL_TYPES = {
- 'identity_admin': ('identity', 'admin'),
+ 'identity_admin': ('auth', 'admin'),
'user': ('identity', None),
'alt_user': ('identity', 'alt')
}
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index a4081c9..3850e0e 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -40,8 +40,8 @@
self.default_admin_creds = cred_provider.get_configured_credentials(
'identity_admin', fill_in=True,
identity_version=self.identity_version)
- self.identity_admin_client, self.network_admin_client = (
- self._get_admin_clients())
+ (self.identity_admin_client, self.network_admin_client,
+ self.networks_admin_client) = self._get_admin_clients()
# Domain where isolated credentials are provisioned (v3 only).
# Use that of the admin account is None is configured.
self.creds_domain_name = None
@@ -61,9 +61,9 @@
"""
os = clients.Manager(self.default_admin_creds)
if self.identity_version == 'v2':
- return os.identity_client, os.network_client
+ return os.identity_client, os.network_client, os.networks_client
else:
- return os.identity_v3_client, os.network_client
+ return os.identity_v3_client, os.network_client, os.networks_client
def _create_creds(self, suffix="", admin=False, roles=None):
"""Create random credentials under the following schema.
@@ -158,7 +158,7 @@
return network, subnet, router
def _create_network(self, name, tenant_id):
- resp_body = self.network_admin_client.create_network(
+ resp_body = self.networks_admin_client.create_network(
name=name, tenant_id=tenant_id)
return resp_body['network']
@@ -268,7 +268,7 @@
subnet_name)
def _clear_isolated_network(self, network_id, network_name):
- net_client = self.network_admin_client
+ net_client = self.networks_admin_client
try:
net_client.delete_network(network_id)
except lib_exc.NotFound:
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 9308390..3bead88 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -171,3 +171,14 @@
if dhcp_client == 'udhcpc' and not fixed_ip:
raise ValueError("need to set 'fixed_ip' for udhcpc client")
return getattr(self, '_renew_lease_' + dhcp_client)(fixed_ip=fixed_ip)
+
+ def mount(self, dev_name, mount_path='/mnt'):
+ cmd_mount = 'sudo mount /dev/%s %s' % (dev_name, mount_path)
+ self.exec_command(cmd_mount)
+
+ def umount(self, mount_path='/mnt'):
+ self.exec_command('sudo umount %s' % mount_path)
+
+ def make_fs(self, dev_name, fs='ext4'):
+ cmd_mkfs = 'sudo /usr/sbin/mke2fs -t %s /dev/%s' % (fs, dev_name)
+ self.exec_command(cmd_mkfs)
diff --git a/tempest/config.py b/tempest/config.py
index 3d3ddff..b7aafeb 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -82,6 +82,26 @@
"creates. However in some neutron configurations, like "
"with VLAN provider networks, this doesn't work. So if "
"set to False the isolated networks will not be created"),
+ cfg.StrOpt('admin_username',
+ help="Username for an administrative user. This is needed for "
+ "authenticating requests made by tenant isolation to "
+ "create users and projects",
+ deprecated_group='identity'),
+ cfg.StrOpt('admin_tenant_name',
+ help="Tenant name to use for an administrative user. This is "
+ "needed for authenticating requests made by tenant "
+ "isolation to create users and projects",
+ deprecated_group='identity'),
+ cfg.StrOpt('admin_password',
+ help="Password to use for an administrative user. This is "
+ "needed for authenticating requests made by tenant "
+ "isolation to create users and projects",
+ secret=True,
+ deprecated_group='identity'),
+ cfg.StrOpt('admin_domain_name',
+ help="Admin domain name for authentication (Keystone V3)."
+ "The same domain applies to user and project",
+ deprecated_group='identity'),
]
identity_group = cfg.OptGroup(name='identity',
@@ -133,42 +153,38 @@
help="The endpoint type to use for OpenStack Identity "
"(Keystone) API v3"),
cfg.StrOpt('username',
- help="Username to use for Nova API requests."),
+ help="Username to use for Nova API requests.",
+ deprecated_for_removal=True),
cfg.StrOpt('tenant_name',
- help="Tenant name to use for Nova API requests."),
+ help="Tenant name to use for Nova API requests.",
+ deprecated_for_removal=True),
cfg.StrOpt('admin_role',
default='admin',
help="Role required to administrate keystone."),
cfg.StrOpt('password',
help="API key to use when authenticating.",
- secret=True),
+ secret=True,
+ deprecated_for_removal=True),
cfg.StrOpt('domain_name',
help="Domain name for authentication (Keystone V3)."
- "The same domain applies to user and project"),
+ "The same domain applies to user and project",
+ deprecated_for_removal=True),
cfg.StrOpt('alt_username',
help="Username of alternate user to use for Nova API "
- "requests."),
+ "requests.",
+ deprecated_for_removal=True),
cfg.StrOpt('alt_tenant_name',
help="Alternate user's Tenant name to use for Nova API "
- "requests."),
+ "requests.",
+ deprecated_for_removal=True),
cfg.StrOpt('alt_password',
help="API key to use when authenticating as alternate user.",
- secret=True),
+ secret=True,
+ deprecated_for_removal=True),
cfg.StrOpt('alt_domain_name',
help="Alternate domain name for authentication (Keystone V3)."
- "The same domain applies to user and project"),
- cfg.StrOpt('admin_username',
- help="Administrative Username to use for "
- "Keystone API requests."),
- cfg.StrOpt('admin_tenant_name',
- help="Administrative Tenant name to use for Keystone API "
- "requests."),
- cfg.StrOpt('admin_password',
- help="API key to use when authenticating as admin.",
- secret=True),
- cfg.StrOpt('admin_domain_name',
- help="Admin domain name for authentication (Keystone V3)."
- "The same domain applies to user and project"),
+ "The same domain applies to user and project",
+ deprecated_for_removal=True),
cfg.StrOpt('default_domain_id',
default='default',
help="ID of the default domain"),
@@ -424,6 +440,9 @@
help='Does the test environment support creating instances '
'with multiple ports on the same network? This is only '
'valid when using Neutron.'),
+ cfg.BoolOpt('config_drive',
+ default=True,
+ help='Enable special configuration drive with metadata.'),
]
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 7ab3864..fd84570 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -61,6 +61,7 @@
cls.interface_client = cls.manager.interfaces_client
# Neutron network client
cls.network_client = cls.manager.network_client
+ cls.networks_client = cls.manager.networks_client
# Heat client
cls.orchestration_client = cls.manager.orchestration_client
@@ -557,6 +558,29 @@
floating_ip['ip'], thing['id'])
return floating_ip
+ def create_timestamp(self, server_or_ip, dev_name=None, mount_path='/mnt'):
+ ssh_client = self.get_remote_client(server_or_ip)
+ if dev_name is not None:
+ ssh_client.make_fs(dev_name)
+ ssh_client.mount(dev_name, mount_path)
+ cmd_timestamp = 'sudo sh -c "date > %s/timestamp; sync"' % mount_path
+ ssh_client.exec_command(cmd_timestamp)
+ timestamp = ssh_client.exec_command('sudo cat %s/timestamp'
+ % mount_path)
+ if dev_name is not None:
+ ssh_client.umount(mount_path)
+ return timestamp
+
+ def get_timestamp(self, server_or_ip, dev_name=None, mount_path='/mnt'):
+ ssh_client = self.get_remote_client(server_or_ip)
+ if dev_name is not None:
+ ssh_client.mount(dev_name, mount_path)
+ timestamp = ssh_client.exec_command('sudo cat %s/timestamp'
+ % mount_path)
+ if dev_name is not None:
+ ssh_client.umount(mount_path)
+ return timestamp
+
class NetworkScenarioTest(ScenarioTest):
"""Base class for network scenario tests.
@@ -582,23 +606,25 @@
super(NetworkScenarioTest, cls).resource_setup()
cls.tenant_id = cls.manager.identity_client.tenant_id
- def _create_network(self, client=None, tenant_id=None,
- namestart='network-smoke-'):
+ def _create_network(self, client=None, networks_client=None,
+ tenant_id=None, namestart='network-smoke-'):
if not client:
client = self.network_client
+ if not networks_client:
+ networks_client = self.networks_client
if not tenant_id:
tenant_id = client.tenant_id
name = data_utils.rand_name(namestart)
- result = client.create_network(name=name, tenant_id=tenant_id)
- network = net_resources.DeletableNetwork(client=client,
- **result['network'])
+ result = networks_client.create_network(name=name, tenant_id=tenant_id)
+ network = net_resources.DeletableNetwork(
+ networks_client=networks_client, **result['network'])
self.assertEqual(network.name, name)
self.addCleanup(self.delete_wrapper, network.delete)
return network
def _list_networks(self, *args, **kwargs):
"""List networks using admin creds """
- networks_list = self.admin_manager.network_client.list_networks(
+ networks_list = self.admin_manager.networks_client.list_networks(
*args, **kwargs)
return networks_list['networks']
@@ -1035,8 +1061,8 @@
router.update(admin_state_up=admin_state_up)
self.assertEqual(admin_state_up, router.admin_state_up)
- def create_networks(self, client=None, tenant_id=None,
- dns_nameservers=None):
+ def create_networks(self, client=None, networks_client=None,
+ tenant_id=None, dns_nameservers=None):
"""Create a network with a subnet connected to a router.
The baremetal driver is a special case since all nodes are
@@ -1061,7 +1087,9 @@
router = None
subnet = None
else:
- network = self._create_network(client=client, tenant_id=tenant_id)
+ network = self._create_network(
+ client=client, networks_client=networks_client,
+ tenant_id=tenant_id)
router = self._get_router(client=client, tenant_id=tenant_id)
subnet_kwargs = dict(network=network, client=client)
@@ -1074,9 +1102,12 @@
def create_server(self, name=None, image=None, flavor=None,
wait_on_boot=True, wait_on_delete=True,
- network_client=None, create_kwargs=None):
+ network_client=None, networks_client=None,
+ create_kwargs=None):
if network_client is None:
network_client = self.network_client
+ if networks_client is None:
+ networks_client = self.networks_client
vnic_type = CONF.network.port_vnic_type
@@ -1112,7 +1143,7 @@
# as we would expect when passing the call to the clients
# with no networks
if not networks:
- networks = network_client.list_networks(filters={
+ networks = networks_client.list_networks(filters={
'router:external': False})
self.assertEqual(1, len(networks),
"There is more than one"
diff --git a/tempest/scenario/test_dashboard_basic_ops.py b/tempest/scenario/test_dashboard_basic_ops.py
index d5bad64..f6d9f88 100644
--- a/tempest/scenario/test_dashboard_basic_ops.py
+++ b/tempest/scenario/test_dashboard_basic_ops.py
@@ -90,7 +90,7 @@
# construct login url for dashboard, discovery accommodates non-/ web
# root for dashboard
- login_url = CONF.dashboard.dashboard_url + parser.login[1:]
+ login_url = parse.urljoin(CONF.dashboard.dashboard_url, parser.login)
# Prepare login form request
req = request.Request(login_url)
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 8ca5e72..31ccd5b 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -658,6 +658,7 @@
self.assertEqual('', port['device_id'])
self.assertEqual('', port['device_owner'])
+ @test.requires_ext(service='network', extension='l3_agent_scheduler')
@test.idempotent_id('2e788c46-fb3f-4ac9-8f82-0561555bea73')
@test.services('compute', 'network')
def test_router_rescheduling(self):
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 297076c..a35c0b2 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -249,6 +249,7 @@
server = self.create_server(
name=name,
network_client=tenant.manager.network_client,
+ networks_client=tenant.manager.networks_client,
create_kwargs=create_kwargs)
self.assertEqual(
sorted([s['name'] for s in security_groups]),
@@ -289,7 +290,8 @@
def _create_tenant_network(self, tenant):
network, subnet, router = self.create_networks(
- client=tenant.manager.network_client)
+ client=tenant.manager.network_client,
+ networks_client=tenant.manager.networks_client)
tenant.set_network(network, subnet, router)
def _set_compute_context(self, tenant):
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index 0f27cd1..e2f8adb 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import json
+
from oslo_log import log as logging
from tempest import config
@@ -39,6 +41,7 @@
* Launch an instance
* Perform ssh to instance
* Verify metadata service
+ * Verify metadata on config_drive
* Terminate the instance
"""
@@ -72,9 +75,12 @@
def boot_instance(self):
# Create server with image and flavor from input scenario
security_groups = [{'name': self.security_group['name']}]
+ self.md = {'meta1': 'data1', 'meta2': 'data2', 'metaN': 'dataN'}
create_kwargs = {
'key_name': self.keypair['name'],
- 'security_groups': security_groups
+ 'security_groups': security_groups,
+ 'config_drive': CONF.compute_feature_enabled.config_drive,
+ 'metadata': self.md
}
self.instance = self.create_server(image=self.image_ref,
flavor=self.flavor_ref,
@@ -119,6 +125,22 @@
'verify metadata on server. '
'%s is empty.' % md_url)
+ def verify_metadata_on_config_drive(self):
+ if self.run_ssh and CONF.compute_feature_enabled.config_drive:
+ # Verify metadata on config_drive
+ cmd_blkid = 'blkid -t LABEL=config-2 -o device'
+ dev_name = self.ssh_client.exec_command(cmd_blkid)
+ dev_name = dev_name.rstrip()
+ self.ssh_client.exec_command('sudo mount %s /mnt' % dev_name)
+ cmd_md = 'sudo cat /mnt/openstack/latest/meta_data.json'
+ result = self.ssh_client.exec_command(cmd_md)
+ self.ssh_client.exec_command('sudo umount /mnt')
+ result = json.loads(result)
+ self.assertIn('meta', result)
+ msg = ('Failed while verifying metadata on config_drive on server.'
+ ' Result of command "%s" is NOT "%s".' % (cmd_md, self.md))
+ self.assertEqual(self.md, result['meta'], msg)
+
@test.idempotent_id('7fff3fb3-91d8-4fd0-bd7d-0204f1f180ba')
@test.attr(type='smoke')
@test.services('compute', 'network')
@@ -128,4 +150,5 @@
self.boot_instance()
self.verify_ssh()
self.verify_metadata()
+ self.verify_metadata_on_config_drive()
self.servers_client.delete_server(self.instance['id'])
diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py
index bf4b8e7..dbc9bbb 100644
--- a/tempest/scenario/test_shelve_instance.py
+++ b/tempest/scenario/test_shelve_instance.py
@@ -37,16 +37,6 @@
"""
- def _write_timestamp(self, server_or_ip):
- ssh_client = self.get_remote_client(server_or_ip)
- ssh_client.exec_command('date > /tmp/timestamp; sync')
- self.timestamp = ssh_client.exec_command('cat /tmp/timestamp')
-
- def _check_timestamp(self, server_or_ip):
- ssh_client = self.get_remote_client(server_or_ip)
- got_timestamp = ssh_client.exec_command('cat /tmp/timestamp')
- self.assertEqual(self.timestamp, got_timestamp)
-
def _shelve_then_unshelve_server(self, server):
self.servers_client.shelve_server(server['id'])
offload_time = CONF.compute.shelved_offload_time
@@ -96,18 +86,19 @@
floating_ip['id'])
self.floating_ips_client.associate_floating_ip_to_server(
floating_ip['ip'], server['id'])
- self._write_timestamp(floating_ip['ip'])
+ timestamp = self.create_timestamp(floating_ip['ip'])
else:
- self._write_timestamp(server)
+ timestamp = self.create_timestamp(server)
# Prevent bug #1257594 from coming back
# Unshelve used to boot the instance with the original image, not
# with the instance snapshot
self._shelve_then_unshelve_server(server)
if CONF.compute.use_floatingip_for_ssh:
- self._check_timestamp(floating_ip['ip'])
+ timestamp2 = self.get_timestamp(floating_ip['ip'])
else:
- self._check_timestamp(server)
+ timestamp2 = self.get_timestamp(server)
+ self.assertEqual(timestamp, timestamp2)
@test.idempotent_id('1164e700-0af0-4a4c-8792-35909a88743c')
@testtools.skipUnless(CONF.compute_feature_enabled.shelve,
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index b5e5da8..79b809f 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -47,16 +47,6 @@
def _add_keypair(self):
self.keypair = self.create_keypair()
- def _write_timestamp(self, server_or_ip):
- ssh_client = self.get_remote_client(server_or_ip)
- ssh_client.exec_command('date > /tmp/timestamp; sync')
- self.timestamp = ssh_client.exec_command('cat /tmp/timestamp')
-
- def _check_timestamp(self, server_or_ip):
- ssh_client = self.get_remote_client(server_or_ip)
- got_timestamp = ssh_client.exec_command('cat /tmp/timestamp')
- self.assertEqual(self.timestamp, got_timestamp)
-
@test.idempotent_id('608e604b-1d63-4a82-8e3e-91bc665c90b4')
@testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
'Snapshotting is not available.')
@@ -70,9 +60,9 @@
server = self._boot_image(CONF.compute.image_ref)
if CONF.compute.use_floatingip_for_ssh:
fip_for_server = self.create_floating_ip(server)
- self._write_timestamp(fip_for_server['ip'])
+ timestamp = self.create_timestamp(fip_for_server['ip'])
else:
- self._write_timestamp(server)
+ timestamp = self.create_timestamp(server)
# snapshot the instance
snapshot_image = self.create_server_snapshot(server=server)
@@ -83,6 +73,7 @@
# check the existence of the timestamp file in the second instance
if CONF.compute.use_floatingip_for_ssh:
fip_for_snapshot = self.create_floating_ip(server_from_snapshot)
- self._check_timestamp(fip_for_snapshot['ip'])
+ timestamp2 = self.get_timestamp(fip_for_snapshot['ip'])
else:
- self._check_timestamp(server_from_snapshot)
+ timestamp2 = self.get_timestamp(server_from_snapshot)
+ self.assertEqual(timestamp, timestamp2)
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 91e4657..a4f9896 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -74,9 +74,6 @@
def _add_keypair(self):
self.keypair = self.create_keypair()
- def _ssh_to_server(self, server_or_ip):
- return self.get_remote_client(server_or_ip)
-
def _create_volume_snapshot(self, volume):
snapshot_name = data_utils.rand_name('scenario-snapshot')
_, snapshot = self.snapshots_client.create_snapshot(
@@ -127,23 +124,6 @@
CONF.compute.build_interval):
raise exceptions.TimeoutException
- def _create_timestamp(self, server_or_ip):
- ssh_client = self._ssh_to_server(server_or_ip)
- ssh_client.exec_command('sudo /usr/sbin/mkfs.ext4 /dev/%s'
- % CONF.compute.volume_device_name)
- ssh_client.exec_command('sudo mount /dev/%s /mnt'
- % CONF.compute.volume_device_name)
- ssh_client.exec_command('sudo sh -c "date > /mnt/timestamp;sync"')
- self.timestamp = ssh_client.exec_command('sudo cat /mnt/timestamp')
- ssh_client.exec_command('sudo umount /mnt')
-
- def _check_timestamp(self, server_or_ip):
- ssh_client = self._ssh_to_server(server_or_ip)
- ssh_client.exec_command('sudo mount /dev/%s /mnt'
- % CONF.compute.volume_device_name)
- got_timestamp = ssh_client.exec_command('sudo cat /mnt/timestamp')
- self.assertEqual(self.timestamp, got_timestamp)
-
@decorators.skip_because(bug="1205344")
@test.idempotent_id('10fd234a-515c-41e5-b092-8323060598c5')
@testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
@@ -167,7 +147,8 @@
self._attach_volume(server, volume)
self._wait_for_volume_available_on_the_system(ip_for_server)
- self._create_timestamp(ip_for_server)
+ timestamp = self.create_timestamp(ip_for_server,
+ CONF.compute.volume_device_name)
self._detach_volume(server, volume)
# snapshot the volume
@@ -196,4 +177,6 @@
self._wait_for_volume_available_on_the_system(ip_for_snapshot)
# check the existence of the timestamp file in the volume2
- self._check_timestamp(ip_for_snapshot)
+ timestamp2 = self.get_timestamp(ip_for_snapshot,
+ CONF.compute.volume_device_name)
+ self.assertEqual(timestamp, timestamp2)
diff --git a/tempest/services/compute/json/snapshots_extensions_client.py b/tempest/services/compute/json/snapshots_client.py
similarity index 97%
rename from tempest/services/compute/json/snapshots_extensions_client.py
rename to tempest/services/compute/json/snapshots_client.py
index 6902a39..e3f92db 100644
--- a/tempest/services/compute/json/snapshots_extensions_client.py
+++ b/tempest/services/compute/json/snapshots_client.py
@@ -21,7 +21,7 @@
from tempest.common import service_client
-class SnapshotsExtensionsClient(service_client.ServiceClient):
+class SnapshotsClient(service_client.ServiceClient):
def create_snapshot(self, volume_id, **kwargs):
post_body = {
diff --git a/tempest/services/identity/v2/json/identity_client.py b/tempest/services/identity/v2/json/identity_client.py
index cf4c546..f37bc08 100644
--- a/tempest/services/identity/v2/json/identity_client.py
+++ b/tempest/services/identity/v2/json/identity_client.py
@@ -327,7 +327,8 @@
patch_body = json.dumps({'user': patch_body})
resp, body = self.patch('OS-KSCRUD/users/%s' % user_id, patch_body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def list_extensions(self):
"""List all the extensions."""
@@ -360,4 +361,5 @@
resp, body = self.get('/users/%s/credentials/OS-EC2/%s' %
(user_id, access))
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index a345d56..10bd23e 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -34,28 +34,6 @@
quotas
"""
- def create_network(self, **kwargs):
- uri = '/networks'
- post_data = {'network': kwargs}
- return self.create_resource(uri, post_data)
-
- def update_network(self, network_id, **kwargs):
- uri = '/networks/%s' % network_id
- post_data = {'network': kwargs}
- return self.update_resource(uri, post_data)
-
- def show_network(self, network_id, **fields):
- uri = '/networks/%s' % network_id
- return self.show_resource(uri, **fields)
-
- def delete_network(self, network_id):
- uri = '/networks/%s' % network_id
- return self.delete_resource(uri)
-
- def list_networks(self, **filters):
- uri = '/networks'
- return self.list_resources(uri, **filters)
-
def create_subnet(self, **kwargs):
uri = '/subnets'
post_data = {'subnet': kwargs}
diff --git a/tempest/services/network/json/networks_client.py b/tempest/services/network/json/networks_client.py
new file mode 100644
index 0000000..2907d44
--- /dev/null
+++ b/tempest/services/network/json/networks_client.py
@@ -0,0 +1,38 @@
+# 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.services.network.json import base
+
+
+class NetworksClient(base.BaseNetworkClient):
+
+ def create_network(self, **kwargs):
+ uri = '/networks'
+ post_data = {'network': kwargs}
+ return self.create_resource(uri, post_data)
+
+ def update_network(self, network_id, **kwargs):
+ uri = '/networks/%s' % network_id
+ post_data = {'network': kwargs}
+ return self.update_resource(uri, post_data)
+
+ def show_network(self, network_id, **fields):
+ uri = '/networks/%s' % network_id
+ return self.show_resource(uri, **fields)
+
+ def delete_network(self, network_id):
+ uri = '/networks/%s' % network_id
+ return self.delete_resource(uri)
+
+ def list_networks(self, **filters):
+ uri = '/networks'
+ return self.list_resources(uri, **filters)
diff --git a/tempest/services/network/resources.py b/tempest/services/network/resources.py
index 4d45515..23d936e 100644
--- a/tempest/services/network/resources.py
+++ b/tempest/services/network/resources.py
@@ -41,6 +41,7 @@
def __init__(self, *args, **kwargs):
self.client = kwargs.pop('client', None)
+ self.networks_client = kwargs.pop('networks_client', None)
super(DeletableResource, self).__init__(*args, **kwargs)
def __str__(self):
@@ -72,7 +73,7 @@
class DeletableNetwork(DeletableResource):
def delete(self):
- self.client.delete_network(self.id)
+ self.networks_client.delete_network(self.id)
class DeletableSubnet(DeletableResource):
diff --git a/tempest/tests/common/test_admin_available.py b/tempest/tests/common/test_admin_available.py
index 5c69c5e..9f47ccc 100644
--- a/tempest/tests/common/test_admin_available.py
+++ b/tempest/tests/common/test_admin_available.py
@@ -64,9 +64,9 @@
else:
(u, t, p) = (None, None, None)
- cfg.CONF.set_default('admin_username', u, group='identity')
- cfg.CONF.set_default('admin_tenant_name', t, group='identity')
- cfg.CONF.set_default('admin_password', p, group='identity')
+ cfg.CONF.set_default('admin_username', u, group='auth')
+ cfg.CONF.set_default('admin_tenant_name', t, group='auth')
+ cfg.CONF.set_default('admin_password', p, group='auth')
expected = admin_creds is not None or tenant_isolation
observed = credentials.is_admin_available()
diff --git a/tempest/tests/common/test_cred_provider.py b/tempest/tests/common/test_cred_provider.py
index 1bc7147..d404660 100644
--- a/tempest/tests/common/test_cred_provider.py
+++ b/tempest/tests/common/test_cred_provider.py
@@ -123,5 +123,9 @@
cfg.CONF.set_default('auth_version', 'v3', group='identity')
# Identity group items
for prefix in ['', 'alt_', 'admin_']:
+ if prefix == 'admin_':
+ group = 'auth'
+ else:
+ group = 'identity'
cfg.CONF.set_default(prefix + 'domain_name', 'fake_domain_name',
- group='identity')
+ group=group)
diff --git a/tempest/tests/fake_config.py b/tempest/tests/fake_config.py
index 4898c9c..ca8bc3e 100644
--- a/tempest/tests/fake_config.py
+++ b/tempest/tests/fake_config.py
@@ -48,9 +48,13 @@
for config_option in ['username', 'password', 'tenant_name']:
# Identity group items
for prefix in ['', 'alt_', 'admin_']:
+ if prefix == 'admin_':
+ group = 'auth'
+ else:
+ group = 'identity'
self.conf.set_default(prefix + config_option,
'fake_' + config_option,
- group='identity')
+ group=group)
class FakePrivate(config.TempestConfigPrivate):
diff --git a/tempest/tests/services/compute/test_hosts_client.py b/tempest/tests/services/compute/test_hosts_client.py
new file mode 100644
index 0000000..2b7fdb5
--- /dev/null
+++ b/tempest/tests/services/compute/test_hosts_client.py
@@ -0,0 +1,147 @@
+# Copyright 2015 NEC Corporation. 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.services.compute.json import hosts_client
+from tempest.tests import fake_auth_provider
+from tempest.tests.services.compute import base
+
+
+class TestHostsClient(base.BaseComputeServiceTest):
+ FAKE_HOST_DATA = {
+ "host": {
+ "resource": {
+ "cpu": 1,
+ "disk_gb": 1028,
+ "host": "c1a7de0ac9d94e4baceae031d05caae3",
+ "memory_mb": 8192,
+ "project": "(total)"
+ }
+ },
+ "hosts": {
+ "host_name": "c1a7de0ac9d94e4baceae031d05caae3",
+ "service": "conductor",
+ "zone": "internal"
+ },
+ "enable_hosts": {
+ "host": "65c5d5b7e3bd44308e67fc50f362aee6",
+ "maintenance_mode": "off_maintenance",
+ "status": "enabled"
+ }
+ }
+
+ FAKE_CONTROL_DATA = {
+ "shutdown": {
+ "host": "c1a7de0ac9d94e4baceae031d05caae3",
+ "power_action": "shutdown"
+ },
+ "startup": {
+ "host": "c1a7de0ac9d94e4baceae031d05caae3",
+ "power_action": "startup"
+ },
+ "reboot": {
+ "host": "c1a7de0ac9d94e4baceae031d05caae3",
+ "power_action": "reboot"
+ }}
+
+ HOST_DATA = {'host': [FAKE_HOST_DATA['host']]}
+ HOSTS_DATA = {'hosts': [FAKE_HOST_DATA['hosts']]}
+ ENABLE_HOST_DATA = FAKE_HOST_DATA['enable_hosts']
+ HOST_ID = "c1a7de0ac9d94e4baceae031d05caae3"
+ TEST_HOST_DATA = {
+ "status": "enable",
+ "maintenance_mode": "disable"
+ }
+
+ def setUp(self):
+ super(TestHostsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = hosts_client.HostsClient(fake_auth, 'compute',
+ 'regionOne')
+ self.params = {'hostname': self.HOST_ID}
+ self.func2mock = {
+ 'get': 'tempest.common.service_client.ServiceClient.get',
+ 'put': 'tempest.common.service_client.ServiceClient.put'}
+
+ def _test_host_data(self, test_type='list', bytes_body=False):
+ expected_resp = self.HOST_DATA
+ if test_type != 'list':
+ function_call = self.client.show_host
+ else:
+ expected_resp = self.HOSTS_DATA
+ function_call = self.client.list_hosts
+ self.params = {'host_name': self.HOST_ID}
+
+ self.check_service_client_function(
+ function_call, self.func2mock['get'],
+ expected_resp, bytes_body,
+ 200, **self.params)
+
+ def _test_update_hosts(self, bytes_body=False):
+ expected_resp = self.ENABLE_HOST_DATA
+ self.check_service_client_function(
+ self.client.update_host, self.func2mock['put'],
+ expected_resp, bytes_body,
+ 200, **self.params)
+
+ def _test_control_host(self, control_op='reboot', bytes_body=False):
+ if control_op == 'start':
+ expected_resp = self.FAKE_CONTROL_DATA['startup']
+ function_call = self.client.startup_host
+ elif control_op == 'stop':
+ expected_resp = self.FAKE_CONTROL_DATA['shutdown']
+ function_call = self.client.shutdown_host
+ else:
+ expected_resp = self.FAKE_CONTROL_DATA['reboot']
+ function_call = self.client.reboot_host
+
+ self.check_service_client_function(
+ function_call, self.func2mock['get'],
+ expected_resp, bytes_body,
+ 200, **self.params)
+
+ def test_show_host_with_str_body(self):
+ self._test_host_data('show')
+
+ def test_show_host_with_bytes_body(self):
+ self._test_host_data('show', True)
+
+ def test_list_host_with_str_body(self):
+ self._test_host_data()
+
+ def test_list_host_with_bytes_body(self):
+ self._test_host_data(bytes_body=True)
+
+ def test_start_host_with_str_body(self):
+ self._test_control_host('start')
+
+ def test_start_host_with_bytes_body(self):
+ self._test_control_host('start', True)
+
+ def test_stop_host_with_str_body(self):
+ self._test_control_host('stop')
+
+ def test_stop_host_with_bytes_body(self):
+ self._test_control_host('stop', True)
+
+ def test_reboot_host_with_str_body(self):
+ self._test_control_host('reboot')
+
+ def test_reboot_host_with_bytes_body(self):
+ self._test_control_host('reboot', True)
+
+ def test_update_host_with_str_body(self):
+ self._test_update_hosts()
+
+ def test_update_host_with_bytes_body(self):
+ self._test_update_hosts(True)
diff --git a/tempest/tests/services/compute/test_interfaces_client.py b/tempest/tests/services/compute/test_interfaces_client.py
new file mode 100644
index 0000000..235585a
--- /dev/null
+++ b/tempest/tests/services/compute/test_interfaces_client.py
@@ -0,0 +1,98 @@
+# Copyright 2015 NEC Corporation. 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.services.compute.json import interfaces_client
+from tempest.tests import fake_auth_provider
+from tempest.tests.services.compute import base
+
+
+class TestInterfacesClient(base.BaseComputeServiceTest):
+ # Data Values to be used for testing #
+ FAKE_INTERFACE_DATA = {
+ "fixed_ips": [{
+ "ip_address": "192.168.1.1",
+ "subnet_id": "f8a6e8f8-c2ec-497c-9f23-da9616de54ef"
+ }],
+ "mac_addr": "fa:16:3e:4c:2c:30",
+ "net_id": "3cb9bc59-5699-4588-a4b1-b87f96708bc6",
+ "port_id": "ce531f90-199f-48c0-816c-13e38010b442",
+ "port_state": "ACTIVE"}
+
+ FAKE_SHOW_DATA = {
+ "interfaceAttachment": FAKE_INTERFACE_DATA}
+ FAKE_LIST_DATA = {
+ "interfaceAttachments": [FAKE_INTERFACE_DATA]}
+
+ FAKE_SERVER_ID = "ec14c864-096e-4e27-bb8a-2c2b4dc6f3f5"
+ FAKE_PORT_ID = FAKE_SHOW_DATA['interfaceAttachment']['port_id']
+ func2mock = {
+ 'delete': 'tempest.common.service_client.ServiceClient.delete',
+ 'get': 'tempest.common.service_client.ServiceClient.get',
+ 'post': 'tempest.common.service_client.ServiceClient.post'}
+
+ def setUp(self):
+ super(TestInterfacesClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = interfaces_client.InterfacesClient(fake_auth,
+ "compute",
+ "regionOne")
+
+ def _test_interface_operation(self, operation="create", bytes_body=False):
+ response_code = 200
+ expected_op = self.FAKE_SHOW_DATA
+ mock_operation = self.func2mock['get']
+ params = {'server_id': self.FAKE_SERVER_ID,
+ 'port_id': self.FAKE_PORT_ID}
+ if operation == 'list':
+ expected_op = self.FAKE_LIST_DATA
+ function = self.client.list_interfaces
+ params = {'server_id': self.FAKE_SERVER_ID}
+ elif operation == 'show':
+ function = self.client.show_interface
+ elif operation == 'delete':
+ expected_op = {}
+ mock_operation = self.func2mock['delete']
+ function = self.client.delete_interface
+ response_code = 202
+ else:
+ function = self.client.create_interface
+ mock_operation = self.func2mock['post']
+
+ self.check_service_client_function(
+ function, mock_operation, expected_op,
+ bytes_body, response_code, **params)
+
+ def test_list_interfaces_with_str_body(self):
+ self._test_interface_operation('list')
+
+ def test_list_interfaces_with_bytes_body(self):
+ self._test_interface_operation('list', True)
+
+ def test_show_interface_with_str_body(self):
+ self._test_interface_operation('show')
+
+ def test_show_interface_with_bytes_body(self):
+ self._test_interface_operation('show', True)
+
+ def test_delete_interface_with_str_body(self):
+ self._test_interface_operation('delete')
+
+ def test_delete_interface_with_bytes_body(self):
+ self._test_interface_operation('delete', True)
+
+ def test_create_interface_with_str_body(self):
+ self._test_interface_operation()
+
+ def test_create_interface_with_bytes_body(self):
+ self._test_interface_operation(bytes_body=True)
diff --git a/tempest/tests/services/compute/test_servers_client.py b/tempest/tests/services/compute/test_servers_client.py
new file mode 100644
index 0000000..5813318
--- /dev/null
+++ b/tempest/tests/services/compute/test_servers_client.py
@@ -0,0 +1,133 @@
+# Copyright 2015 IBM Corp.
+#
+# 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.services.compute.json import servers_client
+from tempest.tests import fake_auth_provider
+from tempest.tests.services.compute import base
+
+
+class TestServersClient(base.BaseComputeServiceTest):
+
+ FAKE_SERVERS = {'servers': [{
+ "id": "616fb98f-46ca-475e-917e-2563e5a8cd19",
+ "links": [
+ {
+ "href": "http://os.co/v2/616fb98f-46ca-475e-917e-2563e5a8cd19",
+ "rel": "self"
+ },
+ {
+ "href": "http://os.co/616fb98f-46ca-475e-917e-2563e5a8cd19",
+ "rel": "bookmark"
+ }
+ ],
+ "name": u"new\u1234-server-test"}]
+ }
+
+ FAKE_SERVER_GET = {'server': {
+ "accessIPv4": "",
+ "accessIPv6": "",
+ "addresses": {
+ "private": [
+ {
+ "addr": "192.168.0.3",
+ "version": 4
+ }
+ ]
+ },
+ "created": "2012-08-20T21:11:09Z",
+ "flavor": {
+ "id": "1",
+ "links": [
+ {
+ "href": "http://os.com/openstack/flavors/1",
+ "rel": "bookmark"
+ }
+ ]
+ },
+ "hostId": "65201c14a29663e06d0748e561207d998b343e1d164bfa0aafa9c45d",
+ "id": "893c7791-f1df-4c3d-8383-3caae9656c62",
+ "image": {
+ "id": "70a599e0-31e7-49b7-b260-868f441e862b",
+ "links": [
+ {
+ "href": "http://imgs/70a599e0-31e7-49b7-b260-868f441e862b",
+ "rel": "bookmark"
+ }
+ ]
+ },
+ "links": [
+ {
+ "href": "http://v2/srvs/893c7791-f1df-4c3d-8383-3caae9656c62",
+ "rel": "self"
+ },
+ {
+ "href": "http://srvs/893c7791-f1df-4c3d-8383-3caae9656c62",
+ "rel": "bookmark"
+ }
+ ],
+ "metadata": {
+ u"My Server Nu\1234me": u"Apau\1234che1"
+ },
+ "name": u"new\u1234-server-test",
+ "progress": 0,
+ "status": "ACTIVE",
+ "tenant_id": "openstack",
+ "updated": "2012-08-20T21:11:09Z",
+ "user_id": "fake"}
+ }
+
+ server_id = FAKE_SERVER_GET['server']['id']
+
+ def setUp(self):
+ super(TestServersClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = servers_client.ServersClient(
+ fake_auth, 'compute', 'regionOne')
+
+ def test_list_servers_with_str_body(self):
+ self._test_list_servers()
+
+ def test_list_servers_with_bytes_body(self):
+ self._test_list_servers(bytes_body=True)
+
+ def _test_list_servers(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_servers,
+ 'tempest.common.service_client.ServiceClient.get',
+ self.FAKE_SERVERS,
+ bytes_body)
+
+ def test_show_server_with_str_body(self):
+ self._test_show_server()
+
+ def test_show_server_with_bytes_body(self):
+ self._test_show_server(bytes_body=True)
+
+ def _test_show_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_server,
+ 'tempest.common.service_client.ServiceClient.get',
+ self.FAKE_SERVER_GET,
+ bytes_body,
+ server_id=self.server_id
+ )
+
+ def test_delete_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.delete_server,
+ 'tempest.common.service_client.ServiceClient.delete',
+ {},
+ status=204,
+ server_id=self.server_id
+ )
diff --git a/tempest/tests/test_tenant_isolation.py b/tempest/tests/test_tenant_isolation.py
index cc4de2d..5aba2c7 100644
--- a/tempest/tests/test_tenant_isolation.py
+++ b/tempest/tests/test_tenant_isolation.py
@@ -120,7 +120,7 @@
def _mock_network_create(self, iso_creds, id, name):
net_fix = self.useFixture(mockpatch.PatchObject(
- iso_creds.network_admin_client,
+ iso_creds.networks_admin_client,
'create_network',
return_value={'network': {'id': id, 'name': name}}))
return net_fix
@@ -268,7 +268,7 @@
self._mock_list_role()
self._mock_user_create('1234', 'fake_prim_user')
self._mock_tenant_create('1234', 'fake_prim_tenant')
- net = mock.patch.object(iso_creds.network_admin_client,
+ net = mock.patch.object(iso_creds.networks_admin_client,
'delete_network')
net_mock = net.start()
subnet = mock.patch.object(iso_creds.network_admin_client,
@@ -361,7 +361,7 @@
'IdentityClient.delete_user')
self.patch('tempest.services.identity.v2.json.identity_client.'
'IdentityClient.delete_tenant')
- net = mock.patch.object(iso_creds.network_admin_client,
+ net = mock.patch.object(iso_creds.networks_admin_client,
'delete_network')
net_mock = net.start()
subnet = mock.patch.object(iso_creds.network_admin_client,
@@ -494,7 +494,7 @@
self._mock_list_role()
self._mock_user_create('1234', 'fake_prim_user')
self._mock_tenant_create('1234', 'fake_prim_tenant')
- net = mock.patch.object(iso_creds.network_admin_client,
+ net = mock.patch.object(iso_creds.networks_admin_client,
'delete_network')
net_mock = net.start()
subnet = mock.patch.object(iso_creds.network_admin_client,