From a4223f1d89ea7033cbae35790a0411ec439cdb6d Mon Sep 17 00:00:00 2001 From: Johannes Erdfelt Date: Fri, 6 Jan 2012 12:57:37 -0800 Subject: KVM and XEN Disk Management Parity Implements blueprint disk-configuration-parity This change splits local_gb into root_gb and ephemeral_gb. libvirt interpreted local_gb as what ephemeral_gb is now, whereas XenAPI interpreted local_gb as what root_gb is now. Change-Id: I496600991bac1e990326d4ded1607fee08209d68 --- nova/db/sqlalchemy/api.py | 4 +- .../versions/074_change_flavor_local_gb.py | 130 +++++++++ .../migrate_repo/versions/074_sqlite_upgrade.sql | 313 +++++++++++++++++++++ nova/db/sqlalchemy/models.py | 8 +- 4 files changed, 450 insertions(+), 5 deletions(-) create mode 100644 nova/db/sqlalchemy/migrate_repo/versions/074_change_flavor_local_gb.py create mode 100644 nova/db/sqlalchemy/migrate_repo/versions/074_sqlite_upgrade.sql (limited to 'nova/db') diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index b59e50544..794861b11 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -3380,9 +3380,9 @@ def instance_type_get_all(context, inactive=False, filters=None): if 'min_memory_mb' in filters: query = query.filter( models.InstanceTypes.memory_mb >= filters['min_memory_mb']) - if 'min_local_gb' in filters: + if 'min_root_gb' in filters: query = query.filter( - models.InstanceTypes.local_gb >= filters['min_local_gb']) + models.InstanceTypes.root_gb >= filters['min_root_gb']) inst_types = query.order_by("name").all() diff --git a/nova/db/sqlalchemy/migrate_repo/versions/074_change_flavor_local_gb.py b/nova/db/sqlalchemy/migrate_repo/versions/074_change_flavor_local_gb.py new file mode 100644 index 000000000..ef7e3293a --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/074_change_flavor_local_gb.py @@ -0,0 +1,130 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 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. + +import sqlalchemy +from sqlalchemy import select, Column, Integer + +from nova import exception +from nova import flags +from nova import log as logging + + +LOG = logging.getLogger('nova.db.sqlalchemy.migrate_repo.versions') + +FLAGS = flags.FLAGS + +meta = sqlalchemy.MetaData() + + +def _get_table(name): + return sqlalchemy.Table(name, meta, autoload=True) + + +def upgrade_libvirt(instances, instance_types): + # Update instance_types first + tiny = None + for inst_type in instance_types.select().execute(): + if inst_type['name'] == 'm1.tiny': + tiny = inst_type['id'] + root_gb = 0 + else: + root_gb = 10 + + instance_types.update()\ + .values(root_gb=root_gb, + ephemeral_gb=inst_type['local_gb'])\ + .where(instance_types.c.id == inst_type['id'])\ + .execute() + + # then update instances following same pattern + instances.update()\ + .values(root_gb=10, + ephemeral_gb=instances.c.local_gb)\ + .execute() + + if tiny is not None: + instances.update()\ + .values(root_gb=0, + ephemeral_gb=instances.c.local_gb)\ + .where(instances.c.instance_type_id == tiny)\ + .execute() + + +def upgrade_other(instances, instance_types): + for table in (instances, instance_types): + table.update().values(root_gb=table.c.local_gb, + ephemeral_gb=0).execute() + + +def upgrade(migrate_engine): + if not FLAGS.connection_type: + raise exception.Error("Need connection_type specified to run " + "migration") + + meta.bind = migrate_engine + instances = _get_table('instances') + instance_types = _get_table('instance_types') + + for table in (instances, instance_types): + root_gb = Column('root_gb', Integer) + root_gb.create(table) + ephemeral_gb = Column('ephemeral_gb', Integer) + ephemeral_gb.create(table) + + # Since this migration is part of the work to get all drivers + # working the same way, we need to treat the new root_gb and + # ephemeral_gb columns differently depending on what the + # driver implementation used to behave like. + if FLAGS.connection_type == 'libvirt': + upgrade_libvirt(instances, instance_types) + else: + upgrade_other(instances, instance_types) + + default_local_device = instances.c.default_local_device + default_local_device.alter(name='default_ephemeral_device') + + for table in (instances, instance_types): + table.drop_column('local_gb') + + +def downgrade(migrate_engine): + meta.bind = migrate_engine + instances = _get_table('instances') + instance_types = _get_table('instance_types') + + for table in (instances, instance_types): + local_gb = Column('root_gb', Integer) + local_gb.create(table) + + try: + for table in (instances, instance_types): + if FLAGS.connection_type == 'libvirt': + column = table.c.ephemeral_gb + else: + column = table.c.root_gb + table.update().values(local_gb=column).execute() + except Exception: + for table in (instances, instance_types): + table.drop_column('local_gb') + raise + + default_ephemeral_device = instances.c.default_ephemeral_device + default_ephemeral_device.alter(name='default_local_device') + + for table in (instances, instance_types): + table.drop_column('root_gb') + table.drop_column('ephemeral_gb') diff --git a/nova/db/sqlalchemy/migrate_repo/versions/074_sqlite_upgrade.sql b/nova/db/sqlalchemy/migrate_repo/versions/074_sqlite_upgrade.sql new file mode 100644 index 000000000..e2708111b --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/074_sqlite_upgrade.sql @@ -0,0 +1,313 @@ +-- sqlalchemy-migrate is surprisingly broken when it comes to migrations +-- for sqlite. As a result, we have to do much of the work manually here + +BEGIN TRANSACTION; + -- make backup of instance_types + CREATE TEMPORARY TABLE instance_types_backup ( + created_at DATETIME, + updated_at DATETIME, + deleted_at DATETIME, + deleted BOOLEAN, + name VARCHAR(255), + id INTEGER NOT NULL, + memory_mb INTEGER NOT NULL, + vcpus INTEGER NOT NULL, + local_gb INTEGER NOT NULL, + swap INTEGER NOT NULL, + rxtx_factor FLOAT, + vcpu_weight INTEGER, + flavorid VARCHAR(255), + PRIMARY KEY (id), + UNIQUE (flavorid), + CHECK (deleted IN (0, 1)), + UNIQUE (name) + ); + + INSERT INTO instance_types_backup + SELECT created_at, + updated_at, + deleted_at, + deleted, + name, + id, + memory_mb, + vcpus, + local_gb, + swap, + rxtx_factor, + vcpu_weight, + flavorid + FROM instance_types; + + DROP TABLE instance_types; + + CREATE TABLE instance_types ( + created_at DATETIME, + updated_at DATETIME, + deleted_at DATETIME, + deleted BOOLEAN, + name VARCHAR(255), + id INTEGER NOT NULL, + memory_mb INTEGER NOT NULL, + vcpus INTEGER NOT NULL, + root_gb INTEGER NOT NULL, + ephemeral_gb INTEGER NOT NULL, + swap INTEGER NOT NULL, + rxtx_factor FLOAT, + vcpu_weight INTEGER, + flavorid VARCHAR(255), + PRIMARY KEY (id), + UNIQUE (flavorid), + CHECK (deleted IN (0, 1)), + UNIQUE (name) + ); + + -- copy from backup to new table with root_gb set to local_gb and + -- ephmeral_gb set to 0 + INSERT INTO instance_types + SELECT created_at, + updated_at, + deleted_at, + deleted, + name, + id, + memory_mb, + vcpus, + local_gb, + 0, + swap, + rxtx_factor, + vcpu_weight, + flavorid + FROM instance_types_backup; + + DROP TABLE instance_types_backup; + + -- make backup of instances + CREATE TEMPORARY TABLE instances_backup ( + created_at DATETIME, + updated_at DATETIME, + deleted_at DATETIME, + deleted BOOLEAN, + id INTEGER NOT NULL, + internal_id INTEGER, + user_id VARCHAR(255), + project_id VARCHAR(255), + image_ref VARCHAR(255), + kernel_id VARCHAR(255), + ramdisk_id VARCHAR(255), + server_name VARCHAR(255), + launch_index INTEGER, + key_name VARCHAR(255), + key_data TEXT, + power_state INTEGER, + vm_state VARCHAR(255), + memory_mb INTEGER, + vcpus INTEGER, + local_gb INTEGER, + hostname VARCHAR(255), + host VARCHAR(255), + user_data TEXT, + reservation_id VARCHAR(255), + scheduled_at DATETIME, + launched_at DATETIME, + terminated_at DATETIME, + display_name VARCHAR(255), + display_description VARCHAR(255), + availability_zone VARCHAR(255), + locked BOOLEAN, + os_type VARCHAR(255), + launched_on TEXT, + instance_type_id INTEGER, + vm_mode VARCHAR(255), + uuid VARCHAR(36), + architecture VARCHAR(255), + root_device_name VARCHAR(255), + access_ip_v4 VARCHAR(255), + access_ip_v6 VARCHAR(255), + config_drive VARCHAR(255), + task_state VARCHAR(255), + default_local_device VARCHAR(255), + default_swap_device VARCHAR(255), + progress INTEGER, + auto_disk_config BOOLEAN, + shutdown_terminate BOOLEAN, + disable_terminate BOOLEAN, + PRIMARY KEY (id), + CHECK (deleted IN (0, 1)), + CHECK (locked IN (0, 1)), + CHECK (auto_disk_config IN (0, 1)), + CHECK (shutdown_terminate IN (0, 1)), + CHECK (disable_terminate IN (0, 1)) + ); + + INSERT INTO instances_backup + SELECT created_at, + updated_at, + deleted_at, + deleted, + id, + internal_id, + user_id, + project_id, + image_ref, + kernel_id, + ramdisk_id, + server_name, + launch_index, + key_name, + key_data, + power_state, + vm_state, + memory_mb, + vcpus, + local_gb, + hostname, + host, + user_data, + reservation_id, + scheduled_at, + launched_at, + terminated_at, + display_name, + display_description, + availability_zone, + locked, + os_type, + launched_on, + instance_type_id, + vm_mode, + uuid, + architecture, + root_device_name, + access_ip_v4, + access_ip_v6, + config_drive, + task_state, + default_local_device, + default_swap_device, + progress, + auto_disk_config, + shutdown_terminate, + disable_terminate + FROM instances; + + DROP TABLE instances; + + CREATE TABLE instances ( + created_at DATETIME, + updated_at DATETIME, + deleted_at DATETIME, + deleted BOOLEAN, + id INTEGER NOT NULL, + internal_id INTEGER, + user_id VARCHAR(255), + project_id VARCHAR(255), + image_ref VARCHAR(255), + kernel_id VARCHAR(255), + ramdisk_id VARCHAR(255), + server_name VARCHAR(255), + launch_index INTEGER, + key_name VARCHAR(255), + key_data TEXT, + power_state INTEGER, + vm_state VARCHAR(255), + memory_mb INTEGER, + vcpus INTEGER, + root_gb INTEGER, + ephemeral_gb INTEGER, + hostname VARCHAR(255), + host VARCHAR(255), + user_data TEXT, + reservation_id VARCHAR(255), + scheduled_at DATETIME, + launched_at DATETIME, + terminated_at DATETIME, + display_name VARCHAR(255), + display_description VARCHAR(255), + availability_zone VARCHAR(255), + locked BOOLEAN, + os_type VARCHAR(255), + launched_on TEXT, + instance_type_id INTEGER, + vm_mode VARCHAR(255), + uuid VARCHAR(36), + architecture VARCHAR(255), + root_device_name VARCHAR(255), + access_ip_v4 VARCHAR(255), + access_ip_v6 VARCHAR(255), + config_drive VARCHAR(255), + task_state VARCHAR(255), + default_ephemeral_device VARCHAR(255), + default_swap_device VARCHAR(255), + progress INTEGER, + auto_disk_config BOOLEAN, + shutdown_terminate BOOLEAN, + disable_terminate BOOLEAN, + PRIMARY KEY (id), + CHECK (deleted IN (0, 1)), + CHECK (locked IN (0, 1)), + CHECK (auto_disk_config IN (0, 1)), + CHECK (shutdown_terminate IN (0, 1)), + CHECK (disable_terminate IN (0, 1)) + ); + + CREATE INDEX project_id ON instances (project_id); + CREATE UNIQUE INDEX uuid ON instances (uuid); + + -- copy from backup to new table with root_gb set to local_gb and + -- ephmeral_gb set to 0 + INSERT INTO instances + SELECT created_at, + updated_at, + deleted_at, + deleted, + id, + internal_id, + user_id, + project_id, + image_ref, + kernel_id, + ramdisk_id, + server_name, + launch_index, + key_name, + key_data, + power_state, + vm_state, + memory_mb, + vcpus, + local_gb, + 0, + hostname, + host, + user_data, + reservation_id, + scheduled_at, + launched_at, + terminated_at, + display_name, + display_description, + availability_zone, + locked, + os_type, + launched_on, + instance_type_id, + vm_mode, + uuid, + architecture, + root_device_name, + access_ip_v4, + access_ip_v6, + config_drive, + task_state, + default_local_device, + default_swap_device, + progress, + auto_disk_config, + shutdown_terminate, + disable_terminate + FROM instances_backup; + + DROP TABLE instances_backup; +COMMIT; diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 2dfc798b6..f7b9a555c 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -223,7 +223,8 @@ class Instance(BASE, NovaBase): memory_mb = Column(Integer) vcpus = Column(Integer) - local_gb = Column(Integer) + root_gb = Column(Integer) + ephemeral_gb = Column(Integer) hostname = Column(String(255)) host = Column(String(255)) # , ForeignKey('hosts.id')) @@ -256,7 +257,7 @@ class Instance(BASE, NovaBase): uuid = Column(String(36)) root_device_name = Column(String(255)) - default_local_device = Column(String(255), nullable=True) + default_ephemeral_device = Column(String(255), nullable=True) default_swap_device = Column(String(255), nullable=True) config_drive = Column(String(255)) @@ -339,7 +340,8 @@ class InstanceTypes(BASE, NovaBase): name = Column(String(255), unique=True) memory_mb = Column(Integer) vcpus = Column(Integer) - local_gb = Column(Integer) + root_gb = Column(Integer) + ephemeral_gb = Column(Integer) flavorid = Column(String(255), unique=True) swap = Column(Integer, nullable=False, default=0) rxtx_factor = Column(Float, nullable=False, default=1) -- cgit