199 lines
7.8 KiB
Python
199 lines
7.8 KiB
Python
# Copyright 2020 Red Hat Inc.
|
|
# 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 create_volume in the TaskFlow volume.flow.api"""
|
|
|
|
import ddt
|
|
import mock
|
|
|
|
from cinder import context
|
|
from cinder import exception
|
|
from cinder import test
|
|
from cinder.volume.flows.api import create_volume
|
|
from cinder.volume import volume_types
|
|
|
|
|
|
@ddt.ddt
|
|
class ExtractVolumeRequestTaskValidationsTestCase(test.TestCase):
|
|
"""Test validation code.
|
|
|
|
The ExtractVolumeRequestTask takes a set of inputs that will form a
|
|
volume-create request and validates them, inferring values for "missing"
|
|
inputs.
|
|
|
|
This class tests the validation code, not the Task itself.
|
|
"""
|
|
|
|
def setUp(self):
|
|
super(ExtractVolumeRequestTaskValidationsTestCase, self).setUp()
|
|
self.context = context.get_admin_context()
|
|
|
|
fake_vol_type = 'vt-from-volume_type'
|
|
fake_source_vol = {'volume_type_id': 'vt-from-source_vol'}
|
|
fake_snapshot = {'volume_type_id': 'vt-from-snapshot'}
|
|
fake_img_vol_type_id = 'vt-from-image_volume_type_id'
|
|
fake_config_value = 'vt-from-config-value'
|
|
|
|
big_ass_data_tuple = (
|
|
# case 0: null params and no configured default should
|
|
# result in the system default volume type
|
|
{'param_vol_type': None,
|
|
'param_source_vol': None,
|
|
'param_snap': None,
|
|
'param_img_vol_type_id': None,
|
|
'config_value': None,
|
|
'expected_vol_type': volume_types.DEFAULT_VOLUME_TYPE},
|
|
# case set 1: if a volume_type is passed, should always be selected
|
|
{'param_vol_type': fake_vol_type,
|
|
'param_source_vol': None,
|
|
'param_snap': None,
|
|
'param_img_vol_type_id': None,
|
|
'config_value': None,
|
|
'expected_vol_type': 'vt-from-volume_type'},
|
|
{'param_vol_type': fake_vol_type,
|
|
'param_source_vol': fake_source_vol,
|
|
'param_snap': fake_snapshot,
|
|
'param_img_vol_type_id': fake_img_vol_type_id,
|
|
'config_value': fake_config_value,
|
|
'expected_vol_type': 'vt-from-volume_type'},
|
|
# case set 2: if no volume_type is passed, the vt from the
|
|
# source_volume should be selected
|
|
{'param_vol_type': None,
|
|
'param_source_vol': fake_source_vol,
|
|
'param_snap': None,
|
|
'param_img_vol_type_id': None,
|
|
'config_value': None,
|
|
'expected_vol_type': 'vt-from-source_vol'},
|
|
{'param_vol_type': None,
|
|
'param_source_vol': fake_source_vol,
|
|
'param_snap': fake_snapshot,
|
|
'param_img_vol_type_id': fake_img_vol_type_id,
|
|
'config_value': fake_config_value,
|
|
'expected_vol_type': 'vt-from-source_vol'},
|
|
# case set 3: no volume_type, no source_volume, so snapshot's type
|
|
# should be selected
|
|
{'param_vol_type': None,
|
|
'param_source_vol': None,
|
|
'param_snap': fake_snapshot,
|
|
'param_img_vol_type_id': None,
|
|
'config_value': None,
|
|
'expected_vol_type': 'vt-from-snapshot'},
|
|
{'param_vol_type': None,
|
|
'param_source_vol': None,
|
|
'param_snap': fake_snapshot,
|
|
'param_img_vol_type_id': fake_img_vol_type_id,
|
|
'config_value': fake_config_value,
|
|
'expected_vol_type': 'vt-from-snapshot'},
|
|
# case set 4: no volume_type, no source_volume, no snapshot --
|
|
# use the volume_type from the image metadata
|
|
{'param_vol_type': None,
|
|
'param_source_vol': None,
|
|
'param_snap': None,
|
|
'param_img_vol_type_id': fake_img_vol_type_id,
|
|
'config_value': None,
|
|
'expected_vol_type': 'vt-from-image_volume_type_id'},
|
|
{'param_vol_type': None,
|
|
'param_source_vol': None,
|
|
'param_snap': None,
|
|
'param_img_vol_type_id': fake_img_vol_type_id,
|
|
'config_value': fake_config_value,
|
|
'expected_vol_type': 'vt-from-image_volume_type_id'},
|
|
# case 5: params all null, should use configured volume_type
|
|
{'param_vol_type': None,
|
|
'param_source_vol': None,
|
|
'param_snap': None,
|
|
'param_img_vol_type_id': None,
|
|
'config_value': fake_config_value,
|
|
'expected_vol_type': 'vt-from-config-value'})
|
|
|
|
def reflect_second(a, b):
|
|
return b
|
|
|
|
@ddt.data(*big_ass_data_tuple)
|
|
@mock.patch('cinder.objects.VolumeType.get_by_name_or_id',
|
|
side_effect = reflect_second)
|
|
@mock.patch('cinder.volume.volume_types.get_volume_type_by_name',
|
|
side_effect = reflect_second)
|
|
@ddt.unpack
|
|
def test__get_volume_type(self,
|
|
mock_get_volume_type_by_name,
|
|
mock_get_by_name_or_id,
|
|
param_vol_type,
|
|
param_source_vol,
|
|
param_snap,
|
|
param_img_vol_type_id,
|
|
config_value,
|
|
expected_vol_type):
|
|
|
|
self.flags(default_volume_type=config_value)
|
|
|
|
test_fn = create_volume.ExtractVolumeRequestTask._get_volume_type
|
|
|
|
self.assertEqual(expected_vol_type,
|
|
test_fn(self.context,
|
|
param_vol_type,
|
|
param_source_vol,
|
|
param_snap,
|
|
param_img_vol_type_id))
|
|
|
|
# Before the Train release, an invalid volume type specifier
|
|
# would not raise an exception; it would log an error and you'd
|
|
# get a volume with volume_type == None. We want to verify that
|
|
# specifying a non-existent volume_type always raises an exception
|
|
smaller_data_tuple = (
|
|
{'param_source_vol': fake_source_vol,
|
|
'param_snap': None,
|
|
'param_img_vol_type_id': None,
|
|
'config_value': None},
|
|
{'param_source_vol': None,
|
|
'param_snap': fake_snapshot,
|
|
'param_img_vol_type_id': None,
|
|
'config_value': None},
|
|
{'param_source_vol': None,
|
|
'param_snap': None,
|
|
'param_img_vol_type_id': fake_img_vol_type_id,
|
|
'config_value': None},
|
|
{'param_source_vol': None,
|
|
'param_snap': None,
|
|
'param_img_vol_type_id': None,
|
|
'config_value': fake_config_value})
|
|
|
|
@ddt.data(*smaller_data_tuple)
|
|
@mock.patch('cinder.objects.VolumeType.get_by_name_or_id',
|
|
side_effect = exception.VolumeTypeNotFoundByName(
|
|
volume_type_name="get_by_name_or_id"))
|
|
@mock.patch('cinder.volume.volume_types.get_volume_type_by_name',
|
|
side_effect = exception.VolumeTypeNotFoundByName(
|
|
volume_type_name="get_by_name"))
|
|
@ddt.unpack
|
|
def test_neg_get_volume_type(self,
|
|
mock_get_volume_type_by_name,
|
|
mock_get_by_name_or_id,
|
|
param_source_vol,
|
|
param_snap,
|
|
param_img_vol_type_id,
|
|
config_value):
|
|
|
|
self.flags(default_volume_type=config_value)
|
|
|
|
test_fn = create_volume.ExtractVolumeRequestTask._get_volume_type
|
|
|
|
self.assertRaises(exception.VolumeTypeNotFoundByName,
|
|
test_fn,
|
|
self.context,
|
|
None,
|
|
param_source_vol,
|
|
param_snap,
|
|
param_img_vol_type_id)
|