def test_create(self, mock_ensure_cache): rp = resource_provider.ResourceProvider(context=self.context, uuid=_RESOURCE_PROVIDER_UUID, name=_RESOURCE_PROVIDER_NAME) rp.create() inv = resource_provider.Inventory(context=self.context, resource_provider=rp, resource_class=_RESOURCE_CLASS_NAME, total=16, reserved=2, min_unit=1, max_unit=8, step_size=1, allocation_ratio=1.0) inv_list = resource_provider.InventoryList(context=self.context, objects=[inv]) rp.set_inventory(inv_list) obj = resource_provider.Allocation(context=self.context, resource_provider=rp, resource_class=_RESOURCE_CLASS_NAME, consumer_id=uuids.fake_instance, used=8) alloc_list = resource_provider.AllocationList(self.context, objects=[obj]) self.assertNotIn("id", obj) alloc_list.create_all() self.assertIn("id", obj)
def test_create_with_id_fails(self): rp = resource_provider.ResourceProvider(context=self.context, uuid=_RESOURCE_PROVIDER_UUID, name=_RESOURCE_PROVIDER_NAME) rp.create() inv = resource_provider.Inventory(context=self.context, resource_provider=rp, resource_class=_RESOURCE_CLASS_NAME, total=16, reserved=2, min_unit=1, max_unit=8, step_size=1, allocation_ratio=1.0) inv_list = resource_provider.InventoryList(context=self.context, objects=[inv]) rp.set_inventory(inv_list) obj = resource_provider.Allocation(context=self.context, id=99, resource_provider=rp, resource_class=_RESOURCE_CLASS_NAME, consumer_id=uuids.fake_instance, used=8) alloc_list = resource_provider.AllocationList(self.context, objects=[obj]) self.assertRaises(exception.ObjectActionError, alloc_list.create_all)
def _set_allocations(req, schema): context = req.environ['placement.context'] consumer_uuid = util.wsgi_path_item(req.environ, 'consumer_uuid') data = util.extract_json(req.body, schema) allocation_data = data['allocations'] # If the body includes an allocation for a resource provider # that does not exist, raise a 400. allocation_objects = [] for allocation in allocation_data: resource_provider_uuid = allocation['resource_provider']['uuid'] try: resource_provider = rp_obj.ResourceProvider.get_by_uuid( context, resource_provider_uuid) except exception.NotFound: raise webob.exc.HTTPBadRequest( _("Allocation for resource provider '%(rp_uuid)s' " "that does not exist.") % {'rp_uuid': resource_provider_uuid}) resources = allocation['resources'] for resource_class in resources: allocation = rp_obj.Allocation(resource_provider=resource_provider, consumer_id=consumer_uuid, resource_class=resource_class, used=resources[resource_class]) allocation_objects.append(allocation) allocations = rp_obj.AllocationList( context, objects=allocation_objects, project_id=data.get('project_id'), user_id=data.get('user_id'), ) try: allocations.create_all() LOG.debug("Successfully wrote allocations %s", allocations) # InvalidInventory is a parent for several exceptions that # indicate either that Inventory is not present, or that # capacity limits have been exceeded. except exception.NotFound as exc: raise webob.exc.HTTPBadRequest( _("Unable to allocate inventory for resource provider " "%(rp_uuid)s: %(error)s") % { 'rp_uuid': resource_provider_uuid, 'error': exc }) except exception.InvalidInventory as exc: raise webob.exc.HTTPConflict( _('Unable to allocate inventory: %(error)s') % {'error': exc}) except exception.ConcurrentUpdateDetected as exc: raise webob.exc.HTTPConflict( _('Inventory changed while attempting to allocate: %(error)s') % {'error': exc}) req.response.status = 204 req.response.content_type = None return req.response
def set_allocations(req): context = req.environ['placement.context'] data = util.extract_json(req.body, schema.POST_ALLOCATIONS_V1_13) # Create a sequence of allocation objects to be used in an # AllocationList.create_all() call, which will mean all the changes # happen within a single transaction and with resource provider # generations check all in one go. allocation_objects = [] for consumer_uuid in data: project_id = data[consumer_uuid]['project_id'] user_id = data[consumer_uuid]['user_id'] allocations = data[consumer_uuid]['allocations'] if allocations: for resource_provider_uuid in allocations: resources = allocations[resource_provider_uuid]['resources'] new_allocations = _new_allocations(context, resource_provider_uuid, consumer_uuid, resources, project_id, user_id) allocation_objects.extend(new_allocations) else: # The allocations are empty, which means wipe them out. # Internal to the allocation object this is signalled by a # used value of 0. allocations = rp_obj.AllocationList.get_all_by_consumer_id( context, consumer_uuid) for allocation in allocations: allocation.used = 0 allocation_objects.append(allocation) allocations = rp_obj.AllocationList( context, objects=allocation_objects) try: allocations.create_all() LOG.debug("Successfully wrote allocations %s", allocations) except exception.NotFound as exc: raise webob.exc.HTTPBadRequest( _("Unable to allocate inventory %(error)s") % {'error': exc}) except exception.InvalidInventory as exc: # InvalidInventory is a parent for several exceptions that # indicate either that Inventory is not present, or that # capacity limits have been exceeded. raise webob.exc.HTTPConflict( _('Unable to allocate inventory: %(error)s') % {'error': exc}) except exception.ConcurrentUpdateDetected as exc: raise webob.exc.HTTPConflict( _('Inventory changed while attempting to allocate: %(error)s') % {'error': exc}) req.response.status = 204 req.response.content_type = None return req.response
def _allocate_from_provider(rp, rc, used): # NOTE(efried): Always use a random consumer UUID - we don't want to # override any existing allocations from the test case. rp_obj.AllocationList( rp._context, objects=[ rp_obj.Allocation( rp._context, resource_provider=rp, resource_class=rc, consumer_id=uuidutils.generate_uuid(), used=used)] ).create_all()
def _set_allocations_for_consumer(req, schema): context = req.environ['placement.context'] consumer_uuid = util.wsgi_path_item(req.environ, 'consumer_uuid') data = util.extract_json(req.body, schema) allocation_data = data['allocations'] # Normalize allocation data to dict. want_version = req.environ[microversion.MICROVERSION_ENVIRON] if not want_version.matches((1, 12)): allocations_dict = {} # Allocation are list-ish, transform to dict-ish for allocation in allocation_data: resource_provider_uuid = allocation['resource_provider']['uuid'] allocations_dict[resource_provider_uuid] = { 'resources': allocation['resources'] } allocation_data = allocations_dict # If the body includes an allocation for a resource provider # that does not exist, raise a 400. allocation_objects = [] for resource_provider_uuid, allocation in allocation_data.items(): new_allocations = _new_allocations(context, resource_provider_uuid, consumer_uuid, allocation['resources'], data.get('project_id'), data.get('user_id')) allocation_objects.extend(new_allocations) allocations = rp_obj.AllocationList( context, objects=allocation_objects) try: allocations.create_all() LOG.debug("Successfully wrote allocations %s", allocations) # InvalidInventory is a parent for several exceptions that # indicate either that Inventory is not present, or that # capacity limits have been exceeded. except exception.NotFound as exc: raise webob.exc.HTTPBadRequest( _("Unable to allocate inventory for consumer " "%(consumer_uuid)s: %(error)s") % {'consumer_uuid': consumer_uuid, 'error': exc}) except exception.InvalidInventory as exc: raise webob.exc.HTTPConflict( _('Unable to allocate inventory: %(error)s') % {'error': exc}) except exception.ConcurrentUpdateDetected as exc: raise webob.exc.HTTPConflict( _('Inventory changed while attempting to allocate: %(error)s') % {'error': exc}) req.response.status = 204 req.response.content_type = None return req.response
def start_fixture(self): super(AllocationFixture, self).start_fixture() self.context = context.get_admin_context() # For use creating and querying allocations/usages os.environ['ALT_USER_ID'] = uuidutils.generate_uuid() project_id = os.environ['PROJECT_ID'] user_id = os.environ['USER_ID'] alt_user_id = os.environ['ALT_USER_ID'] # Stealing from the super rp_name = os.environ['RP_NAME'] rp_uuid = os.environ['RP_UUID'] rp = rp_obj.ResourceProvider( self.context, name=rp_name, uuid=rp_uuid) rp.create() # Create some DISK_GB inventory and allocations. consumer_id = uuidutils.generate_uuid() inventory = rp_obj.Inventory( self.context, resource_provider=rp, resource_class='DISK_GB', total=2048, step_size=10, min_unit=10, max_unit=600) inventory.obj_set_defaults() rp.add_inventory(inventory) alloc1 = rp_obj.Allocation( self.context, resource_provider=rp, resource_class='DISK_GB', consumer_id=consumer_id, project_id=project_id, user_id=user_id, used=500) alloc2 = rp_obj.Allocation( self.context, resource_provider=rp, resource_class='DISK_GB', consumer_id=consumer_id, project_id=project_id, user_id=user_id, used=500) alloc_list = rp_obj.AllocationList( self.context, objects=[alloc1, alloc2] ) alloc_list.create_all() # Create some VCPU inventory and allocations. consumer_id = uuidutils.generate_uuid() os.environ['CONSUMER_ID'] = consumer_id inventory = rp_obj.Inventory( self.context, resource_provider=rp, resource_class='VCPU', total=10, max_unit=4) inventory.obj_set_defaults() rp.add_inventory(inventory) alloc1 = rp_obj.Allocation( self.context, resource_provider=rp, resource_class='VCPU', consumer_id=consumer_id, project_id=project_id, user_id=user_id, used=2) alloc2 = rp_obj.Allocation( self.context, resource_provider=rp, resource_class='VCPU', consumer_id=consumer_id, project_id=project_id, user_id=user_id, used=4) alloc_list = rp_obj.AllocationList( self.context, objects=[alloc1, alloc2]) alloc_list.create_all() # Create a couple of allocations for a different user. consumer_id = uuidutils.generate_uuid() alloc1 = rp_obj.Allocation( self.context, resource_provider=rp, resource_class='DISK_GB', consumer_id=consumer_id, project_id=project_id, user_id=alt_user_id, used=20) alloc2 = rp_obj.Allocation( self.context, resource_provider=rp, resource_class='VCPU', consumer_id=consumer_id, project_id=project_id, user_id=alt_user_id, used=1) alloc_list = rp_obj.AllocationList( self.context, objects=[alloc1, alloc2]) alloc_list.create_all() # The ALT_RP_XXX variables are for a resource provider that has # not been created in the Allocation fixture os.environ['ALT_RP_UUID'] = uuidutils.generate_uuid() os.environ['ALT_RP_NAME'] = uuidutils.generate_uuid()