22725754 - Keystone needs to support MySQL Cluster
authorOctave Orgeron <octave.orgeron@oracle.com>
Fri, 01 Apr 2016 14:13:41 -0600
changeset 5705 1dd01efcbd26
parent 5704 8213f7c64d74
child 5706 87efc4971896
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
components/openstack/cinder/files/cinder.conf
components/openstack/cinder/patches/mysql_cluster_support.patch
components/openstack/glance/files/glance-api.conf
components/openstack/glance/files/glance-registry.conf
components/openstack/glance/files/glance-scrubber.conf
components/openstack/glance/patches/mysql_cluster_support.patch
components/openstack/heat/files/heat.conf
components/openstack/heat/patches/mysql_cluster_support.patch
components/openstack/ironic/files/ironic.conf
components/openstack/ironic/patches/mysql_cluster_support.patch
components/openstack/keystone/files/keystone.conf
components/openstack/keystone/patches/mysql_cluster_support.patch
components/openstack/neutron/files/neutron.conf
components/openstack/neutron/patches/mysql_cluster_support.patch
components/openstack/nova/files/nova.conf
components/openstack/nova/patches/mysql_cluster_support.patch
components/python/oslo.db/patches/mysql_cluster_support.patch
--- 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',