Repository: incubator-ariatosca Updated Branches: refs/heads/ARIA-92-plugin-in-implementation-string 842ec0d40 -> 669356657 (forced update)
Default configuration for execution plugin Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/66935665 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/66935665 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/66935665 Branch: refs/heads/ARIA-92-plugin-in-implementation-string Commit: 669356657e568ea6bfed414c3193c47bcbdc5394 Parents: a6bfe80 Author: Tal Liron <[email protected]> Authored: Thu Mar 30 19:36:51 2017 -0500 Committer: Tal Liron <[email protected]> Committed: Fri Mar 31 12:13:31 2017 -0500 ---------------------------------------------------------------------- aria/modeling/orchestration.py | 1 - aria/modeling/service_instance.py | 12 +- aria/orchestrator/execution_plugin/__init__.py | 145 +++++++++++++++++-- .../execution_plugin/ssh/operations.py | 2 - aria/orchestrator/workflows/api/task.py | 7 +- aria/orchestrator/workflows/exceptions.py | 10 +- .../simple_v1_0/modeling/__init__.py | 2 +- .../node-cellar/node-cellar.yaml | 10 +- 8 files changed, 153 insertions(+), 36 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/66935665/aria/modeling/orchestration.py ---------------------------------------------------------------------- diff --git a/aria/modeling/orchestration.py b/aria/modeling/orchestration.py index e7118f9..b5c735d 100644 --- a/aria/modeling/orchestration.py +++ b/aria/modeling/orchestration.py @@ -263,7 +263,6 @@ class TaskBase(ModelMixin): retry_interval = Column(Float, default=0) ignore_failure = Column(Boolean, default=False) - # Operation specific fields implementation = Column(String) configuration = Column(modeling_types.StrictDict(key_cls=basestring)) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/66935665/aria/modeling/service_instance.py ---------------------------------------------------------------------- diff --git a/aria/modeling/service_instance.py b/aria/modeling/service_instance.py index 8852887..ecfae2c 100644 --- a/aria/modeling/service_instance.py +++ b/aria/modeling/service_instance.py @@ -391,16 +391,8 @@ class NodeBase(InstanceModelMixin): # pylint: disable=too-many-public-methods @property def ip(self): - # TODO: totally broken - if not self.host_fk: - return None - host_node = self.host - if 'ip' in host_node.runtime_properties: # pylint: disable=no-member - return host_node.runtime_properties['ip'] # pylint: disable=no-member - host_node = host_node.node_template # pylint: disable=no-member - host_ip_property = host_node.properties.get('ip') - if host_ip_property: - return host_ip_property.value + if self.host and self.host.runtime_properties: + return self.host.runtime_properties.get('ip') return None # endregion http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/66935665/aria/orchestrator/execution_plugin/__init__.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/execution_plugin/__init__.py b/aria/orchestrator/execution_plugin/__init__.py index 5561ddf..5a79cbe 100644 --- a/aria/orchestrator/execution_plugin/__init__.py +++ b/aria/orchestrator/execution_plugin/__init__.py @@ -15,6 +15,7 @@ from contextlib import contextmanager from ...modeling import models +from ...utils.formatting import full_type_name # Populated during execution of python scripts @@ -35,11 +36,12 @@ def python_script_scope(operation_ctx, operation_inputs): inputs = None -def init_operation(operation_task): +def configure_operation(operation_task): from . import operations inputs = {} inputs['script_path'] = operation_task.implementation + inputs['process'] = _get_process(operation_task.configuration.get('process')) host = None if operation_task.actor_type == 'node': @@ -51,27 +53,138 @@ def init_operation(operation_task): elif edge == 'target': host = operation_task.actor.target_node.host else: - raise ValueError('"edge" configuration must be "source" or "target": {0}'.format(edge)) + raise ValueError('"edge" configuration must be "source" or "target" for "{0}": {1}' + .format(operation_task.implementation, edge)) + ip = host.ip if host is not None else None + #ip = '1.2.3.4' - if host is None: - # Local operation - operation_task.implementation = '{0}.{1}'.format(operations.__name__, - operations.run_script_locally.__name__) + if ip is None: + _configure_local(operation_task) else: - # Remote SSH operation via Fabric - inputs['use_sudo'] = _to_bool(operation_task.configuration.get('use_sudo')) - inputs['hide_output'] = operation_task.configuration.get('hide_output') - inputs['fabric_env'] = operation_task.configuration.get('fabric_env') - # How to set up fabric env? - # How to set up host address? - operation_task.implementation = '{0}.{1}'.format(operations.__name__, - operations.run_script_with_ssh.__name__) + _configure_remote(operation_task, inputs, ip) for k, v in inputs.iteritems(): operation_task.inputs[k] = models.Parameter.wrap(k, v) -def _to_bool(value): +def _configure_local(operation_task): + """ + Local operation. + """ + operation_task.implementation = '{0}.{1}'.format(operations.__name__, + operations.run_script_locally.__name__) + + +def _configure_remote(operation_task, inputs, ip): + """ + Remote SSH operation via Fabric. + """ + default_user = 'admin' + default_password = 'admin' + ssh = _get_ssh(operation_task.configuration.get('ssh')) + if 'user' not in ssh: + ssh['user'] = default_user + if ('password' not in ssh) and ('key' not in ssh) and ('key_filename' not in ssh): + ssh['password'] = default_password + inputs['use_sudo'] = ssh.get('use_sudo') + inputs['hide_output'] = ssh.get('hide_output') + inputs['fabric_env'] = {} + inputs['fabric_env']['host_string'] = ip + if 'warn_only' in ssh: + inputs['fabric_env']['warn_only'] = ssh['warn_only'] + inputs['fabric_env']['user'] = ssh.get('user') + inputs['fabric_env']['password'] = ssh.get('password') + inputs['fabric_env']['key'] = ssh.get('key') + inputs['fabric_env']['key_filename'] = ssh.get('key_filename') + + if inputs['fabric_env'].get('user') is None: + raise ValueError('must configure "ssh.user" for "{0}"' + .format(operation_task.implementation)) + if (inputs['fabric_env'].get('password') is None) and \ + (inputs['fabric_env'].get('key') is None) and \ + (inputs['fabric_env'].get('key_filename') is None): + raise ValueError( + 'must configure "ssh.password", "ssh.key", or "ssh.key_filename" for "{0}"' + .format(operation_task.implementation)) + + operation_task.implementation = '{0}.{1}'.format(operations.__name__, + operations.run_script_with_ssh.__name__) + + +def _get_process(value): + from ..workflows.exceptions import TaskCreationException if value is None: return None - return unicode(value).lower() == 'true' + _validate_type(value, dict, 'process') + for k, v in value.iteritems(): + if k == 'eval_python': + value[k] = _str_to_bool(v, 'process.eval_python') + elif k == 'cwd': + _validate_type(v, basestring, 'process.cwd') + elif k == 'command_prefix': + _validate_type(v, basestring, 'process.command_prefix') + elif k == 'args': + value[k] = _dict_to_list(v, 'process.args') + elif k == 'env': + _validate_type(v, dict, 'process.env') + else: + raise TaskCreationException('unsupported configuration: "process.{0}"'.format(k)) + return value + + +def _get_ssh(value): + from ..workflows.exceptions import TaskCreationException + if value is None: + return {} + _validate_type(value, dict, 'ssh') + for k, v in value.iteritems(): + if k == 'use_sudo': + value[k] = _str_to_bool(v, 'ssh.use_sudo') + elif k == 'hide_output': + value[k] = _dict_to_list(v, 'ssh.hide_output') + elif k == 'warn_only': + value[k] = _str_to_bool(v, 'ssh.warn_only') + elif k == 'user': + _validate_type(v, basestring, 'ssh.user') + elif k == 'password': + _validate_type(v, basestring, 'ssh.password') + elif k == 'key': + _validate_type(v, basestring, 'ssh.key') + elif k == 'key_filename': + _validate_type(v, basestring, 'ssh.key_filename') + else: + raise TaskCreationException('unsupported configuration: "ssh.{0}"'.format(k)) + return value + + +def _validate_type(value, the_type, name): + from ..workflows.exceptions import TaskCreationException + if not isinstance(value, the_type): + raise TaskCreationException('"{0}" configuration is not a {1}' + .format(name, full_type_name(the_type))) + +def _str_to_bool(value, name): + from ..workflows.exceptions import TaskCreationException + if value is None: + return None + _validate_type(value, basestring, name) + if value == 'true': + return True + elif value == 'false': + return False + else: + raise TaskCreationException('"{0}" configuration is not "true" or "false": {1}' + .format(name, repr(value))) + + +def _dict_to_list(the_dict, name): + from ..workflows.exceptions import TaskCreationException + _validate_type(the_dict, dict, name) + value = [] + for k in sorted(the_dict): + v = the_dict[k] + if not isinstance(v, basestring): + raise TaskCreationException('"{0}.{1}" configuration is not a string: {2}' + .format(name, k, repr(v))) + value.append(v) + return value http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/66935665/aria/orchestrator/execution_plugin/ssh/operations.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/execution_plugin/ssh/operations.py b/aria/orchestrator/execution_plugin/ssh/operations.py index f240beb..d760ba8 100644 --- a/aria/orchestrator/execution_plugin/ssh/operations.py +++ b/aria/orchestrator/execution_plugin/ssh/operations.py @@ -143,8 +143,6 @@ def _fabric_env(ctx, fabric_env, warn_only): env = constants.FABRIC_ENV_DEFAULTS.copy() env.update(fabric_env or {}) env.setdefault('warn_only', warn_only) - if 'host_string' not in env: - env['host_string'] = ctx.task.runs_on.ip # validations if not env.get('host_string'): ctx.task.abort('`host_string` not supplied and ip cannot be deduced automatically') http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/66935665/aria/orchestrator/workflows/api/task.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/workflows/api/task.py b/aria/orchestrator/workflows/api/task.py index 902f1be..150863d 100644 --- a/aria/orchestrator/workflows/api/task.py +++ b/aria/orchestrator/workflows/api/task.py @@ -89,6 +89,11 @@ class OperationTask(BaseTask): 'Could not find operation "{0}" on interface "{1}" for {2} "{3}"' .format(operation_name, interface_name, actor_type, actor.name)) + if operation.implementation is None: + raise exceptions.OperationNotFoundException( + 'Empty operation "{0}" on interface "{1}" for {2} "{3}"' + .format(operation_name, interface_name, actor_type, actor.name)) + self.name = OperationTask.NAME_FORMAT.format(type=actor_type, name=actor.name, interface=interface_name, @@ -127,7 +132,7 @@ class OperationTask(BaseTask): actor_type, actor.name)) else: # Default plugin (execution) - execution_plugin.init_operation(self) + execution_plugin.configure_operation(self) @classmethod def for_node(cls, http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/66935665/aria/orchestrator/workflows/exceptions.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/workflows/exceptions.py b/aria/orchestrator/workflows/exceptions.py index 4fb8dd7..0ca263f 100644 --- a/aria/orchestrator/workflows/exceptions.py +++ b/aria/orchestrator/workflows/exceptions.py @@ -70,13 +70,19 @@ class TaskException(exceptions.AriaError): """ -class OperationNotFoundException(TaskException): +class TaskCreationException(TaskException): + """ + Could not create the task. + """ + + +class OperationNotFoundException(TaskCreationException): """ Could not find an operation on the node or relationship. """ -class PluginNotFoundException(TaskException): +class PluginNotFoundException(TaskCreationException): """ Could not find a plugin matching the plugin specification. """ http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/66935665/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py index 45c26eb..a54c57c 100644 --- a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py +++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py @@ -693,5 +693,5 @@ def set_nested(the_dict, keys, value): the_dict[key] = value else: if key not in the_dict: - the_dict[key] = StrictDict(key_class=basestring, value_class=basestring) + the_dict[key] = StrictDict(key_class=basestring) set_nested(the_dict[key], keys, value) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/66935665/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml ---------------------------------------------------------------------- diff --git a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml index 3cffc0b..65fbf92 100644 --- a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml +++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml @@ -160,11 +160,15 @@ topology_template: Configure: target_changed: implementation: - primary: mongodb/host_changed.sh + primary: changed.sh dependencies: - - runs_on > target + - edge > target + #- { concat: [ process.args.1 >, mongodb ] } + - process.args.1 > mongodb + - process.args.2 > host - ssh.user > admin - - ssh.password > 12345 + - ssh.password > 1234 + - ssh.use_sudo > true nginx: type: nginx.Nginx
