Coverage for manila/api/v2/share_network_subnets.py: 95%
167 statements
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
1# Copyright 2019 NetApp, Inc.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
16from http import client as http_client
18from oslo_config import cfg
19from oslo_db import exception as db_exception
20from oslo_log import log
21import webob
22from webob import exc
24from manila.api import common as api_common
25from manila.api.openstack import api_version_request as api_version
26from manila.api.openstack import wsgi
27from manila.api.v2 import metadata as metadata_controller
28from manila.api.views import share_network_subnets as subnet_views
29from manila.db import api as db_api
30from manila import exception
31from manila.i18n import _
32from manila.message import api as message_api
33from manila.message import message_field
34from manila import share
35from manila.share import rpcapi as share_rpcapi
37LOG = log.getLogger(__name__)
38CONF = cfg.CONF
41class ShareNetworkSubnetController(wsgi.Controller,
42 metadata_controller.MetadataController):
43 """The Share Network Subnet API controller for the OpenStack API."""
45 resource_name = 'share_network_subnet'
46 _view_builder_class = subnet_views.ViewBuilder
48 def __init__(self):
49 super(ShareNetworkSubnetController, self).__init__()
50 self.share_rpcapi = share_rpcapi.ShareAPI()
51 self.share_api = share.API()
52 self.message_api = message_api.API()
54 @wsgi.Controller.api_version("2.51")
55 @wsgi.Controller.authorize
56 def index(self, req, share_network_id):
57 """Returns a list of share network subnets."""
58 context = req.environ['manila.context']
60 try:
61 share_network = db_api.share_network_get(context, share_network_id)
62 except exception.ShareNetworkNotFound as e:
63 raise exc.HTTPNotFound(explanation=e.msg)
65 return self._view_builder.build_share_network_subnets(
66 req, share_network.get('share_network_subnets'))
68 def _all_share_servers_are_auto_deletable(self, share_network_subnet):
69 return all([ss['is_auto_deletable'] for ss
70 in share_network_subnet['share_servers']])
72 @wsgi.Controller.api_version('2.51')
73 @wsgi.Controller.authorize
74 def delete(self, req, share_network_id, share_network_subnet_id):
75 """Delete specified share network subnet."""
76 context = req.environ['manila.context']
78 try:
79 db_api.share_network_get(context, share_network_id)
80 except exception.ShareNetworkNotFound as e:
81 raise exc.HTTPNotFound(explanation=e.msg)
83 try:
84 share_network_subnet = db_api.share_network_subnet_get(
85 context, share_network_subnet_id)
86 except exception.ShareNetworkSubnetNotFound as e:
87 raise exc.HTTPNotFound(explanation=e.msg)
89 for share_server in share_network_subnet['share_servers'] or []:
90 shares = db_api.share_instance_get_all_by_share_server(
91 context, share_server['id'])
92 if shares:
93 msg = _("Cannot delete share network subnet %(id)s, it has "
94 "one or more shares.") % {
95 'id': share_network_subnet_id}
96 LOG.error(msg)
97 raise exc.HTTPConflict(explanation=msg)
99 share_groups = db_api.share_group_get_all_by_share_server(
100 context, share_server['id'])
101 if share_groups: 101 ↛ 102line 101 didn't jump to line 102 because the condition on line 101 was never true
102 msg = _("Cannot delete share network subnet %(id)s, it has "
103 "one or more share groups.") % {
104 'id': share_network_subnet_id}
105 LOG.error(msg)
106 raise exc.HTTPConflict(explanation=msg)
108 # NOTE(silvacarlose): Do not allow the deletion of any share server
109 # if any of them has the flag is_auto_deletable = False
110 if not self._all_share_servers_are_auto_deletable(
111 share_network_subnet):
112 msg = _("The service cannot determine if there are any "
113 "non-managed shares on the share network subnet %(id)s,"
114 "so it cannot be deleted. Please contact the cloud "
115 "administrator to rectify.") % {
116 'id': share_network_subnet_id}
117 LOG.error(msg)
118 raise exc.HTTPConflict(explanation=msg)
120 for share_server in share_network_subnet['share_servers']:
121 self.share_rpcapi.delete_share_server(context, share_server)
123 db_api.share_network_subnet_delete(context, share_network_subnet_id)
124 return webob.Response(status_int=http_client.ACCEPTED)
126 @wsgi.Controller.api_version("2.51")
127 @wsgi.Controller.authorize
128 def create(self, req, share_network_id, body):
129 """Add a new share network subnet into the share network."""
130 context = req.environ['manila.context']
131 if not self.is_valid_body(body, 'share-network-subnet'):
132 msg = _("Share Network Subnet is missing from the request body.")
133 raise exc.HTTPBadRequest(explanation=msg)
134 data = body['share-network-subnet']
136 if req.api_version_request >= api_version.APIVersionRequest("2.78"):
137 api_common.check_metadata_properties(data.get('metadata'))
138 else:
139 data.pop('metadata', None)
141 data['share_network_id'] = share_network_id
142 multiple_subnet_support = (req.api_version_request >=
143 api_version.APIVersionRequest("2.70"))
144 share_network, existing_subnets = api_common.validate_subnet_create(
145 context, share_network_id, data, multiple_subnet_support)
147 # create subnet operation on subnets with share servers means that an
148 # allocation update is requested.
149 if existing_subnets and existing_subnets[0]['share_servers']:
151 # NOTE(felipe_rodrigues): all subnets have the same set of share
152 # servers, so we can just get the servers from one of them. Not
153 # necessarily all share servers from the specified AZ will be
154 # updated, only the ones created with subnets in the AZ. Others
155 # created with default AZ will only have its allocations updated
156 # when default subnet set is updated.
157 data['share_servers'] = existing_subnets[0]['share_servers']
158 try:
159 share_network_subnet = (
160 self.share_api.update_share_server_network_allocations(
161 context, share_network, data))
162 except exception.ServiceIsDown as e:
163 msg = _('Could not add the share network subnet.')
164 LOG.error(e)
165 raise exc.HTTPInternalServerError(explanation=msg)
166 except exception.InvalidShareNetwork as e:
167 raise exc.HTTPBadRequest(explanation=e.msg)
168 except db_exception.DBError as e:
169 msg = _('Could not add the share network subnet.')
170 LOG.error(e)
171 raise exc.HTTPInternalServerError(explanation=msg)
172 else:
173 try:
174 share_network_subnet = db_api.share_network_subnet_create(
175 context, data)
176 metadata_support = (req.api_version_request >=
177 api_version.APIVersionRequest("2.89"))
178 if metadata_support and data.get('metadata'): 178 ↛ 179line 178 didn't jump to line 179 because the condition on line 178 was never true
179 context = req.environ['manila.context']
180 self.share_api.update_share_network_subnet_from_metadata(
181 context,
182 share_network_id,
183 share_network_subnet['id'],
184 data.get('metadata'))
185 except db_exception.DBError as e:
186 msg = _('Could not create the share network subnet.')
187 LOG.error(e)
188 raise exc.HTTPInternalServerError(explanation=msg)
190 share_network_subnet = db_api.share_network_subnet_get(
191 context, share_network_subnet['id'])
192 return self._view_builder.build_share_network_subnet(
193 req, share_network_subnet)
195 @wsgi.Controller.api_version('2.51')
196 @wsgi.Controller.authorize
197 def show(self, req, share_network_id, share_network_subnet_id):
198 """Show share network subnet."""
199 context = req.environ['manila.context']
201 try:
202 db_api.share_network_get(context, share_network_id)
203 except exception.ShareNetworkNotFound as e:
204 raise exc.HTTPNotFound(explanation=e.msg)
206 try:
207 share_network_subnet = db_api.share_network_subnet_get(
208 context, share_network_subnet_id)
209 except exception.ShareNetworkSubnetNotFound as e:
210 raise exc.HTTPNotFound(explanation=e.msg)
212 return self._view_builder.build_share_network_subnet(
213 req, share_network_subnet)
215 @wsgi.Controller.api_version("2.78")
216 @wsgi.Controller.authorize("get_metadata")
217 def index_metadata(self, req, share_network_id, resource_id):
218 """Returns the list of metadata for a given share network subnet."""
219 return self._index_metadata(req, resource_id,
220 parent_id=share_network_id)
222 @wsgi.Controller.api_version("2.78")
223 @wsgi.Controller.authorize("update_metadata")
224 def create_metadata(self, req, share_network_id, resource_id, body):
225 """Create metadata for a given share network subnet."""
226 metadata = self._create_metadata(req, resource_id, body,
227 parent_id=share_network_id)
228 if req.api_version_request >= api_version.APIVersionRequest("2.89"):
229 context = req.environ['manila.context']
230 self.share_api.update_share_network_subnet_from_metadata(
231 context,
232 share_network_id,
233 resource_id,
234 metadata.get('metadata'))
235 return metadata
237 @wsgi.Controller.api_version("2.78")
238 @wsgi.Controller.authorize("update_metadata")
239 def update_all_metadata(self, req, share_network_id, resource_id, body):
240 """Update entire metadata for a given share network subnet."""
241 metadata = self._update_all_metadata(req, resource_id, body,
242 parent_id=share_network_id)
243 if req.api_version_request >= api_version.APIVersionRequest("2.89"):
244 context = req.environ['manila.context']
245 self.share_api.update_share_network_subnet_from_metadata(
246 context,
247 share_network_id,
248 resource_id,
249 metadata.get('metadata'))
250 return metadata
252 @wsgi.Controller.api_version("2.78")
253 @wsgi.Controller.authorize("update_metadata")
254 def update_metadata_item(self, req, share_network_id, resource_id, body,
255 key):
256 """Update metadata item for a given share network subnet."""
257 metadata = self._update_metadata_item(req, resource_id, body, key,
258 parent_id=share_network_id)
259 if req.api_version_request >= api_version.APIVersionRequest("2.89"):
260 context = req.environ['manila.context']
261 self.share_api.update_share_network_subnet_from_metadata(
262 context,
263 share_network_id,
264 resource_id,
265 metadata.get('metadata'))
266 return metadata
268 @wsgi.Controller.api_version("2.78")
269 @wsgi.Controller.authorize("get_metadata")
270 def show_metadata(self, req, share_network_id, resource_id, key):
271 """Show metadata for a given share network subnet."""
272 return self._show_metadata(req, resource_id, key,
273 parent_id=share_network_id)
275 @wsgi.Controller.api_version("2.78")
276 @wsgi.Controller.authorize("delete_metadata")
277 def delete_metadata(self, req, share_network_id, resource_id, key):
278 """Delete metadata for a given share network subnet."""
279 if req.api_version_request >= api_version.APIVersionRequest("2.89"):
280 driver_keys = getattr(
281 CONF, 'driver_updatable_subnet_metadata', [])
282 if key in driver_keys: 282 ↛ 293line 282 didn't jump to line 293 because the condition on line 282 was always true
283 context = req.environ['manila.context']
284 share_network = db_api.share_network_get(
285 context, share_network_id)
286 self.message_api.create(
287 context,
288 message_field.Action.UPDATE_METADATA,
289 share_network['project_id'],
290 resource_type=message_field.Resource.SHARE_NETWORK_SUBNET,
291 resource_id=resource_id,
292 detail=message_field.Detail.UPDATE_METADATA_NOT_DELETED)
293 return self._delete_metadata(req, resource_id, key,
294 parent_id=share_network_id)
297def create_resource():
298 return wsgi.Resource(ShareNetworkSubnetController())