diff options
Diffstat (limited to 'moon_manager/moon_manager/plugins')
-rw-r--r-- | moon_manager/moon_manager/plugins/__init__.py | 12 | ||||
-rw-r--r-- | moon_manager/moon_manager/plugins/global_attrs.py | 582 | ||||
-rw-r--r-- | moon_manager/moon_manager/plugins/moon_keystone_plugin.py | 77 | ||||
-rw-r--r-- | moon_manager/moon_manager/plugins/moon_nova_plugin.py | 71 | ||||
-rw-r--r-- | moon_manager/moon_manager/plugins/moon_openstack_plugin.py | 203 | ||||
-rw-r--r-- | moon_manager/moon_manager/plugins/pyorchestrator.py | 493 | ||||
-rw-r--r-- | moon_manager/moon_manager/plugins/sql.py | 2085 |
7 files changed, 3523 insertions, 0 deletions
diff --git a/moon_manager/moon_manager/plugins/__init__.py b/moon_manager/moon_manager/plugins/__init__.py new file mode 100644 index 00000000..1856aa2c --- /dev/null +++ b/moon_manager/moon_manager/plugins/__init__.py @@ -0,0 +1,12 @@ +# Software Name: MOON + +# Version: 5.4 + +# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors +# SPDX-License-Identifier: Apache-2.0 + +# This software is distributed under the 'Apache License 2.0', +# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt' +# or see the "LICENSE" file for more details. + + diff --git a/moon_manager/moon_manager/plugins/global_attrs.py b/moon_manager/moon_manager/plugins/global_attrs.py new file mode 100644 index 00000000..fdf51fd4 --- /dev/null +++ b/moon_manager/moon_manager/plugins/global_attrs.py @@ -0,0 +1,582 @@ +# Software Name: MOON + +# Version: 5.4 + +# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors +# SPDX-License-Identifier: Apache-2.0 + +# This software is distributed under the 'Apache License 2.0', +# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt' +# or see the "LICENSE" file for more details. + +""" +Plugin to request OpenStack infrastructure: +- Keystone +- Nova +""" + +import json +import logging +import time +import requests +from moon_manager.pip_driver import InformationDriver +from moon_manager.api.configuration import get_configuration +from moon_utilities import exceptions + +LOGGER = logging.getLogger("moon.manager.plugins.global_attrs") + +PLUGIN_TYPE = "information" + + +class AttrsConnector(InformationDriver): + + def __init__(self, driver_name, engine_name): + self.driver_name = driver_name + self.engine_name = engine_name + self.conf = get_configuration("information").get("global_attrs", {}) + self.drivers = {} + + def driver(self, driver_name="file"): + if driver_name.startswith("file"): + if not self.drivers.get("file"): + self.drivers["file"] = AttrsConnectorFile() + return self.drivers["file"] + if driver_name == "http": + if not self.drivers.get("file"): + self.drivers["http"] = AttrsConnectorHTTP() + return self.drivers["http"] + if driver_name == "mysql": + if not self.drivers.get("file"): + self.drivers["mysql"] = AttrsConnectorSQL() + return self.drivers["sql"] + if driver_name == "sqlite": + if not self.drivers.get("file"): + self.drivers["sqlite"] = AttrsConnectorSQL() + return self.drivers["sql"] + if driver_name == "driver": + if not self.drivers.get("file"): + self.drivers["driver"] = AttrsConnectorDriver() + return self.drivers["driver"] + + def set_auth(self, **kwargs): + """Set authorizations if necessary + + :param kwargs: arguments which are necessary to login to the server + :return: headers to use + """ + raise NotImplementedError + + def unset_auth(self, **kwargs): + """Unset the authorization is necessary + + :param kwargs: arguments which are necessary to logout to the server + :return: headers to use + """ + raise NotImplementedError + + def get_objects(self, object_id=None, object_type=None, **kwargs): + """List objects in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to list the object + :return: a list of objects + """ + if not object_type: + object_type = list(self.conf.get("attributes").keys()) + elif isinstance(object_type, str): + object_type = [object_type, ] + + results = {} + for _type in object_type: + if _type in self.conf.get("attributes"): + driver_name = self.conf.get("attributes").get(_type).get("url").split(":")[0] + value = self.driver(driver_name).get_object(_type, **kwargs) + results[_type] = { + "id": _type, + "value": value, + "values": self.conf.get("attributes").get(_type).get("values"), + "default": self.conf.get("attributes").get(_type).get("default") + } + else: + raise exceptions.AttributeUnknownError( + "Cannot find global attribute {}".format(object_type)) + return results + + def get_object(self, object_type=None, **kwargs): + """List specific object in the server + + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to list the object + :return: a list of objects + """ + if object_type in self.conf.get("attributes"): + driver_name = self.conf.get("attributes").get(object_type).get("url").split(":")[0] + value = self.driver(driver_name).get_object(object_type, **kwargs) + return { + "id": object_type, + "value": value, + "values": self.conf.get("attributes").get(object_type).get("values"), + "default": self.conf.get("attributes").get(object_type).get("default") + } + else: + raise exceptions.AttributeUnknownError( + "Cannot find global attribute {}".format(object_type)) + + def add_object(self, object_id=None, object_type=None, **kwargs): + """Add an object in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to add the object + :return: the object added + """ + if object_type in self.conf.get("attributes"): + driver_name = self.conf.get("attributes").get(object_type).get("url").split(":")[0] + value = self.driver(driver_name).add_object(object_id, object_type, **kwargs) + return { + "id": object_type, + "value": value, + "values": self.conf.get("attributes").get(object_type).get("values"), + "default": self.conf.get("attributes").get(object_type).get("default") + } + raise exceptions.AttributeUnknownError( + "Cannot find global attribute {}".format(object_type)) + + def update_object(self, object_id, object_type=None, **kwargs): + """Update an object in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to update the object + :return: the object updated + """ + if object_type in self.conf.get("attributes"): + driver_name = self.conf.get("attributes").get(object_type).get("url").split(":")[0] + value = self.driver(driver_name).update_object(object_id, object_type, **kwargs) + return { + "id": object_type, + "value": value, + "values": self.conf.get("attributes").get(object_type).get("values"), + "default": self.conf.get("attributes").get(object_type).get("default") + } + raise exceptions.AttributeUnknownError( + "Cannot find global attribute {}".format(object_type)) + + def delete_object(self, object_id=None, object_type=None, **kwargs): + """Delete an object in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to delete the object + :return: True if the object has been deleted + """ + if object_type in self.conf.get("attributes"): + driver_name = self.conf.get("attributes").get(object_type).get("url").split(":")[0] + value = self.driver(driver_name).delete_object(object_id, object_type, **kwargs) + return { + "id": object_type, + "value": value, + "values": self.conf.get("attributes").get(object_type).get("values"), + "default": self.conf.get("attributes").get(object_type).get("default") + } + raise exceptions.AttributeUnknownError( + "Cannot find global attribute {}".format(object_type)) + + +class AttrsConnectorFile: + + def __init__(self): + self.conf = get_configuration("information").get("global_attrs", {}) + + def set_auth(self, **kwargs): + """Set authorizations if necessary + + :param kwargs: arguments which are necessary to login to the server + :return: headers to use + """ + raise NotImplementedError + + def unset_auth(self, **kwargs): + """Unset the authorization is necessary + + :param kwargs: arguments which are necessary to logout to the server + :return: headers to use + """ + raise NotImplementedError + + def get_objects(self, object_id=None, object_type=None, **kwargs): + """List objects in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to list the object + :return: a list of objects + """ + if not object_type: + object_type = list(self.conf.get("attributes").keys()) + elif isinstance(object_type, str): + object_type = [object_type, ] + + for _type in object_type: + filename = self.conf.get("attributes").get(_type).get("url").split(":")[1].strip() + try: + yield {_type: open(filename).read().strip()} + except FileNotFoundError: + LOGGER.error("Cannot find file name {}".format(filename)) + yield {_type: self.conf.get("attributes").get(_type).get("default")} + + def get_object(self, object_type, **kwargs): + """Get specific object in the server + + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to list the object + :return: a list of objects + """ + filename = self.conf.get("attributes").get(object_type).get("url").split(":")[1].strip() + try: + return open(filename).read().strip() + except FileNotFoundError: + LOGGER.error("Cannot find file name {}".format(filename)) + return self.conf.get("attributes").get(object_type).get("default") + + def add_object(self, object_id=None, object_type=None, **kwargs): + """Add an object in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to add the object + :return: the object added + """ + filename = self.conf.get("attributes").get(object_type).get("url").split(":")[1].strip() + default_value = self.conf.get("attributes").get(object_type).get("default") + open(filename, "w").write(default_value) + return default_value + + def update_object(self, object_id, object_type=None, **kwargs): + """Update an object in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to update the object + :return: the object updated + """ + filename = self.conf.get("attributes").get(object_type).get("url").split(":")[1].strip() + values = self.conf.get("attributes").get(object_type).get("values") + if object_id in values: + open(filename, "w").write(object_id) + return object_id + raise exceptions.AttributeValueUnknownError( + "The given value ({}) is not part of the authorized values ({})".format( + object_id, ", ".join(values))) + + def delete_object(self, object_id=None, object_type=None, **kwargs): + """Delete an object in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to delete the object + :return: True if the object has been deleted + """ + filename = self.conf.get("attributes").get(object_type).get("url").split(":")[1].strip() + default_value = self.conf.get("attributes").get(object_type).get("default") + open(filename, "w").write(default_value) + return default_value + + +class AttrsConnectorHTTP: + + def __init__(self): + self.conf = get_configuration("information").get("global_attrs", {}) + + def set_auth(self, **kwargs): + """Set authorizations if necessary + + :param kwargs: arguments which are necessary to login to the server + :return: headers to use + """ + raise NotImplementedError + + def unset_auth(self, **kwargs): + """Unset the authorization is necessary + + :param kwargs: arguments which are necessary to logout to the server + :return: headers to use + """ + raise NotImplementedError + + def get_users(self, user_id=None, **kwargs): + """List users in the server + + :param user_id: the user name or user ID + :param kwargs: all arguments necessary to list users + :return: a list of users + """ + raise NotImplementedError + + def add_user(self, user_id=None, **kwargs): + """Add a user in the server + + :param user_id: the user name or user ID + :param kwargs: all arguments necessary to add a user + :return: the user added + """ + raise NotImplementedError + + def update_user(self, user_id, **kwargs): + """Update a user in the server + + :param user_id: the user name or user ID + :param kwargs: all arguments necessary to update the user + :return: the user updated + """ + raise NotImplementedError + + def delete_user(self, user_id, **kwargs): + """Delete a user in the server + + :param user_id: the user name or user ID + :param kwargs: all arguments necessary to delete the user + :return: True if the user has been deleted + """ + raise NotImplementedError + + def get_objects(self, object_id=None, object_type=None, **kwargs): + """List objects in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to list the object + :return: a list of objects + """ + raise NotImplementedError + + def add_object(self, object_id=None, object_type=None, **kwargs): + """Add an object in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to add the object + :return: the object added + """ + raise NotImplementedError + + def update_object(self, object_id, object_type=None, **kwargs): + """Update an object in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to update the object + :return: the object updated + """ + raise NotImplementedError + + def delete_object(self, object_id=None, object_type=None, **kwargs): + """Delete an object in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to delete the object + :return: True if the object has been deleted + """ + raise NotImplementedError + + +class AttrsConnectorSQL: + + def __init__(self): + self.conf = get_configuration("information").get("global_attrs", {}) + + def set_auth(self, **kwargs): + """Set authorizations if necessary + + :param kwargs: arguments which are necessary to login to the server + :return: headers to use + """ + raise NotImplementedError + + def unset_auth(self, **kwargs): + """Unset the authorization is necessary + + :param kwargs: arguments which are necessary to logout to the server + :return: headers to use + """ + raise NotImplementedError + + def get_users(self, user_id=None, **kwargs): + """List users in the server + + :param user_id: the user name or user ID + :param kwargs: all arguments necessary to list users + :return: a list of users + """ + raise NotImplementedError + + def add_user(self, user_id=None, **kwargs): + """Add a user in the server + + :param user_id: the user name or user ID + :param kwargs: all arguments necessary to add a user + :return: the user added + """ + raise NotImplementedError + + def update_user(self, user_id, **kwargs): + """Update a user in the server + + :param user_id: the user name or user ID + :param kwargs: all arguments necessary to update the user + :return: the user updated + """ + raise NotImplementedError + + def delete_user(self, user_id, **kwargs): + """Delete a user in the server + + :param user_id: the user name or user ID + :param kwargs: all arguments necessary to delete the user + :return: True if the user has been deleted + """ + raise NotImplementedError + + def get_objects(self, object_id=None, object_type=None, **kwargs): + """List objects in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to list the object + :return: a list of objects + """ + raise NotImplementedError + + def add_object(self, object_id=None, object_type=None, **kwargs): + """Add an object in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to add the object + :return: the object added + """ + raise NotImplementedError + + def update_object(self, object_id, object_type=None, **kwargs): + """Update an object in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to update the object + :return: the object updated + """ + raise NotImplementedError + + def delete_object(self, object_id=None, object_type=None, **kwargs): + """Delete an object in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to delete the object + :return: True if the object has been deleted + """ + raise NotImplementedError + + +class AttrsConnectorDriver: + + def __init__(self): + self.conf = get_configuration("information").get("global_attrs", {}) + + def set_auth(self, **kwargs): + """Set authorizations if necessary + + :param kwargs: arguments which are necessary to login to the server + :return: headers to use + """ + raise NotImplementedError + + def unset_auth(self, **kwargs): + """Unset the authorization is necessary + + :param kwargs: arguments which are necessary to logout to the server + :return: headers to use + """ + raise NotImplementedError + + def get_users(self, user_id=None, **kwargs): + """List users in the server + + :param user_id: the user name or user ID + :param kwargs: all arguments necessary to list users + :return: a list of users + """ + raise NotImplementedError + + def add_user(self, user_id=None, **kwargs): + """Add a user in the server + + :param user_id: the user name or user ID + :param kwargs: all arguments necessary to add a user + :return: the user added + """ + raise NotImplementedError + + def update_user(self, user_id, **kwargs): + """Update a user in the server + + :param user_id: the user name or user ID + :param kwargs: all arguments necessary to update the user + :return: the user updated + """ + raise NotImplementedError + + def delete_user(self, user_id, **kwargs): + """Delete a user in the server + + :param user_id: the user name or user ID + :param kwargs: all arguments necessary to delete the user + :return: True if the user has been deleted + """ + raise NotImplementedError + + def get_objects(self, object_id=None, object_type=None, **kwargs): + """List objects in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to list the object + :return: a list of objects + """ + raise NotImplementedError + + def add_object(self, object_id=None, object_type=None, **kwargs): + """Add an object in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to add the object + :return: the object added + """ + raise NotImplementedError + + def update_object(self, object_id, object_type=None, **kwargs): + """Update an object in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to update the object + :return: the object updated + """ + raise NotImplementedError + + def delete_object(self, object_id=None, object_type=None, **kwargs): + """Delete an object in the server + + :param object_id: the object name or user ID + :param object_type: the object type (project, vms, ...) + :param kwargs: all arguments necessary to delete the object + :return: True if the object has been deleted + """ + raise NotImplementedError + + +class Connector(AttrsConnector): + pass diff --git a/moon_manager/moon_manager/plugins/moon_keystone_plugin.py b/moon_manager/moon_manager/plugins/moon_keystone_plugin.py new file mode 100644 index 00000000..0fb9b363 --- /dev/null +++ b/moon_manager/moon_manager/plugins/moon_keystone_plugin.py @@ -0,0 +1,77 @@ +# Software Name: MOON + +# Version: 5.4 + +# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors +# SPDX-License-Identifier: Apache-2.0 + +# This software is distributed under the 'Apache License 2.0', +# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt' +# or see the "LICENSE" file for more details. + +""" +Plugin to request OpenStack infrastructure: +- Keystone +""" + +from moon_manager.plugins.moon_openstack_plugin import * + +LOGGER = logging.getLogger("moon.manager.plugins.moon_keystone_plugin") + +PLUGIN_TYPE = "information" +_ = str + + +class KeystoneConnector(OpenStackConnector): + + def get_items(self, item_id=None, **kwargs): + username = "" + domain_id = "" + if "username" in kwargs: + username = kwargs['username'] + if "domain_id" in kwargs: + domain_id = kwargs['domain_id'] + if username and domain_id: + return self._get(endpoint="/users?name={}&domain_id={}".format(username, domain_id), + _exception=KeystoneUserError) + elif username: + return self._get(endpoint="/users?name={}".format(username), + _exception=KeystoneUserError) + elif domain_id: + return self._get(endpoint="/users?domain_id={}".format(domain_id), + _exception=KeystoneUserError) + else: + return self._get(endpoint="/users", + _exception=KeystoneUserError) + + def add_item(self, item_id=None, **kwargs): + if 'name' not in kwargs: + raise KeystoneError("Cannot find name in request") + _user = { + "user": { + "enabled": True, + "name": kwargs['name'], + } + } + if 'project' in kwargs: + _user['user']['default_project_id'] = kwargs['project'] + if 'domain' in kwargs: + _user['user']['domain_id'] = kwargs['domain'] + if 'password' in kwargs: + _user['user']['password'] = kwargs['password'] + try: + return self._post(endpoint="/users/", + data=_user, + _exception=KeystoneUserError) + except KeystoneUserConflict: + return True + + def update_item(self, item_id, **kwargs): + raise NotImplementedError() # pragma: no cover + + def delete_item(self, item_id, **kwargs): + raise NotImplementedError() # pragma: no cover + + +class Connector(KeystoneConnector): + pass diff --git a/moon_manager/moon_manager/plugins/moon_nova_plugin.py b/moon_manager/moon_manager/plugins/moon_nova_plugin.py new file mode 100644 index 00000000..0848152e --- /dev/null +++ b/moon_manager/moon_manager/plugins/moon_nova_plugin.py @@ -0,0 +1,71 @@ +# Software Name: MOON + +# Version: 5.4 + +# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors +# SPDX-License-Identifier: Apache-2.0 + +# This software is distributed under the 'Apache License 2.0', +# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt' +# or see the "LICENSE" file for more details. + +""" +Plugin to request OpenStack infrastructure: +- Nova +""" + +from moon_manager.plugins.moon_openstack_plugin import * + +LOGGER = logging.getLogger("moon.manager.plugins.moon_nova_plugin") + +PLUGIN_TYPE = "information" +_ = str + +# Nova exceptions + + +class NovaError(MoonError): + description = _("There is an error connecting to Nova.") + code = 400 + title = 'Nova error' + logger = "ERROR" + + +class NovaProjectError(NovaError): + description = _("There is an error retrieving projects from the Nova service.") + code = 400 + title = 'Nova project error' + logger = "ERROR" + + +class NovaUserError(NovaError): + description = _("There is an error retrieving users from the Nova service.") + code = 400 + title = 'Nova user error' + logger = "ERROR" + + +class NovaUserConflict(NovaUserError): + description = _("A user with that name already exist.") + code = 400 + title = 'Nova user error' + logger = "ERROR" + + +class NovaConnector(OpenStackConnector): + + def get_items(self, item_id=None, **kwargs): + return self._get(endpoint="/servers", _exception=NovaProjectError) + + def add_item(self, object_id=None, **kwargs): + raise NotImplementedError() # pragma: no cover + + def update_item(self, item_id, **kwargs): + raise NotImplementedError() # pragma: no cover + + def delete_item(self, item_id, **kwargs): + raise NotImplementedError() # pragma: no cover + + +class Connector(NovaConnector): + pass diff --git a/moon_manager/moon_manager/plugins/moon_openstack_plugin.py b/moon_manager/moon_manager/plugins/moon_openstack_plugin.py new file mode 100644 index 00000000..a4b8a237 --- /dev/null +++ b/moon_manager/moon_manager/plugins/moon_openstack_plugin.py @@ -0,0 +1,203 @@ +# Software Name: MOON + +# Version: 5.4 + +# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors +# SPDX-License-Identifier: Apache-2.0 + +# This software is distributed under the 'Apache License 2.0', +# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt' +# or see the "LICENSE" file for more details. + +""" +Abstract plugin to request OpenStack infrastructure +""" + +import json +import logging +import time +import requests +from moon_manager.pip_driver import InformationDriver +from moon_manager.api.configuration import get_configuration +from moon_utilities.exceptions import MoonError + +LOGGER = logging.getLogger("moon.manager.plugins.moon_openstack_plugin") + +PLUGIN_TYPE = "information" +_ = str + + +# Keystone exceptions + + +class KeystoneError(MoonError): + description = _("There is an error connecting to Keystone.") + code = 400 + title = 'Keystone error' + logger = "ERROR" + + +class KeystoneProjectError(KeystoneError): + description = _("There is an error retrieving projects from the Keystone service.") + code = 400 + title = 'Keystone project error' + logger = "ERROR" + + +class KeystoneUserError(KeystoneError): + description = _("There is an error retrieving users from the Keystone service.") + code = 400 + title = 'Keystone user error' + logger = "ERROR" + + +class KeystoneUserConflict(KeystoneUserError): + description = _("A user with that name already exist.") + code = 400 + title = 'Keystone user error' + logger = "ERROR" + + +class OpenStackConnector(InformationDriver): + + def __init__(self, driver_name, engine_name, conf): + self.driver_name = driver_name + self.engine_name = engine_name + self.opst_conf = get_configuration("information") + + if not self.opst_conf: + raise Exception("Cannot find OpenStack configuration in configuration file") + + self.__headers = {} + self.__user = conf.get("user", self.opst_conf['user']) + self.__password = conf.get("password", self.opst_conf['password']) + self.__domain = conf.get("domain", self.opst_conf['domain']) + self.__project = conf.get("project", self.opst_conf['project']) + self.__url = conf.get("url", self.opst_conf['url']) + + def set_auth(self, **kwargs): + start_time = time.time() + user = kwargs.get("user", self.opst_conf['user']) + password = kwargs.get("password", self.opst_conf['password']) + domain = kwargs.get("domain", self.opst_conf['domain']) + project = kwargs.get("project", self.opst_conf['project']) + url = kwargs.get("url", self.opst_conf['url']) + headers = { + "Content-Type": "application/json" + } + data_auth = { + "auth": { + "identity": { + "methods": [ + "password" + ], + "password": { + "user": { + "domain": { + "id": domain + }, + "name": user, + "password": password + } + } + }, + "scope": { + "project": { + "domain": { + "id": domain + }, + "name": project + } + } + } + } + + while True: + req = requests.post("{}/auth/tokens".format(url), + json=data_auth, headers=headers, + verify=kwargs.get("certificate", self.opst_conf['certificate'])) + + if req.status_code in (200, 201, 204): + self.__headers['X-Auth-Token'] = req.headers['X-Subject-Token'] + return self.__headers + LOGGER.warning("Waiting for Keystone...") + if time.time() - start_time == 100: + LOGGER.error(req.text) + raise KeystoneError + time.sleep(5) + + def unset_auth(self, **kwargs): + url = kwargs.get("url", self.opst_conf['url']) + self.__headers['X-Subject-Token'] = self.__headers['X-Auth-Token'] + req = requests.delete("{}/auth/tokens".format(url), headers=self.__headers, + verify=kwargs.get("certificate", self.opst_conf['certificate'])) + if req.status_code in (200, 201, 204): + return + LOGGER.error(req.text) + raise KeystoneError + + def _get(self, endpoint, url=None, _exception=KeystoneError): + if not url: + if not self.__url: + LOGGER.warning("Cannot retrieve the URL for the OpenStack endpoint") + return {'users': []} + url = self.__url + + req = requests.get("{}{}".format(url, endpoint), + headers=self.__headers) + if req.status_code not in (200, 201): + LOGGER.error(req.text) + raise _exception + data = req.json() + return data + + def _post(self, endpoint, url=None, data=None, _exception=KeystoneError): + if not url: + if not self.__url: + LOGGER.warning("Cannot retrieve the URL for the OpenStack endpoint") + return {'users': []} + url = self.__url + + req = requests.post("{}{}".format(url, endpoint), + data=json.dumps(data), + headers=self.__headers) + if req.status_code == 409: + LOGGER.warning(req.text) + raise KeystoneUserConflict + if req.status_code not in (200, 201): + LOGGER.error(req.text) + raise _exception + data = req.json() + return data + + def create_project(self, **tenant_dict): + if "name" not in tenant_dict: + raise KeystoneProjectError("Cannot get the project name.") + _project = { + "project": { + "description": tenant_dict['description'], + "domain_id": tenant_dict['domain'], + "enabled": tenant_dict['enabled'], + "is_domain": tenant_dict['is_domain'], + "name": tenant_dict['name'] + } + } + return self._post(endpoint="/projects/", + url=self.opst_conf["url"], + data=_project, + _exception=KeystoneProjectError) + + def get_projects(self): + return self._get(endpoint="/projects/", url=self.opst_conf["url"], _exception=KeystoneProjectError) + + def get_items(self, item_id=None, **kwargs): + raise NotImplementedError() # pragma: no cover + + def add_item(self, item_id=None, **kwargs): + raise NotImplementedError() # pragma: no cover + + def update_item(self, item_id, **kwargs): + raise NotImplementedError() # pragma: no cover + + def delete_item(self, item_id, **kwargs): + raise NotImplementedError() # pragma: no cover diff --git a/moon_manager/moon_manager/plugins/pyorchestrator.py b/moon_manager/moon_manager/plugins/pyorchestrator.py new file mode 100644 index 00000000..736e9144 --- /dev/null +++ b/moon_manager/moon_manager/plugins/pyorchestrator.py @@ -0,0 +1,493 @@ +# Software Name: MOON + +# Version: 5.4 + +# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors +# SPDX-License-Identifier: Apache-2.0 + +# This software is distributed under the 'Apache License 2.0', +# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt' +# or see the "LICENSE" file for more details. + +""" +PyOrchestrator plugin +""" +import logging +import os +import time +import subprocess # nosec +from uuid import uuid4 +import requests +import yaml +from moon_manager.orchestration_driver import SlaveDriver +from moon_manager.orchestration_driver import PipelineDriver +from moon_manager import db_driver +from moon_manager.api.configuration import get_configuration +from moon_utilities.auth_functions import get_api_key_for_user, xor_decode +from moon_utilities import exceptions +from datetime import datetime + +LOGGER = logging.getLogger("moon.manager.orchestrator.driver.pyorchestrator") + +PLUGIN_TYPE = "orchestration" +WRAPPERS = {} +PORTS = [] + + +def init(): + """ + Initialize the plugin by initializing wrappers + :return: nothing + """ + + slaves = db_driver.SlaveManager.get_slaves(moon_user_id="admin") + # TODO: check if server with UUID is not already up and running + for _slave in slaves: + LOGGER.info("testing PDP {}".format(_slave)) + if _slave not in WRAPPERS: + start_new_server(_slave, slaves[_slave]) + + +def create_gunicorn_config(host, port, uuid): + """ + Create a Gunicorn config file in a temporary directory + :return: filename + """ + config_dir = get_configuration("orchestration").get("config_dir", "/tmp") # nosec + # (/tmp is a fallback solution) + filename = os.path.join(config_dir, "gunicorn_{}.cfg".format(uuid)) + file_descriptor = open(filename, "w") + file_descriptor.write("""bind = "{host}:{port}" +workers = {workers} +moon = "{moon_filename}" + """.format( + host=host, + port=port, + workers=1, + moon_filename=os.path.join(config_dir, "moon_{}.yaml".format(uuid)), + )) + file_descriptor.close() + return filename + + +def create_moon_config(uuid, data): + """ + Create a Gunicorn config file in a temporary directory + :return: filename + """ + _log_config = get_configuration("logging") + config_dir = get_configuration("orchestration").get("config_dir", "/tmp") # nosec + # (/tmp is a fallback solution) + _log_config["handlers"]["file"]["filename"] = os.path.join(config_dir, + "moon_{}.log".format(uuid)) + __manager_url = get_configuration("management")["url"] + api_token = get_api_key_for_user(get_configuration("management")["user"]) + filename = os.path.join(config_dir, "moon_{}.yaml".format(uuid)) + pwd_file = os.path.join(get_configuration("orchestration")["config_dir"], + "db_{}.json".format(uuid)) + config_dict = { + "type": "wrapper", + "uuid": str(uuid), + "management": { + "url": __manager_url, + "user": get_configuration("management")["user"], + "password": get_configuration("management")["password"], + "token_file": pwd_file + }, + "incremental_updates": False, + "api_token": api_token, + "data": "", + "logging": _log_config, + "orchestration": { + "driver": "moon_engine.plugins.pyorchestrator", + "connection": "local", + "port": "20000...20100", + "config_dir": config_dir + }, + "authorization": {"driver": "moon_engine.plugins.authz"}, + "plugins": {"directory": get_configuration("plugins")["directory"]}, + "debug": get_configuration(key='debug', default=False), + "grant_if_unknown_project": data.get("grant_if_unknown_project") + } + LOGGER.info("Writing config file to {}".format(filename)) + yaml.dump(config_dict, open(filename, "w"), default_flow_style=False) + return filename + + +def kill_server(uuid): + """ + Kill the server given its UUID + :param uuid: UUID of the server + :return: nothing + """ + if uuid in WRAPPERS: + LOGGER.info("Killing server {} after {} of uptime".format( + uuid, str(datetime.now() - datetime.fromtimestamp(WRAPPERS[uuid]["starttime"])) + )) + with open(WRAPPERS[uuid]["process"], 'r') as pid_file: + try: + pid = int(pid_file.read()) + except ValueError: + LOGGER.error("The pid found in {} is not valid".format(WRAPPERS[uuid]["process"])) + return + + os.kill(pid, 15) + del_server_port(WRAPPERS[uuid]["port"]) + WRAPPERS.pop(uuid) + else: + LOGGER.warning("Cannot find UUID {} in wrappers or interfaces".format(uuid)) + + +def get_ports_range(): + """ + Get the range inside we can create new server + :return: (port_min, port_max) + """ + ports_range = get_configuration("orchestration")["port"] + return int(ports_range.split(".")[0]), int(ports_range.split(".")[-1]) + + +def get_next_port(server_host="127.0.0.1"): + """ + Check the next free TCP port for this host + :param server_host: the server host + :return: a TCP port (int) + """ + port_min, port_max = get_ports_range() + _port = port_min + _ports = [] + for _wrapper in WRAPPERS: + _ports.append(WRAPPERS[_wrapper]["port"]) + _ports.sort() + if not _ports: + _port = port_min + elif _ports[-1] + 1 > port_max: + raise Exception( + "Cannot add a new slave because " + "the port range is bounded to {}".format(port_max)) + while True: + if _port in _ports: + _port += 1 + continue + try: + requests.get("http://{}:{}/status".format(server_host, _port), timeout=1) + except requests.exceptions.ConnectionError: + break + if _port > port_max: + raise Exception( + "Cannot add a new slave because " + "the port range is bounded to {}".format(port_max)) + _port += 1 + return _port + + +def add_server_port(port): + """ + Append the server port in cache + :param port: TCP port + :return: None + """ + PORTS.append(port) + + +def del_server_port(port): + """ + Delete the server port in cache + :param port: TCP port + :return: None + """ + try: + PORTS.remove(port) + except ValueError: + LOGGER.warning("port {} is not in the known port".format(port)) + + +def get_server_url(uuid=None): + """ + Retrieve the server URL for this Slave ID + If no server can be found, return None + :param uuid: slave ID + :return: a URL or None + """ + if not uuid: + return + url = "" + try: + if uuid in WRAPPERS: + url = "http://{}:{}".format(WRAPPERS[uuid]["server_ip"], + WRAPPERS[uuid]["port"]) + LOGGER.debug(f"url in get_server_url '{url}'") + if url: + response = requests.get(url + "/status") + if response.status_code == 200: + return url + except TimeoutError as _exception: + LOGGER.warning("A timeout occurred when connecting to {}".format(url)) + # if port has not be found in local data, try to get information from remote servers + port_min, port_max = get_ports_range() + # FIXME: all servers may be not on localhost + host = "127.0.0.1" + LOGGER.debug(f"Go search through slaves") + for _port in range(port_min, port_max): + try: + req = requests.get("http://{}:{}/status".format(host, _port), timeout=1) + data = req.json() + if "status" in data and data["status"]["uuid"] == uuid: + return "http://{}:{}".format(host, _port) + except Exception as _exception: + LOGGER.warning("Error getting information from {}:{} ({})".format(host, _port, str(_exception))) + return + + +def start_new_server(uuid, data): + """Start a new server in a new process + + :param uuid: UUID of the server + :param data: data of the server + :return: nothing + """ + _url = get_server_url(uuid) + config_dir = get_configuration("orchestration").get("config_dir", "/tmp") # nosec + # (/tmp is a fallback solution) + config_filename = os.path.join(config_dir, "moon_{}.yaml".format(uuid)) + # FIXME: maybe the server is not on the 127.0.0.1 + server_ip = "127.0.0.1" + LOGGER.info("Starting server {} {}".format(_url, uuid)) + # debug = get_configuration("debug", False) + if _url: + _port = int(_url.split(":")[-1]) + add_server_port(_port) + WRAPPERS[uuid] = { + "starttime": data["extra"].get("starttime"), + "port": _port, + "server_ip": server_ip, + "name": data.get("name"), + "status": "up", + "process": data.get("process"), + "api_key": data.get("api_key"), + "log": data.get("log") + } + else: + _port = get_next_port() + pid_file = os.path.join(config_dir, uuid + ".pid") + # NOTE: we have actually no solution to get the actual IP address + # so we need to put 0.0.0.0 in the host address + gunicorn_config = create_gunicorn_config(host="0.0.0.0", # nosec + port=_port, + uuid=uuid) + create_moon_config(uuid=uuid, data=data) + _command = ["gunicorn", "moon_engine.server:__hug_wsgi__", "--threads", "10", + "--log-level", "debug", "--log-file", gunicorn_config.replace("cfg", "log"), + "-p", pid_file, "-c", gunicorn_config] + LOGGER.info("command: {}".format(" ".join(_command))) + WRAPPERS[uuid] = { + "starttime": time.time(), + "port": _port, + "server_ip": server_ip, + "name": data.get("name"), + "status": "down", + "process": pid_file, + } + subprocess.Popen(_command, stdout=subprocess.PIPE, close_fds=True) # nosec + # Note: wait the process creation + time.sleep(1) + config = yaml.safe_load(open(config_filename)) + log_file = config["logging"]["handlers"]["file"]["filename"] + WRAPPERS[uuid]["log"] = log_file + for cpt in range(10): + try: + f_sock = open(log_file) + except FileNotFoundError: + time.sleep(1) + else: + break + else: + LOGGER.error("Cannot find log file ({})".format(log_file)) + return + p_sock = 0 + LOGGER.info("Process running") + WRAPPERS[uuid]["status"] = "up" + while True: + f_sock.seek(p_sock) + latest_data = f_sock.read() + p_sock = f_sock.tell() + if latest_data and "APIKEY" in latest_data: + _index_start = latest_data.index("APIKEY=") + len("APIKEY=") + _index_stop = latest_data.index("\n", _index_start) + key = latest_data[_index_start:_index_stop].strip() + api_key = get_api_key_for_user("admin") + try: + engine_api_key = xor_decode(key, api_key) + LOGGER.info(f"key={key}") + LOGGER.info(f"engine_api_key={engine_api_key}") + except exceptions.DecryptError: + engine_api_key = False + WRAPPERS[uuid]["api_key"] = engine_api_key + break + time.sleep(1) + + +class SlaveConnector(SlaveDriver): + """ + Connector to Slave API + """ + + def __init__(self, driver_name, engine_name): + self.driver_name = driver_name + self.engine_name = engine_name + + def update_slave(self, slave_id, value): + LOGGER.info("Updating the slave {} with {}".format(slave_id, value)) + slave_url = WRAPPERS[slave_id]['server_ip'] + slave_port = WRAPPERS[slave_id]['port'] + + config_dir = get_configuration("orchestration").get("config_dir", "/tmp") # nosec + config_filename = os.path.join(config_dir, "moon_{}.yaml".format(slave_id)) + + conf = yaml.safe_load(open(config_filename, 'r')) + for key in value: + if key in conf: + conf[key] = value[key] + + os.remove(config_filename) + yaml.dump(conf, open(config_filename, "w"), default_flow_style=False) + + req = requests.put("http://{}:{}/update".format(slave_url, slave_port), + headers={"x-api-key": WRAPPERS[slave_id]["api_key"]}) + return req + + def delete_slave(self, slave_id): + LOGGER.info("Deleting slave {}".format(slave_id)) + kill_server(slave_id) + + def add_slave(self, slave_id=None, data=None): + LOGGER.info("Adding slave {} {}".format(slave_id, data)) + if not slave_id: + slave_id = uuid4().hex + start_new_server(slave_id, data) + return WRAPPERS[slave_id] + + def get_slaves(self, slave_id=None): + LOGGER.info("Get slaves {}".format(WRAPPERS)) + results = {} + for wrapper in WRAPPERS: + results[wrapper] = { + "starttime": WRAPPERS[wrapper]["starttime"], + "port": WRAPPERS[wrapper]["port"], + "server_ip": WRAPPERS[wrapper]["server_ip"], + "name": WRAPPERS[wrapper]["name"], + "status": "down", + "log": WRAPPERS[wrapper]["log"] + } + try: + req = requests.get("http://{}:{}/status".format( + WRAPPERS[wrapper]["server_ip"], + WRAPPERS[wrapper]["port"] + )) + if req.status_code == 200: + results[wrapper]["status"] = "up" + else: + results[wrapper]["status"] = "down" + LOGGER.info("get_slaves: {} {} {}".format( + slave_id, req.status_code, results[wrapper]["status"])) + except TimeoutError: + LOGGER.warning("Timeout connecting {} on port {}".format( + WRAPPERS[wrapper]["server_ip"], + WRAPPERS[wrapper]["port"] + )) + except requests.exceptions.ConnectionError: + results[wrapper]["status"] = "down" + return results + + +class PipelineConnector(PipelineDriver): + """ + Connector to Pipeline API + """ + + def __init__(self, driver_name, engine_name): + self.driver_name = driver_name + self.engine_name = engine_name + + def update_pipeline(self, pipeline_id, data): + for _wrapper in WRAPPERS: + _url = get_server_url(_wrapper) + req = requests.put("{}/update/pdp/{}".format(_url, pipeline_id), + headers={"x-api-key": WRAPPERS[_wrapper]["api_key"]}, + json=data) + if req.status_code == 206: + LOGGER.warning("No pipeline available...") + elif req.status_code != 202: + LOGGER.warning("Error sending upgrade command to pipeline ({})".format(req.text)) + + def delete_pipeline(self, pipeline_id): + LOGGER.info("Deleting pipeline {}".format(pipeline_id)) + for _wrapper in WRAPPERS: + if WRAPPERS[_wrapper]['status'] == "down": + continue + # FIXME: we should manage https here + _url = "http://{}:{}".format(WRAPPERS[_wrapper]['server_ip'], + WRAPPERS[_wrapper]['port']) + req = requests.delete("{}/pipeline/{}".format(_url, pipeline_id), + headers={"x-api-key": WRAPPERS[_wrapper]["api_key"]}) + LOGGER.info("{}/pipeline/{}".format(_url, pipeline_id)) + if req.status_code != 200: + LOGGER.error("Cannot delete the pipeline in slave {} ({}, {})".format( + _wrapper, req.status_code, req.content)) + # FIXME: make a request to the correct wrapper + + def add_pipeline(self, pipeline_id=None, data=None): + LOGGER.info("Adding POD in manager {} {}".format(pipeline_id, data)) + if not pipeline_id: + pipeline_id = uuid4().hex + slaves = data.get("slaves", []) + pipelines = [] + for _wrapper in WRAPPERS: + if slaves and (WRAPPERS[_wrapper]['name'] not in slaves): + continue + # FIXME: we should manage https here + _url = "http://{}:{}".format(WRAPPERS[_wrapper]['server_ip'], + WRAPPERS[_wrapper]['port']) + req = requests.put("{}/pipeline/{}".format(_url, pipeline_id), json=data, + headers={"x-api-key": WRAPPERS[_wrapper]['api_key']}) + if req.status_code != 200: + LOGGER.error("Cannot create a new pipeline ({}, {})".format(req.status_code, + req.content)) + elif "pipelines" not in req.json(): + LOGGER.error("Cannot create a new pipeline ({}, {})".format(req.status_code, + req.content)) + else: + pipelines.append(req.json()) + LOGGER.info("Pipeline created {}".format(pipelines)) + return pipelines + # FIXME: make a request to the correct wrapper + + def get_pipelines(self, slave_id=None, pipeline_id=None): + results = {} + for _wrapper in WRAPPERS: + if slave_id and _wrapper != slave_id: + continue + if WRAPPERS[_wrapper]['status'] == "down": + continue + results[_wrapper] = {} + # FIXME: we should manage https here + _url = "http://{}:{}".format(WRAPPERS[_wrapper]['server_ip'], + WRAPPERS[_wrapper]['port']) + req = requests.get("{}/pipelines".format(_url), + headers={"x-api-key": WRAPPERS[_wrapper]['api_key']}) + if req.status_code != 200: + LOGGER.error("Cannot get information for slave {} ({}, {})".format( + _wrapper, req.status_code, req.content)) + else: + # FIXME: filter on pipeline_id + results[_wrapper] = req.json() + return results + + +class Connector(SlaveConnector, PipelineConnector): + """ + General connector to get all APIs in one endpoint + """ + + def __init__(self, *args, **kwargs): + init() diff --git a/moon_manager/moon_manager/plugins/sql.py b/moon_manager/moon_manager/plugins/sql.py new file mode 100644 index 00000000..de850a5c --- /dev/null +++ b/moon_manager/moon_manager/plugins/sql.py @@ -0,0 +1,2085 @@ +# Software Name: MOON + +# Version: 5.4 + +# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors +# SPDX-License-Identifier: Apache-2.0 + +# This software is distributed under the 'Apache License 2.0', +# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt' +# or see the "LICENSE" file for more details. + + +import copy +import json +import logging +from contextlib import contextmanager +from uuid import uuid4 + +import sqlalchemy +import sqlalchemy as sql +from moon_manager.api import configuration +from moon_manager.db_driver import PDPDriver, PolicyDriver, ModelDriver, SlaveDriver +from moon_utilities import exceptions +from sqlalchemy import create_engine +from sqlalchemy import types as sql_types +from sqlalchemy.ext.declarative import declarative_base, declared_attr +from sqlalchemy.orm import sessionmaker + +logger = logging.getLogger("moon.manager.db.driver.sql") + +PLUGIN_TYPE = "db" + +Base = declarative_base() +DEBUG = True if configuration.get_configuration( + "logging")['loggers']['moon']['level'] == "DEBUG" else False + + +class DictBase: + attributes = [] + + @classmethod + def from_dict(cls, d): + new_d = d.copy() + return cls(**new_d) + # new_d = d.copy() + # + # new_d['extra'] = {k: new_d.pop(k) for k in six.iterkeys(d) + # if k not in cls.attributes and k != 'extra'} + # + # return cls(**new_d) + + def to_dict(self): + d = dict() + for attr in self.__class__.attributes: + d[attr] = getattr(self, attr) + return d + + def __getitem__(self, key): + # if "extra" in dir(self) and key in self.extra: + # return self.extra[key] + return getattr(self, key) + + +class JsonBlob(sql_types.TypeDecorator): + impl = sql.Text + + def process_bind_param(self, value, dialect): + return json.dumps(value) + + def process_result_value(self, value, dialect): + return json.loads(value) + + +class Model(Base, DictBase): + __tablename__ = 'models' + attributes = ['id', 'name', 'value'] + id = sql.Column(sql.String(64), primary_key=True) + name = sql.Column(sql.String(256), nullable=False) + value = sql.Column(JsonBlob(), nullable=True) + + def to_dict(self): + return { + "name": self.name, + "description": self.value.get("description", ""), + "meta_rules": self.value.get("meta_rules", list()), + } + + +class Policy(Base, DictBase): + __tablename__ = 'policies' + attributes = ['id', 'name', 'model_id', 'value'] + id = sql.Column(sql.String(64), primary_key=True) + name = sql.Column(sql.String(256), nullable=False) + model_id = sql.Column(sql.String(64), nullable=True, default="") + value = sql.Column(JsonBlob(), nullable=True) + + def to_dict(self): + return { + "description": self.value.get("description", ""), + "genre": self.value.get("genre", ""), + "model_id": self.model_id, + "name": self.name + } + + +class PDP(Base, DictBase): + __tablename__ = 'pdp' + attributes = ['id', 'name', 'vim_project_id', 'value'] + id = sql.Column(sql.String(64), primary_key=True) + name = sql.Column(sql.String(256), nullable=False) + vim_project_id = sql.Column(sql.String(64), nullable=True, default="") + value = sql.Column(JsonBlob(), nullable=True) + + def to_dict(self): + return { + "name": self.name, + "description": self.value.get("description", ""), + "vim_project_id": self.vim_project_id, + "security_pipeline": self.value.get("security_pipeline", []), + } + + +class Slave(Base, DictBase): + __tablename__ = 'slaves' + attributes = ['id', 'name', 'address', 'process', 'log', 'api_key', 'value'] + id = sql.Column(sql.String(64), primary_key=True) + name = sql.Column(sql.String(256), nullable=False) + address = sql.Column(sql.String(256), nullable=True, default="") + process = sql.Column(sql.String(256), nullable=False, default="") + log = sql.Column(sql.String(256), nullable=False, default="") + api_key = sql.Column(sql.String(256), nullable=False, default="") + value = sql.Column(JsonBlob(), nullable=True) + grant_if_unknown_project = sql.Column(sql.Boolean(), nullable=False, default=True) + + def to_dict(self): + return { + "name": self.name, + "address": self.address, + "description": self.value.get("description", ""), + "grant_if_unknown_project": self.grant_if_unknown_project, + "process": self.process, + "log": self.log, + "api_key": self.api_key, + "extra": self.value + } + + +class PerimeterCategoryBase(DictBase): + attributes = ['id', 'name', 'description'] + id = sql.Column(sql.String(64), primary_key=True) + name = sql.Column(sql.String(256), nullable=False) + description = sql.Column(sql.String(256), nullable=True) + + +class SubjectCategory(Base, PerimeterCategoryBase): + __tablename__ = 'subject_categories' + + +class ObjectCategory(Base, PerimeterCategoryBase): + __tablename__ = 'object_categories' + + +class ActionCategory(Base, PerimeterCategoryBase): + __tablename__ = 'action_categories' + + +class PerimeterBase(DictBase): + attributes = ['id', 'name', 'value'] + id = sql.Column(sql.String(64), primary_key=True) + name = sql.Column(sql.String(256), nullable=False) + value = sql.Column(JsonBlob(), nullable=True) + __mapper_args__ = {'concrete': True} + + def __repr__(self): + return "{} with name {} : {}".format(self.id, self.name, json.dumps(self.value)) + + def to_return(self): + return { + 'id': self.id, + 'name': self.name, + 'description': self.value.get("description", ""), + 'email': self.value.get("email", ""), + 'extra': self.value.get("extra", dict()), + 'policy_list': self.value.get("policy_list", []) + } + + def to_dict(self): + dict_value = copy.deepcopy(self.value) + dict_value["name"] = self.name + return { + 'id': self.id, + 'value': dict_value + } + + +class Subject(Base, PerimeterBase): + __tablename__ = 'subjects' + + +class Object(Base, PerimeterBase): + __tablename__ = 'objects' + + +class Action(Base, PerimeterBase): + __tablename__ = 'actions' + + +class PerimeterDataBase(DictBase): + attributes = ['id', 'name', 'value', 'category_id', 'policy_id'] + id = sql.Column(sql.String(64), primary_key=True) + name = sql.Column(sql.String(256), nullable=False) + value = sql.Column(JsonBlob(), nullable=True) + + @declared_attr + def policy_id(cls): + return sql.Column(sql.ForeignKey("policies.id"), nullable=False) + + def to_dict(self): + return { + 'id': self.id, + 'name': self.name, + 'description': self.value.get("description", ""), + 'category_id': self.category_id, + 'policy_id': self.policy_id + } + + +class SubjectData(Base, PerimeterDataBase): + __tablename__ = 'subject_data' + category_id = sql.Column(sql.ForeignKey("subject_categories.id"), nullable=False) + + +class ObjectData(Base, PerimeterDataBase): + __tablename__ = 'object_data' + category_id = sql.Column(sql.ForeignKey("object_categories.id"), nullable=False) + + +class ActionData(Base, PerimeterDataBase): + __tablename__ = 'action_data' + category_id = sql.Column(sql.ForeignKey("action_categories.id"), nullable=False) + + +class PerimeterAssignmentBase(DictBase): + attributes = ['id', 'assignments', 'policy_id', 'subject_id', 'category_id'] + id = sql.Column(sql.String(64), primary_key=True) + assignments = sql.Column(JsonBlob(), nullable=True) + category_id = None + + @declared_attr + def policy_id(cls): + return sql.Column(sql.ForeignKey("policies.id"), nullable=False) + + def _to_dict(self, element_key, element_value): + return { + "id": self.id, + "policy_id": self.policy_id, + element_key: element_value, + "category_id": self.category_id, + "assignments": self.assignments, + } + + +class SubjectAssignment(Base, PerimeterAssignmentBase): + __tablename__ = 'subject_assignments' + subject_id = sql.Column(sql.ForeignKey("subjects.id"), nullable=False) + category_id = sql.Column(sql.ForeignKey("subject_categories.id"), nullable=False) + + def to_dict(self): + return self._to_dict("subject_id", self.subject_id) + + +class ObjectAssignment(Base, PerimeterAssignmentBase): + __tablename__ = 'object_assignments' + attributes = ['id', 'assignments', 'policy_id', 'object_id', 'category_id'] + object_id = sql.Column(sql.ForeignKey("objects.id"), nullable=False) + category_id = sql.Column(sql.ForeignKey("object_categories.id"), nullable=False) + + def to_dict(self): + return self._to_dict("object_id", self.object_id) + + +class ActionAssignment(Base, PerimeterAssignmentBase): + __tablename__ = 'action_assignments' + attributes = ['id', 'assignments', 'policy_id', 'action_id', 'category_id'] + action_id = sql.Column(sql.ForeignKey("actions.id"), nullable=False) + category_id = sql.Column(sql.ForeignKey("action_categories.id"), nullable=False) + + def to_dict(self): + return self._to_dict("action_id", self.action_id) + + +class MetaRule(Base, DictBase): + __tablename__ = 'meta_rules' + attributes = ['id', 'name', 'subject_categories', 'object_categories', 'action_categories', + 'value'] + id = sql.Column(sql.String(64), primary_key=True) + name = sql.Column(sql.String(256), nullable=False) + subject_categories = sql.Column(JsonBlob(), nullable=True) + object_categories = sql.Column(JsonBlob(), nullable=True) + action_categories = sql.Column(JsonBlob(), nullable=True) + value = sql.Column(JsonBlob(), nullable=True) + + def to_dict(self): + return { + "name": self.name, + "description": self.value.get("description", ""), + "subject_categories": self.subject_categories, + "object_categories": self.object_categories, + "action_categories": self.action_categories, + } + + +class Rule(Base, DictBase): + __tablename__ = 'rules' + attributes = ['id', 'rule', 'policy_id', 'meta_rule_id'] + id = sql.Column(sql.String(64), primary_key=True) + rule = sql.Column(JsonBlob(), nullable=True) + policy_id = sql.Column(sql.ForeignKey("policies.id"), nullable=False) + meta_rule_id = sql.Column(sql.ForeignKey("meta_rules.id"), nullable=False) + + def to_dict(self): + return { + 'id': self.id, + 'rule': self.rule["rule"], + 'instructions': self.rule["instructions"], + 'enabled': self.rule["enabled"], + 'policy_id': self.policy_id, + 'meta_rule_id': self.meta_rule_id + } + + def __repr__(self): + return "{}".format(self.rule) + + +@contextmanager +def session_scope(engine): + """Provide a transactional scope around a series of operations.""" + if type(engine) is str: + echo = DEBUG + engine = create_engine(engine, echo=echo) + session = sessionmaker(bind=engine)() + try: + yield session + session.commit() + except: + session.rollback() + raise + finally: + session.close() + + +class BaseConnector(object): + """Provide a base connector to connect them all""" + engine = "" + + def __init__(self, engine_name): + echo = DEBUG + self.engine = create_engine(engine_name, echo=echo) + + def init_db(self): + Base.metadata.create_all(self.engine) + + def set_engine(self, engine_name): + self.engine = engine_name + + def get_session(self): + return session_scope(self.engine) + + def get_session_for_read(self): + return self.get_session() + + def get_session_for_write(self): + return self.get_session() + + +class PDPConnector(BaseConnector, PDPDriver): + + def update_pdp(self, pdp_id, value): + try: + with self.get_session_for_write() as session: + query = session.query(PDP) + query = query.filter_by(id=pdp_id) + ref = query.first() + if ref: + value_wo_name = copy.deepcopy(value) + value_wo_name.pop("name", None) + value_wo_name.pop("vim_project_id", None) + ref.name = value["name"] + ref.vim_project_id = value.get("vim_project_id", "") + d = dict(ref.value) + d.update(value_wo_name) + setattr(ref, "value", d) + return {ref.id: ref.to_dict()} + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.PdpExisting + raise error + + def delete_policy_from_pdp(self, pdp_id, policy_id): + with self.get_session_for_write() as session: + ref = session.query(PDP).get(pdp_id) + if ref: + if policy_id in ref.value['security_pipeline']: + __value = copy.deepcopy(ref.value) + __value['security_pipeline'].remove(policy_id) + setattr(ref, "value", __value) + return {ref.id: ref.to_dict()} + return {} + + def delete_pdp(self, pdp_id): + with self.get_session_for_write() as session: + ref = session.query(PDP).get(pdp_id) + session.delete(ref) + + def add_pdp(self, pdp_id=None, value=None): + try: + with self.get_session_for_write() as session: + value_wo_name = copy.deepcopy(value) + value_wo_name.pop("name", None) + value_wo_name.pop("vim_project_id", None) + new = PDP.from_dict({ + "id": pdp_id if pdp_id else uuid4().hex, + "name": value["name"], + "vim_project_id": value["vim_project_id"], + "value": value_wo_name + }) + session.add(new) + return {new.id: new.to_dict()} + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.PdpExisting + raise error + + def get_pdp(self, pdp_id=None): + with self.get_session_for_read() as session: + query = session.query(PDP) + if pdp_id: + query = query.filter_by(id=pdp_id) + ref_list = query.all() + return {_ref.id: _ref.to_dict() for _ref in ref_list} + + +class SlaveConnector(BaseConnector, SlaveDriver): + + def update_slave(self, slave_id, value): + try: + with self.get_session_for_write() as session: + query = session.query(Slave) + query = query.filter_by(id=slave_id) + ref = query.first() + if ref: + value_wo_name = copy.deepcopy(value) + value_wo_name.pop("name", None) + value_wo_name.pop("address", None) + value_wo_name.pop("grant_if_unknown_project", None) + # ref.name = value["name"] + if 'address' in value: + ref.address = value.get("address") + if 'grant_if_unknown_project' in value: + ref.grant_if_unknown_project = value.get("grant_if_unknown_project") + d = dict(ref.value) + d.update(value_wo_name) + setattr(ref, "value", d) + return {ref.id: ref.to_dict()} + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.PdpExisting + raise error + + def delete_slave(self, slave_id): + with self.get_session_for_write() as session: + ref = session.query(Slave).get(slave_id) + session.delete(ref) + + def add_slave(self, slave_id=None, value=None): + try: + with self.get_session_for_write() as session: + value_wo_name = copy.deepcopy(value) + value_wo_name.pop("name", None) + value_wo_name.pop("address", None) + value_wo_name.pop("grant_if_unknown_project", None) + new = Slave.from_dict({ + "id": slave_id if slave_id else uuid4().hex, + "name": value["name"], + "address": value.get("address", ""), + "grant_if_unknown_project": value.get("grant_if_unknown_project"), + "log": "", + "process": "", + "api_key": "", + "value": value_wo_name + }) + session.add(new) + return {new.id: new.to_dict()} + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.PdpExisting + raise error + + def get_slaves(self, slave_id=None): + with self.get_session_for_read() as session: + query = session.query(Slave) + if slave_id: + query = query.filter_by(id=slave_id) + ref_list = query.all() + return {_ref.id: _ref.to_dict() for _ref in ref_list} + + +class PolicyConnector(BaseConnector, PolicyDriver): + + def update_policy(self, policy_id, value): + try: + with self.get_session_for_write() as session: + query = session.query(Policy) + query = query.filter_by(id=policy_id) + ref = query.first() + + if ref: + value_wo_other_info = copy.deepcopy(value) + value_wo_other_info.pop("name", None) + value_wo_other_info.pop("model_id", None) + ref.name = value["name"] + ref.model_id = value["model_id"] + d = dict(ref.value) + d.update(value_wo_other_info) + setattr(ref, "value", d) + return {ref.id: ref.to_dict()} + + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.PolicyExisting + raise error + + def delete_policy(self, policy_id): + with self.get_session_for_write() as session: + ref = session.query(Policy).get(policy_id) + session.delete(ref) + + def add_policy(self, policy_id=None, value=None): + try: + with self.get_session_for_write() as session: + value_wo_other_info = copy.deepcopy(value) + value_wo_other_info.pop("name", None) + value_wo_other_info.pop("model_id", None) + new = Policy.from_dict({ + "id": policy_id if policy_id else uuid4().hex, + "name": value["name"], + "model_id": value.get("model_id", ""), + "value": value_wo_other_info + }) + session.add(new) + return {new.id: new.to_dict()} + + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.PolicyExisting + raise error + + def get_policies(self, policy_id=None, policy_name=None): + with self.get_session_for_read() as session: + query = session.query(Policy) + if policy_id: + query = query.filter_by(id=policy_id) + elif policy_name: + query = query.filter_by(name=policy_name) + + ref_list = query.all() + return {_ref.id: _ref.to_dict() for _ref in ref_list} + + def __get_perimeters(self, ClassType, policy_id, perimeter_id=None): + + with self.get_session_for_read() as session: + query = session.query(ClassType) + + if perimeter_id: + query = query.filter_by(id=perimeter_id) + + ref_list = copy.deepcopy(query.all()) + + if policy_id: + results = [] + for _ref in ref_list: + _ref_value = _ref.to_return() + if policy_id in _ref_value["policy_list"]: + results.append(_ref) + return {_ref.id: _ref.to_return() for _ref in results} + return {_ref.id: _ref.to_return() for _ref in ref_list} + + def __get_perimeter_by_name(self, ClassType, perimeter_name): + # if not policy_id: + # raise exceptions.PolicyUnknown + with self.get_session_for_read() as session: + query = session.query(ClassType) + if not perimeter_name or not perimeter_name.strip(): + raise exceptions.PerimeterContentError('invalid name') + query = query.filter_by(name=perimeter_name) + ref_list = copy.deepcopy(query.all()) + return {_ref.id: _ref.to_return() for _ref in ref_list} + + def __update_perimeter(self, class_type, class_type_exception, perimeter_id, value): + if not perimeter_id: + return exceptions.PerimeterContentError + with self.get_session_for_write() as session: + query = session.query(class_type) + query = query.filter_by(id=perimeter_id) + _perimeter = query.first() + if not _perimeter: + raise class_type_exception + temp_perimeter = copy.deepcopy(_perimeter.to_dict()) + if 'name' in value: + temp_perimeter['value']['name'] = value['name'] + if 'description' in value: + temp_perimeter['value']['description'] = value['description'] + if 'extra' in value: + temp_perimeter['value']['extra'] = value['extra'] + if 'email' in value: + temp_perimeter['value']['email'] = value['email'] + name = temp_perimeter['value']['name'] + temp_perimeter['value'].pop("name", None) + new_perimeter = class_type.from_dict({ + "id": temp_perimeter["id"], + "name": name, + "value": temp_perimeter["value"] + }) + _perimeter.value = new_perimeter.value + _perimeter.name = new_perimeter.name + return {_perimeter.id: _perimeter.to_return()} + + def __set_perimeter(self, ClassType, ClassTypeException, policy_id, perimeter_id=None, + value=None): + if not value or "name" not in value or not value["name"].strip(): + raise exceptions.PerimeterContentError('invalid name') + with self.get_session_for_write() as session: + _perimeter = None + if perimeter_id: + query = session.query(ClassType) + query = query.filter_by(id=perimeter_id) + _perimeter = query.first() + if not perimeter_id and not _perimeter: + query = session.query(ClassType) + query = query.filter_by(name=value['name']) + _perimeter = query.first() + if _perimeter: + raise ClassTypeException + if not _perimeter: + value_wo_name = copy.deepcopy(value) + if "policy_list" not in value_wo_name or type( + value_wo_name["policy_list"]) is not list: + value_wo_name["policy_list"] = [] + if policy_id and policy_id not in value_wo_name["policy_list"]: + value_wo_name["policy_list"] = [policy_id, ] + + value_wo_name.pop("name", None) + new = ClassType.from_dict({ + "id": perimeter_id if perimeter_id else uuid4().hex, + "name": value["name"], + "value": value_wo_name + }) + session.add(new) + return {new.id: new.to_return()} + else: + _value = copy.deepcopy(_perimeter.to_dict()) + if "policy_list" not in _value["value"] or type( + _value["value"]["policy_list"]) is not list: + _value["value"]["policy_list"] = [] + if policy_id and policy_id not in _value["value"]["policy_list"]: + _value["value"]["policy_list"].append(policy_id) + else: + if policy_id: + raise exceptions.PolicyExisting + raise exceptions.PerimeterContentError + + _value["value"].update(value) + + name = _value["value"]["name"] + _value["value"].pop("name") + new_perimeter = ClassType.from_dict({ + "id": _value["id"], + "name": name, + "value": _value["value"] + }) + _perimeter.value = new_perimeter.value + _perimeter.name = new_perimeter.name + return {_perimeter.id: _perimeter.to_return()} + + def __delete_perimeter(self, ClassType, ClassUnknownException, policy_id, perimeter_id): + with self.get_session_for_write() as session: + query = session.query(ClassType) + query = query.filter_by(id=perimeter_id) + _perimeter = query.first() + if not _perimeter: + raise ClassUnknownException + if not _perimeter.value["policy_list"]: + session.delete(_perimeter) + else: + if not policy_id: + raise exceptions.PolicyUnknown + + old_perimeter = copy.deepcopy(_perimeter.to_dict()) + try: + old_perimeter["value"]["policy_list"].remove(policy_id) + new_perimeter = ClassType.from_dict(old_perimeter) + + + # else: + # if new_perimeter.value["policy_list"]: + setattr(_perimeter, "value", getattr(new_perimeter, "value")) + except ValueError: + if not _perimeter.value["policy_list"]: + session.delete(_perimeter) + + def get_subjects(self, policy_id, perimeter_id=None): + return self.__get_perimeters(Subject, policy_id, perimeter_id) + + def get_subject_by_name(self, perimeter_name): + return self.__get_perimeter_by_name(Subject, perimeter_name) + + def set_subject(self, policy_id, perimeter_id=None, value=None): + try: + return self.__set_perimeter(Subject, exceptions.SubjectExisting, policy_id, + perimeter_id=perimeter_id, value=value) + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.SubjectExisting + raise error + + def update_subject(self, perimeter_id, value): + try: + return self.__update_perimeter(Subject, exceptions.SubjectExisting, perimeter_id, value) + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.SubjectExisting + raise error + + def delete_subject(self, policy_id, perimeter_id): + self.__delete_perimeter(Subject, exceptions.SubjectUnknown, policy_id, perimeter_id) + + def get_objects(self, policy_id, perimeter_id=None): + return self.__get_perimeters(Object, policy_id, perimeter_id) + + def get_object_by_name(self, perimeter_name): + return self.__get_perimeter_by_name(Object, perimeter_name) + + def set_object(self, policy_id, perimeter_id=None, value=None): + try: + return self.__set_perimeter(Object, exceptions.ObjectExisting, policy_id, + perimeter_id=perimeter_id, value=value) + except sqlalchemy.exc.IntegrityError as error: + logger.exception("IntegrityError {}".format(error)) + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.ObjectExisting + raise error + + def update_object(self, perimeter_id, value): + try: + return self.__update_perimeter(Object, exceptions.ObjectExisting, perimeter_id, value) + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.ObjectExisting + raise error + + def delete_object(self, policy_id, perimeter_id): + self.__delete_perimeter(Object, exceptions.ObjectUnknown, policy_id, perimeter_id) + + def get_actions(self, policy_id, perimeter_id=None): + return self.__get_perimeters(Action, policy_id, perimeter_id) + + def get_action_by_name(self, perimeter_name): + return self.__get_perimeter_by_name(Action, perimeter_name) + + def set_action(self, policy_id, perimeter_id=None, value=None): + try: + return self.__set_perimeter(Action, exceptions.ActionExisting, policy_id, + perimeter_id=perimeter_id, value=value) + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.ActionExisting + raise error + + def update_action(self, perimeter_id, value): + try: + return self.__update_perimeter(Action, exceptions.ActionExisting, perimeter_id, value) + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.ActionExisting + raise error + + def delete_action(self, policy_id, perimeter_id): + self.__delete_perimeter(Action, exceptions.ActionUnknown, policy_id, perimeter_id) + + def __is_data_exist(self, ClassType, category_id=None): + + with self.get_session_for_read() as session: + query = session.query(ClassType) + query = query.filter_by(category_id=category_id) + ref_list = query.all() + if ref_list: + return True + return False + + def __get_data(self, ClassType, policy_id, data_id=None, category_id=None): + with self.get_session_for_read() as session: + query = session.query(ClassType) + if policy_id and data_id and category_id: + query = query.filter_by(policy_id=policy_id, id=data_id, category_id=category_id) + elif policy_id and category_id: + query = query.filter_by(policy_id=policy_id, category_id=category_id) + elif category_id: + query = query.filter_by(category_id=category_id) + elif policy_id: + query = query.filter_by(policy_id=policy_id) + else: + raise exceptions.PolicyUnknown + + ref_list = query.all() + return { + "policy_id": policy_id, + "category_id": category_id, + "data": {_ref.id: _ref.to_dict() for _ref in ref_list} + } + + def __set_data(self, ClassType, ClassTypeData, policy_id, data_id=None, category_id=None, + value=None): + with self.get_session_for_write() as session: + query = session.query(ClassTypeData) + query = query.filter_by(policy_id=policy_id, id=data_id, category_id=category_id) + ref = query.first() + if not ref: + value_wo_name = copy.deepcopy(value) + value_wo_name.pop("name", None) + new_ref = ClassTypeData.from_dict( + { + "id": data_id if data_id else uuid4().hex, + 'name': value["name"], + 'value': value_wo_name, + 'category_id': category_id, + 'policy_id': policy_id, + } + ) + session.add(new_ref) + ref = new_ref + else: + for attr in ClassType.attributes: + if attr != 'id': + setattr(ref, attr, getattr(ref, attr)) + # session.flush() + return { + "policy_id": policy_id, + "category_id": category_id, + "data": {ref.id: ref.to_dict()} + } + + def __delete_data(self, ClassType, policy_id, category_id, data_id): + + if not data_id: + raise exceptions.DataUnknown + with self.get_session_for_write() as session: + query = session.query(ClassType) + if category_id: + query = query.filter_by(policy_id=policy_id, category_id=category_id, id=data_id) + else: + query = query.filter_by(policy_id=policy_id, id=data_id) + ref = query.first() + if ref: + session.delete(ref) + + def is_subject_data_exist(self, category_id=None): + return self.__is_data_exist(SubjectData, category_id=category_id) + + def get_subject_data(self, policy_id, data_id=None, category_id=None): + return self.__get_data(SubjectData, policy_id, data_id=data_id, category_id=category_id) + + def set_subject_data(self, policy_id, data_id=None, category_id=None, value=None): + try: + return self.__set_data(Subject, SubjectData, policy_id, data_id=data_id, + category_id=category_id, value=value) + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.SubjectScopeExisting + raise error + + def delete_subject_data(self, policy_id, category_id, data_id): + return self.__delete_data(SubjectData, policy_id, category_id, data_id) + + def is_object_data_exist(self, category_id=None): + return self.__is_data_exist(ObjectData, category_id=category_id) + + def get_object_data(self, policy_id, data_id=None, category_id=None): + return self.__get_data(ObjectData, policy_id, data_id=data_id, category_id=category_id) + + def set_object_data(self, policy_id, data_id=None, category_id=None, value=None): + try: + return self.__set_data(Object, ObjectData, policy_id, data_id=data_id, + category_id=category_id, value=value) + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.ObjectScopeExisting + raise error + + def delete_object_data(self, policy_id, category_id, data_id): + return self.__delete_data(ObjectData, policy_id, category_id, data_id) + + def is_action_data_exist(self, category_id=None): + return self.__is_data_exist(ActionData, category_id=category_id) + + def get_action_data(self, policy_id, data_id=None, category_id=None): + return self.__get_data(ActionData, policy_id, data_id=data_id, category_id=category_id) + + def set_action_data(self, policy_id, data_id=None, category_id=None, value=None): + try: + return self.__set_data(Action, ActionData, policy_id, data_id=data_id, + category_id=category_id, value=value) + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.ActionScopeExisting + raise error + + def delete_action_data(self, policy_id, category_id, data_id): + return self.__delete_data(ActionData, policy_id, category_id, data_id) + + def get_subject_assignments(self, policy_id, subject_id=None, category_id=None): + with self.get_session_for_write() as session: + query = session.query(SubjectAssignment) + if subject_id and category_id: + # TODO change the subject_id to perimeter_id to allow code refactoring + query = query.filter_by(policy_id=policy_id, subject_id=subject_id, + category_id=category_id) + elif subject_id: + query = query.filter_by(policy_id=policy_id, subject_id=subject_id) + else: + query = query.filter_by(policy_id=policy_id) + ref_list = query.all() + return {_ref.id: _ref.to_dict() for _ref in ref_list} + + def add_subject_assignment(self, policy_id, subject_id, category_id, data_id): + with self.get_session_for_write() as session: + query = session.query(SubjectAssignment) + query = query.filter_by(policy_id=policy_id, subject_id=subject_id, + category_id=category_id) + ref = query.first() + if ref: + old_ref = copy.deepcopy(ref.to_dict()) + assignments = old_ref["assignments"] + if data_id not in assignments: + assignments.append(data_id) + setattr(ref, "assignments", assignments) + else: + raise exceptions.SubjectAssignmentExisting + else: + ref = SubjectAssignment.from_dict( + { + "id": uuid4().hex, + "policy_id": policy_id, + "subject_id": subject_id, + "category_id": category_id, + "assignments": [data_id, ], + } + ) + session.add(ref) + return {ref.id: ref.to_dict()} + + def is_subject_category_has_assignment(self, category_id): + return self.__is_category_has_assignment(SubjectAssignment, category_id) + + def is_object_category_has_assignment(self, category_id): + return self.__is_category_has_assignment(ObjectAssignment, category_id) + + def is_action_category_has_assignment(self, category_id): + return self.__is_category_has_assignment(ActionAssignment, category_id) + + def __is_category_has_assignment(self, ClassType, category_id): + with self.get_session_for_write() as session: + query = session.query(ClassType) + query = query.filter_by(category_id=category_id) + count = query.count() + return count > 0 + + def delete_subject_assignment(self, policy_id, subject_id, category_id, data_id): + with self.get_session_for_write() as session: + query = session.query(SubjectAssignment) + + if policy_id and subject_id and category_id: + query = query.filter_by(policy_id=policy_id, subject_id=subject_id, + category_id=category_id) + + elif policy_id and subject_id: + query = query.filter_by(policy_id=policy_id, subject_id=subject_id) + + elif policy_id: + query = query.filter_by(policy_id=policy_id) + + ref_list = query.all() + if ref_list: + for _ref in ref_list: + old_ref = copy.deepcopy(_ref.to_dict()) + assignments = old_ref["assignments"] + if data_id: + if data_id in assignments: + assignments.remove(data_id) + if not assignments: + session.delete(_ref) + else: + # FIXME (asteroide): the setattr doesn't work here ; the assignments is not updated in the database + setattr(_ref, "assignments", assignments) + else: + session.delete(_ref) + + def get_object_assignments(self, policy_id, object_id=None, category_id=None): + with self.get_session_for_write() as session: + query = session.query(ObjectAssignment) + if object_id and category_id: + # TODO change the object_id to perimeter_id to allow code refactoring + query = query.filter_by(policy_id=policy_id, object_id=object_id, + category_id=category_id) + elif object_id: + query = query.filter_by(policy_id=policy_id, object_id=object_id) + else: + query = query.filter_by(policy_id=policy_id) + ref_list = query.all() + return {_ref.id: _ref.to_dict() for _ref in ref_list} + + def add_object_assignment(self, policy_id, object_id, category_id, data_id): + with self.get_session_for_write() as session: + query = session.query(ObjectAssignment) + query = query.filter_by(policy_id=policy_id, object_id=object_id, + category_id=category_id) + ref = query.first() + if ref: + old_ref = copy.deepcopy(ref.to_dict()) + assignments = old_ref["assignments"] + if data_id not in assignments: + assignments.append(data_id) + setattr(ref, "assignments", assignments) + else: + raise exceptions.ObjectAssignmentExisting + else: + ref = ObjectAssignment.from_dict( + { + "id": uuid4().hex, + "policy_id": policy_id, + "object_id": object_id, + "category_id": category_id, + "assignments": [data_id, ], + } + ) + session.add(ref) + return {ref.id: ref.to_dict()} + + def delete_object_assignment(self, policy_id, object_id, category_id, data_id): + with self.get_session_for_write() as session: + query = session.query(ObjectAssignment) + + if policy_id and object_id and category_id: + query = query.filter_by(policy_id=policy_id, object_id=object_id, + category_id=category_id) + elif policy_id and object_id: + query = query.filter_by(policy_id=policy_id, object_id=object_id) + + elif policy_id: + query = query.filter_by(policy_id=policy_id) + + + + ref_list = query.all() + if ref_list: + for _ref in ref_list: + old_ref = copy.deepcopy(_ref.to_dict()) + assignments = old_ref["assignments"] + if data_id: + if data_id in assignments: + assignments.remove(data_id) + if not assignments: + session.delete(_ref) + else: + # FIXME (asteroide): the setattr doesn't work here ; the assignments is not updated in the database + setattr(_ref, "assignments", assignments) + else: + session.delete(_ref) + + def get_action_assignments(self, policy_id, action_id=None, category_id=None): + with self.get_session_for_write() as session: + if not policy_id: + return exceptions.PolicyUnknown + query = session.query(ActionAssignment) + if action_id and category_id: + # TODO change the action_id to perimeter_id to allow code refactoring + query = query.filter_by(policy_id=policy_id, action_id=action_id, + category_id=category_id) + elif action_id: + query = query.filter_by(policy_id=policy_id, action_id=action_id) + elif category_id: + query = query.filter_by(policy_id=policy_id, category_id=category_id) + else: + query = query.filter_by(policy_id=policy_id) + ref_list = query.all() + return {_ref.id: _ref.to_dict() for _ref in ref_list} + + def add_action_assignment(self, policy_id, action_id, category_id, data_id): + with self.get_session_for_write() as session: + query = session.query(ActionAssignment) + query = query.filter_by(policy_id=policy_id, action_id=action_id, + category_id=category_id) + ref = query.first() + if ref: + old_ref = copy.deepcopy(ref.to_dict()) + assignments = old_ref["assignments"] + if data_id not in assignments: + assignments.append(data_id) + setattr(ref, "assignments", assignments) + else: + raise exceptions.ActionAssignmentExisting + else: + ref = ActionAssignment.from_dict( + { + "id": uuid4().hex, + "policy_id": policy_id, + "action_id": action_id, + "category_id": category_id, + "assignments": [data_id, ], + } + ) + session.add(ref) + return {ref.id: ref.to_dict()} + + def delete_action_assignment(self, policy_id, action_id, category_id, data_id): + with self.get_session_for_write() as session: + query = session.query(ActionAssignment) + + if policy_id and action_id and category_id: + query = query.filter_by(policy_id=policy_id, action_id=action_id, + category_id=category_id) + + elif policy_id and action_id: + query = query.filter_by(policy_id=policy_id, action_id=action_id) + + elif policy_id: + query = query.filter_by(policy_id=policy_id) + + + + ref_list = query.all() + if ref_list: + for _ref in ref_list: + old_ref = copy.deepcopy(_ref.to_dict()) + assignments = old_ref["assignments"] + if data_id: + if data_id in assignments: + assignments.remove(data_id) + if not assignments: + session.delete(_ref) + else: + # FIXME (asteroide): the setattr doesn't work here ; the assignments is not updated in the database + setattr(_ref, "assignments", assignments) + else: + session.delete(_ref) + + def get_rules(self, policy_id, rule_id=None, meta_rule_id=None): + with self.get_session_for_read() as session: + query = session.query(Rule) + if rule_id: + query = query.filter_by(id=rule_id) + ref = query.first() + if ref: + return {ref.id: ref.to_dict()} + return {} + elif meta_rule_id and policy_id: + query = query.filter_by(policy_id=policy_id, meta_rule_id=meta_rule_id) + ref_list = query.all() + return { + "meta_rule_id": meta_rule_id, + "policy_id": policy_id, + "rules": list(map(lambda x: x.to_dict(), ref_list)) + } + else: + query = query.filter_by(policy_id=policy_id) + ref_list = query.all() + return { + "policy_id": policy_id, + "rules": list(map(lambda x: x.to_dict(), ref_list)) + } + + def is_meta_rule_has_rules(self, meta_rule_id): + with self.get_session_for_read() as session: + query = session.query(Rule) + + query = query.filter_by(meta_rule_id=meta_rule_id) + count = query.count() + return count > 0 + + def add_rule(self, policy_id, meta_rule_id, value): + try: + rules = self.get_rules(policy_id, meta_rule_id=meta_rule_id) + for _rule in map(lambda x: x["rule"], rules["rules"]): + if list(value.get('rule')) == list(_rule): + raise exceptions.RuleExisting + with self.get_session_for_write() as session: + ref = Rule.from_dict( + { + "id": uuid4().hex, + "policy_id": policy_id, + "meta_rule_id": meta_rule_id, + "rule": value + } + ) + session.add(ref) + return {ref.id: ref.to_dict()} + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.RuleExisting + raise error + + def update_rule(self, rule_id, value): + try: + with self.get_session_for_write() as session: + query = session.query(Rule) + query = query.filter_by(id=rule_id) + ref = query.first() + + if ref: + value_wo_name = copy.deepcopy(value) + value_wo_name.pop('name', None) + value_wo_name.pop('policy_id', None) + value_wo_name.pop('meta_rule_id', None) + d = dict(ref.rule) + d.update(value_wo_name) + ref.rule = d + return {ref.id: ref.to_dict()} + + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.PolicyExisting + raise error + + def delete_rule(self, policy_id, rule_id): + with self.get_session_for_write() as session: + query = session.query(Rule) + query = query.filter_by(policy_id=policy_id, id=rule_id) + ref = query.first() + if ref: + session.delete(ref) + + +class ModelConnector(BaseConnector, ModelDriver): + + def update_model(self, model_id, value): + try: + with self.get_session_for_write() as session: + query = session.query(Model) + if model_id: + query = query.filter_by(id=model_id) + ref = query.first() + if ref: + value_wo_name = copy.deepcopy(value) + value_wo_name.pop("name", None) + setattr(ref, "name", value["name"]) + d = dict(ref.value) + d.update(value_wo_name) + setattr(ref, "value", d) + return {ref.id: ref.to_dict()} + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.ModelExisting + raise error + + def delete_model(self, model_id): + with self.get_session_for_write() as session: + ref = session.query(Model).get(model_id) + session.delete(ref) + + def add_model(self, model_id=None, value=None): + try: + with self.get_session_for_write() as session: + value_wo_name = copy.deepcopy(value) + value_wo_name.pop("name", None) + new = Model.from_dict({ + "id": model_id if model_id else uuid4().hex, + "name": value["name"], + "value": value_wo_name + }) + session.add(new) + return {new.id: new.to_dict()} + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.ModelExisting + raise error + + def get_models(self, model_id=None): + with self.get_session_for_read() as session: + query = session.query(Model) + if model_id: + ref_list = query.filter(Model.id == model_id) + else: + ref_list = query.all() + + r = {_ref.id: _ref.to_dict() for _ref in ref_list} + return r + + def set_meta_rule(self, meta_rule_id, value): + try: + with self.get_session_for_write() as session: + value_wo_other_data = copy.deepcopy(value) + value_wo_other_data.pop("name", None) + value_wo_other_data.pop("subject_categories", None) + value_wo_other_data.pop("object_categories", None) + value_wo_other_data.pop("action_categories", None) + if meta_rule_id is None: + try: + ref = MetaRule.from_dict( + { + "id": uuid4().hex, + "name": value["name"], + "subject_categories": value["subject_categories"], + "object_categories": value["object_categories"], + "action_categories": value["action_categories"], + "value": value_wo_other_data + } + ) + session.add(ref) + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.MetaRuleExisting + raise error + else: + query = session.query(MetaRule) + query = query.filter_by(id=meta_rule_id) + ref = query.first() + setattr(ref, "name", value["name"]) + setattr(ref, "subject_categories", value["subject_categories"]) + setattr(ref, "object_categories", value["object_categories"]) + setattr(ref, "action_categories", value["action_categories"]) + setattr(ref, "value", value_wo_other_data) + return {ref.id: ref.to_dict()} + except sqlalchemy.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.MetaRuleExisting + raise error + + def get_meta_rules(self, meta_rule_id=None): + with self.get_session_for_read() as session: + query = session.query(MetaRule) + if meta_rule_id: + query = query.filter_by(id=meta_rule_id) + ref_list = query.all() + return {_ref.id: _ref.to_dict() for _ref in ref_list} + + def delete_meta_rule(self, meta_rule_id=None): + with self.get_session_for_write() as session: + query = session.query(MetaRule) + query = query.filter_by(id=meta_rule_id) + ref = query.first() + if ref: + session.delete(ref) + + def __get_perimeter_categories(self, ClassType, category_id=None): + with self.get_session_for_read() as session: + query = session.query(ClassType) + if category_id != None: + query = query.filter_by(id=category_id) + ref_list = query.all() + return {_ref.id: _ref.to_dict() for _ref in ref_list} + + def __get_perimeter_categories_by_category_name(self, ClassType, category_name=None): + with self.get_session_for_read() as session: + query = session.query(ClassType) + if category_name != None: + query = query.filter_by(name=category_name) + ref_list = query.all() + return {_ref.id: _ref.to_dict() for _ref in ref_list} + + def __add_perimeter_category(self, ClassType, name, description, uuid=None): + if not name or not name.strip(): + raise exceptions.CategoryNameInvalid + with self.get_session_for_write() as session: + ref = ClassType.from_dict( + { + "id": uuid if uuid else uuid4().hex, + "name": name, + "description": description + } + ) + session.add(ref) + return {ref.id: ref.to_dict()} + + def __delete_perimeter_category(self, ClassType, category_id): + with self.get_session_for_write() as session: + query = session.query(ClassType) + query = query.filter_by(id=category_id) + ref = query.first() + if ref: + session.delete(ref) + #TODO: MAY BE!duplicate to get_subject_categories_by_ + def get_subject_categories(self, category_id=None, category_name=None): + if category_name != None: + return self.__get_perimeter_categories_by_category_name(SubjectCategory, category_name=category_name) + return self.__get_perimeter_categories(SubjectCategory, category_id=category_id) + + + def add_subject_category(self, name, description, uuid=None): + try: + return self.__add_perimeter_category(SubjectCategory, name, description, uuid=uuid) + except sql.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.SubjectCategoryExisting + raise error + + def delete_subject_category(self, category_id): + self.__delete_perimeter_category(SubjectCategory, category_id) + + def get_object_categories(self, category_id=None, category_name=None): + if category_name != None: + return self.__get_perimeter_categories_by_category_name(ObjectCategory, category_name=category_name) + return self.__get_perimeter_categories(ObjectCategory, category_id=category_id) + + def add_object_category(self, name, description, uuid=None): + try: + return self.__add_perimeter_category(ObjectCategory, name, description, uuid=uuid) + except sql.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.ObjectCategoryExisting + raise error + + def delete_object_category(self, category_id): + self.__delete_perimeter_category(ObjectCategory, category_id) + + def get_action_categories(self, category_id=None, category_name=None): + if category_name != None: + return self.__get_perimeter_categories_by_category_name(ActionCategory, category_name=category_name) + return self.__get_perimeter_categories(ActionCategory, category_id=category_id) + + def add_action_category(self, name, description, uuid=None): + try: + return self.__add_perimeter_category(ActionCategory, name, description, uuid=uuid) + except sql.exc.IntegrityError as error: + if 'UNIQUE constraint' in str(error) or 'Duplicate entry' in str(error): + raise exceptions.ActionCategoryExisting + raise error + + def delete_action_category(self, category_id): + self.__delete_perimeter_category(ActionCategory, category_id) + + # Getter and Setter for subject_category + + # def get_subject_categories_dict(self, intra_extension_id): + # with self.get_session_for_read() as session: + # query = session.query(SubjectCategory) + # query = query.filter_by(intra_extension_id=intra_extension_id) + # ref_list = query.all() + # return {_ref.id: _ref.subject_category for _ref in ref_list} + # + # def set_subject_category_dict(self, intra_extension_id, subject_category_id, subject_category_dict): + # with self.get_session_for_write() as session: + # query = session.query(SubjectCategory) + # query = query.filter_by(intra_extension_id=intra_extension_id, id=subject_category_id) + # ref = query.first() + # new_ref = SubjectCategory.from_dict( + # { + # "id": subject_category_id, + # 'subject_category': subject_category_dict, + # 'intra_extension_id': intra_extension_id + # } + # ) + # if not ref: + # session.add(new_ref) + # ref = new_ref + # else: + # for attr in SubjectCategory.attributes: + # if attr != 'id': + # setattr(ref, attr, getattr(new_ref, attr)) + # # # session.flush() + # return {subject_category_id: SubjectCategory.to_dict(ref)['subject_category']} + # + # def del_subject_category(self, intra_extension_id, subject_category_id): + # with self.get_session_for_write() as session: + # query = session.query(SubjectCategory) + # query = query.filter_by(intra_extension_id=intra_extension_id, id=subject_category_id) + # ref = query.first() + # self.del_subject_assignment(intra_extension_id, None, None, None) + # session.delete(ref) + # + # # Getter and Setter for object_category + # + # def get_object_categories_dict(self, intra_extension_id): + # with self.get_session_for_read() as session: + # query = session.query(ObjectCategory) + # query = query.filter_by(intra_extension_id=intra_extension_id) + # ref_list = query.all() + # return {_ref.id: _ref.object_category for _ref in ref_list} + # + # def set_object_category_dict(self, intra_extension_id, object_category_id, object_category_dict): + # with self.get_session_for_write() as session: + # query = session.query(ObjectCategory) + # query = query.filter_by(intra_extension_id=intra_extension_id, id=object_category_id) + # ref = query.first() + # new_ref = ObjectCategory.from_dict( + # { + # "id": object_category_id, + # 'object_category': object_category_dict, + # 'intra_extension_id': intra_extension_id + # } + # ) + # if not ref: + # session.add(new_ref) + # ref = new_ref + # else: + # for attr in ObjectCategory.attributes: + # if attr != 'id': + # setattr(ref, attr, getattr(new_ref, attr)) + # # session.flush() + # return {object_category_id: ObjectCategory.to_dict(ref)['object_category']} + # + # def del_object_category(self, intra_extension_id, object_category_id): + # with self.get_session_for_write() as session: + # query = session.query(ObjectCategory) + # query = query.filter_by(intra_extension_id=intra_extension_id, id=object_category_id) + # ref = query.first() + # self.del_object_assignment(intra_extension_id, None, None, None) + # session.delete(ref) + # + # # Getter and Setter for action_category + # + # def get_action_categories_dict(self, intra_extension_id): + # with self.get_session_for_read() as session: + # query = session.query(ActionCategory) + # query = query.filter_by(intra_extension_id=intra_extension_id) + # ref_list = query.all() + # return {_ref.id: _ref.action_category for _ref in ref_list} + # + # def set_action_category_dict(self, intra_extension_id, action_category_id, action_category_dict): + # with self.get_session_for_write() as session: + # query = session.query(ActionCategory) + # query = query.filter_by(intra_extension_id=intra_extension_id, id=action_category_id) + # ref = query.first() + # new_ref = ActionCategory.from_dict( + # { + # "id": action_category_id, + # 'action_category': action_category_dict, + # 'intra_extension_id': intra_extension_id + # } + # ) + # if not ref: + # session.add(new_ref) + # ref = new_ref + # else: + # for attr in ActionCategory.attributes: + # if attr != 'id': + # setattr(ref, attr, getattr(new_ref, attr)) + # # session.flush() + # return {action_category_id: ActionCategory.to_dict(ref)['action_category']} + # + # def del_action_category(self, intra_extension_id, action_category_id): + # with self.get_session_for_write() as session: + # query = session.query(ActionCategory) + # query = query.filter_by(intra_extension_id=intra_extension_id, id=action_category_id) + # ref = query.first() + # self.del_action_assignment(intra_extension_id, None, None, None) + # session.delete(ref) + + # Perimeter + + # def get_subjects_dict(self, intra_extension_id): + # with self.get_session_for_read() as session: + # query = session.query(Subject) + # query = query.filter_by(intra_extension_id=intra_extension_id) + # ref_list = query.all() + # return {_ref.id: _ref.subject for _ref in ref_list} + # + # def set_subject_dict(self, intra_extension_id, subject_id, subject_dict): + # with self.get_session_for_write() as session: + # query = session.query(Subject) + # query = query.filter_by(intra_extension_id=intra_extension_id, id=subject_id) + # ref = query.first() + # # if 'id' in subject_dict: + # # subject_dict['id'] = subject_id + # new_ref = Subject.from_dict( + # { + # "id": subject_id, + # 'subject': subject_dict, + # 'intra_extension_id': intra_extension_id + # } + # ) + # if not ref: + # session.add(new_ref) + # ref = new_ref + # else: + # for attr in Subject.attributes: + # if attr != 'id': + # setattr(ref, attr, getattr(new_ref, attr)) + # # session.flush() + # return {subject_id: Subject.to_dict(ref)['subject']} + # + # def del_subject(self, intra_extension_id, subject_id): + # with self.get_session_for_write() as session: + # query = session.query(Subject) + # query = query.filter_by(intra_extension_id=intra_extension_id, id=subject_id) + # ref = query.first() + # session.delete(ref) + # + # def get_objects_dict(self, intra_extension_id): + # with self.get_session_for_read() as session: + # query = session.query(Object) + # query = query.filter_by(intra_extension_id=intra_extension_id) + # ref_list = query.all() + # return {_ref.id: _ref.object for _ref in ref_list} + # + # def set_object_dict(self, intra_extension_id, object_id, object_dict): + # with self.get_session_for_write() as session: + # query = session.query(Object) + # query = query.filter_by(intra_extension_id=intra_extension_id, id=object_id) + # ref = query.first() + # new_ref = Object.from_dict( + # { + # "id": object_id, + # 'object': object_dict, + # 'intra_extension_id': intra_extension_id + # } + # ) + # if not ref: + # session.add(new_ref) + # ref = new_ref + # else: + # for attr in Object.attributes: + # if attr != 'id': + # setattr(ref, attr, getattr(new_ref, attr)) + # # session.flush() + # return {object_id: Object.to_dict(ref)['object']} + # + # def del_object(self, intra_extension_id, object_id): + # with self.get_session_for_write() as session: + # query = session.query(Object) + # query = query.filter_by(intra_extension_id=intra_extension_id, id=object_id) + # ref = query.first() + # session.delete(ref) + # + # def get_actions_dict(self, intra_extension_id): + # with self.get_session_for_read() as session: + # query = session.query(Action) + # query = query.filter_by(intra_extension_id=intra_extension_id) + # ref_list = query.all() + # return {_ref.id: _ref.action for _ref in ref_list} + # + # def set_action_dict(self, intra_extension_id, action_id, action_dict): + # with self.get_session_for_write() as session: + # query = session.query(Action) + # query = query.filter_by(intra_extension_id=intra_extension_id, id=action_id) + # ref = query.first() + # new_ref = Action.from_dict( + # { + # "id": action_id, + # 'action': action_dict, + # 'intra_extension_id': intra_extension_id + # } + # ) + # if not ref: + # session.add(new_ref) + # ref = new_ref + # else: + # for attr in Action.attributes: + # if attr != 'id': + # setattr(ref, attr, getattr(new_ref, attr)) + # # session.flush() + # return {action_id: Action.to_dict(ref)['action']} + # + # def del_action(self, intra_extension_id, action_id): + # with self.get_session_for_write() as session: + # query = session.query(Action) + # query = query.filter_by(intra_extension_id=intra_extension_id, id=action_id) + # ref = query.first() + # session.delete(ref) + + # Getter and Setter for subject_scope + + # def get_subject_scopes_dict(self, intra_extension_id, subject_category_id): + # with self.get_session_for_read() as session: + # query = session.query(SubjectScope) + # query = query.filter_by(intra_extension_id=intra_extension_id, subject_category_id=subject_category_id) + # ref_list = query.all() + # return {_ref.id: _ref.subject_scope for _ref in ref_list} + # + # def set_subject_scope_dict(self, intra_extension_id, subject_category_id, subject_scope_id, subject_scope_dict): + # with self.get_session_for_write() as session: + # query = session.query(SubjectScope) + # query = query.filter_by(intra_extension_id=intra_extension_id, subject_category_id=subject_category_id, id=subject_scope_id) + # ref = query.first() + # new_ref = SubjectScope.from_dict( + # { + # "id": subject_scope_id, + # 'subject_scope': subject_scope_dict, + # 'intra_extension_id': intra_extension_id, + # 'subject_category_id': subject_category_id + # } + # ) + # if not ref: + # session.add(new_ref) + # ref = new_ref + # else: + # for attr in Subject.attributes: + # if attr != 'id': + # setattr(ref, attr, getattr(new_ref, attr)) + # # session.flush() + # return {subject_scope_id: SubjectScope.to_dict(ref)['subject_scope']} + # + # def del_subject_scope(self, intra_extension_id, subject_category_id, subject_scope_id): + # with self.get_session_for_write() as session: + # query = session.query(SubjectScope) + # if not subject_category_id or not subject_scope_id: + # query = query.filter_by(intra_extension_id=intra_extension_id) + # for ref in query.all(): + # session.delete(ref) + # else: + # query = query.filter_by(intra_extension_id=intra_extension_id, subject_category_id=subject_category_id, id=subject_scope_id) + # ref = query.first() + # session.delete(ref) + # + # # Getter and Setter for object_category_scope + # + # def get_object_scopes_dict(self, intra_extension_id, object_category_id): + # with self.get_session_for_read() as session: + # query = session.query(ObjectScope) + # query = query.filter_by(intra_extension_id=intra_extension_id, object_category_id=object_category_id) + # ref_list = query.all() + # return {_ref.id: _ref.object_scope for _ref in ref_list} + # + # def set_object_scope_dict(self, intra_extension_id, object_category_id, object_scope_id, object_scope_dict): + # with self.get_session_for_write() as session: + # query = session.query(ObjectScope) + # query = query.filter_by(intra_extension_id=intra_extension_id, object_category_id=object_category_id, id=object_scope_id) + # ref = query.first() + # new_ref = ObjectScope.from_dict( + # { + # "id": object_scope_id, + # 'object_scope': object_scope_dict, + # 'intra_extension_id': intra_extension_id, + # 'object_category_id': object_category_id + # } + # ) + # if not ref: + # session.add(new_ref) + # ref = new_ref + # else: + # for attr in Object.attributes: + # if attr != 'id': + # setattr(ref, attr, getattr(new_ref, attr)) + # # session.flush() + # return {object_scope_id: ObjectScope.to_dict(ref)['object_scope']} + # + # def del_object_scope(self, intra_extension_id, object_category_id, object_scope_id): + # with self.get_session_for_write() as session: + # query = session.query(ObjectScope) + # if not object_category_id or not object_scope_id: + # query = query.filter_by(intra_extension_id=intra_extension_id) + # for ref in query.all(): + # session.delete(ref) + # else: + # query = query.filter_by(intra_extension_id=intra_extension_id, object_category_id=object_category_id, id=object_scope_id) + # ref = query.first() + # session.delete(ref) + # + # # Getter and Setter for action_scope + # + # def get_action_scopes_dict(self, intra_extension_id, action_category_id): + # with self.get_session_for_read() as session: + # query = session.query(ActionScope) + # query = query.filter_by(intra_extension_id=intra_extension_id, action_category_id=action_category_id) + # ref_list = query.all() + # return {_ref.id: _ref.action_scope for _ref in ref_list} + # + # def set_action_scope_dict(self, intra_extension_id, action_category_id, action_scope_id, action_scope_dict): + # with self.get_session_for_write() as session: + # query = session.query(ActionScope) + # query = query.filter_by(intra_extension_id=intra_extension_id, action_category_id=action_category_id, id=action_scope_id) + # ref = query.first() + # new_ref = ActionScope.from_dict( + # { + # "id": action_scope_id, + # 'action_scope': action_scope_dict, + # 'intra_extension_id': intra_extension_id, + # 'action_category_id': action_category_id + # } + # ) + # if not ref: + # session.add(new_ref) + # ref = new_ref + # else: + # for attr in Action.attributes: + # if attr != 'id': + # setattr(ref, attr, getattr(new_ref, attr)) + # # session.flush() + # return {action_scope_id: ActionScope.to_dict(ref)['action_scope']} + # + # def del_action_scope(self, intra_extension_id, action_category_id, action_scope_id): + # with self.get_session_for_write() as session: + # query = session.query(ActionScope) + # if not action_category_id or not action_scope_id: + # query = query.filter_by(intra_extension_id=intra_extension_id) + # for ref in query.all(): + # session.delete(ref) + # else: + # query = query.filter_by(intra_extension_id=intra_extension_id, action_category_id=action_category_id, id=action_scope_id) + # ref = query.first() + # session.delete(ref) + # + # # Getter and Setter for subject_category_assignment + # + # def get_subject_assignment_list(self, intra_extension_id, subject_id, subject_category_id): + # with self.get_session_for_read() as session: + # query = session.query(SubjectAssignment) + # if not subject_id or not subject_category_id or not subject_category_id: + # query = query.filter_by(intra_extension_id=intra_extension_id) + # ref = query.all() + # return ref + # else: + # query = query.filter_by(intra_extension_id=intra_extension_id, subject_id=subject_id, subject_category_id=subject_category_id) + # ref = query.first() + # if not ref: + # return list() + # LOG.info("get_subject_assignment_list {}".format(ref.subject_assignment)) + # return list(ref.subject_assignment) + # + # def set_subject_assignment_list(self, intra_extension_id, subject_id, subject_category_id, subject_assignment_list=[]): + # with self.get_session_for_write() as session: + # query = session.query(SubjectAssignment) + # query = query.filter_by(intra_extension_id=intra_extension_id, subject_id=subject_id, subject_category_id=subject_category_id) + # ref = query.first() + # new_ref = SubjectAssignment.from_dict( + # { + # "id": uuid4().hex, + # 'subject_assignment': subject_assignment_list, + # 'intra_extension_id': intra_extension_id, + # 'subject_id': subject_id, + # 'subject_category_id': subject_category_id + # } + # ) + # if not ref: + # session.add(new_ref) + # ref = new_ref + # else: + # for attr in SubjectAssignment.attributes: + # if attr != 'id': + # setattr(ref, attr, getattr(new_ref, attr)) + # # session.flush() + # return subject_assignment_list + # + # def add_subject_assignment_list(self, intra_extension_id, subject_id, subject_category_id, subject_scope_id): + # new_subject_assignment_list = self.get_subject_assignment_list(intra_extension_id, subject_id, subject_category_id) + # if subject_scope_id not in new_subject_assignment_list: + # new_subject_assignment_list.append(subject_scope_id) + # return self.set_subject_assignment_list(intra_extension_id, subject_id, subject_category_id, new_subject_assignment_list) + # + # def del_subject_assignment(self, intra_extension_id, subject_id, subject_category_id, subject_scope_id): + # if not subject_id or not subject_category_id or not subject_category_id: + # with self.get_session_for_write() as session: + # for ref in self.get_subject_assignment_list(intra_extension_id, None, None): + # session.delete(ref) + # session.flush() + # return + # new_subject_assignment_list = self.get_subject_assignment_list(intra_extension_id, subject_id, subject_category_id) + # new_subject_assignment_list.remove(subject_scope_id) + # return self.set_subject_assignment_list(intra_extension_id, subject_id, subject_category_id, new_subject_assignment_list) + # + # # Getter and Setter for object_category_assignment + # + # def get_object_assignment_list(self, intra_extension_id, object_id, object_category_id): + # with self.get_session_for_read() as session: + # query = session.query(ObjectAssignment) + # if not object_id or not object_category_id or not object_category_id: + # query = query.filter_by(intra_extension_id=intra_extension_id) + # ref = query.all() + # return ref + # else: + # query = query.filter_by(intra_extension_id=intra_extension_id, object_id=object_id, object_category_id=object_category_id) + # ref = query.first() + # if not ref: + # return list() + # return list(ref.object_assignment) + # + # def set_object_assignment_list(self, intra_extension_id, object_id, object_category_id, object_assignment_list=[]): + # with self.get_session_for_write() as session: + # query = session.query(ObjectAssignment) + # query = query.filter_by(intra_extension_id=intra_extension_id, object_id=object_id, object_category_id=object_category_id) + # ref = query.first() + # new_ref = ObjectAssignment.from_dict( + # { + # "id": uuid4().hex, + # 'object_assignment': object_assignment_list, + # 'intra_extension_id': intra_extension_id, + # 'object_id': object_id, + # 'object_category_id': object_category_id + # } + # ) + # if not ref: + # session.add(new_ref) + # else: + # for attr in ObjectAssignment.attributes: + # if attr != 'id': + # setattr(ref, attr, getattr(new_ref, attr)) + # # session.flush() + # return self.get_object_assignment_list(intra_extension_id, object_id, object_category_id) + # + # def add_object_assignment_list(self, intra_extension_id, object_id, object_category_id, object_scope_id): + # new_object_assignment_list = self.get_object_assignment_list(intra_extension_id, object_id, object_category_id) + # if object_scope_id not in new_object_assignment_list: + # new_object_assignment_list.append(object_scope_id) + # return self.set_object_assignment_list(intra_extension_id, object_id, object_category_id, new_object_assignment_list) + # + # def del_object_assignment(self, intra_extension_id, object_id, object_category_id, object_scope_id): + # if not object_id or not object_category_id or not object_category_id: + # with self.get_session_for_write() as session: + # for ref in self.get_object_assignment_list(intra_extension_id, None, None): + # session.delete(ref) + # session.flush() + # return + # new_object_assignment_list = self.get_object_assignment_list(intra_extension_id, object_id, object_category_id) + # new_object_assignment_list.remove(object_scope_id) + # return self.set_object_assignment_list(intra_extension_id, object_id, object_category_id, new_object_assignment_list) + # + # # Getter and Setter for action_category_assignment + # + # def get_action_assignment_list(self, intra_extension_id, action_id, action_category_id): + # with self.get_session_for_read() as session: + # query = session.query(ActionAssignment) + # if not action_id or not action_category_id or not action_category_id: + # query = query.filter_by(intra_extension_id=intra_extension_id) + # ref = query.all() + # return ref + # else: + # query = query.filter_by(intra_extension_id=intra_extension_id, action_id=action_id, action_category_id=action_category_id) + # ref = query.first() + # if not ref: + # return list() + # return list(ref.action_assignment) + # + # def set_action_assignment_list(self, intra_extension_id, action_id, action_category_id, action_assignment_list=[]): + # with self.get_session_for_write() as session: + # query = session.query(ActionAssignment) + # query = query.filter_by(intra_extension_id=intra_extension_id, action_id=action_id, action_category_id=action_category_id) + # ref = query.first() + # new_ref = ActionAssignment.from_dict( + # { + # "id": uuid4().hex, + # 'action_assignment': action_assignment_list, + # 'intra_extension_id': intra_extension_id, + # 'action_id': action_id, + # 'action_category_id': action_category_id + # } + # ) + # if not ref: + # session.add(new_ref) + # else: + # for attr in ActionAssignment.attributes: + # if attr != 'id': + # setattr(ref, attr, getattr(new_ref, attr)) + # # session.flush() + # return self.get_action_assignment_list(intra_extension_id, action_id, action_category_id) + # + # def add_action_assignment_list(self, intra_extension_id, action_id, action_category_id, action_scope_id): + # new_action_assignment_list = self.get_action_assignment_list(intra_extension_id, action_id, action_category_id) + # if action_scope_id not in new_action_assignment_list: + # new_action_assignment_list.append(action_scope_id) + # return self.set_action_assignment_list(intra_extension_id, action_id, action_category_id, new_action_assignment_list) + # + # def del_action_assignment(self, intra_extension_id, action_id, action_category_id, action_scope_id): + # if not action_id or not action_category_id or not action_category_id: + # with self.get_session_for_write() as session: + # for ref in self.get_action_assignment_list(intra_extension_id, None, None): + # session.delete(ref) + # session.flush() + # return + # new_action_assignment_list = self.get_action_assignment_list(intra_extension_id, action_id, action_category_id) + # new_action_assignment_list.remove(action_scope_id) + # return self.set_action_assignment_list(intra_extension_id, action_id, action_category_id, new_action_assignment_list) + # + # # Getter and Setter for sub_meta_rule + # + # def get_aggregation_algorithm_id(self, intra_extension_id): + # with self.get_session_for_read() as session: + # query = session.query(IntraExtension) + # query = query.filter_by(id=intra_extension_id) + # ref = query.first() + # try: + # return {"aggregation_algorithm": ref.intra_extension["aggregation_algorithm"]} + # except KeyError: + # return "" + # + # def set_aggregation_algorithm_id(self, intra_extension_id, aggregation_algorithm_id): + # with self.get_session_for_write() as session: + # query = session.query(IntraExtension) + # query = query.filter_by(id=intra_extension_id) + # ref = query.first() + # intra_extension_dict = dict(ref.intra_extension) + # intra_extension_dict["aggregation_algorithm"] = aggregation_algorithm_id + # setattr(ref, "intra_extension", intra_extension_dict) + # # session.flush() + # return {"aggregation_algorithm": ref.intra_extension["aggregation_algorithm"]} + # + # def del_aggregation_algorithm(self, intra_extension_id): + # with self.get_session_for_write() as session: + # query = session.query(IntraExtension) + # query = query.filter_by(id=intra_extension_id) + # ref = query.first() + # intra_extension_dict = dict(ref.intra_extension) + # intra_extension_dict["aggregation_algorithm"] = "" + # setattr(ref, "intra_extension", intra_extension_dict) + # return self.get_aggregation_algorithm_id(intra_extension_id) + # + # # Getter and Setter for sub_meta_rule + # + # def get_sub_meta_rules_dict(self, intra_extension_id): + # with self.get_session_for_read() as session: + # query = session.query(SubMetaRule) + # query = query.filter_by(intra_extension_id=intra_extension_id) + # ref_list = query.all() + # return {_ref.id: _ref.sub_meta_rule for _ref in ref_list} + # + # def set_sub_meta_rule_dict(self, intra_extension_id, sub_meta_rule_id, sub_meta_rule_dict): + # with self.get_session_for_write() as session: + # query = session.query(SubMetaRule) + # query = query.filter_by(intra_extension_id=intra_extension_id, id=sub_meta_rule_id) + # ref = query.first() + # new_ref = SubMetaRule.from_dict( + # { + # "id": sub_meta_rule_id, + # 'sub_meta_rule': sub_meta_rule_dict, + # 'intra_extension_id': intra_extension_id + # } + # ) + # if not ref: + # session.add(new_ref) + # else: + # _sub_meta_rule_dict = dict(ref.sub_meta_rule) + # _sub_meta_rule_dict.update(sub_meta_rule_dict) + # setattr(new_ref, "sub_meta_rule", _sub_meta_rule_dict) + # for attr in SubMetaRule.attributes: + # if attr != 'id': + # setattr(ref, attr, getattr(new_ref, attr)) + # # session.flush() + # return self.get_sub_meta_rules_dict(intra_extension_id) + # + # def del_sub_meta_rule(self, intra_extension_id, sub_meta_rule_id): + # with self.get_session_for_write() as session: + # query = session.query(SubMetaRule) + # query = query.filter_by(intra_extension_id=intra_extension_id, id=sub_meta_rule_id) + # ref = query.first() + # session.delete(ref) + # + # # Getter and Setter for rules + # + # def get_rules_dict(self, intra_extension_id, sub_meta_rule_id): + # with self.get_session_for_read() as session: + # query = session.query(Rule) + # query = query.filter_by(intra_extension_id=intra_extension_id, sub_meta_rule_id=sub_meta_rule_id) + # ref_list = query.all() + # return {_ref.id: _ref.rule for _ref in ref_list} + # + # def set_rule_dict(self, intra_extension_id, sub_meta_rule_id, rule_id, rule_list): + # with self.get_session_for_write() as session: + # query = session.query(Rule) + # query = query.filter_by(intra_extension_id=intra_extension_id, sub_meta_rule_id=sub_meta_rule_id, id=rule_id) + # ref = query.first() + # new_ref = Rule.from_dict( + # { + # "id": rule_id, + # 'rule': rule_list, + # 'intra_extension_id': intra_extension_id, + # 'sub_meta_rule_id': sub_meta_rule_id + # } + # ) + # if not ref: + # session.add(new_ref) + # ref = new_ref + # else: + # for attr in Rule.attributes: + # if attr != 'id': + # setattr(ref, attr, getattr(new_ref, attr)) + # # session.flush() + # return {rule_id: ref.rule} + # + # def del_rule(self, intra_extension_id, sub_meta_rule_id, rule_id): + # with self.get_session_for_write() as session: + # query = session.query(Rule) + # query = query.filter_by(intra_extension_id=intra_extension_id, sub_meta_rule_id=sub_meta_rule_id, id=rule_id) + # ref = query.first() + # session.delete(ref) + + +class Connector(PDPConnector, PolicyConnector, ModelConnector, SlaveConnector): + pass |