示例#1
0
    def test_wait_for_media_switch_diff_interface(self, m_read_netlink_socket,
                                                  m_socket):
        """wait_for_media_disconnect_connect ignores unexpected interfaces.

        The first two messages are for other interfaces and last two are for
        expected interface. So the function exit only after receiving last
        2 messages and therefore the call count for m_read_netlink_socket
        has to be 4
        """
        other_ifname = "eth1"
        expected_ifname = "eth0"
        data_op_down_eth1 = self._media_switch_data(other_ifname, RTM_NEWLINK,
                                                    OPER_DOWN)
        data_op_up_eth1 = self._media_switch_data(other_ifname, RTM_NEWLINK,
                                                  OPER_UP)
        data_op_down_eth0 = self._media_switch_data(expected_ifname,
                                                    RTM_NEWLINK, OPER_DOWN)
        data_op_up_eth0 = self._media_switch_data(expected_ifname, RTM_NEWLINK,
                                                  OPER_UP)
        m_read_netlink_socket.side_effect = [
            data_op_down_eth1,
            data_op_up_eth1,
            data_op_down_eth0,
            data_op_up_eth0,
        ]
        wait_for_media_disconnect_connect(m_socket, expected_ifname)
        self.assertIn(
            "Ignored netlink event on interface %s" % other_ifname,
            self.logs.getvalue(),
        )
        self.assertEqual(m_read_netlink_socket.call_count, 4)
示例#2
0
    def test_wait_for_media_switch_diff_interface(self, m_read_netlink_socket,
                                                  m_socket):
        '''wait_for_media_disconnect_connect ignores unexpected interfaces.

        The first two messages are for other interfaces and last two are for
        expected interface. So the function exit only after receiving last
        2 messages and therefore the call count for m_read_netlink_socket
        has to be 4
        '''
        other_ifname = "eth1"
        expected_ifname = "eth0"
        data_op_down_eth1 = self._media_switch_data(
                                other_ifname, RTM_NEWLINK, OPER_DOWN)
        data_op_up_eth1 = self._media_switch_data(
                                other_ifname, RTM_NEWLINK, OPER_UP)
        data_op_down_eth0 = self._media_switch_data(
                                expected_ifname, RTM_NEWLINK, OPER_DOWN)
        data_op_up_eth0 = self._media_switch_data(
                                expected_ifname, RTM_NEWLINK, OPER_UP)
        m_read_netlink_socket.side_effect = [data_op_down_eth1,
                                             data_op_up_eth1,
                                             data_op_down_eth0,
                                             data_op_up_eth0]
        wait_for_media_disconnect_connect(m_socket, expected_ifname)
        self.assertIn('Ignored netlink event on interface %s' % other_ifname,
                      self.logs.getvalue())
        self.assertEqual(m_read_netlink_socket.call_count, 4)
示例#3
0
 def test_wait_invalid_socket(self, m_read_netlink_socket, m_socket):
     '''wait_for_media_disconnect_connect handle none netlink socket.'''
     socket = None
     ifname = "eth0"
     with self.assertRaises(AssertionError) as context:
         wait_for_media_disconnect_connect(socket, ifname)
     self.assertTrue('netlink socket is none' in str(context.exception))
示例#4
0
    def test_invalid_msgtype_setlink(self, m_read_netlink_socket, m_socket):
        """wait_for_media_disconnect_connect ignores SETLINK events.

        The first two messages are for oper down and up for RTM_GETLINK type
        which it will ignore. 3rd and 4th messages are RTM_NEWLINK with down
        and up messages. This function should exit after 4th messages since it
        sees down->up scenario. So the call count for m_read_netlink_socket
        has to be 4 ignoring first 2 messages of RTM_GETLINK and
        last 2 messages of RTM_NEWLINK
        """
        ifname = "eth0"
        data_setlink_down = self._media_switch_data(ifname, RTM_SETLINK,
                                                    OPER_DOWN)
        data_setlink_up = self._media_switch_data(ifname, RTM_SETLINK, OPER_UP)
        data_newlink_down = self._media_switch_data(ifname, RTM_NEWLINK,
                                                    OPER_DOWN)
        data_newlink_up = self._media_switch_data(ifname, RTM_NEWLINK, OPER_UP)
        m_read_netlink_socket.side_effect = [
            data_setlink_down,
            data_setlink_up,
            data_newlink_down,
            data_newlink_up,
            data_newlink_down,
            data_newlink_up,
        ]
        wait_for_media_disconnect_connect(m_socket, ifname)
        self.assertEqual(m_read_netlink_socket.call_count, 4)
示例#5
0
 def test_wait_invalid_socket(self, m_read_netlink_socket, m_socket):
     """wait_for_media_disconnect_connect handle none netlink socket."""
     socket = None
     ifname = "eth0"
     with self.assertRaises(AssertionError) as context:
         wait_for_media_disconnect_connect(socket, ifname)
     self.assertTrue("netlink socket is none" in str(context.exception))
示例#6
0
 def test_netlink_invalid_switch_scenario(self, m_read_netlink_socket,
                                          m_socket):
     """returns only if it receives UP event after a DOWN event"""
     ifname = "eth0"
     data_op_down = self._media_switch_data(ifname, RTM_NEWLINK, OPER_DOWN)
     data_op_up = self._media_switch_data(ifname, RTM_NEWLINK, OPER_UP)
     data_op_dormant = self._media_switch_data(ifname, RTM_NEWLINK,
                                               OPER_DORMANT)
     data_op_notpresent = self._media_switch_data(ifname, RTM_NEWLINK,
                                                  OPER_NOTPRESENT)
     data_op_lowerdown = self._media_switch_data(ifname, RTM_NEWLINK,
                                                 OPER_LOWERLAYERDOWN)
     data_op_testing = self._media_switch_data(ifname, RTM_NEWLINK,
                                               OPER_TESTING)
     data_op_unknown = self._media_switch_data(ifname, RTM_NEWLINK,
                                               OPER_UNKNOWN)
     m_read_netlink_socket.side_effect = [
         data_op_up,
         data_op_up,
         data_op_dormant,
         data_op_up,
         data_op_notpresent,
         data_op_up,
         data_op_lowerdown,
         data_op_up,
         data_op_testing,
         data_op_up,
         data_op_unknown,
         data_op_up,
         data_op_down,
         data_op_up,
     ]
     wait_for_media_disconnect_connect(m_socket, ifname)
     self.assertEqual(m_read_netlink_socket.call_count, 14)
示例#7
0
 def test_netlink_invalid_switch_scenario(self, m_read_netlink_socket,
                                          m_socket):
     '''returns only if it receives UP event after a DOWN event'''
     ifname = "eth0"
     data_op_down = self._media_switch_data(ifname, RTM_NEWLINK, OPER_DOWN)
     data_op_up = self._media_switch_data(ifname, RTM_NEWLINK, OPER_UP)
     data_op_dormant = self._media_switch_data(ifname, RTM_NEWLINK,
                                               OPER_DORMANT)
     data_op_notpresent = self._media_switch_data(ifname, RTM_NEWLINK,
                                                  OPER_NOTPRESENT)
     data_op_lowerdown = self._media_switch_data(ifname, RTM_NEWLINK,
                                                 OPER_LOWERLAYERDOWN)
     data_op_testing = self._media_switch_data(ifname, RTM_NEWLINK,
                                               OPER_TESTING)
     data_op_unknown = self._media_switch_data(ifname, RTM_NEWLINK,
                                               OPER_UNKNOWN)
     m_read_netlink_socket.side_effect = [data_op_up, data_op_up,
                                          data_op_dormant, data_op_up,
                                          data_op_notpresent, data_op_up,
                                          data_op_lowerdown, data_op_up,
                                          data_op_testing, data_op_up,
                                          data_op_unknown, data_op_up,
                                          data_op_down, data_op_up]
     wait_for_media_disconnect_connect(m_socket, ifname)
     self.assertEqual(m_read_netlink_socket.call_count, 14)
示例#8
0
    def test_invalid_msgtype_setlink(self, m_read_netlink_socket, m_socket):
        '''wait_for_media_disconnect_connect ignores SETLINK events.

        The first two messages are for oper down and up for RTM_GETLINK type
        which it will ignore. 3rd and 4th messages are RTM_NEWLINK with down
        and up messages. This function should exit after 4th messages since it
        sees down->up scenario. So the call count for m_read_netlink_socket
        has to be 4 ignoring first 2 messages of RTM_GETLINK and
        last 2 messages of RTM_NEWLINK
        '''
        ifname = "eth0"
        data_setlink_down = self._media_switch_data(
                                    ifname, RTM_SETLINK, OPER_DOWN)
        data_setlink_up = self._media_switch_data(
                                    ifname, RTM_SETLINK, OPER_UP)
        data_newlink_down = self._media_switch_data(
                                    ifname, RTM_NEWLINK, OPER_DOWN)
        data_newlink_up = self._media_switch_data(
                                    ifname, RTM_NEWLINK, OPER_UP)
        m_read_netlink_socket.side_effect = [data_setlink_down,
                                             data_setlink_up,
                                             data_newlink_down,
                                             data_newlink_up,
                                             data_newlink_down,
                                             data_newlink_up]
        wait_for_media_disconnect_connect(m_socket, ifname)
        self.assertEqual(m_read_netlink_socket.call_count, 4)
示例#9
0
 def test_read_multiple_netlink_msgs(self, m_read_netlink_socket, m_socket):
     """Read multiple messages in single receive call"""
     ifname = "eth0"
     bytes = ifname.encode("utf-8")
     data = bytearray(96)
     struct.pack_into("=LHHLL", data, 0, 48, RTM_NEWLINK, 0, 0, 0)
     struct.pack_into(
         "HH4sHHc",
         data,
         RTATTR_START_OFFSET,
         8,
         3,
         bytes,
         5,
         16,
         int_to_bytes(OPER_DOWN),
     )
     struct.pack_into("=LHHLL", data, 48, 48, RTM_NEWLINK, 0, 0, 0)
     struct.pack_into(
         "HH4sHHc",
         data,
         48 + RTATTR_START_OFFSET,
         8,
         3,
         bytes,
         5,
         16,
         int_to_bytes(OPER_UP),
     )
     m_read_netlink_socket.return_value = data
     wait_for_media_disconnect_connect(m_socket, ifname)
     self.assertEqual(m_read_netlink_socket.call_count, 1)
示例#10
0
 def test_read_partial_netlink_msgs(self, m_read_netlink_socket, m_socket):
     """Read partial messages in receive call"""
     ifname = "eth0"
     bytes = ifname.encode("utf-8")
     data1 = bytearray(112)
     data2 = bytearray(32)
     struct.pack_into("=LHHLL", data1, 0, 48, RTM_NEWLINK, 0, 0, 0)
     struct.pack_into(
         "HH4sHHc",
         data1,
         RTATTR_START_OFFSET,
         8,
         3,
         bytes,
         5,
         16,
         int_to_bytes(OPER_DOWN),
     )
     struct.pack_into("=LHHLL", data1, 48, 48, RTM_NEWLINK, 0, 0, 0)
     struct.pack_into("HH4sHHc", data1, 80, 8, 3, bytes, 5, 16,
                      int_to_bytes(OPER_DOWN))
     struct.pack_into("=LHHLL", data1, 96, 48, RTM_NEWLINK, 0, 0, 0)
     struct.pack_into("HH4sHHc", data2, 16, 8, 3, bytes, 5, 16,
                      int_to_bytes(OPER_UP))
     m_read_netlink_socket.side_effect = [data1, data2]
     wait_for_media_disconnect_connect(m_socket, ifname)
     self.assertEqual(m_read_netlink_socket.call_count, 2)
示例#11
0
    def _poll_imds(self):
        """Poll IMDS for the new provisioning data until we get a valid
        response. Then return the returned JSON object."""
        url = IMDS_URL + "reprovisiondata?api-version=2017-04-02"
        headers = {"Metadata": "true"}
        nl_sock = None
        report_ready = bool(not os.path.isfile(REPORTED_READY_MARKER_FILE))

        def exc_cb(msg, exception):
            if isinstance(exception, UrlError) and exception.code == 404:
                return True
            # If we get an exception while trying to call IMDS, we
            # call DHCP and setup the ephemeral network to acquire the new IP.
            return False

        LOG.debug("Wait for vnetswitch to happen")
        while True:
            try:
                # Save our EphemeralDHCPv4 context so we avoid repeated dhcp
                self._ephemeral_dhcp_ctx = EphemeralDHCPv4()
                lease = self._ephemeral_dhcp_ctx.obtain_lease()
                if report_ready:
                    try:
                        nl_sock = netlink.create_bound_netlink_socket()
                    except netlink.NetlinkCreateSocketError as e:
                        LOG.warning(e)
                        self._ephemeral_dhcp_ctx.clean_network()
                        return
                    path = REPORTED_READY_MARKER_FILE
                    LOG.info("Creating a marker file to report ready: %s",
                             path)
                    util.write_file(
                        path, "{pid}: {time}\n".format(pid=os.getpid(),
                                                       time=time()))
                    self._report_ready(lease=lease)
                    report_ready = False
                    try:
                        netlink.wait_for_media_disconnect_connect(
                            nl_sock, lease['interface'])
                    except AssertionError as error:
                        LOG.error(error)
                        return
                    self._ephemeral_dhcp_ctx.clean_network()
                else:
                    return readurl(url,
                                   timeout=1,
                                   headers=headers,
                                   exception_cb=exc_cb,
                                   infinite=True,
                                   log_req_resp=False).contents
            except UrlError:
                # Teardown our EphemeralDHCPv4 context on failure as we retry
                self._ephemeral_dhcp_ctx.clean_network()
                pass
            finally:
                if nl_sock:
                    nl_sock.close()
示例#12
0
 def test_media_down_up_scenario(self, m_read_netlink_socket, m_socket):
     """Test for media down up sequence for required interface name"""
     ifname = "eth0"
     # construct data for Oper State down
     data_op_down = self._media_switch_data(ifname, RTM_NEWLINK, OPER_DOWN)
     # construct data for Oper State up
     data_op_up = self._media_switch_data(ifname, RTM_NEWLINK, OPER_UP)
     m_read_netlink_socket.side_effect = [data_op_down, data_op_up]
     wait_for_media_disconnect_connect(m_socket, ifname)
     self.assertEqual(m_read_netlink_socket.call_count, 2)
示例#13
0
 def test_wait_invalid_rta_attr(self, m_read_netlink_socket, m_socket):
     ''' wait_for_media_disconnect_connect handles invalid rta data'''
     ifname = "eth0"
     data_invalid1 = self._media_switch_data(None, RTM_NEWLINK, OPER_DOWN)
     data_invalid2 = self._media_switch_data(ifname, RTM_NEWLINK, None)
     data_op_down = self._media_switch_data(ifname, RTM_NEWLINK, OPER_DOWN)
     data_op_up = self._media_switch_data(ifname, RTM_NEWLINK, OPER_UP)
     m_read_netlink_socket.side_effect = [data_invalid1, data_invalid2,
                                          data_op_down, data_op_up]
     wait_for_media_disconnect_connect(m_socket, ifname)
     self.assertEqual(m_read_netlink_socket.call_count, 4)
示例#14
0
 def test_wait_invalid_ifname(self, m_read_netlink_socket, m_socket):
     '''wait_for_media_disconnect_connect handle none interface name'''
     ifname = None
     with self.assertRaises(AssertionError) as context:
         wait_for_media_disconnect_connect(m_socket, ifname)
     self.assertTrue('interface name is none' in str(context.exception))
     ifname = ""
     with self.assertRaises(AssertionError) as context:
         wait_for_media_disconnect_connect(m_socket, ifname)
     self.assertTrue('interface name cannot be empty' in
                     str(context.exception))
示例#15
0
 def test_media_down_up_scenario(self, m_read_netlink_socket,
                                 m_socket):
     '''Test for media down up sequence for required interface name'''
     ifname = "eth0"
     # construct data for Oper State down
     data_op_down = self._media_switch_data(ifname, RTM_NEWLINK, OPER_DOWN)
     # construct data for Oper State up
     data_op_up = self._media_switch_data(ifname, RTM_NEWLINK, OPER_UP)
     m_read_netlink_socket.side_effect = [data_op_down, data_op_up]
     wait_for_media_disconnect_connect(m_socket, ifname)
     self.assertEqual(m_read_netlink_socket.call_count, 2)
示例#16
0
 def test_wait_invalid_ifname(self, m_read_netlink_socket, m_socket):
     """wait_for_media_disconnect_connect handle none interface name"""
     ifname = None
     with self.assertRaises(AssertionError) as context:
         wait_for_media_disconnect_connect(m_socket, ifname)
     self.assertTrue("interface name is none" in str(context.exception))
     ifname = ""
     with self.assertRaises(AssertionError) as context:
         wait_for_media_disconnect_connect(m_socket, ifname)
     self.assertTrue(
         "interface name cannot be empty" in str(context.exception))
示例#17
0
 def test_wait_invalid_rta_attr(self, m_read_netlink_socket, m_socket):
     ''' wait_for_media_disconnect_connect handles invalid rta data'''
     ifname = "eth0"
     data_invalid1 = self._media_switch_data(None, RTM_NEWLINK, OPER_DOWN)
     data_invalid2 = self._media_switch_data(ifname, RTM_NEWLINK, None)
     data_op_down = self._media_switch_data(ifname, RTM_NEWLINK, OPER_DOWN)
     data_op_up = self._media_switch_data(ifname, RTM_NEWLINK, OPER_UP)
     m_read_netlink_socket.side_effect = [
         data_invalid1, data_invalid2, data_op_down, data_op_up
     ]
     wait_for_media_disconnect_connect(m_socket, ifname)
     self.assertEqual(m_read_netlink_socket.call_count, 4)
示例#18
0
 def test_netlink_valid_inbetween_transitions(self, m_read_netlink_socket,
                                              m_socket):
     '''wait_for_media_disconnect_connect handles in between transitions'''
     ifname = "eth0"
     data_op_down = self._media_switch_data(ifname, RTM_NEWLINK, OPER_DOWN)
     data_op_up = self._media_switch_data(ifname, RTM_NEWLINK, OPER_UP)
     data_op_dormant = self._media_switch_data(ifname, RTM_NEWLINK,
                                               OPER_DORMANT)
     data_op_unknown = self._media_switch_data(ifname, RTM_NEWLINK,
                                               OPER_UNKNOWN)
     m_read_netlink_socket.side_effect = [data_op_down, data_op_dormant,
                                          data_op_unknown, data_op_up]
     wait_for_media_disconnect_connect(m_socket, ifname)
     self.assertEqual(m_read_netlink_socket.call_count, 4)
示例#19
0
 def test_read_multiple_netlink_msgs(self, m_read_netlink_socket, m_socket):
     '''Read multiple messages in single receive call'''
     ifname = "eth0"
     bytes = ifname.encode("utf-8")
     data = bytearray(96)
     struct.pack_into("=LHHLL", data, 0, 48, RTM_NEWLINK, 0, 0, 0)
     struct.pack_into("HH4sHHc", data, RTATTR_START_OFFSET, 8, 3,
                      bytes, 5, 16, int_to_bytes(OPER_DOWN))
     struct.pack_into("=LHHLL", data, 48, 48, RTM_NEWLINK, 0, 0, 0)
     struct.pack_into("HH4sHHc", data, 48 + RTATTR_START_OFFSET, 8,
                      3, bytes, 5, 16, int_to_bytes(OPER_UP))
     m_read_netlink_socket.return_value = data
     wait_for_media_disconnect_connect(m_socket, ifname)
     self.assertEqual(m_read_netlink_socket.call_count, 1)
示例#20
0
    def test_netlink_invalid_operstate(self, m_read_netlink_socket, m_socket):
        '''wait_for_media_disconnect_connect should handle invalid operstates.

        The function should not fail and return even if it receives invalid
        operstates. It always should wait for down up sequence.
        '''
        ifname = "eth0"
        data_op_down = self._media_switch_data(ifname, RTM_NEWLINK, OPER_DOWN)
        data_op_up = self._media_switch_data(ifname, RTM_NEWLINK, OPER_UP)
        data_op_invalid = self._media_switch_data(ifname, RTM_NEWLINK, 7)
        m_read_netlink_socket.side_effect = [data_op_invalid, data_op_up,
                                             data_op_down, data_op_invalid,
                                             data_op_up]
        wait_for_media_disconnect_connect(m_socket, ifname)
        self.assertEqual(m_read_netlink_socket.call_count, 5)
示例#21
0
 def test_netlink_valid_inbetween_transitions(self, m_read_netlink_socket,
                                              m_socket):
     '''wait_for_media_disconnect_connect handles in between transitions'''
     ifname = "eth0"
     data_op_down = self._media_switch_data(ifname, RTM_NEWLINK, OPER_DOWN)
     data_op_up = self._media_switch_data(ifname, RTM_NEWLINK, OPER_UP)
     data_op_dormant = self._media_switch_data(ifname, RTM_NEWLINK,
                                               OPER_DORMANT)
     data_op_unknown = self._media_switch_data(ifname, RTM_NEWLINK,
                                               OPER_UNKNOWN)
     m_read_netlink_socket.side_effect = [
         data_op_down, data_op_dormant, data_op_unknown, data_op_up
     ]
     wait_for_media_disconnect_connect(m_socket, ifname)
     self.assertEqual(m_read_netlink_socket.call_count, 4)
示例#22
0
    def test_netlink_invalid_operstate(self, m_read_netlink_socket, m_socket):
        '''wait_for_media_disconnect_connect should handle invalid operstates.

        The function should not fail and return even if it receives invalid
        operstates. It always should wait for down up sequence.
        '''
        ifname = "eth0"
        data_op_down = self._media_switch_data(ifname, RTM_NEWLINK, OPER_DOWN)
        data_op_up = self._media_switch_data(ifname, RTM_NEWLINK, OPER_UP)
        data_op_invalid = self._media_switch_data(ifname, RTM_NEWLINK, 7)
        m_read_netlink_socket.side_effect = [
            data_op_invalid, data_op_up, data_op_down, data_op_invalid,
            data_op_up
        ]
        wait_for_media_disconnect_connect(m_socket, ifname)
        self.assertEqual(m_read_netlink_socket.call_count, 5)
示例#23
0
 def test_read_partial_netlink_msgs(self, m_read_netlink_socket, m_socket):
     '''Read partial messages in receive call'''
     ifname = "eth0"
     bytes = ifname.encode("utf-8")
     data1 = bytearray(112)
     data2 = bytearray(32)
     struct.pack_into("=LHHLL", data1, 0, 48, RTM_NEWLINK, 0, 0, 0)
     struct.pack_into("HH4sHHc", data1, RTATTR_START_OFFSET, 8, 3,
                      bytes, 5, 16, int_to_bytes(OPER_DOWN))
     struct.pack_into("=LHHLL", data1, 48, 48, RTM_NEWLINK, 0, 0, 0)
     struct.pack_into("HH4sHHc", data1, 80, 8, 3, bytes, 5, 16,
                      int_to_bytes(OPER_DOWN))
     struct.pack_into("=LHHLL", data1, 96, 48, RTM_NEWLINK, 0, 0, 0)
     struct.pack_into("HH4sHHc", data2, 16, 8, 3, bytes, 5, 16,
                      int_to_bytes(OPER_UP))
     m_read_netlink_socket.side_effect = [data1, data2]
     wait_for_media_disconnect_connect(m_socket, ifname)
     self.assertEqual(m_read_netlink_socket.call_count, 2)
示例#24
0
    def test_invalid_msgtype_getlink(self, m_read_netlink_socket, m_socket):
        '''wait_for_media_disconnect_connect ignores GETLINK events.

        The first two messages are for oper down and up for RTM_GETLINK type
        which netlink module will ignore. The last 2 messages are RTM_NEWLINK
        with oper state down and up messages. Therefore the call count for
        m_read_netlink_socket has to be 4 ignoring first 2 messages
        of RTM_GETLINK
        '''
        ifname = "eth0"
        data_getlink_down = self._media_switch_data(ifname, RTM_GETLINK,
                                                    OPER_DOWN)
        data_getlink_up = self._media_switch_data(ifname, RTM_GETLINK, OPER_UP)
        data_newlink_down = self._media_switch_data(ifname, RTM_NEWLINK,
                                                    OPER_DOWN)
        data_newlink_up = self._media_switch_data(ifname, RTM_NEWLINK, OPER_UP)
        m_read_netlink_socket.side_effect = [
            data_getlink_down, data_getlink_up, data_newlink_down,
            data_newlink_up
        ]
        wait_for_media_disconnect_connect(m_socket, ifname)
        self.assertEqual(m_read_netlink_socket.call_count, 4)
示例#25
0
    def test_invalid_msgtype_getlink(self, m_read_netlink_socket, m_socket):
        '''wait_for_media_disconnect_connect ignores GETLINK events.

        The first two messages are for oper down and up for RTM_GETLINK type
        which netlink module will ignore. The last 2 messages are RTM_NEWLINK
        with oper state down and up messages. Therefore the call count for
        m_read_netlink_socket has to be 4 ignoring first 2 messages
        of RTM_GETLINK
        '''
        ifname = "eth0"
        data_getlink_down = self._media_switch_data(
                                    ifname, RTM_GETLINK, OPER_DOWN)
        data_getlink_up = self._media_switch_data(
                                    ifname, RTM_GETLINK, OPER_UP)
        data_newlink_down = self._media_switch_data(
                                    ifname, RTM_NEWLINK, OPER_DOWN)
        data_newlink_up = self._media_switch_data(
                                    ifname, RTM_NEWLINK, OPER_UP)
        m_read_netlink_socket.side_effect = [data_getlink_down,
                                             data_getlink_up,
                                             data_newlink_down,
                                             data_newlink_up]
        wait_for_media_disconnect_connect(m_socket, ifname)
        self.assertEqual(m_read_netlink_socket.call_count, 4)