Merge "Report backend state in service list"
This commit is contained in:
commit
9cbb200ec2
@ -34,6 +34,7 @@ from cinder.scheduler import rpcapi as scheduler_rpcapi
|
|||||||
from cinder import utils
|
from cinder import utils
|
||||||
from cinder import volume
|
from cinder import volume
|
||||||
from cinder.volume import rpcapi as volume_rpcapi
|
from cinder.volume import rpcapi as volume_rpcapi
|
||||||
|
from cinder.volume import utils as volume_utils
|
||||||
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
@ -73,6 +74,16 @@ class ServiceController(wsgi.Controller):
|
|||||||
filters['binary'] = req.GET['binary']
|
filters['binary'] = req.GET['binary']
|
||||||
|
|
||||||
services = objects.ServiceList.get_all(context, filters)
|
services = objects.ServiceList.get_all(context, filters)
|
||||||
|
# Get backend state from scheduler
|
||||||
|
if req.api_version_request.matches(mv.BACKEND_STATE_REPORT):
|
||||||
|
backend_state_map = {}
|
||||||
|
scheduler_api = self.rpc_apis[constants.SCHEDULER_BINARY]
|
||||||
|
pools = scheduler_api.get_pools(context)
|
||||||
|
for pool in pools:
|
||||||
|
backend_name = volume_utils.extract_host(pool.get("name"))
|
||||||
|
back_state = pool.get('capabilities', {}).get('backend_state',
|
||||||
|
'up')
|
||||||
|
backend_state_map[backend_name] = back_state
|
||||||
|
|
||||||
svcs = []
|
svcs = []
|
||||||
for svc in services:
|
for svc in services:
|
||||||
@ -95,6 +106,10 @@ class ServiceController(wsgi.Controller):
|
|||||||
'status': active, 'state': art,
|
'status': active, 'state': art,
|
||||||
'updated_at': updated_at}
|
'updated_at': updated_at}
|
||||||
|
|
||||||
|
if (req.api_version_request.matches(mv.BACKEND_STATE_REPORT) and
|
||||||
|
svc.binary == constants.VOLUME_BINARY):
|
||||||
|
ret_fields['backend_state'] = backend_state_map.get(svc.host)
|
||||||
|
|
||||||
# On CLUSTER_SUPPORT we added cluster support
|
# On CLUSTER_SUPPORT we added cluster support
|
||||||
if req.api_version_request.matches(mv.CLUSTER_SUPPORT):
|
if req.api_version_request.matches(mv.CLUSTER_SUPPORT):
|
||||||
ret_fields['cluster'] = svc.cluster_name
|
ret_fields['cluster'] = svc.cluster_name
|
||||||
|
@ -135,6 +135,8 @@ VOLUME_CREATE_FROM_BACKUP = '3.47'
|
|||||||
|
|
||||||
VOLUME_SHARED_TARGETS_AND_SERVICE_FIELDS = '3.48'
|
VOLUME_SHARED_TARGETS_AND_SERVICE_FIELDS = '3.48'
|
||||||
|
|
||||||
|
BACKEND_STATE_REPORT = '3.49'
|
||||||
|
|
||||||
|
|
||||||
def get_mv_header(version):
|
def get_mv_header(version):
|
||||||
"""Gets a formatted HTTP microversion header.
|
"""Gets a formatted HTTP microversion header.
|
||||||
|
@ -112,6 +112,7 @@ REST_API_VERSION_HISTORY = """
|
|||||||
* 3.46 - Support create volume by Nova specific image (0 size image).
|
* 3.46 - Support create volume by Nova specific image (0 size image).
|
||||||
* 3.47 - Support create volume from backup.
|
* 3.47 - Support create volume from backup.
|
||||||
* 3.48 - Add ``shared_targets`` and ``service_uuid`` fields to volume.
|
* 3.48 - Add ``shared_targets`` and ``service_uuid`` fields to volume.
|
||||||
|
* 3.49 - Support report backend storage state in service list.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# The minimum and maximum versions of the API supported
|
# The minimum and maximum versions of the API supported
|
||||||
@ -119,7 +120,7 @@ REST_API_VERSION_HISTORY = """
|
|||||||
# minimum version of the API supported.
|
# minimum version of the API supported.
|
||||||
# Explicitly using /v2 endpoints will still work
|
# Explicitly using /v2 endpoints will still work
|
||||||
_MIN_API_VERSION = "3.0"
|
_MIN_API_VERSION = "3.0"
|
||||||
_MAX_API_VERSION = "3.48"
|
_MAX_API_VERSION = "3.49"
|
||||||
_LEGACY_API_VERSION2 = "2.0"
|
_LEGACY_API_VERSION2 = "2.0"
|
||||||
UPDATED = "2017-09-19T20:18:14Z"
|
UPDATED = "2017-09-19T20:18:14Z"
|
||||||
|
|
||||||
|
@ -390,3 +390,7 @@ Support create volume from backup.
|
|||||||
3.48
|
3.48
|
||||||
----
|
----
|
||||||
Add ``shared_targets`` and ``service_uuid`` fields to volume.
|
Add ``shared_targets`` and ``service_uuid`` fields to volume.
|
||||||
|
|
||||||
|
3.49
|
||||||
|
----
|
||||||
|
Support report backend storage state in service list.
|
||||||
|
@ -192,7 +192,13 @@ def fake_utcnow(with_timezone=False):
|
|||||||
return datetime.datetime(2012, 10, 29, 13, 42, 11, tzinfo=tzinfo)
|
return datetime.datetime(2012, 10, 29, 13, 42, 11, tzinfo=tzinfo)
|
||||||
|
|
||||||
|
|
||||||
|
def fake_get_pools(ctxt, filters=None):
|
||||||
|
return [{"name": "host1", "capabilities": {"backend_state": "up"}},
|
||||||
|
{"name": "host2", "capabilities": {"backend_state": "down"}}]
|
||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
|
@mock.patch('cinder.scheduler.rpcapi.SchedulerAPI.get_pools', fake_get_pools)
|
||||||
@mock.patch('cinder.db.service_get_all', fake_service_get_all)
|
@mock.patch('cinder.db.service_get_all', fake_service_get_all)
|
||||||
@mock.patch('cinder.db.service_get', fake_service_get)
|
@mock.patch('cinder.db.service_get', fake_service_get)
|
||||||
@mock.patch('oslo_utils.timeutils.utcnow', fake_utcnow)
|
@mock.patch('oslo_utils.timeutils.utcnow', fake_utcnow)
|
||||||
@ -337,6 +343,63 @@ class ServicesTest(test.TestCase):
|
|||||||
]}
|
]}
|
||||||
self.assertEqual(response, res_dict)
|
self.assertEqual(response, res_dict)
|
||||||
|
|
||||||
|
def test_services_list_with_backend_state(self):
|
||||||
|
req = FakeRequest(version=mv.BACKEND_STATE_REPORT)
|
||||||
|
res_dict = self.controller.index(req)
|
||||||
|
|
||||||
|
response = {'services': [{'binary': 'cinder-scheduler',
|
||||||
|
'cluster': None,
|
||||||
|
'host': 'host1', 'zone': 'cinder',
|
||||||
|
'status': 'disabled', 'state': 'up',
|
||||||
|
'updated_at': datetime.datetime(
|
||||||
|
2012, 10, 29, 13, 42, 2)},
|
||||||
|
{'binary': 'cinder-volume',
|
||||||
|
'cluster': None,
|
||||||
|
'host': 'host1', 'zone': 'cinder',
|
||||||
|
'status': 'disabled', 'state': 'up',
|
||||||
|
'updated_at': datetime.datetime(
|
||||||
|
2012, 10, 29, 13, 42, 5),
|
||||||
|
'backend_state': 'up'},
|
||||||
|
{'binary': 'cinder-scheduler',
|
||||||
|
'cluster': 'cluster1',
|
||||||
|
'host': 'host2',
|
||||||
|
'zone': 'cinder',
|
||||||
|
'status': 'enabled', 'state': 'down',
|
||||||
|
'updated_at': datetime.datetime(
|
||||||
|
2012, 9, 19, 6, 55, 34)},
|
||||||
|
{'binary': 'cinder-volume',
|
||||||
|
'cluster': 'cluster1',
|
||||||
|
'host': 'host2',
|
||||||
|
'zone': 'cinder',
|
||||||
|
'status': 'disabled', 'state': 'down',
|
||||||
|
'updated_at': datetime.datetime(
|
||||||
|
2012, 9, 18, 8, 3, 38),
|
||||||
|
'backend_state': 'down'},
|
||||||
|
{'binary': 'cinder-volume',
|
||||||
|
'cluster': 'cluster2',
|
||||||
|
'host': 'host2',
|
||||||
|
'zone': 'cinder',
|
||||||
|
'status': 'disabled', 'state': 'down',
|
||||||
|
'updated_at': datetime.datetime(
|
||||||
|
2012, 10, 29, 13, 42, 5),
|
||||||
|
'backend_state': 'down'},
|
||||||
|
{'binary': 'cinder-volume',
|
||||||
|
'cluster': 'cluster2',
|
||||||
|
'host': 'host2',
|
||||||
|
'zone': 'cinder',
|
||||||
|
'status': 'enabled', 'state': 'down',
|
||||||
|
'updated_at': datetime.datetime(
|
||||||
|
2012, 9, 18, 8, 3, 38),
|
||||||
|
'backend_state': 'down'},
|
||||||
|
{'binary': 'cinder-scheduler',
|
||||||
|
'cluster': None,
|
||||||
|
'host': 'host2',
|
||||||
|
'zone': 'cinder',
|
||||||
|
'status': 'enabled', 'state': 'down',
|
||||||
|
'updated_at': None},
|
||||||
|
]}
|
||||||
|
self.assertEqual(response, res_dict)
|
||||||
|
|
||||||
def test_services_detail(self):
|
def test_services_detail(self):
|
||||||
self.ext_mgr.extensions['os-extended-services'] = True
|
self.ext_mgr.extensions['os-extended-services'] = True
|
||||||
self.controller = services.ServiceController(self.ext_mgr)
|
self.controller = services.ServiceController(self.ext_mgr)
|
||||||
|
@ -276,7 +276,8 @@ class LVMVolumeDriver(driver.VolumeDriver):
|
|||||||
total_volumes=total_volumes,
|
total_volumes=total_volumes,
|
||||||
filter_function=self.get_filter_function(),
|
filter_function=self.get_filter_function(),
|
||||||
goodness_function=self.get_goodness_function(),
|
goodness_function=self.get_goodness_function(),
|
||||||
multiattach=False
|
multiattach=False,
|
||||||
|
backend_state='up'
|
||||||
))
|
))
|
||||||
data["pools"].append(single_pool)
|
data["pools"].append(single_pool)
|
||||||
data["shared_targets"] = False
|
data["shared_targets"] = False
|
||||||
|
20
doc/source/admin/blockstorage-report-backend-state.rst
Normal file
20
doc/source/admin/blockstorage-report-backend-state.rst
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
====================================
|
||||||
|
Report backend state in service list
|
||||||
|
====================================
|
||||||
|
|
||||||
|
Currently, Cinder couldn't report backend state to service, operators only
|
||||||
|
know that cinder-volume process is up, but isn't aware of whether the backend
|
||||||
|
storage device is ok. Users still can create volume and go to fail over and
|
||||||
|
over again. To make maintenance easier, operator could query storage device
|
||||||
|
state via service list and fix the problem more quickly. If device state is
|
||||||
|
*down*, that means volume creation will fail.
|
||||||
|
|
||||||
|
To do so, use the Block Storage API: service list to get the backend state.
|
||||||
|
Run this command:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ openstack volume service list
|
||||||
|
|
||||||
|
Add backend_state: up/down into response body of service list. This feature
|
||||||
|
is supported after microversion 3.49.
|
@ -45,6 +45,7 @@ Amazon EC2 Elastic Block Storage (EBS) offering.
|
|||||||
blockstorage-volume-backups.rst
|
blockstorage-volume-backups.rst
|
||||||
blockstorage-volume-migration.rst
|
blockstorage-volume-migration.rst
|
||||||
blockstorage-volume-number-weigher.rst
|
blockstorage-volume-number-weigher.rst
|
||||||
|
blockstorage-report-backend-state.rst
|
||||||
|
|
||||||
.. _`Storage Decisions`: https://docs.openstack.org/arch-design/design-storage/design-storage-arch.html
|
.. _`Storage Decisions`: https://docs.openstack.org/arch-design/design-storage/design-storage-arch.html
|
||||||
.. _`OpenStack Operations Guide`: https://wiki.openstack.org/wiki/OpsGuide
|
.. _`OpenStack Operations Guide`: https://wiki.openstack.org/wiki/OpsGuide
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Added "backend_state: up/down" in response body of service list if
|
||||||
|
context is admin. This feature will help operators or cloud management
|
||||||
|
system to get the backend device state in every service.
|
||||||
|
If device state is *down*, specify that storage device has got some
|
||||||
|
problems. Give more information to locate bugs quickly.
|
Loading…
x
Reference in New Issue
Block a user