# Copyright (c) 2018 Fujitsu Limited # 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. from unittest import mock from neutron.objects.logapi import logging_resource as log_object from neutron.objects import ports as port_objects from neutron.services.logapi.rpc import server as server_rpc from neutron.tests import base from neutron_lib import constants as nl_const from oslo_utils import uuidutils from neutron_fwaas.services.logapi.common import log_db_api from neutron_fwaas.services.logapi.rpc import log_server as fwg_rpc FWG = 'firewall_group' def _create_log_object(tenant_id, resource_id=None, target_id=None, event='ALL'): log_data = { 'id': uuidutils.generate_uuid(), 'name': 'fake_log_name', 'resource_type': FWG, 'project_id': tenant_id, 'event': event, 'enabled': True} if resource_id: log_data['resource_id'] = resource_id if target_id: log_data['target_id'] = target_id return log_object.Log(**log_data) def _fake_log_info(id, project_id, ports_id, event='ALL'): expected = { 'id': id, 'project_id': project_id, 'ports_log': ports_id, 'event': event } return expected def _fake_port_object(port_id, device_owner, status, project_id=uuidutils.generate_uuid()): port_data = { 'id': port_id, 'device_owner': device_owner, 'project_id': project_id } if status: port_data['status'] = status return port_data class LoggingRpcCallbackTestCase(base.BaseTestCase): def setUp(self): super(LoggingRpcCallbackTestCase, self).setUp() self.context = mock.Mock() self.rpc_callback = server_rpc.LoggingApiSkeleton() log_db_api.fw_plugin_db = mock.Mock() self.vm_port = uuidutils.generate_uuid() self.router_port = uuidutils.generate_uuid() self.fake_vm_port = \ _fake_port_object(self.vm_port, nl_const.DEVICE_OWNER_COMPUTE_PREFIX, nl_const.PORT_STATUS_ACTIVE) self.fake_router_port = \ _fake_port_object(self.router_port, nl_const.DEVICE_OWNER_ROUTER_INTF, nl_const.PORT_STATUS_ACTIVE) self.fake_router_ports = \ [_fake_port_object(self.router_port, device, nl_const.PORT_STATUS_ACTIVE) for device in nl_const.ROUTER_INTERFACE_OWNERS] def test_get_fwg_log_info_for_log_resources(self): fwg_id = uuidutils.generate_uuid() tenant_id = uuidutils.generate_uuid() log_obj = _create_log_object(tenant_id, resource_id=fwg_id) rpc_call = fwg_rpc.get_fwg_log_info_for_log_resources with mock.patch.object(server_rpc, 'get_rpc_method', return_value=rpc_call): fake_ports = ['fake_port_1', 'fake_port_2'] with mock.patch.object(log_db_api, '_get_ports_being_logged', return_value=fake_ports): expected_log_info = [ _fake_log_info(log_obj['id'], tenant_id, fake_ports) ] logs_info = self.rpc_callback.\ get_sg_log_info_for_log_resources(self.context, resource_type=FWG, log_resources=[log_obj]) self.assertEqual(expected_log_info, logs_info) def test_get_fwg_log_info_for_port(self): fwg_id = uuidutils.generate_uuid() port_id = uuidutils.generate_uuid() tenant_id = uuidutils.generate_uuid() log_obj = _create_log_object(tenant_id, resource_id=fwg_id, target_id=port_id) rpc_call = fwg_rpc.get_fwg_log_info_for_port with mock.patch.object(server_rpc, 'get_rpc_method', return_value=rpc_call): with mock.patch.object(log_db_api, 'get_logs_for_port', return_value=[log_obj]): fake_ports = [port_id, 'fake_port2'] with mock.patch.object(log_db_api, '_get_ports_being_logged', return_value=fake_ports): expected_log_info = [_fake_log_info(log_obj['id'], tenant_id, fake_ports)] logs_info = self.rpc_callback.\ get_sg_log_info_for_port(self.context, resource_type=FWG, port_id=port_id) self.assertEqual(expected_log_info, logs_info) def test_get_ports_being_logged_with_target_id(self): tenant_id = uuidutils.generate_uuid() fwg_id = uuidutils.generate_uuid() # Test with VM port log_obj = _create_log_object(tenant_id, resource_id=fwg_id, target_id=self.vm_port) with mock.patch.object(port_objects.Port, 'get_object', return_value=self.fake_vm_port): logged_port_ids = \ log_db_api._get_ports_being_logged(self.context, log_obj) self.assertEqual([], logged_port_ids) # Test with router ports log_obj = _create_log_object(tenant_id, resource_id=fwg_id, target_id=self.router_port) log_db_api.fw_plugin_db. \ get_fwg_attached_to_port = mock.Mock(return_value='fwg_id') with mock.patch.object(port_objects.Port, 'get_object', side_effect=self.fake_router_ports): for port in self.fake_router_ports: logged_port_ids = \ log_db_api._get_ports_being_logged(self.context, log_obj) self.assertEqual([self.router_port], logged_port_ids) # Test with inactive router port self.fake_router_port['status'] = nl_const.PORT_STATUS_DOWN log_obj = _create_log_object(tenant_id, resource_id=fwg_id, target_id=self.router_port) log_db_api.fw_plugin_db. \ get_fwg_attached_to_port = mock.Mock(return_value='fwg_id') with mock.patch.object(port_objects.Port, 'get_object', return_value=self.fake_router_port): logged_port_ids = \ log_db_api._get_ports_being_logged(self.context, log_obj) self.assertEqual([], logged_port_ids) def test_get_ports_being_logged_with_resource_id(self): tenant_id = uuidutils.generate_uuid() fwg_id = uuidutils.generate_uuid() log_obj = _create_log_object(tenant_id, resource_id=fwg_id) log_db_api.fw_plugin_db.get_ports_in_firewall_group = \ mock.Mock(return_value=[self.vm_port]) # Test with VM port with mock.patch.object(port_objects.Port, 'get_object', return_value=self.fake_vm_port): logged_port_ids = \ log_db_api._get_ports_being_logged(self.context, log_obj) self.assertEqual([], logged_port_ids) # Test with router ports router_ports = [self.router_port, self.router_port, self.router_port] log_db_api.fw_plugin_db. \ get_ports_in_firewall_group = mock.Mock(return_value=router_ports) log_db_api.fw_plugin_db. \ get_fwg_attached_to_port = mock.Mock(return_value='fwg_id') with mock.patch.object(port_objects.Port, 'get_object', side_effect=self.fake_router_ports): logged_port_ids = \ log_db_api._get_ports_being_logged(self.context, log_obj) self.assertEqual(router_ports, logged_port_ids) # Test with both vm port and router ports log_db_api.fw_plugin_db.get_ports_in_firewall_group = \ mock.Mock(return_value=[self.vm_port, self.router_port]) log_db_api.fw_plugin_db. \ get_fwg_attached_to_port = mock.Mock(return_value='fwg_id') with mock.patch.object(port_objects.Port, 'get_object', side_effect=[self.fake_vm_port, self.fake_router_port]): logged_port_ids = \ log_db_api._get_ports_being_logged(self.context, log_obj) self.assertEqual([self.router_port], logged_port_ids) # Test with inactive router port log_db_api.fw_plugin_db.get_ports_in_firewall_group = \ mock.Mock(return_value=[self.router_port]) log_db_api.fw_plugin_db. \ get_fwg_attached_to_port = mock.Mock(return_value='fwg_id') with mock.patch.object(port_objects.Port, 'get_object', return_value=self.fake_router_port): logged_port_ids = \ log_db_api._get_ports_being_logged(self.context, log_obj) self.assertEqual([self.router_port], logged_port_ids) def test_get_ports_being_logged_with_ports_in_tenant(self): tenant_id = uuidutils.generate_uuid() log_obj = _create_log_object(tenant_id) log_db_api.fw_plugin_db.get_fwg_ports_in_tenant = \ mock.Mock(return_value=[self.router_port]) log_db_api.fw_plugin_db. \ get_fwg_attached_to_port = mock.Mock(return_value='fwg_id') with mock.patch.object(port_objects.Port, 'get_object', return_value=self.fake_router_port): log_db_api._get_ports_being_logged(self.context, log_obj) log_db_api.fw_plugin_db.get_fwg_ports_in_tenant.\ assert_called_with(self.context, tenant_id) def test_logs_for_port_with_vm_port(self): with mock.patch.object(port_objects.Port, 'get_object', return_value=self.fake_vm_port): logs = log_db_api.get_logs_for_port(self.context, self.vm_port) self.assertEqual([], logs) def test_logs_for_port_with_router_port(self): tenant_id = uuidutils.generate_uuid() resource_id = uuidutils.generate_uuid() target_id = uuidutils.generate_uuid() log_db_api.fw_plugin_db.get_fwg_attached_to_port = \ mock.Mock(side_effect=[[], resource_id, resource_id]) with mock.patch.object(port_objects.Port, 'get_object', return_value=self.fake_router_port): # Test with router port that did not attach to fwg logs = log_db_api.get_logs_for_port(self.context, self.router_port) self.assertEqual([], logs) # Test with router port that attached to fwg # Fake log objects that bounds a given port log = _create_log_object(tenant_id) resource_log = _create_log_object(tenant_id, resource_id) target_log = _create_log_object(tenant_id, resource_id, target_id) log_objs = [log, target_log, resource_log] with mock.patch.object(log_object.Log, 'get_objects', return_value=log_objs): self.fake_router_port = mock.Mock(return_value=target_id) logs = log_db_api.get_logs_for_port(self.context, self.router_port) self.assertEqual(log_objs, logs) # Fake log objects that does not bound a given port unbound_resource = uuidutils.generate_uuid() resource_log = _create_log_object(tenant_id, unbound_resource) target_log = _create_log_object(tenant_id, unbound_resource, target_id) log_objs = [log, target_log, resource_log] with mock.patch.object(log_object.Log, 'get_objects', return_value=log_objs): self.fake_router_port = mock.Mock(return_value=target_id) logs = log_db_api.get_logs_for_port(self.context, self.router_port) self.assertEqual([log], logs) def test_logs_for_fwg(self): tenant_id = uuidutils.generate_uuid() resource_id = uuidutils.generate_uuid() target_id = uuidutils.generate_uuid() # Fake log objects that bounds a given fwg log = _create_log_object(tenant_id) resource_log = _create_log_object(tenant_id, resource_id) target_log = _create_log_object(tenant_id, target_id=target_id) ports_delta = [target_id] # Test with port that in ports_delta log_db_api.fw_plugin_db.get_fwg_attached_to_port = \ mock.Mock(return_value=None) with mock.patch.object(log_object.Log, 'get_objects', return_value=[target_log]): logs = log_db_api.get_logs_for_fwg(self.context, resource_id, ports_delta) self.assertEqual([target_log], logs) # Test with log that bound to a give fwg with mock.patch.object(log_object.Log, 'get_objects', return_value=[resource_log]): logs = log_db_api.get_logs_for_fwg(self.context, resource_id, ports_delta) self.assertEqual([resource_log], logs) # Test with log that does not bound to any fwg or port with mock.patch.object(log_object.Log, 'get_objects', return_value=[log]): logs = log_db_api.get_logs_for_fwg(self.context, resource_id, ports_delta) self.assertEqual([log], logs)