Merge "Remove tool provisioning in Standalone contexts"
[yardstick.git] / yardstick / orchestrator / heat.py
index c55b8f8..5afa415 100644 (file)
@@ -15,6 +15,7 @@ import datetime
 import getpass
 import logging
 import pkg_resources
+import pprint
 import socket
 import tempfile
 import time
@@ -22,6 +23,7 @@ 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 exceptions
@@ -31,17 +33,11 @@ from yardstick.common import constants as consts
 log = logging.getLogger(__name__)
 
 
-HEAT_KEY_UUID_LENGTH = 8
-
 PROVIDER_SRIOV = "sriov"
 
 _DEPLOYED_STACKS = {}
 
 
-def get_short_key_uuid(uuid):
-    return str(uuid)[:HEAT_KEY_UUID_LENGTH]
-
-
 class HeatStack(object):
     """Represents a Heat stack (deployed template) """
 
@@ -51,6 +47,13 @@ class HeatStack(object):
         self._cloud = shade.openstack_cloud()
         self._stack = None
 
+    def _update_stack_tracking(self):
+        outputs = self._stack.outputs
+        self.outputs = {output['output_key']: output['output_value'] for output
+                        in outputs}
+        if self.uuid:
+            _DEPLOYED_STACKS[self.uuid] = self._stack
+
     def create(self, template, heat_parameters, wait, timeout):
         """Creates an OpenStack stack from a template"""
         with tempfile.NamedTemporaryFile('wb', delete=False) as template_file:
@@ -59,11 +62,25 @@ class HeatStack(object):
             self._stack = self._cloud.create_stack(
                 self.name, template_file=template_file.name, wait=wait,
                 timeout=timeout, **heat_parameters)
-        outputs = self._stack.outputs
-        self.outputs = {output['output_key']: output['output_value'] for output
-                        in outputs}
-        if self.uuid:
-            _DEPLOYED_STACKS[self.uuid] = self._stack
+
+        self._update_stack_tracking()
+
+    def get_failures(self):
+        return event_utils.get_events(self._cloud, self._stack.id,
+                                      event_args={'resource_status': 'FAILED'})
+
+    def get(self):
+        """Retrieves an existing stack from the target cloud
+
+        Returns a bool indicating whether the stack exists in the target cloud
+        If the stack exists, it will be stored as self._stack
+        """
+        self._stack = self._cloud.get_stack(self.name)
+        if not self._stack:
+            return False
+
+        self._update_stack_tracking()
+        return True
 
     @staticmethod
     def stacks_exist():
@@ -419,7 +436,7 @@ name (i.e. %s).
             }
         }
 
-    def add_keypair(self, name, key_uuid):
+    def add_keypair(self, name, key_id):
         """add to the template a Nova KeyPair"""
         log.debug("adding Nova::KeyPair '%s'", name)
         self.resources[name] = {
@@ -431,7 +448,7 @@ name (i.e. %s).
                     pkg_resources.resource_string(
                         'yardstick.resources',
                         'files/yardstick_key-' +
-                        get_short_key_uuid(key_uuid) + '.pub'),
+                        key_id + '.pub'),
                     'utf-8')
             }
         }
@@ -486,7 +503,36 @@ name (i.e. %s).
                      'port_range_max': '65535'},
                     {'remote_ip_prefix': '::/0',
                      'ethertype': 'IPv6',
-                     'protocol': 'ipv6-icmp'}
+                     'protocol': 'ipv6-icmp'},
+                    {'remote_ip_prefix': '0.0.0.0/0',
+                     'direction': 'egress',
+                     'protocol': 'tcp',
+                     'port_range_min': '1',
+                     'port_range_max': '65535'},
+                    {'remote_ip_prefix': '0.0.0.0/0',
+                     'direction': 'egress',
+                     'protocol': 'udp',
+                     'port_range_min': '1',
+                     'port_range_max': '65535'},
+                    {'remote_ip_prefix': '0.0.0.0/0',
+                     'direction': 'egress',
+                     'protocol': 'icmp'},
+                    {'remote_ip_prefix': '::/0',
+                     'direction': 'egress',
+                     'ethertype': 'IPv6',
+                     'protocol': 'tcp',
+                     'port_range_min': '1',
+                     'port_range_max': '65535'},
+                    {'remote_ip_prefix': '::/0',
+                     'direction': 'egress',
+                     'ethertype': 'IPv6',
+                     'protocol': 'udp',
+                     'port_range_min': '1',
+                     'port_range_max': '65535'},
+                    {'remote_ip_prefix': '::/0',
+                     'direction': 'egress',
+                     'ethertype': 'IPv6',
+                     'protocol': 'ipv6-icmp'},
                 ]
             }
         }
@@ -585,6 +631,9 @@ name (i.e. %s).
             return stack
 
         if stack.status != self.HEAT_STATUS_COMPLETE:
+            for event in stack.get_failures():
+                log.error("%s", event.resource_status_reason)
+            log.error(pprint.pformat(self._template))
             raise exceptions.HeatTemplateError(stack_name=self.name)
 
         log.info("Creating stack '%s' DONE in %d secs",