def test_addConnectionFor_adds_connection(self): service = RegionService(sentinel.ipcWorker) uuid = factory.make_UUID() c1 = DummyConnection() c2 = DummyConnection() service._addConnectionFor(uuid, c1) service._addConnectionFor(uuid, c2) self.assertEqual({uuid: {c1, c2}}, service.connections)
def test_call__doesnt_add_result_to_cache_for_not_cache_call(self): conn = DummyConnection() conn.ident = factory.make_name("ident") self.patch(conn, "callRemote").return_value = succeed(sentinel.boot_images) client = RackClient(conn, {}) call_cache = client._getCallCache() result = yield client(cluster.ListBootImages) self.assertIs(sentinel.boot_images, result) self.assertNotIn(cluster.ListBootImages, call_cache)
def test_call__adds_result_to_cache(self): conn = DummyConnection() conn.ident = factory.make_name("ident") self.patch(conn, "callRemote").return_value = succeed(sentinel.power_types) client = RackClient(conn, {}) call_cache = client._getCallCache() result = yield client(cluster.DescribePowerTypes) self.assertIs(sentinel.power_types, result) self.assertIs(sentinel.power_types, call_cache[cluster.DescribePowerTypes])
def test_call__returns_cache_value(self): conn = DummyConnection() conn.ident = factory.make_name("ident") client = RackClient(conn, {}) call_cache = client._getCallCache() power_types = {"power_types": [{"name": "ipmi"}, {"name": "wedge"}]} call_cache[cluster.DescribePowerTypes] = power_types result = yield client(cluster.DescribePowerTypes) # The result is a copy. It should equal the result but not be # the same object. self.assertEquals(power_types, result) self.assertIsNot(power_types, result)
def test__call__records_latency_metric(self): mock_metrics = self.patch(PROMETHEUS_METRICS, 'update') conn = DummyConnection() conn.ident = factory.make_name('ident') self.patch(conn, 'callRemote').return_value = (succeed(sentinel.boot_images)) client = RackClient(conn, {}) yield client(cluster.ListBootImages) mock_metrics.assert_called_with('maas_region_rack_rpc_call_latency', 'observe', labels={'call': 'ListBootImages'}, value=ANY)
def test_call__records_latency_metric(self): mock_metrics = self.patch(PROMETHEUS_METRICS, "update") conn = DummyConnection() conn.ident = factory.make_name("ident") self.patch(conn, "callRemote").return_value = succeed(sentinel.boot_images) client = RackClient(conn, {}) yield client(cluster.ListBootImages) mock_metrics.assert_called_with( "maas_region_rack_rpc_call_latency", "observe", labels={"call": "ListBootImages"}, value=ANY, )
def test_removeConnectionFor_is_okay_if_connection_is_not_there(self): service = RegionService(sentinel.ipcWorker) uuid = factory.make_UUID() service._removeConnectionFor(uuid, DummyConnection()) self.assertEqual({uuid: set()}, service.connections)
def test_getCallCache_returns_existing(self): conn = DummyConnection() cache = {} client = RackClient(conn, cache) call_cache = client._getCallCache() call_cache2 = client._getCallCache() self.assertIs(call_cache, cache["call_cache"]) self.assertIs(call_cache2, cache["call_cache"]) self.assertIs(call_cache2, call_cache)
def test_call_with_keyword_arguments_raises_useful_error(self): conn = DummyConnection() client = common.Client(conn) expected_message = re.escape( "provisioningserver.rpc.common.Client called with 3 positional " "arguments, (1, 2, 3), but positional arguments are not " "supported. Usage: client(command, arg1=value1, ...)") with ExpectedException(TypeError, expected_message): client(sentinel.command, 1, 2, 3)
def test_removeConnectionFor_fires_disconnected_event(self): service = RegionService(sentinel.ipcWorker) uuid = factory.make_UUID() c1 = DummyConnection() mock_fire = self.patch(service.events.disconnected, "fire") service._removeConnectionFor(uuid, c1) self.assertThat(mock_fire, MockCalledOnceWith(uuid))
def test__call__adds_result_to_cache(self): conn = DummyConnection() self.patch(conn, 'callRemote').return_value = ( succeed(sentinel.power_types)) client = RackClient(conn, {}) call_cache = client._getCallCache() result = yield client(cluster.DescribePowerTypes) self.assertIs(sentinel.power_types, result) self.assertIs( sentinel.power_types, call_cache[cluster.DescribePowerTypes])
def test_addConnectionFor_notifies_waiters(self): service = RegionService(sentinel.ipcWorker) uuid = factory.make_UUID() c1 = DummyConnection() c2 = DummyConnection() waiter1 = Mock() waiter2 = Mock() service.waiters[uuid].add(waiter1) service.waiters[uuid].add(waiter2) service._addConnectionFor(uuid, c1) service._addConnectionFor(uuid, c2) self.assertEqual({uuid: {c1, c2}}, service.connections) # Both mock waiters are called twice. A real waiter would only be # called once because it immediately unregisters itself once called. self.assertThat(waiter1.callback, MockCallsMatch(call(c1), call(c2))) self.assertThat(waiter2.callback, MockCallsMatch(call(c1), call(c2)))
def test_getAllClients(self): service = RegionService(sentinel.ipcWorker) uuid1 = factory.make_UUID() c1 = DummyConnection() c2 = DummyConnection() service.connections[uuid1].update({c1, c2}) uuid2 = factory.make_UUID() c3 = DummyConnection() c4 = DummyConnection() service.connections[uuid2].update({c3, c4}) clients = service.getAllClients() self.assertThat(list(clients), MatchesAny( MatchesSetwise( Equals(RackClient(c1, {})), Equals(RackClient(c3, {}))), MatchesSetwise( Equals(RackClient(c1, {})), Equals(RackClient(c4, {}))), MatchesSetwise( Equals(RackClient(c2, {})), Equals(RackClient(c3, {}))), MatchesSetwise( Equals(RackClient(c2, {})), Equals(RackClient(c4, {}))), ))
def test_getClientFor_returns_random_connection(self): c1 = DummyConnection() c2 = DummyConnection() chosen = DummyConnection() service = RegionService(sentinel.ipcWorker) uuid = factory.make_UUID() conns_for_uuid = service.connections[uuid] conns_for_uuid.update({c1, c2}) def check_choice(choices): self.assertItemsEqual(choices, conns_for_uuid) return chosen self.patch(random, "choice", check_choice) def check(client): self.assertThat(client, Equals(RackClient(chosen, {}))) self.assertIs(client.cache, service.connectionsCache[client._conn]) return service.getClientFor(uuid).addCallback(check)
def test_getConnectionFor_returns_existing_connection(self): service = RegionService(sentinel.ipcWorker) uuid = factory.make_UUID() conn = DummyConnection() service._addConnectionFor(uuid, conn) d = service._getConnectionFor(uuid, 1) # No waiter is added because a connection is available. self.assertEqual({uuid: set()}, service.waiters) def check(conn_returned): self.assertEquals(conn, conn_returned) return d.addCallback(check)
def test_getConnectionFor_waits_for_connection(self): service = RegionService(sentinel.ipcWorker) uuid = factory.make_UUID() conn = DummyConnection() # Add the connection later (we're in the reactor thread right # now so this won't happen until after we return). reactor.callLater(0, service._addConnectionFor, uuid, conn) d = service._getConnectionFor(uuid, 1) # A waiter is added for the connection we're interested in. self.assertEqual({uuid: {d}}, service.waiters) def check(conn_returned): self.assertEqual(conn, conn_returned) # The waiter has been unregistered. self.assertEqual({uuid: set()}, service.waiters) return d.addCallback(check)
def test__call__returns_cache_value(self): conn = DummyConnection() client = RackClient(conn, {}) call_cache = client._getCallCache() power_types = { "power_types": [ { 'name': 'ipmi', }, { 'name': 'wedge', }, ] } call_cache[cluster.DescribePowerTypes] = power_types result = yield client(cluster.DescribePowerTypes) # The result is a copy. It should equal the result but not be # the same object. self.assertEquals(power_types, result) self.assertIsNot(power_types, result)
def test_getConnectionFor_with_concurrent_waiters(self): service = RegionService(sentinel.ipcWorker) uuid = factory.make_UUID() conn = DummyConnection() # Add the connection later (we're in the reactor thread right # now so this won't happen until after we return). reactor.callLater(0, service._addConnectionFor, uuid, conn) d1 = service._getConnectionFor(uuid, 1) d2 = service._getConnectionFor(uuid, 1) # A waiter is added for each call to _getConnectionFor(). self.assertEqual({uuid: {d1, d2}}, service.waiters) d = DeferredList((d1, d2)) def check(results): self.assertEqual([(True, conn), (True, conn)], results) # The waiters have both been unregistered. self.assertEqual({uuid: set()}, service.waiters) return d.addCallback(check)
def test_init(self): conn = DummyConnection() client = common.Client(conn) self.assertThat(client._conn, Is(conn))
def test_getCallCache_adds_new_call_cache(self): conn = DummyConnection() cache = {} client = RackClient(conn, cache) call_cache = client._getCallCache() self.assertIs(call_cache, cache["call_cache"])