Merge "Make Inventory and ResourceProvider objects use the API DB instead"

This commit is contained in:
Jenkins 2016-05-27 23:36:59 +00:00 committed by Gerrit Code Review
commit f280d26216
5 changed files with 39 additions and 160 deletions

View File

@ -297,28 +297,8 @@ class ComputeNode(base.NovaPersistentObject, base.NovaObject):
pools = jsonutils.dumps(pools.obj_to_primitive())
updates['pci_stats'] = pools
def _should_manage_inventory(self):
related_binaries = ['nova-api', 'nova-conductor', 'nova-scheduler']
required_version = 10
min_ver = objects.Service.get_minimum_version_multi(self._context,
related_binaries)
return min_ver >= required_version
def _update_inventory(self, updates):
"""Update inventory records from legacy model values
:param updates: Legacy model update dict which will be modified when
we return
"""
# NOTE(danms): Here we update our inventory records with our
# resource information. Since this information is prepared in
# updates against our older compute_node columns, we need to
# zero those values after we have updated the inventory
# records so that it is clear that they have been migrated.
# We return True or False here based on whether we found
# inventory records to update. If not, then we need to signal
# to our caller that _create_inventory() needs to be called
# instead
def update_inventory(self):
"""Update inventory records from legacy model values."""
inventory_list = \
objects.InventoryList.get_all_by_resource_provider_uuid(
@ -338,30 +318,22 @@ class ComputeNode(base.NovaPersistentObject, base.NovaObject):
inventory.resource_class)
continue
if key in updates:
if key in self.obj_what_changed():
inventory.total = getattr(self, key)
updates[key] = 0
inventory.save()
return True
def _create_inventory(self, updates):
def create_inventory(self):
"""Create the initial inventory objects for this compute node.
This is only ever called once, either for the first time when a compute
is created, or after an upgrade where the required services have
reached the required version.
:param updates: Legacy model update dict which will be modified when
we return
"""
rp = objects.ResourceProvider(context=self._context, uuid=self.uuid)
rp.create()
# NOTE(danms): Until we remove the columns from compute_nodes,
# we need to constantly zero out each value in our updates to
# signal that we wrote the value into inventory instead.
cpu = objects.Inventory(context=self._context,
resource_provider=rp,
resource_class=fields.ResourceClass.VCPU,
@ -372,7 +344,6 @@ class ComputeNode(base.NovaPersistentObject, base.NovaObject):
step_size=1,
allocation_ratio=self.cpu_allocation_ratio)
cpu.create()
updates['vcpus'] = 0
mem = objects.Inventory(context=self._context,
resource_provider=rp,
@ -384,7 +355,6 @@ class ComputeNode(base.NovaPersistentObject, base.NovaObject):
step_size=1,
allocation_ratio=self.ram_allocation_ratio)
mem.create()
updates['memory_mb'] = 0
# FIXME(danms): Eventually we want to not write this record
# if the compute host is on shared storage. We'll need some
@ -401,7 +371,6 @@ class ComputeNode(base.NovaPersistentObject, base.NovaObject):
step_size=1,
allocation_ratio=self.disk_allocation_ratio)
disk.create()
updates['local_gb'] = 0
@base.remotable
def create(self):
@ -418,9 +387,6 @@ class ComputeNode(base.NovaPersistentObject, base.NovaObject):
self._convert_supported_instances_to_db_format(updates)
self._convert_pci_stats_to_db_format(updates)
if self._should_manage_inventory():
self._create_inventory(updates)
db_compute = db.compute_node_create(self._context, updates)
# NOTE(danms): compute_node_create() operates on (and returns) the
# compute node model only. We need to get the full inventory-based
@ -441,10 +407,6 @@ class ComputeNode(base.NovaPersistentObject, base.NovaObject):
self._convert_supported_instances_to_db_format(updates)
self._convert_pci_stats_to_db_format(updates)
if self._should_manage_inventory():
if not self._update_inventory(updates):
# NOTE(danms): This only happens once
self._create_inventory(updates)
db_compute = db.compute_node_update(self._context, self.id, updates)
# NOTE(danms): compute_node_update() operates on (and returns) the
# compute node model only. We need to get the full inventory-based

View File

@ -13,14 +13,14 @@
from sqlalchemy.orm import joinedload
from nova.db.sqlalchemy import api as db_api
from nova.db.sqlalchemy import models
from nova.db.sqlalchemy import api_models as models
from nova import exception
from nova import objects
from nova.objects import base
from nova.objects import fields
@db_api.main_context_manager.writer
@db_api.api_context_manager.writer
def _create_rp_in_db(context, updates):
db_rp = models.ResourceProvider()
db_rp.update(updates)
@ -28,7 +28,7 @@ def _create_rp_in_db(context, updates):
return db_rp
@db_api.main_context_manager.reader
@db_api.api_context_manager.reader
def _get_rp_by_uuid_from_db(context, uuid):
result = context.session.query(models.ResourceProvider).filter_by(
uuid=uuid).first()
@ -129,7 +129,7 @@ class _HasAResourceProvider(base.NovaObject):
return target
@db_api.main_context_manager.writer
@db_api.api_context_manager.writer
def _create_inventory_in_db(context, updates):
db_inventory = models.Inventory()
db_inventory.update(updates)
@ -137,7 +137,7 @@ def _create_inventory_in_db(context, updates):
return db_inventory
@db_api.main_context_manager.writer
@db_api.api_context_manager.writer
def _update_inventory_in_db(context, id_, updates):
result = context.session.query(
models.Inventory).filter_by(id=id_).update(updates)
@ -199,7 +199,7 @@ class InventoryList(base.ObjectListBase, base.NovaObject):
}
@staticmethod
@db_api.main_context_manager.reader
@db_api.api_context_manager.reader
def _get_all_by_resource_provider(context, rp_uuid):
return context.session.query(models.Inventory).\
options(joinedload('resource_provider')).\

View File

@ -10,13 +10,11 @@
# License for the specific language governing permissions and limitations
# under the License.
import mock
from nova import context
from nova import db
from nova import objects
from nova.objects import fields
from nova import test
from nova.tests import uuidsentinel
class ComputeNodeTestCase(test.TestCase):
@ -24,6 +22,7 @@ class ComputeNodeTestCase(test.TestCase):
super(ComputeNodeTestCase, self).setUp()
self.context = context.RequestContext('fake-user', 'fake-project')
self.cn = objects.ComputeNode(context=self.context,
uuid=uuidsentinel.compute_node,
memory_mb=512, local_gb=1000, vcpus=8,
vcpus_used=0, local_gb_used=0,
memory_mb_used=0, free_ram_mb=0,
@ -33,111 +32,30 @@ class ComputeNodeTestCase(test.TestCase):
ram_allocation_ratio=1.0,
disk_allocation_ratio=1.0)
@mock.patch('nova.objects.Service.get_minimum_version_multi')
def test_create_creates_inventories(self, mock_minver):
mock_minver.return_value = 10
self.cn.create()
self.assertEqual(512, self.cn.memory_mb)
self.assertEqual(1000, self.cn.local_gb)
self.assertEqual(8, self.cn.vcpus)
db_cn = db.compute_node_get(self.context, self.cn.id)
self.assertEqual(0, db_cn['memory_mb'])
self.assertEqual(0, db_cn['local_gb'])
self.assertEqual(0, db_cn['vcpus'])
inventories = objects.InventoryList.get_all_by_resource_provider_uuid(
def test_create_inventory(self):
self.cn.create_inventory()
objs = objects.InventoryList.get_all_by_resource_provider_uuid(
self.context, self.cn.uuid)
self.assertEqual(3, len(inventories))
inv = {i.resource_class: i.total for i in inventories}
expected = {
fields.ResourceClass.DISK_GB: 1000,
fields.ResourceClass.MEMORY_MB: 512,
fields.ResourceClass.VCPU: 8,
}
self.assertEqual(expected, inv)
for obj in objs:
if obj.resource_class == fields.ResourceClass.VCPU:
self.assertEqual(8, obj.total)
elif obj.resource_class == fields.ResourceClass.MEMORY_MB:
self.assertEqual(512, obj.total)
elif obj.resource_class == fields.ResourceClass.DISK_GB:
self.assertEqual(1000, obj.total)
@mock.patch('nova.objects.Service.get_minimum_version_multi')
def test_save_updates_inventories(self, mock_minver):
mock_minver.return_value = 10
self.cn.create()
self.cn.memory_mb = 2048
def test_update_inventory(self):
self.cn.create_inventory()
self.cn.memory_mb = 1024
self.cn.local_gb = 2000
self.cn.save()
self.assertEqual(2048, self.cn.memory_mb)
self.assertEqual(2000, self.cn.local_gb)
self.assertEqual(8, self.cn.vcpus)
db_cn = db.compute_node_get(self.context, self.cn.id)
self.assertEqual(0, db_cn['memory_mb'])
self.assertEqual(0, db_cn['local_gb'])
self.assertEqual(0, db_cn['vcpus'])
inventories = objects.InventoryList.get_all_by_resource_provider_uuid(
self.cn.vcpus = 16
self.cn.update_inventory()
objs = objects.InventoryList.get_all_by_resource_provider_uuid(
self.context, self.cn.uuid)
self.assertEqual(3, len(inventories))
inv = {i.resource_class: i.total for i in inventories}
expected = {
fields.ResourceClass.DISK_GB: 2000,
fields.ResourceClass.MEMORY_MB: 2048,
fields.ResourceClass.VCPU: 8,
}
self.assertEqual(expected, inv)
@mock.patch('nova.objects.Service.get_minimum_version_multi')
def test_save_creates_inventories(self, mock_minver):
mock_minver.return_value = 7
self.cn.create()
inventories = objects.InventoryList.get_all_by_resource_provider_uuid(
self.context, self.cn.uuid)
self.assertEqual(0, len(inventories))
mock_minver.return_value = 10
self.cn.memory_mb = 2048
self.cn.local_gb = 2000
self.cn.save()
self.assertEqual(2048, self.cn.memory_mb)
self.assertEqual(2000, self.cn.local_gb)
self.assertEqual(8, self.cn.vcpus)
db_cn = db.compute_node_get(self.context, self.cn.id)
self.assertEqual(0, db_cn['memory_mb'])
self.assertEqual(0, db_cn['local_gb'])
self.assertEqual(0, db_cn['vcpus'])
inventories = objects.InventoryList.get_all_by_resource_provider_uuid(
self.context, self.cn.uuid)
self.assertEqual(3, len(inventories))
inv = {i.resource_class: i.total for i in inventories}
expected = {
fields.ResourceClass.DISK_GB: 2000,
fields.ResourceClass.MEMORY_MB: 2048,
fields.ResourceClass.VCPU: 8,
}
self.assertEqual(expected, inv)
@mock.patch('nova.objects.Service.get_minimum_version_multi')
def test_create_honors_version(self, mock_minver):
mock_minver.return_value = 7
self.cn.create()
self.assertEqual(512, self.cn.memory_mb)
self.assertEqual(1000, self.cn.local_gb)
self.assertEqual(8, self.cn.vcpus)
db_cn = db.compute_node_get(self.context, self.cn.id)
self.assertEqual(512, db_cn['memory_mb'])
self.assertEqual(1000, db_cn['local_gb'])
self.assertEqual(8, db_cn['vcpus'])
inventories = objects.InventoryList.get_all_by_resource_provider_uuid(
self.context, self.cn.uuid)
self.assertEqual(0, len(inventories))
@mock.patch('nova.objects.Service.get_minimum_version_multi')
def test_save_honors_version(self, mock_minver):
mock_minver.return_value = 7
self.cn.create()
self.cn.memory_mb = 2048
self.cn.local_gb = 2000
self.cn.save()
self.assertEqual(2048, self.cn.memory_mb)
self.assertEqual(2000, self.cn.local_gb)
self.assertEqual(8, self.cn.vcpus)
db_cn = db.compute_node_get(self.context, self.cn.id)
self.assertEqual(2048, db_cn['memory_mb'])
self.assertEqual(2000, db_cn['local_gb'])
self.assertEqual(8, db_cn['vcpus'])
inventories = objects.InventoryList.get_all_by_resource_provider_uuid(
self.context, self.cn.uuid)
self.assertEqual(0, len(inventories))
for obj in objs:
if obj.resource_class == fields.ResourceClass.VCPU:
self.assertEqual(16, obj.total)
elif obj.resource_class == fields.ResourceClass.MEMORY_MB:
self.assertEqual(1024, obj.total)
elif obj.resource_class == fields.ResourceClass.DISK_GB:
self.assertEqual(2000, obj.total)

View File

@ -36,6 +36,7 @@ class ResourceProviderTestCase(test.NoDBTestCase):
def setUp(self):
super(ResourceProviderTestCase, self).setUp()
self.useFixture(fixtures.Database())
self.useFixture(fixtures.Database(database='api'))
self.context = context.RequestContext('fake-user', 'fake-project')
def test_create_resource_provider_requires_uuid(self):

View File

@ -774,8 +774,7 @@ class _MoveClaimTestCase(BaseTrackerTestCase):
@mock.patch('nova.objects.Instance.save')
@mock.patch('nova.objects.InstancePCIRequests.get_by_instance_uuid',
return_value=objects.InstancePCIRequests(requests=[]))
@mock.patch('nova.objects.ComputeNode._create_inventory')
def test_additive_claims(self, mock_ci, mock_get, mock_save):
def test_additive_claims(self, mock_get, mock_save):
limits = self._limits(
2 * FAKE_VIRT_MEMORY_WITH_OVERHEAD,
@ -797,8 +796,7 @@ class _MoveClaimTestCase(BaseTrackerTestCase):
@mock.patch('nova.objects.Instance.save')
@mock.patch('nova.objects.InstancePCIRequests.get_by_instance_uuid',
return_value=objects.InstancePCIRequests(requests=[]))
@mock.patch('nova.objects.ComputeNode._create_inventory')
def test_move_type_not_tracked(self, mock_ci, mock_get, mock_save):
def test_move_type_not_tracked(self, mock_get, mock_save):
self.claim_method(self.context, self.instance, self.instance_type,
limits=self.limits, move_type="live-migration")
mock_save.assert_called_once_with()