Example #1
0
 def test_extract_id_from_snapshot_name_no_match(self, conf_mock):
     conf_mock.snapshot_name_template = '%s-snapshot'
     snap_name = 'd8cd1feb-2dcc-404d-9b15-b86fe3bec0a1'
     result = volume_utils.extract_id_from_snapshot_name(snap_name)
     self.assertIsNone(result)
     snap_name = 'blahblahblah'
     result = volume_utils.extract_id_from_snapshot_name(snap_name)
     self.assertIsNone(result)
 def test_extract_id_from_snapshot_name_no_match(self, conf_mock):
     conf_mock.snapshot_name_template = '%s-snapshot'
     snap_name = 'd8cd1feb-2dcc-404d-9b15-b86fe3bec0a1'
     result = volume_utils.extract_id_from_snapshot_name(snap_name)
     self.assertIsNone(result)
     snap_name = 'blahblahblah'
     result = volume_utils.extract_id_from_snapshot_name(snap_name)
     self.assertIsNone(result)
    def _get_manageable_resource_info(self, cinder_resources, resource_type,
                                      marker, limit, offset, sort_keys,
                                      sort_dirs):
        entries = []
        cinder_ids = [resource['id'] for resource in cinder_resources]

        root_helper = utils.get_root_helper()
        try:
            out, err = self._execute('zfs',
                                     'list',
                                     '-r',
                                     '-H',
                                     '-p',
                                     '-t',
                                     resource_type,
                                     '-oname,volsize',
                                     self.zpool,
                                     root_helper=root_helper,
                                     run_as_root=True)
        except processutils.ProcessExecutionError as exc:
            exception_message = (_("Failed to zfs list, "
                                   "error message was: %s") %
                                 six.text_type(exc.stderr))
            raise exception.VolumeBackendAPIException(data=exception_message)

        for entry in out.splitlines():
            name, size = entry.strip().split('\t')
            if resource_type == 'volume':
                potential_id = volutils.extract_id_from_volume_name(name)
            else:
                potential_id = volutils.extract_id_from_snapshot_name(name)

            info = {
                'reference': {
                    'source-name': name
                },
                'size': int(math.ceil(float(size) / units.Gi)),
                'cinder_id': None,
                'extra_info': None
            }

            if potential_id in cinder_ids:
                info['safe_to_manage'] = False
                info['reason_not_safe'] = 'already managed'
                info['cinder_id'] = potential_id
            else:
                info['safe_to_manage'] = True
                info['reason_not_safe'] = None

            if resource_type == 'snapshot':
                zpool, zvol, snapshot = name.replace('@', '/').split('/')
                info['source_reference'] = {'source-name': zvol}

            entries.append(info)

        return volutils.paginate_entries_list(entries, marker, limit, offset,
                                              sort_keys, sort_dirs)
Example #4
0
    def _get_manageable_resource_info(self, cinder_resources, resource_type,
                                      marker, limit, offset, sort_keys,
                                      sort_dirs):
        entries = []
        lvs = self.vg.get_volumes()
        cinder_ids = [resource['id'] for resource in cinder_resources]

        for lv in lvs:
            is_snap = self.vg.lv_is_snapshot(lv['name'])
            if ((resource_type == 'volume' and is_snap)
                    or (resource_type == 'snapshot' and not is_snap)):
                continue

            if resource_type == 'volume':
                potential_id = volutils.extract_id_from_volume_name(lv['name'])
            else:
                unescape = self._unescape_snapshot(lv['name'])
                potential_id = volutils.extract_id_from_snapshot_name(unescape)
            lv_info = {
                'reference': {
                    'source-name': lv['name']
                },
                'size': int(math.ceil(float(lv['size']))),
                'cinder_id': None,
                'extra_info': None
            }

            if potential_id in cinder_ids:
                lv_info['safe_to_manage'] = False
                lv_info['reason_not_safe'] = 'already managed'
                lv_info['cinder_id'] = potential_id
            elif self.vg.lv_is_open(lv['name']):
                lv_info['safe_to_manage'] = False
                lv_info['reason_not_safe'] = '%s in use' % resource_type
            else:
                lv_info['safe_to_manage'] = True
                lv_info['reason_not_safe'] = None

            if resource_type == 'snapshot':
                origin = self.vg.lv_get_origin(lv['name'])
                lv_info['source_reference'] = {'source-name': origin}

            entries.append(lv_info)

        return volutils.paginate_entries_list(entries, marker, limit, offset,
                                              sort_keys, sort_dirs)
Example #5
0
File: lvm.py Project: NetApp/cinder
    def _get_manageable_resource_info(self, cinder_resources, resource_type,
                                      marker, limit, offset, sort_keys,
                                      sort_dirs):
        entries = []
        lvs = self.vg.get_volumes()
        cinder_ids = [resource['id'] for resource in cinder_resources]

        for lv in lvs:
            is_snap = self.vg.lv_is_snapshot(lv['name'])
            if ((resource_type == 'volume' and is_snap) or
                    (resource_type == 'snapshot' and not is_snap)):
                continue

            if resource_type == 'volume':
                potential_id = volutils.extract_id_from_volume_name(lv['name'])
            else:
                unescape = self._unescape_snapshot(lv['name'])
                potential_id = volutils.extract_id_from_snapshot_name(unescape)
            lv_info = {'reference': {'source-name': lv['name']},
                       'size': int(math.ceil(float(lv['size']))),
                       'cinder_id': None,
                       'extra_info': None}

            if potential_id in cinder_ids:
                lv_info['safe_to_manage'] = False
                lv_info['reason_not_safe'] = 'already managed'
                lv_info['cinder_id'] = potential_id
            elif self.vg.lv_is_open(lv['name']):
                lv_info['safe_to_manage'] = False
                lv_info['reason_not_safe'] = '%s in use' % resource_type
            else:
                lv_info['safe_to_manage'] = True
                lv_info['reason_not_safe'] = None

            if resource_type == 'snapshot':
                origin = self.vg.lv_get_origin(lv['name'])
                lv_info['source_reference'] = {'source-name': origin}

            entries.append(lv_info)

        return volutils.paginate_entries_list(entries, marker, limit, offset,
                                              sort_keys, sort_dirs)
Example #6
0
    def _get_manageable_resource_info(
        self, cinder_resources, resource_type, marker, limit, offset, sort_keys, sort_dirs
    ):
        entries = []
        lvs = self.vg.get_volumes()
        cinder_ids = [resource["id"] for resource in cinder_resources]

        for lv in lvs:
            is_snap = self.vg.lv_is_snapshot(lv["name"])
            if (resource_type == "volume" and is_snap) or (resource_type == "snapshot" and not is_snap):
                continue

            if resource_type == "volume":
                potential_id = volutils.extract_id_from_volume_name(lv["name"])
            else:
                unescape = self._unescape_snapshot(lv["name"])
                potential_id = volutils.extract_id_from_snapshot_name(unescape)
            lv_info = {
                "reference": {"source-name": lv["name"]},
                "size": int(math.ceil(float(lv["size"]))),
                "cinder_id": None,
                "extra_info": None,
            }

            if potential_id in cinder_ids:
                lv_info["safe_to_manage"] = False
                lv_info["reason_not_safe"] = "already managed"
                lv_info["cinder_id"] = potential_id
            elif self.vg.lv_is_open(lv["name"]):
                lv_info["safe_to_manage"] = False
                lv_info["reason_not_safe"] = "%s in use" % resource_type
            else:
                lv_info["safe_to_manage"] = True
                lv_info["reason_not_safe"] = None

            if resource_type == "snapshot":
                origin = self.vg.lv_get_origin(lv["name"])
                lv_info["source_reference"] = {"source-name": origin}

            entries.append(lv_info)

        return volutils.paginate_entries_list(entries, marker, limit, offset, sort_keys, sort_dirs)
Example #7
0
 def test_extract_id_from_snapshot_name(self, conf_mock):
     conf_mock.snapshot_name_template = '%s-snapshot'
     snap_id = 'd8cd1feb-2dcc-404d-9b15-b86fe3bec0a1'
     snap_name = conf_mock.snapshot_name_template % snap_id
     result = volume_utils.extract_id_from_snapshot_name(snap_name)
     self.assertEqual(snap_id, result)
Example #8
0
    def _get_manageable_resource_info(self, cinder_resources, resource_type,
                                      marker, limit, offset, sort_keys,
                                      sort_dirs):
        """Gets the resources on the backend available for management by Cinder.

        Receives the parameters from "get_manageable_volumes" and
        "get_manageable_snapshots" and gets the available resources

        :param cinder_resources: A list of resources in this host that Cinder
        currently manages
        :param resource_type: If it's a volume or a snapshot
        :param marker: The last item of the previous page; we return the
        next results after this value (after sorting)
        :param limit: Maximum number of items to return
        :param offset: Number of items to skip after marker
        :param sort_keys: List of keys to sort results by (valid keys
        are 'identifier' and 'size')
        :param sort_dirs: List of directions to sort by, corresponding to
        sort_keys (valid directions are 'asc' and 'desc')

        :returns: list of dictionaries, each specifying a volume or snapshot
        (resource) in the host, with the following keys:
            - reference (dictionary): The reference for a resource,
            which can be passed to "manage_existing_snapshot".
            - size (int): The size of the resource according to the storage
              backend, rounded up to the nearest GB.
            - safe_to_manage (boolean): Whether or not this resource is
            safe to manage according to the storage backend.
            - reason_not_safe (string): If safe_to_manage is False,
              the reason why.
            - cinder_id (string): If already managed, provide the Cinder ID.
            - extra_info (string): Any extra information to return to the
            user
            - source_reference (string): Similar to "reference", but for the
              snapshot's source volume.
        """

        entries = []
        exports = {}
        bend_rsrc = {}
        cinder_ids = [resource.id for resource in cinder_resources]

        for service in self.config['services']:
            exp_path = self.config['services'][service]['hdp']
            exports[exp_path] = (
                self.config['services'][service]['export']['fs'])

        for exp in exports.keys():
            # bend_rsrc has all the resources in the specified exports
            # volumes {u'172.24.54.39:/Export-Cinder':
            #   ['volume-325e7cdc-8f65-40a8-be9a-6172c12c9394',
            # '     snapshot-1bfb6f0d-9497-4c12-a052-5426a76cacdc','']}
            bend_rsrc[exp] = self._get_volumes_from_export(exp)
            mnt_point = self._get_mount_point_for_share(exp)

            for resource in bend_rsrc[exp]:
                # Ignoring resources of unwanted types
                if ((resource_type == 'volume' and
                     ('.' in resource or 'snapshot' in resource))
                        or (resource_type == 'snapshot' and '.' not in resource
                            and 'snapshot' not in resource)):
                    continue

                path = '%s/%s' % (exp, resource)
                mnt_path = '%s/%s' % (mnt_point, resource)
                size = self._get_file_size(mnt_path)

                rsrc_inf = {
                    'reference': {
                        'source-name': path
                    },
                    'size': size,
                    'cinder_id': None,
                    'extra_info': None
                }

                if resource_type == 'volume':
                    potential_id = utils.extract_id_from_volume_name(resource)
                elif 'snapshot' in resource:
                    # This is for the snapshot legacy case
                    potential_id = utils.extract_id_from_snapshot_name(
                        resource)
                else:
                    potential_id = resource.split('.')[1]

                # When a resource is already managed by cinder, it's not
                # recommended to manage it again. So we set safe_to_manage =
                # False. Otherwise, it is set safe_to_manage = True.
                if potential_id in cinder_ids:
                    rsrc_inf['safe_to_manage'] = False
                    rsrc_inf['reason_not_safe'] = 'already managed'
                    rsrc_inf['cinder_id'] = potential_id
                else:
                    rsrc_inf['safe_to_manage'] = True
                    rsrc_inf['reason_not_safe'] = None

                # If it's a snapshot, we try to get its source volume. However,
                # this search is not reliable in some cases. So, if it's not
                # possible to return a precise result, we return unknown as
                # source-reference, throw a warning message and fill the
                # extra-info.
                if resource_type == 'snapshot':
                    if 'snapshot' not in resource:
                        origin = self._get_snapshot_origin_from_name(resource)
                        if 'unmanage' in origin:
                            origin = origin[16:]
                        else:
                            origin = origin[7:]
                        rsrc_inf['source_reference'] = {'id': origin}
                    else:
                        path = path.split(':')[1]
                        origin = self._get_snapshot_origin(path, exports[exp])

                        if not origin:
                            # if origin is empty, the file is not a clone
                            continue
                        elif len(origin) == 1:
                            origin = origin[0].split('/')[2]
                            origin = utils.extract_id_from_volume_name(origin)
                            rsrc_inf['source_reference'] = {'id': origin}
                        else:
                            LOG.warning(
                                "Could not determine the volume "
                                "that owns the snapshot %(snap)s",
                                {'snap': resource})
                            rsrc_inf['source_reference'] = {'id': 'unknown'}
                            rsrc_inf['extra_info'] = ('Could not determine '
                                                      'the volume that owns '
                                                      'the snapshot')

                entries.append(rsrc_inf)

        return utils.paginate_entries_list(entries, marker, limit, offset,
                                           sort_keys, sort_dirs)
 def test_extract_id_from_snapshot_name(self, conf_mock):
     conf_mock.snapshot_name_template = '%s-snapshot'
     snap_id = 'd8cd1feb-2dcc-404d-9b15-b86fe3bec0a1'
     snap_name = conf_mock.snapshot_name_template % snap_id
     result = volume_utils.extract_id_from_snapshot_name(snap_name)
     self.assertEqual(snap_id, result)
Example #10
0
    def _get_manageable_resource_info(self, cinder_resources, resource_type,
                                      marker, limit, offset, sort_keys,
                                      sort_dirs):
        """Gets the resources on the backend available for management by Cinder.

        Receives the parameters from "get_manageable_volumes" and
        "get_manageable_snapshots" and gets the available resources

        :param cinder_resources: A list of resources in this host that Cinder
        currently manages
        :param resource_type: If it's a volume or a snapshot
        :param marker: The last item of the previous page; we return the
        next results after this value (after sorting)
        :param limit: Maximum number of items to return
        :param offset: Number of items to skip after marker
        :param sort_keys: List of keys to sort results by (valid keys
        are 'identifier' and 'size')
        :param sort_dirs: List of directions to sort by, corresponding to
        sort_keys (valid directions are 'asc' and 'desc')

        :returns: list of dictionaries, each specifying a volume or snapshot
        (resource) in the host, with the following keys:
            - reference (dictionary): The reference for a resource,
            which can be passed to "manage_existing_snapshot".
            - size (int): The size of the resource according to the storage
              backend, rounded up to the nearest GB.
            - safe_to_manage (boolean): Whether or not this resource is
            safe to manage according to the storage backend.
            - reason_not_safe (string): If safe_to_manage is False,
              the reason why.
            - cinder_id (string): If already managed, provide the Cinder ID.
            - extra_info (string): Any extra information to return to the
            user
            - source_reference (string): Similar to "reference", but for the
              snapshot's source volume.
        """

        entries = []
        exports = {}
        bend_rsrc = {}
        cinder_ids = [resource.id for resource in cinder_resources]

        for service in self.config['services']:
            exp_path = self.config['services'][service]['hdp']
            exports[exp_path] = (
                self.config['services'][service]['export']['fs'])

        for exp in exports.keys():
            # bend_rsrc has all the resources in the specified exports
            # volumes {u'172.24.54.39:/Export-Cinder':
            #   ['volume-325e7cdc-8f65-40a8-be9a-6172c12c9394',
            # '     snapshot-1bfb6f0d-9497-4c12-a052-5426a76cacdc','']}
            bend_rsrc[exp] = self._get_volumes_from_export(exp)
            mnt_point = self._get_mount_point_for_share(exp)

            for resource in bend_rsrc[exp]:
                # Ignoring resources of unwanted types
                if ((resource_type == 'volume' and 'snapshot' in resource) or
                        (resource_type == 'snapshot' and
                            'volume' in resource)):
                    continue
                path = '%s/%s' % (exp, resource)
                mnt_path = '%s/%s' % (mnt_point, resource)
                size = self._get_file_size(mnt_path)

                rsrc_inf = {'reference': {'source-name': path},
                            'size': size, 'cinder_id': None,
                            'extra_info': None}

                if resource_type == 'volume':
                    potential_id = utils.extract_id_from_volume_name(resource)
                else:
                    potential_id = utils.extract_id_from_snapshot_name(
                        resource)

                # When a resource is already managed by cinder, it's not
                # recommended to manage it again. So we set safe_to_manage =
                # False. Otherwise, it is set safe_to_manage = True.
                if potential_id in cinder_ids:
                    rsrc_inf['safe_to_manage'] = False
                    rsrc_inf['reason_not_safe'] = 'already managed'
                    rsrc_inf['cinder_id'] = potential_id
                else:
                    rsrc_inf['safe_to_manage'] = True
                    rsrc_inf['reason_not_safe'] = None

                # If it's a snapshot, we try to get its source volume. However,
                # this search is not reliable in some cases. So, if it's not
                # possible to return a precise result, we return unknown as
                # source-reference, throw a warning message and fill the
                # extra-info.
                if resource_type == 'snapshot':
                    path = path.split(':')[1]
                    origin = self._get_snapshot_origin(path, exports[exp])

                    if not origin:
                        # if origin is empty, the file is not a clone
                        continue
                    elif len(origin) == 1:
                        origin = origin[0].split('/')[2]
                        origin = utils.extract_id_from_volume_name(origin)
                        rsrc_inf['source_reference'] = {'id': origin}
                    else:
                        LOG.warning(_LW("Could not determine the volume that "
                                        "owns the snapshot %(snap)s"),
                                    {'snap': resource})
                        rsrc_inf['source_reference'] = {'id': 'unknown'}
                        rsrc_inf['extra_info'] = ('Could not determine the '
                                                  'volume that owns the '
                                                  'snapshot')

                entries.append(rsrc_inf)

        return utils.paginate_entries_list(entries, marker, limit, offset,
                                           sort_keys, sort_dirs)