Repository: incubator-ariatosca Updated Branches: refs/heads/ARIA-321-clearwater e8f15b449 -> 329fe6c65 (forced update)
ARIA-321 Provide Clearwater IMS example * Allows capabilities, interfaces, and properties to override parent definition types only if the new type is a descendant of the overriden type * Fix bugs in model instrumentation (to allow ctx access to capability properties and complex values) * Fix to get_property intrinsic function * Doc fixes related to ARIA-277 Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/329fe6c6 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/329fe6c6 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/329fe6c6 Branch: refs/heads/ARIA-321-clearwater Commit: 329fe6c6537126aade1f50f1682f115c4c52ca1d Parents: c2b8e65 Author: Tal Liron <[email protected]> Authored: Tue Jul 18 17:25:27 2017 -0500 Committer: Tal Liron <[email protected]> Committed: Mon Jul 24 16:32:00 2017 -0500 ---------------------------------------------------------------------- aria/modeling/functions.py | 4 +- aria/orchestrator/context/common.py | 6 +- .../execution_plugin/ctx_proxy/server.py | 39 +- aria/storage/collection_instrumentation.py | 15 +- aria/storage/core.py | 2 +- .../clearwater/clearwater-single-static.yaml | 69 ++++ examples/clearwater/scripts/bono/create.sh | 5 + examples/clearwater/scripts/bono/delete.sh | 0 examples/clearwater/scripts/dime/create.sh | 5 + examples/clearwater/scripts/dime/delete.sh | 0 examples/clearwater/scripts/ellis/create.sh | 5 + examples/clearwater/scripts/ellis/delete.sh | 0 examples/clearwater/scripts/homer/create.sh | 5 + examples/clearwater/scripts/homer/delete.sh | 0 examples/clearwater/scripts/homestead/create.sh | 0 examples/clearwater/scripts/homestead/delete.sh | 0 examples/clearwater/scripts/host/configure.sh | 139 +++++++ examples/clearwater/scripts/ralf/create.sh | 0 examples/clearwater/scripts/ralf/delete.sh | 0 examples/clearwater/scripts/sprout/create.sh | 8 + examples/clearwater/scripts/sprout/delete.sh | 0 examples/clearwater/scripts/velum/create.sh | 8 + examples/clearwater/scripts/velum/delete.sh | 0 examples/clearwater/types/cassandra.yaml | 0 examples/clearwater/types/clearwater.yaml | 285 ++++++++++++++ examples/clearwater/types/ims.yaml | 394 +++++++++++++++++++ examples/hello-world/hello-world.yaml | 38 ++ examples/hello-world/helloworld.yaml | 38 -- .../simple_v1_0/modeling/capabilities.py | 14 +- .../simple_v1_0/modeling/functions.py | 18 +- .../simple_v1_0/modeling/interfaces.py | 14 +- .../simple_v1_0/modeling/parameters.py | 26 +- .../simple_v1_0/presentation/types.py | 8 +- .../aria_extension_tosca/simple_v1_0/types.py | 19 + tests/end2end/test_hello_world.py | 2 +- .../execution_plugin/test_ctx_proxy_server.py | 48 +-- 36 files changed, 1100 insertions(+), 114 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/aria/modeling/functions.py ---------------------------------------------------------------------- diff --git a/aria/modeling/functions.py b/aria/modeling/functions.py index 6544adf..d0ec0cf 100644 --- a/aria/modeling/functions.py +++ b/aria/modeling/functions.py @@ -20,6 +20,7 @@ Mechanism for evaluating intrinsic functions. from ..parser.consumption import ConsumptionContext from ..parser.exceptions import InvalidValueError from ..utils.collections import OrderedDict +from ..utils.type import full_type_name from . import exceptions @@ -89,7 +90,8 @@ def evaluate(value, container_holder, report_issues=False): # pylint: disable=to if (evaluation is None) \ or (not hasattr(evaluation, 'value')) \ or (not hasattr(evaluation, 'final')): - raise InvalidValueError('bad __evaluate__ implementation') + raise InvalidValueError('bad __evaluate__ implementation: {0}' + .format(full_type_name(value))) evaluated = True value = evaluation.value http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/aria/orchestrator/context/common.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/context/common.py b/aria/orchestrator/context/common.py index f400142..c71edca 100644 --- a/aria/orchestrator/context/common.py +++ b/aria/orchestrator/context/common.py @@ -40,8 +40,12 @@ class BaseContext(object): INSTRUMENTATION_FIELDS = ( modeling.models.Node.attributes, modeling.models.Node.properties, + # TODO: modeling.models.Capability.attributes, + modeling.models.Capability.properties, modeling.models.NodeTemplate.attributes, - modeling.models.NodeTemplate.properties + modeling.models.NodeTemplate.properties, + # TODO: modeling.models.CapabilityTemplate.attributes, + modeling.models.CapabilityTemplate.properties ) class PrefixedLogger(object): http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/aria/orchestrator/execution_plugin/ctx_proxy/server.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/execution_plugin/ctx_proxy/server.py b/aria/orchestrator/execution_plugin/ctx_proxy/server.py index ca910e0..d69f841 100644 --- a/aria/orchestrator/execution_plugin/ctx_proxy/server.py +++ b/aria/orchestrator/execution_plugin/ctx_proxy/server.py @@ -157,11 +157,11 @@ def _process_ctx_request(ctx, args): while index < num_args: arg = args[index] attr = _desugar_attr(current, arg) - if attr: + if attr is not None: current = getattr(current, attr) elif isinstance(current, collections.MutableMapping): key = arg - path_dict = _PathDictAccess(current) + path_dict = _PathAccess(current) if index + 1 == num_args: # read dict prop by path value = path_dict.get(key) @@ -174,6 +174,8 @@ def _process_ctx_request(ctx, args): else: raise RuntimeError('Illegal argument while accessing dict') break + elif hasattr(current, '__getitem__') and (arg in current): # *must* be after MutableMapping + current = current[arg] elif callable(current): kwargs = {} remaining_args = args[index:] @@ -183,7 +185,7 @@ def _process_ctx_request(ctx, args): current = current(*remaining_args, **kwargs) break else: - raise RuntimeError('{0} cannot be processed in {1}'.format(arg, args)) + raise RuntimeError('`{0}` cannot be processed in {1}'.format(arg, args)) index += 1 if callable(current): current = current() @@ -201,8 +203,8 @@ def _desugar_attr(obj, attr): return None -class _PathDictAccess(object): - pattern = re.compile(r"(.+)\[(\d+)\]") +class _PathAccess(object): + ARRAY_PATTERN = re.compile(r"(.+)\[(\d+)\]") def __init__(self, obj): self.obj = obj @@ -216,26 +218,35 @@ class _PathDictAccess(object): return value def _get_object_by_path(self, prop_path, fail_on_missing=True): - # when setting a nested object, make sure to also set all the + def has(name): + return (hasattr(current, '__iter__') and (name in current)) or hasattr(current, name) + + def get(name): + if hasattr(current, '__iter__') and (name in current): + return current[name] + return getattr(current, name) + + # When setting a nested object, make sure to also set all the # intermediate path objects current = self.obj for prop_segment in prop_path.split('.'): - match = self.pattern.match(prop_segment) - if match: - index = int(match.group(2)) - property_name = match.group(1) - if property_name not in current: + array_match = _PathAccess.ARRAY_PATTERN.match(prop_segment) + if array_match: + index = int(array_match.group(2)) + property_name = array_match.group(1) + if not has(property_name): self._raise_illegal(prop_path) if not isinstance(current[property_name], list): self._raise_illegal(prop_path) - current = current[property_name][index] + current = get(property_name)[index] else: - if prop_segment not in current: + if not has(prop_segment): if fail_on_missing: self._raise_illegal(prop_path) else: + # TODO: won't this change the model??? current[prop_segment] = {} - current = current[prop_segment] + current = get(prop_segment) return current def _get_parent_obj_prop_name_by_path(self, prop_path): http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/aria/storage/collection_instrumentation.py ---------------------------------------------------------------------- diff --git a/aria/storage/collection_instrumentation.py b/aria/storage/collection_instrumentation.py index c90cb18..dae884a 100644 --- a/aria/storage/collection_instrumentation.py +++ b/aria/storage/collection_instrumentation.py @@ -230,15 +230,20 @@ class _InstrumentedModel(_WrappedBase): def _apply_instrumentation(self): for field in self._instrumentation: + if field.parent.class_ != type(self._wrapped): + # Only apply fields of our class + continue + field_name = field.key field_cls = field.mapper.class_ + field = getattr(self._wrapped, field_name) # Preserve the original value. e.g. original attributes would be located under # _attributes setattr(self, '_{0}'.format(field_name), field) - # set instrumented value + # Set instrumented value if isinstance(field, dict): instrumentation_cls = _InstrumentedDict elif isinstance(field, list): @@ -247,7 +252,7 @@ class _InstrumentedModel(_WrappedBase): # TODO: raise proper error raise exceptions.StorageError( "ARIA supports instrumentation for dict and list. Field {field} of the " - "class {model} is of {type} type.".format( + "class `{model}` is of type `{type}`.".format( field=field, model=self._wrapped, type=type(field))) @@ -277,7 +282,7 @@ class _WrappedModel(_WrappedBase): return _create_instrumented_model( value, instrumentation=self._instrumentation, **self._kwargs) elif hasattr(value, 'metadata') or isinstance(value, (dict, list)): - # Basically checks that the value is indeed an sqlmodel (it should have metadata) + # Basically checks that the value is indeed a SQLAlchemy model (it should have metadata) return _create_wrapped_model( value, instrumentation=self._instrumentation, **self._kwargs) return value @@ -291,6 +296,10 @@ class _WrappedModel(_WrappedBase): def __getitem__(self, item): return self._wrap(self._wrapped[item]) + def __iter__(self): + for item in self._wrapped.__iter__(): + yield self._wrap(item) + def _create_instrumented_model(original_model, mapi, instrumentation): return type('Instrumented{0}'.format(original_model.__class__.__name__), http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/aria/storage/core.py ---------------------------------------------------------------------- diff --git a/aria/storage/core.py b/aria/storage/core.py index 2a5745e..527272c 100644 --- a/aria/storage/core.py +++ b/aria/storage/core.py @@ -130,7 +130,7 @@ class ModelStorage(Storage): """ model_name = model_cls.__modelname__ if model_name in self.registered: - self.logger.debug('{name} in already storage {self!r}'.format(name=model_name, + self.logger.debug('{name} already in storage {self!r}'.format(name=model_name, self=self)) return self.registered[model_name] = self.api(name=model_name, http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/clearwater-single-static.yaml ---------------------------------------------------------------------- diff --git a/examples/clearwater/clearwater-single-static.yaml b/examples/clearwater/clearwater-single-static.yaml new file mode 100644 index 0000000..ccdcac3 --- /dev/null +++ b/examples/clearwater/clearwater-single-static.yaml @@ -0,0 +1,69 @@ +tosca_definitions_version: tosca_simple_yaml_1_0 + +description: >- + Project Clearwater is an open-source IMS core, developed by Metaswitch Networks and released under + the GNU GPLv3. + +metadata: + template_name: clearwater-local + template_author: ARIA + template_version: '1.0.0' + aria_version: '0.1' + +imports: + - types/clearwater.yaml + - aria-1.0 + +topology_template: + + inputs: + hosts.user: + type: string + default: ubuntu + hosts.password: + type: string + default: ubuntu + static_host.public_address: + type: string + default: 192.168.1.170 + static_host.private_address: + type: string + default: 192.168.1.170 + + node_templates: + bono: + type: clearwater.Bono + + sprout: + type: clearwater.Sprout + + dime: + type: clearwater.Dime + + homestead: + type: clearwater.Homestead + + ralf: + type: clearwater.Ralf + + velum: + type: clearwater.Velum + + homer: + type: clearwater.Homer + + ellis: + type: clearwater.Ellis + + static_host: + type: clearwater.Host + attributes: + public_address: { get_input: static_host.public_address } + private_address: { get_input: static_host.private_address } + capabilities: + host: + properties: + ssh.user: { get_input: hosts.user } + ssh.password: { get_input: hosts.password } + max_log_directory_size: 50 MiB + reduce_cassandra_mem_usage: true http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/scripts/bono/create.sh ---------------------------------------------------------------------- diff --git a/examples/clearwater/scripts/bono/create.sh b/examples/clearwater/scripts/bono/create.sh new file mode 100644 index 0000000..6e441c2 --- /dev/null +++ b/examples/clearwater/scripts/bono/create.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -e + +yes | aptdcon --hide-terminal --install bono restund +yes | aptdcon --hide-terminal --install clearwater-management http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/scripts/bono/delete.sh ---------------------------------------------------------------------- diff --git a/examples/clearwater/scripts/bono/delete.sh b/examples/clearwater/scripts/bono/delete.sh new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/scripts/dime/create.sh ---------------------------------------------------------------------- diff --git a/examples/clearwater/scripts/dime/create.sh b/examples/clearwater/scripts/dime/create.sh new file mode 100644 index 0000000..584fcd0 --- /dev/null +++ b/examples/clearwater/scripts/dime/create.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -e + +yes | aptdcon --hide-terminal --install dime clearwater-prov-tools +yes | aptdcon --hide-terminal --install clearwater-management http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/scripts/dime/delete.sh ---------------------------------------------------------------------- diff --git a/examples/clearwater/scripts/dime/delete.sh b/examples/clearwater/scripts/dime/delete.sh new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/scripts/ellis/create.sh ---------------------------------------------------------------------- diff --git a/examples/clearwater/scripts/ellis/create.sh b/examples/clearwater/scripts/ellis/create.sh new file mode 100644 index 0000000..f7fb151 --- /dev/null +++ b/examples/clearwater/scripts/ellis/create.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -e + +yes | aptdcon --hide-terminal --install ellis +yes | aptdcon --hide-terminal --install clearwater-management http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/scripts/ellis/delete.sh ---------------------------------------------------------------------- diff --git a/examples/clearwater/scripts/ellis/delete.sh b/examples/clearwater/scripts/ellis/delete.sh new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/scripts/homer/create.sh ---------------------------------------------------------------------- diff --git a/examples/clearwater/scripts/homer/create.sh b/examples/clearwater/scripts/homer/create.sh new file mode 100644 index 0000000..4aa4893 --- /dev/null +++ b/examples/clearwater/scripts/homer/create.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -e + +yes | aptdcon --hide-terminal --install homer +yes | aptdcon --hide-terminal --install clearwater-management http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/scripts/homer/delete.sh ---------------------------------------------------------------------- diff --git a/examples/clearwater/scripts/homer/delete.sh b/examples/clearwater/scripts/homer/delete.sh new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/scripts/homestead/create.sh ---------------------------------------------------------------------- diff --git a/examples/clearwater/scripts/homestead/create.sh b/examples/clearwater/scripts/homestead/create.sh new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/scripts/homestead/delete.sh ---------------------------------------------------------------------- diff --git a/examples/clearwater/scripts/homestead/delete.sh b/examples/clearwater/scripts/homestead/delete.sh new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/scripts/host/configure.sh ---------------------------------------------------------------------- diff --git a/examples/clearwater/scripts/host/configure.sh b/examples/clearwater/scripts/host/configure.sh new file mode 100644 index 0000000..73e81e8 --- /dev/null +++ b/examples/clearwater/scripts/host/configure.sh @@ -0,0 +1,139 @@ +#!/bin/bash +set -e + +REPO_FILE=/etc/apt/sources.list.d/clearwater.list +REPO_LINE="deb http://repo.cw-ngv.com/stable binary/" +KEY_URL=http://repo.cw-ngv.com/repo_key + +# Clearwater repository +if [ ! -f "$REPO_FILE" ]; then + echo "$REPO_LINE" > "$REPO_FILE" + curl -L "$KEY_URL" | apt-key add - + apt update +fi + +if ! type aptdcon > /dev/null; then + apt install aptdaemon --yes +fi + +# For cw-upload_shared_config +yes | aptdcon --hide-terminal --install clearwater-config-manager + + +GEOGRAPHICALLY_REDUNDANT=False +PRIVATE_IP=$(ctx node attributes private_address) +PUBLIC_IP=$(ctx node attributes public_address) +MAX_LOG_DIRECTORY_SIZE=$(ctx node capabilities host properties max_log_directory_size.value) +REDUCE_CASSANDRA_MEM_USAGE=$(ctx node capabilities host properties reduce_cassandra_mem_usage) +PUBLIC_HOSTNAME=ubuntu +SITE_NAME=aria +ZONE=example.com +SECRET=secret + +mkdir -p /etc/clearwater + + +# Local configuration + +CONFIG_FILE=/etc/clearwater/local_config +ETCD_CLUSTER=$PRIVATE_IP + +echo "# Created by ARIA on $(date -u)" > "$CONFIG_FILE" + +echo >> "$CONFIG_FILE" +echo "# Local IP configuration" >> "$CONFIG_FILE" +echo "local_ip=$PRIVATE_IP" >> "$CONFIG_FILE" +echo "public_ip=$PUBLIC_IP" >> "$CONFIG_FILE" +echo "public_hostname=$PUBLIC_HOSTNAME" >> "$CONFIG_FILE" +echo "etcd_cluster=\"$ETCD_CLUSTER\"" >> "$CONFIG_FILE" + +if [ "$MAX_LOG_DIRECTORY_SIZE" != 0 ]; then + echo >> "$CONFIG_FILE" + echo "max_log_directory_size=$MAX_LOG_DIRECTORY_SIZE" >> "$CONFIG_FILE" +fi + +if [ "$GEOGRAPHICALLY_REDUNDANT" = True ]; then + echo >> "$CONFIG_FILE" + echo "# Geographically redundant" >> "$CONFIG_FILE" + echo "local_site_name=$SITE_NAME" >> "$CONFIG_FILE" + + # On the first Vellum node in the second site, you should set remote_cassandra_seeds to the + # IP address of a Vellum node in the first site. + #echo "remote_cassandra_seeds=" >> "$CONFIG_FILE" +fi + + +# Shared configuration + +CONFIG_FILE=/etc/clearwater/shared_config +SMTP_HOSTNAME=127.0.0.1 +SMTP_USERNAME=username +SMTP_PASSWORD=password + +if [ "$GEOGRAPHICALLY_REDUNDANT" = True ]; then + SPROUT_HOSTNAME=sprout.$SITE_NAME.$ZONE + SPROUT_REGISTRATION_STORE=vellum.$SITE_NAME.$ZONE + HS_HOSTNAME=hs.$SITE_NAME.$ZONE:8888 + HS_PROVISIONING_HOSTNAME=hs.$SITE_NAME.$ZONE:8889 + RALF_HOSTNAME=ralf.$SITE_NAME.$ZONE:10888 + RALF_SESSION_STORE=vellum.$ZONE + XDMS_HOSTNAME=homer.$SITE_NAME.$ZONE:7888 + CHRONOS_HOSTNAME=vellum.$SITE_NAME.$ZONE + CASSANDRA_HOSTNAME=vellum.$SITE_NAME.$ZONE +else + VELLUM_IP=$PRIVATE_IP + HOMESTEAD_IP=$PRIVATE_IP + HOMER_IP=$PRIVATE_IP + + SPROUT_HOSTNAME=$PUBLIC_HOSTNAME + SPROUT_REGISTRATION_STORE=$VELLUM_IP + HS_HOSTNAME=$HOMESTEAD_IP:8888 + HS_PROVISIONING_HOSTNAME=$HOMESTEAD_IP:8889 + RALF_HOSTNAME= + RALF_SESSION_STORE= + XDMS_HOSTNAME=$HOMER_IP:7888 + CHRONOS_HOSTNAME= + CASSANDRA_HOSTNAME= +fi + +echo "# Created by ARIA on $(date -u)" > "$CONFIG_FILE" + +echo >> "$CONFIG_FILE" +echo "# Deployment definitions" >> "$CONFIG_FILE" +echo "home_domain=$ZONE" >> "$CONFIG_FILE" +echo "sprout_hostname=$SPROUT_HOSTNAME" >> "$CONFIG_FILE" +echo "sprout_registration_store=$SPROUT_REGISTRATION_STORE" >> "$CONFIG_FILE" +echo "hs_hostname=$HS_HOSTNAME" >> "$CONFIG_FILE" +echo "hs_provisioning_hostname=$HS_PROVISIONING_HOSTNAME" >> "$CONFIG_FILE" +echo "ralf_hostname=$RALF_HOSTNAME" >> "$CONFIG_FILE" +echo "ralf_session_store=$RALF_SESSION_STORE" >> "$CONFIG_FILE" +echo "xdms_hostname=$XDMS_HOSTNAME" >> "$CONFIG_FILE" +echo "chronos_hostname=$CHRONOS_HOSTNAME" >> "$CONFIG_FILE" +echo "cassandra_hostname=$CASSANDRA_HOSTNAME" >> "$CONFIG_FILE" + +echo >> "$CONFIG_FILE" +echo "# Email server configuration" >> "$CONFIG_FILE" +echo "smtp_smarthost=$SMTP_HOSTNAME" >> "$CONFIG_FILE" +echo "smtp_username=$SMTP_USERNAME" >> "$CONFIG_FILE" +echo "smtp_password=$SMTP_PASSWORD" >> "$CONFIG_FILE" +echo "email_recovery_sender=clearwater@$ZONE" >> "$CONFIG_FILE" + +echo >> "$CONFIG_FILE" +echo "# I-CSCF/S-CSCF configuration" >> "$CONFIG_FILE" +echo "upstream_hostname=scscf.$HOSTNAME" >> "$CONFIG_FILE" + +echo >> "$CONFIG_FILE" +echo "# Keys" >> "$CONFIG_FILE" +echo "signup_key=$SECRET" >> "$CONFIG_FILE" +echo "turn_workaround=$SECRET" >> "$CONFIG_FILE" +echo "ellis_api_key=$SECRET" >> "$CONFIG_FILE" +echo "ellis_cookie_key=$SECRET" >> "$CONFIG_FILE" + +if [ "$REDUCE_CASSANDRA_MEM_USAGE" = True ]; then + echo >> "$CONFIG_FILE" + echo "# $REDUCE_CASSANDRA_MEM_USAGE" >> "$CONFIG_FILE" + echo "reduce_cassandra_mem_usage=Y" >> "$CONFIG_FILE" +fi + +# Copy to other hosts +#cw-upload_shared_config http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/scripts/ralf/create.sh ---------------------------------------------------------------------- diff --git a/examples/clearwater/scripts/ralf/create.sh b/examples/clearwater/scripts/ralf/create.sh new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/scripts/ralf/delete.sh ---------------------------------------------------------------------- diff --git a/examples/clearwater/scripts/ralf/delete.sh b/examples/clearwater/scripts/ralf/delete.sh new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/scripts/sprout/create.sh ---------------------------------------------------------------------- diff --git a/examples/clearwater/scripts/sprout/create.sh b/examples/clearwater/scripts/sprout/create.sh new file mode 100644 index 0000000..32f2a1a --- /dev/null +++ b/examples/clearwater/scripts/sprout/create.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e + +yes | aptdcon --hide-terminal --install sprout +yes | aptdcon --hide-terminal --install clearwater-management + +# Memento +#yes | aptdcon --hide-terminal --install memento-as memento-nginx http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/scripts/sprout/delete.sh ---------------------------------------------------------------------- diff --git a/examples/clearwater/scripts/sprout/delete.sh b/examples/clearwater/scripts/sprout/delete.sh new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/scripts/velum/create.sh ---------------------------------------------------------------------- diff --git a/examples/clearwater/scripts/velum/create.sh b/examples/clearwater/scripts/velum/create.sh new file mode 100644 index 0000000..ae22417 --- /dev/null +++ b/examples/clearwater/scripts/velum/create.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e + +yes | aptdcon --hide-terminal --install vellum +yes | aptdcon --hide-terminal --install clearwater-management + +# Memento +#yes | aptdcon --hide-terminal --install memento-cassandra http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/scripts/velum/delete.sh ---------------------------------------------------------------------- diff --git a/examples/clearwater/scripts/velum/delete.sh b/examples/clearwater/scripts/velum/delete.sh new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/types/cassandra.yaml ---------------------------------------------------------------------- diff --git a/examples/clearwater/types/cassandra.yaml b/examples/clearwater/types/cassandra.yaml new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/types/clearwater.yaml ---------------------------------------------------------------------- diff --git a/examples/clearwater/types/clearwater.yaml b/examples/clearwater/types/clearwater.yaml new file mode 100644 index 0000000..37e5831 --- /dev/null +++ b/examples/clearwater/types/clearwater.yaml @@ -0,0 +1,285 @@ +# http://clearwater.readthedocs.io/en/stable/Clearwater_Architecture.html + +imports: + - ims.yaml + +dsl_definitions: + + clearwater_operation_dependencies: &CLEARWATER_OPERATION_DEPENDENCIES + - "ssh.user > { get_property: [ HOST, host, ssh.user ] }" + - "ssh.password > { get_property: [ HOST, host, ssh.password ] }" + - "ssh.address > { get_attribute: [ HOST, public_address ] }" + - "ssh.use_sudo > true" + +capability_types: + + clearwater.Container: + description: >- + Clearwater container capability. + derived_from: tosca.capabilities.Container + properties: + ssh.user: + type: string + ssh.password: + type: string + max_log_directory_size: + type: scalar-unit.size + default: 0 B # means no max size + reduce_cassandra_mem_usage: + type: boolean + default: false + +node_types: + + clearwater.Host: + description: >- + Clearwater host. + derived_from: tosca.nodes.Compute + interfaces: + Standard: + type: tosca.interfaces.node.lifecycle.Standard + configure: + implementation: + primary: scripts/host/configure.sh + dependencies: *CLEARWATER_OPERATION_DEPENDENCIES + capabilities: + host: # override + type: clearwater.Container + valid_source_types: [ tosca.nodes.SoftwareComponent ] + + clearwater.SoftwareComponent: + description: >- + Clearwater software components must be installed in a Clearwater-capable container. + derived_from: tosca.nodes.SoftwareComponent + requirements: + - host: # override + capability: clearwater.Container + node: tosca.nodes.Compute + relationship: tosca.relationships.HostedOn + + clearwater.Bono: + description: >- + Clearwater edge proxy. + + The Bono nodes form a horizontally scalable SIP edge proxy providing both a SIP IMS Gm + compliant interface and a WebRTC interface to clients. Client connections are load balanced + across the nodes. The Bono node provides the anchor point for the client's connection to the + Clearwater system, including support for various NAT traversal mechanisms. A client is + therefore anchored to a particular Bono node for the duration of its registration, but can + move to another Bono node if the connection or client fails. + + Clients can connect to Bono using SIP/UDP or SIP/TCP. Bono supports any WebRTC client that + performs call setup signaling using SIP over WebSocket. + + Alternatively, Clearwater can be deployed with a third party P-CSCF or Session Border + Controller implementing P-CSCF. In this case Bono nodes are not required. + derived_from: clearwater.SoftwareComponent + capabilities: + Gm: ims.capabilities.Gm + interfaces: + Standard: + type: tosca.interfaces.node.lifecycle.Standard + create: + implementation: + primary: scripts/bono/create.sh + dependencies: *CLEARWATER_OPERATION_DEPENDENCIES + delete: + implementation: + primary: scripts/bono/delete.sh + dependencies: *CLEARWATER_OPERATION_DEPENDENCIES + + clearwater.Sprout: + description: >- + Clearwater SIP router. + + The Sprout nodes act as a horizontally scalable, combined SIP registrar and authoritative + routing proxy, and handle client authentication and the ISC interface to application servers. + The Sprout nodes also contain the in-built MMTEL application server. SIP transactions are load + balanced across the Sprout cluster, so there is no long-lived association between a client and + a particular Sprout node. Sprout does not store any long-lived data itself and instead uses + web service interfaces to Homestead and Homer to retrieve HSS configuration such as + authentication data/user profiles and MMTEL service settings APIs to Vellum for storing + subscriber registration data and for running timers. + + Sprout is where the bulk of the I-CSCF and S-CSCF function resides, with the remainder + provided by Dime (and backed by the long-lived data stores on Vellum). + derived_from: clearwater.SoftwareComponent + properties: + memento: + description: >- + Set to true if you want the Sprout node to include a Memento Application server. + type: boolean + default: false + interfaces: + Standard: + type: tosca.interfaces.node.lifecycle.Standard + create: + implementation: + primary: scripts/sprout/create.sh + dependencies: *CLEARWATER_OPERATION_DEPENDENCIES + delete: + implementation: + primary: scripts/sprout/delete.sh + dependencies: *CLEARWATER_OPERATION_DEPENDENCIES + + clearwater.Dime: + description: >- + Clearwater Diameter gateway. + + Dime nodes run Clearwater's Homestead and Ralf components. + derived_from: clearwater.SoftwareComponent + capabilities: + host: + type: tosca.capabilities.Container + valid_source_types: [ clearwater.DimeSoftwareComponent ] + interfaces: + Standard: + type: tosca.interfaces.node.lifecycle.Standard + create: + implementation: + primary: scripts/dime/create.sh + dependencies: *CLEARWATER_OPERATION_DEPENDENCIES + delete: + implementation: + primary: scripts/dime/delete.sh + dependencies: *CLEARWATER_OPERATION_DEPENDENCIES + + clearwater.DimeSoftwareComponent: + description: >- + Base type for Dime software components. + derived_from: clearwater.SoftwareComponent + requirements: + - host: # override + capability: tosca.capabilities.Container + node: clearwater.Dime + + clearwater.Homestead: + description: >- + Clearwater HSS cache. + + Homestead provides a web services interface to Sprout for retrieving authentication + credentials and user profile information. It can either master the data (in which case it + exposes a web services provisioning interface) or can pull the data from an IMS compliant HSS + over the Cx interface. The Homestead nodes themselves are stateless - the mastered / cached + subscriber data is all stored on Vellum (via Cassandraâs Thrift interface). + + In the IMS architecture, the HSS mirror function is considered to be part of the I-CSCF and + S-CSCF components, so in Clearwater I-CSCF and S-CSCF function is implemented with a + combination of Sprout and Dime clusters. + derived_from: clearwater.DimeSoftwareComponent + capabilities: + Cx: ims.capabilities.Cx + interfaces: + Standard: + type: tosca.interfaces.node.lifecycle.Standard + create: + implementation: + primary: scripts/homestead/create.sh + dependencies: *CLEARWATER_OPERATION_DEPENDENCIES + delete: + implementation: + primary: scripts/homestead/delete.sh + dependencies: *CLEARWATER_OPERATION_DEPENDENCIES + + clearwater.Ralf: + description: >- + Clearwater CTF. + + Ralf provides an HTTP API that both Bono and Sprout can use to report billable events that + should be passed to the CDF (Charging Data Function) over the Rf billing interface. Ralf is + stateless, using Vellum to maintain the long lived session state and run the timers necessary + to enable it to conform to the Rf protocol. + derived_from: clearwater.DimeSoftwareComponent + capabilities: + Rf: ims.capabilities.Rf + interfaces: + Standard: + type: tosca.interfaces.node.lifecycle.Standard + create: + implementation: + primary: scripts/ralf/create.sh + dependencies: *CLEARWATER_OPERATION_DEPENDENCIES + delete: + implementation: + primary: scripts/ralf/delete.sh + dependencies: *CLEARWATER_OPERATION_DEPENDENCIES + + clearwater.Velum: + description: >- + Clearwater state store. + + Vellum is used to maintain all long-lived state in the deployment. It does this by running a + number of cloud optimized, distributed storage clusters. + + - Cassandra. Cassandra is used by Homestead to store authentication credentials and profile + information, and is used by Homer to store MMTEL service settings. Vellum exposes Cassandra's + Thrift API. + + - etcd. etcd is used by Vellum itself to share clustering information between Vellum nodes and + by other nodes in the deployment for shared configuration. + + - Chronos. Chronos is a distributed, redundant, reliable timer service developed by + Clearwater. It is used by Sprout and Ralf nodes to enable timers to be run (e.g. for SIP + Registration expiry) without pinning operations to a specific node (one node can set the timer + and another act on it when it pops). Chronos is accessed via an HTTP API. + + - Memcached / Astaire. Vellum also runs a Memcached cluster fronted by Astaire. Astaire is a + service developed by Clearwater that enabled more rapid scale up and scale down of memcached + clusters. This cluster is used by Sprout and Ralf for storing registration and session state. + derived_from: clearwater.SoftwareComponent + properties: + memento: + description: >- + Set to true if you want your Sprout node includes a Memento Application server. + type: boolean + default: false + interfaces: + Standard: + type: tosca.interfaces.node.lifecycle.Standard + create: + implementation: + primary: scripts/velum/create.sh + dependencies: *CLEARWATER_OPERATION_DEPENDENCIES + delete: + implementation: + primary: scripts/velum/delete.sh + dependencies: *CLEARWATER_OPERATION_DEPENDENCIES + + clearwater.Homer: + description: >- + Clearwater XDMS. + + Homer is a standard XDMS used to store MMTEL service settings documents for each user of the + system. Documents are created, read, updated and deleted using a standard XCAP interface. As + with Homestead, the Homer nodes use Vellum as the data store for all long lived data. + derived_from: clearwater.SoftwareComponent + interfaces: + Standard: + type: tosca.interfaces.node.lifecycle.Standard + create: + implementation: + primary: scripts/homer/create.sh + dependencies: *CLEARWATER_OPERATION_DEPENDENCIES + delete: + implementation: + primary: scripts/homer/delete.sh + dependencies: *CLEARWATER_OPERATION_DEPENDENCIES + + clearwater.Ellis: + description: >- + Ellis is a sample provisioning portal providing self sign-up, password management, line + management and control of MMTEL service settings. It is not intended to be a part of + production Clearwater deployments (it is not easy to horizontally scale because of the MySQL + underpinnings for one thing) but to make the system easy to use out of the box. + derived_from: clearwater.SoftwareComponent + interfaces: + Standard: + type: tosca.interfaces.node.lifecycle.Standard + create: + implementation: + primary: scripts/ellis/create.sh + dependencies: *CLEARWATER_OPERATION_DEPENDENCIES + delete: + implementation: + primary: scripts/ellis/delete.sh + dependencies: *CLEARWATER_OPERATION_DEPENDENCIES http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/clearwater/types/ims.yaml ---------------------------------------------------------------------- diff --git a/examples/clearwater/types/ims.yaml b/examples/clearwater/types/ims.yaml new file mode 100644 index 0000000..6b9d8e3 --- /dev/null +++ b/examples/clearwater/types/ims.yaml @@ -0,0 +1,394 @@ +# https://en.wikipedia.org/wiki/IP_Multimedia_Subsystem#Interfaces_description + +capability_types: + + # In IMS these are called "interfaces". + + ims.capabilities.Diameter: + derived_from: tosca.capabilities.Root + + ims.capabilities.TCP: + derived_from: tosca.capabilities.Root + + ims.capabilities.SIP: + derived_from: tosca.capabilities.Root + + ims.capabilities.RTP: + derived_from: tosca.capabilities.Root + + ims.capabilities.H248: + derived_from: tosca.capabilities.Root + + ims.capabilities.HTTP: + derived_from: tosca.capabilities.Root + + ims.capabilities.MAP: + derived_from: tosca.capabilities.Root + + ims.capabilities.Cr: + description: >- + Used by MRFC to fetch documents (e.g. scripts, announcement files, and other resources) from + an AS. Also used for media control related commands. + derived_from: ims.capabilities.TCP + + ims.capabilities.Cx: + description: >- + Used to send subscriber data to the S-CSCF; including filter criteria and their priority. Also + used to furnish CDF and/or OCF addresses. + derived_from: ims.capabilities.Diameter + + ims.capabilities.Dh: + description: >- + Used by AS to find the HSS holding the user profile information in a multi-HSS environment. + DH_SLF_QUERY indicates an IMPU and DX_SLF_RESP return the HSS name. + derived_from: ims.capabilities.Diameter + + ims.capabilities.Dx: + description: >- + Used by I-CSCF or S-CSCF to find a correct HSS in a multi-HSS environment. DX_SLF_QUERY + indicates an IMPU and DX_SLF_RESP return the HSS name. + derived_from: ims.capabilities.Diameter + + ims.capabilities.Gm: + description: >- + Used to exchange messages between SIP user equipment (UE) or Voip gateway and P-CSCF. + derived_from: ims.capabilities.SIP + + ims.capabilities.Go: + description: >- + Allows operators to control QoS in a user plane and exchange charging correlation + information between IMS and GPRS network. + derived_from: ims.capabilities.Diameter + + ims.capabilities.Gq: + description: >- + Used to exchange policy decisions-related information between P-CSCF and PDF. + derived_from: ims.capabilities.Diameter + + ims.capabilities.Gx: + description: >- + Used to exchange policy decisions-related information between PCEF and PCRF. + derived_from: ims.capabilities.Diameter + + ims.capabilities.Gy: + description: >- + Used for online flow-based bearer charging. Functionally equivalent to Ro interface. + derived_from: ims.capabilities.Diameter + + ims.capabilities.ISC: + description: >- + Reference point between S-CSCF and AS. Main functions are to: + * Notify the AS of the registered IMPU, registration state and UE capabilities + * Supply the AS with information to allow it to execute multiple services + * Convey charging function addresses + derived_from: ims.capabilities.SIP + + ims.capabilities.Ici: + description: >- + Used to exchange messages between an IBCF and another IBCF belonging to a different IMS + network. + derived_from: ims.capabilities.SIP + + ims.capabilities.Izi: + description: >- + Used to forward media streams from a TrGW to another TrGW belonging to a different IMS + network. + derived_from: ims.capabilities.RTP + + ims.capabilities.Ma: + description: >- + Main functions are to: + * Forward SIP requests which are destined to a public service identity hosted by the AS + * Originate a session on behalf of a user or public service identity, if the AS has no + knowledge of a S-CSCF assigned to that user or public service identity + * Convey charging function addresses + derived_from: ims.capabilities.SIP + + ims.capabilities.Mg: + description: >- + ISUP signalling to SIP signalling and forwards SIP signalling to I-CSCF. + derived_from: ims.capabilities.SIP + + ims.capabilities.Mi: + description: >- + Used to exchange messages between S-CSCF and BGCF. + derived_from: ims.capabilities.SIP + + ims.capabilities.Mj: + description: >- + Used for the interworking with the PSTN/CS domain, when the BGCF has determined that a + breakout should occur in the same IMS network to send SIP message from BGCF to MGCF. + derived_from: ims.capabilities.SIP + + ims.capabilities.Mk: + description: >- + Used for the interworking with the PSTN/CS domain, when the BGCF has determined that a + breakout should occur in another IMS network to send SIP message from BGCF to the BGCF in the + other network. + derived_from: ims.capabilities.SIP + + ims.capabilities.Mm: + description: >- + Used for exchanging messages between IMS and external IP networks. + derived_from: ims.capabilities.SIP + + ims.capabilities.Mn: + description: >- + Allows control of user-plane resources. + derived_from: ims.capabilities.H248 + + ims.capabilities.Mp: + description: >- + Allows an MRFC to control media stream resources provided by an MRFP. + derived_from: ims.capabilities.H248 + + ims.capabilities.Mr: + description: >- + Used to exchange information between S-CSCF and MRFC. + derived_from: ims.capabilities.SIP + + ims.capabilities.Mr2: + description: >- + Used to exchange session controls between AS and MRFC. + derived_from: ims.capabilities.SIP + + ims.capabilities.Mw: + description: >- + Used to exchange messages between CSCFs. AGCF appears as a P-CSCF to the other CSCFs. + derived_from: ims.capabilities.SIP + + ims.capabilities.Mx: + description: >- + Used for the interworking with another IMS network, when the BGCF has determined that a + breakout should occur in the other IMS network to send SIP message from BGCF to the IBCF in + the other network. + derived_from: ims.capabilities.SIP + + ims.capabilities.P1: + description: >- + Used for call control services by AGCF to control H.248 A-MGW and residential gateways. + derived_from: ims.capabilities.H248 + + ims.capabilities.P2: + description: >- + Reference point between AGCF and CSCF. + derived_from: ims.capabilities.SIP + + ims.capabilities.Rc: + description: >- + Used by the AS to request that media resources be assigned to a call when using MRB in-line + mode or in query mode. + derived_from: ims.capabilities.SIP + + ims.capabilities.Rf: + description: >- + Used to exchange offline charging information with CDF. + derived_from: ims.capabilities.Diameter + + ims.capabilities.Ro: + description: >- + Used to exchange online charging information with OCF. + derived_from: ims.capabilities.Diameter + + ims.capabilities.Rx: + description: >- + Used to exchange policy and charging related information between P-CSCF and PCRF. Replacement + for the Gq reference point. + derived_from: ims.capabilities.Diameter + + ims.capabilities.Sh: + description: >- + Used to exchange User Profile information (e.g., user-related data, group lists, + user-service-related information or user location information or charging function addresses + (used when the AS has not received the third-party REGISTER for a user)) between an AS (SIP + AS or OSA SCS) and HSS. Also allow AS to activate/deactivate filter criteria stored in the HSS + on a per-subscriber basis. + derived_from: ims.capabilities.Diameter + + ims.capabilities.Si: + description: >- + Transports CAMEL subscription information, including triggers for use by CAMEL-based + application services information. + derived_from: ims.capabilities.MAP + + ims.capabilities.Sr: + description: >- + Used by MRFC to fetch documents (scripts and other resources) from an AS. + derived_from: ims.capabilities.HTTP + + ims.capabilities.Ut: + description: >- + Facilitates the management of subscriber information related to services and settings. + derived_from: ims.capabilities.HTTP + + ims.capabilities.Z: + description: >- + Conversion of POTS services to SIP messages. + derived_from: tosca.capabilities.Root + + +# https://en.wikipedia.org/wiki/IP_Multimedia_Subsystem#Core_network + +node_types: + + # In IMS these are called "functions". + + ims.nodes.HSS: + description: >- + The home subscriber server (HSS), or user profile server function (UPSF), is a master user + database that supports the IMS network entities that actually handle calls. It contains the + subscription-related information (subscriber profiles), performs authentication and + authorization of the user, and can provide information about the subscriber's location and IP + information. It is similar to the GSM home location register (HLR) and Authentication centre + (AuC). + + A subscriber location function (SLF) is needed to map user addresses when multiple HSSs are + used. + derived_from: tosca.nodes.Root + + ims.nodes.CSCF: + description: >- + Several roles of SIP servers or proxies, collectively called Call Session Control Function + (CSCF), are used to process SIP signalling packets in the IMS. + derived_from: tosca.nodes.Root + + ims.nodes.P-CSCF: + description: >- + A Proxy-CSCF (P-CSCF) is a SIP proxy that is the first point of contact for the IMS terminal. + It can be located either in the visited network (in full IMS networks) or in the home network + (when the visited network is not IMS compliant yet). Some networks may use a Session Border + Controller (SBC) for this function. The P-CSCF is at its core a specialized SBC for the + Userânetwork interface which not only protects the network, but also the IMS terminal. The use + of an additional SBC between the IMS terminal and the P-CSCF is unnecessary and infeasible due + to the signaling being encrypted on this leg. The terminal discovers its P-CSCF with either + DHCP, or it may be configured (e.g. during initial provisioning or via a 3GPP IMS Management + Object (MO)) or in the ISIM or assigned in the PDP Context (in General Packet Radio Service + (GPRS)). + derived_from: ims.nodes.CSCF + + ims.nodes.I-CSCF: + description: >- + An Interrogating-CSCF (I-CSCF) is another SIP function located at the edge of an + administrative domain. Its IP address is published in the Domain Name System (DNS) of the + domain (using NAPTR and SRV type of DNS records), so that remote servers can find it, and use + it as a forwarding point (e.g., registering) for SIP packets to this domain. + derived_from: ims.nodes.CSCF + + ims.nodes.S-CSCF: + description: >- + A Serving-CSCF (S-CSCF) is the central node of the signalling plane. It is a SIP server, but + performs session control too. It is always located in the home network. It uses Diameter Cx + and Dx interfaces to the HSS to download user profiles and upload user-to-S-CSCF associations + (the user profile is only cached locally for processing reasons only and is not changed). All + necessary subscriber profile information is loaded from the HSS. + derived_from: ims.nodes.CSCF + + ims.nodes.AS: + description: >- + SIP Application servers (AS) host and execute services, and interface with the S-CSCF using + SIP. An example of an application server that is being developed in 3GPP is the Voice call + continuity Function (VCC Server). Depending on the actual service, the AS can operate in SIP + proxy mode, SIP UA (user agent) mode or SIP B2BUA mode. An AS can be located in the home + network or in an external third-party network. If located in the home network, it can query + the HSS with the Diameter Sh or Si interfaces (for a SIP-AS). + derived_from: tosca.nodes.Root + + ims.nodes.SIP-AS: + description: >- + Host and execute IMS specific services. + derived_from: ims.nodes.AS + + ims.nodes.IM-SSF: + description: >- + IP Multimedia Service Switching Function. Interfaces SIP to CAP to communicate with CAMEL + Application Servers. + derived_from: ims.nodes.AS + + ims.nodes.OSA-SCS: + description: >- + OSA service capability server. Interfaces SIP to the OSA framework. + derived_from: ims.nodes.AS + + ims.nodes.AS-ILCM: + description: >- + The AS-ILCM (Application Server - Incoming Leg Control Model) stores transaction state, and + may optionally store session state depending on the specific service being executed. The + AS-ILCM interfaces to the S-CSCF (ILCM) for an incoming leg. Application Logic provides the + service(s) and interacts between the AS-ILCM and AS-OLCM. + derived_from: ims.nodes.AS + + ims.nodes.AS-OLCM: + description: >- + The AS-OLCM (Application Server - Outgoing Leg Control Model) stores transaction state, and + may optionally store session state depending on the specific service being executed. The + AS-OLCM interfaces to the S-CSCF (OLCM) for an outgoing leg. Application Logic provides the + service(s) and interacts between the AS-ILCM and AS-OLCM. + derived_from: ims.nodes.AS + + ims.nodes.MRF: + description: >- + The Media Resource Function (MRF) provides media related functions such as media manipulation + (e.g. voice stream mixing) and playing of tones and announcements. + + Each MRF is further divided into a media resource function controller (MRFC) and a media + resource function processor (MRFP). + derived_from: tosca.nodes.Root + + ims.nodes.MRFC: + description: >- + The MRFC is a signalling plane node that interprets information coming from an AS and S-CSCF + to control the MRFP. + derived_from: tosca.nodes.Root + + ims.nodes.MRFP: + description: >- + The MRFP is a media plane node used to mix, source or process media streams. It can also + manage access right to shared resources. + derived_from: tosca.nodes.Root + + ims.nodes.MRB: + description: >- + The Media Resource Broker (MRB) is a functional entity that is responsible for both collection + of appropriate published MRF information and supplying of appropriate MRF information to + consuming entities such as the AS. MRB can be used in two modes: + * Query mode: AS queries the MRB for media and sets up the call using the response of MRB + * In-Line Mode: AS sends a SIP INVITE to the MRB. The MRB sets up the call + derived_from: tosca.nodes.Root + + ims.nodes.BGCF: + description: >- + A Breakout Gateway Control Function (BGCF) is a SIP proxy which processes requests for routing + from an S-CSCF when the S-CSCF has determined that the session cannot be routed using DNS or + ENUM/DNS. It includes routing functionality based on telephone numbers. + derived_from: tosca.nodes.Root + + ims.nodes.PTSNGateway: + description: >- + A PSTN/CS gateway interfaces with PSTN circuit switched (CS) networks. For signalling, CS + networks use ISDN User Part (ISUP) (or BICC) over Message Transfer Part (MTP), while IMS uses + SIP over IP. For media, CS networks use Pulse-code modulation (PCM), while IMS uses Real-time + Transport Protocol (RTP). + derived_from: tosca.nodes.Root + + ims.nodes.SGW: + description: >- + A signalling gateway (SGW) interfaces with the signalling plane of the CS. It transforms lower + layer protocols as Stream Control Transmission Protocol (SCTP, an IP protocol) into Message + Transfer Part (MTP, an Signalling System 7 (SS7) protocol), to pass ISDN User Part (ISUP) from + the MGCF to the CS network. + derived_from: ims.nodes.PTSNGateway + + ims.nodes.MGCF: + description: >- + A media gateway controller function (MGCF) is a SIP endpoint that does call control protocol + conversion between SIP and ISUP/BICC and interfaces with the SGW over SCTP. It also controls + the resources in a Media Gateway (MGW) across an H.248 interface. + derived_from: ims.nodes.PTSNGateway + + ims.nodes.MGW: + description: >- + A media gateway (MGW) interfaces with the media plane of the CS network, by converting between + RTP and PCM. It can also transcode when the codecs don't match (e.g., IMS might use AMR, PSTN + might use G.711). + derived_from: ims.nodes.PTSNGateway + \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/hello-world/hello-world.yaml ---------------------------------------------------------------------- diff --git a/examples/hello-world/hello-world.yaml b/examples/hello-world/hello-world.yaml new file mode 100644 index 0000000..86e2ad0 --- /dev/null +++ b/examples/hello-world/hello-world.yaml @@ -0,0 +1,38 @@ +tosca_definitions_version: tosca_simple_yaml_1_0 + +node_types: + + WebServer: + derived_from: tosca:Root + capabilities: + host: + type: tosca:Container + + WebApp: + derived_from: tosca:WebApplication + properties: + port: + type: integer + +topology_template: + + node_templates: + web_server: + type: WebServer + + web_app: + type: WebApp + properties: + port: 9090 + requirements: + - host: web_server + interfaces: + Standard: + configure: scripts/configure.sh + start: scripts/start.sh + stop: scripts/stop.sh + + outputs: + port: + type: integer + value: { get_property: [ web_app, port ] } http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/examples/hello-world/helloworld.yaml ---------------------------------------------------------------------- diff --git a/examples/hello-world/helloworld.yaml b/examples/hello-world/helloworld.yaml deleted file mode 100644 index 2fdc4d4..0000000 --- a/examples/hello-world/helloworld.yaml +++ /dev/null @@ -1,38 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_0 - -node_types: - - WebServer: - derived_from: tosca:Root - capabilities: - host: - type: tosca.capabilities.Container - - WebApp: - derived_from: tosca.nodes.WebApplication - properties: - port: - type: integer - -topology_template: - - node_templates: - web_server: - type: WebServer - - web_app: - type: WebApp - properties: - port: 9090 - requirements: - - host: web_server - interfaces: - Standard: - configure: scripts/configure.sh - start: scripts/start.sh - stop: scripts/stop.sh - - outputs: - port: - type: integer - value: { get_property: [ web_app, port ] } http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py index 5427c7e..1b95bec 100644 --- a/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py +++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py @@ -68,12 +68,14 @@ def get_inherited_capability_definitions(context, presentation, for_presentation capability_definition = capability_definitions[capability_name] # Check if we changed the type - type1 = capability_definition.type - type2 = our_capability_definition.type - if type1 != type2: + type1 = capability_definition._get_type(context) + type2 = our_capability_definition._get_type(context) + + if not type1._is_descendant(context, type2): context.validation.report( - 'capability definition changes type from "{0}" to "{1}" in "{2}"' - .format(type1, type2, presentation._fullname), + 'capability definition type "{0}" is not a descendant of overridden ' + 'capability definition type "{1}"' \ + .format(type1._name, type2._name), locator=our_capability_definition._locator, level=Issue.BETWEEN_TYPES) merge_capability_definition(context, presentation, capability_definition, @@ -168,6 +170,8 @@ def merge_capability_definition(context, presentation, capability_definition, from_capability_definition): raw_properties = OrderedDict() + capability_definition._raw['type'] = from_capability_definition.type + # Merge properties from type from_property_defintions = from_capability_definition.properties merge_raw_parameter_definitions(context, presentation, raw_properties, from_property_defintions, http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py index 590c6a0..ecbfde9 100644 --- a/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py +++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py @@ -200,20 +200,24 @@ class GetProperty(Function): for modelable_entity in modelable_entities: properties = None + # First argument refers to a requirement template? if hasattr(modelable_entity, 'requirement_templates') \ and modelable_entity.requirement_templates \ and (req_or_cap_name in [v.name for v in modelable_entity.requirement_templates]): - for requirement_template in modelable_entity.requirement_templates: - if requirement_template.name == req_or_cap_name: - # First argument refers to a requirement - # TODO: should follow to matched capability in other node... + for requirement in modelable_entity.requirement_templates: + if requirement.name == req_or_cap_name: + # TODO raise CannotEvaluateFunctionException() - # break + # First argument refers to a capability? + elif hasattr(modelable_entity, 'capabilities') \ + and modelable_entity.capabilities \ + and (req_or_cap_name in modelable_entity.capabilities): + properties = modelable_entity.capabilities[req_or_cap_name].properties nested_property_name_or_index = self.nested_property_name_or_index[1:] + # First argument refers to a capability template? elif hasattr(modelable_entity, 'capability_templates') \ and modelable_entity.capability_templates \ and (req_or_cap_name in modelable_entity.capability_templates): - # First argument refers to a capability properties = modelable_entity.capability_templates[req_or_cap_name].properties nested_property_name_or_index = self.nested_property_name_or_index[1:] else: @@ -640,7 +644,7 @@ def get_target(container_holder, name, locator): def get_modelable_entity_parameter(modelable_entity, parameters, nested_parameter_name_or_index): if not parameters: - return False, True, None + return Evaluation(None, True) found = True final = True http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py index d5f447c..d41aa81 100644 --- a/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py +++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py @@ -400,13 +400,15 @@ def merge_raw_operation_definitions(context, raw_operations, our_operations, int def merge_interface_definition(context, interface, our_source, presentation, type_name): if hasattr(our_source, 'type'): # Check if we changed the interface type - input_type1 = interface.type - input_type2 = our_source.type - if (input_type1 is not None) and (input_type2 is not None) and (input_type1 != input_type2): + type1 = interface._get_type(context) + type2 = our_source._get_type(context) + + if (type2 is not None) and not type1._is_descendant(context, type2): context.validation.report( - 'interface definition "%s" changes type from "%s" to "%s" in "%s"' - % (interface._name, input_type1, input_type2, presentation._fullname), - locator=input_type2._locator, level=Issue.BETWEEN_TYPES) + 'interface definition type "{0}" is not a descendant of overridden ' + 'interface definition type "{1}"' \ + .format(type1._name, type2._name), + locator=our_source._locator, level=Issue.BETWEEN_TYPES) # Add/merge inputs our_interface_inputs = our_source._get_inputs(context) \ http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py index 87c1a3b..bd235f6 100644 --- a/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py +++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py @@ -18,7 +18,8 @@ from aria.utils.formatting import pluralize from aria.parser.presentation import Value from aria.parser.validation import Issue -from .data_types import coerce_value +from .data_types import (coerce_value, get_primitive_data_type) +from ..presentation.types import get_type_by_name # @@ -149,16 +150,21 @@ def validate_required_values(context, presentation, values, definitions): def merge_raw_parameter_definition(context, presentation, raw_property_definition, our_property_definition, field_name, property_name): - # Check if we changed the type - # TODO: allow a sub-type? - type1 = raw_property_definition.get('type') - type2 = our_property_definition.type + # Check if we changed the parameter type + type1_name = raw_property_definition.get('type') + type1 = get_type_by_name(context, type1_name, 'data_types') + if type1 is None: + type1 = get_primitive_data_type(type1_name) + type2 = our_property_definition._get_type(context) + if type1 != type2: - context.validation.report( - 'override changes type from "%s" to "%s" for property "%s" in "%s"' - % (type1, type2, property_name, presentation._fullname), - locator=presentation._get_child_locator(field_name, property_name), - level=Issue.BETWEEN_TYPES) + if not hasattr(type1, '_is_descendant') or not type1._is_descendant(context, type2): + context.validation.report( + 'interface definition type "{0}" is not a descendant of overridden ' + 'interface definition type "{1}"' \ + .format(type1._name, type2._name), + locator=presentation._get_child_locator(field_name, property_name), + level=Issue.BETWEEN_TYPES) merge(raw_property_definition, our_property_definition._raw) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py b/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py index 920ebed..5f9750e 100644 --- a/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py +++ b/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py @@ -18,7 +18,8 @@ def convert_name_to_full_type_name(context, name, types_dict): # pylint: disable """ Converts a type name to its full type name, or else returns it unchanged. - Works by checking for ``shorthand_name`` in the types' ``_extensions`` field. See also + Works by checking for ``shorthand_name`` and ``type_qualified_name`` in the types' + ``_extensions`` field. See also :class:`aria_extension_tosca.v1_0.presentation.extensible.ExtensiblePresentation`. Can be used as the conversion function argument in ``type_validator`` and @@ -36,9 +37,10 @@ def convert_name_to_full_type_name(context, name, types_dict): # pylint: disable def get_type_by_name(context, name, *types_dict_names): """ - Gets a type either by its full name or its shorthand name or typequalified name. + Gets a type either by its full name or its shorthand name or type-qualified name. - Works by checking for ``shorthand_name`` in the types' ``_extensions`` field. See also + Works by checking for ``shorthand_name`` and ``type_qualified_name`` in the types' + ``_extensions`` field. See also :class:`~aria_extension_tosca.v1_0.presentation.extensible.ExtensiblePresentation`. The arguments from the third onwards are used to locate a nested field under http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/extensions/aria_extension_tosca/simple_v1_0/types.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_v1_0/types.py b/extensions/aria_extension_tosca/simple_v1_0/types.py index 787aac2..5556179 100644 --- a/extensions/aria_extension_tosca/simple_v1_0/types.py +++ b/extensions/aria_extension_tosca/simple_v1_0/types.py @@ -193,6 +193,17 @@ class DataType(ExtensiblePresentation): return get_data_type(context, self, 'derived_from', allow_none=True) @cachedmethod + def _is_descendant(self, context, the_type): + if the_type is None: + return False + if not hasattr(the_type, '_name'): + # Must be a primitive type + return self._get_primitive_ancestor(context) == the_type + if hasattr(the_type, '_name') and (the_type._name == self._name): + return True + return self._is_descendant(context, the_type._get_parent(context)) + + @cachedmethod def _get_primitive_ancestor(self, context): parent = self._get_parent(context) if parent is not None: @@ -387,6 +398,14 @@ class InterfaceType(ExtensiblePresentation): 'interface_types') @cachedmethod + def _is_descendant(self, context, the_type): + if the_type is None: + return False + elif the_type._name == self._name: + return True + return self._is_descendant(context, the_type._get_parent(context)) + + @cachedmethod def _get_inputs(self, context): return FrozenDict(get_inherited_parameter_definitions(context, self, 'inputs')) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/tests/end2end/test_hello_world.py ---------------------------------------------------------------------- diff --git a/tests/end2end/test_hello_world.py b/tests/end2end/test_hello_world.py index 5e4d7fd..094ffc3 100644 --- a/tests/end2end/test_hello_world.py +++ b/tests/end2end/test_hello_world.py @@ -20,7 +20,7 @@ from .. import helpers def test_hello_world(testenv): - hello_world_template_uri = helpers.get_example_uri('hello-world', 'helloworld.yaml') + hello_world_template_uri = helpers.get_example_uri('hello-world', 'hello-world.yaml') service_name = testenv.install_service(hello_world_template_uri) try: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/329fe6c6/tests/orchestrator/execution_plugin/test_ctx_proxy_server.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/execution_plugin/test_ctx_proxy_server.py b/tests/orchestrator/execution_plugin/test_ctx_proxy_server.py index 7ab1bdb..f7e7e6d 100644 --- a/tests/orchestrator/execution_plugin/test_ctx_proxy_server.py +++ b/tests/orchestrator/execution_plugin/test_ctx_proxy_server.py @@ -290,72 +290,72 @@ class TestCtxEntryPoint(object): class TestPathDictAccess(object): def test_simple_set(self): obj = {} - path_dict = ctx_proxy.server._PathDictAccess(obj) - path_dict.set('foo', 42) + path_access = ctx_proxy.server._PathAccess(obj) + path_access.set('foo', 42) assert obj == {'foo': 42} def test_nested_set(self): obj = {'foo': {}} - path_dict = ctx_proxy.server._PathDictAccess(obj) - path_dict.set('foo.bar', 42) + path_access = ctx_proxy.server._PathAccess(obj) + path_access.set('foo.bar', 42) assert obj == {'foo': {'bar': 42}} def test_set_index(self): obj = {'foo': [None, {'bar': 0}]} - path_dict = ctx_proxy.server._PathDictAccess(obj) - path_dict.set('foo[1].bar', 42) + path_access = ctx_proxy.server._PathAccess(obj) + path_access.set('foo[1].bar', 42) assert obj == {'foo': [None, {'bar': 42}]} def test_set_nonexistent_parent(self): obj = {} - path_dict = ctx_proxy.server._PathDictAccess(obj) - path_dict.set('foo.bar', 42) + path_access = ctx_proxy.server._PathAccess(obj) + path_access.set('foo.bar', 42) assert obj == {'foo': {'bar': 42}} def test_set_nonexistent_parent_nested(self): obj = {} - path_dict = ctx_proxy.server._PathDictAccess(obj) - path_dict.set('foo.bar.baz', 42) + path_access = ctx_proxy.server._PathAccess(obj) + path_access.set('foo.bar.baz', 42) assert obj == {'foo': {'bar': {'baz': 42}}} def test_simple_get(self): obj = {'foo': 42} - path_dict = ctx_proxy.server._PathDictAccess(obj) - result = path_dict.get('foo') + path_access = ctx_proxy.server._PathAccess(obj) + result = path_access.get('foo') assert result == 42 def test_nested_get(self): obj = {'foo': {'bar': 42}} - path_dict = ctx_proxy.server._PathDictAccess(obj) - result = path_dict.get('foo.bar') + path_access = ctx_proxy.server._PathAccess(obj) + result = path_access.get('foo.bar') assert result == 42 def test_nested_get_shadows_dotted_name(self): obj = {'foo': {'bar': 42}, 'foo.bar': 58} - path_dict = ctx_proxy.server._PathDictAccess(obj) - result = path_dict.get('foo.bar') + path_access = ctx_proxy.server._PathAccess(obj) + result = path_access.get('foo.bar') assert result == 42 def test_index_get(self): obj = {'foo': [0, 1]} - path_dict = ctx_proxy.server._PathDictAccess(obj) - result = path_dict.get('foo[1]') + path_access = ctx_proxy.server._PathAccess(obj) + result = path_access.get('foo[1]') assert result == 1 def test_get_nonexistent(self): obj = {} - path_dict = ctx_proxy.server._PathDictAccess(obj) + path_access = ctx_proxy.server._PathAccess(obj) with pytest.raises(RuntimeError): - path_dict.get('foo') + path_access.get('foo') def test_get_by_index_not_list(self): obj = {'foo': {0: 'not-list'}} - path_dict = ctx_proxy.server._PathDictAccess(obj) + path_access = ctx_proxy.server._PathAccess(obj) with pytest.raises(RuntimeError): - path_dict.get('foo[0]') + path_access.get('foo[0]') def test_get_by_index_nonexistent_parent(self): obj = {} - path_dict = ctx_proxy.server._PathDictAccess(obj) + path_access = ctx_proxy.server._PathAccess(obj) with pytest.raises(RuntimeError): - path_dict.get('foo[1]') + path_access.get('foo[1]')
