def _update_sqlite_namespace_id_name_constraint(metadef, metadef_namespaces,
                                                new_constraint_name,
                                                new_fk_name):
    migrate.UniqueConstraint(metadef.c.namespace_id, metadef.c.name).drop()
    migrate.UniqueConstraint(metadef.c.namespace_id,
                             metadef.c.name,
                             name=new_constraint_name).create()
    migrate.ForeignKeyConstraint([metadef.c.namespace_id],
                                 [metadef_namespaces.c.id],
                                 name=new_fk_name).create()
def _downgrade_sqlite_namespace_id_name_constraint(metadef, metadef_namespaces,
                                                   constraint_name, fk_name):
    migrate.UniqueConstraint(metadef.c.namespace_id,
                             metadef.c.name,
                             name=constraint_name).drop()
    migrate.UniqueConstraint(metadef.c.namespace_id, metadef.c.name).create()

    migrate.ForeignKeyConstraint([metadef.c.namespace_id],
                                 [metadef_namespaces.c.id],
                                 name=fk_name).drop()
    migrate.ForeignKeyConstraint([metadef.c.namespace_id],
                                 [metadef_namespaces.c.id]).create()
Exemple #3
0
def upgrade(migrate_engine):
    meta = sql.MetaData()
    meta.bind = migrate_engine

    nonlocal_user = sql.Table('nonlocal_user', meta, autoload=True)
    migrate.UniqueConstraint(nonlocal_user.c.user_id,
                             name='ixu_nonlocal_user_user_id').create()
Exemple #4
0
 def _add_unique_constraint_to_role_name(self,
                                         constraint_name='ixu_role_name'):
     meta = sqlalchemy.MetaData()
     meta.bind = self.engine
     role_table = sqlalchemy.Table('role', meta, autoload=True)
     migrate.UniqueConstraint(role_table.c.name,
                              name=constraint_name).create()
def _drop_unique_constraint_if_exists(inspector, table_name, metadef):
    name = _get_unique_constraint_name(inspector, table_name,
                                       ['namespace_id', 'name'])
    if name:
        migrate.UniqueConstraint(metadef.c.namespace_id,
                                 metadef.c.name,
                                 name=name).drop()
def _alter_sourceassoc(meta, t_name, ix_name, post_action=False):
    if meta.bind.engine.name == 'sqlite':
        return

    sourceassoc = sa.Table('sourceassoc', meta, autoload=True)
    table = sa.Table(t_name, meta, autoload=True)
    user = sa.Table('user', meta, autoload=True)

    c_name = '%s_id' % t_name
    col = getattr(sourceassoc.c, c_name)
    uniq_name = 'uniq_sourceassoc0%s0user_id' % c_name

    uniq_cols = (c_name, 'user_id')
    param = {'columns': [col], 'refcolumns': [table.c.id]}
    user_param = {
        'columns': [sourceassoc.c.user_id],
        'refcolumns': [user.c.id]
    }
    if meta.bind.engine.name == 'mysql':
        param['name'] = 'fk_sourceassoc_%s' % c_name
        user_param['name'] = 'fk_sourceassoc_user_id'

    actions = [
        migrate.ForeignKeyConstraint(**user_param),
        migrate.ForeignKeyConstraint(**param),
        sa.Index(ix_name, sourceassoc.c.source_id, col),
        migrate.UniqueConstraint(*uniq_cols, table=sourceassoc, name=uniq_name)
    ]
    for action in actions:
        action.create() if post_action else action.drop()
def upgrade(migrate_engine):
    meta = sql.MetaData()
    meta.bind = migrate_engine

    role_table = sql.Table(_ROLE_TABLE_NAME, meta, autoload=True)

    # NOTE(morganfainberg): the `role_name` unique constraint is not
    # guaranteed to be named 'ixu_role_name', so we need to search for the
    # correct constraint that only affects role_table.c.name and drop
    # that constraint.
    #
    # This is an idempotent change that reflects the fix to migration
    # 88 if the role_name unique constraint was not named consistently and
    # someone manually fixed the migrations / db without dropping the
    # old constraint.
    # This is a copy of migration 96 to catch any/all deployments that
    # are close to master. migration 96 will be backported to
    # stable/mitaka.
    to_drop = None
    if migrate_engine.name == 'mysql':
        for c in role_table.indexes:
            if (c.unique and len(c.columns) == 1
                    and _ROLE_NAME_COLUMN_NAME in c.columns):
                to_drop = c
                break
    else:
        for c in role_table.constraints:
            if len(c.columns) == 1 and _ROLE_NAME_COLUMN_NAME in c.columns:
                to_drop = c
                break

    if to_drop is not None:
        migrate.UniqueConstraint(role_table.c.name, name=to_drop.name).drop()
def upgrade(migrate_engine):
    meta = sql.MetaData()
    meta.bind = migrate_engine
    # For Mysql and PostgreSQL, drop the FK in limit table, drop the unique
    # constraint in registered limit and limit tables.
    #
    # For SQLite, drop the old tables, then rename the new tables.
    limit_table = sql.Table('limit', meta, autoload=True)
    registered_limit_table = sql.Table('registered_limit', meta, autoload=True)

    if migrate_engine.name != 'sqlite':
        project_table = sql.Table('project', meta, autoload=True)
        inspector = sql.inspect(migrate_engine)
        for fk in inspector.get_foreign_keys('limit'):
            fkey = migrate.ForeignKeyConstraint([limit_table.c.project_id],
                                                [project_table.c.id],
                                                name=fk['name'])
            fkey.drop()
        for uc in inspector.get_unique_constraints('limit'):
            if set(uc['column_names']) == set(
                ['project_id', 'service_id', 'region_id', 'resource_name']):
                uc = migrate.UniqueConstraint(limit_table.c.project_id,
                                              limit_table.c.service_id,
                                              limit_table.c.region_id,
                                              limit_table.c.resource_name,
                                              name=uc['name'])
                uc.drop()
        for uc in inspector.get_unique_constraints('registered_limit'):
            if set(uc['column_names']) == set(
                ['service_id', 'region_id', 'resource_name']):
                uc = migrate.UniqueConstraint(
                    registered_limit_table.c.service_id,
                    registered_limit_table.c.region_id,
                    registered_limit_table.c.resource_name,
                    name=uc['name'])
                uc.drop()

    else:
        registered_limit_table_new = sql.Table('registered_limit_new',
                                               meta,
                                               autoload=True)
        limit_table_new = sql.Table('limit_new', meta, autoload=True)

        limit_table.drop()
        limit_table_new.rename('limit')
        registered_limit_table.drop()
        registered_limit_table_new.rename('registered_limit')
Exemple #9
0
def upgrade(migrate_engine):
    meta = sql.MetaData()
    meta.bind = migrate_engine

    role_table = sql.Table(_ROLE_TABLE_NAME, meta, autoload=True)
    domain_id = sql.Column(_DOMAIN_ID_COLUMN_NAME,
                           sql.String(64),
                           nullable=False,
                           server_default=_NULL_DOMAIN_ID)
    role_table.create_column(domain_id)

    migrate.UniqueConstraint(role_table.c.name,
                             name=_ROLE_NAME_OLD_CONSTRAINT).drop()

    migrate.UniqueConstraint(role_table.c.name,
                             role_table.c.domain_id,
                             name=_ROLE_NAME_NEW_CONSTRAINT).create()
Exemple #10
0
def change_uniq(meta, downgrade=False):
    uniq_name = 'uniq_sourceassoc0meter_id0user_id'
    columns = ('meter_id', 'user_id')

    if meta.bind.engine.name == 'sqlite':
        return

    sourceassoc = sa.Table('sourceassoc', meta, autoload=True)
    meter = sa.Table('meter', meta, autoload=True)
    user = sa.Table('user', meta, autoload=True)
    if meta.bind.engine.name == 'mysql':
        # For mysql dialect all dependent FK should be removed
        #  before renaming of constraint.
        params = {
            'columns': [sourceassoc.c.meter_id],
            'refcolumns': [meter.c.id],
            'name': 'fk_sourceassoc_meter_id'
        }
        migrate.ForeignKeyConstraint(**params).drop()
        params = {
            'columns': [sourceassoc.c.user_id],
            'refcolumns': [user.c.id],
            'name': 'fk_sourceassoc_user_id'
        }
        migrate.ForeignKeyConstraint(**params).drop()
    if downgrade:
        migrate.UniqueConstraint(*columns, table=sourceassoc,
                                 name=uniq_name).drop()
    else:
        migrate.UniqueConstraint(*columns, table=sourceassoc,
                                 name=uniq_name).create()
    if meta.bind.engine.name == 'mysql':
        params = {
            'columns': [sourceassoc.c.meter_id],
            'refcolumns': [meter.c.id],
            'name': 'fk_sourceassoc_meter_id'
        }
        migrate.ForeignKeyConstraint(**params).create()
        params = {
            'columns': [sourceassoc.c.user_id],
            'refcolumns': [user.c.id],
            'name': 'fk_sourceassoc_user_id'
        }
        migrate.ForeignKeyConstraint(**params).create()
Exemple #11
0
def upgrade(migrate_engine):
    meta = sql.MetaData()
    meta.bind = migrate_engine

    cascaded_pods = sql.Table(
        'cascaded_pods', meta,
        sql.Column('pod_id', sql.String(length=36), primary_key=True),
        sql.Column('pod_name', sql.String(length=255), unique=True,
                   nullable=False),
        sql.Column('pod_az_name', sql.String(length=255), nullable=True),
        sql.Column('dc_name', sql.String(length=255), nullable=True),
        sql.Column('az_name', sql.String(length=255), nullable=False),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    cascaded_pod_service_configuration = sql.Table(
        'cascaded_pod_service_configuration', meta,
        sql.Column('service_id', sql.String(length=64), primary_key=True),
        sql.Column('pod_id', sql.String(length=64), nullable=False),
        sql.Column('service_type', sql.String(length=64), nullable=False),
        sql.Column('service_url', sql.String(length=512), nullable=False),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    pod_binding = sql.Table(
        'pod_binding', meta,
        sql.Column('id', sql.String(36), primary_key=True),
        sql.Column('tenant_id', sql.String(length=255), nullable=False),
        sql.Column('pod_id', sql.String(length=255), nullable=False),
        sql.Column('is_binding', sql.Boolean, nullable=False),
        sql.Column('created_at', sql.DateTime),
        sql.Column('updated_at', sql.DateTime),
        migrate.UniqueConstraint(
            'tenant_id', 'pod_id',
            name='pod_binding0tenant_id0pod_id'),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    tables = [cascaded_pods, cascaded_pod_service_configuration,
              pod_binding]
    for table in tables:
        table.create()

    fkey = {'columns': [cascaded_pod_service_configuration.c.pod_id],
            'references': [cascaded_pods.c.pod_id]}
    migrate.ForeignKeyConstraint(columns=fkey['columns'],
                                 refcolumns=fkey['references'],
                                 name=fkey.get('name')).create()

    fkey = {'columns': [pod_binding.c.pod_id],
            'references': [cascaded_pods.c.pod_id]}
    migrate.ForeignKeyConstraint(columns=fkey['columns'],
                                 refcolumns=fkey['references'],
                                 name=fkey.get('name')).create()
def upgrade(migrate_engine):
    meta = MetaData()
    meta.bind = migrate_engine
    instance_types = Table('instance_types', meta, autoload=True)

    string_column = Column('flavorid_str', String(255))

    string_column.create(instance_types)

    try:
        # NOTE(bcwaldon): This catches a bug with python-migrate
        # failing to add the unique constraint
        try:
            migrate.UniqueConstraint(string_column).create()
        except migrate.changeset.NotSupportedError:
            LOG.error("Failed to add unique constraint on flavorid")
            pass

        # NOTE(bcwaldon): this is a hack to preserve uniqueness constraint
        # on existing 'name' column
        try:
            migrate.UniqueConstraint(instance_types.c.name).create()
        except Exception:
            pass

        integer_column = instance_types.c.flavorid

        instance_type_rows = list(instance_types.select().execute())
        for instance_type in instance_type_rows:
            flavorid_int = instance_type.flavorid
            instance_types.update()\
                          .where(integer_column == flavorid_int)\
                          .values(flavorid_str=str(flavorid_int))\
                          .execute()
    except Exception:
        string_column.drop()
        raise

    integer_column.alter(name='flavorid_int')
    string_column.alter(name='flavorid')
    integer_column.drop()
def upgrade(migrate_engine):
    meta = sql.MetaData()
    meta.bind = migrate_engine

    user_table = sql.Table('user', meta, autoload=True)
    local_user_table = sql.Table('local_user', meta, autoload=True)
    password_table = sql.Table('password', meta, autoload=True)

    # migrate data to local_user table
    local_user_values = []
    for row in user_table.select().execute():
        # skip the row that already exists in `local_user`, this could
        # happen if run into a partially-migrated table due to the
        # bug #1549705.
        filter_by = local_user_table.c.user_id == row['id']
        user_count = sql.select([func.count()]).select_from(
            local_user_table).where(filter_by).execute().fetchone()[0]
        if user_count == 0:
            local_user_values.append({
                'user_id': row['id'],
                'domain_id': row['domain_id'],
                'name': row['name']
            })
    if local_user_values:
        local_user_table.insert().values(local_user_values).execute()

    # migrate data to password table
    sel = (sql.select([user_table, local_user_table],
                      use_labels=True).select_from(
                          user_table.join(
                              local_user_table,
                              user_table.c.id == local_user_table.c.user_id)))
    user_rows = sel.execute()
    password_values = []
    for row in user_rows:
        if row['user_password']:
            password_values.append({
                'local_user_id': row['local_user_id'],
                'password': row['user_password']
            })
    if password_values:
        password_table.insert().values(password_values).execute()

    # remove domain_id and name unique constraint
    if migrate_engine.name != 'sqlite':
        migrate.UniqueConstraint(user_table.c.domain_id,
                                 user_table.c.name,
                                 name='ixu_user_name_domain_id').drop()

    # drop user columns
    user_table.c.domain_id.drop()
    user_table.c.name.drop()
    user_table.c.password.drop()
def upgrade(migrate_engine):
    meta = sql.MetaData()
    meta.bind = migrate_engine

    role_table = sql.Table(_ROLE_TABLE_NAME, meta, autoload=True)
    domain_id = sql.Column(_DOMAIN_ID_COLUMN_NAME,
                           sql.String(64),
                           nullable=False,
                           server_default=_NULL_DOMAIN_ID)

    # NOTE(morganfainberg): the `role_name` unique constraint is not
    # guaranteed to be a fixed name, such as 'ixu_role_name`, so we need to
    # search for the correct constraint that only affects role_table.c.name
    # and drop that constraint.
    to_drop = None
    if migrate_engine.name == 'mysql':
        for c in role_table.indexes:
            if (c.unique and len(c.columns) == 1
                    and _ROLE_NAME_COLUMN_NAME in c.columns):
                to_drop = c
                break
    else:
        for c in role_table.constraints:
            if len(c.columns) == 1 and _ROLE_NAME_COLUMN_NAME in c.columns:
                to_drop = c
                break

    if to_drop is not None:
        migrate.UniqueConstraint(role_table.c.name, name=to_drop.name).drop()

    # perform changes after constraint is dropped.
    if 'domain_id' not in role_table.columns:
        # Only create the column if it doesn't already exist.
        role_table.create_column(domain_id)

    migrate.UniqueConstraint(role_table.c.name,
                             role_table.c.domain_id,
                             name=_ROLE_NAME_NEW_CONSTRAINT).create()
def upgrade(migrate_engine):
    meta = sql.MetaData()
    meta.bind = migrate_engine

    user_table = sql.Table(_USER_TABLE_NAME, meta, autoload=True)

    # NOTE(gnuoy): the `domain_id` unique constraint is not guaranteed to
    # be a fixed name, such as 'ixu_user_name_domain_id`, so we need to
    # search for the correct constraint that only affects
    # user_table.c.domain_id and drop that constraint. (Fix based on
    # morganfainbergs fix in 088_domain_specific_roles.py)
    #
    # This is an idempotent change that reflects the fix to migration
    # 91 if the user name & domain_id unique constraint was not named
    # consistently and someone manually fixed the migrations / db
    # without dropping the old constraint.
    # This is a copy of migration 97 to catch any/all deployments that
    # are close to master. migration 97 will be backported to
    # stable/mitaka.

    to_drop = None
    if migrate_engine.name == 'mysql':
        for index in user_table.indexes:
            if (index.unique and len(index.columns) == 2 and
                    _USER_DOMAINID_COLUMN_NAME in index.columns and
                    _USER_NAME_COLUMN_NAME in index.columns):
                to_drop = index
                break
    else:
        for index in user_table.constraints:
            if (len(index.columns) == 2 and
                    _USER_DOMAINID_COLUMN_NAME in index.columns and
                    _USER_NAME_COLUMN_NAME in index.columns):
                to_drop = index
                break

    # remove domain_id and name unique constraint
    if to_drop is not None:
        migrate.UniqueConstraint(user_table.c.domain_id,
                                 user_table.c.name,
                                 name=to_drop.name).drop()

    # If migration 91 was aborted due to Bug #1572341 then columns may not
    # have been dropped.
    if _USER_DOMAINID_COLUMN_NAME in user_table.c:
        user_table.c.domain_id.drop()
    if _USER_NAME_COLUMN_NAME in user_table.c:
        user_table.c.name.drop()
    if _USER_PASSWORD_COLUMN_NAME in user_table.c:
        user_table.c.password.drop()
def upgrade(migrate_engine):
    meta = sql.MetaData()
    meta.bind = migrate_engine

    access_rule = sql.Table('access_rule', meta, autoload=True)

    external_id = sql.Column('external_id', sql.String(64))
    access_rule.create_column(external_id)
    sql.Index('external_id', access_rule.c.external_id).create()
    unique_constraint_id = migrate.UniqueConstraint('external_id',
                                                    table=access_rule)
    unique_constraint_id.create()

    user_id = sql.Column('user_id', sql.String(64))
    access_rule.create_column(user_id)
    sql.Index('user_id', access_rule.c.user_id).create()
    unique_constraint_rule_for_user = migrate.UniqueConstraint(
        'user_id',
        'service',
        'path',
        'method',
        name='duplicate_access_rule_for_user_constraint',
        table=access_rule)
    unique_constraint_rule_for_user.create()
def _downgrade_constraint_with_fk(metadef, metadef_namespaces, constraint_name,
                                  fk_curr_name, fk_next_name):

    fkc = migrate.ForeignKeyConstraint([metadef.c.namespace_id],
                                       [metadef_namespaces.c.id],
                                       name=fk_curr_name)
    fkc.drop()

    migrate.UniqueConstraint(metadef.c.namespace_id,
                             metadef.c.name,
                             name=constraint_name).drop()

    fkc = migrate.ForeignKeyConstraint([metadef.c.namespace_id],
                                       [metadef_namespaces.c.id],
                                       name=fk_next_name)
    fkc.create()
def upgrade(migrate_engine):
    meta = sql.MetaData()
    meta.bind = migrate_engine

    user_table = sql.Table('user', meta, autoload=True)
    local_user_table = sql.Table('local_user', meta, autoload=True)
    password_table = sql.Table('password', meta, autoload=True)

    # migrate data to local_user table
    local_user_values = []
    for row in user_table.select().execute():
        local_user_values.append({
            'user_id': row['id'],
            'domain_id': row['domain_id'],
            'name': row['name']
        })
    if local_user_values:
        local_user_table.insert().values(local_user_values).execute()

    # migrate data to password table
    sel = (sql.select([user_table, local_user_table],
                      use_labels=True).select_from(
                          user_table.join(
                              local_user_table,
                              user_table.c.id == local_user_table.c.user_id)))
    user_rows = sel.execute()
    password_values = []
    for row in user_rows:
        password_values.append({
            'local_user_id': row['local_user_id'],
            'password': row['user_password']
        })
    if password_values:
        password_table.insert().values(password_values).execute()

    # remove domain_id and name unique constraint
    if migrate_engine.name != 'sqlite':
        migrate.UniqueConstraint(user_table.c.domain_id,
                                 user_table.c.name,
                                 name='ixu_user_name_domain_id').drop()

    # drop user columns
    user_table.c.domain_id.drop()
    user_table.c.name.drop()
    user_table.c.password.drop()
def downgrade(migrate_engine):
    meta = MetaData()
    meta.bind = migrate_engine

    instance_types = Table('instance_types', meta, autoload=True)

    integer_column = Column('flavorid_int', Integer())

    integer_column.create(instance_types)

    try:
        # NOTE(bcwaldon): This catches a bug with python-migrate
        # failing to add the unique constraint
        try:
            migrate.UniqueConstraint(integer_column).create()
        except migrate.changeset.NotSupportedError:
            LOG.info("Failed to add unique constraint on flavorid")
            pass

        string_column = instance_types.c.flavorid

        instance_types_rows = list(instance_types.select().execute())
        for instance_type in instance_types_rows:
            flavorid_str = instance_type.flavorid
            try:
                flavorid_int = int(instance_type.flavorid)
            except ValueError:
                msg = _('Could not cast flavorid to integer: %s. '
                        'Set flavorid to an integer-like string to downgrade.')
                LOG.error(msg % instance_type.flavorid)
                raise

            instance_types.update()\
                          .where(string_column == flavorid_str)\
                          .values(flavorid_int=flavorid_int)\
                          .execute()
    except Exception:
        integer_column.drop()
        raise

    string_column.alter(name='flavorid_str')
    integer_column.alter(name='flavorid')
    string_column.drop()
def index_cleanup(meta, engine_names, table_name, uniq_name, columns, create,
                  unique, limited):
    table = sa.Table(table_name, meta, autoload=True)
    if create:
        if limited and meta.bind.engine.name == 'mysql':
            # For some versions of mysql we can get an error
            # "Specified key was too long; max key length is 1000 bytes".
            # We should create an index by hand in this case with limited
            # length of columns.
            columns_mysql = ",".join((c + "(100)" for c in columns))
            sql = ("create index %s ON %s (%s)" %
                   (uniq_name, table, columns_mysql))
            meta.bind.engine.execute(sql)
        else:
            cols = [table.c[col] for col in columns]
            sa.Index(uniq_name, *cols, unique=unique).create()
    else:
        if unique:
            migrate.UniqueConstraint(*columns, table=table).drop()
        else:
            cols = [table.c[col] for col in columns]
            sa.Index(uniq_name, *cols, unique=unique).drop()
def upgrade(migrate_engine):
    meta = sql.MetaData()
    meta.bind = migrate_engine

    shadow_agents = sql.Table(
        'shadow_agents', meta,
        sql.Column('id', sql.String(length=36), primary_key=True),
        sql.Column('pod_id', sql.String(length=64), nullable=False),
        sql.Column('host', sql.String(length=255), nullable=False),
        sql.Column('type', sql.String(length=36), nullable=False),
        sql.Column('tunnel_ip', sql.String(length=48), nullable=False),
        migrate.UniqueConstraint(
            'host', 'type',
            name='host0type'),
        mysql_engine='InnoDB',
        mysql_charset='utf8')
    shadow_agents.create()

    pods = sql.Table('pods', meta, autoload=True)
    fkey = {'columns': [shadow_agents.c.pod_id],
            'references': [pods.c.pod_id]}
    migrate.ForeignKeyConstraint(columns=fkey['columns'],
                                 refcolumns=fkey['references'],
                                 name=fkey.get('name')).create()
Exemple #22
0
def upgrade(migrate_engine):
    meta = sql.MetaData()
    meta.bind = migrate_engine

    resource_routings = sql.Table(
        'resource_routings',
        meta,
        sql.Column('id', sql.BigInteger, primary_key=True),
        sql.Column('top_id', sql.String(length=127), nullable=False),
        sql.Column('bottom_id', sql.String(length=36)),
        sql.Column('pod_id', sql.String(length=64), nullable=False),
        sql.Column('project_id', sql.String(length=36)),
        sql.Column('resource_type', sql.String(length=64), nullable=False),
        sql.Column('created_at', sql.DateTime),
        sql.Column('updated_at', sql.DateTime),
        migrate.UniqueConstraint(
            'top_id',
            'pod_id',
            'resource_type',
            name='resource_routings0top_id0pod_id0resource_type'),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    async_jobs = sql.Table(
        'async_jobs',
        meta,
        sql.Column('id', sql.String(length=36), primary_key=True),
        sql.Column('type', sql.String(length=36)),
        sql.Column('timestamp',
                   sql.TIMESTAMP,
                   server_default=sql.text('CURRENT_TIMESTAMP'),
                   index=True),
        sql.Column('status', sql.String(length=36)),
        sql.Column('resource_id', sql.String(length=127)),
        sql.Column('extra_id', sql.String(length=36)),
        migrate.UniqueConstraint(
            'type',
            'status',
            'resource_id',
            'extra_id',
            name='async_jobs0type0status0resource_id0extra_id'),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    async_job_logs = sql.Table(
        'async_job_logs',
        meta,
        sql.Column('id', sql.String(length=36), primary_key=True),
        sql.Column('resource_id', sql.String(length=127)),
        sql.Column('type', sql.String(length=36)),
        sql.Column('timestamp',
                   sql.TIMESTAMP,
                   server_default=sql.text('CURRENT_TIMESTAMP'),
                   index=True),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    tables = [async_jobs, resource_routings, async_job_logs]
    for table in tables:
        table.create()

    pods = sql.Table('pods', meta, autoload=True)

    fkeys = [{
        'columns': [resource_routings.c.pod_id],
        'references': [pods.c.pod_id]
    }]
    for fkey in fkeys:
        migrate.ForeignKeyConstraint(columns=fkey['columns'],
                                     refcolumns=fkey['references'],
                                     name=fkey.get('name')).create()
def upgrade(migrate_engine):
    meta = sql.MetaData()
    meta.bind = migrate_engine
    inspector = sql.inspect(migrate_engine)

    user = sql.Table('user', meta, autoload=True)
    local_user = sql.Table('local_user', meta, autoload=True)
    nonlocal_user = sql.Table('nonlocal_user', meta, autoload=True)

    # drop previous fk constraints
    fk_name = _get_fk_name(inspector, 'local_user', 'user_id')
    if fk_name:
        migrate.ForeignKeyConstraint(columns=[local_user.c.user_id],
                                     refcolumns=[user.c.id],
                                     name=fk_name).drop()

    fk_name = _get_fk_name(inspector, 'nonlocal_user', 'user_id')
    if fk_name:
        migrate.ForeignKeyConstraint(columns=[nonlocal_user.c.user_id],
                                     refcolumns=[user.c.id],
                                     name=fk_name).drop()

    # create user unique constraint needed for the new composite fk constraint
    migrate.UniqueConstraint(user.c.id,
                             user.c.domain_id,
                             name='ixu_user_id_domain_id').create()
    # create new composite fk constraints
    migrate.ForeignKeyConstraint(
        columns=[local_user.c.user_id, local_user.c.domain_id],
        refcolumns=[user.c.id, user.c.domain_id],
        onupdate='CASCADE',
        ondelete='CASCADE').create()
    migrate.ForeignKeyConstraint(
        columns=[nonlocal_user.c.user_id, nonlocal_user.c.domain_id],
        refcolumns=[user.c.id, user.c.domain_id],
        onupdate='CASCADE',
        ondelete='CASCADE').create()

    # drop triggers
    if upgrades.USE_TRIGGERS:
        if migrate_engine.name == 'postgresql':
            drop_local_user_insert_trigger = (
                'DROP TRIGGER local_user_after_insert_trigger on local_user;')
            drop_local_user_update_trigger = (
                'DROP TRIGGER local_user_after_update_trigger on local_user;')
            drop_nonlocal_user_insert_trigger = (
                'DROP TRIGGER nonlocal_user_after_insert_trigger '
                'on nonlocal_user;')
            drop_nonlocal_user_update_trigger = (
                'DROP TRIGGER nonlocal_user_after_update_trigger '
                'on nonlocal_user;')
        elif migrate_engine.name == 'mysql':
            drop_local_user_insert_trigger = (
                'DROP TRIGGER local_user_after_insert_trigger;')
            drop_local_user_update_trigger = (
                'DROP TRIGGER local_user_after_update_trigger;')
            drop_nonlocal_user_insert_trigger = (
                'DROP TRIGGER nonlocal_user_after_insert_trigger;')
            drop_nonlocal_user_update_trigger = (
                'DROP TRIGGER nonlocal_user_after_update_trigger;')
        else:
            drop_local_user_insert_trigger = (
                'DROP TRIGGER IF EXISTS local_user_after_insert_trigger;')
            drop_local_user_update_trigger = (
                'DROP TRIGGER IF EXISTS local_user_after_update_trigger;')
            drop_nonlocal_user_insert_trigger = (
                'DROP TRIGGER IF EXISTS nonlocal_user_after_insert_trigger;')
            drop_nonlocal_user_update_trigger = (
                'DROP TRIGGER IF EXISTS nonlocal_user_after_update_trigger;')
        migrate_engine.execute(drop_local_user_insert_trigger)
        migrate_engine.execute(drop_local_user_update_trigger)
        migrate_engine.execute(drop_nonlocal_user_insert_trigger)
        migrate_engine.execute(drop_nonlocal_user_update_trigger)
Exemple #24
0
def upgrade(migrate_engine):

    # For both registered_limit and limit tables in MySQL and PostgreSQL:
    #
    # 1. drop the primary key on `id` column.
    # 2. create a auto increment `internal_id` column with primary key.
    # 3. add unique constraint on `id` column.
    #
    # But SQLite doesn't support add primary key to a existed table, so for
    # SQLite, we'll follow the steps, take the registered_limit as an example:
    #
    # 1. Add a new table `registered_limit_new` which contains `internal_id`
    #    column.
    # 2. migrate the data from `registered_limit` to `registered_limit_new`
    # 3. drop the `registered_limit`, rename `registered_limit_new` to
    #    `registered_limit`.

    meta = sql.MetaData()
    meta.bind = migrate_engine
    registered_limit_table = sql.Table('registered_limit', meta, autoload=True)
    limit_table = sql.Table('limit', meta, autoload=True)

    if migrate_engine.name != 'sqlite':
        pk = migrate.PrimaryKeyConstraint('id', table=registered_limit_table)
        pk.drop()
        if migrate_engine.name == 'mysql':
            migrate_engine.execute(MYSQL_CREATE_ID_PRIMARY_KEY_COLUMN %
                                   'registered_limit')
        else:
            migrate_engine.execute(POSTGRESQL_CREATE_ID_PRIMARY_KEY_COLUMN %
                                   'registered_limit')
        unique_constraint = migrate.UniqueConstraint(
            'id', table=registered_limit_table)
        unique_constraint.create()

        pk = migrate.PrimaryKeyConstraint('id', table=limit_table)
        pk.drop()
        if migrate_engine.name == 'mysql':
            migrate_engine.execute(MYSQL_CREATE_ID_PRIMARY_KEY_COLUMN %
                                   'limit')
        else:
            migrate_engine.execute(POSTGRESQL_CREATE_ID_PRIMARY_KEY_COLUMN %
                                   'limit')
        unique_constraint = migrate.UniqueConstraint('id', table=limit_table)
        unique_constraint.create()
    else:
        # SQLite case
        registered_limit_table_new = sql.Table(
            'registered_limit_new',
            meta,
            sql.Column('internal_id', sql.Integer, primary_key=True),
            sql.Column('id', sql.String(length=64), unique=True),
            sql.Column('service_id', sql.String(64)),
            sql.Column('region_id', sql.String(64), nullable=True),
            sql.Column('resource_name', sql.String(255)),
            sql.Column('default_limit', sql.Integer, nullable=False),
            sql.Column('description', sql.Text),
            mysql_engine='InnoDB',
            mysql_charset='utf8')
        registered_limit_table_new.create(migrate_engine, checkfirst=True)

        limit_table_new = sql.Table('limit_new',
                                    meta,
                                    sql.Column('internal_id',
                                               sql.Integer,
                                               primary_key=True),
                                    sql.Column('id',
                                               sql.String(length=64),
                                               unique=True),
                                    sql.Column('project_id', sql.String(64)),
                                    sql.Column('service_id', sql.String(64)),
                                    sql.Column('region_id',
                                               sql.String(64),
                                               nullable=True),
                                    sql.Column('resource_name',
                                               sql.String(255)),
                                    sql.Column('resource_limit',
                                               sql.Integer,
                                               nullable=False),
                                    sql.Column('description', sql.Text),
                                    mysql_engine='InnoDB',
                                    mysql_charset='utf8')
        limit_table_new.create(migrate_engine, checkfirst=True)
Exemple #25
0
def upgrade(migrate_engine):
    meta = sqlalchemy.MetaData()
    meta.bind = migrate_engine
    inspector = inspect(migrate_engine)

    metadef_namespaces = Table('metadef_namespaces', meta, autoload=True)
    metadef_properties = Table('metadef_properties', meta, autoload=True)
    metadef_objects = Table('metadef_objects', meta, autoload=True)
    metadef_ns_res_types = Table('metadef_namespace_resource_types',
                                 meta,
                                 autoload=True)
    metadef_resource_types = Table('metadef_resource_types',
                                   meta,
                                   autoload=True)
    metadef_tags = Table('metadef_tags', meta, autoload=True)

    constraints = [
        ('ix_namespaces_namespace', [metadef_namespaces.c.namespace]),
        ('ix_objects_namespace_id_name',
         [metadef_objects.c.namespace_id, metadef_objects.c.name]),
        ('ix_metadef_properties_namespace_id_name',
         [metadef_properties.c.namespace_id, metadef_properties.c.name])
    ]
    metadef_tags_constraints = inspector.get_unique_constraints('metadef_tags')
    for constraint in metadef_tags_constraints:
        if set(constraint['column_names']) == set(['namespace_id', 'name']):
            constraints.append(
                (constraint['name'],
                 [metadef_tags.c.namespace_id, metadef_tags.c.name]))
    if meta.bind.name == "ibm_db_sa":
        # For db2, the following constraints need to be dropped first,
        # otherwise the index like ix_metadef_ns_res_types_namespace_id
        # will fail to create. These constraints will be added back at
        # the end. It should not affect the origional logic for other
        # database backends.
        for (constraint_name, cols) in constraints:
            _change_db2_unique_constraint('drop', constraint_name, *cols)
    else:
        Index('ix_namespaces_namespace', metadef_namespaces.c.namespace).drop()

        Index('ix_objects_namespace_id_name', metadef_objects.c.namespace_id,
              metadef_objects.c.name).drop()

        Index('ix_metadef_properties_namespace_id_name',
              metadef_properties.c.namespace_id,
              metadef_properties.c.name).drop()

    fkc = migrate.ForeignKeyConstraint([metadef_tags.c.namespace_id],
                                       [metadef_namespaces.c.id])
    fkc.create()

    # `migrate` module removes unique constraint after adding
    # foreign key to the table in sqlite.
    # The reason of this issue is that it isn't possible to add fkc to
    # existing table in sqlite. Instead of this we should recreate the table
    # with needed fkc in the declaration. Migrate package provide us with such
    # possibility, but unfortunately it recreates the table without
    # constraints. Create unique constraint manually.
    if migrate_engine.name == 'sqlite' and len(
            inspector.get_unique_constraints('metadef_tags')) == 0:
        uc = migrate.UniqueConstraint(metadef_tags.c.namespace_id,
                                      metadef_tags.c.name)
        uc.create()

    if meta.bind.name != "ibm_db_sa":
        Index('ix_tags_namespace_id_name', metadef_tags.c.namespace_id,
              metadef_tags.c.name).drop()

    Index('ix_metadef_tags_name', metadef_tags.c.name).create()

    Index('ix_metadef_tags_namespace_id', metadef_tags.c.namespace_id,
          metadef_tags.c.name).create()

    if migrate_engine.name == 'mysql':
        # We need to drop some foreign keys first  because unique constraints
        # that we want to delete depend on them. So drop the fk and recreate
        # it again after unique constraint deletion.
        fkc = migrate.ForeignKeyConstraint([metadef_properties.c.namespace_id],
                                           [metadef_namespaces.c.id],
                                           name='metadef_properties_ibfk_1')
        fkc.drop()
        constraint = UniqueConstraint(metadef_properties.c.namespace_id,
                                      metadef_properties.c.name,
                                      name='namespace_id')
        migrate_engine.execute(DropConstraint(constraint))
        fkc.create()

        fkc = migrate.ForeignKeyConstraint([metadef_objects.c.namespace_id],
                                           [metadef_namespaces.c.id],
                                           name='metadef_objects_ibfk_1')
        fkc.drop()
        constraint = UniqueConstraint(metadef_objects.c.namespace_id,
                                      metadef_objects.c.name,
                                      name='namespace_id')
        migrate_engine.execute(DropConstraint(constraint))
        fkc.create()

        constraint = UniqueConstraint(metadef_ns_res_types.c.resource_type_id,
                                      metadef_ns_res_types.c.namespace_id,
                                      name='resource_type_id')
        migrate_engine.execute(DropConstraint(constraint))

        constraint = UniqueConstraint(metadef_namespaces.c.namespace,
                                      name='namespace')
        migrate_engine.execute(DropConstraint(constraint))

        constraint = UniqueConstraint(metadef_resource_types.c.name,
                                      name='name')
        migrate_engine.execute(DropConstraint(constraint))

    if migrate_engine.name == 'postgresql':
        met_obj_index_name = (
            inspector.get_unique_constraints('metadef_objects')[0]['name'])
        constraint = UniqueConstraint(metadef_objects.c.namespace_id,
                                      metadef_objects.c.name,
                                      name=met_obj_index_name)
        migrate_engine.execute(DropConstraint(constraint))

        met_prop_index_name = (
            inspector.get_unique_constraints('metadef_properties')[0]['name'])
        constraint = UniqueConstraint(metadef_properties.c.namespace_id,
                                      metadef_properties.c.name,
                                      name=met_prop_index_name)
        migrate_engine.execute(DropConstraint(constraint))

        metadef_namespaces_name = (
            inspector.get_unique_constraints('metadef_namespaces')[0]['name'])
        constraint = UniqueConstraint(metadef_namespaces.c.namespace,
                                      name=metadef_namespaces_name)
        migrate_engine.execute(DropConstraint(constraint))

        metadef_resource_types_name = (inspector.get_unique_constraints(
            'metadef_resource_types')[0]['name'])
        constraint = UniqueConstraint(metadef_resource_types.c.name,
                                      name=metadef_resource_types_name)
        migrate_engine.execute(DropConstraint(constraint))

        constraint = UniqueConstraint(
            metadef_tags.c.namespace_id,
            metadef_tags.c.name,
            name='metadef_tags_namespace_id_name_key')
        migrate_engine.execute(DropConstraint(constraint))

    Index('ix_metadef_ns_res_types_namespace_id',
          metadef_ns_res_types.c.namespace_id).create()

    Index('ix_metadef_namespaces_namespace',
          metadef_namespaces.c.namespace).create()

    Index('ix_metadef_namespaces_owner', metadef_namespaces.c.owner).create()

    Index('ix_metadef_objects_name', metadef_objects.c.name).create()

    Index('ix_metadef_objects_namespace_id',
          metadef_objects.c.namespace_id).create()

    Index('ix_metadef_properties_name', metadef_properties.c.name).create()

    Index('ix_metadef_properties_namespace_id',
          metadef_properties.c.namespace_id).create()

    if meta.bind.name == "ibm_db_sa":
        # For db2, add these constraints back. It should not affect the
        # origional logic for other database backends.
        for (constraint_name, cols) in constraints:
            _change_db2_unique_constraint('create', constraint_name, *cols)
def upgrade(migrate_engine):
    meta = sql.MetaData()
    meta.bind = migrate_engine

    if migrate_engine.name == 'mysql':
        # In Folsom we explicitly converted migrate_version to UTF8.
        migrate_engine.execute(
            'ALTER TABLE migrate_version CONVERT TO CHARACTER SET utf8')
        # Set default DB charset to UTF8.
        migrate_engine.execute('ALTER DATABASE %s DEFAULT CHARACTER SET utf8' %
                               migrate_engine.url.database)

    credential = sql.Table('credential',
                           meta,
                           sql.Column('id',
                                      sql.String(length=64),
                                      primary_key=True),
                           sql.Column('user_id',
                                      sql.String(length=64),
                                      nullable=False),
                           sql.Column('project_id', sql.String(length=64)),
                           sql.Column('blob', ks_sql.JsonBlob, nullable=False),
                           sql.Column('type',
                                      sql.String(length=255),
                                      nullable=False),
                           sql.Column('extra', ks_sql.JsonBlob.impl),
                           mysql_engine='InnoDB',
                           mysql_charset='utf8')

    domain = sql.Table('domain',
                       meta,
                       sql.Column('id',
                                  sql.String(length=64),
                                  primary_key=True),
                       sql.Column('name',
                                  sql.String(length=64),
                                  nullable=False),
                       sql.Column('enabled',
                                  sql.Boolean,
                                  default=True,
                                  nullable=False),
                       sql.Column('extra', ks_sql.JsonBlob.impl),
                       mysql_engine='InnoDB',
                       mysql_charset='utf8')

    endpoint = sql.Table('endpoint',
                         meta,
                         sql.Column('id',
                                    sql.String(length=64),
                                    primary_key=True),
                         sql.Column('legacy_endpoint_id',
                                    sql.String(length=64)),
                         sql.Column('interface',
                                    sql.String(length=8),
                                    nullable=False),
                         sql.Column('region', sql.String(length=255)),
                         sql.Column('service_id',
                                    sql.String(length=64),
                                    nullable=False),
                         sql.Column('url', sql.Text, nullable=False),
                         sql.Column('extra', ks_sql.JsonBlob.impl),
                         mysql_engine='InnoDB',
                         mysql_charset='utf8')

    group = sql.Table('group',
                      meta,
                      sql.Column('id', sql.String(length=64),
                                 primary_key=True),
                      sql.Column('domain_id',
                                 sql.String(length=64),
                                 nullable=False),
                      sql.Column('name', sql.String(length=64),
                                 nullable=False),
                      sql.Column('description', sql.Text),
                      sql.Column('extra', ks_sql.JsonBlob.impl),
                      mysql_engine='InnoDB',
                      mysql_charset='utf8')

    group_domain_metadata = sql.Table('group_domain_metadata',
                                      meta,
                                      sql.Column('group_id',
                                                 sql.String(length=64),
                                                 primary_key=True),
                                      sql.Column('domain_id',
                                                 sql.String(length=64),
                                                 primary_key=True),
                                      sql.Column('data', ks_sql.JsonBlob.impl),
                                      mysql_engine='InnoDB',
                                      mysql_charset='utf8')

    group_project_metadata = sql.Table('group_project_metadata',
                                       meta,
                                       sql.Column('group_id',
                                                  sql.String(length=64),
                                                  primary_key=True),
                                       sql.Column('project_id',
                                                  sql.String(length=64),
                                                  primary_key=True),
                                       sql.Column('data',
                                                  ks_sql.JsonBlob.impl),
                                       mysql_engine='InnoDB',
                                       mysql_charset='utf8')

    policy = sql.Table('policy',
                       meta,
                       sql.Column('id',
                                  sql.String(length=64),
                                  primary_key=True),
                       sql.Column('type',
                                  sql.String(length=255),
                                  nullable=False),
                       sql.Column('blob', ks_sql.JsonBlob, nullable=False),
                       sql.Column('extra', ks_sql.JsonBlob.impl),
                       mysql_engine='InnoDB',
                       mysql_charset='utf8')

    project = sql.Table('project',
                        meta,
                        sql.Column('id',
                                   sql.String(length=64),
                                   primary_key=True),
                        sql.Column('name',
                                   sql.String(length=64),
                                   nullable=False),
                        sql.Column('extra', ks_sql.JsonBlob.impl),
                        sql.Column('description', sql.Text),
                        sql.Column('enabled', sql.Boolean),
                        sql.Column('domain_id',
                                   sql.String(length=64),
                                   nullable=False),
                        mysql_engine='InnoDB',
                        mysql_charset='utf8')

    role = sql.Table('role',
                     meta,
                     sql.Column('id', sql.String(length=64), primary_key=True),
                     sql.Column('name', sql.String(length=255),
                                nullable=False),
                     sql.Column('extra', ks_sql.JsonBlob.impl),
                     mysql_engine='InnoDB',
                     mysql_charset='utf8')

    service = sql.Table('service',
                        meta,
                        sql.Column('id',
                                   sql.String(length=64),
                                   primary_key=True),
                        sql.Column('type', sql.String(length=255)),
                        sql.Column('extra', ks_sql.JsonBlob.impl),
                        mysql_engine='InnoDB',
                        mysql_charset='utf8')

    token = sql.Table('token',
                      meta,
                      sql.Column('id', sql.String(length=64),
                                 primary_key=True),
                      sql.Column('expires', sql.DateTime, default=None),
                      sql.Column('extra', ks_sql.JsonBlob.impl),
                      sql.Column('valid',
                                 sql.Boolean,
                                 default=True,
                                 nullable=False),
                      sql.Column('trust_id', sql.String(length=64)),
                      sql.Column('user_id', sql.String(length=64)),
                      mysql_engine='InnoDB',
                      mysql_charset='utf8')

    trust = sql.Table('trust',
                      meta,
                      sql.Column('id', sql.String(length=64),
                                 primary_key=True),
                      sql.Column('trustor_user_id',
                                 sql.String(length=64),
                                 nullable=False),
                      sql.Column('trustee_user_id',
                                 sql.String(length=64),
                                 nullable=False),
                      sql.Column('project_id', sql.String(length=64)),
                      sql.Column('impersonation', sql.Boolean, nullable=False),
                      sql.Column('deleted_at', sql.DateTime),
                      sql.Column('expires_at', sql.DateTime),
                      sql.Column('extra', ks_sql.JsonBlob.impl),
                      mysql_engine='InnoDB',
                      mysql_charset='utf8')

    trust_role = sql.Table('trust_role',
                           meta,
                           sql.Column('trust_id',
                                      sql.String(length=64),
                                      primary_key=True,
                                      nullable=False),
                           sql.Column('role_id',
                                      sql.String(length=64),
                                      primary_key=True,
                                      nullable=False),
                           mysql_engine='InnoDB',
                           mysql_charset='utf8')

    user = sql.Table('user',
                     meta,
                     sql.Column('id', sql.String(length=64), primary_key=True),
                     sql.Column('name', sql.String(length=255),
                                nullable=False),
                     sql.Column('extra', ks_sql.JsonBlob.impl),
                     sql.Column('password', sql.String(length=128)),
                     sql.Column('enabled', sql.Boolean),
                     sql.Column('domain_id',
                                sql.String(length=64),
                                nullable=False),
                     sql.Column('default_project_id', sql.String(length=64)),
                     mysql_engine='InnoDB',
                     mysql_charset='utf8')

    user_domain_metadata = sql.Table('user_domain_metadata',
                                     meta,
                                     sql.Column('user_id',
                                                sql.String(length=64),
                                                primary_key=True),
                                     sql.Column('domain_id',
                                                sql.String(length=64),
                                                primary_key=True),
                                     sql.Column('data', ks_sql.JsonBlob.impl),
                                     mysql_engine='InnoDB',
                                     mysql_charset='utf8')

    user_group_membership = sql.Table('user_group_membership',
                                      meta,
                                      sql.Column('user_id',
                                                 sql.String(length=64),
                                                 primary_key=True),
                                      sql.Column('group_id',
                                                 sql.String(length=64),
                                                 primary_key=True),
                                      mysql_engine='InnoDB',
                                      mysql_charset='utf8')

    user_project_metadata = sql.Table('user_project_metadata',
                                      meta,
                                      sql.Column('user_id',
                                                 sql.String(length=64),
                                                 primary_key=True),
                                      sql.Column('project_id',
                                                 sql.String(length=64),
                                                 primary_key=True),
                                      sql.Column('data', ks_sql.JsonBlob.impl),
                                      mysql_engine='InnoDB',
                                      mysql_charset='utf8')

    # create all tables
    tables = [
        credential, domain, endpoint, group, group_domain_metadata,
        group_project_metadata, policy, project, role, service, token, trust,
        trust_role, user, user_domain_metadata, user_group_membership,
        user_project_metadata
    ]

    for table in tables:
        try:
            table.create()
        except Exception:
            LOG.exception('Exception while creating table: %r', table)
            raise

    # Unique Constraints
    migrate.UniqueConstraint(user.c.domain_id,
                             user.c.name,
                             name='ixu_user_name_domain_id').create()
    migrate.UniqueConstraint(group.c.domain_id,
                             group.c.name,
                             name='ixu_group_name_domain_id').create()
    migrate.UniqueConstraint(role.c.name, name='ixu_role_name').create()
    migrate.UniqueConstraint(project.c.domain_id,
                             project.c.name,
                             name='ixu_project_name_domain_id').create()
    migrate.UniqueConstraint(domain.c.name, name='ixu_domain_name').create()

    # Indexes
    sql.Index('ix_token_expires', token.c.expires).create()
    sql.Index('ix_token_valid', token.c.valid).create()

    fkeys = [{
        'columns': [user_project_metadata.c.project_id],
        'references': [project.c.id],
        'name': 'fk_user_project_metadata_project_id'
    }, {
        'columns': [user_domain_metadata.c.domain_id],
        'references': [domain.c.id],
        'name': 'fk_user_domain_metadata_domain_id'
    }, {
        'columns': [group_project_metadata.c.project_id],
        'references': [project.c.id],
        'name': 'fk_group_project_metadata_project_id'
    }, {
        'columns': [group_domain_metadata.c.domain_id],
        'references': [domain.c.id],
        'name': 'fk_group_domain_metadata_domain_id'
    }, {
        'columns': [endpoint.c.service_id],
        'references': [service.c.id]
    }, {
        'columns': [user_group_membership.c.group_id],
        'references': [group.c.id],
        'name': 'fk_user_group_membership_group_id'
    }, {
        'columns': [user_group_membership.c.user_id],
        'references': [user.c.id],
        'name': 'fk_user_group_membership_user_id'
    }, {
        'columns': [user.c.domain_id],
        'references': [domain.c.id],
        'name': 'fk_user_domain_id'
    }, {
        'columns': [group.c.domain_id],
        'references': [domain.c.id],
        'name': 'fk_group_domain_id'
    }, {
        'columns': [project.c.domain_id],
        'references': [domain.c.id],
        'name': 'fk_project_domain_id'
    }]

    for fkey in fkeys:
        migrate.ForeignKeyConstraint(columns=fkey['columns'],
                                     refcolumns=fkey['references'],
                                     name=fkey.get('name')).create()

    # Create the default domain.
    session = orm.sessionmaker(bind=migrate_engine)()
    domain.insert(migration_helpers.get_default_domain()).execute()
    session.commit()
Exemple #27
0
 def _drop_unique_constraint_to_role_name(self,
                                          constraint_name='ixu_role_name'):
     role_table = sqlalchemy.Table('role', self.metadata, autoload=True)
     migrate.UniqueConstraint(role_table.c.name,
                              name=constraint_name).drop()
def upgrade(migrate_engine):
    meta = sql.MetaData()
    meta.bind = migrate_engine

    if migrate_engine.name == 'mysql':
        # In Folsom we explicitly converted migrate_version to UTF8.
        migrate_engine.execute(
            'ALTER TABLE migrate_version CONVERT TO CHARACTER SET utf8')
        # Set default DB charset to UTF8.
        migrate_engine.execute('ALTER DATABASE %s DEFAULT CHARACTER SET utf8' %
                               migrate_engine.url.database)

    credential = sql.Table('credential',
                           meta,
                           sql.Column('id',
                                      sql.String(length=64),
                                      primary_key=True),
                           sql.Column('user_id',
                                      sql.String(length=64),
                                      nullable=False),
                           sql.Column('project_id', sql.String(length=64)),
                           sql.Column('blob', ks_sql.JsonBlob, nullable=False),
                           sql.Column('type',
                                      sql.String(length=255),
                                      nullable=False),
                           sql.Column('extra', ks_sql.JsonBlob.impl),
                           mysql_engine='InnoDB',
                           mysql_charset='utf8')

    domain = sql.Table('domain',
                       meta,
                       sql.Column('id',
                                  sql.String(length=64),
                                  primary_key=True),
                       sql.Column('name',
                                  sql.String(length=64),
                                  nullable=False),
                       sql.Column('enabled',
                                  sql.Boolean,
                                  default=True,
                                  nullable=False),
                       sql.Column('extra', ks_sql.JsonBlob.impl),
                       mysql_engine='InnoDB',
                       mysql_charset='utf8')

    endpoint = sql.Table('endpoint',
                         meta,
                         sql.Column('id',
                                    sql.String(length=64),
                                    primary_key=True),
                         sql.Column('legacy_endpoint_id',
                                    sql.String(length=64)),
                         sql.Column('interface',
                                    sql.String(length=8),
                                    nullable=False),
                         sql.Column('service_id',
                                    sql.String(length=64),
                                    nullable=False),
                         sql.Column('url', sql.Text, nullable=False),
                         sql.Column('extra', ks_sql.JsonBlob.impl),
                         sql.Column('enabled',
                                    sql.Boolean,
                                    nullable=False,
                                    default=True,
                                    server_default='1'),
                         sql.Column('region_id',
                                    sql.String(length=255),
                                    nullable=True),
                         mysql_engine='InnoDB',
                         mysql_charset='utf8')

    group = sql.Table('group',
                      meta,
                      sql.Column('id', sql.String(length=64),
                                 primary_key=True),
                      sql.Column('domain_id',
                                 sql.String(length=64),
                                 nullable=False),
                      sql.Column('name', sql.String(length=64),
                                 nullable=False),
                      sql.Column('description', sql.Text),
                      sql.Column('extra', ks_sql.JsonBlob.impl),
                      mysql_engine='InnoDB',
                      mysql_charset='utf8')

    policy = sql.Table('policy',
                       meta,
                       sql.Column('id',
                                  sql.String(length=64),
                                  primary_key=True),
                       sql.Column('type',
                                  sql.String(length=255),
                                  nullable=False),
                       sql.Column('blob', ks_sql.JsonBlob, nullable=False),
                       sql.Column('extra', ks_sql.JsonBlob.impl),
                       mysql_engine='InnoDB',
                       mysql_charset='utf8')

    project = sql.Table('project',
                        meta,
                        sql.Column('id',
                                   sql.String(length=64),
                                   primary_key=True),
                        sql.Column('name',
                                   sql.String(length=64),
                                   nullable=False),
                        sql.Column('extra', ks_sql.JsonBlob.impl),
                        sql.Column('description', sql.Text),
                        sql.Column('enabled', sql.Boolean),
                        sql.Column('domain_id',
                                   sql.String(length=64),
                                   nullable=False),
                        sql.Column('parent_id', sql.String(64), nullable=True),
                        mysql_engine='InnoDB',
                        mysql_charset='utf8')

    role = sql.Table('role',
                     meta,
                     sql.Column('id', sql.String(length=64), primary_key=True),
                     sql.Column('name', sql.String(length=255),
                                nullable=False),
                     sql.Column('extra', ks_sql.JsonBlob.impl),
                     mysql_engine='InnoDB',
                     mysql_charset='utf8')

    service = sql.Table('service',
                        meta,
                        sql.Column('id',
                                   sql.String(length=64),
                                   primary_key=True),
                        sql.Column('type', sql.String(length=255)),
                        sql.Column('enabled',
                                   sql.Boolean,
                                   nullable=False,
                                   default=True,
                                   server_default='1'),
                        sql.Column('extra', ks_sql.JsonBlob.impl),
                        mysql_engine='InnoDB',
                        mysql_charset='utf8')

    token = sql.Table('token',
                      meta,
                      sql.Column('id', sql.String(length=64),
                                 primary_key=True),
                      sql.Column('expires', sql.DateTime, default=None),
                      sql.Column('extra', ks_sql.JsonBlob.impl),
                      sql.Column('valid',
                                 sql.Boolean,
                                 default=True,
                                 nullable=False),
                      sql.Column('trust_id', sql.String(length=64)),
                      sql.Column('user_id', sql.String(length=64)),
                      mysql_engine='InnoDB',
                      mysql_charset='utf8')

    trust = sql.Table('trust',
                      meta,
                      sql.Column('id', sql.String(length=64),
                                 primary_key=True),
                      sql.Column('trustor_user_id',
                                 sql.String(length=64),
                                 nullable=False),
                      sql.Column('trustee_user_id',
                                 sql.String(length=64),
                                 nullable=False),
                      sql.Column('project_id', sql.String(length=64)),
                      sql.Column('impersonation', sql.Boolean, nullable=False),
                      sql.Column('deleted_at', sql.DateTime),
                      sql.Column('expires_at', sql.DateTime),
                      sql.Column('remaining_uses', sql.Integer, nullable=True),
                      sql.Column('extra', ks_sql.JsonBlob.impl),
                      mysql_engine='InnoDB',
                      mysql_charset='utf8')

    trust_role = sql.Table('trust_role',
                           meta,
                           sql.Column('trust_id',
                                      sql.String(length=64),
                                      primary_key=True,
                                      nullable=False),
                           sql.Column('role_id',
                                      sql.String(length=64),
                                      primary_key=True,
                                      nullable=False),
                           mysql_engine='InnoDB',
                           mysql_charset='utf8')

    user = sql.Table('user',
                     meta,
                     sql.Column('id', sql.String(length=64), primary_key=True),
                     sql.Column('name', sql.String(length=255),
                                nullable=False),
                     sql.Column('extra', ks_sql.JsonBlob.impl),
                     sql.Column('password', sql.String(length=128)),
                     sql.Column('enabled', sql.Boolean),
                     sql.Column('domain_id',
                                sql.String(length=64),
                                nullable=False),
                     sql.Column('default_project_id', sql.String(length=64)),
                     mysql_engine='InnoDB',
                     mysql_charset='utf8')

    user_group_membership = sql.Table('user_group_membership',
                                      meta,
                                      sql.Column('user_id',
                                                 sql.String(length=64),
                                                 primary_key=True),
                                      sql.Column('group_id',
                                                 sql.String(length=64),
                                                 primary_key=True),
                                      mysql_engine='InnoDB',
                                      mysql_charset='utf8')

    region = sql.Table('region',
                       meta,
                       sql.Column('id', sql.String(255), primary_key=True),
                       sql.Column('description',
                                  sql.String(255),
                                  nullable=False),
                       sql.Column('parent_region_id',
                                  sql.String(255),
                                  nullable=True),
                       sql.Column('extra', sql.Text()),
                       mysql_engine='InnoDB',
                       mysql_charset='utf8')

    assignment = sql.Table(
        'assignment',
        meta,
        sql.Column('type',
                   sql.Enum(assignment_sql.AssignmentType.USER_PROJECT,
                            assignment_sql.AssignmentType.GROUP_PROJECT,
                            assignment_sql.AssignmentType.USER_DOMAIN,
                            assignment_sql.AssignmentType.GROUP_DOMAIN,
                            name='type'),
                   nullable=False),
        sql.Column('actor_id', sql.String(64), nullable=False),
        sql.Column('target_id', sql.String(64), nullable=False),
        sql.Column('role_id', sql.String(64), nullable=False),
        sql.Column('inherited', sql.Boolean, default=False, nullable=False),
        sql.PrimaryKeyConstraint('type', 'actor_id', 'target_id', 'role_id'),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    mapping = sql.Table('id_mapping',
                        meta,
                        sql.Column('public_id',
                                   sql.String(64),
                                   primary_key=True),
                        sql.Column('domain_id', sql.String(64),
                                   nullable=False),
                        sql.Column('local_id', sql.String(64), nullable=False),
                        sql.Column('entity_type',
                                   sql.Enum(mapping_backend.EntityType.USER,
                                            mapping_backend.EntityType.GROUP,
                                            name='entity_type'),
                                   nullable=False),
                        mysql_engine='InnoDB',
                        mysql_charset='utf8')

    domain_config_whitelist = sql.Table('whitelisted_config',
                                        meta,
                                        sql.Column('domain_id',
                                                   sql.String(64),
                                                   primary_key=True),
                                        sql.Column('group',
                                                   sql.String(255),
                                                   primary_key=True),
                                        sql.Column('option',
                                                   sql.String(255),
                                                   primary_key=True),
                                        sql.Column('value',
                                                   ks_sql.JsonBlob.impl,
                                                   nullable=False),
                                        mysql_engine='InnoDB',
                                        mysql_charset='utf8')

    domain_config_sensitive = sql.Table('sensitive_config',
                                        meta,
                                        sql.Column('domain_id',
                                                   sql.String(64),
                                                   primary_key=True),
                                        sql.Column('group',
                                                   sql.String(255),
                                                   primary_key=True),
                                        sql.Column('option',
                                                   sql.String(255),
                                                   primary_key=True),
                                        sql.Column('value',
                                                   ks_sql.JsonBlob.impl,
                                                   nullable=False),
                                        mysql_engine='InnoDB',
                                        mysql_charset='utf8')

    # create all tables
    tables = [
        credential, domain, endpoint, group, policy, project, role, service,
        token, trust, trust_role, user, user_group_membership, region,
        assignment, mapping, domain_config_whitelist, domain_config_sensitive
    ]

    for table in tables:
        try:
            table.create()
        except Exception:
            LOG.exception('Exception while creating table: %r', table)
            raise

    # Unique Constraints
    migrate.UniqueConstraint(user.c.domain_id,
                             user.c.name,
                             name='ixu_user_name_domain_id').create()
    migrate.UniqueConstraint(group.c.domain_id,
                             group.c.name,
                             name='ixu_group_name_domain_id').create()
    migrate.UniqueConstraint(role.c.name, name='ixu_role_name').create()
    migrate.UniqueConstraint(project.c.domain_id,
                             project.c.name,
                             name='ixu_project_name_domain_id').create()
    migrate.UniqueConstraint(domain.c.name, name='ixu_domain_name').create()
    migrate.UniqueConstraint(mapping.c.domain_id,
                             mapping.c.local_id,
                             mapping.c.entity_type,
                             name='domain_id').create()

    # Indexes
    sql.Index('ix_token_expires', token.c.expires).create()
    sql.Index('ix_token_expires_valid', token.c.expires,
              token.c.valid).create()
    sql.Index('ix_actor_id', assignment.c.actor_id).create()
    sql.Index('ix_token_user_id', token.c.user_id).create()
    sql.Index('ix_token_trust_id', token.c.trust_id).create()
    # NOTE(stevemar): The two indexes below were named 'service_id' and
    # 'group_id' in 050_fk_consistent_indexes.py, and need to be preserved
    sql.Index('service_id', endpoint.c.service_id).create()
    sql.Index('group_id', user_group_membership.c.group_id).create()

    fkeys = [
        {
            'columns': [endpoint.c.service_id],
            'references': [service.c.id]
        },
        {
            'columns': [user_group_membership.c.group_id],
            'references': [group.c.id],
            'name': 'fk_user_group_membership_group_id'
        },
        {
            'columns': [user_group_membership.c.user_id],
            'references': [user.c.id],
            'name': 'fk_user_group_membership_user_id'
        },
        {
            'columns': [project.c.domain_id],
            'references': [domain.c.id],
            'name': 'fk_project_domain_id'
        },
        {
            'columns': [endpoint.c.region_id],
            'references': [region.c.id],
            'name': 'fk_endpoint_region_id'
        },
        {
            'columns': [project.c.parent_id],
            'references': [project.c.id],
            'name': 'project_parent_id_fkey'
        },
    ]

    if migrate_engine.name == 'sqlite':
        # NOTE(stevemar): We need to keep this FK constraint due to 073, but
        # only for sqlite, once we collapse 073 we can remove this constraint
        fkeys.append({
            'columns': [assignment.c.role_id],
            'references': [role.c.id],
            'name': 'fk_assignment_role_id'
        })

    for fkey in fkeys:
        migrate.ForeignKeyConstraint(columns=fkey['columns'],
                                     refcolumns=fkey['references'],
                                     name=fkey.get('name')).create()

    # Create the default domain.
    session = orm.sessionmaker(bind=migrate_engine)()
    domain.insert(migration_helpers.get_default_domain()).execute()
    session.commit()
def upgrade(migrate_engine):
    meta = sql.MetaData()
    meta.bind = migrate_engine

    aggregates = sql.Table(
        'aggregates', meta,
        sql.Column('id', sql.Integer, primary_key=True),
        sql.Column('name', sql.String(255), unique=True),
        sql.Column('created_at', sql.DateTime),
        sql.Column('updated_at', sql.DateTime),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    aggregate_metadata = sql.Table(
        'aggregate_metadata', meta,
        sql.Column('id', sql.Integer, primary_key=True),
        sql.Column('key', sql.String(255), nullable=False),
        sql.Column('value', sql.String(255), nullable=False),
        sql.Column('aggregate_id', sql.Integer, nullable=False),
        sql.Column('created_at', sql.DateTime),
        sql.Column('updated_at', sql.DateTime),
        migrate.UniqueConstraint(
            'aggregate_id', 'key',
            name='uniq_aggregate_metadata0aggregate_id0key'),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    instance_types = sql.Table(
        'instance_types', meta,
        sql.Column('id', sql.Integer, primary_key=True),
        sql.Column('name', sql.String(255), unique=True),
        sql.Column('memory_mb', sql.Integer, nullable=False),
        sql.Column('vcpus', sql.Integer, nullable=False),
        sql.Column('root_gb', sql.Integer),
        sql.Column('ephemeral_gb', sql.Integer),
        sql.Column('flavorid', sql.String(255), unique=True),
        sql.Column('swap', sql.Integer, nullable=False, default=0),
        sql.Column('rxtx_factor', sql.Float, default=1),
        sql.Column('vcpu_weight', sql.Integer),
        sql.Column('disabled', sql.Boolean, default=False),
        sql.Column('is_public', sql.Boolean, default=True),
        sql.Column('created_at', sql.DateTime),
        sql.Column('updated_at', sql.DateTime),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    instance_type_projects = sql.Table(
        'instance_type_projects', meta,
        sql.Column('id', sql.Integer, primary_key=True),
        sql.Column('instance_type_id', sql.Integer, nullable=False),
        sql.Column('project_id', sql.String(255)),
        sql.Column('created_at', sql.DateTime),
        sql.Column('updated_at', sql.DateTime),
        migrate.UniqueConstraint(
            'instance_type_id', 'project_id',
            name='uniq_instance_type_projects0instance_type_id0project_id'),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    instance_type_extra_specs = sql.Table(
        'instance_type_extra_specs', meta,
        sql.Column('id', sql.Integer, primary_key=True),
        sql.Column('key', sql.String(255)),
        sql.Column('value', sql.String(255)),
        sql.Column('instance_type_id', sql.Integer, nullable=False),
        sql.Column('created_at', sql.DateTime),
        sql.Column('updated_at', sql.DateTime),
        migrate.UniqueConstraint(
            'instance_type_id', 'key',
            name='uniq_instance_type_extra_specs0instance_type_id0key'),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    enum = sql.Enum('ssh', 'x509', metadata=meta, name='keypair_types')
    enum.create()

    key_pairs = sql.Table(
        'key_pairs', meta,
        sql.Column('id', sql.Integer, primary_key=True, nullable=False),
        sql.Column('name', sql.String(255), nullable=False),
        sql.Column('user_id', sql.String(255)),
        sql.Column('fingerprint', sql.String(255)),
        sql.Column('public_key', MediumText()),
        sql.Column('type', enum, nullable=False, server_default='ssh'),
        sql.Column('created_at', sql.DateTime),
        sql.Column('updated_at', sql.DateTime),
        migrate.UniqueConstraint(
            'user_id', 'name',
            name='uniq_key_pairs0user_id0name'),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    quotas = sql.Table(
        'quotas', meta,
        sql.Column('id', sql.Integer, primary_key=True),
        sql.Column('project_id', sql.String(255), index=True),
        sql.Column('resource', sql.String(255), nullable=False),
        sql.Column('hard_limit', sql.Integer),
        sql.Column('allocated', sql.Integer, default=0),
        sql.Column('created_at', sql.DateTime),
        sql.Column('updated_at', sql.DateTime),
        sql.Column('deleted_at', sql.DateTime),
        sql.Column('deleted', sql.Integer),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    quota_classes = sql.Table(
        'quota_classes', meta,
        sql.Column('id', sql.Integer, primary_key=True),
        sql.Column('class_name', sql.String(255), index=True),
        sql.Column('resource', sql.String(255), nullable=False),
        sql.Column('hard_limit', sql.Integer),
        sql.Column('created_at', sql.DateTime),
        sql.Column('updated_at', sql.DateTime),
        sql.Column('deleted_at', sql.DateTime),
        sql.Column('deleted', sql.Integer),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    quota_usages = sql.Table(
        'quota_usages', meta,
        sql.Column('id', sql.Integer, primary_key=True),
        sql.Column('project_id', sql.String(255), index=True),
        sql.Column('user_id', sql.String(255), index=True),
        sql.Column('resource', sql.String(255), nullable=False),
        sql.Column('in_use', sql.Integer),
        sql.Column('reserved', sql.Integer),
        sql.Column('until_refresh', sql.Integer),
        sql.Column('created_at', sql.DateTime),
        sql.Column('updated_at', sql.DateTime),
        sql.Column('deleted_at', sql.DateTime),
        sql.Column('deleted', sql.Integer),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    reservations = sql.Table(
        'reservations', meta,
        sql.Column('id', sql.Integer(), primary_key=True),
        sql.Column('uuid', sql.String(length=36), nullable=False),
        sql.Column('usage_id', sql.Integer(),
                   sql.ForeignKey('quota_usages.id'),
                   nullable=False),
        sql.Column('project_id',
                   sql.String(length=255),
                   index=True),
        sql.Column('resource',
                   sql.String(length=255)),
        sql.Column('delta', sql.Integer(), nullable=False),
        sql.Column('expire', sql.DateTime),

        sql.Column('created_at', sql.DateTime),
        sql.Column('updated_at', sql.DateTime),
        sql.Column('deleted_at', sql.DateTime),
        sql.Column('deleted', sql.Boolean(create_constraint=True,
                                          name=None)),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    volume_types = sql.Table(
        'volume_types', meta,
        sql.Column('id', sql.String(36), primary_key=True),
        sql.Column('name', sql.String(255), unique=True),
        sql.Column('description', sql.String(255)),
        sql.Column('qos_specs_id', sql.String(36)),
        sql.Column('is_public', sql.Boolean, default=True),
        sql.Column('created_at', sql.DateTime),
        sql.Column('updated_at', sql.DateTime),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    quality_of_service_specs = sql.Table(
        'quality_of_service_specs', meta,
        sql.Column('id', sql.String(36), primary_key=True),
        sql.Column('specs_id', sql.String(36)),
        sql.Column('key', sql.String(255)),
        sql.Column('value', sql.String(255)),
        sql.Column('created_at', sql.DateTime),
        sql.Column('updated_at', sql.DateTime),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    cascaded_pods_resource_routing = sql.Table(
        'cascaded_pods_resource_routing', meta,
        sql.Column('id', sql.Integer, primary_key=True),
        sql.Column('top_id', sql.String(length=127), nullable=False),
        sql.Column('bottom_id', sql.String(length=36)),
        sql.Column('pod_id', sql.String(length=64), nullable=False),
        sql.Column('project_id', sql.String(length=36)),
        sql.Column('resource_type', sql.String(length=64), nullable=False),
        sql.Column('created_at', sql.DateTime),
        sql.Column('updated_at', sql.DateTime),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    job = sql.Table(
        'job', meta,
        sql.Column('id', sql.String(length=36), primary_key=True),
        sql.Column('type', sql.String(length=36)),
        sql.Column('timestamp', sql.TIMESTAMP,
                   server_default=sql.text('CURRENT_TIMESTAMP')),
        sql.Column('status', sql.String(length=36)),
        sql.Column('resource_id', sql.String(length=36)),
        sql.Column('extra_id', sql.String(length=36)),
        migrate.UniqueConstraint(
            'type', 'status', 'resource_id', 'extra_id',
            name='job0type0status0resource_id0extra_id'),
        mysql_engine='InnoDB',
        mysql_charset='utf8')

    tables = [aggregates, aggregate_metadata, instance_types,
              instance_type_projects, instance_type_extra_specs, key_pairs,
              quotas, quota_classes, quota_usages, reservations,
              volume_types, job,
              quality_of_service_specs, cascaded_pods_resource_routing]
    for table in tables:
        table.create()

    cascaded_pods = sql.Table('cascaded_pods', meta, autoload=True)

    fkeys = [{'columns': [instance_type_projects.c.instance_type_id],
              'references': [instance_types.c.id]},
             {'columns': [instance_type_extra_specs.c.instance_type_id],
              'references': [instance_types.c.id]},
             {'columns': [reservations.c.usage_id],
              'references': [quota_usages.c.id]},
             {'columns': [volume_types.c.qos_specs_id],
              'references': [quality_of_service_specs.c.id]},
             {'columns': [quality_of_service_specs.c.specs_id],
              'references': [quality_of_service_specs.c.id]},
             {'columns': [aggregate_metadata.c.aggregate_id],
              'references': [aggregates.c.id]},
             {'columns': [cascaded_pods_resource_routing.c.pod_id],
              'references': [cascaded_pods.c.pod_id]}]
    for fkey in fkeys:
        migrate.ForeignKeyConstraint(columns=fkey['columns'],
                                     refcolumns=fkey['references'],
                                     name=fkey.get('name')).create()
Exemple #30
0
def upgrade(migrate_engine):
    meta = sql.MetaData()
    meta.bind = migrate_engine

    if migrate_engine.name == 'mysql':
        # In Folsom we explicitly converted migrate_version to UTF8.
        migrate_engine.execute(
            'ALTER TABLE migrate_version CONVERT TO CHARACTER SET utf8')
        # Set default DB charset to UTF8.
        migrate_engine.execute('ALTER DATABASE %s DEFAULT CHARACTER SET utf8' %
                               migrate_engine.url.database)

    application_credential = sql.Table(
        'application_credential',
        meta,
        sql.Column('internal_id',
                   sql.Integer,
                   primary_key=True,
                   nullable=False),
        sql.Column('id', sql.String(length=64), nullable=False),
        sql.Column('name', sql.String(length=255), nullable=False),
        sql.Column('secret_hash', sql.String(length=255), nullable=False),
        sql.Column('description', sql.Text),
        sql.Column('user_id', sql.String(length=64), nullable=False),
        sql.Column('project_id', sql.String(64), nullable=True),
        sql.Column('expires_at', ks_sql.DateTimeInt()),
        sql.Column('system', sql.String(64), nullable=True),
        sql.Column('unrestricted', sql.Boolean),
        sql.UniqueConstraint('user_id',
                             'name',
                             name='duplicate_app_cred_constraint'),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    assignment = sql.Table(
        'assignment',
        meta,
        sql.Column(
            'type',
            sql.Enum(
                assignment_sql.AssignmentType.USER_PROJECT,
                assignment_sql.AssignmentType.GROUP_PROJECT,
                assignment_sql.AssignmentType.USER_DOMAIN,
                assignment_sql.AssignmentType.GROUP_DOMAIN,
                name='type',
            ),
            nullable=False,
        ),
        sql.Column('actor_id', sql.String(64), nullable=False),
        sql.Column('target_id', sql.String(64), nullable=False),
        sql.Column('role_id', sql.String(64), nullable=False),
        sql.Column('inherited', sql.Boolean, default=False, nullable=False),
        sql.PrimaryKeyConstraint(
            'type',
            'actor_id',
            'target_id',
            'role_id',
            'inherited',
        ),
        sql.Index('ix_actor_id', 'actor_id'),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    access_rule = sql.Table(
        'access_rule',
        meta,
        sql.Column('id', sql.Integer, primary_key=True, nullable=False),
        sql.Column('service', sql.String(64)),
        sql.Column('path', sql.String(128)),
        sql.Column('method', sql.String(16)),
        sql.Column('external_id', sql.String(64)),
        sql.Column('user_id', sql.String(64)),
        sql.UniqueConstraint(
            'external_id',
            name='access_rule_external_id_key',
        ),
        sql.UniqueConstraint(
            'user_id',
            'service',
            'path',
            'method',
            name='duplicate_access_rule_for_user_constraint',
        ),
        sql.Index('user_id', 'user_id'),
        sql.Index('external_id', 'external_id'),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    config_register = sql.Table(
        'config_register',
        meta,
        sql.Column('type', sql.String(64), primary_key=True),
        sql.Column('domain_id', sql.String(64), nullable=False),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    consumer = sql.Table(
        'consumer',
        meta,
        sql.Column('id', sql.String(64), primary_key=True, nullable=False),
        sql.Column('description', sql.String(64), nullable=True),
        sql.Column('secret', sql.String(64), nullable=False),
        sql.Column('extra', sql.Text(), nullable=False),
    )

    credential = sql.Table(
        'credential',
        meta,
        sql.Column('id', sql.String(length=64), primary_key=True),
        sql.Column('user_id', sql.String(length=64), nullable=False),
        sql.Column('project_id', sql.String(length=64)),
        sql.Column('type', sql.String(length=255), nullable=False),
        sql.Column('extra', ks_sql.JsonBlob.impl),
        sql.Column('key_hash', sql.String(64), nullable=False),
        sql.Column(
            'encrypted_blob',
            ks_sql.Text,
            nullable=False,
        ),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    group = sql.Table(
        'group',
        meta,
        sql.Column('id', sql.String(length=64), primary_key=True),
        sql.Column('domain_id', sql.String(length=64), nullable=False),
        sql.Column('name', sql.String(length=64), nullable=False),
        sql.Column('description', sql.Text),
        sql.Column('extra', ks_sql.JsonBlob.impl),
        migrate.UniqueConstraint(
            'domain_id',
            'name',
            name='ixu_group_name_domain_id',
        ),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    id_mapping = sql.Table(
        'id_mapping',
        meta,
        sql.Column('public_id', sql.String(64), primary_key=True),
        sql.Column('domain_id', sql.String(64), nullable=False),
        sql.Column('local_id', sql.String(64), nullable=False),
        sql.Column(
            'entity_type',
            sql.Enum(
                mapping_backend.EntityType.USER,
                mapping_backend.EntityType.GROUP,
                name='entity_type',
            ),
            nullable=False,
        ),
        migrate.UniqueConstraint(
            'domain_id',
            'local_id',
            'entity_type',
            name='domain_id',
        ),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    identity_provider = sql.Table(
        'identity_provider',
        meta,
        sql.Column('id', sql.String(64), primary_key=True),
        sql.Column('enabled', sql.Boolean, nullable=False),
        sql.Column('description', sql.Text(), nullable=True),
        sql.Column('domain_id', sql.String(64), nullable=False),
        sql.Column('authorization_ttl', sql.Integer, nullable=True),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    idp_remote_ids = sql.Table(
        'idp_remote_ids',
        meta,
        sql.Column(
            'idp_id',
            sql.String(64),
            sql.ForeignKey(identity_provider.c.id, ondelete='CASCADE'),
        ),
        sql.Column('remote_id', sql.String(255), primary_key=True),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    mapping = sql.Table(
        'mapping',
        meta,
        sql.Column('id', sql.String(64), primary_key=True),
        sql.Column('rules', sql.Text(), nullable=False),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    policy = sql.Table(
        'policy',
        meta,
        sql.Column('id', sql.String(length=64), primary_key=True),
        sql.Column('type', sql.String(length=255), nullable=False),
        sql.Column('blob', ks_sql.JsonBlob, nullable=False),
        sql.Column('extra', ks_sql.JsonBlob.impl),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    policy_association = sql.Table(
        'policy_association',
        meta,
        sql.Column('id', sql.String(64), primary_key=True),
        sql.Column('policy_id', sql.String(64), nullable=False),
        sql.Column('endpoint_id', sql.String(64), nullable=True),
        sql.Column('service_id', sql.String(64), nullable=True),
        sql.Column('region_id', sql.String(64), nullable=True),
        sql.UniqueConstraint('endpoint_id', 'service_id', 'region_id'),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    project = sql.Table(
        'project',
        meta,
        sql.Column('id', sql.String(length=64), primary_key=True),
        sql.Column('name', sql.String(length=64), nullable=False),
        sql.Column('extra', ks_sql.JsonBlob.impl),
        sql.Column('description', sql.Text),
        sql.Column('enabled', sql.Boolean),
        sql.Column(
            'domain_id',
            sql.String(length=64),
            sql.ForeignKey(
                'project.id',
                name='project_domain_id_fkey',
            ),
            nullable=False,
        ),
        sql.Column(
            'parent_id',
            sql.String(64),
            sql.ForeignKey(
                'project.id',
                name='project_parent_id_fkey',
            ),
            nullable=True,
        ),
        sql.Column(
            'is_domain',
            sql.Boolean,
            nullable=False,
            server_default='0',
            default=False,
        ),
        migrate.UniqueConstraint(
            'domain_id',
            'name',
            name='ixu_project_name_domain_id',
        ),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    project_endpoint = sql.Table(
        'project_endpoint',
        meta,
        sql.Column('endpoint_id',
                   sql.String(64),
                   primary_key=True,
                   nullable=False),
        sql.Column('project_id',
                   sql.String(64),
                   primary_key=True,
                   nullable=False),
    )

    project_option = sql.Table(
        'project_option',
        meta,
        sql.Column(
            'project_id',
            sql.String(64),
            sql.ForeignKey(project.c.id, ondelete='CASCADE'),
            nullable=False,
            primary_key=True,
        ),
        sql.Column('option_id',
                   sql.String(4),
                   nullable=False,
                   primary_key=True),
        sql.Column('option_value', ks_sql.JsonBlob, nullable=True),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    # NOTE(lamt) To allow tag name to be case sensitive for MySQL, the 'name'
    # column needs to use collation, which is incompatible with Postgresql.
    # Using unicode to mirror nova's server tag:
    # https://github.com/openstack/nova/blob/master/nova/db/sqlalchemy/models.py
    project_tag = sql.Table(
        'project_tag',
        meta,
        sql.Column(
            'project_id',
            sql.String(64),
            sql.ForeignKey(project.c.id, ondelete='CASCADE'),
            nullable=False,
            primary_key=True,
        ),
        sql.Column('name', sql.Unicode(255), nullable=False, primary_key=True),
        sql.UniqueConstraint('project_id', 'name'),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    region = sql.Table(
        'region',
        meta,
        sql.Column('id', sql.String(255), primary_key=True),
        sql.Column('description', sql.String(255), nullable=False),
        sql.Column('parent_region_id', sql.String(255), nullable=True),
        sql.Column('extra', sql.Text()),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    registered_limit = sql.Table(
        'registered_limit',
        meta,
        sql.Column('id', sql.String(length=64), nullable=False),
        sql.Column('service_id', sql.String(255)),
        sql.Column('region_id', sql.String(64), nullable=True),
        sql.Column('resource_name', sql.String(255)),
        sql.Column('default_limit', sql.Integer, nullable=False),
        sql.Column('description', sql.Text),
        sql.Column('internal_id', sql.Integer, primary_key=True),
        # NOTE(stephenfin): Name chosen to preserve backwards compatibility
        # with names used for primary key unique constraints
        sql.UniqueConstraint('id', name='registered_limit_id_key'),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    request_token = sql.Table(
        'request_token',
        meta,
        sql.Column('id', sql.String(64), primary_key=True, nullable=False),
        sql.Column('request_secret', sql.String(64), nullable=False),
        sql.Column('verifier', sql.String(64), nullable=True),
        sql.Column('authorizing_user_id', sql.String(64), nullable=True),
        sql.Column('requested_project_id', sql.String(64), nullable=False),
        sql.Column('role_ids', sql.Text(), nullable=True),
        sql.Column(
            'consumer_id',
            sql.String(64),
            sql.ForeignKey(consumer.c.id),
            nullable=False,
            index=True,
        ),
        sql.Column('expires_at', sql.String(64), nullable=True),
    )

    revocation_event = sql.Table(
        'revocation_event',
        meta,
        sql.Column('id', sql.Integer, primary_key=True),
        sql.Column('domain_id', sql.String(64)),
        sql.Column('project_id', sql.String(64)),
        sql.Column('user_id', sql.String(64)),
        sql.Column('role_id', sql.String(64)),
        sql.Column('trust_id', sql.String(64)),
        sql.Column('consumer_id', sql.String(64)),
        sql.Column('access_token_id', sql.String(64)),
        sql.Column('issued_before', sql.DateTime(), nullable=False),
        sql.Column('expires_at', sql.DateTime()),
        sql.Column('revoked_at', sql.DateTime(), nullable=False),
        sql.Column('audit_id', sql.String(32), nullable=True),
        sql.Column('audit_chain_id', sql.String(32), nullable=True),
        # NOTE(stephenfin): The '_new' suffix here is due to migration 095,
        # which changed the 'id' column from String(64) to Integer. It did this
        # by creating a 'revocation_event_new' table and populating it with
        # data from the 'revocation_event' table before deleting the
        # 'revocation_event' table and renaming the 'revocation_event_new'
        # table to 'revocation_event'. Because the 'revoked_at' column had
        # 'index=True', sqlalchemy automatically generated the index name as
        # 'ix_{table}_{column}'. However, when intitially created, '{table}'
        # was 'revocation_event_new' so the index got that name. We may wish to
        # rename this eventually.
        sql.Index('ix_revocation_event_new_revoked_at', 'revoked_at'),
        sql.Index('ix_revocation_event_issued_before', 'issued_before'),
        sql.Index(
            'ix_revocation_event_project_id_issued_before',
            'project_id',
            'issued_before',
        ),
        sql.Index(
            'ix_revocation_event_user_id_issued_before',
            'user_id',
            'issued_before',
        ),
        sql.Index(
            'ix_revocation_event_audit_id_issued_before',
            'audit_id',
            'issued_before',
        ),
    )

    role = sql.Table(
        'role',
        meta,
        sql.Column('id', sql.String(length=64), primary_key=True),
        sql.Column('name', sql.String(length=255), nullable=False),
        sql.Column('extra', ks_sql.JsonBlob.impl),
        sql.Column(
            'domain_id',
            sql.String(64),
            nullable=False,
            server_default='<<null>>',
        ),
        sql.Column('description', sql.String(255), nullable=True),
        migrate.UniqueConstraint(
            'name',
            'domain_id',
            name='ixu_role_name_domain_id',
        ),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    role_option = sql.Table(
        'role_option',
        meta,
        sql.Column(
            'role_id',
            sql.String(64),
            sql.ForeignKey(role.c.id, ondelete='CASCADE'),
            nullable=False,
            primary_key=True,
        ),
        sql.Column('option_id',
                   sql.String(4),
                   nullable=False,
                   primary_key=True),
        sql.Column('option_value', ks_sql.JsonBlob, nullable=True),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    sensitive_config = sql.Table(
        'sensitive_config',
        meta,
        sql.Column('domain_id', sql.String(64), primary_key=True),
        sql.Column('group', sql.String(255), primary_key=True),
        sql.Column('option', sql.String(255), primary_key=True),
        sql.Column('value', ks_sql.JsonBlob.impl, nullable=False),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    service = sql.Table(
        'service',
        meta,
        sql.Column('id', sql.String(length=64), primary_key=True),
        sql.Column('type', sql.String(length=255)),
        sql.Column(
            'enabled',
            sql.Boolean,
            nullable=False,
            default=True,
            server_default='1',
        ),
        sql.Column('extra', ks_sql.JsonBlob.impl),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    service_provider = sql.Table(
        'service_provider',
        meta,
        sql.Column('auth_url', sql.String(256), nullable=False),
        sql.Column('id', sql.String(64), primary_key=True),
        sql.Column('enabled', sql.Boolean, nullable=False),
        sql.Column('description', sql.Text(), nullable=True),
        sql.Column('sp_url', sql.String(256), nullable=False),
        sql.Column(
            'relay_state_prefix',
            sql.String(256),
            nullable=False,
            server_default=service_provider_relay_state_prefix_default,
        ),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    system_assignment = sql.Table(
        'system_assignment',
        meta,
        sql.Column('type', sql.String(64), nullable=False),
        sql.Column('actor_id', sql.String(64), nullable=False),
        sql.Column('target_id', sql.String(64), nullable=False),
        sql.Column('role_id', sql.String(64), nullable=False),
        sql.Column('inherited', sql.Boolean, default=False, nullable=False),
        sql.PrimaryKeyConstraint('type', 'actor_id', 'target_id', 'role_id',
                                 'inherited'),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    token = sql.Table(
        'token',
        meta,
        sql.Column('id', sql.String(length=64), primary_key=True),
        sql.Column('expires', sql.DateTime, default=None),
        sql.Column('extra', ks_sql.JsonBlob.impl),
        sql.Column('valid', sql.Boolean, default=True, nullable=False),
        sql.Column('trust_id', sql.String(length=64)),
        sql.Column('user_id', sql.String(length=64)),
        sql.Index('ix_token_expires', 'expires'),
        sql.Index('ix_token_expires_valid', 'expires', 'valid'),
        sql.Index('ix_token_user_id', 'user_id'),
        sql.Index('ix_token_trust_id', 'trust_id'),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    trust = sql.Table(
        'trust',
        meta,
        sql.Column('id', sql.String(length=64), primary_key=True),
        sql.Column('trustor_user_id', sql.String(length=64), nullable=False),
        sql.Column('trustee_user_id', sql.String(length=64), nullable=False),
        sql.Column('project_id', sql.String(length=64)),
        sql.Column('impersonation', sql.Boolean, nullable=False),
        sql.Column('deleted_at', sql.DateTime),
        sql.Column('expires_at', sql.DateTime),
        sql.Column('remaining_uses', sql.Integer, nullable=True),
        sql.Column('extra', ks_sql.JsonBlob.impl),
        sql.Column('expires_at_int', ks_sql.DateTimeInt()),
        sql.UniqueConstraint(
            'trustor_user_id',
            'trustee_user_id',
            'project_id',
            'impersonation',
            'expires_at',
            'expires_at_int',
            name='duplicate_trust_constraint_expanded',
        ),
        sql.Column(
            'redelegated_trust_id',
            sql.String(64),
            nullable=True,
        ),
        sql.Column(
            'redelegation_count',
            sql.Integer,
            nullable=True,
        ),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    trust_role = sql.Table(
        'trust_role',
        meta,
        sql.Column('trust_id',
                   sql.String(length=64),
                   primary_key=True,
                   nullable=False),
        sql.Column('role_id',
                   sql.String(length=64),
                   primary_key=True,
                   nullable=False),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    user = sql.Table(
        'user',
        meta,
        sql.Column('id', sql.String(length=64), primary_key=True),
        sql.Column('extra', ks_sql.JsonBlob.impl),
        sql.Column('enabled', sql.Boolean),
        sql.Column('default_project_id', sql.String(length=64)),
        sql.Column('created_at', sql.DateTime(), nullable=True),
        sql.Column('last_active_at', sql.Date(), nullable=True),
        sql.Column('domain_id', sql.String(64), nullable=False),
        sql.UniqueConstraint('id', 'domain_id', name='ixu_user_id_domain_id'),
        sql.Index('ix_default_project_id', 'default_project_id'),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    user_group_membership = sql.Table(
        'user_group_membership',
        meta,
        sql.Column(
            'user_id',
            sql.String(length=64),
            sql.ForeignKey(
                user.c.id,
                name='fk_user_group_membership_user_id',
            ),
            primary_key=True,
        ),
        sql.Column(
            'group_id',
            sql.String(length=64),
            sql.ForeignKey(
                group.c.id,
                name='fk_user_group_membership_group_id',
            ),
            primary_key=True,
        ),
        # NOTE(stevemar): The index was named 'group_id' in
        # 050_fk_consistent_indexes.py and needs to be preserved
        sql.Index('group_id', 'group_id'),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    user_option = sql.Table(
        'user_option',
        meta,
        sql.Column(
            'user_id',
            sql.String(64),
            sql.ForeignKey(user.c.id, ondelete='CASCADE'),
            nullable=False,
            primary_key=True,
        ),
        sql.Column('option_id',
                   sql.String(4),
                   nullable=False,
                   primary_key=True),
        sql.Column('option_value', ks_sql.JsonBlob, nullable=True),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    whitelisted_config = sql.Table(
        'whitelisted_config',
        meta,
        sql.Column('domain_id', sql.String(64), primary_key=True),
        sql.Column('group', sql.String(255), primary_key=True),
        sql.Column('option', sql.String(255), primary_key=True),
        sql.Column('value', ks_sql.JsonBlob.impl, nullable=False),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    access_token = sql.Table(
        'access_token',
        meta,
        sql.Column('id', sql.String(64), primary_key=True, nullable=False),
        sql.Column('access_secret', sql.String(64), nullable=False),
        sql.Column('authorizing_user_id',
                   sql.String(64),
                   nullable=False,
                   index=True),
        sql.Column('project_id', sql.String(64), nullable=False),
        sql.Column('role_ids', sql.Text(), nullable=False),
        sql.Column(
            'consumer_id',
            sql.String(64),
            sql.ForeignKey(consumer.c.id),
            nullable=False,
            index=True,
        ),
        sql.Column('expires_at', sql.String(64), nullable=True),
    )

    application_credential_role = sql.Table(
        'application_credential_role',
        meta,
        sql.Column(
            'application_credential_id',
            sql.Integer,
            sql.ForeignKey(application_credential.c.internal_id,
                           ondelete='CASCADE'),
            primary_key=True,
            nullable=False,
        ),
        sql.Column('role_id',
                   sql.String(length=64),
                   primary_key=True,
                   nullable=False),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    application_credential_access_rule = sql.Table(
        'application_credential_access_rule',
        meta,
        sql.Column(
            'application_credential_id',
            sql.Integer,
            sql.ForeignKey(application_credential.c.internal_id,
                           ondelete='CASCADE'),
            primary_key=True,
            nullable=False,
        ),
        sql.Column(
            'access_rule_id',
            sql.Integer,
            sql.ForeignKey(access_rule.c.id, ondelete='CASCADE'),
            primary_key=True,
            nullable=False,
        ),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    endpoint = sql.Table(
        'endpoint',
        meta,
        sql.Column('id', sql.String(length=64), primary_key=True),
        sql.Column('legacy_endpoint_id', sql.String(length=64)),
        sql.Column('interface', sql.String(length=8), nullable=False),
        sql.Column(
            'service_id',
            sql.String(length=64),
            sql.ForeignKey(
                service.c.id,
                name='endpoint_service_id_fkey',
            ),
            nullable=False,
        ),
        sql.Column('url', sql.Text, nullable=False),
        sql.Column('extra', ks_sql.JsonBlob.impl),
        sql.Column(
            'enabled',
            sql.Boolean,
            nullable=False,
            default=True,
            server_default='1',
        ),
        sql.Column(
            'region_id',
            sql.String(length=255),
            sql.ForeignKey(
                region.c.id,
                name='fk_endpoint_region_id',
            ),
            nullable=True,
        ),
        # NOTE(stevemar): The index was named 'service_id' in
        # 050_fk_consistent_indexes.py and needs to be preserved
        sql.Index('service_id', 'service_id'),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    endpoint_group = sql.Table(
        'endpoint_group',
        meta,
        sql.Column('id', sql.String(64), primary_key=True),
        sql.Column('name', sql.String(255), nullable=False),
        sql.Column('description', sql.Text, nullable=True),
        sql.Column('filters', sql.Text(), nullable=False),
    )

    expiring_user_group_membership = sql.Table(
        'expiring_user_group_membership',
        meta,
        sql.Column(
            'user_id',
            sql.String(64),
            sql.ForeignKey(user.c.id),
            primary_key=True,
        ),
        sql.Column(
            'group_id',
            sql.String(64),
            sql.ForeignKey(group.c.id),
            primary_key=True,
        ),
        sql.Column(
            'idp_id',
            sql.String(64),
            sql.ForeignKey(identity_provider.c.id, ondelete='CASCADE'),
            primary_key=True,
        ),
        sql.Column('last_verified', sql.DateTime(), nullable=False),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    federation_protocol = sql.Table(
        'federation_protocol',
        meta,
        sql.Column('id', sql.String(64), primary_key=True),
        sql.Column(
            'idp_id',
            sql.String(64),
            sql.ForeignKey(identity_provider.c.id, ondelete='CASCADE'),
            primary_key=True,
        ),
        sql.Column('mapping_id', sql.String(64), nullable=False),
        sql.Column('remote_id_attribute', sql.String(64)),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    implied_role = sql.Table(
        'implied_role',
        meta,
        sql.Column(
            'prior_role_id',
            sql.String(length=64),
            sql.ForeignKey(
                role.c.id,
                name='implied_role_prior_role_id_fkey',
                ondelete='CASCADE',
            ),
            primary_key=True,
        ),
        sql.Column(
            'implied_role_id',
            sql.String(length=64),
            sql.ForeignKey(
                role.c.id,
                name='implied_role_implied_role_id_fkey',
                ondelete='CASCADE',
            ),
            primary_key=True,
        ),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    limit = sql.Table(
        'limit',
        meta,
        sql.Column('id', sql.String(length=64), nullable=False),
        sql.Column('project_id', sql.String(64), nullable=True),
        sql.Column('resource_limit', sql.Integer, nullable=False),
        sql.Column('description', sql.Text),
        sql.Column('internal_id', sql.Integer, primary_key=True),
        # FIXME(stephenfin): This should have a foreign key constraint on
        # registered_limit.id, but sqlalchemy-migrate clearly didn't handle
        # creating a column with embedded FK info as was attempted in 048
        sql.Column(
            'registered_limit_id',
            sql.String(64),
        ),
        sql.Column('domain_id', sql.String(64), nullable=True),
        # NOTE(stephenfin): Name chosen to preserve backwards compatibility
        # with names used for primary key unique constraints
        sql.UniqueConstraint('id', name='limit_id_key'),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    local_user = sql.Table(
        'local_user',
        meta,
        sql.Column('id', sql.Integer, primary_key=True, nullable=False),
        sql.Column(
            'user_id',
            sql.String(64),
            nullable=False,
            unique=True,
        ),
        sql.Column('domain_id', sql.String(64), nullable=False),
        sql.Column('name', sql.String(255), nullable=False),
        sql.Column('failed_auth_count', sql.Integer, nullable=True),
        sql.Column('failed_auth_at', sql.DateTime(), nullable=True),
        sql.ForeignKeyConstraint(
            ['user_id', 'domain_id'],
            [user.c.id, user.c.domain_id],
            name='local_user_user_id_fkey',
            onupdate='CASCADE',
            ondelete='CASCADE',
        ),
        sql.UniqueConstraint('domain_id', 'name'),
    )

    nonlocal_user = sql.Table(
        'nonlocal_user',
        meta,
        sql.Column('domain_id', sql.String(64), primary_key=True),
        sql.Column('name', sql.String(255), primary_key=True),
        sql.Column(
            'user_id',
            sql.String(64),
            nullable=False,
        ),
        sql.ForeignKeyConstraint(
            ['user_id', 'domain_id'],
            [user.c.id, user.c.domain_id],
            name='nonlocal_user_user_id_fkey',
            onupdate='CASCADE',
            ondelete='CASCADE',
        ),
        sql.UniqueConstraint('user_id', name='ixu_nonlocal_user_user_id'),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    password = sql.Table(
        'password',
        meta,
        sql.Column('id', sql.Integer, primary_key=True, nullable=False),
        sql.Column(
            'local_user_id',
            sql.Integer,
            sql.ForeignKey(local_user.c.id, ondelete='CASCADE'),
            nullable=False,
        ),
        sql.Column('expires_at', sql.DateTime(), nullable=True),
        sql.Column(
            'self_service',
            sql.Boolean,
            nullable=False,
            server_default='0',
            default=False,
        ),
        # NOTE(notmorgan): To support the full range of scrypt and pbkfd
        # password hash lengths, this should be closer to varchar(1500) instead
        # of varchar(255).
        sql.Column('password_hash', sql.String(255), nullable=True),
        sql.Column(
            'created_at_int',
            ks_sql.DateTimeInt(),
            nullable=False,
            default=0,
            server_default='0',
        ),
        sql.Column('expires_at_int', ks_sql.DateTimeInt(), nullable=True),
        sql.Column(
            'created_at',
            sql.DateTime(),
            nullable=False,
            default=datetime.datetime.utcnow,
        ),
    )

    project_endpoint_group = sql.Table(
        'project_endpoint_group',
        meta,
        sql.Column(
            'endpoint_group_id',
            sql.String(64),
            sql.ForeignKey(endpoint_group.c.id),
            nullable=False,
        ),
        sql.Column('project_id', sql.String(64), nullable=False),
        sql.PrimaryKeyConstraint('endpoint_group_id', 'project_id'),
    )

    federated_user = sql.Table(
        'federated_user',
        meta,
        sql.Column('id', sql.Integer, primary_key=True, nullable=False),
        sql.Column(
            'user_id',
            sql.String(64),
            sql.ForeignKey(user.c.id, ondelete='CASCADE'),
            nullable=False,
        ),
        sql.Column(
            'idp_id',
            sql.String(64),
            sql.ForeignKey(identity_provider.c.id, ondelete='CASCADE'),
            nullable=False,
        ),
        sql.Column('protocol_id', sql.String(64), nullable=False),
        sql.Column('unique_id', sql.String(255), nullable=False),
        sql.Column('display_name', sql.String(255), nullable=True),
        sql.ForeignKeyConstraint(
            ['protocol_id', 'idp_id'],
            [federation_protocol.c.id, federation_protocol.c.idp_id],
            name='federated_user_protocol_id_fkey',
            ondelete='CASCADE',
        ),
        sql.UniqueConstraint('idp_id', 'protocol_id', 'unique_id'),
        mysql_engine='InnoDB',
        mysql_charset='utf8',
    )

    # create all tables
    tables = [
        access_rule,
        application_credential,
        assignment,
        config_register,
        consumer,
        credential,
        group,
        id_mapping,
        identity_provider,
        idp_remote_ids,
        mapping,
        policy,
        policy_association,
        project,
        project_endpoint,
        project_option,
        project_tag,
        region,
        registered_limit,
        request_token,
        revocation_event,
        role,
        role_option,
        sensitive_config,
        service,
        service_provider,
        system_assignment,
        token,
        trust,
        trust_role,
        user,
        user_group_membership,
        user_option,
        whitelisted_config,
        access_token,
        application_credential_access_rule,
        application_credential_role,
        endpoint,
        endpoint_group,
        expiring_user_group_membership,
        federation_protocol,
        implied_role,
        limit,
        local_user,
        nonlocal_user,
        password,
        project_endpoint_group,
        federated_user,
    ]

    for table in tables:
        try:
            table.create()
        except Exception:
            LOG.exception('Exception while creating table: %r', table)
            raise

    fkeys = []

    if migrate_engine.name == 'sqlite':
        # NOTE(stevemar): We need to keep this FK constraint due to 073, but
        # only for sqlite, once we collapse 073 we can remove this constraint
        fkeys.append(
            {
                'columns': [assignment.c.role_id],
                'references': [role.c.id],
                'name': 'fk_assignment_role_id',
            }, )

    for fkey in fkeys:
        migrate.ForeignKeyConstraint(
            columns=fkey['columns'],
            refcolumns=fkey['references'],
            name=fkey.get('name'),
            ondelete=fkey.get('ondelete'),
            onupdate=fkey.get('onupdate'),
        ).create()

    # TODO(stephenfin): Remove these procedures in a future contract migration

    if migrate_engine.name == 'postgresql':
        error_message = ('Credential migration in progress. Cannot perform '
                         'writes to credential table.')
        credential_update_trigger = textwrap.dedent(f"""
        CREATE OR REPLACE FUNCTION keystone_read_only_update()
          RETURNS trigger AS
        $BODY$
        BEGIN
          IF NEW.encrypted_blob IS NULL THEN
            RAISE EXCEPTION '{error_message}';
          END IF;
          IF NEW.encrypted_blob IS NOT NULL AND OLD.blob IS NULL THEN
            RAISE EXCEPTION '{error_message}';
          END IF;
          RETURN NEW;
        END
        $BODY$ LANGUAGE plpgsql;
        """)
        migrate_engine.execute(credential_update_trigger)

        error_message = ('Identity provider migration in progress. Cannot '
                         'insert new rows into the identity_provider table at '
                         'this time.')
        identity_provider_insert_trigger = textwrap.dedent(f"""
        CREATE OR REPLACE FUNCTION keystone_read_only_insert()
          RETURNS trigger AS
        $BODY$
        BEGIN
          RAISE EXCEPTION '{error_message}';
        END
        $BODY$ LANGUAGE plpgsql;
        """)
        migrate_engine.execute(identity_provider_insert_trigger)

        federated_user_insert_trigger = textwrap.dedent("""
        CREATE OR REPLACE FUNCTION update_federated_user_domain_id()
            RETURNS trigger AS
        $BODY$
        BEGIN
            UPDATE "user" SET domain_id = (
                SELECT domain_id FROM identity_provider WHERE id = NEW.idp_id)
                WHERE id = NEW.user_id and domain_id IS NULL;
            RETURN NULL;
        END
        $BODY$ LANGUAGE plpgsql;
        """)
        migrate_engine.execute(federated_user_insert_trigger)

        local_user_insert_trigger = textwrap.dedent("""
        CREATE OR REPLACE FUNCTION update_user_domain_id()
            RETURNS trigger AS
        $BODY$
        BEGIN
            UPDATE "user" SET domain_id = NEW.domain_id
                WHERE id = NEW.user_id;
            RETURN NULL;
        END
        $BODY$ LANGUAGE plpgsql;
        """)
        migrate_engine.execute(local_user_insert_trigger)

    # FIXME(stephenfin): Remove these indexes. They're left over from attempts
    # to remove foreign key constraints in past migrations. Apparently
    # sqlalchemy-migrate didn't do the job fully and left behind indexes
    if migrate_engine.name == 'mysql':
        sql.Index('region_id', registered_limit.c.region_id).create()

        # FIXME(stephenfin): This should be dropped when we add the FK
        # constraint to this column
        sql.Index('registered_limit_id', limit.c.registered_limit_id).create()

        # FIXME(stephenfin): These are leftover from when we removed a FK
        # constraint and should probable be dropped
        sql.Index('domain_id', identity_provider.c.domain_id).create()
        sql.Index('domain_id', user.c.domain_id).create()