Merge "Docker plugin add cpu share property"
This commit is contained in:
commit
e53b3ff73b
@ -31,7 +31,7 @@ from heat.engine import support
|
|||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
DOCKER_INSTALLED = False
|
DOCKER_INSTALLED = False
|
||||||
READ_ONLY_MIN_API_VERSION = '1.17'
|
MIN_API_VERSION_MAP = {'read_only': '1.17', 'cpu_shares': '1.8'}
|
||||||
# conditionally import so tests can work without having the dependency
|
# conditionally import so tests can work without having the dependency
|
||||||
# satisfied
|
# satisfied
|
||||||
try:
|
try:
|
||||||
@ -47,12 +47,12 @@ class DockerContainer(resource.Resource):
|
|||||||
DOCKER_ENDPOINT, HOSTNAME, USER, MEMORY, PORT_SPECS,
|
DOCKER_ENDPOINT, HOSTNAME, USER, MEMORY, PORT_SPECS,
|
||||||
PRIVILEGED, TTY, OPEN_STDIN, STDIN_ONCE, ENV, CMD, DNS,
|
PRIVILEGED, TTY, OPEN_STDIN, STDIN_ONCE, ENV, CMD, DNS,
|
||||||
IMAGE, VOLUMES, VOLUMES_FROM, PORT_BINDINGS, LINKS, NAME,
|
IMAGE, VOLUMES, VOLUMES_FROM, PORT_BINDINGS, LINKS, NAME,
|
||||||
RESTART_POLICY, CAP_ADD, CAP_DROP, READ_ONLY,
|
RESTART_POLICY, CAP_ADD, CAP_DROP, READ_ONLY, CPU_SHARES,
|
||||||
) = (
|
) = (
|
||||||
'docker_endpoint', 'hostname', 'user', 'memory', 'port_specs',
|
'docker_endpoint', 'hostname', 'user', 'memory', 'port_specs',
|
||||||
'privileged', 'tty', 'open_stdin', 'stdin_once', 'env', 'cmd', 'dns',
|
'privileged', 'tty', 'open_stdin', 'stdin_once', 'env', 'cmd', 'dns',
|
||||||
'image', 'volumes', 'volumes_from', 'port_bindings', 'links', 'name',
|
'image', 'volumes', 'volumes_from', 'port_bindings', 'links', 'name',
|
||||||
'restart_policy', 'cap_add', 'cap_drop', 'read_only'
|
'restart_policy', 'cap_add', 'cap_drop', 'read_only', 'cpu_shares',
|
||||||
)
|
)
|
||||||
|
|
||||||
ATTRIBUTES = (
|
ATTRIBUTES = (
|
||||||
@ -223,9 +223,17 @@ class DockerContainer(resource.Resource):
|
|||||||
properties.Schema.BOOLEAN,
|
properties.Schema.BOOLEAN,
|
||||||
_('If true, mount the container\'s root filesystem '
|
_('If true, mount the container\'s root filesystem '
|
||||||
'as read only (only supported for API version >= %s).') %
|
'as read only (only supported for API version >= %s).') %
|
||||||
READ_ONLY_MIN_API_VERSION,
|
MIN_API_VERSION_MAP['read_only'],
|
||||||
default=False,
|
default=False,
|
||||||
support_status=support.SupportStatus(version='2015.1'),
|
support_status=support.SupportStatus(version='2015.1'),
|
||||||
|
),
|
||||||
|
CPU_SHARES: properties.Schema(
|
||||||
|
properties.Schema.INTEGER,
|
||||||
|
_('Relative weight which determines the allocation of the CPU '
|
||||||
|
'processing power(only supported for API version >= %s).') %
|
||||||
|
MIN_API_VERSION_MAP['cpu_shares'],
|
||||||
|
default=0,
|
||||||
|
support_status=support.SupportStatus(version='2015.2'),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,10 +351,10 @@ class DockerContainer(resource.Resource):
|
|||||||
'environment': self.properties[self.ENV],
|
'environment': self.properties[self.ENV],
|
||||||
'dns': self.properties[self.DNS],
|
'dns': self.properties[self.DNS],
|
||||||
'volumes': self.properties[self.VOLUMES],
|
'volumes': self.properties[self.VOLUMES],
|
||||||
'name': self.properties[self.NAME]
|
'name': self.properties[self.NAME],
|
||||||
|
'cpu_shares': self.properties[self.CPU_SHARES]
|
||||||
}
|
}
|
||||||
client = self.get_client()
|
client = self.get_client()
|
||||||
version = client.version()['ApiVersion']
|
|
||||||
client.pull(self.properties[self.IMAGE])
|
client.pull(self.properties[self.IMAGE])
|
||||||
result = client.create_container(**create_args)
|
result = client.create_container(**create_args)
|
||||||
container_id = result['Id']
|
container_id = result['Id']
|
||||||
@ -371,12 +379,7 @@ class DockerContainer(resource.Resource):
|
|||||||
if self.properties[self.CAP_DROP]:
|
if self.properties[self.CAP_DROP]:
|
||||||
start_args['cap_drop'] = self.properties[self.CAP_DROP]
|
start_args['cap_drop'] = self.properties[self.CAP_DROP]
|
||||||
if self.properties[self.READ_ONLY]:
|
if self.properties[self.READ_ONLY]:
|
||||||
if compare_version(READ_ONLY_MIN_API_VERSION, version) >= 0:
|
|
||||||
start_args[self.READ_ONLY] = True
|
start_args[self.READ_ONLY] = True
|
||||||
else:
|
|
||||||
raise InvalidArgForVersion(arg=self.READ_ONLY,
|
|
||||||
min_version=(
|
|
||||||
READ_ONLY_MIN_API_VERSION))
|
|
||||||
|
|
||||||
client.start(container_id, **start_args)
|
client.start(container_id, **start_args)
|
||||||
return container_id
|
return container_id
|
||||||
@ -439,6 +442,22 @@ class DockerContainer(resource.Resource):
|
|||||||
status = self._get_container_status(container_id)
|
status = self._get_container_status(container_id)
|
||||||
return status['Running']
|
return status['Running']
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
super(DockerContainer, self).validate()
|
||||||
|
self._validate_arg_for_api_version()
|
||||||
|
|
||||||
|
def _validate_arg_for_api_version(self):
|
||||||
|
version = None
|
||||||
|
for key in MIN_API_VERSION_MAP:
|
||||||
|
if self.properties[key]:
|
||||||
|
if not version:
|
||||||
|
client = self.get_client()
|
||||||
|
version = client.version()['ApiVersion']
|
||||||
|
min_version = MIN_API_VERSION_MAP[key]
|
||||||
|
if compare_version(min_version, version) < 0:
|
||||||
|
raise InvalidArgForVersion(arg=key,
|
||||||
|
min_version=min_version)
|
||||||
|
|
||||||
|
|
||||||
def resource_mapping():
|
def resource_mapping():
|
||||||
return {
|
return {
|
||||||
|
@ -19,6 +19,7 @@ from oslo_utils import importutils
|
|||||||
import six
|
import six
|
||||||
|
|
||||||
from heat.common import exception
|
from heat.common import exception
|
||||||
|
from heat.common.i18n import _
|
||||||
from heat.common import template_format
|
from heat.common import template_format
|
||||||
from heat.engine import resource
|
from heat.engine import resource
|
||||||
from heat.engine import rsrc_defn
|
from heat.engine import rsrc_defn
|
||||||
@ -314,24 +315,48 @@ class DockerContainerTest(common.HeatTestCase):
|
|||||||
self.assertEqual(['samalba/wordpress'], client.pulled_images)
|
self.assertEqual(['samalba/wordpress'], client.pulled_images)
|
||||||
self.assertIs(True, client.container_start[0]['read_only'])
|
self.assertIs(True, client.container_start[0]['read_only'])
|
||||||
|
|
||||||
def test_start_with_read_only_for_low_api_version(self):
|
def arg_for_low_api_version(self, arg, value, low_version):
|
||||||
t = template_format.parse(template)
|
t = template_format.parse(template)
|
||||||
stack = utils.parse_stack(t)
|
stack = utils.parse_stack(t)
|
||||||
definition = stack.t.resource_definitions(stack)['Blog']
|
definition = stack.t.resource_definitions(stack)['Blog']
|
||||||
definition['Properties']['read_only'] = True
|
definition['Properties'][arg] = value
|
||||||
my_resource = docker_container.DockerContainer(
|
my_resource = docker_container.DockerContainer(
|
||||||
'Blog', definition, stack)
|
'Blog', definition, stack)
|
||||||
get_client_mock = self.patchobject(my_resource, 'get_client')
|
get_client_mock = self.patchobject(my_resource, 'get_client')
|
||||||
get_client_mock.return_value = fakeclient.FakeDockerClient()
|
get_client_mock.return_value = fakeclient.FakeDockerClient()
|
||||||
get_client_mock.return_value.set_api_version('1.16')
|
get_client_mock.return_value.set_api_version(low_version)
|
||||||
self.assertIsNone(my_resource.validate())
|
msg = self.assertRaises(docker_container.InvalidArgForVersion,
|
||||||
msg = self.assertRaises(exception.ResourceFailure,
|
my_resource.validate)
|
||||||
scheduler.TaskRunner(my_resource.create))
|
min_version = docker_container.MIN_API_VERSION_MAP[arg]
|
||||||
expected = ('InvalidArgForVersion: "read_only" is not supported '
|
args = dict(arg=arg, min_version=min_version)
|
||||||
'for API version < "1.17"')
|
expected = _('"%(arg)s" is not supported for API version '
|
||||||
|
'< "%(min_version)s"') % args
|
||||||
self.assertEqual(expected, six.text_type(msg))
|
self.assertEqual(expected, six.text_type(msg))
|
||||||
|
|
||||||
|
def test_start_with_read_only_for_low_api_version(self):
|
||||||
|
self.arg_for_low_api_version('read_only', True, '1.16')
|
||||||
|
|
||||||
def test_compare_version(self):
|
def test_compare_version(self):
|
||||||
self.assertEqual(docker_container.compare_version('1.17', '1.17'), 0)
|
self.assertEqual(docker_container.compare_version('1.17', '1.17'), 0)
|
||||||
self.assertEqual(docker_container.compare_version('1.17', '1.16'), -1)
|
self.assertEqual(docker_container.compare_version('1.17', '1.16'), -1)
|
||||||
self.assertEqual(docker_container.compare_version('1.17', '1.18'), 1)
|
self.assertEqual(docker_container.compare_version('1.17', '1.18'), 1)
|
||||||
|
|
||||||
|
def test_create_with_cpu_shares(self):
|
||||||
|
t = template_format.parse(template)
|
||||||
|
stack = utils.parse_stack(t)
|
||||||
|
definition = stack.t.resource_definitions(stack)['Blog']
|
||||||
|
definition['Properties']['cpu_shares'] = 512
|
||||||
|
my_resource = docker_container.DockerContainer(
|
||||||
|
'Blog', definition, stack)
|
||||||
|
get_client_mock = self.patchobject(my_resource, 'get_client')
|
||||||
|
get_client_mock.return_value = fakeclient.FakeDockerClient()
|
||||||
|
self.assertIsNone(my_resource.validate())
|
||||||
|
scheduler.TaskRunner(my_resource.create)()
|
||||||
|
self.assertEqual((my_resource.CREATE, my_resource.COMPLETE),
|
||||||
|
my_resource.state)
|
||||||
|
client = my_resource.get_client()
|
||||||
|
self.assertEqual(['samalba/wordpress'], client.pulled_images)
|
||||||
|
self.assertEqual(512, client.container_create[0]['cpu_shares'])
|
||||||
|
|
||||||
|
def test_create_with_cpu_shares_for_low_api_version(self):
|
||||||
|
self.arg_for_low_api_version('cpu_shares', 512, '1.7')
|
||||||
|
Loading…
Reference in New Issue
Block a user