diff options
Diffstat (limited to 'networking-odl/networking_odl/journal/dependency_validations.py')
-rw-r--r-- | networking-odl/networking_odl/journal/dependency_validations.py | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/networking-odl/networking_odl/journal/dependency_validations.py b/networking-odl/networking_odl/journal/dependency_validations.py new file mode 100644 index 0000000..a6f5f96 --- /dev/null +++ b/networking-odl/networking_odl/journal/dependency_validations.py @@ -0,0 +1,267 @@ +# Copyright (c) 2015 OpenStack Foundation +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from networking_odl.common import constants as odl_const +from networking_odl.db import db + + +def _is_valid_update_operation(session, row): + # Check if there are older updates in the queue + if db.check_for_older_ops(session, row): + return False + + # Check for a pending or processing create operation on this uuid + if db.check_for_pending_or_processing_ops( + session, row.object_uuid, odl_const.ODL_CREATE): + return False + return True + + +def validate_network_operation(session, row): + """Validate the network operation based on dependencies. + + Validate network operation depending on whether it's dependencies + are still in 'pending' or 'processing' state. e.g. + """ + if row.operation == odl_const.ODL_DELETE: + # Check for any pending or processing create or update + # ops on this uuid itself + if db.check_for_pending_or_processing_ops( + session, row.object_uuid, [odl_const.ODL_UPDATE, + odl_const.ODL_CREATE]): + return False + # Check for dependent operations + if db.check_for_pending_delete_ops_with_parent( + session, odl_const.ODL_SUBNET, row.object_uuid): + return False + if db.check_for_pending_delete_ops_with_parent( + session, odl_const.ODL_PORT, row.object_uuid): + return False + if db.check_for_pending_delete_ops_with_parent( + session, odl_const.ODL_ROUTER, row.object_uuid): + return False + elif (row.operation == odl_const.ODL_UPDATE and + not _is_valid_update_operation(session, row)): + return False + return True + + +def validate_subnet_operation(session, row): + """Validate the subnet operation based on dependencies. + + Validate subnet operation depending on whether it's dependencies + are still in 'pending' or 'processing' state. e.g. + """ + if row.operation in (odl_const.ODL_CREATE, odl_const.ODL_UPDATE): + network_id = row.data['network_id'] + # Check for pending or processing network operations + if db.check_for_pending_or_processing_ops(session, network_id): + return False + if (row.operation == odl_const.ODL_UPDATE and + not _is_valid_update_operation(session, row)): + return False + elif row.operation == odl_const.ODL_DELETE: + # Check for any pending or processing create or update + # ops on this uuid itself + if db.check_for_pending_or_processing_ops( + session, row.object_uuid, [odl_const.ODL_UPDATE, + odl_const.ODL_CREATE]): + return False + # Check for dependent operations + if db.check_for_pending_delete_ops_with_parent( + session, odl_const.ODL_PORT, row.object_uuid): + return False + + return True + + +def validate_port_operation(session, row): + """Validate port operation based on dependencies. + + Validate port operation depending on whether it's dependencies + are still in 'pending' or 'processing' state. e.g. + """ + if row.operation in (odl_const.ODL_CREATE, odl_const.ODL_UPDATE): + network_id = row.data['network_id'] + # Check for pending or processing network operations + ops = db.check_for_pending_or_processing_ops(session, network_id) + # Check for pending subnet operations. + for fixed_ip in row.data['fixed_ips']: + ip_ops = db.check_for_pending_or_processing_ops( + session, fixed_ip['subnet_id']) + ops = ops or ip_ops + + if ops: + return False + if (row.operation == odl_const.ODL_UPDATE and + not _is_valid_update_operation(session, row)): + return False + elif row.operation == odl_const.ODL_DELETE: + # Check for any pending or processing create or update + # ops on this uuid itself + if db.check_for_pending_or_processing_ops( + session, row.object_uuid, [odl_const.ODL_UPDATE, + odl_const.ODL_CREATE]): + return False + + return True + + +def validate_router_operation(session, row): + """Validate router operation based on dependencies. + + Validate router operation depending on whether it's dependencies + are still in 'pending' or 'processing' state. + """ + if row.operation in (odl_const.ODL_CREATE, odl_const.ODL_UPDATE): + if row.data['gw_port_id'] is not None: + if db.check_for_pending_or_processing_ops(session, + row.data['gw_port_id']): + return False + if (row.operation == odl_const.ODL_UPDATE and + not _is_valid_update_operation(session, row)): + return False + elif row.operation == odl_const.ODL_DELETE: + # Check for any pending or processing create or update + # operations on this uuid. + if db.check_for_pending_or_processing_ops(session, row.object_uuid, + [odl_const.ODL_UPDATE, + odl_const.ODL_CREATE]): + return False + + # Check that dependent port delete operation has completed. + if db.check_for_pending_delete_ops_with_parent( + session, odl_const.ODL_PORT, row.object_uuid): + return False + + # Check that dependent floatingip delete operation has completed. + if db.check_for_pending_delete_ops_with_parent( + session, odl_const.ODL_FLOATINGIP, row.object_uuid): + return False + + # Check that dependent router interface remove operation has completed. + if db.check_for_pending_remove_ops_with_parent( + session, row.object_uuid): + return False + + return True + + +def validate_floatingip_operation(session, row): + """Validate floatingip operation based on dependencies. + + Validate floating IP operation depending on whether it's dependencies + are still in 'pending' or 'processing' state. + """ + if row.operation in (odl_const.ODL_CREATE, odl_const.ODL_UPDATE): + network_id = row.data.get('floating_network_id') + if network_id is not None: + if not db.check_for_pending_or_processing_ops(session, network_id): + port_id = row.data.get('port_id') + if port_id is not None: + if db.check_for_pending_or_processing_ops(session, + port_id): + return False + else: + return False + + router_id = row.data.get('router_id') + if router_id is not None: + if db.check_for_pending_or_processing_ops(session, router_id): + return False + if (row.operation == odl_const.ODL_UPDATE and + not _is_valid_update_operation(session, row)): + return False + elif row.operation == odl_const.ODL_DELETE: + # Check for any pending or processing create or update + # ops on this uuid itself + if db.check_for_pending_or_processing_ops(session, row.object_uuid, + [odl_const.ODL_UPDATE, + odl_const.ODL_CREATE]): + return False + + return True + + +def validate_router_interface_operation(session, row): + """Validate router_interface operation based on dependencies. + + Validate router_interface operation depending on whether it's dependencies + are still in 'pending' or 'processing' state. + """ + if row.operation == odl_const.ODL_ADD: + # Verify that router event has been completed. + if db.check_for_pending_or_processing_ops(session, row.data['id']): + return False + + # TODO(rcurran): Check for port_id? + if db.check_for_pending_or_processing_ops(session, + row.data['subnet_id']): + return False + elif row.operation == odl_const.ODL_REMOVE: + if db.check_for_pending_or_processing_add(session, row.data['id'], + row.data['subnet_id']): + return False + + return True + + +def validate_security_group_operation(session, row): + """Validate security_group operation based on dependencies. + + Validate security_group operation depending on whether it's dependencies + are still in 'pending' or 'processing' state. e.g. + """ + return True + + +def validate_security_group_rule_operation(session, row): + """Validate security_group_rule operation based on dependencies. + + Validate security_group_rule operation depending on whether it's + dependencies are still in 'pending' or 'processing' state. e.g. + """ + return True + +_VALIDATION_MAP = { + odl_const.ODL_NETWORK: validate_network_operation, + odl_const.ODL_SUBNET: validate_subnet_operation, + odl_const.ODL_PORT: validate_port_operation, + odl_const.ODL_ROUTER: validate_router_operation, + odl_const.ODL_ROUTER_INTF: validate_router_interface_operation, + odl_const.ODL_FLOATINGIP: validate_floatingip_operation, + odl_const.ODL_SG: validate_security_group_operation, + odl_const.ODL_SG_RULE: validate_security_group_rule_operation, +} + + +def validate(session, row): + """Validate resource dependency in journaled operations. + + :param session: db session + :param row: entry in journal entry to be validated + """ + return _VALIDATION_MAP[row.object_type](session, row) + + +def register_validator(object_type, validator): + """Register validator function for given resource. + + :param object_type: neutron resource type + :param validator: function to be registered which validates resource + dependencies + """ + assert object_type not in _VALIDATION_MAP + _VALIDATION_MAP[object_type] = validator |