Skip to content

Commit b4b0d10

Browse files
authored
Merge pull request #54 from DistributedTaskScheduling/implementation-job
Implementation of Job class
2 parents cbd50d6 + 6a39243 commit b4b0d10

File tree

11 files changed

+495
-37
lines changed

11 files changed

+495
-37
lines changed

src/ja/common/docker_context.py

Lines changed: 118 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
and hardware constraints.
55
"""
66
from abc import ABC, abstractmethod
7-
from typing import List, Dict
7+
from typing import List, Dict, cast
88
from ja.common.message.base import Serializable
99

1010

11-
class MountPoint:
11+
class MountPoint(Serializable):
1212
"""!
1313
A mount point consists of:
1414
1. A directory to be mounted(@source_path).
@@ -21,18 +21,38 @@ def __init__(self, source_path: str, mount_path: str):
2121
@param source_path The host directory to be mounted.
2222
@param mount_path The target path in the container to mount at.
2323
"""
24+
self._source_path = source_path
25+
self._mount_path = mount_path
26+
27+
def __eq__(self, other: object) -> bool:
28+
if isinstance(other, MountPoint):
29+
return self.source_path == other.source_path and self.mount_path == other.mount_path
30+
else:
31+
return False
2432

2533
@property
2634
def source_path(self) -> str:
2735
"""!
2836
@return The directory to be mounted.
2937
"""
38+
return self._source_path
3039

3140
@property
3241
def mount_path(self) -> str:
3342
"""!
3443
@return The path where the directory should be mounted.
3544
"""
45+
return self._mount_path
46+
47+
def to_dict(self) -> Dict[str, object]:
48+
return {"source_path": self.source_path, "mount_path": self.mount_path}
49+
50+
@classmethod
51+
def from_dict(cls, property_dict: Dict[str, object]) -> "MountPoint":
52+
source_path = cls._get_str_from_dict(property_dict=property_dict, key="source_path")
53+
mount_path = cls._get_str_from_dict(property_dict=property_dict, key="mount_path")
54+
cls._assert_all_properties_used(property_dict)
55+
return MountPoint(source_path=source_path, mount_path=mount_path)
3656

3757

3858
class IDockerContext(Serializable, ABC):
@@ -41,19 +61,83 @@ class IDockerContext(Serializable, ABC):
4161
run a job in.
4262
"""
4363

64+
def __eq__(self, other: object) -> bool:
65+
if isinstance(other, IDockerContext):
66+
return self.dockerfile_source == other.dockerfile_source and self.mount_points == other.mount_points
67+
else:
68+
return False
69+
70+
@property
4471
@abstractmethod
45-
def get_dockerfile_source(self) -> str:
72+
def dockerfile_source(self) -> str:
4673
"""!
4774
@return The string contents of a Dockerfile which can be used to build
4875
the docker image.
4976
"""
5077

78+
@property
5179
@abstractmethod
52-
def get_mount_points(self) -> List[MountPoint]:
80+
def mount_points(self) -> List[MountPoint]:
5381
"""!
5482
@return A list of all mount points for the job.
5583
"""
5684

85+
@classmethod
86+
@abstractmethod
87+
def from_dict(cls, property_dict: Dict[str, object]) -> "IDockerContext":
88+
pass
89+
90+
91+
class DockerContext(IDockerContext):
92+
"""
93+
An implementation of the IDockerContext interface
94+
"""
95+
def __init__(self, dockerfile_source: str, mount_points: List[MountPoint]):
96+
"""
97+
@param dockerfile_source: The string contents of a Dockerfile which can be used to build the docker image.
98+
@param mount_points: A list of all mount points for the job.
99+
"""
100+
self._dockerfile_source = dockerfile_source
101+
self._mount_points = mount_points
102+
103+
@property
104+
def dockerfile_source(self) -> str:
105+
return self._dockerfile_source
106+
107+
@property
108+
def mount_points(self) -> List[MountPoint]:
109+
return self._mount_points
110+
111+
def to_dict(self) -> Dict[str, object]:
112+
return_dict: Dict[str, object] = dict()
113+
return_dict["dockerfile_source"] = self.dockerfile_source
114+
return_dict["mount_points"] = [_mount_point.to_dict() for _mount_point in self.mount_points]
115+
return return_dict
116+
117+
@classmethod
118+
def from_dict(cls, property_dict: Dict[str, object]) -> IDockerContext:
119+
dockerfile_source = cls._get_str_from_dict(property_dict=property_dict, key="dockerfile_source")
120+
121+
prop: object = cls._get_from_dict(property_dict=property_dict, key="mount_points")
122+
if not isinstance(prop, list):
123+
cls._raise_error_wrong_type(
124+
key="mount_points", expected_type="List[MountPoint]",
125+
actual_type=prop.__class__.__name__
126+
)
127+
object_list = cast(List[object], prop)
128+
mount_point_list: List[MountPoint] = []
129+
for _object in object_list:
130+
if not isinstance(_object, dict):
131+
cls._raise_error_wrong_type(
132+
key="mount_points", expected_type="List[MountPoint]",
133+
actual_type="List[object]"
134+
)
135+
mount_point_list.append(MountPoint.from_dict(
136+
cast(Dict[str, object], _object)
137+
))
138+
cls._assert_all_properties_used(property_dict)
139+
return DockerContext(dockerfile_source=dockerfile_source, mount_points=mount_point_list)
140+
57141

58142
class DockerConstraints(Serializable):
59143
"""
@@ -62,9 +146,21 @@ class DockerConstraints(Serializable):
62146
def __init__(self, cpu_threads: int = -1, memory: int = 1):
63147
"""!
64148
Create a new set of Docker constraints.
65-
@param cpu_threads Initial value of @cpu_threads.
66-
@param memory The value of @memory.
149+
@param cpu_threads Initial value of @cpu_threads. -1 if unknown. Must be > 0 if set to exact number.
150+
@param memory The value of @memory, must be > 0.
67151
"""
152+
self._cpu_threads = -1
153+
if cpu_threads != -1:
154+
self.cpu_threads = cpu_threads
155+
if memory < 1:
156+
raise ValueError("Cannot set memory to %s because this value is < 1." % memory)
157+
self._memory = memory
158+
159+
def __eq__(self, other: object) -> bool:
160+
if isinstance(other, DockerConstraints):
161+
return self.cpu_threads == other.cpu_threads and self.memory == other.memory
162+
else:
163+
return False
68164

69165
@property
70166
def cpu_threads(self) -> int:
@@ -73,6 +169,7 @@ def cpu_threads(self) -> int:
73169
-1 means that the amount of threads is not set, in which case the
74170
number of threads will be determined when scheduling the job.
75171
"""
172+
return self._cpu_threads
76173

77174
@cpu_threads.setter
78175
def cpu_threads(self, count_threads: int) -> None:
@@ -81,16 +178,29 @@ def cpu_threads(self, count_threads: int) -> None:
81178
If the number of cpu threads is already set(i.e it is not equal to -1),
82179
this will raise a RuntimeError.
83180
"""
181+
if self._cpu_threads != -1:
182+
raise RuntimeError("cpu_threads can only be set once.")
183+
elif count_threads < 1:
184+
raise ValueError("Cannot set cpu_threads to %s because this value is < 1." % count_threads)
185+
else:
186+
self._cpu_threads = count_threads
84187

85188
@property
86189
def memory(self) -> int:
87190
"""!
88191
@return The maximum amount of RAM in MB to allocate for this container.
89192
"""
193+
return self._memory
90194

91195
def to_dict(self) -> Dict[str, object]:
92-
pass
196+
return_dict: Dict[str, object] = dict()
197+
return_dict["cpu_threads"] = self.cpu_threads
198+
return_dict["memory"] = self.memory
199+
return return_dict
93200

94201
@classmethod
95202
def from_dict(cls, property_dict: Dict[str, object]) -> "DockerConstraints":
96-
pass
203+
cpu_threads = cls._get_int_from_dict(property_dict=property_dict, key="cpu_threads")
204+
memory = cls._get_int_from_dict(property_dict=property_dict, key="memory")
205+
cls._assert_all_properties_used(property_dict)
206+
return DockerConstraints(cpu_threads=cpu_threads, memory=memory)

0 commit comments

Comments
 (0)