]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Volume types need to be specified when creating CG
authorXing Yang <xing.yang@emc.com>
Sat, 6 Sep 2014 17:32:02 +0000 (13:32 -0400)
committerXing Yang <xing.yang@emc.com>
Sat, 13 Sep 2014 18:36:03 +0000 (14:36 -0400)
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

cinder/api/contrib/consistencygroups.py
cinder/consistencygroup/api.py
cinder/scheduler/manager.py
cinder/tests/api/contrib/test_consistencygroups.py
cinder/tests/api/v2/test_volumes.py
cinder/tests/scheduler/test_scheduler.py
cinder/volume/api.py

index 9ae8863c02f8dac9d90bf7a5d8980f7ace9edad7..6b09f868b21d16aba085481b0b4bcaf97f74fae6 100644 (file)
@@ -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)
index bda01e4fa5eb08a8f8e02dfd5ddb03fb8ed8f1f0..a4dfead0fbe174019c6c1ead8cfd40563f4924d2 100644 (file)
@@ -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
 
index 68a022e2475f844df4aa0f31dd3e6eff3dd961b1..9376713840acdb256136e356974c92d845467dbb 100644 (file)
@@ -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'})
 
index 18a183c0bc0bfe78e4249679806f1f3bd113eb46..11889e25d3cb4a368f46b4b800aaaf2c930825b5 100644 (file)
@@ -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(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(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(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('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('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'])
index ca94c4fea4e4abf91719525f2eb4d8808f86ec58..1fded8937ead48e008e368e24967981aa25c18e2 100644 (file)
@@ -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(),
index 42c7180eeade4d0462fd5b38bd795a0691a5ae94..c7497c98c54c93f3248de7668aa5377a9b2855c4 100644 (file)
@@ -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."""
index 8bbe004aedf948fdb9d4166ec9f6e2ddc6045e60..e06ee1d08ac9276b6719c796631e7dd77be95836 100644 (file)
@@ -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: