diff options
-rw-r--r-- | nova/console/api.py | 40 | ||||
-rw-r--r-- | nova/console/manager.py | 7 | ||||
-rw-r--r-- | nova/console/vmrc_manager.py | 2 | ||||
-rw-r--r-- | nova/db/api.py | 12 | ||||
-rw-r--r-- | nova/db/sqlalchemy/api.py | 20 | ||||
-rw-r--r-- | nova/db/sqlalchemy/migrate_repo/versions/102_consoles_uses_uuid.py | 80 | ||||
-rw-r--r-- | nova/db/sqlalchemy/migrate_repo/versions/102_sqlite_downgrade.sql | 72 | ||||
-rw-r--r-- | nova/db/sqlalchemy/migrate_repo/versions/102_sqlite_upgrade.sql | 72 | ||||
-rw-r--r-- | nova/db/sqlalchemy/models.py | 2 | ||||
-rw-r--r-- | nova/exception.py | 4 | ||||
-rw-r--r-- | nova/tests/console/test_console.py | 4 |
11 files changed, 270 insertions, 45 deletions
diff --git a/nova/console/api.py b/nova/console/api.py index fa0836d44..46718a49e 100644 --- a/nova/console/api.py +++ b/nova/console/api.py @@ -34,29 +34,29 @@ class API(base.Base): def __init__(self, **kwargs): super(API, self).__init__(**kwargs) - def get_consoles(self, context, instance_id): - instance_id = self._translate_uuid_if_necessary(context, instance_id) - return self.db.console_get_all_by_instance(context, instance_id) + def get_consoles(self, context, instance_uuid): + instance_id = self._translate_uuid_if_necessary(context, instance_uuid) + return self.db.console_get_all_by_instance(context, instance_uuid) - def get_console(self, context, instance_id, console_id): - instance_id = self._translate_uuid_if_necessary(context, instance_id) - return self.db.console_get(context, console_id, instance_id) + def get_console(self, context, instance_id, console_uuid): + instance_id = self._translate_uuid_if_necessary(context, instance_uuid) + return self.db.console_get(context, console_id, instance_uuid) - def delete_console(self, context, instance_id, console_id): - instance_id = self._translate_uuid_if_necessary(context, instance_id) - console = self.db.console_get(context, console_id, instance_id) + def delete_console(self, context, instance_id, console_uuid): + instance_id = self._translate_uuid_if_necessary(context, instance_uuid) + console = self.db.console_get(context, console_id, instance_uuid) topic = rpc.queue_get_for(context, FLAGS.console_topic, pool['host']) rpcapi = console_rpcapi.ConsoleAPI(topic=topic) rpcapi.remove_console(context, console['id']) - def create_console(self, context, instance_id): + def create_console(self, context, instance_uuid): #NOTE(mdragon): If we wanted to return this the console info # here, as we would need to do a call. # They can just do an index later to fetch # console info. I am not sure which is better # here. - instance = self._get_instance(context, instance_id) + instance = self._get_instance(context, instance_uuid) topic = self._get_console_topic(context, instance['host']), rpcapi = console_rpcapi.ConsoleAPI(topic=topic) rpcapi.add_console(context, instance['id']) @@ -65,15 +65,15 @@ class API(base.Base): rpcapi = compute_rpcapi.ComputeAPI() return rpcapi.get_console_topic(context, instance_host) - def _translate_uuid_if_necessary(self, context, instance_id): - if utils.is_uuid_like(instance_id): - instance = self.db.instance_get_by_uuid(context, instance_id) - instance_id = instance['id'] - return instance_id + def _translate_id_if_necessary(self, context, instance_uuid): + if not utils.is_uuid_like(instance_uuid): + instance = self.db.instance_get(context, instance_uuid) + instance_uuid = instance['uuid'] + return instance_uuid - def _get_instance(self, context, instance_id): - if utils.is_uuid_like(instance_id): - instance = self.db.instance_get_by_uuid(context, instance_id) + def _get_instance(self, context, instance_uuid): + if utils.is_uuid_like(instance_uuid): + instance = self.db.instance_get_by_uuid(context, instance_uuid) else: - instance = self.db.instance_get(context, instance_id) + instance = self.db.instance_get(context, instance_uuid) return instance diff --git a/nova/console/manager.py b/nova/console/manager.py index cc2c71d41..bc5894290 100644 --- a/nova/console/manager.py +++ b/nova/console/manager.py @@ -75,8 +75,8 @@ class ConsoleProxyManager(manager.Manager): pool = self.get_pool_for_instance_host(context, host) try: console = self.db.console_get_by_pool_instance(context, - pool['id'], - instance_id) + pool['id'], + instance['uuid']) except exception.NotFound: LOG.debug(_('Adding console'), instance=instance) if not password: @@ -84,13 +84,14 @@ class ConsoleProxyManager(manager.Manager): if not port: port = self.driver.get_port(context) console_data = {'instance_name': name, - 'instance_id': instance_id, + 'instance_uuid': instance['uuid'], 'password': password, 'pool_id': pool['id']} if port: console_data['port'] = port console = self.db.console_create(context, console_data) self.driver.setup_console(context, console) + return console['id'] @exception.wrap_exception() diff --git a/nova/console/vmrc_manager.py b/nova/console/vmrc_manager.py index 996ed2afd..cb6fd51ad 100644 --- a/nova/console/vmrc_manager.py +++ b/nova/console/vmrc_manager.py @@ -99,7 +99,7 @@ class ConsoleVMRCManager(manager.Manager): try: console = self.db.console_get_by_pool_instance(context, pool['id'], - instance_id) + instance['uuid']) if self.driver.is_otp(): console = self._generate_console(context, pool, diff --git a/nova/db/api.py b/nova/db/api.py index 93f2b060b..a5adfbc75 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -1505,19 +1505,19 @@ def console_delete(context, console_id): return IMPL.console_delete(context, console_id) -def console_get_by_pool_instance(context, pool_id, instance_id): +def console_get_by_pool_instance(context, pool_id, instance_uuid): """Get console entry for a given instance and pool.""" - return IMPL.console_get_by_pool_instance(context, pool_id, instance_id) + return IMPL.console_get_by_pool_instance(context, pool_id, instance_uuid) -def console_get_all_by_instance(context, instance_id): +def console_get_all_by_instance(context, instance_uuid): """Get consoles for a given instance.""" - return IMPL.console_get_all_by_instance(context, instance_id) + return IMPL.console_get_all_by_instance(context, instance_uuid) -def console_get(context, console_id, instance_id=None): +def console_get(context, console_id, instance_uuid=None): """Get a specific console (possibly on a given instance).""" - return IMPL.console_get(context, console_id, instance_id) + return IMPL.console_get(context, console_id, instance_uuid) ################## diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index f7a6b59a6..ec6606908 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -3894,40 +3894,40 @@ def console_delete(context, console_id): delete() -def console_get_by_pool_instance(context, pool_id, instance_id): +def console_get_by_pool_instance(context, pool_id, instance_uuid): result = model_query(context, models.Console, read_deleted="yes").\ filter_by(pool_id=pool_id).\ - filter_by(instance_id=instance_id).\ + filter_by(instance_uuid=instance_uuid).\ options(joinedload('pool')).\ first() if not result: raise exception.ConsoleNotFoundInPoolForInstance( - pool_id=pool_id, instance_id=instance_id) + pool_id=pool_id, instance_uuid=instance_uuid) return result -def console_get_all_by_instance(context, instance_id): +def console_get_all_by_instance(context, instance_uuid): return model_query(context, models.Console, read_deleted="yes").\ - filter_by(instance_id=instance_id).\ + filter_by(instance_uuid=instance_uuid).\ all() -def console_get(context, console_id, instance_id=None): +def console_get(context, console_id, instance_uuid=None): query = model_query(context, models.Console, read_deleted="yes").\ filter_by(id=console_id).\ options(joinedload('pool')) - if instance_id is not None: - query = query.filter_by(instance_id=instance_id) + if instance_uuid is not None: + query = query.filter_by(instance_uuid=instance_uuid) result = query.first() if not result: - if instance_id: + if instance_uuid: raise exception.ConsoleNotFoundForInstance( - console_id=console_id, instance_id=instance_id) + console_id=console_id, instance_uuid=instance_uuid) else: raise exception.ConsoleNotFound(console_id=console_id) diff --git a/nova/db/sqlalchemy/migrate_repo/versions/102_consoles_uses_uuid.py b/nova/db/sqlalchemy/migrate_repo/versions/102_consoles_uses_uuid.py new file mode 100644 index 000000000..1f0989c8f --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/102_consoles_uses_uuid.py @@ -0,0 +1,80 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 OpenStack LLC. +# Copyright 2012 Michael Still and Canonical 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. + +from sqlalchemy import select, Column, ForeignKey, Integer +from sqlalchemy import MetaData, String, Table +from migrate import ForeignKeyConstraint + +from nova import log as logging + + +LOG = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + consoles = Table('consoles', meta, autoload=True) + instances = Table('instances', meta, autoload=True) + uuid_column = Column('instance_uuid', String(36)) + uuid_column.create(consoles) + + try: + consoles.update().values( + instance_uuid=select( + [instances.c.uuid], + instances.c.id == consoles.c.instance_id) + ).execute() + except Exception: + uuid_column.drop() + raise + + fkeys = list(consoles.c.instance_id.foreign_keys) + if fkeys: + try: + fkey_name = fkeys[0].constraint.name + ForeignKeyConstraint( + columns=[consoles.c.instance_id], + refcolumns=[instances.c.id], + name=fkey_name).drop() + except Exception: + LOG.error(_("foreign key constraint couldn't be removed")) + raise + + consoles.c.instance_id.drop() + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + consoles = Table('consoles', meta, autoload=True) + instances = Table('instances', meta, autoload=True) + id_column = Column('instance_id', Integer, ForeignKey('instances.id')) + id_column.create(consoles) + + try: + consoles.update().values( + instance_id=select( + [instances.c.id], + instances.c.uuid == consoles.c.instance_uuid) + ).execute() + except Exception: + id_column.drop() + raise + + consoles.c.instance_uuid.drop() diff --git a/nova/db/sqlalchemy/migrate_repo/versions/102_sqlite_downgrade.sql b/nova/db/sqlalchemy/migrate_repo/versions/102_sqlite_downgrade.sql new file mode 100644 index 000000000..8a0b4938e --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/102_sqlite_downgrade.sql @@ -0,0 +1,72 @@ +BEGIN TRANSACTION; + CREATE TEMPORARY TABLE consoles_backup ( + created_at DATETIME, + updated_at DATETIME, + deleted_at DATETIME, + deleted BOOLEAN, + id INTEGER NOT NULL, + instance_name VARCHAR(255), + instance_id INTEGER NOT NULL, + instance_uuid VARCHAR(36), + password VARCHAR(255), + port INTEGER, + pool_id INTEGER, + PRIMARY KEY (id) + ); + + INSERT INTO consoles_backup + SELECT created_at, + updated_at, + deleted_at, + deleted, + id, + instance_name, + NULL, + instance_uuid, + password, + port, + pool_id + FROM consoles; + + UPDATE consoles_backup + SET instance_uuid= + (SELECT id + FROM instances + WHERE consoles_backup.instance_uuid = instances.uuid + ); + + DROP TABLE consoles; + + CREATE TABLE consoles ( + created_at DATETIME, + updated_at DATETIME, + deleted_at DATETIME, + deleted BOOLEAN, + id INTEGER NOT NULL, + instance_name VARCHAR(255), + instance_id INTEGER NOT NULL, + password VARCHAR(255), + port INTEGER, + pool_id INTEGER, + PRIMARY KEY (id), + FOREIGN KEY(instance_id) REFERENCES instances (id) + ); + + CREATE INDEX consoles_pool_id ON consoles(pool_id); + + INSERT INTO consoles + SELECT created_at, + updated_at, + deleted_at, + deleted, + id, + instance_name, + instance_id, + password, + port, + pool_id + FROM consoles_backup; + + DROP TABLE consoles_backup; + +COMMIT;
\ No newline at end of file diff --git a/nova/db/sqlalchemy/migrate_repo/versions/102_sqlite_upgrade.sql b/nova/db/sqlalchemy/migrate_repo/versions/102_sqlite_upgrade.sql new file mode 100644 index 000000000..3e2db86a9 --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/102_sqlite_upgrade.sql @@ -0,0 +1,72 @@ +BEGIN TRANSACTION; + CREATE TEMPORARY TABLE consoles_backup ( + created_at DATETIME, + updated_at DATETIME, + deleted_at DATETIME, + deleted BOOLEAN, + id INTEGER NOT NULL, + instance_name VARCHAR(255), + instance_id INTEGER NOT NULL, + instance_uuid VARCHAR(36), + password VARCHAR(255), + port INTEGER, + pool_id INTEGER, + PRIMARY KEY (id) + ); + + INSERT INTO consoles_backup + SELECT created_at, + updated_at, + deleted_at, + deleted, + id, + instance_name, + instance_id, + NULL, + password, + port, + pool_id + FROM consoles; + + UPDATE consoles_backup + SET instance_uuid= + (SELECT uuid + FROM instances + WHERE consoles_backup.instance_id = instances.id + ); + + DROP TABLE consoles; + + CREATE TABLE consoles ( + created_at DATETIME, + updated_at DATETIME, + deleted_at DATETIME, + deleted BOOLEAN, + id INTEGER NOT NULL, + instance_name VARCHAR(255), + instance_uuid VARCHAR(36), + password VARCHAR(255), + port INTEGER, + pool_id INTEGER, + PRIMARY KEY (id), + FOREIGN KEY(instance_uuid) REFERENCES instances (uuid) + ); + + CREATE INDEX consoles_pool_id ON consoles(pool_id); + + INSERT INTO consoles + SELECT created_at, + updated_at, + deleted_at, + deleted, + id, + instance_name, + instance_uuid, + password, + port, + pool_id + FROM consoles_backup; + + DROP TABLE consoles_backup; + +COMMIT; diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 2576b237c..0a3f07b9a 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -846,7 +846,7 @@ class Console(BASE, NovaBase): __tablename__ = 'consoles' id = Column(Integer, primary_key=True) instance_name = Column(String(255)) - instance_id = Column(Integer) + instance_uuid = Column(String(36)) password = Column(String(255)) port = Column(Integer, nullable=True) pool_id = Column(Integer, ForeignKey('console_pools.id')) diff --git a/nova/exception.py b/nova/exception.py index bf9318fd2..5904a0014 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -774,11 +774,11 @@ class ConsoleNotFound(NotFound): class ConsoleNotFoundForInstance(ConsoleNotFound): - message = _("Console for instance %(instance_id)s could not be found.") + message = _("Console for instance %(instance_uuid)s could not be found.") class ConsoleNotFoundInPoolForInstance(ConsoleNotFound): - message = _("Console for instance %(instance_id)s " + message = _("Console for instance %(instance_uuid)s " "in pool %(pool_id)s could not be found.") diff --git a/nova/tests/console/test_console.py b/nova/tests/console/test_console.py index 626cf2206..986ffeb2e 100644 --- a/nova/tests/console/test_console.py +++ b/nova/tests/console/test_console.py @@ -95,8 +95,8 @@ class ConsoleTestCase(test.TestCase): instance['host'], self.console.host, self.console.driver.console_type) - console_instances = [con['instance_id'] for con in pool.consoles] - self.assert_(instance_id in console_instances) + console_instances = [con['instance_uuid'] for con in pool.consoles] + self.assert_(instance['uuid'] in console_instances) db.instance_destroy(self.context, instance_id) def test_add_console_does_not_duplicate(self): |