Make os-availability-zones know about cells
This removes the direct-to-object listing of Service objects by the availability zone routines. Instead, it implements a cell-scanning approach in HostAPI and uses that for consistent behavior. The modified behavior of service_get_all() in HostAPI was originally in another patch, but is moved here because of dependency sequencing. The HostAPI patch later in this series uses this as well. Related to blueprint cells-aware-api Change-Id: I65c2b436bef8837c0e10a5e502e9cd598d9aa0c3
This commit is contained in:
parent
c6231539a7
commit
39c1b252e8
nova
@ -16,8 +16,8 @@ from nova.api.openstack.compute.schemas import availability_zone as schema
|
||||
from nova.api.openstack import extensions
|
||||
from nova.api.openstack import wsgi
|
||||
from nova import availability_zones
|
||||
from nova import compute
|
||||
import nova.conf
|
||||
from nova import objects
|
||||
from nova.policies import availability_zone as az_policies
|
||||
from nova import servicegroup
|
||||
|
||||
@ -32,6 +32,7 @@ class AvailabilityZoneController(wsgi.Controller):
|
||||
def __init__(self):
|
||||
super(AvailabilityZoneController, self).__init__()
|
||||
self.servicegroup_api = servicegroup.API()
|
||||
self.host_api = compute.HostAPI()
|
||||
|
||||
def _get_filtered_availability_zones(self, zones, is_available):
|
||||
result = []
|
||||
@ -62,8 +63,9 @@ class AvailabilityZoneController(wsgi.Controller):
|
||||
availability_zones.get_availability_zones(ctxt)
|
||||
|
||||
# Available services
|
||||
enabled_services = objects.ServiceList.get_all(context, disabled=False,
|
||||
set_zones=True)
|
||||
enabled_services = self.host_api.service_get_all(
|
||||
context, {'disabled': False}, set_zones=True, all_cells=True)
|
||||
|
||||
zone_hosts = {}
|
||||
host_services = {}
|
||||
api_services = ('nova-osapi_compute', 'nova-ec2', 'nova-metadata')
|
||||
|
@ -120,8 +120,12 @@ def get_availability_zones(context, get_only_available=False,
|
||||
:param with_hosts: whether to return hosts part of the AZs
|
||||
:type with_hosts: bool
|
||||
"""
|
||||
enabled_services = objects.ServiceList.get_all(context, disabled=False,
|
||||
set_zones=True)
|
||||
# NOTE(danms): Avoid circular import
|
||||
from nova import compute
|
||||
hostapi = compute.HostAPI()
|
||||
|
||||
enabled_services = hostapi.service_get_all(
|
||||
context, {'disabled': False}, set_zones=True, all_cells=True)
|
||||
|
||||
available_zones = []
|
||||
for (zone, host) in [(service['availability_zone'], service['host'])
|
||||
@ -136,8 +140,8 @@ def get_availability_zones(context, get_only_available=False,
|
||||
available_zones = list(_available_zones.items())
|
||||
|
||||
if not get_only_available:
|
||||
disabled_services = objects.ServiceList.get_all(context, disabled=True,
|
||||
set_zones=True)
|
||||
disabled_services = hostapi.service_get_all(
|
||||
context, {'disabled': True}, set_zones=True, all_cells=True)
|
||||
not_available_zones = []
|
||||
azs = available_zones if not with_hosts else dict(available_zones)
|
||||
zones = [(service['availability_zone'], service['host'])
|
||||
|
@ -4325,20 +4325,36 @@ class HostAPI(base.Base):
|
||||
payload)
|
||||
return result
|
||||
|
||||
def service_get_all(self, context, filters=None, set_zones=False):
|
||||
def service_get_all(self, context, filters=None, set_zones=False,
|
||||
all_cells=False):
|
||||
"""Returns a list of services, optionally filtering the results.
|
||||
|
||||
If specified, 'filters' should be a dictionary containing services
|
||||
attributes and matching values. Ie, to get a list of services for
|
||||
the 'compute' topic, use filters={'topic': 'compute'}.
|
||||
|
||||
If all_cells=True, then scan all cells and merge the results.
|
||||
"""
|
||||
if filters is None:
|
||||
filters = {}
|
||||
disabled = filters.pop('disabled', None)
|
||||
if 'availability_zone' in filters:
|
||||
set_zones = True
|
||||
services = objects.ServiceList.get_all(context, disabled,
|
||||
set_zones=set_zones)
|
||||
|
||||
# NOTE(danms): Eventually this all_cells nonsense should go away
|
||||
# and we should always iterate over the cells. However, certain
|
||||
# callers need the legacy behavior for now.
|
||||
if all_cells:
|
||||
load_cells()
|
||||
services = []
|
||||
for cell in CELLS:
|
||||
with nova_context.target_cell(context, cell):
|
||||
cell_services = objects.ServiceList.get_all(
|
||||
context, disabled, set_zones=set_zones)
|
||||
services.extend(cell_services)
|
||||
else:
|
||||
services = objects.ServiceList.get_all(context, disabled,
|
||||
set_zones=set_zones)
|
||||
ret_services = []
|
||||
for service in services:
|
||||
for key, val in filters.items():
|
||||
|
@ -546,7 +546,13 @@ class HostAPI(compute_api.HostAPI):
|
||||
"""Returns the result of calling "uptime" on the target host."""
|
||||
return self.cells_rpcapi.get_host_uptime(context, host_name)
|
||||
|
||||
def service_get_all(self, context, filters=None, set_zones=False):
|
||||
def service_get_all(self, context, filters=None, set_zones=False,
|
||||
all_cells=False):
|
||||
"""Get all services.
|
||||
|
||||
Note that this is the cellsv1 variant, which means we ignore the
|
||||
"all_cells" parameter.
|
||||
"""
|
||||
if filters is None:
|
||||
filters = {}
|
||||
if 'availability_zone' in filters:
|
||||
|
@ -173,6 +173,17 @@ class ComputeHostAPITestCase(test.TestCase):
|
||||
|
||||
_do_test()
|
||||
|
||||
def test_service_get_all_cells(self):
|
||||
cells = objects.CellMappingList.get_all(self.ctxt)
|
||||
for cell in cells:
|
||||
with context.target_cell(self.ctxt, cell):
|
||||
objects.Service(context=self.ctxt,
|
||||
binary='nova-compute',
|
||||
host='host-%s' % cell.uuid).create()
|
||||
services = self.host_api.service_get_all(self.ctxt, all_cells=True)
|
||||
self.assertEqual(sorted(['host-%s' % cell.uuid for cell in cells]),
|
||||
sorted([svc.host for svc in services]))
|
||||
|
||||
def test_service_get_all_no_zones(self):
|
||||
services = [dict(test_service.fake_service,
|
||||
id=1, topic='compute', host='host1'),
|
||||
@ -338,6 +349,10 @@ class ComputeHostAPICellsTestCase(ComputeHostAPITestCase):
|
||||
self.flags(cell_type='api', group='cells')
|
||||
super(ComputeHostAPICellsTestCase, self).setUp()
|
||||
|
||||
@testtools.skip('cellsv1 does not use this')
|
||||
def test_service_get_all_cells(self):
|
||||
pass
|
||||
|
||||
def test_service_get_all_no_zones(self):
|
||||
services = [
|
||||
cells_utils.ServiceProxy(
|
||||
|
Loading…
x
Reference in New Issue
Block a user