Support scheduler strategy for swarm cluster

Swarm cluster can be created by specifying any of the scheduler
strategy supported by swarm. The strategy can be specified
while creating cluster template using labels parameter, Ex:-
--labels swarm_strategy=spread
Supported values for swarm_strategy=spread, binpack, random

Change-Id: If471f10a3b1f955638a77d5afe462aebdeb4277c
Implements: blueprint add-support-different-strategy-in-swarmbay
This commit is contained in:
yatin 2016-11-03 12:00:54 +05:30
parent ceb59dd1c4
commit 2d160ecfcb
8 changed files with 60 additions and 4 deletions

View File

@ -28,6 +28,7 @@ SUPPORTED_ISOLATION = ['filesystem/posix', 'filesystem/linux',
'cgroups/mem', 'docker/runtime', 'cgroups/mem', 'docker/runtime',
'namespaces/pid'] 'namespaces/pid']
SUPPORTED_IMAGE_PROVIDERS = ['docker', 'appc'] SUPPORTED_IMAGE_PROVIDERS = ['docker', 'appc']
SUPPORTED_SWARM_STRATEGY = ['spread', 'binpack', 'random']
def validate_image(cli, image): def validate_image(cli, image):
@ -166,6 +167,21 @@ def validate_labels_executor_env_variables(labels):
raise exception.InvalidParameterValue(err) raise exception.InvalidParameterValue(err)
def validate_labels_strategy(labels):
"""Validate swarm_strategy"""
swarm_strategy = list(labels.get('swarm_strategy', "").split())
unsupported_strategy = set(swarm_strategy) - set(
SUPPORTED_SWARM_STRATEGY)
if (len(unsupported_strategy) > 0):
raise exception.InvalidParameterValue(_(
'property "labels/swarm_strategy" with value '
'"%(strategy)s" is not supported, supported values are: '
'%(supported_strategies)s') % {
'strategy': ' '.join(list(unsupported_strategy)),
'supported_strategies': ', '.join(
SUPPORTED_SWARM_STRATEGY + ['unspecified'])})
def validate_os_resources(context, cluster_template, cluster=None): def validate_os_resources(context, cluster_template, cluster=None):
"""Validate ClusterTemplate's OpenStack Resources""" """Validate ClusterTemplate's OpenStack Resources"""
@ -201,4 +217,5 @@ labels_validators = {'mesos_slave_isolation': validate_labels_isolation,
'mesos_slave_image_providers': 'mesos_slave_image_providers':
validate_labels_image_providers, validate_labels_image_providers,
'mesos_slave_executor_env_variables': 'mesos_slave_executor_env_variables':
validate_labels_executor_env_variables} validate_labels_executor_env_variables,
'swarm_strategy': validate_labels_strategy}

View File

@ -94,7 +94,8 @@ class SwarmFedoraTemplateDefinition(template_def.BaseTemplateDefinition):
extra_params['magnum_url'] = osc.magnum_url() extra_params['magnum_url'] = osc.magnum_url()
label_list = ['flannel_network_cidr', 'flannel_backend', label_list = ['flannel_network_cidr', 'flannel_backend',
'flannel_network_subnetlen', 'rexray_preempt'] 'flannel_network_subnetlen', 'rexray_preempt',
'swarm_strategy']
extra_params['auth_url'] = context.auth_url extra_params['auth_url'] = context.auth_url

View File

@ -20,6 +20,7 @@ ExecStart=/usr/bin/docker run --name swarm-manager \\
-e no_proxy=$NO_PROXY \\ -e no_proxy=$NO_PROXY \\
swarm:$SWARM_VERSION \\ swarm:$SWARM_VERSION \\
manage -H tcp://0.0.0.0:2375 \\ manage -H tcp://0.0.0.0:2375 \\
--strategy $SWARM_STRATEGY \\
--replication \\ --replication \\
--advertise $NODE_IP:2376 \\ --advertise $NODE_IP:2376 \\
END_SERVICE_TOP END_SERVICE_TOP

View File

@ -147,6 +147,12 @@ parameters:
description: version of swarm used for swarm cluster description: version of swarm used for swarm cluster
default: 1.0.0 default: 1.0.0
swarm_strategy:
type: string
description: >
schedule strategy to be used by swarm manager
default: "spread"
trustee_domain_id: trustee_domain_id:
type: string type: string
description: domain id of the trustee description: domain id of the trustee
@ -414,6 +420,7 @@ resources:
etcd_server_ip: {get_attr: [etcd_loadbalancer, vip_address]} etcd_server_ip: {get_attr: [etcd_loadbalancer, vip_address]}
api_ip_address: {get_attr: [api_pool_floating, floating_ip_address]} api_ip_address: {get_attr: [api_pool_floating, floating_ip_address]}
swarm_version: {get_param: swarm_version} swarm_version: {get_param: swarm_version}
swarm_strategy: {get_param: swarm_strategy}
trustee_user_id: {get_param: trustee_user_id} trustee_user_id: {get_param: trustee_user_id}
trustee_password: {get_param: trustee_password} trustee_password: {get_param: trustee_password}
trust_id: {get_param: trust_id} trust_id: {get_param: trust_id}

View File

@ -103,6 +103,13 @@ parameters:
type: string type: string
description: version of swarm used for swarm cluster description: version of swarm used for swarm cluster
swarm_strategy:
type: string
description: >
schedule strategy to be used by swarm manager
constraints:
- allowed_values: ["spread", "binpack", "random"]
secgroup_swarm_master_id: secgroup_swarm_master_id:
type: string type: string
description: ID of the security group for swarm master. description: ID of the security group for swarm master.
@ -315,6 +322,7 @@ resources:
"$NO_PROXY": {get_param: no_proxy} "$NO_PROXY": {get_param: no_proxy}
"$TLS_DISABLED": {get_param: tls_disabled} "$TLS_DISABLED": {get_param: tls_disabled}
"$SWARM_VERSION": {get_param: swarm_version} "$SWARM_VERSION": {get_param: swarm_version}
"$SWARM_STRATEGY": {get_param: swarm_strategy}
enable_services: enable_services:
type: "OS::Heat::SoftwareConfig" type: "OS::Heat::SoftwareConfig"

View File

@ -186,6 +186,20 @@ class TestAttrValidator(base.BaseTestCase):
attr_validator.validate_labels_isolation, attr_validator.validate_labels_isolation,
fake_labels) fake_labels)
def test_validate_labels_strategy_valid(self):
fake_labels = {'swarm_strategy': 'spread'}
attr_validator.validate_labels_strategy(fake_labels)
def test_validate_labels_strategy_missing(self):
fake_labels = {'strategy': 'spread'}
attr_validator.validate_labels_strategy(fake_labels)
def test_validate_labels_strategy_invalid(self):
fake_labels = {'swarm_strategy': 'invalid'}
self.assertRaises(exception.InvalidParameterValue,
attr_validator.validate_labels_strategy,
fake_labels)
@mock.patch('magnum.api.utils.get_openstack_resource') @mock.patch('magnum.api.utils.get_openstack_resource')
def test_validate_image_with_valid_image_by_name(self, mock_os_res): def test_validate_image_with_valid_image_by_name(self, mock_os_res):
mock_image = {'name': 'fedora-21-atomic-5', mock_image = {'name': 'fedora-21-atomic-5',

View File

@ -51,7 +51,8 @@ class TestClusterConductorWithSwarm(base.TestCase):
'labels': {'flannel_network_cidr': '10.101.0.0/16', 'labels': {'flannel_network_cidr': '10.101.0.0/16',
'flannel_network_subnetlen': '26', 'flannel_network_subnetlen': '26',
'flannel_backend': 'vxlan', 'flannel_backend': 'vxlan',
'rexray_preempt': 'False'}, 'rexray_preempt': 'False',
'swarm_strategy': 'spread'},
'master_lb_enabled': False, 'master_lb_enabled': False,
'volume_driver': 'rexray' 'volume_driver': 'rexray'
} }
@ -139,6 +140,7 @@ class TestClusterConductorWithSwarm(base.TestCase):
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de', 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
'auth_url': 'http://192.168.10.10:5000/v3', 'auth_url': 'http://192.168.10.10:5000/v3',
'swarm_version': 'fake-version', 'swarm_version': 'fake-version',
'swarm_strategy': u'spread',
'volume_driver': 'rexray', 'volume_driver': 'rexray',
'rexray_preempt': 'False' 'rexray_preempt': 'False'
} }
@ -209,6 +211,7 @@ class TestClusterConductorWithSwarm(base.TestCase):
'auth_url': 'http://192.168.10.10:5000/v3', 'auth_url': 'http://192.168.10.10:5000/v3',
'docker_storage_driver': 'devicemapper', 'docker_storage_driver': 'devicemapper',
'swarm_version': 'fake-version', 'swarm_version': 'fake-version',
'swarm_strategy': u'spread',
'volume_driver': 'rexray', 'volume_driver': 'rexray',
'rexray_preempt': 'False' 'rexray_preempt': 'False'
} }
@ -272,6 +275,7 @@ class TestClusterConductorWithSwarm(base.TestCase):
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de', 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
'auth_url': 'http://192.168.10.10:5000/v3', 'auth_url': 'http://192.168.10.10:5000/v3',
'swarm_version': 'fake-version', 'swarm_version': 'fake-version',
'swarm_strategy': u'spread',
'rexray_preempt': 'False' 'rexray_preempt': 'False'
} }
self.assertEqual(expected, definition) self.assertEqual(expected, definition)
@ -335,6 +339,7 @@ class TestClusterConductorWithSwarm(base.TestCase):
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de', 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
'auth_url': 'http://192.168.10.10:5000/v3', 'auth_url': 'http://192.168.10.10:5000/v3',
'swarm_version': 'fake-version', 'swarm_version': 'fake-version',
'swarm_strategy': u'spread',
'volume_driver': 'rexray', 'volume_driver': 'rexray',
'rexray_preempt': 'False' 'rexray_preempt': 'False'
} }
@ -400,6 +405,7 @@ class TestClusterConductorWithSwarm(base.TestCase):
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de', 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
'auth_url': 'http://192.168.10.10:5000/v3', 'auth_url': 'http://192.168.10.10:5000/v3',
'swarm_version': 'fake-version', 'swarm_version': 'fake-version',
'swarm_strategy': u'spread',
'volume_driver': 'rexray', 'volume_driver': 'rexray',
'rexray_preempt': 'False' 'rexray_preempt': 'False'
} }

View File

@ -718,6 +718,7 @@ class AtomicSwarmTemplateDefinitionTestCase(base.TestCase):
'flannel_network_subnetlen') 'flannel_network_subnetlen')
flannel_backend = mock_cluster_template.labels.get('flannel_backend') flannel_backend = mock_cluster_template.labels.get('flannel_backend')
rexray_preempt = mock_cluster_template.labels.get('rexray_preempt') rexray_preempt = mock_cluster_template.labels.get('rexray_preempt')
swarm_strategy = mock_cluster_template.labels.get('swarm_strategy')
swarm_def = swarm_tdef.AtomicSwarmTemplateDefinition() swarm_def = swarm_tdef.AtomicSwarmTemplateDefinition()
@ -730,7 +731,8 @@ class AtomicSwarmTemplateDefinitionTestCase(base.TestCase):
'flannel_backend': flannel_backend, 'flannel_backend': flannel_backend,
'flannel_network_subnetlen': flannel_subnet, 'flannel_network_subnetlen': flannel_subnet,
'auth_url': 'http://192.168.10.10:5000/v3', 'auth_url': 'http://192.168.10.10:5000/v3',
'rexray_preempt': rexray_preempt}} 'rexray_preempt': rexray_preempt,
'swarm_strategy': swarm_strategy}}
mock_get_params.assert_called_once_with(mock_context, mock_get_params.assert_called_once_with(mock_context,
mock_cluster_template, mock_cluster_template,
mock_cluster, mock_cluster,