Esempio n. 1
0
    def _allow_access(self, context, share, access, share_server=None):
        if access['access_type'] != CEPHX_ACCESS_TYPE:
            raise exception.InvalidShareAccess(
                reason=_("Only 'cephx' access type allowed."))

        ceph_auth_id = access['access_to']

        # We need to check here rather than the API or Manila Client to see
        # if the ceph_auth_id is the same as the one specified for Manila's
        # usage. This is due to the fact that the API and the Manila client
        # cannot read the contents of the Manila configuration file. If it
        # is the same, we need to error out.
        if ceph_auth_id == CONF.cephfs_auth_id:
            error_message = (_('Ceph authentication ID %s must be different '
                             'than the one the Manila service uses.') %
                             ceph_auth_id)
            raise exception.InvalidInput(message=error_message)

        # TODO(rraja): Log the Ceph point release version, once available, in
        # which the volume client can enable read-only access.
        if not getattr(self.volume_client, 'version', None):
            if access['access_level'] == constants.ACCESS_LEVEL_RO:
                raise exception.InvalidShareAccessLevel(
                    level=constants.ACCESS_LEVEL_RO)
            auth_result = self.volume_client.authorize(
                self._share_path(share), ceph_auth_id)
        else:
            readonly = access['access_level'] == constants.ACCESS_LEVEL_RO
            auth_result = self.volume_client.authorize(
                self._share_path(share), ceph_auth_id, readonly=readonly,
                tenant_id=share['project_id'])

        return auth_result['auth_key']
Esempio n. 2
0
    def _allow_access(self, context, share, access, share_server=None):
        if access['access_type'] != CEPHX_ACCESS_TYPE:
            raise exception.InvalidShareAccess(
                reason=_("Only 'cephx' access type allowed."))

        if access['access_level'] == constants.ACCESS_LEVEL_RO:
            raise exception.InvalidShareAccessLevel(
                level=constants.ACCESS_LEVEL_RO)

        ceph_auth_id = access['access_to']

        # We need to check here rather than the API or Manila Client to see
        # if the ceph_auth_id is the same as the one specified for Manila's
        # usage. This is due to the fact that the API and the Manila client
        # cannot read the contents of the Manila configuration file. If it
        # is the same, we need to error out.
        if ceph_auth_id == CONF.cephfs_auth_id:
            error_message = (_('Ceph authentication ID %s must be different '
                             'than the one the Manila service uses.') %
                             ceph_auth_id)
            raise exception.InvalidInput(message=error_message)

        auth_result = self.volume_client.authorize(self._share_path(share),
                                                   ceph_auth_id)

        return auth_result['auth_key']
Esempio n. 3
0
    def allow_access(self, context, share, share_name, access):
        """Allows access to the CIFS share for a given user."""
        if access['access_type'] != 'user':
            msg = _("Cluster Mode supports only 'user' type for share access"
                    " rules with CIFS protocol.")
            raise exception.InvalidShareAccess(reason=msg)

        user_name = access['access_to']

        if access['access_level'] == constants.ACCESS_LEVEL_RW:
            readonly = False
        elif access['access_level'] == constants.ACCESS_LEVEL_RO:
            readonly = True
        else:
            raise exception.InvalidShareAccessLevel(
                level=access['access_level'])

        target, share_name = self._get_export_location(share)
        try:
            self._client.add_cifs_share_access(share_name,
                                               user_name,
                                               readonly)
        except netapp_api.NaApiError as e:
            if e.code == netapp_api.EDUPLICATEENTRY:
                # Duplicate entry, so use specific exception.
                raise exception.ShareAccessExists(
                    access_type=access['access_type'], access=access)
            raise e
Esempio n. 4
0
 def _get_infinidat_access_level(self, access):
     """Translates between Manila access levels to INFINIDAT API ones"""
     access_level = access['access_level']
     try:
         return _MANILA_TO_INFINIDAT_ACCESS_LEVEL[access_level]
     except KeyError:
         raise exception.InvalidShareAccessLevel(level=access_level)
Esempio n. 5
0
 def _get_access_group(self, access_level):
     if access_level == const.ACCESS_LEVEL_RO:
         access = "read list"
     elif access_level == const.ACCESS_LEVEL_RW:
         access = "valid users"
     else:
         raise exception.InvalidShareAccessLevel(level=access_level)
     return access
Esempio n. 6
0
    def _validate_access_rule(self, rule):
        """Checks whether access rule type and level are valid."""

        if rule['access_type'] != 'ip':
            msg = _("Clustered Data ONTAP supports only 'ip' type for share "
                    "access rules with NFS protocol.")
            raise exception.InvalidShareAccess(reason=msg)

        if rule['access_level'] not in constants.ACCESS_LEVELS:
            raise exception.InvalidShareAccessLevel(level=rule['access_level'])
Esempio n. 7
0
    def allow_access(self, context, share, access, share_server=None):
        """Allow access to the share."""

        # NOTE(vponomaryov): use direct verification for case some additional
        # level is added.
        access_level = access['access_level']
        if access_level not in (const.ACCESS_LEVEL_RW, const.ACCESS_LEVEL_RO):
            raise exception.InvalidShareAccessLevel(level=access_level)
        self._get_helper(share).allow_access(
            share_server['backend_details'], share['name'],
            access['access_type'], access['access_level'], access['access_to'])
Esempio n. 8
0
def validate_access_rules(access_rules):

    allowed_types = {'ip'}
    allowed_levels = _MANILA_TO_VAST_ACCESS_LEVEL.keys()

    for access in (access_rules or []):
        access_type = access['access_type']
        access_level = access['access_level']
        if access_type not in allowed_types:
            reason = _("Only %s access type allowed.") % (', '.join(
                tuple(["'%s'" % x for x in allowed_types])))
            raise exception.InvalidShareAccess(reason=reason)
        if access_level not in allowed_levels:
            raise exception.InvalidShareAccessLevel(level=access_level)
Esempio n. 9
0
    def allow_access(self, context, share, access, share_server=None):
        """Allow access to a share."""
        access_level = access['access_level']
        if access_level not in const.ACCESS_LEVELS:
            raise exception.InvalidShareAccessLevel(level=access_level)

        share_proto = share['share_proto']

        if share_proto == 'NFS':
            self._nfs_allow_access(context, share, access, share_server)
        elif share_proto == 'CIFS':
            self._cifs_allow_access(context, share, access, share_server)
        else:
            raise exception.InvalidShare(
                reason=(_('Invalid NAS protocol supplied: %s.') % share_proto))
Esempio n. 10
0
    def _allow_access(self, context, share, access, share_server=None):
        if access['access_type'] != CEPHX_ACCESS_TYPE:
            raise exception.InvalidShareAccess(
                reason=_("Only 'cephx' access type allowed."))

        if access['access_level'] == constants.ACCESS_LEVEL_RO:
            raise exception.InvalidShareAccessLevel(
                level=constants.ACCESS_LEVEL_RO)

        ceph_auth_id = access['access_to']

        auth_result = self.volume_client.authorize(self._share_path(share),
                                                   ceph_auth_id)

        return auth_result['auth_key']
Esempio n. 11
0
    def allow_access(self, server, share_name, access_type, access_level,
                     access_to):
        """Add access for share."""
        if access_type != 'ip':
            reason = _('Only ip access type allowed.')
            raise exception.InvalidShareAccess(reason=reason)
        if access_level != const.ACCESS_LEVEL_RW:
            raise exception.InvalidShareAccessLevel(level=access_level)

        hosts = self._get_allow_hosts(server, share_name)
        if access_to in hosts:
            raise exception.ShareAccessExists(access_type=access_type,
                                              access=access_to)
        hosts.append(access_to)
        self._set_allow_hosts(server, hosts, share_name)
Esempio n. 12
0
    def allow_access(self, context, share, access, share_server=None):
        """Allow access to a share."""
        access_level = access['access_level']
        if access_level not in const.ACCESS_LEVELS:
            raise exception.InvalidShareAccessLevel(level=access_level)

        share_proto = share['share_proto'].upper()

        self._validate_share_protocol(share_proto)
        self._validate_share_access_type(share, access)

        if share_proto == 'CIFS':
            self._cifs_allow_access(share, access)
        elif share_proto == 'NFS':
            self._nfs_allow_access(share, access)
Esempio n. 13
0
    def _allow_access(self, context, share, access, share_server=None):
        """Give access of a share to an IP."""

        access_type = access['access_type']
        server = access['access_to']
        if access_type != 'ip':
            raise exception.InvalidShareAccess('Only ip access type '
                                               'supported.')
        access_level = access['access_level']

        if access_level not in (const.ACCESS_LEVEL_RW, const.ACCESS_LEVEL_RO):
            raise exception.InvalidShareAccessLevel(level=access_level)
        export_path = share['export_locations'][0]['path'].split(':', 1)
        va_sharepath = six.text_type(export_path[1])
        access_level = '%s,%s' % (six.text_type(access_level),
                                  'sync,no_root_squash')

        path = self._nfs_add_str
        provider = '%s:%s' % (self.host, self._port)
        data = {}
        va_share_info = ("{\"share\":[{\"fileSystemPath\":\"" + va_sharepath +
                         "\",\"shareType\":\"NFS\",\"shareDetails\":" +
                         "[{\"client\":\"" + server +
                         "\",\"exportOptions\":\"" +
                         access_level + "\"}]}]}")

        data["shareDetails"] = va_share_info

        result = self._access_api(self.session, provider, path,
                                  json.dumps(data), 'POST')

        if not result:
            message = (('ACCESSShareDriver access failed sharepath %s '
                        'server %s'),
                       va_sharepath,
                       server)
            LOG.error(message)
            raise exception.ShareBackendException(msg=message)

        LOG.debug("ACCESSShareDriver allow_access sharepath %s server %s",
                  va_sharepath, server)

        data2 = {"type": "SHARE", "key": "manila"}
        data2["id"] = va_sharepath
        data2["value"] = 'manila_share'
        path = self._update_object
        result = self._access_api(self.session, provider, path,
                                  json.dumps(data2), 'POST')
Esempio n. 14
0
    def validate_access_rules(access_rules, allowed_types, allowed_levels):
        """Validates access rules according to access_type and access_level.

        :param access_rules: List of access rules to be validated.
        :param allowed_types: tuple of allowed type values.
        :param allowed_levels: tuple of allowed level values.
        """
        for access in (access_rules or []):
            access_type = access['access_type']
            access_level = access['access_level']
            if access_type not in allowed_types:
                reason = _("Only %s access type allowed.") % (
                    ', '.join(tuple(["'%s'" % x for x in allowed_types])))
                raise exception.InvalidShareAccess(reason=reason)
            if access_level not in allowed_levels:
                raise exception.InvalidShareAccessLevel(level=access_level)
Esempio n. 15
0
    def _allow_access(self, context, share, access, share_server=None):
        if access['access_type'] != CEPHX_ACCESS_TYPE:
            raise exception.InvalidShareAccessType(type=access['access_type'])

        ceph_auth_id = access['access_to']

        # We need to check here rather than the API or Manila Client to see
        # if the ceph_auth_id is the same as the one specified for Manila's
        # usage. This is due to the fact that the API and the Manila client
        # cannot read the contents of the Manila configuration file. If it
        # is the same, we need to error out.
        if ceph_auth_id == CONF.cephfs_auth_id:
            error_message = (_('Ceph authentication ID %s must be different '
                               'than the one the Manila service uses.') %
                             ceph_auth_id)
            raise exception.InvalidShareAccess(reason=error_message)

        if not getattr(self.volume_client, 'version', None):
            if access['access_level'] == constants.ACCESS_LEVEL_RO:
                LOG.error("Need python-cephfs package version 10.2.3 or "
                          "greater to enable read-only access.")
                raise exception.InvalidShareAccessLevel(
                    level=constants.ACCESS_LEVEL_RO)

            auth_result = self.volume_client.authorize(
                cephfs_share_path(share), ceph_auth_id)
        else:
            readonly = access['access_level'] == constants.ACCESS_LEVEL_RO
            try:
                auth_result = self.volume_client.authorize(
                    cephfs_share_path(share),
                    ceph_auth_id,
                    readonly=readonly,
                    tenant_id=share['project_id'])
            except Exception as e:
                if 'not allowed' in str(e).lower():
                    msg = ("Access to client %(client)s is not allowed. "
                           "Reason: %(reason)s")
                    msg_payload = {'client': ceph_auth_id, 'reason': e}
                    raise exception.InvalidShareAccess(reason=msg %
                                                       msg_payload)
                raise

        return auth_result['auth_key']
Esempio n. 16
0
    def allow_access(self, context, share, share_name, access):
        """Allows access to a given NFS share."""
        if access['access_type'] != 'ip':
            reason = _('Only ip access type allowed.')
            raise exception.InvalidShareAccess(reason)

        self._ensure_export_policy(share, share_name)
        export_policy_name = self._get_export_policy_name(share)
        rule = access['access_to']

        if access['access_level'] == constants.ACCESS_LEVEL_RW:
            readonly = False
        elif access['access_level'] == constants.ACCESS_LEVEL_RO:
            readonly = True
        else:
            raise exception.InvalidShareAccessLevel(
                level=access['access_level'])

        self._client.add_nfs_export_rule(export_policy_name, rule, readonly)
Esempio n. 17
0
    def allow_access(self, context, share, share_name, access):
        """Allows access to a given NFS share."""
        if access['access_type'] != 'ip':
            msg = _("Cluster Mode supports only 'ip' type for share access"
                    " rules with NFS protocol.")
            raise exception.InvalidShareAccess(reason=msg)

        self._ensure_export_policy(share, share_name)
        export_policy_name = self._get_export_policy_name(share)
        rule = access['access_to']

        if access['access_level'] == constants.ACCESS_LEVEL_RW:
            readonly = False
        elif access['access_level'] == constants.ACCESS_LEVEL_RO:
            readonly = True
        else:
            raise exception.InvalidShareAccessLevel(
                level=access['access_level'])

        self._client.add_nfs_export_rule(export_policy_name, rule, readonly)
Esempio n. 18
0
    def test_update_access_add_rm(self):
        alice = {
            'id': 'instance_mapping_id1',
            'access_id': 'accessid1',
            'access_level': 'rw',
            'access_type': 'cephx',
            'access_to': 'alice'
        }
        bob = {
            'id': 'instance_mapping_id2',
            'access_id': 'accessid2',
            'access_level': 'ro',
            'access_type': 'cephx',
            'access_to': 'bob'
        }
        manila = {
            'id': 'instance_mapping_id3',
            'access_id': 'accessid3',
            'access_level': 'ro',
            'access_type': 'cephx',
            'access_to': 'manila'
        }
        admin = {
            'id': 'instance_mapping_id4',
            'access_id': 'accessid4',
            'access_level': 'rw',
            'access_type': 'cephx',
            'access_to': 'admin'
        }
        dabo = {
            'id': 'instance_mapping_id5',
            'access_id': 'accessid5',
            'access_level': 'rwx',
            'access_type': 'cephx',
            'access_to': 'dabo'
        }

        allow_access_side_effects = [
            'abc123',
            exception.InvalidShareAccess(reason='not'),
            exception.InvalidShareAccess(reason='allowed'),
            exception.InvalidShareAccessLevel(level='rwx')
        ]
        self.mock_object(self._native_protocol_helper.message_api, 'create')
        self.mock_object(self._native_protocol_helper, '_deny_access')
        self.mock_object(self._native_protocol_helper,
                         '_allow_access',
                         mock.Mock(side_effect=allow_access_side_effects))

        access_updates = self._native_protocol_helper.update_access(
            self._context,
            self._share,
            access_rules=[alice, manila, admin, dabo],
            add_rules=[alice, manila, admin, dabo],
            delete_rules=[bob])

        expected_access_updates = {
            'accessid1': {'access_key': 'abc123'},
            'accessid3': {'state': 'error'},
            'accessid4': {'state': 'error'},
            'accessid5': {'state': 'error'}
        }
        self.assertEqual(expected_access_updates, access_updates)
        self._native_protocol_helper._allow_access.assert_has_calls(
            [mock.call(self._context, self._share, alice),
             mock.call(self._context, self._share, manila),
             mock.call(self._context, self._share, admin)])
        self._native_protocol_helper._deny_access.assert_called_once_with(
            self._context, self._share, bob)
        self.assertEqual(
            3, self._native_protocol_helper.message_api.create.call_count)