Files
deb-murano/murano/dsl/dsl.py
Stan Lagun bb2d0e5a84 Support for multi-regional apps was added
Now all OpenStack resource classes inherit CloudResource
that provides getRegion method and regionName property.
This allows to assign resources to different regions.
getRegion() returns CloudRegion instance that resource or it
parent belong to. CloudRegion has the similar interface to
Environment class and is the correct way to get HeatStack
instance associated with the regoin, default network
configuration, security group manager and agent listener
instances. Environment acts as the default region so backward
compatibility is not broken. However new applications
should not use environment to set security group rules but
rather a region(s) of their instance(s) in order to work correctly
when their instances were configured to use region other then
the default.

Change-Id: I4dbf40c65042e9a354f3bfadfcd63a63e6e3e418
2016-08-12 07:09:58 -07:00

376 lines
12 KiB
Python

# Copyright (c) 2015 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import inspect
import os.path
import eventlet
import six
from yaql.language import expressions as yaql_expressions
from yaql.language import specs
from yaql.language import utils
from yaql.language import yaqltypes
from yaql import yaql_interface
from murano.dsl import constants
from murano.dsl import dsl_types
from murano.dsl import helpers
NO_VALUE = utils.create_marker('NO_VALUE')
def name(dsl_name):
def wrapper(cls):
cls.__murano_name = dsl_name
return cls
return wrapper
class MuranoObjectParameter(yaqltypes.PythonType):
def __init__(self, murano_class=None, nullable=False, version_spec=None,
decorate=True):
self.murano_class = murano_class
self.version_spec = version_spec
self.decorate = decorate
super(MuranoObjectParameter, self).__init__(
(dsl_types.MuranoObject, MuranoObjectInterface), nullable)
def check(self, value, context, *args, **kwargs):
if not super(MuranoObjectParameter, self).check(
value, context, *args, **kwargs):
return False
if value is None or isinstance(value, yaql_expressions.Expression):
return True
if isinstance(value, MuranoObjectInterface):
value = value.object
if not isinstance(value, dsl_types.MuranoObject):
return False
if self.murano_class:
murano_class = self.murano_class
if isinstance(murano_class, six.string_types):
return helpers.is_instance_of(
value, murano_class,
self.version_spec or helpers.get_type(context))
else:
return murano_class.is_compatible(value)
else:
return True
def convert(self, value, sender, context, function_spec, engine,
*args, **kwargs):
result = super(MuranoObjectParameter, self).convert(
value, sender, context, function_spec, engine, *args, **kwargs)
if self.decorate:
return MuranoObjectInterface.create(result)
else:
if isinstance(result, dsl_types.MuranoObject):
return result
return None if result is None else result.object
class ThisParameter(yaqltypes.HiddenParameterType, yaqltypes.SmartType):
def __init__(self):
super(ThisParameter, self).__init__(False)
def convert(self, value, sender, context, function_spec, engine,
*args, **kwargs):
return get_this(context)
class InterfacesParameter(yaqltypes.HiddenParameterType,
yaqltypes.SmartType):
def __init__(self):
super(InterfacesParameter, self).__init__(False)
def convert(self, value, sender, context, function_spec, engine,
*args, **kwargs):
this = helpers.get_this(context)
return Interfaces(this)
class MuranoTypeParameter(yaqltypes.PythonType):
def __init__(self, base_type=None, nullable=False, context=None,
resolve_strings=True):
self._context = context
self._base_type = base_type
self._resolve_strings = resolve_strings
super(MuranoTypeParameter, self).__init__(
(dsl_types.MuranoTypeReference,
six.string_types), nullable)
def check(self, value, context, *args, **kwargs):
if not super(MuranoTypeParameter, self).check(
value, context, *args, **kwargs):
return False
if isinstance(value, six.string_types):
if not self._resolve_strings:
return False
value = helpers.get_class(value, context).get_reference()
if isinstance(value, dsl_types.MuranoTypeReference):
if not self._base_type:
return True
return self._base_type.is_compatible(value)
return True
def convert(self, value, sender, context, function_spec, engine,
*args, **kwargs):
context = self._context or context
if isinstance(value, yaql_expressions.Expression):
value = value(utils.NO_VALUE, context, engine)
value = super(MuranoTypeParameter, self).convert(
value, sender, context, function_spec, engine)
if isinstance(value, six.string_types):
value = helpers.get_class(value, context).get_reference()
if self._base_type and not self._base_type.is_compatible(value):
raise ValueError('Value must be subtype of {0}'.format(
self._base_type.name
))
return value
class MuranoObjectInterface(dsl_types.MuranoObjectInterface):
class DataInterface(object):
def __init__(self, object_interface):
object.__setattr__(self, '__object_interface', object_interface)
def __getattr__(self, item):
oi = getattr(self, '__object_interface')
return oi[item]
def __setattr__(self, key, value):
oi = getattr(self, '__object_interface')
oi[key] = value
class CallInterface(object):
def __init__(self, mpl_object, object_store):
self.__object = mpl_object
self.__object_store = object_store
def __getattr__(self, item):
def func(*args, **kwargs):
self._insert_instruction()
with helpers.with_object_store(self.__object_store):
context = helpers.get_context()
return to_mutable(self.__object.type.invoke(
item, self.__object, args, kwargs,
context), helpers.get_yaql_engine(context))
return func
@staticmethod
def _insert_instruction():
context = helpers.get_context()
if context:
frame = inspect.stack()[2]
location = dsl_types.ExpressionFilePosition(
os.path.abspath(frame[1]), frame[2],
-1, frame[2], -1)
context[constants.CTX_CURRENT_INSTRUCTION] = NativeInstruction(
frame[4][0].strip(), location)
def __init__(self, mpl_object, object_store=None):
self.__object = mpl_object
self.__object_store = object_store or helpers.get_object_store()
@staticmethod
def create(mpl_object, object_store=None):
if mpl_object is None or isinstance(mpl_object, MuranoObjectInterface):
return mpl_object
return MuranoObjectInterface(mpl_object, object_store)
@property
def object(self):
return self.__object
@property
def id(self):
return self.__object.object_id
@property
def owner(self):
owner = self.__object.owner
return MuranoObjectInterface.create(owner)
def find_owner(self, type, optional=False):
if isinstance(type, six.string_types):
type = helpers.get_class(type)
elif isinstance(type, dsl_types.MuranoTypeReference):
type = type.type
p = self.__object.owner
while p is not None:
if type.is_compatible(p):
return MuranoObjectInterface(p)
p = p.owner
if not optional:
raise ValueError('Object is not owned by any instance of type '
'{0}'.format(type.name))
return None
@property
def type(self):
return self.__object.type
@property
def package(self):
return self.type.package
@property
def properties(self):
return MuranoObjectInterface.DataInterface(self)
@property
def name(self):
return self.object.name
@property
def extension(self):
return self.__object.extension
def cast(self, murano_class, version_spec=None):
return MuranoObjectInterface.create(
helpers.cast(
self.__object, murano_class,
version_spec or helpers.get_type()))
def is_instance_of(self, murano_class, version_spec=None):
return helpers.is_instance_of(
self.__object, murano_class,
version_spec or helpers.get_type())
def ancestors(self):
return self.type.ancestors()
def __getitem__(self, item):
context = helpers.get_context()
return to_mutable(
self.__object.get_property(item, context),
helpers.get_yaql_engine(context))
def __setitem__(self, key, value):
context = helpers.get_context()
value = helpers.evaluate(value, context)
self.__object.set_property(key, value, context)
def __call__(self):
return MuranoObjectInterface.CallInterface(
self.object, self.__object_store)
def __repr__(self):
return '<{0}>'.format(repr(self.object))
def __eq__(self, other):
if isinstance(other, MuranoObjectInterface):
return self.object == other.object
else:
return False
def __ne__(self, other):
return not (self == other)
def __hash__(self):
return hash(self.object)
class Interfaces(object):
def __init__(self, mpl_object):
self.__object = mpl_object
def yaql(self, receiver=utils.NO_VALUE):
return yaql_interface.YaqlInterface(
helpers.get_context(), helpers.get_yaql_engine(), receiver)
def this(self):
return self.methods(self.__object)
def methods(self, mpl_object):
return MuranoObjectInterface.create(mpl_object)
@property
def execution_session(self):
return helpers.get_execution_session()
@property
def caller(self):
caller_context = helpers.get_caller_context()
if caller_context is None:
return None
return get_this(caller_context)
@property
def attributes(self):
executor = helpers.get_executor()
return executor.attribute_store
@property
def class_config(self):
return self.__object.type.package.get_class_config(
self.__object.type.name)
@property
def package_loader(self):
return helpers.get_package_loader()
class NativeInstruction(object):
def __init__(self, instruction, location):
self.instruction = instruction
self.source_file_position = location
def __str__(self):
return self.instruction
def to_mutable(obj, yaql_engine=None):
if yaql_engine is None:
yaql_engine = helpers.get_yaql_engine()
def converter(value, limit_func, engine, rec):
if isinstance(value, dsl_types.MuranoObject):
return MuranoObjectInterface.create(value)
else:
return utils.convert_output_data(value, limit_func, engine, rec)
limiter = lambda it: utils.limit_iterable(it, constants.ITERATORS_LIMIT)
return converter(obj, limiter, yaql_engine, converter)
def meta(type_name, value):
def wrapper(func):
fd = specs.get_function_definition(func)
mpl_meta = fd.meta.get(constants.META_MPL_META, [])
mpl_meta.append({type_name: value})
specs.meta(type_name, mpl_meta)(func)
return wrapper
def get_this(context=None):
this = helpers.get_this(context)
return MuranoObjectInterface.create(this)
def get_execution_session():
return helpers.get_execution_session()
def spawn(func, *args, **kwargs):
context = helpers.get_context()
object_store = helpers.get_object_store()
def wrapper():
with helpers.with_object_store(object_store):
with helpers.contextual(context):
return func(*args, **kwargs)
return eventlet.spawn(wrapper)