"Fossies" - the Fresh Open Source Software Archive

Member "manila-8.1.4/manila/share/drivers/netapp/dataontap/protocols/nfs_cmode.py" (19 Nov 2020, 7457 Bytes) of package /linux/misc/openstack/manila-8.1.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "nfs_cmode.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 8.1.3_vs_8.1.4.

    1 # Copyright (c) 2015 Clinton Knight.  All rights reserved.
    2 #
    3 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
    4 #    not use this file except in compliance with the License. You may obtain
    5 #    a copy of the License at
    6 #
    7 #         http://www.apache.org/licenses/LICENSE-2.0
    8 #
    9 #    Unless required by applicable law or agreed to in writing, software
   10 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   11 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   12 #    License for the specific language governing permissions and limitations
   13 #    under the License.
   14 """
   15 NetApp cDOT NFS protocol helper class.
   16 """
   17 
   18 import uuid
   19 
   20 from oslo_log import log
   21 import six
   22 
   23 from manila.common import constants
   24 from manila import exception
   25 from manila.share.drivers.netapp.dataontap.protocols import base
   26 from manila.share.drivers.netapp import utils as na_utils
   27 
   28 
   29 LOG = log.getLogger(__name__)
   30 
   31 
   32 class NetAppCmodeNFSHelper(base.NetAppBaseHelper):
   33     """NetApp cDOT NFS protocol helper class."""
   34 
   35     @staticmethod
   36     def _escaped_address(address):
   37         if ':' in address:
   38             return '[%s]' % address
   39         else:
   40             return address
   41 
   42     @na_utils.trace
   43     def create_share(self, share, share_name,
   44                      clear_current_export_policy=True):
   45         """Creates NFS share."""
   46         if clear_current_export_policy:
   47             self._client.clear_nfs_export_policy_for_volume(share_name)
   48         self._ensure_export_policy(share, share_name)
   49         export_path = self._client.get_volume_junction_path(share_name)
   50 
   51         # Return a callback that may be used for generating export paths
   52         # for this share.
   53         return (lambda export_address, export_path=export_path:
   54                 ':'.join([self._escaped_address(export_address),
   55                           export_path]))
   56 
   57     @na_utils.trace
   58     @base.access_rules_synchronized
   59     def delete_share(self, share, share_name):
   60         """Deletes NFS share."""
   61         LOG.debug('Deleting NFS export policy for share %s', share['id'])
   62         export_policy_name = self._get_export_policy_name(share)
   63         self._client.clear_nfs_export_policy_for_volume(share_name)
   64         self._client.soft_delete_nfs_export_policy(export_policy_name)
   65 
   66     @na_utils.trace
   67     @base.access_rules_synchronized
   68     def update_access(self, share, share_name, rules):
   69         """Replaces the list of access rules known to the backend storage."""
   70 
   71         # Ensure rules are valid
   72         for rule in rules:
   73             self._validate_access_rule(rule)
   74 
   75         # Sort rules by ascending network size
   76         new_rules = {rule['access_to']: rule['access_level'] for rule in rules}
   77         addresses = sorted(new_rules, reverse=True)
   78 
   79         # Ensure current export policy has the name we expect
   80         self._ensure_export_policy(share, share_name)
   81         export_policy_name = self._get_export_policy_name(share)
   82 
   83         # Make temp policy names so this non-atomic workflow remains resilient
   84         # across process interruptions.
   85         temp_new_export_policy_name = self._get_temp_export_policy_name()
   86         temp_old_export_policy_name = self._get_temp_export_policy_name()
   87 
   88         # Create new export policy
   89         self._client.create_nfs_export_policy(temp_new_export_policy_name)
   90 
   91         # Add new rules to new policy
   92         for address in addresses:
   93             self._client.add_nfs_export_rule(
   94                 temp_new_export_policy_name, address,
   95                 self._is_readonly(new_rules[address]))
   96 
   97         # Rename policy currently in force
   98         LOG.info('Renaming NFS export policy for share %(share)s to '
   99                  '%(policy)s.',
  100                  {'share': share_name, 'policy': temp_old_export_policy_name})
  101         self._client.rename_nfs_export_policy(export_policy_name,
  102                                               temp_old_export_policy_name)
  103 
  104         # Switch share to the new policy
  105         LOG.info('Setting NFS export policy for share %(share)s to '
  106                  '%(policy)s.',
  107                  {'share': share_name, 'policy': temp_new_export_policy_name})
  108         self._client.set_nfs_export_policy_for_volume(
  109             share_name, temp_new_export_policy_name)
  110 
  111         # Delete old policy
  112         self._client.soft_delete_nfs_export_policy(temp_old_export_policy_name)
  113 
  114         # Rename new policy to its final name
  115         LOG.info('Renaming NFS export policy for share %(share)s to '
  116                  '%(policy)s.',
  117                  {'share': share_name, 'policy': export_policy_name})
  118         self._client.rename_nfs_export_policy(temp_new_export_policy_name,
  119                                               export_policy_name)
  120 
  121     @na_utils.trace
  122     def _validate_access_rule(self, rule):
  123         """Checks whether access rule type and level are valid."""
  124 
  125         if rule['access_type'] != 'ip':
  126             msg = ("Clustered Data ONTAP supports only 'ip' type for share "
  127                    "access rules with NFS protocol.")
  128             raise exception.InvalidShareAccess(reason=msg)
  129 
  130         if rule['access_level'] not in constants.ACCESS_LEVELS:
  131             raise exception.InvalidShareAccessLevel(level=rule['access_level'])
  132 
  133     @na_utils.trace
  134     def get_target(self, share):
  135         """Returns ID of target OnTap device based on export location."""
  136         return self._get_export_location(share)[0]
  137 
  138     @na_utils.trace
  139     def get_share_name_for_share(self, share):
  140         """Returns the flexvol name that hosts a share."""
  141         _, volume_junction_path = self._get_export_location(share)
  142         volume = self._client.get_volume_at_junction_path(volume_junction_path)
  143         return volume.get('name') if volume else None
  144 
  145     @staticmethod
  146     def _get_export_location(share):
  147         """Returns IP address and export location of an NFS share."""
  148         export_location = share['export_location'] or ':'
  149         result = export_location.rsplit(':', 1)
  150         if len(result) != 2:
  151             return ['', '']
  152         return result
  153 
  154     @staticmethod
  155     def _get_temp_export_policy_name():
  156         """Builds export policy name for an NFS share."""
  157         return 'temp_' + six.text_type(uuid.uuid1()).replace('-', '_')
  158 
  159     @staticmethod
  160     def _get_export_policy_name(share):
  161         """Builds export policy name for an NFS share."""
  162         return 'policy_' + share['id'].replace('-', '_')
  163 
  164     @na_utils.trace
  165     def _ensure_export_policy(self, share, share_name):
  166         """Ensures a flexvol/share has an export policy.
  167 
  168         This method ensures a flexvol has an export policy with a name
  169         containing the share ID.  For legacy reasons, this may not
  170         always be the case.
  171         """
  172         expected_export_policy = self._get_export_policy_name(share)
  173         actual_export_policy = self._client.get_nfs_export_policy_for_volume(
  174             share_name)
  175 
  176         if actual_export_policy == expected_export_policy:
  177             return
  178         elif actual_export_policy == 'default':
  179             self._client.create_nfs_export_policy(expected_export_policy)
  180             self._client.set_nfs_export_policy_for_volume(
  181                 share_name, expected_export_policy)
  182         else:
  183             self._client.rename_nfs_export_policy(actual_export_policy,
  184                                                   expected_export_policy)
  185 
  186     @na_utils.trace
  187     def cleanup_demoted_replica(self, share, share_name):
  188         return