Add feature to specify driver explicitly
Allow ClusterTemplate to explicitly specify a driver to use for creating Clusters. This is initially sourced from the image property 'magnum_driver', but may be improved to be specified via client in the future. Falls back to old driver discovery using (coe, server_type, os) tuple to keep existing behaviour. Change-Id: I9e206b589951a02360d3cef0282a9538236ef53b
This commit is contained in:
parent
c2567f202a
commit
8a30ad3462
@ -158,6 +158,9 @@ class ClusterTemplate(base.APIBase):
|
||||
tags = wtypes.StringType(min_length=0, max_length=255)
|
||||
"""A comma separated list of tags."""
|
||||
|
||||
driver = wtypes.StringType(min_length=0, max_length=255)
|
||||
"""Driver name set explicitly"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.fields = []
|
||||
for field in objects.ClusterTemplate.fields:
|
||||
@ -413,6 +416,9 @@ class ClusterTemplatesController(base.Controller):
|
||||
cluster_template_dict['cluster_distro'] = image_data['os_distro']
|
||||
cluster_template_dict['project_id'] = context.project_id
|
||||
cluster_template_dict['user_id'] = context.user_id
|
||||
# NOTE(jake): read driver from image for now, update client to provide
|
||||
# this as param in the future
|
||||
cluster_template_dict['driver'] = image_data.get('magnum_driver')
|
||||
# check permissions for making cluster_template public or hidden
|
||||
if cluster_template_dict['public'] or cluster_template_dict['hidden']:
|
||||
if not policy.enforce(context, "clustertemplate:publish", None,
|
||||
|
@ -68,7 +68,8 @@ def enforce_driver_supported():
|
||||
def wrapper(func, *args, **kwargs):
|
||||
cluster_template = args[1]
|
||||
cluster_distro = cluster_template.cluster_distro
|
||||
if not cluster_distro:
|
||||
driver_name = cluster_template.driver
|
||||
if not cluster_distro or not driver_name:
|
||||
try:
|
||||
cli = clients.OpenStackClients(pecan.request.context)
|
||||
image_id = cluster_template.image_id
|
||||
@ -76,11 +77,13 @@ def enforce_driver_supported():
|
||||
image_id,
|
||||
'images')
|
||||
cluster_distro = image.get('os_distro')
|
||||
driver_name = image.get('magnum_driver')
|
||||
except Exception:
|
||||
pass
|
||||
cluster_type = (cluster_template.server_type,
|
||||
cluster_distro,
|
||||
cluster_template.coe)
|
||||
cluster_template.coe,
|
||||
driver_name)
|
||||
driver.Driver.get_driver(*cluster_type)
|
||||
return func(*args, **kwargs)
|
||||
|
||||
|
@ -267,6 +267,10 @@ class ClusterTypeNotSupported(NotSupported):
|
||||
" not supported.")
|
||||
|
||||
|
||||
class ClusterDriverNotSupported(NotSupported):
|
||||
message = _("Cluster driver (%(driver_name)s) not supported.")
|
||||
|
||||
|
||||
class RequiredParameterNotProvided(Invalid):
|
||||
message = _("Required parameter %(heat_param)s not provided.")
|
||||
|
||||
|
@ -146,7 +146,8 @@ class Handler(object):
|
||||
ct = conductor_utils.retrieve_cluster_template(context, cluster)
|
||||
cluster_driver = driver.Driver.get_driver(ct.server_type,
|
||||
ct.cluster_distro,
|
||||
ct.coe)
|
||||
ct.coe,
|
||||
ct.driver)
|
||||
# Update cluster
|
||||
try:
|
||||
conductor_utils.notify_about_cluster_operation(
|
||||
@ -182,7 +183,8 @@ class Handler(object):
|
||||
ct = conductor_utils.retrieve_cluster_template(context, cluster)
|
||||
cluster_driver = driver.Driver.get_driver(ct.server_type,
|
||||
ct.cluster_distro,
|
||||
ct.coe)
|
||||
ct.coe,
|
||||
ct.driver)
|
||||
try:
|
||||
conductor_utils.notify_about_cluster_operation(
|
||||
context, taxonomy.ACTION_DELETE, taxonomy.OUTCOME_PENDING,
|
||||
@ -263,7 +265,8 @@ class Handler(object):
|
||||
ct = conductor_utils.retrieve_cluster_template(context, cluster)
|
||||
cluster_driver = driver.Driver.get_driver(ct.server_type,
|
||||
ct.cluster_distro,
|
||||
ct.coe)
|
||||
ct.coe,
|
||||
ct.driver)
|
||||
# Backup the old node count so that we can restore it
|
||||
# in case of an exception.
|
||||
old_node_count = nodegroup.node_count
|
||||
@ -327,7 +330,8 @@ class Handler(object):
|
||||
ct = conductor_utils.retrieve_cluster_template(context, cluster)
|
||||
cluster_driver = driver.Driver.get_driver(ct.server_type,
|
||||
ct.cluster_distro,
|
||||
ct.coe)
|
||||
ct.coe,
|
||||
ct.driver)
|
||||
|
||||
# Upgrade cluster
|
||||
try:
|
||||
|
@ -0,0 +1,34 @@
|
||||
#
|
||||
# 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 driver to cluster_template
|
||||
|
||||
Revision ID: c0f832afc4fd
|
||||
Revises: 7da8489d6a68
|
||||
Create Date: 2024-01-29 13:18:15.181043
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'c0f832afc4fd'
|
||||
down_revision = '7da8489d6a68'
|
||||
|
||||
from alembic import op # noqa: E402
|
||||
import sqlalchemy as sa # noqa: E402
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.add_column('cluster_template',
|
||||
sa.Column('driver', sa.String(length=255),
|
||||
nullable=True))
|
||||
# ### end Alembic commands ###
|
@ -191,6 +191,7 @@ class ClusterTemplate(Base):
|
||||
floating_ip_enabled = Column(Boolean, default=True)
|
||||
hidden = Column(Boolean, default=False)
|
||||
tags = Column(String(255))
|
||||
driver = Column(String(255))
|
||||
|
||||
|
||||
class X509KeyPair(Base):
|
||||
|
@ -17,6 +17,7 @@ import abc
|
||||
import importlib_metadata as metadata
|
||||
from oslo_config import cfg
|
||||
from stevedore import driver
|
||||
from stevedore import exception as stevedore_exception
|
||||
|
||||
from magnum.common import exception
|
||||
from magnum.objects import cluster_template
|
||||
@ -84,7 +85,7 @@ class Driver(object, metaclass=abc.ABCMeta):
|
||||
return cls.definitions
|
||||
|
||||
@classmethod
|
||||
def get_driver(cls, server_type, os, coe):
|
||||
def get_driver(cls, server_type, os, coe, driver_name=None):
|
||||
"""Get Driver.
|
||||
|
||||
Returns the Driver class for the provided cluster_type.
|
||||
@ -121,6 +122,16 @@ class Driver(object, metaclass=abc.ABCMeta):
|
||||
definition_map = cls.get_drivers()
|
||||
cluster_type = (server_type, os, coe)
|
||||
|
||||
# if driver_name is specified, use that
|
||||
if driver_name:
|
||||
try:
|
||||
found = driver.DriverManager("magnum.drivers",
|
||||
driver_name).driver()
|
||||
return found
|
||||
except stevedore_exception.NoMatches:
|
||||
raise exception.ClusterDriverNotSupported(
|
||||
driver_name=driver_name)
|
||||
|
||||
if cluster_type not in definition_map:
|
||||
raise exception.ClusterTypeNotSupported(
|
||||
server_type=server_type,
|
||||
@ -137,7 +148,8 @@ class Driver(object, metaclass=abc.ABCMeta):
|
||||
def get_driver_for_cluster(cls, context, cluster):
|
||||
ct = cluster_template.ClusterTemplate.get_by_uuid(
|
||||
context, cluster.cluster_template_id)
|
||||
return cls.get_driver(ct.server_type, ct.cluster_distro, ct.coe)
|
||||
return cls.get_driver(ct.server_type, ct.cluster_distro, ct.coe,
|
||||
ct.driver)
|
||||
|
||||
def update_cluster_status(self, context, cluster, use_admin_ctx=False):
|
||||
"""Update the cluster status based on underlying orchestration
|
||||
|
@ -43,7 +43,8 @@ class ClusterTemplate(base.MagnumPersistentObject, base.MagnumObject,
|
||||
# Version 1.18: DockerStorageDriver is a StringField (was an Enum)
|
||||
# Version 1.19: Added 'hidden' field
|
||||
# Version 1.20: Added 'tags' field
|
||||
VERSION = '1.20'
|
||||
# Version 1.21: Added 'driver' field
|
||||
VERSION = '1.21'
|
||||
|
||||
dbapi = dbapi.get_instance()
|
||||
|
||||
@ -81,6 +82,7 @@ class ClusterTemplate(base.MagnumPersistentObject, base.MagnumObject,
|
||||
'floating_ip_enabled': fields.BooleanField(default=True),
|
||||
'hidden': fields.BooleanField(default=False),
|
||||
'tags': fields.StringField(nullable=True),
|
||||
'driver': fields.StringField(nullable=True),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
|
@ -1177,6 +1177,18 @@ class TestPost(api_base.FunctionalTest):
|
||||
response.json['created_at']).replace(tzinfo=None)
|
||||
self.assertEqual(test_time, return_created_at)
|
||||
|
||||
@mock.patch('magnum.api.attr_validator.validate_image')
|
||||
def test_create_cluster_template_with_driver_name(self, mock_image_data):
|
||||
mock_image = {'name': 'mock_name',
|
||||
'os_distro': 'fedora-atomic',
|
||||
'magnum_driver': 'mock_driver'}
|
||||
mock_image_data.return_value = mock_image
|
||||
bdict = apiutils.cluster_template_post_data()
|
||||
resp = self.post_json('/clustertemplates', bdict)
|
||||
self.assertEqual(201, resp.status_int)
|
||||
self.assertEqual(resp.json['driver'],
|
||||
mock_image.get('magnum_driver'))
|
||||
|
||||
|
||||
class TestDelete(api_base.FunctionalTest):
|
||||
|
||||
|
@ -58,6 +58,7 @@ def get_test_cluster_template(**kw):
|
||||
'floating_ip_enabled': kw.get('floating_ip_enabled', True),
|
||||
'hidden': kw.get('hidden', False),
|
||||
'tags': kw.get('tags', ""),
|
||||
'driver': kw.get('driver', ""),
|
||||
}
|
||||
|
||||
|
||||
|
@ -356,7 +356,7 @@ class TestObject(test_base.TestCase, _TestObject):
|
||||
# https://docs.openstack.org/magnum/latest/contributor/objects.html
|
||||
object_data = {
|
||||
'Cluster': '1.23-dfaf9ecb65a5fcab4f6c36497a8bc866',
|
||||
'ClusterTemplate': '1.20-a9334881d1dc6e077faec68214fa9d1d',
|
||||
'ClusterTemplate': '1.21-2d23d472f415b5e7571603a8689898e3',
|
||||
'Certificate': '1.2-64f24db0e10ad4cbd72aea21d2075a80',
|
||||
'MyObj': '1.0-34c4b1aadefd177b13f9a2f894cc23cd',
|
||||
'X509KeyPair': '1.2-d81950af36c59a71365e33ce539d24f9',
|
||||
|
@ -0,0 +1,14 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Add a feature to prevent drivers clashing when multiple drivers are able to
|
||||
provide the same functionality.
|
||||
|
||||
Drivers used to be selected based on a tuple of (server_type, os, coe). This
|
||||
can be a problem if multiple drivers provides the same functionality, e.g. a
|
||||
tuple like (vm, ubuntu, kubernetes).
|
||||
|
||||
To allow for this, it is now possible to explicitly specify a driver name,
|
||||
instead of relying on the lookup. The driver name is the same as the
|
||||
entrypoint name, and can be specified by a Cluster Template through the
|
||||
Glance image property "magnum_driver".
|
Loading…
Reference in New Issue
Block a user