diff --git a/oswin_tempest_plugin/tests/_mixins/optional_feature.py b/oswin_tempest_plugin/tests/_mixins/optional_feature.py new file mode 100644 index 0000000..045a6f5 --- /dev/null +++ b/oswin_tempest_plugin/tests/_mixins/optional_feature.py @@ -0,0 +1,90 @@ +# Copyright 2017 Cloudbase Solutions SRL +# 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. + +import testtools + +from oswin_tempest_plugin import config +from oswin_tempest_plugin.tests._mixins import resize + +CONF = config.CONF + + +class _OptionalFeatureMixin(resize._ResizeUtils): + """Optional Feature mixin. + + Some features are optional, and can be turned on / off through resize + with certain flavors. + Examples of optional features: vNUMA, QoS, SR-IOV, PCI passthrough, + RemoteFX. + + This mixin will add the following tests: + * test_feature + * test_resize_add_feature + * test_resize_remove_feature + + The resize tests will create a new instance, resize it to a new flavor ( + turning on / off the optional feature), and check its network + connectivity. + + The optional feature flavor is based on the configured compute.flavor_ref, + with some updates. For example, if the vNUMA configuration is to be tested, + the new flavor would contain the flavor extra_spec {'hw:numa_nodes="1"'}. + Keep in mind that all the extra_spec keys and values have to be strings. + """ + + # NOTE(claudiub): This flavor dict contains updates to the base flavor + # tempest is configured with. For example, _FEATURE_FLAVOR can be: + # _BIGGER_FLAVOR = {'extra_specs': {'hw:numa_nodes': 1'}} + # which means a flavor having that flavor extra_spec will be created, and + # a created instance will be resize to / from it. + + _FEATURE_FLAVOR = {} + + def _get_flavor_ref(self): + """Gets a new optional feature flavor ref. + + Creates a new flavor based on the configured flavor_ref, with some + updates specific to the optional feature. + + :returns: nova flavor ID. + """ + # NOTE(claudiub): Unless explicitly given another flavor, + # _create_server will call this method to get the flavor reference + # needed to spawn a new instance. Thus, any other test will spawn + # instances with this Optional Feature. + new_flavor = self._create_new_flavor(CONF.compute.flavor_ref, + self._FEATURE_FLAVOR) + return new_flavor['id'] + + def test_feature(self): + server_tuple = self._create_server() + self._check_server_connectivity(server_tuple) + + @testtools.skipUnless(CONF.compute_feature_enabled.resize, + 'Resize is not available.') + def test_resize_add_feature(self): + new_flavor = self._create_new_flavor(CONF.compute.flavor_ref, + self._FEATURE_FLAVOR) + server_tuple = self._create_server(CONF.compute.flavor_ref) + self._resize_server(server_tuple, new_flavor) + self._check_server_connectivity(server_tuple) + + @testtools.skipUnless(CONF.compute_feature_enabled.resize, + 'Resize is not available.') + def test_resize_remove_feature(self): + vanilla_flavor = CONF.compute.flavor_ref + server_tuple = self._create_server() + self._resize_server(server_tuple, vanilla_flavor) + self._check_server_connectivity(server_tuple) diff --git a/oswin_tempest_plugin/tests/scenario/test_vnuma.py b/oswin_tempest_plugin/tests/scenario/test_vnuma.py new file mode 100644 index 0000000..3fa1977 --- /dev/null +++ b/oswin_tempest_plugin/tests/scenario/test_vnuma.py @@ -0,0 +1,36 @@ +# Copyright 2017 Cloudbase Solutions SRL +# 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 oswin_tempest_plugin.tests import test_base +from oswin_tempest_plugin.tests._mixins import migrate +from oswin_tempest_plugin.tests._mixins import optional_feature +from oswin_tempest_plugin.tests._mixins import resize + + +class HyperVvNumaTestCase(test_base.TestBase, + migrate._MigrateMixin, + optional_feature._OptionalFeatureMixin, + resize._ResizeMixin): + """Hyper-V vNUMA test suite. + + This test suite will spawn instances requiring NUMA placement. + """ + + _FEATURE_FLAVOR = {'extra_specs': {'hw:numa_nodes': '1'}} + _BIGGER_FLAVOR = {'ram': 128, 'extra_specs': {'hw:numa_nodes': '1'}} + + # NOTE(claudiub): Hyper-V does not support asymmetric NUMA topologies. + _FEATURE_FLAVOR = {'ram': '128', 'extra_specs': { + 'hw:numa_nodes': '2', 'hw:numa_mem.0': '128'}} diff --git a/oswin_tempest_plugin/tests/test_base.py b/oswin_tempest_plugin/tests/test_base.py index 0160c30..24c58af 100644 --- a/oswin_tempest_plugin/tests/test_base.py +++ b/oswin_tempest_plugin/tests/test_base.py @@ -132,12 +132,19 @@ class TestBase(tempest.test.BaseTestCase): )['flavor'] self.addCleanup(self._flavor_cleanup, new_flavor['id']) + + # Add flavor extra_specs, if needed. + extra_specs = flavor_updates.get('extra_specs') + if extra_specs: + self.admin_flavors_client.set_flavor_extra_spec( + new_flavor['id'], **extra_specs) + return new_flavor def _get_flavor_ref(self): return CONF.compute.flavor_ref - def _create_server(self): + def _create_server(self, flavor=None): """Wrapper utility that returns a test server. This wrapper utility calls the common create test server and @@ -146,7 +153,7 @@ class TestBase(tempest.test.BaseTestCase): clients = self.os_primary name = data_utils.rand_name(self.__class__.__name__ + "-server") image_id = self._get_image_ref() - flavor = self._get_flavor_ref() + flavor = flavor or self._get_flavor_ref() keypair = self.create_keypair() tenant_network = self.get_tenant_network() security_group = self._create_security_group()