diff --git a/tox.ini b/tox.ini index 9aa6047c..e4152688 100644 --- a/tox.ini +++ b/tox.ini @@ -21,6 +21,7 @@ commands = flake8 {posargs} [flake8] +ignore = H405 enable-extensions = H106,H203,H904 show-source = True exclude = .git,.venv,.tox,dist,doc,*egg diff --git a/whitebox_tempest_plugin/common/__init__.py b/whitebox_tempest_plugin/common/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/whitebox_tempest_plugin/common/utils.py b/whitebox_tempest_plugin/common/utils.py new file mode 100644 index 00000000..717574e7 --- /dev/null +++ b/whitebox_tempest_plugin/common/utils.py @@ -0,0 +1,57 @@ +# Copyright 2017 Red Hat +# 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 oslo_log import log as logging +from tempest import config + + +CONF = config.CONF +LOG = logging.getLogger(__name__) + + +def _get_hv_ip_from_conf(id): + conf_hvs = CONF.whitebox.hypervisors + if conf_hvs: + return conf_hvs.get(id) + + +def get_hypervisor_ip(client, hostname): + """Finds the IP address of a compute node based on its hostname. This is + necessary in case a compute node isn't accessible by its IP address as it + appears in the nova API. Such a situation arises in infrared deployments of + OSP12, for example. + + :param client: The hypervisors client to use. + :param hostname: The compute node's hostname, from the instance's + OS-EXT-SRV-ATTR:host attribute. + :return: The IP address of the compute node - either as configuired in the + hypervisors section of our config file, or as returned by the nova + API as fallback. + """ + hvs = client.list_hypervisors(detail=True)['hypervisors'] + compute_node_address = None + for hv in hvs: + if hv['service']['host'] == hostname: + hv_ip = _get_hv_ip_from_conf(str(hv['id'])) + if hv_ip: + compute_node_address = hv_ip + LOG.info('Using %s for hypervisor %s ' + 'from config file', (hv_ip, hv['id'])) + else: + compute_node_address = hv['host_ip'] + LOG.info('Using %s as fallback since hypervisor %s not ' + 'in config file', (compute_node_address, + hv['id'])) + return compute_node_address diff --git a/whitebox_tempest_plugin/config.py b/whitebox_tempest_plugin/config.py index 0f57cd95..763c46e0 100644 --- a/whitebox_tempest_plugin/config.py +++ b/whitebox_tempest_plugin/config.py @@ -37,4 +37,11 @@ opts = [ 'containers', default=False, help='Deployment is containerized.'), + cfg.DictOpt( + 'hypervisors', + help="Dictionary of hypervisor IP addresses, in the " + "id => IP format. Should be used when the IP returned " + "by 'nova hypervisor-show' isn't reachable from the " + "node running tempest. Starting with microversion " + "2.53, the id is a UUID."), ] diff --git a/whitebox_tempest_plugin/tests/unit/base.py b/whitebox_tempest_plugin/tests/unit/base.py index 2911d501..051d5c1b 100644 --- a/whitebox_tempest_plugin/tests/unit/base.py +++ b/whitebox_tempest_plugin/tests/unit/base.py @@ -13,7 +13,15 @@ # under the License. from oslotest import base +from tempest import config + +CONF = config.CONF class WhiteboxPluginTestCase(base.BaseTestCase): - pass + + def flags(self, **kw): + """Override flag variables for a test.""" + group = kw.pop('group', None) + for k, v in kw.items(): + CONF.set_override(k, v, group) diff --git a/whitebox_tempest_plugin/tests/unit/test_placeholder.py b/whitebox_tempest_plugin/tests/unit/test_placeholder.py deleted file mode 100644 index 63f0df75..00000000 --- a/whitebox_tempest_plugin/tests/unit/test_placeholder.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright 2018 Red Hat -# -# 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 whitebox_tempest_plugin.tests.unit import base - - -class PlaceholderTestCase(base.WhiteboxPluginTestCase): - # TODO(artom) Remove this class when we add actual unit tests. This class - # is only necessary to to avoid stestr complaining about not finding any - # tests. - - def test_placeholder(self): - pass diff --git a/whitebox_tempest_plugin/tests/unit/test_utils.py b/whitebox_tempest_plugin/tests/unit/test_utils.py new file mode 100644 index 00000000..550adc27 --- /dev/null +++ b/whitebox_tempest_plugin/tests/unit/test_utils.py @@ -0,0 +1,53 @@ +# Copyright 2018 Red Hat +# +# 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 mock + +from whitebox_tempest_plugin.common import utils +from whitebox_tempest_plugin.tests.unit import base + + +class UtilsTestCase(base.WhiteboxPluginTestCase): + + def setUp(self): + super(UtilsTestCase, self).setUp() + self.client = mock.Mock() + fake_hvs = { + 'hypervisors': [ + {'service': {'host': 'host1'}, + 'host_ip': '192.168.0.1', + 'id': 1}, + {'service': {'host': 'host2'}, + 'host_ip': '192.168.0.2', + 'id': 2}, + {'service': {'host': 'host3'}, + 'host_ip': '192.168.0.3', + 'id': 3} + ] + } + self.client.list_hypervisors = mock.Mock(return_value=fake_hvs) + + def test_get_hypervisor_ip_hv_in_config(self): + self.flags(hypervisors={'1': '10.0.0.1'}, group='whitebox') + self.assertEqual('10.0.0.1', + utils.get_hypervisor_ip(self.client, 'host1')) + + def test_get_hypervisor_ip_hv_not_in_config(self): + self.flags(hypervisors={'1': '10.0.0.1'}, group='whitebox') + self.assertEqual('192.168.0.2', + utils.get_hypervisor_ip(self.client, 'host2')) + + def test_get_hypervisor_ip_no_hvs_in_config(self): + self.assertEqual('192.168.0.3', + utils.get_hypervisor_ip(self.client, 'host3'))