Merge "Debugging information when dpdk bind fails should be improved"
[yardstick.git] / yardstick / tests / unit / orchestrator / test_heat.py
index f53c9b7..2e60a72 100644 (file)
@@ -9,6 +9,7 @@
 
 import tempfile
 
+import munch
 import mock
 from oslo_serialization import jsonutils
 from oslo_utils import uuidutils
@@ -16,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
 
@@ -40,14 +42,26 @@ class HeatStackTestCase(unittest.TestCase):
         self._mock_stack_delete = mock.patch.object(self.heatstack._cloud,
                                                     'delete_stack')
         self.mock_stack_delete = self._mock_stack_delete.start()
+        self._mock_stack_get = mock.patch.object(self.heatstack._cloud,
+                                                 'get_stack')
+        self.mock_stack_get = self._mock_stack_get.start()
 
         self.addCleanup(self._cleanup)
 
     def _cleanup(self):
         self._mock_stack_create.stop()
         self._mock_stack_delete.stop()
+        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'}
@@ -89,11 +103,107 @@ class HeatStackTestCase(unittest.TestCase):
         self.assertFalse(heat._DEPLOYED_STACKS)
         self.mock_stack_delete.assert_called_once_with(id, wait=True)
 
+    def test_delete_bug_in_shade(self):
+        id = uuidutils.generate_uuid()
+        self.heatstack._stack = FakeStack(
+            outputs=mock.Mock(), status=mock.Mock(), id=id)
+        heat._DEPLOYED_STACKS[id] = self.heatstack._stack
+        self.mock_stack_delete.side_effect = TypeError()
+
+        ret = self.heatstack.delete(wait=True)
+        self.assertTrue(ret)
+        self.assertFalse(heat._DEPLOYED_STACKS)
+        self.mock_stack_delete.assert_called_once_with(id, wait=True)
+
+    def test_get(self):
+        # make sure shade/get_stack is called with the appropriate vars
+        self.mock_stack_get.return_value = munch.Munch(
+            id="my-existing-stack-id",
+            outputs=[
+                {
+                 u'output_value': u'b734d06a-dec7-...',
+                 u'output_key': u'ares.demo-test-port-network_id',
+                 u'description': u''
+                },
+                {u'output_value': u'b08da78c-2218-...',
+                 u'output_key': u'ares.demo-test-port-subnet_id',
+                 u'description': u''
+                },
+                {u'output_value': u'10.0.1.0/24',
+                 u'output_key': u'demo-test-subnet-cidr',
+                 u'description': u''
+                },
+                {u'output_value': u'b08da78c-2218-...',
+                 u'output_key': u'demo-test-subnet',
+                 u'description': u''
+                },
+                {u'output_value': u'b1a03624-aefc-...',
+                 u'output_key': u'ares.demo',
+                 u'description': u''
+                },
+                {u'output_value': u'266a8088-c630-...',
+                 u'output_key': u'demo-secgroup',
+                 u'description': u''
+                },
+                {u'output_value': u'10.0.1.5',
+                 u'output_key': u'ares.demo-test-port',
+                 u'description': u''
+                },
+                {u'output_value': u'10.0.1.1',
+                 u'output_key': u'demo-test-subnet-gateway_ip',
+                 u'description': u''
+                },
+                {u'output_value': u'',
+                 u'output_key': u'ares.demo-test-port-device_id',
+                 u'description': u''
+                },
+                {u'output_value': u'172.24.4.7',
+                 u'output_key': u'ares.demo-fip',
+                 u'description': u''
+                },
+                {u'output_value': u'fa:16:3e:6c:c3:0f',
+                 u'output_key': u'ares.demo-test-port-mac_address',
+                 u'description': u''}
+            ]
+        )
+        expected_outputs = {
+            'ares.demo-test-port-network_id': 'b734d06a-dec7-...',
+            'ares.demo-test-port-subnet_id': 'b08da78c-2218-...',
+            'demo-test-subnet-cidr': '10.0.1.0/24',
+            'demo-test-subnet': 'b08da78c-2218-...',
+            'ares.demo': 'b1a03624-aefc-...',
+            'demo-secgroup': '266a8088-c630-...',
+            'ares.demo-test-port': '10.0.1.5',
+            'demo-test-subnet-gateway_ip': '10.0.1.1',
+            'ares.demo-test-port-device_id': '',
+            'ares.demo-fip': '172.24.4.7',
+            'ares.demo-test-port-mac_address': 'fa:16:3e:6c:c3:0f',
+        }
+
+        stack_id = "my-existing-stack-id"
+        self.heatstack.name = "my-existing-stack"
+        self.heatstack.get()
+
+        self.mock_stack_get.assert_called_once_with(self.heatstack.name)
+        self.assertEqual(expected_outputs, self.heatstack.outputs)
+        self.assertEqual(1, len(heat._DEPLOYED_STACKS))
+        self.assertEqual(self.heatstack._stack,
+                         heat._DEPLOYED_STACKS[stack_id])
+
+    def test_get_invalid_name(self):
+        # No context matching this name exists
+        self.mock_stack_get.return_value = []
+        self.heatstack.name = 'not-a-stack'
+        self.heatstack.get()
+        self.assertEqual(0, len(heat._DEPLOYED_STACKS))
+
 
 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')
@@ -146,9 +256,29 @@ class HeatTemplateTestCase(unittest.TestCase):
         self.assertEqual(self.template.resources['some-server-group'][
                              'properties']['policies'], ['anti-affinity'])
 
+    def test_add_security_group(self):
+        security_group = {
+            'rules': [
+                {'remote_ip_prefix': '0.0.0.0/0',
+                 'port_range_max': 65535,
+                 'port_range_min': 1,
+                 'protocol': 'custom'},
+            ]
+        }
+        self.template.add_security_group('some-security-group', security_group)
+
+        secgroup_rsc = self.template.resources['some-security-group']
+
+        self.assertEqual(secgroup_rsc['type'], "OS::Neutron::SecurityGroup")
+        self.assertEqual(secgroup_rsc['properties']['description'],
+                         "Custom security group rules defined by the user")
+        self.assertEqual(secgroup_rsc['properties']['rules'][0]['protocol'],
+                         'custom')
+
     def test__add_resources_to_template_raw(self):
         test_context = node.NodeContext()
-        test_context.name = 'foo'
+        self.addCleanup(test_context._delete_context)
+        test_context._name = 'foo'
         test_context.template_file = '/tmp/some-heat-file'
         test_context.heat_parameters = {'image': 'cirros'}
         test_context.key_filename = "/tmp/1234"
@@ -172,10 +302,18 @@ class HeatTemplateTestCase(unittest.TestCase):
         heat_template.add_subnet("subnet2", "network2", "cidr2")
         heat_template.add_router("router1", "gw1", "subnet1")
         heat_template.add_router_interface("router_if1", "router1", "subnet1")
-        heat_template.add_port("port1", "network1", "subnet1", "normal")
-        heat_template.add_port("port2", "network2", "subnet2", "normal",
+        network1 = mock.MagicMock()
+        network1.stack_name = "network1"
+        network1.subnet_stack_name = "subnet1"
+        network1.vnic_type = "normal"
+        network2 = mock.MagicMock()
+        network2.stack_name = "network2"
+        network2.subnet_stack_name = "subnet2"
+        network2.vnic_type = "normal"
+        heat_template.add_port("port1", network1)
+        heat_template.add_port("port2", network2,
                                sec_group_id="sec_group1", provider="not-sriov")
-        heat_template.add_port("port3", "network2", "subnet2", "normal",
+        heat_template.add_port("port3", network2,
                                sec_group_id="sec_group1", provider="sriov")
         heat_template.add_floating_ip("floating_ip1", "network1", "port1",
                                       "router_if1")
@@ -229,8 +367,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)
@@ -246,13 +388,30 @@ class HeatTemplateTestCase(unittest.TestCase):
             3600)
         self.assertEqual(heat_stack, ret)
 
-
     def test_create_block_status_no_complete(self):
         heat_stack = mock.Mock()
         heat_stack.status = 'other status'
+        heat_stack.get_failures.return_value = []
         with mock.patch.object(heat, 'HeatStack', return_value=heat_stack):
             self.assertRaises(exceptions.HeatTemplateError,
                               self.template.create, block=True)
         heat_stack.create.assert_called_once_with(
             self.template._template, self.template.heat_parameters, True,
             3600)
+
+    def test_create_block_status_no_complete_with_reasons(self):
+        heat_stack = mock.Mock()
+        heat_stack.status = 'other status'
+        heat_stack.get_failures.return_value = [
+            mock.Mock(resource_status_reason="A reason"),
+            mock.Mock(resource_status_reason="Something else")
+        ]
+        with mock.patch.object(heat, 'HeatStack', return_value=heat_stack):
+            with mock.patch.object(heat, 'log') as mock_log:
+                self.assertRaises(exceptions.HeatTemplateError,
+                                  self.template.create, block=True)
+                mock_log.error.assert_any_call("%s", "A reason")
+                mock_log.error.assert_any_call("%s", "Something else")
+        heat_stack.create.assert_called_once_with(
+            self.template._template, self.template.heat_parameters, True,
+            3600)