Esempio n. 1
0
 def _remap_standard_boolean_extra_specs(self, extra_specs):
     """Replace standard boolean extra specs with NetApp-specific ones."""
     specs = copy.deepcopy(extra_specs)
     for (key, netapp_key) in self.STANDARD_BOOLEAN_EXTRA_SPECS_MAP.items():
         if key in specs:
             bool_value = share_types.parse_boolean_extra_spec(key, specs[key])
             specs[netapp_key] = "true" if bool_value else "false"
             del specs[key]
     return specs
Esempio n. 2
0
 def _remap_standard_boolean_extra_specs(self, extra_specs):
     """Replace standard boolean extra specs with NetApp-specific ones."""
     specs = copy.deepcopy(extra_specs)
     for (key, netapp_key) in self.STANDARD_BOOLEAN_EXTRA_SPECS_MAP.items():
         if key in specs:
             bool_value = share_types.parse_boolean_extra_spec(key,
                                                               specs[key])
             specs[netapp_key] = 'true' if bool_value else 'false'
             del specs[key]
     return specs
Esempio n. 3
0
    def test_parse_boolean_extra_spec(self, spec_value, expected):

        result = share_types.parse_boolean_extra_spec('fake_key', spec_value)

        self.assertEqual(expected, result)
Esempio n. 4
0
    def manage_existing(self, share, driver_options):
        """Manages a share that exists on backend."""
        if share['share_proto'].lower() == 'nfs':
            # 10.0.0.1:/share/example
            LOG.info(
                "Share %(shr_path)s will be managed with ID "
                "%(shr_id)s.", {
                    'shr_path': share['export_locations'][0]['path'],
                    'shr_id': share['id']
                })

            old_path_info = share['export_locations'][0]['path'].split(
                ':/share/')

            if len(old_path_info) == 2:
                ip = old_path_info[0]
                share_name = old_path_info[1]
            else:
                msg = _("Incorrect path. It should have the following format: "
                        "IP:/share/share_name.")
                raise exception.ShareBackendException(msg=msg)
        else:
            msg = _('Invalid NAS protocol: %s') % share['share_proto']
            raise exception.InvalidInput(reason=msg)

        if ip != self.configuration.qnap_share_ip:
            msg = _("The NAS IP %(ip)s is not configured.") % {'ip': ip}
            raise exception.ShareBackendException(msg=msg)

        existing_share = self.api_executor.get_share_info(
            self.configuration.qnap_poolname, vol_label=share_name)
        if existing_share is None:
            msg = _("The share %s trying to be managed was not found on "
                    "backend.") % share['id']
            raise exception.ManageInvalidShare(reason=msg)

        extra_specs = share_types.get_extra_specs_from_share(share)
        qnap_thin_provision = share_types.parse_boolean_extra_spec(
            'thin_provisioning',
            extra_specs.get("thin_provisioning")
            or extra_specs.get('capabilities:thin_provisioning') or 'true')
        qnap_compression = share_types.parse_boolean_extra_spec(
            'compression',
            extra_specs.get("compression")
            or extra_specs.get('capabilities:compression') or 'true')
        qnap_deduplication = share_types.parse_boolean_extra_spec(
            'dedupe',
            extra_specs.get("dedupe") or extra_specs.get('capabilities:dedupe')
            or 'false')
        qnap_ssd_cache = share_types.parse_boolean_extra_spec(
            'qnap_ssd_cache',
            extra_specs.get("qnap_ssd_cache")
            or extra_specs.get("capabilities:qnap_ssd_cache") or 'false')
        LOG.debug(
            'qnap_thin_provision: %(qnap_thin_provision)s '
            'qnap_compression: %(qnap_compression)s '
            'qnap_deduplication: %(qnap_deduplication)s '
            'qnap_ssd_cache: %(qnap_ssd_cache)s', {
                'qnap_thin_provision': qnap_thin_provision,
                'qnap_compression': qnap_compression,
                'qnap_deduplication': qnap_deduplication,
                'qnap_ssd_cache': qnap_ssd_cache
            })
        if (qnap_deduplication and not qnap_thin_provision):
            msg = _("Dedupe cannot be enabled without thin_provisioning.")
            LOG.debug('Dedupe cannot be enabled without thin_provisioning.')
            raise exception.InvalidExtraSpec(reason=msg)

        vol_no = existing_share.find('vol_no').text
        vol = self.api_executor.get_specific_volinfo(vol_no)
        vol_size_gb = math.ceil(float(vol.find('size').text) / units.Gi)

        share_dict = {
            'sharename': share_name,
            'old_sharename': share_name,
            'thin_provision': qnap_thin_provision,
            'compression': qnap_compression,
            'deduplication': qnap_deduplication,
            'ssd_cache': qnap_ssd_cache,
            'share_proto': share['share_proto']
        }
        self.api_executor.edit_share(share_dict)

        _metadata = {}
        _metadata['volID'] = vol_no
        _metadata['volName'] = share_name
        _metadata['thin_provision'] = qnap_thin_provision
        _metadata['compression'] = qnap_compression
        _metadata['deduplication'] = qnap_deduplication
        _metadata['ssd_cache'] = qnap_ssd_cache
        self.private_storage.update(share['id'], _metadata)

        LOG.info(
            "Share %(shr_path)s was successfully managed with ID "
            "%(shr_id)s.", {
                'shr_path': share['export_locations'][0]['path'],
                'shr_id': share['id']
            })

        export_locations = self._get_location_path(
            share_name, share['share_proto'], self.configuration.qnap_share_ip,
            vol_no)

        return {'size': vol_size_gb, 'export_locations': export_locations}
Esempio n. 5
0
    def create_share(self, context, share, share_server=None):
        """Create a new share."""
        LOG.debug('share: %s', share.__dict__)
        extra_specs = share_types.get_extra_specs_from_share(share)
        LOG.debug('extra_specs: %s', extra_specs)
        qnap_thin_provision = share_types.parse_boolean_extra_spec(
            'thin_provisioning',
            extra_specs.get("thin_provisioning")
            or extra_specs.get('capabilities:thin_provisioning') or 'true')
        qnap_compression = share_types.parse_boolean_extra_spec(
            'compression',
            extra_specs.get("compression")
            or extra_specs.get('capabilities:compression') or 'true')
        qnap_deduplication = share_types.parse_boolean_extra_spec(
            'dedupe',
            extra_specs.get("dedupe") or extra_specs.get('capabilities:dedupe')
            or 'false')
        qnap_ssd_cache = share_types.parse_boolean_extra_spec(
            'qnap_ssd_cache',
            extra_specs.get("qnap_ssd_cache")
            or extra_specs.get("capabilities:qnap_ssd_cache") or 'false')
        LOG.debug(
            'qnap_thin_provision: %(qnap_thin_provision)s '
            'qnap_compression: %(qnap_compression)s '
            'qnap_deduplication: %(qnap_deduplication)s '
            'qnap_ssd_cache: %(qnap_ssd_cache)s', {
                'qnap_thin_provision': qnap_thin_provision,
                'qnap_compression': qnap_compression,
                'qnap_deduplication': qnap_deduplication,
                'qnap_ssd_cache': qnap_ssd_cache
            })

        share_proto = share['share_proto']

        # User could create two shares with the same name on horizon.
        # Therefore, we should not use displayname to create shares on NAS.
        create_share_name = self._gen_random_name("share")
        # If share name exists, need to change to another name.
        created_share = self.api_executor.get_share_info(
            self.configuration.qnap_poolname, vol_label=create_share_name)
        LOG.debug('created_share: %s', created_share)
        if created_share is not None:
            msg = (_("The share name %s is used by other share on NAS.") %
                   create_share_name)
            LOG.error(msg)
            raise exception.ShareBackendException(msg=msg)

        if (qnap_deduplication and not qnap_thin_provision):
            msg = _("Dedupe cannot be enabled without thin_provisioning.")
            LOG.debug('Dedupe cannot be enabled without thin_provisioning.')
            raise exception.InvalidExtraSpec(reason=msg)
        self.api_executor.create_share(share,
                                       self.configuration.qnap_poolname,
                                       create_share_name,
                                       share_proto,
                                       qnap_thin_provision=qnap_thin_provision,
                                       qnap_compression=qnap_compression,
                                       qnap_deduplication=qnap_deduplication,
                                       qnap_ssd_cache=qnap_ssd_cache)
        created_share = self._get_share_info(create_share_name)
        volID = created_share.find('vol_no').text
        # Use private_storage to record volume ID and Name created in the NAS.
        LOG.debug('volID: %(volID)s '
                  'volName: %(create_share_name)s', {
                      'volID': volID,
                      'create_share_name': create_share_name
                  })
        _metadata = {
            'volID': volID,
            'volName': create_share_name,
            'thin_provision': qnap_thin_provision,
            'compression': qnap_compression,
            'deduplication': qnap_deduplication,
            'ssd_cache': qnap_ssd_cache
        }
        self.private_storage.update(share['id'], _metadata)

        return self._get_location_path(create_share_name, share['share_proto'],
                                       self.configuration.qnap_share_ip, volID)
Esempio n. 6
0
    def test_parse_boolean_extra_spec(self, spec_value, expected):

        result = share_types.parse_boolean_extra_spec('fake_key', spec_value)

        self.assertEqual(expected, result)
Esempio n. 7
0
    def manage_existing(self, share, driver_options):
        """Manages a share that exists on backend."""
        if share['share_proto'].lower() == 'nfs':
            # 10.0.0.1:/share/example
            LOG.info("Share %(shr_path)s will be managed with ID "
                     "%(shr_id)s.",
                     {'shr_path': share['export_locations'][0]['path'],
                      'shr_id': share['id']})

            old_path_info = share['export_locations'][0]['path'].split(
                ':/share/')

            if len(old_path_info) == 2:
                ip = old_path_info[0]
                share_name = old_path_info[1]
            else:
                msg = _("Incorrect path. It should have the following format: "
                        "IP:/share/share_name.")
                raise exception.ShareBackendException(msg=msg)
        else:
            msg = _('Invalid NAS protocol: %s') % share['share_proto']
            raise exception.InvalidInput(reason=msg)

        if ip != self.configuration.qnap_share_ip:
            msg = _("The NAS IP %(ip)s is not configured.") % {'ip': ip}
            raise exception.ShareBackendException(msg=msg)

        existing_share = self.api_executor.get_share_info(
            self.configuration.qnap_poolname,
            vol_label=share_name)
        if existing_share is None:
            msg = _("The share %s trying to be managed was not found on "
                    "backend.") % share['id']
            raise exception.ManageInvalidShare(reason=msg)

        extra_specs = share_types.get_extra_specs_from_share(share)
        qnap_thin_provision = share_types.parse_boolean_extra_spec(
            'thin_provisioning', extra_specs.get("thin_provisioning") or
            extra_specs.get('capabilities:thin_provisioning') or 'true')
        qnap_compression = share_types.parse_boolean_extra_spec(
            'compression', extra_specs.get("compression") or
            extra_specs.get('capabilities:compression') or 'true')
        qnap_deduplication = share_types.parse_boolean_extra_spec(
            'dedupe', extra_specs.get("dedupe") or
            extra_specs.get('capabilities:dedupe') or 'false')
        qnap_ssd_cache = share_types.parse_boolean_extra_spec(
            'qnap_ssd_cache', extra_specs.get("qnap_ssd_cache") or
            extra_specs.get("capabilities:qnap_ssd_cache") or 'false')
        LOG.debug('qnap_thin_provision: %(qnap_thin_provision)s '
                  'qnap_compression: %(qnap_compression)s '
                  'qnap_deduplication: %(qnap_deduplication)s '
                  'qnap_ssd_cache: %(qnap_ssd_cache)s',
                  {'qnap_thin_provision': qnap_thin_provision,
                   'qnap_compression': qnap_compression,
                   'qnap_deduplication': qnap_deduplication,
                   'qnap_ssd_cache': qnap_ssd_cache})
        if (qnap_deduplication and not qnap_thin_provision):
            msg = _("Dedupe cannot be enabled without thin_provisioning.")
            LOG.debug('Dedupe cannot be enabled without thin_provisioning.')
            raise exception.InvalidExtraSpec(reason=msg)

        vol_no = existing_share.find('vol_no').text
        vol = self.api_executor.get_specific_volinfo(vol_no)
        vol_size_gb = math.ceil(float(vol.find('size').text) / units.Gi)

        share_dict = {
            'sharename': share_name,
            'old_sharename': share_name,
            'thin_provision': qnap_thin_provision,
            'compression': qnap_compression,
            'deduplication': qnap_deduplication,
            'ssd_cache': qnap_ssd_cache,
            'share_proto': share['share_proto']
        }
        self.api_executor.edit_share(share_dict)

        _metadata = {}
        _metadata['volID'] = vol_no
        _metadata['volName'] = share_name
        _metadata['thin_provision'] = qnap_thin_provision
        _metadata['compression'] = qnap_compression
        _metadata['deduplication'] = qnap_deduplication
        _metadata['ssd_cache'] = qnap_ssd_cache
        self.private_storage.update(share['id'], _metadata)

        LOG.info("Share %(shr_path)s was successfully managed with ID "
                 "%(shr_id)s.",
                 {'shr_path': share['export_locations'][0]['path'],
                  'shr_id': share['id']})

        export_locations = self._get_location_path(
            share_name,
            share['share_proto'],
            self.configuration.qnap_share_ip,
            vol_no)

        return {'size': vol_size_gb, 'export_locations': export_locations}
Esempio n. 8
0
    def create_share(self, context, share, share_server=None):
        """Create a new share."""
        LOG.debug('share: %s', share.__dict__)
        extra_specs = share_types.get_extra_specs_from_share(share)
        LOG.debug('extra_specs: %s', extra_specs)
        qnap_thin_provision = share_types.parse_boolean_extra_spec(
            'thin_provisioning', extra_specs.get("thin_provisioning") or
            extra_specs.get('capabilities:thin_provisioning') or 'true')
        qnap_compression = share_types.parse_boolean_extra_spec(
            'compression', extra_specs.get("compression") or
            extra_specs.get('capabilities:compression') or 'true')
        qnap_deduplication = share_types.parse_boolean_extra_spec(
            'dedupe', extra_specs.get("dedupe") or
            extra_specs.get('capabilities:dedupe') or 'false')
        qnap_ssd_cache = share_types.parse_boolean_extra_spec(
            'qnap_ssd_cache', extra_specs.get("qnap_ssd_cache") or
            extra_specs.get("capabilities:qnap_ssd_cache") or 'false')
        LOG.debug('qnap_thin_provision: %(qnap_thin_provision)s '
                  'qnap_compression: %(qnap_compression)s '
                  'qnap_deduplication: %(qnap_deduplication)s '
                  'qnap_ssd_cache: %(qnap_ssd_cache)s',
                  {'qnap_thin_provision': qnap_thin_provision,
                   'qnap_compression': qnap_compression,
                   'qnap_deduplication': qnap_deduplication,
                   'qnap_ssd_cache': qnap_ssd_cache})

        share_proto = share['share_proto']

        # User could create two shares with the same name on horizon.
        # Therefore, we should not use displayname to create shares on NAS.
        create_share_name = self._gen_random_name("share")
        # If share name exists, need to change to another name.
        created_share = self.api_executor.get_share_info(
            self.configuration.qnap_poolname,
            vol_label=create_share_name)
        LOG.debug('created_share: %s', created_share)
        if created_share is not None:
            msg = (_("The share name %s is used by other share on NAS.") %
                   create_share_name)
            LOG.error(msg)
            raise exception.ShareBackendException(msg=msg)

        if (qnap_deduplication and not qnap_thin_provision):
            msg = _("Dedupe cannot be enabled without thin_provisioning.")
            LOG.debug('Dedupe cannot be enabled without thin_provisioning.')
            raise exception.InvalidExtraSpec(reason=msg)
        self.api_executor.create_share(
            share,
            self.configuration.qnap_poolname,
            create_share_name,
            share_proto,
            qnap_thin_provision=qnap_thin_provision,
            qnap_compression=qnap_compression,
            qnap_deduplication=qnap_deduplication,
            qnap_ssd_cache=qnap_ssd_cache)
        created_share = self._get_share_info(create_share_name)
        volID = created_share.find('vol_no').text
        # Use private_storage to record volume ID and Name created in the NAS.
        LOG.debug('volID: %(volID)s '
                  'volName: %(create_share_name)s',
                  {'volID': volID,
                   'create_share_name': create_share_name})
        _metadata = {'volID': volID,
                     'volName': create_share_name,
                     'thin_provision': qnap_thin_provision,
                     'compression': qnap_compression,
                     'deduplication': qnap_deduplication,
                     'ssd_cache': qnap_ssd_cache}
        self.private_storage.update(share['id'], _metadata)

        return self._get_location_path(create_share_name,
                                       share['share_proto'],
                                       self.configuration.qnap_share_ip,
                                       volID)