"Fossies" - the Fresh Open Source Software Archive 
Member "manila-8.1.4/manila/share/drivers/netapp/dataontap/protocols/cifs_cmode.py" (19 Nov 2020, 7286 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 "cifs_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 CIFS protocol helper class.
16 """
17
18 import re
19
20 from manila.common import constants
21 from manila import exception
22 from manila.i18n import _
23 from manila.share.drivers.netapp.dataontap.protocols import base
24 from manila.share.drivers.netapp import utils as na_utils
25
26
27 class NetAppCmodeCIFSHelper(base.NetAppBaseHelper):
28 """NetApp cDOT CIFS protocol helper class."""
29
30 @na_utils.trace
31 def create_share(self, share, share_name,
32 clear_current_export_policy=True):
33 """Creates CIFS share on Data ONTAP Vserver."""
34 self._client.create_cifs_share(share_name)
35 if clear_current_export_policy:
36 self._client.remove_cifs_share_access(share_name, 'Everyone')
37
38 # Ensure 'ntfs' security style
39 self._client.set_volume_security_style(share_name,
40 security_style='ntfs')
41
42 # Return a callback that may be used for generating export paths
43 # for this share.
44 return (lambda export_address, share_name=share_name:
45 r'\\%s\%s' % (export_address, share_name))
46
47 @na_utils.trace
48 def delete_share(self, share, share_name):
49 """Deletes CIFS share on Data ONTAP Vserver."""
50 host_ip, share_name = self._get_export_location(share)
51 self._client.remove_cifs_share(share_name)
52
53 @na_utils.trace
54 @base.access_rules_synchronized
55 def update_access(self, share, share_name, rules):
56 """Replaces the list of access rules known to the backend storage."""
57
58 # Ensure rules are valid
59 for rule in rules:
60 self._validate_access_rule(rule)
61
62 new_rules = {rule['access_to']: rule['access_level'] for rule in rules}
63
64 # Get rules from share
65 existing_rules = self._get_access_rules(share, share_name)
66
67 # Update rules in an order that will prevent transient disruptions
68 self._handle_added_rules(share_name, existing_rules, new_rules)
69 self._handle_ro_to_rw_rules(share_name, existing_rules, new_rules)
70 self._handle_rw_to_ro_rules(share_name, existing_rules, new_rules)
71 self._handle_deleted_rules(share_name, existing_rules, new_rules)
72
73 @na_utils.trace
74 def _validate_access_rule(self, rule):
75 """Checks whether access rule type and level are valid."""
76
77 if rule['access_type'] != 'user':
78 msg = _("Clustered Data ONTAP supports only 'user' type for "
79 "share access rules with CIFS protocol.")
80 raise exception.InvalidShareAccess(reason=msg)
81
82 if rule['access_level'] not in constants.ACCESS_LEVELS:
83 raise exception.InvalidShareAccessLevel(level=rule['access_level'])
84
85 @na_utils.trace
86 def _handle_added_rules(self, share_name, existing_rules, new_rules):
87 """Updates access rules added between two rule sets."""
88 added_rules = {
89 user_or_group: permission
90 for user_or_group, permission in new_rules.items()
91 if user_or_group not in existing_rules
92 }
93
94 for user_or_group, permission in added_rules.items():
95 self._client.add_cifs_share_access(
96 share_name, user_or_group, self._is_readonly(permission))
97
98 @na_utils.trace
99 def _handle_ro_to_rw_rules(self, share_name, existing_rules, new_rules):
100 """Updates access rules modified (RO-->RW) between two rule sets."""
101 modified_rules = {
102 user_or_group: permission
103 for user_or_group, permission in new_rules.items()
104 if (user_or_group in existing_rules and
105 permission == constants.ACCESS_LEVEL_RW and
106 existing_rules[user_or_group] != 'full_control')
107 }
108
109 for user_or_group, permission in modified_rules.items():
110 self._client.modify_cifs_share_access(
111 share_name, user_or_group, self._is_readonly(permission))
112
113 @na_utils.trace
114 def _handle_rw_to_ro_rules(self, share_name, existing_rules, new_rules):
115 """Returns access rules modified (RW-->RO) between two rule sets."""
116 modified_rules = {
117 user_or_group: permission
118 for user_or_group, permission in new_rules.items()
119 if (user_or_group in existing_rules and
120 permission == constants.ACCESS_LEVEL_RO and
121 existing_rules[user_or_group] != 'read')
122 }
123
124 for user_or_group, permission in modified_rules.items():
125 self._client.modify_cifs_share_access(
126 share_name, user_or_group, self._is_readonly(permission))
127
128 @na_utils.trace
129 def _handle_deleted_rules(self, share_name, existing_rules, new_rules):
130 """Returns access rules deleted between two rule sets."""
131 deleted_rules = {
132 user_or_group: permission
133 for user_or_group, permission in existing_rules.items()
134 if user_or_group not in new_rules
135 }
136
137 for user_or_group, permission in deleted_rules.items():
138 self._client.remove_cifs_share_access(share_name, user_or_group)
139
140 @na_utils.trace
141 def _get_access_rules(self, share, share_name):
142 """Returns the list of access rules known to the backend storage."""
143 return self._client.get_cifs_share_access(share_name)
144
145 @na_utils.trace
146 def get_target(self, share):
147 """Returns OnTap target IP based on share export location."""
148 return self._get_export_location(share)[0]
149
150 @na_utils.trace
151 def get_share_name_for_share(self, share):
152 """Returns the flexvol name that hosts a share."""
153 _, share_name = self._get_export_location(share)
154 return share_name
155
156 @staticmethod
157 def _get_export_location(share):
158 """Returns host ip and share name for a given CIFS share."""
159 export_location = share['export_location'] or '\\\\\\'
160 regex = r'^(?:\\\\|//)(?P<host_ip>.*)(?:\\|/)(?P<share_name>.*)$'
161 match = re.match(regex, export_location)
162 if match:
163 return match.group('host_ip'), match.group('share_name')
164 else:
165 return '', ''
166
167 @na_utils.trace
168 def cleanup_demoted_replica(self, share, share_name):
169 """Cleans up some things regarding a demoted replica."""
170 # NOTE(carloss): This is necessary due to bug 1879368. If we do not
171 # remove this CIFS share, in case the demoted replica is promoted
172 # back, the promotion will fail due to a duplicated entry for the
173 # share, since a create share request is sent to the backend every
174 # time a promotion occurs.
175 self._client.remove_cifs_share(share_name)