Drop implementation for OS::Magnum::Bay/BayModel

Magnum has deprecated it's Bay API and BayModel API a long ago and
these resource types were deprecated and are hidden in Heat now.

Magnum has removed the old API during Zed cycle and the resources are
no longer supported, so we should remove the implementation now.

Change-Id: If4c6a83a83f9eb29407eb632f47c7229b5492ffd
This commit is contained in:
Takashi Kajinami 2022-09-21 14:58:09 +09:00
parent 1b42c7296a
commit 87bdbfdcab
5 changed files with 2 additions and 322 deletions

View File

@ -57,10 +57,6 @@ class MagnumClientPlugin(client_plugin.ClientPlugin):
raise exception.EntityNotFound(entity=entity_msg, raise exception.EntityNotFound(entity=entity_msg,
name=value) name=value)
def get_baymodel(self, value):
return self._get_rsrc_name_or_id(value, entity='baymodels',
entity_msg='BayModel')
def get_cluster_template(self, value): def get_cluster_template(self, value):
return self._get_rsrc_name_or_id(value, entity='cluster_templates', return self._get_rsrc_name_or_id(value, entity='cluster_templates',
entity_msg='ClusterTemplate') entity_msg='ClusterTemplate')
@ -70,9 +66,3 @@ class ClusterTemplateConstraint(constraints.BaseCustomConstraint):
resource_client_name = CLIENT_NAME resource_client_name = CLIENT_NAME
resource_getter_name = 'get_cluster_template' resource_getter_name = 'get_cluster_template'
class BaymodelConstraint(constraints.BaseCustomConstraint):
resource_client_name = CLIENT_NAME
resource_getter_name = 'get_baymodel'

View File

@ -11,15 +11,12 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from heat.common import exception
from heat.common.i18n import _ from heat.common.i18n import _
from heat.engine import constraints from heat.engine.resources.openstack.heat import none_resource
from heat.engine import properties
from heat.engine import resource
from heat.engine import support from heat.engine import support
class Bay(resource.Resource): class Bay(none_resource.NoneResource):
"""A resource that creates a Magnum Bay. """A resource that creates a Magnum Bay.
This resource has been deprecated in favor of OS::Magnum::Cluster. This resource has been deprecated in favor of OS::Magnum::Cluster.
@ -40,136 +37,6 @@ class Bay(resource.Resource):
) )
) )
PROPERTIES = (
NAME, BAYMODEL, NODE_COUNT, MASTER_COUNT, DISCOVERY_URL,
BAY_CREATE_TIMEOUT
) = (
'name', 'baymodel', 'node_count', 'master_count',
'discovery_url', 'bay_create_timeout'
)
properties_schema = {
NAME: properties.Schema(
properties.Schema.STRING,
_('The bay name.')
),
BAYMODEL: properties.Schema(
properties.Schema.STRING,
_('The name or ID of the bay model.'),
constraints=[
constraints.CustomConstraint('magnum.baymodel')
],
required=True
),
NODE_COUNT: properties.Schema(
properties.Schema.INTEGER,
_('The node count for this bay.'),
constraints=[constraints.Range(min=1)],
update_allowed=True,
default=1
),
MASTER_COUNT: properties.Schema(
properties.Schema.INTEGER,
_('The number of master nodes for this bay.'),
constraints=[constraints.Range(min=1)],
update_allowed=True,
default=1
),
DISCOVERY_URL: properties.Schema(
properties.Schema.STRING,
_('Specifies a custom discovery url for node discovery.')
),
BAY_CREATE_TIMEOUT: properties.Schema(
properties.Schema.INTEGER,
_('Timeout for creating the bay in minutes. '
'Set to 0 for no timeout.'),
constraints=[constraints.Range(min=0)],
default=0
)
}
default_client_name = 'magnum'
entity = 'bays'
def handle_create(self):
args = {
'name': self.properties[self.NAME],
'baymodel_id': self.properties[self.BAYMODEL],
'node_count': self.properties[self.NODE_COUNT],
'master_count': self.properties[self.NODE_COUNT],
'discovery_url': self.properties[self.DISCOVERY_URL],
'bay_create_timeout': self.properties[self.BAY_CREATE_TIMEOUT]
}
bay = self.client().bays.create(**args)
self.resource_id_set(bay.uuid)
return bay.uuid
def check_create_complete(self, id):
bay = self.client().bays.get(id)
if bay.status == 'CREATE_IN_PROGRESS':
return False
elif bay.status is None:
return False
elif bay.status == 'CREATE_COMPLETE':
return True
elif bay.status == 'CREATE_FAILED':
msg = (_("Failed to create Bay '%(name)s' - %(reason)s")
% {'name': self.name, 'reason': bay.status_reason})
raise exception.ResourceInError(status_reason=msg,
resource_status=bay.status)
else:
msg = (_("Unknown status creating Bay '%(name)s' - %(reason)s")
% {'name': self.name, 'reason': bay.status_reason})
raise exception.ResourceUnknownStatus(status_reason=msg,
resource_status=bay.status)
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
if prop_diff:
patch = [{'op': 'replace', 'path': '/' + k, 'value': v}
for k, v in prop_diff.items()]
self.client().bays.update(self.resource_id, patch)
return self.resource_id
def parse_live_resource_data(self, resource_properties, resource_data):
record_reality = {}
for key in [self.NODE_COUNT, self.MASTER_COUNT]:
record_reality.update({key: resource_data.get(key)})
return record_reality
def check_update_complete(self, id):
bay = self.client().bays.get(id)
# Check update complete request might get status before the status
# got changed to update in progress, so we allow `CREATE_COMPLETE`
# for it.
if bay.status in ['UPDATE_IN_PROGRESS', 'CREATE_COMPLETE']:
return False
elif bay.status == 'UPDATE_COMPLETE':
return True
elif bay.status == 'UPDATE_FAILED':
msg = (_("Failed to update Bay '%(name)s' - %(reason)s")
% {'name': self.name, 'reason': bay.status_reason})
raise exception.ResourceInError(status_reason=msg,
resource_status=bay.status)
else:
msg = (_("Unknown status updating Bay '%(name)s' - %(reason)s")
% {'name': self.name, 'reason': bay.status_reason})
raise exception.ResourceUnknownStatus(status_reason=msg,
resource_status=bay.status)
def check_delete_complete(self, id):
if not id:
return True
try:
self.client().bays.get(id)
except Exception as exc:
self.client_plugin().ignore_not_found(exc)
return True
return False
def resource_mapping(): def resource_mapping():
return { return {

View File

@ -56,22 +56,3 @@ class ClusterTemplateConstraintTest(common.HeatTestCase):
self.mock_cluster_template_get.side_effect = mc_exc.NotFound() self.mock_cluster_template_get.side_effect = mc_exc.NotFound()
self.assertFalse(self.constraint.validate( self.assertFalse(self.constraint.validate(
"bad_cluster_template", self.ctx)) "bad_cluster_template", self.ctx))
class BaymodelConstraintTest(common.HeatTestCase):
def setUp(self):
super(BaymodelConstraintTest, self).setUp()
self.ctx = utils.dummy_context()
self.mock_baymodel_get = mock.Mock()
self.ctx.clients.client_plugin(
'magnum').client().baymodels.get = self.mock_baymodel_get
self.constraint = mc.BaymodelConstraint()
def test_validate(self):
self.mock_baymodel_get.return_value = fake_cluster_template(
id='badbaymodel')
self.assertTrue(self.constraint.validate("mybaymodel", self.ctx))
def test_validate_fail(self):
self.mock_baymodel_get.side_effect = mc_exc.NotFound()
self.assertFalse(self.constraint.validate("badbaymodel", self.ctx))

View File

@ -1,157 +0,0 @@
#
# 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.
import copy
from unittest import mock
from oslo_config import cfg
from heat.common import exception
from heat.common import template_format
from heat.engine.clients.os import magnum as mc
from heat.engine import resource
from heat.engine.resources.openstack.magnum import bay
from heat.engine import scheduler
from heat.engine import template
from heat.tests import common
from heat.tests import utils
magnum_template = '''
heat_template_version: 2015-04-30
resources:
test_bay:
type: OS::Magnum::Bay
properties:
name: test_bay
baymodel: 123456
node_count: 5
master_count: 1
discovery_url: https://discovery.etcd.io
bay_create_timeout: 15
'''
RESOURCE_TYPE = 'OS::Magnum::Bay'
class TestMagnumBay(common.HeatTestCase):
def setUp(self):
super(TestMagnumBay, self).setUp()
resource._register_class(RESOURCE_TYPE, bay.Bay)
t = template_format.parse(magnum_template)
self.stack = utils.parse_stack(t)
resource_defns = self.stack.t.resource_definitions(self.stack)
self.rsrc_defn = resource_defns['test_bay']
self.client = mock.Mock()
self.patchobject(bay.Bay, 'client', return_value=self.client)
self.patchobject(mc.MagnumClientPlugin, 'get_baymodel')
def _create_resource(self, name, snippet, stack, stat='CREATE_COMPLETE'):
self.resource_id = '12345'
value = mock.MagicMock(uuid=self.resource_id)
self.client.bays.create.return_value = value
get_rv = mock.MagicMock(status=stat)
self.client.bays.get.return_value = get_rv
b = bay.Bay(name, snippet, stack)
return b
def test_bay_create(self):
b = self._create_resource('bay', self.rsrc_defn, self.stack)
scheduler.TaskRunner(b.create)()
self.assertEqual(self.resource_id, b.resource_id)
self.assertEqual((b.CREATE, b.COMPLETE), b.state)
def test_bay_create_failed(self):
cfg.CONF.set_override('action_retry_limit', 0)
b = self._create_resource('bay', self.rsrc_defn, self.stack,
stat='CREATE_FAILED')
exc = self.assertRaises(
exception.ResourceFailure,
scheduler.TaskRunner(b.create))
self.assertIn("Failed to create Bay", str(exc))
def test_bay_create_unknown_status(self):
b = self._create_resource('bay', self.rsrc_defn, self.stack,
stat='CREATE_FOO')
exc = self.assertRaises(
exception.ResourceFailure,
scheduler.TaskRunner(b.create))
self.assertIn("Unknown status creating Bay", str(exc))
def test_bay_update(self):
b = self._create_resource('bay', self.rsrc_defn, self.stack)
scheduler.TaskRunner(b.create)()
status = mock.MagicMock(status='UPDATE_COMPLETE')
self.client.bays.get.return_value = status
t = template_format.parse(magnum_template)
new_t = copy.deepcopy(t)
new_t['resources']['test_bay']['properties']['node_count'] = 10
rsrc_defns = template.Template(new_t).resource_definitions(self.stack)
new_bm = rsrc_defns['test_bay']
scheduler.TaskRunner(b.update, new_bm)()
self.assertEqual((b.UPDATE, b.COMPLETE), b.state)
def test_bay_update_failed(self):
b = self._create_resource('bay', self.rsrc_defn, self.stack)
scheduler.TaskRunner(b.create)()
status = mock.MagicMock(status='UPDATE_FAILED')
self.client.bays.get.return_value = status
t = template_format.parse(magnum_template)
new_t = copy.deepcopy(t)
new_t['resources']['test_bay']['properties']['node_count'] = 10
rsrc_defns = template.Template(new_t).resource_definitions(self.stack)
new_bm = rsrc_defns['test_bay']
exc = self.assertRaises(
exception.ResourceFailure,
scheduler.TaskRunner(b.update, new_bm))
self.assertIn("Failed to update Bay", str(exc))
def test_bay_update_unknown_status(self):
b = self._create_resource('bay', self.rsrc_defn, self.stack)
scheduler.TaskRunner(b.create)()
status = mock.MagicMock(status='UPDATE_BAR')
self.client.bays.get.return_value = status
t = template_format.parse(magnum_template)
new_t = copy.deepcopy(t)
new_t['resources']['test_bay']['properties']['node_count'] = 10
rsrc_defns = template.Template(new_t).resource_definitions(self.stack)
new_bm = rsrc_defns['test_bay']
exc = self.assertRaises(
exception.ResourceFailure,
scheduler.TaskRunner(b.update, new_bm))
self.assertIn("Unknown status updating Bay", str(exc))
def test_bay_delete(self):
b = self._create_resource('bay', self.rsrc_defn, self.stack)
scheduler.TaskRunner(b.create)()
b.client_plugin = mock.MagicMock()
self.client.bays.get.side_effect = Exception('Not Found')
self.client.get.reset_mock()
scheduler.TaskRunner(b.delete)()
self.assertEqual((b.DELETE, b.COMPLETE), b.state)
self.assertEqual(2, self.client.bays.get.call_count)
def test_bay_get_live_state(self):
b = self._create_resource('bay', self.rsrc_defn, self.stack)
scheduler.TaskRunner(b.create)()
value = mock.MagicMock()
value.to_dict.return_value = {
'name': 'test_bay',
'baymodel': 123456,
'node_count': 5,
'master_count': 1,
'discovery_url': 'https://discovery.etcd.io',
'bay_create_timeout': 15}
self.client.bays.get.return_value = value
reality = b.get_live_state(b.properties)
self.assertEqual({'node_count': 5, 'master_count': 1}, reality)

View File

@ -125,7 +125,6 @@ heat.constraints =
keystone.role = heat.engine.clients.os.keystone.keystone_constraints:KeystoneRoleConstraint keystone.role = heat.engine.clients.os.keystone.keystone_constraints:KeystoneRoleConstraint
keystone.service = heat.engine.clients.os.keystone.keystone_constraints:KeystoneServiceConstraint keystone.service = heat.engine.clients.os.keystone.keystone_constraints:KeystoneServiceConstraint
keystone.user = heat.engine.clients.os.keystone.keystone_constraints:KeystoneUserConstraint keystone.user = heat.engine.clients.os.keystone.keystone_constraints:KeystoneUserConstraint
magnum.baymodel = heat.engine.clients.os.magnum:BaymodelConstraint
magnum.cluster_template = heat.engine.clients.os.magnum:ClusterTemplateConstraint magnum.cluster_template = heat.engine.clients.os.magnum:ClusterTemplateConstraint
manila.share_network = heat.engine.clients.os.manila:ManilaShareNetworkConstraint manila.share_network = heat.engine.clients.os.manila:ManilaShareNetworkConstraint
manila.share_snapshot = heat.engine.clients.os.manila:ManilaShareSnapshotConstraint manila.share_snapshot = heat.engine.clients.os.manila:ManilaShareSnapshotConstraint