48ce34a68e
If cluster is enabled, the group should be updated with cluster as well. Change-Id: I72dc6c61f10417f8382c7c488be27ed5199b75b9 Implements: blueprint cinder-volume-active-active-support
271 lines
13 KiB
Python
271 lines
13 KiB
Python
# Copyright 2010 United States Government as represented by the
|
|
# Administrator of the National Aeronautics and Space Administration.
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
"""Tests for volume init host method cases."""
|
|
|
|
import mock
|
|
from oslo_config import cfg
|
|
|
|
from cinder import context
|
|
from cinder import objects
|
|
from cinder.tests.unit import utils as tests_utils
|
|
from cinder.tests.unit import volume as base
|
|
from cinder.volume import driver
|
|
from cinder.volume import utils as volutils
|
|
|
|
|
|
CONF = cfg.CONF
|
|
|
|
|
|
class VolumeInitHostTestCase(base.BaseVolumeTestCase):
|
|
|
|
def setUp(self):
|
|
super(VolumeInitHostTestCase, self).setUp()
|
|
self.service_id = 1
|
|
|
|
@mock.patch('cinder.manager.CleanableManager.init_host')
|
|
def test_init_host_count_allocated_capacity(self, init_host_mock):
|
|
vol0 = tests_utils.create_volume(
|
|
self.context, size=100, host=CONF.host)
|
|
vol1 = tests_utils.create_volume(
|
|
self.context, size=128,
|
|
host=volutils.append_host(CONF.host, 'pool0'))
|
|
vol2 = tests_utils.create_volume(
|
|
self.context, size=256,
|
|
host=volutils.append_host(CONF.host, 'pool0'))
|
|
vol3 = tests_utils.create_volume(
|
|
self.context, size=512,
|
|
host=volutils.append_host(CONF.host, 'pool1'))
|
|
vol4 = tests_utils.create_volume(
|
|
self.context, size=1024,
|
|
host=volutils.append_host(CONF.host, 'pool2'))
|
|
self.volume.init_host(service_id=self.service_id)
|
|
init_host_mock.assert_called_once_with(
|
|
service_id=self.service_id, added_to_cluster=None)
|
|
stats = self.volume.stats
|
|
self.assertEqual(2020, stats['allocated_capacity_gb'])
|
|
self.assertEqual(
|
|
384, stats['pools']['pool0']['allocated_capacity_gb'])
|
|
self.assertEqual(
|
|
512, stats['pools']['pool1']['allocated_capacity_gb'])
|
|
self.assertEqual(
|
|
1024, stats['pools']['pool2']['allocated_capacity_gb'])
|
|
|
|
# NOTE(jdg): On the create we have host='xyz', BUT
|
|
# here we do a db.volume_get, and now the host has
|
|
# been updated to xyz#pool-name. Note this is
|
|
# done via the managers init, which calls the drivers
|
|
# get_pool method, which in the legacy case is going
|
|
# to be volume_backend_name or None
|
|
|
|
vol0.refresh()
|
|
expected_host = volutils.append_host(CONF.host, 'fake')
|
|
self.assertEqual(expected_host, vol0.host)
|
|
self.volume.delete_volume(self.context, vol0)
|
|
self.volume.delete_volume(self.context, vol1)
|
|
self.volume.delete_volume(self.context, vol2)
|
|
self.volume.delete_volume(self.context, vol3)
|
|
self.volume.delete_volume(self.context, vol4)
|
|
|
|
@mock.patch('cinder.manager.CleanableManager.init_host')
|
|
def test_init_host_count_allocated_capacity_cluster(self, init_host_mock):
|
|
cluster_name = 'mycluster'
|
|
self.volume.cluster = cluster_name
|
|
# All these volumes belong to the same cluster, so we will calculate
|
|
# the capacity of them all because we query the DB by cluster_name.
|
|
tests_utils.create_volume(self.context, size=100, host=CONF.host,
|
|
cluster_name=cluster_name)
|
|
tests_utils.create_volume(
|
|
self.context, size=128, cluster_name=cluster_name,
|
|
host=volutils.append_host(CONF.host, 'pool0'))
|
|
tests_utils.create_volume(
|
|
self.context, size=256, cluster_name=cluster_name,
|
|
host=volutils.append_host(CONF.host + '2', 'pool0'))
|
|
tests_utils.create_volume(
|
|
self.context, size=512, cluster_name=cluster_name,
|
|
host=volutils.append_host(CONF.host + '2', 'pool1'))
|
|
tests_utils.create_volume(
|
|
self.context, size=1024, cluster_name=cluster_name,
|
|
host=volutils.append_host(CONF.host + '3', 'pool2'))
|
|
|
|
# These don't belong to the cluster so they will be ignored
|
|
tests_utils.create_volume(
|
|
self.context, size=1024,
|
|
host=volutils.append_host(CONF.host, 'pool2'))
|
|
tests_utils.create_volume(
|
|
self.context, size=1024, cluster_name=cluster_name + '1',
|
|
host=volutils.append_host(CONF.host + '3', 'pool2'))
|
|
|
|
self.volume.init_host(service_id=self.service_id)
|
|
init_host_mock.assert_called_once_with(
|
|
service_id=self.service_id, added_to_cluster=None)
|
|
stats = self.volume.stats
|
|
self.assertEqual(2020, stats['allocated_capacity_gb'])
|
|
self.assertEqual(
|
|
384, stats['pools']['pool0']['allocated_capacity_gb'])
|
|
self.assertEqual(
|
|
512, stats['pools']['pool1']['allocated_capacity_gb'])
|
|
self.assertEqual(
|
|
1024, stats['pools']['pool2']['allocated_capacity_gb'])
|
|
|
|
@mock.patch.object(driver.BaseVD, "update_provider_info")
|
|
def test_init_host_sync_provider_info(self, mock_update):
|
|
vol0 = tests_utils.create_volume(
|
|
self.context, size=1, host=CONF.host)
|
|
vol1 = tests_utils.create_volume(
|
|
self.context, size=1, host=CONF.host)
|
|
vol2 = tests_utils.create_volume(
|
|
self.context, size=1, host=CONF.host, status='creating')
|
|
snap0 = tests_utils.create_snapshot(self.context, vol0.id)
|
|
snap1 = tests_utils.create_snapshot(self.context, vol1.id)
|
|
# Return values for update_provider_info
|
|
volumes = [{'id': vol0.id, 'provider_id': '1 2 xxxx'},
|
|
{'id': vol1.id, 'provider_id': '3 4 yyyy'}]
|
|
snapshots = [{'id': snap0.id, 'provider_id': '5 6 xxxx'},
|
|
{'id': snap1.id, 'provider_id': '7 8 yyyy'}]
|
|
mock_update.return_value = (volumes, snapshots)
|
|
# initialize
|
|
self.volume.init_host(service_id=self.service_id)
|
|
# Grab volume and snapshot objects
|
|
vol0_obj = objects.Volume.get_by_id(context.get_admin_context(),
|
|
vol0.id)
|
|
vol1_obj = objects.Volume.get_by_id(context.get_admin_context(),
|
|
vol1.id)
|
|
vol2_obj = objects.Volume.get_by_id(context.get_admin_context(),
|
|
vol2.id)
|
|
snap0_obj = objects.Snapshot.get_by_id(self.context, snap0.id)
|
|
snap1_obj = objects.Snapshot.get_by_id(self.context, snap1.id)
|
|
# Check updated provider ids
|
|
self.assertEqual('1 2 xxxx', vol0_obj.provider_id)
|
|
self.assertEqual('3 4 yyyy', vol1_obj.provider_id)
|
|
self.assertIsNone(vol2_obj.provider_id)
|
|
self.assertEqual('5 6 xxxx', snap0_obj.provider_id)
|
|
self.assertEqual('7 8 yyyy', snap1_obj.provider_id)
|
|
# Clean up
|
|
self.volume.delete_snapshot(self.context, snap0_obj)
|
|
self.volume.delete_snapshot(self.context, snap1_obj)
|
|
self.volume.delete_volume(self.context, vol0)
|
|
self.volume.delete_volume(self.context, vol1)
|
|
|
|
@mock.patch.object(driver.BaseVD, "update_provider_info")
|
|
def test_init_host_sync_provider_info_no_update(self, mock_update):
|
|
vol0 = tests_utils.create_volume(
|
|
self.context, size=1, host=CONF.host)
|
|
vol1 = tests_utils.create_volume(
|
|
self.context, size=1, host=CONF.host)
|
|
snap0 = tests_utils.create_snapshot(self.context, vol0.id)
|
|
snap1 = tests_utils.create_snapshot(self.context, vol1.id)
|
|
mock_update.return_value = ([], [])
|
|
# initialize
|
|
self.volume.init_host(service_id=self.service_id)
|
|
# Grab volume and snapshot objects
|
|
vol0_obj = objects.Volume.get_by_id(context.get_admin_context(),
|
|
vol0.id)
|
|
vol1_obj = objects.Volume.get_by_id(context.get_admin_context(),
|
|
vol1.id)
|
|
snap0_obj = objects.Snapshot.get_by_id(self.context, snap0.id)
|
|
snap1_obj = objects.Snapshot.get_by_id(self.context, snap1.id)
|
|
# Check provider ids are not changed
|
|
self.assertIsNone(vol0_obj.provider_id)
|
|
self.assertIsNone(vol1_obj.provider_id)
|
|
self.assertIsNone(snap0_obj.provider_id)
|
|
self.assertIsNone(snap1_obj.provider_id)
|
|
# Clean up
|
|
self.volume.delete_snapshot(self.context, snap0_obj)
|
|
self.volume.delete_snapshot(self.context, snap1_obj)
|
|
self.volume.delete_volume(self.context, vol0)
|
|
self.volume.delete_volume(self.context, vol1)
|
|
|
|
@mock.patch.object(driver.BaseVD, "update_provider_info")
|
|
def test_init_host_sync_provider_info_no_update_cluster(self, mock_update):
|
|
cluster_name = 'mycluster'
|
|
self.volume.cluster = cluster_name
|
|
vol0 = tests_utils.create_volume(
|
|
self.context, size=1, host=CONF.host, cluster_name=cluster_name)
|
|
vol1 = tests_utils.create_volume(
|
|
self.context, size=1, host=CONF.host + '2',
|
|
cluster_name=cluster_name)
|
|
vol2 = tests_utils.create_volume(
|
|
self.context, size=1, host=CONF.host)
|
|
vol3 = tests_utils.create_volume(
|
|
self.context, size=1, host=CONF.host,
|
|
cluster_name=cluster_name + '2')
|
|
snap0 = tests_utils.create_snapshot(self.context, vol0.id)
|
|
snap1 = tests_utils.create_snapshot(self.context, vol1.id)
|
|
tests_utils.create_snapshot(self.context, vol2.id)
|
|
tests_utils.create_snapshot(self.context, vol3.id)
|
|
mock_update.return_value = ([], [])
|
|
# initialize
|
|
self.volume.init_host(service_id=self.service_id)
|
|
# Grab volume and snapshot objects
|
|
vol0_obj = objects.Volume.get_by_id(context.get_admin_context(),
|
|
vol0.id)
|
|
vol1_obj = objects.Volume.get_by_id(context.get_admin_context(),
|
|
vol1.id)
|
|
snap0_obj = objects.Snapshot.get_by_id(self.context, snap0.id)
|
|
snap1_obj = objects.Snapshot.get_by_id(self.context, snap1.id)
|
|
|
|
self.assertSetEqual({vol0.id, vol1.id},
|
|
{vol.id for vol in mock_update.call_args[0][0]})
|
|
self.assertSetEqual({snap0.id, snap1.id},
|
|
{snap.id for snap in mock_update.call_args[0][1]})
|
|
# Check provider ids are not changed
|
|
self.assertIsNone(vol0_obj.provider_id)
|
|
self.assertIsNone(vol1_obj.provider_id)
|
|
self.assertIsNone(snap0_obj.provider_id)
|
|
self.assertIsNone(snap1_obj.provider_id)
|
|
# Clean up
|
|
self.volume.delete_snapshot(self.context, snap0_obj)
|
|
self.volume.delete_snapshot(self.context, snap1_obj)
|
|
self.volume.delete_volume(self.context, vol0)
|
|
self.volume.delete_volume(self.context, vol1)
|
|
|
|
@mock.patch('cinder.volume.manager.VolumeManager.'
|
|
'_include_resources_in_cluster')
|
|
def test_init_host_cluster_not_changed(self, include_in_cluster_mock):
|
|
self.volume.init_host(added_to_cluster=False,
|
|
service_id=self.service_id)
|
|
include_in_cluster_mock.assert_not_called()
|
|
|
|
@mock.patch('cinder.objects.group.GroupList.include_in_cluster')
|
|
@mock.patch('cinder.objects.snapshot.SnapshotList.get_all',
|
|
return_value=[])
|
|
@mock.patch('cinder.objects.volume.VolumeList.get_all', return_value=[])
|
|
@mock.patch('cinder.objects.volume.VolumeList.include_in_cluster')
|
|
@mock.patch('cinder.objects.consistencygroup.ConsistencyGroupList.'
|
|
'include_in_cluster')
|
|
@mock.patch('cinder.db.image_volume_cache_include_in_cluster')
|
|
def test_init_host_added_to_cluster(self, image_cache_include_mock,
|
|
cg_include_mock,
|
|
vol_include_mock, vol_get_all_mock,
|
|
snap_get_all_mock, group_include_mock):
|
|
cluster = str(mock.sentinel.cluster)
|
|
self.mock_object(self.volume, 'cluster', cluster)
|
|
self.volume.init_host(added_to_cluster=True,
|
|
service_id=self.service_id)
|
|
|
|
vol_include_mock.assert_called_once_with(mock.ANY, cluster,
|
|
host=self.volume.host)
|
|
cg_include_mock.assert_called_once_with(mock.ANY, cluster,
|
|
host=self.volume.host)
|
|
image_cache_include_mock.assert_called_once_with(mock.ANY, cluster,
|
|
host=self.volume.host)
|
|
group_include_mock.assert_called_once_with(mock.ANY, cluster,
|
|
host=self.volume.host)
|
|
vol_get_all_mock.assert_called_once_with(
|
|
mock.ANY, filters={'cluster_name': cluster})
|
|
snap_get_all_mock.assert_called_once_with(
|
|
mock.ANY, filters={'cluster_name': cluster})
|