2506030cf1
1.As mentioned in [1], we should avoid using six.iterXXX to achieve iterators. We can use dict.XXX instead, as it will return iterators in PY3 as well. 2.In py2, the performance about list should be negligible, see the link [2]. [1] https://wiki.openstack.org/wiki/Python3 [2] http://lists.openstack.org/pipermail/openstack-dev/2015-June/066391.html Change-Id: If90a56fad941e4bb55da1e9f14a8133983efc027
181 lines
6.7 KiB
Python
181 lines
6.7 KiB
Python
# Copyright (c) 2015 OpenStack Foundation.
|
|
# All Rights Reserved.
|
|
#
|
|
# 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.
|
|
|
|
"""
|
|
Default actions reside in this module.
|
|
These action are available out of the box for Murano users.
|
|
|
|
"""
|
|
import yaql.language.utils as utils
|
|
|
|
import murano.dsl.exceptions as exceptions
|
|
import murano.dsl.murano_object as mo
|
|
import murano.policy.modify.actions.base as base
|
|
|
|
|
|
class ActionUtils(object):
|
|
def _get_objects_by_id(self, obj, objects=None):
|
|
if objects is None:
|
|
objects = {}
|
|
if isinstance(obj, mo.MuranoObject):
|
|
objects[obj.object_id] = obj
|
|
for prop_name in obj.type.properties:
|
|
try:
|
|
prop_val = obj.get_property(prop_name)
|
|
except exceptions.UninitializedPropertyAccessError:
|
|
continue
|
|
self._get_objects_by_id(prop_val, objects)
|
|
elif isinstance(obj, tuple):
|
|
for item in obj:
|
|
self._get_objects_by_id(item, objects)
|
|
elif isinstance(obj, utils.FrozenDict):
|
|
for k, v in obj.items():
|
|
self._get_objects_by_id(k, objects)
|
|
self._get_objects_by_id(v, objects)
|
|
return objects
|
|
|
|
@staticmethod
|
|
def _check_present(obj_id, objects):
|
|
if obj_id not in objects.keys():
|
|
raise ValueError('No such object, obj_id: {0}'
|
|
.format(obj_id))
|
|
|
|
|
|
class RemoveObjectAction(base.ModifyActionBase, ActionUtils):
|
|
"""Remove object from given model"""
|
|
|
|
def __init__(self, object_id):
|
|
"""Initializes action parameters
|
|
|
|
:param object_id: id of an object
|
|
"""
|
|
self._object_id = object_id
|
|
|
|
@staticmethod
|
|
def _match_object_id(obj_id, obj):
|
|
return isinstance(obj, mo.MuranoObject) and obj_id == obj.object_id
|
|
|
|
def modify(self, obj):
|
|
"""Remove object from given model"""
|
|
objects = self._get_objects_by_id(obj)
|
|
self._check_present(self._object_id, objects)
|
|
|
|
for _obj in objects.values():
|
|
for prop_name in _obj.type.properties:
|
|
try:
|
|
val = _obj.get_property(prop_name)
|
|
except exceptions.UninitializedPropertyAccessError:
|
|
continue
|
|
if self._match_object_id(self._object_id, val):
|
|
_obj.set_property(prop_name, None)
|
|
# remove object from list
|
|
elif isinstance(val, tuple):
|
|
filtered_list = list(val)
|
|
for item in val:
|
|
if self._match_object_id(self._object_id, item):
|
|
filtered_list.remove(item)
|
|
if len(filtered_list) < len(val):
|
|
_obj.set_property(prop_name, tuple(filtered_list))
|
|
# remove object from dict
|
|
elif isinstance(val, utils.FrozenDict):
|
|
filtered_dict = {k: v for k, v in val.items() if not
|
|
self._match_object_id(self._object_id,
|
|
k) and not
|
|
self._match_object_id(self._object_id, v)}
|
|
if len(filtered_dict) < len(val):
|
|
_obj.set_property(prop_name,
|
|
utils.FrozenDict(filtered_dict))
|
|
|
|
|
|
class SetPropertyAction(base.ModifyActionBase, ActionUtils):
|
|
"""Set property on given object"""
|
|
|
|
def __init__(self, object_id, prop_name, value):
|
|
"""Initializes action parameters
|
|
|
|
:param object_id: id of an object
|
|
:param prop_name: property name
|
|
:param value: new value of the property
|
|
"""
|
|
self._object_id = object_id
|
|
self._prop_name = prop_name
|
|
self._value = value
|
|
|
|
def modify(self, obj):
|
|
"""Set property on given object in model"""
|
|
objects = self._get_objects_by_id(obj)
|
|
self._check_present(self._object_id, objects)
|
|
target_obj = objects[self._object_id]
|
|
target_obj.set_property(self._prop_name, self._value)
|
|
|
|
|
|
class RemoveRelationAction(SetPropertyAction):
|
|
"""Remove relation from given model"""
|
|
|
|
def __init__(self, object_id, prop_name):
|
|
super(RemoveRelationAction, self).__init__(object_id, prop_name, None)
|
|
|
|
|
|
class AddObjectAction(base.ModifyActionBase, ActionUtils):
|
|
"""Add new object to object model"""
|
|
|
|
def __init__(self, owner_id, owner_relation, type, init_args):
|
|
"""Initializes action parameters
|
|
|
|
:param owner_id: id of an owner
|
|
:param owner_relation: name of relation on owner
|
|
:param type: new object type
|
|
:param init_args: properties of the new object
|
|
"""
|
|
self._init_args = init_args
|
|
self._type = type
|
|
self._owner_relation = owner_relation
|
|
self._owner_id = owner_id
|
|
|
|
def modify(self, model):
|
|
"""Creates new object and adds it to the model"""
|
|
new_obj = {'type': type}
|
|
new_obj.update(self._init_args)
|
|
objects = self._get_objects_by_id(model)
|
|
self._check_present(self._owner_id, objects)
|
|
owner = objects[self._owner_id]
|
|
# adding objects to list or dict is not supported for now
|
|
owner.set_property(self._owner_relation, new_obj)
|
|
|
|
|
|
class AddRelationAction(base.ModifyActionBase, ActionUtils):
|
|
"""Adds relation between two existing objects within model"""
|
|
|
|
def __init__(self, source_id, relation, target_id):
|
|
"""Initializes action parameters
|
|
|
|
:param source_id: id of an relation source
|
|
:param relation: name of relation on source object
|
|
:param target_id: id of an relation target
|
|
"""
|
|
self._source_id = source_id
|
|
self._relation = relation
|
|
self._target_id = target_id
|
|
|
|
def modify(self, model):
|
|
"""Creates new object and adds it to the model"""
|
|
objects = self._get_objects_by_id(model)
|
|
self._check_present(self._source_id, objects)
|
|
self._check_present(self._target_id, objects)
|
|
source = objects[self._source_id]
|
|
target = objects[self._target_id]
|
|
# adding objects to list or dict is not supported for now
|
|
source.set_property(self._relation, target)
|