22725754 - Keystone needs to support MySQL Cluster
22725850 - Cinder needs to support MySQL Cluster
22725863 - Glance needs to support MySQL Cluster
22725887 - Heat needs to support MySQL Cluster
22726240 - Ironic needs to support MySQL Cluster
22726251 - Neutron needs to support MySQL Cluster
22726259 - Nova needs to support MySQL Cluster
23033470 - oslo.db needs a database option to support MySQL Cluster
--- a/components/openstack/cinder/files/cinder.conf Fri Apr 01 14:10:25 2016 -0600
+++ b/components/openstack/cinder/files/cinder.conf Fri Apr 01 14:13:41 2016 -0600
@@ -2555,6 +2555,12 @@
# value)
#mysql_sql_mode=TRADITIONAL
+# This configures the MySQL storage engine. This allows for OpenStack to
+# support different storage engines such as InnoDB, NDB, etc. By Default,
+# this value will be set to InnoDB. For MySQL Cluster, set to NDBCLUSTER.
+# Example: mysql_storage_engine=(string value)
+#mysql_storage_engine = InnoDB
+
# Timeout before idle SQL connections are reaped. (integer
# value)
# Deprecated group/name - [DEFAULT]/sql_idle_timeout
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/openstack/cinder/patches/mysql_cluster_support.patch Fri Apr 01 14:13:41 2016 -0600
@@ -0,0 +1,668 @@
+This patchset is for bug:
+
+22725850 - Cinder needs to support MySQL Cluster
+
+This fixes the following aspects of Cinder:
+1. Implementation of an oslo.db configuration parameter to specify the MySQL
+ storage engine (mysql_storage_engine).
+2. Replacement of hardcoded SQL statements that set the engine to "InnoDB"
+ to the above configuration value.
+3. Logic to handle SQL differences between MySQL InnoDB and MySQL Cluster (NDB).
+ This includes column lengths, constraints, foreign keys, and indexes.
+
+This has not been committed upstream, but has been filed in launchpad:
+
+https://bugs.launchpad.net/cinder/+bug/1564110
+
+
+--- cinder-2015.1.2/cinder/tests/test_migrations.py.orig 2016-03-29 17:09:39.000000000 -0600
++++ cinder-2015.1.2/cinder/tests/test_migrations.py 2016-03-29 17:10:56.573462129 -0600
+@@ -27,11 +27,13 @@ from migrate.versioning import repositor
+ from oslo_db.sqlalchemy import test_base
+ from oslo_db.sqlalchemy import test_migrations
+ from oslo_db.sqlalchemy import utils as db_utils
++from oslo_config import cfg
+ import sqlalchemy
+
+ from cinder.db import migration
+ import cinder.db.sqlalchemy.migrate_repo
+
++CONF = cfg.CONF
+
+ class MigrationsMixin(test_migrations.WalkVersionsMixin):
+ """Test sqlalchemy-migrate migrations."""
+@@ -850,8 +852,9 @@ class TestMysqlMigrations(test_base.MySQ
+ "SELECT count(*) "
+ "from information_schema.TABLES "
+ "where TABLE_SCHEMA='openstack_citest' "
+- "and ENGINE!='InnoDB' "
+- "and TABLE_NAME!='migrate_version'")
++ "and ENGINE!='%(mysql_storage_engine)s' "
++ "and TABLE_NAME!='migrate_version'" %
++ dict(mysql_storage_engine=CONF.database.mysql_storage_engine))
+ count = noninnodb.scalar()
+ self.assertEqual(count, 0, "%d non InnoDB tables created" % count)
+
+--- cinder-2015.1.2/cinder/db/sqlalchemy/models.py.orig 2016-03-29 17:09:39.000000000 -0600
++++ cinder-2015.1.2/cinder/db/sqlalchemy/models.py 2016-03-29 17:10:56.573860608 -0600
+@@ -36,7 +36,7 @@ class CinderBase(models.TimestampMixin,
+ models.ModelBase):
+ """Base class for Cinder Models."""
+
+- __table_args__ = {'mysql_engine': 'InnoDB'}
++ __table_args__ = {'mysql_engine': CONF.database.mysql_storage_engine }
+
+ # TODO(rpodolyaka): reuse models.SoftDeleteMixin in the next stage
+ # of implementing of BP db-cleanup
+@@ -488,7 +488,7 @@ class IscsiTarget(BASE, CinderBase):
+ """Represents an iscsi target for a given host."""
+ __tablename__ = 'iscsi_targets'
+ __table_args__ = (schema.UniqueConstraint("target_num", "host"),
+- {'mysql_engine': 'InnoDB'})
++ {'mysql_engine': CONF.database.mysql_storage_engine })
+ id = Column(Integer, primary_key=True)
+ target_num = Column(Integer)
+ host = Column(String(255))
+@@ -576,7 +576,7 @@ class DriverInitiatorData(BASE, models.T
+ __tablename__ = 'driver_initiator_data'
+ __table_args__ = (
+ schema.UniqueConstraint("initiator", "namespace", "key"),
+- {'mysql_engine': 'InnoDB'}
++ {'mysql_engine': CONF.database.mysql_storage_engine }
+ )
+ id = Column(Integer, primary_key=True, nullable=False)
+ initiator = Column(String(255), index=True, nullable=False)
+--- cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/038_add_driver_initiator_data_table.py.orig 2016-03-29 17:09:39.000000000 -0600
++++ cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/038_add_driver_initiator_data_table.py 2016-03-29 17:10:56.574137554 -0600
+@@ -18,6 +18,9 @@ from cinder.i18n import _LE
+
+ LOG = logging.getLogger(__name__)
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = MetaData()
+@@ -34,7 +37,7 @@ def upgrade(migrate_engine):
+ Column('key', String(length=255), nullable=False),
+ Column('value', String(length=255)),
+ UniqueConstraint('initiator', 'namespace', 'key'),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+--- cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/020_add_volume_admin_metadata_table.py.orig 2016-03-29 17:09:39.000000000 -0600
++++ cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/020_add_volume_admin_metadata_table.py 2016-03-29 17:10:56.574417302 -0600
+@@ -18,6 +18,9 @@ from cinder.i18n import _
+
+ LOG = logging.getLogger(__name__)
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = MetaData()
+@@ -37,7 +40,7 @@ def upgrade(migrate_engine):
+ nullable=False),
+ Column('key', String(length=255)),
+ Column('value', String(length=255)),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+--- cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/040_add_volume_attachment.py.orig 2016-03-29 17:09:39.000000000 -0600
++++ cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/040_add_volume_attachment.py 2016-03-29 17:10:56.574694629 -0600
+@@ -27,6 +27,9 @@ LOG = logging.getLogger(__name__)
+
+ CREATED_AT = datetime.datetime.now() # noqa
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ """Add volume multi attachment table."""
+@@ -56,7 +59,7 @@ def upgrade(migrate_engine):
+ Column('detach_time', DateTime),
+ Column('attach_mode', String(length=36)),
+ Column('attach_status', String(length=255)),
+- mysql_engine='InnoDB'
++ mysql_engine=CONF.database.mysql_storage_engine
+ )
+
+ try:
+--- cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/003_glance_metadata.py.orig 2016-03-29 17:09:39.000000000 -0600
++++ cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/003_glance_metadata.py 2016-03-29 17:10:56.574973087 -0600
+@@ -20,6 +20,9 @@ from cinder.i18n import _
+
+ LOG = logging.getLogger(__name__)
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = MetaData()
+@@ -31,11 +34,11 @@ def upgrade(migrate_engine):
+ Table('volumes',
+ meta,
+ Column('id', Integer(), primary_key=True, nullable=False),
+- mysql_engine='InnoDB')
++ mysql_engine=CONF.database.mysql_storage_engine)
+ Table('snapshots',
+ meta,
+ Column('id', Integer(), primary_key=True, nullable=False),
+- mysql_engine='InnoDB')
++ mysql_engine=CONF.database.mysql_storage_engine)
+ # Create new table
+ volume_glance_metadata = Table(
+ 'volume_glance_metadata',
+@@ -50,7 +53,7 @@ def upgrade(migrate_engine):
+ ForeignKey('snapshots.id')),
+ Column('key', String(255)),
+ Column('value', Text),
+- mysql_engine='InnoDB'
++ mysql_engine=CONF.database.mysql_storage_engine
+ )
+
+ try:
+--- cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/008_add_backup.py.orig 2016-03-29 17:09:39.000000000 -0600
++++ cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/008_add_backup.py 2016-03-29 17:10:56.575243585 -0600
+@@ -21,6 +21,9 @@ from cinder.i18n import _
+
+ LOG = logging.getLogger(__name__)
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = MetaData()
+@@ -48,7 +51,7 @@ def upgrade(migrate_engine):
+ Column('service', String(length=255)),
+ Column('size', Integer()),
+ Column('object_count', Integer()),
+- mysql_engine='InnoDB'
++ mysql_engine=CONF.database.mysql_storage_engine
+ )
+
+ try:
+--- cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/015_drop_migrations_table.py.orig 2016-03-29 17:09:39.000000000 -0600
++++ cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/015_drop_migrations_table.py 2016-03-29 17:10:56.575465610 -0600
+@@ -18,6 +18,9 @@ from cinder.i18n import _LE
+
+ LOG = logging.getLogger(__name__)
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ TABLE_NAME = 'migrations'
+
+@@ -52,7 +55,7 @@ def downgrade(migrate_engine):
+ Column('new_instance_type_id', Integer),
+ Column('instance_uuid', String(length=255), nullable=True),
+ Column('status', String(length=255)),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+--- cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/025_add_consistencygroup.py.orig 2016-03-29 17:09:39.000000000 -0600
++++ cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/025_add_consistencygroup.py 2016-03-29 17:10:56.575689167 -0600
+@@ -22,6 +22,9 @@ from cinder.i18n import _
+
+ LOG = logging.getLogger(__name__)
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = MetaData()
+@@ -43,7 +46,7 @@ def upgrade(migrate_engine):
+ Column('description', String(length=255)),
+ Column('volume_type_id', String(length=255)),
+ Column('status', String(length=255)),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8',
+ )
+
+@@ -69,7 +72,7 @@ def upgrade(migrate_engine):
+ Column('name', String(length=255)),
+ Column('description', String(length=255)),
+ Column('status', String(length=255)),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8',
+ )
+
+--- cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/002_quota_class.py.orig 2016-03-29 17:09:39.000000000 -0600
++++ cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/002_quota_class.py 2016-03-29 17:10:56.575924797 -0600
+@@ -21,6 +21,9 @@ from cinder.i18n import _LE
+
+ LOG = logging.getLogger(__name__)
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = MetaData()
+@@ -40,7 +43,7 @@ def upgrade(migrate_engine):
+ Column('resource',
+ String(length=255)),
+ Column('hard_limit', Integer(), nullable=True),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8',
+ )
+
+@@ -65,7 +68,7 @@ def upgrade(migrate_engine):
+ Column('in_use', Integer(), nullable=False),
+ Column('reserved', Integer(), nullable=False),
+ Column('until_refresh', Integer(), nullable=True),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8',
+ )
+
+@@ -96,7 +99,7 @@ def upgrade(migrate_engine):
+ String(length=255)),
+ Column('delta', Integer(), nullable=False),
+ Column('expire', DateTime(timezone=False)),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8',
+ )
+
+--- cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/032_add_volume_type_projects.py.orig 2016-03-29 17:09:39.000000000 -0600
++++ cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/032_add_volume_type_projects.py 2016-03-29 17:10:56.576131670 -0600
+@@ -18,6 +18,9 @@ from cinder.i18n import _
+
+ LOG = logging.getLogger(__name__)
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = MetaData()
+@@ -44,7 +47,7 @@ def upgrade(migrate_engine):
+ Column('project_id', String(length=255)),
+ Column('deleted', Boolean(create_constraint=True, name=None)),
+ UniqueConstraint('volume_type_id', 'project_id', 'deleted'),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ )
+
+ try:
+--- cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/016_drop_sm_tables.py.orig 2016-03-29 17:09:39.000000000 -0600
++++ cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/016_drop_sm_tables.py 2016-03-29 17:10:56.576370016 -0600
+@@ -20,6 +20,9 @@ from cinder.i18n import _
+
+ LOG = logging.getLogger(__name__)
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = MetaData()
+@@ -58,7 +61,7 @@ def downgrade(migrate_engine):
+ Column('sr_uuid', String(length=255)),
+ Column('sr_type', String(length=255)),
+ Column('config_params', String(length=2047)),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -71,7 +74,7 @@ def downgrade(migrate_engine):
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('label', String(length=255)),
+ Column('description', String(length=255)),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -88,7 +91,7 @@ def downgrade(migrate_engine):
+ Column('backend_id', Integer, ForeignKey('sm_backend_config.id'),
+ nullable=False),
+ Column('vdi_uuid', String(length=255)),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+--- cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/010_add_transfers_table.py.orig 2016-03-29 17:09:39.000000000 -0600
++++ cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/010_add_transfers_table.py 2016-03-29 17:10:56.576569645 -0600
+@@ -18,6 +18,9 @@ from cinder.i18n import _
+
+ LOG = logging.getLogger(__name__)
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = MetaData()
+@@ -39,7 +42,7 @@ def upgrade(migrate_engine):
+ Column('salt', String(length=255)),
+ Column('crypt_hash', String(length=255)),
+ Column('expires_at', DateTime(timezone=False)),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+--- cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/009_add_snapshot_metadata_table.py.orig 2016-03-29 17:09:39.000000000 -0600
++++ cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/009_add_snapshot_metadata_table.py 2016-03-29 17:10:56.576767256 -0600
+@@ -18,6 +18,9 @@ from cinder.i18n import _
+
+ LOG = logging.getLogger(__name__)
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = MetaData()
+@@ -37,7 +40,7 @@ def upgrade(migrate_engine):
+ nullable=False),
+ Column('key', String(length=255)),
+ Column('value', String(length=255)),
+- mysql_engine='InnoDB'
++ mysql_engine=CONF.database.mysql_storage_engine
+ )
+
+ try:
+--- cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/018_add_qos_specs.py.orig 2016-03-29 17:09:39.000000000 -0600
++++ cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/018_add_qos_specs.py 2016-03-29 17:10:56.576967318 -0600
+@@ -23,6 +23,9 @@ from cinder.i18n import _
+
+ LOG = logging.getLogger(__name__)
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ """Add volume_type_rate_limit table."""
+@@ -40,7 +43,7 @@ def upgrade(migrate_engine):
+ ForeignKey('quality_of_service_specs.id')),
+ Column('key', String(255)),
+ Column('value', String(255)),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+--- cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/017_add_encryption_information.py.orig 2016-03-29 17:09:39.000000000 -0600
++++ cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/017_add_encryption_information.py 2016-03-29 17:10:56.577171207 -0600
+@@ -19,9 +19,11 @@ from sqlalchemy import Boolean, DateTime
+
+ from cinder.i18n import _
+
+-
+ LOG = logging.getLogger(__name__)
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = MetaData(bind=migrate_engine)
+@@ -69,9 +71,9 @@ def upgrade(migrate_engine):
+ # scheme unless each volume type is associated with at most one
+ # encryption scheme.
+ Column('volume_type_id', String(length=36),
+- ForeignKey(volume_types.c.id),
++ ForeignKey(volume_types.c.id, name='encryption_ibfk_1'),
+ primary_key=True, nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+--- cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/001_cinder_init.py.orig 2016-03-29 17:09:39.000000000 -0600
++++ cinder-2015.1.2/cinder/db/sqlalchemy/migrate_repo/versions/001_cinder_init.py 2016-03-30 13:21:47.918291632 -0600
+@@ -18,9 +18,16 @@ from sqlalchemy import Integer, MetaData
+
+ from cinder.i18n import _
+
+-
+ LOG = logging.getLogger(__name__)
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
++
++if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ db_string_length = 128
++else:
++ db_string_length = 255
+
+ def define_tables(meta):
+ migrations = Table(
+@@ -30,14 +37,14 @@ def define_tables(meta):
+ Column('deleted_at', DateTime),
+ Column('deleted', Boolean),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('source_compute', String(length=255)),
+- Column('dest_compute', String(length=255)),
+- Column('dest_host', String(length=255)),
+- Column('status', String(length=255)),
+- Column('instance_uuid', String(length=255)),
++ Column('source_compute', String(length=db_string_length)),
++ Column('dest_compute', String(length=db_string_length)),
++ Column('dest_host', String(length=db_string_length)),
++ Column('status', String(length=db_string_length)),
++ Column('instance_uuid', String(length=db_string_length)),
+ Column('old_instance_type_id', Integer),
+ Column('new_instance_type_id', Integer),
+- mysql_engine='InnoDB'
++ mysql_engine=CONF.database.mysql_storage_engine
+ )
+
+ services = Table(
+@@ -47,13 +54,13 @@ def define_tables(meta):
+ Column('deleted_at', DateTime),
+ Column('deleted', Boolean),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('host', String(length=255)),
+- Column('binary', String(length=255)),
+- Column('topic', String(length=255)),
++ Column('host', String(length=db_string_length)),
++ Column('binary', String(length=db_string_length)),
++ Column('topic', String(length=db_string_length)),
+ Column('report_count', Integer, nullable=False),
+ Column('disabled', Boolean),
+- Column('availability_zone', String(length=255)),
+- mysql_engine='InnoDB'
++ Column('availability_zone', String(length=db_string_length)),
++ mysql_engine=CONF.database.mysql_storage_engine
+ )
+
+ sm_flavors = Table(
+@@ -63,9 +70,9 @@ def define_tables(meta):
+ Column('deleted_at', DateTime),
+ Column('deleted', Boolean),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('label', String(length=255)),
+- Column('description', String(length=255)),
+- mysql_engine='InnoDB'
++ Column('label', String(length=db_string_length)),
++ Column('description', String(length=db_string_length)),
++ mysql_engine=CONF.database.mysql_storage_engine
+ )
+
+ sm_backend_config = Table(
+@@ -77,10 +84,10 @@ def define_tables(meta):
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('flavor_id', Integer, ForeignKey('sm_flavors.id'),
+ nullable=False),
+- Column('sr_uuid', String(length=255)),
+- Column('sr_type', String(length=255)),
++ Column('sr_uuid', String(length=db_string_length)),
++ Column('sr_type', String(length=db_string_length)),
+ Column('config_params', String(length=2047)),
+- mysql_engine='InnoDB'
++ mysql_engine=CONF.database.mysql_storage_engine
+ )
+
+ sm_volume = Table(
+@@ -95,8 +102,8 @@ def define_tables(meta):
+ nullable=False),
+ Column('backend_id', Integer, ForeignKey('sm_backend_config.id'),
+ nullable=False),
+- Column('vdi_uuid', String(length=255)),
+- mysql_engine='InnoDB'
++ Column('vdi_uuid', String(length=db_string_length)),
++ mysql_engine=CONF.database.mysql_storage_engine
+ )
+
+ snapshots = Table(
+@@ -107,15 +114,15 @@ def define_tables(meta):
+ Column('deleted', Boolean),
+ Column('id', String(length=36), primary_key=True, nullable=False),
+ Column('volume_id', String(length=36), nullable=False),
+- Column('user_id', String(length=255)),
+- Column('project_id', String(length=255)),
+- Column('status', String(length=255)),
+- Column('progress', String(length=255)),
++ Column('user_id', String(length=db_string_length)),
++ Column('project_id', String(length=db_string_length)),
++ Column('status', String(length=db_string_length)),
++ Column('progress', String(length=db_string_length)),
+ Column('volume_size', Integer),
+ Column('scheduled_at', DateTime),
+- Column('display_name', String(length=255)),
+- Column('display_description', String(length=255)),
+- mysql_engine='InnoDB'
++ Column('display_name', String(length=db_string_length)),
++ Column('display_description', String(length=db_string_length)),
++ mysql_engine=CONF.database.mysql_storage_engine
+ )
+
+ volume_types = Table(
+@@ -125,8 +132,8 @@ def define_tables(meta):
+ Column('deleted_at', DateTime),
+ Column('deleted', Boolean),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('name', String(length=255)),
+- mysql_engine='InnoDB'
++ Column('name', String(length=db_string_length)),
++ mysql_engine=CONF.database.mysql_storage_engine
+ )
+
+ volume_metadata = Table(
+@@ -138,9 +145,9 @@ def define_tables(meta):
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('volume_id', String(length=36), ForeignKey('volumes.id'),
+ nullable=False),
+- Column('key', String(length=255)),
+- Column('value', String(length=255)),
+- mysql_engine='InnoDB'
++ Column('key', String(length=db_string_length)),
++ Column('value', String(length=db_string_length)),
++ mysql_engine=CONF.database.mysql_storage_engine
+ )
+
+ volume_type_extra_specs = Table(
+@@ -152,9 +159,9 @@ def define_tables(meta):
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('volume_type_id', Integer, ForeignKey('volume_types.id'),
+ nullable=False),
+- Column('key', String(length=255)),
+- Column('value', String(length=255)),
+- mysql_engine='InnoDB'
++ Column('key', String(length=db_string_length)),
++ Column('value', String(length=db_string_length)),
++ mysql_engine=CONF.database.mysql_storage_engine
+ )
+
+ volumes = Table(
+@@ -164,27 +171,27 @@ def define_tables(meta):
+ Column('deleted_at', DateTime),
+ Column('deleted', Boolean),
+ Column('id', String(length=36), primary_key=True, nullable=False),
+- Column('ec2_id', String(length=255)),
+- Column('user_id', String(length=255)),
+- Column('project_id', String(length=255)),
+- Column('host', String(length=255)),
++ Column('ec2_id', String(length=db_string_length)),
++ Column('user_id', String(length=db_string_length)),
++ Column('project_id', String(length=db_string_length)),
++ Column('host', String(length=db_string_length)),
+ Column('size', Integer),
+- Column('availability_zone', String(length=255)),
++ Column('availability_zone', String(length=db_string_length)),
+ Column('instance_uuid', String(length=36)),
+- Column('mountpoint', String(length=255)),
+- Column('attach_time', String(length=255)),
+- Column('status', String(length=255)),
+- Column('attach_status', String(length=255)),
++ Column('mountpoint', String(length=db_string_length)),
++ Column('attach_time', String(length=db_string_length)),
++ Column('status', String(length=db_string_length)),
++ Column('attach_status', String(length=db_string_length)),
+ Column('scheduled_at', DateTime),
+ Column('launched_at', DateTime),
+ Column('terminated_at', DateTime),
+- Column('display_name', String(length=255)),
+- Column('display_description', String(length=255)),
++ Column('display_name', String(length=db_string_length)),
++ Column('display_description', String(length=db_string_length)),
+ Column('provider_location', String(length=256)),
+ Column('provider_auth', String(length=256)),
+ Column('snapshot_id', String(length=36)),
+ Column('volume_type_id', Integer),
+- mysql_engine='InnoDB'
++ mysql_engine=CONF.database.mysql_storage_engine
+ )
+
+ quotas = Table(
+@@ -194,10 +201,10 @@ def define_tables(meta):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('deleted', Boolean),
+- Column('project_id', String(length=255)),
+- Column('resource', String(length=255), nullable=False),
++ Column('project_id', String(length=db_string_length)),
++ Column('resource', String(length=db_string_length), nullable=False),
+ Column('hard_limit', Integer),
+- mysql_engine='InnoDB'
++ mysql_engine=CONF.database.mysql_storage_engine
+ )
+
+ iscsi_targets = Table(
+@@ -208,10 +215,10 @@ def define_tables(meta):
+ Column('deleted', Boolean),
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('target_num', Integer),
+- Column('host', String(length=255)),
++ Column('host', String(length=db_string_length)),
+ Column('volume_id', String(length=36), ForeignKey('volumes.id'),
+ nullable=True),
+- mysql_engine='InnoDB'
++ mysql_engine=CONF.database.mysql_storage_engine
+ )
+ return [sm_flavors,
+ sm_backend_config,
+@@ -266,7 +273,8 @@ def upgrade(migrate_engine):
+ migrate_engine.execute(
+ "ALTER DATABASE %s DEFAULT CHARACTER SET utf8" %
+ migrate_engine.url.database)
+- migrate_engine.execute("ALTER TABLE %s Engine=InnoDB" % table)
++ migrate_engine.execute("ALTER TABLE %(db_table)s Engine=%(mysql_storage_engine)s" %
++ dict(db_table=table, mysql_storage_engine=CONF.database.mysql_storage_engine))
+
+
+ def downgrade(migrate_engine):
--- a/components/openstack/glance/files/glance-api.conf Fri Apr 01 14:10:25 2016 -0600
+++ b/components/openstack/glance/files/glance-api.conf Fri Apr 01 14:13:41 2016 -0600
@@ -514,6 +514,12 @@
# Example: mysql_sql_mode= (string value)
#mysql_sql_mode = TRADITIONAL
+# This configures the MySQL storage engine. This allows for OpenStack to
+# support different storage engines such as InnoDB, NDB, etc. By Default,
+# this value will be set to InnoDB. For MySQL Cluster, set to NDBCLUSTER.
+# Example: mysql_storage_engine=(string value)
+#mysql_storage_engine = InnoDB
+
# Timeout before idle SQL connections are reaped. (integer value)
# Deprecated group/name - [DEFAULT]/sql_idle_timeout
# Deprecated group/name - [DATABASE]/sql_idle_timeout
--- a/components/openstack/glance/files/glance-registry.conf Fri Apr 01 14:10:25 2016 -0600
+++ b/components/openstack/glance/files/glance-registry.conf Fri Apr 01 14:13:41 2016 -0600
@@ -352,6 +352,12 @@
# Example: mysql_sql_mode= (string value)
#mysql_sql_mode = TRADITIONAL
+# This configures the MySQL storage engine. This allows for OpenStack to
+# support different storage engines such as InnoDB, NDB, etc. By Default,
+# this value will be set to InnoDB. For MySQL Cluster, set to NDBCLUSTER.
+# Example: mysql_storage_engine=(string value)
+#mysql_storage_engine = InnoDB
+
# Timeout before idle SQL connections are reaped. (integer value)
# Deprecated group/name - [DEFAULT]/sql_idle_timeout
# Deprecated group/name - [DATABASE]/sql_idle_timeout
--- a/components/openstack/glance/files/glance-scrubber.conf Fri Apr 01 14:10:25 2016 -0600
+++ b/components/openstack/glance/files/glance-scrubber.conf Fri Apr 01 14:13:41 2016 -0600
@@ -288,6 +288,12 @@
# Example: mysql_sql_mode= (string value)
#mysql_sql_mode = TRADITIONAL
+# This configures the MySQL storage engine. This allows for OpenStack to
+# support different storage engines such as InnoDB, NDB, etc. By Default,
+# this value will be set to InnoDB. For MySQL Cluster, set to NDBCLUSTER.
+# Example: mysql_storage_engine=(string value)
+#mysql_storage_engine = InnoDB
+
# Timeout before idle SQL connections are reaped. (integer value)
# Deprecated group/name - [DEFAULT]/sql_idle_timeout
# Deprecated group/name - [DATABASE]/sql_idle_timeout
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/openstack/glance/patches/mysql_cluster_support.patch Fri Apr 01 14:13:41 2016 -0600
@@ -0,0 +1,1084 @@
+This patchset is for bug:
+
+22725863 - Glance needs to support MySQL Cluster
+
+This fixes the following aspects of Glance:
+1. Implementation of an oslo.db configuration parameter to specify the MySQL
+ storage engine (mysql_storage_engine).
+2. Replacement of hardcoded SQL statements that set the engine to "InnoDB"
+ to the above configuration value.
+3. Logic to handle SQL differences between MySQL InnoDB and MySQL Cluster (NDB).
+ This includes column lengths, constraints, foreign keys, and indexes.
+
+This has not been committed upstream, but has been filed in launchpad:
+
+https://bugs.launchpad.net/glance/+bug/1564110
+
+
+--- glance-2015.1.2/glance/tests/unit/test_migrations.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/tests/unit/test_migrations.py 2016-03-29 17:07:06.903071123 -0600
+@@ -127,7 +127,7 @@ class MigrationsMixin(test_migrations.Wa
+ sqlalchemy.Boolean(),
+ nullable=False,
+ default=False),
+- mysql_engine='InnoDB')
++ mysql_engine=CONF.database.mysql_storage_engine)
+ images_001.create()
+
+ def test_version_control_existing_db(self):
+@@ -1650,10 +1650,10 @@ class TestMysqlMigrations(test_base.MySQ
+ noninnodb = self.migrate_engine.execute(
+ "SELECT count(*) "
+ "FROM information_schema.TABLES "
+- "WHERE TABLE_SCHEMA='%s' "
+- "AND ENGINE!='InnoDB' "
++ "WHERE TABLE_SCHEMA='%(table_schema)s' "
++ "AND ENGINE!='%(mysql_storage_engine)s' "
+ "AND TABLE_NAME!='migrate_version'"
+- % self.migrate_engine.url.database)
++ % dict(table_schema=self.migrate_engine.url.database, mysql_storage_engine=CONF.database.mysql_storage_engine))
+ count = noninnodb.scalar()
+ self.assertEqual(count, 0, "%d non InnoDB tables created" % count)
+
+--- glance-2015.1.2/glance/db/sqlalchemy/models_metadef.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/models_metadef.py 2016-03-29 17:07:06.903402899 -0600
+@@ -31,6 +31,8 @@ from sqlalchemy import Text
+
+ from glance.db.sqlalchemy.models import JSONEncodedDict
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ class DictionaryBase(models.ModelBase):
+ metadata = None
+@@ -48,7 +50,7 @@ BASE_DICT = declarative_base(cls=Diction
+ class GlanceMetadefBase(models.TimestampMixin):
+ """Base class for Glance Metadef Models."""
+
+- __table_args__ = {'mysql_engine': 'InnoDB'}
++ __table_args__ = {'mysql_engine': CONF.database.mysql_storage_engine}
+ __table_initialized__ = False
+ __protected_attributes__ = set(["created_at", "updated_at"])
+
+--- glance-2015.1.2/glance/db/sqlalchemy/models_artifacts.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/models_artifacts.py 2016-03-29 17:07:06.903762560 -0600
+@@ -14,6 +14,8 @@
+
+ import uuid
+
++from oslo_config import cfg
++from oslo_db import options as db_options
+ from oslo_db.sqlalchemy import models
+ from oslo_utils import timeutils
+ from sqlalchemy import BigInteger
+@@ -36,6 +38,9 @@ from glance.common import semver_db
+ from glance import i18n
+ from oslo_log import log as os_logging
+
++CONF = cfg.CONF
++db_options.set_defaults(CONF)
++
+ BASE = declarative.declarative_base()
+ LOG = os_logging.getLogger(__name__)
+ _LW = i18n._LW
+@@ -44,7 +49,7 @@ _LW = i18n._LW
+ class ArtifactBase(models.ModelBase, models.TimestampMixin):
+ """Base class for Artifact Models."""
+
+- __table_args__ = {'mysql_engine': 'InnoDB'}
++ __table_args__ = {'mysql_engine': CONF.database.mysql_storage_engine}
+ __table_initialized__ = False
+ __protected_attributes__ = set([
+ "created_at", "updated_at"])
+@@ -102,7 +107,7 @@ class Artifact(BASE, ArtifactBase):
+ Index('ix_artifact_state', 'state'),
+ Index('ix_artifact_owner', 'owner'),
+ Index('ix_artifact_visibility', 'visibility'),
+- {'mysql_engine': 'InnoDB'})
++ {'mysql_engine': CONF.database.mysql_storage_engine})
+
+ __protected_attributes__ = ArtifactBase.__protected_attributes__.union(
+ set(['published_at', 'deleted_at']))
+@@ -219,7 +224,7 @@ class ArtifactDependency(BASE, ArtifactB
+ 'artifact_dest'),
+ Index('ix_artifact_dependencies_direct_dependencies',
+ 'artifact_source', 'is_direct'),
+- {'mysql_engine': 'InnoDB'})
++ {'mysql_engine': CONF.database.mysql_storage_engine})
+
+ id = Column(String(36), primary_key=True, nullable=False,
+ default=lambda: str(uuid.uuid4()))
+@@ -248,7 +253,7 @@ class ArtifactTag(BASE, ArtifactBase):
+ __table_args__ = (Index('ix_artifact_tags_artifact_id', 'artifact_id'),
+ Index('ix_artifact_tags_artifact_id_tag_value',
+ 'artifact_id', 'value'),
+- {'mysql_engine': 'InnoDB'},)
++ {'mysql_engine': CONF.database.mysql_storage_engine},)
+
+ id = Column(String(36), primary_key=True, nullable=False,
+ default=lambda: str(uuid.uuid4()))
+@@ -265,7 +270,7 @@ class ArtifactProperty(BASE, ArtifactBas
+ __table_args__ = (
+ Index('ix_artifact_properties_artifact_id', 'artifact_id'),
+ Index('ix_artifact_properties_name', 'name'),
+- {'mysql_engine': 'InnoDB'},)
++ {'mysql_engine': CONF.database.mysql_storage_engine},)
+ id = Column(String(36), primary_key=True, nullable=False,
+ default=lambda: str(uuid.uuid4()))
+ artifact_id = Column(String(36), ForeignKey('artifacts.id'),
+@@ -287,7 +292,7 @@ class ArtifactBlob(BASE, ArtifactBase):
+ __table_args__ = (
+ Index('ix_artifact_blobs_artifact_id', 'artifact_id'),
+ Index('ix_artifact_blobs_name', 'name'),
+- {'mysql_engine': 'InnoDB'},)
++ {'mysql_engine': CONF.database.mysql_storage_engine},)
+ id = Column(String(36), primary_key=True, nullable=False,
+ default=lambda: str(uuid.uuid4()))
+ artifact_id = Column(String(36), ForeignKey('artifacts.id'),
+@@ -306,7 +311,7 @@ class ArtifactBlobLocation(BASE, Artifac
+ __tablename__ = 'artifact_blob_locations'
+ __table_args__ = (Index('ix_artifact_blob_locations_blob_id',
+ 'blob_id'),
+- {'mysql_engine': 'InnoDB'})
++ {'mysql_engine': CONF.database.mysql_storage_engine})
+
+ id = Column(String(36), primary_key=True, nullable=False,
+ default=lambda: str(uuid.uuid4()))
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/007_add_owner.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/007_add_owner.py 2016-03-29 17:07:06.903986716 -0600
+@@ -20,6 +20,8 @@ from glance.db.sqlalchemy.migrate_repo.s
+ Boolean, DateTime, BigInteger, Integer, String,
+ Text, from_migration_import) # noqa
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def get_images_table(meta):
+ """
+@@ -50,7 +52,7 @@ def get_images_table(meta):
+ index=True),
+ Column('checksum', String(32)),
+ Column('owner', String(255)),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ extend_existing=True)
+
+ return images
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/003_add_disk_format.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/003_add_disk_format.py 2016-03-29 17:07:06.904214431 -0600
+@@ -19,6 +19,8 @@ from sqlalchemy import * # noqa
+ from glance.db.sqlalchemy.migrate_repo.schema import (
+ Boolean, DateTime, Integer, String, Text, from_migration_import) # noqa
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def get_images_table(meta):
+ """
+@@ -47,7 +49,7 @@ def get_images_table(meta):
+ nullable=False,
+ default=False,
+ index=True),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ extend_existing=True)
+
+ return images
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/005_size_big_integer.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/005_size_big_integer.py 2016-03-29 17:07:06.904424798 -0600
+@@ -20,6 +20,8 @@ from glance.db.sqlalchemy.migrate_repo.s
+ Boolean, DateTime, BigInteger, Integer, String,
+ Text, from_migration_import) # noqa
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def get_images_table(meta):
+ """
+@@ -48,7 +50,7 @@ def get_images_table(meta):
+ nullable=False,
+ default=False,
+ index=True),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ extend_existing=True)
+
+ return images
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/022_image_member_index.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/022_image_member_index.py 2016-03-30 13:24:32.609884883 -0600
+@@ -21,6 +21,8 @@ from sqlalchemy import and_, func, orm
+ from sqlalchemy import MetaData, Table
+ from sqlalchemy.exc import OperationalError, ProgrammingError
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ NEW_KEYNAME = 'image_members_image_id_member_deleted_at_key'
+ ORIGINAL_KEYNAME_RE = re.compile('image_members_image_id.*_key')
+@@ -28,21 +30,24 @@ ORIGINAL_KEYNAME_RE = re.compile('image_
+
+ def upgrade(migrate_engine):
+ image_members = _get_image_members_table(migrate_engine)
+-
+- if migrate_engine.name in ('mysql', 'postgresql'):
+- try:
+- UniqueConstraint('image_id',
+- name=_get_original_keyname(migrate_engine.name),
+- table=image_members).drop()
+- except (OperationalError, ProgrammingError, db_exception.DBError):
+- UniqueConstraint('image_id',
+- name=_infer_original_keyname(image_members),
+- table=image_members).drop()
+- UniqueConstraint('image_id',
+- 'member',
+- 'deleted_at',
+- name=NEW_KEYNAME,
+- table=image_members).create()
++ # MySQL Cluster, a.k.a. NDB does not support the original constraint and index.
++ # Only if we are not using MySQL Cluster, will the index be dropped.
++ if CONF.database.mysql_storage_engine != "NDBCLUSTER":
++ if migrate_engine.name in ('mysql', 'postgresql'):
++ try:
++ UniqueConstraint('image_id',
++ name=_get_original_keyname(migrate_engine.name),
++ table=image_members).drop()
++ except (OperationalError, ProgrammingError, db_exception.DBError):
++ UniqueConstraint('image_id',
++ name=_infer_original_keyname(image_members),
++ table=image_members).drop()
++
++ UniqueConstraint('image_id',
++ 'member',
++ 'deleted_at',
++ name=NEW_KEYNAME,
++ table=image_members).create()
+
+
+ def downgrade(migrate_engine):
+@@ -53,10 +58,13 @@ def downgrade(migrate_engine):
+ UniqueConstraint('image_id',
+ name=NEW_KEYNAME,
+ table=image_members).drop()
+- UniqueConstraint('image_id',
+- 'member',
+- name=_get_original_keyname(migrate_engine.name),
+- table=image_members).create()
++ # MySQL Cluster, a.k.a. NDB does not support the original constraint and index.
++ # Only if we are not using MySQL Cluster, will the index be created.
++ if CONF.database.mysql_storage_engine != "NDBCLUSTER":
++ UniqueConstraint('image_id',
++ 'member',
++ name=_get_original_keyname(migrate_engine.name),
++ table=image_members).create()
+
+
+ def _get_image_members_table(migrate_engine):
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/040_add_changes_to_satisfy_metadefs_tags.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/040_add_changes_to_satisfy_metadefs_tags.py 2016-03-29 17:07:06.904941488 -0600
+@@ -14,11 +14,15 @@
+ import sqlalchemy
+ from sqlalchemy import (Table, Index)
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ if migrate_engine.name == 'mysql':
+ meta = sqlalchemy.MetaData()
+ meta.bind = migrate_engine
+ metadef_tags = Table('metadef_tags', meta, autoload=True)
+- Index('namespace_id', metadef_tags.c.namespace_id,
+- metadef_tags.c.name).drop()
++ # MySQL Cluster, a.k.a NDB, does not support this index drop.
++ if CONF.database.mysql_storage_engine != "NDBCLUSTER":
++ Index('namespace_id', metadef_tags.c.namespace_id,
++ metadef_tags.c.name).drop()
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/001_add_images_table.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/001_add_images_table.py 2016-03-29 17:07:06.905205576 -0600
+@@ -18,6 +18,8 @@ from sqlalchemy.schema import (Column, M
+ from glance.db.sqlalchemy.migrate_repo.schema import (
+ Boolean, DateTime, Integer, String, Text, create_tables, drop_tables) # noqa
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def define_images_table(meta):
+ images = Table('images',
+@@ -41,7 +43,7 @@ def define_images_table(meta):
+ nullable=False,
+ default=False,
+ index=True),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ extend_existing=True)
+
+ return images
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/014_add_image_tags_table.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/014_add_image_tags_table.py 2016-03-29 17:07:06.905423969 -0600
+@@ -17,6 +17,8 @@ from sqlalchemy import schema
+
+ from glance.db.sqlalchemy.migrate_repo import schema as glance_schema
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def define_image_tags_table(meta):
+ # Load the images table so the foreign key can be set up properly
+@@ -46,7 +48,7 @@ def define_image_tags_table(meta):
+ glance_schema.Boolean(),
+ nullable=False,
+ default=False),
+- mysql_engine='InnoDB')
++ mysql_engine=CONF.database.mysql_storage_engine)
+
+ schema.Index('ix_image_tags_image_id',
+ image_tags.c.image_id)
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/038_add_metadef_tags_table.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/038_add_metadef_tags_table.py 2016-03-29 17:07:06.905642340 -0600
+@@ -18,27 +18,46 @@ from sqlalchemy.schema import (
+ from glance.db.sqlalchemy.migrate_repo.schema import (
+ DateTime, Integer, String, create_tables, drop_tables) # noqa
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def define_metadef_tags_table(meta):
+ _constr_kwargs = {}
+- metadef_tags = Table('metadef_tags',
+- meta,
+- Column('id', Integer(), primary_key=True,
+- nullable=False),
+- Column('namespace_id', Integer(),
+- nullable=False),
+- Column('name', String(80), nullable=False),
+- Column('created_at', DateTime(), nullable=False),
+- Column('updated_at', DateTime()),
+- UniqueConstraint('namespace_id', 'name',
+- **_constr_kwargs),
+- mysql_engine='InnoDB',
+- extend_existing=False)
++
++ # MySQL Cluster, a.k.a. NDB, does not support this constraint.
++ # If MySQL Cluster is enabled, the constraint will not be configured.
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ metadef_tags = Table('metadef_tags',
++ meta,
++ Column('id', Integer(), primary_key=True,
++ nullable=False),
++ Column('namespace_id', Integer(),
++ nullable=False),
++ Column('name', String(80), nullable=False),
++ Column('created_at', DateTime(), nullable=False),
++ Column('updated_at', DateTime()),
++ mysql_engine=CONF.database.mysql_storage_engine,
++ extend_existing=False)
++ else:
++ metadef_tags = Table('metadef_tags',
++ meta,
++ Column('id', Integer(), primary_key=True,
++ nullable=False),
++ Column('namespace_id', Integer(),
++ nullable=False),
++ Column('name', String(80), nullable=False),
++ Column('created_at', DateTime(), nullable=False),
++ Column('updated_at', DateTime()),
++ UniqueConstraint('namespace_id', 'name',
++ **_constr_kwargs),
++ mysql_engine=CONF.database.mysql_storage_engine,
++ extend_existing=False)
+
+- if meta.bind.name != 'ibm_db_sa':
+- Index('ix_tags_namespace_id_name',
+- metadef_tags.c.namespace_id,
+- metadef_tags.c.name)
++ if CONF.database.mysql_storage_engine != "NDBCLUSTER":
++ if meta.bind.name != 'ibm_db_sa':
++ Index('ix_tags_namespace_id_name',
++ metadef_tags.c.namespace_id,
++ metadef_tags.c.name)
+
+ return metadef_tags
+
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/006_key_to_name.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/006_key_to_name.py 2016-03-29 17:07:06.905862002 -0600
+@@ -19,6 +19,8 @@ from sqlalchemy import * # noqa
+ from glance.db.sqlalchemy.migrate_repo.schema import (
+ Boolean, DateTime, Integer, String, Text, from_migration_import) # noqa
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def get_images_table(meta):
+ """
+@@ -63,7 +65,7 @@ def get_image_properties_table(meta):
+ default=False,
+ index=True),
+ UniqueConstraint('image_id', 'name'),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ extend_existing=True)
+
+ return image_properties
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/030_add_tasks_table.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/030_add_tasks_table.py 2016-03-29 17:07:06.906075874 -0600
+@@ -19,6 +19,8 @@ from sqlalchemy.schema import (Column, M
+ from glance.db.sqlalchemy.migrate_repo.schema import (
+ Boolean, DateTime, String, Text, create_tables, drop_tables) # noqa
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def define_tasks_table(meta):
+ tasks = Table('tasks',
+@@ -38,7 +40,7 @@ def define_tasks_table(meta):
+ Boolean(),
+ nullable=False,
+ default=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ extend_existing=True)
+
+ Index('ix_tasks_type', tasks.c.type)
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/039_add_changes_to_satisfy_models_metadef.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/039_add_changes_to_satisfy_models_metadef.py 2016-03-29 17:07:06.906324945 -0600
+@@ -16,6 +16,8 @@ from sqlalchemy import inspect
+ from sqlalchemy import (Table, Index, UniqueConstraint)
+ from sqlalchemy.schema import (AddConstraint, DropConstraint)
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = sqlalchemy.MetaData()
+@@ -57,8 +59,10 @@ def upgrade(migrate_engine):
+ metadef_tags.c.name)
+ uc.create()
+
+- Index('ix_tags_namespace_id_name', metadef_tags.c.namespace_id,
+- metadef_tags.c.name).drop()
++ # MySQL Cluster, a.k.a. NDB, does not support this index removal.
++ if CONF.database.mysql_storage_engine != "NDBCLUSTER":
++ Index('ix_tags_namespace_id_name', metadef_tags.c.namespace_id,
++ metadef_tags.c.name).drop()
+
+ Index('ix_metadef_tags_name', metadef_tags.c.name).create()
+
+@@ -190,9 +194,10 @@ def downgrade(migrate_engine):
+ fkc = migrate.ForeignKeyConstraint([metadef_tags.c.namespace_id],
+ [metadef_namespaces.c.id])
+ fkc.drop()
+-
+- Index('ix_tags_namespace_id_name', metadef_tags.c.namespace_id,
+- metadef_tags.c.name).create()
++ # MySQL Cluster, a.k.a. NDB, does not support this index.
++ if CONF.database.mysql_storage_engine != "NDBCLUSTER":
++ Index('ix_tags_namespace_id_name', metadef_tags.c.namespace_id,
++ metadef_tags.c.name).create()
+ else:
+ # NOTE(ochuprykov): fkc can't be dropped via `migrate` in sqlite,so it
+ # is necessary to recreate table manually and populate it with data
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/008_add_image_members_table.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/008_add_image_members_table.py 2016-03-29 17:07:06.906575837 -0600
+@@ -20,6 +20,8 @@ from glance.db.sqlalchemy.migrate_repo.s
+ Boolean, DateTime, Integer, String, create_tables,
+ drop_tables, from_migration_import) # noqa
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def get_images_table(meta):
+ """
+@@ -45,40 +47,71 @@ def get_image_properties_table(meta):
+
+ def get_image_members_table(meta):
+ images = get_images_table(meta) # noqa
+-
+- image_members = Table('image_members',
+- meta,
+- Column('id',
+- Integer(),
+- primary_key=True,
+- nullable=False),
+- Column('image_id',
+- Integer(),
+- ForeignKey('images.id'),
+- nullable=False,
+- index=True),
+- Column('member', String(255), nullable=False),
+- Column('can_share',
+- Boolean(),
+- nullable=False,
+- default=False),
+- 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', 'member'),
+- mysql_engine='InnoDB',
+- extend_existing=True)
++
++ # MySQL Cluster, a.k.a. NDB, does not support this constraint and index.
++ # If MySQl Cluster is being used, the constraint and index will not be created.
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ image_members = Table('image_members',
++ meta,
++ Column('id',
++ Integer(),
++ primary_key=True,
++ nullable=False),
++ Column('image_id',
++ Integer(),
++ ForeignKey('images.id'),
++ nullable=False,
++ index=True),
++ Column('member', String(255), nullable=False),
++ Column('can_share',
++ Boolean(),
++ nullable=False,
++ default=False),
++ Column('created_at', DateTime(), nullable=False),
++ Column('updated_at', DateTime()),
++ Column('deleted_at', DateTime()),
++ Column('deleted',
++ Boolean(),
++ nullable=False,
++ default=False,
++ index=True),
++ mysql_engine=CONF.database.mysql_storage_engine,
++ extend_existing=True)
++ else:
++ image_members = Table('image_members',
++ meta,
++ Column('id',
++ Integer(),
++ primary_key=True,
++ nullable=False),
++ Column('image_id',
++ Integer(),
++ ForeignKey('images.id'),
++ nullable=False,
++ index=True),
++ Column('member', String(255), nullable=False),
++ Column('can_share',
++ Boolean(),
++ nullable=False,
++ default=False),
++ 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', 'member'),
++ mysql_engine=CONF.database.mysql_storage_engine,
++ extend_existing=True)
+
+ # DB2: an index has already been created for the UniqueConstraint option
+ # specified on the Table() statement above.
+- if meta.bind.name != "ibm_db_sa":
+- Index('ix_image_members_image_id_member', image_members.c.image_id,
+- image_members.c.member)
++ if CONF.database.mysql_storage_engine != "NDBCLUSTER":
++ if meta.bind.name != "ibm_db_sa":
++ Index('ix_image_members_image_id_member', image_members.c.image_id,
++ image_members.c.member)
+
+ return image_members
+
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/002_add_image_properties_table.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/002_add_image_properties_table.py 2016-03-29 17:07:06.906818665 -0600
+@@ -20,6 +20,8 @@ from glance.db.sqlalchemy.migrate_repo.s
+ Boolean, DateTime, Integer, String, Text, create_tables, drop_tables,
+ from_migration_import) # noqa
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def define_image_properties_table(meta):
+ (define_images_table,) = from_migration_import(
+@@ -36,31 +38,58 @@ def define_image_properties_table(meta):
+ if meta.bind.name == 'ibm_db_sa':
+ constr_kwargs['name'] = 'ix_image_properties_image_id_key'
+
+- 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('key', 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', 'key',
+- **constr_kwargs),
+- mysql_engine='InnoDB',
+- extend_existing=True)
++ # MySQL Cluster, a.k.a. NDB, does not support the constraint here.
++ # This will remove the constraint if MySQL Cluster is being used.
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ 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('key', 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),
++ mysql_engine=CONF.database.mysql_storage_engine,
++ extend_existing=True)
++ else:
++ 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('key', 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', 'key',
++ **constr_kwargs),
++ mysql_engine=CONF.database.mysql_storage_engine,
++ extend_existing=True)
+
+ if meta.bind.name != 'ibm_db_sa':
+ Index('ix_image_properties_image_id_key',
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/035_add_metadef_tables.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/035_add_metadef_tables.py 2016-03-29 17:07:06.907133202 -0600
+@@ -21,6 +21,8 @@ from glance.db.sqlalchemy.migrate_repo.s
+ Boolean, DateTime, Integer, String, Text, create_tables,
+ drop_tables) # noqa
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ RESOURCE_TYPES = [u'OS::Glance::Image', u'OS::Cinder::Volume',
+ u'OS::Nova::Flavor', u'OS::Nova::Aggregate',
+@@ -65,7 +67,7 @@ def define_metadef_namespaces_table(meta
+ Column('created_at', DateTime(), nullable=False),
+ Column('updated_at', DateTime()),
+ UniqueConstraint('namespace', **_constr_kwargs),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ extend_existing=True)
+
+ if meta.bind.name != 'ibm_db_sa':
+@@ -80,22 +82,41 @@ def define_metadef_objects_table(meta):
+ if meta.bind.name == 'ibm_db_sa':
+ _constr_kwargs['name'] = 'ix_objects_namespace_id_name'
+
+- objects = Table('metadef_objects',
+- meta,
+- Column('id', Integer(), primary_key=True, nullable=False),
+- Column('namespace_id', Integer(),
+- ForeignKey('metadef_namespaces.id'),
+- nullable=False),
+- Column('name', String(80), nullable=False),
+- Column('description', Text()),
+- Column('required', Text()),
+- Column('schema', Text(), nullable=False),
+- Column('created_at', DateTime(), nullable=False),
+- Column('updated_at', DateTime()),
+- UniqueConstraint('namespace_id', 'name',
+- **_constr_kwargs),
+- mysql_engine='InnoDB',
+- extend_existing=True)
++ # MySQL Cluster, a.k.a. NDB, requires explicit foreign key names
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ objects = Table('metadef_objects',
++ meta,
++ Column('id', Integer(), primary_key=True, nullable=False),
++ Column('namespace_id', Integer(),
++ ForeignKey('metadef_namespaces.id', name='metadef_objects_ibfk_1'),
++ nullable=False),
++ Column('name', String(80), nullable=False),
++ Column('description', Text()),
++ Column('required', Text()),
++ Column('schema', Text(), nullable=False),
++ Column('created_at', DateTime(), nullable=False),
++ Column('updated_at', DateTime()),
++ UniqueConstraint('namespace_id', 'name',
++ **_constr_kwargs),
++ mysql_engine=CONF.database.mysql_storage_engine,
++ extend_existing=True)
++ else:
++ objects = Table('metadef_objects',
++ meta,
++ Column('id', Integer(), primary_key=True, nullable=False),
++ Column('namespace_id', Integer(),
++ ForeignKey('metadef_namespaces.id'),
++ nullable=False),
++ Column('name', String(80), nullable=False),
++ Column('description', Text()),
++ Column('required', Text()),
++ Column('schema', Text(), nullable=False),
++ Column('created_at', DateTime(), nullable=False),
++ Column('updated_at', DateTime()),
++ UniqueConstraint('namespace_id', 'name',
++ **_constr_kwargs),
++ mysql_engine=CONF.database.mysql_storage_engine,
++ extend_existing=True)
+
+ if meta.bind.name != 'ibm_db_sa':
+ Index('ix_objects_namespace_id_name',
+@@ -111,19 +132,35 @@ def define_metadef_properties_table(meta
+ if meta.bind.name == 'ibm_db_sa':
+ _constr_kwargs['name'] = 'ix_metadef_properties_namespace_id_name'
+
+- metadef_properties = Table(
+- 'metadef_properties',
+- meta,
+- Column('id', Integer(), primary_key=True, nullable=False),
+- Column('namespace_id', Integer(), ForeignKey('metadef_namespaces.id'),
+- nullable=False),
+- Column('name', String(80), nullable=False),
+- Column('schema', Text(), nullable=False),
+- Column('created_at', DateTime(), nullable=False),
+- Column('updated_at', DateTime()),
+- UniqueConstraint('namespace_id', 'name', **_constr_kwargs),
+- mysql_engine='InnoDB',
+- extend_existing=True)
++ # MySQL Cluster, a.k.a. NDB, requires explicit foreign key names
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ metadef_properties = Table(
++ 'metadef_properties',
++ meta,
++ Column('id', Integer(), primary_key=True, nullable=False),
++ Column('namespace_id', Integer(), ForeignKey('metadef_namespaces.id', name='metadef_properties_ibfk_1'),
++ nullable=False),
++ Column('name', String(80), nullable=False),
++ Column('schema', Text(), nullable=False),
++ Column('created_at', DateTime(), nullable=False),
++ Column('updated_at', DateTime()),
++ UniqueConstraint('namespace_id', 'name', **_constr_kwargs),
++ mysql_engine=CONF.database.mysql_storage_engine,
++ extend_existing=True)
++ else:
++ metadef_properties = Table(
++ 'metadef_properties',
++ meta,
++ Column('id', Integer(), primary_key=True, nullable=False),
++ Column('namespace_id', Integer(), ForeignKey('metadef_namespaces.id'),
++ nullable=False),
++ Column('name', String(80), nullable=False),
++ Column('schema', Text(), nullable=False),
++ Column('created_at', DateTime(), nullable=False),
++ Column('updated_at', DateTime()),
++ UniqueConstraint('namespace_id', 'name', **_constr_kwargs),
++ mysql_engine=CONF.database.mysql_storage_engine,
++ extend_existing=True)
+
+ if meta.bind.name != 'ibm_db_sa':
+ Index('ix_metadef_properties_namespace_id_name',
+@@ -148,7 +185,7 @@ def define_metadef_resource_types_table(
+ Column('created_at', DateTime(), nullable=False),
+ Column('updated_at', DateTime()),
+ UniqueConstraint('name', **_constr_kwargs),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ extend_existing=True)
+
+ if meta.bind.name != 'ibm_db_sa':
+@@ -164,23 +201,41 @@ def define_metadef_namespace_resource_ty
+ if meta.bind.name == 'ibm_db_sa':
+ _constr_kwargs['name'] = 'ix_metadef_ns_res_types_res_type_id_ns_id'
+
+- metadef_associations = Table(
+- 'metadef_namespace_resource_types',
+- meta,
+- Column('resource_type_id', Integer(),
+- ForeignKey('metadef_resource_types.id'),
+- primary_key=True, nullable=False),
+- Column('namespace_id', Integer(),
+- ForeignKey('metadef_namespaces.id'),
+- primary_key=True, nullable=False),
+- Column('properties_target', String(80)),
+- Column('prefix', String(80)),
+- Column('created_at', DateTime(), nullable=False),
+- Column('updated_at', DateTime()),
+- UniqueConstraint('resource_type_id', 'namespace_id',
+- **_constr_kwargs),
+- mysql_engine='InnoDB',
+- extend_existing=True)
++ # MySQL Cluster, a.k.a. NDB, does not support these foreign keys, which are later removed.
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ metadef_associations = Table(
++ 'metadef_namespace_resource_types',
++ meta,
++ Column('resource_type_id', Integer(),
++ primary_key=True, nullable=False),
++ Column('namespace_id', Integer(),
++ primary_key=True, nullable=False),
++ Column('properties_target', String(80)),
++ Column('prefix', String(80)),
++ Column('created_at', DateTime(), nullable=False),
++ Column('updated_at', DateTime()),
++ UniqueConstraint('resource_type_id', 'namespace_id',
++ **_constr_kwargs),
++ mysql_engine=CONF.database.mysql_storage_engine,
++ extend_existing=True)
++ else:
++ metadef_associations = Table(
++ 'metadef_namespace_resource_types',
++ meta,
++ Column('resource_type_id', Integer(),
++ ForeignKey('metadef_resource_types.id'),
++ primary_key=True, nullable=False),
++ Column('namespace_id', Integer(),
++ ForeignKey('metadef_namespaces.id'),
++ primary_key=True, nullable=False),
++ Column('properties_target', String(80)),
++ Column('prefix', String(80)),
++ Column('created_at', DateTime(), nullable=False),
++ Column('updated_at', DateTime()),
++ UniqueConstraint('resource_type_id', 'namespace_id',
++ **_constr_kwargs),
++ mysql_engine=CONF.database.mysql_storage_engine,
++ extend_existing=True)
+
+ if meta.bind.name != 'ibm_db_sa':
+ Index('ix_metadef_ns_res_types_res_type_id_ns_id',
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/037_add_changes_to_satisfy_models.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/037_add_changes_to_satisfy_models.py 2016-03-29 17:07:06.907343254 -0600
+@@ -17,6 +17,8 @@ from sqlalchemy.schema import (AddConstr
+ from sqlalchemy import sql
+ from sqlalchemy import update
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = sqlalchemy.MetaData()
+@@ -74,10 +76,14 @@ def upgrade(migrate_engine):
+
+ 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))
++ # MySQL Cluster, a.k.a. NDB, does not support the constraint here.
++ # This will only add the constraint if MySQL Cluster is not being used.
++ if CONF.database.mysql_storage_engine != "NDBCLUSTER":
++ 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(
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/009_add_mindisk_and_minram.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/009_add_mindisk_and_minram.py 2016-03-29 17:07:06.907546197 -0600
+@@ -19,6 +19,8 @@ from sqlalchemy import * # noqa
+ from glance.db.sqlalchemy.migrate_repo.schema import (
+ Boolean, DateTime, Integer, String, Text, from_migration_import) # noqa
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def get_images_table(meta):
+ """
+@@ -51,7 +53,7 @@ def get_images_table(meta):
+ Column('owner', String(255)),
+ Column('min_disk', Integer(), default=0),
+ Column('min_ram', Integer(), default=0),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ extend_existing=True)
+
+ return images
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/032_add_task_info_table.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/032_add_task_info_table.py 2016-03-29 17:07:06.907745900 -0600
+@@ -22,6 +22,8 @@ from glance.db.sqlalchemy.migrate_repo.s
+
+ TASKS_MIGRATE_COLUMNS = ['input', 'message', 'result']
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def define_task_info_table(meta):
+ Table('tasks', meta, autoload=True)
+@@ -37,7 +39,7 @@ def define_task_info_table(meta):
+ Column('input', Text()),
+ Column('result', Text()),
+ Column('message', Text()),
+- mysql_engine='InnoDB')
++ mysql_engine=CONF.database.mysql_storage_engine)
+
+ return task_info
+
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/004_add_checksum.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/004_add_checksum.py 2016-03-29 17:07:06.907943819 -0600
+@@ -19,6 +19,8 @@ from sqlalchemy import * # noqa
+ from glance.db.sqlalchemy.migrate_repo.schema import (
+ Boolean, DateTime, Integer, String, Text, from_migration_import) # noqa
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def get_images_table(meta):
+ """
+@@ -48,7 +50,7 @@ def get_images_table(meta):
+ default=False,
+ index=True),
+ Column('checksum', String(32)),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ extend_existing=True)
+
+ return images
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/021_set_engine_mysql_innodb.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/021_set_engine_mysql_innodb.py 2016-03-30 13:26:40.476217686 -0600
+@@ -18,17 +18,20 @@ from sqlalchemy import MetaData
+
+ tables = ['image_locations']
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = MetaData()
+ meta.bind = migrate_engine
+ if migrate_engine.name == "mysql":
+- d = migrate_engine.execute("SHOW TABLE STATUS WHERE Engine!='InnoDB';")
++ d = migrate_engine.execute("SHOW TABLE STATUS WHERE Engine!='%s';" %
++ CONF.database.mysql_storage_engine)
+ for row in d.fetchall():
+ table_name = row[0]
+ if table_name in tables:
+- migrate_engine.execute("ALTER TABLE %s Engine=InnoDB" %
+- table_name)
++ migrate_engine.execute("ALTER TABLE %(db_table)s Engine=%(mysql_storage_engine)s" %
++ dict(db_table=table_name, mysql_storage_engine=CONF.database.mysql_storage_engine))
+
+
+ def downgrade(migrate_engine):
+--- glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/041_add_artifact_tables.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/migrate_repo/versions/041_add_artifact_tables.py 2016-03-29 17:07:06.908396017 -0600
+@@ -19,6 +19,8 @@ from glance.db.sqlalchemy.migrate_repo.s
+ BigInteger, Boolean, DateTime, Integer, Numeric, String, Text,
+ create_tables) # noqa
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def define_artifacts_table(meta):
+ artifacts = Table('artifacts',
+@@ -43,7 +45,7 @@ def define_artifacts_table(meta):
+ nullable=False),
+ Column('deleted_at', DateTime()),
+ Column('published_at', DateTime()),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ extend_existing=True)
+
+ Index('ix_artifact_name_and_version', artifacts.c.name,
+@@ -68,7 +70,7 @@ def define_artifact_tags_table(meta):
+ Column('created_at', DateTime(), nullable=False),
+ Column('updated_at', DateTime(),
+ nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ extend_existing=True)
+
+ Index('ix_artifact_tags_artifact_id', artifact_tags.c.artifact_id)
+@@ -100,7 +102,7 @@ def define_artifact_dependencies_table(m
+ nullable=False),
+ Column('updated_at', DateTime(),
+ nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ extend_existing=True)
+
+ Index('ix_artifact_dependencies_source_id',
+@@ -131,7 +133,7 @@ def define_artifact_blobs_table(meta):
+ Column('created_at', DateTime(), nullable=False),
+ Column('updated_at', DateTime(),
+ nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ extend_existing=True)
+ Index('ix_artifact_blobs_artifact_id',
+ artifact_blobs.c.artifact_id)
+@@ -161,7 +163,7 @@ def define_artifact_properties_table(met
+ Column('updated_at', DateTime(),
+ nullable=False),
+ Column('position', Integer()),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ extend_existing=True)
+ Index('ix_artifact_properties_artifact_id',
+ artifact_properties.c.artifact_id)
+@@ -186,7 +188,7 @@ def define_artifact_blob_locations_table
+ Column('position', Integer()),
+ Column('status', String(36),
+ nullable=True),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ extend_existing=True)
+ Index('ix_artifact_blob_locations_blob_id',
+ artifact_blob_locations.c.blob_id)
+--- glance-2015.1.2/glance/db/sqlalchemy/models.py.orig 2016-03-29 17:03:10.000000000 -0600
++++ glance-2015.1.2/glance/db/sqlalchemy/models.py 2016-03-29 17:07:06.908596794 -0600
+@@ -39,6 +39,8 @@ from sqlalchemy import Text
+ from sqlalchemy.types import TypeDecorator
+ from sqlalchemy import UniqueConstraint
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ BASE = declarative_base()
+
+@@ -67,7 +69,7 @@ class JSONEncodedDict(TypeDecorator):
+ class GlanceBase(models.ModelBase, models.TimestampMixin):
+ """Base class for Glance Models."""
+
+- __table_args__ = {'mysql_engine': 'InnoDB'}
++ __table_args__ = {'mysql_engine': CONF.database.mysql_storage_engine}
+ __table_initialized__ = False
+ __protected_attributes__ = set([
+ "created_at", "updated_at", "deleted_at", "deleted"])
--- a/components/openstack/heat/files/heat.conf Fri Apr 01 14:10:25 2016 -0600
+++ b/components/openstack/heat/files/heat.conf Fri Apr 01 14:13:41 2016 -0600
@@ -727,6 +727,12 @@
# (string value)
#mysql_sql_mode = TRADITIONAL
+# This configures the MySQL storage engine. This allows for OpenStack to
+# support different storage engines such as InnoDB, NDB, etc. By Default,
+# this value will be set to InnoDB. For MySQL Cluster, set to NDBCLUSTER.
+# Example: mysql_storage_engine=(string value)
+#mysql_storage_engine = InnoDB
+
# Timeout before idle SQL connections are reaped. (integer value)
# Deprecated group/name - [DEFAULT]/sql_idle_timeout
# Deprecated group/name - [DATABASE]/sql_idle_timeout
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/openstack/heat/patches/mysql_cluster_support.patch Fri Apr 01 14:13:41 2016 -0600
@@ -0,0 +1,279 @@
+This patchset is for bug:
+
+22725887 - Heat needs to support MySQL Cluster
+
+This fixes the following aspects of Heat:
+1. Implementation of an oslo.db configuration parameter to specify the MySQL
+ storage engine (mysql_storage_engine).
+2. Replacement of hardcoded SQL statements that set the engine to "InnoDB"
+ to the above configuration value.
+3. Logic to handle SQL differences between MySQL InnoDB and MySQL Cluster (NDB).
+ This includes column lengths, constraints, foreign keys, and indexes.
+
+This has not been committed upstream, but has been filed in launchpad:
+
+https://bugs.launchpad.net/heat/+bug/1564110
+
+
+--- heat-2015.1.2/heat/db/sqlalchemy/migrate_repo/versions/054_stack_tags_table.py.orig 2016-03-21 13:47:51.478823055 -0600
++++ heat-2015.1.2/heat/db/sqlalchemy/migrate_repo/versions/054_stack_tags_table.py 2016-03-21 14:10:49.491818130 -0600
+@@ -15,6 +15,8 @@ import sqlalchemy
+
+ from heat.db.sqlalchemy import types as heat_db_types
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = sqlalchemy.MetaData(bind=migrate_engine)
+@@ -35,7 +37,7 @@ def upgrade(migrate_engine):
+ sqlalchemy.String(36),
+ sqlalchemy.ForeignKey('stack.id'),
+ nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+ stack_tag.create()
+--- heat-2015.1.2/heat/db/sqlalchemy/migrate_repo/versions/015_grizzly.py.orig 2016-03-21 13:47:51.489113007 -0600
++++ heat-2015.1.2/heat/db/sqlalchemy/migrate_repo/versions/015_grizzly.py 2016-03-21 14:12:11.161688299 -0600
+@@ -13,6 +13,8 @@
+
+ import sqlalchemy
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = sqlalchemy.MetaData()
+@@ -25,7 +27,7 @@ def upgrade(migrate_engine):
+ sqlalchemy.Column('created_at', sqlalchemy.DateTime),
+ sqlalchemy.Column('updated_at', sqlalchemy.DateTime),
+ sqlalchemy.Column('template', sqlalchemy.Text),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -44,7 +46,7 @@ def upgrade(migrate_engine):
+ sqlalchemy.Column('aws_auth_url', sqlalchemy.Text),
+ sqlalchemy.Column('tenant_id', sqlalchemy.String(256)),
+ sqlalchemy.Column('aws_creds', sqlalchemy.Text),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -71,7 +73,7 @@ def upgrade(migrate_engine):
+ sqlalchemy.Column('tenant', sqlalchemy.String(256)),
+ sqlalchemy.Column('disable_rollback', sqlalchemy.Boolean,
+ nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -88,7 +90,7 @@ def upgrade(migrate_engine):
+ sqlalchemy.Column('stack_id', sqlalchemy.String(36),
+ sqlalchemy.ForeignKey('stack.id'), nullable=False),
+ sqlalchemy.Column('rsrc_metadata', sqlalchemy.Text),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -106,7 +108,7 @@ def upgrade(migrate_engine):
+ sqlalchemy.Column('resource_status_reason', sqlalchemy.String(255)),
+ sqlalchemy.Column('resource_type', sqlalchemy.String(255)),
+ sqlalchemy.Column('resource_properties', sqlalchemy.PickleType),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -122,7 +124,7 @@ def upgrade(migrate_engine):
+ sqlalchemy.Column('last_evaluated', sqlalchemy.DateTime),
+ sqlalchemy.Column('stack_id', sqlalchemy.String(36),
+ sqlalchemy.ForeignKey('stack.id'), nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -136,7 +138,7 @@ def upgrade(migrate_engine):
+ sqlalchemy.Column('watch_rule_id', sqlalchemy.Integer,
+ sqlalchemy.ForeignKey('watch_rule.id'),
+ nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+--- heat-2015.1.2/heat/db/sqlalchemy/migrate_repo/versions/059_sync_point.py.orig 2016-03-21 13:47:51.477364113 -0600
++++ heat-2015.1.2/heat/db/sqlalchemy/migrate_repo/versions/059_sync_point.py 2016-03-21 14:10:19.959407071 -0600
+@@ -15,6 +15,8 @@ import sqlalchemy
+
+ from heat.db.sqlalchemy import types as heat_db_types
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = sqlalchemy.MetaData()
+@@ -41,7 +43,7 @@ def upgrade(migrate_engine):
+ sqlalchemy.ForeignKeyConstraint(['stack_id'], ['stack.id'],
+ name='fk_stack_id'),
+
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+ sync_point.create()
+--- heat-2015.1.2/heat/db/sqlalchemy/migrate_repo/versions/033_software_config.py.orig 2016-03-21 13:47:51.474901896 -0600
++++ heat-2015.1.2/heat/db/sqlalchemy/migrate_repo/versions/033_software_config.py 2016-03-21 14:09:45.997088917 -0600
+@@ -15,6 +15,8 @@ import sqlalchemy
+
+ from heat.db.sqlalchemy import types
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = sqlalchemy.MetaData()
+@@ -34,7 +36,7 @@ def upgrade(migrate_engine):
+ sqlalchemy.Column('tenant', sqlalchemy.String(64),
+ nullable=False,
+ index=True),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+ software_config.create()
+@@ -63,7 +65,7 @@ def upgrade(migrate_engine):
+ sqlalchemy.Column('tenant', sqlalchemy.String(64),
+ nullable=False,
+ index=True),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+ software_deployment.create()
+--- heat-2015.1.2/heat/db/sqlalchemy/migrate_repo/versions/057_resource_uuid_to_id.py.orig 2016-03-21 15:20:39.094701078 -0600
++++ heat-2015.1.2/heat/db/sqlalchemy/migrate_repo/versions/057_resource_uuid_to_id.py 2016-03-21 15:27:03.703520056 -0600
+@@ -194,10 +194,11 @@ def upgrade_resource_data_post(migrate_e
+ name = inspector.get_indexes('resource_data')[0]['name']
+ sqlalchemy.Index(name, rd_table.c.resource_id).drop()
+
++ # Change column before it becomes a foreign key
++ rd_table.c.resource_id.alter(nullable=False)
+ cons = migrate.ForeignKeyConstraint(columns=[rd_table.c.resource_id],
+ refcolumns=[res_table.c.id])
+ cons.create()
+- rd_table.c.resource_id.alter(nullable=False)
+
+ rd_table.c.tmp_res_uuid.drop()
+
+--- heat-2015.1.2/heat/db/sqlalchemy/migrate_repo/versions/044_snapshots.py.orig 2016-03-21 13:47:51.463766122 -0600
++++ heat-2015.1.2/heat/db/sqlalchemy/migrate_repo/versions/044_snapshots.py 2016-03-21 14:06:42.631756412 -0600
+@@ -15,6 +15,8 @@ import sqlalchemy
+
+ from heat.db.sqlalchemy import types
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = sqlalchemy.MetaData()
+@@ -38,7 +40,7 @@ def upgrade(migrate_engine):
+ sqlalchemy.Column('tenant', sqlalchemy.String(64),
+ nullable=False,
+ index=True),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+ sqlalchemy.Table('stack', meta, autoload=True)
+--- heat-2015.1.2/heat/db/sqlalchemy/migrate_repo/versions/051_service.py.orig 2016-03-21 13:47:51.491891604 -0600
++++ heat-2015.1.2/heat/db/sqlalchemy/migrate_repo/versions/051_service.py 2016-03-21 14:13:20.248008442 -0600
+@@ -17,6 +17,8 @@ import uuid
+
+ import sqlalchemy
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = sqlalchemy.MetaData()
+@@ -36,7 +38,7 @@ def upgrade(migrate_engine):
+ sqlalchemy.Column('created_at', sqlalchemy.DateTime),
+ sqlalchemy.Column('updated_at', sqlalchemy.DateTime),
+ sqlalchemy.Column('deleted_at', sqlalchemy.DateTime),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+ service.create()
+--- heat-2015.1.2/heat/db/sqlalchemy/migrate_repo/versions/021_resource_data.py.orig 2016-03-21 13:47:51.490496353 -0600
++++ heat-2015.1.2/heat/db/sqlalchemy/migrate_repo/versions/021_resource_data.py 2016-03-21 14:12:44.701121260 -0600
+@@ -13,6 +13,8 @@
+
+ import sqlalchemy
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = sqlalchemy.MetaData()
+@@ -33,7 +35,7 @@ def upgrade(migrate_engine):
+ sqlalchemy.String(36),
+ sqlalchemy.ForeignKey('resource.id'),
+ nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+ sqlalchemy.Table('resource', meta, autoload=True)
+--- heat-2015.1.2/heat/db/sqlalchemy/migrate_repo/versions/031_stack_lock.py.orig 2016-03-21 13:47:51.493279368 -0600
++++ heat-2015.1.2/heat/db/sqlalchemy/migrate_repo/versions/031_stack_lock.py 2016-03-21 14:13:42.399970934 -0600
+@@ -13,6 +13,8 @@
+
+ import sqlalchemy
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = sqlalchemy.MetaData()
+@@ -27,7 +29,7 @@ def upgrade(migrate_engine):
+ sqlalchemy.Column('created_at', sqlalchemy.DateTime),
+ sqlalchemy.Column('updated_at', sqlalchemy.DateTime),
+ sqlalchemy.Column('engine_id', sqlalchemy.String(length=36)),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+ sqlalchemy.Table('stack', meta, autoload=True)
+--- heat-2015.1.2/heat/db/sqlalchemy/models.py.orig 2016-03-21 13:47:51.458115014 -0600
++++ heat-2015.1.2/heat/db/sqlalchemy/models.py 2016-03-21 14:03:29.252734801 -0600
+@@ -27,6 +27,9 @@ from sqlalchemy.orm import session as or
+
+ from heat.db.sqlalchemy import types
+
++from oslo_config import cfg
++CONF = cfg.CONF
++
+ BASE = declarative.declarative_base()
+
+
+@@ -37,7 +40,10 @@ def get_session():
+
+ class HeatBase(models.ModelBase, models.TimestampMixin):
+ """Base class for Heat Models."""
+- __table_args__ = {'mysql_engine': 'InnoDB'}
++ if CONF.database.mysql_storage_engine == 'NDBCLUSTER':
++ __table_args__ = {'mysql_engine': 'NDBCLUSTER'}
++ else:
++ __table_args__ = {'mysql_engine': 'InnoDB'}
+
+ def expire(self, session=None, attrs=None):
+ """Expire this object ()."""
--- a/components/openstack/ironic/files/ironic.conf Fri Apr 01 14:10:25 2016 -0600
+++ b/components/openstack/ironic/files/ironic.conf Fri Apr 01 14:13:41 2016 -0600
@@ -635,6 +635,12 @@
# value)
#mysql_sql_mode=TRADITIONAL
+# This configures the MySQL storage engine. This allows for OpenStack to
+# support different storage engines such as InnoDB, NDB, etc. By Default,
+# this value will be set to InnoDB. For MySQL Cluster, set to NDBCLUSTER.
+# Example: mysql_storage_engine=(string value)
+#mysql_storage_engine = InnoDB
+
# Timeout before idle SQL connections are reaped. (integer
# value)
# Deprecated group/name - [DEFAULT]/sql_idle_timeout
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/openstack/ironic/patches/mysql_cluster_support.patch Fri Apr 01 14:13:41 2016 -0600
@@ -0,0 +1,92 @@
+This patchset is for bug:
+
+22726240 - Ironic needs to support MySQL Cluster
+
+This fixes the following aspects of Ironic:
+1. Implementation of an oslo.db configuration parameter to specify the MySQL
+ storage engine (mysql_storage_engine).
+2. Replacement of hardcoded SQL statements that set the engine to "InnoDB"
+ to the above configuration value.
+3. Logic to handle SQL differences between MySQL InnoDB and MySQL Cluster (NDB).
+ This includes column lengths, constraints, foreign keys, and indexes.
+
+This has not been committed upstream, but has been filed in launchpad:
+
+https://bugs.launchpad.net/ironic/+bug/1564110
+
+
+--- ironic-2015.1.2/ironic/db/sqlalchemy/alembic/versions/2581ebaf0cb2_initial_migration.py.orig 2016-03-21 16:12:03.214356068 -0600
++++ ironic-2015.1.2/ironic/db/sqlalchemy/alembic/versions/2581ebaf0cb2_initial_migration.py 2016-03-21 16:33:15.312722952 -0600
+@@ -26,6 +26,8 @@ down_revision = None
+ from alembic import op
+ import sqlalchemy as sa
+
++from oslo_config import cfg
++CONF = cfg.CONF
+
+ def upgrade():
+ # commands auto generated by Alembic - please adjust!
+@@ -38,7 +40,7 @@ def upgrade():
+ sa.Column('drivers', sa.Text(), nullable=True),
+ sa.PrimaryKeyConstraint('id'),
+ sa.UniqueConstraint('hostname', name='uniq_conductors0hostname'),
+- mysql_ENGINE='InnoDB',
++ mysql_ENGINE=CONF.database.mysql_storage_engine,
+ mysql_DEFAULT_CHARSET='UTF8'
+ )
+ op.create_table(
+@@ -51,7 +53,7 @@ def upgrade():
+ sa.Column('description', sa.String(length=255), nullable=True),
+ sa.PrimaryKeyConstraint('id'),
+ sa.UniqueConstraint('uuid', name='uniq_chassis0uuid'),
+- mysql_ENGINE='InnoDB',
++ mysql_ENGINE=CONF.database.mysql_storage_engine,
+ mysql_DEFAULT_CHARSET='UTF8'
+ )
+ op.create_table(
+@@ -77,7 +79,7 @@ def upgrade():
+ sa.ForeignKeyConstraint(['chassis_id'], ['chassis.id'], ),
+ sa.PrimaryKeyConstraint('id'),
+ sa.UniqueConstraint('uuid', name='uniq_nodes0uuid'),
+- mysql_ENGINE='InnoDB',
++ mysql_ENGINE=CONF.database.mysql_storage_engine,
+ mysql_DEFAULT_CHARSET='UTF8'
+ )
+ op.create_index('node_instance_uuid', 'nodes', ['instance_uuid'],
+@@ -95,7 +97,7 @@ def upgrade():
+ sa.PrimaryKeyConstraint('id'),
+ sa.UniqueConstraint('address', name='uniq_ports0address'),
+ sa.UniqueConstraint('uuid', name='uniq_ports0uuid'),
+- mysql_ENGINE='InnoDB',
++ mysql_ENGINE=CONF.database.mysql_storage_engine,
+ mysql_DEFAULT_CHARSET='UTF8'
+ )
+ # end Alembic commands
+--- ironic-2015.1.2/ironic/db/sqlalchemy/alembic/versions/487deb87cc9d_add_conductor_affinity_and_online.py.orig 2016-03-21 17:24:03.913800383 -0600
++++ ironic-2015.1.2/ironic/db/sqlalchemy/alembic/versions/487deb87cc9d_add_conductor_affinity_and_online.py 2016-03-22 10:35:08.185257998 -0600
+@@ -29,7 +29,7 @@ import sqlalchemy as sa
+ def upgrade():
+ op.add_column(
+ 'conductors',
+- sa.Column('online', sa.Boolean(), default=True))
++ sa.Column('online', sa.Boolean(), default=True, quote=True))
+ op.add_column(
+ 'nodes',
+ sa.Column('conductor_affinity', sa.Integer(),
+--- ironic-2015.1.2/ironic/db/sqlalchemy/models.py.orig 2016-03-21 16:12:03.216554516 -0600
++++ ironic-2015.1.2/ironic/db/sqlalchemy/models.py 2016-03-21 17:13:13.683753382 -0600
+@@ -49,8 +49,12 @@ db_options.set_defaults(cfg.CONF, _DEFAU
+ def table_args():
+ engine_name = urlparse.urlparse(cfg.CONF.database.connection).scheme
+ if engine_name == 'mysql':
+- return {'mysql_engine': cfg.CONF.database.mysql_engine,
+- 'mysql_charset': "utf8"}
++ if cfg.CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ return {'mysql_engine': cfg.CONF.database.mysql_storage_engine,
++ 'mysql_charset': "utf8"}
++ else:
++ return {'mysql_engine': cfg.CONF.database.mysql_engine,
++ 'mysql_charset': "utf8"}
+ return None
+
+
--- a/components/openstack/keystone/files/keystone.conf Fri Apr 01 14:10:25 2016 -0600
+++ b/components/openstack/keystone/files/keystone.conf Fri Apr 01 14:13:41 2016 -0600
@@ -427,6 +427,12 @@
# (string value)
#mysql_sql_mode = TRADITIONAL
+# This configures the MySQL storage engine. This allows for OpenStack to
+# support different storage engines such as InnoDB, NDB, etc. By Default,
+# this value will be set to InnoDB. For MySQL Cluster, set to NDBCLUSTER.
+# Example: mysql_storage_engine=(string value)
+#mysql_storage_engine = InnoDB
+
# Timeout before idle SQL connections are reaped. (integer value)
# Deprecated group/name - [DEFAULT]/sql_idle_timeout
# Deprecated group/name - [DATABASE]/sql_idle_timeout
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/openstack/keystone/patches/mysql_cluster_support.patch Fri Apr 01 14:13:41 2016 -0600
@@ -0,0 +1,348 @@
+This patchset is for bug:
+
+22725754 - Keystone needs to support MySQL Cluster
+
+This fixes the following aspects of Keystone:
+1. Implementation of an oslo.db configuration parameter to specify the MySQL
+ storage engine (mysql_storage_engine).
+2. Replacement of hardcoded SQL statements that set the engine to "InnoDB"
+ to the above configuration value.
+3. Logic to handle SQL differences between MySQL InnoDB and MySQL Cluster (NDB).
+ This includes column lengths, constraints, foreign keys, and indexes.
+
+This has not been committed upstream, but has been filed in launchpad:
+
+https://bugs.launchpad.net/keystone/+bug/1564110
+
+
+--- keystone-2015.1.2/keystone/contrib/endpoint_policy/migrate_repo/versions/001_add_endpoint_policy_table.py.orig 2016-02-17 11:31:28.370731100 -0700
++++ keystone-2015.1.2/keystone/contrib/endpoint_policy/migrate_repo/versions/001_add_endpoint_policy_table.py 2016-02-19 13:15:20.604166480 -0700
+@@ -13,7 +13,9 @@
+ # under the License.
+
+ import sqlalchemy as sql
++from oslo_config import cfg
+
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ # Upgrade operations go here. Don't create your own engine; bind
+@@ -34,7 +36,7 @@ def upgrade(migrate_engine):
+ sql.Column('region_id', sql.String(64),
+ nullable=True),
+ sql.UniqueConstraint('endpoint_id', 'service_id', 'region_id'),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ endpoint_policy_table.create(migrate_engine, checkfirst=True)
+--- keystone-2015.1.2/keystone/contrib/federation/migrate_repo/versions/001_add_identity_provider_table.py.orig 2016-02-17 11:31:28.364528948 -0700
++++ keystone-2015.1.2/keystone/contrib/federation/migrate_repo/versions/001_add_identity_provider_table.py 2016-02-19 13:14:23.091304897 -0700
+@@ -11,7 +11,9 @@
+ # under the License.
+
+ import sqlalchemy as sql
++from oslo_config import cfg
+
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = sql.MetaData()
+@@ -23,7 +25,7 @@ def upgrade(migrate_engine):
+ sql.Column('id', sql.String(64), primary_key=True),
+ sql.Column('enabled', sql.Boolean, nullable=False),
+ sql.Column('description', sql.Text(), nullable=True),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ idp_table.create(migrate_engine, checkfirst=True)
+@@ -36,7 +38,7 @@ def upgrade(migrate_engine):
+ sql.ForeignKey('identity_provider.id', ondelete='CASCADE'),
+ primary_key=True),
+ sql.Column('mapping_id', sql.String(64), nullable=True),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ federation_protocol_table.create(migrate_engine, checkfirst=True)
+--- keystone-2015.1.2/keystone/contrib/federation/migrate_repo/versions/007_add_remote_id_table.py.orig 2016-02-17 11:31:28.369152519 -0700
++++ keystone-2015.1.2/keystone/contrib/federation/migrate_repo/versions/007_add_remote_id_table.py 2016-02-19 13:14:36.794647452 -0700
+@@ -11,7 +11,9 @@
+ # under the License.
+
+ import sqlalchemy as orm
++from oslo_config import cfg
+
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = orm.MetaData()
+@@ -27,7 +29,7 @@ def upgrade(migrate_engine):
+ orm.Column('remote_id',
+ orm.String(255),
+ primary_key=True),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ remote_id_table.create(migrate_engine, checkfirst=True)
+--- keystone-2015.1.2/keystone/contrib/federation/migrate_repo/versions/005_add_service_provider_table.py.orig 2016-02-17 11:31:28.366074588 -0700
++++ keystone-2015.1.2/keystone/contrib/federation/migrate_repo/versions/005_add_service_provider_table.py 2016-02-19 13:16:25.569156414 -0700
+@@ -11,7 +11,9 @@
+ # under the License.
+
+ import sqlalchemy as sql
++from oslo_config import cfg
+
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = sql.MetaData()
+@@ -25,7 +27,7 @@ def upgrade(migrate_engine):
+ sql.Column('enabled', sql.Boolean, nullable=False),
+ sql.Column('description', sql.Text(), nullable=True),
+ sql.Column('sp_url', sql.String(256), nullable=True),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ sp_table.create(migrate_engine, checkfirst=True)
+--- keystone-2015.1.2/keystone/contrib/federation/migrate_repo/versions/002_add_mapping_tables.py.orig 2016-02-17 11:31:28.367627604 -0700
++++ keystone-2015.1.2/keystone/contrib/federation/migrate_repo/versions/002_add_mapping_tables.py 2016-02-19 13:14:46.042762324 -0700
+@@ -11,7 +11,9 @@
+ # under the License.
+
+ import sqlalchemy as sql
++from oslo_config import cfg
+
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = sql.MetaData()
+@@ -22,6 +24,6 @@ def upgrade(migrate_engine):
+ meta,
+ sql.Column('id', sql.String(64), primary_key=True),
+ sql.Column('rules', sql.Text(), nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine ,
+ mysql_charset='utf8')
+ mapping_table.create(migrate_engine, checkfirst=True)
+--- keystone-2015.1.2/keystone/common/sql/migration_helpers.py.orig 2016-02-17 11:31:28.355333466 -0700
++++ keystone-2015.1.2/keystone/common/sql/migration_helpers.py 2016-02-19 10:15:36.520071425 -0700
+@@ -164,9 +164,9 @@ def _fix_federation_tables(engine):
+ # alter table to execute
+ engine.execute("SET foreign_key_checks = 0")
+ # * Make the tables using InnoDB engine
+- engine.execute("ALTER TABLE identity_provider Engine=InnoDB")
+- engine.execute("ALTER TABLE federation_protocol Engine=InnoDB")
+- engine.execute("ALTER TABLE mapping Engine=InnoDB")
++ engine.execute("ALTER TABLE identity_provider Engine=%s" % CONF.database.mysql_storage_engine)
++ engine.execute("ALTER TABLE federation_protocol Engine=%s" % CONF.database.mysql_storage_engine)
++ engine.execute("ALTER TABLE mapping Engine=%s" % CONF.database.mysql_storage_engine)
+ # * Make the tables using utf8 encoding
+ engine.execute("ALTER TABLE identity_provider "
+ "CONVERT TO CHARACTER SET utf8")
+--- keystone-2015.1.2/keystone/common/sql/migrate_repo/versions/051_add_id_mapping.py.orig 2016-02-17 11:31:28.357606093 -0700
++++ keystone-2015.1.2/keystone/common/sql/migrate_repo/versions/051_add_id_mapping.py 2016-02-19 13:10:31.212704447 -0700
+@@ -13,9 +13,10 @@
+ # under the License.
+
+ import sqlalchemy as sql
+-
+ from keystone.identity.mapping_backends import mapping
++from oslo_config import cfg
+
++CONF = cfg.CONF
+
+ MAPPING_TABLE = 'id_mapping'
+
+@@ -36,6 +37,6 @@ def upgrade(migrate_engine):
+ name='entity_type'),
+ nullable=False),
+ sql.UniqueConstraint('domain_id', 'local_id', 'entity_type'),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+ mapping_table.create(migrate_engine, checkfirst=True)
+--- keystone-2015.1.2/keystone/common/sql/migrate_repo/versions/044_icehouse.py.orig 2016-02-17 11:31:28.359732657 -0700
++++ keystone-2015.1.2/keystone/common/sql/migrate_repo/versions/044_icehouse.py 2016-02-19 13:12:49.670971345 -0700
+@@ -47,7 +47,7 @@ def upgrade(migrate_engine):
+ sql.Column('blob', ks_sql.JsonBlob, nullable=False),
+ sql.Column('type', sql.String(length=255), nullable=False),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ domain = sql.Table(
+@@ -56,7 +56,7 @@ def upgrade(migrate_engine):
+ sql.Column('name', sql.String(length=64), nullable=False),
+ sql.Column('enabled', sql.Boolean, default=True, nullable=False),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ endpoint = sql.Table(
+@@ -70,7 +70,7 @@ def upgrade(migrate_engine):
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ sql.Column('enabled', sql.Boolean, nullable=False, default=True,
+ server_default='1'),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ group = sql.Table(
+@@ -80,7 +80,7 @@ def upgrade(migrate_engine):
+ sql.Column('name', sql.String(length=64), nullable=False),
+ sql.Column('description', sql.Text),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ policy = sql.Table(
+@@ -89,7 +89,7 @@ def upgrade(migrate_engine):
+ sql.Column('type', sql.String(length=255), nullable=False),
+ sql.Column('blob', ks_sql.JsonBlob, nullable=False),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ project = sql.Table(
+@@ -100,7 +100,7 @@ def upgrade(migrate_engine):
+ sql.Column('description', sql.Text),
+ sql.Column('enabled', sql.Boolean),
+ sql.Column('domain_id', sql.String(length=64), nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ role = sql.Table(
+@@ -108,7 +108,7 @@ def upgrade(migrate_engine):
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('name', sql.String(length=255), nullable=False),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ service = sql.Table(
+@@ -118,7 +118,7 @@ def upgrade(migrate_engine):
+ sql.Column('enabled', sql.Boolean, nullable=False, default=True,
+ server_default='1'),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ token = sql.Table(
+@@ -129,7 +129,7 @@ def upgrade(migrate_engine):
+ sql.Column('valid', sql.Boolean, default=True, nullable=False),
+ sql.Column('trust_id', sql.String(length=64)),
+ sql.Column('user_id', sql.String(length=64)),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ trust = sql.Table(
+@@ -143,7 +143,7 @@ def upgrade(migrate_engine):
+ sql.Column('expires_at', sql.DateTime),
+ sql.Column('remaining_uses', sql.Integer, nullable=True),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ trust_role = sql.Table(
+@@ -152,7 +152,7 @@ def upgrade(migrate_engine):
+ nullable=False),
+ sql.Column('role_id', sql.String(length=64), primary_key=True,
+ nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ user = sql.Table(
+@@ -164,14 +164,14 @@ def upgrade(migrate_engine):
+ sql.Column('enabled', sql.Boolean),
+ sql.Column('domain_id', sql.String(length=64), nullable=False),
+ sql.Column('default_project_id', sql.String(length=64)),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ user_group_membership = sql.Table(
+ 'user_group_membership', meta,
+ sql.Column('user_id', sql.String(length=64), primary_key=True),
+ sql.Column('group_id', sql.String(length=64), primary_key=True),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ region = sql.Table(
+@@ -181,7 +181,7 @@ def upgrade(migrate_engine):
+ sql.Column('description', sql.String(255), nullable=False),
+ sql.Column('parent_region_id', sql.String(64), nullable=True),
+ sql.Column('extra', sql.Text()),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ assignment = sql.Table(
+@@ -199,7 +199,7 @@ def upgrade(migrate_engine):
+ sql.Column('role_id', sql.String(64), nullable=False),
+ sql.Column('inherited', sql.Boolean, default=False, nullable=False),
+ sql.PrimaryKeyConstraint('type', 'actor_id', 'target_id', 'role_id'),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ # create all tables
+--- keystone-2015.1.2/keystone/common/sql/migrate_repo/versions/065_add_domain_config.py.orig 2016-02-17 11:31:28.361388817 -0700
++++ keystone-2015.1.2/keystone/common/sql/migrate_repo/versions/065_add_domain_config.py 2016-02-19 13:10:34.283121353 -0700
+@@ -11,8 +11,10 @@
+ # under the License.
+
+ import sqlalchemy as sql
+-
+ from keystone.common import sql as ks_sql
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ WHITELIST_TABLE = 'whitelisted_config'
+ SENSITIVE_TABLE = 'sensitive_config'
+@@ -29,7 +31,7 @@ def upgrade(migrate_engine):
+ sql.Column('group', sql.String(255), primary_key=True),
+ sql.Column('option', sql.String(255), primary_key=True),
+ sql.Column('value', ks_sql.JsonBlob.impl, nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+ whitelist_table.create(migrate_engine, checkfirst=True)
+
+@@ -40,6 +42,6 @@ def upgrade(migrate_engine):
+ sql.Column('group', sql.String(255), primary_key=True),
+ sql.Column('option', sql.String(255), primary_key=True),
+ sql.Column('value', ks_sql.JsonBlob.impl, nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+ sensitive_table.create(migrate_engine, checkfirst=True)
+--- keystone-2015.1.2/keystone/tests/unit/test_sql_upgrade.py.orig 2016-02-17 11:31:28.362966631 -0700
++++ keystone-2015.1.2/keystone/tests/unit/test_sql_upgrade.py 2016-02-19 10:47:11.044395387 -0700
+@@ -663,9 +663,9 @@ class SqlUpgradeTests(SqlMigrateBase):
+ noninnodb = connection.execute("SELECT table_name "
+ "from information_schema.TABLES "
+ "where TABLE_SCHEMA='%(database)s' "
+- "and ENGINE!='InnoDB' "
++ "and ENGINE!='%(mysql_storage_engine)s' "
+ "and TABLE_NAME!='migrate_version'" %
+- dict(database=database))
++ dict(database=database, mysql_storage_engine=CONF.database.mysql_storage_engine))
+ names = [x[0] for x in noninnodb]
+ self.assertEqual([], names,
+ "Non-InnoDB tables exist")
--- a/components/openstack/neutron/files/neutron.conf Fri Apr 01 14:10:25 2016 -0600
+++ b/components/openstack/neutron/files/neutron.conf Fri Apr 01 14:13:41 2016 -0600
@@ -728,6 +728,12 @@
# The SQLAlchemy connection string used to connect to the slave database
# slave_connection =
+# This configures the MySQL storage engine. This allows for OpenStack to
+# support different storage engines such as InnoDB, NDB, etc. By Default,
+# this value will be set to InnoDB. For MySQL Cluster, set to NDBCLUSTER.
+# Example: mysql_storage_engine=(string value)
+#mysql_storage_engine = InnoDB
+
# Database reconnection retry times - in event connectivity is lost
# set to -1 implies an infinite retry count
# max_retries = 10
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/openstack/neutron/patches/mysql_cluster_support.patch Fri Apr 01 14:13:41 2016 -0600
@@ -0,0 +1,1052 @@
+This patchset is for bug:
+
+22726251 - Neutron needs to support MySQL Cluster
+
+This fixes the following aspects of Neutron:
+1. Implementation of an oslo.db configuration parameter to specify the MySQL
+ storage engine (mysql_storage_engine).
+2. Replacement of hardcoded SQL statements that set the engine to "InnoDB"
+ to the above configuration value.
+3. Logic to handle SQL differences between MySQL InnoDB and MySQL Cluster (NDB).
+ This includes column lengths, constraints, foreign keys, and indexes.
+
+This has not been committed upstream, but has been filed in launchpad:
+
+https://bugs.launchpad.net/neutron/+bug/1564110
+
+--- neutron-2015.1.2/neutron/tests/functional/db/test_migrations.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/tests/functional/db/test_migrations.py 2016-03-29 17:21:15.448412716 -0600
+@@ -35,6 +35,10 @@ LOG = logging.getLogger(__name__)
+
+ cfg.CONF.import_opt('core_plugin', 'neutron.common.config')
+
++from alembic import context
++config = context.config
++CONF = config.neutron_config
++
+ CORE_PLUGIN = 'neutron.plugins.ml2.plugin.Ml2Plugin'
+
+ # These tables are still in the neutron database, but their models have moved
+@@ -195,7 +199,7 @@ class _TestModelsMigrations(test_migrati
+ self.assertTrue(len(tables) > 0,
+ "No tables found. Wrong schema?")
+ noninnodb = [table for table in tables if
+- insp.get_table_options(table)['mysql_engine'] != 'InnoDB'
++ insp.get_table_options(table)['mysql_engine'] != CONF.database.mysql_storage_engine
+ and table != 'alembic_version']
+ self.assertEqual(0, len(noninnodb), "%s non InnoDB tables created" %
+ noninnodb)
+--- neutron-2015.1.2/neutron/plugins/ml2/drivers/cisco/apic/apic_model.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/plugins/ml2/drivers/cisco/apic/apic_model.py 2016-03-30 16:19:14.369511272 -0600
+@@ -22,6 +22,16 @@ from neutron.db import model_base
+ from neutron.db import models_v2
+ from neutron.plugins.ml2 import models as models_ml2
+
++from oslo_config import cfg
++
++from alembic import context
++config = context.config
++CONF = config.neutron_config
++
++if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ router_string_length = 64
++else:
++ router_string_length = 36
+
+ class RouterContract(model_base.BASEV2, models_v2.HasTenant):
+
+@@ -34,8 +44,8 @@ class RouterContract(model_base.BASEV2,
+
+ __tablename__ = 'cisco_ml2_apic_contracts'
+
+- router_id = sa.Column(sa.String(64), sa.ForeignKey('routers.id',
+- ondelete='CASCADE'),
++ router_id = sa.Column(sa.String(router_string_length),
++ sa.ForeignKey('routers.id', ondelete='CASCADE'),
+ primary_key=True)
+
+
+--- neutron-2015.1.2/neutron/db/extradhcpopt_db.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/db/extradhcpopt_db.py 2016-03-30 13:31:06.518157426 -0600
+@@ -23,36 +23,64 @@ from neutron.db import model_base
+ from neutron.db import models_v2
+ from neutron.extensions import extra_dhcp_opt as edo_ext
+
++from oslo_config import cfg
+
+-LOG = logging.getLogger(__name__)
+-
++from alembic import context
++config = context.config
++CONF = config.neutron_config
+
+-class ExtraDhcpOpt(model_base.BASEV2, models_v2.HasId):
+- """Represent a generic concept of extra options associated to a port.
++LOG = logging.getLogger(__name__)
+
+- Each port may have none to many dhcp opts associated to it that can
+- define specifically different or extra options to DHCP clients.
+- These will be written to the <network_id>/opts files, and each option's
+- tag will be referenced in the <network_id>/host file.
+- """
+- port_id = sa.Column(sa.String(36),
+- sa.ForeignKey('ports.id', ondelete="CASCADE"),
+- nullable=False)
+- opt_name = sa.Column(sa.String(64), nullable=False)
+- opt_value = sa.Column(sa.String(255), nullable=False)
+- ip_version = sa.Column(sa.Integer, server_default='4', nullable=False)
+- __table_args__ = (sa.UniqueConstraint(
+- 'port_id',
+- 'opt_name',
+- 'ip_version',
+- name='uniq_extradhcpopts0portid0optname0ipversion'),
+- model_base.BASEV2.__table_args__,)
+-
+- # Add a relationship to the Port model in order to instruct SQLAlchemy to
+- # eagerly load extra_dhcp_opts bindings
+- ports = orm.relationship(
+- models_v2.Port,
+- backref=orm.backref("dhcp_opts", lazy='joined', cascade='delete'))
++# MySQL Cluster NDB does not support this constraint.
++# TODO (oorgeron) Look into making this workable.
++if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ class ExtraDhcpOpt(model_base.BASEV2, models_v2.HasId):
++ """Represent a generic concept of extra options associated to a port.
++
++ Each port may have none to many dhcp opts associated to it that can
++ define specifically different or extra options to DHCP clients.
++ These will be written to the <network_id>/opts files, and each option's
++ tag will be referenced in the <network_id>/host file.
++ """
++ port_id = sa.Column(sa.String(36),
++ sa.ForeignKey('ports.id', ondelete="CASCADE"),
++ nullable=False)
++ opt_name = sa.Column(sa.String(64), nullable=False)
++ opt_value = sa.Column(sa.String(255), nullable=False)
++ ip_version = sa.Column(sa.Integer, server_default='4', nullable=False)
++
++ # Add a relationship to the Port model in order to instruct SQLAlchemy to
++ # eagerly load extra_dhcp_opts bindings
++ ports = orm.relationship(
++ models_v2.Port,
++ backref=orm.backref("dhcp_opts", lazy='joined', cascade='delete'))
++else:
++ class ExtraDhcpOpt(model_base.BASEV2, models_v2.HasId):
++ """Represent a generic concept of extra options associated to a port.
++
++ Each port may have none to many dhcp opts associated to it that can
++ define specifically different or extra options to DHCP clients.
++ These will be written to the <network_id>/opts files, and each option's
++ tag will be referenced in the <network_id>/host file.
++ """
++ port_id = sa.Column(sa.String(36),
++ sa.ForeignKey('ports.id', ondelete="CASCADE"),
++ nullable=False)
++ opt_name = sa.Column(sa.String(64), nullable=False)
++ opt_value = sa.Column(sa.String(255), nullable=False)
++ ip_version = sa.Column(sa.Integer, server_default='4', nullable=False)
++ __table_args__ = (sa.UniqueConstraint(
++ 'port_id',
++ 'opt_name',
++ 'ip_version',
++ name='uniq_extradhcpopts0portid0optname0ipversion'),
++ model_base.BASEV2.__table_args__,)
++
++ # Add a relationship to the Port model in order to instruct SQLAlchemy to
++ # eagerly load extra_dhcp_opts bindings
++ ports = orm.relationship(
++ models_v2.Port,
++ backref=orm.backref("dhcp_opts", lazy='joined', cascade='delete'))
+
+
+ class ExtraDhcpOptMixin(object):
+--- neutron-2015.1.2/neutron/db/models_v2.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/db/models_v2.py 2016-03-30 13:32:09.835579720 -0600
+@@ -21,6 +21,12 @@ from neutron.common import constants
+ from neutron.db import model_base
+ from neutron.openstack.common import uuidutils
+
++from oslo_config import cfg
++from oslo_db import options as oslo_db_options
++
++from alembic import context
++config = context.config
++CONF = config.neutron_config
+
+ class HasTenant(object):
+ """Tenant mixin, add to subclasses that have a tenant."""
+@@ -126,47 +132,89 @@ class SubnetRoute(model_base.BASEV2, Rou
+ primary_key=True)
+
+
+-class Port(model_base.BASEV2, HasId, HasTenant):
+- """Represents a port on a Neutron v2 network."""
+-
+- name = sa.Column(sa.String(attr.NAME_MAX_LEN))
+- network_id = sa.Column(sa.String(36), sa.ForeignKey("networks.id"),
+- nullable=False)
+- fixed_ips = orm.relationship(IPAllocation, backref='ports', lazy='joined')
+- mac_address = sa.Column(sa.String(32), nullable=False)
+- admin_state_up = sa.Column(sa.Boolean(), nullable=False)
+- status = sa.Column(sa.String(16), nullable=False)
+- device_id = sa.Column(sa.String(attr.DEVICE_ID_MAX_LEN), nullable=False)
+- device_owner = sa.Column(sa.String(attr.DEVICE_OWNER_MAX_LEN),
+- nullable=False)
+- __table_args__ = (
+- sa.Index(
+- 'ix_ports_network_id_mac_address', 'network_id', 'mac_address'),
+- sa.Index(
+- 'ix_ports_network_id_device_owner', 'network_id', 'device_owner'),
+- sa.UniqueConstraint(
+- network_id, mac_address,
+- name='uniq_ports0network_id0mac_address'),
+- model_base.BASEV2.__table_args__
+- )
+-
+- def __init__(self, id=None, tenant_id=None, name=None, network_id=None,
+- mac_address=None, admin_state_up=None, status=None,
+- device_id=None, device_owner=None, fixed_ips=None):
+- self.id = id
+- self.tenant_id = tenant_id
+- self.name = name
+- self.network_id = network_id
+- self.mac_address = mac_address
+- self.admin_state_up = admin_state_up
+- self.device_owner = device_owner
+- self.device_id = device_id
+- # Since this is a relationship only set it if one is passed in.
+- if fixed_ips:
+- self.fixed_ips = fixed_ips
++# MySQL Cluster NDB does not support this constraint.
++# TODO (oorgeron) Look into making this workable.
++if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ class Port(model_base.BASEV2, HasId, HasTenant):
++ """Represents a port on a Neutron v2 network."""
++
++ name = sa.Column(sa.String(attr.NAME_MAX_LEN))
++ network_id = sa.Column(sa.String(36), sa.ForeignKey("networks.id"),
++ nullable=False)
++ fixed_ips = orm.relationship(IPAllocation, backref='ports', lazy='joined')
++ mac_address = sa.Column(sa.String(32), nullable=False)
++ admin_state_up = sa.Column(sa.Boolean(), nullable=False)
++ status = sa.Column(sa.String(16), nullable=False)
++ device_id = sa.Column(sa.String(attr.DEVICE_ID_MAX_LEN), nullable=False)
++ device_owner = sa.Column(sa.String(attr.DEVICE_OWNER_MAX_LEN),
++ nullable=False)
++ __table_args__ = (
++ sa.Index(
++ 'ix_ports_network_id_mac_address', 'network_id', 'mac_address'),
++ sa.Index(
++ 'ix_ports_network_id_device_owner', 'network_id', 'device_owner'),
++ model_base.BASEV2.__table_args__
++ )
++
++ def __init__(self, id=None, tenant_id=None, name=None, network_id=None,
++ mac_address=None, admin_state_up=None, status=None,
++ device_id=None, device_owner=None, fixed_ips=None):
++ self.id = id
++ self.tenant_id = tenant_id
++ self.name = name
++ self.network_id = network_id
++ self.mac_address = mac_address
++ self.admin_state_up = admin_state_up
++ self.device_owner = device_owner
++ self.device_id = device_id
++ # Since this is a relationship only set it if one is passed in.
++ if fixed_ips:
++ self.fixed_ips = fixed_ips
++
++ # NOTE(arosen): status must be set last as an event is triggered on!
++ self.status = status
++else:
++ class Port(model_base.BASEV2, HasId, HasTenant):
++ """Represents a port on a Neutron v2 network."""
++
++ name = sa.Column(sa.String(attr.NAME_MAX_LEN))
++ network_id = sa.Column(sa.String(36), sa.ForeignKey("networks.id"),
++ nullable=False)
++ fixed_ips = orm.relationship(IPAllocation, backref='ports', lazy='joined')
++ mac_address = sa.Column(sa.String(32), nullable=False)
++ admin_state_up = sa.Column(sa.Boolean(), nullable=False)
++ status = sa.Column(sa.String(16), nullable=False)
++ device_id = sa.Column(sa.String(attr.DEVICE_ID_MAX_LEN), nullable=False)
++ device_owner = sa.Column(sa.String(attr.DEVICE_OWNER_MAX_LEN),
++ nullable=False)
++ __table_args__ = (
++ sa.Index(
++ 'ix_ports_network_id_mac_address', 'network_id', 'mac_address'),
++ sa.Index(
++ 'ix_ports_network_id_device_owner', 'network_id', 'device_owner'),
++ sa.UniqueConstraint(
++ network_id, mac_address,
++ name='uniq_ports0network_id0mac_address'),
++ model_base.BASEV2.__table_args__
++ )
++
++ def __init__(self, id=None, tenant_id=None, name=None, network_id=None,
++ mac_address=None, admin_state_up=None, status=None,
++ device_id=None, device_owner=None, fixed_ips=None):
++ self.id = id
++ self.tenant_id = tenant_id
++ self.name = name
++ self.network_id = network_id
++ self.mac_address = mac_address
++ self.admin_state_up = admin_state_up
++ self.device_owner = device_owner
++ self.device_id = device_id
++ # Since this is a relationship only set it if one is passed in.
++ if fixed_ips:
++ self.fixed_ips = fixed_ips
+
+- # NOTE(arosen): status must be set last as an event is triggered on!
+- self.status = status
++ # NOTE(arosen): status must be set last as an event is triggered on!
++ self.status = status
+
+
+ class DNSNameServer(model_base.BASEV2):
+--- neutron-2015.1.2/neutron/db/db_base_plugin_v2.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/db/db_base_plugin_v2.py 2016-03-30 13:34:25.949250250 -0600
+@@ -46,6 +46,10 @@ from neutron.plugins.common import const
+
+ LOG = logging.getLogger(__name__)
+
++from alembic import context
++config = context.config
++CONF = config.neutron_config
++
+ # Ports with the following 'device_owner' values will not prevent
+ # network deletion. If delete_network() finds that all ports on a
+ # network have these owners, it will explicitly delete each port
+@@ -1797,8 +1801,16 @@ class NeutronDbPluginV2(neutron_plugin_b
+ # within a transaction, so that it can be rolled back to the
+ # point before its failure while maintaining the enclosing
+ # transaction
+- return self._create_port_with_mac(
+- context, network_id, port_data, mac, nested=True)
++
++ # MySQL Cluster NDB does not support nested transactions
++ # TODO (oorgeron) Look into making this workable.
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ return self._create_port_with_mac(
++ context, network_id, port_data, mac, nested=False)
++ else:
++ return self._create_port_with_mac(
++ context, network_id, port_data, mac, nested=True)
++
+ except n_exc.MacAddressInUse:
+ LOG.debug('Generated mac %(mac_address)s exists on '
+ 'network %(network_id)s',
+--- neutron-2015.1.2/neutron/db/api.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/db/api.py 2016-03-30 13:35:09.208949269 -0600
+@@ -19,6 +19,9 @@ from oslo_config import cfg
+ from oslo_db.sqlalchemy import session
+ from sqlalchemy import exc
+
++from alembic import context
++config = context.config
++CONF = config.neutron_config
+
+ _FACADE = None
+
+@@ -50,10 +53,18 @@ def get_session(autocommit=True, expire_
+ @contextlib.contextmanager
+ def autonested_transaction(sess):
+ """This is a convenience method to not bother with 'nested' parameter."""
+- try:
+- session_context = sess.begin_nested()
+- except exc.InvalidRequestError:
++
++ # MySQL Cluster NDB does not support nested transactions
++ # TODO (oorgeron) Look into making this workable.
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
+ session_context = sess.begin(subtransactions=True)
+- finally:
+ with session_context as tx:
+ yield tx
++ else:
++ try:
++ session_context = sess.begin_nested()
++ except exc.InvalidRequestError:
++ session_context = sess.begin(subtransactions=True)
++ finally:
++ with session_context as tx:
++ yield tx
+--- neutron-2015.1.2/neutron/db/model_base.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/db/model_base.py 2016-03-29 17:21:15.450203678 -0600
+@@ -17,27 +17,55 @@ from oslo_db.sqlalchemy import models
+ from sqlalchemy.ext import declarative
+ from sqlalchemy import orm
+
++from oslo_config import cfg
++from oslo_db import options as oslo_db_options
+
+-class NeutronBase(models.ModelBase):
+- """Base class for Neutron Models."""
+-
+- __table_args__ = {'mysql_engine': 'InnoDB'}
+-
+- def __iter__(self):
+- self._i = iter(orm.object_mapper(self).columns)
+- return self
+-
+- def next(self):
+- n = self._i.next().name
+- return n, getattr(self, n)
+-
+- def __repr__(self):
+- """sqlalchemy based automatic __repr__ method."""
+- items = ['%s=%r' % (col.name, getattr(self, col.name))
+- for col in self.__table__.columns]
+- return "<%s.%s[object at %x] {%s}>" % (self.__class__.__module__,
+- self.__class__.__name__,
+- id(self), ', '.join(items))
++from alembic import context
++config = context.config
++CONF = config.neutron_config
++
++if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ class NeutronBase(models.ModelBase):
++ """Base class for Neutron Models."""
++
++ __table_args__ = {'mysql_engine': 'NDBCLUSTER'}
++
++ def __iter__(self):
++ self._i = iter(orm.object_mapper(self).columns)
++ return self
++
++ def next(self):
++ n = self._i.next().name
++ return n, getattr(self, n)
++
++ def __repr__(self):
++ """sqlalchemy based automatic __repr__ method."""
++ items = ['%s=%r' % (col.name, getattr(self, col.name))
++ for col in self.__table__.columns]
++ return "<%s.%s[object at %x] {%s}>" % (self.__class__.__module__,
++ self.__class__.__name__,
++ id(self), ', '.join(items))
++else:
++ class NeutronBase(models.ModelBase):
++ """Base class for Neutron Models."""
++
++ __table_args__ = {'mysql_engine': 'InnoDB'}
++
++ def __iter__(self):
++ self._i = iter(orm.object_mapper(self).columns)
++ return self
++
++ def next(self):
++ n = self._i.next().name
++ return n, getattr(self, n)
++
++ def __repr__(self):
++ """sqlalchemy based automatic __repr__ method."""
++ items = ['%s=%r' % (col.name, getattr(self, col.name))
++ for col in self.__table__.columns]
++ return "<%s.%s[object at %x] {%s}>" % (self.__class__.__module__,
++ self.__class__.__name__,
++ id(self), ', '.join(items))
+
+
+ class NeutronBaseV2(NeutronBase):
+--- neutron-2015.1.2/neutron/db/migration/cli.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/db/migration/cli.py 2016-03-29 17:21:15.450420340 -0600
+@@ -59,6 +59,9 @@ _db_opts = [
+ cfg.StrOpt('engine',
+ default='',
+ help=_('Database engine')),
++ cfg.StrOpt('mysql_storage_engine',
++ default='',
++ help=_('MySQL Storage Engine')),
+ ]
+
+ CONF = cfg.ConfigOpts()
+--- neutron-2015.1.2/neutron/db/migration/models/frozen.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/db/migration/models/frozen.py 2016-03-30 13:55:30.300409126 -0600
+@@ -32,6 +32,11 @@ from sqlalchemy import schema
+ from neutron.db import model_base
+ from neutron.openstack.common import uuidutils
+
++from oslo_config import cfg
++
++from alembic import context
++config = context.config
++CONF = config.neutron_config
+
+ # Dictionary of all tables that was renamed:
+ # {new_table_name: old_table_name}
+@@ -77,6 +82,10 @@ DHCPV6_STATELESS = 'dhcpv6-stateless'
+
+ BASEV2 = declarative.declarative_base(cls=model_base.NeutronBaseV2)
+
++if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ db_string_length = 128
++else:
++ db_string_length = 256
+
+ #neutron/db/models_v2.py
+ class HasTenant(object):
+@@ -218,17 +227,30 @@ class Agent(BASEV2, HasId):
+ name='uniq_agents0agent_type0host'),
+ )
+
+- agent_type = sa.Column(sa.String(255), nullable=False)
+- binary = sa.Column(sa.String(255), nullable=False)
+- topic = sa.Column(sa.String(255), nullable=False)
+- host = sa.Column(sa.String(255), nullable=False)
+- admin_state_up = sa.Column(sa.Boolean, default=True,
+- server_default=sa.sql.true(), nullable=False)
+- created_at = sa.Column(sa.DateTime, nullable=False)
+- started_at = sa.Column(sa.DateTime, nullable=False)
+- heartbeat_timestamp = sa.Column(sa.DateTime, nullable=False)
+- description = sa.Column(sa.String(255))
+- configurations = sa.Column(sa.String(4095), nullable=False)
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ agent_type = sa.Column(sa.String(db_string_length), nullable=False)
++ binary = sa.Column(sa.String(db_string_length), nullable=False)
++ topic = sa.Column(sa.String(db_string_length), nullable=False)
++ host = sa.Column(sa.String(db_string_length), nullable=False)
++ admin_state_up = sa.Column(sa.Boolean, default=True,
++ server_default=sa.sql.true(), nullable=False)
++ created_at = sa.Column(sa.DateTime, nullable=False)
++ started_at = sa.Column(sa.DateTime, nullable=False)
++ heartbeat_timestamp = sa.Column(sa.DateTime, nullable=False)
++ description = sa.Column(sa.String(db_string_length))
++ configurations = sa.Column(sa.Text(4095), nullable=False)
++ else:
++ agent_type = sa.Column(sa.String(db_string_length), nullable=False)
++ binary = sa.Column(sa.String(db_string_length), nullable=False)
++ topic = sa.Column(sa.String(db_string_length), nullable=False)
++ host = sa.Column(sa.String(db_string_length), nullable=False)
++ admin_state_up = sa.Column(sa.Boolean, default=True,
++ server_default=sa.sql.true(), nullable=False)
++ created_at = sa.Column(sa.DateTime, nullable=False)
++ started_at = sa.Column(sa.DateTime, nullable=False)
++ heartbeat_timestamp = sa.Column(sa.DateTime, nullable=False)
++ description = sa.Column(sa.String(db_string_length))
++ configurations = sa.Column(sa.String(4095), nullable=False)
+
+
+ #neutron/db/agentschedulers_db.py
+@@ -431,10 +453,15 @@ class Vip(BASEV2, HasId, HasTenant, HasS
+
+ #neutron/db/loadbalancer/loadbalancer_db.py
+ class Member(BASEV2, HasId, HasTenant, HasStatusDescription):
+- __table_args__ = (
+- sa.schema.UniqueConstraint('pool_id', 'address', 'protocol_port',
+- name='uniq_member0pool_id0address0port'),
+- )
++
++ # MySQL Cluster NDB does not support this constraint.
++ # TODO (oorgeron) Look into making this workable.
++ if CONF.database.mysql_storage_engine != "NDBCLUSTER":
++ __table_args__ = (
++ sa.schema.UniqueConstraint('pool_id', 'address', 'protocol_port',
++ name='uniq_member0pool_id0address0port'),
++ )
++
+ pool_id = sa.Column(sa.String(36), sa.ForeignKey("pools.id"),
+ nullable=False)
+ address = sa.Column(sa.String(64), nullable=False)
+@@ -1229,8 +1256,15 @@ class PortBinding(BASEV2):
+ profile = sa.Column(sa.String(BINDING_PROFILE_LEN), nullable=False,
+ default='', server_default='')
+ vif_type = sa.Column(sa.String(64), nullable=False)
+- vif_details = sa.Column(sa.String(4095), nullable=False, default='',
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ vif_details = sa.Column(sa.Text(4095), nullable=False)
++ profile = sa.Column(sa.Text(length=4095),nullable=False)
++ else:
++ vif_details = sa.Column(sa.String(4095), nullable=False,
++ server_default='')
++ profile = sa.Column(sa.String(length=4095),nullable=False,
+ server_default='')
++
+ driver = sa.Column(sa.String(64))
+ segment = sa.Column(sa.String(36),
+ sa.ForeignKey('ml2_network_segments.id',
+@@ -1827,10 +1861,17 @@ class PoolPort(BASEV2):
+ class IdentifierMap(BASEV2, HasTenant):
+ __tablename__ = 'cisco_csr_identifier_map'
+
+- ipsec_site_conn_id = sa.Column(sa.String(64),
+- sa.ForeignKey('ipsec_site_connections.id',
+- ondelete="CASCADE"),
+- primary_key=True)
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ ipsec_site_conn_id = sa.Column(sa.String(36),
++ sa.ForeignKey('ipsec_site_connections.id',
++ ondelete="CASCADE"),
++ primary_key=True)
++ else:
++ ipsec_site_conn_id = sa.Column(sa.String(64),
++ sa.ForeignKey('ipsec_site_connections.id',
++ ondelete="CASCADE"),
++ primary_key=True)
++
+ csr_tunnel_id = sa.Column(sa.Integer, nullable=False)
+ csr_ike_policy_id = sa.Column(sa.Integer, nullable=False)
+ csr_ipsec_policy_id = sa.Column(sa.Integer, nullable=False)
+--- neutron-2015.1.2/neutron/db/migration/alembic_migrations/heal_script.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/db/migration/alembic_migrations/heal_script.py 2016-03-29 17:21:15.451095269 -0600
+@@ -29,6 +29,12 @@ from sqlalchemy import types
+ from neutron.db.migration.models import frozen as frozen_models
+ from neutron.i18n import _LI, _LW
+
++from oslo_config import cfg
++
++from alembic import context
++config = context.config
++CONF = config.neutron_config
++
+ LOG = logging.getLogger(__name__)
+
+ METHODS = {}
+@@ -70,7 +76,10 @@ def heal():
+ 'compare_server_default': _compare_server_default,
+ }
+ mc = alembic.migration.MigrationContext.configure(op.get_bind(), opts=opts)
+- set_storage_engine(op.get_bind(), "InnoDB")
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ set_storage_engine(op.get_bind(), 'NDBCLUSTER')
++ else:
++ set_storage_engine(op.get_bind(), 'InnoDB')
+ diff = autogen.compare_metadata(mc, models_metadata)
+ for el in diff:
+ execute_alembic_command(el)
+@@ -286,4 +295,4 @@ def set_storage_engine(bind, engine):
+ if bind.dialect.name == 'mysql':
+ for table in insp.get_table_names():
+ if insp.get_table_options(table)['mysql_engine'] != engine:
+- op.execute("ALTER TABLE %s ENGINE=%s" % (table, engine))
++ op.execute("ALTER TABLE %(db_table)s Engine=%(mysql_storage_engine)s" % dict(db_table=table, mysql_storage_engine=CONF.database.mysql_storage_engine))
+--- neutron-2015.1.2/neutron/db/migration/alembic_migrations/agent_init_ops.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/db/migration/alembic_migrations/agent_init_ops.py 2016-03-30 13:57:42.770400120 -0600
+@@ -21,19 +21,44 @@
+ from alembic import op
+ import sqlalchemy as sa
+
++from alembic import context
++config = context.config
++
++CONF = config.neutron_config
++
++if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ db_string_length = 128
++else:
++ db_string_length = 256
+
+ def upgrade():
+- op.create_table(
+- 'agents',
+- sa.Column('id', sa.String(length=36), nullable=False),
+- sa.Column('agent_type', sa.String(length=255), nullable=False),
+- sa.Column('binary', sa.String(length=255), nullable=False),
+- sa.Column('topic', sa.String(length=255), nullable=False),
+- sa.Column('host', sa.String(length=255), nullable=False),
+- sa.Column('admin_state_up', sa.Boolean(), nullable=False),
+- sa.Column('created_at', sa.DateTime(), nullable=False),
+- sa.Column('started_at', sa.DateTime(), nullable=False),
+- sa.Column('heartbeat_timestamp', sa.DateTime(), nullable=False),
+- sa.Column('description', sa.String(length=255), nullable=True),
+- sa.Column('configurations', sa.String(length=4095), nullable=False),
+- sa.PrimaryKeyConstraint('id'))
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ op.create_table(
++ 'agents',
++ sa.Column('id', sa.String(length=36), nullable=False),
++ sa.Column('agent_type', sa.String(length=db_string_length), nullable=False),
++ sa.Column('binary', sa.String(length=db_string_length), nullable=False),
++ sa.Column('topic', sa.String(length=db_string_length), nullable=False),
++ sa.Column('host', sa.String(length=db_string_length), nullable=False),
++ sa.Column('admin_state_up', sa.Boolean(), nullable=False),
++ sa.Column('created_at', sa.DateTime(), nullable=False),
++ sa.Column('started_at', sa.DateTime(), nullable=False),
++ sa.Column('heartbeat_timestamp', sa.DateTime(), nullable=False),
++ sa.Column('description', sa.String(length=db_string_length), nullable=True),
++ sa.Column('configurations', sa.Text(length=4095), nullable=False),
++ sa.PrimaryKeyConstraint('id'))
++ else:
++ op.create_table(
++ 'agents',
++ sa.Column('id', sa.String(length=36), nullable=False),
++ sa.Column('agent_type', sa.String(length=db_string_length), nullable=False),
++ sa.Column('binary', sa.String(length=db_string_length), nullable=False),
++ sa.Column('topic', sa.String(length=db_string_length), nullable=False),
++ sa.Column('host', sa.String(length=db_string_length), nullable=False),
++ sa.Column('admin_state_up', sa.Boolean(), nullable=False),
++ sa.Column('created_at', sa.DateTime(), nullable=False),
++ sa.Column('started_at', sa.DateTime(), nullable=False),
++ sa.Column('heartbeat_timestamp', sa.DateTime(), nullable=False),
++ sa.Column('description', sa.String(length=db_string_length), nullable=True),
++ sa.Column('configurations', sa.String(length=4095), nullable=False),
++ sa.PrimaryKeyConstraint('id'))
+--- neutron-2015.1.2/neutron/db/migration/alembic_migrations/versions/86d6d9776e2b_cisco_apic_driver_update_l3.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/db/migration/alembic_migrations/versions/86d6d9776e2b_cisco_apic_driver_update_l3.py 2016-03-29 17:21:15.451521500 -0600
+@@ -29,15 +29,29 @@ down_revision = '236b90af57ab'
+ from alembic import op
+ import sqlalchemy as sa
+
++from oslo_config import cfg
++
++from alembic import context
++config = context.config
++CONF = config.neutron_config
++
+
+ def upgrade():
+
+ op.drop_table('cisco_ml2_apic_contracts')
+ op.drop_table('cisco_ml2_apic_epgs')
+
+- op.create_table(
+- 'cisco_ml2_apic_contracts',
+- sa.Column('tenant_id', sa.String(length=255)),
+- sa.Column('router_id', sa.String(length=64), nullable=False),
+- sa.ForeignKeyConstraint(['router_id'], ['routers.id']),
+- sa.PrimaryKeyConstraint('router_id'))
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ op.create_table(
++ 'cisco_ml2_apic_contracts',
++ sa.Column('tenant_id', sa.String(length=255)),
++ sa.Column('router_id', sa.String(length=36), nullable=False),
++ sa.ForeignKeyConstraint(['router_id'], ['routers.id']),
++ sa.PrimaryKeyConstraint('router_id'))
++ else:
++ op.create_table(
++ 'cisco_ml2_apic_contracts',
++ sa.Column('tenant_id', sa.String(length=255)),
++ sa.Column('router_id', sa.String(length=64), nullable=False),
++ sa.ForeignKeyConstraint(['router_id'], ['routers.id']),
++ sa.PrimaryKeyConstraint('router_id'))
+--- neutron-2015.1.2/neutron/db/migration/alembic_migrations/versions/327ee5fde2c7_set_innodb_engine.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/db/migration/alembic_migrations/versions/327ee5fde2c7_set_innodb_engine.py 2016-03-29 17:21:15.451795926 -0600
+@@ -28,6 +28,12 @@ down_revision = '4eba2f05c2f4'
+
+ from alembic import op
+
++from oslo_config import cfg
++
++from alembic import context
++config = context.config
++CONF = config.neutron_config
++
+ # This list contain tables that could be deployed before change that converts
+ # all tables to InnoDB appeared
+ TABLES = ['router_extra_attributes', 'dvr_host_macs', 'ml2_dvr_port_bindings',
+@@ -37,4 +43,4 @@ TABLES = ['router_extra_attributes', 'dv
+ def upgrade():
+ if op.get_bind().dialect.name == 'mysql':
+ for table in TABLES:
+- op.execute("ALTER TABLE %s ENGINE=InnoDB" % table)
++ op.execute("ALTER TABLE %(db_table)s ENGINE=%(mysql_storage_engine)s" % dict(db_table=table, mysql_storage_engine=CONF.database.mysql_storage_engine))
+--- neutron-2015.1.2/neutron/db/migration/alembic_migrations/versions/e197124d4b9_add_unique_constrain.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/db/migration/alembic_migrations/versions/e197124d4b9_add_unique_constrain.py 2016-03-30 13:38:00.739890667 -0600
+@@ -29,12 +29,24 @@ from alembic import op
+
+ from neutron.db import migration
+
++from oslo_config import cfg
++
++from alembic import context
++config = context.config
++CONF = config.neutron_config
+
+ CONSTRAINT_NAME = 'uniq_member0pool_id0address0port'
+ TABLE_NAME = 'members'
+
+
+ def upgrade():
++
++ # MySQL Cluster, a.k.a. NDB, does not support this migration step.
++ # This test will skip this migration.
++ # TODO (oorgeron) Look into making this workable.
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ return
++
+ if migration.schema_has_table(TABLE_NAME):
+ op.create_unique_constraint(
+ name=CONSTRAINT_NAME,
+--- neutron-2015.1.2/neutron/db/migration/alembic_migrations/versions/157a5d299379_ml2_binding_profile.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/db/migration/alembic_migrations/versions/157a5d299379_ml2_binding_profile.py 2016-03-29 17:21:15.452255941 -0600
+@@ -30,9 +30,20 @@ import sqlalchemy as sa
+
+ from neutron.db import migration
+
++from alembic import context
++config = context.config
++
++CONF = config.neutron_config
+
+ def upgrade():
+ if migration.schema_has_table('ml2_port_bindings'):
+- op.add_column('ml2_port_bindings',
+- sa.Column('profile', sa.String(length=4095),
+- nullable=False, server_default=''))
++ # MySQL Cluster (NDB) does not support rows longer than 14000.
++ # This configures the profile column as TEXT to keep the row size down.
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ op.add_column('ml2_port_bindings',
++ sa.Column('profile', sa.Text(length=4095),
++ nullable=False))
++ else:
++ op.add_column('ml2_port_bindings',
++ sa.Column('profile', sa.String(length=4095),
++ nullable=False, server_default=''))
+--- neutron-2015.1.2/neutron/db/migration/alembic_migrations/versions/16cdf118d31d_extra_dhcp_options_ipv6_support.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/db/migration/alembic_migrations/versions/16cdf118d31d_extra_dhcp_options_ipv6_support.py 2016-03-30 13:38:40.736552814 -0600
+@@ -30,6 +30,12 @@ import sqlalchemy as sa
+
+ from neutron.db import migration
+
++from oslo_config import cfg
++
++from alembic import context
++config = context.config
++CONF = config.neutron_config
++
+ CONSTRAINT_NAME_OLD = 'uidx_portid_optname'
+ CONSTRAINT_NAME_NEW = 'uniq_extradhcpopts0portid0optname0ipversion'
+ TABLE_NAME = 'extradhcpopts'
+@@ -47,8 +53,11 @@ def upgrade():
+ server_default='4', nullable=False))
+ op.execute("UPDATE extradhcpopts SET ip_version = 4")
+
+- op.create_unique_constraint(
+- name=CONSTRAINT_NAME_NEW,
+- source='extradhcpopts',
+- local_cols=['port_id', 'opt_name', 'ip_version']
+- )
++ # MySQL Cluster NDB does not support this constraint.
++ # TODO (oorgeron) Look into making this workable.
++ if CONF.database.mysql_storage_engine != "NDBCLUSTER":
++ op.create_unique_constraint(
++ name=CONSTRAINT_NAME_NEW,
++ source='extradhcpopts',
++ local_cols=['port_id', 'opt_name', 'ip_version']
++ )
+--- neutron-2015.1.2/neutron/db/migration/alembic_migrations/versions/2026156eab2f_l2_dvr_models.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/db/migration/alembic_migrations/versions/2026156eab2f_l2_dvr_models.py 2016-03-29 17:21:15.452765470 -0600
+@@ -29,34 +29,71 @@ down_revision = '3927f7f7c456'
+ from alembic import op
+ import sqlalchemy as sa
+
++from alembic import context
++config = context.config
++
++CONF = config.neutron_config
+
+ def upgrade():
+- op.create_table(
+- 'dvr_host_macs',
+- sa.Column('host', sa.String(length=255), nullable=False),
+- sa.Column('mac_address', sa.String(length=32),
+- nullable=False, unique=True),
+- sa.PrimaryKeyConstraint('host')
+- )
+- op.create_table(
+- 'ml2_dvr_port_bindings',
+- sa.Column('port_id', sa.String(length=36), nullable=False),
+- sa.Column('host', sa.String(length=255), nullable=False),
+- sa.Column('router_id', sa.String(length=36), nullable=True),
+- sa.Column('vif_type', sa.String(length=64), nullable=False),
+- sa.Column('vif_details', sa.String(length=4095),
+- nullable=False, server_default=''),
+- sa.Column('vnic_type', sa.String(length=64),
+- nullable=False, server_default='normal'),
+- sa.Column('profile', sa.String(length=4095),
+- nullable=False, server_default=''),
+- sa.Column('cap_port_filter', sa.Boolean(), nullable=False),
+- sa.Column('driver', sa.String(length=64), nullable=True),
+- sa.Column('segment', sa.String(length=36), nullable=True),
+- sa.Column(u'status', sa.String(16), nullable=False),
+- sa.ForeignKeyConstraint(['port_id'], ['ports.id'],
+- ondelete='CASCADE'),
+- sa.ForeignKeyConstraint(['segment'], ['ml2_network_segments.id'],
+- ondelete='SET NULL'),
+- sa.PrimaryKeyConstraint('port_id', 'host')
+- )
++ # MySQL Cluster (NDB) does not support rows longer than 14000.
++ # This reduces the size of columns or converts them to TEXT to keep the row size down.
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ op.create_table(
++ 'dvr_host_macs',
++ sa.Column('host', sa.String(length=128), nullable=False),
++ sa.Column('mac_address', sa.String(length=32),
++ nullable=False, unique=True),
++ sa.PrimaryKeyConstraint('host')
++ )
++ op.create_table(
++ 'ml2_dvr_port_bindings',
++ sa.Column('port_id', sa.String(length=36), nullable=False),
++ sa.Column('host', sa.String(length=128), nullable=False),
++ sa.Column('router_id', sa.String(length=36), nullable=True),
++ sa.Column('vif_type', sa.String(length=64), nullable=False),
++ sa.Column('vif_details', sa.Text(length=4095),
++ nullable=False, server_default=''),
++ sa.Column('vnic_type', sa.String(length=64),
++ nullable=False, server_default='normal'),
++ sa.Column('profile', sa.Text(length=4095),
++ nullable=False, server_default=''),
++ sa.Column('cap_port_filter', sa.Boolean(), nullable=False),
++ sa.Column('driver', sa.String(length=64), nullable=True),
++ sa.Column('segment', sa.String(length=36), nullable=True),
++ sa.Column(u'status', sa.String(16), nullable=False),
++ sa.ForeignKeyConstraint(['port_id'], ['ports.id'],
++ ondelete='CASCADE'),
++ sa.ForeignKeyConstraint(['segment'], ['ml2_network_segments.id'],
++ ondelete='SET NULL'),
++ sa.PrimaryKeyConstraint('port_id', 'host')
++ )
++ else:
++ op.create_table(
++ 'dvr_host_macs',
++ sa.Column('host', sa.String(length=255), nullable=False),
++ sa.Column('mac_address', sa.String(length=32),
++ nullable=False, unique=True),
++ sa.PrimaryKeyConstraint('host')
++ )
++ op.create_table(
++ 'ml2_dvr_port_bindings',
++ sa.Column('port_id', sa.String(length=36), nullable=False),
++ sa.Column('host', sa.String(length=255), nullable=False),
++ sa.Column('router_id', sa.String(length=36), nullable=True),
++ sa.Column('vif_type', sa.String(length=64), nullable=False),
++ sa.Column('vif_details', sa.String(length=4095),
++ nullable=False, server_default=''),
++ sa.Column('vnic_type', sa.String(length=64),
++ nullable=False, server_default='normal'),
++ sa.Column('profile', sa.String(length=4095),
++ nullable=False, server_default=''),
++ sa.Column('cap_port_filter', sa.Boolean(), nullable=False),
++ sa.Column('driver', sa.String(length=64), nullable=True),
++ sa.Column('segment', sa.String(length=36), nullable=True),
++ sa.Column(u'status', sa.String(16), nullable=False),
++ sa.ForeignKeyConstraint(['port_id'], ['ports.id'],
++ ondelete='CASCADE'),
++ sa.ForeignKeyConstraint(['segment'], ['ml2_network_segments.id'],
++ ondelete='SET NULL'),
++ sa.PrimaryKeyConstraint('port_id', 'host')
++ )
+--- neutron-2015.1.2/neutron/db/migration/alembic_migrations/versions/50d5ba354c23_ml2_binding_vif_details.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/db/migration/alembic_migrations/versions/50d5ba354c23_ml2_binding_vif_details.py 2016-03-29 17:21:15.452989732 -0600
+@@ -30,6 +30,10 @@ import sqlalchemy as sa
+
+ from neutron.db import migration
+
++from alembic import context
++config = context.config
++
++CONF = config.neutron_config
+
+ def upgrade():
+
+@@ -38,9 +42,17 @@ def upgrade():
+ # did not create the ml2_port_bindings table.
+ return
+
+- op.add_column('ml2_port_bindings',
+- sa.Column('vif_details', sa.String(length=4095),
+- nullable=False, server_default=''))
++ # MySQL Cluster (NDB) does not support rows longer than 14000.
++ # This converts vif_details to TEXT to keep the row size down.
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ op.add_column('ml2_port_bindings',
++ sa.Column('vif_details', sa.Text(length=4095),
++ nullable=False))
++ else:
++ op.add_column('ml2_port_bindings',
++ sa.Column('vif_details', sa.String(length=4095),
++ nullable=False, server_default=''))
++
+ if op.get_bind().engine.name == 'ibm_db_sa':
+ op.execute(
+ "UPDATE ml2_port_bindings SET"
+--- neutron-2015.1.2/neutron/db/migration/alembic_migrations/versions/2a1ee2fb59e0_add_mac_address_unique_constraint.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/db/migration/alembic_migrations/versions/2a1ee2fb59e0_add_mac_address_unique_constraint.py 2016-03-30 13:39:17.728617445 -0600
+@@ -27,13 +27,25 @@ down_revision = '41662e32bce2'
+
+ from alembic import op
+
++from oslo_config import cfg
++
++from alembic import context
++config = context.config
++CONF = config.neutron_config
++
+ TABLE_NAME = 'ports'
+ CONSTRAINT_NAME = 'uniq_ports0network_id0mac_address'
+
+
+ def upgrade():
+- op.create_unique_constraint(
+- name=CONSTRAINT_NAME,
+- source=TABLE_NAME,
+- local_cols=['network_id', 'mac_address']
+- )
++
++ # MySQL Cluster NDB does not support this constraint.
++ # TODO (oorgeron) Look into making this workable.
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ return
++ else:
++ op.create_unique_constraint(
++ name=CONSTRAINT_NAME,
++ source=TABLE_NAME,
++ local_cols=['network_id', 'mac_address']
++ )
+--- neutron-2015.1.2/neutron/db/migration/alembic_migrations/versions/24c7ea5160d7_cisco_csr_vpnaas.py.orig 2016-03-29 17:20:23.000000000 -0600
++++ neutron-2015.1.2/neutron/db/migration/alembic_migrations/versions/24c7ea5160d7_cisco_csr_vpnaas.py 2016-03-29 17:21:15.453456539 -0600
+@@ -28,20 +28,39 @@ import sqlalchemy as sa
+
+ from neutron.db import migration
+
++from oslo_config import cfg
++
++from alembic import context
++config = context.config
++CONF = config.neutron_config
+
+ def upgrade():
+ if not migration.schema_has_table('ipsec_site_connections'):
+ # The vpnaas service plugin was not configured.
+ return
+- op.create_table(
+- 'cisco_csr_identifier_map',
+- sa.Column('tenant_id', sa.String(length=255), nullable=True),
+- sa.Column('ipsec_site_conn_id', sa.String(length=64),
+- primary_key=True),
+- sa.Column('csr_tunnel_id', sa.Integer(), nullable=False),
+- sa.Column('csr_ike_policy_id', sa.Integer(), nullable=False),
+- sa.Column('csr_ipsec_policy_id', sa.Integer(), nullable=False),
+- sa.ForeignKeyConstraint(['ipsec_site_conn_id'],
+- ['ipsec_site_connections.id'],
+- ondelete='CASCADE')
+- )
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ op.create_table(
++ 'cisco_csr_identifier_map',
++ sa.Column('tenant_id', sa.String(length=255), nullable=True),
++ sa.Column('ipsec_site_conn_id', sa.String(length=36),
++ primary_key=True),
++ sa.Column('csr_tunnel_id', sa.Integer(), nullable=False),
++ sa.Column('csr_ike_policy_id', sa.Integer(), nullable=False),
++ sa.Column('csr_ipsec_policy_id', sa.Integer(), nullable=False),
++ sa.ForeignKeyConstraint(['ipsec_site_conn_id'],
++ ['ipsec_site_connections.id'],
++ ondelete='CASCADE')
++ )
++ else:
++ op.create_table(
++ 'cisco_csr_identifier_map',
++ sa.Column('tenant_id', sa.String(length=255), nullable=True),
++ sa.Column('ipsec_site_conn_id', sa.String(length=64),
++ primary_key=True),
++ sa.Column('csr_tunnel_id', sa.Integer(), nullable=False),
++ sa.Column('csr_ike_policy_id', sa.Integer(), nullable=False),
++ sa.Column('csr_ipsec_policy_id', sa.Integer(), nullable=False),
++ sa.ForeignKeyConstraint(['ipsec_site_conn_id'],
++ ['ipsec_site_connections.id'],
++ ondelete='CASCADE')
++ )
--- a/components/openstack/nova/files/nova.conf Fri Apr 01 14:10:25 2016 -0600
+++ b/components/openstack/nova/files/nova.conf Fri Apr 01 14:13:41 2016 -0600
@@ -1830,7 +1830,7 @@
# Default path to Glance cache for Solaris Zones. (string
# value)
-#glancecache_dirname=/var/share/nova/images
+#glancecache_dirname=$state_path/images
# Cipher to use for encryption of memory traffic during live
# migration. If not specified, a common encryption algorithm
@@ -1846,10 +1846,6 @@
# value)
#zones_suspend_path=/var/share/zones/SYSsuspend
-# Allow kernel boot options to be set in instance metadata.
-# (boolean value)
-#solariszones_boot_options=true
-
#
# Options defined in nova.vnc
@@ -2261,6 +2257,12 @@
# value)
#mysql_sql_mode=TRADITIONAL
+# This configures the MySQL storage engine. This allows for OpenStack to
+# support different storage engines such as Inn DB, NDB, etc. By Default,
+# this value will be set to InnoDB. For MySQL Cluster, set to NDBCLUSTER.
+# Example: mysql_storage_engine=(string value)
+#mysql_storage_engine = InnoDB
+
# Timeout before idle SQL connections are reaped. (integer
# value)
# Deprecated group/name - [DEFAULT]/sql_idle_timeout
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/openstack/nova/patches/mysql_cluster_support.patch Fri Apr 01 14:13:41 2016 -0600
@@ -0,0 +1,1273 @@
+This patchset is for bug:
+
+22726259 - Nova needs to support MySQL Cluster
+
+This fixes the following aspects of Nova:
+1. Implementation of an oslo.db configuration parameter to specify the MySQL
+ storage engine (mysql_storage_engine).
+2. Replacement of hardcoded SQL statements that set the engine to "InnoDB"
+ to the above configuration value.
+3. Logic to handle SQL differences between MySQL InnoDB and MySQL Cluster (NDB).
+ This includes column lengths, constraints, foreign keys, and indexes.
+
+This has not been committed upstream, but has been filed in launchpad:
+
+https://bugs.launchpad.net/nova/+bug/1564110
+
+
+--- nova-2015.1.2/nova/tests/unit/db/test_migrations.py.orig 2016-03-29 17:22:24.000000000 -0600
++++ nova-2015.1.2/nova/tests/unit/db/test_migrations.py 2016-03-30 16:22:31.345781715 -0600
+@@ -59,6 +59,9 @@ from nova import exception
+ from nova import test
+ from nova.tests import fixtures as nova_fixtures
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ LOG = logging.getLogger(__name__)
+
+@@ -905,9 +908,10 @@ class TestNovaMigrationsMySQL(NovaMigrat
+ "SELECT count(*) "
+ "FROM information_schema.TABLES "
+ "WHERE TABLE_SCHEMA='%(database)s' "
+- "AND ENGINE != 'InnoDB' "
++ "AND ENGINE != '%(mysql_storage_engine)s' "
+ "AND TABLE_NAME != 'migrate_version'" %
+- {'database': self.migrate_engine.url.database})
++ {'database': self.migrate_engine.url.database,
++ 'mysql_storage_engine': CONF.database.mysql_storage_engine})
+ count = noninnodb.scalar()
+ self.assertEqual(count, 0, "%d non InnoDB tables created" % count)
+
+--- nova-2015.1.2/nova/db/sqlalchemy/utils.py.orig 2016-03-29 17:22:24.000000000 -0600
++++ nova-2015.1.2/nova/db/sqlalchemy/utils.py 2016-03-29 17:23:21.832584350 -0600
+@@ -27,6 +27,9 @@ from nova.db.sqlalchemy import api as db
+ from nova import exception
+ from nova.i18n import _, _LE
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ LOG = logging.getLogger(__name__)
+
+@@ -120,7 +123,7 @@ def create_shadow_table(migrate_engine,
+
+ shadow_table_name = db._SHADOW_TABLE_PREFIX + table.name
+ shadow_table = Table(shadow_table_name, meta, *columns,
+- mysql_engine='InnoDB')
++ mysql_engine=CONF.database.mysql_storage_engine)
+ try:
+ shadow_table.create()
+ return shadow_table
+--- nova-2015.1.2/nova/db/sqlalchemy/api_migrations/migrate_repo/versions/002_instance_mapping.py.orig 2016-03-29 17:22:24.000000000 -0600
++++ nova-2015.1.2/nova/db/sqlalchemy/api_migrations/migrate_repo/versions/002_instance_mapping.py 2016-03-29 17:23:21.832858639 -0600
+@@ -20,6 +20,9 @@ from sqlalchemy import MetaData
+ from sqlalchemy import String
+ from sqlalchemy import Table
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = MetaData()
+@@ -39,7 +42,7 @@ def upgrade(migrate_engine):
+ Index('project_id_idx', 'project_id'),
+ ForeignKeyConstraint(columns=['cell_id'],
+ refcolumns=[cell_mappings.c.id]),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+ instance_mappings.create(checkfirst=True)
+--- nova-2015.1.2/nova/db/sqlalchemy/api_migrations/migrate_repo/versions/001_cell_mapping.py.orig 2016-03-29 17:22:24.000000000 -0600
++++ nova-2015.1.2/nova/db/sqlalchemy/api_migrations/migrate_repo/versions/001_cell_mapping.py 2016-03-29 17:23:21.833110868 -0600
+@@ -20,6 +20,9 @@ from sqlalchemy import String
+ from sqlalchemy import Table
+ from sqlalchemy import Text
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = MetaData()
+@@ -35,7 +38,7 @@ def upgrade(migrate_engine):
+ Column('database_connection', Text()),
+ UniqueConstraint('uuid', name='uniq_cell_mappings0uuid'),
+ Index('uuid_idx', 'uuid'),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+--- nova-2015.1.2/nova/db/sqlalchemy/migrate_repo/versions/252_add_instance_extra_table.py.orig 2016-03-29 17:22:24.000000000 -0600
++++ nova-2015.1.2/nova/db/sqlalchemy/migrate_repo/versions/252_add_instance_extra_table.py 2016-03-29 17:23:21.833360742 -0600
+@@ -21,6 +21,9 @@ from sqlalchemy import String
+ from sqlalchemy import Table
+ from sqlalchemy import Text
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = MetaData()
+@@ -42,7 +45,7 @@ def upgrade(migrate_engine):
+ continue
+ _columns = tuple([Column(*args, **kwargs)
+ for args, kwargs in columns])
+- table = Table(basename, meta, *_columns, mysql_engine='InnoDB',
++ table = Table(basename, meta, *_columns, mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+ table.create()
+
+--- nova-2015.1.2/nova/db/sqlalchemy/migrate_repo/versions/267_instance_uuid_non_nullable.py.orig 2016-03-29 17:22:24.000000000 -0600
++++ nova-2015.1.2/nova/db/sqlalchemy/migrate_repo/versions/267_instance_uuid_non_nullable.py 2016-03-29 17:23:21.833658136 -0600
+@@ -23,6 +23,10 @@ from nova.i18n import _
+
+ LOG = logging.getLogger(__name__)
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
++
+ UC_NAME = 'uniq_instances0uuid'
+
+
+@@ -90,6 +94,12 @@ def process_null_records(meta, scan=True
+
+
+ def upgrade(migrate_engine):
++
++ # MySQL Cluster, a.k.a. NDB, has non-NULL records from the beginning.
++ # If we are using NDB, we will return without migrating as it is not required.
++ if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ return
++
+ # NOTE(mriedem): We're going to load up all of the tables so we can find
+ # any with an instance_uuid column since those may be foreign keys back
+ # to the instances table and we want to cleanup those records first. We
+--- nova-2015.1.2/nova/db/sqlalchemy/migrate_repo/versions/250_remove_instance_groups_metadata.py.orig 2016-03-29 17:22:24.000000000 -0600
++++ nova-2015.1.2/nova/db/sqlalchemy/migrate_repo/versions/250_remove_instance_groups_metadata.py 2016-03-29 17:23:21.833942694 -0600
+@@ -17,6 +17,9 @@
+ from sqlalchemy import MetaData, Table, Column, DateTime, Integer, String, \
+ ForeignKey
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ """Remove the instance_group_metadata table."""
+@@ -49,7 +52,7 @@ def downgrade(migrate_engine):
+ Column('value', String(length=255)),
+ Column('group_id', Integer, ForeignKey('instance_groups.id'),
+ nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8',
+ )
+ group_metadata.create()
+@@ -65,7 +68,7 @@ def downgrade(migrate_engine):
+ Column('group_id', Integer,
+ ForeignKey('shadow_instance_groups.id'),
+ nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8',
+ )
+ shadow_group_metadata.create()
+--- nova-2015.1.2/nova/db/sqlalchemy/migrate_repo/versions/216_havana.py.orig 2016-03-29 17:22:24.000000000 -0600
++++ nova-2015.1.2/nova/db/sqlalchemy/migrate_repo/versions/216_havana.py 2016-03-29 17:23:21.835352443 -0600
+@@ -25,6 +25,15 @@ from nova.i18n import _LE
+
+ LOG = logging.getLogger(__name__)
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
++
++if CONF.database.mysql_storage_engine == "NDBCLUSTER":
++ db_string_length = 128
++else:
++ db_string_length = 255
++
+
+ # Note on the autoincrement flag: this is defaulted for primary key columns
+ # of integral type, so is no longer set explicitly in such cases.
+@@ -76,7 +85,7 @@ def _create_shadow_tables(migrate_engine
+
+ shadow_table_name = 'shadow_' + table_name
+ shadow_table = Table(shadow_table_name, meta, *columns,
+- mysql_engine='InnoDB')
++ mysql_engine=CONF.database.mysql_storage_engine)
+ try:
+ shadow_table.create()
+ except Exception:
+@@ -167,7 +176,7 @@ def _create_dump_tables(migrate_engine):
+ else:
+ columns.append(column.copy())
+ table_dump = Table(dump_table_name, meta, *columns,
+- mysql_engine='InnoDB')
++ mysql_engine=CONF.database.mysql_storage_engine)
+ table_dump.create()
+
+
+@@ -180,14 +189,14 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('hypervisor', String(length=255)),
+- Column('os', String(length=255)),
+- Column('architecture', String(length=255)),
+- Column('version', String(length=255)),
+- Column('url', String(length=255)),
+- Column('md5hash', String(length=255)),
++ Column('hypervisor', String(length=db_string_length)),
++ Column('os', String(length=db_string_length)),
++ Column('architecture', String(length=db_string_length)),
++ Column('version', String(length=db_string_length)),
++ Column('url', String(length=db_string_length)),
++ Column('md5hash', String(length=db_string_length)),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -196,11 +205,11 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('host', String(length=255)),
++ Column('host', String(length=db_string_length)),
+ Column('aggregate_id', Integer, ForeignKey('aggregates.id'),
+ nullable=False),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -211,10 +220,10 @@ def upgrade(migrate_engine):
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('aggregate_id', Integer, ForeignKey('aggregates.id'),
+ nullable=False),
+- Column('key', String(length=255), nullable=False),
+- Column('value', String(length=255), nullable=False),
++ Column('key', String(length=db_string_length), nullable=False),
++ Column('value', String(length=db_string_length), nullable=False),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -223,9 +232,9 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('name', String(length=255)),
++ Column('name', String(length=db_string_length)),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -234,7 +243,7 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('device_name', String(length=255), nullable=True),
++ Column('device_name', String(length=db_string_length), nullable=True),
+ Column('delete_on_termination', Boolean),
+ Column('snapshot_id', String(length=36), nullable=True),
+ Column('volume_id', String(length=36), nullable=True),
+@@ -243,14 +252,14 @@ def upgrade(migrate_engine):
+ Column('connection_info', MediumText()),
+ Column('instance_uuid', String(length=36)),
+ Column('deleted', Integer),
+- Column('source_type', String(length=255), nullable=True),
+- Column('destination_type', String(length=255), nullable=True),
+- Column('guest_format', String(length=255), nullable=True),
+- Column('device_type', String(length=255), nullable=True),
+- Column('disk_bus', String(length=255), nullable=True),
++ Column('source_type', String(length=db_string_length), nullable=True),
++ Column('destination_type', String(length=db_string_length), nullable=True),
++ Column('guest_format', String(length=db_string_length), nullable=True),
++ Column('device_type', String(length=db_string_length), nullable=True),
++ Column('disk_bus', String(length=db_string_length), nullable=True),
+ Column('boot_index', Integer),
+ Column('image_id', String(length=36), nullable=True),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -263,12 +272,12 @@ def upgrade(migrate_engine):
+ Column('last_refreshed', DateTime),
+ Column('bw_in', BigInteger),
+ Column('bw_out', BigInteger),
+- Column('mac', String(length=255)),
++ Column('mac', String(length=db_string_length)),
+ Column('uuid', String(length=36)),
+ Column('last_ctr_in', BigInteger()),
+ Column('last_ctr_out', BigInteger()),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -277,14 +286,14 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('api_url', String(length=255)),
++ Column('api_url', String(length=db_string_length)),
+ Column('weight_offset', Float),
+ Column('weight_scale', Float),
+- Column('name', String(length=255)),
++ Column('name', String(length=db_string_length)),
+ Column('is_parent', Boolean),
+ Column('deleted', Integer),
+- Column('transport_url', String(length=255), nullable=False),
+- mysql_engine='InnoDB',
++ Column('transport_url', String(length=db_string_length), nullable=False),
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -293,11 +302,11 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('user_id', String(length=255)),
+- Column('project_id', String(length=255)),
+- Column('file_name', String(length=255)),
++ Column('user_id', String(length=db_string_length)),
++ Column('project_id', String(length=db_string_length)),
++ Column('file_name', String(length=db_string_length)),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -307,10 +316,10 @@ def upgrade(migrate_engine):
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('compute_node_id', Integer, nullable=False),
+- Column('key', String(length=255), nullable=False),
+- Column('value', String(length=255)),
++ Column('key', String(length=db_string_length), nullable=False),
++ Column('value', String(length=db_string_length)),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -334,12 +343,12 @@ def upgrade(migrate_engine):
+ Column('free_disk_gb', Integer),
+ Column('current_workload', Integer),
+ Column('running_vms', Integer),
+- Column('hypervisor_hostname', String(length=255)),
++ Column('hypervisor_hostname', String(length=db_string_length)),
+ Column('deleted', Integer),
+ Column('host_ip', InetSmall()),
+ Column('supported_instances', Text),
+ Column('pci_stats', Text, nullable=True),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -349,14 +358,14 @@ def upgrade(migrate_engine):
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('address', InetSmall()),
+- Column('username', String(length=255)),
+- Column('password', String(length=255)),
+- Column('console_type', String(length=255)),
+- Column('public_hostname', String(length=255)),
+- Column('host', String(length=255)),
+- Column('compute_host', String(length=255)),
++ Column('username', String(length=db_string_length)),
++ Column('password', String(length=db_string_length)),
++ Column('console_type', String(length=db_string_length)),
++ Column('public_hostname', String(length=db_string_length)),
++ Column('host', String(length=db_string_length)),
++ Column('compute_host', String(length=db_string_length)),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -365,15 +374,15 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('instance_name', String(length=255)),
+- Column('password', String(length=255)),
++ Column('instance_name', String(length=db_string_length)),
++ Column('password', String(length=db_string_length)),
+ Column('port', Integer),
+ Column('pool_id', Integer, ForeignKey('console_pools.id')),
+ Column('instance_uuid', String(length=36),
+ ForeignKey('instances.uuid',
+ name='consoles_instance_uuid_fkey')),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -382,11 +391,11 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('deleted', Boolean),
+- Column('domain', String(length=255), primary_key=True, nullable=False),
+- Column('scope', String(length=255)),
+- Column('availability_zone', String(length=255)),
+- Column('project_id', String(length=255)),
+- mysql_engine='InnoDB',
++ Column('domain', String(length=db_string_length), primary_key=True, nullable=False),
++ Column('scope', String(length=db_string_length)),
++ Column('availability_zone', String(length=db_string_length)),
++ Column('project_id', String(length=db_string_length)),
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -401,10 +410,10 @@ def upgrade(migrate_engine):
+ Column('leased', Boolean),
+ Column('reserved', Boolean),
+ Column('virtual_interface_id', Integer),
+- Column('host', String(length=255)),
++ Column('host', String(length=db_string_length)),
+ Column('instance_uuid', String(length=36)),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -415,13 +424,13 @@ def upgrade(migrate_engine):
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('address', InetSmall()),
+ Column('fixed_ip_id', Integer),
+- Column('project_id', String(length=255)),
+- Column('host', String(length=255)),
++ Column('project_id', String(length=db_string_length)),
++ Column('host', String(length=db_string_length)),
+ Column('auto_assigned', Boolean),
+- Column('pool', String(length=255)),
+- Column('interface', String(length=255)),
++ Column('pool', String(length=db_string_length)),
++ Column('interface', String(length=db_string_length)),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -432,11 +441,11 @@ def upgrade(migrate_engine):
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('instance_uuid', String(length=36)),
+ Column('code', Integer, nullable=False),
+- Column('message', String(length=255)),
++ Column('message', String(length=db_string_length)),
+ Column('details', MediumText()),
+- Column('host', String(length=255)),
++ Column('host', String(length=db_string_length)),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -447,7 +456,7 @@ def upgrade(migrate_engine):
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('uuid', String(36), nullable=False),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -459,7 +468,7 @@ def upgrade(migrate_engine):
+ Column('network_info', MediumText()),
+ Column('instance_uuid', String(length=36), nullable=False),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -469,13 +478,13 @@ def upgrade(migrate_engine):
+ Column('deleted_at', DateTime),
+ Column('deleted', Integer),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('user_id', String(length=255)),
+- Column('project_id', String(length=255)),
++ Column('user_id', String(length=db_string_length)),
++ Column('project_id', String(length=db_string_length)),
+ Column('uuid', String(length=36), nullable=False),
+- Column('name', String(length=255)),
++ Column('name', String(length=db_string_length)),
+ UniqueConstraint('uuid', 'deleted',
+ name='uniq_instance_groups0uuid0deleted'),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8',
+ )
+
+@@ -485,11 +494,11 @@ def upgrade(migrate_engine):
+ Column('deleted_at', DateTime),
+ Column('deleted', Integer),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('key', String(length=255)),
+- Column('value', String(length=255)),
++ Column('key', String(length=db_string_length)),
++ Column('value', String(length=db_string_length)),
+ Column('group_id', Integer, ForeignKey('instance_groups.id'),
+ nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8',
+ )
+
+@@ -499,10 +508,10 @@ def upgrade(migrate_engine):
+ Column('deleted_at', DateTime),
+ Column('deleted', Integer),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('policy', String(length=255)),
++ Column('policy', String(length=db_string_length)),
+ Column('group_id', Integer, ForeignKey('instance_groups.id'),
+ nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8',
+ )
+
+@@ -512,10 +521,10 @@ def upgrade(migrate_engine):
+ Column('deleted_at', DateTime),
+ Column('deleted', Integer),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('instance_id', String(length=255)),
++ Column('instance_id', String(length=db_string_length)),
+ Column('group_id', Integer, ForeignKey('instance_groups.id'),
+ nullable=False),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8',
+ )
+
+@@ -524,11 +533,11 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('key', String(length=255)),
+- Column('value', String(length=255)),
++ Column('key', String(length=db_string_length)),
++ Column('value', String(length=db_string_length)),
+ Column('instance_uuid', String(length=36), nullable=True),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -538,10 +547,10 @@ def upgrade(migrate_engine):
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('instance_uuid', String(length=36), nullable=False),
+- Column('key', String(length=255), nullable=False),
+- Column('value', String(length=255)),
++ Column('key', String(length=db_string_length), nullable=False),
++ Column('value', String(length=db_string_length)),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -552,10 +561,10 @@ def upgrade(migrate_engine):
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('instance_type_id', Integer, ForeignKey('instance_types.id'),
+ nullable=False),
+- Column('key', String(length=255)),
+- Column('value', String(length=255)),
++ Column('key', String(length=db_string_length)),
++ Column('value', String(length=db_string_length)),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -565,9 +574,9 @@ def upgrade(migrate_engine):
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('instance_type_id', Integer, nullable=False),
+- Column('project_id', String(length=255)),
++ Column('project_id', String(length=db_string_length)),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -575,20 +584,20 @@ def upgrade(migrate_engine):
+ Column('created_at', DateTime),
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+- Column('name', String(length=255)),
++ Column('name', String(length=db_string_length)),
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('memory_mb', Integer, nullable=False),
+ Column('vcpus', Integer, nullable=False),
+ Column('swap', Integer, nullable=False),
+ Column('vcpu_weight', Integer),
+- Column('flavorid', String(length=255)),
++ Column('flavorid', String(length=db_string_length)),
+ Column('rxtx_factor', Float),
+ Column('root_gb', Integer),
+ Column('ephemeral_gb', Integer),
+ Column('disabled', Boolean),
+ Column('is_public', Boolean),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -599,54 +608,54 @@ def upgrade(migrate_engine):
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('internal_id', Integer),
+- Column('user_id', String(length=255)),
+- Column('project_id', String(length=255)),
+- Column('image_ref', String(length=255)),
+- Column('kernel_id', String(length=255)),
+- Column('ramdisk_id', String(length=255)),
++ Column('user_id', String(length=db_string_length)),
++ Column('project_id', String(length=db_string_length)),
++ Column('image_ref', String(length=db_string_length)),
++ Column('kernel_id', String(length=db_string_length)),
++ Column('ramdisk_id', String(length=db_string_length)),
+ Column('launch_index', Integer),
+- Column('key_name', String(length=255)),
++ Column('key_name', String(length=db_string_length)),
+ Column('key_data', MediumText()),
+ Column('power_state', Integer),
+- Column('vm_state', String(length=255)),
++ Column('vm_state', String(length=db_string_length)),
+ Column('memory_mb', Integer),
+ Column('vcpus', Integer),
+- Column('hostname', String(length=255)),
+- Column('host', String(length=255)),
++ Column('hostname', String(length=db_string_length)),
++ Column('host', String(length=db_string_length)),
+ Column('user_data', MediumText()),
+- Column('reservation_id', String(length=255)),
++ Column('reservation_id', String(length=db_string_length)),
+ Column('scheduled_at', DateTime),
+ Column('launched_at', DateTime),
+ Column('terminated_at', DateTime),
+- Column('display_name', String(length=255)),
+- Column('display_description', String(length=255)),
+- Column('availability_zone', String(length=255)),
++ Column('display_name', String(length=db_string_length)),
++ Column('display_description', String(length=db_string_length)),
++ Column('availability_zone', String(length=db_string_length)),
+ Column('locked', Boolean),
+- Column('os_type', String(length=255)),
++ Column('os_type', String(length=db_string_length)),
+ Column('launched_on', MediumText()),
+ Column('instance_type_id', Integer),
+- Column('vm_mode', String(length=255)),
+- Column('uuid', String(length=36)),
+- Column('architecture', String(length=255)),
+- Column('root_device_name', String(length=255)),
++ Column('vm_mode', String(length=db_string_length)),
++ Column('uuid', String(length=36), nullable=False),
++ Column('architecture', String(length=db_string_length)),
++ Column('root_device_name', String(length=db_string_length)),
+ Column('access_ip_v4', InetSmall()),
+ Column('access_ip_v6', InetSmall()),
+- Column('config_drive', String(length=255)),
+- Column('task_state', String(length=255)),
+- Column('default_ephemeral_device', String(length=255)),
+- Column('default_swap_device', String(length=255)),
++ Column('config_drive', String(length=db_string_length)),
++ Column('task_state', String(length=db_string_length)),
++ Column('default_ephemeral_device', String(length=db_string_length)),
++ Column('default_swap_device', String(length=db_string_length)),
+ Column('progress', Integer),
+ Column('auto_disk_config', Boolean),
+ Column('shutdown_terminate', Boolean),
+ Column('disable_terminate', Boolean),
+ Column('root_gb', Integer),
+ Column('ephemeral_gb', Integer),
+- Column('cell_name', String(length=255)),
+- Column('node', String(length=255)),
++ Column('cell_name', String(length=db_string_length)),
++ Column('node', String(length=db_string_length)),
+ Column('deleted', Integer),
+ Column('locked_by', inst_lock_enum),
+ Column('cleaned', Integer, default=0),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -655,16 +664,16 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('action', String(length=255)),
++ Column('action', String(length=db_string_length)),
+ Column('instance_uuid', String(length=36)),
+- Column('request_id', String(length=255)),
+- Column('user_id', String(length=255)),
+- Column('project_id', String(length=255)),
++ Column('request_id', String(length=db_string_length)),
++ Column('user_id', String(length=db_string_length)),
++ Column('project_id', String(length=db_string_length)),
+ Column('start_time', DateTime),
+ Column('finish_time', DateTime),
+- Column('message', String(length=255)),
++ Column('message', String(length=db_string_length)),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8',
+ )
+
+@@ -673,14 +682,14 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('event', String(length=255)),
++ Column('event', String(length=db_string_length)),
+ Column('action_id', Integer, ForeignKey('instance_actions.id')),
+ Column('start_time', DateTime),
+ Column('finish_time', DateTime),
+- Column('result', String(length=255)),
++ Column('result', String(length=db_string_length)),
+ Column('traceback', Text),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8',
+ )
+
+@@ -690,10 +699,10 @@ def upgrade(migrate_engine):
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('target_num', Integer),
+- Column('host', String(length=255)),
++ Column('host', String(length=db_string_length)),
+ Column('volume_id', String(length=36), nullable=True),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -702,12 +711,12 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('name', String(length=255)),
+- Column('user_id', String(length=255)),
+- Column('fingerprint', String(length=255)),
++ Column('name', String(length=db_string_length)),
++ Column('user_id', String(length=db_string_length)),
++ Column('fingerprint', String(length=db_string_length)),
+ Column('public_key', MediumText()),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -716,17 +725,17 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('source_compute', String(length=255)),
+- Column('dest_compute', String(length=255)),
+- Column('dest_host', String(length=255)),
+- Column('status', String(length=255)),
++ Column('source_compute', String(length=db_string_length)),
++ Column('dest_compute', String(length=db_string_length)),
++ Column('dest_host', String(length=db_string_length)),
++ Column('status', String(length=db_string_length)),
+ Column('instance_uuid', String(length=36)),
+ Column('old_instance_type_id', Integer),
+ Column('new_instance_type_id', Integer),
+- Column('source_node', String(length=255)),
+- Column('dest_node', String(length=255)),
++ Column('source_node', String(length=db_string_length)),
++ Column('dest_node', String(length=db_string_length)),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -738,7 +747,7 @@ def upgrade(migrate_engine):
+ Column('injected', Boolean),
+ Column('cidr', Inet()),
+ Column('netmask', InetSmall()),
+- Column('bridge', String(length=255)),
++ Column('bridge', String(length=db_string_length)),
+ Column('gateway', InetSmall()),
+ Column('broadcast', InetSmall()),
+ Column('dns1', InetSmall()),
+@@ -747,20 +756,20 @@ def upgrade(migrate_engine):
+ Column('vpn_public_port', Integer),
+ Column('vpn_private_address', InetSmall()),
+ Column('dhcp_start', InetSmall()),
+- Column('project_id', String(length=255)),
+- Column('host', String(length=255)),
++ Column('project_id', String(length=db_string_length)),
++ Column('host', String(length=db_string_length)),
+ Column('cidr_v6', Inet()),
+ Column('gateway_v6', InetSmall()),
+- Column('label', String(length=255)),
++ Column('label', String(length=db_string_length)),
+ Column('netmask_v6', InetSmall()),
+- Column('bridge_interface', String(length=255)),
++ Column('bridge_interface', String(length=db_string_length)),
+ Column('multi_host', Boolean),
+ Column('dns2', InetSmall()),
+ Column('uuid', String(length=36)),
+ Column('priority', Integer),
+ Column('rxtx_base', Integer),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -776,8 +785,8 @@ def upgrade(migrate_engine):
+ Column('product_id', String(4)),
+ Column('vendor_id', String(4)),
+ Column('dev_type', String(8)),
+- Column('dev_id', String(255)),
+- Column('label', String(255), nullable=False),
++ Column('dev_id', String(db_string_length)),
++ Column('label', String(db_string_length), nullable=False),
+ Column('status', String(36), nullable=False),
+ Column('extra_info', Text, nullable=True),
+ Column('instance_uuid', String(36), nullable=True),
+@@ -788,7 +797,7 @@ def upgrade(migrate_engine):
+ UniqueConstraint('compute_node_id',
+ 'address', 'deleted',
+ name=pci_devices_uc_name),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+
+ provider_fw_rules = Table('provider_fw_rules', meta,
+@@ -801,7 +810,7 @@ def upgrade(migrate_engine):
+ Column('to_port', Integer),
+ Column('cidr', Inet()),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -810,11 +819,11 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('class_name', String(length=255)),
+- Column('resource', String(length=255)),
++ Column('class_name', String(length=db_string_length)),
++ Column('resource', String(length=db_string_length)),
+ Column('hard_limit', Integer),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -823,14 +832,14 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('project_id', String(length=255)),
+- Column('resource', String(length=255)),
++ Column('project_id', String(length=db_string_length)),
++ Column('resource', String(length=db_string_length)),
+ Column('in_use', Integer, nullable=False),
+ Column('reserved', Integer, nullable=False),
+ Column('until_refresh', Integer),
+ Column('deleted', Integer),
+- Column('user_id', String(length=255)),
+- mysql_engine='InnoDB',
++ Column('user_id', String(length=db_string_length)),
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -839,11 +848,11 @@ def upgrade(migrate_engine):
+ Column('created_at', DateTime),
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+- Column('project_id', String(length=255)),
+- Column('resource', String(length=255), nullable=False),
++ Column('project_id', String(length=db_string_length)),
++ Column('resource', String(length=db_string_length), nullable=False),
+ Column('hard_limit', Integer),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -856,18 +865,18 @@ def upgrade(migrate_engine):
+ Column('deleted_at', DateTime),
+ Column('deleted', Integer),
+ Column('user_id',
+- String(length=255),
++ String(length=db_string_length),
+ nullable=False),
+ Column('project_id',
+- String(length=255),
++ String(length=db_string_length),
+ nullable=False),
+ Column('resource',
+- String(length=255),
++ String(length=db_string_length),
+ nullable=False),
+ Column('hard_limit', Integer, nullable=True),
+ UniqueConstraint('user_id', 'project_id', 'resource',
+ 'deleted', name=uniq_name),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8',
+ )
+
+@@ -878,13 +887,13 @@ def upgrade(migrate_engine):
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('uuid', String(length=36), nullable=False),
+ Column('usage_id', Integer, nullable=False),
+- Column('project_id', String(length=255)),
+- Column('resource', String(length=255)),
++ Column('project_id', String(length=db_string_length)),
++ Column('resource', String(length=db_string_length)),
+ Column('delta', Integer, nullable=False),
+ Column('expire', DateTime),
+ Column('deleted', Integer),
+- Column('user_id', String(length=255)),
+- mysql_engine='InnoDB',
++ Column('user_id', String(length=db_string_length)),
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -895,7 +904,7 @@ def upgrade(migrate_engine):
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('uuid', String(length=36), nullable=False),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -908,7 +917,7 @@ def upgrade(migrate_engine):
+ Column('security_group_id', Integer),
+ Column('instance_uuid', String(length=36)),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -918,13 +927,13 @@ def upgrade(migrate_engine):
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('parent_group_id', Integer, ForeignKey('security_groups.id')),
+- Column('protocol', String(length=255)),
++ Column('protocol', String(length=db_string_length)),
+ Column('from_port', Integer),
+ Column('to_port', Integer),
+ Column('cidr', Inet()),
+ Column('group_id', Integer, ForeignKey('security_groups.id')),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -933,12 +942,12 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('name', String(length=255)),
+- Column('description', String(length=255)),
+- Column('user_id', String(length=255)),
+- Column('project_id', String(length=255)),
++ Column('name', String(length=db_string_length)),
++ Column('description', String(length=db_string_length)),
++ Column('user_id', String(length=db_string_length)),
++ Column('project_id', String(length=db_string_length)),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -952,7 +961,7 @@ def upgrade(migrate_engine):
+ Column('from_port', Integer),
+ Column('to_port', Integer),
+ Column('cidr', Inet()),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8',
+ )
+
+@@ -961,14 +970,14 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('host', String(length=255)),
+- Column('binary', String(length=255)),
+- Column('topic', String(length=255)),
++ Column('host', String(length=db_string_length)),
++ Column('binary', String(length=db_string_length)),
++ Column('topic', String(length=db_string_length)),
+ Column('report_count', Integer, nullable=False),
+ Column('disabled', Boolean),
+ Column('deleted', Integer),
+- Column('disabled_reason', String(length=255)),
+- mysql_engine='InnoDB',
++ Column('disabled_reason', String(length=db_string_length)),
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -979,7 +988,7 @@ def upgrade(migrate_engine):
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('uuid', String(length=36), nullable=False),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -989,16 +998,16 @@ def upgrade(migrate_engine):
+ Column('deleted_at', DateTime),
+ Column('id', String(length=36), primary_key=True, nullable=False),
+ Column('volume_id', String(length=36), nullable=False),
+- Column('user_id', String(length=255)),
+- Column('project_id', String(length=255)),
+- Column('status', String(length=255)),
+- Column('progress', String(length=255)),
++ Column('user_id', String(length=db_string_length)),
++ Column('project_id', String(length=db_string_length)),
++ Column('status', String(length=db_string_length)),
++ Column('progress', String(length=db_string_length)),
+ Column('volume_size', Integer),
+ Column('scheduled_at', DateTime),
+- Column('display_name', String(length=255)),
+- Column('display_description', String(length=255)),
++ Column('display_name', String(length=db_string_length)),
++ Column('display_description', String(length=db_string_length)),
+ Column('deleted', String(length=36)),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -1007,16 +1016,16 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('task_name', String(length=255), nullable=False),
+- Column('state', String(length=255), nullable=False),
+- Column('host', String(length=255), nullable=False),
++ Column('task_name', String(length=db_string_length), nullable=False),
++ Column('state', String(length=db_string_length), nullable=False),
++ Column('host', String(length=db_string_length), nullable=False),
+ Column('period_beginning', DateTime, nullable=False),
+ Column('period_ending', DateTime, nullable=False),
+- Column('message', String(length=255), nullable=False),
++ Column('message', String(length=db_string_length), nullable=False),
+ Column('task_items', Integer),
+ Column('errors', Integer),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -1025,12 +1034,12 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', Integer, primary_key=True, nullable=False),
+- Column('address', String(length=255)),
++ Column('address', String(length=db_string_length)),
+ Column('network_id', Integer),
+ Column('uuid', String(length=36)),
+ Column('instance_uuid', String(length=36), nullable=True),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -1041,7 +1050,7 @@ def upgrade(migrate_engine):
+ Column('id', Integer, primary_key=True, nullable=False),
+ Column('uuid', String(length=36), nullable=False),
+ Column('deleted', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -1050,20 +1059,20 @@ def upgrade(migrate_engine):
+ Column('updated_at', DateTime),
+ Column('deleted_at', DateTime),
+ Column('id', String(length=36), primary_key=True, nullable=False),
+- Column('ec2_id', String(length=255)),
+- Column('user_id', String(length=255)),
+- Column('project_id', String(length=255)),
+- Column('host', String(length=255)),
++ Column('ec2_id', String(length=db_string_length)),
++ Column('user_id', String(length=db_string_length)),
++ Column('project_id', String(length=db_string_length)),
++ Column('host', String(length=db_string_length)),
+ Column('size', Integer),
+- Column('availability_zone', String(length=255)),
+- Column('mountpoint', String(length=255)),
+- Column('status', String(length=255)),
+- Column('attach_status', String(length=255)),
++ Column('availability_zone', String(length=db_string_length)),
++ Column('mountpoint', String(length=db_string_length)),
++ Column('status', String(length=db_string_length)),
++ Column('attach_status', String(length=db_string_length)),
+ Column('scheduled_at', DateTime),
+ Column('launched_at', DateTime),
+ Column('terminated_at', DateTime),
+- Column('display_name', String(length=255)),
+- Column('display_description', String(length=255)),
++ Column('display_name', String(length=db_string_length)),
++ Column('display_description', String(length=db_string_length)),
+ Column('provider_location', String(length=256)),
+ Column('provider_auth', String(length=256)),
+ Column('snapshot_id', String(length=36)),
+@@ -1071,7 +1080,7 @@ def upgrade(migrate_engine):
+ Column('instance_uuid', String(length=36)),
+ Column('attach_time', DateTime),
+ Column('deleted', String(length=36)),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -1095,8 +1104,8 @@ def upgrade(migrate_engine):
+ Column("instance_uuid", String(length=36)),
+ Column("project_id", String(length=36)),
+ Column("user_id", String(length=36)),
+- Column("availability_zone", String(length=255)),
+- mysql_engine='InnoDB',
++ Column("availability_zone", String(length=db_string_length)),
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+
+@@ -1223,15 +1232,21 @@ def upgrade(migrate_engine):
+ table=aggregate_hosts,
+ name=uc_name).create()
+
+- uc_name = 'uniq_aggregate_metadata0aggregate_id0key0deleted'
+- UniqueConstraint('aggregate_id', 'key', 'deleted',
+- table=aggregate_metadata,
+- name=uc_name).create()
+-
+- uc_name = 'uniq_instance_type_extra_specs0instance_type_id0key0deleted'
+- UniqueConstraint('instance_type_id', 'key', 'deleted',
+- table=instance_type_extra_specs,
+- name=uc_name).create()
++ # Constraint does not work in MySQL Cluster, a.k.a NDB.
++ #
++ if CONF.database.mysql_storage_engine != "NDBCLUSTER":
++ uc_name = 'uniq_aggregate_metadata0aggregate_id0key0deleted'
++ UniqueConstraint('aggregate_id', 'key', 'deleted',
++ table=aggregate_metadata,
++ name=uc_name).create()
++
++ # Constraint does not work in MySQL Cluster, a.k.a NDB.
++ #
++ if CONF.database.mysql_storage_engine != "NDBCLUSTER":
++ uc_name = 'uniq_instance_type_extra_specs0instance_type_id0key0deleted'
++ UniqueConstraint('instance_type_id', 'key', 'deleted',
++ table=instance_type_extra_specs,
++ name=uc_name).create()
+
+ # created first (to preserve ordering for schema diffs)
+ mysql_pre_indexes = [
+--- nova-2015.1.2/nova/db/sqlalchemy/migrate_repo/versions/266_add_instance_tags.py.orig 2016-03-29 17:22:24.000000000 -0600
++++ nova-2015.1.2/nova/db/sqlalchemy/migrate_repo/versions/266_add_instance_tags.py 2016-03-29 17:23:21.835566671 -0600
+@@ -12,6 +12,9 @@
+
+ import sqlalchemy as sa
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(migrate_engine):
+ meta = sa.MetaData(bind=migrate_engine)
+@@ -22,7 +25,7 @@ def upgrade(migrate_engine):
+ sa.Column('tag', sa.Unicode(80), primary_key=True,
+ nullable=False),
+ sa.Index('tags_tag_idx', 'tag'),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8')
+ tags.create()
+
+--- nova-2015.1.2/nova/db/sqlalchemy/migrate_repo/versions/233_add_stats_in_compute_nodes.py.orig 2016-03-29 17:22:24.000000000 -0600
++++ nova-2015.1.2/nova/db/sqlalchemy/migrate_repo/versions/233_add_stats_in_compute_nodes.py 2016-03-29 17:23:21.835820531 -0600
+@@ -25,6 +25,9 @@ from sqlalchemy import String
+ from sqlalchemy import Table
+ from sqlalchemy import Text
+
++from oslo_config import cfg
++
++CONF = cfg.CONF
+
+ def upgrade(engine):
+ meta = MetaData()
+@@ -73,7 +76,7 @@ def downgrade(engine):
+ index=True),
+ Index('compute_node_stats_node_id_and_deleted_idx',
+ 'compute_node_id', 'deleted'),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+ table.create()
+@@ -88,7 +91,7 @@ def downgrade(engine):
+ Column('key', String(255), nullable=False),
+ Column('value', String(255), nullable=True),
+ Column('compute_node_id', Integer),
+- mysql_engine='InnoDB',
++ mysql_engine=CONF.database.mysql_storage_engine,
+ mysql_charset='utf8'
+ )
+ table.create()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/python/oslo.db/patches/mysql_cluster_support.patch Fri Apr 01 14:13:41 2016 -0600
@@ -0,0 +1,28 @@
+This patchset is for bug:
+
+23033470 - oslo.db needs a database option to support MySQL Cluster
+
+This fixes the following aspects of Oslo.db:
+1. Implementation of an oslo.db configuration parameter to specify the MySQL
+ storage engine (mysql_storage_engine).
+
+This has not been committed upstream, but has been filed in launchpad:
+
+https://bugs.launchpad.net/oslo.db/+bug/1564110
+
+
+--- oslo.db-1.7.2/oslo_db/options.py.orig 2016-02-17 14:56:11.276310637 -0700
++++ oslo.db-1.7.2/oslo_db/options.py 2016-02-19 10:32:20.551188376 -0700
+@@ -50,6 +50,12 @@ database_opts = [
+ 'server-set SQL mode. To use whatever SQL mode '
+ 'is set by the server configuration, '
+ 'set this to no value. Example: mysql_sql_mode='),
++ cfg.StrOpt('mysql_storage_engine',
++ default='InnoDB',
++ help='This configures the MySQL storage engine. '
++ 'This allows for OpenStack to support different storage engines '
++ 'such as InnoDB, NDB, etc. For MySQL Cluster, set to NDBCLUSTER. '
++ 'Example: mysql_storage_engine=NDBCLUSTER'),
+ cfg.IntOpt('idle_timeout',
+ default=3600,
+ deprecated_opts=[cfg.DeprecatedOpt('sql_idle_timeout',