Merge "Add live migration with trunk test"
This commit is contained in:
commit
b125d0124d
|
@ -23,6 +23,8 @@ from tempest.common import compute
|
|||
from tempest.common import utils
|
||||
from tempest.common import waiters
|
||||
from tempest import config
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib.common.utils import test_utils
|
||||
from tempest.lib import decorators
|
||||
|
||||
CONF = config.CONF
|
||||
|
@ -55,6 +57,10 @@ class LiveMigrationTestBase(base.BaseV2ComputeAdminTest):
|
|||
def setup_clients(cls):
|
||||
super(LiveMigrationTestBase, cls).setup_clients()
|
||||
cls.admin_migration_client = cls.os_admin.migrations_client
|
||||
cls.networks_client = cls.os_primary.networks_client
|
||||
cls.subnets_client = cls.os_primary.subnets_client
|
||||
cls.ports_client = cls.os_primary.ports_client
|
||||
cls.trunks_client = cls.os_primary.trunks_client
|
||||
|
||||
def _migrate_server_to(self, server_id, dest_host, volume_backed=False):
|
||||
kwargs = dict()
|
||||
|
@ -197,6 +203,86 @@ class LiveMigrationTest(LiveMigrationTestBase):
|
|||
|
||||
self.assertEqual(volume_id1, volume_id2)
|
||||
|
||||
def _create_net_subnet(self, name, cidr):
|
||||
net_name = data_utils.rand_name(name=name)
|
||||
net = self.networks_client.create_network(name=net_name)['network']
|
||||
self.addClassResourceCleanup(
|
||||
self.networks_client.delete_network, net['id'])
|
||||
|
||||
subnet = self.subnets_client.create_subnet(
|
||||
network_id=net['id'],
|
||||
cidr=cidr,
|
||||
ip_version=4)
|
||||
self.addClassResourceCleanup(self.subnets_client.delete_subnet,
|
||||
subnet['subnet']['id'])
|
||||
return net
|
||||
|
||||
def _create_port(self, network_id, name):
|
||||
name = data_utils.rand_name(name=name)
|
||||
port = self.ports_client.create_port(name=name,
|
||||
network_id=network_id)['port']
|
||||
self.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc,
|
||||
self.ports_client.delete_port,
|
||||
port_id=port['id'])
|
||||
return port
|
||||
|
||||
def _create_trunk_with_subport(self):
|
||||
tenant_network = self.get_tenant_network()
|
||||
parent = self._create_port(network_id=tenant_network['id'],
|
||||
name='parent')
|
||||
net = self._create_net_subnet(name='subport_net', cidr='19.80.0.0/24')
|
||||
subport = self._create_port(network_id=net['id'], name='subport')
|
||||
|
||||
trunk = self.trunks_client.create_trunk(
|
||||
name=data_utils.rand_name('trunk'),
|
||||
port_id=parent['id'],
|
||||
sub_ports=[{"segmentation_id": 42, "port_id": subport['id'],
|
||||
"segmentation_type": "vlan"}]
|
||||
)['trunk']
|
||||
self.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc,
|
||||
self.trunks_client.delete_trunk,
|
||||
trunk['id'])
|
||||
return trunk, parent, subport
|
||||
|
||||
def _is_port_status_active(self, port_id):
|
||||
port = self.ports_client.show_port(port_id)['port']
|
||||
return port['status'] == 'ACTIVE'
|
||||
|
||||
@decorators.idempotent_id('0022c12e-a482-42b0-be2d-396b5f0cffe3')
|
||||
@utils.requires_ext(service='network', extension='trunk')
|
||||
@utils.services('network')
|
||||
def test_live_migration_with_trunk(self):
|
||||
"""Test live migration with trunk and subport"""
|
||||
trunk, parent, subport = self._create_trunk_with_subport()
|
||||
|
||||
server = self.create_test_server(
|
||||
wait_until="ACTIVE", networks=[{'port': parent['id']}])
|
||||
|
||||
# Wait till subport status is ACTIVE
|
||||
self.assertTrue(
|
||||
test_utils.call_until_true(
|
||||
self._is_port_status_active, CONF.validation.connect_timeout,
|
||||
5, subport['id']))
|
||||
parent = self.ports_client.show_port(parent['id'])['port']
|
||||
self.assertEqual('ACTIVE', parent['status'])
|
||||
subport = self.ports_client.show_port(subport['id'])['port']
|
||||
|
||||
if not CONF.compute_feature_enabled.can_migrate_between_any_hosts:
|
||||
# not to specify a host so that the scheduler will pick one
|
||||
target_host = None
|
||||
else:
|
||||
target_host = self.get_host_other_than(server['id'])
|
||||
|
||||
self._live_migrate(server['id'], target_host, 'ACTIVE')
|
||||
|
||||
# Wait till subport status is ACTIVE
|
||||
self.assertTrue(
|
||||
test_utils.call_until_true(
|
||||
self._is_port_status_active, CONF.validation.connect_timeout,
|
||||
5, subport['id']))
|
||||
parent = self.ports_client.show_port(parent['id'])['port']
|
||||
self.assertEqual('ACTIVE', parent['status'])
|
||||
|
||||
|
||||
class LiveMigrationRemoteConsolesV26Test(LiveMigrationTestBase):
|
||||
min_microversion = '2.6'
|
||||
|
|
|
@ -72,6 +72,7 @@ class Manager(clients.ServiceClients):
|
|||
self.qos_client = self.network.QosClient()
|
||||
self.qos_min_bw_client = self.network.QosMinimumBandwidthRulesClient()
|
||||
self.segments_client = self.network.SegmentsClient()
|
||||
self.trunks_client = self.network.TrunksClient()
|
||||
|
||||
def _set_image_clients(self):
|
||||
if CONF.service_available.glance:
|
||||
|
|
|
@ -36,6 +36,7 @@ from tempest.lib.services.network.service_providers_client import \
|
|||
from tempest.lib.services.network.subnetpools_client import SubnetpoolsClient
|
||||
from tempest.lib.services.network.subnets_client import SubnetsClient
|
||||
from tempest.lib.services.network.tags_client import TagsClient
|
||||
from tempest.lib.services.network.trunks_client import TrunksClient
|
||||
from tempest.lib.services.network.versions_client import NetworkVersionsClient
|
||||
|
||||
__all__ = ['AgentsClient', 'ExtensionsClient', 'FloatingIPsClient',
|
||||
|
@ -44,4 +45,4 @@ __all__ = ['AgentsClient', 'ExtensionsClient', 'FloatingIPsClient',
|
|||
'QosClient', 'QosMinimumBandwidthRulesClient', 'QuotasClient',
|
||||
'RoutersClient', 'SecurityGroupRulesClient', 'SecurityGroupsClient',
|
||||
'SegmentsClient', 'ServiceProvidersClient', 'SubnetpoolsClient',
|
||||
'SubnetsClient', 'TagsClient']
|
||||
'SubnetsClient', 'TagsClient', 'TrunksClient']
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
# 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.lib.services.network import base
|
||||
|
||||
|
||||
class TrunksClient(base.BaseNetworkClient):
|
||||
|
||||
def create_trunk(self, **kwargs):
|
||||
"""Creates a trunk.
|
||||
|
||||
For a full list of available parameters, please refer to the official
|
||||
API reference:
|
||||
https://docs.openstack.org/api-ref/network/v2/index.html#create-trunk
|
||||
"""
|
||||
uri = '/trunks'
|
||||
post_data = {'trunk': kwargs}
|
||||
return self.create_resource(uri, post_data)
|
||||
|
||||
def update_trunk(self, trunk_id, **kwargs):
|
||||
"""Updates a trunk.
|
||||
|
||||
For a full list of available parameters, please refer to the official
|
||||
API reference:
|
||||
https://docs.openstack.org/api-ref/network/v2/index.html#update-trunk
|
||||
"""
|
||||
uri = '/trunks/%s' % trunk_id
|
||||
put_data = {'trunk': kwargs}
|
||||
return self.update_resource(uri, put_data)
|
||||
|
||||
def show_trunk(self, trunk_id):
|
||||
"""Shows details for a trunk.
|
||||
|
||||
For a full list of available parameters, please refer to the official
|
||||
API reference:
|
||||
https://docs.openstack.org/api-ref/network/v2/index.html#show-trunk
|
||||
"""
|
||||
uri = '/trunks/%s' % trunk_id
|
||||
return self.show_resource(uri)
|
||||
|
||||
def delete_trunk(self, trunk_id):
|
||||
"""Deletes a trunk.
|
||||
|
||||
For a full list of available parameters, please refer to the official
|
||||
API reference:
|
||||
https://docs.openstack.org/api-ref/network/v2/index.html#delete-trunk
|
||||
"""
|
||||
uri = '/trunks/%s' % trunk_id
|
||||
return self.delete_resource(uri)
|
||||
|
||||
def list_trunks(self, **filters):
|
||||
"""Lists trunks to which the tenant has access.
|
||||
|
||||
For a full list of available parameters, please refer to the official
|
||||
API reference:
|
||||
https://docs.openstack.org/api-ref/network/v2/index.html#list-trunks
|
||||
"""
|
||||
uri = '/trunks'
|
||||
return self.list_resources(uri, **filters)
|
||||
|
||||
def add_subports_to_trunk(self, trunk_id, sub_ports):
|
||||
"""Add subports to a trunk.
|
||||
|
||||
For a full list of available parameters, please refer to the official
|
||||
API reference:
|
||||
https://docs.openstack.org/api-ref/network/v2/index.html#add-subports-to-trunk
|
||||
"""
|
||||
uri = '/trunks/%s/add_subports' % trunk_id
|
||||
put_data = {'sub_ports': sub_ports}
|
||||
return self.update_resource(uri, put_data)
|
||||
|
||||
def delete_subports_from_trunk(self, trunk_id, sub_ports):
|
||||
"""Deletes subports from a trunk.
|
||||
|
||||
For a full list of available parameters, please refer to the official
|
||||
API reference:
|
||||
https://docs.openstack.org/api-ref/network/v2/index.html#delete-subports-from-trunk
|
||||
"""
|
||||
uri = '/trunks/%s/remove_subports' % trunk_id
|
||||
put_data = {'sub_ports': sub_ports}
|
||||
return self.update_resource(uri, put_data)
|
||||
|
||||
def list_subports_of_trunk(self, trunk_id):
|
||||
"""List subports of a trunk.
|
||||
|
||||
For a full list of available parameters, please refer to the official
|
||||
API reference:
|
||||
https://docs.openstack.org/api-ref/network/v2/index.html#list-subports-for-trunk
|
||||
"""
|
||||
uri = '/trunks/%s/get_subports' % trunk_id
|
||||
return self.list_resources(uri)
|
|
@ -0,0 +1,201 @@
|
|||
# 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.
|
||||
|
||||
import copy
|
||||
|
||||
from tempest.lib.services.network import trunks_client
|
||||
from tempest.tests.lib import fake_auth_provider
|
||||
from tempest.tests.lib.services import base
|
||||
|
||||
|
||||
class TestTrunksClient(base.BaseServiceTest):
|
||||
|
||||
FAKE_TRUNK_ID = "dfbc2103-93cf-4edf-952a-ef6deb32ddc6"
|
||||
FAKE_PORT_ID = "1f04eb36-6c84-11eb-b0ab-4fc62961629d"
|
||||
FAKE_TRUNKS = {
|
||||
"trunks": [
|
||||
{
|
||||
"admin_state_up": True,
|
||||
"description": "",
|
||||
"id": "dfbc2103-93cf-4edf-952a-ef6deb32ddc6",
|
||||
"name": "trunk0",
|
||||
"port_id": "00130aab-bb51-42a1-a7c4-6703a3a43aa5",
|
||||
"project_id": "",
|
||||
"revision_number": 2,
|
||||
"status": "DOWN",
|
||||
"sub_ports": [
|
||||
{
|
||||
"port_id": "87d2483d-e5e6-483d-b5f0-81b9ed1d1a91",
|
||||
"segmentation_id": 101,
|
||||
"segmentation_type": "vlan"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
},
|
||||
{
|
||||
"admin_state_up": True,
|
||||
"description": "",
|
||||
"id": "9eb0e72e-11d3-4295-bcaf-6c89008d9f0a",
|
||||
"name": "trunk1",
|
||||
"port_id": "035a12bf-2ae3-42ae-8ad6-9f70640cddde",
|
||||
"project_id": "",
|
||||
"revision_number": 2,
|
||||
"status": "DOWN",
|
||||
"sub_ports": [
|
||||
{
|
||||
"port_id": "cba839d5-02e2-4e09-b964-81356da78165",
|
||||
"segmentation_id": 102,
|
||||
"segmentation_type": "vlan"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
FAKE_TRUNK_1 = {
|
||||
"name": "trunk0",
|
||||
"port_id": "00130aab-bb51-42a1-a7c4-6703a3a43aa5"
|
||||
}
|
||||
|
||||
def setUp(self):
|
||||
super(TestTrunksClient, self).setUp()
|
||||
fake_auth = fake_auth_provider.FakeAuthProvider()
|
||||
self.trunks_client = trunks_client.TrunksClient(
|
||||
fake_auth, "network", "regionOne")
|
||||
|
||||
def _test_create_trunk(self, bytes_body=False):
|
||||
self.check_service_client_function(
|
||||
self.trunks_client.create_trunk,
|
||||
"tempest.lib.common.rest_client.RestClient.post",
|
||||
{"trunk": self.FAKE_TRUNKS["trunks"][0]},
|
||||
bytes_body,
|
||||
201,
|
||||
**self.FAKE_TRUNK_1)
|
||||
|
||||
def _test_list_trunks(self, bytes_body=False):
|
||||
self.check_service_client_function(
|
||||
self.trunks_client.list_trunks,
|
||||
"tempest.lib.common.rest_client.RestClient.get",
|
||||
self.FAKE_TRUNKS,
|
||||
bytes_body,
|
||||
200)
|
||||
|
||||
def _test_show_trunk(self, bytes_body=False):
|
||||
self.check_service_client_function(
|
||||
self.trunks_client.show_trunk,
|
||||
"tempest.lib.common.rest_client.RestClient.get",
|
||||
{"trunk": self.FAKE_TRUNKS["trunks"][0]},
|
||||
bytes_body,
|
||||
200,
|
||||
trunk_id=self.FAKE_TRUNK_ID)
|
||||
|
||||
def _test_update_trunk(self, bytes_body=False):
|
||||
update_kwargs = {
|
||||
"admin_state_up": True,
|
||||
"name": "new_trunk"
|
||||
}
|
||||
|
||||
resp_body = {
|
||||
"trunk": copy.deepcopy(
|
||||
self.FAKE_TRUNKS["trunks"][0]
|
||||
)
|
||||
}
|
||||
resp_body["trunk"].update(update_kwargs)
|
||||
|
||||
self.check_service_client_function(
|
||||
self.trunks_client.update_trunk,
|
||||
"tempest.lib.common.rest_client.RestClient.put",
|
||||
resp_body,
|
||||
bytes_body,
|
||||
200,
|
||||
trunk_id=self.FAKE_TRUNK_ID,
|
||||
**update_kwargs)
|
||||
|
||||
def _test_add_subports_to_trunk(self, bytes_body=False):
|
||||
sub_ports = [{
|
||||
"port_id": "f04eb36-6c84-11eb-b0ab-4fc62961629d",
|
||||
"segmentation_type": "vlan",
|
||||
"segmentation_id": "1001"
|
||||
}]
|
||||
resp_body = copy.deepcopy(self.FAKE_TRUNKS["trunks"][0])
|
||||
|
||||
resp_body["sub_ports"].append(sub_ports)
|
||||
self.check_service_client_function(
|
||||
self.trunks_client.add_subports_to_trunk,
|
||||
"tempest.lib.common.rest_client.RestClient.put",
|
||||
resp_body,
|
||||
bytes_body,
|
||||
200,
|
||||
trunk_id=self.FAKE_TRUNK_ID,
|
||||
sub_ports=sub_ports)
|
||||
|
||||
def _test_delete_subports_from_trunk(self, bytes_body=False):
|
||||
fake_sub_ports = self.FAKE_TRUNKS['trunks'][0]['sub_ports']
|
||||
sub_ports = [
|
||||
{"port_id": fake_sub_ports[0]['port_id']}
|
||||
]
|
||||
resp_body = copy.deepcopy(self.FAKE_TRUNKS["trunks"][0])
|
||||
|
||||
resp_body['sub_ports'] = []
|
||||
self.check_service_client_function(
|
||||
self.trunks_client.delete_subports_from_trunk,
|
||||
"tempest.lib.common.rest_client.RestClient.put",
|
||||
resp_body,
|
||||
bytes_body,
|
||||
200,
|
||||
trunk_id=self.FAKE_TRUNK_ID,
|
||||
sub_ports=sub_ports)
|
||||
|
||||
def test_create_trunk_with_str_body(self):
|
||||
self._test_create_trunk()
|
||||
|
||||
def test_create_trunk_with_bytes_body(self):
|
||||
self._test_create_trunk(bytes_body=True)
|
||||
|
||||
def test_list_trunks_with_str_body(self):
|
||||
self._test_list_trunks()
|
||||
|
||||
def test_list_trunks_with_bytes_body(self):
|
||||
self._test_list_trunks(bytes_body=True)
|
||||
|
||||
def test_show_trunk_with_str_body(self):
|
||||
self._test_show_trunk()
|
||||
|
||||
def test_show_trunk_with_bytes_body(self):
|
||||
self._test_show_trunk(bytes_body=True)
|
||||
|
||||
def test_update_trunk_with_str_body(self):
|
||||
self._test_update_trunk()
|
||||
|
||||
def test_update_trunk_with_bytes_body(self):
|
||||
self._test_update_trunk(bytes_body=True)
|
||||
|
||||
def test_add_subports_to_trunk_str_body(self):
|
||||
self._test_add_subports_to_trunk()
|
||||
|
||||
def test_add_subports_to_trunk_bytes_body(self):
|
||||
self._test_add_subports_to_trunk(bytes_body=True)
|
||||
|
||||
def test_delete_subports_from_trunk_str_body(self):
|
||||
self._test_delete_subports_from_trunk()
|
||||
|
||||
def test_delete_subports_from_trunk_bytes_body(self):
|
||||
self._test_delete_subports_from_trunk(bytes_body=True)
|
||||
|
||||
def test_delete_trunk(self):
|
||||
self.check_service_client_function(
|
||||
self.trunks_client.delete_trunk,
|
||||
"tempest.lib.common.rest_client.RestClient.delete",
|
||||
{},
|
||||
status=204,
|
||||
trunk_id=self.FAKE_TRUNK_ID)
|
|
@ -302,6 +302,7 @@
|
|||
devstack_services:
|
||||
neutron-placement: true
|
||||
neutron-qos: true
|
||||
neutron-trunk: true
|
||||
group-vars:
|
||||
subnode:
|
||||
devstack_localrc:
|
||||
|
|
Loading…
Reference in New Issue