def verify_index(resource, parent, index_values, schema, idl): ''' Verify if a resource exists in the DB Table using the index. ''' if resource.table not in idl.tables: return None # check if we are dealing with key/value type of forward reference kv_type = False if parent is not None and parent.relation == OVSDB_SCHEMA_CHILD: if schema.ovs_tables[parent.table].references[parent.column].kv_type: kv_type = True if kv_type: # check in parent table that the index exists app_log.debug('verifying key/value type reference') row = utils.kv_index_to_row(index_values, parent, idl) else: dbtable = idl.tables[resource.table] table_schema = schema.ovs_tables[resource.table] row = utils.index_to_row(index_values, table_schema, dbtable) return row
def verify_index(resource, parent, index_values, schema, idl): if resource.table not in idl.tables: return None if parent.relation == OVSDB_SCHEMA_BACK_REFERENCE: reference_keys = schema.ovs_tables[resource.table].references _refCol = None for key, value in reference_keys.iteritems(): if (value.relation == OVSDB_SCHEMA_PARENT and value.ref_table == parent.table): _refCol = key break if _refCol is None: return False dbtable = idl.tables[resource.table] row = utils.index_to_row(index_values, schema.ovs_tables[resource.table], dbtable) if row.__getattr__(_refCol).uuid == parent.row: return row else: return None elif parent.relation == OVSDB_SCHEMA_TOP_LEVEL: dbtable = idl.tables[resource.table] table_schema = schema.ovs_tables[resource.table] row = utils.index_to_row(index_values, table_schema, dbtable) return row else: # check if we are dealing with key/value type of forward reference kv_type = schema.ovs_tables[parent.table].references[ parent.column].kv_type if kv_type: # check in parent table that the index exists app_log.debug('verifying key/value type reference') row = utils.kv_index_to_row(index_values, parent, idl) else: dbtable = idl.tables[resource.table] table_schema = schema.ovs_tables[resource.table] row = utils.index_to_row(index_values, table_schema, dbtable) return row
def setup_row(index_values, table, row_data, txn, reflist, schema, idl, validator_adapter, errors, old_row=None): # Initialize the flag for row to check if it is new row is_new = False # Check if row exists in DB if old_row is not None: row = old_row else: row = utils.index_to_row(index_values, schema.ovs_tables[table], idl.tables[table]) # Create a new row if not found in DB if row is None: if table in immutable_tables: # Do NOT add row in Immutable table_data return (None, False) row = txn.insert(idl.tables[table]) is_new = True # Routes are special case - only static routes can be updated if table == 'Route': if not is_new and row.__getattr__('from') != 'static': return (None, False) elif is_new: row.__setattr__('from', 'static') references = schema.ovs_tables[table].references children = schema.ovs_tables[table].children try: request_type = REQUEST_TYPE_CREATE if is_new else REQUEST_TYPE_UPDATE get_all_errors = True # Check for back-references and remove it from the row data since # it will be checked upon recursive call anyways. _row_data = deepcopy(row_data) for data in row_data: if data in children and data not in references: del _row_data[data] results = verify.verify_config_data(_row_data, table, schema, request_type, get_all_errors) except DataValidationFailed as e: errors.extend(e.detail) config_rows = schema.ovs_tables[table].config config_keys = config_rows.keys() # Iterate over all config keys for key in config_keys: # Ignore if row is existing and column is immutable if not is_new and not config_rows[key].mutable: continue # Set the column values from user config if key not in row_data and not is_new: empty_val = utils.get_empty_by_basic_type(row.__getattr__(key)) row.__setattr__(key, empty_val) elif (key in row_data and (is_new or row.__getattr__(key) != row_data[key])): row.__setattr__(key, row_data[key]) # Delete all the keys that don't exist for key in children: child_table = references[key].ref_table \ if key in references else key # Check if table is immutable if child_table in immutable_tables: if not is_new and (key not in row_data or not row_data[key]): # Deep clean-up children, even if missing or empty, # Ignore if immutable if key in references: kv_type = references[key].kv_type if kv_type: rowlist = row.__getattr__(key).values() else: rowlist = row.__getattr__(key) clean_subtree(child_table, rowlist, txn, schema, idl, validator_adapter) else: clean_subtree(child_table, [], txn, schema, idl, validator_adapter, row) continue # forward child references if key in references: table_schema = schema.ovs_tables[table] reference = table_schema.references[key] kv_type = reference.kv_type if not is_new and key not in row_data: if kv_type: row.__setattr__(key, {}) else: row.__setattr__(key, []) else: # back-references if child_table not in row_data: new_data = {} else: new_data = row_data[child_table] remove_deleted_rows(child_table, new_data, txn, schema, idl, validator_adapter, row) # set up children that exist for key in children: child_table = references[key].ref_table \ if key in references else key if key in row_data: if key in references: # forward referenced children table_schema = schema.ovs_tables[table] reference = table_schema.references[key] kv_type = reference.kv_type kv_key_type = None current_child_rows = {} # Key-value type children (Dict type) # Example - BGP_Router is KV-Type child of VRF if kv_type: kv_key_type = reference.kv_key_type if not is_new: current_child_rows = row.__getattr__(key) child_reference_list = {} # Regular children else: child_reference_list = [] # Iterate over each child_row for child_index, child_row_data in row_data[key].iteritems(): current_row = None if kv_type: if (kv_key_type is not None and kv_key_type.name == 'integer'): child_index = int(child_index) if child_index in current_child_rows: current_row = current_child_rows[child_index] child_index_values = [] else: child_index_values = utils.escaped_split(child_index) (child_row, is_child_new) = setup_row(child_index_values, child_table, child_row_data, txn, reflist, schema, idl, validator_adapter, errors, current_row) if child_row is None: continue op = REQUEST_TYPE_CREATE if is_child_new else \ REQUEST_TYPE_UPDATE validator_adapter.add_resource_op(op, child_row, child_table, row, table) if kv_type: child_reference_list.update({child_index: child_row}) else: child_reference_list.append(child_row) # Save this in global reflist reflist[(child_table, child_index)] = (child_row, is_child_new) if child_table not in immutable_tables: row.__setattr__(key, child_reference_list) else: # backward referenced children parent_column = None references = schema.ovs_tables[child_table].references for col_name, col_value in references.iteritems(): if col_value.relation == 'parent': parent_column = col_name break # Iterate over each child_row for child_index, child_row_data in row_data[key].iteritems(): child_index_values = utils.escaped_split(child_index) (child_row, is_child_new) = setup_row(child_index_values, child_table, child_row_data, txn, reflist, schema, idl, validator_adapter, errors) if child_row is None: continue op = REQUEST_TYPE_CREATE if is_child_new else \ REQUEST_TYPE_UPDATE validator_adapter.add_resource_op(op, child_row, child_table, row, table) # Set the references column in child row if parent_column is not None and is_child_new: child_row.__setattr__(parent_column, row) # save this in global reflist reflist[(child_table, child_index)] = (child_row, is_child_new) return (row, is_new)