From 718fca9de44aa06ede8d91a9df667c82e7be81d0 Mon Sep 17 00:00:00 2001 From: Paul Murray Date: Fri, 20 May 2016 14:08:02 +0100 Subject: [PATCH] Add console auth tokens table and model Console auth tokens will be saved in the database instead of in memory in a console auth server. Adding the table and models is the first step to do this. Co-Authored-By: Eli Qiao Change-Id: I42c25b465efb7e03769c9557f66feaa92cfa207c partially-implements: blueprint convert-consoles-to-objects --- nova/db/sqlalchemy/api.py | 2 + .../333_add_console_auth_tokens_table.py | 50 +++++++++++++++++++ nova/db/sqlalchemy/models.py | 29 +++++++++++ nova/tests/unit/db/test_db_api.py | 4 +- nova/tests/unit/db/test_migrations.py | 21 ++++++++ 5 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 nova/db/sqlalchemy/migrate_repo/versions/333_add_console_auth_tokens_table.py diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 35f2d214dd10..5ade9974d3d6 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -1801,6 +1801,8 @@ def instance_destroy(context, instance_uuid, constraint=None): # column 'deleted' in 'tags' table. context.session.query(models.Tag).filter_by( resource_id=instance_uuid).delete() + context.session.query(models.ConsoleAuthToken).filter_by( + instance_uuid=instance_uuid).delete() return instance_ref diff --git a/nova/db/sqlalchemy/migrate_repo/versions/333_add_console_auth_tokens_table.py b/nova/db/sqlalchemy/migrate_repo/versions/333_add_console_auth_tokens_table.py new file mode 100644 index 000000000000..027cd75cc25c --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/333_add_console_auth_tokens_table.py @@ -0,0 +1,50 @@ +# Copyright 2016 Intel Corporation +# Copyright 2016 Hewlett Packard Enterprise Development Company LP +# +# 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 migrate import UniqueConstraint +from sqlalchemy import Column +from sqlalchemy import DateTime +from sqlalchemy import Index +from sqlalchemy import Integer +from sqlalchemy import MetaData +from sqlalchemy import String +from sqlalchemy import Table + + +def upgrade(migrate_engine): + + meta = MetaData() + meta.bind = migrate_engine + auth_tokens = Table('console_auth_tokens', meta, + Column('created_at', DateTime), + Column('updated_at', DateTime), + Column('id', Integer, primary_key=True, nullable=False), + Column('token_hash', String(255), nullable=False), + Column('console_type', String(255), nullable=False), + Column('host', String(255), nullable=False), + Column('port', Integer, nullable=False), + Column('internal_access_path', String(255)), + Column('instance_uuid', String(36), nullable=False), + Column('expires', Integer, nullable=False), + Index('console_auth_tokens_instance_uuid_idx', 'instance_uuid'), + Index('console_auth_tokens_host_expires_idx', 'host', 'expires'), + Index('console_auth_tokens_token_hash_idx', 'token_hash'), + UniqueConstraint('token_hash', + name='uniq_console_auth_tokens0token_hash'), + mysql_engine='InnoDB', + mysql_charset='utf8' + ) + + auth_tokens.create(checkfirst=True) diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index cf8d7b7da662..f954e64fe9b5 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -1530,3 +1530,32 @@ class ResourceProviderAggregate(BASE, models.ModelBase): resource_provider_id = Column(Integer, primary_key=True, nullable=False) aggregate_id = Column(Integer, primary_key=True, nullable=False) + + +class ConsoleAuthToken(BASE, NovaBase): + """Represents a console auth token""" + + __tablename__ = 'console_auth_tokens' + __table_args__ = ( + Index('console_auth_tokens_instance_uuid_idx', 'instance_uuid'), + Index('console_auth_tokens_host_expires_idx', 'host', 'expires'), + Index('console_auth_tokens_token_hash_idx', 'token_hash'), + schema.UniqueConstraint("token_hash", + name="uniq_console_auth_tokens0token_hash") + ) + id = Column(Integer, primary_key=True, nullable=False) + token_hash = Column(String(255), nullable=False) + console_type = Column(String(255), nullable=False) + host = Column(String(255), nullable=False) + port = Column(Integer, nullable=False) + internal_access_path = Column(String(255)) + instance_uuid = Column(String(36), nullable=False) + expires = Column(Integer, nullable=False) + + instance = orm.relationship( + "Instance", + backref='console_auth_tokens', + primaryjoin='and_(ConsoleAuthToken.instance_uuid == Instance.uuid,' + 'Instance.deleted == 0)', + foreign_keys=instance_uuid + ) diff --git a/nova/tests/unit/db/test_db_api.py b/nova/tests/unit/db/test_db_api.py index d5aae57aba34..f238e9cb8d1c 100644 --- a/nova/tests/unit/db/test_db_api.py +++ b/nova/tests/unit/db/test_db_api.py @@ -8564,8 +8564,10 @@ class ArchiveTestCase(test.TestCase, ModelsObjectComparatorMixin): # ('resource_providers', 'allocations' and 'inventories') # with no shadow table and it's OK, so skip. # 318 adds one more: 'resource_provider_aggregates'. + # NOTE(PaulMurray): migration 333 adds 'console_auth_tokens' if table_name in ['tags', 'resource_providers', 'allocations', - 'inventories', 'resource_provider_aggregates']: + 'inventories', 'resource_provider_aggregates', + 'console_auth_tokens']: continue if table_name.startswith("shadow_"): diff --git a/nova/tests/unit/db/test_migrations.py b/nova/tests/unit/db/test_migrations.py index 602e6832b22a..6d2bbda92401 100644 --- a/nova/tests/unit/db/test_migrations.py +++ b/nova/tests/unit/db/test_migrations.py @@ -890,6 +890,27 @@ class NovaMigrationsCheckers(test_migrations.ModelsMigrationsSync, def _check_332(self, engine, data): self.assertColumnExists(engine, 'instance_extra', 'keypairs') + def _check_333(self, engine, data): + self.assertColumnExists(engine, 'console_auth_tokens', 'id') + self.assertColumnExists(engine, 'console_auth_tokens', 'token_hash') + self.assertColumnExists(engine, 'console_auth_tokens', 'console_type') + self.assertColumnExists(engine, 'console_auth_tokens', 'host') + self.assertColumnExists(engine, 'console_auth_tokens', 'port') + self.assertColumnExists(engine, 'console_auth_tokens', + 'internal_access_path') + self.assertColumnExists(engine, 'console_auth_tokens', + 'instance_uuid') + self.assertColumnExists(engine, 'console_auth_tokens', 'expires') + self.assertIndexMembers(engine, 'console_auth_tokens', + 'console_auth_tokens_instance_uuid_idx', + ['instance_uuid']) + self.assertIndexMembers(engine, 'console_auth_tokens', + 'console_auth_tokens_host_expires_idx', + ['host', 'expires']) + self.assertIndexMembers(engine, 'console_auth_tokens', + 'console_auth_tokens_token_hash_idx', + ['token_hash']) + class TestNovaMigrationsSQLite(NovaMigrationsCheckers, test_base.DbTestCase,