Add "os_cloud_config" as a new context flag parameter 63/59163/4
authorRodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com>
Thu, 26 Apr 2018 14:24:44 +0000 (15:24 +0100)
committerEmma Foley <emma.l.foley@intel.com>
Thu, 28 Jun 2018 08:20:25 +0000 (08:20 +0000)
This new parameter will contain the OpenStack cloud specific configuration
used by Shade client. This new flag is used only in Heat context.

By default, this new parameter (dict) will contain this content:
  'os_cloud_config': {'verify': False}

This field will be used by HeatStack [1] to create a Shade cloud. Shade
retrieves, if not defined, the OpenStack configuration from
"os_client_config". This configuration is used to generate the cloud
configuration, which is the description of the OpenStackCloud returned.

The default parameter defined, "verify", refers to the related bug. By
default, in case of using SSL certificate it will not be verified.

[1] https://github.com/opnfv/yardstick/blob/b338d3091bb0beb89d4ad9f7c144f43a31a19a74/yardstick/orchestrator/heat.py#L47

JIRA: YARDSTICK-1139

Change-Id: I875a7018401b84e51dab775b8194174645d27e06
Signed-off-by: Rodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com>
(cherry picked from commit 9ae331e1aa1081c3e821512d1940846dfb4063ec)

yardstick/benchmark/contexts/base.py
yardstick/benchmark/contexts/heat.py
yardstick/common/constants.py
yardstick/common/openstack_utils.py
yardstick/orchestrator/heat.py
yardstick/tests/unit/benchmark/contexts/test_base.py
yardstick/tests/unit/benchmark/contexts/test_heat.py
yardstick/tests/unit/common/test_openstack_utils.py
yardstick/tests/unit/orchestrator/test_heat.py

index 0707c1c..64cee83 100644 (file)
@@ -6,17 +6,20 @@
 # which accompanies this distribution, and is available at
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
+
 import abc
 import six
 
-import yardstick.common.utils as utils
+from yardstick.common import constants
+from yardstick.common import utils
 
 
 class Flags(object):
     """Class to represent the status of the flags in a context"""
 
     _FLAGS = {'no_setup': False,
-              'no_teardown': False}
+              'no_teardown': False,
+              'os_cloud_config': constants.OS_CLOUD_DEFAULT_CONFIG}
 
     def __init__(self, **kwargs):
         for name, value in self._FLAGS.items():
index 3d8907b..cc87176 100644 (file)
@@ -325,8 +325,10 @@ class HeatContext(Context):
         if not os.path.exists(self.key_filename):
             SSH.gen_keys(self.key_filename)
 
-        heat_template = HeatTemplate(self.name, self.template_file,
-                                     self.heat_parameters)
+        heat_template = HeatTemplate(
+            self.name, template_file=self.template_file,
+            heat_parameters=self.heat_parameters,
+            os_cloud_config=self._flags.os_cloud_config)
 
         if self.template_file is None:
             self._add_resources_to_template(heat_template)
index 3f5c374..f6e4ab7 100644 (file)
@@ -167,3 +167,6 @@ IS_PUBLIC = 'is_public'
 # general
 TESTCASE_PRE = 'opnfv_yardstick_'
 TESTSUITE_PRE = 'opnfv_'
+
+# OpenStack cloud default config parameters
+OS_CLOUD_DEFAULT_CONFIG = {'verify': False}
index 6664047..6ff6617 100644 (file)
@@ -7,18 +7,20 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 
-import os
+import copy
 import logging
+import os
 
+from cinderclient import client as cinderclient
+from novaclient import client as novaclient
+from glanceclient import client as glanceclient
 from keystoneauth1 import loading
 from keystoneauth1 import session
+from neutronclient.neutron import client as neutronclient
 import shade
 from shade import exc
 
-from cinderclient import client as cinderclient
-from novaclient import client as novaclient
-from glanceclient import client as glanceclient
-from neutronclient.neutron import client as neutronclient
+from yardstick.common import constants
 
 
 log = logging.getLogger(__name__)
@@ -154,8 +156,21 @@ def get_glance_client():    # pragma: no cover
     return glanceclient.Client(get_glance_client_version(), session=sess)
 
 
-def get_shade_client():
-    return shade.openstack_cloud()
+def get_shade_client(**os_cloud_config):
+    """Get Shade OpenStack cloud client
+
+    By default, the input parameters given to "shade.openstack_cloud" method
+    are stored in "constants.OS_CLOUD_DEFAULT_CONFIG". The input parameters
+    passed in this function, "os_cloud_config", will overwrite the default
+    ones.
+
+    :param os_cloud_config: (kwargs) input arguments for
+                            "shade.openstack_cloud" method.
+    :return: ``shade.OpenStackCloud`` object.
+    """
+    params = copy.deepcopy(constants.OS_CLOUD_DEFAULT_CONFIG)
+    params.update(os_cloud_config)
+    return shade.openstack_cloud(**params)
 
 
 # *********************************************
index 5afa415..bfc1f70 100644 (file)
@@ -22,13 +22,13 @@ import time
 
 from oslo_serialization import jsonutils
 from oslo_utils import encodeutils
-import shade
 from shade._heat import event_utils
 
-import yardstick.common.openstack_utils as op_utils
+from yardstick.common import constants as consts
 from yardstick.common import exceptions
 from yardstick.common import template_format
-from yardstick.common import constants as consts
+from yardstick.common import openstack_utils as op_utils
+
 
 log = logging.getLogger(__name__)
 
@@ -41,10 +41,11 @@ _DEPLOYED_STACKS = {}
 class HeatStack(object):
     """Represents a Heat stack (deployed template) """
 
-    def __init__(self, name):
+    def __init__(self, name, os_cloud_config=None):
         self.name = name
         self.outputs = {}
-        self._cloud = shade.openstack_cloud()
+        os_cloud_config = {} if not os_cloud_config else os_cloud_config
+        self._cloud = op_utils.get_shade_client(**os_cloud_config)
         self._stack = None
 
     def _update_stack_tracking(self):
@@ -152,10 +153,12 @@ name (i.e. %s).
         # short hand for resources part of template
         self.resources = self._template['resources']
 
-    def __init__(self, name, template_file=None, heat_parameters=None):
+    def __init__(self, name, template_file=None, heat_parameters=None,
+                 os_cloud_config=None):
         self.name = name
         self.keystone_client = None
         self.heat_parameters = {}
+        self._os_cloud_config = {} if not os_cloud_config else os_cloud_config
 
         # heat_parameters is passed to heat in stack create, empty dict when
         # yardstick creates the template (no get_param in resources part)
@@ -229,7 +232,11 @@ name (i.e. %s).
 
         name = "%s-%s" % (server_name, volume_name)
 
+        # TODO(elfoley): Fix this on master, it is a bug, and exposes untested
+        # code.  Yardstick will crash when heat context uses volume.
+        # pylint: disable=no-value-for-parameter
         volume_id = op_utils.get_volume_id(volume_name)
+        # pylint: enable=no-value-for-parameter
         if not volume_id:
             volume_id = {'get_resource': volume_name}
         self.resources[name] = {
@@ -622,7 +629,7 @@ name (i.e. %s).
         log.info("Creating stack '%s' START", self.name)
 
         start_time = time.time()
-        stack = HeatStack(self.name)
+        stack = HeatStack(self.name, os_cloud_config=self._os_cloud_config)
         stack.create(self._template, self.heat_parameters, block, timeout)
 
         if not block:
index 1311317..81267cf 100644 (file)
@@ -39,6 +39,7 @@ class FlagsTestCase(ut_base.BaseUnitTestCase):
     def test___init__(self):
         self.assertFalse(self.flags.no_setup)
         self.assertFalse(self.flags.no_teardown)
+        self.assertEqual({'verify': False}, self.flags.os_cloud_config)
 
     def test___init__with_flags(self):
         flags = base.Flags(no_setup=True)
@@ -46,10 +47,12 @@ class FlagsTestCase(ut_base.BaseUnitTestCase):
         self.assertFalse(flags.no_teardown)
 
     def test_parse(self):
-        self.flags.parse(no_setup=True, no_teardown="False")
+        self.flags.parse(no_setup=True, no_teardown='False',
+                         os_cloud_config={'verify': True})
 
         self.assertTrue(self.flags.no_setup)
-        self.assertEqual(self.flags.no_teardown, "False")
+        self.assertEqual('False', self.flags.no_teardown)
+        self.assertEqual({'verify': True}, self.flags.os_cloud_config)
 
     def test_parse_forbidden_flags(self):
         self.flags.parse(foo=42)
index 749f731..bcc3590 100644 (file)
@@ -230,7 +230,7 @@ class HeatContextTestCase(ut_base.BaseUnitTestCase):
 
     @mock.patch.object(os.path, 'exists', return_value=False)
     @mock.patch.object(ssh.SSH, 'gen_keys')
-    @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
+    @mock.patch.object(heat, 'HeatTemplate')
     def test_deploy(self, mock_template, mock_genkeys, mock_path_exists):
         self.test_context._name = 'foo'
         self.test_context._task_id = '1234567890'
@@ -241,9 +241,10 @@ class HeatContextTestCase(ut_base.BaseUnitTestCase):
         self.test_context.get_neutron_info = mock.MagicMock()
         self.test_context.deploy()
 
-        mock_template.assert_called_with('foo-12345678',
-                                         '/bar/baz/some-heat-file',
-                                         {'image': 'cirros'})
+        mock_template.assert_called_with(
+            'foo-12345678', template_file='/bar/baz/some-heat-file',
+            heat_parameters={'image': 'cirros'},
+            os_cloud_config=self.test_context._flags.os_cloud_config)
         self.assertIsNotNone(self.test_context.stack)
         key_filename = ''.join(
             [consts.YARDSTICK_ROOT_PATH,
index c9f9129..9361a97 100644 (file)
 from oslo_utils import uuidutils
 import unittest
 import mock
-
+import shade
 from shade import exc
+
+from yardstick.common import constants
 from yardstick.common import openstack_utils
 
 
@@ -35,6 +37,29 @@ class GetHeatApiVersionTestCase(unittest.TestCase):
             self.assertEqual(api_version, expected_result)
 
 
+class GetShadeClientTestCase(unittest.TestCase):
+
+    @mock.patch.object(shade, 'openstack_cloud', return_value='os_client')
+    def test_get_shade_client(self, mock_openstack_cloud):
+        os_cloud_config = {'param1': True, 'param2': 'value2'}
+        self.assertEqual('os_client',
+                         openstack_utils.get_shade_client(**os_cloud_config))
+        os_cloud_config.update(constants.OS_CLOUD_DEFAULT_CONFIG)
+        mock_openstack_cloud.assert_called_once_with(**os_cloud_config)
+
+        mock_openstack_cloud.reset_mock()
+        os_cloud_config = {'verify': True, 'param2': 'value2'}
+        self.assertEqual('os_client',
+                         openstack_utils.get_shade_client(**os_cloud_config))
+        mock_openstack_cloud.assert_called_once_with(**os_cloud_config)
+
+    @mock.patch.object(shade, 'openstack_cloud', return_value='os_client')
+    def test_get_shade_client_no_parameters(self, mock_openstack_cloud):
+        self.assertEqual('os_client', openstack_utils.get_shade_client())
+        mock_openstack_cloud.assert_called_once_with(
+            **constants.OS_CLOUD_DEFAULT_CONFIG)
+
+
 class DeleteNeutronNetTestCase(unittest.TestCase):
 
     def setUp(self):
index 9598eeb..3ec59a3 100644 (file)
@@ -17,6 +17,7 @@ import shade
 import unittest
 
 from yardstick.benchmark.contexts import node
+from yardstick.common import constants
 from yardstick.common import exceptions
 from yardstick.orchestrator import heat
 
@@ -53,6 +54,14 @@ class HeatStackTestCase(unittest.TestCase):
         self._mock_stack_get.stop()
         heat._DEPLOYED_STACKS = {}
 
+    @mock.patch.object(shade, 'openstack_cloud')
+    def test__init(self, mock_openstack_cloud):
+        os_cloud_config = {'key': 'value'}
+        heatstack = heat.HeatStack('name', os_cloud_config=os_cloud_config)
+        self.assertEqual('name', heatstack.name)
+        os_cloud_config.update(constants.OS_CLOUD_DEFAULT_CONFIG)
+        mock_openstack_cloud.assert_called_once_with(**os_cloud_config)
+
     def test_create(self):
         template = {'tkey': 'tval'}
         heat_parameters = {'pkey': 'pval'}
@@ -192,7 +201,9 @@ class HeatStackTestCase(unittest.TestCase):
 class HeatTemplateTestCase(unittest.TestCase):
 
     def setUp(self):
-        self.template = heat.HeatTemplate('test')
+        self._os_cloud_config = {'key1': 'value1'}
+        self.template = heat.HeatTemplate(
+            'test', os_cloud_config=self._os_cloud_config)
 
     def test_add_tenant_network(self):
         self.template.add_network('some-network')
@@ -337,8 +348,12 @@ class HeatTemplateTestCase(unittest.TestCase):
 
     def test_create_not_block(self):
         heat_stack = mock.Mock()
-        with mock.patch.object(heat, 'HeatStack', return_value=heat_stack):
+        with mock.patch.object(heat, 'HeatStack', return_value=heat_stack) \
+                as mock_heatstack:
             ret = self.template.create(block=False)
+
+        mock_heatstack.assert_called_once_with(
+            self.template.name, os_cloud_config=self.template._os_cloud_config)
         heat_stack.create.assert_called_once_with(
             self.template._template, self.template.heat_parameters, False,
             3600)