From 90153a2ca5dbf8cb0d52ce9f152205f3d246e698 Mon Sep 17 00:00:00 2001 From: Daan Oosterveld Date: Tue, 9 Feb 2016 10:19:59 +0100 Subject: [PATCH] Adds ulimit to the docker module The ulimit will be specified as a list and separated by colons. The hard limit is optional, in which case it is equal to the soft limit. The ulimits are compared to the ulimits of the container and added or adjusted accordingly on by a reload. The module ensures that ulimits are available in the capabilities iff ulimits is passes as a parameter. --- cloud/docker/docker.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/cloud/docker/docker.py b/cloud/docker/docker.py index 7184b22ccfa..72aa158e713 100644 --- a/cloud/docker/docker.py +++ b/cloud/docker/docker.py @@ -370,6 +370,14 @@ options: required: false default: 0 version_added: "2.1" + ulimits: + description: + - ulimits, list ulimits with name, soft and optionally + hard limit separated by colons. e.g. nofile:1024:2048 + Requires docker-py >= 1.2.0 and docker >= 1.6.0 + required: false + default: null + version_added: "2.1" author: - "Cove Schneider (@cove)" @@ -378,6 +386,7 @@ author: - "Ash Wilson (@smashwilson)" - "Thomas Steinbach (@ThomasSteinbach)" - "Philippe Jandot (@zfil)" + - "Daan Oosterveld (@dusdanig) requirements: - "python >= 2.6" - "docker-py >= 0.3.0" @@ -660,6 +669,7 @@ class DockerManager(object): 'read_only': ((1, 0, 0), '1.17'), 'labels': ((1, 2, 0), '1.18'), 'stop_timeout': ((0, 5, 0), '1.0'), + 'ulimits': ((1, 2, 0), '1.18'), # Clientside only 'insecure_registry': ((0, 5, 0), '0.0') } @@ -714,6 +724,19 @@ class DockerManager(object): self.env = self.module.params.get('env', None) + self.ulimits = None + if self.module.params.get('ulimits'): + self.ulimits = [] + ulimits = self.module.params.get('ulimits') + for ulimit in ulimits: + parts = ulimit.split(":") + if len(parts) == 2: + self.ulimits.append({'name': parts[0], 'soft': int(parts[1]), 'hard': int(parts[1])}) + elif len(parts) == 3: + self.ulimits.append({'name': parts[0], 'soft': int(parts[1]), 'hard': int(parts[2])}) + else: + self.module.fail_json(msg='ulimits support 2 to 3 arguments') + # Connect to the docker server using any configured host and TLS settings. env_host = os.getenv('DOCKER_HOST') @@ -1165,6 +1188,16 @@ class DockerManager(object): differing.append(container) continue + # ULIMITS + + expected_ulimit_keys = set(map(lambda x: '%s:%s:%s' % (x['name'],x['soft'],x['hard']), self.ulimits or [])) + actual_ulimit_keys = set(map(lambda x: '%s:%s:%s' % (x['Name'],x['Soft'],x['Hard']), (container['HostConfig']['Ulimits'] or []))) + + if actual_ulimit_keys != expected_ulimit_keys: + self.reload_reasons.append('ulimits ({0} => {1})'.format(actual_ulimit_keys, expected_ulimit_keys)) + differing.append(container) + continue + # CPU_SHARES expected_cpu_shares = self.module.params.get('cpu_shares') @@ -1566,6 +1599,9 @@ class DockerManager(object): else: params['host_config']['Memory'] = mem_limit + if self.ulimits is not None: + self.ensure_capability('ulimits') + params['host_config']['ulimits'] = self.ulimits def do_create(count, params): results = [] @@ -1813,6 +1849,7 @@ def main(): labels = dict(default={}, type='dict'), stop_timeout = dict(default=10, type='int'), timeout = dict(required=False, default=DEFAULT_TIMEOUT_SECONDS, type='int'), + ulimits = dict(default=None, type='list'), ), required_together = ( ['tls_client_cert', 'tls_client_key'],