Allow to request logs for all servers in the stack

adds logic for users of stack_create and update_stack methods
to request logging of console for all OS::Nova::Server resources
present in the stack.

Aim is to use it in tests that create servers tied to WaitCondition
to be able to debug Timeout issues related to them.

Related-Issue: PRODX-11681
Related-Issue: PRODX-11682
Change-Id: Ic767c1523098b8e5ab67b91f0b8c4d8dc83337fa
diff --git a/heat_tempest_plugin/common/test.py b/heat_tempest_plugin/common/test.py
index 83ccdc2..a3f44a0 100644
--- a/heat_tempest_plugin/common/test.py
+++ b/heat_tempest_plugin/common/test.py
@@ -239,6 +239,7 @@
         if not servers:
             servers = self.compute_client.servers.list()
         for server in servers:
+            LOG.info('Server %s', server)
             LOG.info('Console output for %s', server.id)
             LOG.info(server.get_console_output())
 
@@ -390,7 +391,8 @@
                                success_on_not_found=False,
                                signal_required=False,
                                resources_to_signal=None,
-                               is_action_cancelled=False):
+                               is_action_cancelled=False,
+                               log_nova_servers=False):
         """Waits for a Stack to reach a given status.
 
         Note this compares the full $action_$status, e.g
@@ -429,8 +431,23 @@
         message = ('Stack %s failed to reach %s status within '
                    'the required time (%s s).' %
                    (stack_identifier, status, build_timeout))
+        if log_nova_servers:
+            self._log_nova_servers(stack_identifier)
         raise exceptions.TimeoutException(message)
 
+    def _log_nova_servers(self, stack_identifier):
+        server_resources = self.client.resources.list(
+            stack_identifier,
+            type="OS::Nova::Server",
+            nested_depth=999)
+        servers = list(self.compute_client.servers.get(s.physical_resource_id)
+                       for s in server_resources)
+        if not servers:
+            LOG.info("No OS::Nova::Server resources found in stack %s",
+                     stack_identifier)
+            return
+        self._log_console_output(servers=servers)
+
     def _stack_delete(self, stack_identifier):
         try:
             self._handle_in_progress(self.client.stacks.delete,
@@ -463,7 +480,8 @@
                      files=None, parameters=None, tags=None,
                      expected_status='UPDATE_COMPLETE',
                      disable_rollback=True,
-                     existing=False):
+                     existing=False,
+                     log_nova_servers=False):
         env = environment or {}
         env_files = files or {}
         parameters = parameters or {}
@@ -480,7 +498,8 @@
             existing=existing)
 
         kwargs = {'stack_identifier': stack_identifier,
-                  'status': expected_status}
+                  'status': expected_status,
+                  'log_nova_servers': log_nova_servers}
         if expected_status in ['ROLLBACK_COMPLETE']:
             # To trigger rollback you would intentionally fail the stack
             # Hence check for rollback failures
@@ -631,7 +650,8 @@
                      parameters=None, environment=None, tags=None,
                      expected_status='CREATE_COMPLETE',
                      disable_rollback=True, enable_cleanup=True,
-                     environment_files=None, timeout=None):
+                     environment_files=None, timeout=None,
+                     log_nova_servers=False):
         name = stack_name or self._stack_rand_name()
         templ = template or self.template
         templ_files = files or {}
@@ -655,7 +675,8 @@
         stack = self.client.stacks.get(name, resolve_outputs=False)
         stack_identifier = '%s/%s' % (name, stack.id)
         kwargs = {'stack_identifier': stack_identifier,
-                  'status': expected_status}
+                  'status': expected_status,
+                  'log_nova_servers': log_nova_servers}
         if expected_status:
             if expected_status in ['ROLLBACK_COMPLETE']:
                 # To trigger rollback you would intentionally fail the stack