Alter models and add migration
We must have correct models i.e. models that correspond a database schema to use sqlalchemy features. Update models.py and add migration script to correct database schema and get rid of the difference between schema and models. Partial-Bug: #1365436 Change-Id: I9b4571906d39bcdb35048caa58d16ad5e888cce4
This commit is contained in:
parent
b14407fc08
commit
9def368d07
|
@ -26,7 +26,6 @@ import migrate
|
|||
import sqlalchemy
|
||||
|
||||
|
||||
meta = sqlalchemy.MetaData()
|
||||
and_ = sqlalchemy.and_
|
||||
or_ = sqlalchemy.or_
|
||||
|
||||
|
@ -35,19 +34,21 @@ def upgrade(migrate_engine):
|
|||
"""
|
||||
Call the correct dialect-specific upgrade.
|
||||
"""
|
||||
meta = sqlalchemy.MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
||||
t_images = _get_table('images', meta)
|
||||
t_image_members = _get_table('image_members', meta)
|
||||
t_image_properties = _get_table('image_properties', meta)
|
||||
|
||||
dialect = migrate_engine.url.get_dialect().name
|
||||
if dialect == "sqlite":
|
||||
_upgrade_sqlite(t_images, t_image_members, t_image_properties)
|
||||
_upgrade_sqlite(meta, t_images, t_image_members, t_image_properties)
|
||||
_update_all_ids_to_uuids(t_images, t_image_members, t_image_properties)
|
||||
elif dialect == "ibm_db_sa":
|
||||
_upgrade_db2(t_images, t_image_members, t_image_properties)
|
||||
_upgrade_db2(meta, t_images, t_image_members, t_image_properties)
|
||||
_update_all_ids_to_uuids(t_images, t_image_members, t_image_properties)
|
||||
_add_db2_constraints()
|
||||
_add_db2_constraints(meta)
|
||||
else:
|
||||
_upgrade_other(t_images, t_image_members, t_image_properties, dialect)
|
||||
|
||||
|
@ -56,6 +57,7 @@ def downgrade(migrate_engine):
|
|||
"""
|
||||
Call the correct dialect-specific downgrade.
|
||||
"""
|
||||
meta = sqlalchemy.MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
||||
t_images = _get_table('images', meta)
|
||||
|
@ -64,17 +66,17 @@ def downgrade(migrate_engine):
|
|||
dialect = migrate_engine.url.get_dialect().name
|
||||
if dialect == "sqlite":
|
||||
_update_all_uuids_to_ids(t_images, t_image_members, t_image_properties)
|
||||
_downgrade_sqlite(t_images, t_image_members, t_image_properties)
|
||||
_downgrade_sqlite(meta, t_images, t_image_members, t_image_properties)
|
||||
elif dialect == "ibm_db_sa":
|
||||
_remove_db2_constraints()
|
||||
_remove_db2_constraints(meta)
|
||||
_update_all_uuids_to_ids(t_images, t_image_members, t_image_properties)
|
||||
_downgrade_db2(t_images, t_image_members, t_image_properties)
|
||||
_downgrade_db2(meta, t_images, t_image_members, t_image_properties)
|
||||
else:
|
||||
_downgrade_other(t_images, t_image_members, t_image_properties,
|
||||
dialect)
|
||||
|
||||
|
||||
def _upgrade_sqlite(t_images, t_image_members, t_image_properties):
|
||||
def _upgrade_sqlite(meta, t_images, t_image_members, t_image_properties):
|
||||
"""
|
||||
Upgrade 011 -> 012 with special SQLite-compatible logic.
|
||||
"""
|
||||
|
@ -141,10 +143,10 @@ def _upgrade_sqlite(t_images, t_image_members, t_image_properties):
|
|||
for command in sql_commands:
|
||||
meta.bind.execute(command)
|
||||
|
||||
_sqlite_table_swap(t_image_members, t_image_properties, t_images)
|
||||
_sqlite_table_swap(meta, t_image_members, t_image_properties, t_images)
|
||||
|
||||
|
||||
def _upgrade_db2(t_images, t_image_members, t_image_properties):
|
||||
def _upgrade_db2(meta, t_images, t_image_members, t_image_properties):
|
||||
"""
|
||||
Upgrade for DB2.
|
||||
"""
|
||||
|
@ -236,7 +238,7 @@ def _upgrade_db2(t_images, t_image_members, t_image_properties):
|
|||
image_properties_backup.rename(name='image_properties')
|
||||
|
||||
|
||||
def _add_db2_constraints():
|
||||
def _add_db2_constraints(meta):
|
||||
# Create the foreign keys
|
||||
sql_commands = [
|
||||
"""ALTER TABLE image_members ADD CONSTRAINT member_image_id
|
||||
|
@ -250,7 +252,7 @@ def _add_db2_constraints():
|
|||
meta.bind.execute(command)
|
||||
|
||||
|
||||
def _remove_db2_constraints():
|
||||
def _remove_db2_constraints(meta):
|
||||
# Remove the foreign keys constraints
|
||||
sql_commands = [
|
||||
"""ALTER TABLE image_members DROP CONSTRAINT member_image_id;""",
|
||||
|
@ -260,7 +262,7 @@ def _remove_db2_constraints():
|
|||
meta.bind.execute(command)
|
||||
|
||||
|
||||
def _downgrade_db2(t_images, t_image_members, t_image_properties):
|
||||
def _downgrade_db2(meta, t_images, t_image_members, t_image_properties):
|
||||
"""
|
||||
Downgrade for DB2.
|
||||
"""
|
||||
|
@ -352,7 +354,7 @@ def _downgrade_db2(t_images, t_image_members, t_image_properties):
|
|||
image_properties_old.rename(name='image_properties')
|
||||
|
||||
|
||||
def _downgrade_sqlite(t_images, t_image_members, t_image_properties):
|
||||
def _downgrade_sqlite(meta, t_images, t_image_members, t_image_properties):
|
||||
"""
|
||||
Downgrade 012 -> 011 with special SQLite-compatible logic.
|
||||
"""
|
||||
|
@ -419,7 +421,7 @@ def _downgrade_sqlite(t_images, t_image_members, t_image_properties):
|
|||
for command in sql_commands:
|
||||
meta.bind.execute(command)
|
||||
|
||||
_sqlite_table_swap(t_image_members, t_image_properties, t_images)
|
||||
_sqlite_table_swap(meta, t_image_members, t_image_properties, t_images)
|
||||
|
||||
|
||||
def _upgrade_other(t_images, t_image_members, t_image_properties, dialect):
|
||||
|
@ -478,7 +480,7 @@ def _downgrade_other(t_images, t_image_members, t_image_properties, dialect):
|
|||
fk.create()
|
||||
|
||||
|
||||
def _sqlite_table_swap(t_image_members, t_image_properties, t_images):
|
||||
def _sqlite_table_swap(meta, t_image_members, t_image_properties, t_images):
|
||||
t_image_members.drop()
|
||||
t_image_properties.drop()
|
||||
t_images.drop()
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
# 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 sqlalchemy
|
||||
from sqlalchemy import Table, Index, UniqueConstraint, Sequence
|
||||
from sqlalchemy.schema import (AddConstraint, DropConstraint, CreateIndex,
|
||||
ForeignKeyConstraint)
|
||||
from sqlalchemy import sql
|
||||
from sqlalchemy import update
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta = sqlalchemy.MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
||||
if migrate_engine.name not in ['mysql', 'postgresql']:
|
||||
return
|
||||
|
||||
image_properties = Table('image_properties', meta, autoload=True)
|
||||
image_members = Table('image_members', meta, autoload=True)
|
||||
images = Table('images', meta, autoload=True)
|
||||
|
||||
# We have to ensure that we doesn't have `nulls` values since we are going
|
||||
# to set nullable=False
|
||||
migrate_engine.execute(
|
||||
update(image_members)
|
||||
.where(image_members.c.status == sql.expression.null())
|
||||
.values(status='pending'))
|
||||
|
||||
migrate_engine.execute(
|
||||
update(images)
|
||||
.where(images.c.protected == sql.expression.null())
|
||||
.values(protected=sql.expression.false()))
|
||||
|
||||
image_members.c.status.alter(nullable=False, server_default='pending')
|
||||
images.c.protected.alter(
|
||||
nullable=False, server_default=sql.expression.false())
|
||||
|
||||
if migrate_engine.name == 'postgresql':
|
||||
Index('ix_image_properties_image_id_name',
|
||||
image_properties.c.image_id,
|
||||
image_properties.c.name).drop()
|
||||
|
||||
# We have different names of this constraint in different versions of
|
||||
# postgresql. Since we have only one constraint on this table, we can
|
||||
# get it in the following way.
|
||||
name = migrate_engine.execute(
|
||||
"""SELECT conname
|
||||
FROM pg_constraint
|
||||
WHERE conrelid =
|
||||
(SELECT oid
|
||||
FROM pg_class
|
||||
WHERE relname LIKE 'image_properties')
|
||||
AND contype = 'u';""").scalar()
|
||||
|
||||
constraint = UniqueConstraint(image_properties.c.image_id,
|
||||
image_properties.c.name,
|
||||
name='%s' % name)
|
||||
migrate_engine.execute(DropConstraint(constraint))
|
||||
|
||||
constraint = UniqueConstraint(image_properties.c.image_id,
|
||||
image_properties.c.name,
|
||||
name='ix_image_properties_image_id_name')
|
||||
migrate_engine.execute(AddConstraint(constraint))
|
||||
|
||||
images.c.id.alter(server_default=None)
|
||||
if migrate_engine.name == 'mysql':
|
||||
constraint = UniqueConstraint(image_properties.c.image_id,
|
||||
image_properties.c.name,
|
||||
name='image_id')
|
||||
migrate_engine.execute(DropConstraint(constraint))
|
||||
image_locations = Table('image_locations', meta, autoload=True)
|
||||
if len(image_locations.foreign_keys) == 0:
|
||||
migrate_engine.execute(AddConstraint(ForeignKeyConstraint(
|
||||
[image_locations.c.image_id], [images.c.id])))
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta = sqlalchemy.MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
||||
if migrate_engine.name not in ['mysql', 'postgresql']:
|
||||
return
|
||||
|
||||
image_properties = Table('image_properties', meta, autoload=True)
|
||||
image_members = Table('image_members', meta, autoload=True)
|
||||
images = Table('images', meta, autoload=True)
|
||||
|
||||
if migrate_engine.name == 'postgresql':
|
||||
constraint = UniqueConstraint(image_properties.c.image_id,
|
||||
image_properties.c.name,
|
||||
name='ix_image_properties_image_id_name')
|
||||
migrate_engine.execute(DropConstraint(constraint))
|
||||
|
||||
constraint = UniqueConstraint(image_properties.c.image_id,
|
||||
image_properties.c.name)
|
||||
migrate_engine.execute(AddConstraint(constraint))
|
||||
|
||||
index = Index('ix_image_properties_image_id_name',
|
||||
image_properties.c.image_id,
|
||||
image_properties.c.name)
|
||||
migrate_engine.execute(CreateIndex(index))
|
||||
|
||||
images.c.id.alter(server_default=Sequence('images_id_seq')
|
||||
.next_value())
|
||||
|
||||
if migrate_engine.name == 'mysql':
|
||||
constraint = UniqueConstraint(image_properties.c.image_id,
|
||||
image_properties.c.name,
|
||||
name='image_id')
|
||||
migrate_engine.execute(AddConstraint(constraint))
|
||||
|
||||
image_members.c.status.alter(nullable=True, server_default=None)
|
||||
images.c.protected.alter(nullable=True, server_default=None)
|
|
@ -0,0 +1,150 @@
|
|||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TEMPORARY TABLE images_backup (
|
||||
id VARCHAR(36) NOT NULL,
|
||||
name VARCHAR(255),
|
||||
size INTEGER,
|
||||
status VARCHAR(30) NOT NULL,
|
||||
is_public BOOLEAN NOT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME,
|
||||
deleted_at DATETIME,
|
||||
deleted BOOLEAN NOT NULL,
|
||||
disk_format VARCHAR(20),
|
||||
container_format VARCHAR(20),
|
||||
checksum VARCHAR(32),
|
||||
owner VARCHAR(255),
|
||||
min_disk INTEGER,
|
||||
min_ram INTEGER,
|
||||
protected BOOLEAN,
|
||||
virtual_size INTEGER,
|
||||
PRIMARY KEY (id),
|
||||
CHECK (is_public IN (0, 1)),
|
||||
CHECK (deleted IN (0, 1))
|
||||
);
|
||||
|
||||
INSERT INTO images_backup
|
||||
SELECT id, name, size, status, is_public, created_at, updated_at, deleted_at, deleted, disk_format, container_format, checksum, owner, min_disk, min_ram, virtual_size, protected
|
||||
FROM images;
|
||||
|
||||
DROP TABLE images;
|
||||
|
||||
CREATE TABLE images (
|
||||
id VARCHAR(36) NOT NULL,
|
||||
name VARCHAR(255),
|
||||
size INTEGER,
|
||||
status VARCHAR(30) NOT NULL,
|
||||
is_public BOOLEAN NOT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME,
|
||||
deleted_at DATETIME,
|
||||
deleted BOOLEAN NOT NULL,
|
||||
disk_format VARCHAR(20),
|
||||
container_format VARCHAR(20),
|
||||
checksum VARCHAR(32),
|
||||
owner VARCHAR(255),
|
||||
min_disk INTEGER NOT NULL,
|
||||
min_ram INTEGER NOT NULL,
|
||||
protected BOOLEAN,
|
||||
virtual_size INTEGER,
|
||||
PRIMARY KEY (id),
|
||||
CHECK (is_public IN (0, 1)),
|
||||
CHECK (deleted IN (0, 1))
|
||||
);
|
||||
|
||||
CREATE INDEX owner_image_idx ON images (owner);
|
||||
CREATE INDEX checksum_image_idx ON images (checksum);
|
||||
|
||||
INSERT INTO images
|
||||
SELECT id, name, size, status, is_public, created_at, updated_at, deleted_at, deleted, disk_format, container_format, checksum, owner, min_disk, min_ram, protected, virtual_size
|
||||
FROM images_backup;
|
||||
|
||||
DROP TABLE images_backup;
|
||||
|
||||
CREATE TEMPORARY TABLE image_members_backup (
|
||||
id INTEGER NOT NULL,
|
||||
image_id VARCHAR(36) NOT NULL,
|
||||
member VARCHAR(255) NOT NULL,
|
||||
can_share BOOLEAN NOT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME,
|
||||
deleted_at DATETIME,
|
||||
deleted BOOLEAN NOT NULL,
|
||||
status VARCHAR(20),
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (image_id, member),
|
||||
CHECK (can_share IN (0, 1)),
|
||||
CHECK (deleted IN (0, 1)),
|
||||
FOREIGN KEY(image_id) REFERENCES images (id)
|
||||
);
|
||||
|
||||
INSERT INTO image_members_backup
|
||||
SELECT id, image_id, member, can_share, created_at, updated_at, deleted_at, deleted, status
|
||||
FROM image_members;
|
||||
|
||||
DROP TABLE image_members;
|
||||
|
||||
CREATE TABLE image_members (
|
||||
id INTEGER NOT NULL,
|
||||
image_id VARCHAR(36) NOT NULL,
|
||||
member VARCHAR(255) NOT NULL,
|
||||
can_share BOOLEAN NOT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME,
|
||||
deleted_at DATETIME,
|
||||
deleted BOOLEAN NOT NULL,
|
||||
status VARCHAR(20),
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (image_id, member),
|
||||
CHECK (can_share IN (0, 1)),
|
||||
CHECK (deleted IN (0, 1)),
|
||||
FOREIGN KEY(image_id) REFERENCES images (id)
|
||||
);
|
||||
|
||||
INSERT INTO image_members
|
||||
SELECT id, image_id, member, can_share, created_at, updated_at, deleted_at, deleted, status
|
||||
FROM image_members_backup;
|
||||
|
||||
DROP TABLE image_members_backup;
|
||||
|
||||
CREATE TEMPORARY TABLE image_properties_backup (
|
||||
id INTEGER NOT NULL,
|
||||
image_id VARCHAR(36) 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, 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 VARCHAR(36) 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;
|
|
@ -0,0 +1,163 @@
|
|||
BEGIN TRANSACTION;
|
||||
|
||||
UPDATE images SET protected = 0 WHERE protected is NULL;
|
||||
UPDATE image_members SET status = 'pending' WHERE status is NULL;
|
||||
|
||||
CREATE TEMPORARY TABLE images_backup (
|
||||
id VARCHAR(36) NOT NULL,
|
||||
name VARCHAR(255),
|
||||
size INTEGER,
|
||||
status VARCHAR(30) NOT NULL,
|
||||
is_public BOOLEAN NOT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME,
|
||||
deleted_at DATETIME,
|
||||
deleted BOOLEAN NOT NULL,
|
||||
disk_format VARCHAR(20),
|
||||
container_format VARCHAR(20),
|
||||
checksum VARCHAR(32),
|
||||
owner VARCHAR(255),
|
||||
min_disk INTEGER,
|
||||
min_ram INTEGER,
|
||||
protected BOOLEAN NOT NULL DEFAULT 0,
|
||||
virtual_size INTEGER,
|
||||
PRIMARY KEY (id),
|
||||
CHECK (is_public IN (0, 1)),
|
||||
CHECK (deleted IN (0, 1))
|
||||
);
|
||||
|
||||
INSERT INTO images_backup
|
||||
SELECT id, name, size, status, is_public, created_at, updated_at, deleted_at, deleted, disk_format, container_format, checksum, owner, min_disk, min_ram, protected, virtual_size
|
||||
FROM images;
|
||||
|
||||
DROP TABLE images;
|
||||
|
||||
CREATE TABLE images (
|
||||
id VARCHAR(36) NOT NULL,
|
||||
name VARCHAR(255),
|
||||
size INTEGER,
|
||||
status VARCHAR(30) NOT NULL,
|
||||
is_public BOOLEAN NOT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME,
|
||||
deleted_at DATETIME,
|
||||
deleted BOOLEAN NOT NULL,
|
||||
disk_format VARCHAR(20),
|
||||
container_format VARCHAR(20),
|
||||
checksum VARCHAR(32),
|
||||
owner VARCHAR(255),
|
||||
min_disk INTEGER NOT NULL,
|
||||
min_ram INTEGER NOT NULL,
|
||||
protected BOOLEAN NOT NULL DEFAULT 0,
|
||||
virtual_size INTEGER,
|
||||
PRIMARY KEY (id),
|
||||
CHECK (is_public IN (0, 1)),
|
||||
CHECK (deleted IN (0, 1))
|
||||
);
|
||||
|
||||
CREATE INDEX ix_images_deleted ON images (deleted);
|
||||
CREATE INDEX ix_images_is_public ON images (is_public);
|
||||
CREATE INDEX owner_image_idx ON images (owner);
|
||||
CREATE INDEX checksum_image_idx ON images (checksum);
|
||||
|
||||
|
||||
INSERT INTO images
|
||||
SELECT id, name, size, status, is_public, created_at, updated_at, deleted_at, deleted, disk_format, container_format, checksum, owner, min_disk, min_ram, protected, virtual_size
|
||||
FROM images_backup;
|
||||
|
||||
DROP TABLE images_backup;
|
||||
|
||||
CREATE TEMPORARY TABLE image_members_backup (
|
||||
id INTEGER NOT NULL,
|
||||
image_id VARCHAR(36) NOT NULL,
|
||||
member VARCHAR(255) NOT NULL,
|
||||
can_share BOOLEAN NOT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME,
|
||||
deleted_at DATETIME,
|
||||
deleted BOOLEAN NOT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (image_id, member),
|
||||
CHECK (can_share IN (0, 1)),
|
||||
CHECK (deleted IN (0, 1)),
|
||||
FOREIGN KEY(image_id) REFERENCES images (id)
|
||||
);
|
||||
|
||||
INSERT INTO image_members_backup
|
||||
SELECT id, image_id, member, can_share, created_at, updated_at, deleted_at, deleted, status
|
||||
FROM image_members;
|
||||
|
||||
DROP TABLE image_members;
|
||||
|
||||
CREATE TABLE image_members (
|
||||
id INTEGER NOT NULL,
|
||||
image_id VARCHAR(36) NOT NULL,
|
||||
member VARCHAR(255) NOT NULL,
|
||||
can_share BOOLEAN NOT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME,
|
||||
deleted_at DATETIME,
|
||||
deleted BOOLEAN NOT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (image_id, member),
|
||||
CHECK (can_share IN (0, 1)),
|
||||
CHECK (deleted IN (0, 1)),
|
||||
FOREIGN KEY(image_id) REFERENCES images (id),
|
||||
CONSTRAINT image_members_image_id_member_deleted_at_key UNIQUE (image_id, member, deleted_at)
|
||||
);
|
||||
|
||||
CREATE INDEX ix_image_members_deleted ON image_members (deleted);
|
||||
CREATE INDEX ix_image_members_image_id ON image_members (image_id);
|
||||
CREATE INDEX ix_image_members_image_id_member ON image_members (image_id, member);
|
||||
|
||||
INSERT INTO image_members
|
||||
SELECT id, image_id, member, can_share, created_at, updated_at, deleted_at, deleted, status
|
||||
FROM image_members_backup;
|
||||
|
||||
DROP TABLE image_members_backup;
|
||||
|
||||
CREATE TEMPORARY TABLE image_properties_backup (
|
||||
id INTEGER NOT NULL,
|
||||
image_id VARCHAR(36) 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, 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 VARCHAR(36) 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),
|
||||
CONSTRAINT ix_image_properties_image_id_name UNIQUE (image_id, name)
|
||||
);
|
||||
|
||||
CREATE INDEX ix_image_properties_deleted ON image_properties (deleted);
|
||||
CREATE INDEX ix_image_properties_image_id ON image_properties (image_id);
|
||||
|
||||
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;
|
|
@ -33,6 +33,7 @@ from sqlalchemy import ForeignKey
|
|||
from sqlalchemy import Index
|
||||
from sqlalchemy import Integer
|
||||
from sqlalchemy.orm import backref, relationship
|
||||
from sqlalchemy import sql
|
||||
from sqlalchemy import String
|
||||
from sqlalchemy import Text
|
||||
from sqlalchemy.types import TypeDecorator
|
||||
|
@ -82,7 +83,7 @@ class GlanceBase(models.ModelBase, models.TimestampMixin):
|
|||
# required and make changes in oslo (if required) or
|
||||
# in glance (if not).
|
||||
updated_at = Column(DateTime, default=lambda: timeutils.utcnow(),
|
||||
nullable=False, onupdate=lambda: timeutils.utcnow())
|
||||
nullable=True, onupdate=lambda: timeutils.utcnow())
|
||||
# TODO(boris-42): Use SoftDeleteMixin instead of deleted Column after
|
||||
# migration that provides UniqueConstraints and change
|
||||
# type of this column.
|
||||
|
@ -135,7 +136,8 @@ class Image(BASE, GlanceBase):
|
|||
min_disk = Column(Integer, nullable=False, default=0)
|
||||
min_ram = Column(Integer, nullable=False, default=0)
|
||||
owner = Column(String(255))
|
||||
protected = Column(Boolean, nullable=False, default=False)
|
||||
protected = Column(Boolean, nullable=False, default=False,
|
||||
server_default=sql.expression.false())
|
||||
|
||||
|
||||
class ImageProperty(BASE, GlanceBase):
|
||||
|
@ -182,7 +184,7 @@ class ImageLocation(BASE, GlanceBase):
|
|||
image = relationship(Image, backref=backref('locations'))
|
||||
value = Column(Text(), nullable=False)
|
||||
meta_data = Column(JSONEncodedDict(), default={})
|
||||
status = Column(String(30), default='active', nullable=False)
|
||||
status = Column(String(30), server_default='active', nullable=False)
|
||||
|
||||
|
||||
class ImageMember(BASE, GlanceBase):
|
||||
|
@ -206,7 +208,8 @@ class ImageMember(BASE, GlanceBase):
|
|||
|
||||
member = Column(String(255), nullable=False)
|
||||
can_share = Column(Boolean, nullable=False, default=False)
|
||||
status = Column(String(20), nullable=False, default="pending")
|
||||
status = Column(String(20), nullable=False, default="pending",
|
||||
server_default='pending')
|
||||
|
||||
|
||||
class Task(BASE, GlanceBase):
|
||||
|
@ -220,8 +223,8 @@ class Task(BASE, GlanceBase):
|
|||
|
||||
id = Column(String(36), primary_key=True,
|
||||
default=lambda: str(uuid.uuid4()))
|
||||
type = Column(String(30))
|
||||
status = Column(String(30))
|
||||
type = Column(String(30), nullable=False)
|
||||
status = Column(String(30), nullable=False)
|
||||
owner = Column(String(255), nullable=False)
|
||||
expires_at = Column(DateTime, nullable=True)
|
||||
|
||||
|
|
|
@ -56,6 +56,17 @@ CONF = cfg.CONF
|
|||
CONF.import_opt('metadata_encryption_key', 'glance.common.config')
|
||||
|
||||
|
||||
def index_exist(index, table, engine):
|
||||
inspector = sqlalchemy.inspect(engine)
|
||||
return index in [i['name'] for i in inspector.get_indexes(table)]
|
||||
|
||||
|
||||
def unique_constraint_exist(constraint, table, engine):
|
||||
inspector = sqlalchemy.inspect(engine)
|
||||
return constraint in [c['name'] for c in
|
||||
inspector.get_unique_constraints(table)]
|
||||
|
||||
|
||||
class MigrationsMixin(test_migrations.WalkVersionsMixin):
|
||||
@property
|
||||
def INIT_VERSION(self):
|
||||
|
@ -991,7 +1002,6 @@ class MigrationsMixin(test_migrations.WalkVersionsMixin):
|
|||
image_id = 'fake_id_034'
|
||||
temp = dict(deleted=False,
|
||||
created_at=now,
|
||||
updated_at=now,
|
||||
status='active',
|
||||
is_public=True,
|
||||
min_disk=0,
|
||||
|
@ -1218,6 +1228,114 @@ class MigrationsMixin(test_migrations.WalkVersionsMixin):
|
|||
col_data = [col.name for col in table.columns]
|
||||
self.assertEqual(expected_cols, col_data)
|
||||
|
||||
def _check_037(self, engine, data):
|
||||
if engine.name == 'mysql':
|
||||
self.assertFalse(unique_constraint_exist('image_id',
|
||||
'image_properties',
|
||||
engine))
|
||||
|
||||
self.assertTrue(unique_constraint_exist(
|
||||
'ix_image_properties_image_id_name',
|
||||
'image_properties',
|
||||
engine))
|
||||
|
||||
image_members = db_utils.get_table(engine, 'image_members')
|
||||
images = db_utils.get_table(engine, 'images')
|
||||
|
||||
self.assertFalse(image_members.c.status.nullable)
|
||||
self.assertFalse(images.c.protected.nullable)
|
||||
|
||||
now = datetime.datetime.now()
|
||||
temp = dict(
|
||||
deleted=False,
|
||||
created_at=now,
|
||||
status='active',
|
||||
is_public=True,
|
||||
min_disk=0,
|
||||
min_ram=0,
|
||||
id='fake_image_035'
|
||||
)
|
||||
images.insert().values(temp).execute()
|
||||
|
||||
image = (images.select()
|
||||
.where(images.c.id == 'fake_image_035')
|
||||
.execute().fetchone())
|
||||
|
||||
self.assertFalse(image['protected'])
|
||||
|
||||
temp = dict(
|
||||
deleted=False,
|
||||
created_at=now,
|
||||
image_id='fake_image_035',
|
||||
member='fake_member',
|
||||
can_share=True,
|
||||
id=3
|
||||
)
|
||||
|
||||
image_members.insert().values(temp).execute()
|
||||
|
||||
image_member = (image_members.select()
|
||||
.where(image_members.c.id == 3)
|
||||
.execute().fetchone())
|
||||
|
||||
self.assertEqual('pending', image_member['status'])
|
||||
|
||||
def _post_downgrade_037(self, engine):
|
||||
if engine.name == 'mysql':
|
||||
self.assertTrue(unique_constraint_exist('image_id',
|
||||
'image_properties',
|
||||
engine))
|
||||
|
||||
if engine.name == 'postgresql':
|
||||
self.assertTrue(index_exist('ix_image_properties_image_id_name',
|
||||
'image_properties', engine))
|
||||
|
||||
self.assertFalse(unique_constraint_exist(
|
||||
'ix_image_properties_image_id_name',
|
||||
'image_properties',
|
||||
engine))
|
||||
|
||||
image_members = db_utils.get_table(engine, 'image_members')
|
||||
images = db_utils.get_table(engine, 'images')
|
||||
|
||||
self.assertTrue(image_members.c.status.nullable)
|
||||
self.assertTrue(images.c.protected.nullable)
|
||||
|
||||
now = datetime.datetime.now()
|
||||
temp = dict(
|
||||
deleted=False,
|
||||
created_at=now,
|
||||
status='active',
|
||||
is_public=True,
|
||||
min_disk=0,
|
||||
min_ram=0,
|
||||
id='fake_image_035_d'
|
||||
)
|
||||
images.insert().values(temp).execute()
|
||||
|
||||
image = (images.select()
|
||||
.where(images.c.id == 'fake_image_035_d')
|
||||
.execute().fetchone())
|
||||
|
||||
self.assertIsNone(image['protected'])
|
||||
|
||||
temp = dict(
|
||||
deleted=False,
|
||||
created_at=now,
|
||||
image_id='fake_image_035_d',
|
||||
member='fake_member',
|
||||
can_share=True,
|
||||
id=4
|
||||
)
|
||||
|
||||
image_members.insert().values(temp).execute()
|
||||
|
||||
image_member = (image_members.select()
|
||||
.where(image_members.c.id == 4)
|
||||
.execute().fetchone())
|
||||
|
||||
self.assertIsNone(image_member['status'])
|
||||
|
||||
|
||||
class TestMysqlMigrations(test_base.MySQLOpportunisticTestCase,
|
||||
MigrationsMixin):
|
||||
|
|
Loading…
Reference in New Issue