diff options
author | Zuul <zuul@review.opendev.org> | 2022-08-30 05:11:25 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2022-08-30 05:11:25 +0000 |
commit | 218e11ea204ee948a7aa3dcda0febff379ef0ec2 (patch) | |
tree | 611370a1c00ceb9f539fbf06df6545daeb3dd552 /designate/storage/impl_sqlalchemy/alembic | |
parent | 71c7542a892d76a6631e919fdd7ecf636f834eaa (diff) | |
parent | 60c378763aa37246762ff210f024e2af019f6397 (diff) | |
download | designate-218e11ea204ee948a7aa3dcda0febff379ef0ec2.tar.gz |
Merge "Switch Designate to Alembic database migrations"
Diffstat (limited to 'designate/storage/impl_sqlalchemy/alembic')
19 files changed, 1460 insertions, 0 deletions
diff --git a/designate/storage/impl_sqlalchemy/alembic/README b/designate/storage/impl_sqlalchemy/alembic/README new file mode 100644 index 00000000..81b6a350 --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/README @@ -0,0 +1,5 @@ +Please use the "designate-manage database" command for database management. + +Developers adding new migrations can run 'alembic -m "<migration title>"' from +the designate/storage/impl_sqlalchemy directory where the alembic.ini file is +located. diff --git a/designate/storage/impl_sqlalchemy/alembic/env.py b/designate/storage/impl_sqlalchemy/alembic/env.py new file mode 100644 index 00000000..0d23c33e --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/env.py @@ -0,0 +1,83 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License.mport threading +from sqlalchemy import engine_from_config +from sqlalchemy import pool + +from alembic import context + +# this is the Alembic Config object, which provides +# access to the values within the .ini file in use. +config = context.config + +# add your model's MetaData object here +# for 'autogenerate' support +# from myapp import mymodel +# target_metadata = mymodel.Base.metadata +target_metadata = None + +# other values from the config, defined by the needs of env.py, +# can be acquired: +# my_important_option = config.get_main_option("my_important_option") +# ... etc. + + +def run_migrations_offline() -> None: + """Run migrations in 'offline' mode. + + This configures the context with just a URL + and not an Engine, though an Engine is acceptable + here as well. By skipping the Engine creation + we don't even need a DBAPI to be available. + + Calls to context.execute() here emit the given string to the + script output. + + """ + url = config.get_main_option("sqlalchemy.url") + context.configure( + url=url, + target_metadata=target_metadata, + literal_binds=True, + dialect_opts={"paramstyle": "named"}, + ) + + with context.begin_transaction(): + context.run_migrations() + + +def run_migrations_online() -> None: + """Run migrations in 'online' mode. + + In this scenario we need to create an Engine + and associate a connection with the context. + + """ + connectable = engine_from_config( + config.get_section(config.config_ini_section), + prefix="sqlalchemy.", + poolclass=pool.NullPool, + ) + + with connectable.connect() as connection: + context.configure( + connection=connection, target_metadata=target_metadata, + transactional_ddl=True, transaction_per_migration=True + ) + + with context.begin_transaction(): + context.run_migrations() + + +if context.is_offline_mode(): + run_migrations_offline() +else: + run_migrations_online() diff --git a/designate/storage/impl_sqlalchemy/alembic/legacy_utils.py b/designate/storage/impl_sqlalchemy/alembic/legacy_utils.py new file mode 100644 index 00000000..b0f7179e --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/legacy_utils.py @@ -0,0 +1,43 @@ +# Copyright 2022 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from alembic import op +from oslo_log import log as logging +import sqlalchemy as sa + +LOG = logging.getLogger(__name__) + + +def is_migration_needed(equivalent_revision): + metadata = sa.MetaData(bind=op.get_bind()) + sa.MetaData.reflect(metadata) + + if 'migrate_version' not in metadata.tables.keys(): + return True + + version_sql = sa.text("SELECT version FROM migrate_version;") + legacy_db_rev = None + try: + legacy_db_rev = op.get_bind().execute(version_sql).scalar_one_or_none() + except Exception as e: + LOG.debug("Unable to query the database for the legacy revision " + "number. Assuming there is no legacy migration revision " + "or the migration is running in offline mode. Error: %s", + str(e)) + + # Check if this migration was already run by the legacy sqlalchemy-migrate + # migrations. + if legacy_db_rev and int(legacy_db_rev) >= equivalent_revision: + return False + return True diff --git a/designate/storage/impl_sqlalchemy/alembic/script.py.mako b/designate/storage/impl_sqlalchemy/alembic/script.py.mako new file mode 100644 index 00000000..8fd7d546 --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/script.py.mako @@ -0,0 +1,32 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""${message} + +Revision ID: ${up_revision} +Revises: ${down_revision | comma,n} +Create Date: ${create_date} + +""" +from alembic import op +import sqlalchemy as sa +${imports if imports else ""} + +# revision identifiers, used by Alembic. +revision = ${repr(up_revision)} +down_revision = ${repr(down_revision)} +branch_labels = ${repr(branch_labels)} +depends_on = ${repr(depends_on)} + + +def upgrade() -> None: + ${upgrades if upgrades else "pass"} diff --git a/designate/storage/impl_sqlalchemy/alembic/versions/0bcf910ea823_add_zone_attributes.py b/designate/storage/impl_sqlalchemy/alembic/versions/0bcf910ea823_add_zone_attributes.py new file mode 100644 index 00000000..531d11b1 --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/versions/0bcf910ea823_add_zone_attributes.py @@ -0,0 +1,95 @@ +# Copyright 2015 Hewlett-Packard Development Company, L.P. +# Copyright 2022 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""add_zone_attributes + +Revision ID: 0bcf910ea823 +Revises: a69b45715cc1 +Create Date: 2022-07-29 21:36:15.117658 + +""" +from alembic import op +from oslo_utils import timeutils +import sqlalchemy as sa + +from designate.sqlalchemy.types import UUID +from designate.storage.impl_sqlalchemy.alembic import legacy_utils +from designate import utils + +# revision identifiers, used by Alembic. +revision = '0bcf910ea823' +down_revision = 'a69b45715cc1' +branch_labels = None +depends_on = None + +# Equivalent to legacy sqlalchemy-migrate revision 085_add_zone_attributes + +# Note from original migration file: +# Move zone masters to their own table, and allow for abstract keys in the +# attributes table + + +def upgrade() -> None: + # Check if the equivalent legacy migration has already run + if not legacy_utils.is_migration_needed(85): + return + + metadata = sa.MetaData() + + zone_masters_table = op.create_table( + 'zone_masters', metadata, + sa.Column('id', UUID, default=utils.generate_uuid, primary_key=True), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('created_at', sa.DateTime, + default=lambda: timeutils.utcnow()), + sa.Column('updated_at', sa.DateTime, + onupdate=lambda: timeutils.utcnow()), + sa.Column('host', sa.String(32), nullable=False), + sa.Column('port', sa.Integer, nullable=False), + sa.Column('zone_id', UUID, nullable=False), + sa.UniqueConstraint('host', 'port', 'zone_id', name='unique_masters'), + sa.ForeignKeyConstraint(['zone_id'], ['zones.id'], ondelete='CASCADE')) + + zone_attr_sql = sa.text( + 'SELECT id, version, created_at, updated_at, value, zone_id FROM ' + 'zone_attributes WHERE \'key\' = \'master\';') + + masters = op.get_bind().execute(zone_attr_sql).fetchall() + + masters_input = [] + + for master in masters: + host, port = utils.split_host_port( + master['value']) + masters_input.append({ + 'id': master['id'], + 'version': master['version'], + 'created_at': master['created_at'], + 'updated_at': master['updated_at'], + 'zone_id': master['zone_id'], + 'host': host, + 'port': port + }) + + op.bulk_insert(zone_masters_table, masters_input) + + master_delete_sql = sa.text( + 'DELETE FROM zone_attributes WHERE \'key\' = \'master\';') + + op.get_bind().execute(master_delete_sql) + + with op.batch_alter_table('zone_attributes') as batch_op: + batch_op.alter_column('key', type_=sa.String(50), + existing_type=sa.Enum) diff --git a/designate/storage/impl_sqlalchemy/alembic/versions/15b34ff3ecb8_fix_service_charset.py b/designate/storage/impl_sqlalchemy/alembic/versions/15b34ff3ecb8_fix_service_charset.py new file mode 100644 index 00000000..a385ef72 --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/versions/15b34ff3ecb8_fix_service_charset.py @@ -0,0 +1,48 @@ +# Copyright 2016 Hewlett Packard Enterprise Development Company LP +# Copyright 2022 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""fix_service_charset + +Revision ID: 15b34ff3ecb8 +Revises: 304d41c3847a +Create Date: 2022-08-01 16:53:34.612019 + +""" +from alembic import op + +from designate.storage.impl_sqlalchemy.alembic import legacy_utils + +# revision identifiers, used by Alembic. +revision = '15b34ff3ecb8' +down_revision = '304d41c3847a' +branch_labels = None +depends_on = None + +# Equivalent to legacy sqlalchemy-migrate revision 098_fix_service_charset + + +def upgrade() -> None: + # Check if the equivalent legacy migration has already run + if not legacy_utils.is_migration_needed(98): + return + + current_bind = op.get_bind() + if current_bind.dialect.name != 'mysql': + return + + op.execute('SET foreign_key_checks = 0;') + op.execute('ALTER TABLE service_statuses CONVERT TO CHARACTER SET utf8;') + op.execute('SET foreign_key_checks = 1;') + op.execute('ALTER DATABASE DEFAULT CHARACTER SET utf8;') diff --git a/designate/storage/impl_sqlalchemy/alembic/versions/304d41c3847a_add_services.py b/designate/storage/impl_sqlalchemy/alembic/versions/304d41c3847a_add_services.py new file mode 100644 index 00000000..02e6a09a --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/versions/304d41c3847a_add_services.py @@ -0,0 +1,59 @@ +# Copyright 2016 Hewlett Packard Enterprise Development Company LP +# Copyright 2022 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""add_services + +Revision ID: 304d41c3847a +Revises: d04819112169 +Create Date: 2022-08-01 16:41:55.139558 + +""" +from alembic import op +import sqlalchemy as sa + +from designate.sqlalchemy.types import UUID +from designate.storage.impl_sqlalchemy.alembic import legacy_utils +from designate import utils + +# revision identifiers, used by Alembic. +revision = '304d41c3847a' +down_revision = 'd04819112169' +branch_labels = None +depends_on = None + +SERVICE_STATES = ["UP", "DOWN", "WARNING"] + +# Equivalent to legacy sqlalchemy-migrate revision 097_add_services + + +def upgrade() -> None: + # Check if the equivalent legacy migration has already run + if not legacy_utils.is_migration_needed(97): + return + + metadata = sa.MetaData() + + op.create_table( + 'service_statuses', metadata, + sa.Column('id', UUID, default=utils.generate_uuid, primary_key=True), + sa.Column('created_at', sa.DateTime), + sa.Column('updated_at', sa.DateTime), + sa.Column('service_name', sa.String(40), nullable=False), + sa.Column('hostname', sa.String(255), nullable=False), + sa.Column('heartbeated_at', sa.DateTime, nullable=True), + sa.Column('status', sa.Enum(name='service_statuses_enum', + *SERVICE_STATES), nullable=False), + sa.Column('stats', sa.Text, nullable=False), + sa.Column('capabilities', sa.Text, nullable=False)) diff --git a/designate/storage/impl_sqlalchemy/alembic/versions/7977deaa5167_add_rrset_indexes_for_filtering_perf.py b/designate/storage/impl_sqlalchemy/alembic/versions/7977deaa5167_add_rrset_indexes_for_filtering_perf.py new file mode 100644 index 00000000..12abecbd --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/versions/7977deaa5167_add_rrset_indexes_for_filtering_perf.py @@ -0,0 +1,46 @@ +# Copyright 2016 Rackspace +# Copyright 2022 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""add_rrset_indexes_for_filtering_perf + +Revision ID: 7977deaa5167 +Revises: 15b34ff3ecb8 +Create Date: 2022-08-01 17:13:01.429689 + +""" +from alembic import op + +from designate.storage.impl_sqlalchemy.alembic import legacy_utils + +# revision identifiers, used by Alembic. +revision = '7977deaa5167' +down_revision = '15b34ff3ecb8' +branch_labels = None +depends_on = None + +# Equivalent to legacy sqlalchemy-migrate revision +# 099_add_rrset_indexes_for_filtering_perf + + +def upgrade() -> None: + # Check if the equivalent legacy migration has already run + if not legacy_utils.is_migration_needed(99): + return + + op.create_index('rrset_updated_at', 'recordsets', ['updated_at']) + op.create_index('rrset_zoneid', 'recordsets', ['zone_id']) + op.create_index('rrset_type', 'recordsets', ['type']) + op.create_index('rrset_ttl', 'recordsets', ['ttl']) + op.create_index('rrset_tenant_id', 'recordsets', ['tenant_id']) diff --git a/designate/storage/impl_sqlalchemy/alembic/versions/867a331ce1fc_domain_to_zone_rename.py b/designate/storage/impl_sqlalchemy/alembic/versions/867a331ce1fc_domain_to_zone_rename.py new file mode 100644 index 00000000..65b6df70 --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/versions/867a331ce1fc_domain_to_zone_rename.py @@ -0,0 +1,149 @@ +# Copyright 2015 Hewlett-Packard Development Company, L.P. +# Copyright 2022 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""domain_to_zone_rename + +Revision ID: 867a331ce1fc +Revises: c9f427f7180a +Create Date: 2022-07-29 18:41:19.427853 + +""" +from alembic import op +import sqlalchemy as sa + +from designate.sqlalchemy.types import UUID +from designate.storage.impl_sqlalchemy.alembic import legacy_utils + +# revision identifiers, used by Alembic. +revision = '867a331ce1fc' +down_revision = 'c9f427f7180a' +branch_labels = None +depends_on = None + +# Equivalent to legacy sqlalchemy-migrate revision 080_domain_to_zone_rename + +# Notes from the original migration file: +# This migration removes all references to domain from our Database. +# We rename the domains and domain_attribute tables, and rename any columns +# that had "domain" in the name.as +# There is a follow on patch to recreate the FKs for the newly renamed +# tables as the lib we use doesn't seem to like creating FKs on renamed +# tables until after the migration is complete. + + +def _drop_foreign_key(fk_def): + + table = fk_def[0].table + + col = fk_def[0] + ref_col = fk_def[1] + + # We need a naming convention to find unnamed foreign keys on sqlite + naming_convention = { + "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s"} + + # Use .copy() to avoid the set changing during the for operation + # We need to search for the foreign keys as they may be named differently + # between different dialects (mysql, sqlite, etc.) + for fk in table.foreign_keys.copy(): + # We must use batch mode because the unit tests use sqlite + with op.batch_alter_table( + table.name, naming_convention=naming_convention) as batch_op: + + # Check if the fk is the one we want + if fk.column == col and fk.parent == ref_col: + batch_op.drop_constraint(fk.constraint.name, + type_='foreignkey') + + # Check if the fk is the one we want (sometimes it seems the parent + # / col is switched + if fk.parent == col and fk.column == ref_col: + batch_op.drop_constraint(fk.constraint.name, + type_='foreignkey') + + +def upgrade() -> None: + # Check if the equivalent legacy migration has already run + if not legacy_utils.is_migration_needed(80): + return + + convention = { + "ix": 'ix_%(column_0_label)s', + "uq": "uq_%(table_name)s_%(column_0_name)s", + "ck": "ck_%(table_name)s_%(constraint_name)s", + "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", + "pk": "pk_%(table_name)s"} + + metadata = sa.MetaData(naming_convention=convention) + metadata.bind = op.get_bind() + + # Get all the tables + domains_table = sa.Table('domains', metadata, autoload=True) + domain_attrib_table = sa.Table('domain_attributes', metadata, + autoload=True) + recordsets_table = sa.Table('recordsets', metadata, autoload=True) + records_table = sa.Table('records', metadata, autoload=True) + ztr_table = sa.Table('zone_transfer_requests', metadata, autoload=True) + zta_table = sa.Table('zone_transfer_accepts', metadata, autoload=True) + + # Remove the affected FKs + # Define FKs + fks = [ + [domains_table.c.id, domains_table.c.parent_domain_id], + [domain_attrib_table.c.domain_id, domains_table.c.id], + [recordsets_table.c.domain_id, domains_table.c.id], + [records_table.c.domain_id, domains_table.c.id], + [ztr_table.c.domain_id, domains_table.c.id], + [zta_table.c.domain_id, domains_table.c.id] + ] + + # Drop FKs + for fk in fks: + _drop_foreign_key(fk) + + with op.batch_alter_table('domains') as batch_op: + batch_op.alter_column('parent_domain_id', + new_column_name='parent_zone_id', + existing_type=UUID) + op.rename_table('domains', 'zones') + + with op.batch_alter_table('domain_attributes') as batch_op: + batch_op.alter_column('domain_id', new_column_name='zone_id', + existing_type=UUID) + op.rename_table('domain_attributes', 'zone_attributes') + + with op.batch_alter_table('recordsets') as batch_op: + batch_op.alter_column('domain_id', new_column_name='zone_id', + existing_type=UUID) + batch_op.alter_column('domain_shard', new_column_name='zone_shard', + existing_type=sa.SmallInteger) + + with op.batch_alter_table('records') as batch_op: + batch_op.alter_column('domain_id', new_column_name='zone_id', + existing_type=UUID) + batch_op.alter_column('domain_shard', new_column_name='zone_shard', + existing_type=sa.SmallInteger) + + with op.batch_alter_table('zone_transfer_requests') as batch_op: + batch_op.alter_column('domain_id', new_column_name='zone_id', + existing_type=UUID) + + with op.batch_alter_table('zone_transfer_accepts') as batch_op: + batch_op.alter_column('domain_id', new_column_name='zone_id', + existing_type=UUID) + + with op.batch_alter_table('zone_tasks') as batch_op: + batch_op.alter_column('domain_id', new_column_name='zone_id', + existing_type=UUID) diff --git a/designate/storage/impl_sqlalchemy/alembic/versions/91eb1eb7c882_support_caa_records.py b/designate/storage/impl_sqlalchemy/alembic/versions/91eb1eb7c882_support_caa_records.py new file mode 100644 index 00000000..668569ad --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/versions/91eb1eb7c882_support_caa_records.py @@ -0,0 +1,48 @@ +# Copyright 2018 Canonical Ltd. +# Copyright 2022 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""support_caa_records + +Revision ID: 91eb1eb7c882 +Revises: b8999fd10721 +Create Date: 2022-08-01 17:32:21.386556 + +""" +from alembic import op +import sqlalchemy as sa + +from designate.storage.impl_sqlalchemy.alembic import legacy_utils + +# revision identifiers, used by Alembic. +revision = '91eb1eb7c882' +down_revision = 'b8999fd10721' +branch_labels = None +depends_on = None + +# Equivalent to legacy sqlalchemy-migrate revision 102_support_caa_records + + +def upgrade() -> None: + # Check if the equivalent legacy migration has already run + if not legacy_utils.is_migration_needed(102): + return + + RECORD_TYPES = ['A', 'AAAA', 'CNAME', 'MX', 'SRV', 'TXT', 'SPF', 'NS', + 'PTR', 'SSHFP', 'SOA', 'NAPTR', 'CAA'] + + with op.batch_alter_table('recordsets') as batch_op: + batch_op.alter_column('type', type_=sa.Enum(name='record_types', + *RECORD_TYPES), + existing_type=sa.Enum, existing_nullable=False) diff --git a/designate/storage/impl_sqlalchemy/alembic/versions/93a00a815f07_unique_service_status.py b/designate/storage/impl_sqlalchemy/alembic/versions/93a00a815f07_unique_service_status.py new file mode 100644 index 00000000..6071a7ba --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/versions/93a00a815f07_unique_service_status.py @@ -0,0 +1,60 @@ +# Copyright 2022 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""unique_service_status + +Revision ID: 93a00a815f07 +Revises: 7977deaa5167 +Create Date: 2022-08-01 17:17:44.572964 + +""" +import sys + +from alembic import op +from oslo_log import log as logging +import sqlalchemy as sa + +from designate.storage.impl_sqlalchemy.alembic import legacy_utils + +# revision identifiers, used by Alembic. +revision = '93a00a815f07' +down_revision = '7977deaa5167' +branch_labels = None +depends_on = None + +LOG = logging.getLogger() + +# Equivalent to legacy sqlalchemy-migrate revision 100_unique_service_status + +EXPLANATION = """ +You need to manually remove duplicate entries from the database. + +The error message was: +%s +""" + + +def upgrade() -> None: + # Check if the equivalent legacy migration has already run + if not legacy_utils.is_migration_needed(100): + return + + try: + with op.batch_alter_table('service_statuses') as batch_op: + batch_op.create_unique_constraint('unique_service_status', + ['service_name', 'hostname']) + except sa.exc.IntegrityError as e: + LOG.error(EXPLANATION, e) + # Use sys.exit so we don't blow up with a huge trace + sys.exit(1) diff --git a/designate/storage/impl_sqlalchemy/alembic/versions/a69b45715cc1_add_delayed_notify_column.py b/designate/storage/impl_sqlalchemy/alembic/versions/a69b45715cc1_add_delayed_notify_column.py new file mode 100644 index 00000000..93bd6c5f --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/versions/a69b45715cc1_add_delayed_notify_column.py @@ -0,0 +1,45 @@ +# Copyright 2015 Hewlett-Packard Development Company, L.P. +# Copyright 2022 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""add_delayed_notify_column + +Revision ID: a69b45715cc1 +Revises: f9f969f9d85e +Create Date: 2022-07-29 21:30:12.127816 + +""" +from alembic import op +import sqlalchemy as sa + +from designate.storage.impl_sqlalchemy.alembic import legacy_utils + +# revision identifiers, used by Alembic. +revision = 'a69b45715cc1' +down_revision = 'f9f969f9d85e' +branch_labels = None +depends_on = None + +# Equivalent to legacy sqlalchemy-migrate revision +# 084_add_delayed_notify_column + + +def upgrade() -> None: + # Check if the equivalent legacy migration has already run + if not legacy_utils.is_migration_needed(84): + return + + op.add_column('zones', + sa.Column('delayed_notify', sa.Boolean, default=False)) + op.create_index('delayed_notify', 'zones', ['delayed_notify']) diff --git a/designate/storage/impl_sqlalchemy/alembic/versions/b8999fd10721_support_naptr_records.py b/designate/storage/impl_sqlalchemy/alembic/versions/b8999fd10721_support_naptr_records.py new file mode 100644 index 00000000..ec456d4c --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/versions/b8999fd10721_support_naptr_records.py @@ -0,0 +1,48 @@ +# Copyright 2018 Canonical Ltd. +# Copyright 2022 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""support_naptr_records + +Revision ID: b8999fd10721 +Revises: 93a00a815f07 +Create Date: 2022-08-01 17:25:33.058845 + +""" +from alembic import op +import sqlalchemy as sa + +from designate.storage.impl_sqlalchemy.alembic import legacy_utils + +# revision identifiers, used by Alembic. +revision = 'b8999fd10721' +down_revision = '93a00a815f07' +branch_labels = None +depends_on = None + +# Equivalent to legacy sqlalchemy-migrate revision 101_support_naptr_records + + +def upgrade() -> None: + # Check if the equivalent legacy migration has already run + if not legacy_utils.is_migration_needed(101): + return + + RECORD_TYPES = ['A', 'AAAA', 'CNAME', 'MX', 'SRV', 'TXT', 'SPF', 'NS', + 'PTR', 'SSHFP', 'SOA', 'NAPTR'] + + with op.batch_alter_table('recordsets') as batch_op: + batch_op.alter_column('type', type_=sa.Enum(name='record_types', + *RECORD_TYPES), + existing_type=sa.Enum, existing_nullable=False) diff --git a/designate/storage/impl_sqlalchemy/alembic/versions/bfcfc4a07487_unique_ns_record.py b/designate/storage/impl_sqlalchemy/alembic/versions/bfcfc4a07487_unique_ns_record.py new file mode 100644 index 00000000..6f355a60 --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/versions/bfcfc4a07487_unique_ns_record.py @@ -0,0 +1,65 @@ +# Copyright 2015 Hewlett-Packard Development Company, L.P. +# Copyright 2022 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""unique_ns_record + +Revision ID: bfcfc4a07487 +Revises: d9a1883e93e9 +Create Date: 2022-07-29 21:05:19.276173 + +""" +import sys + +from alembic import op +from oslo_log import log as logging +import sqlalchemy as sa + +from designate.storage.impl_sqlalchemy.alembic import legacy_utils + +# revision identifiers, used by Alembic. +revision = 'bfcfc4a07487' +down_revision = 'd9a1883e93e9' +branch_labels = None +depends_on = None + +LOG = logging.getLogger() + +# Equivalent to legacy sqlalchemy-migrate revision 082_unique_ns_record + +# Note from the original migration script: +# Add Unique constraint on ('pool_id', 'hostname') in the pool_ns_records +# table Bug #1517389 + +EXPLANATION = """ +You need to manually remove duplicate entries from the database. + +The error message was: +%s +""" + + +def upgrade() -> None: + # Check if the equivalent legacy migration has already run + if not legacy_utils.is_migration_needed(82): + return + + try: + with op.batch_alter_table('pool_ns_records') as batch_op: + batch_op.create_unique_constraint('unique_ns_name', + ['pool_id', 'hostname']) + except sa.exc.IntegrityError as e: + LOG.error(EXPLANATION, e) + # Use sys.exit so we don't blow up with a huge trace + sys.exit(1) diff --git a/designate/storage/impl_sqlalchemy/alembic/versions/c9f427f7180a_liberty.py b/designate/storage/impl_sqlalchemy/alembic/versions/c9f427f7180a_liberty.py new file mode 100644 index 00000000..62b7135f --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/versions/c9f427f7180a_liberty.py @@ -0,0 +1,340 @@ +# Copyright 2015 Hewlett-Packard Development Company, L.P. +# Copyright 2022 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""liberty + +Revision ID: c9f427f7180a +Revises: +Create Date: 2022-07-28 23:06:40.731452 + +""" +from alembic import op +from oslo_config import cfg +from oslo_utils import timeutils +import sqlalchemy as sa + +from designate.conf import central +from designate.sqlalchemy.types import UUID +from designate.storage.impl_sqlalchemy.alembic import legacy_utils + +# revision identifiers, used by Alembic. +revision = 'c9f427f7180a' +down_revision = None +branch_labels = None +depends_on = None + +# Equivalent to legacy sqlalchemy-migrate revision 070_liberty + +CONF = cfg.CONF +central.register_opts(CONF) + +ACTIONS = ('CREATE', 'DELETE', 'UPDATE', 'NONE') +POOL_PROVISIONERS = ('UNMANAGED',) +RECORD_TYPES = ('A', 'AAAA', 'CNAME', 'MX', 'SRV', 'TXT', 'SPF', 'NS', 'PTR', + 'SSHFP', 'SOA') +RESOURCE_STATUSES = ('ACTIVE', 'PENDING', 'DELETED', 'ERROR') +TASK_STATUSES = ('ACTIVE', 'PENDING', 'DELETED', 'ERROR', 'COMPLETE') +TSIG_ALGORITHMS = ('hmac-md5', 'hmac-sha1', 'hmac-sha224', 'hmac-sha256', + 'hmac-sha384', 'hmac-sha512') +TSIG_SCOPES = ('POOL', 'ZONE') +ZONE_ATTRIBUTE_KEYS = ('master',) +ZONE_TASK_TYPES = ('IMPORT', 'EXPORT') +ZONE_TYPES = ('PRIMARY', 'SECONDARY') + + +def upgrade() -> None: + # Check if the equivalent legacy migration has already run + if not legacy_utils.is_migration_needed(70): + return + + metadata = sa.MetaData() + + pools_table = op.create_table( + 'pools', metadata, + sa.Column('id', UUID, primary_key=True), + sa.Column('created_at', sa.DateTime), + sa.Column('updated_at', sa.DateTime), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('name', sa.String(50), nullable=False), + sa.Column('description', sa.Unicode(160), nullable=True), + sa.Column('tenant_id', sa.String(36), nullable=True), + sa.Column('provisioner', sa.Enum(name='pool_provisioner', + *POOL_PROVISIONERS), + nullable=False, server_default='UNMANAGED'), + sa.UniqueConstraint('name', name='unique_pool_name')) + + op.bulk_insert( + pools_table, + [{'id': CONF['service:central'].default_pool_id, + 'name': 'default', + 'version': 1}]) + + op.create_table( + 'pool_ns_records', metadata, + sa.Column('id', UUID, primary_key=True), + sa.Column('created_at', sa.DateTime), + sa.Column('updated_at', sa.DateTime), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('pool_id', UUID, nullable=False), + sa.Column('priority', sa.Integer, nullable=False), + sa.Column('hostname', sa.String(255), nullable=False), + sa.ForeignKeyConstraint(['pool_id'], ['pools.id'], ondelete='CASCADE')) + + op.create_table( + 'pool_attributes', metadata, + sa.Column('id', UUID, primary_key=True), + sa.Column('created_at', sa.DateTime), + sa.Column('updated_at', sa.DateTime), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('key', sa.String(255), nullable=False), + sa.Column('value', sa.String(255), nullable=False), + sa.Column('pool_id', UUID, nullable=False), + sa.UniqueConstraint('pool_id', 'key', 'value', + name='unique_pool_attribute'), + sa.ForeignKeyConstraint(['pool_id'], ['pools.id'], ondelete='CASCADE')) + + op.create_table( + 'domains', metadata, + sa.Column('id', UUID, primary_key=True), + sa.Column('created_at', sa.DateTime), + sa.Column('updated_at', sa.DateTime), + sa.Column('version', sa.Integer, nullable=False), + sa.Column('tenant_id', sa.String(36), default=None, nullable=True), + sa.Column('name', sa.String(255), nullable=False), + sa.Column('email', sa.String(255), nullable=False), + sa.Column('ttl', sa.Integer, default=CONF.default_ttl, nullable=False), + sa.Column('refresh', sa.Integer, nullable=False), + sa.Column('retry', sa.Integer, nullable=False), + sa.Column('expire', sa.Integer, nullable=False), + sa.Column('minimum', sa.Integer, nullable=False), + sa.Column('parent_domain_id', UUID, default=None, nullable=True), + sa.Column('serial', sa.Integer, nullable=False, server_default='1'), + sa.Column('deleted', sa.CHAR(32), nullable=False, default='0', + server_default='0'), + sa.Column('deleted_at', sa.DateTime, nullable=True, default=None), + sa.Column('description', sa.Unicode(160), nullable=True), + sa.Column('status', sa.Enum(name='domains_resource_statuses', + *RESOURCE_STATUSES), + nullable=False, server_default='PENDING', default='PENDING'), + sa.Column('action', sa.Enum(name='domain_actions', *ACTIONS), + default='CREATE', server_default='CREATE', nullable=False), + sa.Column('pool_id', UUID, default=None, nullable=True), + sa.Column('reverse_name', sa.String(255), nullable=False, + server_default=''), + sa.Column("type", sa.Enum(name='type', *ZONE_TYPES), + server_default='PRIMARY', default='PRIMARY'), + sa.Column('transferred_at', sa.DateTime, default=None), + sa.Column('shard', sa.SmallInteger, nullable=False), + sa.UniqueConstraint('name', 'deleted', 'pool_id', + name='unique_domain_name'), + sa.ForeignKeyConstraint(['parent_domain_id'], + ['domains.id'], + ondelete='SET NULL'), + sa.Index('zone_deleted', 'deleted'), + sa.Index('zone_tenant_deleted', 'tenant_id', 'deleted'), + sa.Index('reverse_name_deleted', 'reverse_name', 'deleted'), + sa.Index('zone_created_at', 'created_at')) + + op.create_table( + 'domain_attributes', metadata, + sa.Column('id', UUID, primary_key=True), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('created_at', sa.DateTime), + sa.Column('updated_at', sa.DateTime), + sa.Column('key', sa.Enum(name='key', *ZONE_ATTRIBUTE_KEYS)), + sa.Column('value', sa.String(255), nullable=False), + sa.Column('domain_id', UUID, nullable=False), + sa.UniqueConstraint('key', 'value', 'domain_id', + name='unique_attributes'), + sa.ForeignKeyConstraint(['domain_id'], ['domains.id'], + ondelete='CASCADE')) + op.create_table( + 'recordsets', metadata, + sa.Column('id', UUID, primary_key=True), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('created_at', sa.DateTime), + sa.Column('updated_at', sa.DateTime), + sa.Column('domain_shard', sa.SmallInteger, nullable=False), + sa.Column('tenant_id', sa.String(36), default=None, nullable=True), + sa.Column('domain_id', UUID, nullable=False), + sa.Column('name', sa.String(255), nullable=False), + sa.Column('type', sa.Enum(name='record_types', *RECORD_TYPES), + nullable=False), + sa.Column('ttl', sa.Integer, default=None, nullable=True), + sa.Column('description', sa.Unicode(160), nullable=True), + sa.Column('reverse_name', sa.String(255), nullable=False, + server_default=''), + sa.UniqueConstraint('domain_id', 'name', 'type', + name='unique_recordset'), + sa.ForeignKeyConstraint(['domain_id'], ['domains.id'], + ondelete='CASCADE'), + sa.Index('rrset_type_domainid', 'type', 'domain_id'), + sa.Index('recordset_type_name', 'type', 'name'), + sa.Index('reverse_name_dom_id', 'reverse_name', 'domain_id'), + sa.Index('recordset_created_at', 'created_at')) + + op.create_table( + 'records', metadata, + sa.Column('id', UUID, primary_key=True), + sa.Column('created_at', sa.DateTime), + sa.Column('updated_at', sa.DateTime), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('data', sa.Text, nullable=False), + sa.Column('domain_id', UUID, nullable=False), + sa.Column('managed', sa.Boolean, default=False), + sa.Column('managed_resource_type', sa.Unicode(50), default=None, + nullable=True), + sa.Column('managed_resource_id', UUID, default=None, nullable=True), + sa.Column('managed_plugin_type', sa.Unicode(50), default=None, + nullable=True), + sa.Column('managed_plugin_name', sa.Unicode(50), default=None, + nullable=True), + sa.Column('hash', sa.String(32), nullable=False), + sa.Column('description', sa.Unicode(160), nullable=True), + sa.Column('status', sa.Enum(name='record_resource_statuses', + *RESOURCE_STATUSES), + server_default='PENDING', default='PENDING', nullable=False), + sa.Column('tenant_id', sa.String(36), default=None, nullable=True), + sa.Column('recordset_id', UUID, nullable=False), + sa.Column('managed_tenant_id', sa.Unicode(36), default=None, + nullable=True), + sa.Column('managed_resource_region', sa.Unicode(100), default=None, + nullable=True), + sa.Column('managed_extra', sa.Unicode(100), default=None, + nullable=True), + sa.Column('action', sa.Enum(name='record_actions', *ACTIONS), + default='CREATE', server_default='CREATE', nullable=False), + sa.Column('serial', sa.Integer, server_default='1', nullable=False), + sa.Column('domain_shard', sa.SmallInteger, nullable=False), + sa.UniqueConstraint('hash', name='unique_record'), + sa.ForeignKeyConstraint(['domain_id'], ['domains.id'], + ondelete='CASCADE'), + sa.ForeignKeyConstraint(['recordset_id'], ['recordsets.id'], + ondelete='CASCADE'), + sa.ForeignKeyConstraint(['domain_id'], ['domains.id'], + ondelete='CASCADE', + name='fkey_records_domain_id'), + sa.ForeignKeyConstraint(['recordset_id'], ['recordsets.id'], + ondelete='CASCADE', + name='fkey_records_recordset_id'), + sa.Index('records_tenant', 'tenant_id'), + sa.Index('record_created_at', 'created_at'), + sa.Index('update_status_index', 'status', 'domain_id', 'tenant_id', + 'created_at', 'serial')) + + op.create_table( + 'quotas', metadata, + sa.Column('id', UUID, primary_key=True), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('created_at', sa.DateTime, + default=lambda: timeutils.utcnow()), + sa.Column('updated_at', sa.DateTime, + onupdate=lambda: timeutils.utcnow()), + sa.Column('tenant_id', sa.String(36), nullable=False), + sa.Column('resource', sa.String(32), nullable=False), + sa.Column('hard_limit', sa.Integer, nullable=False), + sa.UniqueConstraint('tenant_id', 'resource', name='unique_quota')) + + op.create_table( + 'tsigkeys', metadata, + sa.Column('id', UUID, primary_key=True), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('created_at', sa.DateTime), + sa.Column('updated_at', sa.DateTime), + sa.Column('name', sa.String(255), nullable=False), + sa.Column('algorithm', + sa.Enum(name='tsig_algorithms', *TSIG_ALGORITHMS), + nullable=False), + sa.Column('secret', sa.String(255), nullable=False), + sa.Column('scope', sa.Enum(name='tsig_scopes', *TSIG_SCOPES), + nullable=False, server_default='POOL'), + sa.Column('resource_id', UUID, nullable=False), + sa.UniqueConstraint('name', name='unique_tsigkey_name')) + + op.create_table( + 'tlds', metadata, + sa.Column('id', UUID, primary_key=True), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('created_at', sa.DateTime, + default=lambda: timeutils.utcnow()), + sa.Column('updated_at', sa.DateTime, + onupdate=lambda: timeutils.utcnow()), + sa.Column('name', sa.String(255), nullable=False), + sa.Column('description', sa.Unicode(160), nullable=True), + sa.UniqueConstraint('name', name='unique_tld_name')) + + op.create_table( + 'zone_transfer_requests', metadata, + sa.Column('id', UUID, primary_key=True), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('created_at', sa.DateTime), + sa.Column('updated_at', sa.DateTime), + sa.Column('domain_id', UUID, nullable=False), + sa.Column("key", sa.String(255), nullable=False), + sa.Column("description", sa.String(255)), + sa.Column("tenant_id", sa.String(36), default=None, nullable=False), + sa.Column("target_tenant_id", sa.String(36), default=None, + nullable=True), + sa.Column("status", + sa.Enum(name='zone_transfer_requests_resource_statuses', + *TASK_STATUSES), + nullable=False, server_default='ACTIVE', default='ACTIVE'), + sa.ForeignKeyConstraint(['domain_id'], ['domains.id'], + ondelete='CASCADE')) + + op.create_table( + 'zone_transfer_accepts', metadata, + sa.Column('id', UUID, primary_key=True), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('created_at', sa.DateTime), + sa.Column('updated_at', sa.DateTime), + sa.Column('domain_id', UUID, nullable=False), + sa.Column('zone_transfer_request_id', UUID, nullable=False), + sa.Column("tenant_id", sa.String(36), default=None, nullable=False), + sa.Column("status", + sa.Enum(name='zone_transfer_accepts_resource_statuses', + *TASK_STATUSES), + nullable=False, server_default='ACTIVE', default='ACTIVE'), + sa.ForeignKeyConstraint(['domain_id'], ['domains.id'], + ondelete='CASCADE'), + sa.ForeignKeyConstraint(['zone_transfer_request_id'], + ['zone_transfer_requests.id'], + ondelete='CASCADE')) + + op.create_table( + 'zone_tasks', metadata, + sa.Column('id', UUID, primary_key=True), + sa.Column('created_at', sa.DateTime), + sa.Column('updated_at', sa.DateTime), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('tenant_id', sa.String(36), default=None, nullable=True), + sa.Column('domain_id', UUID, nullable=True), + sa.Column('task_type', sa.Enum(name='task_types', *ZONE_TASK_TYPES), + nullable=True), + sa.Column('message', sa.String(160), nullable=True), + sa.Column('status', sa.Enum(name='zone_tasks_resource_statuses', + *TASK_STATUSES), + nullable=False, server_default='ACTIVE', default='ACTIVE'), + sa.Column('location', sa.String(160), nullable=True)) + + op.create_table( + 'blacklists', metadata, + sa.Column('id', UUID, primary_key=True), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('updated_at', sa.DateTime), + sa.Column('created_at', sa.DateTime), + sa.Column('pattern', sa.String(255), nullable=False), + sa.Column('description', sa.Unicode(160), nullable=True), + sa.UniqueConstraint('pattern', name='pattern')) diff --git a/designate/storage/impl_sqlalchemy/alembic/versions/d04819112169_new_pools_tables.py b/designate/storage/impl_sqlalchemy/alembic/versions/d04819112169_new_pools_tables.py new file mode 100644 index 00000000..d321fb51 --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/versions/d04819112169_new_pools_tables.py @@ -0,0 +1,121 @@ +# Copyright 2015 Hewlett-Packard Development Company, L.P. +# Copyright 2022 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""new_pools_tables + +Revision ID: d04819112169 +Revises: 0bcf910ea823 +Create Date: 2022-08-01 16:20:17.440784 + +""" +from alembic import op +from oslo_utils import timeutils +import sqlalchemy as sa + +from designate.sqlalchemy.types import UUID +from designate.storage.impl_sqlalchemy.alembic import legacy_utils +from designate import utils + +# revision identifiers, used by Alembic. +revision = 'd04819112169' +down_revision = '0bcf910ea823' +branch_labels = None +depends_on = None + +# Equivalent to legacy sqlalchemy-migrate revision 086_new_pools_tables + + +def upgrade() -> None: + # Check if the equivalent legacy migration has already run + if not legacy_utils.is_migration_needed(86): + return + + metadata = sa.MetaData() + + op.create_table( + 'pool_nameservers', metadata, + sa.Column('id', UUID, default=utils.generate_uuid, primary_key=True), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('created_at', sa.DateTime, + default=lambda: timeutils.utcnow()), + sa.Column('updated_at', sa.DateTime, + onupdate=lambda: timeutils.utcnow()), + sa.Column('pool_id', UUID, nullable=False), + sa.Column('host', sa.String(255), nullable=False), + sa.Column('port', sa.Integer, nullable=False), + sa.ForeignKeyConstraint(['pool_id'], ['pools.id'], ondelete='CASCADE'), + sa.UniqueConstraint('pool_id', 'host', 'port', + name='unique_pool_host_port')) + + op.create_table( + 'pool_targets', metadata, + sa.Column('id', UUID, default=utils.generate_uuid, primary_key=True), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('created_at', sa.DateTime, + default=lambda: timeutils.utcnow()), + sa.Column('updated_at', sa.DateTime, + onupdate=lambda: timeutils.utcnow()), + sa.Column('pool_id', UUID, nullable=False), + sa.Column('type', sa.String(50), nullable=False), + sa.Column('tsigkey_id', UUID, nullable=True), + sa.Column('description', sa.Unicode(160), nullable=True), + sa.ForeignKeyConstraint(['pool_id'], ['pools.id'], ondelete='CASCADE')) + + op.create_table( + 'pool_target_masters', metadata, + sa.Column('id', UUID, default=utils.generate_uuid, primary_key=True), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('created_at', sa.DateTime, + default=lambda: timeutils.utcnow()), + sa.Column('updated_at', sa.DateTime, + onupdate=lambda: timeutils.utcnow()), + sa.Column('pool_target_id', UUID, nullable=False), + sa.Column('host', sa.String(255), nullable=False), + sa.Column('port', sa.Integer, nullable=False), + sa.ForeignKeyConstraint(['pool_target_id'], ['pool_targets.id'], + ondelete='CASCADE'), + sa.UniqueConstraint('pool_target_id', 'host', 'port', + name='unique_pool_target_host_port')) + + op.create_table( + 'pool_target_options', metadata, + sa.Column('id', UUID, default=utils.generate_uuid, primary_key=True), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('created_at', sa.DateTime, + default=lambda: timeutils.utcnow()), + sa.Column('updated_at', sa.DateTime, + onupdate=lambda: timeutils.utcnow()), + sa.Column('pool_target_id', UUID, nullable=False), + sa.Column('key', sa.String(255), nullable=False), + sa.Column('value', sa.String(255), nullable=False), + sa.ForeignKeyConstraint(['pool_target_id'], ['pool_targets.id'], + ondelete='CASCADE'), + sa.UniqueConstraint('pool_target_id', 'key', + name='unique_pool_target_key')) + + op.create_table( + 'pool_also_notifies', metadata, + sa.Column('id', UUID, default=utils.generate_uuid, primary_key=True), + sa.Column('version', sa.Integer, default=1, nullable=False), + sa.Column('created_at', sa.DateTime, + default=lambda: timeutils.utcnow()), + sa.Column('updated_at', sa.DateTime, + onupdate=lambda: timeutils.utcnow()), + sa.Column('pool_id', UUID, nullable=False), + sa.Column('host', sa.String(255), nullable=False), + sa.Column('port', sa.Integer, nullable=False), + sa.ForeignKeyConstraint(['pool_id'], ['pools.id'], ondelete='CASCADE'), + sa.UniqueConstraint('pool_id', 'host', 'port', + name='unique_pool_also_notifies_pool0host0port')) diff --git a/designate/storage/impl_sqlalchemy/alembic/versions/d9a1883e93e9_add_fks.py b/designate/storage/impl_sqlalchemy/alembic/versions/d9a1883e93e9_add_fks.py new file mode 100644 index 00000000..81d4a557 --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/versions/d9a1883e93e9_add_fks.py @@ -0,0 +1,64 @@ +# Copyright 2015 Hewlett-Packard Development Company, L.P. +# Copyright 2022 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""add_FKs + +Revision ID: d9a1883e93e9 +Revises: 867a331ce1fc +Create Date: 2022-07-29 20:41:51.855014 + +""" +from alembic import op + +from designate.storage.impl_sqlalchemy.alembic import legacy_utils + +# revision identifiers, used by Alembic. +revision = 'd9a1883e93e9' +down_revision = '867a331ce1fc' +branch_labels = None +depends_on = None + +# Equivalent to legacy sqlalchemy-migrate revision 081_add_FKs + + +def upgrade() -> None: + # Check if the equivalent legacy migration has already run + if not legacy_utils.is_migration_needed(81): + return + + # We must use batch mode because the unit tests use sqlite + with op.batch_alter_table('zones') as batch_op: + batch_op.create_foreign_key('fk_zones_id_parent_zone_id', 'zones', + ['parent_zone_id'], ['id'], + ondelete='SET NULL') + with op.batch_alter_table('zone_attributes') as batch_op: + batch_op.create_foreign_key('fk_zone_attributes_zones_id_zone_id', + 'zones', ['zone_id'], ['id'], + ondelete='CASCADE') + with op.batch_alter_table('recordsets') as batch_op: + batch_op.create_foreign_key('fk_recordsets_zones_id_zone_id', 'zones', + ['zone_id'], ['id'], ondelete='CASCADE') + with op.batch_alter_table('records') as batch_op: + batch_op.create_foreign_key('fk_records_zones_id_zone_id', 'zones', + ['zone_id'], ['id'], ondelete='CASCADE') + with op.batch_alter_table('zone_transfer_requests') as batch_op: + batch_op.create_foreign_key('fk_ztr_zones_id_zone_id', 'zones', + ['zone_id'], ['id'], ondelete='CASCADE') + with op.batch_alter_table('zone_transfer_accepts') as batch_op: + batch_op.create_foreign_key('fk_zta_zones_id_zone_id', 'zones', + ['zone_id'], ['id'], ondelete='CASCADE') + with op.batch_alter_table('zone_tasks') as batch_op: + batch_op.create_foreign_key('fk_zone_tasks_zones_id_zone_id', 'zones', + ['zone_id'], ['id'], ondelete='CASCADE') diff --git a/designate/storage/impl_sqlalchemy/alembic/versions/e5e2199ed76e_support_cert_records.py b/designate/storage/impl_sqlalchemy/alembic/versions/e5e2199ed76e_support_cert_records.py new file mode 100644 index 00000000..f759ef6c --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/versions/e5e2199ed76e_support_cert_records.py @@ -0,0 +1,48 @@ +# Copyright 2021 Cloudification GmbH +# Copyright 2022 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""support_cert_records + +Revision ID: e5e2199ed76e +Revises: 91eb1eb7c882 +Create Date: 2022-08-01 17:34:45.569101 + +""" +from alembic import op +import sqlalchemy as sa + +from designate.storage.impl_sqlalchemy.alembic import legacy_utils + +# revision identifiers, used by Alembic. +revision = 'e5e2199ed76e' +down_revision = '91eb1eb7c882' +branch_labels = None +depends_on = None + +# Equivalent to legacy sqlalchemy-migrate revision 103_support_cert_records + + +def upgrade() -> None: + # Check if the equivalent legacy migration has already run + if not legacy_utils.is_migration_needed(103): + return + + RECORD_TYPES = ['A', 'AAAA', 'CNAME', 'MX', 'SRV', 'TXT', 'SPF', 'NS', + 'PTR', 'SSHFP', 'SOA', 'NAPTR', 'CAA', 'CERT'] + + with op.batch_alter_table('recordsets') as batch_op: + batch_op.alter_column('type', type_=sa.Enum(name='record_types', + *RECORD_TYPES), + existing_type=sa.Enum, existing_nullable=False) diff --git a/designate/storage/impl_sqlalchemy/alembic/versions/f9f969f9d85e_change_managed_column_types.py b/designate/storage/impl_sqlalchemy/alembic/versions/f9f969f9d85e_change_managed_column_types.py new file mode 100644 index 00000000..3cec4940 --- /dev/null +++ b/designate/storage/impl_sqlalchemy/alembic/versions/f9f969f9d85e_change_managed_column_types.py @@ -0,0 +1,61 @@ +# Copyright 2016 Hewlett Packard Enterprise Development Company LP +# Copyright 2022 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""change_managed_column_types + +Revision ID: f9f969f9d85e +Revises: bfcfc4a07487 +Create Date: 2022-07-29 21:18:35.403634 + +""" +from alembic import op +import sqlalchemy as sa + +from designate.storage.impl_sqlalchemy.alembic import legacy_utils + +# revision identifiers, used by Alembic. +revision = 'f9f969f9d85e' +down_revision = 'bfcfc4a07487' +branch_labels = None +depends_on = None + +# Equivalent to legacy sqlalchemy-migrate revision +# 083_change_managed_column_types + + +def upgrade() -> None: + # Check if the equivalent legacy migration has already run + if not legacy_utils.is_migration_needed(83): + return + + with op.batch_alter_table('records') as batch_op: + batch_op.alter_column('managed_extra', type_=sa.String(100), + existing_type=sa.Unicode(100), + existing_nullable=True) + batch_op.alter_column('managed_plugin_type', type_=sa.String(50), + existing_type=sa.Unicode(50), + existing_nullable=True) + batch_op.alter_column('managed_plugin_name', type_=sa.String(50), + existing_type=sa.Unicode(50), + existing_nullable=True) + batch_op.alter_column('managed_resource_type', type_=sa.String(50), + existing_type=sa.Unicode(50), + existing_nullable=True) + batch_op.alter_column('managed_resource_region', type_=sa.String(100), + existing_type=sa.Unicode(100), + existing_nullable=True) + batch_op.alter_column('managed_tenant_id', type_=sa.String(36), + existing_type=sa.Unicode(36), + existing_nullable=True) |