Add ability to update provider_id during init

During the Liberty release we added the ability to store
a provider_id for a volume in the Cinder database.  This
simplifies a number of things for back ends when accessing
volumes.

One missing piece here however is that we have no way to
populate this data for existing deployments if/when they
upgrade.

This patch provides a simple solution that issues an update
call to the drivers on host init.  It works by fetching a
list of volumes for the specific host, and passes those in
to the driver.  The driver can do nothing, or it can go
through and sync up the Cinder ID's with it's internal
ID's and return the provider update info.

Change-Id: Ib3b078a6f492afada24e534f380f5f014033d603
This commit is contained in:
John Griffith 2015-08-20 10:45:03 -06:00
parent fdcc2278a0
commit 1a7ce2d32e
4 changed files with 55 additions and 0 deletions

View File

@ -510,6 +510,15 @@ class GenericUtilsTestCase(test.TestCase):
self.assertEqual('sudo cinder-rootwrap /path/to/conf',
utils.get_root_helper())
def test_list_of_dicts_to_dict(self):
a = {'id': '1', 'color': 'orange'}
b = {'id': '2', 'color': 'blue'}
c = {'id': '3', 'color': 'green'}
lst = [a, b, c]
resp = utils.list_of_dicts_to_dict(lst, 'id')
self.assertEqual(c['id'], resp['3']['id'])
class TemporaryChownTestCase(test.TestCase):
@mock.patch('os.stat')

View File

@ -288,6 +288,24 @@ def last_completed_audit_period(unit=None):
return (begin, end)
def list_of_dicts_to_dict(seq, key):
"""Convert list of dicts to a indexted dict.
Takes a list of dicts, and converts it a nested dict
indexed by <key>
:param seq: list of dicts
:parm key: key in dicts to index by
example:
lst = [{'id': 1, ...}, {'id': 2, ...}...]
key = 'id'
returns {1:{'id': 1, ...}, 2:{'id':2, ...}
"""
return {d[key]: dict(d, index=d[key]) for (i, d) in enumerate(seq)}
class ProtectedExpatParser(expatreader.ExpatParser):
"""An expat parser which disables DTD's and entities by default."""

View File

@ -1179,6 +1179,14 @@ class BaseVD(object):
"""
return None
def update_provider_info(self, volid_list):
"""Get provider info updates from driver.
:param volid_list: List of Cinder vol id's to check for updates
:return: dict of update {'id': uuid, provider_id: <provider-id>}
"""
return None
@six.add_metaclass(abc.ABCMeta)
class LocalVD(object):

View File

@ -295,6 +295,25 @@ class VolumeManager(manager.SchedulerDependentManager):
LOG.info(_LI("Determined volume DB was not empty at startup."))
return False
def _sync_provider_info(self, ctxt, volumes):
# NOTE(jdg): For now this just updates provider_id, we can add more
# add more items to the update if theyr'e releveant but we need
# to be safe in what we allow and add a list of allowed keys
# things that make sense are provider_*, replication_status etc
updates = self.driver.update_provider_info([v['id'] for v in volumes])
host_vols = utils.list_of_dicts_to_dict(volumes, 'id')
for u in updates or []:
update = {}
# NOTE(JDG): Make sure returned item is in this hosts volumes
if host_vols.get(u['id'], None):
update['provider_id'] = u['provider_id']
if update:
self.db.volume_update(ctxt,
u['id'],
update)
def init_host(self):
"""Perform any required initialization."""
@ -315,6 +334,7 @@ class VolumeManager(manager.SchedulerDependentManager):
return
volumes = self.db.volume_get_all_by_host(ctxt, self.host)
self._sync_provider_info(ctxt, volumes)
# FIXME volume count for exporting is wrong
try: