self.id_cache = {}
self.str_cache = {}
+ def get_standards(self):
+ """Return a list of {'id': <ID>, 'name': <NAME> for all standard
+ resource classes.
+ """
+ return [{'id': fields.ResourceClass.STANDARD.index(s), 'name': s}
+ for s in fields.ResourceClass.STANDARD]
+
def id_from_string(self, rc_str):
"""Given a string representation of a resource class -- e.g. "DISK_GB"
or "IRON_SILVER" -- return the integer code for the resource class. For
_ALLOC_TBL = models.Allocation.__table__
_INV_TBL = models.Inventory.__table__
_RP_TBL = models.ResourceProvider.__table__
+_RC_TBL = models.ResourceClass.__table__
_RC_CACHE = None
LOG = logging.getLogger(__name__)
def __repr__(self):
strings = [repr(x) for x in self.objects]
return "UsageList[" + ", ".join(strings) + "]"
+
+
+@base.NovaObjectRegistry.register
+class ResourceClass(base.NovaObject):
+ # Version 1.0: Initial version
+ VERSION = '1.0'
+
+ fields = {
+ 'id': fields.IntegerField(read_only=True),
+ 'name': fields.ResourceClassField(read_only=True),
+ }
+
+ @staticmethod
+ def _from_db_object(context, target, source):
+ for field in target.fields:
+ setattr(target, field, source[field])
+
+ target._context = context
+ target.obj_reset_changes()
+ return target
+
+
+@base.NovaObjectRegistry.register
+class ResourceClassList(base.ObjectListBase, base.NovaObject):
+ # Version 1.0: Initial version
+ VERSION = '1.0'
+
+ fields = {
+ 'objects': fields.ListOfObjectsField('ResourceClass'),
+ }
+
+ @staticmethod
+ @db_api.api_context_manager.reader
+ def _get_all(context):
+ _ensure_rc_cache(context)
+ standards = _RC_CACHE.get_standards()
+ customs = list(context.session.query(models.ResourceClass).all())
+ return standards + customs
+
+ @base.remotable_classmethod
+ def get_all(cls, context):
+ resource_classes = cls._get_all(context)
+ return base.obj_make_list(context, cls(context),
+ objects.ResourceClass, resource_classes)
+
+ def __repr__(self):
+ strings = [repr(x) for x in self.objects]
+ return "ResourceClassList[" + ", ".join(strings) + "]"
from nova.db.sqlalchemy import resource_class_cache as rc_cache
from nova import exception
+from nova.objects import fields
from nova import test
from nova.tests import fixtures
self.assertFalse(sel_mock.called)
+ def test_get_standards(self):
+ cache = rc_cache.ResourceClassCache(self.context)
+ standards = cache.get_standards()
+ self.assertEqual(len(standards), len(fields.ResourceClass.STANDARD))
+ names = (rc['name'] for rc in standards)
+ for name in fields.ResourceClass.STANDARD:
+ self.assertIn(name, names)
+
def test_rc_cache_custom(self):
"""Test that non-standard, custom resource classes hit the database and
return appropriate results, caching the results after a single
from nova import exception
from nova import objects
from nova.objects import fields
+from nova.objects import resource_provider as rp_obj
from nova import test
from nova.tests import fixtures
from nova.tests import uuidsentinel
)
-class ResourceProviderBaseCase(test.TestCase):
+class ResourceProviderBaseCase(test.NoDBTestCase):
+
+ USES_DB_SELF = True
def setUp(self):
super(ResourceProviderBaseCase, self).setUp()
+ self.useFixture(fixtures.Database())
+ self.api_db = self.useFixture(fixtures.Database(database='api'))
self.context = context.RequestContext('fake-user', 'fake-project')
def _make_allocation(self, rp_uuid=None):
usage_list = objects.UsageList.get_all_by_resource_provider_uuid(
self.context, db_rp.uuid)
self.assertEqual(2, len(usage_list))
+
+
+class ResourceClassListTestCase(ResourceProviderBaseCase):
+
+ def test_get_all_no_custom(self):
+ """Test that if we haven't yet added any custom resource classes, that
+ we only get a list of ResourceClass objects representing the standard
+ classes.
+ """
+ rcs = objects.ResourceClassList.get_all(self.context)
+ self.assertEqual(len(fields.ResourceClass.STANDARD), len(rcs))
+
+ def test_get_all_with_custom(self):
+ """Test that if we add some custom resource classes, that we get a list
+ of ResourceClass objects representing the standard classes as well as
+ the custom classes.
+ """
+ customs = [
+ ('IRON_NFV', 10001),
+ ('IRON_ENTERPRISE', 10002),
+ ]
+ with self.api_db.get_engine().connect() as conn:
+ for custom in customs:
+ c_name, c_id = custom
+ ins = rp_obj._RC_TBL.insert().values(id=c_id, name=c_name)
+ conn.execute(ins)
+
+ rcs = objects.ResourceClassList.get_all(self.context)
+ expected_count = len(fields.ResourceClass.STANDARD) + len(customs)
+ self.assertEqual(expected_count, len(rcs))
'Quotas': '1.2-1fe4cd50593aaf5d36a6dc5ab3f98fb3',
'QuotasNoOp': '1.2-e041ddeb7dc8188ca71706f78aad41c1',
'RequestSpec': '1.7-5ff3e9df208bf25f8215f1b87624970d',
+ 'ResourceClass': '1.0-e6b367e2cf1733c5f3526f20a3286fe9',
+ 'ResourceClassList': '1.0-4ee0d9efdfd681fed822da88376e04d2',
'ResourceProvider': '1.1-7bbcd5ea1c51782692f55489ab08dea6',
'ResourceProviderList': '1.0-82bd48d8d0f7913bbe7266f3835c81bf',
'S3ImageMapping': '1.0-7dd7366a890d82660ed121de9092276e',