text: # Copyright 2015 Cisco Systems.
  # 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 collections
  
  from oslo_serialization import jsonutils
  
  import mock
  
  from neutron.tests import base
  
  from networking_cisco.apps.saf.agent.vdp import dfa_vdp_mgr
  from networking_cisco.apps.saf.agent.vdp import ovs_vdp
  from networking_cisco.apps.saf.common import constants
  from networking_cisco.apps.saf.common import dfa_sys_lib as utils
  from networking_cisco.apps.saf.common import utils as common_utils
  
  try:
      OrderedDict = collections.OrderedDict
  except AttributeError:
      import ordereddict
      OrderedDict = ordereddict.OrderedDict
  
  
  class DfaVdpMgrTest(base.BaseTestCase):
      """A test suite to exercise the DfaVdpMgr Class.  """
  
      def setUp(self):
          '''Setup routine '''
          super(DfaVdpMgrTest, self).setUp()
          self.root_helper = 'sudo'
          self.port_name = "loc_veth"
          self.uplink = "eth2"
          self.port_str = "loc_veth_eth2"
          self.br_integ = 'br-int1'
          self.br_ex = 'br-ethd1'
          self.rpc_client = mock.Mock()
          self.host = 'hostabc'
          self.config_dict = {'integration_bridge': self.br_integ,
                              'external_bridge': self.br_ex,
                              'root_helper': self.root_helper,
                              'node_list': 'hostabc',
                              'node_uplink_list': self.uplink}
          self.execute = mock.patch.object(
              utils, "execute", spec=utils.execute).start()
          mock.patch('time.sleep').start()
          self.topo_disc = mock.patch(
              'networking_cisco.apps.saf.agent.topo_disc.topo_disc.'
              'TopoDisc').start()
          self._test_dfa_mgr_init()
  
      def _test_dfa_mgr_init(self):
          '''Test routine for init '''
          with mock.patch('networking_cisco.apps.saf.common.utils.'
                          'EventProcessingThread') as event_fn,\
                  mock.patch('networking_cisco.apps.saf.common.'
                             'utils.PeriodicTask') as period_fn:
              event_obj = event_fn.return_value
              period_obj = period_fn.return_value
              parent = mock.MagicMock()
              parent.attach_mock(event_obj.start, 'start')
              parent.attach_mock(period_obj.run, 'run')
              self.dfa_vdp_mgr = dfa_vdp_mgr.VdpMgr(self.config_dict,
                                                    self.rpc_client,
                                                    self.host)
          event_fn.assert_called_with("VDP_Mgr", self.dfa_vdp_mgr,
                                      'process_queue')
          period_fn.assert_any_call(constants.ERR_PROC_INTERVAL,
                                    self.dfa_vdp_mgr.process_err_queue)
          period_fn.assert_any_call(constants.UPLINK_DET_INTERVAL,
                                    self.dfa_vdp_mgr.vdp_uplink_proc_top)
          expected_calls = [mock.call.start(), mock.call.run(), mock.call.run()]
          parent.assert_has_calls(expected_calls)
  
      def _setup_uplink_msg(self, status):
          '''construct the uplink message '''
          msg = dfa_vdp_mgr.VdpQueMsg(constants.UPLINK_MSG_TYPE, status=status,
                                      phy_uplink=self.uplink,
                                      br_int=self.br_integ,
                                      br_ex=self.br_ex,
                                      root_helper=self.root_helper)
          return msg
  
      def _setup_vm_msg(self, status):
          '''construct the VM message '''
          msg = dfa_vdp_mgr.VdpQueMsg(constants.VM_MSG_TYPE,
                                      port_uuid='0000-1111-2222-3333',
                                      vm_mac='00:00:fa:11:22:33',
                                      net_uuid='0000-aaaa-bbbb-cccc',
                                      segmentation_id=10001, status=status,
                                      oui=None, phy_uplink=self.uplink)
          return msg
  
      def _setup_bulk_vm_msg(self, status):
          """construct the Bulk VM message. """
          vm_dict = self._construct_vm_dict(status)
          msg = dfa_vdp_mgr.VdpQueMsg(constants.VM_BULK_SYNC_MSG_TYPE,
                                      vm_bulk_list=[vm_dict],
                                      phy_uplink=self.uplink)
          return msg
  
      def _construct_vm_dict(self, status):
          """Construct a sample VM dict. """
          vm_dict = {'status': status, 'port_uuid': '0000-1111-2222-3333',
                     'vm_mac': '00:00:fa:11:22:33',
                     'net_uuid': '0000-aaaa-bbbb-cccc', 'vdp_vlan': 3005,
                     'segmentation_id': 10001, 'oui': None, 'local_vlan': 10,
                     'phy_uplink': self.uplink}
          return vm_dict
  
      def _test_process_up_uplink_event(self):
          '''Test routine when a uplink is detected '''
          msg = self._setup_uplink_msg('up')
          self.dfa_vdp_mgr.phy_uplink = self.uplink
          with mock.patch('networking_cisco.apps.saf.agent.'
                          'vdp.ovs_vdp.OVSNeutronVdp') as ovs_vdp_fn, \
              mock.patch.object(self.dfa_vdp_mgr, 'save_uplink') as (
                  save_uplink_fn), \
              mock.patch.object(
                  self.dfa_vdp_mgr.topo_disc, 'uncfg_intf') as uncfg_intf_fn, \
              mock.patch.object(
                  self.dfa_vdp_mgr.topo_disc, 'cfg_intf') as cfg_intf_fn:
              self.dfa_vdp_mgr.process_uplink_event(msg, self.uplink)
          veth_val = self.dfa_vdp_mgr.ovs_vdp_obj_dict[
              self.uplink].get_lldp_local_bridge_port()
          ovs_vdp_fn.assert_called_with(self.uplink, self.br_integ, self.br_ex,
                                        self.root_helper,
                                        self.dfa_vdp_mgr.vdp_vlan_change_cb)
          save_uplink_fn.assert_called_with(
              uplink=self.uplink, veth_intf=veth_val)
          uncfg_intf_fn.assert_called_with(self.uplink)
          cfg_intf_fn.assert_called_with(
              self.dfa_vdp_mgr.ovs_vdp_obj_dict[
                  self.uplink].get_lldp_local_bridge_port(),
              phy_interface=self.uplink)
  
      def test_process_up_uplink_event_lldp_fail(self):
          """Test routine when a uplink is detected and lldp is down. """
          msg = self._setup_uplink_msg('up')
          self.dfa_vdp_mgr.phy_uplink = self.uplink
          with mock.patch('networking_cisco.apps.saf.agent.'
                          'vdp.ovs_vdp.OVSNeutronVdp') as ovs_vdp_fn, \
              mock.patch.object(self.dfa_vdp_mgr.err_que, 'enqueue') as enq, \
              mock.patch.object(
                  self.dfa_vdp_mgr, 'save_uplink') as save_uplink_fn:
              ovs_vdp_fn.return_value.is_lldpad_setup_done.return_value = False
              ovs_vdp_fn.return_value.get_uplink_fail_reason.return_value = (
                  'Some Reason')
              self.dfa_vdp_mgr.process_uplink_event(msg, self.uplink)
          ovs_vdp_fn.assert_called_with(self.uplink, self.br_integ, self.br_ex,
                                        self.root_helper,
                                        self.dfa_vdp_mgr.vdp_vlan_change_cb)
          save_uplink_fn.assert_called_with(
              uplink=self.uplink, fail_reason='Some Reason')
          enq.assert_called_with(constants.Q_UPL_PRIO, msg)
  
      def _test_process_down_uplink_event(self):
          '''Test routine when a uplink goes down '''
          msg = self._setup_uplink_msg('down')
          self.dfa_vdp_mgr.phy_uplink = self.uplink
          del_flow = mock.patch.object(
              ovs_vdp, "delete_uplink_and_flows",
              spec=ovs_vdp.delete_uplink_and_flows).start()
          with mock.patch.object(self.dfa_vdp_mgr, 'save_uplink') as sav_fn, \
              mock.patch.object(
                  self.dfa_vdp_mgr.topo_disc, 'uncfg_intf') as uncfg_intf_fn, \
              mock.patch.object(
                  self.dfa_vdp_mgr.topo_disc, 'cfg_intf') as cfg_intf_fn:
              parent = mock.MagicMock()
              parent.attach_mock(del_flow, 'delete_uplink_and_flows')
              parent.attach_mock(uncfg_intf_fn, 'uncfg_intf')
              parent.attach_mock(cfg_intf_fn, 'cfg_intf')
              self.dfa_vdp_mgr.process_uplink_event(msg, self.uplink)
          expected_call = [mock.call.delete_uplink_and_flows(self.root_helper,
                                                             self.br_ex,
                                                             self.uplink),
                           mock.call.uncfg_intf(None),
                           mock.call.cfg_intf(self.uplink)]
          parent.assert_has_calls(expected_call)
          sav_fn.assert_called_with()
  
      def _test_process_down_uplink_event_clear(self):
          '''Test routine when a uplink goes down and flow is cleared '''
          msg = self._setup_uplink_msg('down')
          self.dfa_vdp_mgr.phy_uplink = self.uplink
          self.dfa_vdp_mgr.ovs_vdp_obj_dict = {}
          self.dfa_vdp_mgr.ovs_vdp_obj_dict[self.uplink] = mock.Mock()
          with mock.patch.object(self.dfa_vdp_mgr.ovs_vdp_obj_dict[self.uplink],
                                 'clear_obj_params') as vdp_clear_fn, \
              mock.patch.object(self.dfa_vdp_mgr, 'save_uplink') as sav_fn, \
              mock.patch.object(
                  self.dfa_vdp_mgr.topo_disc, 'uncfg_intf') as uncfg_intf_fn, \
              mock.patch.object(
                  self.dfa_vdp_mgr.topo_disc, 'cfg_intf') as cfg_intf_fn:
              self.dfa_vdp_mgr.process_uplink_event(msg, self.uplink)
          vdp_clear_fn.assert_called_with()
          sav_fn.assert_called_with()
          uncfg_intf_fn.assert_called_with(None)
          cfg_intf_fn.assert_called_with(self.uplink)
  
      def _test_process_vm_event_succ(self):
          '''Test routine for VM event process is successful '''
          msg = self._setup_vm_msg('up')
          lvid = 10
          vdp_vlan = 3000
          self.dfa_vdp_mgr.uplink_det_compl = True
          port_reply = {'result': True, 'fail_reason': None}
          self.dfa_vdp_mgr.ovs_vdp_obj_dict = {self.uplink: mock.Mock()}
          with mock.patch.object(
              self.dfa_vdp_mgr, 'update_vm_result') as save_vmres_fn, \
              mock.patch.object(self.dfa_vdp_mgr.ovs_vdp_obj_dict[self.uplink],
                                'send_vdp_port_event',
                                return_value=port_reply), \
              mock.patch.object(self.dfa_vdp_mgr.ovs_vdp_obj_dict[self.uplink],
                                'get_lvid_vdp_vlan',
                                return_value=[lvid, vdp_vlan]):
              self.dfa_vdp_mgr.process_vm_event(msg, self.uplink)
          save_vmres_fn.assert_called_with('0000-1111-2222-3333', 'SUCCESS',
                                           fail_reason=None, lvid=lvid,
                                           vdp_vlan=vdp_vlan)
  
      def _test_process_vm_event_fail(self):
          '''Test routine for VM event process has failed '''
          msg = self._setup_vm_msg('up')
          self.dfa_vdp_mgr.uplink_det_compl = True
          self.dfa_vdp_mgr.ovs_vdp_obj_dict = {self.uplink: mock.Mock()}
          port_reply = {'result': False, 'fail_reason': 'some reason'}
          with mock.patch.object(
              self.dfa_vdp_mgr, 'update_vm_result') as save_vmres_fn, \
              mock.patch.object(self.dfa_vdp_mgr.ovs_vdp_obj_dict[self.uplink],
                                'send_vdp_port_event',
                                return_value=port_reply):
              self.dfa_vdp_mgr.process_vm_event(msg, self.uplink)
          save_vmres_fn.assert_called_with('0000-1111-2222-3333', 'CREATE:FAIL',
                                           fail_reason='some reason')
  
      def test_process_vm_event_uplink_not_rcvd(self):
          """Test for VM event process, when uplink event is not received. """
          msg = self._setup_vm_msg('up')
          self.dfa_vdp_mgr.uplink_det_compl = True
          with mock.patch.object(self.dfa_vdp_mgr, 'update_vm_result') as \
                  save_vmres_fn:
              self.dfa_vdp_mgr.process_vm_event(msg, self.uplink)
          save_vmres_fn.assert_called_with('0000-1111-2222-3333', 'CREATE:FAIL')
  
      def test_process_vm_down_event_uplink_not_rcvd(self):
          """Test for VM down event, when uplink event is not received. """
          msg = self._setup_vm_msg('down')
          self.dfa_vdp_mgr.uplink_det_compl = True
          with mock.patch.object(self.dfa_vdp_mgr, 'update_vm_result') as \
                  save_vmres_fn:
              self.dfa_vdp_mgr.process_vm_event(msg, self.uplink)
          save_vmres_fn.assert_called_with('0000-1111-2222-3333', 'DELETE:FAIL')
  
      def test_process_uplink_event_case1(self):
          '''Top routine that calls the uplink down case '''
          self._test_process_down_uplink_event()
  
      def test_process_uplink_event_case2(self):
          '''Top routine that calls the uplink detect case '''
          self._test_process_up_uplink_event()
          self._test_process_down_uplink_event_clear()
  
      def test_process_vm_event_succ(self):
          '''Top routine that calls process VM event success case '''
          self._test_process_vm_event_succ()
  
      def test_process_vm_event_fail(self):
          '''Top routine that calls process VM event fail case '''
          self._test_process_vm_event_fail()
  
      def test_process_static_uplink_new(self):
          """Test routine for static uplink, first time call."""
          ret = self.dfa_vdp_mgr.static_uplink_detect(None)
          self.assertEqual(ret, self.uplink)
  
      def test_process_static_uplink_normal(self):
          """Test routine for static uplink, normal case."""
          ret = self.dfa_vdp_mgr.static_uplink_detect('veth_temp')
          self.assertEqual(ret, 'normal')
  
      def test_process_static_uplink_down(self):
          """Test routine for static uplink, down case."""
          self.dfa_vdp_mgr.phy_uplink = 'eth3'
          ret = self.dfa_vdp_mgr.static_uplink_detect(None)
          self.assertEqual(ret, 'down')
  
      def test_vdp_vlan_change_cb(self):
          """Function to test the VDP VLAN change Callback. """
          port_uuid = '0000-1111-2222-3333'
          lvid = 10
          vdp_vlan = 3000
          with mock.patch.object(self.dfa_vdp_mgr, 'update_vm_result') as \
                  save_vmres_fn:
              self.dfa_vdp_mgr.vdp_vlan_change_cb(port_uuid, lvid, vdp_vlan,
                                                  'some reason')
          save_vmres_fn.assert_called_with('0000-1111-2222-3333', 'SUCCESS',
                                           lvid=lvid, vdp_vlan=vdp_vlan,
                                           fail_reason='some reason')
  
      def _test_setup_uplink_params_steady(self):
          """Internal function to setup the DFA VDP Mgr parameters. """
          self.dfa_vdp_mgr.is_os_run = True
          self.dfa_vdp_mgr.restart_uplink_called = True
          self.dfa_vdp_mgr.process_uplink_ongoing = False
          self.dfa_vdp_mgr.uplink_det_compl = False
          self.dfa_vdp_mgr.static_uplink = False
          self.dfa_vdp_mgr.phy_uplink = self.uplink
          self.dfa_vdp_mgr.ovs_vdp_obj_dict = {self.uplink: mock.Mock()}
  
      def test_vdp_uplink_proc_down_threshold_exceed(self):
          """Test VDP uplink proc for down case, when threshold exceed. """
          self._test_setup_uplink_params_steady()
          self.dfa_vdp_mgr.uplink_down_cnt = 3
          with mock.patch('networking_cisco.apps.saf.agent.detect_uplink.'
                          'detect_uplink', return_value='down'), \
              mock.patch('networking_cisco.apps.saf.agent.vdp.dfa_vdp_mgr.'
                         'VdpQueMsg', return_value='some obj') as vdp_que, \
              mock.patch.object(self.dfa_vdp_mgr.que, 'enqueue') as enq, \
              mock.patch.object(self.dfa_vdp_mgr.ovs_vdp_obj_dict[self.uplink],
                                'get_lldp_local_bridge_port',
                                return_value='veth_eth1'):
              self.dfa_vdp_mgr.vdp_uplink_proc()
          vdp_que.assert_called_with(
              constants.UPLINK_MSG_TYPE, status='down',
              phy_uplink=self.uplink, br_int=self.dfa_vdp_mgr.br_integ,
              br_ex=self.dfa_vdp_mgr.br_ex,
              root_helper=self.dfa_vdp_mgr.root_helper)
          enq.assert_called_with(constants.Q_UPL_PRIO, 'some obj')
  
      def test_vdp_uplink_proc_down_threshold_not_exceed(self):
          """Test VDP uplink proc for down case, when threshold not exceed. """
          self._test_setup_uplink_params_steady()
          self.dfa_vdp_mgr.uplink_down_cnt = 1
          with mock.patch('networking_cisco.apps.saf.agent.detect_uplink.'
                          'detect_uplink', return_value='down'), \
              mock.patch('networking_cisco.apps.saf.agent.vdp.dfa_vdp_mgr.'
                         'VdpQueMsg', return_value='some obj') as vdp_que, \
              mock.patch.object(self.dfa_vdp_mgr.que, 'enqueue') as enq, \
              mock.patch.object(self.dfa_vdp_mgr.ovs_vdp_obj_dict[self.uplink],
                                'get_lldp_local_bridge_port',
                                return_value='veth_eth1'):
              self.dfa_vdp_mgr.vdp_uplink_proc()
          vdp_que.assert_not_called()
          enq.assert_not_called()
  
      def test_vdp_uplink_proc_none(self):
          """Test VDP uplink proc for none case. """
          self._test_setup_uplink_params_steady()
          with mock.patch('networking_cisco.apps.saf.agent.detect_uplink.'
                          'detect_uplink', return_value=None), \
              mock.patch('networking_cisco.apps.saf.agent.vdp.dfa_vdp_mgr.'
                         'VdpQueMsg', return_value='some obj') as vdp_que, \
              mock.patch.object(self.dfa_vdp_mgr.ovs_vdp_obj_dict[self.uplink],
                                'get_lldp_local_bridge_port',
                                return_value=None), \
              mock.patch.object(self.dfa_vdp_mgr.que, 'enqueue') as enq, \
              mock.patch.object(self.dfa_vdp_mgr, 'save_uplink') as (
                  save_uplink_fn):
              self.dfa_vdp_mgr.vdp_uplink_proc()
          vdp_que.assert_not_called()
          enq.assert_not_called()
          save_uplink_fn.assert_called_with(
              fail_reason=constants.uplink_undiscovered_reason)
  
      def test_vdp_uplink_proc_normal(self):
          """Test VDP uplink proc for normal case. """
          self._test_setup_uplink_params_steady()
          with mock.patch('networking_cisco.apps.saf.agent.detect_uplink.'
                          'detect_uplink', return_value='normal'), \
              mock.patch('networking_cisco.apps.saf.agent.vdp.dfa_vdp_mgr.'
                         'VdpQueMsg', return_value='some obj') as vdp_que, \
              mock.patch('networking_cisco.apps.saf.common.dfa_sys_lib.'
                         'get_bond_intf', return_value=None), \
              mock.patch.object(self.dfa_vdp_mgr.ovs_vdp_obj_dict[self.uplink],
                                'get_lldp_local_bridge_port',
                                return_value='veth_eth1'), \
              mock.patch.object(self.dfa_vdp_mgr.que, 'enqueue') as enq, \
              mock.patch.object(self.dfa_vdp_mgr, 'save_uplink') as (
                  save_uplink_fn):
              self.dfa_vdp_mgr.vdp_uplink_proc()
          vdp_que.assert_called_with(
              constants.UPLINK_MSG_TYPE, status='up',
              phy_uplink=self.uplink, br_int=self.dfa_vdp_mgr.br_integ,
              br_ex=self.dfa_vdp_mgr.br_ex,
              root_helper=self.dfa_vdp_mgr.root_helper)
          enq.assert_called_with(constants.Q_UPL_PRIO, 'some obj')
          save_uplink_fn.assert_not_called()
  
      def test_vdp_uplink_proc_normal_static(self):
          """Test VDP uplink proc for normal case for static uplink. """
          self._test_setup_uplink_params_steady()
          self.dfa_vdp_mgr.static_uplink = True
          with mock.patch('networking_cisco.apps.saf.agent.vdp.dfa_vdp_mgr.'
                          'VdpQueMsg', return_value='some obj') as vdp_que, \
              mock.patch('networking_cisco.apps.saf.common.dfa_sys_lib.'
                         'get_bond_intf', return_value=None), \
              mock.patch.object(self.dfa_vdp_mgr, 'static_uplink_detect',
                                return_value='normal'), \
              mock.patch.object(self.dfa_vdp_mgr.ovs_vdp_obj_dict[self.uplink],
                                'get_lldp_local_bridge_port',
                                return_value='veth_eth1'), \
              mock.patch.object(self.dfa_vdp_mgr.que, 'enqueue') as enq, \
              mock.patch.object(self.dfa_vdp_mgr, 'save_uplink') as (
                  save_uplink_fn):
              self.dfa_vdp_mgr.vdp_uplink_proc()
          vdp_que.assert_called_with(
              constants.UPLINK_MSG_TYPE, status='up',
              phy_uplink=self.uplink, br_int=self.dfa_vdp_mgr.br_integ,
              br_ex=self.dfa_vdp_mgr.br_ex,
              root_helper=self.dfa_vdp_mgr.root_helper)
          enq.assert_called_with(constants.Q_UPL_PRIO, 'some obj')
          save_uplink_fn.assert_not_called()
  
      def test_vdp_uplink_proc_normal_bulk_vm_not_rcvd(self):
          """Test VDP uplink proc for normal case, for bulk VM.
  
          This is for the case when bulk VM notificationis not received.
          """
          self._test_setup_uplink_params_steady()
          self.dfa_vdp_mgr.bulk_vm_rcvd_flag = False
          self.dfa_vdp_mgr.bulk_vm_check_cnt = 2
          with mock.patch('networking_cisco.apps.saf.agent.detect_uplink.'
                          'detect_uplink', return_value='normal'), \
              mock.patch('networking_cisco.apps.saf.agent.vdp.dfa_vdp_mgr.'
                         'VdpQueMsg', return_value='some obj') as vdp_que, \
              mock.patch('networking_cisco.apps.saf.common.dfa_sys_lib.'
                         'get_bond_intf', return_value=None), \
              mock.patch.object(self.dfa_vdp_mgr.ovs_vdp_obj_dict[self.uplink],
                                'get_lldp_local_bridge_port',
                                return_value='veth_eth1'), \
              mock.patch.object(self.dfa_vdp_mgr.que, 'enqueue') as enq, \
              mock.patch.object(self.dfa_vdp_mgr, 'save_uplink') as (
                  save_uplink_fn):
              self.dfa_vdp_mgr.vdp_uplink_proc()
          vdp_que.assert_called_with(
              constants.UPLINK_MSG_TYPE, status='up',
              phy_uplink=self.uplink, br_int=self.dfa_vdp_mgr.br_integ,
              br_ex=self.dfa_vdp_mgr.br_ex,
              root_helper=self.dfa_vdp_mgr.root_helper)
          enq.assert_called_with(constants.Q_UPL_PRIO, 'some obj')
          save_uplink_fn.assert_called_with(uplink=self.uplink,
                                            veth_intf='veth_eth1')
  
      def test_vdp_uplink_proc_normal_bond_intf(self):
          """Test VDP uplink proc for normal case, for bond interface. """
          self._test_setup_uplink_params_steady()
          with mock.patch('networking_cisco.apps.saf.agent.detect_uplink.'
                          'detect_uplink', return_value='normal'), \
              mock.patch('networking_cisco.apps.saf.agent.vdp.dfa_vdp_mgr.'
                         'VdpQueMsg', return_value='some obj') as vdp_que, \
              mock.patch('networking_cisco.apps.saf.common.dfa_sys_lib.'
                         'get_bond_intf', return_value='bond0'), \
              mock.patch.object(self.dfa_vdp_mgr.ovs_vdp_obj_dict[self.uplink],
                                'get_lldp_local_bridge_port',
                                return_value='veth_eth1'), \
              mock.patch.object(self.dfa_vdp_mgr.que, 'enqueue') as enq, \
              mock.patch.object(self.dfa_vdp_mgr, 'save_uplink') as (
                  save_uplink_fn):
              parent = mock.MagicMock()
              parent.attach_mock(save_uplink_fn, 'save_uplink')
              parent.attach_mock(vdp_que, 'VdpQueMsg')
              parent.attach_mock(enq, 'enqueue')
              self.dfa_vdp_mgr.vdp_uplink_proc()
          expected_calls = [
              mock.call.save_uplink(
                  fail_reason=constants.port_transition_bond_down_reason),
              mock.call.VdpQueMsg(
                  constants.UPLINK_MSG_TYPE, status='down',
                  phy_uplink=self.uplink, br_int=self.dfa_vdp_mgr.br_integ,
                  br_ex=self.dfa_vdp_mgr.br_ex,
                  root_helper=self.dfa_vdp_mgr.root_helper),
              mock.call.enqueue(1, 'some obj'),
              mock.call.save_uplink(
                  fail_reason=constants.port_transition_bond_up_reason,
                  uplink='bond0'),
              mock.call.VdpQueMsg(
                  constants.UPLINK_MSG_TYPE, status='up',
                  phy_uplink='bond0', br_int=self.dfa_vdp_mgr.br_integ,
                  br_ex=self.dfa_vdp_mgr.br_ex,
                  root_helper=self.dfa_vdp_mgr.root_helper),
              mock.call.enqueue(1, 'some obj')]
          parent.assert_has_calls(expected_calls, any_order=False)
          self.assertEqual('bond0', self.dfa_vdp_mgr.phy_uplink)
          self.assertTrue(self.dfa_vdp_mgr.process_uplink_ongoing)
          self.assertFalse(self.dfa_vdp_mgr.uplink_det_compl)
  
      def test_vdp_uplink_proc_new_uplink(self):
          """Test VDP uplink proc for a new uplink case. """
          self._test_setup_uplink_params_steady()
          with mock.patch('networking_cisco.apps.saf.agent.detect_uplink.'
                          'detect_uplink', return_value='eth4'), \
              mock.patch('networking_cisco.apps.saf.agent.vdp.dfa_vdp_mgr.'
                         'VdpQueMsg', return_value='some obj') as vdp_que, \
              mock.patch.object(self.dfa_vdp_mgr.ovs_vdp_obj_dict[self.uplink],
                                'get_lldp_local_bridge_port',
                                return_value='veth_eth1'), \
              mock.patch.object(self.dfa_vdp_mgr.que, 'enqueue') as enq, \
              mock.patch.object(self.dfa_vdp_mgr, 'save_uplink') as (
                  save_uplink_fn):
              self.dfa_vdp_mgr.vdp_uplink_proc()
          vdp_que.assert_called_with(
              constants.UPLINK_MSG_TYPE, status='up',
              phy_uplink='eth4', br_int=self.dfa_vdp_mgr.br_integ,
              br_ex=self.dfa_vdp_mgr.br_ex,
              root_helper=self.dfa_vdp_mgr.root_helper)
          enq.assert_called_with(constants.Q_UPL_PRIO, 'some obj')
          save_uplink_fn.assert_called_with(uplink='eth4', veth_intf='veth_eth1')
          self.assertTrue(self.dfa_vdp_mgr.process_uplink_ongoing)
          self.assertEqual('eth4', self.dfa_vdp_mgr.phy_uplink)
  
      def test_process_bulk_vm_event_up(self):
          "Test Bulk Process event for up status. """
          msg = self._setup_bulk_vm_msg('up')
          self.dfa_vdp_mgr.ovs_vdp_obj_dict = {}
          self.dfa_vdp_mgr.ovs_vdp_obj_dict[self.uplink] = mock.Mock()
          with mock.patch('networking_cisco.apps.saf.agent.vdp.dfa_vdp_mgr.'
                          'VdpQueMsg', return_value='some obj') as vdp_que, \
              mock.patch.object(self.dfa_vdp_mgr,
                                'process_vm_event') as process_vm_event:
              self.dfa_vdp_mgr.uplink_det_compl = True
              self.dfa_vdp_mgr.process_bulk_vm_event(msg, self.uplink)
          vm_dict = self._construct_vm_dict('up')
          vdp_que.assert_called_with(
              constants.VM_MSG_TYPE, port_uuid=vm_dict['port_uuid'],
              vm_mac=vm_dict['vm_mac'], net_uuid=vm_dict['net_uuid'],
              segmentation_id=vm_dict['segmentation_id'],
              status=vm_dict['status'], oui=vm_dict['oui'],
              phy_uplink=self.uplink)
          process_vm_event.assert_called_with('some obj', self.uplink)
  
      def test_process_bulk_vm_event_down(self):
          "Test Bulk Process event for down status. """
          msg = self._setup_bulk_vm_msg('down')
          self.dfa_vdp_mgr.ovs_vdp_obj_dict = {}
          self.dfa_vdp_mgr.ovs_vdp_obj_dict[self.uplink] = mock.Mock()
          with mock.patch('networking_cisco.apps.saf.agent.vdp.dfa_vdp_mgr.'
                          'VdpQueMsg', return_value='some obj') as vdp_que, \
              mock.patch.object(self.dfa_vdp_mgr.ovs_vdp_obj_dict[self.uplink],
                                'pop_local_cache') as pop_ovs_cache, \
              mock.patch.object(self.dfa_vdp_mgr,
                                'process_vm_event') as process_vm_event:
              self.dfa_vdp_mgr.uplink_det_compl = True
              self.dfa_vdp_mgr.process_bulk_vm_event(msg, self.uplink)
          vm_dict = self._construct_vm_dict('down')
          pop_ovs_cache.assert_called_with(
              vm_dict['port_uuid'], vm_dict['vm_mac'], vm_dict['net_uuid'],
              vm_dict['local_vlan'], vm_dict['vdp_vlan'],
              vm_dict['segmentation_id'])
          vdp_que.assert_called_with(
              constants.VM_MSG_TYPE, port_uuid=vm_dict['port_uuid'],
              vm_mac=vm_dict['vm_mac'], net_uuid=vm_dict['net_uuid'],
              segmentation_id=vm_dict['segmentation_id'],
              status=vm_dict['status'], oui=vm_dict['oui'],
              phy_uplink=self.uplink)
          process_vm_event.assert_called_with('some obj', self.uplink)
  
      def test_vdp_vm_event_dict(self):
          """Test for VM event, when input is a VM dict. """
          vm_dict = self._construct_vm_dict('up')
          self.dfa_vdp_mgr.phy_uplink = self.uplink
          with mock.patch('networking_cisco.apps.saf.agent.vdp.dfa_vdp_mgr.'
                          'VdpQueMsg', return_value='some obj') as vdp_que, \
              mock.patch.object(self.dfa_vdp_mgr.que, 'enqueue') as enq, \
              mock.patch('networking_cisco.apps.saf.agent.vdp.dfa_vdp_mgr.'
                         'VdpQueMsg', return_value='some obj') as vdp_que:
              self.dfa_vdp_mgr.vdp_vm_event(vm_dict)
          vdp_que.assert_called_with(
              constants.VM_MSG_TYPE, port_uuid=vm_dict['port_uuid'],
              vm_mac=vm_dict['vm_mac'], net_uuid=vm_dict['net_uuid'],
              segmentation_id=vm_dict['segmentation_id'],
              status=vm_dict['status'], oui=vm_dict['oui'],
              phy_uplink=self.uplink)
          enq.assert_called_with(constants.Q_VM_PRIO, 'some obj')
  
      def test_vdp_vm_event_list(self):
          """Test for VM event, when input is a VM dict list. """
          vm_dict = self._construct_vm_dict('up')
          self.dfa_vdp_mgr.phy_uplink = self.uplink
          with mock.patch('networking_cisco.apps.saf.agent.vdp.dfa_vdp_mgr.'
                          'VdpQueMsg', return_value='some obj') as vdp_que, \
              mock.patch.object(self.dfa_vdp_mgr.que, 'enqueue') as enq, \
              mock.patch('networking_cisco.apps.saf.agent.vdp.dfa_vdp_mgr.'
                         'VdpQueMsg', return_value='some obj') as vdp_que:
              self.dfa_vdp_mgr.vdp_vm_event([vm_dict])
          vdp_que.assert_called_with(
              constants.VM_BULK_SYNC_MSG_TYPE,
              vm_bulk_list=[vm_dict], phy_uplink=self.uplink)
          enq.assert_called_with(constants.Q_VM_PRIO, 'some obj')
          self.assertTrue(self.dfa_vdp_mgr.bulk_vm_rcvd_flag)
  
      def test_dfa_uplink_restart_no_uplink(self):
          """Test for DFA uplink restart case with no uplink. """
          uplink_dict = {}
          with mock.patch('networking_cisco.apps.saf.agent.vdp.ovs_vdp.'
                          'delete_uplink_and_flows') as ovs_del_flow:
              self.dfa_vdp_mgr.dfa_uplink_restart(uplink_dict)
          self.assertTrue(self.dfa_vdp_mgr.restart_uplink_called)
          ovs_del_flow.assert_not_called()
  
      def test_dfa_uplink_restart_valid_uplink_veth(self):
          """Test for DFA uplink restart case with valid uplink/veth. """
          uplink_dict = {'uplink': self.uplink, 'veth_intf': 'veth_eth1'}
          with mock.patch('networking_cisco.apps.saf.agent.vdp.ovs_vdp.'
                          'delete_uplink_and_flows') as ovs_del_flow:
              self.dfa_vdp_mgr.dfa_uplink_restart(uplink_dict)
          self.assertTrue(self.dfa_vdp_mgr.restart_uplink_called)
          self.assertEqual(self.uplink, self.dfa_vdp_mgr.phy_uplink)
          self.assertEqual('veth_eth1', self.dfa_vdp_mgr.veth_intf)
          ovs_del_flow.assert_not_called()
  
      def test_dfa_uplink_restart_invalid_veth(self):
          """Test for DFA uplink restart case with invalid veth. """
          uplink_dict = {'uplink': self.uplink}
          with mock.patch('networking_cisco.apps.saf.agent.vdp.ovs_vdp.'
                          'delete_uplink_and_flows') as ovs_del_flow:
              self.dfa_vdp_mgr.dfa_uplink_restart(uplink_dict)
          self.assertTrue(self.dfa_vdp_mgr.restart_uplink_called)
          ovs_del_flow.assert_called_with(
              self.dfa_vdp_mgr.root_helper, self.dfa_vdp_mgr.br_ex, self.uplink)
  
      def _get_topo_disc_arg(self):
          """Fill the argument to topology discovery. """
          return {'phy_interface': self.uplink, 'remote_evb_cfgd': True,
                  'remote_evb_mode': 'bridge', 'remote_mgmt_addr': '10.1.1.1',
                  'remote_system_desc': 'Cisco Test Os',
                  'remote_system_name': 'N6K-1', 'remote_port': 'e2/1',
                  'remote_chassis_id_mac': '00:11:22:33:44:55',
                  'remote_port_id_mac': '00:22:33:44:55:66'}
  
      def _get_topo_dict_final(self):
          """Fill the argument to topology discovery for final check. """
          return {'host': None, 'protocol_interface': self.uplink,
                  'heartbeat': 'Jan 1',
                  'phy_interface': self.uplink, 'remote_evb_cfgd': True,
                  'remote_evb_mode': 'bridge',
                  'remote_mgmt_addr': '10.1.1.1',
                  'remote_system_desc': 'Cisco Test Os',
                  'remote_system_name': 'N6K-1', 'remote_port': 'e2/1',
                  'remote_chassis_id_mac': '00:11:22:33:44:55',
                  'remote_port_id_mac': '00:22:33:44:55:66',
                  'configurations': jsonutils.dumps({})}
  
      def test_topo_disc_cb(self):
          """Test the topology discovery CB function. """
          topo_dict = self._get_topo_disc_arg()
          topo_dict_final = self._get_topo_dict_final()
          topo_obj = common_utils.Dict2Obj(topo_dict)
          with mock.patch('time.ctime') as ctime_fn:
              ctime_fn.return_value = 'Jan 1'
              self.dfa_vdp_mgr.topo_disc_cb(self.uplink, topo_obj)
          self.rpc_client.make_msg.assert_called_with(
              'save_topo_disc_params', {}, msg=jsonutils.dumps(topo_dict_final))
  