summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Johnson <johnsomor@gmail.com>2022-07-29 23:05:51 +0000
committerMichael Johnson <johnsomor@gmail.com>2022-08-04 17:15:09 +0000
commit60c378763aa37246762ff210f024e2af019f6397 (patch)
tree276580f9a47b624f51327aa49f2b1bb1ac07cd58
parentd58514ec84328a495cf85f6b4d6b521b20898f61 (diff)
downloaddesignate-60c378763aa37246762ff210f024e2af019f6397.tar.gz
Switch Designate to Alembic database migrations
Currently Designate is using sqlalchemy-migrate for database schema migrations. sqlalchemy-migrate/migrate have been deprecated for some time. This patch moves switches Designate to use Alembic for database migrations. Change-Id: I90ecb4d409b8b609b384997fa4cc9c65755409b3
-rw-r--r--designate/manage/database.py79
-rw-r--r--designate/storage/impl_sqlalchemy/alembic.ini105
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/README5
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/env.py83
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/legacy_utils.py43
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/script.py.mako (renamed from designate/storage/impl_sqlalchemy/migrate_repo/manage.py)29
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/versions/0bcf910ea823_add_zone_attributes.py95
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/versions/15b34ff3ecb8_fix_service_charset.py48
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/versions/304d41c3847a_add_services.py59
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/versions/7977deaa5167_add_rrset_indexes_for_filtering_perf.py46
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/versions/867a331ce1fc_domain_to_zone_rename.py149
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/versions/91eb1eb7c882_support_caa_records.py48
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/versions/93a00a815f07_unique_service_status.py60
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/versions/a69b45715cc1_add_delayed_notify_column.py45
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/versions/b8999fd10721_support_naptr_records.py48
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/versions/bfcfc4a07487_unique_ns_record.py65
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/versions/c9f427f7180a_liberty.py340
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/versions/d04819112169_new_pools_tables.py121
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/versions/d9a1883e93e9_add_fks.py64
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/versions/e5e2199ed76e_support_cert_records.py48
-rw-r--r--designate/storage/impl_sqlalchemy/alembic/versions/f9f969f9d85e_change_managed_column_types.py61
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/README4
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/migrate.cfg25
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/utils.py44
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/070_liberty.py400
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/071_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/072_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/073_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/074_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/075_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/076_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/077_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/078_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/079_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/080_domain_to_zone_rename.py119
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/081_add_FKs.py62
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/082_unique_ns_record.py62
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/083_change_managed_column_types.py39
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/084_add_delayed_notify_column.py35
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/085_add_zone_attributes.py97
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/086_new_pools_tables.py127
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/087_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/088_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/089_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/090_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/091_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/092_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/093_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/094_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/095_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/096_placeholder.py26
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/097_add_services.py53
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/098_fix_service_charset.py34
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/099_add_rrset_indexes_for_filtering_perf.py36
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/100_unique_service_status.py47
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/101_support_naptr_records.py29
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/102_support_caa_records.py29
-rw-r--r--designate/storage/impl_sqlalchemy/migrate_repo/versions/103_support_cert_records.py29
-rw-r--r--designate/tests/__init__.py10
-rw-r--r--designate/tests/fixtures.py20
-rw-r--r--designate/tests/test_manage/test_database.py62
-rw-r--r--designate/tests/test_storage/test_sqlalchemy.py27
-rw-r--r--designate/tests/unit/storage/__init__.py (renamed from designate/storage/impl_sqlalchemy/migrate_repo/__init__.py)0
-rw-r--r--designate/tests/unit/storage/impl_sqlalchemy/__init__.py (renamed from designate/storage/impl_sqlalchemy/migrate_repo/versions/__init__.py)0
-rw-r--r--designate/tests/unit/storage/impl_sqlalchemy/alembic/__init__.py0
-rw-r--r--designate/tests/unit/storage/impl_sqlalchemy/alembic/test_legacy_utils.py56
-rw-r--r--designate/tests/unit/test_upgrade_checks.py25
-rw-r--r--releasenotes/notes/Switch-to-alembic-migrations-15b7701f4e8b37c1.yaml7
-rw-r--r--requirements.txt2
69 files changed, 1777 insertions, 1838 deletions
diff --git a/designate/manage/database.py b/designate/manage/database.py
index 72108abb..c86946f1 100644
--- a/designate/manage/database.py
+++ b/designate/manage/database.py
@@ -13,41 +13,76 @@
# 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 io import StringIO
import os
+import sys
-from migrate.versioning import api as versioning_api
+from alembic import command as alembic_command
+from alembic.config import Config
from oslo_config import cfg
from oslo_log import log as logging
from designate.manage import base
-from designate.sqlalchemy import utils
-
+CONF = cfg.CONF
LOG = logging.getLogger(__name__)
-REPOSITORY = os.path.abspath(os.path.join(os.path.dirname(__file__), '..',
- 'storage', 'impl_sqlalchemy',
- 'migrate_repo'))
-cfg.CONF.import_opt('connection', 'designate.storage.impl_sqlalchemy',
- group='storage:sqlalchemy')
-CONF = cfg.CONF
-INIT_VERSION = 69
+class DatabaseCommands(base.Commands):
+ def _get_alembic_config(self, db_url=None, stringio_buffer=sys.stdout):
+ alembic_dir = os.path.join(os.path.dirname(__file__),
+ os.pardir, 'storage/impl_sqlalchemy')
+ alembic_cfg = Config(os.path.join(alembic_dir, 'alembic.ini'),
+ stdout=stringio_buffer)
+ alembic_cfg.set_main_option(
+ 'script_location', 'designate.storage.impl_sqlalchemy:alembic')
+ if db_url:
+ alembic_cfg.set_main_option('sqlalchemy.url', db_url)
+ else:
+ alembic_cfg.set_main_option('sqlalchemy.url',
+ CONF['storage:sqlalchemy'].connection)
+ return alembic_cfg
-def get_manager():
- return utils.get_migration_manager(
- REPOSITORY, CONF['storage:sqlalchemy'].connection, INIT_VERSION)
+ def current(self, db_url=None, stringio_buffer=sys.stdout):
+ alembic_command.current(
+ self._get_alembic_config(db_url=db_url,
+ stringio_buffer=stringio_buffer))
+ def heads(self, db_url=None, stringio_buffer=sys.stdout):
+ alembic_command.heads(
+ self._get_alembic_config(db_url=db_url,
+ stringio_buffer=stringio_buffer))
-class DatabaseCommands(base.Commands):
- def version(self):
- current = get_manager().version()
- latest = versioning_api.version(repository=REPOSITORY).value
+ def history(self, db_url=None, stringio_buffer=sys.stdout):
+ alembic_command.history(
+ self._get_alembic_config(db_url=db_url,
+ stringio_buffer=stringio_buffer))
+
+ def version(self, db_url=None):
+ # Using StringIO buffers here to keep the command output as similar
+ # as it was before the migration to alembic.
+ current_buffer = StringIO()
+ latest_buffer = StringIO()
+ alembic_command.current(
+ self._get_alembic_config(db_url=db_url,
+ stringio_buffer=current_buffer))
+ current = current_buffer.getvalue().replace('\n', ' ')
+ current_buffer.close()
+ alembic_command.heads(
+ self._get_alembic_config(db_url=db_url,
+ stringio_buffer=latest_buffer))
+ latest = latest_buffer.getvalue().replace('\n', ' ')
+ latest_buffer.close()
print("Current: %s Latest: %s" % (current, latest))
- def sync(self):
- get_manager().upgrade(None)
+ def sync(self, db_url=None, stringio_buffer=sys.stdout):
+ alembic_command.upgrade(
+ self._get_alembic_config(db_url=db_url,
+ stringio_buffer=stringio_buffer), 'head')
- @base.args('revision', nargs='?')
- def upgrade(self, revision):
- get_manager().upgrade(revision)
+ @base.args('revision', default='head', nargs='?',
+ help='The revision identifier to upgrade to.')
+ def upgrade(self, revision, db_url=None, stringio_buffer=sys.stdout):
+ alembic_command.upgrade(
+ self._get_alembic_config(
+ db_url=db_url, stringio_buffer=stringio_buffer), revision)
diff --git a/designate/storage/impl_sqlalchemy/alembic.ini b/designate/storage/impl_sqlalchemy/alembic.ini
new file mode 100644
index 00000000..4cf877d2
--- /dev/null
+++ b/designate/storage/impl_sqlalchemy/alembic.ini
@@ -0,0 +1,105 @@
+# A generic, single database configuration.
+
+[alembic]
+# path to migration scripts
+script_location = alembic
+
+# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
+# Uncomment the line below if you want the files to be prepended with date and time
+# see https://alembic.sqlalchemy.org/en/latest/tutorial.html#editing-the-ini-file
+# for all available tokens
+# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s
+
+# sys.path path, will be prepended to sys.path if present.
+# defaults to the current working directory.
+prepend_sys_path = .
+
+# timezone to use when rendering the date within the migration file
+# as well as the filename.
+# If specified, requires the python-dateutil library that can be
+# installed by adding `alembic[tz]` to the pip requirements
+# string value is passed to dateutil.tz.gettz()
+# leave blank for localtime
+# timezone =
+
+# max length of characters to apply to the
+# "slug" field
+# truncate_slug_length = 40
+
+# set to 'true' to run the environment during
+# the 'revision' command, regardless of autogenerate
+# revision_environment = false
+
+# set to 'true' to allow .pyc and .pyo files without
+# a source .py file to be detected as revisions in the
+# versions/ directory
+# sourceless = false
+
+# version location specification; This defaults
+# to alembic/versions. When using multiple version
+# directories, initial revisions must be specified with --version-path.
+# The path separator used here should be the separator specified by "version_path_separator" below.
+# version_locations = %(here)s/bar:%(here)s/bat:alembic/versions
+
+# version path separator; As mentioned above, this is the character used to split
+# version_locations. The default within new alembic.ini files is "os", which uses os.pathsep.
+# If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas.
+# Valid values for version_path_separator are:
+#
+# version_path_separator = :
+# version_path_separator = ;
+# version_path_separator = space
+version_path_separator = os # Use os.pathsep. Default configuration used for new projects.
+
+# the output encoding used when revision files
+# are written from script.py.mako
+# output_encoding = utf-8
+
+sqlalchemy.url =
+
+
+[post_write_hooks]
+# post_write_hooks defines scripts or Python functions that are run
+# on newly generated revision scripts. See the documentation for further
+# detail and examples
+
+# format using "black" - use the console_scripts runner, against the "black" entrypoint
+# hooks = black
+# black.type = console_scripts
+# black.entrypoint = black
+# black.options = -l 79 REVISION_SCRIPT_FILENAME
+
+# Logging configuration
+[loggers]
+keys = root,sqlalchemy,alembic
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = WARN
+handlers = console
+qualname =
+
+[logger_sqlalchemy]
+level = WARN
+handlers =
+qualname = sqlalchemy.engine
+
+[logger_alembic]
+level = INFO
+handlers =
+qualname = alembic
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(levelname)-5.5s [%(name)s] %(message)s
+datefmt = %H:%M:%S
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/migrate_repo/manage.py b/designate/storage/impl_sqlalchemy/alembic/script.py.mako
index 658a0ba1..8fd7d546 100644
--- a/designate/storage/impl_sqlalchemy/migrate_repo/manage.py
+++ b/designate/storage/impl_sqlalchemy/alembic/script.py.mako
@@ -1,10 +1,3 @@
-#!/usr/bin/env python
-
-# Copyright 2012 Hewlett-Packard Development Company, L.P.
-# All Rights Reserved.
-#
-# Author: Patrick Galbraith <patg@hp.com>
-#
# 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
@@ -17,7 +10,23 @@
# License for the specific language governing permissions and limitations
# under the License.
-from migrate.versioning.shell import main
+"""${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)}
+
-if __name__ == '__main__':
- main(debug='False')
+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)
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/README b/designate/storage/impl_sqlalchemy/migrate_repo/README
deleted file mode 100644
index 2f979fcb..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/README
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a database migration repository for the project Designate.
-
-More information at
-http://code.google.com/p/sqlalchemy-migrate/
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/migrate.cfg b/designate/storage/impl_sqlalchemy/migrate_repo/migrate.cfg
deleted file mode 100644
index 98d4dff3..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/migrate.cfg
+++ /dev/null
@@ -1,25 +0,0 @@
-[db_settings]
-# Used to identify which repository this database is versioned under.
-# You can use the name of your project.
-repository_id=Designate
-
-# The name of the database table used to track the schema version.
-# This name shouldn't already be used by your project.
-# If this is changed once a database is under version control, you'll need to
-# change the table name in each database too.
-version_table=migrate_version
-
-# When committing a change script, Migrate will attempt to generate the
-# sql for all supported databases; normally, if one of them fails - probably
-# because you don't have that database installed - it is ignored and the
-# commit continues, perhaps ending successfully.
-# Databases in this list MUST compile successfully during a commit, or the
-# entire commit will fail. List the databases your application will actually
-# be using to ensure your updates to that database work properly.
-# This must be a list; example: ['postgres','sqlite']
-required_dbs=[]
-
-# When creating new change scripts, Migrate will stamp the new script with
-# a version number. By default this is latest_version + 1. You can set this
-# to 'true' to tell Migrate to use the UTC timestamp instead.
-use_timestamp_numbering=False
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/utils.py b/designate/storage/impl_sqlalchemy/migrate_repo/utils.py
deleted file mode 100644
index fd94e151..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/utils.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2012 Hewlett-Packard Development Company, L.P.
-# All Rights Reserved.
-#
-# Author: Patrick Galbraith <patg@hp.com>
-#
-# 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.
-
-"""
-Various conveniences used for migration scripts
-"""
-from oslo_log import log as logging
-from sqlalchemy.schema import Table as SqlaTable
-
-
-LOG = logging.getLogger(__name__)
-
-
-def create_tables(tables):
- for table in tables:
- LOG.debug("Creating table %s", table)
- table.create()
-
-
-def drop_tables(tables):
- for table in tables:
- LOG.debug("Dropping table %s", table)
- table.drop()
-
-
-def Table(*args, **kwargs):
- if 'mysql_engine' not in kwargs:
- kwargs['mysql_engine'] = 'INNODB'
-
- return SqlaTable(*args, **kwargs)
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/070_liberty.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/070_liberty.py
deleted file mode 100644
index f9e95518..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/070_liberty.py
+++ /dev/null
@@ -1,400 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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 sqlalchemy import (Table, MetaData, Column, String, Text, Integer,
- SmallInteger, CHAR, DateTime, Enum, Boolean, Unicode,
- UniqueConstraint, ForeignKeyConstraint, Index)
-
-from oslo_config import cfg
-from oslo_utils import timeutils
-
-from designate.conf import central
-from designate.sqlalchemy.types import UUID
-
-
-CONF = cfg.CONF
-central.register_opts(CONF)
-
-RESOURCE_STATUSES = ['ACTIVE', 'PENDING', 'DELETED', 'ERROR']
-RECORD_TYPES = ['A', 'AAAA', 'CNAME', 'MX', 'SRV', 'TXT', 'SPF', 'NS', 'PTR',
- 'SSHFP', 'SOA']
-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']
-POOL_PROVISIONERS = ['UNMANAGED']
-ACTIONS = ['CREATE', 'DELETE', 'UPDATE', 'NONE']
-
-ZONE_ATTRIBUTE_KEYS = ('master',)
-
-ZONE_TYPES = ('PRIMARY', 'SECONDARY',)
-ZONE_TASK_TYPES = ['IMPORT', 'EXPORT']
-
-
-metadata = MetaData()
-
-quotas = Table('quotas', metadata,
- Column('id', UUID, primary_key=True),
- Column('version', Integer(), default=1, nullable=False),
- Column('created_at', DateTime, default=lambda: timeutils.utcnow()),
- Column('updated_at', DateTime, onupdate=lambda: timeutils.utcnow()),
-
- Column('tenant_id', String(36), nullable=False),
- Column('resource', String(32), nullable=False),
- Column('hard_limit', Integer(), nullable=False),
-
- UniqueConstraint('tenant_id', 'resource', name='unique_quota'),
-
- mysql_engine='InnoDB',
- mysql_charset='utf8',
-)
-
-tlds = Table('tlds', metadata,
- Column('id', UUID, primary_key=True),
- Column('version', Integer(), default=1, nullable=False),
- Column('created_at', DateTime, default=lambda: timeutils.utcnow()),
- Column('updated_at', DateTime, onupdate=lambda: timeutils.utcnow()),
-
- Column('name', String(255), nullable=False),
- Column('description', Unicode(160), nullable=True),
-
- UniqueConstraint('name', name='unique_tld_name'),
-
- mysql_engine='InnoDB',
- mysql_charset='utf8',
-)
-
-domains = Table('domains', metadata,
- Column('id', UUID, primary_key=True),
- Column('created_at', DateTime),
- Column('updated_at', DateTime),
- Column('version', Integer(), nullable=False),
- Column('tenant_id', String(36), default=None, nullable=True),
- Column('name', String(255), nullable=False),
- Column('email', String(255), nullable=False),
- Column('ttl', Integer, default=CONF.default_ttl, nullable=False),
- Column('refresh', Integer, nullable=False),
- Column('retry', Integer, nullable=False),
- Column('expire', Integer, nullable=False),
- Column('minimum', Integer, nullable=False),
- Column('parent_domain_id', UUID, default=None, nullable=True),
- Column('serial', Integer, nullable=False, server_default='1'),
- Column('deleted', CHAR(32), nullable=False, default='0',
- server_default='0'),
- Column('deleted_at', DateTime, nullable=True, default=None),
- Column('description', Unicode(160), nullable=True),
- Column('status', Enum(name='domains_resource_statuses',
- *RESOURCE_STATUSES),
- nullable=False, server_default='PENDING', default='PENDING'),
- Column('action', Enum(name='domain_actions', *ACTIONS),
- default='CREATE', server_default='CREATE', nullable=False),
- Column('pool_id', UUID, default=None, nullable=True),
- Column('reverse_name', String(255), nullable=False, server_default=''),
- Column("type", Enum(name='type', *ZONE_TYPES),
- server_default='PRIMARY', default='PRIMARY'),
- Column('transferred_at', DateTime, default=None),
- Column('shard', SmallInteger(), nullable=False),
-
- UniqueConstraint('name', 'deleted', 'pool_id', name='unique_domain_name'),
- ForeignKeyConstraint(['parent_domain_id'],
- ['domains.id'],
- ondelete='SET NULL'),
-
- Index('zone_deleted', 'deleted'),
- Index('zone_tenant_deleted', 'tenant_id', 'deleted'),
- Index('reverse_name_deleted', 'reverse_name', 'deleted'),
- Index('zone_created_at', 'created_at'),
-
- mysql_engine='InnoDB',
- mysql_charset='utf8',
-)
-
-domain_attributes = Table('domain_attributes', metadata,
- Column('id', UUID(), primary_key=True),
- Column('version', Integer(), default=1, nullable=False),
- Column('created_at', DateTime),
- Column('updated_at', DateTime),
-
- Column('key', Enum(name='key', *ZONE_ATTRIBUTE_KEYS)),
- Column('value', String(255), nullable=False),
- Column('domain_id', UUID(), nullable=False),
-
- UniqueConstraint('key', 'value', 'domain_id', name='unique_attributes'),
- ForeignKeyConstraint(['domain_id'], ['domains.id'], ondelete='CASCADE'),
-
- mysql_engine='INNODB',
- mysql_charset='utf8'
-)
-
-recordsets = Table('recordsets', metadata,
- Column('id', UUID, primary_key=True),
- Column('version', Integer(), default=1, nullable=False),
- Column('created_at', DateTime),
- Column('updated_at', DateTime),
- Column('domain_shard', SmallInteger(), nullable=False),
-
- Column('tenant_id', String(36), default=None, nullable=True),
- Column('domain_id', UUID, nullable=False),
- Column('name', String(255), nullable=False),
- Column('type', Enum(name='record_types', *RECORD_TYPES), nullable=False),
- Column('ttl', Integer, default=None, nullable=True),
- Column('description', Unicode(160), nullable=True),
- Column('reverse_name', String(255), nullable=False, server_default=''),
-
- UniqueConstraint('domain_id', 'name', 'type', name='unique_recordset'),
- ForeignKeyConstraint(['domain_id'], ['domains.id'], ondelete='CASCADE'),
-
- Index('rrset_type_domainid', 'type', 'domain_id'),
- Index('recordset_type_name', 'type', 'name'),
- Index('reverse_name_dom_id', 'reverse_name', 'domain_id'),
- Index('recordset_created_at', 'created_at'),
-
- mysql_engine='InnoDB',
- mysql_charset='utf8',
-)
-
-records = Table('records', metadata,
- Column('id', UUID, primary_key=True),
- Column('created_at', DateTime),
- Column('updated_at', DateTime),
- Column('version', Integer(), default=1, nullable=False),
- Column('data', Text, nullable=False),
- Column('domain_id', UUID, nullable=False),
- Column('managed', Boolean, default=False),
- Column('managed_resource_type', Unicode(50), default=None, nullable=True),
- Column('managed_resource_id', UUID, default=None, nullable=True),
- Column('managed_plugin_type', Unicode(50), default=None, nullable=True),
- Column('managed_plugin_name', Unicode(50), default=None, nullable=True),
- Column('hash', String(32), nullable=False),
- Column('description', Unicode(160), nullable=True),
- Column('status', Enum(name='record_resource_statuses', *RESOURCE_STATUSES),
- server_default='PENDING', default='PENDING', nullable=False),
- Column('tenant_id', String(36), default=None, nullable=True),
- Column('recordset_id', UUID, nullable=False),
- Column('managed_tenant_id', Unicode(36), default=None, nullable=True),
- Column('managed_resource_region', Unicode(100), default=None,
- nullable=True),
- Column('managed_extra', Unicode(100), default=None, nullable=True),
- Column('action', Enum(name='record_actions', *ACTIONS),
- default='CREATE', server_default='CREATE', nullable=False),
- Column('serial', Integer(), server_default='1', nullable=False),
- Column('domain_shard', SmallInteger(), nullable=False),
-
- UniqueConstraint('hash', name='unique_record'),
- ForeignKeyConstraint(['domain_id'], ['domains.id'], ondelete='CASCADE'),
- ForeignKeyConstraint(['recordset_id'], ['recordsets.id'],
- ondelete='CASCADE'),
- ForeignKeyConstraint(['domain_id'], ['domains.id'], ondelete='CASCADE',
- name='fkey_records_domain_id'),
- ForeignKeyConstraint(['recordset_id'], ['recordsets.id'],
- ondelete='CASCADE', name='fkey_records_recordset_id'),
- Index('records_tenant', 'tenant_id'),
- Index('record_created_at', 'created_at'),
- Index('update_status_index', 'status', 'domain_id', 'tenant_id',
- 'created_at', 'serial'),
-
- mysql_engine='InnoDB',
- mysql_charset='utf8',
-)
-
-tsigkeys = Table('tsigkeys', metadata,
- Column('id', UUID, primary_key=True),
- Column('version', Integer(), default=1, nullable=False),
- Column('created_at', DateTime),
- Column('updated_at', DateTime),
-
- Column('name', String(255), nullable=False),
- Column('algorithm', Enum(name='tsig_algorithms', *TSIG_ALGORITHMS),
- nullable=False),
- Column('secret', String(255), nullable=False),
- Column('scope', Enum(name='tsig_scopes', *TSIG_SCOPES), nullable=False,
- server_default='POOL'),
- Column('resource_id', UUID, nullable=False),
-
- UniqueConstraint('name', name='unique_tsigkey_name'),
-
- mysql_engine='InnoDB',
- mysql_charset='utf8',
-)
-
-blacklists = Table('blacklists', metadata,
- Column('id', UUID, primary_key=True),
- Column('version', Integer(), default=1, nullable=False),
- Column('updated_at', DateTime),
- Column('created_at', DateTime),
-
- Column('pattern', String(255), nullable=False),
- Column('description', Unicode(160), nullable=True),
-
- UniqueConstraint('pattern', name='pattern'),
-
- mysql_engine='InnoDB',
- mysql_charset='utf8',
-)
-
-pools = Table('pools', metadata,
- Column('id', UUID, primary_key=True),
- Column('created_at', DateTime),
- Column('updated_at', DateTime),
- Column('version', Integer(), default=1, nullable=False),
-
- Column('name', String(50), nullable=False),
- Column('description', Unicode(160), nullable=True),
- Column('tenant_id', String(36), nullable=True),
- Column('provisioner', Enum(name='pool_provisioner', *POOL_PROVISIONERS),
- nullable=False, server_default='UNMANAGED'),
-
- UniqueConstraint('name', name='unique_pool_name'),
-
- mysql_engine='INNODB',
- mysql_charset='utf8'
-)
-
-pool_attributes = Table('pool_attributes', metadata,
- Column('id', UUID(), primary_key=True),
- Column('created_at', DateTime),
- Column('updated_at', DateTime),
- Column('version', Integer(), default=1, nullable=False),
-
- Column('key', String(255), nullable=False),
- Column('value', String(255), nullable=False),
- Column('pool_id', UUID(), nullable=False),
-
- UniqueConstraint('pool_id', 'key', 'value', name='unique_pool_attribute'),
-
- ForeignKeyConstraint(['pool_id'], ['pools.id'], ondelete='CASCADE'),
-
- mysql_engine='INNODB',
- mysql_charset='utf8'
-)
-
-pool_ns_records = Table('pool_ns_records', metadata,
- Column('id', UUID(), primary_key=True),
- Column('created_at', DateTime),
- Column('updated_at', DateTime),
- Column('version', Integer(), default=1, nullable=False),
-
- Column('pool_id', UUID(), nullable=False),
- Column('priority', Integer(), nullable=False),
- Column('hostname', String(255), nullable=False),
-
- ForeignKeyConstraint(['pool_id'], ['pools.id'], ondelete='CASCADE'),
-
- mysql_engine='INNODB',
- mysql_charset='utf8')
-
-zone_transfer_requests = Table('zone_transfer_requests', metadata,
- Column('id', UUID, primary_key=True),
- Column('version', Integer(), default=1, nullable=False),
- Column('created_at', DateTime),
- Column('updated_at', DateTime),
-
- Column('domain_id', UUID, nullable=False),
- Column("key", String(255), nullable=False),
- Column("description", String(255)),
- Column("tenant_id", String(36), default=None, nullable=False),
- Column("target_tenant_id", String(36), default=None, nullable=True),
- Column("status", Enum(name='zone_transfer_requests_resource_statuses',
- *TASK_STATUSES),
- nullable=False, server_default='ACTIVE',
- default='ACTIVE'),
-
- ForeignKeyConstraint(['domain_id'], ['domains.id'], ondelete='CASCADE'),
-
- mysql_engine='InnoDB',
- mysql_charset='utf8',
-)
-
-zone_transfer_accepts = Table('zone_transfer_accepts', metadata,
- Column('id', UUID, primary_key=True),
- Column('version', Integer(), default=1, nullable=False),
- Column('created_at', DateTime),
- Column('updated_at', DateTime),
-
- Column('domain_id', UUID, nullable=False),
- Column('zone_transfer_request_id', UUID, nullable=False),
- Column("tenant_id", String(36), default=None, nullable=False),
- Column("status", Enum(name='zone_transfer_accepts_resource_statuses',
- *TASK_STATUSES),
- nullable=False, server_default='ACTIVE',
- default='ACTIVE'),
-
- ForeignKeyConstraint(['domain_id'], ['domains.id'], ondelete='CASCADE'),
- ForeignKeyConstraint(
- ['zone_transfer_request_id'],
- ['zone_transfer_requests.id'],
- ondelete='CASCADE'),
-
- mysql_engine='InnoDB',
- mysql_charset='utf8',
-)
-
-zone_tasks = Table('zone_tasks', metadata,
- Column('id', UUID(), primary_key=True),
- Column('created_at', DateTime),
- Column('updated_at', DateTime),
- Column('version', Integer(), default=1, nullable=False),
- Column('tenant_id', String(36), default=None, nullable=True),
-
- Column('domain_id', UUID(), nullable=True),
- Column('task_type', Enum(name='task_types', *ZONE_TASK_TYPES),
- nullable=True),
- Column('message', String(160), nullable=True),
- Column('status', Enum(name='zone_tasks_resource_statuses', *TASK_STATUSES),
- nullable=False, server_default='ACTIVE',
- default='ACTIVE'),
- Column('location', String(160), nullable=True),
-
- mysql_engine='INNODB',
- mysql_charset='utf8')
-
-
-def default_shard(context, id_col):
- return int(context.current_parameters[id_col][0:3], 16)
-
-
-def upgrade(migrate_engine):
- metadata.bind = migrate_engine
-
- default_pool_id = CONF['service:central'].default_pool_id
-
- with migrate_engine.begin() as conn:
- if migrate_engine.name == "mysql":
- conn.execute("SET foreign_key_checks = 0;")
-
- pools.create()
- pool_ns_records.create()
- pool_attributes.create()
- domains.create()
- domain_attributes.create()
- recordsets.create()
- records.create()
- quotas.create()
- tsigkeys.create()
- tlds.create()
- zone_transfer_requests.create()
- zone_transfer_accepts.create()
- zone_tasks.create()
- blacklists.create()
-
- pools.insert().execute(
- id=default_pool_id,
- name='default',
- version=1
- )
-
- if migrate_engine.name == "mysql":
- conn.execute("SET foreign_key_checks = 1;")
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/071_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/071_placeholder.py
deleted file mode 100644
index 2eb4c09e..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/071_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Kilo backports.
-# Do not use this number for new Liberty work. New Liberty work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/072_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/072_placeholder.py
deleted file mode 100644
index 2eb4c09e..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/072_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Kilo backports.
-# Do not use this number for new Liberty work. New Liberty work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/073_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/073_placeholder.py
deleted file mode 100644
index 2eb4c09e..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/073_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Kilo backports.
-# Do not use this number for new Liberty work. New Liberty work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/074_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/074_placeholder.py
deleted file mode 100644
index 2eb4c09e..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/074_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Kilo backports.
-# Do not use this number for new Liberty work. New Liberty work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/075_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/075_placeholder.py
deleted file mode 100644
index 2eb4c09e..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/075_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Kilo backports.
-# Do not use this number for new Liberty work. New Liberty work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/076_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/076_placeholder.py
deleted file mode 100644
index 2eb4c09e..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/076_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Kilo backports.
-# Do not use this number for new Liberty work. New Liberty work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/077_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/077_placeholder.py
deleted file mode 100644
index 2eb4c09e..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/077_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Kilo backports.
-# Do not use this number for new Liberty work. New Liberty work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/078_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/078_placeholder.py
deleted file mode 100644
index 2eb4c09e..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/078_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Kilo backports.
-# Do not use this number for new Liberty work. New Liberty work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/079_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/079_placeholder.py
deleted file mode 100644
index 2eb4c09e..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/079_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Kilo backports.
-# Do not use this number for new Liberty work. New Liberty work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/080_domain_to_zone_rename.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/080_domain_to_zone_rename.py
deleted file mode 100644
index caa3861f..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/080_domain_to_zone_rename.py
+++ /dev/null
@@ -1,119 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Graham Hayes <graham.hayes@hpe.com>
-#
-# 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.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-from sqlalchemy.schema import MetaData, Table
-from migrate.changeset.constraint import UniqueConstraint, \
- ForeignKeyConstraint, PathNotFoundError
-
-
-# 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.
-
-meta = MetaData()
-
-
-def drop_foreign_key(fk_def):
-
- table = fk_def[0].table
-
- col = fk_def[0]
- ref_col = fk_def[1]
-
- # Use .copy() to avoid the set changing during the for operation
- for fk in table.foreign_keys.copy():
- # Check if the fk is the one we want
- if fk.column == col and fk.parent == ref_col:
-
- fkc = ForeignKeyConstraint([fk.column], [fk.parent],
- name=fk.constraint.name)
- fkc.drop()
- # 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:
-
- fkc = ForeignKeyConstraint([fk.parent], [fk.column],
- name=fk.constraint.name)
- fkc.drop()
-
-
-def drop_unique_constraint(uc_def):
- uc = UniqueConstraint(*uc_def[2], table=uc_def[0], name=uc_def[1])
- try:
- uc.drop()
- except PathNotFoundError:
- pass
-
-
-def upgrade(migrate_engine):
- meta.bind = migrate_engine
-
- # Get all the tables
- domains_table = Table('domains', meta, autoload=True)
- domain_attrib_table = Table('domain_attributes', meta, autoload=True)
- recordsets_table = Table('recordsets', meta, autoload=True)
- records_table = Table('records', meta, autoload=True)
- ztr_table = Table('zone_transfer_requests', meta, autoload=True)
- zta_table = Table('zone_transfer_accepts', meta, autoload=True)
- zt_table = Table('zone_tasks', meta, 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)
-
- # Change the table structures
-
- # Domains Table changes
- domains_table.c.parent_domain_id.alter(name='parent_zone_id')
- domains_table.rename('zones')
-
- # Domain Attributes
- domain_attrib_table.c.domain_id.alter(name='zone_id')
- domain_attrib_table.rename('zone_attributes')
-
- # Recordsets
- recordsets_table.c.domain_id.alter(name='zone_id')
- recordsets_table.c.domain_shard.alter(name='zone_shard')
-
- # Records
- records_table.c.domain_id.alter(name="zone_id")
- records_table.c.domain_shard.alter(name="zone_shard")
-
- # Zone Transfer Requests
- ztr_table.c.domain_id.alter(name='zone_id')
-
- # Zone Transfer Requests
- zta_table.c.domain_id.alter(name='zone_id')
-
- # Zone Tasks
- zt_table.c.domain_id.alter(name='zone_id')
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/081_add_FKs.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/081_add_FKs.py
deleted file mode 100644
index 07d6213d..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/081_add_FKs.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Graham Hayes <graham.hayes@hpe.com>
-#
-# 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.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-from migrate.changeset.constraint import ForeignKeyConstraint
-from sqlalchemy.schema import MetaData, Table
-
-# This migration adds back the FKs removed in migration 80, as sqlalchemy
-# migrate seems to need to wait to add FKs to renamed tables.
-
-meta = MetaData()
-
-
-def upgrade(migrate_engine):
-
- meta.bind = migrate_engine
-
- # Get all the tables
- zones_table = Table('zones', meta, autoload=True)
- zone_attrib_table = Table('zone_attributes', meta, autoload=True)
- recordsets_table = Table('recordsets', meta, autoload=True)
- records_table = Table('records', meta, autoload=True)
- ztr_table = Table('zone_transfer_requests', meta, autoload=True)
- zta_table = Table('zone_transfer_accepts', meta, autoload=True)
- zt_table = Table('zone_tasks', meta, autoload=True)
-
- # Create new FKs
-
- fks = []
-
- fks.append(ForeignKeyConstraint([zones_table.c.parent_zone_id],
- [zones_table.c.id], ondelete='SET NULL'))
- fks.append(ForeignKeyConstraint([zone_attrib_table.c.zone_id],
- [zones_table.c.id], ondelete='CASCADE'))
- fks.append(ForeignKeyConstraint([recordsets_table.c.zone_id],
- [zones_table.c.id], ondelete='CASCADE'))
- fks.append(ForeignKeyConstraint([records_table.c.zone_id],
- [zones_table.c.id], ondelete='CASCADE'))
- fks.append(ForeignKeyConstraint([ztr_table.c.zone_id],
- [zones_table.c.id], ondelete='CASCADE'))
- fks.append(ForeignKeyConstraint([zta_table.c.zone_id],
- [zones_table.c.id], ondelete='CASCADE'))
- fks.append(ForeignKeyConstraint([zt_table.c.zone_id],
- [zones_table.c.id], ondelete='CASCADE'))
-
- for fk in fks:
- fk.create()
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/082_unique_ns_record.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/082_unique_ns_record.py
deleted file mode 100644
index 681fb061..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/082_unique_ns_record.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Endre Karlson <endre.karlson@hpe.com>
-#
-# 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 Unique constraint on ('pool_id', 'hostname') in the pool_ns_records
-table Bug #1517389"""
-
-import sys
-
-from migrate.changeset.constraint import UniqueConstraint
-from oslo_log import log as logging
-from sqlalchemy.engine.reflection import Inspector
-from sqlalchemy import exc
-from sqlalchemy.schema import MetaData, Table
-
-LOG = logging.getLogger()
-
-meta = MetaData()
-
-CONSTRAINT_NAME = "unique_ns_name"
-
-explanation = """
-You need to manually remove duplicate entries from the database.
-
-The error message was:
-%s
-"""
-
-
-def upgrade(migrate_engine):
- meta.bind = migrate_engine
-
- pool_ns_records_table = Table('pool_ns_records', meta, autoload=True)
-
- # Only apply it if it's not there (It's been backported to L)
- insp = Inspector.from_engine(migrate_engine)
- unique_constraints = insp.get_unique_constraints('pool_ns_records')
- unique_constraint_names = [i['name'] for i in unique_constraints]
-
- if CONSTRAINT_NAME not in unique_constraint_names:
- # We define the constraint here if not it shows in the list above.
- constraint = UniqueConstraint('pool_id', 'hostname',
- name=CONSTRAINT_NAME,
- table=pool_ns_records_table)
- try:
- constraint.create()
- except 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/migrate_repo/versions/083_change_managed_column_types.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/083_change_managed_column_types.py
deleted file mode 100644
index ebce3c2c..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/083_change_managed_column_types.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright 2016 Hewlett Packard Enterprise Development Company LP
-#
-# Author: Federico Ceratto <federico.ceratto@hpe.com>
-#
-# 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.
-
-"""
-Switch managed_* column types from Unicode to String
-Bug #276448
-"""
-
-from oslo_log import log as logging
-from sqlalchemy.schema import MetaData, Table
-from sqlalchemy import String
-
-LOG = logging.getLogger()
-meta = MetaData()
-
-
-def upgrade(migrate_engine):
- meta.bind = migrate_engine
- records = Table('records', meta, autoload=True)
-
- records.columns.managed_extra.alter(type=String(100))
- records.columns.managed_plugin_type.alter(type=String(50))
- records.columns.managed_plugin_name.alter(type=String(50))
- records.columns.managed_resource_type.alter(type=String(50))
- records.columns.managed_resource_region.alter(type=String(100))
- records.columns.managed_tenant_id.alter(type=String(36))
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/084_add_delayed_notify_column.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/084_add_delayed_notify_column.py
deleted file mode 100644
index 764dd663..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/084_add_delayed_notify_column.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Federico Ceratto <federico.ceratto@hpe.com>
-#
-# 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.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-from oslo_log import log as logging
-from sqlalchemy import Boolean
-from sqlalchemy.schema import Column, MetaData, Table, Index
-
-LOG = logging.getLogger(__name__)
-meta = MetaData()
-
-
-def upgrade(migrate_engine):
- LOG.info("Adding boolean column delayed_notify to table 'zones'")
- meta.bind = migrate_engine
- zones_table = Table('zones', meta, autoload=True)
- col = Column('delayed_notify', Boolean(), default=False)
- col.create(zones_table)
- index = Index('delayed_notify', zones_table.c.delayed_notify)
- index.create(migrate_engine)
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/085_add_zone_attributes.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/085_add_zone_attributes.py
deleted file mode 100644
index 3ab5a4bb..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/085_add_zone_attributes.py
+++ /dev/null
@@ -1,97 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# 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.
-
-"""Move zone masters to their own table, and allow for abstract keys in the
-attributes table"""
-
-from migrate.changeset.constraint import UniqueConstraint
-from oslo_log import log as logging
-from oslo_utils import timeutils
-from sqlalchemy import DateTime, Integer, String, select
-from sqlalchemy.schema import MetaData, Table, Column, ForeignKeyConstraint
-
-from designate.sqlalchemy.types import UUID
-from designate import utils
-
-LOG = logging.getLogger()
-
-meta = MetaData()
-
-zone_masters_table = Table('zone_masters', meta,
- Column('id', UUID(), default=utils.generate_uuid, primary_key=True),
- Column('version', Integer(), default=1, nullable=False),
- Column('created_at', DateTime, default=lambda: timeutils.utcnow()),
- Column('updated_at', DateTime, onupdate=lambda: timeutils.utcnow()),
-
- Column('host', String(32), nullable=False),
- Column('port', Integer(), nullable=False),
- Column('zone_id', UUID(), nullable=False),
-
- UniqueConstraint('host', 'port', 'zone_id', name='unique_masters'),
- ForeignKeyConstraint(['zone_id'], ['zones.id'], ondelete='CASCADE'),
-
- mysql_engine='InnoDB',
- mysql_charset='utf8'
-)
-
-
-def upgrade(migrate_engine):
- meta.bind = migrate_engine
- zone_attibutes_table = Table('zone_attributes', meta, autoload=True)
-
- connection = migrate_engine.connect()
-
- transaction = connection.begin()
- try:
-
- zone_masters_table.create()
-
- masters = select(
- [
- zone_attibutes_table.c.id,
- zone_attibutes_table.c.version,
- zone_attibutes_table.c.created_at,
- zone_attibutes_table.c.updated_at,
- zone_attibutes_table.c.value,
- zone_attibutes_table.c.zone_id
- ]
- ).where(
- zone_attibutes_table.c.key == 'master'
- ).execute().fetchall()
-
- masters_input = []
-
- for master in masters:
- host, port = utils.split_host_port(
- master[zone_attibutes_table.c.value])
- masters_input.append({
- 'id': master[zone_attibutes_table.c.id],
- 'version': master[zone_attibutes_table.c.version],
- 'created_at': master[zone_attibutes_table.c.created_at],
- 'updated_at': master[zone_attibutes_table.c.updated_at],
- 'zone_id': master[zone_attibutes_table.c.zone_id],
- 'host': host,
- 'port': port
- })
-
- zone_attibutes_table.insert(masters_input)
-
- zone_attibutes_table.delete().where(
- zone_attibutes_table.c.key == 'master')
-
- zone_attibutes_table.c.key.alter(type=String(50))
- transaction.commit()
- except Exception:
- transaction.rollback()
- raise
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/086_new_pools_tables.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/086_new_pools_tables.py
deleted file mode 100644
index 776afab1..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/086_new_pools_tables.py
+++ /dev/null
@@ -1,127 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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 oslo_utils import timeutils
-from sqlalchemy import (Integer, String, Unicode, DateTime,
- ForeignKeyConstraint, UniqueConstraint)
-from sqlalchemy.schema import Table, Column, MetaData
-
-from designate.sqlalchemy.types import UUID
-from designate import utils
-
-meta = MetaData()
-
-pool_nameservers = Table('pool_nameservers', meta,
- Column('id', UUID, default=utils.generate_uuid, primary_key=True),
- Column('version', Integer(), default=1, nullable=False),
- Column('created_at', DateTime, default=lambda: timeutils.utcnow()),
- Column('updated_at', DateTime, onupdate=lambda: timeutils.utcnow()),
-
- Column('pool_id', UUID(), nullable=False),
- Column('host', String(255), nullable=False),
- Column('port', Integer(), nullable=False),
-
- ForeignKeyConstraint(['pool_id'], ['pools.id'], ondelete='CASCADE'),
- UniqueConstraint('pool_id', 'host', 'port', name='unique_pool_host_port'),
-
- mysql_engine='InnoDB',
- mysql_charset='utf8',
-)
-
-pool_targets = Table('pool_targets', meta,
- Column('id', UUID, default=utils.generate_uuid, primary_key=True),
- Column('version', Integer(), default=1, nullable=False),
- Column('created_at', DateTime, default=lambda: timeutils.utcnow()),
- Column('updated_at', DateTime, onupdate=lambda: timeutils.utcnow()),
-
- Column('pool_id', UUID(), nullable=False),
- Column('type', String(50), nullable=False),
- Column('tsigkey_id', UUID(), nullable=True),
- Column('description', Unicode(160), nullable=True),
-
- ForeignKeyConstraint(['pool_id'], ['pools.id'], ondelete='CASCADE'),
-
- mysql_engine='InnoDB',
- mysql_charset='utf8',
-)
-
-pool_target_masters = Table('pool_target_masters', meta,
- Column('id', UUID, default=utils.generate_uuid, primary_key=True),
- Column('version', Integer(), default=1, nullable=False),
- Column('created_at', DateTime, default=lambda: timeutils.utcnow()),
- Column('updated_at', DateTime, onupdate=lambda: timeutils.utcnow()),
-
- Column('pool_target_id', UUID(), nullable=False),
- Column('host', String(255), nullable=False),
- Column('port', Integer(), nullable=False),
-
- ForeignKeyConstraint(['pool_target_id'], ['pool_targets.id'],
- ondelete='CASCADE'),
- UniqueConstraint('pool_target_id', 'host', 'port',
- name='unique_pool_target_host_port'),
-
- mysql_engine='InnoDB',
- mysql_charset='utf8',
-)
-
-pool_target_options = Table('pool_target_options', meta,
- Column('id', UUID, default=utils.generate_uuid, primary_key=True),
- Column('version', Integer(), default=1, nullable=False),
- Column('created_at', DateTime, default=lambda: timeutils.utcnow()),
- Column('updated_at', DateTime, onupdate=lambda: timeutils.utcnow()),
-
- Column('pool_target_id', UUID(), nullable=False),
- Column('key', String(255), nullable=False),
- Column('value', String(255), nullable=False),
-
- ForeignKeyConstraint(['pool_target_id'], ['pool_targets.id'],
- ondelete='CASCADE'),
- UniqueConstraint('pool_target_id', 'key', name='unique_pool_target_key'),
-
- mysql_engine='InnoDB',
- mysql_charset='utf8',
-)
-
-pool_also_notifies = Table('pool_also_notifies', meta,
- Column('id', UUID, default=utils.generate_uuid, primary_key=True),
- Column('version', Integer(), default=1, nullable=False),
- Column('created_at', DateTime, default=lambda: timeutils.utcnow()),
- Column('updated_at', DateTime, onupdate=lambda: timeutils.utcnow()),
-
- Column('pool_id', UUID(), nullable=False),
- Column('host', String(255), nullable=False),
- Column('port', Integer(), nullable=False),
-
- ForeignKeyConstraint(['pool_id'], ['pools.id'], ondelete='CASCADE'),
- UniqueConstraint('pool_id', 'host', 'port',
- name='unique_pool_also_notifies_pool0host0port'),
-
- mysql_engine='InnoDB',
- mysql_charset='utf8',
-)
-
-
-def upgrade(migrate_engine):
- meta.bind = migrate_engine
-
- # Load the pool_attributes_table table schema for relations
- Table('pools', meta, autoload=True)
-
- pool_nameservers.create(checkfirst=True)
- pool_targets.create(checkfirst=True)
- pool_target_options.create(checkfirst=True)
- pool_target_masters.create(checkfirst=True)
- pool_also_notifies.create(checkfirst=True)
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/087_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/087_placeholder.py
deleted file mode 100644
index ccb4f6f8..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/087_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Mitaka backports.
-# Do not use this number for new Newton work. New Newton work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/088_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/088_placeholder.py
deleted file mode 100644
index ccb4f6f8..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/088_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Mitaka backports.
-# Do not use this number for new Newton work. New Newton work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/089_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/089_placeholder.py
deleted file mode 100644
index ccb4f6f8..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/089_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Mitaka backports.
-# Do not use this number for new Newton work. New Newton work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/090_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/090_placeholder.py
deleted file mode 100644
index ccb4f6f8..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/090_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Mitaka backports.
-# Do not use this number for new Newton work. New Newton work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/091_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/091_placeholder.py
deleted file mode 100644
index ccb4f6f8..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/091_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Mitaka backports.
-# Do not use this number for new Newton work. New Newton work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/092_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/092_placeholder.py
deleted file mode 100644
index ccb4f6f8..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/092_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Mitaka backports.
-# Do not use this number for new Newton work. New Newton work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/093_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/093_placeholder.py
deleted file mode 100644
index ccb4f6f8..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/093_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Mitaka backports.
-# Do not use this number for new Newton work. New Newton work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/094_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/094_placeholder.py
deleted file mode 100644
index ccb4f6f8..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/094_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Mitaka backports.
-# Do not use this number for new Newton work. New Newton work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/095_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/095_placeholder.py
deleted file mode 100644
index ccb4f6f8..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/095_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Mitaka backports.
-# Do not use this number for new Newton work. New Newton work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/096_placeholder.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/096_placeholder.py
deleted file mode 100644
index ccb4f6f8..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/096_placeholder.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Author: Kiall Mac Innes <kiall@hpe.com>
-#
-# 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.
-#
-# This is a placeholder for Mitaka backports.
-# Do not use this number for new Newton work. New Newton work starts after
-# all the placeholders.
-#
-# See https://blueprints.launchpad.net/nova/+spec/backportable-db-migrations
-# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/097_add_services.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/097_add_services.py
deleted file mode 100644
index 48ce661e..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/097_add_services.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright 2016 Hewlett Packard Enterprise Development Company LP
-#
-# 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 Service Status tables"""
-
-
-from oslo_log import log as logging
-from sqlalchemy.schema import Table, Column, MetaData
-from sqlalchemy import String, DateTime, Enum, Text
-
-from designate.sqlalchemy.types import UUID
-from designate import utils
-
-LOG = logging.getLogger()
-
-meta = MetaData()
-
-SERVICE_STATES = [
- "UP", "DOWN", "WARNING"
-]
-
-
-def upgrade(migrate_engine):
- meta.bind = migrate_engine
-
- status_enum = Enum(name='service_statuses_enum', metadata=meta,
- *SERVICE_STATES)
- status_enum.create(checkfirst=True)
-
- service_status_table = Table('service_statuses', meta,
- Column('id', UUID(), default=utils.generate_uuid, primary_key=True),
- Column('created_at', DateTime),
- Column('updated_at', DateTime),
-
- Column('service_name', String(40), nullable=False),
- Column('hostname', String(255), nullable=False),
- Column('heartbeated_at', DateTime, nullable=True),
- Column('status', status_enum, nullable=False),
- Column('stats', Text, nullable=False),
- Column('capabilities', Text, nullable=False),
- )
- service_status_table.create(checkfirst=True)
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/098_fix_service_charset.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/098_fix_service_charset.py
deleted file mode 100644
index 14f47c2d..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/098_fix_service_charset.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2016 Hewlett Packard Enterprise Development Company LP
-#
-# 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 sqlalchemy.schema import MetaData
-
-
-meta = MetaData()
-
-
-def upgrade(migrate_engine):
- meta = MetaData()
- meta.bind = migrate_engine
-
- if migrate_engine.name != "mysql":
- return
-
- migrate_engine.execute("SET foreign_key_checks = 0;")
- migrate_engine.execute(
- "ALTER TABLE service_statuses CONVERT TO CHARACTER SET utf8;")
- migrate_engine.execute("SET foreign_key_checks = 1;")
- migrate_engine.execute(
- "ALTER DATABASE %s DEFAULT CHARACTER SET utf8;"
- % migrate_engine.url.database)
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/099_add_rrset_indexes_for_filtering_perf.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/099_add_rrset_indexes_for_filtering_perf.py
deleted file mode 100644
index c03b7ac8..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/099_add_rrset_indexes_for_filtering_perf.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright 2016 Rackspace
-#
-# Author: James Li <james.li@rackspace.com>
-#
-# 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 oslo_log import log as logging
-from sqlalchemy.schema import MetaData, Table, Index
-
-LOG = logging.getLogger(__name__)
-meta = MetaData()
-
-
-def upgrade(migrate_engine):
- meta.bind = migrate_engine
- recordsets_table = Table('recordsets', meta, autoload=True)
-
- Index('rrset_updated_at', recordsets_table.c.updated_at
- ).create(migrate_engine)
- Index('rrset_zoneid', recordsets_table.c.zone_id
- ).create(migrate_engine)
- Index('rrset_type', recordsets_table.c.type).create(migrate_engine)
- Index('rrset_ttl', recordsets_table.c.ttl).create(migrate_engine)
- Index('rrset_tenant_id', recordsets_table.c.tenant_id
- ).create(migrate_engine)
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/100_unique_service_status.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/100_unique_service_status.py
deleted file mode 100644
index fad49325..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/100_unique_service_status.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# 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 Unique constraint on ('service_name', 'hostname') in the
-service_statuses table for bug #1768824"""
-
-import sys
-
-from migrate.changeset.constraint import UniqueConstraint
-from oslo_log import log as logging
-from sqlalchemy import exc
-from sqlalchemy.schema import MetaData
-from sqlalchemy.schema import Table
-
-LOG = logging.getLogger()
-EXPLANATION = """
-You need to manually remove duplicate entries from the database.
-
-The error message was:
-%s
-"""
-
-
-def upgrade(migrate_engine):
- meta = MetaData()
- meta.bind = migrate_engine
- service_statuses_table = Table('service_statuses', meta, autoload=True)
-
- # Add UniqueConstraint based on service_name and hostname.
- constraint = UniqueConstraint('service_name', 'hostname',
- table=service_statuses_table,
- name="unique_service_status")
- try:
- constraint.create()
- except 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/migrate_repo/versions/101_support_naptr_records.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/101_support_naptr_records.py
deleted file mode 100644
index 7cd91ea7..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/101_support_naptr_records.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 2018 Canonical Ltd.
-#
-# Author: Tytus Kurek <tytus.kurek@canonical.com>
-#
-# 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 sqlalchemy import MetaData, Table, Enum
-
-meta = MetaData()
-
-
-def upgrade(migrate_engine):
- meta.bind = migrate_engine
-
- RECORD_TYPES = ['A', 'AAAA', 'CNAME', 'MX', 'SRV', 'TXT', 'SPF', 'NS',
- 'PTR', 'SSHFP', 'SOA', 'NAPTR']
-
- records_table = Table('recordsets', meta, autoload=True)
- records_table.columns.type.alter(name='type', type=Enum(*RECORD_TYPES))
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/102_support_caa_records.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/102_support_caa_records.py
deleted file mode 100644
index 32ec4fcd..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/102_support_caa_records.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 2018 Canonical Ltd.
-#
-# Author: Tytus Kurek <tytus.kurek@canonical.com>
-#
-# 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 sqlalchemy import MetaData, Table, Enum
-
-meta = MetaData()
-
-
-def upgrade(migrate_engine):
- meta.bind = migrate_engine
-
- RECORD_TYPES = ['A', 'AAAA', 'CNAME', 'MX', 'SRV', 'TXT', 'SPF', 'NS',
- 'PTR', 'SSHFP', 'SOA', 'NAPTR', 'CAA']
-
- records_table = Table('recordsets', meta, autoload=True)
- records_table.columns.type.alter(name='type', type=Enum(*RECORD_TYPES))
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/103_support_cert_records.py b/designate/storage/impl_sqlalchemy/migrate_repo/versions/103_support_cert_records.py
deleted file mode 100644
index 85ba5b67..00000000
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/103_support_cert_records.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 2021 Cloudification GmbH
-#
-# Author: cloudification <contact@cloudification.io>
-#
-# 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 sqlalchemy import MetaData, Table, Enum
-
-meta = MetaData()
-
-
-def upgrade(migrate_engine):
- meta.bind = migrate_engine
-
- RECORD_TYPES = ['A', 'AAAA', 'CNAME', 'MX', 'SRV', 'TXT', 'SPF', 'NS',
- 'PTR', 'SSHFP', 'SOA', 'NAPTR', 'CAA', 'CERT']
-
- records_table = Table('recordsets', meta, autoload=True)
- records_table.columns.type.alter(name='type', type=Enum(*RECORD_TYPES))
diff --git a/designate/tests/__init__.py b/designate/tests/__init__.py
index 4a30744e..a6400fbe 100644
--- a/designate/tests/__init__.py
+++ b/designate/tests/__init__.py
@@ -33,7 +33,6 @@ from designate.common import constants
import designate.conf
from designate.context import DesignateContext
from designate import exceptions
-from designate.manage import database as manage_database
from designate import objects
from designate import policy
from designate import storage
@@ -359,15 +358,8 @@ class TestCase(base.BaseTestCase):
self._disable_osprofiler()
- # The database fixture needs to be set up here (as opposed to isolated
- # in a storage test case) because many tests end up using storage.
- REPOSITORY = os.path.abspath(os.path.join(os.path.dirname(__file__),
- '..', 'storage',
- 'impl_sqlalchemy',
- 'migrate_repo'))
self.db_fixture = self.useFixture(
- fixtures.DatabaseFixture.get_fixture(
- REPOSITORY, manage_database.INIT_VERSION))
+ fixtures.DatabaseFixture.get_fixture())
if os.getenv('DESIGNATE_SQL_DEBUG', "False").lower() in _TRUE_VALUES:
connection_debug = 50
diff --git a/designate/tests/fixtures.py b/designate/tests/fixtures.py
index 8ef03fc9..33709e06 100644
--- a/designate/tests/fixtures.py
+++ b/designate/tests/fixtures.py
@@ -33,12 +33,12 @@ from oslo_log import log as logging
from oslo_utils import importutils
import tooz.coordination
+from designate.manage import database as db_commands
from designate import network_api
from designate.network_api import fake as fake_network_api
from designate import policy
from designate import rpc
import designate.service
-from designate.sqlalchemy import utils as sqlalchemy_utils
import designate.utils
"""Test fixtures
@@ -117,14 +117,13 @@ class PolicyFixture(fixtures.Fixture):
class DatabaseFixture(fixtures.Fixture):
- fixtures = {}
+ fixture = None
@staticmethod
- def get_fixture(repo_path, init_version=None):
- if repo_path not in DatabaseFixture.fixtures:
- DatabaseFixture.fixtures[repo_path] = DatabaseFixture(
- repo_path, init_version)
- return DatabaseFixture.fixtures[repo_path]
+ def get_fixture():
+ if not DatabaseFixture.fixture:
+ DatabaseFixture.fixture = DatabaseFixture()
+ return DatabaseFixture.fixture
def _mktemp(self):
"""Create temporary database file
@@ -142,7 +141,7 @@ class DatabaseFixture(fixtures.Fixture):
dir=tmp_dir)
return path
- def __init__(self, repo_path, init_version=None):
+ def __init__(self):
super(DatabaseFixture, self).__init__()
# Create the Golden DB
@@ -150,9 +149,8 @@ class DatabaseFixture(fixtures.Fixture):
self.golden_url = 'sqlite:///%s' % self.golden_db
# Migrate the Golden DB
- manager = sqlalchemy_utils.get_migration_manager(
- repo_path, self.golden_url, init_version)
- manager.upgrade(None)
+ db_cmds = db_commands.DatabaseCommands()
+ db_cmds.upgrade('head', db_url=self.golden_url)
# Prepare the Working Copy DB
self.working_copy = self._mktemp()
diff --git a/designate/tests/test_manage/test_database.py b/designate/tests/test_manage/test_database.py
new file mode 100644
index 00000000..c318ea42
--- /dev/null
+++ b/designate/tests/test_manage/test_database.py
@@ -0,0 +1,62 @@
+# 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 io import StringIO
+from unittest import mock
+
+from designate.manage import database
+from designate import tests as designate_tests
+
+
+class TestManageDatabase(designate_tests.TestCase):
+
+ def setUp(self):
+ super(TestManageDatabase, self).setUp()
+ self.stdlog = designate_tests.fixtures.StandardLogging()
+ self.useFixture(self.stdlog)
+
+ self.db_cmds = database.DatabaseCommands()
+
+ def test_current(self):
+ cmd_output = StringIO()
+ self.db_cmds.current(stringio_buffer=cmd_output)
+ self.assertIn('head', cmd_output.getvalue())
+
+ def test_heads(self):
+ cmd_output = StringIO()
+ self.db_cmds.heads(stringio_buffer=cmd_output)
+ self.assertIn('head', cmd_output.getvalue())
+
+ def test_history(self):
+ cmd_output = StringIO()
+ self.db_cmds.history(stringio_buffer=cmd_output)
+ self.assertIn('head', cmd_output.getvalue())
+
+ def test_version(self):
+ with mock.patch('sys.stdout', new=StringIO()) as cmd_output:
+ self.db_cmds.version()
+ self.assertIn('head', cmd_output.getvalue())
+
+ def test_sync(self):
+ cmd_output = StringIO()
+ self.db_cmds.sync(stringio_buffer=cmd_output)
+ # The test framework will run the migration, so there should be
+ # no output of this command run.
+ self.assertEqual('', cmd_output.getvalue())
+
+ def test_upgrade(self):
+ cmd_output = StringIO()
+ self.db_cmds.upgrade('head', stringio_buffer=cmd_output)
+ # The test framework will run the migration, so there should be
+ # no output of this command run.
+ self.assertEqual('', cmd_output.getvalue())
diff --git a/designate/tests/test_storage/test_sqlalchemy.py b/designate/tests/test_storage/test_sqlalchemy.py
index 9a4bf321..52a56afd 100644
--- a/designate/tests/test_storage/test_sqlalchemy.py
+++ b/designate/tests/test_storage/test_sqlalchemy.py
@@ -31,7 +31,6 @@ class SqlalchemyStorageTest(StorageTestCase, TestCase):
def test_schema_table_names(self):
table_names = [
u'blacklists',
- u'migrate_version',
u'pool_also_notifies',
u'pool_attributes',
u'pool_nameservers',
@@ -54,10 +53,32 @@ class SqlalchemyStorageTest(StorageTestCase, TestCase):
u'zones'
]
inspector = self.storage.get_inspector()
- self.assertEqual(table_names, inspector.get_table_names())
+
+ actual_table_names = inspector.get_table_names()
+
+ # We have transitioned database schema migration tools.
+ # They use different tracking tables. Accomidate that one or both
+ # may exist in this test.
+ migration_table_found = False
+ if ('migrate_version' in actual_table_names or
+ 'alembic_version' in actual_table_names):
+ migration_table_found = True
+ self.assertTrue(migration_table_found,
+ 'A DB migration table was not found.')
+ try:
+ actual_table_names.remove('migrate_version')
+ except ValueError:
+ pass
+ try:
+ actual_table_names.remove('alembic_version')
+ except ValueError:
+ pass
+
+ self.assertEqual(table_names, actual_table_names)
def test_schema_table_indexes(self):
- indexes_t = self.storage.engine.execute("SELECT * FROM sqlite_master WHERE type = 'index';") # noqa
+ indexes_t = self.storage.engine.execute(
+ "SELECT * FROM sqlite_master WHERE type = 'index';")
indexes = {} # table name -> index names -> cmd
for _, index_name, table_name, num, cmd in indexes_t:
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/__init__.py b/designate/tests/unit/storage/__init__.py
index e69de29b..e69de29b 100644
--- a/designate/storage/impl_sqlalchemy/migrate_repo/__init__.py
+++ b/designate/tests/unit/storage/__init__.py
diff --git a/designate/storage/impl_sqlalchemy/migrate_repo/versions/__init__.py b/designate/tests/unit/storage/impl_sqlalchemy/__init__.py
index e69de29b..e69de29b 100644
--- a/designate/storage/impl_sqlalchemy/migrate_repo/versions/__init__.py
+++ b/designate/tests/unit/storage/impl_sqlalchemy/__init__.py
diff --git a/designate/tests/unit/storage/impl_sqlalchemy/alembic/__init__.py b/designate/tests/unit/storage/impl_sqlalchemy/alembic/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/designate/tests/unit/storage/impl_sqlalchemy/alembic/__init__.py
diff --git a/designate/tests/unit/storage/impl_sqlalchemy/alembic/test_legacy_utils.py b/designate/tests/unit/storage/impl_sqlalchemy/alembic/test_legacy_utils.py
new file mode 100644
index 00000000..5b8702ce
--- /dev/null
+++ b/designate/tests/unit/storage/impl_sqlalchemy/alembic/test_legacy_utils.py
@@ -0,0 +1,56 @@
+# 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 unittest import mock
+
+import oslotest.base
+
+from designate.storage.impl_sqlalchemy.alembic import legacy_utils
+
+
+class TestLegacyUtils(oslotest.base.BaseTestCase):
+
+ @mock.patch('sqlalchemy.MetaData')
+ @mock.patch('alembic.op.get_bind')
+ def test_is_migration_needed(self, mock_get_bind, mock_metadata):
+ mock_bind = mock.MagicMock()
+ mock_get_bind.return_value = mock_bind
+ mock_execute = mock.MagicMock()
+ mock_bind.execute.return_value = mock_execute
+ mock_metadata_obj = mock.MagicMock()
+ mock_metadata_obj.tables.keys.side_effect = [
+ [], ['migrate_version'], ['migrate_version'],
+ ['migrate_version'], ['migrate_version'],
+ ['migrate_version'], ['migrate_version']]
+ mock_metadata.return_value = mock_metadata_obj
+
+ mock_execute.scalar_one_or_none.side_effect = [
+ None, '79', '80', '81', Exception('boom')]
+
+ # No existing migrate_version table
+ self.assertTrue(legacy_utils.is_migration_needed(2022))
+
+ # DB revision None
+ self.assertTrue(legacy_utils.is_migration_needed(80))
+
+ # DB revision 79
+ self.assertTrue(legacy_utils.is_migration_needed(80))
+
+ # DB revision 80
+ self.assertFalse(legacy_utils.is_migration_needed(80))
+
+ # DB revision 81
+ self.assertFalse(legacy_utils.is_migration_needed(80))
+
+ # DB revision query exception (no table, etc.)
+ self.assertTrue(legacy_utils.is_migration_needed(80))
diff --git a/designate/tests/unit/test_upgrade_checks.py b/designate/tests/unit/test_upgrade_checks.py
index da8f2ffb..9d2c3fba 100644
--- a/designate/tests/unit/test_upgrade_checks.py
+++ b/designate/tests/unit/test_upgrade_checks.py
@@ -11,8 +11,8 @@
# 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 unittest import mock
-from migrate.changeset.constraint import UniqueConstraint
from oslo_upgradecheck import upgradecheck
from sqlalchemy.schema import MetaData
from sqlalchemy.schema import Table
@@ -52,22 +52,13 @@ class TestDuplicateServiceStatus(tests.TestCase):
self.assertEqual(upgradecheck.Code.SUCCESS,
checks._duplicate_service_status().code)
- def test_failure(self):
- # Drop unique constraint so we can test error cases
- constraint = UniqueConstraint('service_name', 'hostname',
- table=self.service_statuses_table,
- name="unique_service_status")
- constraint.drop()
- fake_record = {'id': '1',
- 'service_name': 'worker',
- 'hostname': 'localhost',
- 'status': 'UP',
- 'stats': '',
- 'capabilities': '',
- }
- self.service_statuses_table.insert().execute(fake_record)
- fake_record['id'] = '2'
- self.service_statuses_table.insert().execute(fake_record)
+ @mock.patch('designate.sqlalchemy.session.get_engine')
+ def test_failure(self, mock_get_engine):
+ mock_engine = mock.MagicMock()
+ mock_execute = mock.MagicMock()
+ mock_engine.execute.return_value = mock_execute
+ mock_execute.fetchall.return_value = [(2,)]
+ mock_get_engine.return_value = mock_engine
checks = status.Checks()
self.assertEqual(upgradecheck.Code.FAILURE,
diff --git a/releasenotes/notes/Switch-to-alembic-migrations-15b7701f4e8b37c1.yaml b/releasenotes/notes/Switch-to-alembic-migrations-15b7701f4e8b37c1.yaml
new file mode 100644
index 00000000..7e8389a0
--- /dev/null
+++ b/releasenotes/notes/Switch-to-alembic-migrations-15b7701f4e8b37c1.yaml
@@ -0,0 +1,7 @@
+---
+other:
+ - |
+ Designate will now use Alembic migrations for database schema updates.
+ This transition will automatically be handled for upgrades.
+ The sqlalchemy-migrate package has been removed from the Designate
+ requirements and the alembic package has been added.
diff --git a/requirements.txt b/requirements.txt
index 6fa0ddf9..73d13ea5 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,6 +5,7 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
+alembic>=1.6.5 # MIT
eventlet>=0.26.1 # MIT
Flask!=0.11,>=0.10 # BSD
greenlet>=0.4.15 # MIT
@@ -35,7 +36,6 @@ python-neutronclient>=6.7.0 # Apache-2.0
requests>=2.23.0 # Apache-2.0
tenacity>=6.0.0 # Apache-2.0
SQLAlchemy>=1.2.19 # MIT
-sqlalchemy-migrate>=0.11.0 # Apache-2.0
stevedore>=1.20.0 # Apache-2.0
WebOb>=1.7.1 # MIT
dnspython>=1.16.0 # http://www.dnspython.org/LICENSE