From c07dd53a2aea40ffb4c5080a7b741eb25485d691 Mon Sep 17 00:00:00 2001 From: Dustin Falgout Date: Fri, 30 Oct 2015 20:57:15 -0500 Subject: [PATCH 1/3] Incorporates feedback from and closes #814 Signed-off-by: Dustin Falgout --- docker/utils/utils.py | 34 ++++++++++++++++++++--------- docs/hostconfig.md | 21 ++++++++++-------- tests/integration/container_test.py | 33 ++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 19 deletions(-) diff --git a/docker/utils/utils.py b/docker/utils/utils.py index 39d0eba962..b9424f0f2c 100644 --- a/docker/utils/utils.py +++ b/docker/utils/utils.py @@ -469,16 +469,17 @@ def parse_bytes(s): return s -def create_host_config( - binds=None, port_bindings=None, lxc_conf=None, - publish_all_ports=False, links=None, privileged=False, - dns=None, dns_search=None, volumes_from=None, network_mode=None, - restart_policy=None, cap_add=None, cap_drop=None, devices=None, - extra_hosts=None, read_only=None, pid_mode=None, ipc_mode=None, - security_opt=None, ulimits=None, log_config=None, mem_limit=None, - memswap_limit=None, cgroup_parent=None, group_add=None, cpu_quota=None, - cpu_period=None, version=None -): +def create_host_config(binds=None, port_bindings=None, lxc_conf=None, + publish_all_ports=False, links=None, privileged=False, + dns=None, dns_search=None, volumes_from=None, + network_mode=None, restart_policy=None, cap_add=None, + cap_drop=None, devices=None, extra_hosts=None, + read_only=None, pid_mode=None, ipc_mode=None, + security_opt=None, ulimits=None, log_config=None, + mem_limit=None, memswap_limit=None, mem_swappiness=None, + cgroup_parent=None, group_add=None, cpu_quota=None, + cpu_period=None, version=None): + host_config = {} if not version: @@ -491,6 +492,7 @@ def create_host_config( if mem_limit is not None: if isinstance(mem_limit, six.string_types): mem_limit = parse_bytes(mem_limit) + host_config['Memory'] = mem_limit if memswap_limit is not None: @@ -498,6 +500,18 @@ def create_host_config( memswap_limit = parse_bytes(memswap_limit) host_config['MemorySwap'] = memswap_limit + if mem_swappiness is not None: + if version_lt(version, '1.20'): + raise errors.InvalidVersion( + 'mem_swappiness param not supported for API version < 1.20' + ) + if not isinstance(mem_swappiness, int): + raise TypeError( + 'Invalid type for mem_swappiness param: expected int but' + ' found {0}'.format(type(mem_swappiness)) + ) + host_config['MemorySwappiness'] = mem_swappiness + if pid_mode not in (None, 'host'): raise errors.DockerException( 'Invalid value for pid param: {0}'.format(pid_mode) diff --git a/docs/hostconfig.md b/docs/hostconfig.md index 4c17eb33da..0ae10be5b9 100644 --- a/docs/hostconfig.md +++ b/docs/hostconfig.md @@ -34,10 +34,11 @@ Docker bridge, 'none': no networking for this container, 'container:[name|id]': reuses another container network stack), 'host': use the host network stack inside the container. -`restart_policy` is available since v1.2.0 and sets the RestartPolicy for how a -container should or should not be restarted on exit. By default the policy is -set to no meaning do not restart the container when it exits. The user may -specify the restart policy as a dictionary for example: +`restart_policy` is available since v1.2.0 and sets the container's *RestartPolicy* +which defines the conditions under which a container should be restarted upon exit. +If no *RestartPolicy* is defined, the container will not be restarted when it exits. +The *RestartPolicy* is specified as a dict. For example, if the container +should always be restarted: ```python { "MaximumRetryCount": 0, @@ -45,8 +46,8 @@ specify the restart policy as a dictionary for example: } ``` -For always restarting the container on exit or can specify to restart the -container to restart on failure and can limit number of restarts. For example: +It is possible to restart the container only on failure as well as limit the number +of restarts. For example: ```python { "MaximumRetryCount": 5, @@ -95,10 +96,12 @@ for example: of ulimits to be set in the container. * log_config (`docker.utils.LogConfig` or dict): Logging configuration to container -* mem_limit (str or num): Maximum amount of memory container is allowed to - consume. (e.g. `'1g'`) -* memswap_limit (str or num): Maximum amount of memory + swap a container is +* mem_limit (str or int): Maximum amount of memory container is allowed to + consume. (e.g. `'1G'`) +* memswap_limit (str or int): Maximum amount of memory + swap a container is allowed to consume. +* mem_swappiness (str or int): Tune a container's memory swappiness behavior. + Accepts number between 0 and 100. * group_add (list): List of additional group names and/or IDs that the container process will run as. * devices (list): A list of devices to add to the container specified as dicts diff --git a/tests/integration/container_test.py b/tests/integration/container_test.py index 9606e14b92..af2b93bfe7 100644 --- a/tests/integration/container_test.py +++ b/tests/integration/container_test.py @@ -337,6 +337,39 @@ def test_valid_no_config_specified(self): self.assertEqual(container_log_config['Type'], "json-file") self.assertEqual(container_log_config['Config'], {}) + def test_create_with_memory_constraints_with_str(self): + ctnr = self.client.create_container( + BUSYBOX, 'true', + host_config=self.client.create_host_config( + memswap_limit='1G', + mem_swappiness='40', + mem_limit='700M' + ) + ) + self.assertIn('Id', ctnr) + self.tmp_containers.append(ctnr['Id']) + self.client.start(ctnr) + inspect = self.client.inspect_container(ctnr) + + self.assertIn('HostConfig', inspect) + host_config = inspect['HostConfig'] + for limit in ['Memory', 'MemorySwappiness', 'MemorySwap']: + self.assertIn(limit, host_config) + + def test_create_with_memory_constraints_with_int(self): + ctnr = self.client.create_container( + BUSYBOX, 'true', + host_config=self.client.create_host_config(mem_swappiness=40) + ) + self.assertIn('Id', ctnr) + self.tmp_containers.append(ctnr['Id']) + self.client.start(ctnr) + inspect = self.client.inspect_container(ctnr) + + self.assertIn('HostConfig', inspect) + host_config = inspect['HostConfig'] + self.assertIn('MemorySwappiness', host_config) + class VolumeBindTest(api_test.BaseTestCase): def setUp(self): From 01353c11cad2952ef75945f5425ba87434535daf Mon Sep 17 00:00:00 2001 From: Dustin Falgout Date: Thu, 5 Nov 2015 02:51:46 -0600 Subject: [PATCH 2/3] Dont include mem_swappiness when testing use of str values Signed-off-by: Dustin Falgout --- tests/integration/container_test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/integration/container_test.py b/tests/integration/container_test.py index af2b93bfe7..d77b8469e0 100644 --- a/tests/integration/container_test.py +++ b/tests/integration/container_test.py @@ -342,7 +342,6 @@ def test_create_with_memory_constraints_with_str(self): BUSYBOX, 'true', host_config=self.client.create_host_config( memswap_limit='1G', - mem_swappiness='40', mem_limit='700M' ) ) @@ -353,7 +352,7 @@ def test_create_with_memory_constraints_with_str(self): self.assertIn('HostConfig', inspect) host_config = inspect['HostConfig'] - for limit in ['Memory', 'MemorySwappiness', 'MemorySwap']: + for limit in ['Memory', 'MemorySwap']: self.assertIn(limit, host_config) def test_create_with_memory_constraints_with_int(self): From 64fc383f2c573daab75c85459e87052ef0a31cdd Mon Sep 17 00:00:00 2001 From: Dustin Falgout Date: Mon, 9 Nov 2015 02:39:47 -0600 Subject: [PATCH 3/3] Update hostconfig.md Signed-off-by: Dustin Falgout --- docs/hostconfig.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/hostconfig.md b/docs/hostconfig.md index 0ae10be5b9..40accce3d3 100644 --- a/docs/hostconfig.md +++ b/docs/hostconfig.md @@ -100,7 +100,7 @@ for example: consume. (e.g. `'1G'`) * memswap_limit (str or int): Maximum amount of memory + swap a container is allowed to consume. -* mem_swappiness (str or int): Tune a container's memory swappiness behavior. +* mem_swappiness (int): Tune a container's memory swappiness behavior. Accepts number between 0 and 100. * group_add (list): List of additional group names and/or IDs that the container process will run as.