diff --git a/heat/db/sqlalchemy/migrate_repo/versions/054_stack_tags_table.py b/heat/db/sqlalchemy/migrate_repo/versions/054_stack_tags_table.py new file mode 100644 index 0000000000..654e6372d9 --- /dev/null +++ b/heat/db/sqlalchemy/migrate_repo/versions/054_stack_tags_table.py @@ -0,0 +1,52 @@ +# +# 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 heat.db.sqlalchemy import types as heat_db_types + + +def upgrade(migrate_engine): + meta = sqlalchemy.MetaData(bind=migrate_engine) + + stack = sqlalchemy.Table('stack', meta, autoload=True) + stack.c.tags.drop() + + stack_tag = sqlalchemy.Table( + 'stack_tag', meta, + sqlalchemy.Column('id', + sqlalchemy.Integer, + primary_key=True, + nullable=False), + sqlalchemy.Column('created_at', sqlalchemy.DateTime), + sqlalchemy.Column('updated_at', sqlalchemy.DateTime), + sqlalchemy.Column('tag', sqlalchemy.Unicode(80)), + sqlalchemy.Column('stack_id', + sqlalchemy.String(36), + sqlalchemy.ForeignKey('stack.id'), + nullable=False), + mysql_engine='InnoDB', + mysql_charset='utf8' + ) + stack_tag.create() + + +def downgrade(migrate_engine): + meta = sqlalchemy.MetaData(bind=migrate_engine) + + stack = sqlalchemy.Table('stack', meta, autoload=True) + tags = sqlalchemy.Column('tags', heat_db_types.Json) + tags.create(stack) + + stack_tag = sqlalchemy.Table('stack_tag', meta, autoload=True) + stack_tag.drop() diff --git a/heat/db/sqlalchemy/models.py b/heat/db/sqlalchemy/models.py index 81ee04e2fd..c7bf8d58ae 100644 --- a/heat/db/sqlalchemy/models.py +++ b/heat/db/sqlalchemy/models.py @@ -109,6 +109,22 @@ class RawTemplate(BASE, HeatBase): files = sqlalchemy.Column(types.Json) +class StackTag(BASE, HeatBase): + """Key/value store of arbitrary stack tags.""" + + __tablename__ = 'stack_tag' + + id = sqlalchemy.Column('id', + sqlalchemy.Integer, + primary_key=True, + nullable=False) + tag = sqlalchemy.Column('tag', sqlalchemy.Unicode(80)) + stack_id = sqlalchemy.Column('stack_id', + sqlalchemy.String(36), + sqlalchemy.ForeignKey('stack.id'), + nullable=False) + + class Stack(BASE, HeatBase, SoftDelete, StateAware): """Represents a stack created by the heat engine.""" @@ -139,8 +155,9 @@ class Stack(BASE, HeatBase, SoftDelete, StateAware): nullable=True) backup = sqlalchemy.Column('backup', sqlalchemy.Boolean) nested_depth = sqlalchemy.Column('nested_depth', sqlalchemy.Integer) - tags = sqlalchemy.Column('tags', types.Json) convergence = sqlalchemy.Column('convergence', sqlalchemy.Boolean) + tags = relationship(StackTag, cascade="all,delete", + backref=backref('stack')) # Override timestamp column to store the correct value: it should be the # time the create/update call was issued, not the time the DB entry is