Example #1
0
    def test_place_sampling(self, shuffle, client_class):
        client_class.side_effect = self.create_fake_client
        shuffle.side_effect = self.fake_shuffle(
            [ChildInfo(id="bar", address="bar"),
             ChildInfo(id="baz", address="baz"),
             ChildInfo(id="qux", address="qux")])

        bar_client = MagicMock()
        bar_response = PlaceResponse(PlaceResultCode.OK, agent_id="bar",
                                     score=Score(5, 90))
        bar_client.host_place.return_value = bar_response
        self._clients["bar"] = bar_client

        baz_client = MagicMock()
        baz_response = PlaceResponse(PlaceResultCode.OK, agent_id="baz",
                                     score=Score(30, 80))
        baz_client.host_place.return_value = baz_response
        self._clients["baz"] = baz_client

        scheduler = LeafScheduler("foo", 9, False)
        scheduler.configure([ChildInfo(id="qux", address="qux"),
                             ChildInfo(id="bar", address="bar"),
                             ChildInfo(id="baz", address="baz")])

        response = scheduler.place(self._place_request())
        assert_that(response, is_(same_instance(baz_response)))
    def test_place_during_reconfigure(self):
        # Create leaf scheduler which will return RESOURCE_CONSTRAINT
        scheduler = LeafScheduler("foo", 1, False)
        scheduler._placement_hosts = MagicMock()
        scheduler._placement_hosts.return_value = []

        # Create scheduler handler
        handler = SchedulerHandler()
        handler._create_scheduler = MagicMock()
        handler._create_scheduler.return_value = scheduler

        # Configure scheduler handler with leaf scheduler
        handler.configure([
            SchedulerRole("foo",
                          "parent-id",
                          scheduler_children=[ChildInfo(id="child")])
        ])
        assert_that(handler._schedulers, has_length(1))

        concurrency = 5
        threads = []
        results = {}
        done = [False]

        # Define the thread which keeps calling place, to make sure it
        # always return RESOURCE_CONSTRAINT
        def _loop():
            while True:
                actual_response = handler.place(PlaceRequest(
                    Resource(), "foo"))
                assert_that(actual_response.result,
                            is_not(PlaceResultCode.SYSTEM_ERROR))

                if done[0]:
                    results[threading.current_thread().name] = True
                    break

        for _ in xrange(concurrency):
            thread = threading.Thread(target=_loop)
            thread.start()
            threads.append(thread)

        # Reconfigure scheduler to demote it. To test when reconfiguring,
        # there is no race when new schedulers replacing the old ones.
        handler.configure([])
        assert_that(handler._schedulers, has_length(0))
        time.sleep(0.1)
        done[0] = True

        for thread in threads:
            thread.join()

        assert_that(len(results), equal_to(concurrency))
    def test_place_during_reconfigure(self):
        # Create leaf scheduler which will return RESOURCE_CONSTRAINT
        scheduler = LeafScheduler("foo", 1, False)
        scheduler._placement_hosts = MagicMock()
        scheduler._placement_hosts.return_value = []

        # Create scheduler handler
        handler = SchedulerHandler()
        handler._create_scheduler = MagicMock()
        handler._create_scheduler.return_value = scheduler

        # Configure scheduler handler with leaf scheduler
        handler.configure(
            [SchedulerRole("foo", "parent-id",
                           scheduler_children=[ChildInfo(id="child")])])
        assert_that(handler._schedulers, has_length(1))

        concurrency = 5
        threads = []
        results = {}
        done = [False]

        # Define the thread which keeps calling place, to make sure it
        # always return RESOURCE_CONSTRAINT
        def _loop():
            while True:
                actual_response = handler.place(
                    PlaceRequest(Resource(), "foo"))
                assert_that(actual_response.result,
                            is_not(PlaceResultCode.SYSTEM_ERROR))

                if done[0]:
                    results[threading.current_thread().name] = True
                    break

        for _ in xrange(concurrency):
            thread = threading.Thread(target=_loop)
            thread.start()
            threads.append(thread)

        # Reconfigure scheduler to demote it. To test when reconfiguring,
        # there is no race when new schedulers replacing the old ones.
        handler.configure([])
        assert_that(handler._schedulers, has_length(0))
        time.sleep(0.1)
        done[0] = True

        for thread in threads:
            thread.join()

        assert_that(len(results), equal_to(concurrency))
Example #4
0
    def test_place_local_agent(self, client_class):
        client_class.side_effect = self.create_fake_client

        remote_client = MagicMock()
        self._clients["local-id"] = remote_client

        local_response = PlaceResponse(
            PlaceResultCode.OK, agent_id="local-id", score=Score(5, 90))
        self._scheduler_handler.host_place.return_value = local_response

        scheduler = LeafScheduler("foo", 9, False)
        scheduler.configure([ChildInfo(id="local-id")])

        response = scheduler.place(self._place_request())
        assert_that(remote_client.place.called, is_(False))
        assert_that(response, is_(same_instance(local_response)))
Example #5
0
 def _create_scheduler_with_hosts(self, name, number_of_hosts):
     scheduler = LeafScheduler(name, 1.0, False)
     hosts = []
     for num in range(number_of_hosts):
         child = name + "_host_" + str(num)
         child_id = "id_" + child
         child_address = "address_" + child
         hosts.append(
             ChildInfo(id=child_id, address=child_address, port=num))
         client = MagicMock()
         response = PlaceResponse(PlaceResultCode.OK,
                                  agent_id=child_id,
                                  score=Score(100, 90))
         client.host_place.return_value = response
         self._clients[child_address] = client
     scheduler.configure(hosts)
     return scheduler
Example #6
0
    def test_place_exception(self, client_class):
        client_class.side_effect = self.create_fake_client

        client = MagicMock()
        e = TimeoutError()
        client.place.side_effect = e
        self._clients["baz"] = client

        scheduler = LeafScheduler("foo", 1.0, False)
        scheduler.configure([ChildInfo(id="baz", address="baz", port=123)])

        response = scheduler.place(self._place_request())
        assert_that(response.result, is_(PlaceResultCode.SYSTEM_ERROR))

        # must shutdown to join the futures since the patch lifecycle
        # ends when this method returns
        self._threadpool.shutdown()
Example #7
0
    def test_place_res_with_missing(self, health_checker, client_class):
        client_class.side_effect = self.create_fake_client
        _health_checker = MagicMock()
        health_checker.return_value = _health_checker
        _health_checker.get_missing_hosts = ["bar"]

        baz_client = MagicMock()
        baz_response = PlaceResponse(PlaceResultCode.OK, agent_id="baz",
                                     score=Score(30, 80))
        baz_client.host_place.return_value = baz_response
        self._clients["baz"] = baz_client

        scheduler = LeafScheduler("foo", 1.0, True)
        scheduler.configure([ChildInfo(id="bar", address="bar"),
                             ChildInfo(id="baz", address="baz")])

        response = scheduler.place(self._place_request())
        assert_that(response, is_(same_instance(baz_response)))
Example #8
0
    def test_find_resource_found(self, client_class):
        client_class.side_effect = self.create_fake_client

        bar_client = MagicMock()
        bar_response = FindResponse(FindResultCode.NOT_FOUND)
        bar_client.host_find.return_value = bar_response
        self._clients["bar"] = bar_client

        baz_client = MagicMock()
        baz_response = FindResponse(FindResultCode.OK)
        baz_client.host_find.return_value = baz_response
        self._clients["baz"] = baz_client

        scheduler = LeafScheduler("foo", 9, False)
        scheduler.configure([ChildInfo(id="bar", address="bar"),
                             ChildInfo(id="baz", address="baz")])

        response = scheduler.find(self._place_request())
        assert_that(response, is_(same_instance(baz_response)))
Example #9
0
    def test_place_resource_not_found(self, client_class):
        client_class.side_effect = self.create_fake_client

        bar_client = MagicMock()
        bar_response = PlaceResponse(PlaceResultCode.NO_SUCH_RESOURCE)
        bar_client.host_place.return_value = bar_response
        self._clients["bar"] = bar_client

        baz_client = MagicMock()
        baz_response = PlaceResponse(PlaceResultCode.SYSTEM_ERROR)
        baz_client.host_place.return_value = baz_response
        self._clients["baz"] = baz_client

        scheduler = LeafScheduler("foo", 9, False)
        scheduler.configure([ChildInfo(id="bar", address="bar"),
                             ChildInfo(id="baz", address="baz")])

        response = scheduler.place(self._place_request())
        assert_that(response.result, is_(PlaceResultCode.NO_SUCH_RESOURCE))
Example #10
0
    def test_find_timeout(self, wait_fn, client_class):
        client_class.side_effect = self.create_fake_client

        client = MagicMock()
        response = FindResponse(FindResultCode.OK)
        client.find.return_value = response
        self._clients["baz"] = client

        scheduler = LeafScheduler("foo", 9, False)
        scheduler.configure([ChildInfo(id="baz", address="baz")])

        wait_fn.return_value = set(), set()

        response = scheduler.find(self._place_request())
        assert_that(response.result, is_(FindResultCode.NOT_FOUND))

        # must shutdown to join the futures since the patch lifecycle
        # ends when this method returns
        self._threadpool.shutdown()
Example #11
0
    def test_place_timeout(self, client_class,
                           wait_fn, serial_fn):
        client_class.side_effect = self.create_fake_client

        client = MagicMock()
        response = PlaceResponse(PlaceResultCode.OK)
        client.place.return_value = response
        self._clients["baz"] = client

        wait_fn.return_value = set(), set()
        serial_fn.return_value = set()

        scheduler = LeafScheduler("foo", 9, False)
        scheduler.configure([ChildInfo(id="baz", address="baz")])

        response = scheduler.place(self._place_request())
        assert_that(response.result, is_(PlaceResultCode.SYSTEM_ERROR))

        # must shutdown to join the futures since the patch lifecycle
        # ends when this method returns
        self._threadpool.shutdown()
Example #12
0
    def test_find_clears_scheduler_id(self, client_class):
        client_class.side_effect = self.create_fake_client

        client = MagicMock()
        self._clients["bar"] = client

        scheduler = LeafScheduler("foo", 9, False)
        scheduler.configure([ChildInfo(id="bar", address="bar")])
        scheduler.find(FindRequest(scheduler_id="foo"))

        client.host_find.assert_called_with(FindRequest())
Example #13
0
 def test_uninitialized_scheduler(self):
     scheduler = LeafScheduler("foo", 9, False)
     self.assertRaises(InvalidScheduler,
                       scheduler.place, self._place_request())
     self.assertRaises(InvalidScheduler,
                       scheduler.find, FindRequest())
Example #14
0
    def test_configured(self):
        """
        Test that the configured settings are set correctly.
        """
        # Check that the configured flag is only set after configuration.
        scheduler = LeafScheduler("foo", 9, False)
        self.assertEqual(scheduler._configured, ConfigStates.UNINITIALIZED)

        scheduler.configure(self._build_scheduler_configure())
        _hosts = scheduler._get_hosts()
        self.assertEqual(scheduler._configured, ConfigStates.INITIALIZED)
        self.assertEqual(len(_hosts), 3)

        ds_set_1 = set()
        ds_tag_set_1 = set()
        net_set_1 = set()
        ds_set_2 = set()
        ds_tag_set_2 = set()
        net_set_2 = set()
        ds_set_3 = set()
        ds_tag_set_3 = set()
        net_set_3 = set()

        ds_set_1.add("ds_1")
        ds_set_1.add("ds_2")
        ds_set_1.add("ds_3")
        ds_tag_set_1.add("ds_tag_1")
        ds_tag_set_1.add("ds_tag_2")
        ds_tag_set_1.add("ds_tag_3")
        net_set_1.add("net_1")
        net_set_1.add("net_2")
        net_set_1.add("net_3")

        ds_set_2.add("ds_4")
        ds_set_2.add("ds_5")
        ds_set_2.add("ds_6")
        ds_tag_set_2.add("ds_tag_4")
        ds_tag_set_2.add("ds_tag_5")
        ds_tag_set_2.add("ds_tag_6")
        net_set_2.add("net_4")
        net_set_2.add("net_5")
        net_set_2.add("net_6")

        ds_set_3.add("ds_7")
        ds_set_3.add("ds_8")
        ds_set_3.add("ds_9")
        ds_tag_set_3.add("ds_tag_7")
        ds_tag_set_3.add("ds_tag_8")
        ds_tag_set_3.add("ds_tag_9")
        net_set_3.add("net_7")
        net_set_3.add("net_8")
        net_set_3.add("net_9")

        for child in _hosts:
            # assert there're only 3 resources type,
            # i.e values are coalesced.
            self.assertEqual(len(child.constraints), 3)

            for constraint in child.constraints:
                if constraint.type == ResourceConstraintType.DATASTORE:
                    if child.id == "baz_1":
                        self.assertEqual(
                            set(constraint.values) == ds_set_1, True)
                    if child.id == "baz_2":
                        self.assertEqual(
                            set(constraint.values) == ds_set_2, True)
                    if child.id == "baz_3":
                        self.assertEqual(
                            set(constraint.values) == ds_set_3, True)
                if constraint.type == ResourceConstraintType.DATASTORE_TAG:
                    if child.id == "baz_1":
                        self.assertEqual(
                            set(constraint.values) == ds_tag_set_1, True)
                    if child.id == "baz_2":
                        self.assertEqual(
                            set(constraint.values) == ds_tag_set_2, True)
                    if child.id == "baz_3":
                        self.assertEqual(
                            set(constraint.values) == ds_tag_set_3, True)
                if constraint.type == ResourceConstraintType.NETWORK:
                    if child.id == "baz_1":
                        self.assertEqual(
                            set(constraint.values) == net_set_1, True)
                    if child.id == "baz_2":
                        self.assertEqual(
                            set(constraint.values) == net_set_2, True)
                    if child.id == "baz_3":
                        self.assertEqual(
                            set(constraint.values) == net_set_3, True)

        scheduler.cleanup()
        self.assertEqual(scheduler._configured, ConfigStates.UNINITIALIZED)
Example #15
0
    def test_place_with_resource_constraints(self, client_class):
        client_class.side_effect = self.create_fake_client

        bar_client = MagicMock()
        bar_response = PlaceResponse(PlaceResultCode.OK, agent_id="baz_1",
                                     score=Score(5, 90))
        bar_client.host_place.return_value = bar_response
        self._clients["baz_1"] = bar_client

        baz_client = MagicMock()
        baz_response = PlaceResponse(PlaceResultCode.OK, agent_id="baz_2",
                                     score=Score(30, 80))
        baz_client.host_place.return_value = baz_response
        self._clients["baz_2"] = baz_client

        baz_client = MagicMock()
        baz_response = PlaceResponse(PlaceResultCode.OK, agent_id="baz_3",
                                     score=Score(35, 85))
        baz_client.host_place.return_value = baz_response
        self._clients["baz_3"] = baz_client

        scheduler = LeafScheduler("foo", 8, False)
        scheduler.configure(self._build_scheduler_configure())

        # Check OR among values, should succeed
        request = self._place_request()
        request.resource.vm.resource_constraints = [ResourceConstraint(
            ResourceConstraintType.NETWORK, ["net_1", "net_17"])]
        response = scheduler.place(request)
        assert_that(response.result, is_(PlaceResultCode.OK))
        assert_that(response.agent_id, is_("baz_1"))

        # Check AND among constraints, should fail
        request = self._place_request()
        request.resource.vm.resource_constraints = [
            ResourceConstraint(
                ResourceConstraintType.NETWORK, ["net_1"]),
            ResourceConstraint(
                ResourceConstraintType.NETWORK, ["net_4"])]

        response = scheduler.place(request)
        assert_that(response.result, is_(PlaceResultCode.NO_SUCH_RESOURCE))

        # Check AND among constraints, should succeed
        request = self._place_request()
        request.resource.vm.resource_constraints = [
            ResourceConstraint(
                ResourceConstraintType.DATASTORE, ["ds_1"]),
            ResourceConstraint(
                ResourceConstraintType.NETWORK, ["net_2"])]

        response = scheduler.place(request)
        assert_that(response.result, is_(PlaceResultCode.OK))
        assert_that(response.agent_id, is_("baz_1"))

        # Check OR among values + AND among constraints, should succeed
        request = self._place_request()
        request.resource.vm.resource_constraints = [
            ResourceConstraint(
                ResourceConstraintType.NETWORK,
                ["net_1", "net_17"]),
            ResourceConstraint(
                ResourceConstraintType.DATASTORE_TAG,
                ["ds_tag_18", "ds_tag_1"])]

        response = scheduler.place(request)
        assert_that(response.result, is_(PlaceResultCode.OK))
        assert_that(response.agent_id, is_("baz_1"))

        # Check OR among values + AND among constraints, should fail
        request = self._place_request()
        request.resource.vm.resource_constraints = [
            ResourceConstraint(
                ResourceConstraintType.NETWORK,
                ["net_1", "net_17"]),
            ResourceConstraint(
                ResourceConstraintType.DATASTORE_TAG,
                ["ds_tag_18", "ds_tag_19"])]

        response = scheduler.place(request)
        assert_that(response.result, is_(PlaceResultCode.NO_SUCH_RESOURCE))