Ejemplo n.º 1
0
    def __call__(self, value):
        if value is None or value.strip(' ') is '':
            message = _("Invalid configuration. hpe3par_fpg must be set.")
            LOG.error(message)
            raise exception.HPE3ParInvalid(err=message)

        ips = []
        values = value.split(",")
        # Extract pool name
        pool_name = values.pop(0).strip()

        # values will now be ['ip1', ...]
        if len(values) < self.min_ip:
            msg = (_("Require at least %s IPs configured per "
                     "pool") % self.min_ip)
            raise exception.HPE3ParInvalid(err=msg)
        if len(values) > self.max_ip:
            msg = (_("Cannot configure IPs more than max supported "
                     "%s IPs per pool") % self.max_ip)
            raise exception.HPE3ParInvalid(err=msg)

        for ip_addr in values:
            ip_addr = types.String.__call__(self, ip_addr.strip())
            try:
                ips.append(types.IPAddress.__call__(self, ip_addr))
            except ValueError as verror:
                raise exception.HPE3ParInvalid(err=verror)
        fpg = {pool_name: ips}
        return fpg
Ejemplo n.º 2
0
 def _validate_pool_ips(addresses, conf_pool_ips):
     # Pool configured IP addresses should be subset of IP addresses
     # retured from vfs
     if not set(conf_pool_ips) <= set(addresses):
         msg = _("Incorrect configuration. "
                 "Configuration pool IP address did not match with "
                 "IP addresses at 3par array")
         raise exception.HPE3ParInvalid(err=msg)
Ejemplo n.º 3
0
    def do_setup(self, context):
        """Any initialization the share driver does while starting."""

        LOG.info(_LI("Starting share driver %(driver_name)s (%(version)s)"), {
            'driver_name': self.__class__.__name__,
            'version': self.VERSION
        })

        if not self.driver_handles_share_servers:
            self.share_ip_address = self.configuration.hpe3par_share_ip_address
            if not self.share_ip_address:
                raise exception.HPE3ParInvalid(
                    _("Unsupported configuration. "
                      "hpe3par_share_ip_address must be set when "
                      "driver_handles_share_servers is False."))

        mediator = hpe_3par_mediator.HPE3ParMediator(
            hpe3par_username=self.configuration.hpe3par_username,
            hpe3par_password=self.configuration.hpe3par_password,
            hpe3par_api_url=self.configuration.hpe3par_api_url,
            hpe3par_debug=self.configuration.hpe3par_debug,
            hpe3par_san_ip=self.configuration.hpe3par_san_ip,
            hpe3par_san_login=self.configuration.hpe3par_san_login,
            hpe3par_san_password=self.configuration.hpe3par_san_password,
            hpe3par_san_ssh_port=self.configuration.hpe3par_san_ssh_port,
            hpe3par_fstore_per_share=(
                self.configuration.hpe3par_fstore_per_share),
            hpe3par_require_cifs_ip=self.configuration.hpe3par_require_cifs_ip,
            hpe3par_share_ip_address=(
                self.configuration.hpe3par_share_ip_address),
            hpe3par_cifs_admin_access_username=(
                self.configuration.hpe3par_cifs_admin_access_username),
            hpe3par_cifs_admin_access_password=(
                self.configuration.hpe3par_cifs_admin_access_password),
            hpe3par_cifs_admin_access_domain=(
                self.configuration.hpe3par_cifs_admin_access_domain),
            hpe3par_share_mount_path=(
                self.configuration.hpe3par_share_mount_path),
            my_ip=self.configuration.my_ip,
            ssh_conn_timeout=self.configuration.ssh_conn_timeout,
        )

        mediator.do_setup()

        # FPG must be configured and must exist.
        self.fpg = self.configuration.safe_get('hpe3par_fpg')
        # Validate the FPG and discover the VFS
        # This also validates the client, connection, firmware, WSAPI, FPG...
        self.vfs = mediator.get_vfs_name(self.fpg)

        # Don't set _hpe3par until it is ready. Otherwise _update_stats fails.
        self._hpe3par = mediator
Ejemplo n.º 4
0
    def __init__(self,
                 min_ip=0,
                 max_ip=MAX_SUPPORTED_IP_PER_VFS,
                 type_name='FPG'):
        types.String.__init__(self, type_name=type_name)
        types.IPAddress.__init__(self, type_name=type_name)

        if max_ip < min_ip:
            msg = _("Pool's max acceptable IP cannot be less than min.")
            raise exception.HPE3ParInvalid(err=msg)

        if min_ip < 0:
            msg = _("Pools must be configured with zero or more IPs.")
            raise exception.HPE3ParInvalid(err=msg)

        if max_ip > FPG.MAX_SUPPORTED_IP_PER_VFS:
            msg = (_("Pool's max acceptable IP cannot be greater than "
                     "supported value=%s.") % FPG.MAX_SUPPORTED_IP_PER_VFS)
            raise exception.HPE3ParInvalid(err=msg)

        self.min_ip = min_ip
        self.max_ip = max_ip
Ejemplo n.º 5
0
    def _validate_access_type(protocol, access_type):

        if access_type not in ('ip', 'user'):
            msg = (_("Invalid access type.  Expected 'ip' or 'user'.  "
                     "Actual '%s'.") % access_type)
            LOG.error(msg)
            raise exception.InvalidInput(msg)

        if protocol == 'nfs' and access_type != 'ip':
            msg = (_("Invalid NFS access type.  HPE 3PAR NFS supports 'ip'. "
                     "Actual '%s'.") % access_type)
            LOG.error(msg)
            raise exception.HPE3ParInvalid(msg)

        return protocol
Ejemplo n.º 6
0
        def _construct_fpg():
            # FPG must be configured and must exist.
            # self.configuration.safe_get('hpe3par_fpg') will have value in
            # following format:
            # [ {'pool_name':['ip_addr', 'ip_addr', ...]}, ... ]
            for fpg in self.configuration.safe_get('hpe3par_fpg'):
                pool_name = list(fpg)[0]
                conf_pool_ips = fpg[pool_name]

                # Validate the FPG and discover the VFS
                # This also validates the client, connection, firmware, WSAPI,
                # FPG...
                vfs_info = mediator.get_vfs(pool_name)
                if self.driver_handles_share_servers:
                    # Use discovered IP(s) from array
                    self.fpgs[pool_name] = {
                        vfs_info['vfsname']: vfs_info['vfsip']['address']
                    }
                elif conf_pool_ips == []:
                    # not DHSS and IPs not configured in manila.conf.
                    if not vfs_info['vfsip']['address']:
                        msg = _("Unsupported configuration. "
                                "hpe3par_fpg must have IP address "
                                "or be discoverable at 3PAR")
                        LOG.error(msg)
                        raise exception.HPE3ParInvalid(err=msg)
                    else:
                        # Use discovered pool ips
                        self.fpgs[pool_name] = {
                            vfs_info['vfsname']: vfs_info['vfsip']['address']
                        }
                else:
                    # not DHSS and IPs configured in manila.conf
                    _validate_pool_ips(vfs_info['vfsip']['address'],
                                       conf_pool_ips)
                    self.fpgs[pool_name] = {vfs_info['vfsname']: conf_pool_ips}
Ejemplo n.º 7
0
    def _change_access(self,
                       plus_or_minus,
                       project_id,
                       share_id,
                       share_proto,
                       access_type,
                       access_to,
                       access_level,
                       fpg,
                       vfs,
                       extra_specs=None):
        """Allow or deny access to a share.

        Plus_or_minus character indicates add to allow list (+) or remove from
        allow list (-).
        """

        readonly = access_level == 'ro'
        protocol = self.ensure_supported_protocol(share_proto)

        try:
            self._validate_access_type(protocol, access_type)
        except Exception:
            if plus_or_minus == DENY:
                # Catch invalid rules for deny. Allow them to be deleted.
                return
            else:
                raise

        fshare = self._find_fshare(project_id,
                                   share_id,
                                   protocol,
                                   fpg,
                                   vfs,
                                   readonly=readonly)
        if not fshare:
            # Change access might apply to the share with the name that
            # does not match the access_level prefix.
            other_fshare = self._find_fshare(project_id,
                                             share_id,
                                             protocol,
                                             fpg,
                                             vfs,
                                             readonly=not readonly)
            if other_fshare:

                if plus_or_minus == DENY:
                    # Try to deny rule from 'other' share for SMB or legacy.
                    fshare = other_fshare

                elif self._is_share_from_snapshot(other_fshare):
                    # Found a share-from-snapshot from before
                    # "-ro" was added to the name. Use it.
                    fshare = other_fshare

                elif protocol == 'nfs':
                    # We don't have the RO|RW share we need, but the
                    # opposite one already exists. It is OK to create
                    # the one we need for ALLOW with NFS (not from snapshot).
                    fstore = other_fshare.get('fstoreName')
                    sharedir = other_fshare.get('shareDir')
                    comment = other_fshare.get('comment')

                    fshare = self._create_share(project_id,
                                                share_id,
                                                protocol,
                                                extra_specs,
                                                fpg,
                                                vfs,
                                                fstore=fstore,
                                                sharedir=sharedir,
                                                readonly=readonly,
                                                size=None,
                                                comment=comment)
                else:
                    # SMB only has one share for RO and RW. Try to use it.
                    fshare = other_fshare

            if not fshare:
                msg = _('Failed to change (%(change)s) access '
                        'to FPG/share %(fpg)s/%(share)s '
                        'for %(type)s %(to)s %(level)s): '
                        'Share does not exist on 3PAR.')
                msg_data = {
                    'change': plus_or_minus,
                    'fpg': fpg,
                    'share': share_id,
                    'type': access_type,
                    'to': access_to,
                    'level': access_level,
                }

                if plus_or_minus == DENY:
                    LOG.warning(msg, msg_data)
                    return
                else:
                    raise exception.HPE3ParInvalid(err=msg % msg_data)

        try:
            self._validate_access_level(protocol, access_type, access_level,
                                        fshare)
        except exception.InvalidShareAccess as e:
            if plus_or_minus == DENY:
                # Allow invalid access rules to be deleted.
                msg = _('Ignoring deny invalid access rule '
                        'for FPG/share %(fpg)s/%(share)s '
                        'for %(type)s %(to)s %(level)s): %(e)s')
                msg_data = {
                    'change': plus_or_minus,
                    'fpg': fpg,
                    'share': share_id,
                    'type': access_type,
                    'to': access_to,
                    'level': access_level,
                    'e': six.text_type(e),
                }
                LOG.info(msg, msg_data)
                return
            else:
                raise

        share_name = fshare.get('shareName')
        setfshare_kwargs = {
            'fpg': fpg,
            'fstore': fshare.get('fstoreName'),
            'comment': fshare.get('comment'),
        }

        if protocol == 'nfs':
            access_change = '%s%s' % (plus_or_minus, access_to)
            setfshare_kwargs['clientip'] = access_change

        elif protocol == 'smb':

            if access_type == 'ip':
                access_change = '%s%s' % (plus_or_minus, access_to)
                setfshare_kwargs['allowip'] = access_change

            else:
                access_str = 'read' if readonly else 'fullcontrol'
                perm = '%s%s:%s' % (plus_or_minus, access_to, access_str)
                setfshare_kwargs['allowperm'] = perm

        try:
            result = self._client.setfshare(protocol, vfs, share_name,
                                            **setfshare_kwargs)

            result = self.ignore_benign_access_results(plus_or_minus,
                                                       access_type, access_to,
                                                       result)

        except Exception as e:
            result = six.text_type(e)

        LOG.debug("setfshare result=%s", result)
        if result:
            msg = (_('Failed to change (%(change)s) access to FPG/share '
                     '%(fpg)s/%(share)s for %(type)s %(to)s %(level)s: '
                     '%(error)s') % {
                         'change': plus_or_minus,
                         'fpg': fpg,
                         'share': share_id,
                         'type': access_type,
                         'to': access_to,
                         'level': access_level,
                         'error': result
                     })
            raise exception.ShareBackendException(msg=msg)