# vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright 2013 VMware, 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. # import contextlib import copy import webob.exc from neutron.api.v2 import attributes from neutron import context from neutron.extensions import firewall from neutron import manager from neutron.openstack.common import uuidutils from neutron.plugins.common import constants as const from neutron.tests.unit.db.firewall import test_db_firewall from neutron.tests.unit.nicira import test_edge_router _uuid = uuidutils.generate_uuid FW_PLUGIN_CLASS = ( "neutron.plugins.nicira.NeutronServicePlugin.NvpAdvancedPlugin" ) class FirewallTestExtensionManager( test_edge_router.ServiceRouterTestExtensionManager): def get_resources(self): # If l3 resources have been loaded and updated by main API # router, update the map in the l3 extension so it will load # the same attributes as the API router resources = super(FirewallTestExtensionManager, self).get_resources() firewall_attr_map = copy.deepcopy(firewall.RESOURCE_ATTRIBUTE_MAP) for res in firewall.RESOURCE_ATTRIBUTE_MAP.keys(): attr_info = attributes.RESOURCE_ATTRIBUTE_MAP.get(res) if attr_info: firewall.RESOURCE_ATTRIBUTE_MAP[res] = attr_info fw_resources = firewall.Firewall.get_resources() # restore the original resources once the controllers are created firewall.RESOURCE_ATTRIBUTE_MAP = firewall_attr_map resources.extend(fw_resources) return resources def get_actions(self): return [] def get_request_extensions(self): return [] class FirewallPluginTestCase(test_db_firewall.FirewallPluginDbTestCase, test_edge_router.ServiceRouterTest): def vcns_firewall_patch(self): self.vcns_instance.return_value.update_firewall.side_effect = ( self.fc2.update_firewall) self.vcns_instance.return_value.delete_firewall.side_effect = ( self.fc2.delete_firewall) self.vcns_instance.return_value.update_firewall_rule.side_effect = ( self.fc2.update_firewall_rule) self.vcns_instance.return_value.delete_firewall_rule.side_effect = ( self.fc2.delete_firewall_rule) self.vcns_instance.return_value.add_firewall_rule_above.side_effect = ( self.fc2.add_firewall_rule_above) self.vcns_instance.return_value.add_firewall_rule.side_effect = ( self.fc2.add_firewall_rule) self.vcns_instance.return_value.get_firewall.side_effect = ( self.fc2.get_firewall) self.vcns_instance.return_value.get_firewall_rule.side_effect = ( self.fc2.get_firewall_rule) def setUp(self): # Save the global RESOURCE_ATTRIBUTE_MAP self.saved_attr_map = {} for resource, attrs in attributes.RESOURCE_ATTRIBUTE_MAP.iteritems(): self.saved_attr_map[resource] = attrs.copy() super(FirewallPluginTestCase, self).setUp( ext_mgr=FirewallTestExtensionManager(), fw_plugin=FW_PLUGIN_CLASS) self.vcns_firewall_patch() self.plugin = manager.NeutronManager.get_plugin() self.router_id = None def tearDown(self): super(FirewallPluginTestCase, self).tearDown() # Restore the global RESOURCE_ATTRIBUTE_MAP attributes.RESOURCE_ATTRIBUTE_MAP = self.saved_attr_map self.ext_api = None self.plugin = None def _fake_router_edge_mapping(self): req = self._create_router(self.fmt, self._tenant_id) res = self.deserialize(self.fmt, req) self.router_id = res['router']['id'] def _create_firewall(self, fmt, name, description, firewall_policy_id, admin_state_up=True, expected_res_status=None, **kwargs): data = {'firewall': {'name': name, 'description': description, 'firewall_policy_id': firewall_policy_id, 'router_id': self.router_id, 'admin_state_up': admin_state_up, 'tenant_id': self._tenant_id}} firewall_req = self.new_create_request('firewalls', data, fmt) firewall_res = firewall_req.get_response(self.ext_api) if expected_res_status: self.assertEqual(firewall_res.status_int, expected_res_status) return firewall_res def test_create_firewall(self): self._fake_router_edge_mapping() name = "new_fw" attrs = self._get_test_firewall_attrs(name) with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['firewall_policy_id'] = fwp_id with self.firewall(name=name, firewall_policy_id=fwp_id, router_id=self.router_id, admin_state_up= test_db_firewall.ADMIN_STATE_UP, expected_res_status=201) as fw: attrs = self._replace_firewall_status( attrs, const.PENDING_CREATE, const.ACTIVE) for k, v in attrs.iteritems(): self.assertEqual(fw['firewall'][k], v) def test_update_firewall(self): self._fake_router_edge_mapping() name = "new_fw" attrs = self._get_test_firewall_attrs(name) with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['firewall_policy_id'] = fwp_id with self.firewall( firewall_policy_id=fwp_id, router_id=self.router_id, admin_state_up=test_db_firewall.ADMIN_STATE_UP) as fw: fw_id = fw['firewall']['id'] new_data = {'firewall': {'name': name}} req = self.new_update_request('firewalls', new_data, fw_id) res = req.get_response(self.ext_api) self.assertEqual(res.status_int, 200) res_json = self.deserialize( self.fmt, res) attrs = self._replace_firewall_status( attrs, const.PENDING_CREATE, const.ACTIVE) for k, v in attrs.iteritems(): self.assertEqual(res_json['firewall'][k], v) def test_delete_firewall(self): ctx = context.get_admin_context() self._fake_router_edge_mapping() with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall( firewall_policy_id=fwp_id, router_id=self.router_id, admin_state_up=test_db_firewall.ADMIN_STATE_UP, no_delete=True) as fw: fw_id = fw['firewall']['id'] with ctx.session.begin(subtransactions=True): req = self.new_delete_request('firewalls', fw_id) res = req.get_response(self.ext_api) self.assertEqual(res.status_int, 204) self.assertRaises( firewall.FirewallNotFound, self.plugin.get_firewall, ctx, fw_id) def test_create_firewall_with_rules(self): ctx = context.get_admin_context() self._fake_router_edge_mapping() with contextlib.nested(self.firewall_rule(name='fwr1'), self.firewall_rule(name='fwr2'), self.firewall_rule(name='fwr3')) as fr: with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] fw_rule_ids = [r['firewall_rule']['id'] for r in fr] data = {'firewall_policy': {'firewall_rules': fw_rule_ids}} req = self.new_update_request( 'firewall_policies', data, fwp_id) req.get_response(self.ext_api) attrs = self._get_test_firewall_attrs() attrs['firewall_policy_id'] = fwp_id with self.firewall( firewall_policy_id=fwp_id, router_id=self.router_id, admin_state_up=test_db_firewall.ADMIN_STATE_UP) as fw: rule_list = ( self.plugin._make_firewall_rule_list_by_policy_id( ctx, fw['firewall']['firewall_policy_id'])) self._compare_firewall_rule_lists( fwp_id, fr, rule_list) def test_update_firewall_policy_with_no_firewall(self): name = "new_firewall_policy1" attrs = self._get_test_firewall_policy_attrs(name) with self.firewall_policy(shared=test_db_firewall.SHARED, firewall_rules=None, audited=test_db_firewall.AUDITED) as fwp: data = {'firewall_policy': {'name': name}} req = self.new_update_request('firewall_policies', data, fwp['firewall_policy']['id']) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) for k, v in attrs.iteritems(): self.assertEqual(res['firewall_policy'][k], v) def test_update_firewall_policy_with_firewall(self): self._fake_router_edge_mapping() name = "new_firewall_policy1" attrs = self._get_test_firewall_policy_attrs(name) with self.firewall_policy(shared=test_db_firewall.SHARED, firewall_rules=None, audited=test_db_firewall.AUDITED) as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall(firewall_policy_id=fwp_id, router_id=self.router_id, admin_state_up= test_db_firewall.ADMIN_STATE_UP): data = {'firewall_policy': {'name': name}} req = self.new_update_request( 'firewall_policies', data, fwp['firewall_policy']['id']) res = self.deserialize( self.fmt, req.get_response(self.ext_api)) for k, v in attrs.iteritems(): self.assertEqual(res['firewall_policy'][k], v) def test_update_firewall_rule_with_no_firewall(self): name = "new_firewall_rule1" attrs = self._get_test_firewall_rule_attrs(name) attrs['source_port'] = '10:20' attrs['destination_port'] = '30:40' with self.firewall_rule() as fwr: data = {'firewall_rule': {'name': name, 'source_port': '10:20', 'destination_port': '30:40'}} req = self.new_update_request( 'firewall_rules', data, fwr['firewall_rule']['id']) res = self.deserialize( self.fmt, req.get_response(self.ext_api)) for k, v in attrs.iteritems(): self.assertEqual(res['firewall_rule'][k], v) attrs['source_port'] = '10000' attrs['destination_port'] = '80' with self.firewall_rule() as fwr: data = {'firewall_rule': {'name': name, 'source_port': 10000, 'destination_port': 80}} req = self.new_update_request('firewall_rules', data, fwr['firewall_rule']['id']) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) for k, v in attrs.iteritems(): self.assertEqual(res['firewall_rule'][k], v) attrs['source_port'] = None attrs['destination_port'] = None with self.firewall_rule() as fwr: data = {'firewall_rule': {'name': name, 'source_port': None, 'destination_port': None}} req = self.new_update_request( 'firewall_rules', data, fwr['firewall_rule']['id']) res = self.deserialize( self.fmt, req.get_response(self.ext_api)) for k, v in attrs.iteritems(): self.assertEqual(res['firewall_rule'][k], v) def test_update_firewall_rule_with_firewall(self): self._fake_router_edge_mapping() name = "new_firewall_rule1" attrs = self._get_test_firewall_rule_attrs(name) with self.firewall_rule() as fwr: with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['firewall_policy_id'] = fwp_id with self.firewall(firewall_policy_id=fwp_id, router_id=self.router_id, admin_state_up= test_db_firewall.ADMIN_STATE_UP): fwr_id = fwr['firewall_rule']['id'] data = {'firewall_policy': {'firewall_rules': [fwr_id]}} req = self.new_update_request( 'firewall_policies', data, fwp['firewall_policy']['id']) req.get_response(self.ext_api) data = {'firewall_rule': {'name': name}} req = self.new_update_request( 'firewall_rules', data, fwr['firewall_rule']['id']) res = self.deserialize( self.fmt, req.get_response(self.ext_api)) attrs['firewall_policy_id'] = fwp_id for k, v in attrs.iteritems(): self.assertEqual(res['firewall_rule'][k], v) def test_insert_rule_with_no_firewall(self): attrs = self._get_test_firewall_policy_attrs() attrs['audited'] = False attrs['firewall_list'] = [] with contextlib.nested(self.firewall_rule(name='fwr0'), self.firewall_rule(name='fwr1'), self.firewall_rule(name='fwr2'), self.firewall_rule(name='fwr3'), self.firewall_rule(name='fwr4'), self.firewall_rule(name='fwr5'), self.firewall_rule(name='fwr6')) as fwr: with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['id'] = fwp_id # test insert when rule list is empty fwr0_id = fwr[0]['firewall_rule']['id'] attrs['firewall_rules'].insert(0, fwr0_id) self._rule_action('insert', fwp_id, fwr0_id, insert_before=None, insert_after=None, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) # test insert at top of rule list, insert_before and # insert_after not provided fwr1_id = fwr[1]['firewall_rule']['id'] attrs['firewall_rules'].insert(0, fwr1_id) insert_data = {'firewall_rule_id': fwr1_id} self._rule_action('insert', fwp_id, fwr0_id, expected_code=webob.exc.HTTPOk.code, expected_body=attrs, body_data=insert_data) # test insert at top of list above existing rule fwr2_id = fwr[2]['firewall_rule']['id'] attrs['firewall_rules'].insert(0, fwr2_id) self._rule_action('insert', fwp_id, fwr2_id, insert_before=fwr1_id, insert_after=None, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) # test insert at bottom of list fwr3_id = fwr[3]['firewall_rule']['id'] attrs['firewall_rules'].append(fwr3_id) self._rule_action('insert', fwp_id, fwr3_id, insert_before=None, insert_after=fwr0_id, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) # test insert in the middle of the list using # insert_before fwr4_id = fwr[4]['firewall_rule']['id'] attrs['firewall_rules'].insert(1, fwr4_id) self._rule_action('insert', fwp_id, fwr4_id, insert_before=fwr1_id, insert_after=None, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) # test insert in the middle of the list using # insert_after fwr5_id = fwr[5]['firewall_rule']['id'] attrs['firewall_rules'].insert(1, fwr5_id) self._rule_action('insert', fwp_id, fwr5_id, insert_before=None, insert_after=fwr2_id, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) # test insert when both insert_before and # insert_after are set fwr6_id = fwr[6]['firewall_rule']['id'] attrs['firewall_rules'].insert(1, fwr6_id) self._rule_action('insert', fwp_id, fwr6_id, insert_before=fwr5_id, insert_after=fwr5_id, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) def test_insert_rule_with_firewall(self): self._fake_router_edge_mapping() attrs = self._get_test_firewall_policy_attrs() attrs['audited'] = False attrs['firewall_list'] = [] with contextlib.nested(self.firewall_rule(name='fwr0'), self.firewall_rule(name='fwr1'), self.firewall_rule(name='fwr2'), self.firewall_rule(name='fwr3'), self.firewall_rule(name='fwr4'), self.firewall_rule(name='fwr5'), self.firewall_rule(name='fwr6')) as fwr: with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['id'] = fwp_id with self.firewall(router_id=self.router_id, firewall_policy_id=fwp_id) as fw: # test insert when rule list is empty fwr0_id = fwr[0]['firewall_rule']['id'] attrs['firewall_rules'].insert(0, fwr0_id) attrs['firewall_list'].insert(0, fw['firewall']['id']) self._rule_action('insert', fwp_id, fwr0_id, insert_before=None, insert_after=None, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) # test insert at top of rule list, insert_before and # insert_after not provided fwr1_id = fwr[1]['firewall_rule']['id'] attrs['firewall_rules'].insert(0, fwr1_id) insert_data = {'firewall_rule_id': fwr1_id} self._rule_action( 'insert', fwp_id, fwr0_id, expected_code=webob.exc.HTTPOk.code, expected_body=attrs, body_data=insert_data) # test insert at top of list above existing rule fwr2_id = fwr[2]['firewall_rule']['id'] attrs['firewall_rules'].insert(0, fwr2_id) self._rule_action('insert', fwp_id, fwr2_id, insert_before=fwr1_id, insert_after=None, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) # test insert at bottom of list fwr3_id = fwr[3]['firewall_rule']['id'] attrs['firewall_rules'].append(fwr3_id) self._rule_action('insert', fwp_id, fwr3_id, insert_before=None, insert_after=fwr0_id, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) # test insert in the middle of the list using # insert_before fwr4_id = fwr[4]['firewall_rule']['id'] attrs['firewall_rules'].insert(1, fwr4_id) self._rule_action('insert', fwp_id, fwr4_id, insert_before=fwr1_id, insert_after=None, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) # test insert in the middle of the list using # insert_after fwr5_id = fwr[5]['firewall_rule']['id'] attrs['firewall_rules'].insert(1, fwr5_id) self._rule_action('insert', fwp_id, fwr5_id, insert_before=None, insert_after=fwr2_id, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) # test insert when both insert_before and # insert_after are set fwr6_id = fwr[6]['firewall_rule']['id'] attrs['firewall_rules'].insert(1, fwr6_id) self._rule_action('insert', fwp_id, fwr6_id, insert_before=fwr5_id, insert_after=fwr5_id, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) def test_remove_rule_with_no_firewall(self): attrs = self._get_test_firewall_policy_attrs() attrs['audited'] = False attrs['firewall_list'] = [] with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['id'] = fwp_id with contextlib.nested(self.firewall_rule(name='fwr1'), self.firewall_rule(name='fwr2'), self.firewall_rule(name='fwr3')) as fr1: fw_rule_ids = [r['firewall_rule']['id'] for r in fr1] attrs['firewall_rules'] = fw_rule_ids[:] data = {'firewall_policy': {'firewall_rules': fw_rule_ids}} req = self.new_update_request('firewall_policies', data, fwp_id) req.get_response(self.ext_api) # test removing a rule from a policy that does not exist self._rule_action('remove', '123', fw_rule_ids[1], expected_code=webob.exc.HTTPNotFound.code, expected_body=None) # test removing a rule in the middle of the list attrs['firewall_rules'].remove(fw_rule_ids[1]) self._rule_action('remove', fwp_id, fw_rule_ids[1], expected_body=attrs) # test removing a rule at the top of the list attrs['firewall_rules'].remove(fw_rule_ids[0]) self._rule_action('remove', fwp_id, fw_rule_ids[0], expected_body=attrs) # test removing remaining rule in the list attrs['firewall_rules'].remove(fw_rule_ids[2]) self._rule_action('remove', fwp_id, fw_rule_ids[2], expected_body=attrs) # test removing rule that is not associated with the policy self._rule_action('remove', fwp_id, fw_rule_ids[2], expected_code=webob.exc.HTTPBadRequest.code, expected_body=None) def test_remove_rule_with_firewall(self): self._fake_router_edge_mapping() attrs = self._get_test_firewall_policy_attrs() attrs['audited'] = False attrs['firewall_list'] = [] with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['id'] = fwp_id with self.firewall(router_id=self.router_id, firewall_policy_id=fwp_id) as fw: attrs['firewall_list'].insert(0, fw['firewall']['id']) with contextlib.nested(self.firewall_rule(name='fwr1'), self.firewall_rule(name='fwr2'), self.firewall_rule(name='fwr3')) as fr1: fw_rule_ids = [r['firewall_rule']['id'] for r in fr1] attrs['firewall_rules'] = fw_rule_ids[:] data = {'firewall_policy': {'firewall_rules': fw_rule_ids}} req = self.new_update_request( 'firewall_policies', data, fwp_id) req.get_response(self.ext_api) # test removing a rule from a policy that does not exist self._rule_action( 'remove', '123', fw_rule_ids[1], expected_code=webob.exc.HTTPNotFound.code, expected_body=None) # test removing a rule in the middle of the list attrs['firewall_rules'].remove(fw_rule_ids[1]) self._rule_action('remove', fwp_id, fw_rule_ids[1], expected_body=attrs) # test removing a rule at the top of the list attrs['firewall_rules'].remove(fw_rule_ids[0]) self._rule_action('remove', fwp_id, fw_rule_ids[0], expected_body=attrs) # test removing remaining rule in the list attrs['firewall_rules'].remove(fw_rule_ids[2]) self._rule_action('remove', fwp_id, fw_rule_ids[2], expected_body=attrs) # test removing rule that is not #associated with the policy self._rule_action( 'remove', fwp_id, fw_rule_ids[2], expected_code=webob.exc.HTTPBadRequest.code, expected_body=None)