diff --git a/data/workflows/AD.xml b/data/workflows/AD.xml index b961a84..bea86b4 100644 --- a/data/workflows/AD.xml +++ b/data/workflows/AD.xml @@ -40,7 +40,7 @@ ( + Unable to deploy instance ) due to @@ -71,7 +71,7 @@ ( + Unable to set admin password on unit ) due to @@ -102,7 +102,7 @@ ( + Unable to set domain administrator password on unit ) due to @@ -142,7 +142,7 @@ ( + Unable to create a Primary DC on unit ) due to @@ -166,7 +166,7 @@ ( + Unable assign DNS IP on unit ) due to @@ -200,7 +200,7 @@ ( + Unit ) was unable to leave the domain due to @@ -257,7 +257,7 @@ ( + Unit ) was unable to join the domain due to diff --git a/data/workflows/AspNetApps.xml b/data/workflows/AspNetApps.xml index aba3eba..38e6e37 100644 --- a/data/workflows/AspNetApps.xml +++ b/data/workflows/AspNetApps.xml @@ -39,7 +39,7 @@ ( + Unable to deploy instance ) due to @@ -63,7 +63,7 @@ ( + Unable to create a Server Farm load balancer on unit ) due to @@ -94,7 +94,7 @@ ( + Unable to set admin password on unit ) @@ -125,7 +125,7 @@ ( + Unable to install IIS on ) @@ -162,11 +162,11 @@ ( + Unable to deploy WebApp on ) - \ No newline at end of file + diff --git a/data/workflows/ExternalAD.xml.example b/data/workflows/ExternalAD.xml.example index 1e5a6bb..1ee70fe 100644 --- a/data/workflows/ExternalAD.xml.example +++ b/data/workflows/ExternalAD.xml.example @@ -85,7 +85,7 @@ ( + Unit ) was unable to join the domain due to diff --git a/data/workflows/MsSqlCluster.xml b/data/workflows/MsSqlCluster.xml index 47acb35..7b1efe1 100644 --- a/data/workflows/MsSqlCluster.xml +++ b/data/workflows/MsSqlCluster.xml @@ -40,7 +40,7 @@ ( + Unable to deploy instance ) due to @@ -83,7 +83,7 @@ ( + Unable to set admin password on unit ) due to @@ -122,7 +122,7 @@ ( + Unable to install prerequisites on unit ) due to @@ -173,7 +173,7 @@ due to due to @@ -206,7 +206,7 @@ ) due to ) due to @@ -251,7 +251,7 @@ ( + Unable to install SQL Server on unit ) due to @@ -296,7 +296,7 @@ ( + Unable to initialize AlwaysOn AG for ) due to @@ -356,7 +356,7 @@ ( + Unable to initialize primary replica for SQL Server AG for ) due to @@ -401,7 +401,7 @@ ( + Unable to initialize secondary replica for SQL Server AG for ) due to diff --git a/data/workflows/MsSqlServer.xml b/data/workflows/MsSqlServer.xml index 547870a..3a90c1c 100644 --- a/data/workflows/MsSqlServer.xml +++ b/data/workflows/MsSqlServer.xml @@ -39,7 +39,7 @@ ( + Unable to deploy instance ) due to @@ -95,7 +95,7 @@ ( + Unable to set admin password on unit ) due to @@ -137,11 +137,11 @@ ( + Unable to install MS SQL Server on unit ) due to - \ No newline at end of file + diff --git a/muranoconductor/cloud_formation.py b/muranoconductor/cloud_formation.py index 80b8d34..52c4b23 100644 --- a/muranoconductor/cloud_formation.py +++ b/muranoconductor/cloud_formation.py @@ -18,6 +18,7 @@ import config import random import string import time +import datetime import xml_code_engine from openstack.common import log as logging @@ -38,7 +39,7 @@ def update_cf_stack(engine, context, body, template, result=None, error=None, context[error] = { 'message': getattr(error_result, 'message', None), 'strerror': getattr(error_result, 'strerror', None), - 'timestamp': time.time() + 'timestamp': datetime.datetime.now().isoformat() } failure_handler = body.find('failure') if failure_handler is not None: diff --git a/muranoconductor/windows_agent.py b/muranoconductor/windows_agent.py index 7459eeb..46fba6f 100644 --- a/muranoconductor/windows_agent.py +++ b/muranoconductor/windows_agent.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. import os.path +import datetime from muranoconductor.commands.windows_agent import AgentTimeoutException from muranoconductor.commands.windows_agent import UnhandledAgentException @@ -42,26 +43,20 @@ def send_command(engine, context, body, template, service, unit, errors = [] if isinstance(result_value, AgentTimeoutException): errors.append({ - 'type': "timeout", - 'messages': [result_value.message], - 'timeout': result_value.timeout + 'source': 'timeout', + 'message': result_value.message, + 'timeout': result_value.timeout, + 'timestamp': datetime.datetime.now().isoformat() }) else: if result_value['IsException']: - msg = "A general exception has occurred in the Agent: " + \ - result_value['Result'] - errors.append({ - 'type': "general", - 'messages': [msg], - }) - + errors.append(dict(_get_exception_info( + result_value.get('Result', [])), source='execution_plan')) else: - for res in result_value['Result']: + for res in result_value.get('Result', []): if res['IsException']: - errors.append({ - 'type': 'inner', - 'messages': res['Result'] - }) + errors.append(dict(_get_exception_info( + res.get('Result', [])), source='command')) else: ok.append(res) @@ -77,8 +72,7 @@ def send_command(engine, context, body, template, service, unit, failure_handler = body.find('failure') if failure_handler is not None: log.warning( - "Handling errors ({0}) in failure block".format(errors), - exc_info=True) + 'Handling errors ({0}) in failure block'.format(errors)) engine.evaluate_content(failure_handler, context) else: log.error("No failure block found for errors", exc_info=True) @@ -92,4 +86,18 @@ def send_command(engine, context, body, template, service, unit, unit=unit, service=service, callback=callback, timeout=timeout) +def _get_array_item(array, index): + return array[index] if len(array) > index else None + + +def _get_exception_info(data): + data = data or [] + return { + 'type': _get_array_item(data, 0), + 'message': _get_array_item(data, 1), + 'command': _get_array_item(data, 2), + 'details': _get_array_item(data, 3), + 'timestamp': datetime.datetime.now().isoformat() + } + xml_code_engine.XmlCodeEngine.register_function(send_command, "send-command") diff --git a/muranoconductor/workflow.py b/muranoconductor/workflow.py index 1c0faf1..baf7a1b 100644 --- a/muranoconductor/workflow.py +++ b/muranoconductor/workflow.py @@ -14,6 +14,7 @@ # limitations under the License. import logging +import anyjson import jsonpath import re import types @@ -283,6 +284,10 @@ class Workflow(object): context['/dataSource']['temp']['_stop_requested'] = True +def format_error(context, error, **kwargs): + error_data = context[error] + return anyjson.dumps(error_data) + xml_code_engine.XmlCodeEngine.register_function( Workflow._rule_func, 'rule') @@ -301,6 +306,9 @@ xml_code_engine.XmlCodeEngine.register_function( xml_code_engine.XmlCodeEngine.register_function( Workflow._select_all_func, 'select-all') +xml_code_engine.XmlCodeEngine.register_function( + format_error, "format-error") + xml_code_engine.XmlCodeEngine.register_function( Workflow._select_single_func, 'select-single')