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
This commit is contained in:
Eli Qiao 2016-03-22 16:25:42 +08:00
parent 0d07b47190
commit c82da08946
2 changed files with 34 additions and 4 deletions

View File

@ -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,7 +371,9 @@ class Connection(api.Connection):
except NoResultFound:
raise exception.BayModelNotFound(baymodel=baymodel_id)
if self.is_baymodel_referenced(session, ref['uuid']):
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)

View File

@ -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'