Merge "add ulimit support for kolla_docker"
This commit is contained in:
commit
da98030909
@ -474,7 +474,8 @@ class DockerWorker(object):
|
|||||||
'memswap_limit': 'MemorySwap', 'cpu_period': 'CpuPeriod',
|
'memswap_limit': 'MemorySwap', 'cpu_period': 'CpuPeriod',
|
||||||
'cpu_quota': 'CpuQuota', 'cpu_shares': 'CpuShares',
|
'cpu_quota': 'CpuQuota', 'cpu_shares': 'CpuShares',
|
||||||
'cpuset_cpus': 'CpusetCpus', 'cpuset_mems': 'CpusetMems',
|
'cpuset_cpus': 'CpusetCpus', 'cpuset_mems': 'CpusetMems',
|
||||||
'kernel_memory': 'KernelMemory', 'blkio_weight': 'BlkioWeight'}
|
'kernel_memory': 'KernelMemory', 'blkio_weight': 'BlkioWeight',
|
||||||
|
'ulimits': 'Ulimits'}
|
||||||
unsupported = set(new_dimensions.keys()) - \
|
unsupported = set(new_dimensions.keys()) - \
|
||||||
set(dimension_map.keys())
|
set(dimension_map.keys())
|
||||||
if unsupported:
|
if unsupported:
|
||||||
@ -486,13 +487,29 @@ class DockerWorker(object):
|
|||||||
# NOTE(mgoddard): If a resource has been explicitly requested,
|
# NOTE(mgoddard): If a resource has been explicitly requested,
|
||||||
# check for a match. Otherwise, ensure is is set to the default.
|
# check for a match. Otherwise, ensure is is set to the default.
|
||||||
if key1 in new_dimensions:
|
if key1 in new_dimensions:
|
||||||
if new_dimensions[key1] != current_dimensions[key2]:
|
if key1 == 'ulimits':
|
||||||
|
if self.compare_ulimits(new_dimensions[key1],
|
||||||
|
current_dimensions[key2]):
|
||||||
|
return True
|
||||||
|
elif new_dimensions[key1] != current_dimensions[key2]:
|
||||||
return True
|
return True
|
||||||
elif current_dimensions[key2]:
|
elif current_dimensions[key2]:
|
||||||
# The default values of all currently supported resources are
|
# The default values of all currently supported resources are
|
||||||
# '' or 0 - both falsey.
|
# '' or 0 - both falsey.
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def compare_ulimits(self, new_ulimits, current_ulimits):
|
||||||
|
# The new_ulimits is dict, we need make it to a list of Ulimit
|
||||||
|
# instance.
|
||||||
|
new_ulimits = self.build_ulimits(new_ulimits)
|
||||||
|
|
||||||
|
def key(ulimit):
|
||||||
|
return ulimit['Name']
|
||||||
|
|
||||||
|
if current_ulimits is None:
|
||||||
|
current_ulimits = []
|
||||||
|
return sorted(new_ulimits, key=key) != sorted(current_ulimits, key=key)
|
||||||
|
|
||||||
def compare_command(self, container_info):
|
def compare_command(self, container_info):
|
||||||
new_command = self.params.get('command')
|
new_command = self.params.get('command')
|
||||||
if new_command is not None:
|
if new_command is not None:
|
||||||
@ -606,6 +623,40 @@ class DockerWorker(object):
|
|||||||
|
|
||||||
return vol_list, vol_dict
|
return vol_list, vol_dict
|
||||||
|
|
||||||
|
def parse_dimensions(self, dimensions):
|
||||||
|
# When the data object contains types such as
|
||||||
|
# docker.types.Ulimit, Ansible will fail when these are
|
||||||
|
# returned via exit_json or fail_json. HostConfig is derived from dict,
|
||||||
|
# but its constructor requires additional arguments.
|
||||||
|
# to avoid that, here do copy the dimensions and return a new one.
|
||||||
|
dimensions = dimensions.copy()
|
||||||
|
|
||||||
|
supported = {'cpu_period', 'cpu_quota', 'cpu_shares',
|
||||||
|
'cpuset_cpus', 'cpuset_mems', 'mem_limit',
|
||||||
|
'mem_reservation', 'memswap_limit',
|
||||||
|
'kernel_memory', 'blkio_weight', 'ulimits'}
|
||||||
|
unsupported = set(dimensions) - supported
|
||||||
|
if unsupported:
|
||||||
|
self.module.exit_json(failed=True,
|
||||||
|
msg=repr("Unsupported dimensions"),
|
||||||
|
unsupported_dimensions=unsupported)
|
||||||
|
|
||||||
|
ulimits = dimensions.get('ulimits')
|
||||||
|
if ulimits:
|
||||||
|
dimensions['ulimits'] = self.build_ulimits(ulimits)
|
||||||
|
|
||||||
|
return dimensions
|
||||||
|
|
||||||
|
def build_ulimits(self, ulimits):
|
||||||
|
ulimits_opt = []
|
||||||
|
for key, value in ulimits.items():
|
||||||
|
soft = value.get('soft')
|
||||||
|
hard = value.get('hard')
|
||||||
|
ulimits_opt.append(docker.types.Ulimit(name=key,
|
||||||
|
soft=soft,
|
||||||
|
hard=hard))
|
||||||
|
return ulimits_opt
|
||||||
|
|
||||||
def build_host_config(self, binds):
|
def build_host_config(self, binds):
|
||||||
options = {
|
options = {
|
||||||
'network_mode': 'host',
|
'network_mode': 'host',
|
||||||
@ -617,17 +668,11 @@ class DockerWorker(object):
|
|||||||
'volumes_from': self.params.get('volumes_from')
|
'volumes_from': self.params.get('volumes_from')
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.params.get('dimensions'):
|
dimensions = self.params.get('dimensions')
|
||||||
supported = {'cpu_period', 'cpu_quota', 'cpu_shares',
|
|
||||||
'cpuset_cpus', 'cpuset_mems', 'mem_limit',
|
if dimensions:
|
||||||
'mem_reservation', 'memswap_limit',
|
dimensions = self.parse_dimensions(dimensions)
|
||||||
'kernel_memory', 'blkio_weight'}
|
options.update(dimensions)
|
||||||
unsupported = set(self.params.get('dimensions')) - supported
|
|
||||||
if unsupported:
|
|
||||||
self.module.exit_json(failed=True,
|
|
||||||
msg=repr("Unsupported dimensions"),
|
|
||||||
unsupported_dimensions=unsupported)
|
|
||||||
options.update(self.params.get('dimensions'))
|
|
||||||
|
|
||||||
if self.params.get('restart_policy') in ['on-failure',
|
if self.params.get('restart_policy') in ['on-failure',
|
||||||
'always',
|
'always',
|
||||||
@ -940,5 +985,6 @@ def main():
|
|||||||
module.fail_json(changed=True, msg=repr(traceback.format_exc()),
|
module.fail_json(changed=True, msg=repr(traceback.format_exc()),
|
||||||
**dw.result)
|
**dw.result)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
@ -27,6 +27,7 @@ The resources currently supported by Kolla Ansible are:
|
|||||||
memswap_limit
|
memswap_limit
|
||||||
kernel_memory
|
kernel_memory
|
||||||
blkio_weight
|
blkio_weight
|
||||||
|
ulimits
|
||||||
|
|
||||||
Pre-deployment Configuration
|
Pre-deployment Configuration
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@ -67,6 +68,9 @@ Dimensions are defined as a mapping from a Docker resource name
|
|||||||
* - cpuset_mems
|
* - cpuset_mems
|
||||||
- String
|
- String
|
||||||
- ''(Empty String)
|
- ''(Empty String)
|
||||||
|
* - ulimits
|
||||||
|
- Dict
|
||||||
|
- {}
|
||||||
|
|
||||||
|
|
||||||
The variable ``default_container_dimensions`` sets the default dimensions
|
The variable ``default_container_dimensions`` sets the default dimensions
|
||||||
@ -96,6 +100,23 @@ options section in ``/etc/kolla/globals.yml``:
|
|||||||
nova_libvirt_dimensions:
|
nova_libvirt_dimensions:
|
||||||
cpuset_cpus: "2"
|
cpuset_cpus: "2"
|
||||||
|
|
||||||
|
How to config ulimits in kolla
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
<container_name>_dimensions:
|
||||||
|
ulimits:
|
||||||
|
nofile:
|
||||||
|
soft: 131072
|
||||||
|
hard: 131072
|
||||||
|
fsize:
|
||||||
|
soft: 131072
|
||||||
|
hard: 131072
|
||||||
|
|
||||||
|
A list of valid names can be found [here]
|
||||||
|
(https://github.com/docker/go-units/blob/d4a9b9617350c034730bc5051c605919943080bf/ulimit.go#L46-L63)
|
||||||
|
|
||||||
Deployment
|
Deployment
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -142,6 +142,7 @@ kolla_internal_vip_address: "10.10.10.254"
|
|||||||
# mem_reservation:
|
# mem_reservation:
|
||||||
# memswap_limit:
|
# memswap_limit:
|
||||||
# kernel_memory:
|
# kernel_memory:
|
||||||
|
# ulimits:
|
||||||
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Add ulimit support for kolla_docker which provides ability
|
||||||
|
of modify docker ulimits。
|
@ -23,6 +23,7 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
import mock
|
import mock
|
||||||
from docker import errors as docker_error
|
from docker import errors as docker_error
|
||||||
|
from docker.types import Ulimit
|
||||||
from oslotest import base
|
from oslotest import base
|
||||||
|
|
||||||
this_dir = os.path.dirname(sys.modules[__name__].__file__)
|
this_dir = os.path.dirname(sys.modules[__name__].__file__)
|
||||||
@ -904,7 +905,8 @@ class TestAttrComp(base.BaseTestCase):
|
|||||||
container_info['HostConfig'] = {
|
container_info['HostConfig'] = {
|
||||||
'CpuPeriod': 0, 'KernelMemory': 0, 'Memory': 0, 'CpuQuota': 0,
|
'CpuPeriod': 0, 'KernelMemory': 0, 'Memory': 0, 'CpuQuota': 0,
|
||||||
'CpusetCpus': '', 'CpuShares': 0, 'BlkioWeight': 0,
|
'CpusetCpus': '', 'CpuShares': 0, 'BlkioWeight': 0,
|
||||||
'CpusetMems': '', 'MemorySwap': 0, 'MemoryReservation': 0}
|
'CpusetMems': '', 'MemorySwap': 0, 'MemoryReservation': 0,
|
||||||
|
'Ulimits': []}
|
||||||
self.dw = get_DockerWorker(self.fake_data['params'])
|
self.dw = get_DockerWorker(self.fake_data['params'])
|
||||||
self.assertTrue(self.dw.compare_dimensions(container_info))
|
self.assertTrue(self.dw.compare_dimensions(container_info))
|
||||||
|
|
||||||
@ -915,7 +917,8 @@ class TestAttrComp(base.BaseTestCase):
|
|||||||
container_info['HostConfig'] = {
|
container_info['HostConfig'] = {
|
||||||
'CpuPeriod': 0, 'KernelMemory': 0, 'Memory': 0, 'CpuQuota': 0,
|
'CpuPeriod': 0, 'KernelMemory': 0, 'Memory': 0, 'CpuQuota': 0,
|
||||||
'CpusetCpus': '', 'CpuShares': 0, 'BlkioWeight': 10,
|
'CpusetCpus': '', 'CpuShares': 0, 'BlkioWeight': 10,
|
||||||
'CpusetMems': '', 'MemorySwap': 0, 'MemoryReservation': 0}
|
'CpusetMems': '', 'MemorySwap': 0, 'MemoryReservation': 0,
|
||||||
|
'Ulimits': []}
|
||||||
self.dw = get_DockerWorker(self.fake_data['params'])
|
self.dw = get_DockerWorker(self.fake_data['params'])
|
||||||
self.assertFalse(self.dw.compare_dimensions(container_info))
|
self.assertFalse(self.dw.compare_dimensions(container_info))
|
||||||
|
|
||||||
@ -926,7 +929,8 @@ class TestAttrComp(base.BaseTestCase):
|
|||||||
container_info['HostConfig'] = {
|
container_info['HostConfig'] = {
|
||||||
'CpuPeriod': 0, 'KernelMemory': 0, 'Memory': 0, 'CpuQuota': 0,
|
'CpuPeriod': 0, 'KernelMemory': 0, 'Memory': 0, 'CpuQuota': 0,
|
||||||
'CpusetCpus': '', 'CpuShares': 0, 'BlkioWeight': 0,
|
'CpusetCpus': '', 'CpuShares': 0, 'BlkioWeight': 0,
|
||||||
'CpusetMems': '', 'MemorySwap': 0, 'MemoryReservation': 0}
|
'CpusetMems': '', 'MemorySwap': 0, 'MemoryReservation': 0,
|
||||||
|
'Ulimits': []}
|
||||||
self.dw = get_DockerWorker(self.fake_data['params'])
|
self.dw = get_DockerWorker(self.fake_data['params'])
|
||||||
self.dw.compare_dimensions(container_info)
|
self.dw.compare_dimensions(container_info)
|
||||||
self.dw.module.exit_json.assert_called_once_with(
|
self.dw.module.exit_json.assert_called_once_with(
|
||||||
@ -939,7 +943,8 @@ class TestAttrComp(base.BaseTestCase):
|
|||||||
container_info['HostConfig'] = {
|
container_info['HostConfig'] = {
|
||||||
'CpuPeriod': 0, 'KernelMemory': 0, 'Memory': 0, 'CpuQuota': 0,
|
'CpuPeriod': 0, 'KernelMemory': 0, 'Memory': 0, 'CpuQuota': 0,
|
||||||
'CpusetCpus': '1', 'CpuShares': 0, 'BlkioWeight': 0,
|
'CpusetCpus': '1', 'CpuShares': 0, 'BlkioWeight': 0,
|
||||||
'CpusetMems': '', 'MemorySwap': 0, 'MemoryReservation': 0}
|
'CpusetMems': '', 'MemorySwap': 0, 'MemoryReservation': 0,
|
||||||
|
'Ulimits': []}
|
||||||
self.dw = get_DockerWorker(self.fake_data['params'])
|
self.dw = get_DockerWorker(self.fake_data['params'])
|
||||||
self.assertTrue(self.dw.compare_dimensions(container_info))
|
self.assertTrue(self.dw.compare_dimensions(container_info))
|
||||||
|
|
||||||
@ -954,7 +959,8 @@ class TestAttrComp(base.BaseTestCase):
|
|||||||
container_info['HostConfig'] = {
|
container_info['HostConfig'] = {
|
||||||
'CpuPeriod': 0, 'KernelMemory': 0, 'Memory': 10, 'CpuQuota': 0,
|
'CpuPeriod': 0, 'KernelMemory': 0, 'Memory': 10, 'CpuQuota': 0,
|
||||||
'CpusetCpus': '', 'CpuShares': 0, 'BlkioWeight': 0,
|
'CpusetCpus': '', 'CpuShares': 0, 'BlkioWeight': 0,
|
||||||
'CpusetMems': '', 'MemorySwap': 0, 'MemoryReservation': 10}
|
'CpusetMems': '', 'MemorySwap': 0, 'MemoryReservation': 10,
|
||||||
|
'Ulimits': []}
|
||||||
self.dw = get_DockerWorker(self.fake_data['params'])
|
self.dw = get_DockerWorker(self.fake_data['params'])
|
||||||
self.assertTrue(self.dw.compare_dimensions(container_info))
|
self.assertTrue(self.dw.compare_dimensions(container_info))
|
||||||
|
|
||||||
@ -969,7 +975,8 @@ class TestAttrComp(base.BaseTestCase):
|
|||||||
container_info['HostConfig'] = {
|
container_info['HostConfig'] = {
|
||||||
'CpuPeriod': 0, 'KernelMemory': 0, 'Memory': 0, 'CpuQuota': 0,
|
'CpuPeriod': 0, 'KernelMemory': 0, 'Memory': 0, 'CpuQuota': 0,
|
||||||
'CpusetCpus': '', 'CpuShares': 0, 'BlkioWeight': 0,
|
'CpusetCpus': '', 'CpuShares': 0, 'BlkioWeight': 0,
|
||||||
'CpusetMems': '', 'MemorySwap': 0, 'MemoryReservation': 0}
|
'CpusetMems': '', 'MemorySwap': 0, 'MemoryReservation': 0,
|
||||||
|
'Ulimits': []}
|
||||||
self.dw = get_DockerWorker(self.fake_data['params'])
|
self.dw = get_DockerWorker(self.fake_data['params'])
|
||||||
self.assertFalse(self.dw.compare_dimensions(container_info))
|
self.assertFalse(self.dw.compare_dimensions(container_info))
|
||||||
|
|
||||||
@ -977,3 +984,29 @@ class TestAttrComp(base.BaseTestCase):
|
|||||||
container_info = {'State': dict(Status='running')}
|
container_info = {'State': dict(Status='running')}
|
||||||
self.dw = get_DockerWorker({'state': 'exited'})
|
self.dw = get_DockerWorker({'state': 'exited'})
|
||||||
self.assertTrue(self.dw.compare_container_state(container_info))
|
self.assertTrue(self.dw.compare_container_state(container_info))
|
||||||
|
|
||||||
|
def test_compare_ulimits_pos(self):
|
||||||
|
self.fake_data['params']['dimensions'] = {
|
||||||
|
'ulimits': {'nofile': {'soft': 131072, 'hard': 131072}}}
|
||||||
|
container_info = dict()
|
||||||
|
container_info['HostConfig'] = {
|
||||||
|
'CpuPeriod': 0, 'KernelMemory': 0, 'Memory': 0, 'CpuQuota': 0,
|
||||||
|
'CpusetCpus': '', 'CpuShares': 0, 'BlkioWeight': 0,
|
||||||
|
'CpusetMems': '', 'MemorySwap': 0, 'MemoryReservation': 0,
|
||||||
|
'Ulimits': []}
|
||||||
|
self.dw = get_DockerWorker(self.fake_data['params'])
|
||||||
|
self.assertTrue(self.dw.compare_dimensions(container_info))
|
||||||
|
|
||||||
|
def test_compare_ulimits_neg(self):
|
||||||
|
self.fake_data['params']['dimensions'] = {
|
||||||
|
'ulimits': {'nofile': {'soft': 131072, 'hard': 131072}}}
|
||||||
|
ulimits_nofile = Ulimit(name='nofile',
|
||||||
|
soft=131072, hard=131072)
|
||||||
|
container_info = dict()
|
||||||
|
container_info['HostConfig'] = {
|
||||||
|
'CpuPeriod': 0, 'KernelMemory': 0, 'Memory': 0, 'CpuQuota': 0,
|
||||||
|
'CpusetCpus': '', 'CpuShares': 0, 'BlkioWeight': 0,
|
||||||
|
'CpusetMems': '', 'MemorySwap': 0, 'MemoryReservation': 0,
|
||||||
|
'Ulimits': [ulimits_nofile]}
|
||||||
|
self.dw = get_DockerWorker(self.fake_data['params'])
|
||||||
|
self.assertFalse(self.dw.compare_dimensions(container_info))
|
||||||
|
Loading…
Reference in New Issue
Block a user