Commit fdfb3a1f authored by Daniele Venzano's avatar Daniele Venzano

Implement constraints

parent 49209ec7
......@@ -47,7 +47,7 @@ confidence=
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
disable=line-too-long,logging-format-interpolation,too-few-public-methods,too-many-instance-attributes,fixme,too-many-branches,file-ignored,global-statement,redefined-variable-type,no-self-use
disable=line-too-long,logging-format-interpolation,too-few-public-methods,too-many-instance-attributes,fixme,too-many-branches,file-ignored,global-statement,redefined-variable-type,no-self-use,too-many-statements
[REPORTS]
......
......@@ -142,6 +142,10 @@ def _service_check(data):
if not hasattr(data['networks'], '__iter__'):
raise InvalidApplicationDescription(msg='networks should be an iterable')
if 'constraints' in data:
if not hasattr(data['constraints'], '__iter__'):
raise InvalidApplicationDescription(msg='networks should be an iterable')
def _port_check(data):
required_keys = ['name', 'protocol', 'port_number', 'is_main_endpoint']
......
......@@ -16,7 +16,7 @@
"""Exceptions that can be raised throughout the Zoe codebase."""
class ZoeException(Exception):
class ZoeLibException(Exception):
"""
A generic exception.
"""
......
......@@ -18,7 +18,7 @@
from argparse import Namespace
import time
import logging
from typing import Iterable, Callable, Dict, Any
from typing import Iterable, Callable, Dict, Any, Union
import humanfriendly
......@@ -32,7 +32,7 @@ import docker.errors
import docker.utils
from zoe_master.stats import SwarmStats, SwarmNodeStats
from zoe_lib.exceptions import ZoeException
from zoe_lib.exceptions import ZoeLibException
log = logging.getLogger(__name__)
......@@ -51,14 +51,18 @@ class DockerContainerOptions:
self.restart = True
self.labels = []
self.gelf_log_address = ''
self.constraints = []
def add_env_variable(self, name: str, value: str) -> None:
"""Adds an environment variable to the container definition."""
if value is not None:
self.env[name] = value
def add_constraint(self, constraint):
"""Add a placement constraint (use docker syntax)."""
self.constraints.append(constraint)
def add_env_variable(self, name: str, value: Union[str, None]) -> None:
"""Add an environment variable to the container definition."""
self.env[name] = value
@property
def environment(self) -> Dict[str, str]:
def environment(self) -> Dict[str, Union[str, None]]:
"""Access the environment variables."""
return self.env
......@@ -126,7 +130,7 @@ class SwarmClient:
elif 'http://' or 'https://' in url:
manager = url
else:
raise ZoeException('Unsupported URL scheme for Swarm')
raise ZoeLibException('Unsupported URL scheme for Swarm')
log.debug('Connecting to Swarm at {}'.format(manager))
self.cli = docker.Client(base_url=manager)
......@@ -189,6 +193,9 @@ class SwarmClient:
for port in options.ports:
port_bindings[port] = None
for constraint in options.constraints:
options.add_env_variable(constraint, None)
if options.gelf_log_address != '':
log_config = docker.utils.LogConfig(type="gelf", config={'gelf-address': options.gelf_log_address, 'labels': ",".join(options.labels)})
else:
......@@ -217,7 +224,7 @@ class SwarmClient:
except Exception as e:
if cont is not None:
self.cli.remove_container(container=cont.get('Id'), force=True)
raise ZoeException(str(e))
raise ZoeLibException(str(e))
info = self.inspect_container(cont.get('Id'))
return info
......@@ -227,7 +234,7 @@ class SwarmClient:
try:
docker_info = self.cli.inspect_container(container=docker_id)
except Exception as e:
raise ZoeException(str(e))
raise ZoeLibException(str(e))
info = {
"docker_id": docker_id,
......
......@@ -21,6 +21,7 @@ from zoe_master.workspace.filesystem import ZoeFSWorkspace
from zoe_master.exceptions import ZoeStartExecutionRetryException, ZoeStartExecutionFatalException, ZoeException
from zoe_lib.config import get_conf
from zoe_lib.exceptions import ZoeLibException
from zoe_lib.sql_manager import Execution, Service
from zoe_lib.swarm_client import DockerContainerOptions, SwarmClient
......@@ -89,6 +90,10 @@ def _spawn_service(execution: Execution, service: Service, env_subst_dict: dict)
for path, mount_point, readonly in service.description['volumes']:
copts.add_volume_bind(path, mount_point, readonly)
if 'constraints' in service.description:
for constraint in service.description['constraints']:
copts.add_constraint(constraint)
fswk = ZoeFSWorkspace()
if fswk.can_be_attached():
copts.add_volume_bind(fswk.get_path(execution.user_id), fswk.get_mountpoint(), False)
......@@ -106,6 +111,8 @@ def _spawn_service(execution: Execution, service: Service, env_subst_dict: dict)
cont_info = swarm.spawn_container(service.description['docker_image'], copts)
except ZoeException as e:
raise ZoeStartExecutionRetryException(str(e))
except ZoeLibException as e:
raise ZoeStartExecutionRetryException(str(e))
service.set_active(cont_info["docker_id"])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment