Пример #1
0
    def create_group_snapshot(self, context, group_snapshot, snapshots):
        """Creates a Cinder group snapshot object.

        The Cinder group snapshot object is created by making use of an ONTAP
        consistency group snapshot in order to provide write-order consistency
        for a set of flexvols snapshots. First, a list of the flexvols backing
        the given Cinder group must be gathered. An ONTAP group-snapshot of
        these flexvols will create a snapshot copy of all the Cinder volumes in
        the generic volume group. For each Cinder volume in the group, it is
        then necessary to clone its backing file from the ONTAP cg-snapshot.
        The naming convention used to for the clones is what indicates the
        clone's role as a Cinder snapshot and its inclusion in a Cinder group.
        The ONTAP cg-snapshot of the flexvols is deleted after the cloning
        operation is completed.

        :returns: An implicit update for the group snapshot and snapshot models
                 that is then used by the manager to set the models to
                 available.
        """
        try:
            if volume_utils.is_group_a_cg_snapshot_type(group_snapshot):
                self._create_consistent_group_snapshot(group_snapshot,
                                                       snapshots)
            else:
                for snapshot in snapshots:
                    self._clone_backing_file_for_volume(
                        snapshot['volume_name'], snapshot['name'],
                        snapshot['volume_id'], is_snapshot=True)
        except Exception as ex:
            err_msg = (_("Create group snapshot failed (%s).") % ex)
            LOG.exception(err_msg, resource=group_snapshot)
            raise na_utils.NetAppDriverException(err_msg)

        return None, None
Пример #2
0
    def create_group_from_src(self,
                              context,
                              group,
                              volumes,
                              group_snapshot=None,
                              snapshots=None,
                              source_group=None,
                              source_vols=None):
        """Creates a group from source."""
        # The source is either group_snapshot+snapshots or
        # source_group+source_vols. The target is group+volumes
        # we assume the source (source_vols / snapshots) are in the same
        # order as the target (volumes)

        # let generic volume group support handle non-cgsnapshots
        if not volume_utils.is_group_a_cg_snapshot_type(group):
            raise NotImplementedError()
        self.create_group(context, group)
        new_infinidat_group = self._get_infinidat_cg(group)
        if group_snapshot is not None and snapshots is not None:
            for volume, snapshot in zip(volumes, snapshots):
                self.create_volume_from_snapshot(volume, snapshot)
                new_infinidat_volume = self._get_infinidat_volume(volume)
                new_infinidat_group.add_member(new_infinidat_volume)
        elif source_group is not None and source_vols is not None:
            for volume, src_vol in zip(volumes, source_vols):
                self.create_cloned_volume(volume, src_vol)
                new_infinidat_volume = self._get_infinidat_volume(volume)
                new_infinidat_group.add_member(new_infinidat_volume)
        return None, None
Пример #3
0
 def create_group(self, context, group):
     """Creates a group."""
     # let generic volume group support handle non-cgsnapshots
     if not volume_utils.is_group_a_cg_snapshot_type(group):
         raise NotImplementedError()
     obj = self._system.cons_groups.create(name=self._make_cg_name(group),
                                           pool=self._get_infinidat_pool())
     self._set_cinder_object_metadata(obj, group)
     return {'status': fields.GroupStatus.AVAILABLE}
Пример #4
0
    def inner(self, *args, **kwargs):
        # Only used to decorating the second argument is `group`
        if volume_utils.is_group_a_cg_snapshot_type(args[1]):
            return func(self, *args, **kwargs)

        LOG.debug('Group is not a consistency group. Unity driver does '
                  'nothing.')
        # This exception will let cinder handle it as a generic group
        raise NotImplementedError()
Пример #5
0
 def update_group(self, group, add_volumes=None):
     if add_volumes and volume_utils.is_group_a_cg_snapshot_type(group):
         for volume in add_volumes:
             ldev = utils.get_ldev(volume)
             if ldev is None:
                 msg = utils.output_log(MSG.LDEV_NOT_EXIST_FOR_ADD_GROUP,
                                        volume_id=volume.id,
                                        group='consistency group',
                                        group_id=group.id)
                 self.raise_error(msg)
     return None, None, None
Пример #6
0
 def delete_group(self, context, group, volumes):
     """Deletes a group."""
     # let generic volume group support handle non-cgsnapshots
     if not volume_utils.is_group_a_cg_snapshot_type(group):
         raise NotImplementedError()
     try:
         infinidat_cg = self._get_infinidat_cg(group)
     except exception.InvalidGroup:
         pass  # group not found
     else:
         infinidat_cg.safe_delete()
     for volume in volumes:
         self.delete_volume(volume)
     return None, None
Пример #7
0
 def delete_group_snapshot(self, context, group_snapshot, snapshots):
     """Deletes a group_snapshot."""
     # let generic volume group support handle non-cgsnapshots
     if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot):
         raise NotImplementedError()
     cgsnap_name = self._make_group_snapshot_name(group_snapshot)
     infinidat_cgsnap = self._system.cons_groups.safe_get(name=cgsnap_name)
     if infinidat_cgsnap is not None:
         if not infinidat_cgsnap.is_snapgroup():
             msg = _('Group "%s" is not a snapshot group') % cgsnap_name
             LOG.error(msg)
             raise exception.InvalidGroupSnapshot(message=msg)
         infinidat_cgsnap.safe_delete()
     for snapshot in snapshots:
         self.delete_snapshot(snapshot)
     return None, None
Пример #8
0
    def create_group(self, context, group):
        """Driver entry point for creating a generic volume group.

        ONTAP does not maintain an actual group construct. As a result, no
        communtication to the backend is necessary for generic volume group
        creation.

        :returns: Hard-coded model update for generic volume group model.
        """
        model_update = {'status': fields.GroupStatus.AVAILABLE}
        if (self._is_flexgroup(host=group['host'])
                and volume_utils.is_group_a_cg_snapshot_type(group)):
            msg = _("Cannot create %s consistency group on FlexGroup pool.")
            raise na_utils.NetAppDriverException(msg % group['id'])

        return model_update
Пример #9
0
 def create_group_snapshot(self, context, group_snapshot, snapshots):
     """Creates a group_snapshot."""
     # let generic volume group support handle non-cgsnapshots
     if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot):
         raise NotImplementedError()
     infinidat_cg = self._get_infinidat_cg(group_snapshot.group)
     group_snap_name = self._make_group_snapshot_name(group_snapshot)
     new_group = infinidat_cg.create_snapshot(name=group_snap_name)
     # update the names of the individual snapshots in the new snapgroup
     # to match the names we use for cinder snapshots
     for infinidat_snapshot in new_group.get_members():
         parent_name = infinidat_snapshot.get_parent().get_name()
         for cinder_snapshot in snapshots:
             if cinder_snapshot.volume_id in parent_name:
                 snapshot_name = self._make_snapshot_name(cinder_snapshot)
                 infinidat_snapshot.update_name(snapshot_name)
     return None, None
Пример #10
0
 def update_group(self,
                  context,
                  group,
                  add_volumes=None,
                  remove_volumes=None):
     """Updates a group."""
     # let generic volume group support handle non-cgsnapshots
     if not volume_utils.is_group_a_cg_snapshot_type(group):
         raise NotImplementedError()
     add_volumes = add_volumes if add_volumes else []
     remove_volumes = remove_volumes if remove_volumes else []
     infinidat_cg = self._get_infinidat_cg(group)
     for vol in add_volumes:
         infinidat_volume = self._get_infinidat_volume(vol)
         infinidat_cg.add_member(infinidat_volume)
     for vol in remove_volumes:
         infinidat_volume = self._get_infinidat_volume(vol)
         infinidat_cg.remove_member(infinidat_volume)
     return None, None, None
Пример #11
0
    def update_group(self,
                     context,
                     group,
                     add_volumes=None,
                     remove_volumes=None):
        """Driver entry point for updating a generic volume group.

        Since no actual group construct is ever created in ONTAP, it is not
        necessary to update any metadata on the backend. Since this is a NO-OP,
        there is guaranteed to be no change in any of the volumes' statuses.
        """
        if volume_utils.is_group_a_cg_snapshot_type(group):
            for vol in add_volumes:
                if self._is_flexgroup(host=vol['host']):
                    msg = _("Cannot add volume from FlexGroup pool to "
                            "consistency group.")
                    raise na_utils.NetAppDriverException(msg)

        return None, None, None
Пример #12
0
    def create_group_snapshot(self, context, group_snapshot, snapshots):
        """Creates a Cinder group snapshot object.

        The Cinder group snapshot object is created by making use of an ONTAP
        consistency group snapshot in order to provide write-order consistency
        for a set of flexvols snapshots. First, a list of the flexvols backing
        the given Cinder group must be gathered. An ONTAP group-snapshot of
        these flexvols will create a snapshot copy of all the Cinder volumes in
        the generic volume group. For each Cinder volume in the group, it is
        then necessary to clone its backing file from the ONTAP cg-snapshot.
        The naming convention used to for the clones is what indicates the
        clone's role as a Cinder snapshot and its inclusion in a Cinder group.
        The ONTAP cg-snapshot of the flexvols is deleted after the cloning
        operation is completed.

        :returns: An implicit update for the group snapshot and snapshot models
                 that is then used by the manager to set the models to
                 available.
        """
        try:
            if volume_utils.is_group_a_cg_snapshot_type(group_snapshot):
                # NOTE(felipe_rodrigues): ONTAP FlexGroup does not support
                # consistency group snapshot, so all members must be inside
                # a FlexVol pool.
                for snapshot in snapshots:
                    if self._is_flexgroup(host=snapshot['volume']['host']):
                        msg = _("Cannot create consistency group snapshot with"
                                " volumes on a FlexGroup pool.")
                        raise na_utils.NetAppDriverException(msg)

                self._create_consistent_group_snapshot(group_snapshot,
                                                       snapshots)
            else:
                for snapshot in snapshots:
                    self.create_snapshot(snapshot)
        except Exception as ex:
            err_msg = (_("Create group snapshot failed (%s).") % ex)
            LOG.exception(err_msg, resource=group_snapshot)
            raise na_utils.NetAppDriverException(err_msg)

        return None, None
Пример #13
0
    def create_group_from_src(self,
                              context,
                              group,
                              volumes,
                              group_snapshot=None,
                              sorted_snapshots=None,
                              source_group=None,
                              sorted_source_vols=None):
        """Creates a group from a group snapshot or a group of cinder vols.

        :returns: An implicit update for the volumes model that is
                 interpreted by the manager as a successful operation.
        """
        LOG.debug("VOLUMES %s ", ', '.join([vol['id'] for vol in volumes]))
        model_update = None
        volumes_model_update = []

        if group_snapshot:
            vols = zip(volumes, sorted_snapshots)

            for volume, snapshot in vols:
                update = self.create_volume_from_snapshot(volume, snapshot)
                update['id'] = volume['id']
                volumes_model_update.append(update)

        elif source_group and sorted_source_vols:
            hosts = []
            for source_vol in sorted_source_vols:
                # NOTE(felipe_rodrigues): ONTAP FlexGroup does not support
                # consistency group snapshot, so if any source volume is on a
                # FlexGroup, the operation must be create from a not-cg,
                # falling back to the generic group support.
                if self._is_flexgroup(host=source_vol['host']):
                    if volume_utils.is_group_a_cg_snapshot_type(group):
                        msg = _("Cannot create consistency group with volume "
                                "on a FlexGroup pool.")
                        raise na_utils.NetAppDriverException(msg)
                    else:
                        # falls back to generic support
                        raise NotImplementedError()
                hosts.append(source_vol['host'])

            flexvols = self._get_flexvol_names_from_hosts(hosts)

            # Create snapshot for backing flexvol
            snapshot_name = 'snapshot-temp-' + source_group['id']
            self.zapi_client.create_cg_snapshot(flexvols, snapshot_name)

            # Start clone process for new volumes
            vols = zip(volumes, sorted_source_vols)
            for volume, source_vol in vols:
                self._clone_backing_file_for_volume(
                    source_vol['name'],
                    volume['name'],
                    source_vol['id'],
                    source_snapshot=snapshot_name)
                volume_model_update = (self._get_volume_model_update(volume)
                                       or {})
                volume_model_update.update({
                    'id':
                    volume['id'],
                    'provider_location':
                    source_vol['provider_location'],
                })
                volumes_model_update.append(volume_model_update)

            # Delete backing flexvol snapshots
            for flexvol_name in flexvols:
                self.zapi_client.wait_for_busy_snapshot(
                    flexvol_name, snapshot_name)
                self.zapi_client.delete_snapshot(flexvol_name, snapshot_name)
        else:
            LOG.error("Unexpected set of parameters received when "
                      "creating group from source.")
            model_update = {'status': fields.GroupStatus.ERROR}

        return model_update, volumes_model_update
Пример #14
0
 def inner(self, *args, **kwargs):
     if not volume_utils.is_group_a_cg_snapshot_type(args[1]):
         raise NotImplementedError
     return func(self, *args, **kwargs)
Пример #15
0
 def is_in_cg(self):
     if self._is_in_cg is None:
         self._is_in_cg = (self._volume.group
                           and volume_utils.is_group_a_cg_snapshot_type(
                               self._volume.group))
     return self._is_in_cg
Пример #16
0
 def create_group_snapshot(self, context, group_snapshot, snapshots):
     if volume_utils.is_group_a_cg_snapshot_type(group_snapshot):
         return self._create_cgsnapshot(context, group_snapshot, snapshots)
     else:
         return self._create_non_cgsnapshot(group_snapshot, snapshots)