# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
#
# 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 mock

import time

import logging
from oslo_config import cfg

from networking_vsphere.agent import ovsvapp_agent
from networking_vsphere.common import constants as ovsvapp_const
from networking_vsphere.common import error
from networking_vsphere.tests import base
from networking_vsphere.tests.unit.drivers import fake_manager
from networking_vsphere.utils import resource_util

from neutron.agent.common import ovs_lib
from neutron.common import utils as n_utils
from neutron.plugins.common import constants as p_const
from neutron.plugins.common import utils as p_utils
from neutron.plugins.ml2.drivers.openvswitch.agent import ovs_neutron_agent as ovs_agent  # noqa
from neutron.plugins.ml2.drivers.openvswitch.agent import vlanmanager

NETWORK_ID = 'fake_net_id'
VNIC_ADDED = 'VNIC_ADDED'
FAKE_DEVICE_ID = 'fake_device_id'
FAKE_VM = 'fake_vm'
FAKE_HOST_1 = 'fake_host_1'
FAKE_HOST_2 = 'fake_host_2'
FAKE_CLUSTER_MOID = 'fake_cluster_moid'
FAKE_CLUSTER_1 = 'fake_cluster_1'
FAKE_CLUSTER_2 = 'fake_cluster_2'
FAKE_VCENTER = 'fake_vcenter'
FAKE_PORT_1 = 'fake_port_1'
FAKE_PORT_2 = 'fake_port_2'
FAKE_PORT_3 = 'fake_port_3'
FAKE_PORT_4 = 'fake_port_4'
MAC_ADDRESS = '01:02:03:04:05:06'
FAKE_CONTEXT = 'fake_context'
FAKE_SG = {'fake_sg': 'fake_sg_rule'}

FAKE_SG_RULE = {'security_group_source_groups': ['fake_rule_1',
                                                 'fake_rule_2',
                                                 'fake_rule_3'],
                'security_group_rules': [
                {'ethertype': 'IPv4',
                 'direction': 'egress',
                 'security_group_id': 'fake_id'
                 }],
                'sg_provider_rules': [
                {'ethertype': 'IPv4',
                 'direction': 'egress',
                 'source_port_range_min': 67,
                 'source_port_range_max': 67,
                 'port_range_min': 68,
                 'port_range_max': 68
                 }]
                }

FAKE_SG_RULES = {FAKE_PORT_1: FAKE_SG_RULE}

FAKE_SG_RULES_MULTI_PORTS = {FAKE_PORT_1: FAKE_SG_RULE,
                             FAKE_PORT_2: FAKE_SG_RULE
                             }

FAKE_SG_RULES_MISSING = {FAKE_PORT_1: {'security_group_source_groups': [
                                       'fake_rule_1',
                                       'fake_rule_2',
                                       'fake_rule_3'],
                                       'sg_provider_rules': [],
                                       'security_group_rules': [
                                       {'ethertype': 'IPv4',
                                        'direction': 'egress'
                                        }]
                                       }
                         }

FAKE_SG_RULES_PARTIAL = {FAKE_PORT_1: {'security_group_source_groups': [
                                       'fake_rule_1',
                                       'fake_rule_2',
                                       'fake_rule_3'],
                                       'sg_provider_rules': [],
                                       'security_group_rules': [
                                       {'ethertype': 'IPv4',
                                        'direction': 'egress',
                                        'port_range_min': 22,
                                        'port_range_max': 22
                                        }]
                                       }
                         }


DEVICE = {'id': FAKE_DEVICE_ID,
          'cluster_id': FAKE_CLUSTER_1,
          'host': FAKE_HOST_1,
          'vcenter': FAKE_VCENTER}


class SampleEvent(object):
    def __init__(self, type, host, cluster, srcobj, host_changed=False):
        self.event_type = type
        self.host_name = host
        self.cluster_id = cluster
        self.src_obj = srcobj
        self.host_changed = host_changed


class VM(object):
    def __init__(self, uuid, vnics):
        self.uuid = uuid
        self.vnics = vnics


class SamplePort(object):
    def __init__(self, port_uuid, mac_address=None, pg_id=None):
        self.port_uuid = port_uuid
        self.mac_address = mac_address
        self.pg_id = pg_id


class SamplePortUIDMac(object):
    def __init__(self, port_uuid, mac_address):
        self.port_uuid = port_uuid
        self.mac_address = mac_address


class TestOVSvAppAgentRestart(base.TestCase):

    @mock.patch('neutron.common.config.init')
    @mock.patch('neutron.common.config.setup_logging')
    @mock.patch('neutron.agent.ovsdb.api.'
                'API.get')
    @mock.patch('networking_vsphere.agent.ovsvapp_agent.RpcPluginApi')
    @mock.patch('neutron.agent.securitygroups_rpc.SecurityGroupServerRpcApi')
    @mock.patch('neutron.agent.rpc.PluginReportStateAPI')
    @mock.patch('networking_vsphere.agent.ovsvapp_agent.OVSvAppPluginApi')
    @mock.patch('neutron.context.get_admin_context_without_session')
    @mock.patch('neutron.agent.rpc.create_consumers')
    @mock.patch('neutron.plugins.ml2.drivers.openvswitch.agent.'
                'ovs_neutron_agent.OVSNeutronAgent.setup_integration_br')
    @mock.patch('networking_vsphere.agent.ovsvapp_agent.'
                'OVSvAppAgent.setup_ovs_bridges')
    @mock.patch('networking_vsphere.agent.ovsvapp_agent.'
                'OVSvAppAgent.setup_security_br')
    @mock.patch('networking_vsphere.agent.ovsvapp_agent.'
                'OVSvAppAgent._init_ovs_flows')
    @mock.patch('networking_vsphere.drivers.ovs_firewall.OVSFirewallDriver.'
                'check_ovs_firewall_restart')
    @mock.patch('networking_vsphere.drivers.ovs_firewall.'
                'OVSFirewallDriver.setup_base_flows')
    @mock.patch('neutron.agent.common.ovs_lib.OVSBridge.create')
    @mock.patch('neutron.agent.common.ovs_lib.OVSBridge.set_secure_mode')
    @mock.patch('neutron.agent.common.ovs_lib.OVSBridge.get_port_ofport')
    @mock.patch('networking_vsphere.agent.ovsvapp_agent.OVSvAppAgent.__init__')
    def setUp(self, mock_ovs_init, mock_get_port_ofport,
              mock_set_secure_mode, mock_create_ovs_bridge,
              mock_setup_base_flows, mock_check_ovs_firewall_restart,
              mock_init_ovs_flows, mock_setup_security_br,
              mock_setup_ovs_bridges,
              mock_setup_integration_br, mock_create_consumers,
              mock_get_admin_context_without_session, mock_ovsvapp_pluginapi,
              mock_plugin_report_stateapi, mock_securitygroup_server_rpcapi,
              mock_rpc_pluginapi, mock_ovsdb_api, mock_setup_logging,
              mock_init):
        super(TestOVSvAppAgentRestart, self).setUp()
        cfg.CONF.set_override('security_bridge_mapping',
                              "fake_sec_br:fake_if", 'SECURITYGROUP')
        mock_get_port_ofport.return_value = 5
        mock_ovs_init.return_value = None
        self.agent = ovsvapp_agent.OVSvAppAgent()
        self.agent.run_refresh_firewall_loop = False
        self.LOG = ovsvapp_agent.LOG
        self.agent.monitor_log = logging.getLogger('monitor')

    def test_check_ovsvapp_agent_restart(self):
        self.agent.int_br = mock.Mock()
        with mock.patch.object(self.agent.int_br, 'bridge_exists',
                               return_value=True) as mock_br_exists, \
                mock.patch.object(self.agent.int_br, 'dump_flows_for_table',
                                  return_value='') as mock_dump_flows:
            self.assertFalse(self.agent.check_ovsvapp_agent_restart())
            self.assertTrue(mock_br_exists.called)
            self.assertTrue(mock_dump_flows.called)
            mock_dump_flows.return_value = 'cookie = 0x0'
            self.assertTrue(self.agent.check_ovsvapp_agent_restart())
            self.assertTrue(mock_br_exists.called)
            self.assertTrue(mock_dump_flows.called)


class TestOVSvAppAgent(base.TestCase):

    @mock.patch('neutron.common.config.init')
    @mock.patch('neutron.common.config.setup_logging')
    @mock.patch('neutron.agent.ovsdb.api.'
                'API.get')
    @mock.patch('networking_vsphere.agent.ovsvapp_agent.RpcPluginApi')
    @mock.patch('neutron.agent.securitygroups_rpc.SecurityGroupServerRpcApi')
    @mock.patch('neutron.agent.rpc.PluginReportStateAPI')
    @mock.patch('networking_vsphere.agent.ovsvapp_agent.OVSvAppPluginApi')
    @mock.patch('neutron.context.get_admin_context_without_session')
    @mock.patch('neutron.agent.rpc.create_consumers')
    @mock.patch('neutron.plugins.ml2.drivers.openvswitch.agent.'
                'ovs_neutron_agent.OVSNeutronAgent.setup_integration_br')
    @mock.patch('networking_vsphere.agent.ovsvapp_agent.'
                'OVSvAppAgent.check_ovsvapp_agent_restart')
    @mock.patch('networking_vsphere.agent.ovsvapp_agent.'
                'OVSvAppAgent.setup_ovs_bridges')
    @mock.patch('networking_vsphere.agent.ovsvapp_agent.'
                'OVSvAppAgent.setup_security_br')
    @mock.patch('networking_vsphere.agent.ovsvapp_agent.'
                'OVSvAppAgent._init_ovs_flows')
    @mock.patch('networking_vsphere.drivers.ovs_firewall.OVSFirewallDriver.'
                'check_ovs_firewall_restart')
    @mock.patch('networking_vsphere.drivers.ovs_firewall.'
                'OVSFirewallDriver.setup_base_flows')
    @mock.patch('neutron.agent.common.ovs_lib.OVSBridge.create')
    @mock.patch('neutron.agent.common.ovs_lib.OVSBridge.set_secure_mode')
    @mock.patch('neutron.agent.common.ovs_lib.OVSBridge.get_port_ofport')
    def setUp(self, mock_get_port_ofport,
              mock_set_secure_mode, mock_create_ovs_bridge,
              mock_setup_base_flows, mock_check_ovs_firewall_restart,
              mock_init_ovs_flows, mock_setup_security_br,
              mock_setup_ovs_bridges, mock_check_ovsvapp_agent_restart,
              mock_setup_integration_br, mock_create_consumers,
              mock_get_admin_context_without_session, mock_ovsvapp_pluginapi,
              mock_plugin_report_stateapi, mock_securitygroup_server_rpcapi,
              mock_rpc_pluginapi, mock_ovsdb_api, mock_setup_logging,
              mock_init):
        super(TestOVSvAppAgent, self).setUp()
        cfg.CONF.set_override('security_bridge_mapping',
                              "fake_sec_br:fake_if", 'SECURITYGROUP')
        mock_check_ovsvapp_agent_restart.return_value = False
        mock_get_port_ofport.return_value = 5
        self.agent = ovsvapp_agent.OVSvAppAgent()
        self.agent.run_refresh_firewall_loop = False
        self.LOG = ovsvapp_agent.LOG
        self.agent.monitor_log = logging.getLogger('monitor')

    def _build_port(self, port):
        port = {'admin_state_up': False,
                'id': port,
                'device': DEVICE,
                'network_id': NETWORK_ID,
                'physical_network': 'physnet1',
                'segmentation_id': '1001',
                'lvid': 1,
                'network_type': 'vlan',
                'fixed_ips': [{'subnet_id': 'subnet_uuid',
                               'ip_address': '1.1.1.1'}],
                'device_owner': 'compute:None',
                'security_groups': FAKE_SG,
                'mac_address': MAC_ADDRESS,
                'device_id': FAKE_DEVICE_ID
                }
        return port

    def _build_update_port(self, port):
        port = {'admin_state_up': False,
                'id': port,
                'network_id': NETWORK_ID,
                'fixed_ips': [{'subnet_id': 'subnet_uuid',
                               'ip_address': '1.1.1.1'}],
                'device_owner': 'compute:None',
                'security_groups': FAKE_SG,
                'mac_address': MAC_ADDRESS,
                'device_id': FAKE_DEVICE_ID
                }
        return port

    def test_setup_security_br_none(self):
        cfg.CONF.set_override('security_bridge_mapping',
                              None, 'SECURITYGROUP')
        self.agent.sec_br = mock.Mock()
        with mock.patch.object(self.LOG, 'warning') as mock_logger_warn,\
                mock.patch.object(self.agent.sec_br, 'bridge_exists'
                                  ) as mock_ovs_bridge:
            self.assertRaises(SystemExit,
                              self.agent.setup_security_br)
            self.assertTrue(mock_logger_warn.called)
            self.assertFalse(mock_ovs_bridge.called)

    def test_setup_security_br(self):
        cfg.CONF.set_override('security_bridge_mapping',
                              "br-fake:fake_if", 'SECURITYGROUP')
        self.agent.sec_br = mock.Mock()
        self.agent.int_br = mock.Mock()
        with mock.patch.object(self.LOG, 'info') as mock_logger_info, \
                mock.patch.object(ovs_lib, "OVSBridge") as mock_ovs_br, \
                mock.patch.object(self.agent.sec_br,
                                  "add_patch_port",
                                  return_value=5), \
                mock.patch.object(self.agent.int_br,
                                  "add_patch_port",
                                  return_value=6):
            self.agent.setup_security_br()
            self.assertTrue(mock_ovs_br.called)
            self.assertTrue(self.agent.sec_br.add_patch_port.called)
            self.assertTrue(mock_logger_info.called)

    def test_recover_security_br_none(self):
        cfg.CONF.set_override('security_bridge_mapping',
                              None, 'SECURITYGROUP')
        self.agent.sec_br = mock.Mock()
        with mock.patch.object(self.LOG, 'warning') as mock_logger_warn, \
                mock.patch.object(self.agent.sec_br, 'bridge_exists'
                                  ) as mock_ovs_bridge:
            self.assertRaises(SystemExit,
                              self.agent.recover_security_br)
            self.assertTrue(mock_logger_warn.called)
            self.assertFalse(mock_ovs_bridge.called)

    @mock.patch('neutron.agent.common.ovs_lib.OVSBridge')
    def test_recover_security_br(self, mock_ovs_bridge):
        cfg.CONF.set_override('security_bridge_mapping',
                              "br-sec:physnet1", 'SECURITYGROUP')
        self.agent.int_br = mock.Mock()
        self.agent.sec_br = mock.Mock()
        mock_br = mock_ovs_bridge.return_value
        with mock.patch.object(self.LOG, 'info') as mock_logger_info, \
                mock.patch.object(mock_br, 'bridge_exists'), \
                mock.patch.object(mock_br, 'add_patch_port') as mock_add_patch_port, \
                mock.patch.object(self.agent.int_br,
                                  "get_port_ofport",
                                  return_value=6), \
                mock.patch.object(mock_br,
                                  "get_port_ofport",
                                  return_value=6), \
                mock.patch.object(mock_br,
                                  "delete_port") as mock_delete_port:
            mock_br.get_bridge_for_iface.return_value = 'br-sec'
            self.agent.recover_security_br()
            self.assertTrue(mock_logger_info.called)
            self.assertFalse(mock_delete_port.called)
            self.assertFalse(mock_add_patch_port.called)
            mock_br.get_bridge_for_iface.return_value = 'br-fake'
            self.agent.recover_security_br()
            self.assertTrue(mock_logger_info.called)
            self.assertTrue(mock_delete_port.called)
            self.assertTrue(mock_add_patch_port.called)

    @mock.patch('neutron.agent.ovsdb.api.'
                'API.get')
    def test_recover_physical_bridges(self, mock_ovsdb_api):
        cfg.CONF.set_override('bridge_mappings',
                              ["physnet1:br-eth1"], 'OVSVAPP')
        self.agent.bridge_mappings = n_utils.parse_mappings(
            cfg.CONF.OVSVAPP.bridge_mappings)
        with mock.patch.object(self.LOG, 'info') as mock_logger_info, \
                mock.patch.object(self.LOG, 'error') as mock_logger_error, \
                mock.patch.object(self.agent, "br_phys_cls") as mock_ovs_br, \
                mock.patch.object(ovs_lib.BaseOVS,
                                  "get_bridges",
                                  return_value=['br-eth1']
                                  ), \
                mock.patch.object(p_utils, 'get_interface_name'
                                  ) as mock_int_name, \
                mock.patch.object(self.agent.int_br,
                                  "get_port_ofport",
                                  return_value=6) as mock_get_ofport:
            self.agent.recover_physical_bridges(self.agent.bridge_mappings)
            self.assertTrue(mock_logger_info.called)
            self.assertFalse(mock_logger_error.called)
            self.assertTrue(mock_ovs_br.called)
            self.assertTrue(mock_get_ofport.called)
            self.assertTrue(mock_int_name.called)
            self.assertEqual(self.agent.int_ofports['physnet1'], 6)

    def test_init_ovs_flows(self):
        cfg.CONF.set_override('bridge_mappings',
                              ["physnet1:br-eth1"], 'OVSVAPP')
        self.agent.bridge_mappings = n_utils.parse_mappings(
            cfg.CONF.OVSVAPP.bridge_mappings)
        self.agent.patch_sec_ofport = 5
        self.agent.int_ofports = {'physnet1': 'br-eth1'}
        self.agent.phys_ofports = {"physnet1": "br-eth1"}
        port = self._build_port(FAKE_PORT_1)
        br = self._build_phys_brs(port)
        self.agent.br = mock.Mock()
        with mock.patch.object(self.agent.int_br,
                               "delete_flows"
                               ) as mock_int_br_delete_flows, \
            mock.patch.object(self.agent,
                              "br_phys_cls") as mock_ovs_br, \
            mock.patch.object(self.agent.int_br,
                              "add_flow") as mock_int_br_add_flow:
            self.agent._init_ovs_flows(self.agent.bridge_mappings)
            self.assertTrue(mock_int_br_delete_flows.called)
            self.assertTrue(mock_ovs_br.called)
            self.assertTrue(br.delete_flows.called)
            self.assertTrue(br.add_flows.called)
            self.assertTrue(mock_int_br_add_flow.called)

    def test_update_port_bindings(self):
        self.agent.ports_to_bind.add("fake_port")
        with mock.patch.object(self.agent.ovsvapp_rpc,
                               "update_ports_binding",
                               return_value=set(["fake_port"])
                               ) as mock_update_ports_binding, \
                mock.patch.object(self.LOG, 'exception'
                                  ) as mock_log_exception:
            self.agent._update_port_bindings()
            self.assertTrue(mock_update_ports_binding.called)
            self.assertFalse(self.agent.ports_to_bind)
            self.assertFalse(mock_log_exception.called)

    def test_update_port_bindings_rpc_exception(self):
        self.agent.ports_to_bind.add("fake_port")
        with mock.patch.object(self.agent.ovsvapp_rpc,
                               "update_ports_binding",
                               side_effect=Exception()
                               ) as mock_update_port_binding, \
                mock.patch.object(self.LOG, 'exception'
                                  ) as mock_log_exception:
            self.assertRaises(
                error.OVSvAppNeutronAgentError,
                self.agent._update_port_bindings)
            self.assertTrue(mock_update_port_binding.called)
            self.assertTrue(mock_log_exception.called)
            self.assertEqual(set(['fake_port']),
                             self.agent.ports_to_bind)

    def test_update_port_bindings_partial(self):
        self.agent.ports_to_bind.add("fake_port1")
        self.agent.ports_to_bind.add("fake_port2")
        self.agent.ports_to_bind.add("fake_port3")
        with mock.patch.object(self.agent.ovsvapp_rpc,
                               "update_ports_binding",
                               return_value=set(["fake_port1",
                                                "fake_port2"])
                               ) as mock_update_port_binding, \
                mock.patch.object(self.LOG, 'exception'):
            self.agent._update_port_bindings()
            self.assertTrue(mock_update_port_binding.called)
            self.assertEqual(set(["fake_port3"]),
                             self.agent.ports_to_bind)

    def test_setup_ovs_bridges_vlan(self):
        cfg.CONF.set_override('tenant_network_types',
                              "vlan", 'OVSVAPP')
        cfg.CONF.set_override('bridge_mappings',
                              ["physnet1:br-eth1"], 'OVSVAPP')
        with mock.patch.object(self.agent, 'setup_physical_bridges'
                               ) as mock_phys_brs, \
                mock.patch.object(self.agent, '_init_ovs_flows'
                                  ) as mock_init_ovs_flows:
            self.agent.setup_ovs_bridges()
            mock_phys_brs.assert_called_with(self.agent.bridge_mappings)
            mock_init_ovs_flows.assert_called_with(self.agent.bridge_mappings)

    @mock.patch('neutron.agent.ovsdb.api.'
                'API.get')
    def test_setup_ovs_bridges_vxlan(self, mock_ovsdb_api):
        self.agent.local_ip = "10.10.10.10"
        self.agent.tenant_network_types = [p_const.TYPE_VXLAN]
        with mock.patch.object(self.agent, 'setup_tunnel_br'
                               ) as mock_setup_tunnel_br, \
                mock.patch.object(self.agent, 'setup_tunnel_br_flows'
                                  ) as mock_setup_tunnel_br_flows:
            self.agent.setup_ovs_bridges()
            mock_setup_tunnel_br.assert_called_with("br-tun")
            self.assertTrue(mock_setup_tunnel_br_flows.called)

    def test_setup_ovs_bridges_vxlan_ofport(self):
        cfg.CONF.set_override('tenant_network_types',
                              "vxlan", 'OVSVAPP')
        cfg.CONF.set_override('local_ip',
                              "10.10.10.10", 'OVSVAPP')
        cfg.CONF.set_override('tunnel_bridge',
                              "br-tun", 'OVSVAPP')
        self.agent.tun_br = mock.Mock()
        self.agent.int_br = mock.Mock()
        self.agent.local_ip = "10.10.10.10"
        self.agent.tenant_network_types = [p_const.TYPE_VXLAN]
        with mock.patch.object(self.agent.tun_br,
                               "add_patch_port",
                               return_value=5), \
                mock.patch.object(self.agent.int_br,
                                  "add_patch_port",
                                  return_value=6), \
                mock.patch.object(self.agent, 'setup_tunnel_br_flows'
                                  ) as mock_setup_tunnel_br_flows:
            self.agent.setup_ovs_bridges()
            self.assertTrue(self.agent.tun_br.add_patch_port.called)
            self.assertEqual(self.agent.patch_tun_ofport, 6)
            self.assertEqual(self.agent.patch_int_ofport, 5)
            self.assertTrue(mock_setup_tunnel_br_flows.called)

    def test_mitigate_ovs_restart_vlan(self):
        self.agent.refresh_firewall_required = False
        self.agent.devices_to_filter = set(['1111'])
        self.agent.cluster_host_ports = set(['1111'])
        self.agent.cluster_other_ports = set(['2222'])
        with mock.patch.object(self.LOG, 'info') as mock_logger_info, \
                mock.patch.object(self.agent, "setup_integration_br"
                                  ) as mock_int_br, \
                mock.patch.object(self.agent, "setup_physical_bridges"
                                  ) as mock_phys_brs, \
                mock.patch.object(self.agent, "setup_security_br"
                                  ) as mock_sec_br, \
                mock.patch.object(self.agent.sg_agent, "init_firewall"
                                  ) as mock_init_fw, \
                mock.patch.object(self.agent, "setup_tunnel_br"
                                  ) as mock_setup_tunnel_br,\
                mock.patch.object(self.agent, 'setup_tunnel_br_flows'
                                  ) as mock_setup_tunnel_br_flows, \
                mock.patch.object(self.agent, "_init_ovs_flows"
                                  ) as mock_init_flows, \
                mock.patch.object(self.agent.monitor_log, "warning"
                                  ) as monitor_warning, \
                mock.patch.object(self.agent.monitor_log, "info"
                                  ) as monitor_info:
            self.agent.mitigate_ovs_restart()
            self.assertTrue(mock_int_br.called)
            self.assertTrue(mock_phys_brs.called)
            self.assertTrue(mock_sec_br.called)
            self.assertFalse(mock_setup_tunnel_br.called)
            self.assertFalse(mock_setup_tunnel_br_flows.called)
            self.assertTrue(mock_init_fw.called)
            self.assertTrue(mock_init_flows.called)
            self.assertTrue(self.agent.refresh_firewall_required)
            self.assertEqual(2, len(self.agent.devices_to_filter))
            monitor_warning.assert_called_with("ovs: broken")
            monitor_info.assert_called_with("ovs: ok")
            self.assertTrue(mock_logger_info.called)

    def test_mitigate_ovs_restart_vxlan(self):
        self.agent.enable_tunneling = True
        self.agent.refresh_firewall_required = False
        self.agent.devices_to_filter = set(['1111'])
        self.agent.cluster_host_ports = set(['1111'])
        self.agent.cluster_other_ports = set(['2222'])
        with mock.patch.object(self.LOG, 'info') as mock_logger_info, \
                mock.patch.object(self.agent, "setup_integration_br"), \
                mock.patch.object(self.agent, "setup_physical_bridges"
                                  ) as mock_phys_brs, \
                mock.patch.object(self.agent, "setup_security_br"), \
                mock.patch.object(self.agent.sg_agent, "init_firewall"
                                  ), \
                mock.patch.object(self.agent, "setup_tunnel_br"
                                  ) as mock_setup_tunnel_br,\
                mock.patch.object(self.agent, 'setup_tunnel_br_flows'
                                  ) as mock_setup_tunnel_br_flows, \
                mock.patch.object(self.agent, "tunnel_sync"
                                  ) as mock_tun_sync, \