def _flavor_extra_specs_add(context, flavor_id, specs, max_retries=10): writer = db_api.api_context_manager.writer for attempt in range(max_retries): try: spec_refs = context.session.query( api_models.FlavorExtraSpecs).\ filter_by(flavor_id=flavor_id).\ filter(api_models.FlavorExtraSpecs.key.in_( specs.keys())).\ all() existing_keys = set() for spec_ref in spec_refs: key = spec_ref["key"] existing_keys.add(key) with writer.savepoint.using(context): spec_ref.update({"value": specs[key]}) for key, value in specs.items(): if key in existing_keys: continue spec_ref = api_models.FlavorExtraSpecs() with writer.savepoint.using(context): spec_ref.update({"key": key, "value": value, "flavor_id": flavor_id}) context.session.add(spec_ref) return specs except db_exc.DBDuplicateEntry: # a concurrent transaction has been committed, # try again unless this was the last attempt if attempt == max_retries - 1: raise exception.FlavorExtraSpecUpdateCreateFailed( id=flavor_id, retries=max_retries)
def test_create_flavor_db_duplicate(self): body = {'extra_specs': {'hw:numa_nodes': '1'}} req = self._get_request('1/os-extra_specs', use_admin_context=True) with mock.patch( 'nova.objects.Flavor.save', side_effect=exception.FlavorExtraSpecUpdateCreateFailed( id='', retries=10)): self.assertRaises(webob.exc.HTTPConflict, self.controller.create, req, 1, body=body)
def test_update_flavor_db_duplicate(self): body = {'hw:cpu_policy': 'shared'} req = self._get_request('1/os-extra_specs/hw:cpu_policy', use_admin_context=True) with mock.patch( 'nova.objects.Flavor.save', side_effect=exception.FlavorExtraSpecUpdateCreateFailed( id=1, retries=5)): self.assertRaises(webob.exc.HTTPConflict, self.controller.update, req, 1, 'hw:cpu_policy', body=body)
def fake_instance_type_extra_specs_update_or_create(*args, **kwargs): raise exception.FlavorExtraSpecUpdateCreateFailed(id=1, retries=5)