Volume types need to be specified when creating CG
When creating a consistency group, the scheduler will find a backend that supports all input volume types. If volume types are not provided, the default_volume_type in cinder.conf will be used, however, this could cause inconsistent behavior in a user environment where the default_volume_type is defined in some places but not in others. This fix removed the use of default_volume_type for CG creation, added a check to verify that volume types are provided when creating a CG. When creating a volume and adding it to a CG, we need to make sure a volume type is provided as well. Change-Id: I078d4fdd8d92529e853be16272ad74d1e130f712 Closes-Bug: #1366371
This commit is contained in:
parent
52df6822f6
commit
9082273305
@ -125,11 +125,10 @@ class ConsistencyGroupsController(wsgi.Controller):
|
||||
group = self.consistencygroup_api.get(context, id)
|
||||
self.consistencygroup_api.delete(context, group, force)
|
||||
except exception.ConsistencyGroupNotFound:
|
||||
msg = _("Consistency group could not be found")
|
||||
msg = _("Consistency group %s could not be found.") % id
|
||||
raise exc.HTTPNotFound(explanation=msg)
|
||||
except exception.InvalidConsistencyGroup:
|
||||
msg = _("Invalid consistency group")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
except exception.InvalidConsistencyGroup as error:
|
||||
raise exc.HTTPBadRequest(explanation=error.msg)
|
||||
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@ -176,6 +175,10 @@ class ConsistencyGroupsController(wsgi.Controller):
|
||||
name = consistencygroup.get('name', None)
|
||||
description = consistencygroup.get('description', None)
|
||||
volume_types = consistencygroup.get('volume_types', None)
|
||||
if not volume_types:
|
||||
msg = _("volume_types must be provided to create "
|
||||
"consistency group %(name)s.") % {'name': name}
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
availability_zone = consistencygroup.get('availability_zone', None)
|
||||
|
||||
LOG.info(_("Creating consistency group %(name)s."),
|
||||
@ -184,7 +187,7 @@ class ConsistencyGroupsController(wsgi.Controller):
|
||||
|
||||
try:
|
||||
new_consistencygroup = self.consistencygroup_api.create(
|
||||
context, name, description, cg_volume_types=volume_types,
|
||||
context, name, description, volume_types,
|
||||
availability_zone=availability_zone)
|
||||
except exception.InvalidConsistencyGroup as error:
|
||||
raise exc.HTTPBadRequest(explanation=error.msg)
|
||||
|
@ -104,27 +104,20 @@ class API(base.Base):
|
||||
return availability_zone
|
||||
|
||||
def create(self, context, name, description,
|
||||
cg_volume_types=None, availability_zone=None):
|
||||
cg_volume_types, availability_zone=None):
|
||||
|
||||
check_policy(context, 'create')
|
||||
volume_type_list = None
|
||||
if cg_volume_types:
|
||||
volume_type_list = cg_volume_types.split(',')
|
||||
volume_type_list = cg_volume_types.split(',')
|
||||
|
||||
req_volume_types = []
|
||||
if volume_type_list:
|
||||
req_volume_types = (self.db.volume_types_get_by_name_or_id(
|
||||
context, volume_type_list))
|
||||
|
||||
if not req_volume_types:
|
||||
volume_type = volume_types.get_default_volume_type()
|
||||
req_volume_types.append(volume_type)
|
||||
req_volume_types = (self.db.volume_types_get_by_name_or_id(
|
||||
context, volume_type_list))
|
||||
|
||||
req_volume_type_ids = ""
|
||||
for voltype in req_volume_types:
|
||||
if voltype:
|
||||
req_volume_type_ids = (
|
||||
req_volume_type_ids + voltype.get('id') + ",")
|
||||
req_volume_type_ids = (
|
||||
req_volume_type_ids + voltype.get('id') + ",")
|
||||
if len(req_volume_type_ids) == 0:
|
||||
req_volume_type_ids = None
|
||||
|
||||
|
@ -96,18 +96,18 @@ class SchedulerManager(manager.Manager):
|
||||
context, group_id,
|
||||
request_spec_list,
|
||||
filter_properties_list)
|
||||
except exception.NoValidHost as ex:
|
||||
except exception.NoValidHost:
|
||||
msg = (_("Could not find a host for consistency group "
|
||||
"%(group_id)s.") %
|
||||
{'group_id': group_id})
|
||||
LOG.error(msg)
|
||||
db.consistencygroup_update(context, group_id,
|
||||
{'status': 'error'})
|
||||
except Exception as ex:
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_("Failed to create consistency group "
|
||||
"%(group_id)s."))
|
||||
LOG.exception(ex)
|
||||
LOG.exception(_("Failed to create consistency group "
|
||||
"%(group_id)s."),
|
||||
{'group_id': group_id})
|
||||
db.consistencygroup_update(context, group_id,
|
||||
{'status': 'error'})
|
||||
|
||||
|
@ -26,6 +26,7 @@ import webob
|
||||
import cinder.consistencygroup
|
||||
from cinder import context
|
||||
from cinder import db
|
||||
from cinder.i18n import _
|
||||
from cinder import test
|
||||
from cinder.tests.api import fakes
|
||||
|
||||
@ -73,14 +74,15 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
res_dict = json.loads(res.body)
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
self.assertEqual(res_dict['consistencygroup']['availability_zone'],
|
||||
'az1')
|
||||
self.assertEqual(res_dict['consistencygroup']['description'],
|
||||
'this is a test consistency group')
|
||||
self.assertEqual(res_dict['consistencygroup']['name'],
|
||||
'test_consistencygroup')
|
||||
self.assertEqual(res_dict['consistencygroup']['status'], 'creating')
|
||||
self.assertEqual(200, res.status_int)
|
||||
self.assertEqual('az1',
|
||||
res_dict['consistencygroup']['availability_zone'])
|
||||
self.assertEqual('this is a test consistency group',
|
||||
res_dict['consistencygroup']['description'])
|
||||
self.assertEqual('test_consistencygroup',
|
||||
res_dict['consistencygroup']['name'])
|
||||
self.assertEqual('creating',
|
||||
res_dict['consistencygroup']['status'])
|
||||
|
||||
db.consistencygroup_destroy(context.get_admin_context(),
|
||||
consistencygroup_id)
|
||||
@ -93,11 +95,11 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
req.headers['Content-Type'] = 'application/xml'
|
||||
req.headers['Accept'] = 'application/xml'
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
self.assertEqual(res.status_int, 200)
|
||||
self.assertEqual(200, res.status_int)
|
||||
dom = minidom.parseString(res.body)
|
||||
consistencygroup = dom.getElementsByTagName('consistencygroup')
|
||||
name = consistencygroup.item(0).getAttribute('name')
|
||||
self.assertEqual(name.strip(), "test_consistencygroup")
|
||||
self.assertEqual("test_consistencygroup", name.strip())
|
||||
db.consistencygroup_destroy(
|
||||
context.get_admin_context(),
|
||||
consistencygroup_id)
|
||||
@ -109,10 +111,10 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
res_dict = json.loads(res.body)
|
||||
|
||||
self.assertEqual(res.status_int, 404)
|
||||
self.assertEqual(res_dict['itemNotFound']['code'], 404)
|
||||
self.assertEqual(res_dict['itemNotFound']['message'],
|
||||
'ConsistencyGroup 9999 could not be found.')
|
||||
self.assertEqual(404, res.status_int)
|
||||
self.assertEqual(404, res_dict['itemNotFound']['code'])
|
||||
self.assertEqual('ConsistencyGroup 9999 could not be found.',
|
||||
res_dict['itemNotFound']['message'])
|
||||
|
||||
def test_list_consistencygroups_json(self):
|
||||
consistencygroup_id1 = self._create_consistencygroup()
|
||||
@ -125,19 +127,19 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
res_dict = json.loads(res.body)
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
self.assertEqual(res_dict['consistencygroups'][0]['id'],
|
||||
consistencygroup_id1)
|
||||
self.assertEqual(res_dict['consistencygroups'][0]['name'],
|
||||
'test_consistencygroup')
|
||||
self.assertEqual(res_dict['consistencygroups'][1]['id'],
|
||||
consistencygroup_id2)
|
||||
self.assertEqual(res_dict['consistencygroups'][1]['name'],
|
||||
'test_consistencygroup')
|
||||
self.assertEqual(res_dict['consistencygroups'][2]['id'],
|
||||
consistencygroup_id3)
|
||||
self.assertEqual(res_dict['consistencygroups'][2]['name'],
|
||||
'test_consistencygroup')
|
||||
self.assertEqual(200, res.status_int)
|
||||
self.assertEqual(consistencygroup_id1,
|
||||
res_dict['consistencygroups'][0]['id'])
|
||||
self.assertEqual('test_consistencygroup',
|
||||
res_dict['consistencygroups'][0]['name'])
|
||||
self.assertEqual(consistencygroup_id2,
|
||||
res_dict['consistencygroups'][1]['id'])
|
||||
self.assertEqual('test_consistencygroup',
|
||||
res_dict['consistencygroups'][1]['name'])
|
||||
self.assertEqual(consistencygroup_id3,
|
||||
res_dict['consistencygroups'][2]['id'])
|
||||
self.assertEqual('test_consistencygroup',
|
||||
res_dict['consistencygroups'][2]['name'])
|
||||
|
||||
db.consistencygroup_destroy(context.get_admin_context(),
|
||||
consistencygroup_id3)
|
||||
@ -157,16 +159,16 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
req.headers['Accept'] = 'application/xml'
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
self.assertEqual(200, res.status_int)
|
||||
dom = minidom.parseString(res.body)
|
||||
consistencygroup_list = dom.getElementsByTagName('consistencygroup')
|
||||
|
||||
self.assertEqual(consistencygroup_list.item(0).getAttribute('id'),
|
||||
consistencygroup_id1)
|
||||
self.assertEqual(consistencygroup_list.item(1).getAttribute('id'),
|
||||
consistencygroup_id2)
|
||||
self.assertEqual(consistencygroup_list.item(2).getAttribute('id'),
|
||||
consistencygroup_id3)
|
||||
self.assertEqual(consistencygroup_id1,
|
||||
consistencygroup_list.item(0).getAttribute('id'))
|
||||
self.assertEqual(consistencygroup_id2,
|
||||
consistencygroup_list.item(1).getAttribute('id'))
|
||||
self.assertEqual(consistencygroup_id3,
|
||||
consistencygroup_list.item(2).getAttribute('id'))
|
||||
|
||||
db.consistencygroup_destroy(context.get_admin_context(),
|
||||
consistencygroup_id3)
|
||||
@ -187,39 +189,39 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
res_dict = json.loads(res.body)
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
self.assertEqual(res_dict['consistencygroups'][0]['availability_zone'],
|
||||
'az1')
|
||||
self.assertEqual(res_dict['consistencygroups'][0]['description'],
|
||||
'this is a test consistency group')
|
||||
self.assertEqual(res_dict['consistencygroups'][0]['name'],
|
||||
'test_consistencygroup')
|
||||
self.assertEqual(res_dict['consistencygroups'][0]['id'],
|
||||
consistencygroup_id1)
|
||||
self.assertEqual(res_dict['consistencygroups'][0]['status'],
|
||||
'creating')
|
||||
self.assertEqual(200, res.status_int)
|
||||
self.assertEqual('az1',
|
||||
res_dict['consistencygroups'][0]['availability_zone'])
|
||||
self.assertEqual('this is a test consistency group',
|
||||
res_dict['consistencygroups'][0]['description'])
|
||||
self.assertEqual('test_consistencygroup',
|
||||
res_dict['consistencygroups'][0]['name'])
|
||||
self.assertEqual(consistencygroup_id1,
|
||||
res_dict['consistencygroups'][0]['id'])
|
||||
self.assertEqual('creating',
|
||||
res_dict['consistencygroups'][0]['status'])
|
||||
|
||||
self.assertEqual(res_dict['consistencygroups'][1]['availability_zone'],
|
||||
'az1')
|
||||
self.assertEqual(res_dict['consistencygroups'][1]['description'],
|
||||
'this is a test consistency group')
|
||||
self.assertEqual(res_dict['consistencygroups'][1]['name'],
|
||||
'test_consistencygroup')
|
||||
self.assertEqual(res_dict['consistencygroups'][1]['id'],
|
||||
consistencygroup_id2)
|
||||
self.assertEqual(res_dict['consistencygroups'][1]['status'],
|
||||
'creating')
|
||||
self.assertEqual('az1',
|
||||
res_dict['consistencygroups'][1]['availability_zone'])
|
||||
self.assertEqual('this is a test consistency group',
|
||||
res_dict['consistencygroups'][1]['description'])
|
||||
self.assertEqual('test_consistencygroup',
|
||||
res_dict['consistencygroups'][1]['name'])
|
||||
self.assertEqual(consistencygroup_id2,
|
||||
res_dict['consistencygroups'][1]['id'])
|
||||
self.assertEqual('creating',
|
||||
res_dict['consistencygroups'][1]['status'])
|
||||
|
||||
self.assertEqual(res_dict['consistencygroups'][2]['availability_zone'],
|
||||
'az1')
|
||||
self.assertEqual(res_dict['consistencygroups'][2]['description'],
|
||||
'this is a test consistency group')
|
||||
self.assertEqual(res_dict['consistencygroups'][2]['name'],
|
||||
'test_consistencygroup')
|
||||
self.assertEqual(res_dict['consistencygroups'][2]['id'],
|
||||
consistencygroup_id3)
|
||||
self.assertEqual(res_dict['consistencygroups'][2]['status'],
|
||||
'creating')
|
||||
self.assertEqual('az1',
|
||||
res_dict['consistencygroups'][2]['availability_zone'])
|
||||
self.assertEqual('this is a test consistency group',
|
||||
res_dict['consistencygroups'][2]['description'])
|
||||
self.assertEqual('test_consistencygroup',
|
||||
res_dict['consistencygroups'][2]['name'])
|
||||
self.assertEqual(consistencygroup_id3,
|
||||
res_dict['consistencygroups'][2]['id'])
|
||||
self.assertEqual('creating',
|
||||
res_dict['consistencygroups'][2]['status'])
|
||||
|
||||
db.consistencygroup_destroy(context.get_admin_context(),
|
||||
consistencygroup_id3)
|
||||
@ -239,54 +241,57 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
req.headers['Accept'] = 'application/xml'
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
self.assertEqual(200, res.status_int)
|
||||
dom = minidom.parseString(res.body)
|
||||
consistencygroup_detail = dom.getElementsByTagName('consistencygroup')
|
||||
|
||||
self.assertEqual(
|
||||
consistencygroup_detail.item(0).getAttribute('availability_zone'),
|
||||
'az1')
|
||||
'az1',
|
||||
consistencygroup_detail.item(0).getAttribute('availability_zone'))
|
||||
self.assertEqual(
|
||||
consistencygroup_detail.item(0).getAttribute('description'),
|
||||
'this is a test consistency group')
|
||||
'this is a test consistency group',
|
||||
consistencygroup_detail.item(0).getAttribute('description'))
|
||||
self.assertEqual(
|
||||
consistencygroup_detail.item(0).getAttribute('name'),
|
||||
'test_consistencygroup')
|
||||
'test_consistencygroup',
|
||||
consistencygroup_detail.item(0).getAttribute('name'))
|
||||
self.assertEqual(
|
||||
consistencygroup_detail.item(0).getAttribute('id'),
|
||||
consistencygroup_id1)
|
||||
consistencygroup_id1,
|
||||
consistencygroup_detail.item(0).getAttribute('id'))
|
||||
self.assertEqual(
|
||||
consistencygroup_detail.item(0).getAttribute('status'), 'creating')
|
||||
'creating',
|
||||
consistencygroup_detail.item(0).getAttribute('status'))
|
||||
|
||||
self.assertEqual(
|
||||
consistencygroup_detail.item(1).getAttribute('availability_zone'),
|
||||
'az1')
|
||||
'az1',
|
||||
consistencygroup_detail.item(1).getAttribute('availability_zone'))
|
||||
self.assertEqual(
|
||||
consistencygroup_detail.item(1).getAttribute('description'),
|
||||
'this is a test consistency group')
|
||||
'this is a test consistency group',
|
||||
consistencygroup_detail.item(1).getAttribute('description'))
|
||||
self.assertEqual(
|
||||
consistencygroup_detail.item(1).getAttribute('name'),
|
||||
'test_consistencygroup')
|
||||
'test_consistencygroup',
|
||||
consistencygroup_detail.item(1).getAttribute('name'))
|
||||
self.assertEqual(
|
||||
consistencygroup_detail.item(1).getAttribute('id'),
|
||||
consistencygroup_id2)
|
||||
consistencygroup_id2,
|
||||
consistencygroup_detail.item(1).getAttribute('id'))
|
||||
self.assertEqual(
|
||||
consistencygroup_detail.item(1).getAttribute('status'), 'creating')
|
||||
'creating',
|
||||
consistencygroup_detail.item(1).getAttribute('status'))
|
||||
|
||||
self.assertEqual(
|
||||
consistencygroup_detail.item(2).getAttribute('availability_zone'),
|
||||
'az1')
|
||||
'az1',
|
||||
consistencygroup_detail.item(2).getAttribute('availability_zone'))
|
||||
self.assertEqual(
|
||||
consistencygroup_detail.item(2).getAttribute('description'),
|
||||
'this is a test consistency group')
|
||||
'this is a test consistency group',
|
||||
consistencygroup_detail.item(2).getAttribute('description'))
|
||||
self.assertEqual(
|
||||
consistencygroup_detail.item(2).getAttribute('name'),
|
||||
'test_consistencygroup')
|
||||
'test_consistencygroup',
|
||||
consistencygroup_detail.item(2).getAttribute('name'))
|
||||
self.assertEqual(
|
||||
consistencygroup_detail.item(2).getAttribute('id'),
|
||||
consistencygroup_id3)
|
||||
consistencygroup_id3,
|
||||
consistencygroup_detail.item(2).getAttribute('id'))
|
||||
self.assertEqual(
|
||||
consistencygroup_detail.item(2).getAttribute('status'), 'creating')
|
||||
'creating',
|
||||
consistencygroup_detail.item(2).getAttribute('status'))
|
||||
|
||||
db.consistencygroup_destroy(context.get_admin_context(),
|
||||
consistencygroup_id3)
|
||||
@ -297,7 +302,14 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
|
||||
def test_create_consistencygroup_json(self):
|
||||
group_id = "1"
|
||||
|
||||
# Create volume type
|
||||
vol_type = 'test'
|
||||
db.volume_type_create(context.get_admin_context(),
|
||||
{'name': vol_type, 'extra_specs': {}})
|
||||
|
||||
body = {"consistencygroup": {"name": "cg1",
|
||||
"volume_types": vol_type,
|
||||
"description":
|
||||
"Consistency Group 1", }}
|
||||
req = webob.Request.blank('/v2/fake/consistencygroups')
|
||||
@ -307,7 +319,7 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
res_dict = json.loads(res.body)
|
||||
|
||||
self.assertEqual(res.status_int, 202)
|
||||
self.assertEqual(202, res.status_int)
|
||||
self.assertIn('id', res_dict['consistencygroup'])
|
||||
|
||||
db.consistencygroup_destroy(context.get_admin_context(), group_id)
|
||||
@ -322,11 +334,11 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
res_dict = json.loads(res.body)
|
||||
|
||||
self.assertEqual(res.status_int, 400)
|
||||
self.assertEqual(res_dict['badRequest']['code'], 400)
|
||||
self.assertEqual(res_dict['badRequest']['message'],
|
||||
'The server could not comply with the request since'
|
||||
' it is either malformed or otherwise incorrect.')
|
||||
self.assertEqual(400, res.status_int)
|
||||
self.assertEqual(400, res_dict['badRequest']['code'])
|
||||
self.assertEqual('The server could not comply with the request since'
|
||||
' it is either malformed or otherwise incorrect.',
|
||||
res_dict['badRequest']['message'])
|
||||
|
||||
def test_delete_consistencygroup_available(self):
|
||||
consistencygroup_id = self._create_consistencygroup(status='available')
|
||||
@ -338,10 +350,10 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
req.body = json.dumps(body)
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
|
||||
self.assertEqual(res.status_int, 202)
|
||||
self.assertEqual(self._get_consistencygroup_attrib(consistencygroup_id,
|
||||
'status'),
|
||||
'deleting')
|
||||
self.assertEqual(202, res.status_int)
|
||||
self.assertEqual('deleting',
|
||||
self._get_consistencygroup_attrib(consistencygroup_id,
|
||||
'status'))
|
||||
|
||||
db.consistencygroup_destroy(context.get_admin_context(),
|
||||
consistencygroup_id)
|
||||
@ -354,10 +366,10 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
res_dict = json.loads(res.body)
|
||||
|
||||
self.assertEqual(res.status_int, 404)
|
||||
self.assertEqual(res_dict['itemNotFound']['code'], 404)
|
||||
self.assertEqual(res_dict['itemNotFound']['message'],
|
||||
'Consistency group could not be found')
|
||||
self.assertEqual(404, res.status_int)
|
||||
self.assertEqual(404, res_dict['itemNotFound']['code'])
|
||||
self.assertEqual('Consistency group 9999 could not be found.',
|
||||
res_dict['itemNotFound']['message'])
|
||||
|
||||
def test_delete_consistencygroup_with_Invalidconsistencygroup(self):
|
||||
consistencygroup_id = self._create_consistencygroup(status='invalid')
|
||||
@ -370,10 +382,11 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
res_dict = json.loads(res.body)
|
||||
|
||||
self.assertEqual(res.status_int, 400)
|
||||
self.assertEqual(res_dict['badRequest']['code'], 400)
|
||||
self.assertEqual(res_dict['badRequest']['message'],
|
||||
'Invalid consistency group')
|
||||
self.assertEqual(400, res.status_int)
|
||||
self.assertEqual(400, res_dict['badRequest']['code'])
|
||||
msg = (_('Invalid ConsistencyGroup: Consistency group status must be '
|
||||
'available or error, but current status is: invalid'))
|
||||
self.assertEqual(msg, res_dict['badRequest']['message'])
|
||||
|
||||
db.consistencygroup_destroy(context.get_admin_context(),
|
||||
consistencygroup_id)
|
||||
@ -425,3 +438,21 @@ class ConsistencyGroupsAPITestCase(test.TestCase):
|
||||
context.get_admin_context(read_deleted='yes'),
|
||||
cg['id'])
|
||||
self.assertEqual(cg['status'], 'deleted')
|
||||
|
||||
def test_create_consistencygroup_failed_no_volume_type(self):
|
||||
name = 'cg1'
|
||||
body = {"consistencygroup": {"name": name,
|
||||
"description":
|
||||
"Consistency Group 1", }}
|
||||
req = webob.Request.blank('/v2/fake/consistencygroups')
|
||||
req.method = 'POST'
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.body = json.dumps(body)
|
||||
res = req.get_response(fakes.wsgi_app())
|
||||
res_dict = json.loads(res.body)
|
||||
|
||||
self.assertEqual(400, res.status_int)
|
||||
self.assertEqual(400, res_dict['badRequest']['code'])
|
||||
msg = (_('volume_types must be provided to create '
|
||||
'consistency group %s.') % name)
|
||||
self.assertEqual(msg, res_dict['badRequest']['message'])
|
||||
|
@ -115,6 +115,36 @@ class VolumeApiTest(test.TestCase):
|
||||
'encrypted': False}}
|
||||
self.assertEqual(res_dict, ex)
|
||||
|
||||
def test_volume_create_with_consistencygroup_invalid_type(self):
|
||||
ctxt = context.RequestContext('fake', 'fake', auth_token=True)
|
||||
vol_type = db.volume_type_create(
|
||||
context.get_admin_context(),
|
||||
dict(name=CONF.default_volume_type, extra_specs={})
|
||||
)
|
||||
db_vol_type = db.volume_type_get(context.get_admin_context(),
|
||||
vol_type.id)
|
||||
cg = {
|
||||
'id': '1',
|
||||
'name': 'cg1',
|
||||
'volume_type_id': db_vol_type['id'],
|
||||
}
|
||||
fake_type = {
|
||||
'id': '9999',
|
||||
'name': 'fake',
|
||||
}
|
||||
vol_api = volume_api.API()
|
||||
|
||||
self.assertRaises(exception.InvalidInput,
|
||||
vol_api.create,
|
||||
ctxt, 1, 'vol1', 'volume 1',
|
||||
consistencygroup=cg)
|
||||
|
||||
self.assertRaises(exception.InvalidInput,
|
||||
vol_api.create,
|
||||
ctxt, 1, 'vol1', 'volume 1',
|
||||
volume_type=fake_type,
|
||||
consistencygroup=cg)
|
||||
|
||||
def test_volume_create_with_type(self):
|
||||
vol_type = db.volume_type_create(
|
||||
context.get_admin_context(),
|
||||
|
@ -22,7 +22,10 @@ import mock
|
||||
from oslo.config import cfg
|
||||
|
||||
from cinder import context
|
||||
from cinder import db
|
||||
from cinder import exception
|
||||
from cinder.i18n import _
|
||||
from cinder.openstack.common import log as logging
|
||||
from cinder.scheduler import driver
|
||||
from cinder.scheduler import filter_scheduler
|
||||
from cinder.scheduler import manager
|
||||
@ -188,6 +191,46 @@ class SchedulerManagerTestCase(test.TestCase):
|
||||
{'status': 'in-use'})
|
||||
self.manager.driver.find_retype_host = orig_retype
|
||||
|
||||
def test_create_consistencygroup_exceptions(self):
|
||||
with mock.patch.object(filter_scheduler.FilterScheduler,
|
||||
'schedule_create_consistencygroup') as mock_cg:
|
||||
original_driver = self.manager.driver
|
||||
self.manager.driver = filter_scheduler.FilterScheduler
|
||||
LOG = logging.getLogger('cinder.scheduler.manager')
|
||||
self.stubs.Set(LOG, 'error', mock.Mock())
|
||||
self.stubs.Set(LOG, 'exception', mock.Mock())
|
||||
self.stubs.Set(db, 'consistencygroup_update', mock.Mock())
|
||||
|
||||
ex = exception.CinderException('test')
|
||||
mock_cg.side_effect = ex
|
||||
group_id = '1'
|
||||
self.assertRaises(exception.CinderException,
|
||||
self.manager.create_consistencygroup,
|
||||
self.context,
|
||||
'volume',
|
||||
group_id)
|
||||
LOG.exception.assert_called_once_with(_(
|
||||
"Failed to create consistency group "
|
||||
"%(group_id)s."), {'group_id': group_id})
|
||||
db.consistencygroup_update.assert_called_once_with(
|
||||
self.context, group_id, {'status': 'error'})
|
||||
|
||||
mock_cg.reset_mock()
|
||||
LOG.exception.reset_mock()
|
||||
db.consistencygroup_update.reset_mock()
|
||||
|
||||
mock_cg.side_effect = exception.NoValidHost(
|
||||
reason="No weighed hosts available")
|
||||
self.manager.create_consistencygroup(
|
||||
self.context, 'volume', group_id)
|
||||
LOG.error.assert_called_once_with(_(
|
||||
"Could not find a host for consistency group "
|
||||
"%(group_id)s.") % {'group_id': group_id})
|
||||
db.consistencygroup_update.assert_called_once_with(
|
||||
self.context, group_id, {'status': 'error'})
|
||||
|
||||
self.manager.driver = original_driver
|
||||
|
||||
|
||||
class SchedulerTestCase(test.TestCase):
|
||||
"""Test case for base scheduler driver class."""
|
||||
|
@ -155,11 +155,15 @@ class API(base.Base):
|
||||
scheduler_hints=None, backup_source_volume=None,
|
||||
source_replica=None, consistencygroup=None):
|
||||
|
||||
if volume_type and consistencygroup:
|
||||
if consistencygroup:
|
||||
if not volume_type:
|
||||
msg = _("volume_type must be provided when creating "
|
||||
"a volume in a consistency group.")
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
cg_voltypeids = consistencygroup.get('volume_type_id')
|
||||
if volume_type.get('id') not in cg_voltypeids:
|
||||
msg = _("Invalid volume_type provided (requested type "
|
||||
"must be supported by this consistency group.")
|
||||
"must be supported by this consistency group).")
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
if source_volume and volume_type:
|
||||
|
Loading…
x
Reference in New Issue
Block a user