66import time
77import zipfile
88from pathlib import Path
9+ from pprint import pformat
910from typing import Dict , Optional
1011
1112import aiopg
1213import attr
1314from aiodocker import Docker
1415from aiodocker .containers import DockerContainer
1516from aiodocker .exceptions import DockerContainerError , DockerError
17+ from models_library .service_settings import ServiceSettings
1618from packaging import version
19+ from pydantic import BaseModel
1720from servicelib .logging_utils import log_decorator
1821from servicelib .utils import fire_and_forget_task , logged_gather
1922from simcore_sdk import node_data , node_ports_v2
@@ -70,6 +73,13 @@ def log_error(_, path, excinfo):
7073 shutil .rmtree (str (folder ), onerror = log_error )
7174
7275
76+ class ServiceResources (BaseModel ):
77+ memory_reservation : int = 0
78+ memory_limit : int = config .SERVICES_MAX_MEMORY_BYTES
79+ nano_cpus_reservation : int = 0
80+ nano_cpus_limit : int = config .SERVICES_MAX_NANO_CPUS
81+
82+
7383@attr .s (auto_attribs = True )
7484class Executor :
7585 db_engine : aiopg .sa .Engine = None
@@ -80,6 +90,7 @@ class Executor:
8090 stack_name : str = config .SWARM_STACK_NAME
8191 shared_folders : TaskSharedVolumes = None
8292 integration_version : version .Version = version .parse ("0.0.0" )
93+ service_settings : ServiceSettings = []
8394
8495 @log_decorator (logger = log )
8596 async def run (self ):
@@ -187,6 +198,10 @@ async def _process_task_inputs(self) -> Dict:
187198 for port in (await PORTS .inputs ).values ()
188199 ]
189200 )
201+ await self ._post_messages (
202+ LogType .LOG ,
203+ "[sidecar]Downloaded inputs." ,
204+ )
190205 return input_ports
191206
192207 @log_decorator (logger = log )
@@ -225,6 +240,17 @@ async def _pull_image(self):
225240 image_cfg ["Config" ]["Labels" ]["io.simcore.integration-version" ]
226241 )["integration-version" ]
227242 )
243+ # get service settings
244+ self .service_settings = ServiceSettings .parse_raw (
245+ image_cfg ["Config" ]["Labels" ].get ("simcore.service.settings" , "[]" )
246+ )
247+ log .debug (
248+ "found following service settings: %s" , pformat (self .service_settings )
249+ )
250+ await self ._post_messages (
251+ LogType .LOG ,
252+ f"[sidecar]Pulled { self .task .image ['name' ]} :{ self .task .image ['tag' ]} " ,
253+ )
228254
229255 @log_decorator (logger = log )
230256 async def _create_container_config (self , docker_image : str ) -> Dict :
@@ -247,6 +273,32 @@ async def _create_container_config(self, docker_image: str) -> Dict:
247273 )
248274 host_log_path = await get_volume_mount_point (config .SIDECAR_DOCKER_VOLUME_LOG )
249275
276+ # get user-defined IT limitations
277+ async def _get_resource_limitations () -> Dict [str , int ]:
278+ resource_limitations = {
279+ "Memory" : config .SERVICES_MAX_MEMORY_BYTES ,
280+ "NanoCPUs" : config .SERVICES_MAX_NANO_CPUS ,
281+ }
282+ for setting in self .service_settings :
283+ if not setting .name == "Resources" :
284+ continue
285+ if not isinstance (setting .value , dict ):
286+ continue
287+
288+ limits = setting .value .get ("Limits" , {})
289+ resource_limitations ["Memory" ] = limits .get (
290+ "MemoryBytes" , config .SERVICES_MAX_MEMORY_BYTES
291+ )
292+ resource_limitations ["NanoCPUs" ] = limits .get (
293+ "NanoCPUs" , config .SERVICES_MAX_NANO_CPUS
294+ )
295+ log .debug (
296+ "Current resource limitations are %s" , pformat (resource_limitations )
297+ )
298+ return resource_limitations
299+
300+ resource_limitations = await _get_resource_limitations ()
301+
250302 docker_container_config = {
251303 "Env" : env_vars ,
252304 "Cmd" : "run" ,
@@ -255,12 +307,12 @@ async def _create_container_config(self, docker_image: str) -> Dict:
255307 "user_id" : str (self .user_id ),
256308 "study_id" : str (self .task .project_id ),
257309 "node_id" : str (self .task .node_id ),
258- "nano_cpus_limit" : str (config . SERVICES_MAX_NANO_CPUS ),
259- "mem_limit" : str (config . SERVICES_MAX_MEMORY_BYTES ),
310+ "nano_cpus_limit" : str (resource_limitations [ "NanoCPUs" ] ),
311+ "mem_limit" : str (resource_limitations [ "Memory" ] ),
260312 },
261313 "HostConfig" : {
262- "Memory" : config . SERVICES_MAX_MEMORY_BYTES ,
263- "NanoCPUs" : config . SERVICES_MAX_NANO_CPUS ,
314+ "Memory" : resource_limitations [ "Memory" ] ,
315+ "NanoCPUs" : resource_limitations [ "NanoCPUs" ] ,
264316 "Init" : True ,
265317 "AutoRemove" : False ,
266318 "Binds" : [
@@ -272,6 +324,7 @@ async def _create_container_config(self, docker_image: str) -> Dict:
272324 ],
273325 },
274326 }
327+
275328 return docker_container_config
276329
277330 @log_decorator (logger = log )
0 commit comments