Skip to content

Commit 3f7d622

Browse files
committed
Add cpu_count, cpu_percent, cpus parameters to container HostConfig.
Signed-off-by: Alexey Rokhin <[email protected]>
1 parent f127a9f commit 3f7d622

File tree

4 files changed

+95
-1
lines changed

4 files changed

+95
-1
lines changed

docker/models/containers.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,10 +456,13 @@ def run(self, image, command=None, stdout=True, stderr=False,
456456
cap_add (list of str): Add kernel capabilities. For example,
457457
``["SYS_ADMIN", "MKNOD"]``.
458458
cap_drop (list of str): Drop kernel capabilities.
459+
cpu_count (int): CPU count (Windows only).
460+
cpu_percent (int): CPU percent (Windows only).
459461
cpu_period (int): The length of a CPU period in microseconds.
460462
cpu_quota (int): Microseconds of CPU time that the container can
461463
get in a CPU period.
462464
cpu_shares (int): CPU shares (relative weight).
465+
cpus (float): Number of CPUs.
463466
cpuset_cpus (str): CPUs in which to allow execution (``0-3``,
464467
``0,1``).
465468
detach (bool): Run container in the background and return a
@@ -801,9 +804,12 @@ def prune(self, filters=None):
801804
'cap_add',
802805
'cap_drop',
803806
'cgroup_parent',
807+
'cpu_count',
808+
'cpu_percent',
804809
'cpu_period',
805810
'cpu_quota',
806811
'cpu_shares',
812+
'cpus',
807813
'cpuset_cpus',
808814
'device_read_bps',
809815
'device_read_iops',

docker/types/containers.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ def __init__(self, version, binds=None, port_bindings=None,
118118
tmpfs=None, oom_score_adj=None, dns_opt=None, cpu_shares=None,
119119
cpuset_cpus=None, userns_mode=None, pids_limit=None,
120120
isolation=None, auto_remove=False, storage_opt=None,
121-
init=None, init_path=None, volume_driver=None):
121+
init=None, init_path=None, volume_driver=None,
122+
cpu_count=None, cpu_percent=None, cpus=None):
122123

123124
if mem_limit is not None:
124125
self['Memory'] = parse_bytes(mem_limit)
@@ -433,6 +434,30 @@ def __init__(self, version, binds=None, port_bindings=None,
433434
raise host_config_version_error('volume_driver', '1.21')
434435
self['VolumeDriver'] = volume_driver
435436

437+
if cpu_count:
438+
if not isinstance(cpu_count, int):
439+
raise host_config_type_error('cpu_count', cpu_count, 'int')
440+
if version_lt(version, '1.25'):
441+
raise host_config_version_error('cpu_count', '1.25')
442+
443+
self['CpuCount'] = cpu_count
444+
445+
if cpu_percent:
446+
if not isinstance(cpu_percent, int):
447+
raise host_config_type_error('cpu_percent', cpu_percent, 'int')
448+
if version_lt(version, '1.25'):
449+
raise host_config_version_error('cpu_percent', '1.25')
450+
451+
self['CpuPercent'] = cpu_percent
452+
453+
if cpus:
454+
if not isinstance(cpus, (float, int)):
455+
raise host_config_type_error('cpus', cpus, 'float')
456+
if version_lt(version, '1.25'):
457+
raise host_config_version_error('cpus', '1.25')
458+
459+
self['NanoCpus'] = int(1000000000 * cpus)
460+
436461

437462
def host_config_type_error(param, param_value, expected):
438463
error_msg = 'Invalid type for {0} param: expected {1} but found {2}'

tests/unit/api_container_test.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,6 +1152,36 @@ def test_create_container_with_unicode_envvars(self):
11521152
self.assertEqual(args[0][1], url_prefix + 'containers/create')
11531153
self.assertEqual(json.loads(args[1]['data'])['Env'], expected)
11541154

1155+
@requires_api_version('1.25')
1156+
def test_create_container_with_host_config_cpus(self):
1157+
self.client.create_container(
1158+
'busybox', 'ls', host_config=self.client.create_host_config(
1159+
cpu_count=1,
1160+
cpu_percent=20,
1161+
cpus=10
1162+
)
1163+
)
1164+
1165+
args = fake_request.call_args
1166+
self.assertEqual(args[0][1],
1167+
url_prefix + 'containers/create')
1168+
1169+
self.assertEqual(json.loads(args[1]['data']),
1170+
json.loads('''
1171+
{"Tty": false, "Image": "busybox",
1172+
"Cmd": ["ls"], "AttachStdin": false,
1173+
"AttachStderr": true,
1174+
"AttachStdout": true, "OpenStdin": false,
1175+
"StdinOnce": false,
1176+
"NetworkDisabled": false,
1177+
"HostConfig": {
1178+
"CpuCount": 1,
1179+
"CpuPercent": 20,
1180+
"NanoCpus": 10000000000,
1181+
"NetworkMode": "default"
1182+
}}'''))
1183+
self.assertEqual(args[1]['headers'], {'Content-Type': 'application/json'})
1184+
11551185

11561186
class ContainerTest(BaseAPIClientTest):
11571187
def test_list_containers(self):

tests/unit/dockertypes_test.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,39 @@ def test_create_host_config_with_volume_driver(self):
172172

173173
config = create_host_config(version='1.21', volume_driver='local')
174174
assert config.get('VolumeDriver') == 'local'
175+
176+
def test_create_host_config_invalid_cpu_count_types(self):
177+
with pytest.raises(TypeError):
178+
create_host_config(version='1.25', cpu_count='1')
179+
180+
def test_create_host_config_with_cpu_count(self):
181+
config = create_host_config(version='1.25', cpu_count=2)
182+
self.assertEqual(config.get('CpuCount'), 2)
183+
self.assertRaises(
184+
InvalidVersion, lambda: create_host_config(
185+
version='1.24', cpu_count=1))
186+
187+
def test_create_host_config_invalid_cpu_percent_types(self):
188+
with pytest.raises(TypeError):
189+
create_host_config(version='1.25', cpu_percent='1')
190+
191+
def test_create_host_config_with_cpu_percent(self):
192+
config = create_host_config(version='1.25', cpu_percent=15)
193+
self.assertEqual(config.get('CpuPercent'), 15)
194+
self.assertRaises(
195+
InvalidVersion, lambda: create_host_config(
196+
version='1.24', cpu_percent=10))
197+
198+
def test_create_host_config_invalid_cpus_types(self):
199+
with pytest.raises(TypeError):
200+
create_host_config(version='1.25', cpus='0')
201+
202+
def test_create_host_config_with_cpus(self):
203+
config = create_host_config(version='1.25', cpus=100)
204+
self.assertEqual(config.get('NanoCpus'), 100000000000)
205+
self.assertRaises(
206+
InvalidVersion, lambda: create_host_config(
207+
version='1.24', cpus=1))
175208

176209

177210
class ContainerConfigTest(unittest.TestCase):

0 commit comments

Comments
 (0)