Skip to content

Commit 3709c70

Browse files
committed
Merge branch 'joshpurvis-jp-cpushares'
2 parents abd4611 + 0e4314a commit 3709c70

File tree

5 files changed

+111
-4
lines changed

5 files changed

+111
-4
lines changed

docker/utils/utils.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,8 @@ def create_host_config(binds=None, port_bindings=None, lxc_conf=None,
620620
device_write_bps=None, device_read_iops=None,
621621
device_write_iops=None, oom_kill_disable=False,
622622
shm_size=None, sysctls=None, version=None, tmpfs=None,
623-
oom_score_adj=None, dns_opt=None):
623+
oom_score_adj=None, dns_opt=None, cpu_shares=None,
624+
cpuset_cpus=None):
624625

625626
host_config = {}
626627

@@ -809,6 +810,21 @@ def create_host_config(binds=None, port_bindings=None, lxc_conf=None,
809810

810811
host_config['CpuPeriod'] = cpu_period
811812

813+
if cpu_shares:
814+
if version_lt(version, '1.18'):
815+
raise host_config_version_error('cpu_shares', '1.18')
816+
817+
if not isinstance(cpu_shares, int):
818+
raise host_config_type_error('cpu_shares', cpu_shares, 'int')
819+
820+
host_config['CpuShares'] = cpu_shares
821+
822+
if cpuset_cpus:
823+
if version_lt(version, '1.18'):
824+
raise host_config_version_error('cpuset_cpus', '1.18')
825+
826+
host_config['CpuSetCpus'] = cpuset_cpus
827+
812828
if blkio_weight:
813829
if not isinstance(blkio_weight, int):
814830
raise host_config_type_error('blkio_weight', blkio_weight, 'int')
@@ -981,6 +997,14 @@ def create_container_config(
981997
'labels were only introduced in API version 1.18'
982998
)
983999

1000+
if cpuset is not None or cpu_shares is not None:
1001+
if version_gte(version, '1.18'):
1002+
warnings.warn(
1003+
'The cpuset_cpus and cpu_shares options have been moved to '
1004+
'host_config in API version 1.18, and will be removed',
1005+
DeprecationWarning
1006+
)
1007+
9841008
if stop_signal is not None and compare_version('1.21', version) < 0:
9851009
raise errors.InvalidVersion(
9861010
'stop_signal was only introduced in API version 1.21'
@@ -1010,6 +1034,7 @@ def create_container_config(
10101034

10111035
if mem_limit is not None:
10121036
mem_limit = parse_bytes(mem_limit)
1037+
10131038
if memswap_limit is not None:
10141039
memswap_limit = parse_bytes(memswap_limit)
10151040

docs/api.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,6 @@ from. Optionally a single string joining container id's with commas
246246
* network_disabled (bool): Disable networking
247247
* name (str): A name for the container
248248
* entrypoint (str or list): An entrypoint
249-
* cpu_shares (int): CPU shares (relative weight)
250249
* working_dir (str): Path to the working directory
251250
* domainname (str or list): Set custom DNS search domains
252251
* memswap_limit (int):

docs/hostconfig.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ for example:
109109
* cpu_group (int): The length of a CPU period in microseconds.
110110
* cpu_period (int): Microseconds of CPU time that the container can get in a
111111
CPU period.
112+
* cpu_shares (int): CPU shares (relative weight)
113+
* cpuset_cpus (str): CPUs in which to allow execution (0-3, 0,1)
112114
* blkio_weight: Block IO weight (relative weight), accepts a weight value between 10 and 1000.
113115
* blkio_weight_device: Block IO weight (relative device weight) in the form of:
114116
`[{"Path": "device_path", "Weight": weight}]`

tests/integration/container_test.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,11 +1096,38 @@ def test_update_container(self):
10961096
container = self.client.create_container(
10971097
BUSYBOX, 'top', host_config=self.client.create_host_config(
10981098
mem_limit=old_mem_limit
1099-
), cpu_shares=102
1099+
)
11001100
)
11011101
self.tmp_containers.append(container)
11021102
self.client.start(container)
11031103
self.client.update_container(container, mem_limit=new_mem_limit)
11041104
inspect_data = self.client.inspect_container(container)
11051105
self.assertEqual(inspect_data['HostConfig']['Memory'], new_mem_limit)
1106-
self.assertEqual(inspect_data['HostConfig']['CpuShares'], 102)
1106+
1107+
1108+
class ContainerCPUTest(helpers.BaseTestCase):
1109+
@requires_api_version('1.18')
1110+
def test_container_cpu_shares(self):
1111+
cpu_shares = 512
1112+
container = self.client.create_container(
1113+
BUSYBOX, 'ls', host_config=self.client.create_host_config(
1114+
cpu_shares=cpu_shares
1115+
)
1116+
)
1117+
self.tmp_containers.append(container)
1118+
self.client.start(container)
1119+
inspect_data = self.client.inspect_container(container)
1120+
self.assertEqual(inspect_data['HostConfig']['CpuShares'], 512)
1121+
1122+
@requires_api_version('1.18')
1123+
def test_container_cpuset(self):
1124+
cpuset_cpus = "0,1"
1125+
container = self.client.create_container(
1126+
BUSYBOX, 'ls', host_config=self.client.create_host_config(
1127+
cpuset_cpus=cpuset_cpus
1128+
)
1129+
)
1130+
self.tmp_containers.append(container)
1131+
self.client.start(container)
1132+
inspect_data = self.client.inspect_container(container)
1133+
self.assertEqual(inspect_data['HostConfig']['CpusetCpus'], cpuset_cpus)

tests/unit/container_test.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,33 @@ def test_create_container_with_cpu_shares(self):
286286
self.assertEqual(args[1]['headers'],
287287
{'Content-Type': 'application/json'})
288288

289+
@requires_api_version('1.18')
290+
def test_create_container_with_host_config_cpu_shares(self):
291+
self.client.create_container(
292+
'busybox', 'ls', host_config=self.client.create_host_config(
293+
cpu_shares=512
294+
)
295+
)
296+
297+
args = fake_request.call_args
298+
self.assertEqual(args[0][1],
299+
url_prefix + 'containers/create')
300+
301+
self.assertEqual(json.loads(args[1]['data']),
302+
json.loads('''
303+
{"Tty": false, "Image": "busybox",
304+
"Cmd": ["ls"], "AttachStdin": false,
305+
"AttachStderr": true,
306+
"AttachStdout": true, "OpenStdin": false,
307+
"StdinOnce": false,
308+
"NetworkDisabled": false,
309+
"HostConfig": {
310+
"CpuShares": 512,
311+
"NetworkMode": "default"
312+
}}'''))
313+
self.assertEqual(args[1]['headers'],
314+
{'Content-Type': 'application/json'})
315+
289316
def test_create_container_with_cpuset(self):
290317
self.client.create_container('busybox', 'ls',
291318
cpuset='0,1')
@@ -306,6 +333,33 @@ def test_create_container_with_cpuset(self):
306333
self.assertEqual(args[1]['headers'],
307334
{'Content-Type': 'application/json'})
308335

336+
@requires_api_version('1.18')
337+
def test_create_container_with_host_config_cpuset(self):
338+
self.client.create_container(
339+
'busybox', 'ls', host_config=self.client.create_host_config(
340+
cpuset_cpus='0,1'
341+
)
342+
)
343+
344+
args = fake_request.call_args
345+
self.assertEqual(args[0][1],
346+
url_prefix + 'containers/create')
347+
348+
self.assertEqual(json.loads(args[1]['data']),
349+
json.loads('''
350+
{"Tty": false, "Image": "busybox",
351+
"Cmd": ["ls"], "AttachStdin": false,
352+
"AttachStderr": true,
353+
"AttachStdout": true, "OpenStdin": false,
354+
"StdinOnce": false,
355+
"NetworkDisabled": false,
356+
"HostConfig": {
357+
"CpuSetCpus": "0,1",
358+
"NetworkMode": "default"
359+
}}'''))
360+
self.assertEqual(args[1]['headers'],
361+
{'Content-Type': 'application/json'})
362+
309363
def test_create_container_with_cgroup_parent(self):
310364
self.client.create_container(
311365
'busybox', 'ls', host_config=self.client.create_host_config(

0 commit comments

Comments
 (0)