diff options
| author | Jenkins <jenkins@review.openstack.org> | 2012-11-13 21:06:42 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2012-11-13 21:06:42 +0000 |
| commit | b45ca52108a0b64f18885abb3c42cd4a2ff89ee8 (patch) | |
| tree | c67f1cb5f3889cc2083ba44fba74e96265cf17f0 | |
| parent | 083bccd34bc35dc043f17ff6ade66c64dd4bead2 (diff) | |
| parent | 3e25d9bc235381081210ca160bb1188ed05274ea (diff) | |
| download | nova-b45ca52108a0b64f18885abb3c42cd4a2ff89ee8.tar.gz nova-b45ca52108a0b64f18885abb3c42cd4a2ff89ee8.tar.xz nova-b45ca52108a0b64f18885abb3c42cd4a2ff89ee8.zip | |
Merge "Add DB query to get in-progress migrations."
| -rw-r--r-- | nova/db/api.py | 7 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/api.py | 11 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/migrate_repo/versions/137_add_indexes_to_migrations.py | 46 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/models.py | 5 | ||||
| -rw-r--r-- | nova/tests/test_db_api.py | 49 |
5 files changed, 118 insertions, 0 deletions
diff --git a/nova/db/api.py b/nova/db/api.py index 04786a1fb..ea47e5f43 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -406,6 +406,13 @@ def migration_get_unconfirmed_by_dest_compute(context, confirm_window, confirm_window, dest_compute) +def migration_get_in_progress_by_host(context, host): + """Finds all migrations for the given host that are not yet confirmed or + reverted. + """ + return IMPL.migration_get_in_progress_by_host(context, host) + + #################### diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 72caad74d..ec78a87e6 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -3351,6 +3351,17 @@ def migration_get_unconfirmed_by_dest_compute(context, confirm_window, all() +@require_admin_context +def migration_get_in_progress_by_host(context, host, session=None): + + return model_query(context, models.Migration, session=session).\ + filter(or_(models.Migration.source_compute == host, + models.Migration.dest_compute == host)).\ + filter(~models.Migration.status.in_(['confirmed', 'reverted'])).\ + options(joinedload('instance')).\ + all() + + ################## diff --git a/nova/db/sqlalchemy/migrate_repo/versions/137_add_indexes_to_migrations.py b/nova/db/sqlalchemy/migrate_repo/versions/137_add_indexes_to_migrations.py new file mode 100644 index 000000000..1499bd351 --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/137_add_indexes_to_migrations.py @@ -0,0 +1,46 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 OpenStack LLC. +# 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. + +from sqlalchemy import Index, MetaData, Table +from sqlalchemy.exc import IntegrityError + + +def upgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + t = Table('migrations', meta, autoload=True) + + # Based on migration_get_in_progress_by_host + # from: nova/db/sqlalchemy/api.py + i = Index('migrations_by_host_and_status_idx', t.c.deleted, + t.c.source_compute, t.c.dest_compute, t.c.status) + try: + i.create(migrate_engine) + except IntegrityError: + pass + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + t = Table('migrations', meta, autoload=True) + + i = Index('migrations_by_host_and_status_idx', t.c.deleted, + t.c.source_compute, t.c.dest_compute, t.c.status) + i.drop(migrate_engine) diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 194b80f2d..d7c638ff8 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -641,6 +641,11 @@ class Migration(BASE, NovaBase): #TODO(_cerberus_): enum status = Column(String(255)) + instance = relationship("Instance", foreign_keys=instance_uuid, + primaryjoin='and_(Migration.instance_uuid == ' + 'Instance.uuid, Instance.deleted == ' + 'False)') + class Network(BASE, NovaBase): """Represents a network.""" diff --git a/nova/tests/test_db_api.py b/nova/tests/test_db_api.py index 7a71a1247..001880483 100644 --- a/nova/tests/test_db_api.py +++ b/nova/tests/test_db_api.py @@ -1013,6 +1013,55 @@ class CapacityTestCase(test.TestCase): self.assertEqual(1, int(stat['value'])) +class MigrationTestCase(test.TestCase): + + def setUp(self): + super(MigrationTestCase, self).setUp() + self.ctxt = context.get_admin_context() + + self._create() + self._create() + self._create(status='reverted') + self._create(status='confirmed') + self._create(source_compute='host2', dest_compute='host1') + self._create(source_compute='host2', dest_compute='host3') + self._create(source_compute='host3', dest_compute='host4') + + def _create(self, status='migrating', source_compute='host1', + dest_compute='host2'): + + values = {'host': source_compute} + instance = db.instance_create(self.ctxt, values) + + values = {'status': status, 'source_compute': source_compute, + 'dest_compute': dest_compute, + 'instance_uuid': instance['uuid']} + db.migration_create(self.ctxt, values) + + def _assert_in_progress(self, migrations): + for migration in migrations: + self.assertNotEqual('confirmed', migration.status) + self.assertNotEqual('reverted', migration.status) + + def test_in_progress_host1(self): + migrations = db.migration_get_in_progress_by_host(self.ctxt, 'host1') + # 2 as source + 1 as dest + self.assertEqual(3, len(migrations)) + self._assert_in_progress(migrations) + + def test_in_progress_host2(self): + migrations = db.migration_get_in_progress_by_host(self.ctxt, 'host2') + # 2 as dest, 2 as source + self.assertEqual(4, len(migrations)) + self._assert_in_progress(migrations) + + def test_instance_join(self): + migrations = db.migration_get_in_progress_by_host(self.ctxt, 'host2') + for migration in migrations: + instance = migration['instance'] + self.assertEqual(migration['instance_uuid'], instance['uuid']) + + class TestIpAllocation(test.TestCase): def setUp(self): |
