Add objects.ServiceList.get_all_computes_by_hv_type

This adds a new method to the service list object to get all compute
service records for a given hypervisor type. It's queried with a join to
the compute_nodes table, as that's the only place hypervisor type is
stored.

Change-Id: Ic044362d232e340145fa30f100c3e5e37abb5e6e
This commit is contained in:
Jim Rollenhagen 2016-08-01 15:49:31 +00:00
parent 8d007b4c30
commit 45317d6273
6 changed files with 116 additions and 2 deletions

View File

@ -146,6 +146,16 @@ def service_get_all_by_binary(context, binary, include_disabled=False):
include_disabled=include_disabled)
def service_get_all_computes_by_hv_type(context, hv_type,
include_disabled=False):
"""Get all compute services for a given hypervisor type.
Includes disabled services if 'include_disabled' parameter is True.
"""
return IMPL.service_get_all_computes_by_hv_type(context, hv_type,
include_disabled=include_disabled)
def service_get_all_by_host(context, host):
"""Get all services for a given host."""
return IMPL.service_get_all_by_host(context, host)

View File

@ -494,6 +494,20 @@ def service_get_all_by_binary(context, binary, include_disabled=False):
return query.all()
@pick_context_manager_reader
def service_get_all_computes_by_hv_type(context, hv_type,
include_disabled=False):
query = model_query(context, models.Service, read_deleted="no").\
filter_by(binary='nova-compute')
if not include_disabled:
query = query.filter_by(disabled=False)
query = query.join(models.ComputeNode,
models.Service.host == models.ComputeNode.host).\
filter(models.ComputeNode.hypervisor_type == hv_type).\
distinct('host')
return query.all()
@pick_context_manager_reader
def service_get_by_host_and_binary(context, host, binary):
result = model_query(context, models.Service, read_deleted="no").\

View File

@ -410,7 +410,8 @@ class ServiceList(base.ObjectListBase, base.NovaObject):
# Version 1.16: Service version 1.18
# Version 1.17: Service version 1.19
# Version 1.18: Added include_disabled parameter to get_by_binary()
VERSION = '1.18'
# Version 1.19: Added get_all_computes_by_hv_type()
VERSION = '1.19'
fields = {
'objects': fields.ListOfObjectsField('Service'),
@ -445,3 +446,10 @@ class ServiceList(base.ObjectListBase, base.NovaObject):
context, db_services)
return base.obj_make_list(context, cls(context), objects.Service,
db_services)
@base.remotable_classmethod
def get_all_computes_by_hv_type(cls, context, hv_type):
db_services = db.service_get_all_computes_by_hv_type(
context, hv_type, include_disabled=False)
return base.obj_make_list(context, cls(context), objects.Service,
db_services)

View File

@ -86,6 +86,34 @@ def _reservation_get(context, uuid):
return result
def _make_compute_node(host, node, hv_type, service_id):
compute_node_dict = dict(vcpus=2, memory_mb=1024, local_gb=2048,
uuid=uuidsentinel.fake_compute_node,
vcpus_used=0, memory_mb_used=0,
local_gb_used=0, free_ram_mb=1024,
free_disk_gb=2048, hypervisor_type=hv_type,
hypervisor_version=1, cpu_info="",
running_vms=0, current_workload=0,
service_id=service_id,
host=host,
disk_available_least=100,
hypervisor_hostname=node,
host_ip='127.0.0.1',
supported_instances='',
pci_stats='',
metrics='',
extra_resources='',
cpu_allocation_ratio=16.0,
ram_allocation_ratio=1.5,
disk_allocation_ratio=1.0,
stats='', numa_topology='')
# add some random stats
stats = dict(num_instances=3, num_proj_12345=2,
num_proj_23456=2, num_vm_building=3)
compute_node_dict['stats'] = jsonutils.dumps(stats)
return compute_node_dict
def _quota_reserve(context, project_id, user_id):
"""Create sample Quota, QuotaUsage and Reservation objects.
@ -3510,6 +3538,50 @@ class ServiceTestCase(test.TestCase, ModelsObjectComparatorMixin):
include_disabled=True)
self._assertEqualListsOfObjects(expected, real)
def test_service_get_all_computes_by_hv_type(self):
values = [
{'host': 'host1', 'binary': 'nova-compute'},
{'host': 'host2', 'binary': 'nova-compute', 'disabled': True},
{'host': 'host3', 'binary': 'nova-compute'},
{'host': 'host4', 'binary': 'b2'}
]
services = [self._create_service(vals) for vals in values]
compute_nodes = [
_make_compute_node('host1', 'node1', 'ironic', services[0]['id']),
_make_compute_node('host1', 'node2', 'ironic', services[0]['id']),
_make_compute_node('host2', 'node3', 'ironic', services[1]['id']),
_make_compute_node('host3', 'host3', 'kvm', services[2]['id']),
]
[db.compute_node_create(self.ctxt, cn) for cn in compute_nodes]
expected = services[:1]
real = db.service_get_all_computes_by_hv_type(self.ctxt,
'ironic',
include_disabled=False)
self._assertEqualListsOfObjects(expected, real)
def test_service_get_all_computes_by_hv_type_include_disabled(self):
values = [
{'host': 'host1', 'binary': 'nova-compute'},
{'host': 'host2', 'binary': 'nova-compute', 'disabled': True},
{'host': 'host3', 'binary': 'nova-compute'},
{'host': 'host4', 'binary': 'b2'}
]
services = [self._create_service(vals) for vals in values]
compute_nodes = [
_make_compute_node('host1', 'node1', 'ironic', services[0]['id']),
_make_compute_node('host1', 'node2', 'ironic', services[0]['id']),
_make_compute_node('host2', 'node3', 'ironic', services[1]['id']),
_make_compute_node('host3', 'host3', 'kvm', services[2]['id']),
]
[db.compute_node_create(self.ctxt, cn) for cn in compute_nodes]
expected = services[:2]
real = db.service_get_all_computes_by_hv_type(self.ctxt,
'ironic',
include_disabled=True)
self._assertEqualListsOfObjects(expected, real)
def test_service_get_all_by_host(self):
values = [
{'host': 'host1', 'topic': 't11', 'binary': 'b11'},

View File

@ -1191,7 +1191,7 @@ object_data = {
'SecurityGroupRule': '1.1-ae1da17b79970012e8536f88cb3c6b29',
'SecurityGroupRuleList': '1.2-0005c47fcd0fb78dd6d7fd32a1409f5b',
'Service': '1.20-0f9c0bf701e68640b78638fd09e2cddc',
'ServiceList': '1.18-6c52cb616621c1af2415dcc11faf5c1a',
'ServiceList': '1.19-5325bce13eebcbf22edc9678285270cc',
'TaskLog': '1.0-78b0534366f29aa3eebb01860fbe18fe',
'TaskLogList': '1.0-cc8cce1af8a283b9d28b55fcd682e777',
'Tag': '1.1-8b8d7d5b48887651a0e01241672e2963',

View File

@ -274,6 +274,16 @@ class _TestServiceObject(object):
# Make sure it doesn't re-fetch this
service_obj.compute_node
@mock.patch.object(db, 'service_get_all_computes_by_hv_type')
def test_get_all_computes_by_hv_type(self, mock_get_all):
mock_get_all.return_value = [fake_service]
services = service.ServiceList.get_all_computes_by_hv_type(
self.context, 'hv-type')
self.assertEqual(1, len(services))
self.compare_obj(services[0], fake_service, allow_missing=OPTIONAL)
mock_get_all.assert_called_once_with(self.context, 'hv-type',
include_disabled=False)
def test_load_when_orphaned(self):
service_obj = service.Service()
service_obj.id = 123