Merge "Fix create from snapshot and source volume"
This commit is contained in:
commit
aade6e01fa
@ -517,10 +517,15 @@ class FilterScheduler(driver.Scheduler):
|
||||
# snapshot or volume).
|
||||
resource_backend = request_spec.get('resource_backend')
|
||||
if weighed_backends and resource_backend:
|
||||
resource_backend_has_pool = bool(utils.extract_host(
|
||||
resource_backend, 'pool'))
|
||||
# Get host name including host@backend#pool info from
|
||||
# weighed_backends.
|
||||
for backend in weighed_backends[::-1]:
|
||||
backend_id = utils.extract_host(backend.obj.backend_id)
|
||||
backend_id = (
|
||||
backend.obj.backend_id if resource_backend_has_pool
|
||||
else utils.extract_host(backend.obj.backend_id)
|
||||
)
|
||||
if backend_id != resource_backend:
|
||||
weighed_backends.remove(backend)
|
||||
if not weighed_backends:
|
||||
|
@ -15,16 +15,197 @@
|
||||
"""
|
||||
Fakes For Scheduler tests.
|
||||
"""
|
||||
import copy
|
||||
|
||||
from oslo_utils import timeutils
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from cinder.scheduler import filter_scheduler
|
||||
from cinder.scheduler import host_manager
|
||||
from cinder.volume import utils
|
||||
|
||||
|
||||
UTC_NOW = timeutils.utcnow()
|
||||
|
||||
SERVICE_STATES = {
|
||||
'host1': {'total_capacity_gb': 1024,
|
||||
'free_capacity_gb': 1024,
|
||||
'allocated_capacity_gb': 0,
|
||||
'provisioned_capacity_gb': 0,
|
||||
'max_over_subscription_ratio': 1.0,
|
||||
'thin_provisioning_support': False,
|
||||
'thick_provisioning_support': True,
|
||||
'reserved_percentage': 10,
|
||||
'volume_backend_name': 'lvm1',
|
||||
'timestamp': UTC_NOW,
|
||||
'multiattach': True,
|
||||
'uuid': 'a3a593da-7f8d-4bb7-8b4c-f2bc1e0b4824'},
|
||||
'host2': {'total_capacity_gb': 2048,
|
||||
'free_capacity_gb': 300,
|
||||
'allocated_capacity_gb': 1748,
|
||||
'provisioned_capacity_gb': 1748,
|
||||
'max_over_subscription_ratio': 1.5,
|
||||
'thin_provisioning_support': True,
|
||||
'thick_provisioning_support': False,
|
||||
'reserved_percentage': 10,
|
||||
'volume_backend_name': 'lvm2',
|
||||
'timestamp': UTC_NOW,
|
||||
'uuid': '4200b32b-0bf9-436c-86b2-0675f6ac218e'},
|
||||
'host3': {'total_capacity_gb': 512,
|
||||
'free_capacity_gb': 256,
|
||||
'allocated_capacity_gb': 256,
|
||||
'provisioned_capacity_gb': 256,
|
||||
'max_over_subscription_ratio': 2.0,
|
||||
'thin_provisioning_support': False,
|
||||
'thick_provisioning_support': True,
|
||||
'reserved_percentage': 0,
|
||||
'volume_backend_name': 'lvm3',
|
||||
'timestamp': UTC_NOW,
|
||||
'uuid': '6d91e7f5-ca17-4e3b-bf4f-19ca77166dd7'},
|
||||
'host4': {'total_capacity_gb': 2048,
|
||||
'free_capacity_gb': 200,
|
||||
'allocated_capacity_gb': 1848,
|
||||
'provisioned_capacity_gb': 2047,
|
||||
'max_over_subscription_ratio': 1.0,
|
||||
'thin_provisioning_support': True,
|
||||
'thick_provisioning_support': False,
|
||||
'reserved_percentage': 5,
|
||||
'volume_backend_name': 'lvm4',
|
||||
'timestamp': UTC_NOW,
|
||||
'consistent_group_snapshot_enabled': True,
|
||||
'uuid': '18417850-2ca9-43d1-9619-ae16bfb0f655'},
|
||||
'host5': {'total_capacity_gb': 'infinite',
|
||||
'free_capacity_gb': 'unknown',
|
||||
'allocated_capacity_gb': 1548,
|
||||
'provisioned_capacity_gb': 1548,
|
||||
'max_over_subscription_ratio': 1.0,
|
||||
'thin_provisioning_support': True,
|
||||
'thick_provisioning_support': False,
|
||||
'reserved_percentage': 5,
|
||||
'timestamp': UTC_NOW,
|
||||
'uuid': 'f838f35c-4035-464f-9792-ce60e390c13d'},
|
||||
}
|
||||
|
||||
SERVICE_STATES_WITH_POOLS = {
|
||||
'host1@BackendA': {
|
||||
'uuid': 'a3a593da-7f8d-4bb7-8b4c-f2bc1e0b4824',
|
||||
'replication_enabled': False,
|
||||
'driver_version': '1.0.0',
|
||||
'volume_backend_name': 'BackendA',
|
||||
'pools': [
|
||||
{
|
||||
'total_capacity_gb': 1024,
|
||||
'free_capacity_gb': 1024,
|
||||
'allocated_capacity_gb': 0,
|
||||
'provisioned_capacity_gb': 0,
|
||||
'max_over_subscription_ratio': 1.0,
|
||||
'thin_provisioning_support': False,
|
||||
'thick_provisioning_support': True,
|
||||
'reserved_percentage': 15,
|
||||
'pool_name': 'openstack_iscsi_1',
|
||||
},
|
||||
{
|
||||
'total_capacity_gb': 2048,
|
||||
'free_capacity_gb': 1008,
|
||||
'allocated_capacity_gb': 0,
|
||||
'provisioned_capacity_gb': 0,
|
||||
'max_over_subscription_ratio': 1.0,
|
||||
'thin_provisioning_support': True,
|
||||
'thick_provisioning_support': False,
|
||||
'reserved_percentage': 15,
|
||||
'pool_name': 'openstack_iscsi_2',
|
||||
},
|
||||
|
||||
],
|
||||
'storage_protocol': 'iSCSI',
|
||||
'timestamp': UTC_NOW,
|
||||
},
|
||||
'host1@BackendB': {
|
||||
'replication_enabled': True,
|
||||
'driver_version': '1.5.0',
|
||||
'volume_backend_name': 'BackendB',
|
||||
'uuid': '4200b32b-0bf9-436c-86b2-0675f6ac218e',
|
||||
'pools': [
|
||||
{
|
||||
'total_capacity_gb': 2048,
|
||||
'free_capacity_gb': 300,
|
||||
'allocated_capacity_gb': 1748,
|
||||
'provisioned_capacity_gb': 1748,
|
||||
'max_over_subscription_ratio': 1.5,
|
||||
'thin_provisioning_support': True,
|
||||
'thick_provisioning_support': False,
|
||||
'reserved_percentage': 10,
|
||||
'pool_name': 'openstack_nfs_1',
|
||||
},
|
||||
{
|
||||
'total_capacity_gb': 512,
|
||||
'free_capacity_gb': 256,
|
||||
'allocated_capacity_gb': 256,
|
||||
'provisioned_capacity_gb': 256,
|
||||
'max_over_subscription_ratio': 2.0,
|
||||
'thin_provisioning_support': True,
|
||||
'thick_provisioning_support': False,
|
||||
'reserved_percentage': 10,
|
||||
'pool_name': 'openstack_nfs_2',
|
||||
},
|
||||
|
||||
],
|
||||
'storage_protocol': 'nfs',
|
||||
'timestamp': UTC_NOW,
|
||||
},
|
||||
'host2@BackendX': {
|
||||
'replication_enabled': False,
|
||||
'driver_version': '3.5.1',
|
||||
'total_capacity_gb': 512,
|
||||
'free_capacity_gb': 256,
|
||||
'allocated_capacity_gb': 256,
|
||||
'provisioned_capacity_gb': 256,
|
||||
'max_over_subscription_ratio': 2.0,
|
||||
'thin_provisioning_support': False,
|
||||
'thick_provisioning_support': True,
|
||||
'reserved_percentage': 0,
|
||||
'volume_backend_name': 'BackendX',
|
||||
'storage_protocol': 'iSCSI',
|
||||
'timestamp': UTC_NOW,
|
||||
'uuid': '6d91e7f5-ca17-4e3b-bf4f-19ca77166dd7'
|
||||
},
|
||||
'host3@BackendY': {
|
||||
'replication_enabled': True,
|
||||
'driver_version': '1.5.0',
|
||||
'volume_backend_name': 'BackendY',
|
||||
'uuid': '18417850-2ca9-43d1-9619-ae16bfb0f655',
|
||||
'pools': [
|
||||
{
|
||||
'total_capacity_gb': 'infinite',
|
||||
'free_capacity_gb': 'unknown',
|
||||
'allocated_capacity_gb': 170,
|
||||
'provisioned_capacity_gb': 170,
|
||||
'max_over_subscription_ratio': 1.0,
|
||||
'thin_provisioning_support': False,
|
||||
'thick_provisioning_support': True,
|
||||
'QoS_support': True,
|
||||
'reserved_percentage': 0,
|
||||
'pool_name': 'openstack_fcp_1',
|
||||
},
|
||||
{
|
||||
'total_capacity_gb': 'infinite',
|
||||
'free_capacity_gb': 'unknown',
|
||||
'allocated_capacity_gb': 1548,
|
||||
'provisioned_capacity_gb': 1548,
|
||||
'max_over_subscription_ratio': 1.0,
|
||||
'thin_provisioning_support': True,
|
||||
'thick_provisioning_support': False,
|
||||
'QoS_support': True,
|
||||
'reserved_percentage': 0,
|
||||
'pool_name': 'openstack_fcp_2',
|
||||
},
|
||||
|
||||
],
|
||||
'storage_protocol': 'fc',
|
||||
'timestamp': UTC_NOW,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class FakeFilterScheduler(filter_scheduler.FilterScheduler):
|
||||
def __init__(self, *args, **kwargs):
|
||||
@ -33,67 +214,13 @@ class FakeFilterScheduler(filter_scheduler.FilterScheduler):
|
||||
|
||||
|
||||
class FakeHostManager(host_manager.HostManager):
|
||||
def __init__(self):
|
||||
def __init__(self, multibackend_with_pools=False):
|
||||
super(FakeHostManager, self).__init__()
|
||||
|
||||
self.service_states = {
|
||||
'host1': {'total_capacity_gb': 1024,
|
||||
'free_capacity_gb': 1024,
|
||||
'allocated_capacity_gb': 0,
|
||||
'provisioned_capacity_gb': 0,
|
||||
'max_over_subscription_ratio': 1.0,
|
||||
'thin_provisioning_support': False,
|
||||
'thick_provisioning_support': True,
|
||||
'reserved_percentage': 10,
|
||||
'volume_backend_name': 'lvm1',
|
||||
'timestamp': UTC_NOW,
|
||||
'multiattach': True,
|
||||
'uuid': 'a3a593da-7f8d-4bb7-8b4c-f2bc1e0b4824'},
|
||||
'host2': {'total_capacity_gb': 2048,
|
||||
'free_capacity_gb': 300,
|
||||
'allocated_capacity_gb': 1748,
|
||||
'provisioned_capacity_gb': 1748,
|
||||
'max_over_subscription_ratio': 1.5,
|
||||
'thin_provisioning_support': True,
|
||||
'thick_provisioning_support': False,
|
||||
'reserved_percentage': 10,
|
||||
'volume_backend_name': 'lvm2',
|
||||
'timestamp': UTC_NOW,
|
||||
'uuid': '4200b32b-0bf9-436c-86b2-0675f6ac218e'},
|
||||
'host3': {'total_capacity_gb': 512,
|
||||
'free_capacity_gb': 256,
|
||||
'allocated_capacity_gb': 256,
|
||||
'provisioned_capacity_gb': 256,
|
||||
'max_over_subscription_ratio': 2.0,
|
||||
'thin_provisioning_support': False,
|
||||
'thick_provisioning_support': True,
|
||||
'reserved_percentage': 0,
|
||||
'volume_backend_name': 'lvm3',
|
||||
'timestamp': UTC_NOW,
|
||||
'uuid': '6d91e7f5-ca17-4e3b-bf4f-19ca77166dd7'},
|
||||
'host4': {'total_capacity_gb': 2048,
|
||||
'free_capacity_gb': 200,
|
||||
'allocated_capacity_gb': 1848,
|
||||
'provisioned_capacity_gb': 2047,
|
||||
'max_over_subscription_ratio': 1.0,
|
||||
'thin_provisioning_support': True,
|
||||
'thick_provisioning_support': False,
|
||||
'reserved_percentage': 5,
|
||||
'volume_backend_name': 'lvm4',
|
||||
'timestamp': UTC_NOW,
|
||||
'consistent_group_snapshot_enabled': True,
|
||||
'uuid': '18417850-2ca9-43d1-9619-ae16bfb0f655'},
|
||||
'host5': {'total_capacity_gb': 'infinite',
|
||||
'free_capacity_gb': 'unknown',
|
||||
'allocated_capacity_gb': 1548,
|
||||
'provisioned_capacity_gb': 1548,
|
||||
'max_over_subscription_ratio': 1.0,
|
||||
'thin_provisioning_support': True,
|
||||
'thick_provisioning_support': False,
|
||||
'reserved_percentage': 5,
|
||||
'timestamp': UTC_NOW,
|
||||
'uuid': 'f838f35c-4035-464f-9792-ce60e390c13d'},
|
||||
}
|
||||
self.service_states = copy.deepcopy(
|
||||
SERVICE_STATES_WITH_POOLS if multibackend_with_pools
|
||||
else SERVICE_STATES
|
||||
)
|
||||
|
||||
|
||||
class FakeBackendState(host_manager.BackendState):
|
||||
@ -152,24 +279,34 @@ class FakeNovaClient(object):
|
||||
ext_srv_attr=ext_srv_attr)
|
||||
|
||||
|
||||
def mock_host_manager_db_calls(mock_obj, disabled=None):
|
||||
services = [
|
||||
dict(id=1, host='host1', topic='volume', disabled=False,
|
||||
availability_zone='zone1', updated_at=timeutils.utcnow(),
|
||||
uuid='a3a593da-7f8d-4bb7-8b4c-f2bc1e0b4824'),
|
||||
dict(id=2, host='host2', topic='volume', disabled=False,
|
||||
availability_zone='zone1', updated_at=timeutils.utcnow(),
|
||||
uuid='4200b32b-0bf9-436c-86b2-0675f6ac218e'),
|
||||
dict(id=3, host='host3', topic='volume', disabled=False,
|
||||
availability_zone='zone2', updated_at=timeutils.utcnow(),
|
||||
uuid='4200b32b-0bf9-436c-86b2-0675f6ac218e'),
|
||||
dict(id=4, host='host4', topic='volume', disabled=False,
|
||||
availability_zone='zone3', updated_at=timeutils.utcnow(),
|
||||
uuid='18417850-2ca9-43d1-9619-ae16bfb0f655'),
|
||||
dict(id=5, host='host5', topic='volume', disabled=False,
|
||||
availability_zone='zone3', updated_at=timeutils.utcnow(),
|
||||
uuid='f838f35c-4035-464f-9792-ce60e390c13d'),
|
||||
]
|
||||
def mock_host_manager_db_calls(mock_obj, backends_with_pools=False,
|
||||
disabled=None):
|
||||
service_states = (
|
||||
SERVICE_STATES_WITH_POOLS if backends_with_pools else SERVICE_STATES
|
||||
)
|
||||
services = []
|
||||
az_map = {
|
||||
'host1': 'zone1',
|
||||
'host2': 'zone1',
|
||||
'host3': 'zone2',
|
||||
'host4': 'zone3',
|
||||
'host5': 'zone3',
|
||||
}
|
||||
sid = 0
|
||||
for svc, state in service_states.items():
|
||||
sid += 1
|
||||
services.append(
|
||||
{
|
||||
'id': sid,
|
||||
'host': svc,
|
||||
'availability_zone': az_map[utils.extract_host(svc, 'host')],
|
||||
'topic': 'volume',
|
||||
'disabled': False,
|
||||
'updated_at': timeutils.utcnow(),
|
||||
'uuid': state.get('uuid', uuidutils.generate_uuid()),
|
||||
}
|
||||
)
|
||||
|
||||
if disabled is None:
|
||||
mock_obj.return_value = services
|
||||
else:
|
||||
|
@ -184,34 +184,50 @@ class FilterSchedulerTestCase(test_scheduler.SchedulerTestCase):
|
||||
self.assertIsNotNone(weighed_host.obj)
|
||||
self.assertTrue(_mock_service_get_all.called)
|
||||
|
||||
@ddt.data(('host10@BackendA', True),
|
||||
('host10@BackendB#openstack_nfs_1', True),
|
||||
('host10', False))
|
||||
@ddt.unpack
|
||||
@mock.patch('cinder.db.service_get_all')
|
||||
def test_create_volume_host_different_with_resource_backend(
|
||||
self, _mock_service_get_all):
|
||||
self, resource_backend, multibackend_with_pools,
|
||||
_mock_service_get_all):
|
||||
sched = fakes.FakeFilterScheduler()
|
||||
sched.host_manager = fakes.FakeHostManager()
|
||||
fakes.mock_host_manager_db_calls(_mock_service_get_all)
|
||||
sched.host_manager = fakes.FakeHostManager(
|
||||
multibackend_with_pools=multibackend_with_pools)
|
||||
fakes.mock_host_manager_db_calls(
|
||||
_mock_service_get_all, backends_with_pools=multibackend_with_pools)
|
||||
fake_context = context.RequestContext('user', 'project')
|
||||
request_spec = {'volume_properties': {'project_id': 1,
|
||||
'size': 1},
|
||||
'volume_type': {'name': 'LVM_iSCSI'},
|
||||
'resource_backend': 'host_none'}
|
||||
'resource_backend': resource_backend}
|
||||
weighed_host = sched._schedule(fake_context, request_spec, {})
|
||||
self.assertIsNone(weighed_host)
|
||||
|
||||
@ddt.data(('host1@BackendA', True),
|
||||
('host1@BackendB#openstack_nfs_1', True),
|
||||
('host1', False))
|
||||
@ddt.unpack
|
||||
@mock.patch('cinder.db.service_get_all')
|
||||
def test_create_volume_host_same_as_resource(self, _mock_service_get_all):
|
||||
def test_create_volume_host_same_as_resource(self, resource_backend,
|
||||
multibackend_with_pools,
|
||||
_mock_service_get_all):
|
||||
# Ensure we don't clear the host whose backend is same as
|
||||
# group's backend.
|
||||
# requested backend (ex: create from source-volume/snapshot,
|
||||
# or create within a group)
|
||||
sched = fakes.FakeFilterScheduler()
|
||||
sched.host_manager = fakes.FakeHostManager()
|
||||
fakes.mock_host_manager_db_calls(_mock_service_get_all)
|
||||
sched.host_manager = fakes.FakeHostManager(
|
||||
multibackend_with_pools=multibackend_with_pools)
|
||||
fakes.mock_host_manager_db_calls(
|
||||
_mock_service_get_all, backends_with_pools=multibackend_with_pools)
|
||||
fake_context = context.RequestContext('user', 'project')
|
||||
request_spec = {'volume_properties': {'project_id': 1,
|
||||
'size': 1},
|
||||
'volume_type': {'name': 'LVM_iSCSI'},
|
||||
'resource_backend': 'host1'}
|
||||
'resource_backend': resource_backend}
|
||||
weighed_host = sched._schedule(fake_context, request_spec, {})
|
||||
self.assertEqual('host1#lvm1', weighed_host.obj.host)
|
||||
self.assertIn(resource_backend, weighed_host.obj.host)
|
||||
|
||||
def test_max_attempts(self):
|
||||
self.flags(scheduler_max_attempts=4)
|
||||
|
@ -86,7 +86,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
|
||||
fake_volume_api.FakeDb())
|
||||
|
||||
task._cast_create_volume(self.ctxt, spec, {})
|
||||
mock_extract_host.assert_called_once_with('host@backend#pool')
|
||||
mock_extract_host.assert_not_called()
|
||||
|
||||
snapshot = fake_snapshot.fake_snapshot_obj(self.ctxt,
|
||||
volume=volume)
|
||||
@ -110,8 +110,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
|
||||
|
||||
task._cast_create_volume(self.ctxt, spec, {})
|
||||
mock_snapshot_get.assert_called_once_with(self.ctxt, snapshot.id)
|
||||
mock_extract_host.assert_has_calls([mock.call('host@backend#pool'),
|
||||
mock.call('host@backend#pool')])
|
||||
mock_extract_host.assert_not_called()
|
||||
|
||||
@mock.patch('cinder.objects.Volume.get_by_id')
|
||||
@mock.patch('cinder.volume.utils.extract_host')
|
||||
|
@ -770,12 +770,10 @@ class VolumeCastTask(flow_utils.CinderTask):
|
||||
# before creating volume, we schedule this request to scheduler
|
||||
# service with the desired backend information.
|
||||
snapshot = objects.Snapshot.get_by_id(context, snapshot_id)
|
||||
request_spec['resource_backend'] = vol_utils.extract_host(
|
||||
snapshot.volume.host)
|
||||
request_spec['resource_backend'] = snapshot.volume.host
|
||||
elif source_volid:
|
||||
source_volume_ref = objects.Volume.get_by_id(context, source_volid)
|
||||
request_spec['resource_backend'] = vol_utils.extract_host(
|
||||
source_volume_ref.host)
|
||||
request_spec['resource_backend'] = source_volume_ref.host
|
||||
|
||||
self.scheduler_rpcapi.create_volume(
|
||||
context,
|
||||
|
Loading…
x
Reference in New Issue
Block a user