Skip to content

Commit

Permalink
Rename DB columns: tenant -> project
Browse files Browse the repository at this point in the history
All occurences of ``tenant_id`` across the neutron database are
being renamed to ``project_id``.

This neutron-fwaas change accompanies the neutron change:
I87a8ef342ccea004731ba0192b23a8e79bc382dc

Partially-Implements: blueprint keystone-v3

Change-Id: I984502745629280c033e52f0f1c06fc268fa0255
  • Loading branch information
HenryGessau committed Jul 14, 2016
1 parent 050b9e0 commit c3e491c
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 6 deletions.
31 changes: 28 additions & 3 deletions neutron_fwaas/db/firewall/firewall_db.py
Expand Up @@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.

from neutron.api.v2 import attributes as attr
from neutron.callbacks import events
from neutron.callbacks import registry
from neutron.callbacks import resources
Expand All @@ -27,6 +28,7 @@
from oslo_log import log as logging
from oslo_utils import uuidutils
import sqlalchemy as sa
from sqlalchemy.ext import declarative
from sqlalchemy.ext.orderinglist import ordering_list
from sqlalchemy import orm
from sqlalchemy.orm import exc
Expand All @@ -39,7 +41,30 @@
LOG = logging.getLogger(__name__)


class FirewallRule(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
class HasTenant(object):
# NOTE(HenryG): Temporary solution!
# Remove when I87a8ef342ccea004731ba0192b23a8e79bc382dc is merged.

project_id = sa.Column(sa.String(attr.TENANT_ID_MAX_LEN), index=True)

def __init__(self, *args, **kwargs):
# NOTE(HenryG): debtcollector requires init in class
super(HasTenant, self).__init__(*args, **kwargs)

def get_tenant_id(self):
return self.project_id

def set_tenant_id(self, value):
self.project_id = value

@declarative.declared_attr
def tenant_id(cls):
return orm.synonym(
'project_id',
descriptor=property(cls.get_tenant_id, cls.set_tenant_id))


class FirewallRule(model_base.BASEV2, models_v2.HasId, HasTenant):
"""Represents a Firewall rule."""
__tablename__ = 'firewall_rules'
__table_args__ = ({'mysql_collate': 'utf8_bin'})
Expand All @@ -63,7 +88,7 @@ class FirewallRule(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
position = sa.Column(sa.Integer)


class Firewall(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
class Firewall(model_base.BASEV2, models_v2.HasId, HasTenant):
"""Represents a Firewall resource."""
__tablename__ = 'firewalls'
__table_args__ = ({'mysql_collate': 'utf8_bin'})
Expand All @@ -77,7 +102,7 @@ class Firewall(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
nullable=True)


class FirewallPolicy(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
class FirewallPolicy(model_base.BASEV2, models_v2.HasId, HasTenant):
"""Represents a Firewall Policy resource."""
__tablename__ = 'firewall_policies'
__table_args__ = ({'mysql_collate': 'utf8_bin'})
Expand Down
Expand Up @@ -26,6 +26,7 @@
down_revision = '4202e3047e47'

from alembic import op
from oslo_db import exception
import sqlalchemy as sa

SQL_STATEMENT = (
Expand All @@ -34,7 +35,7 @@
"f.id as fw_id, r.id as router_id "
"from firewalls f, routers r "
"where "
"f.tenant_id=r.tenant_id"
"f.tenant_id=r.%s"
)


Expand All @@ -49,4 +50,10 @@ def upgrade():
sa.PrimaryKeyConstraint('fw_id', 'router_id'),
)

op.execute(SQL_STATEMENT)
# Depending on when neutron-fwaas is installed with neutron, this script
# may be run before or after the neutron core tables have had their
# tenant_id columns renamed to project_id. Account for both scenarios.
try:
op.execute(SQL_STATEMENT % 'tenant_id')
except exception.DBError:
op.execute(SQL_STATEMENT % 'project_id')
@@ -1 +1 @@
458aa42b14b
f83a0b2964d0
@@ -0,0 +1,139 @@
# Copyright 2016 <PUT YOUR NAME/COMPANY HERE>
#
# 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.
#

"""rename tenant to project
Revision ID: f83a0b2964d0
Revises: 458aa42b14b
Create Date: 2016-07-14 13:11:53.112622
"""

from alembic import op
import sqlalchemy as sa
from sqlalchemy.engine import reflection


# revision identifiers, used by Alembic.
revision = 'f83a0b2964d0'
down_revision = '458aa42b14b'


_INSPECTOR = None


def get_inspector():
"""Reuse inspector"""

global _INSPECTOR

if _INSPECTOR:
return _INSPECTOR

else:
bind = op.get_bind()
_INSPECTOR = reflection.Inspector.from_engine(bind)

return _INSPECTOR


def get_tables():
"""
Returns hardcoded list of tables which have ``tenant_id`` column.
The list is hardcoded to match the state of the schema when this
upgrade script is run.
"""

tables = [
'firewalls',
'firewall_policies',
'firewall_rules',
]

return tables


def get_columns(table):
"""Returns list of columns for given table."""
inspector = get_inspector()
return inspector.get_columns(table)


def get_data():
"""Returns combined list of tuples: [(table, column)].
The list is built from tables with a tenant_id column.
"""

output = []
tables = get_tables()
for table in tables:
columns = get_columns(table)

for column in columns:
if column['name'] == 'tenant_id':
output.append((table, column))

return output


def alter_column(table, column):
old_name = 'tenant_id'
new_name = 'project_id'

op.alter_column(
table_name=table,
column_name=old_name,
new_column_name=new_name,
existing_type=column['type'],
existing_nullable=column['nullable']
)


def recreate_index(index, table_name):
old_name = index['name']
new_name = old_name.replace('tenant', 'project')

op.drop_index(op.f(old_name), table_name)
op.create_index(new_name, table_name, ['project_id'])


def upgrade():
"""Code reused from
Change-Id: I87a8ef342ccea004731ba0192b23a8e79bc382dc
"""

inspector = get_inspector()

data = get_data()
for table, column in data:
alter_column(table, column)

indexes = inspector.get_indexes(table)
for index in indexes:
if 'tenant_id' in index['name']:
recreate_index(index, table)


def contract_creation_exceptions():
"""Special migration for the blueprint to support Keystone V3.
We drop all tenant_id columns and create project_id columns instead.
"""
return {
sa.Column: ['.'.join([table, 'project_id']) for table in get_tables()],
sa.Index: get_tables()
}

0 comments on commit c3e491c

Please sign in to comment.