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:
Oleksii Chuprykov 2014-09-02 13:14:21 +03:00
parent b14407fc08
commit 9def368d07
6 changed files with 582 additions and 23 deletions

View File

@ -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()

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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):