示例#1
0
def setup_table(table, table_data, txn, reflist, schema, idl,
                validator_adapter, errors):

    # Iterate over each row
    for index, row_data in table_data.iteritems():
        index_values = utils.escaped_split(index)

        (row, isNew) = setup_row(index_values, table, row_data, txn, reflist,
                                 schema, idl, validator_adapter, errors)
        if row is None:
            continue

        op = REQUEST_TYPE_CREATE if isNew else REQUEST_TYPE_UPDATE
        validator_adapter.add_resource_op(op, row, table)

        # Save this in global reflist
        reflist[(table, index)] = (row, isNew)
示例#2
0
文件: _write.py 项目: mirmali/ops
def index_to_row(index, table_schema, dbtable):
    """
    This subroutine fetches the row reference using index.
    index is either of type uuid.UUID or is a uri escaped string which contains
    the combination indices that are used to identify a resource.
    """
    if isinstance(index, uuid.UUID):
        # index is of type UUID
        if index in dbtable.rows:
            return dbtable.rows[index]
        else:
            return None
    else:
        # index is an escaped combine indices string
        index_values = utils.escaped_split(index)
        indexes = table_schema.indexes

        # if table has no indexes, we create a new entry
        if not table_schema.index_columns:
            return None

        # TODO: Raise an exception here as this is an error
        if len(index_values) != len(indexes):
            raise Exception('Combination index error for table')

        for row in dbtable.rows.itervalues():
            i = 0
            for index, value in zip(indexes, index_values):
                if index == 'uuid':
                    if str(row.uuid) != value:
                        break
                elif str(row.__getattr__(index)) != value:
                    break

                # matched index
                i += 1

            if i == len(indexes):
                return row

        return None
示例#3
0
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)