Changes "key" column in image_properties to "name".
As with all things migration, this was a pain in the ass. MySQL doesn't support RENAME INDEX, so a custom SQL migration file for it was needed. Likewise, SQLite doesn't support either RENAME INDEX or ALTER TABLE CHANGE COLUMN, so it also needed a custom migration script.
This commit is contained in:
parent
2a4a88330c
commit
c14827491b
|
@ -243,22 +243,22 @@ def _set_properties_for_image(context, image_ref, properties, session=None):
|
|||
"""
|
||||
orig_properties = {}
|
||||
for prop_ref in image_ref.properties:
|
||||
orig_properties[prop_ref.key] = prop_ref
|
||||
orig_properties[prop_ref.name] = prop_ref
|
||||
|
||||
for key, value in properties.iteritems():
|
||||
for name, value in properties.iteritems():
|
||||
prop_values = {'image_id': image_ref.id,
|
||||
'key': key,
|
||||
'name': name,
|
||||
'value': value}
|
||||
if key in orig_properties:
|
||||
prop_ref = orig_properties[key]
|
||||
if name in orig_properties:
|
||||
prop_ref = orig_properties[name]
|
||||
image_property_update(context, prop_ref, prop_values,
|
||||
session=session)
|
||||
else:
|
||||
image_property_create(context, prop_values, session=session)
|
||||
|
||||
for key in orig_properties.keys():
|
||||
if not key in properties:
|
||||
prop_ref = orig_properties[key]
|
||||
for name in orig_properties.keys():
|
||||
if not name in properties:
|
||||
prop_ref = orig_properties[name]
|
||||
image_property_delete(context, prop_ref, session=session)
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2011 OpenStack LLC.
|
||||
# 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 migrate.changeset import *
|
||||
from sqlalchemy import *
|
||||
from sqlalchemy.sql import and_, not_
|
||||
|
||||
from glance.registry.db.migrate_repo.schema import (
|
||||
Boolean, DateTime, Integer, String, Text, from_migration_import)
|
||||
|
||||
|
||||
def get_images_table(meta):
|
||||
"""
|
||||
No changes to the image properties table from 002...
|
||||
"""
|
||||
(get_images_table,) = from_migration_import(
|
||||
'004_add_checksum', ['get_images_table'])
|
||||
|
||||
images = get_images_table(meta)
|
||||
return images
|
||||
|
||||
|
||||
def get_image_properties_table(meta):
|
||||
"""
|
||||
Returns the Table object for the image_properties table that
|
||||
corresponds to the image_properties table definition of this version.
|
||||
"""
|
||||
(get_images_table,) = from_migration_import(
|
||||
'004_add_checksum', ['get_images_table'])
|
||||
|
||||
images = get_images_table(meta)
|
||||
|
||||
image_properties = Table('image_properties', meta,
|
||||
Column('id', Integer(), primary_key=True, nullable=False),
|
||||
Column('image_id', Integer(), ForeignKey('images.id'), nullable=False,
|
||||
index=True),
|
||||
Column('name', String(255), nullable=False),
|
||||
Column('value', Text()),
|
||||
Column('created_at', DateTime(), nullable=False),
|
||||
Column('updated_at', DateTime()),
|
||||
Column('deleted_at', DateTime()),
|
||||
Column('deleted', Boolean(), nullable=False, default=False,
|
||||
index=True),
|
||||
UniqueConstraint('image_id', 'name'),
|
||||
mysql_engine='InnoDB',
|
||||
useexisting=True)
|
||||
|
||||
return image_properties
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
||||
(get_image_properties_table,) = from_migration_import(
|
||||
'004_add_checksum', ['get_image_properties_table'])
|
||||
image_properties = get_image_properties_table(meta)
|
||||
|
||||
index = Index('ix_image_properties_image_id_get',
|
||||
image_properties.c.image_id,
|
||||
image_properties.c.key)
|
||||
index.rename('ix_image_properties_image_id_name')
|
||||
|
||||
image_properties = get_image_properties_table(meta)
|
||||
image_properties.columns['key'].alter(name="name")
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
||||
image_properties = get_image_properties_table(meta)
|
||||
|
||||
index = Index('ix_image_properties_image_id_name',
|
||||
image_properties.c.image_id,
|
||||
image_properties.c.name)
|
||||
index.rename('ix_image_properties_image_id_key')
|
||||
|
||||
image_properties.columns['name'].alter(name="key")
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* This file is necessary because MySQL does not support
|
||||
* renaming indexes.
|
||||
*/
|
||||
DROP INDEX ix_image_properties_image_id_name ON image_properties;
|
||||
|
||||
/* Rename the `key` column to `name` */
|
||||
ALTER TABLE image_properties
|
||||
CHANGE COLUMN name `key` VARCHAR(255) NOT NULL;
|
||||
|
||||
CREATE UNIQUE INDEX ix_image_properties_image_id_key ON image_properties (image_id, key);
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* This file is necessary because MySQL does not support
|
||||
* renaming indexes.
|
||||
*/
|
||||
DROP INDEX ix_image_properties_image_id_key ON image_properties;
|
||||
|
||||
/* Rename the `key` column to `name` */
|
||||
ALTER TABLE image_properties
|
||||
CHANGE COLUMN `key` name VARCHAR(255) NOT NULL;
|
||||
|
||||
CREATE UNIQUE INDEX ix_image_properties_image_id_name ON image_properties (image_id, name);
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* This is necessary because SQLite does not support
|
||||
* RENAME INDEX or ALTER TABLE CHANGE COLUMN.
|
||||
*/
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TEMPORARY TABLE image_properties_backup (
|
||||
id INTEGER NOT NULL,
|
||||
image_id INTEGER NOT NULL,
|
||||
key VARCHAR(255) NOT NULL,
|
||||
value TEXT,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME,
|
||||
deleted_at DATETIME,
|
||||
deleted BOOLEAN NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
INSERT INTO image_properties_backup
|
||||
SELECT id, image_id, name, value, created_at, updated_at, deleted_at, deleted
|
||||
FROM image_properties;
|
||||
|
||||
DROP TABLE image_properties;
|
||||
|
||||
CREATE TABLE image_properties (
|
||||
id INTEGER NOT NULL,
|
||||
image_id INTEGER NOT NULL,
|
||||
key VARCHAR(255) NOT NULL,
|
||||
value TEXT,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME,
|
||||
deleted_at DATETIME,
|
||||
deleted BOOLEAN NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
CHECK (deleted IN (0, 1)),
|
||||
UNIQUE (image_id, key),
|
||||
FOREIGN KEY(image_id) REFERENCES images (id)
|
||||
);
|
||||
CREATE INDEX ix_image_properties_name ON image_properties (name);
|
||||
|
||||
INSERT INTO image_properties (id, image_id, key, value, created_at, updated_at, deleted_at, deleted)
|
||||
SELECT id, image_id, name, value, created_at, updated_at, deleted_at, deleted
|
||||
FROM image_properties_backup;
|
||||
|
||||
DROP TABLE image_properties_backup;
|
||||
COMMIT;
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* This is necessary because SQLite does not support
|
||||
* RENAME INDEX or ALTER TABLE CHANGE COLUMN.
|
||||
*/
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TEMPORARY TABLE image_properties_backup (
|
||||
id INTEGER NOT NULL,
|
||||
image_id INTEGER NOT NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
value TEXT,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME,
|
||||
deleted_at DATETIME,
|
||||
deleted BOOLEAN NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
INSERT INTO image_properties_backup
|
||||
SELECT id, image_id, key, value, created_at, updated_at, deleted_at, deleted
|
||||
FROM image_properties;
|
||||
|
||||
DROP TABLE image_properties;
|
||||
|
||||
CREATE TABLE image_properties (
|
||||
id INTEGER NOT NULL,
|
||||
image_id INTEGER NOT NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
value TEXT,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME,
|
||||
deleted_at DATETIME,
|
||||
deleted BOOLEAN NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
CHECK (deleted IN (0, 1)),
|
||||
UNIQUE (image_id, name),
|
||||
FOREIGN KEY(image_id) REFERENCES images (id)
|
||||
);
|
||||
CREATE INDEX ix_image_properties_name ON image_properties (name);
|
||||
|
||||
INSERT INTO image_properties (id, image_id, name, value, created_at, updated_at, deleted_at, deleted)
|
||||
SELECT id, image_id, name, value, created_at, updated_at, deleted_at, deleted
|
||||
FROM image_properties_backup;
|
||||
|
||||
DROP TABLE image_properties_backup;
|
||||
COMMIT;
|
|
@ -110,13 +110,11 @@ class Image(BASE, ModelBase):
|
|||
class ImageProperty(BASE, ModelBase):
|
||||
"""Represents an image properties in the datastore"""
|
||||
__tablename__ = 'image_properties'
|
||||
__table_args__ = (UniqueConstraint('image_id', 'key'), {})
|
||||
__table_args__ = (UniqueConstraint('image_id', 'name'), {})
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
image_id = Column(Integer, ForeignKey('images.id'), nullable=False)
|
||||
image = relationship(Image, backref=backref('properties'))
|
||||
|
||||
# FIXME(sirp): KEY is a reserved word in SQL, might be a good idea to
|
||||
# rename this column
|
||||
key = Column(String(255), index=True, nullable=False)
|
||||
name = Column(String(255), index=True, nullable=False)
|
||||
value = Column(Text)
|
||||
|
|
|
@ -199,7 +199,7 @@ def make_image_dict(image):
|
|||
# TODO(sirp): should this be a dict, or a list of dicts?
|
||||
# A plain dict is more convenient, but list of dicts would provide
|
||||
# access to created_at, etc
|
||||
properties = dict((p['key'], p['value'])
|
||||
properties = dict((p['name'], p['value'])
|
||||
for p in image['properties'] if not p['deleted'])
|
||||
|
||||
image_dict = _fetch_attrs(image, db_api.IMAGE_ATTRS)
|
||||
|
|
|
@ -285,7 +285,7 @@ def stub_out_registry_db_image_api(stubs):
|
|||
'checksum': None,
|
||||
'size': 13,
|
||||
'location': "swift://user:passwd@acct/container/obj.tar.0",
|
||||
'properties': [{'key': 'type',
|
||||
'properties': [{'name': 'type',
|
||||
'value': 'kernel',
|
||||
'deleted': False}]},
|
||||
{'id': 2,
|
||||
|
@ -330,7 +330,7 @@ def stub_out_registry_db_image_api(stubs):
|
|||
if 'properties' in values.keys():
|
||||
for k, v in values['properties'].items():
|
||||
p = {}
|
||||
p['key'] = k
|
||||
p['name'] = k
|
||||
p['value'] = v
|
||||
p['deleted'] = False
|
||||
p['created_at'] = datetime.datetime.utcnow()
|
||||
|
@ -356,7 +356,7 @@ def stub_out_registry_db_image_api(stubs):
|
|||
if 'properties' in values.keys():
|
||||
for k, v in values['properties'].items():
|
||||
p = {}
|
||||
p['key'] = k
|
||||
p['name'] = k
|
||||
p['value'] = v
|
||||
p['deleted'] = False
|
||||
p['created_at'] = datetime.datetime.utcnow()
|
||||
|
|
Loading…
Reference in New Issue