Skip to content

Commit 8a30ad3

Browse files
committed
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
1 parent c2567f2 commit 8a30ad3

File tree

12 files changed

+103
-10
lines changed

12 files changed

+103
-10
lines changed

magnum/api/controllers/v1/cluster_template.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ class ClusterTemplate(base.APIBase):
158158
tags = wtypes.StringType(min_length=0, max_length=255)
159159
"""A comma separated list of tags."""
160160

161+
driver = wtypes.StringType(min_length=0, max_length=255)
162+
"""Driver name set explicitly"""
163+
161164
def __init__(self, **kwargs):
162165
self.fields = []
163166
for field in objects.ClusterTemplate.fields:
@@ -413,6 +416,9 @@ def post(self, cluster_template):
413416
cluster_template_dict['cluster_distro'] = image_data['os_distro']
414417
cluster_template_dict['project_id'] = context.project_id
415418
cluster_template_dict['user_id'] = context.user_id
419+
# NOTE(jake): read driver from image for now, update client to provide
420+
# this as param in the future
421+
cluster_template_dict['driver'] = image_data.get('magnum_driver')
416422
# check permissions for making cluster_template public or hidden
417423
if cluster_template_dict['public'] or cluster_template_dict['hidden']:
418424
if not policy.enforce(context, "clustertemplate:publish", None,

magnum/api/validation.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,22 @@ def enforce_driver_supported():
6868
def wrapper(func, *args, **kwargs):
6969
cluster_template = args[1]
7070
cluster_distro = cluster_template.cluster_distro
71-
if not cluster_distro:
71+
driver_name = cluster_template.driver
72+
if not cluster_distro or not driver_name:
7273
try:
7374
cli = clients.OpenStackClients(pecan.request.context)
7475
image_id = cluster_template.image_id
7576
image = api_utils.get_openstack_resource(cli.glance().images,
7677
image_id,
7778
'images')
7879
cluster_distro = image.get('os_distro')
80+
driver_name = image.get('magnum_driver')
7981
except Exception:
8082
pass
8183
cluster_type = (cluster_template.server_type,
8284
cluster_distro,
83-
cluster_template.coe)
85+
cluster_template.coe,
86+
driver_name)
8487
driver.Driver.get_driver(*cluster_type)
8588
return func(*args, **kwargs)
8689

magnum/common/exception.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,10 @@ class ClusterTypeNotSupported(NotSupported):
267267
" not supported.")
268268

269269

270+
class ClusterDriverNotSupported(NotSupported):
271+
message = _("Cluster driver (%(driver_name)s) not supported.")
272+
273+
270274
class RequiredParameterNotProvided(Invalid):
271275
message = _("Required parameter %(heat_param)s not provided.")
272276

magnum/conductor/handlers/cluster_conductor.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@ def cluster_update(self, context, cluster, node_count,
146146
ct = conductor_utils.retrieve_cluster_template(context, cluster)
147147
cluster_driver = driver.Driver.get_driver(ct.server_type,
148148
ct.cluster_distro,
149-
ct.coe)
149+
ct.coe,
150+
ct.driver)
150151
# Update cluster
151152
try:
152153
conductor_utils.notify_about_cluster_operation(
@@ -182,7 +183,8 @@ def cluster_delete(self, context, uuid):
182183
ct = conductor_utils.retrieve_cluster_template(context, cluster)
183184
cluster_driver = driver.Driver.get_driver(ct.server_type,
184185
ct.cluster_distro,
185-
ct.coe)
186+
ct.coe,
187+
ct.driver)
186188
try:
187189
conductor_utils.notify_about_cluster_operation(
188190
context, taxonomy.ACTION_DELETE, taxonomy.OUTCOME_PENDING,
@@ -263,7 +265,8 @@ def cluster_resize(self, context, cluster,
263265
ct = conductor_utils.retrieve_cluster_template(context, cluster)
264266
cluster_driver = driver.Driver.get_driver(ct.server_type,
265267
ct.cluster_distro,
266-
ct.coe)
268+
ct.coe,
269+
ct.driver)
267270
# Backup the old node count so that we can restore it
268271
# in case of an exception.
269272
old_node_count = nodegroup.node_count
@@ -327,7 +330,8 @@ def cluster_upgrade(self, context, cluster, cluster_template,
327330
ct = conductor_utils.retrieve_cluster_template(context, cluster)
328331
cluster_driver = driver.Driver.get_driver(ct.server_type,
329332
ct.cluster_distro,
330-
ct.coe)
333+
ct.coe,
334+
ct.driver)
331335

332336
# Upgrade cluster
333337
try:
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#
2+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
3+
# not use this file except in compliance with the License. You may obtain
4+
# a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11+
# License for the specific language governing permissions and limitations
12+
# under the License.
13+
14+
"""add driver to cluster_template
15+
16+
Revision ID: c0f832afc4fd
17+
Revises: 7da8489d6a68
18+
Create Date: 2024-01-29 13:18:15.181043
19+
20+
"""
21+
22+
# revision identifiers, used by Alembic.
23+
revision = 'c0f832afc4fd'
24+
down_revision = '7da8489d6a68'
25+
26+
from alembic import op # noqa: E402
27+
import sqlalchemy as sa # noqa: E402
28+
29+
30+
def upgrade():
31+
op.add_column('cluster_template',
32+
sa.Column('driver', sa.String(length=255),
33+
nullable=True))
34+
# ### end Alembic commands ###

magnum/db/sqlalchemy/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ class ClusterTemplate(Base):
191191
floating_ip_enabled = Column(Boolean, default=True)
192192
hidden = Column(Boolean, default=False)
193193
tags = Column(String(255))
194+
driver = Column(String(255))
194195

195196

196197
class X509KeyPair(Base):

magnum/drivers/common/driver.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import importlib_metadata as metadata
1818
from oslo_config import cfg
1919
from stevedore import driver
20+
from stevedore import exception as stevedore_exception
2021

2122
from magnum.common import exception
2223
from magnum.objects import cluster_template
@@ -84,7 +85,7 @@ class Driver2(Driver):
8485
return cls.definitions
8586

8687
@classmethod
87-
def get_driver(cls, server_type, os, coe):
88+
def get_driver(cls, server_type, os, coe, driver_name=None):
8889
"""Get Driver.
8990
9091
Returns the Driver class for the provided cluster_type.
@@ -121,6 +122,16 @@ class Driver2(Driver):
121122
definition_map = cls.get_drivers()
122123
cluster_type = (server_type, os, coe)
123124

125+
# if driver_name is specified, use that
126+
if driver_name:
127+
try:
128+
found = driver.DriverManager("magnum.drivers",
129+
driver_name).driver()
130+
return found
131+
except stevedore_exception.NoMatches:
132+
raise exception.ClusterDriverNotSupported(
133+
driver_name=driver_name)
134+
124135
if cluster_type not in definition_map:
125136
raise exception.ClusterTypeNotSupported(
126137
server_type=server_type,
@@ -137,7 +148,8 @@ class Driver2(Driver):
137148
def get_driver_for_cluster(cls, context, cluster):
138149
ct = cluster_template.ClusterTemplate.get_by_uuid(
139150
context, cluster.cluster_template_id)
140-
return cls.get_driver(ct.server_type, ct.cluster_distro, ct.coe)
151+
return cls.get_driver(ct.server_type, ct.cluster_distro, ct.coe,
152+
ct.driver)
141153

142154
def update_cluster_status(self, context, cluster, use_admin_ctx=False):
143155
"""Update the cluster status based on underlying orchestration

magnum/objects/cluster_template.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ class ClusterTemplate(base.MagnumPersistentObject, base.MagnumObject,
4343
# Version 1.18: DockerStorageDriver is a StringField (was an Enum)
4444
# Version 1.19: Added 'hidden' field
4545
# Version 1.20: Added 'tags' field
46-
VERSION = '1.20'
46+
# Version 1.21: Added 'driver' field
47+
VERSION = '1.21'
4748

4849
dbapi = dbapi.get_instance()
4950

@@ -81,6 +82,7 @@ class ClusterTemplate(base.MagnumPersistentObject, base.MagnumObject,
8182
'floating_ip_enabled': fields.BooleanField(default=True),
8283
'hidden': fields.BooleanField(default=False),
8384
'tags': fields.StringField(nullable=True),
85+
'driver': fields.StringField(nullable=True),
8486
}
8587

8688
@staticmethod

magnum/tests/unit/api/controllers/v1/test_cluster_template.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,6 +1177,18 @@ def test_create_cluster_template_with_multi_dns(self, mock_utcnow,
11771177
response.json['created_at']).replace(tzinfo=None)
11781178
self.assertEqual(test_time, return_created_at)
11791179

1180+
@mock.patch('magnum.api.attr_validator.validate_image')
1181+
def test_create_cluster_template_with_driver_name(self, mock_image_data):
1182+
mock_image = {'name': 'mock_name',
1183+
'os_distro': 'fedora-atomic',
1184+
'magnum_driver': 'mock_driver'}
1185+
mock_image_data.return_value = mock_image
1186+
bdict = apiutils.cluster_template_post_data()
1187+
resp = self.post_json('/clustertemplates', bdict)
1188+
self.assertEqual(201, resp.status_int)
1189+
self.assertEqual(resp.json['driver'],
1190+
mock_image.get('magnum_driver'))
1191+
11801192

11811193
class TestDelete(api_base.FunctionalTest):
11821194

magnum/tests/unit/db/utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ def get_test_cluster_template(**kw):
5858
'floating_ip_enabled': kw.get('floating_ip_enabled', True),
5959
'hidden': kw.get('hidden', False),
6060
'tags': kw.get('tags', ""),
61+
'driver': kw.get('driver', ""),
6162
}
6263

6364

0 commit comments

Comments
 (0)