[openstack-glance/f16] Cherry pick some upstream fixes for DB upgrade issues (#809430)
Mark McLoughlin
markmc at fedoraproject.org
Wed Apr 4 11:22:11 UTC 2012
commit 905d4d5dbaf16ac02e35dad85447e8c96eb3ae54
Author: Mark McLoughlin <markmc at redhat.com>
Date: Wed Apr 4 12:21:25 2012 +0100
Cherry pick some upstream fixes for DB upgrade issues (#809430)
- Allow specifying the current version in 'glance-manage version_control'
- Don't use BIGINT in sqlite DBs
...fying-the-current-version-in-glance-manag.patch | 241 ++++++++++++++++++++
...-Compile-BigInteger-to-INTEGER-for-sqlite.patch | 86 +++++++
openstack-glance.spec | 11 +-
3 files changed, 337 insertions(+), 1 deletions(-)
---
diff --git a/0003-Allow-specifying-the-current-version-in-glance-manag.patch b/0003-Allow-specifying-the-current-version-in-glance-manag.patch
new file mode 100644
index 0000000..0819641
--- /dev/null
+++ b/0003-Allow-specifying-the-current-version-in-glance-manag.patch
@@ -0,0 +1,241 @@
+From 8d251ad2ad0936323f790585c7d19cae4a5dc925 Mon Sep 17 00:00:00 2001
+From: Mark McLoughlin <markmc at redhat.com>
+Date: Tue, 27 Mar 2012 12:23:47 +0100
+Subject: [PATCH] Allow specifying the current version in 'glance-manage
+ version_control'
+
+Fixes bug #966242
+
+The version_control command is a bit useless since you can't actually
+specify what version to use and it defaults to version=0.
+
+Allow the user to specify a version:
+
+ $> glance-manage version_control 9 # set the diablo version
+
+and default to the latest version if none is specified.
+
+Also, allow db_sync to be supplied a version for the case where we're
+upgrading an unversioned DB.
+
+Finally, re-work the argument handling in glance-manage to more easily
+handle optional args.
+
+The tests are extended to test using db_sync for upgrades and to test
+placing an existing database under version control.
+
+Change-Id: I231dc710554198bfd1fdcb82c3c3768963f64bd8
+---
+ bin/glance-manage | 29 ++++++++-------------
+ glance/registry/db/migration.py | 20 ++++++++++----
+ glance/tests/unit/test_migrations.py | 46 +++++++++++++++++++++++++++++----
+ 3 files changed, 65 insertions(+), 30 deletions(-)
+
+diff --git a/bin/glance-manage b/bin/glance-manage
+index f635232..138fdac 100755
+--- a/bin/glance-manage
++++ b/bin/glance-manage
+@@ -67,42 +67,35 @@ def do_db_version(options, args):
+
+ def do_upgrade(options, args):
+ """Upgrade the database's migration level"""
+- try:
+- db_version = args[1]
+- except IndexError:
+- db_version = None
+-
+- glance.registry.db.migration.upgrade(options, version=db_version)
++ version = args.pop(0) if args else None
++ glance.registry.db.migration.upgrade(options, version)
+
+
+ def do_downgrade(options, args):
+ """Downgrade the database's migration level"""
+- try:
+- db_version = args[1]
+- except IndexError:
++ if not args:
+ raise exception.MissingArgumentError(
+ "downgrade requires a version argument")
+-
+- glance.registry.db.migration.downgrade(options, version=db_version)
++ version = args.pop(0)
++ glance.registry.db.migration.downgrade(options, version)
+
+
+ def do_version_control(options, args):
+ """Place a database under migration control"""
+- glance.registry.db.migration.version_control(options)
++ version = args.pop(0) if args else None
++ glance.registry.db.migration.version_control(options, version)
+
+
+ def do_db_sync(options, args):
+ """Place a database under migration control and upgrade"""
+- try:
+- db_version = args[1]
+- except IndexError:
+- db_version = None
+- glance.registry.db.migration.db_sync(options, version=db_version)
++ version = args.pop(0) if args else None
++ current_version = args.pop(0) if args else None
++ glance.registry.db.migration.db_sync(options, version, current_version)
+
+
+ def dispatch_cmd(options, args):
+ """Search for do_* cmd in this module and then run it"""
+- cmd = args[0]
++ cmd = args.pop(0)
+ try:
+ cmd_func = globals()['do_%s' % cmd]
+ except KeyError:
+diff --git a/glance/registry/db/migration.py b/glance/registry/db/migration.py
+index 253107b..0ebd666 100644
+--- a/glance/registry/db/migration.py
++++ b/glance/registry/db/migration.py
+@@ -25,6 +25,7 @@ try:
+ from migrate.versioning import exceptions as versioning_exceptions
+ except ImportError:
+ from migrate import exceptions as versioning_exceptions
++from migrate.versioning import repository as versioning_repository
+
+ from glance.common import exception
+
+@@ -82,7 +83,7 @@ def downgrade(options, version):
+ return versioning_api.downgrade(sql_connection, repo_path, version)
+
+
+-def version_control(options):
++def version_control(options, version=None):
+ """
+ Place a database under migration control
+
+@@ -90,14 +91,14 @@ def version_control(options):
+ """
+ sql_connection = options['sql_connection']
+ try:
+- _version_control(options)
++ _version_control(options, version)
+ except versioning_exceptions.DatabaseAlreadyControlledError, e:
+ msg = (_("database '%(sql_connection)s' is already under migration "
+ "control") % locals())
+ raise exception.DatabaseMigrationError(msg)
+
+
+-def _version_control(options):
++def _version_control(options, version=None):
+ """
+ Place a database under migration control
+
+@@ -105,20 +106,27 @@ def _version_control(options):
+ """
+ repo_path = get_migrate_repo_path()
+ sql_connection = options['sql_connection']
+- return versioning_api.version_control(sql_connection, repo_path)
++ if version is None:
++ version = versioning_repository.Repository(repo_path).latest
++ return versioning_api.version_control(sql_connection, repo_path, version)
+
+
+-def db_sync(options, version=None):
++def db_sync(options, version=None, current_version=None):
+ """
+ Place a database under migration control and perform an upgrade
+
+ :param options: options dict
+ :retval version number
+ """
++ sql_connection = options['sql_connection']
+ try:
+- _version_control(options)
++ _version_control(options, current_version)
+ except versioning_exceptions.DatabaseAlreadyControlledError, e:
+ pass
++ if current_version is not None:
++ msg = (_("database '%(sql_connection)s' is already under "
++ "migration control") % locals())
++ raise exception.DatabaseMigrationError(msg)
+
+ upgrade(options, version=version)
+
+diff --git a/glance/tests/unit/test_migrations.py b/glance/tests/unit/test_migrations.py
+index 0ab4755..a6e3bcb 100644
+--- a/glance/tests/unit/test_migrations.py
++++ b/glance/tests/unit/test_migrations.py
+@@ -35,6 +35,7 @@ from sqlalchemy import *
+ from sqlalchemy.pool import NullPool
+
+ from glance.common import exception
++from glance.registry.db import models
+ import glance.registry.db.migration as migration_api
+ from glance.tests.utils import execute
+
+@@ -127,7 +128,39 @@ class TestMigrations(unittest.TestCase):
+ options = {'sql_connection': TestMigrations.TEST_DATABASES[key]}
+ self._walk_versions(options)
+
+- def _walk_versions(self, options):
++ def test_version_control_existing_db(self):
++ """
++ Creates a DB without version control information, places it
++ under version control and checks that it can be upgraded
++ without errors.
++ """
++ for key, engine in self.engines.items():
++ #conf = utils.TestConfigOpts({
++ # 'sql_connection': TestMigrations.TEST_DATABASES[key]})
++ #conf.register_opt(cfg.StrOpt('sql_connection'))
++ options = {'sql_connection': TestMigrations.TEST_DATABASES[key]}
++ self._create_unversioned_001_db(engine)
++ self._walk_versions(options, initial_version=1)
++
++ def _create_unversioned_001_db(self, engine):
++ # Create the initial version of the images table
++ meta = MetaData()
++ meta.bind = engine
++ images_001 = Table('images', meta,
++ Column('id', models.Integer, primary_key=True),
++ Column('name', String(255)),
++ Column('type', String(30)),
++ Column('size', Integer),
++ Column('status', String(30)),
++ Column('is_public', Boolean, default=False),
++ Column('location', Text),
++ Column('created_at', DateTime(), nullable=False),
++ Column('updated_at', DateTime()),
++ Column('deleted_at', DateTime()),
++ Column('deleted', Boolean(), nullable=False, default=False))
++ images_001.create()
++
++ def _walk_versions(self, options, initial_version=0):
+ # Determine latest version script from the repo, then
+ # upgrade from 1 through to the latest, with no data
+ # in the databases. This just checks that the schema itself
+@@ -138,13 +171,14 @@ class TestMigrations(unittest.TestCase):
+ migration_api.db_version,
+ options)
+ # Place the database under version control
+- migration_api.version_control(options)
++ migration_api.version_control(options, version=initial_version)
+
+ cur_version = migration_api.db_version(options)
+- self.assertEqual(0, cur_version)
++ self.assertEqual(initial_version, cur_version)
+
+- for version in xrange(1, TestMigrations.REPOSITORY.latest + 1):
+- migration_api.upgrade(options, version)
++ for version in xrange(initial_version + 1,
++ TestMigrations.REPOSITORY.latest + 1):
++ migration_api.db_sync(options, version)
+ cur_version = migration_api.db_version(options)
+ self.assertEqual(cur_version, version)
+
+@@ -169,7 +203,7 @@ class TestMigrations(unittest.TestCase):
+ self._no_data_loss_2_to_3_to_2(engine, options)
+
+ def _no_data_loss_2_to_3_to_2(self, engine, options):
+- migration_api.version_control(options)
++ migration_api.version_control(options, version=0)
+ migration_api.upgrade(options, 2)
+
+ cur_version = migration_api.db_version(options)
diff --git a/0004-Compile-BigInteger-to-INTEGER-for-sqlite.patch b/0004-Compile-BigInteger-to-INTEGER-for-sqlite.patch
new file mode 100644
index 0000000..be022b7
--- /dev/null
+++ b/0004-Compile-BigInteger-to-INTEGER-for-sqlite.patch
@@ -0,0 +1,86 @@
+From 571c8c197b2da6bb93adac5d7f71cdac44894782 Mon Sep 17 00:00:00 2001
+From: Eoghan Glynn <eglynn at redhat.com>
+Date: Mon, 2 Apr 2012 18:55:35 +0100
+Subject: [PATCH] Compile BigInteger to INTEGER for sqlite
+
+Fixes bug 966243
+
+Ensure BigInteger does not map to BIGINT for an auto-created
+sqlite registry DB, as this type is not supported by sqlite.
+
+Change-Id: I61f44fbe50ea406d2d593f8f53cab5da3af2222a
+---
+ glance/registry/db/models.py | 6 +++++
+ glance/tests/functional/test_sqlite.py | 39 ++++++++++++++++++++++++++++++++
+ 2 files changed, 45 insertions(+), 0 deletions(-)
+ create mode 100644 glance/tests/functional/test_sqlite.py
+
+diff --git a/glance/registry/db/models.py b/glance/registry/db/models.py
+index a66bc67..c6266b6 100644
+--- a/glance/registry/db/models.py
++++ b/glance/registry/db/models.py
+@@ -27,6 +27,7 @@ from sqlalchemy.orm import relationship, backref, exc, object_mapper, validates
+ from sqlalchemy import Column, Integer, String, BigInteger
+ from sqlalchemy import ForeignKey, DateTime, Boolean, Text
+ from sqlalchemy import UniqueConstraint
++from sqlalchemy.ext.compiler import compiles
+ from sqlalchemy.ext.declarative import declarative_base
+
+ import glance.registry.db.api
+@@ -35,6 +36,11 @@ from glance.common import exception
+ BASE = declarative_base()
+
+
++ at compiles(BigInteger, 'sqlite')
++def compile_big_int_sqlite(type_, compiler, **kw):
++ return 'INTEGER'
++
++
+ class ModelBase(object):
+ """Base class for Nova and Glance Models"""
+ __table_args__ = {'mysql_engine': 'InnoDB'}
+diff --git a/glance/tests/functional/test_sqlite.py b/glance/tests/functional/test_sqlite.py
+new file mode 100644
+index 0000000..4cfff6a
+--- /dev/null
++++ b/glance/tests/functional/test_sqlite.py
+@@ -0,0 +1,39 @@
++# vim: tabstop=4 shiftwidth=4 softtabstop=4
++
++# Copyright 2012 Red Hat, Inc
++# All Rights Reserved.
++#
++# Licensed under the Apache License, Version 2.0 (the "License"); you may
++# not use this file except in compliance with the License. You may obtain
++# a copy of the License at
++#
++# http://www.apache.org/licenses/LICENSE-2.0
++#
++# Unless required by applicable law or agreed to in writing, software
++# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
++# License for the specific language governing permissions and limitations
++# under the License.
++
++"""Functional test cases for sqlite-specific logic"""
++
++
++from glance.tests import functional
++from glance.tests.utils import execute
++
++
++class TestSqlite(functional.FunctionalTest):
++ """Functional tests for sqlite-specific logic"""
++
++ @functional.runs_sql
++ def test_big_int_mapping(self):
++ """Ensure BigInteger not mapped to BIGINT"""
++ self.cleanup()
++ self.start_servers(**self.__dict__.copy())
++
++ cmd = "sqlite3 tests.sqlite '.schema'"
++ exitcode, out, err = execute(cmd, raise_error=True)
++
++ self.assertFalse('BIGINT' in out)
++
++ self.stop_servers()
diff --git a/openstack-glance.spec b/openstack-glance.spec
index 5f1b693..773a800 100644
--- a/openstack-glance.spec
+++ b/openstack-glance.spec
@@ -1,6 +1,6 @@
Name: openstack-glance
Version: 2011.3.1
-Release: 3%{?dist}
+Release: 4%{?dist}
Summary: OpenStack Image Service
Group: Applications/System
@@ -16,6 +16,8 @@ Source3: openstack-glance.logrotate
#
Patch0001: 0001-Always-reference-the-glance-module-from-the-package-.patch
Patch0002: 0002-Don-t-access-the-net-while-building-docs.patch
+Patch0003: 0003-Allow-specifying-the-current-version-in-glance-manag.patch
+Patch0004: 0004-Compile-BigInteger-to-INTEGER-for-sqlite.patch
BuildArch: noarch
BuildRequires: python2-devel
@@ -99,6 +101,8 @@ This package contains documentation files for glance.
%patch0001 -p1
%patch0002 -p1
+%patch0003 -p1
+%patch0004 -p1
sed -i 's|\(sql_connection = sqlite:///\)\(glance.sqlite\)|\1%{_sharedstatedir}/glance/\2|' etc/glance-registry.conf
@@ -211,6 +215,11 @@ fi
%doc doc/build/html
%changelog
+* Wed Apr 4 2012 Mark McLoughlin <markmc at redhat.com> - 2011.3.1-4
+- Cherry pick some upstream fixes for DB upgrade issues (#809430)
+- Allow specifying the current version in 'glance-manage version_control'
+- Don't use BIGINT in sqlite DBs
+
* Mon Feb 13 2012 Russell Bryant <rbryant at redhat.com> - 2011.3.1-3
- Add dependency on python-crypto. (rhbz#789943)
More information about the scm-commits
mailing list