summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ironic/cmd/dbsync.py8
-rw-r--r--ironic/db/migration.py4
-rw-r--r--ironic/db/sqlalchemy/migration.py26
-rw-r--r--ironic/tests/db/sqlalchemy/test_migrations.py28
4 files changed, 61 insertions, 5 deletions
diff --git a/ironic/cmd/dbsync.py b/ironic/cmd/dbsync.py
index d0d6ba6f0..57059ba11 100644
--- a/ironic/cmd/dbsync.py
+++ b/ironic/cmd/dbsync.py
@@ -47,6 +47,9 @@ class DBCommand(object):
def version(self):
print(migration.version())
+ def create_schema(self):
+ migration.create_schema()
+
def add_command_parsers(subparsers):
command_object = DBCommand()
@@ -71,6 +74,9 @@ def add_command_parsers(subparsers):
parser = subparsers.add_parser('version')
parser.set_defaults(func=command_object.version)
+ parser = subparsers.add_parser('create_schema')
+ parser.set_defaults(func=command_object.create_schema)
+
command_opt = cfg.SubCommandOpt('command',
title='Command',
@@ -85,7 +91,7 @@ def main():
# pls change it to ironic-dbsync upgrade
valid_commands = set([
'upgrade', 'downgrade', 'revision',
- 'version', 'stamp'
+ 'version', 'stamp', 'create_schema',
])
if not set(sys.argv) & valid_commands:
sys.argv.append('upgrade')
diff --git a/ironic/db/migration.py b/ironic/db/migration.py
index 35f19d942..846a60e24 100644
--- a/ironic/db/migration.py
+++ b/ironic/db/migration.py
@@ -45,3 +45,7 @@ def stamp(version):
def revision(message, autogenerate):
return IMPL.revision(message, autogenerate)
+
+
+def create_schema():
+ return IMPL.create_schema()
diff --git a/ironic/db/sqlalchemy/migration.py b/ironic/db/sqlalchemy/migration.py
index 6ebb949f7..60e3f53b9 100644
--- a/ironic/db/sqlalchemy/migration.py
+++ b/ironic/db/sqlalchemy/migration.py
@@ -19,8 +19,10 @@ import os
import alembic
from alembic import config as alembic_config
import alembic.migration as alembic_migration
+from oslo.db import exception as db_exc
from ironic.db.sqlalchemy import api as sqla_api
+from ironic.db.sqlalchemy import models
def _alembic_config():
@@ -29,13 +31,14 @@ def _alembic_config():
return config
-def version(config=None):
+def version(config=None, engine=None):
"""Current database version.
:returns: Database version
:rtype: string
"""
- engine = sqla_api.get_engine()
+ if engine is None:
+ engine = sqla_api.get_engine()
with engine.connect() as conn:
context = alembic_migration.MigrationContext.configure(conn)
return context.get_current_revision()
@@ -53,6 +56,25 @@ def upgrade(revision, config=None):
alembic.command.upgrade(config, revision or 'head')
+def create_schema(config=None, engine=None):
+ """Create database schema from models description.
+
+ Can be used for initial installation instead of upgrade('head').
+ """
+ if engine is None:
+ engine = sqla_api.get_engine()
+
+ # NOTE(viktors): If we will use metadata.create_all() for non empty db
+ # schema, it will only add the new tables, but leave
+ # existing as is. So we should avoid of this situation.
+ if version(engine=engine) is not None:
+ raise db_exc.DbMigrationError("DB schema is already under version"
+ " control. Use upgrade() instead")
+
+ models.Base.metadata.create_all(engine)
+ stamp('head', config=config)
+
+
def downgrade(revision, config=None):
"""Used for downgrading database.
diff --git a/ironic/tests/db/sqlalchemy/test_migrations.py b/ironic/tests/db/sqlalchemy/test_migrations.py
index 1c2533593..c6350f49c 100644
--- a/ironic/tests/db/sqlalchemy/test_migrations.py
+++ b/ironic/tests/db/sqlalchemy/test_migrations.py
@@ -42,7 +42,7 @@ import contextlib
from alembic import script
import mock
-from oslo.db import exception
+from oslo.db import exception as db_exc
from oslo.db.sqlalchemy import test_base
from oslo.db.sqlalchemy import test_migrations
from oslo.db.sqlalchemy import utils as db_utils
@@ -315,9 +315,33 @@ class MigrationCheckersMixin(object):
# Ironic will use oslo.db 0.4.0 or higher.
# See bug #1214341 for details.
self.assertRaises(
- (sqlalchemy.exc.IntegrityError, exception.DBDuplicateEntry),
+ (sqlalchemy.exc.IntegrityError, db_exc.DBDuplicateEntry),
nodes.insert().execute, data)
+ def test_upgrade_and_version(self):
+ with patch_with_engine(self.engine):
+ self.migration_api.upgrade('head')
+ self.assertIsNotNone(self.migration_api.version())
+
+ def test_create_schema_and_version(self):
+ with patch_with_engine(self.engine):
+ self.migration_api.create_schema()
+ self.assertIsNotNone(self.migration_api.version())
+
+ def test_upgrade_and_create_schema(self):
+ with patch_with_engine(self.engine):
+ self.migration_api.upgrade('31baaf680d2b')
+ self.assertRaises(db_exc.DbMigrationError,
+ self.migration_api.create_schema)
+
+ def test_upgrade_twice(self):
+ with patch_with_engine(self.engine):
+ self.migration_api.upgrade('31baaf680d2b')
+ v1 = self.migration_api.version()
+ self.migration_api.upgrade('head')
+ v2 = self.migration_api.version()
+ self.assertNotEqual(v1, v2)
+
class TestMigrationsMySQL(MigrationCheckersMixin,
WalkVersionsMixin,