Commit b41c6b07 authored by Daniele Venzano's avatar Daniele Venzano Committed by GitHub

Merge pull request #82 from DistributedSystemsGroup/eur/volumes-fix

Fix volume description and update docs
parents 9c4cda74 8e1c9ddf
......@@ -82,13 +82,13 @@ A number of special values can be used, these will be substituted by Zoe when th
volumes
^^^^^^^
array
object
A list of additional volumes to be mounted in this service container. Each volume is described by an array with three elements:
A list of additional volumes to be mounted in this service container. Each volume is described by an object with three elements:
* host path: the path on the host to mounted
* container path: the path inside the container where host path should be mounted
* read only: a boolean, if true the mountpoint will be read only
* name: the name for this volume. In the container the volume will be mounted as ``/mnt/<name>``
* path: the path on the host (usually on a shared filasystem) that should be mounted in this service container
* read_only: a boolean, if true the volume will be read only
Zoe will always mount the user workspace directory in ``$ZOE_WORKSPACE``.
......
......@@ -4,7 +4,13 @@
"services": [
{
"image": "nginx:alpine",
"volumes": [],
"volumes": [
{
"path": "/tmp",
"name": "test",
"read_only": true
}
],
"environment": [],
"essential_count": 1,
"monitor": true,
......
......@@ -18,5 +18,5 @@
from zoe_lib.state.base import Base
from zoe_lib.state.execution import Execution
from zoe_lib.state.sql_manager import SQLManager
from zoe_lib.state.service import Service, VolumeDescription
from zoe_lib.state.service import Service, VolumeDescription, VolumeDescriptionHostPath
from zoe_lib.state.port import Port
......@@ -63,11 +63,17 @@ class ResourceReservation:
class VolumeDescription:
"""A generic description for container volumes."""
def __init__(self, data):
self.type = "host_directory"
self.path = data[0]
self.mount_point = data[1]
self.readonly = data[2]
def __init__(self, vtype: str):
self.type = vtype
class VolumeDescriptionHostPath(VolumeDescription):
"""Host-based volumes."""
def __init__(self, name: str, path: str, readonly: bool):
super().__init__("host_directory")
self.path = path
self.mount_point = '/mnt/' + name
self.readonly = readonly
class Service:
......@@ -113,7 +119,7 @@ class Service:
self.environment = self.description['environment']
self.command = self.description['command']
self.resource_reservation = ResourceReservation(self.description['resources'])
self.volumes = [VolumeDescription(v) for v in self.description['volumes']]
self.volumes = [VolumeDescriptionHostPath(v['path'], v['name'], v['read_only']) for v in self.description['volumes']]
self.replicas = self.description['replicas']
def serialize(self):
......
......@@ -15,10 +15,10 @@
"""The high-level interface that Zoe uses to talk to the configured container backend."""
from typing import Dict
from typing import Dict, List
from zoe_lib.config import get_conf
from zoe_lib.state import Service, Execution
from zoe_lib.state import Service, Execution, VolumeDescription
from zoe_master.exceptions import ZoeStartExecutionFatalException
from zoe_master.workspace.filesystem import ZoeFSWorkspace
......@@ -43,14 +43,15 @@ def gen_environment(execution: Execution, service: Service, env_subst_dict: Dict
env_list.append(('SERVICE_NAME', service.name))
env_list.append(('PROXY_PATH', get_conf().proxy_path))
fswk = ZoeFSWorkspace()
env_list.append(('ZOE_WORKSPACE', fswk.get_mountpoint()))
wk_vol = ZoeFSWorkspace().get(execution.user_id)
env_list.append(('ZOE_WORKSPACE', wk_vol.mount_point))
return env_list
def gen_volumes(service_: Service, execution: Execution):
def gen_volumes(service: Service, execution: Execution) -> List[VolumeDescription]:
"""Return the list of default volumes to be added to all containers."""
vol_list = []
vol_list = service.volumes
fswk = ZoeFSWorkspace()
wk_vol = fswk.get(execution.user_id)
......
......@@ -26,7 +26,7 @@ import pykube
from zoe_master.stats import ClusterStats, NodeStats
from zoe_master.backends.service_instance import ServiceInstance
from zoe_lib.version import ZOE_VERSION
from zoe_lib.state import VolumeDescription
from zoe_lib.state import VolumeDescription, VolumeDescriptionHostPath
from zoe_lib.config import get_conf
log = logging.getLogger(__name__)
......@@ -191,22 +191,29 @@ class KubernetesReplicationControllerConf:
count = 0
for vol in volumes:
if vol.type != "host_directory":
log.error('Swarm backend does not support volume type {}'.format(vol.type))
aux['spec']['containers'][0]['volumeMounts'][count]['mountPath'] = vol.mount_point
aux['spec']['containers'][0]['volumeMounts'][count]['name'] = name + "-" + str(count)
count += 1
if vol.type == "host_directory":
assert isinstance(vol, VolumeDescriptionHostPath)
aux['spec']['containers'][0]['volumeMounts'][count]['mountPath'] = vol.mount_point
aux['spec']['containers'][0]['volumeMounts'][count]['name'] = name + "-" + str(count)
count += 1
else:
log.error('Kubernetes backend does not support volume type {}'.format(vol.type))
continue
aux['spec']['volumes'] = [{} for _ in range(len(volumes))]
count = 0
for vol in volumes:
aux['spec']['volumes'][count]['name'] = name + "-" + str(count)
aux['spec']['volumes'][count]['hostPath'] = {
'path': vol.path
}
count += 1
if vol.type == "host_directory":
assert isinstance(vol, VolumeDescriptionHostPath)
aux['spec']['volumes'][count]['name'] = name + "-" + str(count)
aux['spec']['volumes'][count]['hostPath'] = {
'path': vol.path
}
count += 1
else:
log.error('Kubernetes backend does not support volume type {}'.format(vol.type))
continue
def get_json(self):
"""Get json file"""
......
......@@ -56,7 +56,7 @@ class ServiceInstance:
self.labels = zoe_master.backends.common.gen_labels(service, execution)
self.environment = service.environment + zoe_master.backends.common.gen_environment(execution, service, env_subst_dict)
self.volumes = service.volumes + zoe_master.backends.common.gen_volumes(service, execution)
self.volumes = zoe_master.backends.common.gen_volumes(service, execution)
self.command = service.command
......
......@@ -40,7 +40,7 @@ import docker.models.containers
import requests.exceptions
from zoe_lib.config import get_conf
from zoe_lib.state import Service
from zoe_lib.state import Service, VolumeDescriptionHostPath
from zoe_master.stats import ClusterStats, NodeStats
from zoe_master.backends.service_instance import ServiceInstance
from zoe_master.exceptions import ZoeException, ZoeNotEnoughResourcesException
......@@ -169,9 +169,11 @@ class SwarmClient:
volumes = {}
for volume in service_instance.volumes:
if volume.type != "host_directory":
if volume.type == "host_directory":
assert isinstance(volume, VolumeDescriptionHostPath)
volumes[volume.path] = {'bind': volume.mount_point, 'mode': ("ro" if volume.readonly else "rw")}
else:
log.error('Swarm backend does not support volume type {}'.format(volume.type))
volumes[volume.path] = {'bind': volume.mount_point, 'mode': ("ro" if volume.readonly else "rw")}
if service_instance.memory_limit is not None:
mem_limit = service_instance.memory_limit.max
......
......@@ -19,7 +19,7 @@ import logging
import os.path
import zoe_lib.config as config
from zoe_lib.state import VolumeDescription
from zoe_lib.state import VolumeDescriptionHostPath
import zoe_master.workspace.base
log = logging.getLogger(__name__)
......@@ -46,8 +46,8 @@ class ZoeFSWorkspace(zoe_master.workspace.base.ZoeWorkspaceBase):
@classmethod
def get_mountpoint(cls):
"""Get the volume mount point."""
return '/workspace'
return 'workspace'
def get(self, user_id):
"""Return a VolumeDescription for the user workspace."""
return VolumeDescription((self.get_path(user_id), self.get_mountpoint(), False))
return VolumeDescriptionHostPath(path=self.get_path(user_id), name=self.get_mountpoint(), readonly=False)
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