Exemple #1
0
    def _validate_access_keys(access_rules, add_rules, delete_rules,
                              access_keys):
        if not isinstance(access_keys, dict):
            msg = _("The access keys must be supplied as a dictionary that "
                    "maps rule IDs to access keys.")
            raise exception.Invalid(message=msg)

        actual_rule_ids = sorted(access_keys)
        expected_rule_ids = []
        if not (add_rules or delete_rules):
            expected_rule_ids = [rule['id'] for rule in access_rules]
        else:
            expected_rule_ids = [rule['id'] for rule in add_rules]
        if actual_rule_ids != sorted(expected_rule_ids):
            msg = (_("The rule IDs supplied: %(actual)s do not match the "
                     "rule IDs that are expected: %(expected)s.") % {
                         'actual': actual_rule_ids,
                         'expected': expected_rule_ids
                     })
            raise exception.Invalid(message=msg)

        for access_key in access_keys.values():
            if not isinstance(access_key, six.string_types):
                msg = (_("Access key %s is not string type.") % access_key)
                raise exception.Invalid(message=msg)
Exemple #2
0
 def _check_boolean_extra_specs_validity(self, share, specs,
                                         keys_of_interest):
     # cDOT compression requires deduplication.
     dedup = specs.get('netapp:dedup', None)
     compression = specs.get('netapp:compression', None)
     if dedup is not None and compression is not None:
         if dedup.lower() == 'false' and compression.lower() == 'true':
             spec = {'netapp:dedup': dedup,
                     'netapp:compression': compression}
             type_id = share['share_type_id']
             share_id = share['id']
             args = {'type_id': type_id, 'share_id': share_id, 'spec': spec}
             msg = _('Invalid combination of extra_specs in share_type '
                     '%(type_id)s for share %(share_id)s: %(spec)s: '
                     'deduplication must be enabled in order for '
                     'compression to be enabled.')
             raise exception.Invalid(msg % args)
     """Check if the boolean_extra_specs have valid values."""
     # Extra spec values must be (ignoring case) 'true' or 'false'.
     for key in keys_of_interest:
         value = specs.get(key)
         if value is not None and value.lower() not in ['true', 'false']:
             type_id = share['share_type_id']
             share_id = share['id']
             arg_map = {'value': value, 'key': key, 'type_id': type_id,
                        'share_id': share_id}
             msg = _('Invalid value "%(value)s" for extra_spec "%(key)s" '
                     'in share_type %(type_id)s for share %(share_id)s.')
             raise exception.Invalid(msg % arg_map)
Exemple #3
0
    def shrink_share(self, share, new_size, share_server=None):
        server_details = share_server['backend_details']

        helper = self._get_helper(share)
        export_location = share['export_locations'][0]['path']
        mount_path = helper.get_share_path_by_export_location(
            server_details, export_location)

        consumed_space = self._get_consumed_space(mount_path, server_details)

        LOG.debug("Consumed space on share: %s", consumed_space)

        if consumed_space >= new_size:
            raise exception.ShareShrinkingPossibleDataLoss(
                share_id=share['id'])

        volume = self._get_volume(self.admin_context, share['id'])

        helper.disable_access_for_maintenance(server_details, share['name'])
        self._unmount_device(share, server_details)

        try:
            self._resize_filesystem(server_details, volume, new_size=new_size)
        except exception.Invalid:
            raise exception.ShareShrinkingPossibleDataLoss(
                share_id=share['id'])
        except Exception as e:
            msg = _("Cannot shrink share: %s") % six.text_type(e)
            raise exception.Invalid(msg)
        finally:
            self._mount_device(share, server_details, volume)
            helper.restore_access_after_maintenance(server_details,
                                                    share['name'])
Exemple #4
0
    def _create_share_server(self, network_info, request_host=None):
        """Is called to create/setup share server"""
        # Return pool name, vfs, IPs for a pool
        pool_name, vfs, ips = self._get_pool_location_from_share_host(
            request_host)

        ip = network_info['network_allocations'][0]['ip_address']
        if ip not in ips:
            # Besides DHSS, admin could have setup IP to VFS directly on array
            if len(ips) > (FPG.MAX_SUPPORTED_IP_PER_VFS - 1):
                message = (_("Pool %s has exceeded 3PAR's "
                             "max supported VFS IP address") % pool_name)
                LOG.error(message)
                raise exception.Invalid(message)

            subnet = utils.cidr_to_netmask(network_info['cidr'])
            vlantag = network_info['segmentation_id']

            self._hpe3par.create_fsip(ip, subnet, vlantag, pool_name, vfs)
            # Update in global saved config, self.fpgs[pool_name]
            ips.append(ip)

        return {
            'share_server_name': network_info['server_id'],
            'share_server_id': network_info['server_id'],
            'ip': ip,
            'subnet': subnet,
            'vlantag': vlantag if vlantag else 0,
            'fpg': pool_name,
            'vfs': vfs
        }
Exemple #5
0
 def wrapper(*args, **kwargs):
     try:
         return f(*args, **kwargs)
     except db_exc.DBDataError:
         msg = _('Error writing field to database.')
         LOG.exception(msg)
         raise exception.Invalid(msg)
Exemple #6
0
 def _check_boolean_extra_specs_validity(self, share, specs,
                                         keys_of_interest):
     """Check if the boolean_extra_specs have valid values."""
     # Extra spec values must be (ignoring case) 'true' or 'false'.
     for key in keys_of_interest:
         value = specs.get(key)
         if value is not None and value.lower() not in ['true', 'false']:
             type_id = share['share_type_id']
             share_id = share['id']
             arg_map = {
                 'value': value,
                 'key': key,
                 'type_id': type_id,
                 'share_id': share_id
             }
             msg = _('Invalid value "%(value)s" for extra_spec "%(key)s" '
                     'in share_type %(type_id)s for share %(share_id)s.')
             raise exception.Invalid(msg % arg_map)
Exemple #7
0
    def _resize_filesystem(self, server_details, volume, new_size=None):
        """Resize filesystem of provided volume."""
        check_command = ['sudo', 'fsck', '-pf', volume['mountpoint']]
        self._ssh_exec(server_details, check_command)
        command = ['sudo', 'resize2fs', volume['mountpoint']]

        if new_size:
            command.append("%sG" % six.text_type(new_size))

        try:
            self._ssh_exec(server_details, command)
        except processutils.ProcessExecutionError as e:
            if e.stderr.find('New size smaller than minimum') != -1:
                msg = (_("Invalid 'new_size' provided: %s") %
                       six.text_type(new_size))
                raise exception.Invalid(msg)
            else:
                msg = _("Cannot resize file-system: %s") % six.text_type(e)
                raise exception.ManilaException(msg)
Exemple #8
0
 def test_invalid(self):
     # Verify response code for exception.Invalid
     e = exception.Invalid()
     self.assertEqual(400, e.code)
Exemple #9
0
    def _setup_server(self, context, share_server, metadata=None):
        try:
            share_network = self.db.share_network_get(
                context, share_server['share_network_id'])
            self.driver.allocate_network(context, share_server, share_network)

            # Get share_network again in case it was updated.
            share_network = self.db.share_network_get(
                context, share_server['share_network_id'])
            network_info = self._form_server_setup_info(
                context, share_server, share_network)
            self._validate_segmentation_id(network_info)

            # NOTE(vponomaryov): Save security services data to share server
            # details table to remove dependency from share network after
            # creation operation. It will allow us to delete share server and
            # share network separately without dependency on each other.
            for security_service in network_info['security_services']:
                ss_type = security_service['type']
                data = {
                    'name': security_service['name'],
                    'domain': security_service['domain'],
                    'server': security_service['server'],
                    'dns_ip': security_service['dns_ip'],
                    'user': security_service['user'],
                    'type': ss_type,
                    'password': security_service['password'],
                }
                self.db.share_server_backend_details_set(
                    context, share_server['id'],
                    {'security_service_' + ss_type: jsonutils.dumps(data)})

            server_info = self.driver.setup_server(
                network_info, metadata=metadata)

            if server_info and isinstance(server_info, dict):
                self.db.share_server_backend_details_set(
                    context, share_server['id'], server_info)
            return self.db.share_server_update(
                context, share_server['id'],
                {'status': constants.STATUS_ACTIVE})
        except Exception as e:
            with excutils.save_and_reraise_exception():
                try:
                    details = getattr(e, 'detail_data', {})
                    if not isinstance(details, dict):
                        msg = (_("Invalid detail_data '%s'")
                               % six.text_type(details))
                        raise exception.Invalid(msg)

                    server_details = details.get('server_details')

                    if not isinstance(server_details, dict):
                        msg = (_("Invalid server_details '%s'")
                               % six.text_type(server_details))
                        raise exception.Invalid(msg)

                    invalid_details = []

                    for key, value in server_details.items():
                        try:
                            self.db.share_server_backend_details_set(
                                context, share_server['id'], {key: value})
                        except Exception:
                            invalid_details.append("%(key)s: %(value)s" % {
                                'key': six.text_type(key),
                                'value': six.text_type(value)
                            })

                    if invalid_details:
                        msg = (_("Following server details are not valid:\n%s")
                               % six.text_type('\n'.join(invalid_details)))
                        raise exception.Invalid(msg)

                except Exception as e:
                    LOG.warning(_LW('Server Information in '
                                    'exception can not be written to db : %s '
                                    ), six.text_type(e))
                finally:
                    self.db.share_server_update(
                        context, share_server['id'],
                        {'status': constants.STATUS_ERROR})
                    self.driver.deallocate_network(context, share_server['id'])
Exemple #10
0
    def delete_snapshot(self, orig_project_id, orig_share_id, orig_proto,
                        snapshot_id, fpg, vfs):
        """Deletes a snapshot of a share."""

        snapshot_tag = self.ensure_prefix(snapshot_id)

        snapshot = self._find_fsnap(orig_project_id, orig_share_id, orig_proto,
                                    snapshot_tag, fpg, vfs)

        if not snapshot:
            return

        fstore = snapshot.get('fstoreName')

        for protocol in ('nfs', 'smb'):
            try:
                shares = self._client.getfshare(protocol,
                                                fpg=fpg,
                                                vfs=vfs,
                                                fstore=fstore)
            except Exception as e:
                msg = (_('Unexpected exception while getting share list. '
                         'Cannot delete snapshot without checking for '
                         'dependent shares first: %s') % six.text_type(e))
                LOG.exception(msg)
                raise exception.ShareBackendException(msg)

            for share in shares['members']:
                if protocol == 'nfs':
                    path = share['sharePath'][1:].split('/')
                    dot_snapshot_index = 3
                else:
                    if share['shareDir']:
                        path = share['shareDir'].split('/')
                    else:
                        path = None
                    dot_snapshot_index = 0

                snapshot_index = dot_snapshot_index + 1
                if path and len(path) > snapshot_index:
                    if (path[dot_snapshot_index] == '.snapshot'
                            and path[snapshot_index].endswith(snapshot_tag)):
                        msg = (_('Cannot delete snapshot because it has a '
                                 'dependent share.'))
                        raise exception.Invalid(msg)

        snapname = snapshot['snapName']
        try:
            result = self._client.removefsnap(vfs,
                                              fstore,
                                              snapname=snapname,
                                              fpg=fpg)

            LOG.debug("removefsnap result=%s", result)

        except Exception as e:
            msg = (_('Failed to delete snapshot for FPG/VFS/fstore/snapshot '
                     '%(fpg)s/%(vfs)s/%(fstore)s/%(snapname)s: %(e)s') % {
                         'fpg': fpg,
                         'vfs': vfs,
                         'fstore': fstore,
                         'snapname': snapname,
                         'e': six.text_type(e)
                     })
            LOG.exception(msg)
            raise exception.ShareBackendException(msg)

        # Try to reclaim the space
        try:
            self._client.startfsnapclean(fpg, reclaimStrategy='maxspeed')
        except Exception as e:
            # Remove already happened so only log this.
            msg = (_('Unexpected exception calling startfsnapclean for FPG '
                     '%(fpg)s: %(e)s') % {
                         'fpg': fpg,
                         'e': six.text_type(e)
                     })
            LOG.exception(msg)