Merge "Fix interfaces response schema"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 2a35aff..80d52a4 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -422,6 +422,11 @@
# Does the test environment have the ec2 api running? (boolean value)
#ec2_api = true
+# Does Nova preserve preexisting ports from Neutron when deleting an
+# instance? This should be set to True if testing Kilo+ Nova. (boolean
+# value)
+#preserve_ports = false
+
[dashboard]
diff --git a/tempest/api/compute/admin/test_security_groups.py b/tempest/api/compute/admin/test_security_groups.py
index 578f73b..6d79a77 100644
--- a/tempest/api/compute/admin/test_security_groups.py
+++ b/tempest/api/compute/admin/test_security_groups.py
@@ -39,7 +39,7 @@
@test.idempotent_id('49667619-5af9-4c63-ab5d-2cfdd1c8f7f1')
@testtools.skipIf(CONF.service_available.neutron,
- "Skipped because neutron do not support all_tenants"
+ "Skipped because neutron does not support all_tenants "
"search filter.")
@test.attr(type='smoke')
@test.services('network')
diff --git a/tempest/config.py b/tempest/config.py
index 119de0e..12620de 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -351,7 +351,13 @@
'images of running instances?'),
cfg.BoolOpt('ec2_api',
default=True,
- help='Does the test environment have the ec2 api running?')
+ help='Does the test environment have the ec2 api running?'),
+ # TODO(mriedem): Remove preserve_ports once juno-eol happens.
+ cfg.BoolOpt('preserve_ports',
+ default=False,
+ help='Does Nova preserve preexisting ports from Neutron '
+ 'when deleting an instance? This should be set to True '
+ 'if testing Kilo+ Nova.')
]
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 81e771c..f8cc17c 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -14,7 +14,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import os
import subprocess
import netaddr
@@ -24,7 +23,6 @@
from tempest_lib import exceptions as lib_exc
from tempest import clients
-from tempest.common import cred_provider
from tempest.common import credentials
from tempest.common.utils.linux import remote_client
from tempest import config
@@ -50,7 +48,6 @@
cls.manager = clients.Manager(
credentials=cls.credentials()
)
- cls.admin_manager = clients.Manager(cls.admin_credentials())
@classmethod
def setup_clients(cls):
@@ -63,7 +60,6 @@
# Compute image client
cls.images_client = cls.manager.images_client
cls.keypairs_client = cls.manager.keypairs_client
- cls.networks_client = cls.admin_manager.networks_client
# Nova security groups client
cls.security_groups_client = cls.manager.security_groups_client
cls.servers_client = cls.manager.servers_client
@@ -542,6 +538,14 @@
super(NetworkScenarioTest, cls).skip_checks()
if not CONF.service_available.neutron:
raise cls.skipException('Neutron not available')
+ if not credentials.is_admin_available():
+ msg = ("Missing Identity Admin API credentials in configuration.")
+ raise cls.skipException(msg)
+
+ @classmethod
+ def setup_credentials(cls):
+ super(NetworkScenarioTest, cls).setup_credentials()
+ cls.admin_manager = clients.Manager(cls.admin_credentials())
@classmethod
def resource_setup(cls):
@@ -1283,9 +1287,17 @@
"""
@classmethod
+ def skip_checks(cls):
+ super(EncryptionScenarioTest, cls).skip_checks()
+ if not credentials.is_admin_available():
+ msg = ("Missing Identity Admin API credentials in configuration.")
+ raise cls.skipException(msg)
+
+ @classmethod
def setup_clients(cls):
super(EncryptionScenarioTest, cls).setup_clients()
- cls.admin_volume_types_client = cls.admin_manager.volume_types_client
+ admin_manager = clients.Manager(cls.admin_credentials())
+ cls.admin_volume_types_client = admin_manager.volume_types_client
def _wait_for_volume_status(self, status):
self.status_timeout(
@@ -1324,49 +1336,6 @@
control_location=control_location)
-class OrchestrationScenarioTest(ScenarioTest):
- """
- Base class for orchestration scenario tests
- """
-
- @classmethod
- def skip_checks(cls):
- super(OrchestrationScenarioTest, cls).skip_checks()
- if not CONF.service_available.heat:
- raise cls.skipException("Heat support is required")
-
- @classmethod
- def credentials(cls):
- admin_creds = cred_provider.get_configured_credentials(
- 'identity_admin')
- creds = cred_provider.get_configured_credentials('user')
- admin_creds.tenant_name = creds.tenant_name
- return admin_creds
-
- def _load_template(self, base_file, file_name):
- filepath = os.path.join(os.path.dirname(os.path.realpath(base_file)),
- file_name)
- with open(filepath) as f:
- return f.read()
-
- @classmethod
- def _stack_rand_name(cls):
- return data_utils.rand_name(cls.__name__ + '-')
-
- @classmethod
- def _get_default_network(cls):
- networks = cls.networks_client.list_networks()
- for net in networks:
- if net['label'] == CONF.compute.fixed_network_name:
- return net
-
- @staticmethod
- def _stack_output(stack, output_key):
- """Return a stack output value for a given key."""
- return next((o['output_value'] for o in stack['outputs']
- if o['output_key'] == output_key), None)
-
-
class SwiftScenarioTest(ScenarioTest):
"""
Provide harness to do Swift scenario tests.
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index bb668f7..3d6abff 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -15,7 +15,6 @@
from oslo_log import log as logging
from tempest_lib.common.utils import data_utils
-from tempest_lib import decorators
import testtools
from tempest import config
@@ -94,8 +93,8 @@
self.servers_client.wait_for_server_status(self.server['id'], 'ACTIVE')
self._check_network_connectivity()
- @decorators.skip_because(bug="1323658")
@test.idempotent_id('61f1aa9a-1573-410e-9054-afa557cab021')
+ @test.stresstest(class_setup_per='process')
@test.services('compute', 'network')
def test_server_connectivity_stop_start(self):
self._setup_network_and_servers()
@@ -147,7 +146,6 @@
self.servers_client.resume_server(self.server['id'])
self._wait_server_status_and_check_network_connectivity()
- @decorators.skip_because(bug="1323658")
@test.idempotent_id('719eb59d-2f42-4b66-b8b1-bb1254473967')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
'Resize is not available.')
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index af7b683..bb19853 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -101,13 +101,19 @@
self.servers = []
def _setup_network_and_servers(self, **kwargs):
+ boot_with_port = kwargs.pop('boot_with_port', False)
self.security_group = \
self._create_security_group(tenant_id=self.tenant_id)
self.network, self.subnet, self.router = self.create_networks(**kwargs)
self.check_networks()
+ self.port_id = None
+ if boot_with_port:
+ # create a port on the network and boot with that
+ self.port_id = self._create_port(self.network['id']).id
+
name = data_utils.rand_name('server-smoke')
- server = self._create_server(name, self.network)
+ server = self._create_server(name, self.network, self.port_id)
self._check_tenant_network_connectivity()
floating_ip = self.create_floating_ip(server)
@@ -141,7 +147,7 @@
self.assertIn(self.router.id,
seen_router_ids)
- def _create_server(self, name, network):
+ def _create_server(self, name, network, port_id=None):
keypair = self.create_keypair()
self.keypairs[keypair['name']] = keypair
security_groups = [{'name': self.security_group['name']}]
@@ -152,6 +158,8 @@
'key_name': keypair['name'],
'security_groups': security_groups,
}
+ if port_id is not None:
+ create_kwargs['networks'][0]['port'] = port_id
server = self.create_server(name=name, create_kwargs=create_kwargs)
self.servers.append(server)
return server
@@ -605,3 +613,39 @@
self.check_public_network_connectivity(
should_connect=True, msg="after updating "
"admin_state_up of instance port to True")
+
+ @test.idempotent_id('759462e1-8535-46b0-ab3a-33aa45c55aaa')
+ @testtools.skipUnless(CONF.compute_feature_enabled.preserve_ports,
+ 'Preserving ports on instance delete may not be '
+ 'supported in the version of Nova being tested.')
+ @test.attr(type='smoke')
+ @test.services('compute', 'network')
+ def test_preserve_preexisting_port(self):
+ """Tests that a pre-existing port provided on server boot is not
+ deleted if the server is deleted.
+
+ Nova should unbind the port from the instance on delete if the port was
+ not created by Nova as part of the boot request.
+ """
+ # Setup the network, create a port and boot the server from that port.
+ self._setup_network_and_servers(boot_with_port=True)
+ _, server = self.floating_ip_tuple
+ self.assertIsNotNone(self.port_id,
+ 'Server should have been created from a '
+ 'pre-existing port.')
+ # Assert the port is bound to the server.
+ port_list = self._list_ports(device_id=server['id'],
+ network_id=self.network['id'])
+ self.assertEqual(1, len(port_list),
+ 'There should only be one port created for '
+ 'server %s.' % server['id'])
+ self.assertEqual(self.port_id, port_list[0]['id'])
+ # Delete the server.
+ self.servers_client.delete_server(server['id'])
+ self.servers_client.wait_for_server_termination(server['id'])
+ # Assert the port still exists on the network but is unbound from
+ # the deleted server.
+ port = self.network_client.show_port(self.port_id)['port']
+ self.assertEqual(self.network['id'], port['network_id'])
+ self.assertEqual('', port['device_id'])
+ self.assertEqual('', port['device_owner'])
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index d095b53..e84d627 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -132,7 +132,14 @@
computes = _get_compute_nodes(controller, ssh_user, ssh_key)
for node in computes:
do_ssh("rm -f %s" % logfiles, node, ssh_user, ssh_key)
+ skip = False
for test in tests:
+ for service in test.get('required_services', []):
+ if not CONF.service_available.get(service):
+ skip = True
+ break
+ if skip:
+ break
if test.get('use_admin', False):
manager = admin_manager
else:
diff --git a/tempest/stress/etc/stress-tox-job.json b/tempest/stress/etc/stress-tox-job.json
index dffc469..9cee316 100644
--- a/tempest/stress/etc/stress-tox-job.json
+++ b/tempest/stress/etc/stress-tox-job.json
@@ -15,5 +15,14 @@
"use_admin": false,
"use_isolated_tenants": false,
"kwargs": {}
+ },
+ {"action": "tempest.stress.actions.unit_test.UnitTest",
+ "threads": 4,
+ "use_admin": false,
+ "use_isolated_tenants": false,
+ "required_services": ["neutron"],
+ "kwargs": {"test_method": "tempest.scenario.test_network_advanced_server_ops.TestNetworkAdvancedServerOps.test_server_connectivity_stop_start",
+ "class_setup_per": "process"}
}
]
+