Automatically place servers using learned resource capacity
This commit is contained in:
@@ -107,6 +107,50 @@ class AgentTests(unittest.TestCase):
|
||||
else:
|
||||
self.assertEqual(inventory["cpuUsagePercent"], usage)
|
||||
|
||||
def resource_container(self):
|
||||
return {"Name": self.agent.container_name(INSTANCE, 1),
|
||||
"Config": {"Labels": {module.LABEL + ".managed": "true", module.LABEL + ".instance": INSTANCE, module.LABEL + ".generation": "1"}},
|
||||
"State": {"Running": True, "StartedAt": "2000-01-01T00:00:00.000000000Z"},
|
||||
"Mounts": [{"Type": "bind", "Source": str(self.agent.instance_dir(INSTANCE, 1) / "app"), "Destination": "/home/plutainer/app"}]}
|
||||
|
||||
def test_instance_resources_batches_owned_containers_and_normalizes_core_cpu_and_memory(self):
|
||||
name = self.agent.container_name(INSTANCE, 1)
|
||||
rows = json.dumps({"Name": name, "CPUPerc": "150.00%", "MemUsage": "384.5MiB / 8GiB", "PIDs": "12"})
|
||||
with patch.object(self.docker, "call", side_effect=["container-id\n", json.dumps([self.resource_container()]), rows]) as call:
|
||||
samples = self.agent.instance_resources()
|
||||
self.assertEqual(len(samples), 1)
|
||||
self.assertEqual(samples[0]["instanceId"], INSTANCE)
|
||||
self.assertEqual(samples[0]["generation"], 1)
|
||||
self.assertEqual(samples[0]["cpuCores"], 1.5)
|
||||
self.assertEqual(samples[0]["memoryBytes"], int(384.5 * 1024 ** 2))
|
||||
self.assertGreater(samples[0]["uptimeSeconds"], 300)
|
||||
self.assertEqual(call.call_args_list[-1].args, ("stats", "--no-stream", "--no-trunc", "--format", "{{json .}}", name))
|
||||
|
||||
def test_instance_resources_ignores_stopped_foreign_and_mismatched_containers(self):
|
||||
for change in ("stopped", "foreign", "generation", "name"):
|
||||
info = self.resource_container()
|
||||
if change == "stopped":
|
||||
info["State"]["Running"] = False
|
||||
elif change == "foreign":
|
||||
info["Mounts"][0]["Source"] = "/another-installation/app"
|
||||
elif change == "generation":
|
||||
info["Config"]["Labels"][module.LABEL + ".generation"] = "2"
|
||||
else:
|
||||
info["Name"] = "unrelated"
|
||||
with patch.object(self.docker, "call", side_effect=["container-id\n", json.dumps([info])]) as call:
|
||||
self.assertEqual(self.agent.instance_resources(), [])
|
||||
self.assertEqual(call.call_count, 2)
|
||||
|
||||
def test_instance_resources_skips_unavailable_stats_instead_of_reporting_zero_usage(self):
|
||||
good = {"Name": self.agent.container_name(INSTANCE, 1), "CPUPerc": "0.00%", "MemUsage": "200MiB / 8GiB", "PIDs": "10"}
|
||||
for override in ({"CPUPerc": "NaN%"}, {"CPUPerc": "-1%"}, {"CPUPerc": "--"}, {"MemUsage": "bad"}, {"MemUsage": "0B / 0B"}, {"PIDs": "0"}, {"Name": "foreign"}):
|
||||
with patch.object(self.docker, "call", side_effect=["container-id\n", json.dumps([self.resource_container()]), json.dumps({**good, **override})]):
|
||||
self.assertEqual(self.agent.instance_resources(), [])
|
||||
with patch.object(self.docker, "call", side_effect=["container-id\n", json.dumps([self.resource_container()]), json.dumps(good)]):
|
||||
self.assertEqual(self.agent.instance_resources()[0]["cpuCores"], 0)
|
||||
with patch.object(self.agent, "instance_resources", side_effect=AgentError("timed out")):
|
||||
self.assertNotIn("instanceResources", self.agent.inventory())
|
||||
|
||||
def operation(self, kind, payload=None, op_id="operation-1", generation=1):
|
||||
return {"id": op_id, "kind": kind, "instanceId": INSTANCE, "generation": generation, "payload": payload or {}}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user