From 2e48a60d82712519c0e90cb2b8998a79ca300caf Mon Sep 17 00:00:00 2001 From: yuntongjin Date: Thu, 17 Dec 2015 12:45:28 +0800 Subject: [PATCH] Add migration progress detail in DB Add migration progress detail : memory_total,memory_processed, memory_remaining,disk_total,disk_processed,disk_remaining into migration DB. Partially implements blueprint live-migration-progress-report Co-Authored-By: ShaoHe Feng Change-Id: Iea97d5d3b003fa42dd41cc923d6e026c67a14485 --- .../compute/legacy_v2/contrib/migrations.py | 8 +++++ nova/api/openstack/compute/migrations.py | 8 +++++ .../315_add_migration_progresss_detail.py | 30 +++++++++++++++++++ nova/db/sqlalchemy/models.py | 6 ++++ nova/objects/migration.py | 17 ++++++++++- .../api/openstack/compute/test_migrations.py | 12 ++++++++ nova/tests/unit/db/test_migrations.py | 14 +++++++++ nova/tests/unit/objects/test_migration.py | 6 ++++ nova/tests/unit/objects/test_objects.py | 2 +- 9 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 nova/db/sqlalchemy/migrate_repo/versions/315_add_migration_progresss_detail.py diff --git a/nova/api/openstack/compute/legacy_v2/contrib/migrations.py b/nova/api/openstack/compute/legacy_v2/contrib/migrations.py index 91a5493c77c7..472dbf6dfa53 100644 --- a/nova/api/openstack/compute/legacy_v2/contrib/migrations.py +++ b/nova/api/openstack/compute/legacy_v2/contrib/migrations.py @@ -31,6 +31,10 @@ def output(migrations_obj): From a MigrationsList's object this method returns a list of primitive objects with the only necessary fields. """ + detail_keys = ['memory_total', 'memory_processed', 'memory_remaining', + 'disk_total', 'disk_processed', 'disk_remaining'] + # Note(Shaohe Feng): We need to leverage the oslo.versionedobjects. + # Then we can pass the target version to it's obj_to_primitive. objects = obj_base.obj_to_primitive(migrations_obj) objects = [x for x in objects if not x['hidden']] for obj in objects: @@ -38,6 +42,10 @@ def output(migrations_obj): del obj['deleted_at'] del obj['migration_type'] del obj['hidden'] + if 'memory_total' in obj: + for key in detail_keys: + del obj[key] + return objects diff --git a/nova/api/openstack/compute/migrations.py b/nova/api/openstack/compute/migrations.py index 919d0b86e24a..265f23b059cf 100644 --- a/nova/api/openstack/compute/migrations.py +++ b/nova/api/openstack/compute/migrations.py @@ -29,6 +29,10 @@ def output(migrations_obj): From a MigrationsList's object this method returns a list of primitive objects with the only necessary fields. """ + detail_keys = ['memory_total', 'memory_processed', 'memory_remaining', + 'disk_total', 'disk_processed', 'disk_remaining'] + # Note(Shaohe Feng): We need to leverage the oslo.versionedobjects. + # Then we can pass the target version to it's obj_to_primitive. objects = obj_base.obj_to_primitive(migrations_obj) objects = [x for x in objects if not x['hidden']] for obj in objects: @@ -36,6 +40,10 @@ def output(migrations_obj): del obj['deleted_at'] del obj['migration_type'] del obj['hidden'] + if 'memory_total' in obj: + for key in detail_keys: + del obj[key] + return objects diff --git a/nova/db/sqlalchemy/migrate_repo/versions/315_add_migration_progresss_detail.py b/nova/db/sqlalchemy/migrate_repo/versions/315_add_migration_progresss_detail.py new file mode 100644 index 000000000000..3fca95cd6dd4 --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/315_add_migration_progresss_detail.py @@ -0,0 +1,30 @@ +# 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 BigInteger +from sqlalchemy import Column +from sqlalchemy import MetaData +from sqlalchemy import Table + + +def upgrade(migrate_engine): + meta = MetaData(bind=migrate_engine) + migrations = Table('migrations', meta, autoload=True) + shadow_migrations = Table('shadow_migrations', meta, autoload=True) + + columns = ['memory_total', 'memory_processed', 'memory_remaining', + 'disk_total', 'disk_processed', 'disk_remaining'] + for column_name in columns: + column = Column(column_name, BigInteger, nullable=True) + migrations.create_column(column) + shadow_migrations.create_column(column.copy()) diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 81a4b9d66985..d1203f7dd438 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -751,6 +751,12 @@ class Migration(BASE, NovaBase, models.SoftDeleteMixin): 'evacuation'), nullable=True) hidden = Column(Boolean, default=False) + memory_total = Column(BigInteger, nullable=True) + memory_processed = Column(BigInteger, nullable=True) + memory_remaining = Column(BigInteger, nullable=True) + disk_total = Column(BigInteger, nullable=True) + disk_processed = Column(BigInteger, nullable=True) + disk_remaining = Column(BigInteger, nullable=True) instance = orm.relationship("Instance", foreign_keys=instance_uuid, primaryjoin='and_(Migration.instance_uuid == ' diff --git a/nova/objects/migration.py b/nova/objects/migration.py index bf17f14866ee..67b7ae5d6b14 100644 --- a/nova/objects/migration.py +++ b/nova/objects/migration.py @@ -36,7 +36,8 @@ class Migration(base.NovaPersistentObject, base.NovaObject, # Version 1.1: String attributes updated to support unicode # Version 1.2: Added migration_type and hidden # Version 1.3: Added get_by_id_and_instance() - VERSION = '1.3' + # Version 1.4: Added migration progress detail + VERSION = '1.4' fields = { 'id': fields.IntegerField(), @@ -53,6 +54,12 @@ class Migration(base.NovaPersistentObject, base.NovaObject, 'live-migration', 'evacuation'], nullable=False), 'hidden': fields.BooleanField(nullable=False, default=False), + 'memory_total': fields.IntegerField(nullable=True), + 'memory_processed': fields.IntegerField(nullable=True), + 'memory_remaining': fields.IntegerField(nullable=True), + 'disk_total': fields.IntegerField(nullable=True), + 'disk_processed': fields.IntegerField(nullable=True), + 'disk_remaining': fields.IntegerField(nullable=True), } @staticmethod @@ -74,6 +81,14 @@ class Migration(base.NovaPersistentObject, base.NovaObject, if 'migration_type' in primitive: del primitive['migration_type'] del primitive['hidden'] + if target_version < (1, 4): + if 'memory_total' in primitive: + del primitive['memory_total'] + del primitive['memory_processed'] + del primitive['memory_remaining'] + del primitive['disk_total'] + del primitive['disk_processed'] + del primitive['disk_remaining'] def obj_load_attr(self, attrname): if attrname == 'migration_type': diff --git a/nova/tests/unit/api/openstack/compute/test_migrations.py b/nova/tests/unit/api/openstack/compute/test_migrations.py index 9de4e7e38a4d..07f1d92127d8 100644 --- a/nova/tests/unit/api/openstack/compute/test_migrations.py +++ b/nova/tests/unit/api/openstack/compute/test_migrations.py @@ -41,6 +41,12 @@ fake_migrations = [ 'new_instance_type_id': 2, 'migration_type': 'resize', 'hidden': False, + 'memory_total': 123456, + 'memory_processed': 12345, + 'memory_remaining': 120000, + 'disk_total': 234567, + 'disk_processed': 23456, + 'disk_remaining': 230000, 'created_at': datetime.datetime(2012, 10, 29, 13, 42, 2), 'updated_at': datetime.datetime(2012, 10, 29, 13, 42, 2), 'deleted_at': None, @@ -59,6 +65,12 @@ fake_migrations = [ 'new_instance_type_id': 6, 'migration_type': 'resize', 'hidden': False, + 'memory_total': 456789, + 'memory_processed': 56789, + 'memory_remaining': 45000, + 'disk_total': 96789, + 'disk_processed': 6789, + 'disk_remaining': 96000, 'created_at': datetime.datetime(2013, 10, 22, 13, 42, 2), 'updated_at': datetime.datetime(2013, 10, 22, 13, 42, 2), 'deleted_at': None, diff --git a/nova/tests/unit/db/test_migrations.py b/nova/tests/unit/db/test_migrations.py index 543ebc3ec62c..8142db500e6d 100644 --- a/nova/tests/unit/db/test_migrations.py +++ b/nova/tests/unit/db/test_migrations.py @@ -833,6 +833,20 @@ class NovaMigrationsCheckers(test_migrations.ModelsMigrationsSync, 'allocations_resource_provider_class_id_idx', ['resource_provider_id', 'resource_class_id']) + def _check_315(self, engine, data): + self.assertColumnExists(engine, 'migrations', + 'memory_total') + self.assertColumnExists(engine, 'migrations', + 'memory_processed') + self.assertColumnExists(engine, 'migrations', + 'memory_remaining') + self.assertColumnExists(engine, 'migrations', + 'disk_total') + self.assertColumnExists(engine, 'migrations', + 'disk_processed') + self.assertColumnExists(engine, 'migrations', + 'disk_remaining') + class TestNovaMigrationsSQLite(NovaMigrationsCheckers, test_base.DbTestCase, diff --git a/nova/tests/unit/objects/test_migration.py b/nova/tests/unit/objects/test_migration.py index d80265d4b82b..2c3c5ee51efe 100644 --- a/nova/tests/unit/objects/test_migration.py +++ b/nova/tests/unit/objects/test_migration.py @@ -46,6 +46,12 @@ def fake_db_migration(**updates): 'status': 'migrating', 'migration_type': 'resize', 'hidden': False, + 'memory_total': 123456, + 'memory_processed': 12345, + 'memory_remaining': 120000, + 'disk_total': 234567, + 'disk_processed': 23456, + 'disk_remaining': 230000, } if updates: diff --git a/nova/tests/unit/objects/test_objects.py b/nova/tests/unit/objects/test_objects.py index ae664d51cef7..767b7bd0498a 100644 --- a/nova/tests/unit/objects/test_objects.py +++ b/nova/tests/unit/objects/test_objects.py @@ -1147,7 +1147,7 @@ object_data = { 'LibvirtLiveMigrateData': '1.1-4ecf40aae7fee7bb37fc3b2123e760de', 'KeyPair': '1.3-bfaa2a8b148cdf11e0c72435d9dd097a', 'KeyPairList': '1.2-58b94f96e776bedaf1e192ddb2a24c4e', - 'Migration': '1.3-c245057c22d505a4e6462ab95fa27166', + 'Migration': '1.4-17979b9f2ae7f28d97043a220b2a8350', 'MigrationContext': '1.0-d8c2f10069e410f639c49082b5932c92', 'MigrationList': '1.2-02c0ec0c50b75ca86a2a74c5e8c911cc', 'MonitorMetric': '1.1-53b1db7c4ae2c531db79761e7acc52ba',