Merge "Allow master_flavor_id on cluster create"

This commit is contained in:
Jenkins 2017-10-05 10:44:50 +00:00 committed by Gerrit Code Review
commit 2bf7e34498
18 changed files with 89 additions and 24 deletions

View File

@ -39,6 +39,7 @@ Request
- node_count: node_count
- create_timeout: create_timeout
- keypair: keypair_id
- master_flavor_id: master_flavor_id
.. note::

View File

@ -5,5 +5,6 @@
"cluster_template_id":"0562d357-8641-4759-8fed-8173f02c9633",
"node_count":2,
"create_timeout":60,
"keypair":"my_keypair"
"keypair":"my_keypair",
"master_flavor_id":null
}

View File

@ -211,7 +211,7 @@ They are loosely grouped as: mandatory, infrastructure, COE specific.
--master-flavor \<master-flavor\>
The nova flavor id for booting the master or manager servers. The
default is 'm1.small'.
default is 'm1.small'. This value can be overridden at cluster creation.
--http-proxy \<http-proxy\>
The IP address for a proxy to use when direct http access from the

View File

@ -95,6 +95,9 @@ class Bay(base.APIBase):
labels = wtypes.DictType(str, str)
"""One or more key/value pairs"""
master_flavor_id = wtypes.StringType(min_length=1, max_length=255)
"""The master flavor of this Bay"""
bay_create_timeout = wsme.wsattr(wtypes.IntegerType(minimum=0), default=60)
"""Timeout for creating the bay in minutes. Default to 60 if not set"""
@ -178,6 +181,7 @@ class Bay(base.APIBase):
if not expand:
bay.unset_fields_except(['uuid', 'name', 'baymodel_id',
'docker_volume_size', 'labels',
'master_flavor_id',
'node_count', 'status',
'bay_create_timeout', 'master_count',
'stack_id'])
@ -203,6 +207,7 @@ class Bay(base.APIBase):
master_count=1,
docker_volume_size=1,
labels={},
master_flavor_id=None,
bay_create_timeout=15,
stack_id='49dc23f5-ffc9-40c3-9d34-7be7f9e34d63',
status=fields.ClusterStatus.CREATE_COMPLETE,
@ -432,6 +437,10 @@ class BaysController(base.Controller):
if bay.labels is None:
bay.labels = baymodel.labels
# If master_flavor_id is not present, use baymodel value
if bay.master_flavor_id == wtypes.Unset or not bay.master_flavor_id:
bay.master_flavor_id = baymodel.master_flavor_id
bay_dict = bay.as_dict()
bay_dict['keypair'] = baymodel.keypair_id
attr_validator.validate_os_resources(context, baymodel.as_dict(),

View File

@ -113,6 +113,9 @@ class Cluster(base.APIBase):
labels = wtypes.DictType(str, str)
"""One or more key/value pairs"""
master_flavor_id = wtypes.StringType(min_length=1, max_length=255)
"""The flavor of the master node for this Cluster"""
create_timeout = wsme.wsattr(wtypes.IntegerType(minimum=0), default=60)
"""Timeout for creating the cluster in minutes. Default to 60 if not set"""
@ -166,6 +169,7 @@ class Cluster(base.APIBase):
cluster.unset_fields_except(['uuid', 'name', 'cluster_template_id',
'keypair', 'docker_volume_size',
'labels', 'node_count', 'status',
'master_flavor_id',
'create_timeout', 'master_count',
'stack_id'])
@ -192,6 +196,7 @@ class Cluster(base.APIBase):
master_count=1,
docker_volume_size=1,
labels={},
master_flavor_id='m1.small',
create_timeout=15,
stack_id='49dc23f5-ffc9-40c3-9d34-7be7f9e34d63',
status=fields.ClusterStatus.CREATE_COMPLETE,
@ -411,6 +416,11 @@ class ClustersController(base.Controller):
if cluster.labels == wtypes.Unset:
cluster.labels = cluster_template.labels
# If master_flavor_id is not present, use cluster_template value
if (cluster.master_flavor_id == wtypes.Unset or
not cluster.master_flavor_id):
cluster.master_flavor_id = cluster_template.master_flavor_id
cluster_dict = cluster.as_dict()
attr_validator.validate_os_resources(context,

View File

@ -0,0 +1,30 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""add master_flavor_id to cluster
Revision ID: 52bcaf58fecb
Revises: a0e7c8450ab1
Create Date: 2017-08-01 11:22:31.277745
"""
# revision identifiers, used by Alembic.
revision = '52bcaf58fecb'
down_revision = 'a0e7c8450ab1'
from alembic import op
import sqlalchemy as sa
def upgrade():
op.add_column('cluster', sa.Column('master_flavor_id',
sa.String(length=255), nullable=True))

View File

@ -117,6 +117,7 @@ class Cluster(Base):
keypair = Column(String(255))
docker_volume_size = Column(Integer())
labels = Column(JSONEncodedDict)
master_flavor_id = Column(String(255))
stack_id = Column(String(255))
api_address = Column(String(255))
node_addresses = Column(JSONEncodedList)

View File

@ -52,7 +52,7 @@ class K8sTemplateDefinition(template_def.BaseTemplateDefinition):
def __init__(self):
super(K8sTemplateDefinition, self).__init__()
self.add_parameter('master_flavor',
cluster_template_attr='master_flavor_id')
cluster_attr='master_flavor_id')
self.add_parameter('minion_flavor',
cluster_template_attr='flavor_id')
self.add_parameter('number_of_minions',

View File

@ -48,7 +48,7 @@ class SwarmFedoraTemplateDefinition(template_def.BaseTemplateDefinition):
self.add_parameter('number_of_nodes',
cluster_attr='node_count')
self.add_parameter('master_flavor',
cluster_template_attr='master_flavor_id')
cluster_attr='master_flavor_id')
self.add_parameter('node_flavor',
cluster_template_attr='flavor_id')
self.add_parameter('docker_volume_size',

View File

@ -61,7 +61,7 @@ class SwarmModeTemplateDefinition(template_def.BaseTemplateDefinition):
self.add_parameter('number_of_nodes',
cluster_attr='node_count')
self.add_parameter('master_flavor',
cluster_template_attr='master_flavor_id')
cluster_attr='master_flavor_id')
self.add_parameter('node_flavor',
cluster_template_attr='flavor_id')
self.add_parameter('docker_volume_size',

View File

@ -31,7 +31,7 @@ class UbuntuMesosTemplateDefinition(template_def.BaseTemplateDefinition):
self.add_parameter('number_of_slaves',
cluster_attr='node_count')
self.add_parameter('master_flavor',
cluster_template_attr='master_flavor_id')
cluster_attr='master_flavor_id')
self.add_parameter('slave_flavor',
cluster_template_attr='flavor_id')
self.add_parameter('cluster_name',

View File

@ -44,8 +44,9 @@ class Cluster(base.MagnumPersistentObject, base.MagnumObject,
# Version 1.13: Added get_count_all method
# Version 1.14: Added 'docker_volume_size' field
# Version 1.15: Added 'labels' field
# Version 1.16: Added 'master_flavor_id' field
VERSION = '1.15'
VERSION = '1.16'
dbapi = dbapi.get_instance()
@ -59,6 +60,7 @@ class Cluster(base.MagnumPersistentObject, base.MagnumObject,
'keypair': fields.StringField(nullable=True),
'docker_volume_size': fields.IntegerField(nullable=True),
'labels': fields.DictOfStringsField(nullable=True),
'master_flavor_id': fields.StringField(nullable=True),
'stack_id': fields.StringField(nullable=True),
'status': m_fields.ClusterStatusField(nullable=True),
'status_reason': fields.StringField(nullable=True),

View File

@ -838,6 +838,24 @@ class TestPost(api_base.FunctionalTest):
self.assertEqual(400, response.status_int)
self.assertTrue(response.json['errors'])
def test_create_cluster_with_master_flavor_id(self):
bdict = apiutils.cluster_post_data()
bdict['master_flavor_id'] = 'm2.small'
response = self.post_json('/clusters', bdict)
self.assertEqual('application/json', response.content_type)
self.assertEqual(202, response.status_int)
cluster, timeout = self.mock_cluster_create.call_args
self.assertEqual('m2.small', cluster[0].master_flavor_id)
def test_create_cluster_without_master_flavor_id(self):
bdict = apiutils.cluster_post_data()
response = self.post_json('/clusters', bdict)
self.assertEqual('application/json', response.content_type)
self.assertEqual(202, response.status_int)
cluster, timeout = self.mock_cluster_create.call_args
# Verify master_flavor_id from ClusterTemplate is used
self.assertEqual('m1.small', cluster[0].master_flavor_id)
class TestDelete(api_base.FunctionalTest):
def setUp(self):

View File

@ -39,6 +39,7 @@ class TestClusterConductorWithK8s(base.TestCase):
'network_driver': 'network_driver',
'volume_driver': 'volume_driver',
'docker_volume_size': 20,
'master_flavor_id': 'flavor_id',
'docker_storage_driver': 'devicemapper',
'cluster_distro': 'fedora-atomic',
'coe': 'kubernetes',
@ -94,6 +95,7 @@ class TestClusterConductorWithK8s(base.TestCase):
'grafana_admin_passwd': 'fake_pwd',
'kube_dashboard_enabled': 'True',
'docker_volume_type': 'lvmdriver-1'},
'master_flavor_id': 'master_flavor_id',
}
self.context.user_name = 'fake_user'
self.context.tenant = 'fake_tenant'
@ -369,6 +371,7 @@ class TestClusterConductorWithK8s(base.TestCase):
'cluster_uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
'discovery_url': 'https://discovery.etcd.io/test',
'docker_volume_size': 20,
'master_flavor': 'master_flavor_id',
'external_network': 'external_network_id',
'flannel_backend': 'vxlan',
'flannel_network_cidr': '10.101.0.0/16',
@ -611,21 +614,6 @@ class TestClusterConductorWithK8s(base.TestCase):
mock_get,
missing_attr='docker_storage_driver')
@patch('requests.get')
@patch('magnum.objects.ClusterTemplate.get_by_uuid')
@patch('magnum.drivers.common.driver.Driver.get_driver')
def test_extract_template_definition_without_master_flavor(
self,
mock_driver,
mock_objects_cluster_template_get_by_uuid,
mock_get):
mock_driver.return_value = k8s_dr.Driver()
self._test_extract_template_definition(
mock_driver,
mock_objects_cluster_template_get_by_uuid,
mock_get,
missing_attr='master_flavor_id')
@patch('requests.get')
@patch('magnum.objects.ClusterTemplate.get_by_uuid')
@patch('magnum.drivers.common.driver.Driver.get_driver')

View File

@ -56,6 +56,7 @@ class TestClusterConductorWithMesos(base.TestCase):
'uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
'cluster_template_id': 'xx-xx-xx-xx',
'keypair': 'keypair_id',
'master_flavor_id': 'master_flavor_id',
'name': 'cluster1',
'stack_id': 'xx-xx-xx-xx',
'api_address': '172.17.2.3',
@ -189,7 +190,8 @@ class TestClusterConductorWithMesos(base.TestCase):
'mesos_slave_isolation': 'docker/runtime,filesystem/linux',
'mesos_slave_executor_env_variables': '{}',
'mesos_slave_work_dir': '/tmp/mesos/slave',
'mesos_slave_image_providers': 'docker'
'mesos_slave_image_providers': 'docker',
'master_flavor': 'master_flavor_id',
}
self.assertEqual(expected, definition)
self.assertEqual(

View File

@ -63,6 +63,7 @@ class TestClusterConductorWithSwarm(base.TestCase):
'cluster_template_id': 'xx-xx-xx-xx',
'keypair': 'keypair_id',
'docker_volume_size': 20,
'master_flavor_id': 'master_flavor_id',
'name': 'cluster1',
'stack_id': 'xx-xx-xx-xx',
'api_address': '172.17.2.3',
@ -304,6 +305,7 @@ class TestClusterConductorWithSwarm(base.TestCase):
'rexray_preempt': 'False',
'docker_volume_type': 'lvmdriver-1',
'docker_volume_size': 20,
'master_flavor': 'master_flavor_id',
}
self.assertEqual(expected, definition)
self.assertEqual(

View File

@ -98,6 +98,7 @@ def get_test_cluster(**kw):
'updated_at': kw.get('updated_at'),
'docker_volume_size': kw.get('docker_volume_size'),
'labels': kw.get('labels'),
'master_flavor_id': kw.get('master_flavor_id', None),
}
# Only add Keystone trusts related attributes on demand since they may

View File

@ -355,7 +355,7 @@ class TestObject(test_base.TestCase, _TestObject):
# For more information on object version testing, read
# http://docs.openstack.org/developer/magnum/objects.html
object_data = {
'Cluster': '1.15-a8ed124644a6a53be1789f44578863f2',
'Cluster': '1.16-7a544c5059697c464810470980f81ba1',
'ClusterTemplate': '1.17-f1ce5212b46506360b41ab5cb7658af4',
'Certificate': '1.1-1924dc077daa844f0f9076332ef96815',
'MyObj': '1.0-34c4b1aadefd177b13f9a2f894cc23cd',