def remove_deleted_rows(table, table_data, txn, schema, idl, validator_adapter, parent=None): parent_column = None parent_table = None if parent is not None: references = schema.ovs_tables[table].references for key, value in references.iteritems(): if value.relation == 'parent': parent_column = key parent_table = value.ref_table break # Find rows for deletion from the DB that are not in the declarative config for row in idl.tables[table].rows.itervalues(): index = utils.row_to_index(row, table, schema, idl, parent) if (parent_column is not None and row.__getattr__(parent_column) != parent): continue # Routes are special case - only static routes can be deleted if table == 'Route' and row.__getattr__('from') != 'static': continue if index not in table_data: # Add to validator adapter for validation and deletion validator_adapter.add_resource_op(REQUEST_TYPE_DELETE, row, table, parent, parent_table)
def get_column_json(column, row, table, schema, idl, uri, selector=None, depth=0, depth_counter=0, fetch_readonly=False, manager=None): reftable = schema.ovs_tables[table].references[column].ref_table relation = schema.ovs_tables[table].references[column].relation row = idl.tables[table].rows[row] column_data = row.__getattr__(column) data = None if not depth: if relation == OVSDB_SCHEMA_REFERENCE: if isinstance(column_data, ovs.db.idl.Row): data = utils.row_to_uri(column_data, reftable, schema, idl) elif isinstance(column_data, list): data = [] for item in column_data: data.append(utils.row_to_uri(item, reftable, schema, idl)) elif isinstance(column_data, dict): data = {} for k, v in column_data.iteritems(): data[k] = utils.row_to_uri(v, reftable, schema, idl) elif relation == OVSDB_SCHEMA_CHILD: _max = schema.ovs_tables[table].references[column].n_max if isinstance(column_data, ovs.db.idl.Row): if _max == 1: data = uri else: index = utils.row_to_index(column_data, reftable, schema, idl) data = uri + '/' + str(index) elif isinstance(column_data, list): data = [] if _max == 1 and len(column_data): data = uri else: for item in column_data: index = utils.row_to_index(item, reftable, schema, idl) data.append(uri + '/' + str(index)) elif isinstance(column_data, dict): data = {} for k, v in column_data.iteritems(): data[k] = uri + '/' + str(k) # GET with depth else: if isinstance(column_data, ovs.db.idl.Row): if fetch_readonly and manager: yield utils.fetch_readonly_columns(schema, table, idl, manager, [column_data]) data = yield get_row_json(column_data.uuid, reftable, schema, idl, uri, selector, depth, depth_counter) elif isinstance(column_data, dict): if fetch_readonly and manager: yield utils.fetch_readonly_columns(schema, table, idl, manager, column_data.values()) data = {} for k, v in column_data.iteritems(): data[k] = yield get_row_json(v.uuid, reftable, schema, idl, uri, selector, depth, depth_counter) elif isinstance(column_data, list): if fetch_readonly and manager: yield utils.fetch_readonly_columns(schema, table, idl, manager, column_data) data = [] for item in column_data: result = yield get_row_json(item.uuid, reftable, schema, idl, uri, selector, depth, depth_counter) data.append(result) raise gen.Return(data)
def _get_row_data(row, table_name, schema, idl, index=None): if index is None: index = utils.row_to_index(row, table_name, schema, idl) row_data = {} # Routes are special case - only static routes are returned if table_name == 'Route' and row.__getattr__('from') != 'static': return # Iterate over all columns in the row table_schema = schema.ovs_tables[table_name] for column_name in table_schema.config.keys(): column_data = row.__getattr__(column_name) # Do not include empty columns if column_data is None or column_data == {} or column_data == []: continue row_data[column_name] = column_data # Iterate over all children (forward and backward references) in the row for child_name in table_schema.children: # Forward reference # Two types of forward references exist # - regular (List of uuid) # - key/value type (Dict type) children_data = {} indexer = 0 if child_name in table_schema.references: # Only include configurable children if (table_schema.references[child_name].category != OVSDB_SCHEMA_CONFIG): continue column_data = row.__getattr__(child_name) child_table_name = table_schema.references[child_name].ref_table # Check kv_type references keys = None kv_type = table_schema.references[child_name].kv_type if kv_type and isinstance(column_data, dict): keys = column_data.keys() column_data = column_data.values() # Iterate through all items in column_data count = 0 for item in column_data: if kv_type: kv_index = keys[count] data = _get_row_data( item, child_table_name, schema, idl, kv_index) children_data.update({keys[count]: data.values()[0]}) count = count + 1 else: data = _get_row_data(item, child_table_name, schema, idl) _indexes = schema.ovs_tables[child_table_name].indexes if len(_indexes) == 1 and _indexes[0] == 'uuid': indexer = indexer + 1 child_index = child_table_name + str(indexer) data = {child_index: data.values()[0]} children_data.update(data) # Backward reference else: column_name = None # Find the 'parent' name from child table (back referenced child) # e.g. in Route table 'vrf' column is the 'parent' column for name, column in (schema.ovs_tables[child_name]. references.iteritems()): if column.relation == OVSDB_SCHEMA_PARENT: # Found the parent column column_name = name break # Iterate through entire child table to find those rows belonging # to the same parent for item in idl.tables[child_name].rows.itervalues(): # Get the parent row reference ref = item.__getattr__(column_name) # Parent reference is same as 'row' (row was passed to #this function) this is now the child of 'row' if ref.uuid == row.uuid: data = _get_row_data(item, child_name, schema, idl) if data is not None: children_data.update(data) if children_data: row_data[child_name] = children_data # Iterate through 'references' from table for refname, refobj in table_schema.references.iteritems(): refdata = [] if ( refobj.relation == OVSDB_SCHEMA_REFERENCE and refobj.category == OVSDB_SCHEMA_CONFIG ): reflist = row.__getattr__(refname) if len(reflist) == 0: continue ref_table_name = table_schema.references[refname].ref_table for item in reflist: key_index = utils.row_to_index( item, ref_table_name, schema, idl) refdata.append(key_index) row_data[refname] = refdata return {index: row_data}
def setup_row(rowdata, table_name, schema, idl, txn): """ set up rows recursively """ row_index = rowdata.keys()[0] row_data = rowdata.values()[0] table_schema = schema.ovs_tables[table_name] idl_table = idl.tables[table_name] # get row reference from table _new = False row = index_to_row(row_index, table_schema, idl_table) if row is None: row = txn.insert(idl.tables[table_name]) _new = True # NOTE: populate configuration data config_keys = table_schema.config.keys() for key in config_keys: # TODO: return error if trying to set an immutable column # skip if trying to set an immutable column for an existing row if not _new and table_schema.config[key].mutable is False: continue if key not in row_data: # skip if it's a new row if _new or row.__getattr__(key) is None: continue else: # set the right empty value value = utils.get_empty_by_basic_type(row.__getattr__(key)) else: value = row_data[key] row.__setattr__(key, value) # NOTE: populate non-config index columns if _new: for key in table_schema.indexes: if key is 'uuid': continue if key not in table_schema.config.keys(): row.__setattr__(key, row_data[key]) # NOTE: set up child references for key in table_schema.children: # NOTE: 'forward' type children if key in table_schema.references: child_table_name = table_schema.references[key].ref_table # skip immutable column if not _new and not table_schema.references[key].mutable: continue # set up empty reference list if key not in row_data: if _new or row.__getattr__(key) is None: continue else: value = utils.get_empty_by_basic_type(row.__getattr__(key)) row.__setattr__(key, value) else: new_data = row_data[key] # {key:UUID} type of reference check kv_type = table_schema.references[key].kv_type # if not a new row, delete non-existent child references if not _new: current_list = row.__getattr__(key) if current_list: if kv_type: current_list = current_list.values() delete_list = [] for item in current_list: index = utils.row_to_index(item, child_table_name, schema, idl) if index not in new_data: delete_list.append(item) if delete_list: for item in delete_list: _delete(item, child_table_name, schema, idl, txn) # setup children children = {} for index, child_data in new_data.iteritems(): _child = setup_row({index:child_data}, child_table_name, schema, idl, txn) children.update(_child) # NOTE: If the child table doesn't have indexes, replace json index # with row.uuid if not schema.ovs_tables[child_table_name].index_columns: for k,v in children.iteritems(): new_data[v.uuid] = new_data[k] del new_data[k] if kv_type: if table_schema.references[key].kv_key_type.name == 'integer': tmp = {} for k,v in children.iteritems(): tmp[int(k)] = v children = tmp row.__setattr__(key, children) else: row.__setattr__(key, children.values()) # Backward reference else: # get list of all 'backward' references column_name = None for x, y in schema.ovs_tables[key].references.iteritems(): if y.relation == OVSDB_SCHEMA_PARENT: column_name = x break # delete non-existent rows # get list of all rows with same parent if not _new: current_list = [] for item in idl.tables[key].rows.itervalues(): parent = item.__getattr__(column_name) if parent.uuid == row.uuid: current_list.append(item) new_data = None if key in row_data: new_data = row_data[key] if current_list: delete_list = [] if new_data is None: delete_list = current_list else: for item in current_list: index = utils.row_to_index(item,key, schema, idl) if index not in new_data: delete_list.append(item) if delete_list: _delete(delete_list, key, schema, idl, txn) # set up children rows if new_data is not None: for x,y in new_data.iteritems(): child = setup_row({x:y}, key, schema, idl, txn) # fill the parent reference column child.values()[0].__setattr__(column_name, row) return {row_index:row}