Squash Icehouse DB Migrations

MySQL: Produces an identical database, with one bug fixed in migration 40.
SQLite: Produces a "better" database, with some lost constraints restored.
PostgreSQL: Produces an identical database, with a bug in migration 39 fixed.

Change-Id: I8c8397ad38cc2d6344aa169c766e3adf18043ee1
This commit is contained in:
Kiall Mac Innes 2014-09-01 18:34:30 +01:00
parent a98b46ad6e
commit abb82d8c3c
43 changed files with 276 additions and 1859 deletions

View File

@ -17,10 +17,10 @@ import os
from migrate.versioning import api as versioning_api
from oslo.config import cfg
from oslo.db.sqlalchemy.migration_cli import manager as migration_manager
from designate.openstack.common import log as logging
from designate.manage import base
from designate.sqlalchemy import utils
LOG = logging.getLogger(__name__)
@ -32,13 +32,12 @@ cfg.CONF.import_opt('connection', 'designate.storage.impl_sqlalchemy',
group='storage:sqlalchemy')
CONF = cfg.CONF
INIT_VERSION = 37
def get_manager():
migration_config = {
'migration_repo_path': REPOSITORY,
'db_url': CONF['storage:sqlalchemy'].connection}
return migration_manager.MigrationManager(migration_config)
return utils.get_migration_manager(
REPOSITORY, CONF['storage:sqlalchemy'].connection, INIT_VERSION)
class DatabaseCommands(base.Commands):

View File

@ -19,6 +19,7 @@ import logging
import sqlalchemy
from oslo.db.sqlalchemy import utils
from oslo.db.sqlalchemy.migration_cli import manager
from designate.i18n import _
from designate.i18n import _LW
@ -27,6 +28,15 @@ from designate.i18n import _LW
LOG = logging.getLogger(__name__)
def get_migration_manager(repo_path, url, init_version=None):
migration_config = {
'migration_repo_path': repo_path,
'db_url': url,
'init_version': init_version,
}
return manager.MigrationManager(migration_config)
# copy from olso/db/sqlalchemy/utils.py
def paginate_query(query, table, limit, sort_keys, marker=None,
sort_dir=None, sort_dirs=None):

View File

@ -1,85 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# 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.
from sqlalchemy import ForeignKey, Enum, Integer, String, DateTime, Text
from sqlalchemy.schema import Column, MetaData
from designate.openstack.common import timeutils
from designate import utils
from designate.storage.impl_sqlalchemy.migrate_repo.utils import Table
from designate.storage.impl_sqlalchemy.migrate_repo.utils import create_tables
from designate.storage.impl_sqlalchemy.migrate_repo.utils import drop_tables
from designate.sqlalchemy.types import Inet
from designate.sqlalchemy.types import UUID
meta = MetaData()
RECORD_TYPES = ['A', 'AAAA', 'CNAME', 'MX', 'SRV', 'TXT', 'NS']
servers = Table('servers', meta,
Column('id', UUID(), default=utils.generate_uuid,
primary_key=True),
Column('created_at', DateTime(), default=timeutils.utcnow),
Column('updated_at', DateTime(), onupdate=timeutils.utcnow),
Column('version', Integer(), default=1, nullable=False),
Column('name', String(255), nullable=False, unique=True),
Column('ipv4', Inet(), nullable=False, unique=True),
Column('ipv6', Inet(), default=None, unique=True))
domains = Table('domains', meta,
Column('id', UUID(), default=utils.generate_uuid,
primary_key=True),
Column('created_at', DateTime(), default=timeutils.utcnow),
Column('updated_at', DateTime(), onupdate=timeutils.utcnow),
Column('version', Integer(), default=1, nullable=False),
Column('tenant_id', String(36), default=None, nullable=True),
Column('name', String(255), nullable=False, unique=True),
Column('email', String(36), nullable=False),
Column('ttl', Integer(), default=3600, nullable=False),
Column('refresh', Integer(), default=3600, nullable=False),
Column('retry', Integer(), default=3600, nullable=False),
Column('expire', Integer(), default=3600, nullable=False),
Column('minimum', Integer(), default=3600, nullable=False))
records = Table('records', meta,
Column('id', UUID(), default=utils.generate_uuid,
primary_key=True),
Column('created_at', DateTime(), default=timeutils.utcnow),
Column('updated_at', DateTime(), onupdate=timeutils.utcnow),
Column('version', Integer(), default=1, nullable=False),
Column('type', Enum(name='record_types', *RECORD_TYPES),
nullable=False),
Column('name', String(255), nullable=False),
Column('data', Text(), nullable=False),
Column('priority', Integer(), default=None),
Column('ttl', Integer(), default=3600, nullable=False),
Column('domain_id', UUID(), ForeignKey('domains.id'),
nullable=False))
def upgrade(migrate_engine):
meta.bind = migrate_engine
tables = [domains, servers, records, ]
create_tables(tables)
def downgrade(migrate_engine):
meta.bind = migrate_engine
tables = [domains, servers, records, ]
drop_tables(tables)

View File

@ -1,55 +0,0 @@
# Copyright 2012 Managed I.T.
#
# Author: Kiall Mac Innes <kiall@managedit.ie>
#
# 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, Column, Boolean, Unicode
from designate.sqlalchemy.types import UUID
meta = MetaData()
def upgrade(migrate_engine):
meta.bind = migrate_engine
records_table = Table('records', meta, autoload=True)
managed_resource = Column('managed_resource', Boolean(), default=False)
managed_resource.create(records_table, populate_default=True)
managed_resource_type = Column('managed_resource_type', Unicode(50),
default=None, nullable=True)
managed_resource_type.create(records_table, populate_default=True)
managed_resource_id = Column('managed_resource_id', UUID(), default=None,
nullable=True)
managed_resource_id.create(records_table, populate_default=True)
def downgrade(migrate_engine):
meta.bind = migrate_engine
records_table = Table('records', meta, autoload=True)
managed_resource_id = Column('managed_resource_id', UUID(), default=None,
nullable=True)
managed_resource_id.drop(records_table)
managed_resource_type = Column('managed_resource_type', Unicode(50),
default=None, nullable=True)
managed_resource_type.drop(records_table)
managed_resource = Column('managed_resource', Boolean(), default=False)
managed_resource.drop(records_table)

View File

@ -1,58 +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.
from sqlalchemy import MetaData, Table
from migrate import ForeignKeyConstraint
meta = MetaData()
def upgrade(migrate_engine):
meta.bind = migrate_engine
dialect = migrate_engine.url.get_dialect().name
records = Table('records', meta, autoload=True)
domains = Table('domains', meta, autoload=True)
# add foreignkey if not sqlite
if not dialect.startswith('sqlite'):
if dialect.startswith('mysql'):
ForeignKeyConstraint(columns=[records.c.domain_id],
refcolumns=[domains.c.id],
name='records_ibfk_1').drop()
else:
ForeignKeyConstraint(columns=[records.c.domain_id],
refcolumns=[domains.c.id]).drop()
ForeignKeyConstraint(columns=[records.c.domain_id],
refcolumns=[domains.c.id],
ondelete='CASCADE',
name='fkey_records_domain_id').create()
def downgrade(migrate_engine):
meta.bind = migrate_engine
dialect = migrate_engine.url.get_dialect().name
records = Table('records', meta, autoload=True)
domains = Table('domains', meta, autoload=True)
# add foreignkey if not sqlite
if not dialect.startswith('sqlite'):
ForeignKeyConstraint(columns=[records.c.domain_id],
refcolumns=[domains.c.id]).drop()
ForeignKeyConstraint(columns=[records.c.domain_id],
refcolumns=[domains.c.id]).create()

View File

@ -1,46 +0,0 @@
# Copyright 2012 Managed I.T.
#
# Author: Kiall Mac Innes <kiall@managedit.ie>
#
# 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, Column, Unicode
meta = MetaData()
def upgrade(migrate_engine):
meta.bind = migrate_engine
records_table = Table('records', meta, autoload=True)
records_table.c.managed_resource.alter(name='managed')
managed_plugin_name = Column('managed_plugin_name', Unicode(50))
managed_plugin_name.create(records_table, populate_default=True)
managed_plugin_type = Column('managed_plugin_type', Unicode(50))
managed_plugin_type.create(records_table, populate_default=True)
def downgrade(migrate_engine):
meta.bind = migrate_engine
records_table = Table('records', meta, autoload=True)
records_table.c.managed.alter(name='managed_resource')
managed_plugin_name = Column('managed_resource_name', Unicode(50))
managed_plugin_name.drop(records_table)
managed_plugin_type = Column('managed_resource_type', Unicode(50))
managed_plugin_type.drop(records_table)

View File

@ -1,32 +0,0 @@
# Copyright 2012 Managed I.T.
#
# Author: Kiall Mac Innes <kiall@managedit.ie>
#
# 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
meta = MetaData()
def upgrade(migrate_engine):
meta.bind = migrate_engine
records_table = Table('records', meta, autoload=True)
records_table.c.ttl.alter(nullable=True, default=None)
def downgrade(migrate_engine):
meta.bind = migrate_engine
records_table = Table('records', meta, autoload=True)
records_table.c.ttl.alter(nullable=False, default=3600)

View File

@ -1,41 +0,0 @@
# Copyright 2012 Managed I.T.
#
# Author: Kiall Mac Innes <kiall@managedit.ie>
#
# 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', 'NS', 'PTR']
records_table = Table('records', meta, autoload=True)
records_table.c.type.alter(type=Enum(name='record_types', *RECORD_TYPES))
def downgrade(migrate_engine):
meta.bind = migrate_engine
RECORD_TYPES = ['A', 'AAAA', 'CNAME', 'MX', 'SRV', 'TXT', 'NS']
records_table = Table('records', meta, autoload=True)
# Delete all PTR records
records_table.filter_by(type='PTR').delete()
# Remove PTR from the ENUM
records_table.c.type.alter(type=Enum(name='record_types', *RECORD_TYPES))

View File

@ -1,47 +0,0 @@
# Copyright 2012 Managed I.T.
#
# Author: Kiall Mac Innes <kiall@managedit.ie>
#
# 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, Column, ForeignKey
from designate.sqlalchemy.types import UUID
meta = MetaData()
def upgrade(migrate_engine):
meta.bind = migrate_engine
domains_table = Table('domains', meta, autoload=True)
parent_domain_id = Column('parent_domain_id',
UUID,
ForeignKey('domains.id'),
default=None,
nullable=True)
parent_domain_id.create(domains_table, populate_default=True)
def downgrade(migrate_engine):
meta.bind = migrate_engine
domains_table = Table('domains', meta, autoload=True)
parent_domain_id = Column('parent_domain_id',
UUID,
ForeignKey('domains.id'),
default=None,
nullable=True)
parent_domain_id.drop(domains_table)

View File

@ -1,42 +0,0 @@
# Copyright 2012 Managed I.T.
#
# Author: Kiall Mac Innes <kiall@managedit.ie>
#
# 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']
records_table = Table('records', meta, autoload=True)
records_table.c.type.alter(type=Enum(name='record_types', *RECORD_TYPES))
def downgrade(migrate_engine):
meta.bind = migrate_engine
RECORD_TYPES = ['A', 'AAAA', 'CNAME', 'MX', 'SRV', 'TXT', 'NS', 'PTR']
records_table = Table('records', meta, autoload=True)
# Delete all SPF records
records_table.filter_by(type='SPF').delete()
# Remove SPF from the ENUM
records_table.c.type.alter(type=Enum(name='record_types', *RECORD_TYPES))

View File

@ -1,51 +0,0 @@
# Copyright 2012 Managed I.T.
#
# Author: Kiall Mac Innes <kiall@managedit.ie>
#
# 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 Enum, Integer, String, DateTime
from sqlalchemy.schema import Table, Column, MetaData
from designate.openstack.common import timeutils
from designate import utils
from designate.sqlalchemy.types import UUID
meta = MetaData()
TSIG_ALGORITHMS = ['hmac-md5', 'hmac-sha1', 'hmac-sha224', 'hmac-sha256',
'hmac-sha384', 'hmac-sha512']
tsigkeys = Table('tsigkeys', meta,
Column('id', UUID(), default=utils.generate_uuid,
primary_key=True),
Column('created_at', DateTime(), default=timeutils.utcnow),
Column('updated_at', DateTime(), onupdate=timeutils.utcnow),
Column('version', Integer(), default=1, nullable=False),
Column('name', String(255), nullable=False, unique=True),
Column('algorithm', Enum(name='tsig_algorithms',
*TSIG_ALGORITHMS),
nullable=False),
Column('secret', String(255), nullable=False))
def upgrade(migrate_engine):
meta.bind = migrate_engine
tsigkeys.create()
def downgrade(migrate_engine):
meta.bind = migrate_engine
tsigkeys.drop()

View File

@ -1,42 +0,0 @@
# Copyright 2012 Managed I.T.
#
# Author: Kiall Mac Innes <kiall@managedit.ie>
#
# 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, Column
from designate.sqlalchemy.types import Inet
meta = MetaData()
def upgrade(migrate_engine):
meta.bind = migrate_engine
servers_table = Table('servers', meta, autoload=True)
servers_table.c.ipv4.drop()
servers_table.c.ipv6.drop()
def downgrade(migrate_engine):
meta.bind = migrate_engine
servers_table = Table('servers', meta, autoload=True)
ipv4 = Column('ipv4', Inet(), nullable=False, unique=True)
ipv6 = Column('ipv6', Inet(), default=None, unique=True)
ipv4.create(servers_table, populate_default=True)
ipv6.create(servers_table, populate_default=True)

View File

@ -1,43 +0,0 @@
# Copyright 2012 Managed I.T.
#
# Author: Kiall Mac Innes <kiall@managedit.ie>
#
# 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']
records_table = Table('records', meta, autoload=True)
records_table.c.type.alter(type=Enum(name='record_types', *RECORD_TYPES))
def downgrade(migrate_engine):
meta.bind = migrate_engine
RECORD_TYPES = ['A', 'AAAA', 'CNAME', 'MX', 'SRV', 'TXT', 'SPF', 'NS',
'PTR']
records_table = Table('records', meta, autoload=True)
# Delete all SSHFP records
records_table.filter_by(type='SSHFP').delete()
# Remove SSHFP from the ENUM
records_table.c.type.alter(type=Enum(name='record_types', *RECORD_TYPES))

View File

@ -1,48 +0,0 @@
# Copyright 2012 Managed I.T.
#
# Author: Kiall Mac Innes <kiall@managedit.ie>
#
# 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, Column, Integer
from designate.openstack.common import timeutils
from designate.openstack.common import log as logging
from designate.i18n import _LW
LOG = logging.getLogger(__name__)
meta = MetaData()
def upgrade(migrate_engine):
meta.bind = migrate_engine
domains_table = Table('domains', meta, autoload=True)
serial = Column('serial', Integer(), default=timeutils.utcnow_ts,
nullable=False, server_default="1")
serial.create(domains_table, populate_default=True)
# Do we have any domains?
domain_count = domains_table.count().execute().first()[0]
if domain_count > 0:
LOG.warn(_LW('A sync-domains is now required in order for the API '
'provided, and backend provided serial numbers to align'))
def downgrade(migrate_engine):
meta.bind = migrate_engine
domains_table = Table('domains', meta, autoload=True)
domains_table.c.serial.drop()

View File

@ -1,32 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
from sqlalchemy import MetaData, Table, String
meta = MetaData()
def upgrade(migrate_engine):
meta.bind = migrate_engine
domains_table = Table('domains', meta, autoload=True)
domains_table.c.email.alter(type=String(255))
def downgrade(migrate_engine):
meta.bind = migrate_engine
domains_table = Table('domains', meta, autoload=True)
domains_table.c.email.alter(type=String(36))

View File

@ -1,47 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
from sqlalchemy import Integer, String, DateTime, UniqueConstraint
from sqlalchemy.schema import Table, Column, MetaData
from designate.openstack.common import timeutils
from designate import utils
from designate.sqlalchemy.types import UUID
meta = MetaData()
quotas = Table('quotas', meta,
Column('id', UUID(), default=utils.generate_uuid,
primary_key=True),
Column('created_at', DateTime(), default=timeutils.utcnow),
Column('updated_at', DateTime(), onupdate=timeutils.utcnow),
Column('version', Integer(), default=1, nullable=False),
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'))
def upgrade(migrate_engine):
meta.bind = migrate_engine
quotas.create()
def downgrade(migrate_engine):
meta.bind = migrate_engine
quotas.drop()

View File

@ -1,78 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
import hashlib
from sqlalchemy.exc import IntegrityError
from sqlalchemy.schema import Table, Column, MetaData
from sqlalchemy.types import String
from designate.openstack.common import log as logging
from designate.i18n import _LW
LOG = logging.getLogger(__name__)
meta = MetaData()
def _build_hash(r):
md5 = hashlib.md5()
md5.update("%s:%s:%s:%s:%s" % (r.domain_id, r.name, r.type, r.data,
r.priority))
return md5.hexdigest()
def upgrade(migrate_engine):
meta.bind = migrate_engine
records_table = Table('records', meta, autoload=True)
# Add the hash column, start with allowing NULLs
hash_column = Column('hash', String(32), nullable=True, default=None,
unique=True)
hash_column.create(records_table, unique_name='unique_record')
sync_domains = []
# Fill out the hash values. We need to do this in a way that lets us track
# which domains need to be re-synced, so having the DB do this directly
# won't work.
for record in records_table.select().execute():
try:
records_table.update()\
.where(records_table.c.id == record.id)\
.values(hash=_build_hash(record))\
.execute()
except IntegrityError:
if record.domain_id not in sync_domains:
sync_domains.append(record.domain_id)
LOG.warn(_LW("Domain '%s' needs to be synchronised") %
record.domain_id)
records_table.delete()\
.where(records_table.c.id == record.id)\
.execute()
# Finally, the column should not be nullable.
records_table.c.hash.alter(nullable=False)
def downgrade(migrate_engine):
meta.bind = migrate_engine
records_table = Table('records', meta, autoload=True)
hash_column = Column('hash', String(32), nullable=False, unique=True)
hash_column.drop(records_table)

View File

@ -1,69 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
from sqlalchemy import MetaData, Table, Column, DateTime
from sqlalchemy.types import CHAR
from migrate.changeset.constraint import UniqueConstraint
meta = MetaData()
def upgrade(migrate_engine):
meta.bind = migrate_engine
domains_table = Table('domains', meta, autoload=True)
# Create the new columns
deleted_column = Column('deleted', CHAR(32), nullable=False, default="0",
server_default="0")
deleted_column.create(domains_table, populate_default=True)
deleted_at_column = Column('deleted_at', DateTime, nullable=True,
default=None)
deleted_at_column.create(domains_table, populate_default=True)
# Drop the old single column unique
# NOTE(kiall): It appears this does nothing. Miration 17 has been added.
# leaving this here for reference.
domains_table.c.name.alter(unique=False)
# Add a new multi-column unique index
constraint = UniqueConstraint('name', 'deleted', name='unique_domain_name',
table=domains_table)
constraint.create()
def downgrade(migrate_engine):
meta.bind = migrate_engine
domains_table = Table('domains', meta, autoload=True)
# Drop the multi-column unique index
constraint = UniqueConstraint('name', 'deleted', name='unique_domain_name',
table=domains_table)
constraint.drop()
# Revert to single column unique
# NOTE(kiall): It appears this does nothing. Miration 17 has been added.
# leaving this here for reference.
domains_table.c.name.alter(unique=True)
# Drop the deleted columns
deleted_column = Column('deleted', CHAR(32), nullable=True, default=None)
deleted_column.drop(domains_table)
deleted_at_column = Column('deleted_at', DateTime, nullable=True,
default=None)
deleted_at_column.drop(domains_table)

View File

@ -1,64 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
import logging
from sqlalchemy import MetaData, Table, Column, String
from sqlalchemy.sql import update
from migrate.changeset.constraint import UniqueConstraint
LOG = logging.getLogger(__name__)
meta = MetaData()
def upgrade(migrate_engine):
meta.bind = migrate_engine
dialect = migrate_engine.url.get_dialect().name
domains_table = Table('domains', meta, autoload=True)
if dialect.startswith('sqlite'):
# SQLite can't drop a constraint. Yay. This will be fun..
# Create a new name column without the unique index
name_tmp_column = Column('name_tmp', String(255))
name_tmp_column.create(domains_table)
# Copy the data over.
query = update(domains_table).values(name_tmp=domains_table.c.name)
migrate_engine.execute(query)
# Delete the name column
domains_table.c.name.drop()
# Rename the name_tmp column to name
domains_table.c.name_tmp.alter(name='name')
elif dialect.startswith('postgresql'):
constraint = UniqueConstraint('name', name='domains_name_key',
table=domains_table)
constraint.drop()
else:
constraint = UniqueConstraint('name', name='name', table=domains_table)
constraint.drop()
def downgrade(migrate_engine):
meta.bind = migrate_engine
domains_table = Table('domains', meta, autoload=True)
constraint = UniqueConstraint('name', name='name', table=domains_table)
constraint.create()

View File

@ -1,65 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# 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.
import logging
from sqlalchemy import MetaData, Table
from migrate.changeset.constraint import UniqueConstraint
LOG = logging.getLogger(__name__)
meta = MetaData()
def upgrade(migrate_engine):
meta.bind = migrate_engine
dialect = migrate_engine.url.get_dialect().name
if dialect.startswith('sqlite'):
domains_table = Table('domains', meta, autoload=True)
servers_table = Table('servers', meta, autoload=True)
# Add missing multi-column unique index
constraint = UniqueConstraint('name', 'deleted',
name='unique_domain_name',
table=domains_table)
constraint.create()
# Add a missing unique index
constraint = UniqueConstraint('name',
name='unique_server_name',
table=servers_table)
constraint.create()
def downgrade(migrate_engine):
meta.bind = migrate_engine
dialect = migrate_engine.url.get_dialect().name
if dialect.startswith('sqlite'):
domains_table = Table('domains', meta, autoload=True)
servers_table = Table('servers', meta, autoload=True)
# Add a new multi-column unique index
constraint = UniqueConstraint('name', 'deleted',
name='unique_domain_name',
table=domains_table)
constraint.drop()
# Add a missing unique index
constraint = UniqueConstraint('name',
name='unique_server_name',
table=servers_table)
constraint.drop()

View File

@ -1,48 +0,0 @@
# Copyright 2013 Rackspace Hosting
#
# Author: Tim Simmons <tim.simmons@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 sqlalchemy import MetaData, Table, Column, Unicode
from designate.openstack.common import log as logging
LOG = logging.getLogger(__name__)
meta = MetaData()
def upgrade(migrate_engine):
meta.bind = migrate_engine
domains_table = Table('domains', meta, autoload=True)
records_table = Table('records', meta, autoload=True)
# Add in description columns in domain/record databases
domain_description = Column('description', Unicode(160),
nullable=True)
domain_description.create(domains_table, populate_default=True)
record_description = Column('description', Unicode(160),
nullable=True)
record_description.create(records_table, populate_default=True)
def downgrade(migrate_engine):
meta.bind = migrate_engine
domains_table = Table('domains', meta, autoload=True)
domains_table.c.description.drop()
record_table = Table('records', meta, autoload=True)
record_table.c.description.drop()

View File

@ -1,43 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
from sqlalchemy.schema import MetaData
meta = MetaData()
def upgrade(migrate_engine):
meta.bind = migrate_engine
if migrate_engine.name == "mysql":
tables = ['domains', 'quotas', 'records', 'servers', 'tsigkeys']
migrate_engine.execute("SET foreign_key_checks = 0")
for table in tables:
migrate_engine.execute(
"ALTER TABLE %s ENGINE=InnoDB" % table)
migrate_engine.execute(
"ALTER TABLE %s CONVERT TO CHARACTER SET utf8" % table)
migrate_engine.execute("SET foreign_key_checks = 1")
migrate_engine.execute(
"ALTER DATABASE %s DEFAULT CHARACTER SET utf8" %
migrate_engine.url.database)
def downgrade(migrate_engine):
# utf8/InnoDB tables are backward compatible.. No need to revert.
pass

View File

@ -1,58 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Graham Hayes <graham.hayes@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.
from sqlalchemy import MetaData, Table, Column, Enum
from designate.openstack.common import log as logging
LOG = logging.getLogger(__name__)
RESOURCE_STATUSES = ['ACTIVE', 'PENDING', 'DELETED']
meta = MetaData()
def upgrade(migrate_engine):
meta.bind = migrate_engine
domains_table = Table('domains', meta, autoload=True)
records_table = Table('records', meta, autoload=True)
# Add a domain & record creation status for async backends
domain_statuses = Enum(name='domain_statuses', metadata=meta,
*RESOURCE_STATUSES)
domain_statuses.create()
record_statuses = Enum(name='record_statuses', metadata=meta,
*RESOURCE_STATUSES)
record_statuses.create()
domain_status = Column('status', domain_statuses, nullable=False,
server_default='ACTIVE', default='ACTIVE')
record_status = Column('status', record_statuses, nullable=False,
server_default='ACTIVE', default='ACTIVE')
domain_status.create(domains_table, populate_default=True)
record_status.create(records_table, populate_default=True)
def downgrade(migrate_engine):
meta.bind = migrate_engine
domains_table = Table('domains', meta, autoload=True)
records_table = Table('records', meta, autoload=True)
domains_table.c.status.drop()
records_table.c.status.drop()

View File

@ -1,30 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
#
# This is a placeholder for Havana backports.
# Do not use this number for new Icehouse work. New Icehouse 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
def downgrade(migration_engine):
pass

View File

@ -1,30 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
#
# This is a placeholder for Havana backports.
# Do not use this number for new Icehouse work. New Icehouse 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
def downgrade(migration_engine):
pass

View File

@ -1,30 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
#
# This is a placeholder for Havana backports.
# Do not use this number for new Icehouse work. New Icehouse 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
def downgrade(migration_engine):
pass

View File

@ -1,30 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
#
# This is a placeholder for Havana backports.
# Do not use this number for new Icehouse work. New Icehouse 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
def downgrade(migration_engine):
pass

View File

@ -1,30 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
#
# This is a placeholder for Havana backports.
# Do not use this number for new Icehouse work. New Icehouse 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
def downgrade(migration_engine):
pass

View File

@ -1,30 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
#
# This is a placeholder for Havana backports.
# Do not use this number for new Icehouse work. New Icehouse 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
def downgrade(migration_engine):
pass

View File

@ -1,30 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
#
# This is a placeholder for Havana backports.
# Do not use this number for new Icehouse work. New Icehouse 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
def downgrade(migration_engine):
pass

View File

@ -1,30 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
#
# This is a placeholder for Havana backports.
# Do not use this number for new Icehouse work. New Icehouse 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
def downgrade(migration_engine):
pass

View File

@ -1,30 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
#
# This is a placeholder for Havana backports.
# Do not use this number for new Icehouse work. New Icehouse 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
def downgrade(migration_engine):
pass

View File

@ -1,30 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
#
# This is a placeholder for Havana backports.
# Do not use this number for new Icehouse work. New Icehouse 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
def downgrade(migration_engine):
pass

View File

@ -1,52 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
from sqlalchemy import MetaData, Table, Column, String
from sqlalchemy.sql import select
from designate.openstack.common import log as logging
LOG = logging.getLogger(__name__)
meta = MetaData()
def upgrade(migrate_engine):
meta.bind = migrate_engine
domains_table = Table('domains', meta, autoload=True)
records_table = Table('records', meta, autoload=True)
# Add the tenant_id column
tenant_id = Column('tenant_id', String(36), default=None, nullable=True)
tenant_id.create(records_table, populate_default=True)
# Populate the tenant_id column
inner_select = select([domains_table.c.tenant_id])\
.where(domains_table.c.id == records_table.c.domain_id)\
.as_scalar()
records_table.update()\
.values(tenant_id=inner_select)\
.execute()
def downgrade(migrate_engine):
meta.bind = migrate_engine
records_table = Table('records', meta, autoload=True)
# Drop the tenant_id column
records_table.c.tenant_id.drop()

View File

@ -1,167 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
import hashlib
from sqlalchemy import ForeignKey, Enum, Integer, String, DateTime, Unicode
from sqlalchemy import func
from sqlalchemy.sql import select
from sqlalchemy.schema import Table, Column, MetaData
from migrate import ForeignKeyConstraint
from migrate.changeset.constraint import UniqueConstraint
from designate.openstack.common import timeutils
from designate import utils
from designate.sqlalchemy.types import UUID
RECORD_TYPES = ['A', 'AAAA', 'CNAME', 'MX', 'SRV', 'TXT', 'SPF', 'NS', 'PTR',
'SSHFP']
meta = MetaData()
recordsets_table = Table(
'recordsets',
meta,
Column('id', UUID(), default=utils.generate_uuid, primary_key=True),
Column('created_at', DateTime(), default=timeutils.utcnow),
Column('updated_at', DateTime(), onupdate=timeutils.utcnow),
Column('version', Integer(), default=1, nullable=False),
Column('tenant_id', String(36), default=None, nullable=True),
Column('domain_id', UUID, ForeignKey('domains.id'), nullable=False),
Column('name', String(255), nullable=False),
Column('type', Enum(name='recordset_types', *RECORD_TYPES),
nullable=False),
Column('ttl', Integer, default=None, nullable=True),
Column('description', Unicode(160), nullable=True),
UniqueConstraint('domain_id', 'name', 'type', name='unique_recordset'),
mysql_engine='INNODB',
mysql_charset='utf8')
def _build_hash(recordset_id, record):
md5 = hashlib.md5()
md5.update("%s:%s:%s" % (recordset_id, record.data, record.priority))
return md5.hexdigest()
def upgrade(migrate_engine):
meta.bind = migrate_engine
records_table = Table('records', meta, autoload=True)
# We need to autoload the domains table for the FK to succeed.
Table('domains', meta, autoload=True)
# Prepare an empty dict to cache (domain_id, name, type) tuples to
# RRSet id's
cache = {}
# Create the recordsets_table table
recordsets_table.create()
# NOTE(kiall): Since we need a unique UUID for each recordset, and need
# to maintain cross DB compatibility, we're stuck doing this
# in code rather than an
# INSERT INTO recordsets_table SELECT (..) FROM records;
results = select(
columns=[
records_table.c.tenant_id,
records_table.c.domain_id,
records_table.c.name,
records_table.c.type,
func.min(records_table.c.ttl).label('ttl'),
func.min(records_table.c.created_at).label('created_at'),
func.max(records_table.c.updated_at).label('updated_at')
],
group_by=[
records_table.c.tenant_id,
records_table.c.domain_id,
records_table.c.name,
records_table.c.type
]
).execute()
for result in results:
# Create the new RecordSet and remember it's id
pk = recordsets_table.insert().execute(
tenant_id=result.tenant_id,
domain_id=result.domain_id,
name=result.name,
type=result.type,
ttl=result.ttl,
created_at=result.created_at,
updated_at=result.updated_at
).inserted_primary_key[0]
# Cache the ID for later
cache_key = "%s.%s.%s" % (result.domain_id, result.name, result.type)
cache[cache_key] = pk
# Add the recordset column to the records table
record_recordset_id = Column('recordset_id', UUID,
default=None,
nullable=True)
record_recordset_id.create(records_table, populate_default=True)
# Fetch all the records
# TODO(kiall): Batch this..
results = select(
columns=[
records_table.c.id,
records_table.c.domain_id,
records_table.c.name,
records_table.c.type,
records_table.c.data,
records_table.c.priority
]
).execute()
# Update each result with the approperiate recordset_id, and refresh
# the hash column to reflect the removal of several fields.
for result in results:
cache_key = "%s.%s.%s" % (result.domain_id, result.name,
result.type)
recordset_id = cache[cache_key]
new_hash = _build_hash(recordset_id, result)
records_table.update()\
.where(records_table.c.id == result.id)\
.values(recordset_id=cache[cache_key], hash=new_hash)\
.execute()
# Now that the records.recordset_id field is populated, lets ensure the
# column is not nullable and is a FK to the records table.
records_table.c.recordset_id.alter(nullable=False)
ForeignKeyConstraint(columns=[records_table.c.recordset_id],
refcolumns=[recordsets_table.c.id],
ondelete='CASCADE',
name='fkey_records_recordset_id').create()
# Finally, drop the now-defunct columns from the records table
records_table.c.name.drop()
records_table.c.type.drop()
records_table.c.ttl.drop()
def downgrade(migrate_engine):
meta.bind = migrate_engine
raise Exception('There is no undo')

View File

@ -1,51 +0,0 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
import logging
from sqlalchemy import MetaData, Table
from migrate.changeset.constraint import UniqueConstraint
LOG = logging.getLogger(__name__)
meta = MetaData()
def upgrade(migrate_engine):
meta.bind = migrate_engine
dialect = migrate_engine.url.get_dialect().name
if dialect.startswith('sqlite'):
records_table = Table('records', meta, autoload=True)
# Add missing unique index
constraint = UniqueConstraint('hash',
name='unique_recordset',
table=records_table)
constraint.create()
def downgrade(migrate_engine):
meta.bind = migrate_engine
dialect = migrate_engine.url.get_dialect().name
if dialect.startswith('sqlite'):
records_table = Table('records', meta, autoload=True)
# Drop the unique index
constraint = UniqueConstraint('hash',
name='unique_recordset',
table=records_table)
constraint.drop()

View File

@ -1,62 +0,0 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Author: Endre Karlson <endre.karlson@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.
#
# This is a placeholder for Havana backports.
# Do not use this number for new Icehouse work. New Icehouse 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
from sqlalchemy import MetaData, Table, Column, Unicode
from designate.openstack.common import log as logging
LOG = logging.getLogger(__name__)
meta = MetaData()
def upgrade(migrate_engine):
meta.bind = migrate_engine
records_table = Table('records', meta, autoload=True)
record_managed_tenant_id = Column(
'managed_tenant_id', Unicode(36), default=None, nullable=True)
record_managed_tenant_id.create(records_table, populate_default=True)
record_managed_resource_region = Column(
'managed_resource_region', Unicode(100), default=None, nullable=True)
record_managed_resource_region.create(records_table, populate_default=True)
record_managed_extra = Column(
'managed_extra', Unicode(100), default=None, nullable=True)
record_managed_extra.create(records_table, populate_default=True)
def downgrade(migrate_engine):
meta.bind = migrate_engine
records_table = Table('records', meta, autoload=True)
record_managed_tenant_id = Column(
'managed_tenant_id', Unicode(36), default=None, nullable=True)
record_managed_tenant_id.drop(records_table)
record_managed_resource_region = Column(
'managed_resource_region', Unicode(100), default=None, nullable=True)
record_managed_resource_region.drop(records_table)
record_extra = Column(
'managed_extra', Unicode(100), default=None, nullable=True)
record_extra.drop(records_table)

View File

@ -1,51 +0,0 @@
# Copyright (c) 2014 Rackspace Hosting
# All Rights Reserved.
#
# 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 Integer, String, DateTime, Unicode
from sqlalchemy.schema import Table, Column, MetaData
from designate.openstack.common import timeutils
from designate import utils
from designate.sqlalchemy.types import UUID
from designate.openstack.common import log as logging
LOG = logging.getLogger(__name__)
meta = MetaData()
tlds_table = Table(
'tlds',
meta,
Column('id', UUID(), default=utils.generate_uuid, primary_key=True),
Column('created_at', DateTime(), default=timeutils.utcnow),
Column('updated_at', DateTime(), onupdate=timeutils.utcnow),
Column('version', Integer(), default=1, nullable=False),
Column('name', String(255), nullable=False, unique=True),
Column('description', Unicode(160), nullable=True),
mysql_engine='INNODB',
mysql_charset='utf8')
def upgrade(migrate_engine):
meta.bind = migrate_engine
tlds_table.create()
def downgrade(migrate_engine):
meta.bind = migrate_engine
tlds_table.drop()

View File

@ -1,56 +0,0 @@
# Copyright (c) 2014 Rackspace Hosting
# All Rights Reserved.
#
# Author: Betsy Luzader <betsy.luzader@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 sqlalchemy import Integer, String, DateTime
from sqlalchemy.schema import Table, Column, MetaData
from designate.openstack.common import timeutils
from designate import utils
from designate.sqlalchemy.types import UUID
meta = MetaData()
blacklists = Table(
'blacklists',
meta,
Column('id', UUID(), default=utils.generate_uuid,
primary_key=True),
Column('created_at', DateTime(),
default=timeutils.utcnow),
Column('updated_at', DateTime(),
onupdate=timeutils.utcnow),
Column('version', Integer(), default=1,
nullable=False),
Column('pattern', String(255), nullable=False,
unique=True),
Column('description', String(160),
nullable=True),
mysql_engine='INNODB',
mysql_charset='utf8')
def upgrade(migrate_engine):
meta.bind = migrate_engine
blacklists.create()
def downgrade(migrate_engine):
meta.bind = migrate_engine
blacklists.drop()

View File

@ -0,0 +1,231 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@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.
from sqlalchemy import Integer, String, DateTime, Unicode, UniqueConstraint, \
CHAR, Enum, ForeignKeyConstraint, Text, Boolean
from sqlalchemy.schema import Table, Column, MetaData
from designate.sqlalchemy.types import UUID
RESOURCE_STATUSES = ['ACTIVE', 'PENDING', 'DELETED']
RECORD_TYPES = ['A', 'AAAA', 'CNAME', 'MX', 'SRV', 'TXT', 'SPF', 'NS', 'PTR',
'SSHFP']
TSIG_ALGORITHMS = ['hmac-md5', 'hmac-sha1', 'hmac-sha224', 'hmac-sha256',
'hmac-sha384', 'hmac-sha512']
meta = MetaData()
blacklists = Table('blacklists', meta,
Column('id', UUID(), primary_key=True),
Column('created_at', DateTime()),
Column('updated_at', DateTime()),
Column('version', Integer(), nullable=False),
Column('pattern', String(255), nullable=False),
Column('description', Unicode(160)),
UniqueConstraint('pattern', name='pattern'),
mysql_engine='INNODB',
mysql_charset='utf8')
domains = Table('domains', meta,
Column('id', UUID(), primary_key=True),
Column('created_at', DateTime()),
Column('updated_at', DateTime()),
Column('version', Integer(), nullable=False),
Column('tenant_id', String(36)),
Column('name', String(255), nullable=False),
Column('email', String(255), nullable=False),
Column('ttl', Integer(), 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()),
Column('serial', Integer(), nullable=False, server_default="1"),
Column('deleted', CHAR(32), nullable=False, server_default='0'),
Column('deleted_at', DateTime),
Column('description', Unicode(160)),
Column('status', Enum(name='domain_statuses', *RESOURCE_STATUSES),
nullable=False, server_default='ACTIVE'),
UniqueConstraint('name', 'deleted', name='unique_domain_name'),
ForeignKeyConstraint(['parent_domain_id'], ['domains.id']),
mysql_engine='INNODB',
mysql_charset='utf8')
quotas = Table('quotas', meta,
Column('id', UUID(), primary_key=True),
Column('created_at', DateTime()),
Column('updated_at', DateTime()),
Column('version', Integer(), nullable=False),
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')
records = Table('records', meta,
Column('id', UUID(), primary_key=True),
Column('created_at', DateTime()),
Column('updated_at', DateTime()),
Column('version', Integer(), nullable=False),
Column('data', Text(), nullable=False),
Column('priority', Integer()),
Column('domain_id', UUID(), nullable=False),
Column('managed', Boolean()),
Column('managed_resource_type', String(50)),
Column('managed_resource_id', UUID()),
Column('managed_plugin_name', String(50)),
Column('managed_plugin_type', String(50)),
Column('hash', String(32), nullable=False),
Column('description', Unicode(160)),
Column('status', Enum(name='record_statuses', *RESOURCE_STATUSES),
nullable=False, server_default='ACTIVE'),
Column('tenant_id', String(36)),
Column('recordset_id', UUID(), nullable=False),
Column('managed_tenant_id', String(36)),
Column('managed_resource_region', String(100)),
Column('managed_extra', String(100)),
UniqueConstraint('hash', name='unique_record'),
ForeignKeyConstraint(['domain_id'], ['domains.id'], ondelete='CASCADE',
name='fkey_records_domain_id'),
ForeignKeyConstraint(['recordset_id'], ['recordsets.id'],
ondelete='CASCADE', name='fkey_records_recordset_id'),
mysql_engine='INNODB',
mysql_charset='utf8')
recordsets = Table('recordsets', meta,
Column('id', UUID(), primary_key=True),
Column('created_at', DateTime()),
Column('updated_at', DateTime()),
Column('version', Integer(), nullable=False),
Column('tenant_id', String(36)),
Column('domain_id', UUID(), nullable=False),
Column('name', String(255), nullable=False),
Column('type', Enum(name='recordset_types', *RECORD_TYPES),
nullable=False),
Column('ttl', Integer()),
Column('description', Unicode(160)),
UniqueConstraint('domain_id', 'name', 'type', name='unique_recordset'),
ForeignKeyConstraint(['domain_id'], ['domains.id']),
mysql_engine='INNODB',
mysql_charset='utf8')
servers = Table('servers', meta,
Column('id', UUID(), primary_key=True),
Column('created_at', DateTime()),
Column('updated_at', DateTime()),
Column('version', Integer(), nullable=False),
Column('name', String(255), nullable=False),
UniqueConstraint('name', name='unique_server_name'),
mysql_engine='INNODB',
mysql_charset='utf8')
tlds = Table('tlds', meta,
Column('id', UUID(), primary_key=True),
Column('created_at', DateTime()),
Column('updated_at', DateTime()),
Column('version', Integer(), nullable=False),
Column('name', String(255), nullable=False),
Column('description', Unicode(160)),
UniqueConstraint('name', name='unique_tld_name'),
mysql_engine='INNODB',
mysql_charset='utf8')
tsigkeys = Table('tsigkeys', meta,
Column('id', UUID(), primary_key=True),
Column('created_at', DateTime()),
Column('updated_at', DateTime()),
Column('version', Integer(), nullable=False),
Column('name', String(255), nullable=False),
Column('algorithm', Enum(name='tsig_algorithms', *TSIG_ALGORITHMS),
nullable=False),
Column('secret', String(255), nullable=False),
UniqueConstraint('name', name='unique_tsigkey_name'),
mysql_engine='INNODB',
mysql_charset='utf8')
def upgrade(migrate_engine):
meta.bind = migrate_engine
with migrate_engine.begin() as conn:
if migrate_engine.name == "mysql":
conn.execute("SET foreign_key_checks = 0;")
elif migrate_engine.name == "postgresql":
conn.execute("SET CONSTRAINTS ALL DEFERRED;")
domains.create(conn)
recordsets.create(conn)
records.create(conn)
blacklists.create(conn)
quotas.create(conn)
servers.create(conn)
tlds.create(conn)
tsigkeys.create(conn)
if migrate_engine.name == "mysql":
conn.execute("SET foreign_key_checks = 1;")
def downgrade(migrate_engine):
meta.bind = migrate_engine
with migrate_engine.begin() as conn:
if migrate_engine.name == "mysql":
conn.execute("SET foreign_key_checks = 0;")
elif migrate_engine.name == "postgresql":
conn.execute("SET CONSTRAINTS ALL DEFERRED;")
tsigkeys.drop()
tlds.drop()
servers.drop()
quotas.drop()
blacklists.drop()
records.drop()
recordsets.drop()
domains.drop()
if migrate_engine.name == "mysql":
conn.execute("SET foreign_key_checks = 1;")

View File

@ -54,7 +54,7 @@ def upgrade(migrate_engine):
'PTR', 'SSHFP', 'SOA']
recordsets_table = Table('recordsets', meta, autoload=True)
recordsets_table.c.type.alter(type=Enum(name='record_types',
recordsets_table.c.type.alter(type=Enum(name='recordset_types',
*RECORD_TYPES))
# Re-add constraint for sqlite

View File

@ -1,4 +1,4 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# Author: Kiall Mac Innes <kiall@hp.com>
#
@ -13,21 +13,24 @@
# 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
from sqlalchemy import Text
from sqlalchemy.schema import Table, MetaData
meta = MetaData()
# No downgrade possible - MySQL may have performed an implicit conversion from
# text -> mediumtext depending on the particular deployments server-wide
# default charset during migration 21's conversion to utf-8.
def upgrade(migrate_engine):
meta.bind = migrate_engine
domains_table = Table('domains', meta, autoload=True)
# Aleady deleted domains will have an incorrect value in the deleted
# column - fix them up.
domains_table.update().where(domains_table.c.deleted != '0')\
.values(deleted=domains_table.c.id)\
.execute()
if migrate_engine.name == "mysql":
records_table = Table('records', meta, autoload=True)
records_table.c.data.alter(type=Text())
def downgrade(migrate_engine):

View File

@ -21,13 +21,10 @@ import shutil
import tempfile
import fixtures
from migrate.versioning import api as versioning_api
from migrate.versioning import repository
from oslotest import base
from oslo.config import cfg
from oslo.messaging import conffixture as messaging_fixture
from oslo.messaging.notify import _impl_test as test_notifier
import sqlalchemy
from testtools import testcase
from designate.openstack.common import log as logging
@ -41,6 +38,8 @@ from designate import exceptions
from designate.network_api import fake as fake_network_api
from designate import network_api
from designate import objects
from designate.manage import database as manage_database
from designate.sqlalchemy import utils as sqlalchemy_utils
LOG = logging.getLogger(__name__)
@ -95,9 +94,10 @@ class DatabaseFixture(fixtures.Fixture):
fixtures = {}
@staticmethod
def get_fixture(repo_path):
def get_fixture(repo_path, init_version=None):
if repo_path not in DatabaseFixture.fixtures:
DatabaseFixture.fixtures[repo_path] = DatabaseFixture(repo_path)
DatabaseFixture.fixtures[repo_path] = DatabaseFixture(
repo_path, init_version)
return DatabaseFixture.fixtures[repo_path]
def _mktemp(self):
@ -105,13 +105,19 @@ class DatabaseFixture(fixtures.Fixture):
dir='/tmp')
return path
def __init__(self, repo_path):
def __init__(self, repo_path, init_version=None):
super(DatabaseFixture, self).__init__()
# Create the Golden DB
self.golden_db = self._mktemp()
engine = sqlalchemy.create_engine('sqlite:///%s' % self.golden_db)
repo = repository.Repository(repo_path)
versioning_api.version_control(engine, repository=repo)
versioning_api.upgrade(engine, repository=repo)
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)
# Prepare the Working Copy DB
self.working_copy = self._mktemp()
self.url = 'sqlite:///%s' % self.working_copy
@ -274,7 +280,8 @@ class TestCase(base.BaseTestCase):
'impl_sqlalchemy',
'migrate_repo'))
self.db_fixture = self.useFixture(
DatabaseFixture.get_fixture(REPOSITORY))
DatabaseFixture.get_fixture(
REPOSITORY, manage_database.INIT_VERSION))
self.config(
connection=self.db_fixture.url,
connection_debug=100,