def _check_create_allocations(self, inventory_kwargs, bad_used, good_used): consumer_uuid = uuidsentinel.consumer rp_class = fields.ResourceClass.DISK_GB rp = self._make_rp_and_inventory(resource_class=rp_class, **inventory_kwargs) # allocation, bad step_size allocation = objects.Allocation(resource_provider=rp, consumer_id=consumer_uuid, resource_class=rp_class, used=bad_used) allocation_list = objects.AllocationList(self.context, objects=[allocation]) self.assertRaises(exception.InvalidAllocationConstraintsViolated, allocation_list.create_all) # correct for step size allocation.used = good_used allocation_list = objects.AllocationList(self.context, objects=[allocation]) allocation_list.create_all() # check usage self._validate_usage(rp, allocation.used)
def start_fixture(self): super(AllocationFixture, self).start_fixture() self.context = context.get_admin_context() # Stealing from the super rp_name = os.environ['RP_NAME'] rp_uuid = os.environ['RP_UUID'] rp = objects.ResourceProvider(self.context, name=rp_name, uuid=rp_uuid) rp.create() # Create some DISK_GB inventory and allocations. inventory = objects.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 = objects.Allocation(self.context, resource_provider=rp, resource_class='DISK_GB', consumer_id=uuidutils.generate_uuid(), used=500) alloc2 = objects.Allocation(self.context, resource_provider=rp, resource_class='DISK_GB', consumer_id=uuidutils.generate_uuid(), used=500) alloc_list = objects.AllocationList(self.context, objects=[alloc1, alloc2]) alloc_list.create_all() # Create some VCPU inventory and allocations. inventory = objects.Inventory(self.context, resource_provider=rp, resource_class='VCPU', total=8, max_unit=4) inventory.obj_set_defaults() rp.add_inventory(inventory) alloc1 = objects.Allocation(self.context, resource_provider=rp, resource_class='VCPU', consumer_id=uuidutils.generate_uuid(), used=2) alloc2 = objects.Allocation(self.context, resource_provider=rp, resource_class='VCPU', consumer_id=uuidutils.generate_uuid(), used=4) alloc_list = objects.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()
def test_create(self, mock_ensure_cache): rp = objects.ResourceProvider(context=self.context, uuid=_RESOURCE_PROVIDER_UUID, name=_RESOURCE_PROVIDER_NAME) rp.create() inv = objects.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.create() obj = objects.Allocation(context=self.context, resource_provider=rp, resource_class=_RESOURCE_CLASS_NAME, consumer_id=uuids.fake_instance, used=8) alloc_list = objects.AllocationList(self.context, objects=[obj]) alloc_list.create_all() rp_al = resource_provider.AllocationList saved_allocations = rp_al.get_all_by_resource_provider_uuid( self.context, rp.uuid) self.assertEqual(1, len(saved_allocations)) self.assertEqual(obj.used, saved_allocations[0].used)
def set_allocations(req): context = req.environ['placement.context'] consumer_uuid = util.wsgi_path_item(req.environ, 'consumer_uuid') data = _extract_allocations(req.body, ALLOCATION_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 = objects.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}, json_formatter=util.json_error_formatter) resources = allocation['resources'] for resource_class in resources: allocation = objects.Allocation( resource_provider=resource_provider, consumer_id=consumer_uuid, resource_class=resource_class, used=resources[resource_class]) allocation_objects.append(allocation) allocations = objects.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 resource provider " "%(rp_uuid)s: %(error)s") % {'rp_uuid': resource_provider_uuid, 'error': exc}) except exception.InvalidInventory as exc: LOG.exception(_LE("Bad inventory")) raise webob.exc.HTTPConflict( _('Unable to allocate inventory: %(error)s') % {'error': exc}, json_formatter=util.json_error_formatter) except exception.ConcurrentUpdateDetected as exc: LOG.exception(_LE("Concurrent Update")) raise webob.exc.HTTPConflict( _('Inventory changed while attempting to allocate: %(error)s') % {'error': exc}, json_formatter=util.json_error_formatter) req.response.status = 204 req.response.content_type = None return req.response
def test_create_with_id_fails(self): rp = objects.ResourceProvider(context=self.context, uuid=_RESOURCE_PROVIDER_UUID, name=_RESOURCE_PROVIDER_NAME) rp.create() inv = objects.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.create() obj = objects.Allocation(context=self.context, id=99, resource_provider=rp, resource_class=_RESOURCE_CLASS_NAME, consumer_id=uuids.fake_instance, used=8) alloc_list = objects.AllocationList(self.context, objects=[obj]) self.assertRaises(exception.ObjectActionError, alloc_list.create_all)
def test_create(self, mock_ensure_cache): rp = objects.ResourceProvider(context=self.context, uuid=_RESOURCE_PROVIDER_UUID, name=_RESOURCE_PROVIDER_NAME) rp.create() inv = objects.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.create() obj = objects.Allocation(context=self.context, resource_provider=rp, resource_class=_RESOURCE_CLASS_NAME, consumer_id=uuids.fake_instance, used=8) alloc_list = objects.AllocationList(self.context, objects=[obj]) self.assertNotIn("id", obj) alloc_list.create_all() self.assertIn("id", obj)
def test_allocation_list_create(self): consumer_uuid = uuidsentinel.consumer # Create two resource providers rp1_name = uuidsentinel.rp1_name rp1_uuid = uuidsentinel.rp1_uuid rp1_class = fields.ResourceClass.DISK_GB rp1_used = 6 rp2_name = uuidsentinel.rp2_name rp2_uuid = uuidsentinel.rp2_uuid rp2_class = fields.ResourceClass.IPV4_ADDRESS rp2_used = 2 rp1 = objects.ResourceProvider( self.context, name=rp1_name, uuid=rp1_uuid) rp1.create() rp2 = objects.ResourceProvider( self.context, name=rp2_name, uuid=rp2_uuid) rp2.create() # Two allocations, one for each resource provider. allocation_1 = objects.Allocation(resource_provider=rp1, consumer_id=consumer_uuid, resource_class=rp1_class, used=rp1_used) allocation_2 = objects.Allocation(resource_provider=rp2, consumer_id=consumer_uuid, resource_class=rp2_class, used=rp2_used) allocation_list = objects.AllocationList( self.context, objects=[allocation_1, allocation_2]) # There's no inventory, we have a failure. self.assertRaises(exception.InvalidInventory, allocation_list.create_all) # Add inventory for one of the two resource providers. This should also # fail, since rp2 has no inventory. inv = objects.Inventory(resource_provider=rp1, resource_class=rp1_class, total=1024) inv.obj_set_defaults() inv_list = objects.InventoryList(objects=[inv]) rp1.set_inventory(inv_list) self.assertRaises(exception.InvalidInventory, allocation_list.create_all) # Add inventory for the second resource provider inv = objects.Inventory(resource_provider=rp2, resource_class=rp2_class, total=255, reserved=2) inv.obj_set_defaults() inv_list = objects.InventoryList(objects=[inv]) rp2.set_inventory(inv_list) # Now the allocations will work. allocation_list.create_all() # Check that those allocations changed usage on each # resource provider. rp1_usage = objects.UsageList.get_all_by_resource_provider_uuid( self.context, rp1_uuid) rp2_usage = objects.UsageList.get_all_by_resource_provider_uuid( self.context, rp2_uuid) self.assertEqual(rp1_used, rp1_usage[0].usage) self.assertEqual(rp2_used, rp2_usage[0].usage) # redo one allocation # TODO(cdent): This does not currently behave as expected # because a new allocataion is created, adding to the total # used, not replacing. rp1_used += 1 allocation_1 = objects.Allocation(resource_provider=rp1, consumer_id=consumer_uuid, resource_class=rp1_class, used=rp1_used) allocation_list = objects.AllocationList( self.context, objects=[allocation_1]) allocation_list.create_all() rp1_usage = objects.UsageList.get_all_by_resource_provider_uuid( self.context, rp1_uuid) self.assertEqual(rp1_used, rp1_usage[0].usage) # delete the allocations for the consumer # NOTE(cdent): The database uses 'consumer_id' for the # column, presumably because some ids might not be uuids, at # some point in the future. consumer_allocations = objects.AllocationList.get_all_by_consumer_id( self.context, consumer_uuid) consumer_allocations.delete_all() rp1_usage = objects.UsageList.get_all_by_resource_provider_uuid( self.context, rp1_uuid) rp2_usage = objects.UsageList.get_all_by_resource_provider_uuid( self.context, rp2_uuid) self.assertEqual(0, rp1_usage[0].usage) self.assertEqual(0, rp2_usage[0].usage)
def test_allocation_checking(self): """Test that allocation check logic works with 2 resource classes on one provider. If this fails, we get a KeyError at create_all() """ consumer_uuid = uuidsentinel.consumer consumer_uuid2 = uuidsentinel.consumer2 # Create one resource provider with 2 classes rp1_name = uuidsentinel.rp1_name rp1_uuid = uuidsentinel.rp1_uuid rp1_class = fields.ResourceClass.DISK_GB rp1_used = 6 rp2_class = fields.ResourceClass.IPV4_ADDRESS rp2_used = 2 rp1 = objects.ResourceProvider(self.context, name=rp1_name, uuid=rp1_uuid) rp1.create() inv = objects.Inventory(resource_provider=rp1, resource_class=rp1_class, total=1024) inv.obj_set_defaults() inv2 = objects.Inventory(resource_provider=rp1, resource_class=rp2_class, total=255, reserved=2) inv2.obj_set_defaults() inv_list = objects.InventoryList(objects=[inv, inv2]) rp1.set_inventory(inv_list) # create the allocations for a first consumer allocation_1 = objects.Allocation(resource_provider=rp1, consumer_id=consumer_uuid, resource_class=rp1_class, used=rp1_used) allocation_2 = objects.Allocation(resource_provider=rp1, consumer_id=consumer_uuid, resource_class=rp2_class, used=rp2_used) allocation_list = objects.AllocationList( self.context, objects=[allocation_1, allocation_2]) allocation_list.create_all() # create the allocations for a second consumer, until we have # allocations for more than one consumer in the db, then we # won't actually be doing real allocation math, which triggers # the sql monster. allocation_1 = objects.Allocation(resource_provider=rp1, consumer_id=consumer_uuid2, resource_class=rp1_class, used=rp1_used) allocation_2 = objects.Allocation(resource_provider=rp1, consumer_id=consumer_uuid2, resource_class=rp2_class, used=rp2_used) allocation_list = objects.AllocationList( self.context, objects=[allocation_1, allocation_2]) # If we are joining wrong, this will be a KeyError allocation_list.create_all()
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 = objects.ResourceProvider( self.context, name=rp_name, uuid=rp_uuid) rp.create() # Create some DISK_GB inventory and allocations. # Each set of allocations must have the same consumer_id because only # the first allocation is used for the project/user association. consumer_id = uuidutils.generate_uuid() inventory = objects.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 = objects.Allocation( self.context, resource_provider=rp, resource_class='DISK_GB', consumer_id=consumer_id, used=500) alloc2 = objects.Allocation( self.context, resource_provider=rp, resource_class='DISK_GB', consumer_id=consumer_id, used=500) alloc_list = objects.AllocationList( self.context, objects=[alloc1, alloc2], project_id=project_id, user_id=user_id, ) alloc_list.create_all() # Create some VCPU inventory and allocations. # Each set of allocations must have the same consumer_id because only # the first allocation is used for the project/user association. consumer_id = uuidutils.generate_uuid() inventory = objects.Inventory( self.context, resource_provider=rp, resource_class='VCPU', total=10, max_unit=4) inventory.obj_set_defaults() rp.add_inventory(inventory) alloc1 = objects.Allocation( self.context, resource_provider=rp, resource_class='VCPU', consumer_id=consumer_id, used=2) alloc2 = objects.Allocation( self.context, resource_provider=rp, resource_class='VCPU', consumer_id=consumer_id, used=4) alloc_list = objects.AllocationList( self.context, objects=[alloc1, alloc2], project_id=project_id, user_id=user_id) alloc_list.create_all() # Create a couple of allocations for a different user. # Each set of allocations must have the same consumer_id because only # the first allocation is used for the project/user association. consumer_id = uuidutils.generate_uuid() alloc1 = objects.Allocation( self.context, resource_provider=rp, resource_class='DISK_GB', consumer_id=consumer_id, used=20) alloc2 = objects.Allocation( self.context, resource_provider=rp, resource_class='VCPU', consumer_id=consumer_id, used=1) alloc_list = objects.AllocationList( self.context, objects=[alloc1, alloc2], project_id=project_id, user_id=alt_user_id) 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()