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))
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)))
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
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()
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)))
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)))
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))
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()
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()
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())
def test_uninitialized_scheduler(self): scheduler = LeafScheduler("foo", 9, False) self.assertRaises(InvalidScheduler, scheduler.place, self._place_request()) self.assertRaises(InvalidScheduler, scheduler.find, FindRequest())
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)
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))