Browse Source

Allow update baymodel's public field even if referenced

Allow update baymodel's public field to be True even if referenced by bays,
User case is one operator wants to share this baymodel to others but doesn't
want to delete the referenced bay.

Please note we only allow to update public to be True case. In case of
True->False, this may lead bays lost baymodel, so don't do this.

Closes-Bug: #1557943
Change-Id: Ia08a2e9611de3559c5cec4eee832bade1f9af09e
changes/29/293329/6
Eli Qiao 6 years ago
parent
commit
c82da08946
  1. 16
      magnum/db/sqlalchemy/api.py
  2. 22
      magnum/tests/unit/api/controllers/v1/test_baymodel.py

16
magnum/db/sqlalchemy/api.py

@ -325,12 +325,18 @@ class Connection(api.Connection):
except NoResultFound:
raise exception.BayModelNotFound(baymodel=baymodel_name)
def is_baymodel_referenced(self, session, baymodel_uuid):
def _is_baymodel_referenced(self, session, baymodel_uuid):
"""Checks whether the baymodel is referenced by bay(s)."""
query = model_query(models.Bay, session=session)
query = self._add_bays_filters(query, {'baymodel_id': baymodel_uuid})
return query.count() != 0
def _is_publishing_baymodel(self, values):
if (len(values) == 1 and
'public' in values and values['public'] is True):
return True
return False
def destroy_baymodel(self, baymodel_id):
session = get_session()
with session.begin():
@ -342,7 +348,7 @@ class Connection(api.Connection):
except NoResultFound:
raise exception.BayModelNotFound(baymodel=baymodel_id)
if self.is_baymodel_referenced(session, baymodel_ref['uuid']):
if self._is_baymodel_referenced(session, baymodel_ref['uuid']):
raise exception.BayModelReferenced(baymodel=baymodel_id)
query.delete()
@ -365,8 +371,10 @@ class Connection(api.Connection):
except NoResultFound:
raise exception.BayModelNotFound(baymodel=baymodel_id)
if self.is_baymodel_referenced(session, ref['uuid']):
raise exception.BayModelReferenced(baymodel=baymodel_id)
if self._is_baymodel_referenced(session, ref['uuid']):
# we only allow to update baymodel to be public
if not self._is_publishing_baymodel(values):
raise exception.BayModelReferenced(baymodel=baymodel_id)
ref.update(values)
return ref

22
magnum/tests/unit/api/controllers/v1/test_baymodel.py

@ -259,6 +259,28 @@ class TestPatch(api_base.FunctionalTest):
[{'path': '/public', 'value': True,
'op': 'replace'}])
def test_update_baymodel_with_bay_allow_update(self):
baymodel = obj_utils.create_test_baymodel(self.context)
obj_utils.create_test_bay(self.context, baymodel_id=baymodel.uuid)
response = self.patch_json('/baymodels/%s' % baymodel.uuid,
[{'path': '/public',
'value': True,
'op': 'replace'}],
expect_errors=True)
self.assertEqual(200, response.status_int)
response = self.get_json('/baymodels/%s' % self.baymodel.uuid)
self.assertEqual(response['public'], True)
def test_update_baymodel_with_bay_not_allow_update(self):
baymodel = obj_utils.create_test_baymodel(self.context)
obj_utils.create_test_bay(self.context, baymodel_id=baymodel.uuid)
response = self.patch_json('/baymodels/%s' % baymodel.uuid,
[{'path': '/name',
'value': 'new_name',
'op': 'replace'}],
expect_errors=True)
self.assertEqual(400, response.status_code)
@mock.patch('oslo_utils.timeutils.utcnow')
def test_replace_singular(self, mock_utcnow):
name = 'bay_model_example_B'

Loading…
Cancel
Save