18 from typing
import List, Optional, Tuple
19 from pathlib
import Path
21 from .
import utils, config_defaults
22 from .base
import BaseConfiguration, CONFIG_DIR
23 from ..utils
import docker
24 from ..node
import NodeMode
25 from ..networking
import networkManager, NetworkRequestError
28 class NodeConfiguration(BaseConfiguration):
31 def getConfigPath(cls) -> Path:
32 return CONFIG_DIR /
"node_config.json"
35 def name(self) -> str:
36 return self.getValue(
"name", str)
39 def name(self, value: str) ->
None:
40 self._raw[
"name"] = value
43 def accessToken(self) -> str:
44 return self.getValue(
"accessToken", str)
47 def accessToken(self, value: str) ->
None:
48 self._raw[
"accessToken"] = value
51 def storagePath(self) -> str:
52 return self.getValue(
"storagePath", str)
55 def storagePath(self, value: Optional[str]) ->
None:
56 self._raw[
"storagePath"] = value
59 def image(self) -> str:
60 return self.getValue(
"image", str)
63 def image(self, value: str) ->
None:
64 self._raw[
"image"] = value
67 def allowGpu(self) -> bool:
68 return self.getValue(
"allowGpu", bool)
71 def allowGpu(self, value: bool) ->
None:
72 self._raw[
"allowGpu"] = value
76 ram = self.getOptValue(
"ram", int)
79 ram = config_defaults.DEFAULT_RAM
84 def ram(self, value: int) ->
None:
85 self._raw[
"ram"] = value
88 def swap(self) -> int:
89 swap = self.getOptValue(
"swap", int)
92 swap = config_defaults.DEFAULT_SWAP_MEMORY
97 def swap(self, value: int) ->
None:
98 self._raw[
"swap"] = value
101 def sharedMemory(self) -> int:
102 sharedMemory = self.getOptValue(
"sharedMemory", int)
104 if sharedMemory
is None:
105 sharedMemory = config_defaults.DEFAULT_SHARED_MEMORY
110 def sharedMemory(self, value: int) ->
None:
111 self._raw[
"sharedMemory"] = value
114 def cpuCount(self) -> int:
115 cpuCount = self.getOptValue(
"cpuCount", int)
118 cpuCount = config_defaults.DEFAULT_CPU_COUNT
123 def cpuCount(self, value: int) ->
None:
124 self._raw[
"cpuCount"] = value
127 def mode(self) -> int:
128 mode = self.getOptValue(
"mode", int)
136 def mode(self, value: int) ->
None:
137 self._raw[
"mode"] = value
141 id = self.getOptValue(
"id", int)
144 id = self.fetchNodeId()
149 def id(self, value: int) ->
None:
150 self._raw[
"id"] = value
153 def allowDocker(self) -> bool:
154 return self.getValue(
"allowDocker", bool)
157 def allowDocker(self, value: bool) ->
None:
158 self._raw[
"allowDocker"] = value
161 def secret(self) -> Optional[str]:
162 return self.getOptValue(
"secret", str)
165 def secret(self, value: Optional[str]) ->
None:
166 self._raw[
"secret"] = value
169 def initScript(self) -> Optional[str]:
170 return self.getOptValue(
"initScript", str)
173 def initScript(self, value: Optional[str]) ->
None:
174 self._raw[
"initScript"] = value
177 def modelId(self) -> Optional[int]:
178 return self.getOptValue(
"modelId", int)
181 def modelId(self, value: Optional[int]) ->
None:
182 self._raw[
"modelId"] = value
185 def nearWalletId(self) -> Optional[str]:
186 return self.getOptValue(
"nearWalletId", str)
189 def nearWalletId(self, value: Optional[str]) ->
None:
190 self._raw[
"nearWalletId"] = value
193 def endpointInvocationPrice(self) -> Optional[float]:
194 return self.getOptValue(
"endpointInvocationPrice", float)
197 def endpointInvocationPrice(self, value: Optional[float]) ->
None:
198 self._raw[
"endpointInvocationPrice"] = value
201 def heartbeatInterval(self) -> int:
202 return self.getValue(
"heartbeatInterval", int, default = config_defaults.HEARTBEAT_INTERVAL)
204 @heartbeatInterval.setter
205 def heartbeatInterval(self, value: int) ->
None:
206 self._raw[
"heartbeatInterval"] = value
208 def _isConfigValid(self) -> Tuple[bool, List[str]]:
211 cpuLimit, ramLimit = docker.getResourceLimits()
212 swapLimit = docker.getDockerSwapLimit()
214 if not isinstance(self._raw.get(
"name"), str):
216 errorMessages.append(
"Invalid configuration. Missing required field \"name\".")
218 if not isinstance(self._raw.get(
"image"), str):
220 errorMessages.append(
"Invalid configuration. Missing required field \"image\".")
222 if not isinstance(self._raw.get(
"accessToken"), str):
224 errorMessages.append(
"Invalid configuration. Missing required field \"accessToken\".")
226 validateRamField = utils.validateRamField(self, ramLimit)
227 if isinstance(validateRamField, tuple):
228 ram, message = validateRamField
229 errorMessages.append(message)
232 validateCpuCount = utils.validateCpuCount(self, cpuLimit)
233 if isinstance(validateCpuCount, tuple):
234 cpuCount, message = validateCpuCount
235 errorMessages.append(message)
236 self.cpuCount = cpuCount
238 validateSwapMemory = utils.validateSwapMemory(self, swapLimit)
239 if isinstance(validateSwapMemory, tuple):
240 swap, message = validateSwapMemory
241 errorMessages.append(message)
244 return isValid, errorMessages
246 def getInitScriptPath(self) -> Optional[Path]:
247 value = self._raw.get(
"initScript")
249 if not isinstance(value, str):
255 path = Path(value).expanduser().absolute()
256 if not path.exists():
261 def fetchNodeId(self) -> int:
263 "name": f
"={self.name}"
266 response = networkManager.get(
"service/directory", params)
267 if response.hasFailed():
268 raise NetworkRequestError(response,
"Failed to fetch node id.")
270 responseJson = response.getJson(dict)
271 data = responseJson.get(
"data")
273 if not isinstance(data, list):
274 raise TypeError(f
"Invalid \"data\" type {type(data)}. Expected: \"list\"")
277 raise ValueError(f
"Node with name \"{self.name}\" not found.")
280 if not isinstance(nodeJson, dict):
281 raise TypeError(f
"Invalid \"nodeJson\" type {type(nodeJson)}. Expected: \"dict\"")
283 id = nodeJson.get(
"id")
284 if not isinstance(id, int):
285 raise TypeError(f
"Invalid \"id\" type {type(id)}. Expected: \"int\"")