diff options
-rw-r--r-- | neutron/context.py | 2 | ||||
-rw-r--r-- | neutron/db/migration/__init__.py | 34 | ||||
-rw-r--r-- | neutron/db/migration/alembic_migrations/versions/31d7f831a591_add_constraint_for_routerid.py | 115 | ||||
-rw-r--r-- | neutron/db/securitygroups_db.py | 6 | ||||
-rw-r--r-- | neutron/extensions/securitygroup.py | 5 | ||||
-rwxr-xr-x | neutron/plugins/linuxbridge/agent/linuxbridge_neutron_agent.py | 3 | ||||
-rw-r--r-- | neutron/tests/unit/test_api_v2_resource.py | 10 | ||||
-rw-r--r-- | neutron/tests/unit/test_extension_security_group.py | 3 |
8 files changed, 83 insertions, 95 deletions
diff --git a/neutron/context.py b/neutron/context.py index f248e70250..1da9b77423 100644 --- a/neutron/context.py +++ b/neutron/context.py @@ -144,7 +144,7 @@ class ContextBase(common_context.RequestContext): context.is_admin = True if 'admin' not in [x.lower() for x in context.roles]: - context.roles.append('admin') + context.roles = context.roles + ["admin"] if read_deleted is not None: context.read_deleted = read_deleted diff --git a/neutron/db/migration/__init__.py b/neutron/db/migration/__init__.py index 55c1443f1f..86cce385af 100644 --- a/neutron/db/migration/__init__.py +++ b/neutron/db/migration/__init__.py @@ -12,11 +12,13 @@ # License for the specific language governing permissions and limitations # under the License. +import contextlib import functools from alembic import context from alembic import op import sqlalchemy as sa +from sqlalchemy.engine import reflection def skip_if_offline(func): @@ -122,3 +124,35 @@ def create_table_if_not_exist_psql(table_name, values): "WHERE NOT table_exist(%(name)r);" % {'name': table_name, 'columns': values}) + + +def remove_foreign_keys(table, foreign_keys): + for fk in foreign_keys: + op.drop_constraint( + name=fk['name'], + table_name=table, + type_='foreignkey' + ) + + +def create_foreign_keys(table, foreign_keys): + for fk in foreign_keys: + op.create_foreign_key( + name=fk['name'], + source=table, + referent=fk['referred_table'], + local_cols=fk['constrained_columns'], + remote_cols=fk['referred_columns'], + ondelete='CASCADE' + ) + + +@contextlib.contextmanager +def remove_fks_from_table(table): + try: + inspector = reflection.Inspector.from_engine(op.get_bind()) + foreign_keys = inspector.get_foreign_keys(table) + remove_foreign_keys(table, foreign_keys) + yield + finally: + create_foreign_keys(table, foreign_keys) diff --git a/neutron/db/migration/alembic_migrations/versions/31d7f831a591_add_constraint_for_routerid.py b/neutron/db/migration/alembic_migrations/versions/31d7f831a591_add_constraint_for_routerid.py index 0ba5f58be7..232156748e 100644 --- a/neutron/db/migration/alembic_migrations/versions/31d7f831a591_add_constraint_for_routerid.py +++ b/neutron/db/migration/alembic_migrations/versions/31d7f831a591_add_constraint_for_routerid.py @@ -27,22 +27,12 @@ down_revision = '37f322991f59' from alembic import op import sqlalchemy as sa -from sqlalchemy.engine import reflection + +from neutron.db import migration TABLE_NAME = 'routerl3agentbindings' PK_NAME = 'pk_routerl3agentbindings' -fk_names = {'postgresql': - {'router_id': - 'routerl3agentbindings_router_id_fkey', - 'l3_agent_id': - 'routerl3agentbindings_l3_agent_id_fkey'}, - 'mysql': - {'router_id': - 'routerl3agentbindings_ibfk_2', - 'l3_agent_id': - 'routerl3agentbindings_ibfk_1'}} - def upgrade(): # In order to sanitize the data during migration, @@ -66,60 +56,32 @@ def upgrade(): op.drop_column(TABLE_NAME, 'id') - # DB2 doesn't support nullable column in primary key - if context.bind.dialect.name == 'ibm_db_sa': - op.alter_column( - table_name=TABLE_NAME, - column_name='router_id', - nullable=False - ) - op.alter_column( + with migration.remove_fks_from_table(TABLE_NAME): + # DB2 doesn't support nullable column in primary key + if context.bind.dialect.name == 'ibm_db_sa': + op.alter_column( + table_name=TABLE_NAME, + column_name='router_id', + nullable=False + ) + op.alter_column( + table_name=TABLE_NAME, + column_name='l3_agent_id', + nullable=False + ) + + op.create_primary_key( + name=PK_NAME, table_name=TABLE_NAME, - column_name='l3_agent_id', - nullable=False + cols=['router_id', 'l3_agent_id'] ) - op.create_primary_key( - name=PK_NAME, - table_name=TABLE_NAME, - cols=['router_id', 'l3_agent_id'] - ) - def downgrade(): context = op.get_context() dialect = context.bind.dialect.name - # Drop the existed foreign key constraints - # In order to perform primary key changes - db2fks = {} - if dialect == 'ibm_db_sa': - # NOTE(mriedem): In DB2 the foreign key names are randomly generated - # if you didn't originally explicitly name them, so the name is like - # SQLxxxxx where the suffix is a random integer. Therefore we go - # through and just drop all of the foreign keys and save them so we - # can re-create them later after the primary key is dropped. - inspector = reflection.Inspector.from_engine(op.get_bind().engine) - db2fks = inspector.get_foreign_keys(TABLE_NAME) - for fk in db2fks: - op.drop_constraint( - name=fk.get('name'), - table_name=TABLE_NAME, - type_='foreignkey' - ) - else: - op.drop_constraint( - name=fk_names[dialect]['l3_agent_id'], - table_name=TABLE_NAME, - type_='foreignkey' - ) - op.drop_constraint( - name=fk_names[dialect]['router_id'], - table_name=TABLE_NAME, - type_='foreignkey' - ) - op.drop_constraint( name=PK_NAME, table_name=TABLE_NAME, @@ -139,38 +101,9 @@ def downgrade(): nullable=False ) - op.create_primary_key( - name=PK_NAME, - table_name=TABLE_NAME, - cols=['id'] - ) - - # Restore the foreign key constraints - if dialect == 'ibm_db_sa': - for fk in db2fks: - op.create_foreign_key( - name=fk.get('name'), - source=TABLE_NAME, - referent=fk.get('referred_table'), - local_cols=fk.get('constrained_columns'), - remote_cols=fk.get('referred_columns'), - ondelete='CASCADE' - ) - else: - op.create_foreign_key( - name=fk_names[dialect]['router_id'], - source=TABLE_NAME, - referent='routers', - local_cols=['router_id'], - remote_cols=['id'], - ondelete='CASCADE' - ) - - op.create_foreign_key( - name=fk_names[dialect]['l3_agent_id'], - source=TABLE_NAME, - referent='agents', - local_cols=['l3_agent_id'], - remote_cols=['id'], - ondelete='CASCADE' + with migration.remove_fks_from_table(TABLE_NAME): + op.create_primary_key( + name=PK_NAME, + table_name=TABLE_NAME, + cols=['id'] ) diff --git a/neutron/db/securitygroups_db.py b/neutron/db/securitygroups_db.py index 23b5c80cb1..9237cf31f2 100644 --- a/neutron/db/securitygroups_db.py +++ b/neutron/db/securitygroups_db.py @@ -296,7 +296,11 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase): def _get_ip_proto_number(self, protocol): if protocol is None: return - return IP_PROTOCOL_MAP.get(protocol, protocol) + # According to bug 1381379, protocol is always set to string to avoid + # problems with comparing int and string in PostgreSQL. Here this + # string is converted to int to give an opportunity to use it as + # before. + return int(IP_PROTOCOL_MAP.get(protocol, protocol)) def _validate_port_range(self, rule): """Check that port_range is valid.""" diff --git a/neutron/extensions/securitygroup.py b/neutron/extensions/securitygroup.py index 89b9d8a74b..3524117ee9 100644 --- a/neutron/extensions/securitygroup.py +++ b/neutron/extensions/securitygroup.py @@ -116,7 +116,10 @@ def convert_protocol(value): try: val = int(value) if val >= 0 and val <= 255: - return value + # Set value of protocol number to string due to bug 1381379, + # PostgreSQL fails when it tries to compare integer with string, + # that exists in db. + return str(value) raise SecurityGroupRuleInvalidProtocol( protocol=value, values=sg_supported_protocols) except (ValueError, TypeError): diff --git a/neutron/plugins/linuxbridge/agent/linuxbridge_neutron_agent.py b/neutron/plugins/linuxbridge/agent/linuxbridge_neutron_agent.py index 8011c0d4bd..d9f7f686f5 100755 --- a/neutron/plugins/linuxbridge/agent/linuxbridge_neutron_agent.py +++ b/neutron/plugins/linuxbridge/agent/linuxbridge_neutron_agent.py @@ -27,6 +27,7 @@ import eventlet eventlet.monkey_patch() from oslo.config import cfg +from six import moves from neutron.agent import l2population_rpc as l2pop_rpc from neutron.agent.linux import ip_lib @@ -523,7 +524,7 @@ class LinuxBridgeManager: 'command': 'bridge fdb', 'mode': 'VXLAN UCAST'}) return False - for segmentation_id in range(1, constants.MAX_VXLAN_VNI + 1): + for segmentation_id in moves.xrange(1, constants.MAX_VXLAN_VNI + 1): if not ip_lib.device_exists( self.get_vxlan_device_name(segmentation_id)): break diff --git a/neutron/tests/unit/test_api_v2_resource.py b/neutron/tests/unit/test_api_v2_resource.py index 91e24de711..ae3dad5a7c 100644 --- a/neutron/tests/unit/test_api_v2_resource.py +++ b/neutron/tests/unit/test_api_v2_resource.py @@ -94,6 +94,16 @@ class RequestTestCase(base.BaseTestCase): def test_context_without_neutron_context(self): self.assertTrue(self.req.context.is_admin) + def test_request_context_elevated(self): + user_context = context.Context( + 'fake_user', 'fake_project', admin=False) + self.assertFalse(user_context.is_admin) + admin_context = user_context.elevated() + self.assertFalse(user_context.is_admin) + self.assertTrue(admin_context.is_admin) + self.assertNotIn('admin', user_context.roles) + self.assertIn('admin', admin_context.roles) + def test_best_match_language(self): # Test that we are actually invoking language negotiation by webop request = wsgi.Request.blank('/') diff --git a/neutron/tests/unit/test_extension_security_group.py b/neutron/tests/unit/test_extension_security_group.py index 4f52ba0807..07a5cb0b39 100644 --- a/neutron/tests/unit/test_extension_security_group.py +++ b/neutron/tests/unit/test_extension_security_group.py @@ -1446,6 +1446,9 @@ class TestConvertProtocol(base.BaseTestCase): self.assertRaises(ext_sg.SecurityGroupRuleInvalidProtocol, ext_sg.convert_protocol, val) + def test_convert_numeric_protocol_to_string(self): + self.assertIsInstance(ext_sg.convert_protocol(2), str) + class TestSecurityGroupsXML(TestSecurityGroups): fmt = 'xml' |