Merge "Add a test for attach/detach port on multiple servers"
This commit is contained in:
commit
964f3be3c1
@ -16,7 +16,9 @@
|
||||
import time
|
||||
|
||||
from tempest.api.compute import base
|
||||
from tempest.common import compute
|
||||
from tempest.common.utils import net_utils
|
||||
from tempest.common import waiters
|
||||
from tempest import config
|
||||
from tempest import exceptions
|
||||
from tempest.lib import exceptions as lib_exc
|
||||
@ -48,6 +50,7 @@ class AttachInterfacesTestJSON(base.BaseV2ComputeTest):
|
||||
cls.networks_client = cls.os.networks_client
|
||||
cls.subnets_client = cls.os.subnets_client
|
||||
cls.ports_client = cls.os.ports_client
|
||||
cls.servers_client = cls.servers_client
|
||||
|
||||
def wait_for_interface_status(self, server, port_id, status):
|
||||
"""Waits for an interface to reach a given status."""
|
||||
@ -73,6 +76,34 @@ class AttachInterfacesTestJSON(base.BaseV2ComputeTest):
|
||||
|
||||
return body
|
||||
|
||||
# TODO(mriedem): move this into a common waiters utility module
|
||||
def wait_for_port_detach(self, port_id):
|
||||
"""Waits for the port's device_id to be unset.
|
||||
|
||||
:param port_id: The id of the port being detached.
|
||||
:returns: The final port dict from the show_port response.
|
||||
"""
|
||||
port = self.ports_client.show_port(port_id)['port']
|
||||
device_id = port['device_id']
|
||||
start = int(time.time())
|
||||
|
||||
# NOTE(mriedem): Nova updates the port's device_id to '' rather than
|
||||
# None, but it's not contractual so handle Falsey either way.
|
||||
while device_id:
|
||||
time.sleep(self.build_interval)
|
||||
port = self.ports_client.show_port(port_id)['port']
|
||||
device_id = port['device_id']
|
||||
|
||||
timed_out = int(time.time()) - start >= self.build_timeout
|
||||
|
||||
if device_id and timed_out:
|
||||
message = ('Port %s failed to detach (device_id %s) within '
|
||||
'the required time (%s s).' %
|
||||
(port_id, device_id, self.build_timeout))
|
||||
raise exceptions.TimeoutException(message)
|
||||
|
||||
return port
|
||||
|
||||
def _check_interface(self, iface, port_id=None, network_id=None,
|
||||
fixed_ip=None, mac_addr=None):
|
||||
self.assertIn('port_state', iface)
|
||||
@ -240,3 +271,40 @@ class AttachInterfacesTestJSON(base.BaseV2ComputeTest):
|
||||
if fixed_ip is not None:
|
||||
break
|
||||
self.servers_client.remove_fixed_ip(server['id'], address=fixed_ip)
|
||||
|
||||
@test.idempotent_id('2f3a0127-95c7-4977-92d2-bc5aec602fb4')
|
||||
def test_reassign_port_between_servers(self):
|
||||
"""Tests the following:
|
||||
|
||||
1. Create a port in Neutron.
|
||||
2. Create two servers in Nova.
|
||||
3. Attach the port to the first server.
|
||||
4. Detach the port from the first server.
|
||||
5. Attach the port to the second server.
|
||||
6. Detach the port from the second server.
|
||||
"""
|
||||
network = self.get_tenant_network()
|
||||
network_id = network['id']
|
||||
port = self.ports_client.create_port(network_id=network_id)
|
||||
port_id = port['port']['id']
|
||||
self.addCleanup(self.ports_client.delete_port, port_id)
|
||||
|
||||
# create two servers
|
||||
_, servers = compute.create_test_server(
|
||||
self.os, tenant_network=network, wait_until='ACTIVE', min_count=2)
|
||||
# add our cleanups for the servers since we bypassed the base class
|
||||
for server in servers:
|
||||
self.addCleanup(waiters.wait_for_server_termination,
|
||||
self.servers_client, server['id'])
|
||||
self.addCleanup(self.servers_client.delete_server, server['id'])
|
||||
|
||||
for server in servers:
|
||||
# attach the port to the server
|
||||
iface = self.client.create_interface(
|
||||
server['id'], port_id=port_id)['interfaceAttachment']
|
||||
self._check_interface(iface, port_id=port_id)
|
||||
|
||||
# detach the port from the server; this is a cast in the compute
|
||||
# API so we have to poll the port until the device_id is unset.
|
||||
self.client.delete_interface(server['id'], port_id)
|
||||
self.wait_for_port_detach(port_id)
|
||||
|
@ -642,6 +642,8 @@ class TestNetworkBasicOps(manager.NetworkScenarioTest):
|
||||
|
||||
Nova should unbind the port from the instance on delete if the port was
|
||||
not created by Nova as part of the boot request.
|
||||
|
||||
We should also be able to boot another server with the same port.
|
||||
"""
|
||||
# Setup the network, create a port and boot the server from that port.
|
||||
self._setup_network_and_servers(boot_with_port=True)
|
||||
@ -670,6 +672,17 @@ class TestNetworkBasicOps(manager.NetworkScenarioTest):
|
||||
self.assertEqual('', port['device_id'])
|
||||
self.assertEqual('', port['device_owner'])
|
||||
|
||||
# Boot another server with the same port to make sure nothing was
|
||||
# left around that could cause issues.
|
||||
name = data_utils.rand_name('reuse-port')
|
||||
server = self._create_server(name, self.network, port['id'])
|
||||
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(port['id'], port_list[0]['id'])
|
||||
|
||||
@test.requires_ext(service='network', extension='l3_agent_scheduler')
|
||||
@test.idempotent_id('2e788c46-fb3f-4ac9-8f82-0561555bea73')
|
||||
@test.services('compute', 'network')
|
||||
|
Loading…
Reference in New Issue
Block a user