688dcd0f88
This patch removes cfg import unused in murano/api/middleware/version_negotiation.py murano/api/versions.py murano/db/catalog/api.py murano/engine/system/test_fixture.py murano/policy/model_policy_enforcer.py murano/tests/unit/cmd/test_api_workers.py murano/tests/unit/cmd/test_engine_workers.py Change-Id: I0f12f15e4def84550ef5bde0840006211cac7809
176 lines
6.0 KiB
Python
176 lines
6.0 KiB
Python
# Copyright (c) 2014 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.
|
|
|
|
import re
|
|
|
|
try:
|
|
# integration with congress is optional
|
|
import congressclient.v1.client as congress_client
|
|
except ImportError as congress_client_import_error:
|
|
congress_client = None
|
|
from oslo_log import log as logging
|
|
|
|
from murano.common import auth_utils
|
|
from murano.common.i18n import _, _LI
|
|
from murano.policy import congress_rules
|
|
from murano.policy.modify.actions import action_manager as am
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class ValidationError(Exception):
|
|
"""Raised for validation errors."""
|
|
pass
|
|
|
|
|
|
class ModelPolicyEnforcer(object):
|
|
"""Policy Enforcer Implementation using Congress client
|
|
|
|
Converts murano model to list of congress data rules.
|
|
|
|
We ask congress using simulation api of congress rest client
|
|
to resolve "murano_system:predeploy_errors(env_id, obj_id, msg)"
|
|
table along with congress data rules to return validation results.
|
|
"""
|
|
|
|
def __init__(self, execution_session, action_manager=None):
|
|
self._execution_session = execution_session
|
|
self._action_manager = action_manager or am.ModifyActionManager()
|
|
self._client = None
|
|
|
|
def _create_client(self):
|
|
if not congress_client:
|
|
# congress client was not imported
|
|
raise congress_client_import_error
|
|
return congress_client.Client(
|
|
**auth_utils.get_session_client_parameters(
|
|
service_type='policy',
|
|
execution_session=self._execution_session))
|
|
|
|
@property
|
|
def client(self):
|
|
if self._client is None:
|
|
self._client = self._create_client()
|
|
return self._client
|
|
|
|
def modify(self, obj, package_loader=None):
|
|
"""Modifies model using Congress rule engine.
|
|
|
|
@type obj: object model
|
|
@param obj: Representation of model starting on
|
|
environment level (['Objects'])
|
|
@type class_loader: murano.dsl.class_loader.MuranoClassLoader
|
|
@param class_loader: Optional. Used for evaluating parent class types
|
|
@raises ValidationError in case validation was not successful
|
|
"""
|
|
|
|
model = obj.to_dictionary()
|
|
|
|
LOG.debug('Modifying model')
|
|
LOG.debug(model)
|
|
|
|
env_id = model['?']['id']
|
|
|
|
result = self._execute_simulation(package_loader, env_id, model,
|
|
'predeploy_modify(eid, oid, action)')
|
|
|
|
raw_actions = result["result"]
|
|
if raw_actions:
|
|
actions = self._parse_simulation_result('predeploy_modify',
|
|
env_id, raw_actions)
|
|
for action in actions:
|
|
self._action_manager.apply_action(obj, action)
|
|
|
|
def validate(self, model, package_loader=None):
|
|
"""Validate model using Congress rule engine.
|
|
|
|
@type model: dict
|
|
@param model: Dictionary representation of model starting on
|
|
environment level (['Objects'])
|
|
@type package_loader: murano.dsl.package_loader.MuranoPackageLoader
|
|
@param package_loader: Optional. Used for evaluating parent class types
|
|
@raises ValidationError in case validation was not successful
|
|
"""
|
|
|
|
if model is None:
|
|
return
|
|
|
|
env_id = model['?']['id']
|
|
|
|
validation_result = self._execute_simulation(
|
|
package_loader, env_id, model,
|
|
'predeploy_errors(eid, oid, msg)')
|
|
|
|
if validation_result["result"]:
|
|
|
|
messages = self._parse_simulation_result(
|
|
'predeploy_errors', env_id,
|
|
validation_result["result"])
|
|
|
|
if messages:
|
|
result_str = "\n ".join(map(str, messages))
|
|
msg = _("Murano object model validation failed: {0}").format(
|
|
"\n " + result_str)
|
|
LOG.error(msg)
|
|
raise ValidationError(msg)
|
|
else:
|
|
LOG.info(_LI('Model valid'))
|
|
|
|
def _execute_simulation(self, package_loader, env_id, model, query):
|
|
rules = congress_rules.CongressRulesManager().convert(
|
|
model, package_loader, self._execution_session.project_id)
|
|
rules_str = list(map(str, rules))
|
|
# cleanup of data populated by murano driver
|
|
rules_str.insert(0, 'deleteEnv("{0}")'.format(env_id))
|
|
rules_line = " ".join(rules_str)
|
|
LOG.debug('Congress rules: \n {rules} '
|
|
.format(rules='\n '.join(rules_str)))
|
|
|
|
validation_result = self.client.execute_policy_action(
|
|
"murano_system",
|
|
"simulate",
|
|
False,
|
|
False,
|
|
{'query': query,
|
|
'action_policy': 'murano_action',
|
|
'sequence': rules_line})
|
|
return validation_result
|
|
|
|
@staticmethod
|
|
def _parse_simulation_result(query, env_id, results):
|
|
"""Transforms the list of results
|
|
|
|
Transforms a list of strings in format:
|
|
|
|
['predeploy_errors("env_id_1", "obj_id_1", "message1")',
|
|
'predeploy_errors("env_id_2", "obj_id_2", "message2")']
|
|
|
|
to a list of strings with message only filtered to provided
|
|
env_id (e.g. 'env_id_1'):
|
|
|
|
['message2']
|
|
"""
|
|
|
|
messages = []
|
|
regexp = query + '\("([^"]*)",\s*"([^"]*)",\s*"(.*)"\)'
|
|
for result in results:
|
|
match = re.search(regexp, result)
|
|
if match:
|
|
if env_id in match.group(1):
|
|
messages.append(match.group(3))
|
|
|
|
return messages
|