Esempio n. 1
0
    def delete(self, context, group, force=False):
        if not group.host:
            self.update_quota(context, group, -1, group.project_id)

            LOG.debug(
                "No host for consistency group %s. Deleting from "
                "the database.", group.id)
            group.destroy()

            return

        if not force and group.status not in ([
                c_fields.ConsistencyGroupStatus.AVAILABLE,
                c_fields.ConsistencyGroupStatus.ERROR
        ]):
            msg = _("Consistency group status must be available or error, "
                    "but current status is: %s") % group.status
            raise exception.InvalidConsistencyGroup(reason=msg)

        cgsnapshots = objects.CGSnapshotList.get_all_by_group(
            context.elevated(), group.id)
        if cgsnapshots:
            msg = _("Consistency group %s still has dependent "
                    "cgsnapshots.") % group.id
            LOG.error(msg)
            raise exception.InvalidConsistencyGroup(reason=msg)

        volumes = self.db.volume_get_all_by_group(context.elevated(), group.id)

        if volumes and not force:
            msg = _("Consistency group %s still contains volumes. "
                    "The force flag is required to delete it.") % group.id
            LOG.error(msg)
            raise exception.InvalidConsistencyGroup(reason=msg)

        for volume in volumes:
            if volume['attach_status'] == "attached":
                msg = _("Volume in consistency group %s is attached. "
                        "Need to detach first.") % group.id
                LOG.error(msg)
                raise exception.InvalidConsistencyGroup(reason=msg)

            snapshots = objects.SnapshotList.get_all_for_volume(
                context, volume['id'])
            if snapshots:
                msg = _("Volume in consistency group still has "
                        "dependent snapshots.")
                LOG.error(msg)
                raise exception.InvalidConsistencyGroup(reason=msg)

        group.status = c_fields.ConsistencyGroupStatus.DELETING
        group.terminated_at = timeutils.utcnow()
        group.save()

        self.volume_rpcapi.delete_consistencygroup(context, group)
Esempio n. 2
0
    def delete(self, context, group, force=False):
        if not group['host']:
            self.update_quota(context, group['id'], -1, group['project_id'])

            msg = ("No host for consistency group %s. Deleting from "
                   "the database.") % group['id']
            LOG.debug(msg)
            self.db.consistencygroup_destroy(context.elevated(), group['id'])

            return

        if not force and group['status'] not in ["available", "error"]:
            msg = _("Consistency group status must be available or error, "
                    "but current status is: %s") % group['status']
            raise exception.InvalidConsistencyGroup(reason=msg)

        cgsnaps = self.db.cgsnapshot_get_all_by_group(context.elevated(),
                                                      group['id'])
        if cgsnaps:
            msg = _("Consistency group %s still has dependent "
                    "cgsnapshots.") % group['id']
            LOG.error(msg)
            raise exception.InvalidConsistencyGroup(reason=msg)

        volumes = self.db.volume_get_all_by_group(context.elevated(),
                                                  group['id'])

        if volumes and not force:
            msg = _("Consistency group %s still contains volumes. "
                    "The force flag is required to delete it.") % group['id']
            LOG.error(msg)
            raise exception.InvalidConsistencyGroup(reason=msg)

        for volume in volumes:
            if volume['attach_status'] == "attached":
                msg = _("Volume in consistency group %s is attached. "
                        "Need to detach first.") % group['id']
                LOG.error(msg)
                raise exception.InvalidConsistencyGroup(reason=msg)

            snapshots = self.db.snapshot_get_all_for_volume(
                context, volume['id'])
            if snapshots:
                msg = _("Volume in consistency group still has "
                        "dependent snapshots.")
                LOG.error(msg)
                raise exception.InvalidConsistencyGroup(reason=msg)

        now = timeutils.utcnow()
        self.db.consistencygroup_update(context, group['id'], {
            'status': 'deleting',
            'terminated_at': now
        })

        self.volume_rpcapi.delete_consistencygroup(context, group)
Esempio n. 3
0
    def _create_cg_from_cgsnapshot(self, context, group, cgsnapshot):
        try:
            snapshots = objects.SnapshotList.get_all_for_cgsnapshot(
                context, cgsnapshot.id)

            if not snapshots:
                msg = _("Cgsnahost is empty. No consistency group "
                        "will be created.")
                raise exception.InvalidConsistencyGroup(reason=msg)

            for snapshot in snapshots:
                kwargs = {}
                kwargs['availability_zone'] = group.availability_zone
                kwargs['cgsnapshot'] = cgsnapshot
                kwargs['consistencygroup'] = group
                kwargs['snapshot'] = snapshot
                volume_type_id = snapshot.volume_type_id
                if volume_type_id:
                    kwargs['volume_type'] = volume_types.get_volume_type(
                        context, volume_type_id)

                # Since cgsnapshot is passed in, the following call will
                # create a db entry for the volume, but will not call the
                # volume manager to create a real volume in the backend yet.
                # If error happens, taskflow will handle rollback of quota
                # and removal of volume entry in the db.
                try:
                    self.volume_api.create(context, snapshot.volume_size, None,
                                           None, **kwargs)
                except exception.CinderException:
                    with excutils.save_and_reraise_exception():
                        LOG.error(
                            _LE("Error occurred when creating volume "
                                "entry from snapshot in the process of "
                                "creating consistency group %(group)s "
                                "from cgsnapshot %(cgsnap)s."), {
                                    'group': group.id,
                                    'cgsnap': cgsnapshot.id
                                })
        except Exception:
            with excutils.save_and_reraise_exception():
                try:
                    group.destroy()
                finally:
                    LOG.error(
                        _LE("Error occurred when creating consistency "
                            "group %(group)s from cgsnapshot "
                            "%(cgsnap)s."), {
                                'group': group.id,
                                'cgsnap': cgsnapshot.id
                            })

        volumes = self.db.volume_get_all_by_group(context, group.id)
        for vol in volumes:
            # Update the host field for the volume.
            self.db.volume_update(context, vol['id'],
                                  {'host': group.get('host')})

        self.volume_rpcapi.create_consistencygroup_from_src(
            context, group, cgsnapshot)
Esempio n. 4
0
    def _create_cg_from_source_cg(self, context, group, source_cg):
        try:
            source_vols = self.db.volume_get_all_by_group(context,
                                                          source_cg.id)

            if not source_vols:
                msg = _("Source CG is empty. No consistency group "
                        "will be created.")
                raise exception.InvalidConsistencyGroup(reason=msg)

            for source_vol in source_vols:
                kwargs = {}
                kwargs['availability_zone'] = group.availability_zone
                kwargs['source_cg'] = source_cg
                kwargs['consistencygroup'] = group
                kwargs['source_volume'] = source_vol
                volume_type_id = source_vol.get('volume_type_id')
                if volume_type_id:
                    kwargs['volume_type'] = volume_types.get_volume_type(
                        context, volume_type_id)

                # Since source_cg is passed in, the following call will
                # create a db entry for the volume, but will not call the
                # volume manager to create a real volume in the backend yet.
                # If error happens, taskflow will handle rollback of quota
                # and removal of volume entry in the db.
                try:
                    self.volume_api.create(context,
                                           source_vol['size'],
                                           None,
                                           None,
                                           **kwargs)
                except exception.CinderException:
                    with excutils.save_and_reraise_exception():
                        LOG.error(_LE("Error occurred when creating cloned "
                                      "volume in the process of creating "
                                      "consistency group %(group)s from "
                                      "source CG %(source_cg)s."),
                                  {'group': group.id,
                                   'source_cg': source_cg.id})
        except Exception:
            with excutils.save_and_reraise_exception():
                try:
                    group.destroy()
                finally:
                    LOG.error(_LE("Error occurred when creating consistency "
                                  "group %(group)s from source CG "
                                  "%(source_cg)s."),
                              {'group': group.id,
                               'source_cg': source_cg.id})

        volumes = self.db.volume_get_all_by_group(context,
                                                  group.id)
        for vol in volumes:
            # Update the host field for the volume.
            self.db.volume_update(context, vol['id'],
                                  {'host': group.host})

        self.volume_rpcapi.create_consistencygroup_from_src(context, group,
                                                            None, source_cg)
Esempio n. 5
0
    def delete(self, context, group, force=False):
        if not group.host:
            self.update_quota(context, group, -1, group.project_id)

            LOG.debug("No host for consistency group %s. Deleting from "
                      "the database.", group.id)
            group.destroy()

            return

        if force:
            expected = {}
        else:
            expected = {'status': (c_fields.ConsistencyGroupStatus.AVAILABLE,
                                   c_fields.ConsistencyGroupStatus.ERROR)}
        filters = [~db.cg_has_cgsnapshot_filter(),
                   ~db.cg_has_volumes_filter(attached_or_with_snapshots=force),
                   ~db.cg_creating_from_src(cg_id=group.id)]
        values = {'status': c_fields.ConsistencyGroupStatus.DELETING}

        if not group.conditional_update(values, expected, filters):
            if force:
                reason = _('Consistency group must not have attached volumes, '
                           'volumes with snapshots, or dependent cgsnapshots')
            else:
                reason = _('Consistency group status must be available or '
                           'error and must not have volumes or dependent '
                           'cgsnapshots')
            msg = (_('Cannot delete consistency group %(id)s. %(reason)s, and '
                     'it cannot be the source for an ongoing CG or CG '
                     'Snapshot creation.')
                   % {'id': group.id, 'reason': reason})
            raise exception.InvalidConsistencyGroup(reason=msg)
        self.volume_rpcapi.delete_consistencygroup(context, group)
Esempio n. 6
0
 def _check_update(self, group, name, description, add_volumes,
                   remove_volumes, allow_empty=False):
     if allow_empty:
         if (name is None and description is None
                 and not add_volumes and not remove_volumes):
             msg = (_("Cannot update consistency group %(group_id)s "
                      "because no valid name, description, add_volumes, "
                      "or remove_volumes were provided.") %
                    {'group_id': group.id})
             raise exception.InvalidConsistencyGroup(reason=msg)
     else:
         if not (name or description or add_volumes or remove_volumes):
             msg = (_("Cannot update consistency group %(group_id)s "
                      "because no valid name, description, add_volumes, "
                      "or remove_volumes were provided.") %
                    {'group_id': group.id})
             raise exception.InvalidConsistencyGroup(reason=msg)
Esempio n. 7
0
    def create_from_src(self, context, name, description=None,
                        cgsnapshot_id=None, source_cgid=None):
        check_policy(context, 'create')

        kwargs = {
            'user_id': context.user_id,
            'project_id': context.project_id,
            'status': c_fields.ConsistencyGroupStatus.CREATING,
            'name': name,
            'description': description,
            'cgsnapshot_id': cgsnapshot_id,
            'source_cgid': source_cgid,
        }

        group = None
        try:
            group = objects.ConsistencyGroup(context=context, **kwargs)
            group.create(cg_snap_id=cgsnapshot_id, cg_id=source_cgid)
        except exception.ConsistencyGroupNotFound:
            with excutils.save_and_reraise_exception():
                LOG.error(_LE("Source CG %(source_cg)s not found when "
                              "creating consistency group %(cg)s from "
                              "source."),
                          {'cg': name, 'source_cg': source_cgid})
        except exception.CgSnapshotNotFound:
            with excutils.save_and_reraise_exception():
                LOG.error(_LE("CG snapshot %(cgsnap)s not found when creating "
                              "consistency group %(cg)s from source."),
                          {'cg': name, 'cgsnap': cgsnapshot_id})
        except Exception:
            with excutils.save_and_reraise_exception():
                LOG.error(_LE("Error occurred when creating consistency group"
                              " %(cg)s from cgsnapshot %(cgsnap)s."),
                          {'cg': name, 'cgsnap': cgsnapshot_id})

        # Update quota for consistencygroups
        self.update_quota(context, group, 1)

        if not group.host:
            msg = _("No host to create consistency group %s.") % group.id
            LOG.error(msg)
            raise exception.InvalidConsistencyGroup(reason=msg)

        if cgsnapshot_id:
            self._create_cg_from_cgsnapshot(context, group, cgsnapshot_id)
        elif source_cgid:
            self._create_cg_from_source_cg(context, group, source_cgid)

        return group
Esempio n. 8
0
    def create_from_src(self, context, name, description, cgsnapshot_id):
        check_policy(context, 'create')

        cgsnapshot = None
        orig_cg = None
        if cgsnapshot_id:
            cgsnapshot = self.db.cgsnapshot_get(context, cgsnapshot_id)
            if cgsnapshot:
                orig_cg = self.db.consistencygroup_get(
                    context, cgsnapshot['consistencygroup_id'])

        options = {
            'user_id': context.user_id,
            'project_id': context.project_id,
            'status': "creating",
            'name': name,
            'description': description,
            'cgsnapshot_id': cgsnapshot_id
        }

        if orig_cg:
            options['volume_type_id'] = orig_cg.get('volume_type_id')
            options['availability_zone'] = orig_cg.get('availability_zone')
            options['host'] = orig_cg.get('host')

        group = None
        try:
            group = self.db.consistencygroup_create(context, options)
        except Exception:
            with excutils.save_and_reraise_exception():
                LOG.error(
                    _LE("Error occurred when creating consistency group"
                        " %(cg)s from cgsnapshot %(cgsnap)s."), {
                            'cg': name,
                            'cgsnap': cgsnapshot_id
                        })

        # Update quota for consistencygroups
        self.update_quota(context, group['id'], 1)

        if not group['host']:
            msg = _("No host to create consistency group %s.") % group['id']
            LOG.error(msg)
            raise exception.InvalidConsistencyGroup(reason=msg)

        self._create_cg_from_cgsnapshot(context, group, cgsnapshot)

        return group
Esempio n. 9
0
    def _extract_consistencygroup(consistencygroup):
        """Extracts the consistencygroup id from the provided consistencygroup.

        This function validates the input consistencygroup dict and checks that
        the status of that consistencygroup is valid for creating a volume in.
        """

        consistencygroup_id = None
        if consistencygroup is not None:
            if consistencygroup['status'] not in CG_PROCEED_STATUS:
                msg = _("Originating consistencygroup status must be one"
                        " of '%s' values")
                msg = msg % (", ".join(CG_PROCEED_STATUS))
                raise exception.InvalidConsistencyGroup(reason=msg)
            consistencygroup_id = consistencygroup['id']
        return consistencygroup_id
Esempio n. 10
0
    def _create_cgsnapshot(self, context, group, name, description):
        volumes = self.db.volume_get_all_by_group(context.elevated(), group.id)

        if not volumes:
            msg = _("Consistency group is empty. No cgsnapshot "
                    "will be created.")
            raise exception.InvalidConsistencyGroup(reason=msg)

        options = {
            'consistencygroup_id': group.id,
            'user_id': context.user_id,
            'project_id': context.project_id,
            'status': "creating",
            'name': name,
            'description': description
        }

        cgsnapshot = None
        cgsnapshot_id = None
        try:
            cgsnapshot = objects.CGSnapshot(context, **options)
            cgsnapshot.create()
            cgsnapshot_id = cgsnapshot.id

            snap_name = cgsnapshot.name
            snap_desc = cgsnapshot.description
            self.volume_api.create_snapshots_in_db(context, volumes, snap_name,
                                                   snap_desc, True,
                                                   cgsnapshot_id)

        except Exception:
            with excutils.save_and_reraise_exception():
                try:
                    if cgsnapshot:
                        cgsnapshot.destroy()
                finally:
                    LOG.error(
                        _LE("Error occurred when creating cgsnapshot"
                            " %s."), cgsnapshot_id)

        self.volume_rpcapi.create_cgsnapshot(context, cgsnapshot)

        return cgsnapshot
Esempio n. 11
0
    def update(self,
               context,
               group,
               name,
               description,
               add_volumes,
               remove_volumes,
               allow_empty=False):
        """Update consistency group."""
        add_volumes_list = []
        remove_volumes_list = []
        if add_volumes:
            add_volumes = add_volumes.strip(',')
            add_volumes_list = add_volumes.split(',')
        if remove_volumes:
            remove_volumes = remove_volumes.strip(',')
            remove_volumes_list = remove_volumes.split(',')

        invalid_uuids = []
        for uuid in add_volumes_list:
            if uuid in remove_volumes_list:
                invalid_uuids.append(uuid)
        if invalid_uuids:
            msg = _("UUIDs %s are in both add and remove volume "
                    "list.") % invalid_uuids
            raise exception.InvalidVolume(reason=msg)

        # Validate name.
        if name == group.name:
            name = None

        # Validate description.
        if description == group.description:
            description = None
        self._check_update(group, name, description, add_volumes,
                           remove_volumes, allow_empty)

        fields = {'updated_at': timeutils.utcnow()}

        # Update name and description in db now. No need to
        # to send them over through an RPC call.
        if allow_empty:
            if name is not None:
                fields['name'] = name
            if description is not None:
                fields['description'] = description
        else:
            if name:
                fields['name'] = name
            if description:
                fields['description'] = description

        # NOTE(geguileo): We will use the updating status in the CG as a lock
        # mechanism to prevent volume add/remove races with other API, while we
        # figure out if we really need to add or remove volumes.
        if add_volumes or remove_volumes:
            fields['status'] = c_fields.ConsistencyGroupStatus.UPDATING

            # We cannot modify the members of this CG if the CG is being used
            # to create another CG or a CGsnapshot is being created
            filters = [
                ~db.cg_creating_from_src(cg_id=group.id),
                ~db.cgsnapshot_creating_from_src()
            ]
        else:
            filters = []

        expected = {'status': c_fields.ConsistencyGroupStatus.AVAILABLE}
        if not group.conditional_update(fields, expected, filters):
            msg = _("Cannot update consistency group %s, status must be "
                    "available, and it cannot be the source for an ongoing "
                    "CG or CG Snapshot creation.") % group.id
            raise exception.InvalidConsistencyGroup(reason=msg)

        # Now the CG is "locked" for updating
        try:
            # Validate volumes in add_volumes and remove_volumes.
            add_volumes_new = self._validate_add_volumes(
                context, group.volumes, add_volumes_list, group)
            remove_volumes_new = self._validate_remove_volumes(
                group.volumes, remove_volumes_list, group)

            self._check_update(group, name, description, add_volumes_new,
                               remove_volumes_new, allow_empty)
        except Exception:
            # If we have an error on the volume_lists we must return status to
            # available as we were doing before removing API races
            with excutils.save_and_reraise_exception():
                group.status = c_fields.ConsistencyGroupStatus.AVAILABLE
                group.save()

        # Do an RPC call only if the update request includes
        # adding/removing volumes. add_volumes_new and remove_volumes_new
        # are strings of volume UUIDs separated by commas with no spaces
        # in between.
        if add_volumes_new or remove_volumes_new:
            self.volume_rpcapi.update_consistencygroup(
                context,
                group,
                add_volumes=add_volumes_new,
                remove_volumes=remove_volumes_new)
        # If there are no new volumes to add or remove and we had changed
        # the status to updating, turn it back to available
        elif group.status == c_fields.ConsistencyGroupStatus.UPDATING:
            group.status = c_fields.ConsistencyGroupStatus.AVAILABLE
            group.save()
Esempio n. 12
0
    def update(self, context, group, name, description, add_volumes,
               remove_volumes):
        """Update consistency group."""
        if group.status != c_fields.ConsistencyGroupStatus.AVAILABLE:
            msg = _("Consistency group status must be available, "
                    "but current status is: %s.") % group.status
            raise exception.InvalidConsistencyGroup(reason=msg)

        add_volumes_list = []
        remove_volumes_list = []
        if add_volumes:
            add_volumes = add_volumes.strip(',')
            add_volumes_list = add_volumes.split(',')
        if remove_volumes:
            remove_volumes = remove_volumes.strip(',')
            remove_volumes_list = remove_volumes.split(',')

        invalid_uuids = []
        for uuid in add_volumes_list:
            if uuid in remove_volumes_list:
                invalid_uuids.append(uuid)
        if invalid_uuids:
            msg = _("UUIDs %s are in both add and remove volume "
                    "list.") % invalid_uuids
            raise exception.InvalidVolume(reason=msg)

        volumes = self.db.volume_get_all_by_group(context, group.id)

        # Validate name.
        if not name or name == group.name:
            name = None

        # Validate description.
        if not description or description == group.description:
            description = None

        # Validate volumes in add_volumes and remove_volumes.
        add_volumes_new = ""
        remove_volumes_new = ""
        if add_volumes_list:
            add_volumes_new = self._validate_add_volumes(
                context, volumes, add_volumes_list, group)
        if remove_volumes_list:
            remove_volumes_new = self._validate_remove_volumes(
                volumes, remove_volumes_list, group)

        if (not name and not description and not add_volumes_new
                and not remove_volumes_new):
            msg = (_("Cannot update consistency group %(group_id)s "
                     "because no valid name, description, add_volumes, "
                     "or remove_volumes were provided.") % {
                         'group_id': group.id
                     })
            raise exception.InvalidConsistencyGroup(reason=msg)

        fields = {'updated_at': timeutils.utcnow()}

        # Update name and description in db now. No need to
        # to send them over through an RPC call.
        if name:
            fields['name'] = name
        if description:
            fields['description'] = description
        if not add_volumes_new and not remove_volumes_new:
            # Only update name or description. Set status to available.
            fields['status'] = 'available'
        else:
            fields['status'] = 'updating'

        group.update(fields)
        group.save()

        # Do an RPC call only if the update request includes
        # adding/removing volumes. add_volumes_new and remove_volumes_new
        # are strings of volume UUIDs separated by commas with no spaces
        # in between.
        if add_volumes_new or remove_volumes_new:
            self.volume_rpcapi.update_consistencygroup(
                context,
                group,
                add_volumes=add_volumes_new,
                remove_volumes=remove_volumes_new)
Esempio n. 13
0
    def create_from_src(self,
                        context,
                        name,
                        description=None,
                        cgsnapshot_id=None,
                        source_cgid=None):
        check_policy(context, 'create')
        cgsnapshot = None
        orig_cg = None
        if cgsnapshot_id:
            try:
                cgsnapshot = objects.CGSnapshot.get_by_id(
                    context, cgsnapshot_id)
            except exception.CgSnapshotNotFound:
                with excutils.save_and_reraise_exception():
                    LOG.error(
                        _LE("CG snapshot %(cgsnap)s not found when "
                            "creating consistency group %(cg)s from "
                            "source."), {
                                'cg': name,
                                'cgsnap': cgsnapshot_id
                            })
            else:
                orig_cg = cgsnapshot.consistencygroup

        source_cg = None
        if source_cgid:
            try:
                source_cg = objects.ConsistencyGroup.get_by_id(
                    context, source_cgid)
            except exception.ConsistencyGroupNotFound:
                with excutils.save_and_reraise_exception():
                    LOG.error(
                        _LE("Source CG %(source_cg)s not found when "
                            "creating consistency group %(cg)s from "
                            "source."), {
                                'cg': name,
                                'source_cg': source_cgid
                            })

        kwargs = {
            'user_id': context.user_id,
            'project_id': context.project_id,
            'status': c_fields.ConsistencyGroupStatus.CREATING,
            'name': name,
            'description': description,
            'cgsnapshot_id': cgsnapshot_id,
            'source_cgid': source_cgid,
        }

        if orig_cg:
            kwargs['volume_type_id'] = orig_cg.volume_type_id
            kwargs['availability_zone'] = orig_cg.availability_zone
            kwargs['host'] = orig_cg.host

        if source_cg:
            kwargs['volume_type_id'] = source_cg.volume_type_id
            kwargs['availability_zone'] = source_cg.availability_zone
            kwargs['host'] = source_cg.host

        group = None
        try:
            group = objects.ConsistencyGroup(context=context, **kwargs)
            group.create()
        except Exception:
            with excutils.save_and_reraise_exception():
                LOG.error(
                    _LE("Error occurred when creating consistency group"
                        " %(cg)s from cgsnapshot %(cgsnap)s."), {
                            'cg': name,
                            'cgsnap': cgsnapshot_id
                        })

        # Update quota for consistencygroups
        self.update_quota(context, group, 1)

        if not group.host:
            msg = _("No host to create consistency group %s.") % group.id
            LOG.error(msg)
            raise exception.InvalidConsistencyGroup(reason=msg)

        if cgsnapshot:
            self._create_cg_from_cgsnapshot(context, group, cgsnapshot)
        elif source_cg:
            self._create_cg_from_source_cg(context, group, source_cg)

        return group
Esempio n. 14
0
    def _create_cg_from_source_cg(self, context, group, source_cgid):
        try:
            source_cg = objects.ConsistencyGroup.get_by_id(
                context, source_cgid)
            source_vols = self.db.volume_get_all_by_group(
                context, source_cg.id)

            if not source_vols:
                msg = _("Source CG is empty. No consistency group "
                        "will be created.")
                raise exception.InvalidConsistencyGroup(reason=msg)

            try:
                values = {'volumes': len(source_vols)}
                QUOTAS.limit_check(context,
                                   project_id=context.project_id,
                                   **values)
            except exception.OverQuota as e:
                group.destroy()
                quotas = e.kwargs['quotas']
                raise exception.VolumeLimitExceeded(allowed=e.kwargs['overs'],
                                                    limit=quotas['volumes'])

            for source_vol in source_vols:
                kwargs = {}
                kwargs['availability_zone'] = group.availability_zone
                kwargs['source_cg'] = source_cg
                kwargs['consistencygroup'] = group
                kwargs['source_volume'] = source_vol
                volume_type_id = source_vol.get('volume_type_id')
                if volume_type_id:
                    kwargs['volume_type'] = (
                        objects.VolumeType.get_by_name_or_id(
                            context, volume_type_id))

                # Since source_cg is passed in, the following call will
                # create a db entry for the volume, but will not call the
                # volume manager to create a real volume in the backend yet.
                # If error happens, taskflow will handle rollback of quota
                # and removal of volume entry in the db.
                try:
                    self.volume_api.create(context, source_vol['size'], None,
                                           None, **kwargs)
                except exception.CinderException:
                    with excutils.save_and_reraise_exception():
                        LOG.error(
                            "Error occurred when creating cloned "
                            "volume in the process of creating "
                            "consistency group %(group)s from "
                            "source CG %(source_cg)s.", {
                                'group': group.id,
                                'source_cg': source_cg.id
                            })
        except Exception:
            with excutils.save_and_reraise_exception():
                try:
                    new_vols = self.db.volume_get_all_by_group(
                        context, group.id)
                    for vol in new_vols:
                        self.volume_api.delete(context, vol, force=True)
                    group.destroy()
                finally:
                    LOG.error(
                        "Error occurred when creating consistency "
                        "group %(group)s from source CG "
                        "%(source_cg)s.", {
                            'group': group.id,
                            'source_cg': source_cg.id
                        })

        volumes = self.db.volume_get_all_by_group(context, group.id)
        for vol in volumes:
            # Update the host field for the volume.
            self.db.volume_update(context, vol['id'], {'host': group.host})

        self.volume_rpcapi.create_consistencygroup_from_src(
            context, group, None, source_cg)