From e39fc1ecb816edfd7e8e1ca62125547d66170ec3 Mon Sep 17 00:00:00 2001 From: Daisuke Taniwaki Date: Thu, 15 Feb 2018 23:10:51 +0900 Subject: [PATCH] Implement helper methods to check the slave availability --- tests/test_mesosslave.py | 37 +++++++++++++++++++++++++++++++++---- ucrspawner/mesosslave.py | 12 ++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/tests/test_mesosslave.py b/tests/test_mesosslave.py index 5cb5098..237c407 100644 --- a/tests/test_mesosslave.py +++ b/tests/test_mesosslave.py @@ -58,13 +58,42 @@ def test_match(monkeypatch): slave.match(MarathonConstraint('foo', 'UNKNOWN', '')) assert str(excinfo.value) == 'Unsupported constraint operator: UNKNOWN' +mesos_master_response_empty = json.loads('{"id":"40237088-f509-46a4-a5f1-c8f88ca8e03f-S0","hostname":"mesos-slave","port":5051,"attributes":{"foo":123.0,"bar":"wow"},"pid":"slave(1)@172.24.0.5:5051","registered_time":1518339392.10703,"resources":{"disk":69716.0,"mem":999.0,"gpus":0.0,"cpus":2.0,"ports":"[31000-32000]"},"used_resources":{"disk":0.0,"mem":0.0,"gpus":0.0,"cpus":0.0},"offered_resources":{"disk":0.0,"mem":0.0,"gpus":0.0,"cpus":0.0},"reserved_resources":{},"unreserved_resources":{"disk":69716.0,"mem":999.0,"gpus":0.0,"cpus":2.0,"ports":"[31000-32000]"},"active":true,"version":"1.4.0","capabilities":["MULTI_ROLE","HIERARCHICAL_ROLE","RESERVATION_REFINEMENT"],"reserved_resources_full":{},"unreserved_resources_full":[{"name":"cpus","type":"SCALAR","scalar":{"value":2.0},"role":"*"},{"name":"mem","type":"SCALAR","scalar":{"value":999.0},"role":"*"},{"name":"disk","type":"SCALAR","scalar":{"value":69716.0},"role":"*"},{"name":"ports","type":"RANGES","ranges":{"range":[{"begin":31000,"end":32000}]},"role":"*"}],"used_resources_full":[],"offered_resources_full":[]}') + +mesos_master_response_used = json.loads('{"id":"40237088-f509-46a4-a5f1-c8f88ca8e03f-S0","hostname":"mesos-slave","port":5051,"attributes":{"foo":123.0,"bar":"wow"},"pid":"slave(1)@172.24.0.5:5051","registered_time":1518339392.10703,"resources":{"disk":69716.0,"mem":999.0,"gpus":0.0,"cpus":2.0,"ports":"[31000-32000]"},"used_resources":{"disk":0.0,"mem":0.0,"gpus":0.0,"cpus":1.0},"offered_resources":{"disk":0.0,"mem":0.0,"gpus":0.0,"cpus":0.0},"reserved_resources":{},"unreserved_resources":{"disk":69716.0,"mem":999.0,"gpus":0.0,"cpus":2.0,"ports":"[31000-32000]"},"active":true,"version":"1.4.0","capabilities":["MULTI_ROLE","HIERARCHICAL_ROLE","RESERVATION_REFINEMENT"],"reserved_resources_full":{},"unreserved_resources_full":[{"name":"cpus","type":"SCALAR","scalar":{"value":2.0},"role":"*"},{"name":"mem","type":"SCALAR","scalar":{"value":999.0},"role":"*"},{"name":"disk","type":"SCALAR","scalar":{"value":69716.0},"role":"*"},{"name":"ports","type":"RANGES","ranges":{"range":[{"begin":31000,"end":32000}]},"role":"*"}],"used_resources_full":[],"offered_resources_full":[]}') + +mesos_master_response_full = json.loads('{"id":"40237088-f509-46a4-a5f1-c8f88ca8e03f-S0","hostname":"mesos-slave","port":5051,"attributes":{"foo":123.0,"bar":"wow"},"pid":"slave(1)@172.24.0.5:5051","registered_time":1518339392.10703,"resources":{"disk":69716.0,"mem":999.0,"gpus":0.0,"cpus":2.0,"ports":"[31000-32000]"},"used_resources":{"disk":0.0,"mem":0.0,"gpus":0.0,"cpus":2.0},"offered_resources":{"disk":0.0,"mem":0.0,"gpus":0.0,"cpus":0.0},"reserved_resources":{},"unreserved_resources":{"disk":69716.0,"mem":999.0,"gpus":0.0,"cpus":2.0,"ports":"[31000-32000]"},"active":true,"version":"1.4.0","capabilities":["MULTI_ROLE","HIERARCHICAL_ROLE","RESERVATION_REFINEMENT"],"reserved_resources_full":{},"unreserved_resources_full":[{"name":"cpus","type":"SCALAR","scalar":{"value":2.0},"role":"*"},{"name":"mem","type":"SCALAR","scalar":{"value":999.0},"role":"*"},{"name":"disk","type":"SCALAR","scalar":{"value":69716.0},"role":"*"},{"name":"ports","type":"RANGES","ranges":{"range":[{"begin":31000,"end":32000}]},"role":"*"}],"used_resources_full":[],"offered_resources_full":[]}') + +def test_is_empty(monkeypatch): + + slave = mesosslave.MesosSlave(mesos_master_response_empty) + assert slave.is_empty() + + slave = mesosslave.MesosSlave(mesos_master_response_used) + assert not slave.is_empty() + + slave = mesosslave.MesosSlave(mesos_master_response_full) + assert not slave.is_empty() + def test_is_available(monkeypatch): - mesos_master_response = json.loads('{"id":"40237088-f509-46a4-a5f1-c8f88ca8e03f-S0","hostname":"mesos-slave","port":5051,"attributes":{"foo":123.0,"bar":"wow"},"pid":"slave(1)@172.24.0.5:5051","registered_time":1518339392.10703,"resources":{"disk":69716.0,"mem":999.0,"gpus":0.0,"cpus":2.0,"ports":"[31000-32000]"},"used_resources":{"disk":0.0,"mem":0.0,"gpus":0.0,"cpus":0.0},"offered_resources":{"disk":0.0,"mem":0.0,"gpus":0.0,"cpus":0.0},"reserved_resources":{},"unreserved_resources":{"disk":69716.0,"mem":999.0,"gpus":0.0,"cpus":2.0,"ports":"[31000-32000]"},"active":true,"version":"1.4.0","capabilities":["MULTI_ROLE","HIERARCHICAL_ROLE","RESERVATION_REFINEMENT"],"reserved_resources_full":{},"unreserved_resources_full":[{"name":"cpus","type":"SCALAR","scalar":{"value":2.0},"role":"*"},{"name":"mem","type":"SCALAR","scalar":{"value":999.0},"role":"*"},{"name":"disk","type":"SCALAR","scalar":{"value":69716.0},"role":"*"},{"name":"ports","type":"RANGES","ranges":{"range":[{"begin":31000,"end":32000}]},"role":"*"}],"used_resources_full":[],"offered_resources_full":[]}') - slave = mesosslave.MesosSlave(mesos_master_response) + slave = mesosslave.MesosSlave(mesos_master_response_empty) assert slave.is_available() - mesos_master_response = json.loads('{"id":"40237088-f509-46a4-a5f1-c8f88ca8e03f-S0","hostname":"mesos-slave","port":5051,"attributes":{"foo":123.0,"bar":"wow"},"pid":"slave(1)@172.24.0.5:5051","registered_time":1518339392.10703,"resources":{"disk":69716.0,"mem":999.0,"gpus":0.0,"cpus":2.0,"ports":"[31000-32000]"},"used_resources":{"disk":0.0,"mem":0.0,"gpus":0.0,"cpus":2.0},"offered_resources":{"disk":0.0,"mem":0.0,"gpus":0.0,"cpus":0.0},"reserved_resources":{},"unreserved_resources":{"disk":69716.0,"mem":999.0,"gpus":0.0,"cpus":2.0,"ports":"[31000-32000]"},"active":true,"version":"1.4.0","capabilities":["MULTI_ROLE","HIERARCHICAL_ROLE","RESERVATION_REFINEMENT"],"reserved_resources_full":{},"unreserved_resources_full":[{"name":"cpus","type":"SCALAR","scalar":{"value":2.0},"role":"*"},{"name":"mem","type":"SCALAR","scalar":{"value":999.0},"role":"*"},{"name":"disk","type":"SCALAR","scalar":{"value":69716.0},"role":"*"},{"name":"ports","type":"RANGES","ranges":{"range":[{"begin":31000,"end":32000}]},"role":"*"}],"used_resources_full":[],"offered_resources_full":[]}') + slave = mesosslave.MesosSlave(mesos_master_response_used) + assert slave.is_available() - slave = mesosslave.MesosSlave(mesos_master_response) + slave = mesosslave.MesosSlave(mesos_master_response_full) assert not slave.is_available() + +def test_is_occupied(monkeypatch): + + slave = mesosslave.MesosSlave(mesos_master_response_empty) + assert not slave.is_occupied() + + slave = mesosslave.MesosSlave(mesos_master_response_used) + assert not slave.is_occupied() + + slave = mesosslave.MesosSlave(mesos_master_response_full) + assert slave.is_occupied() + diff --git a/ucrspawner/mesosslave.py b/ucrspawner/mesosslave.py index e5e8518..d8f30c1 100644 --- a/ucrspawner/mesosslave.py +++ b/ucrspawner/mesosslave.py @@ -20,12 +20,24 @@ def __init__(self, params): self.used_disk = params['used_resources']['disk'] self.used_gpus = int(params['used_resources']['gpus']) + def is_empty(self): + return self.used_cpus == 0 and \ + self.used_mem == 0 and \ + self.used_disk == 0 and \ + self.used_gpus == 0 + def is_available(self): return self.used_cpus < self.cpus and \ self.used_mem < self.mem and \ self.used_disk < self.disk and \ (self.gpus == 0 or self.used_gpus < self.gpus) + def is_occupied(self): + return self.used_cpus >= self.cpus or \ + self.used_mem >= self.mem or \ + self.used_disk >= self.disk or \ + (self.gpus != 0 and self.used_gpus >= self.gpus) + # Match Mesos slaves with Marathon constraints # https://github.com/mesosphere/marathon/blob/v1.5.1/src/main/scala/mesosphere/mesos/Constraints.scala#L34 def match(self, constraint):