From 2f851340ee8969193b9dcc1913401aa9b33c5d97 Mon Sep 17 00:00:00 2001 From: Dolph Mathews Date: Fri, 30 Nov 2012 12:52:26 -0600 Subject: Split endpoint records in SQL by interface This migrates the SQL backend such that v2 endpoints containing up to 3 URL's (public, internal and admin) stored in 'extra' are split into unique endpoints. Because legacy "endpoints" (each having publicUrl, internalUrl and adminUrl) are no longer conceptually identical to v3's "endpoints" (each having an interface and a url), new ID's are assigned to each entity and each API continues to operate using with independent sets of endpoint ID's. Endpoints created on the v3 API are not exposed on the v2 API. Change-Id: I2ba59d55907313ae65e908585fc49be0c4ce899a --- .../sql/migrate_repo/versions/010_endpoints_v3.py | 54 ++++++++++++ .../versions/011_populate_endpoint_type.py | 96 ++++++++++++++++++++++ .../versions/012_drop_legacy_endpoints.py | 51 ++++++++++++ 3 files changed, 201 insertions(+) create mode 100644 keystone/common/sql/migrate_repo/versions/010_endpoints_v3.py create mode 100644 keystone/common/sql/migrate_repo/versions/011_populate_endpoint_type.py create mode 100644 keystone/common/sql/migrate_repo/versions/012_drop_legacy_endpoints.py (limited to 'keystone/common') diff --git a/keystone/common/sql/migrate_repo/versions/010_endpoints_v3.py b/keystone/common/sql/migrate_repo/versions/010_endpoints_v3.py new file mode 100644 index 00000000..2d919aab --- /dev/null +++ b/keystone/common/sql/migrate_repo/versions/010_endpoints_v3.py @@ -0,0 +1,54 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 OpenStack LLC +# +# 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 migrate +import sqlalchemy as sql + + +def upgrade(migrate_engine): + """Create API-version specific endpoint tables.""" + meta = sql.MetaData() + meta.bind = migrate_engine + + legacy_table = sql.Table('endpoint', meta, autoload=True) + legacy_table.rename('endpoint_v2') + + new_table = sql.Table( + 'endpoint_v3', + meta, + sql.Column('id', sql.String(64), primary_key=True), + sql.Column('legacy_endpoint_id', sql.String(64)), + sql.Column('interface', sql.String(8), nullable=False), + sql.Column('region', sql.String(255)), + sql.Column('service_id', + sql.String(64), + sql.ForeignKey('service.id'), + nullable=False), + sql.Column('url', sql.Text(), nullable=False), + sql.Column('extra', sql.Text())) + new_table.create(migrate_engine, checkfirst=True) + + +def downgrade(migrate_engine): + """Replace API-version specific endpoint tables with one based on v2.""" + meta = sql.MetaData() + meta.bind = migrate_engine + + new_table = sql.Table('endpoint_v3', meta, autoload=True) + new_table.drop() + + legacy_table = sql.Table('endpoint_v2', meta, autoload=True) + legacy_table.rename('endpoint') diff --git a/keystone/common/sql/migrate_repo/versions/011_populate_endpoint_type.py b/keystone/common/sql/migrate_repo/versions/011_populate_endpoint_type.py new file mode 100644 index 00000000..ae41d1f3 --- /dev/null +++ b/keystone/common/sql/migrate_repo/versions/011_populate_endpoint_type.py @@ -0,0 +1,96 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 OpenStack LLC +# +# 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 json +import uuid + +import sqlalchemy as sql +from sqlalchemy import orm + + +ENDPOINT_TYPES = ['public', 'internal', 'admin'] + + +def upgrade(migrate_engine): + """Split each legacy endpoint into seperate records for each interface.""" + meta = sql.MetaData() + meta.bind = migrate_engine + + legacy_table = sql.Table('endpoint_v2', meta, autoload=True) + new_table = sql.Table('endpoint_v3', meta, autoload=True) + + session = orm.sessionmaker(bind=migrate_engine)() + for ref in session.query(legacy_table).all(): + # pull urls out of extra + extra = json.loads(ref.extra) + urls = dict((i, extra.pop('%surl' % i)) for i in ENDPOINT_TYPES) + + for interface in ENDPOINT_TYPES: + endpoint = { + 'id': uuid.uuid4().hex, + 'legacy_endpoint_id': ref.id, + 'interface': interface, + 'region': ref.region, + 'service_id': ref.service_id, + 'url': urls[interface], + 'extra': json.dumps(extra), + } + session.execute( + 'INSERT INTO `%s` (%s) VALUES (%s)' % ( + new_table.name, + ', '.join('%s' % k for k in endpoint.keys()), + ', '.join("'%s'" % v for v in endpoint.values()))) + session.commit() + + +def downgrade(migrate_engine): + """Re-create the v2 endpoints table based on v3 endpoints.""" + meta = sql.MetaData() + meta.bind = migrate_engine + + legacy_table = sql.Table('endpoint_v2', meta, autoload=True) + new_table = sql.Table('endpoint_v3', meta, autoload=True) + + session = orm.sessionmaker(bind=migrate_engine)() + for ref in session.query(new_table).all(): + extra = json.loads(ref.extra) + extra['%surl' % ref.interface] = ref.url + endpoint = { + 'id': ref.legacy_endpoint_id, + 'region': ref.region, + 'service_id': ref.service_id, + 'extra': json.dumps(extra), + } + + try: + session.execute( + 'INSERT INTO `%s` (%s) VALUES (%s)' % ( + legacy_table.name, + ', '.join('%s' % k for k in endpoint.keys()), + ', '.join("'%s'" % v for v in endpoint.values()))) + except sql.exc.IntegrityError: + q = session.query(legacy_table) + q = q.filter_by(id=ref.legacy_endpoint_id) + legacy_ref = q.one() + extra = json.loads(legacy_ref.extra) + extra['%surl' % ref.interface] = ref.url + + session.execute( + 'UPDATE `%s` SET extra=\'%s\' WHERE id="%s"' % ( + legacy_table.name, + json.dumps(extra), + legacy_ref.id)) + session.commit() diff --git a/keystone/common/sql/migrate_repo/versions/012_drop_legacy_endpoints.py b/keystone/common/sql/migrate_repo/versions/012_drop_legacy_endpoints.py new file mode 100644 index 00000000..e98fbb40 --- /dev/null +++ b/keystone/common/sql/migrate_repo/versions/012_drop_legacy_endpoints.py @@ -0,0 +1,51 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 OpenStack LLC +# +# 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 migrate +import sqlalchemy as sql + + +def upgrade(migrate_engine): + """Replace API-version specific endpoint tables with one based on v3.""" + meta = sql.MetaData() + meta.bind = migrate_engine + + legacy_table = sql.Table('endpoint_v2', meta, autoload=True) + legacy_table.drop() + + new_table = sql.Table('endpoint_v3', meta, autoload=True) + new_table.rename('endpoint') + + +def downgrade(migrate_engine): + """Create API-version specific endpoint tables.""" + meta = sql.MetaData() + meta.bind = migrate_engine + + new_table = sql.Table('endpoint', meta, autoload=True) + new_table.rename('endpoint_v3') + + legacy_table = sql.Table( + 'endpoint_v2', + meta, + sql.Column('id', sql.String(64), primary_key=True), + sql.Column('region', sql.String(255)), + sql.Column('service_id', + sql.String(64), + sql.ForeignKey('service.id'), + nullable=False), + sql.Column('extra', sql.Text())) + legacy_table.create(migrate_engine, checkfirst=True) -- cgit