Example #1
0
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)
Example #2
0
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)
Example #3
0
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}
Example #4
0
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}