def test_select_neighbors_for_reply_should_not_contain_oldest_peer(self):
     oldest = PodDescriptor("172.0.1.4", 1)
     self.partialView.add_peer(PodDescriptor("172.0.1.6", 2))
     self.partialView.add_peer(oldest)
     self.partialView.add_peer(PodDescriptor("172.0.1.5", 4))
     neighbors = self.partialView.select_neighbors_for_reply(oldest)
     self.assertFalse(neighbors.contains(oldest))
 def test_get_oldest_peer(self):
     self.partialView.add_peer(PodDescriptor("172.0.1.6", 2))
     self.partialView.add_peer(PodDescriptor("172.0.1.4", 1))
     self.partialView.add_peer(PodDescriptor("172.0.1.5", 4))
     oldest = self.partialView.get_oldest_peer()
     self.assertEqual(oldest.ip, "172.0.1.5")
     self.assertEqual(oldest.age, 4)
 def test_sample_descriptors_should_return_less_than_limit_peers_if_size_less_than_limit(
         self):
     self.partialView.add_peer(PodDescriptor("172.0.1.5", 2))
     self.partialView.add_peer(PodDescriptor("172.0.1.4", 3))
     size = self.partialView.size
     sample = self.partialView.sample_descriptors(3)
     self.assertEqual(len(sample), size)
 def test_select_neighbors_for_reply_should_return_a_full_view(self):
     oldest = PodDescriptor("172.0.1.4", 1)
     self.partialView.add_peer(PodDescriptor("172.0.1.6", 2))
     self.partialView.add_peer(oldest)
     self.partialView.add_peer(PodDescriptor("172.0.1.5", 4))
     neighbors = self.partialView.select_neighbors_for_reply(oldest)
     self.assertTrue(neighbors.is_full())
     self.assertEqual(neighbors.size, neighbors.shuffle_length)
 def test_sort(self):
     self.partialView.add_peer(PodDescriptor("172.0.1.5", 2))
     self.partialView.add_peer(PodDescriptor("172.0.1.4", 3))
     self.partialView.add_peer(PodDescriptor("172.0.1.8", 1))
     self.partialView.sort()
     self.assertEqual(self.partialView.peer_list[0].ip, "172.0.1.8")
     self.assertEqual(self.partialView.peer_list[1].ip, "172.0.1.5")
     self.assertEqual(self.partialView.peer_list[2].ip, "172.0.1.4")
 def test_select_neighbors_for_reply_should_contain_avoid_peer_if_size_eq_shuffle_length(
         self):
     oldest = PodDescriptor("172.0.1.4", 1)
     self.partialView.add_peer(PodDescriptor("172.0.1.6", 2))
     self.partialView.add_peer(oldest)
     neighbors = self.partialView.select_neighbors_for_reply(oldest)
     self.assertTrue(neighbors.is_full())
     self.assertEqual(neighbors.size, neighbors.shuffle_length)
 def test_sample_ips_should_return_a_list_of_ips(self):
     self.partialView.add_peer(PodDescriptor("172.0.1.5", 2))
     self.partialView.add_peer(PodDescriptor("172.0.1.4", 3))
     self.partialView.add_peer(PodDescriptor("172.0.1.10", 8))
     limit = 3
     sample = self.partialView.sample_ips(limit)
     self.assertIn("172.0.1.5", sample)
     self.assertIn("172.0.1.4", sample)
     self.assertIn("172.0.1.10", sample)
 def test_sample_descriptors_with_avoid_peer_not_in_view(self):
     to_avoid = PodDescriptor("172.0.1.9", 4)
     self.partialView.add_peer(PodDescriptor("172.0.1.5", 2))
     self.partialView.add_peer(PodDescriptor("172.0.1.4", 3))
     self.partialView.add_peer(PodDescriptor("172.0.1.10", 8))
     limit = 3
     sample = self.partialView.sample_descriptors(limit, to_avoid)
     self.assertEqual(len(sample), limit)
     self.assertFalse(to_avoid in sample)
 def test_sample_descriptors_with_avoid_peer_less_than_limit(self):
     to_avoid = PodDescriptor("172.0.1.9", 4)
     self.partialView.add_peer(PodDescriptor("172.0.1.5", 2))
     self.partialView.add_peer(PodDescriptor("172.0.1.4", 3))
     self.partialView.add_peer(to_avoid)
     limit = 3
     sample = self.partialView.sample_descriptors(limit, to_avoid)
     self.assertEqual(len(sample), 2)
     self.assertFalse(to_avoid in sample)
 def test_sample_descriptors_should_return_no_more_than_limit_peers(self):
     self.partialView.add_peer(PodDescriptor("172.0.1.5", 2))
     self.partialView.add_peer(PodDescriptor("172.0.1.4", 3))
     self.partialView.add_peer(PodDescriptor("172.0.1.9", 4))
     limit = 2
     size = self.partialView.size
     sample = self.partialView.sample_descriptors(limit)
     self.assertNotEqual(limit, size)
     self.assertEqual(len(sample), limit)
 def test_select_neighbors_for_request_and_add_peer_should_return_full_view(
         self):
     oldest = PodDescriptor("172.0.1.4", 1)
     self.partialView.add_peer(PodDescriptor("172.0.1.6", 2))
     self.partialView.add_peer(oldest)
     self.partialView.add_peer(PodDescriptor("172.0.1.5", 4))
     neighbors = self.partialView.select_neighbors_for_request(oldest)
     neighbors.add_peer_ip(self.partialView.ip, allow_self_ip=True)
     self.assertEqual(neighbors.size, self.partialView.shuffle_length)
     self.assertTrue(neighbors.is_full())
 def test_add_peer_should_return_false_if_peer_already_contained(self):
     peer = PodDescriptor("A new IP")
     self.partialView.add_peer(peer)
     size = self.partialView.size
     duplicated = PodDescriptor("A new IP")
     success = self.partialView.add_peer(duplicated)
     self.assertFalse(success)
     self.assertEqual(self.partialView.size, size)
     self.assertEqual(self.partialView.size,
                      len(self.partialView.peer_list))
 def setUp(self):
     self.partialView = PartialView("172.0.1.0")
     self.descriptors = []
     self.ips = [
         "172.0.1.1", "172.0.1.2", "172.0.1.3", "172.0.1.4", "172.0.1.5"
     ]
     for ip in self.ips:
         self.descriptors.append(PodDescriptor(ip))
 def test_add_peer_should_increment_size_if_not_full(self):
     size = self.partialView.size
     peer = PodDescriptor("A new IP")
     self.partialView.add_peer(peer)
     self.assertTrue(self.partialView.contains(peer))
     self.assertEqual(self.partialView.size, size + 1)
     self.assertEqual(self.partialView.size,
                      len(self.partialView.peer_list))
    def test_exchange_views(self):

        p1 = PartialView("First IP", 4, 3)
        p1.add_peer(PodDescriptor("172.0.1.6", 0))
        p1.add_peer(PodDescriptor("172.0.1.3", 2))
        p1.add_peer(PodDescriptor("172.0.1.5", 3))
        p1.add_peer(PodDescriptor("Second IP", 5))

        p2 = PartialView("Second IP", 4, 3)
        p2.add_peer(PodDescriptor("172.0.1.3", 0))
        p2.add_peer(PodDescriptor("172.0.1.5", 1))
        p2.add_peer(PodDescriptor("172.0.1.2", 2))
        p2.add_peer(PodDescriptor("172.0.1.1", 4))

        ########################
        # P1 starts the exchange
        ########################

        # 1) Increase by one the age of all neighbors
        p1.increment()
        # 2) Select neighbor Q with the highest age among all neighbors.
        oldest = p1.get_oldest_peer()
        # 3) Select l - 1 other random neighbors (meaning avoid oldest).
        request = p1.select_neighbors_for_request(oldest)
        # 4) Replace Q's entry with a new entry of age 0 and with P's address.
        request.add_peer_ip(p1.ip, allow_self_ip=True)

        self.assertTrue(request.is_full())
        self.assertEqual(request.size, p1.shuffle_length)

        ################################################
        # P2 receives neighbors and prepares a reply
        ################################################

        reply = p2.select_neighbors_for_reply()

        self.assertTrue(request.is_full())
        self.assertEqual(request.size, p1.shuffle_length)

        # Note that in p1 the oldest is p2
        # p1 and p2 know two peers in common
        # p2 does not have an entry with p1's ip
        # p1.merge should:
        # - Discard 172.0.1.3 and 172.0.1.5
        # - Put in unknown list 172.0.1.2, 172.0.1.1

        # 6) I remove the oldest peer from my view
        p1.remove_peer(oldest)
        p1.merge(request, reply)

        self.assertTrue(p1.is_full())
        for peer in reply.get_peer_list():
            self.assertTrue(p1.contains(peer))

        self.assertLessEqual(self.partialView.size, self.partialView.limit)
 def test_add_peer_with_allow_self_should_allow_self_entry(self):
     ip = "my ip"
     p1 = PartialView(ip)
     peer = PodDescriptor(ip)
     size = self.partialView.size
     success = p1.add_peer(peer, True)
     self.assertTrue(success)
     self.assertTrue(p1.contains_ip(ip))
     self.assertEqual(p1.size, size + 1)
 def test_add_peer_should_not_increment_size_if_full(self):
     peer = PodDescriptor("A new IP")
     for i in range(self.partialView.limit):
         self.partialView.add_peer(self.descriptors[i])
     size = self.partialView.size
     success = self.partialView.add_peer(peer)
     self.assertFalse(success)
     self.assertFalse(self.partialView.contains(peer))
     self.assertEqual(self.partialView.size, size)
     self.assertEqual(self.partialView.size,
                      len(self.partialView.peer_list))
Exemple #18
0
    def bootstrap_exponential_backoff(self, initial_delay, delay):

        logger.debug("Init", ip=self.ip, partialView=self.partialView)
        time.sleep(initial_delay)

        app_name = os.environ['APP']

        attempt = 1
        ips = self.k8s.list_pods_ips_by_field_selector(
            label_selector="app=" + app_name,
            field_selector="status.phase=Running")
        logger.debug("Bootstrapping", running_pods=ips, attempt=attempt)

        # Exponential backoff starts in case the number of running pods is lower than the partialView's limit.
        # TODO: Did I consider also that some pods might not be ready yet?
        # TODO: Consider that there is no need to have at least self.partialView.limit peers ready to start!
        # TODO: There can be peers running with an initial partial view of size < self.partialView.limit
        while len(ips) <= self.partialView.limit:
            attempt += 1
            delay *= 2
            time.sleep(delay)
            ips = self.k8s.list_pods_ips_by_field_selector(
                label_selector="app=epto",
                field_selector="status.phase=Running")
            logger.debug("Bootstrapping", running_pods=ips, attempt=attempt)

        # I populate the PartialView and I avoid to consider myself
        try:
            ips.remove(self.ip)
        except ValueError:
            logger.debug("self.ip was not there")

        while not self.partialView.is_full():
            random_ip = random.choice(ips)
            # TODO: REPLACE WITH self.partialView.add_peer_ip(random_ip)
            self.partialView.add_peer(
                PodDescriptor(random_ip, random.randint(0, 9)))

        logger.debug("Bootstrapping", partialView=self.partialView)
 def test_increment(self):
     self.partialView.add_peer(PodDescriptor("172.0.1.5", 1))
     self.partialView.add_peer(PodDescriptor("172.0.1.7", 3))
     self.partialView.increment()
     self.assertEqual(self.partialView.peer_list[0].age, 2)
     self.assertEqual(self.partialView.peer_list[1].age, 4)
 def test_initial_age_peer(self):
     self.partialView.add_peer(PodDescriptor("172.0.1.5"))
     self.assertEqual(self.partialView.peer_list[0].age, 0)
 def test_get_oldest_peer_should_return_a_pod_descriptor(self):
     self.partialView.add_peer(PodDescriptor("172.0.1.6", 2))
     self.partialView.add_peer(PodDescriptor("172.0.1.4", 1))
     self.partialView.add_peer(PodDescriptor("172.0.1.5", 4))
     oldest = self.partialView.get_oldest_peer()
     self.assertTrue(isinstance(oldest, PodDescriptor))