Add share network with multiple subnets
This patch adds the possibility to create share networks with multiple subnets in Manila. It also updates the share server api to receive "share_network_subnet_id" instead of "share_network_id". Each share network subnet must be associated with only one availability zone. Each share network must have a single default share network subnet. DocImpact APIImpact Depends-On: I13bb48e7c03e16c26946ccf9d48e80592391a3d1 Partially-implements: bp share-network-multiple-subnets Change-Id: Id8814a8b26c9b9dcb1fe71d0d7e9b79e8b8a9210 Closes-Bug: #1588144 Co-Authored-By: lseki <luciomitsuru.seki@fit-tecnologia.org.br> Co-Authored-By: dviroel <viroel@gmail.com>
This commit is contained in:
parent
523c5aaa3a
commit
14d3e268a0
@ -19,6 +19,7 @@ import re
|
||||
import six
|
||||
import string
|
||||
|
||||
from operator import xor
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
from oslo_utils import encodeutils
|
||||
@ -184,6 +185,14 @@ def dict_to_query_str(params):
|
||||
return param_str.rstrip('&')
|
||||
|
||||
|
||||
def check_net_id_and_subnet_id(body):
|
||||
if xor('neutron_net_id' in body, 'neutron_subnet_id' in body):
|
||||
msg = _("When creating a new share network subnet you need to "
|
||||
"specify both neutron_net_id and neutron_subnet_id or "
|
||||
"none of them.")
|
||||
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
|
||||
class ViewBuilder(object):
|
||||
"""Model API responses as dictionaries."""
|
||||
|
||||
|
@ -137,13 +137,16 @@ REST_API_VERSION_HISTORY = """
|
||||
* 2.50 - Added update share type API to Share Type APIs. Through this API
|
||||
we can update the ``name``, ``description`` and/or
|
||||
``share_type_access:is_public`` fields of the share type.
|
||||
* 2.51 - Added Share Network with multiple Subnets. Updated Share Networks
|
||||
to handle with one or more subnets in different availability
|
||||
zones.
|
||||
"""
|
||||
|
||||
# The minimum and maximum versions of the API supported
|
||||
# The default api version request is defined to be the
|
||||
# minimum version of the API supported.
|
||||
_MIN_API_VERSION = "2.0"
|
||||
_MAX_API_VERSION = "2.50"
|
||||
_MAX_API_VERSION = "2.51"
|
||||
DEFAULT_API_VERSION = _MIN_API_VERSION
|
||||
|
||||
|
||||
|
@ -281,3 +281,9 @@ user documentation.
|
||||
Added update share type API to Share Type APIs. We can update the ``name``,
|
||||
``description`` and/or ``share_type_access:is_public`` fields of the share
|
||||
type by the update share type API.
|
||||
|
||||
2.51
|
||||
----
|
||||
Added to the service the possibility to have multiple subnets per share
|
||||
network, each of them associated to a different AZ. It is also possible to
|
||||
configure a default subnet that spans all availability zones.
|
||||
|
@ -151,9 +151,11 @@ class SecurityServiceController(wsgi.Controller):
|
||||
security_service_id):
|
||||
share_networks = db.share_network_get_all_by_security_service(
|
||||
context, security_service_id)
|
||||
|
||||
for sn in share_networks:
|
||||
if sn['share_servers']:
|
||||
return True
|
||||
for sns in sn['share_network_subnets']:
|
||||
if 'share_servers' in sns and sns['share_servers']:
|
||||
return True
|
||||
return False
|
||||
|
||||
def update(self, req, id, body):
|
||||
|
@ -47,21 +47,34 @@ class ShareServerController(wsgi.Controller):
|
||||
|
||||
search_opts = {}
|
||||
search_opts.update(req.GET)
|
||||
|
||||
share_servers = db_api.share_server_get_all(context)
|
||||
for s in share_servers:
|
||||
s.project_id = s.share_network['project_id']
|
||||
if s.share_network['name']:
|
||||
s.share_network_name = s.share_network['name']
|
||||
else:
|
||||
s.share_network_name = s.share_network_id
|
||||
try:
|
||||
s.share_network_id = s.share_network_subnet['share_network_id']
|
||||
share_network = db_api.share_network_get(
|
||||
context, s.share_network_id)
|
||||
s.project_id = share_network['project_id']
|
||||
if share_network['name']:
|
||||
s.share_network_name = share_network['name']
|
||||
else:
|
||||
s.share_network_name = share_network['id']
|
||||
except exception.ShareNetworkNotFound:
|
||||
# NOTE(dviroel): The share-network may already be deleted while
|
||||
# the share-server is in 'deleting' state. In this scenario,
|
||||
# we will return some empty values.
|
||||
LOG.debug("Unable to retrieve share network details for share "
|
||||
"server %(server)s, the network %(network)s was "
|
||||
"not found.",
|
||||
{'server': s.id, 'network': s.share_network_id})
|
||||
s.project_id = ''
|
||||
s.share_network_name = ''
|
||||
if search_opts:
|
||||
for k, v in search_opts.items():
|
||||
share_servers = [s for s in share_servers if
|
||||
(hasattr(s, k) and
|
||||
s[k] == v or k == 'share_network' and
|
||||
v in [s.share_network['name'],
|
||||
s.share_network['id']])]
|
||||
v in [s.share_network_name,
|
||||
s.share_network_id])]
|
||||
return self._view_builder.build_share_servers(req, share_servers)
|
||||
|
||||
@wsgi.Controller.authorize
|
||||
@ -70,13 +83,21 @@ class ShareServerController(wsgi.Controller):
|
||||
context = req.environ['manila.context']
|
||||
try:
|
||||
server = db_api.share_server_get(context, id)
|
||||
server.project_id = server.share_network["project_id"]
|
||||
if server.share_network['name']:
|
||||
server.share_network_name = server.share_network['name']
|
||||
share_network = db_api.share_network_get(
|
||||
context, server.share_network_subnet['share_network_id'])
|
||||
server.share_network_id = share_network['id']
|
||||
server.project_id = share_network['project_id']
|
||||
if share_network['name']:
|
||||
server.share_network_name = share_network['name']
|
||||
else:
|
||||
server.share_network_name = server.share_network_id
|
||||
server.share_network_name = share_network['id']
|
||||
except exception.ShareServerNotFound as e:
|
||||
raise exc.HTTPNotFound(explanation=e)
|
||||
raise exc.HTTPNotFound(explanation=e.msg)
|
||||
except exception.ShareNetworkNotFound as e:
|
||||
msg = _("Share server %s could not be found. Its associated "
|
||||
"share network does not "
|
||||
"exist.") % server.share_network_subnet['share_network_id']
|
||||
raise exc.HTTPNotFound(explanation=msg)
|
||||
return self._view_builder.build_share_server(req, server)
|
||||
|
||||
@wsgi.Controller.authorize
|
||||
@ -86,7 +107,7 @@ class ShareServerController(wsgi.Controller):
|
||||
try:
|
||||
share_server = db_api.share_server_get(context, id)
|
||||
except exception.ShareServerNotFound as e:
|
||||
raise exc.HTTPNotFound(explanation=e)
|
||||
raise exc.HTTPNotFound(explanation=e.msg)
|
||||
|
||||
return self._view_builder.build_share_server_details(
|
||||
share_server['backend_details'])
|
||||
@ -98,7 +119,7 @@ class ShareServerController(wsgi.Controller):
|
||||
try:
|
||||
share_server = db_api.share_server_get(context, id)
|
||||
except exception.ShareServerNotFound as e:
|
||||
raise exc.HTTPNotFound(explanation=e)
|
||||
raise exc.HTTPNotFound(explanation=e.msg)
|
||||
allowed_statuses = [constants.STATUS_ERROR, constants.STATUS_ACTIVE]
|
||||
if share_server['status'] not in allowed_statuses:
|
||||
data = {
|
||||
@ -112,7 +133,7 @@ class ShareServerController(wsgi.Controller):
|
||||
try:
|
||||
self.share_api.delete_share_server(context, share_server)
|
||||
except exception.ShareServerInUse as e:
|
||||
raise exc.HTTPConflict(explanation=e)
|
||||
raise exc.HTTPConflict(explanation=e.msg)
|
||||
return webob.Response(status_int=http_client.ACCEPTED)
|
||||
|
||||
|
||||
|
@ -341,8 +341,15 @@ class ShareMixin(object):
|
||||
context,
|
||||
share_network_id)
|
||||
except exception.ShareNetworkNotFound as e:
|
||||
raise exc.HTTPNotFound(explanation=six.text_type(e))
|
||||
raise exc.HTTPNotFound(explanation=e.msg)
|
||||
kwargs['share_network_id'] = share_network_id
|
||||
if availability_zone_id:
|
||||
if not db.share_network_subnet_get_by_availability_zone_id(
|
||||
context, share_network_id,
|
||||
availability_zone_id=availability_zone_id):
|
||||
msg = _("A share network subnet was not found for the "
|
||||
"requested availability zone.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
display_name = share.get('display_name')
|
||||
display_description = share.get('display_description')
|
||||
|
@ -43,6 +43,7 @@ from manila.api.v2 import share_group_types
|
||||
from manila.api.v2 import share_groups
|
||||
from manila.api.v2 import share_instance_export_locations
|
||||
from manila.api.v2 import share_instances
|
||||
from manila.api.v2 import share_network_subnets
|
||||
from manila.api.v2 import share_networks
|
||||
from manila.api.v2 import share_replica_export_locations
|
||||
from manila.api.v2 import share_replicas
|
||||
@ -296,6 +297,33 @@ class APIRouter(manila.api.openstack.APIRouter):
|
||||
collection={"detail": "GET"},
|
||||
member={"action": "POST"})
|
||||
|
||||
self.resources["share_network_subnets"] = (
|
||||
share_network_subnets.create_resource())
|
||||
mapper.connect("share-networks",
|
||||
"/{project_id}/share-networks/{share_network_id}/"
|
||||
"subnets",
|
||||
controller=self.resources["share_network_subnets"],
|
||||
action="create",
|
||||
conditions={"method": ["POST"]})
|
||||
mapper.connect("share-networks",
|
||||
"/{project_id}/share-networks/{share_network_id}/"
|
||||
"subnets/{share_network_subnet_id}",
|
||||
controller=self.resources["share_network_subnets"],
|
||||
action="delete",
|
||||
conditions={"method": ["DELETE"]})
|
||||
mapper.connect("share-networks",
|
||||
"/{project_id}/share-networks/{share_network_id}/"
|
||||
"subnets/{share_network_subnet_id}",
|
||||
controller=self.resources["share_network_subnets"],
|
||||
action="show",
|
||||
conditions={"method": ["GET"]})
|
||||
mapper.connect("share-networks",
|
||||
"/{project_id}/share-networks/{share_network_id}/"
|
||||
"subnets",
|
||||
controller=self.resources["share_network_subnets"],
|
||||
action="index",
|
||||
conditions={"method": ["GET"]})
|
||||
|
||||
self.resources["share_servers"] = share_servers.create_resource()
|
||||
mapper.resource("share_server",
|
||||
"share-servers",
|
||||
|
202
manila/api/v2/share_network_subnets.py
Normal file
202
manila/api/v2/share_network_subnets.py
Normal file
@ -0,0 +1,202 @@
|
||||
# Copyright 2019 NetApp, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
from manila.api import common
|
||||
from oslo_db import exception as db_exception
|
||||
from oslo_log import log
|
||||
from six.moves import http_client
|
||||
import webob
|
||||
from webob import exc
|
||||
|
||||
from manila.api.openstack import wsgi
|
||||
from manila.api.views import share_network_subnets as subnet_views
|
||||
from manila.db import api as db_api
|
||||
from manila import exception
|
||||
from manila.i18n import _
|
||||
from manila.share import rpcapi as share_rpcapi
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class ShareNetworkSubnetController(wsgi.Controller):
|
||||
"""The Share Network Subnet API controller for the OpenStack API."""
|
||||
|
||||
resource_name = 'share_network_subnet'
|
||||
_view_builder_class = subnet_views.ViewBuilder
|
||||
|
||||
def __init__(self):
|
||||
super(ShareNetworkSubnetController, self).__init__()
|
||||
self.share_rpcapi = share_rpcapi.ShareAPI()
|
||||
|
||||
@wsgi.Controller.api_version("2.51")
|
||||
@wsgi.Controller.authorize
|
||||
def index(self, req, share_network_id):
|
||||
"""Returns a list of share network subnets."""
|
||||
context = req.environ['manila.context']
|
||||
|
||||
try:
|
||||
share_network = db_api.share_network_get(context, share_network_id)
|
||||
except exception.ShareNetworkNotFound as e:
|
||||
raise exc.HTTPNotFound(explanation=e.msg)
|
||||
|
||||
return self._view_builder.build_share_network_subnets(
|
||||
req, share_network.get('share_network_subnets'))
|
||||
|
||||
def _all_share_servers_are_auto_deletable(self, share_network_subnet):
|
||||
return all([ss['is_auto_deletable'] for ss
|
||||
in share_network_subnet['share_servers']])
|
||||
|
||||
@wsgi.Controller.api_version('2.51')
|
||||
@wsgi.Controller.authorize
|
||||
def delete(self, req, share_network_id, share_network_subnet_id):
|
||||
"""Delete specified share network subnet."""
|
||||
context = req.environ['manila.context']
|
||||
|
||||
try:
|
||||
db_api.share_network_get(context, share_network_id)
|
||||
except exception.ShareNetworkNotFound as e:
|
||||
raise exc.HTTPNotFound(explanation=e.msg)
|
||||
|
||||
try:
|
||||
share_network_subnet = db_api.share_network_subnet_get(
|
||||
context, share_network_subnet_id)
|
||||
except exception.ShareNetworkSubnetNotFound as e:
|
||||
raise exc.HTTPNotFound(explanation=e.msg)
|
||||
|
||||
for share_server in share_network_subnet['share_servers'] or []:
|
||||
shares = db_api.share_instances_get_all_by_share_server(
|
||||
context, share_server['id'])
|
||||
if shares:
|
||||
msg = _("Cannot delete share network subnet %(id)s, it has "
|
||||
"one or more shares.") % {
|
||||
'id': share_network_subnet_id}
|
||||
LOG.error(msg)
|
||||
raise exc.HTTPConflict(explanation=msg)
|
||||
|
||||
# NOTE(silvacarlose): Do not allow the deletion of any share server
|
||||
# if any of them has the flag is_auto_deletable = False
|
||||
if not self._all_share_servers_are_auto_deletable(
|
||||
share_network_subnet):
|
||||
msg = _("The service cannot determine if there are any "
|
||||
"non-managed shares on the share network subnet %(id)s,"
|
||||
"so it cannot be deleted. Please contact the cloud "
|
||||
"administrator to rectify.") % {
|
||||
'id': share_network_subnet_id}
|
||||
LOG.error(msg)
|
||||
raise exc.HTTPConflict(explanation=msg)
|
||||
|
||||
for share_server in share_network_subnet['share_servers']:
|
||||
self.share_rpcapi.delete_share_server(context, share_server)
|
||||
|
||||
db_api.share_network_subnet_delete(context, share_network_subnet_id)
|
||||
return webob.Response(status_int=http_client.ACCEPTED)
|
||||
|
||||
def _validate_subnet(self, context, share_network_id, az=None):
|
||||
"""Validate the az for the given subnet.
|
||||
|
||||
If az is None, the method will search for an existent default subnet.
|
||||
In case of a given AZ, validates if there's an existent subnet for it.
|
||||
"""
|
||||
msg = ("Another share network subnet was found in the "
|
||||
"specified availability zone. Only one share network "
|
||||
"subnet is allowed per availability zone for share "
|
||||
"network %s." % share_network_id)
|
||||
if az is None:
|
||||
default_subnet = db_api.share_network_subnet_get_default_subnet(
|
||||
context, share_network_id)
|
||||
if default_subnet is not None:
|
||||
raise exc.HTTPConflict(explanation=msg)
|
||||
else:
|
||||
az_subnet = (
|
||||
db_api.share_network_subnet_get_by_availability_zone_id(
|
||||
context, share_network_id, az['id'])
|
||||
)
|
||||
# If the 'availability_zone_id' is not None, we found a conflict,
|
||||
# otherwise we just have found the default subnet
|
||||
if az_subnet and az_subnet['availability_zone_id']:
|
||||
raise exc.HTTPConflict(explanation=msg)
|
||||
|
||||
@wsgi.Controller.api_version("2.51")
|
||||
@wsgi.Controller.authorize
|
||||
def create(self, req, share_network_id, body):
|
||||
"""Add a new share network subnet into the share network."""
|
||||
context = req.environ['manila.context']
|
||||
|
||||
if not self.is_valid_body(body, 'share-network-subnet'):
|
||||
msg = _("Share Network Subnet is missing from the request body.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
data = body['share-network-subnet']
|
||||
data['share_network_id'] = share_network_id
|
||||
|
||||
common.check_net_id_and_subnet_id(data)
|
||||
|
||||
try:
|
||||
db_api.share_network_get(context, share_network_id)
|
||||
except exception.ShareNetworkNotFound as e:
|
||||
raise exc.HTTPNotFound(explanation=e.msg)
|
||||
|
||||
availability_zone = data.pop('availability_zone', None)
|
||||
subnet_az = None
|
||||
|
||||
if availability_zone:
|
||||
try:
|
||||
subnet_az = db_api.availability_zone_get(context,
|
||||
availability_zone)
|
||||
except exception.AvailabilityZoneNotFound:
|
||||
msg = _("The provided availability zone %s does not "
|
||||
"exist.") % availability_zone
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
self._validate_subnet(context, share_network_id, az=subnet_az)
|
||||
|
||||
try:
|
||||
data['availability_zone_id'] = (
|
||||
subnet_az['id'] if subnet_az is not None else None)
|
||||
share_network_subnet = db_api.share_network_subnet_create(
|
||||
context, data)
|
||||
except db_exception.DBError as e:
|
||||
msg = _('Could not create the share network subnet.')
|
||||
LOG.error(e)
|
||||
raise exc.HTTPInternalServerError(explanation=msg)
|
||||
share_network_subnet = db_api.share_network_subnet_get(
|
||||
context, share_network_subnet['id'])
|
||||
return self._view_builder.build_share_network_subnet(
|
||||
req, share_network_subnet)
|
||||
|
||||
@wsgi.Controller.api_version('2.51')
|
||||
@wsgi.Controller.authorize
|
||||
def show(self, req, share_network_id, share_network_subnet_id):
|
||||
"""Show share network subnet."""
|
||||
context = req.environ['manila.context']
|
||||
|
||||
try:
|
||||
db_api.share_network_get(context, share_network_id)
|
||||
except exception.ShareNetworkNotFound as e:
|
||||
raise exc.HTTPNotFound(explanation=e.msg)
|
||||
|
||||
try:
|
||||
share_network_subnet = db_api.share_network_subnet_get(
|
||||
context, share_network_subnet_id)
|
||||
except exception.ShareNetworkSubnetNotFound as e:
|
||||
raise exc.HTTPNotFound(explanation=e.msg)
|
||||
|
||||
return self._view_builder.build_share_network_subnet(
|
||||
req, share_network_subnet)
|
||||
|
||||
|
||||
def create_resource():
|
||||
return wsgi.Resource(ShareNetworkSubnetController())
|
@ -15,6 +15,7 @@
|
||||
|
||||
"""The shares api."""
|
||||
|
||||
import copy
|
||||
from oslo_db import exception as db_exception
|
||||
from oslo_log import log
|
||||
from oslo_utils import timeutils
|
||||
@ -66,6 +67,9 @@ class ShareNetworkController(wsgi.Controller):
|
||||
return all([ss['is_auto_deletable'] for ss
|
||||
in share_network['share_servers']])
|
||||
|
||||
def _share_network_contains_subnets(self, share_network):
|
||||
return len(share_network['share_network_subnets']) > 1
|
||||
|
||||
def delete(self, req, id):
|
||||
"""Delete specified share network."""
|
||||
context = req.environ['manila.context']
|
||||
@ -95,18 +99,29 @@ class ShareNetworkController(wsgi.Controller):
|
||||
LOG.error(msg)
|
||||
raise exc.HTTPConflict(explanation=msg)
|
||||
|
||||
# NOTE(silvacarlose): Do not allow the deletion of any share server
|
||||
# if one of them has the flag is_auto_deletable = False
|
||||
if not self._all_share_servers_are_auto_deletable(share_network):
|
||||
msg = _("The service cannot determine if there are any "
|
||||
"non-managed shares on the share network %(id)s, so it "
|
||||
"cannot be deleted. Please contact the cloud "
|
||||
"administrator to rectify.") % {'id': id}
|
||||
# NOTE(silvacarlose): Do not allow the deletion of share networks
|
||||
# if it still contains two or more subnets
|
||||
if self._share_network_contains_subnets(share_network):
|
||||
msg = _("The share network %(id)s has more than one subnet "
|
||||
"attached. Please remove the subnets untill you have one "
|
||||
"or no subnets remaining.") % {'id': id}
|
||||
LOG.error(msg)
|
||||
raise exc.HTTPConflict(explanation=msg)
|
||||
|
||||
for share_server in share_network['share_servers']:
|
||||
self.share_rpcapi.delete_share_server(context, share_server)
|
||||
for subnet in share_network['share_network_subnets']:
|
||||
if not self._all_share_servers_are_auto_deletable(subnet):
|
||||
msg = _("The service cannot determine if there are any "
|
||||
"non-managed shares on the share network subnet "
|
||||
"%(id)s, so it cannot be deleted. Please contact the "
|
||||
"cloud administrator to rectify.") % {
|
||||
'id': subnet['id']}
|
||||
LOG.error(msg)
|
||||
raise exc.HTTPConflict(explanation=msg)
|
||||
|
||||
for subnet in share_network['share_network_subnets']:
|
||||
for share_server in subnet['share_servers']:
|
||||
self.share_rpcapi.delete_share_server(context, share_server)
|
||||
|
||||
db_api.share_network_delete(context, id)
|
||||
|
||||
try:
|
||||
@ -122,6 +137,16 @@ class ShareNetworkController(wsgi.Controller):
|
||||
user_id=share_network['user_id'])
|
||||
return webob.Response(status_int=http_client.ACCEPTED)
|
||||
|
||||
def _subnet_has_search_opt(self, key, value, network, exact_value=False):
|
||||
for subnet in network.get('share_network_subnets') or []:
|
||||
if subnet.get(key) == value or (
|
||||
not exact_value and
|
||||
value in subnet.get(key.rstrip('~'))
|
||||
if key.endswith('~') and
|
||||
subnet.get(key.rstrip('~')) else ()):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _get_share_networks(self, req, is_detail=True):
|
||||
"""Returns a list of share networks."""
|
||||
context = req.environ['manila.context']
|
||||
@ -179,19 +204,30 @@ class ShareNetworkController(wsgi.Controller):
|
||||
value = int(value)
|
||||
if (req.api_version_request >=
|
||||
api_version.APIVersionRequest("2.36")):
|
||||
networks = [network for network in networks
|
||||
if network.get(key) == value or
|
||||
(value in network.get(key.rstrip('~'))
|
||||
if key.endswith('~') and
|
||||
network.get(key.rstrip('~')) else ())]
|
||||
networks = [
|
||||
network for network in networks
|
||||
if network.get(key) == value or
|
||||
self._subnet_has_search_opt(key, value, network) or
|
||||
(value in network.get(key.rstrip('~'))
|
||||
if key.endswith('~') and
|
||||
network.get(key.rstrip('~')) else ())]
|
||||
else:
|
||||
networks = [network for network in networks
|
||||
if network.get(key) == value]
|
||||
networks = [
|
||||
network for network in networks
|
||||
if network.get(key) == value or
|
||||
self._subnet_has_search_opt(key, value, network,
|
||||
exact_value=True)]
|
||||
|
||||
limited_list = common.limited(networks, req)
|
||||
return self._view_builder.build_share_networks(
|
||||
req, limited_list, is_detail)
|
||||
|
||||
def _share_network_subnets_contain_share_servers(self, share_network):
|
||||
for subnet in share_network['share_network_subnets']:
|
||||
if subnet['share_servers'] and len(subnet['share_servers']) > 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def index(self, req):
|
||||
"""Returns a summary list of share networks."""
|
||||
policy.check_policy(req.environ['manila.context'], RESOURCE_NAME,
|
||||
@ -223,7 +259,7 @@ class ShareNetworkController(wsgi.Controller):
|
||||
msg = _("nova networking is not supported starting in Ocata.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
if share_network['share_servers']:
|
||||
if self._share_network_subnets_contain_share_servers(share_network):
|
||||
for value in update_values:
|
||||
if value not in ['name', 'description']:
|
||||
msg = (_("Cannot update share network %s. It is used by "
|
||||
@ -231,8 +267,15 @@ class ShareNetworkController(wsgi.Controller):
|
||||
"fields are available for update") %
|
||||
share_network['id'])
|
||||
raise exc.HTTPForbidden(explanation=msg)
|
||||
|
||||
try:
|
||||
if ('neutron_net_id' in update_values or
|
||||
'neutron_subnet_id' in update_values):
|
||||
subnet = db_api.share_network_subnet_get_default_subnet(
|
||||
context, id)
|
||||
if subnet:
|
||||
db_api.share_network_subnet_update(context,
|
||||
subnet['id'],
|
||||
update_values)
|
||||
share_network = db_api.share_network_update(context,
|
||||
id,
|
||||
update_values)
|
||||
@ -250,14 +293,36 @@ class ShareNetworkController(wsgi.Controller):
|
||||
if not body or RESOURCE_NAME not in body:
|
||||
raise exc.HTTPUnprocessableEntity()
|
||||
|
||||
values = body[RESOURCE_NAME]
|
||||
values['project_id'] = context.project_id
|
||||
values['user_id'] = context.user_id
|
||||
share_network_values = body[RESOURCE_NAME]
|
||||
share_network_subnet_values = copy.deepcopy(share_network_values)
|
||||
share_network_values['project_id'] = context.project_id
|
||||
share_network_values['user_id'] = context.user_id
|
||||
|
||||
if 'nova_net_id' in values:
|
||||
if 'nova_net_id' in share_network_values:
|
||||
msg = _("nova networking is not supported starting in Ocata.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
share_network_values.pop('availability_zone', None)
|
||||
share_network_values.pop('neutron_net_id', None)
|
||||
share_network_values.pop('neutron_subnet_id', None)
|
||||
|
||||
if req.api_version_request >= api_version.APIVersionRequest("2.51"):
|
||||
if 'availability_zone' in share_network_subnet_values:
|
||||
try:
|
||||
az = db_api.availability_zone_get(
|
||||
context,
|
||||
share_network_subnet_values['availability_zone'])
|
||||
share_network_subnet_values['availability_zone_id'] = (
|
||||
az['id'])
|
||||
share_network_subnet_values.pop('availability_zone')
|
||||
except exception.AvailabilityZoneNotFound:
|
||||
msg = (_("The provided availability zone %s does not "
|
||||
"exist.")
|
||||
% share_network_subnet_values['availability_zone'])
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
common.check_net_id_and_subnet_id(share_network_subnet_values)
|
||||
|
||||
try:
|
||||
reservations = QUOTAS.reserve(context, share_networks=1)
|
||||
except exception.OverQuota as e:
|
||||
@ -279,13 +344,32 @@ class ShareNetworkController(wsgi.Controller):
|
||||
raise exception.ShareNetworksLimitExceeded(
|
||||
allowed=quotas['share_networks'])
|
||||
else:
|
||||
# Tries to create the new share network
|
||||
try:
|
||||
share_network = db_api.share_network_create(context, values)
|
||||
share_network = db_api.share_network_create(
|
||||
context, share_network_values)
|
||||
except db_exception.DBError as e:
|
||||
LOG.exception(e)
|
||||
msg = "Could not create share network."
|
||||
raise exc.HTTPInternalServerError(explanation=msg)
|
||||
|
||||
share_network_subnet_values['share_network_id'] = (
|
||||
share_network['id'])
|
||||
share_network_subnet_values.pop('id', None)
|
||||
|
||||
# Try to create the share network subnet. If it fails, the service
|
||||
# must rollback the share network creation.
|
||||
try:
|
||||
db_api.share_network_subnet_create(
|
||||
context, share_network_subnet_values)
|
||||
except db_exception.DBError:
|
||||
msg = "Could not save supplied data due to database error"
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
db_api.share_network_delete(context, share_network['id'])
|
||||
msg = _('Could not create share network.')
|
||||
raise exc.HTTPInternalServerError(explanation=msg)
|
||||
|
||||
QUOTAS.commit(context, reservations)
|
||||
share_network = db_api.share_network_get(context,
|
||||
share_network['id'])
|
||||
return self._view_builder.build_share_network(req, share_network)
|
||||
|
||||
def action(self, req, id, body):
|
||||
@ -305,7 +389,7 @@ class ShareNetworkController(wsgi.Controller):
|
||||
context = req.environ['manila.context']
|
||||
policy.check_policy(context, RESOURCE_NAME, 'add_security_service')
|
||||
share_network = db_api.share_network_get(context, id)
|
||||
if share_network['share_servers']:
|
||||
if self._share_network_subnets_contain_share_servers(share_network):
|
||||
msg = _("Cannot add security services. Share network is used.")
|
||||
raise exc.HTTPForbidden(explanation=msg)
|
||||
security_service = db_api.security_service_get(
|
||||
@ -338,7 +422,8 @@ class ShareNetworkController(wsgi.Controller):
|
||||
context = req.environ['manila.context']
|
||||
policy.check_policy(context, RESOURCE_NAME, 'remove_security_service')
|
||||
share_network = db_api.share_network_get(context, id)
|
||||
if share_network['share_servers']:
|
||||
|
||||
if self._share_network_subnets_contain_share_servers(share_network):
|
||||
msg = _("Cannot remove security services. Share network is used.")
|
||||
raise exc.HTTPForbidden(explanation=msg)
|
||||
try:
|
||||
|
@ -116,7 +116,6 @@ class ShareReplicationController(wsgi.Controller, wsgi.AdminActionsMixin):
|
||||
|
||||
share_id = body.get('share_replica').get('share_id')
|
||||
availability_zone = body.get('share_replica').get('availability_zone')
|
||||
share_network_id = body.get('share_replica').get('share_network_id')
|
||||
|
||||
if not share_id:
|
||||
msg = _("Must provide Share ID to add replica.")
|
||||
@ -128,6 +127,8 @@ class ShareReplicationController(wsgi.Controller, wsgi.AdminActionsMixin):
|
||||
msg = _("No share exists with ID %s.")
|
||||
raise exc.HTTPNotFound(explanation=msg % share_id)
|
||||
|
||||
share_network_id = share_ref.get('share_network_id', None)
|
||||
|
||||
try:
|
||||
new_replica = self.share_api.create_share_replica(
|
||||
context, share_ref, availability_zone=availability_zone,
|
||||
|
@ -31,6 +31,7 @@ LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class ShareServerController(share_servers.ShareServerController,
|
||||
wsgi.Controller,
|
||||
wsgi.AdminActionsMixin):
|
||||
"""The Share Server API V2 controller for the OpenStack API."""
|
||||
|
||||
@ -55,28 +56,42 @@ class ShareServerController(share_servers.ShareServerController,
|
||||
def share_server_reset_status(self, req, id, body):
|
||||
return self._reset_status(req, id, body)
|
||||
|
||||
@wsgi.Controller.api_version("2.49")
|
||||
@wsgi.Controller.authorize('manage_share_server')
|
||||
@wsgi.response(202)
|
||||
def manage(self, req, body):
|
||||
def _manage(self, req, body):
|
||||
"""Manage a share server."""
|
||||
LOG.debug("Manage Share Server with id: %s", id)
|
||||
|
||||
context = req.environ['manila.context']
|
||||
identifier, host, share_network, driver_opts = (
|
||||
identifier, host, share_network, driver_opts, network_subnet = (
|
||||
self._validate_manage_share_server_parameters(context, body))
|
||||
|
||||
try:
|
||||
result = self.share_api.manage_share_server(
|
||||
context, identifier, host, share_network, driver_opts)
|
||||
context, identifier, host, network_subnet, driver_opts)
|
||||
except exception.InvalidInput as e:
|
||||
raise exc.HTTPBadRequest(explanation=e)
|
||||
raise exc.HTTPBadRequest(explanation=e.msg)
|
||||
except exception.PolicyNotAuthorized as e:
|
||||
raise exc.HTTPForbidden(explanation=e.msg)
|
||||
|
||||
result.project_id = share_network["project_id"]
|
||||
if result.share_network['name']:
|
||||
result.share_network_name = result.share_network['name']
|
||||
result.share_network_id = share_network["id"]
|
||||
if share_network['name']:
|
||||
result.share_network_name = share_network['name']
|
||||
else:
|
||||
result.share_network_name = result.share_network_id
|
||||
result.share_network_name = share_network['id']
|
||||
return self._view_builder.build_share_server(req, result)
|
||||
|
||||
@wsgi.Controller.api_version('2.51')
|
||||
@wsgi.response(202)
|
||||
def manage(self, req, body):
|
||||
return self._manage(req, body)
|
||||
|
||||
@wsgi.Controller.api_version('2.49') # noqa
|
||||
@wsgi.response(202)
|
||||
def manage(self, req, body): # pylint: disable=function-redefined
|
||||
body.get('share_server', {}).pop('share_network_subnet_id', None)
|
||||
return self._manage(req, body)
|
||||
|
||||
@wsgi.Controller.authorize('unmanage_share_server')
|
||||
def _unmanage(self, req, id, body=None):
|
||||
context = req.environ['manila.context']
|
||||
@ -91,7 +106,7 @@ class ShareServerController(share_servers.ShareServerController,
|
||||
share_server = db_api.share_server_get(
|
||||
context, id)
|
||||
except exception.ShareServerNotFound as e:
|
||||
raise exc.HTTPNotFound(explanation=e)
|
||||
raise exc.HTTPNotFound(explanation=e.msg)
|
||||
|
||||
allowed_statuses = [constants.STATUS_ERROR, constants.STATUS_ACTIVE,
|
||||
constants.STATUS_MANAGE_ERROR,
|
||||
@ -111,7 +126,7 @@ class ShareServerController(share_servers.ShareServerController,
|
||||
context, share_server, force=force)
|
||||
except (exception.ShareServerInUse,
|
||||
exception.PolicyNotAuthorized) as e:
|
||||
raise exc.HTTPBadRequest(explanation=e)
|
||||
raise exc.HTTPBadRequest(explanation=e.msg)
|
||||
|
||||
return webob.Response(status_int=http_client.ACCEPTED)
|
||||
|
||||
@ -141,6 +156,25 @@ class ShareServerController(share_servers.ShareServerController,
|
||||
identifier = data['identifier']
|
||||
host, share_network_id = data['host'], data['share_network_id']
|
||||
|
||||
network_subnet_id = data.get('share_network_subnet_id')
|
||||
if network_subnet_id:
|
||||
try:
|
||||
network_subnet = db_api.share_network_subnet_get(
|
||||
context, network_subnet_id)
|
||||
except exception.ShareNetworkSubnetNotFound:
|
||||
msg = _("The share network subnet %s does not "
|
||||
"exist.") % network_subnet_id
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
else:
|
||||
network_subnet = db_api.share_network_subnet_get_default_subnet(
|
||||
context, share_network_id)
|
||||
|
||||
if network_subnet is None:
|
||||
msg = _("The share network %s does have a default subnet. Create "
|
||||
"one or use a specific subnet to manage this share server "
|
||||
"with API version >= 2.51.") % share_network_id
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
if share_utils.extract_host(host, 'pool'):
|
||||
msg = _("Host parameter should not contain pool.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
@ -168,7 +202,7 @@ class ShareServerController(share_servers.ShareServerController,
|
||||
msg = _("Driver options must be in dictionary format.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
return identifier, host, share_network, driver_opts
|
||||
return identifier, host, share_network, driver_opts, network_subnet
|
||||
|
||||
|
||||
def create_resource():
|
||||
|
53
manila/api/views/share_network_subnets.py
Normal file
53
manila/api/views/share_network_subnets.py
Normal file
@ -0,0 +1,53 @@
|
||||
# Copyright 2019 NetApp, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from manila.api import common
|
||||
|
||||
|
||||
class ViewBuilder(common.ViewBuilder):
|
||||
"""Model a server API response as a python dictionary."""
|
||||
|
||||
_collection_name = 'share_network_subnets'
|
||||
|
||||
def build_share_network_subnet(self, request, share_network_subnet):
|
||||
return {
|
||||
'share_network_subnet': self._build_share_network_subnet_view(
|
||||
request, share_network_subnet)}
|
||||
|
||||
def build_share_network_subnets(self, request, share_network_subnets):
|
||||
return {'share_network_subnets':
|
||||
[self._build_share_network_subnet_view(
|
||||
request, share_network_subnet)
|
||||
for share_network_subnet in share_network_subnets]}
|
||||
|
||||
def _build_share_network_subnet_view(self, request, share_network_subnet):
|
||||
sns = {
|
||||
'id': share_network_subnet.get('id'),
|
||||
'availability_zone': share_network_subnet.get('availability_zone'),
|
||||
'share_network_id': share_network_subnet.get('share_network_id'),
|
||||
'share_network_name': share_network_subnet.share_network['name'],
|
||||
'created_at': share_network_subnet.get('created_at'),
|
||||
'segmentation_id': share_network_subnet.get('segmentation_id'),
|
||||
'neutron_subnet_id': share_network_subnet.get('neutron_subnet_id'),
|
||||
'updated_at': share_network_subnet.get('updated_at'),
|
||||
'neutron_net_id': share_network_subnet.get('neutron_net_id'),
|
||||
'ip_version': share_network_subnet.get('ip_version'),
|
||||
'cidr': share_network_subnet.get('cidr'),
|
||||
'network_type': share_network_subnet.get('network_type'),
|
||||
'mtu': share_network_subnet.get('mtu'),
|
||||
'gateway': share_network_subnet.get('gateway')
|
||||
}
|
||||
self.update_versioned_resource_dict(request, sns, share_network_subnet)
|
||||
return sns
|
@ -20,7 +20,8 @@ class ViewBuilder(common.ViewBuilder):
|
||||
"""Model a server API response as a python dictionary."""
|
||||
|
||||
_collection_name = 'share_networks'
|
||||
_detail_version_modifiers = ["add_gateway", "add_mtu", "add_nova_net_id"]
|
||||
_detail_version_modifiers = ["add_gateway", "add_mtu", "add_nova_net_id",
|
||||
"add_subnets"]
|
||||
|
||||
def build_share_network(self, request, share_network):
|
||||
"""View of a share network."""
|
||||
@ -34,6 +35,20 @@ class ViewBuilder(common.ViewBuilder):
|
||||
request, share_network, is_detail)
|
||||
for share_network in share_networks]}
|
||||
|
||||
def _update_share_network_info(self, request, share_network):
|
||||
for sns in share_network.get('share_network_subnets') or []:
|
||||
if sns.get('is_default') and sns.get('is_default') is True:
|
||||
share_network.update({
|
||||
'neutron_net_id': sns.get('neutron_net_id'),
|
||||
'neutron_subnet_id': sns.get('neutron_subnet_id'),
|
||||
'network_type': sns.get('network_type'),
|
||||
'segmentation_id': sns.get('segmentation_id'),
|
||||
'cidr': sns.get('cidr'),
|
||||
'ip_version': sns.get('ip_version'),
|
||||
'gateway': sns.get('gateway'),
|
||||
'mtu': sns.get('mtu'),
|
||||
})
|
||||
|
||||
def _build_share_network_view(self, request, share_network,
|
||||
is_detail=True):
|
||||
sn = {
|
||||
@ -41,6 +56,7 @@ class ViewBuilder(common.ViewBuilder):
|
||||
'name': share_network.get('name'),
|
||||
}
|
||||
if is_detail:
|
||||
self._update_share_network_info(request, share_network)
|
||||
sn.update({
|
||||
'project_id': share_network.get('project_id'),
|
||||
'created_at': share_network.get('created_at'),
|
||||
@ -57,6 +73,30 @@ class ViewBuilder(common.ViewBuilder):
|
||||
self.update_versioned_resource_dict(request, sn, share_network)
|
||||
return sn
|
||||
|
||||
@common.ViewBuilder.versioned_method("2.51")
|
||||
def add_subnets(self, context, network_dict, network):
|
||||
subnets = [{
|
||||
'id': sns.get('id'),
|
||||
'availability_zone': sns.get('availability_zone'),
|
||||
'created_at': sns.get('created_at'),
|
||||
'updated_at': sns.get('updated_at'),
|
||||
'segmentation_id': sns.get('segmentation_id'),
|
||||
'neutron_net_id': sns.get('neutron_net_id'),
|
||||
'neutron_subnet_id': sns.get('neutron_subnet_id'),
|
||||
'ip_version': sns.get('ip_version'),
|
||||
'cidr': sns.get('cidr'),
|
||||
'network_type': sns.get('network_type'),
|
||||
'mtu': sns.get('mtu'),
|
||||
'gateway': sns.get('gateway'),
|
||||
} for sns in network.get('share_network_subnets')]
|
||||
|
||||
network_dict['share_network_subnets'] = subnets
|
||||
attr_to_remove = [
|
||||
'neutron_net_id', 'neutron_subnet_id', 'network_type',
|
||||
'segmentation_id', 'cidr', 'ip_version', 'gateway', 'mtu']
|
||||
for attr in attr_to_remove:
|
||||
network_dict.pop(attr)
|
||||
|
||||
@common.ViewBuilder.versioned_method("2.18")
|
||||
def add_gateway(self, context, network_dict, network):
|
||||
network_dict['gateway'] = network.get('gateway')
|
||||
|
@ -22,6 +22,7 @@ class ViewBuilder(common.ViewBuilder):
|
||||
_collection_name = 'share_servers'
|
||||
_detail_version_modifiers = [
|
||||
"add_is_auto_deletable_and_identifier_fields",
|
||||
"add_share_network_subnet_id_field"
|
||||
]
|
||||
|
||||
def build_share_server(self, request, share_server):
|
||||
@ -56,11 +57,17 @@ class ViewBuilder(common.ViewBuilder):
|
||||
share_server_dict['created_at'] = share_server.created_at
|
||||
share_server_dict['backend_details'] = share_server.backend_details
|
||||
|
||||
self.update_versioned_resource_dict(
|
||||
request, share_server_dict, share_server)
|
||||
self.update_versioned_resource_dict(
|
||||
request, share_server_dict, share_server)
|
||||
|
||||
return share_server_dict
|
||||
|
||||
@common.ViewBuilder.versioned_method("2.51")
|
||||
def add_share_network_subnet_id_field(
|
||||
self, context, share_server_dict, share_server):
|
||||
share_server_dict['share_network_subnet_id'] = (
|
||||
share_server['share_network_subnet_id'])
|
||||
|
||||
@common.ViewBuilder.versioned_method("2.49")
|
||||
def add_is_auto_deletable_and_identifier_fields(
|
||||
self, context, share_server_dict, share_server):
|
||||
|
@ -848,6 +848,55 @@ def count_share_networks(context, project_id, user_id=None,
|
||||
##################
|
||||
|
||||
|
||||
def share_network_subnet_create(context, values):
|
||||
"""Create a share network subnet DB record."""
|
||||
return IMPL.share_network_subnet_create(context, values)
|
||||
|
||||
|
||||
def share_network_subnet_delete(context, network_subnet_id):
|
||||
"""Delete a share network subnet DB record."""
|
||||
return IMPL.share_network_subnet_delete(context, network_subnet_id)
|
||||
|
||||
|
||||
def share_network_subnet_update(context, network_subnet_id, values):
|
||||
"""Update a share network subnet DB record."""
|
||||
return IMPL.share_network_subnet_update(context, network_subnet_id, values)
|
||||
|
||||
|
||||
def share_network_subnet_get(context, network_subnet_id, session=None):
|
||||
"""Get requested share network subnet DB record."""
|
||||
return IMPL.share_network_subnet_get(context, network_subnet_id,
|
||||
session=session)
|
||||
|
||||
|
||||
def share_network_subnet_get_all(context):
|
||||
"""Get all share network subnet DB record."""
|
||||
return IMPL.share_network_subnet_get_all(context)
|
||||
|
||||
|
||||
def share_network_subnet_get_by_availability_zone_id(context, share_network_id,
|
||||
availability_zone_id):
|
||||
"""Get a share network subnet DB record.
|
||||
|
||||
This method returns a subnet DB record for a given share network id and
|
||||
an availability zone. If the 'availability_zone_id' is 'None', a record may
|
||||
be returned and it will represent the default share network subnet.
|
||||
Be aware that if there is no subnet for a specific availability zone id,
|
||||
this method will return the default share network subnet, if it exists.
|
||||
"""
|
||||
return IMPL.share_network_subnet_get_by_availability_zone_id(
|
||||
context, share_network_id, availability_zone_id)
|
||||
|
||||
|
||||
def share_network_subnet_get_default_subnet(context, share_network_id):
|
||||
"""Get the default share network subnet DB record."""
|
||||
return IMPL.share_network_subnet_get_default_subnet(context,
|
||||
share_network_id)
|
||||
|
||||
|
||||
##################
|
||||
|
||||
|
||||
def network_allocation_create(context, values):
|
||||
"""Create a network allocation DB record."""
|
||||
return IMPL.network_allocation_create(context, values)
|
||||
|
@ -0,0 +1,231 @@
|
||||
# Copyright 2019 NetApp, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""add_share_network_subnets_table_and_modify_share_networks_and_servers
|
||||
|
||||
Revision ID: 805685098bd2
|
||||
Revises: 6a3fd2984bc31
|
||||
Create Date: 2019-05-09 16:28:41.919714
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '805685098bd2'
|
||||
down_revision = '6a3fd2984bc31'
|
||||
|
||||
from alembic import op
|
||||
from manila.db.migrations import utils
|
||||
from oslo_log import log
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
def upgrade():
|
||||
# New table
|
||||
try:
|
||||
share_networks_fk_name = (
|
||||
"fk_share_network_subnets_share_network_id_share_networks")
|
||||
availability_zones_fk_name = (
|
||||
"fk_share_network_subnets_availaility_zone_id_availability_zones")
|
||||
share_network_subnets_table = op.create_table(
|
||||
'share_network_subnets',
|
||||
sa.Column('id', sa.String(36), primary_key=True, nullable=False),
|
||||
sa.Column('neutron_net_id', sa.String(36), nullable=True),
|
||||
sa.Column('neutron_subnet_id', sa.String(36), nullable=True),
|
||||
sa.Column('network_type', sa.String(32), nullable=True),
|
||||
sa.Column('cidr', sa.String(64), nullable=True),
|
||||
sa.Column('segmentation_id', sa.Integer, nullable=True),
|
||||
sa.Column('gateway', sa.String(64), nullable=True),
|
||||
sa.Column('mtu', sa.Integer, nullable=True),
|
||||
sa.Column('share_network_id', sa.String(36), sa.ForeignKey(
|
||||
'share_networks.id', name=share_networks_fk_name)),
|
||||
sa.Column('ip_version', sa.Integer, nullable=True),
|
||||
sa.Column('availability_zone_id', sa.String(36),
|
||||
sa.ForeignKey('availability_zones.id',
|
||||
name=availability_zones_fk_name)),
|
||||
sa.Column('created_at', sa.DateTime),
|
||||
sa.Column('updated_at', sa.DateTime),
|
||||
sa.Column('deleted_at', sa.DateTime),
|
||||
sa.Column('deleted', sa.String(36), default='False'),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8'
|
||||
)
|
||||
except Exception:
|
||||
LOG.error("Table |%s| not created!", 'share_network_subnets')
|
||||
raise
|
||||
|
||||
share_serves_fk_name = (
|
||||
"fk_share_servers_share_network_subnet_id_share_network_subnets")
|
||||
op.add_column(
|
||||
'share_servers',
|
||||
sa.Column(
|
||||
'share_network_subnet_id', sa.String(36),
|
||||
sa.ForeignKey('share_network_subnets.id',
|
||||
name=share_serves_fk_name),
|
||||
)
|
||||
)
|
||||
|
||||
connection = op.get_bind()
|
||||
|
||||
share_networks_table = utils.load_table('share_networks', connection)
|
||||
share_servers_table = utils.load_table('share_servers', connection)
|
||||
|
||||
share_network_subnets = []
|
||||
|
||||
# Get all share_networks and move all their data to share network subnet
|
||||
for share_network in connection.execute(share_networks_table.select()):
|
||||
share_network_subnet = {
|
||||
'id': uuidutils.generate_uuid(),
|
||||
'neutron_net_id': share_network.neutron_net_id,
|
||||
'neutron_subnet_id': share_network.neutron_subnet_id,
|
||||
'network_type': share_network.network_type,
|
||||
'cidr': share_network.cidr,
|
||||
'segmentation_id': share_network.segmentation_id,
|
||||
'gateway': share_network.gateway,
|
||||
'mtu': share_network.mtu,
|
||||
'share_network_id': share_network.id,
|
||||
'ip_version': share_network.ip_version,
|
||||
'created_at': share_network.created_at,
|
||||
'updated_at': share_network.updated_at,
|
||||
'deleted_at': share_network.deleted_at,
|
||||
'deleted': share_network.deleted,
|
||||
}
|
||||
share_network_subnets.append(share_network_subnet)
|
||||
|
||||
# Insertions for the new share network subnets
|
||||
op.bulk_insert(share_network_subnets_table, share_network_subnets)
|
||||
|
||||
# Updates the field share server table with the share network subnet id
|
||||
for sns in share_network_subnets:
|
||||
share_servers = connection.execute(share_servers_table.select().where(
|
||||
share_servers_table.c.share_network_id == sns['share_network_id']
|
||||
))
|
||||
updated_data = {'share_network_subnet_id': sns['id']}
|
||||
_update_share_servers(share_servers, updated_data, share_servers_table)
|
||||
|
||||
if connection.engine.name == 'mysql':
|
||||
# Drops necessary constraint from share servers table. Only mysql
|
||||
# needs constraint handling. Postgresql/sqlite don't
|
||||
op.drop_constraint("share_servers_ibfk_1", "share_servers",
|
||||
type_="foreignkey")
|
||||
|
||||
op.drop_column('share_servers', 'share_network_id')
|
||||
op.drop_column('share_networks', 'neutron_net_id')
|
||||
op.drop_column('share_networks', 'neutron_subnet_id')
|
||||
op.drop_column('share_networks', 'network_type')
|
||||
op.drop_column('share_networks', 'segmentation_id')
|
||||
op.drop_column('share_networks', 'gateway')
|
||||
op.drop_column('share_networks', 'mtu')
|
||||
op.drop_column('share_networks', 'cidr')
|
||||
op.drop_column('share_networks', 'ip_version')
|
||||
|
||||
|
||||
def _update_share_servers(share_servers, updated_data, share_servers_table):
|
||||
for share_server in share_servers:
|
||||
# pylint: disable=no-value-for-parameter
|
||||
op.execute(
|
||||
share_servers_table.update().where(
|
||||
share_servers_table.c.id == share_server.id,
|
||||
).values(updated_data)
|
||||
)
|
||||
|
||||
|
||||
def retrieve_default_subnet(subnets):
|
||||
# NOTE (silvacarlose): A default subnet is that one which doesn't contain
|
||||
# an availability zone. If all the share networks contain an az, we can
|
||||
# retrieve whichever share network, then we pick up the first.
|
||||
for subnet in subnets:
|
||||
if subnet.availability_zone_id is None:
|
||||
return subnet
|
||||
|
||||
return subnets[0] if subnets is not None else None
|
||||
|
||||
|
||||
def downgrade():
|
||||
connection = op.get_bind()
|
||||
|
||||
# Include again the removed fields in the share network table
|
||||
op.add_column('share_networks',
|
||||
sa.Column('neutron_net_id', sa.String(36), nullable=True))
|
||||
op.add_column('share_networks',
|
||||
sa.Column('neutron_subnet_id', sa.String(36), nullable=True))
|
||||
op.add_column('share_networks',
|
||||
sa.Column('network_type', sa.String(32), nullable=True))
|
||||
op.add_column('share_networks',
|
||||
sa.Column('cidr', sa.String(64), nullable=True))
|
||||
op.add_column('share_networks',
|
||||
sa.Column('gateway', sa.String(64), nullable=True))
|
||||
op.add_column('share_networks',
|
||||
sa.Column('mtu', sa.Integer, nullable=True))
|
||||
op.add_column('share_networks',
|
||||
sa.Column('segmentation_id', sa.Integer, nullable=True))
|
||||
op.add_column('share_networks',
|
||||
sa.Column('ip_version', sa.Integer, nullable=True))
|
||||
|
||||
# Include again the removed field in the share server table
|
||||
op.add_column('share_servers',
|
||||
sa.Column('share_network_id', sa.String(36),
|
||||
sa.ForeignKey('share_networks.id',
|
||||
name="share_servers_ibfk_1")))
|
||||
|
||||
share_networks_table = utils.load_table('share_networks', connection)
|
||||
share_servers_table = utils.load_table('share_servers', connection)
|
||||
subnets_table = utils.load_table('share_network_subnets', connection)
|
||||
|
||||
for share_network in connection.execute(share_networks_table.select()):
|
||||
network_subnets = connection.execute(subnets_table.select().where(
|
||||
subnets_table.c.share_network_id == share_network.id))
|
||||
default_subnet = retrieve_default_subnet(network_subnets)
|
||||
|
||||
if default_subnet is not None:
|
||||
op.execute(
|
||||
# pylint: disable=no-value-for-parameter
|
||||
share_networks_table.update().where(
|
||||
share_networks_table.c.id == share_network.id,
|
||||
).values({
|
||||
'neutron_net_id': default_subnet.neutron_net_id,
|
||||
'neutron_subnet_id': default_subnet.neutron_subnet_id,
|
||||
'network_type': default_subnet.network_type,
|
||||
'cidr': default_subnet.cidr,
|
||||
'gateway': default_subnet.gateway,
|
||||
'mtu': default_subnet.mtu,
|
||||
'segmentation_id': default_subnet.segmentation_id,
|
||||
'ip_version': default_subnet.ip_version,
|
||||
})
|
||||
)
|
||||
|
||||
for network_subnet in network_subnets:
|
||||
share_servers = connection.execute(
|
||||
share_servers_table.select().where(
|
||||
share_servers_table.c.share_network_subnet_id ==
|
||||
network_subnet.id))
|
||||
updated_data = {'share_network_id': share_network.id}
|
||||
_update_share_servers(share_servers, updated_data,
|
||||
share_servers_table)
|
||||
|
||||
share_serves_fk_name = (
|
||||
"fk_share_servers_share_network_subnet_id_share_network_subnets")
|
||||
if connection.engine.name == 'mysql':
|
||||
op.drop_constraint(share_serves_fk_name, "share_servers",
|
||||
type_="foreignkey")
|
||||
op.drop_column('share_servers', 'share_network_subnet_id')
|
||||
try:
|
||||
op.drop_table('share_network_subnets')
|
||||
except Exception:
|
||||
LOG.error("Failed to drop 'share_network_subnets' table!")
|
||||
raise
|
@ -42,7 +42,7 @@ from oslo_utils import uuidutils
|
||||
import six
|
||||
from sqlalchemy import MetaData
|
||||
from sqlalchemy import or_
|
||||
from sqlalchemy.orm import joinedload
|
||||
from sqlalchemy.orm import joinedload, load_only
|
||||
from sqlalchemy.sql.expression import literal
|
||||
from sqlalchemy.sql.expression import true
|
||||
from sqlalchemy.sql import func
|
||||
@ -3396,7 +3396,7 @@ def _network_get_query(context, session=None):
|
||||
return (model_query(context, models.ShareNetwork, session=session).
|
||||
options(joinedload('share_instances'),
|
||||
joinedload('security_services'),
|
||||
joinedload('share_servers')))
|
||||
joinedload('share_network_subnets')))
|
||||
|
||||
|
||||
@require_context
|
||||
@ -3454,8 +3454,8 @@ def share_network_get_all_by_security_service(context, security_service_id):
|
||||
join(models.ShareNetworkSecurityServiceAssociation,
|
||||
models.ShareNetwork.id ==
|
||||
models.ShareNetworkSecurityServiceAssociation.share_network_id).
|
||||
filter_by(security_service_id=security_service_id, deleted=0).
|
||||
options(joinedload('share_servers')).all())
|
||||
filter_by(security_service_id=security_service_id, deleted=0)
|
||||
.all())
|
||||
|
||||
|
||||
@require_context
|
||||
@ -3534,13 +3534,103 @@ def count_share_networks(context, project_id, user_id=None,
|
||||
###################
|
||||
|
||||
|
||||
@require_context
|
||||
def _network_subnet_get_query(context, session=None):
|
||||
if session is None:
|
||||
session = get_session()
|
||||
return (model_query(context, models.ShareNetworkSubnet, session=session).
|
||||
options(joinedload('share_servers')))
|
||||
|
||||
|
||||
@require_context
|
||||
def share_network_subnet_create(context, values):
|
||||
values = ensure_model_dict_has_id(values)
|
||||
|
||||
network_subnet_ref = models.ShareNetworkSubnet()
|
||||
network_subnet_ref.update(values)
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
network_subnet_ref.save(session=session)
|
||||
return share_network_subnet_get(
|
||||
context, network_subnet_ref['id'], session=session)
|
||||
|
||||
|
||||
@require_context
|
||||
def share_network_subnet_delete(context, network_subnet_id):
|
||||
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
network_subnet_ref = share_network_subnet_get(context,
|
||||
network_subnet_id,
|
||||
session=session)
|
||||
network_subnet_ref.soft_delete(session=session, update_status=True)
|
||||
|
||||
|
||||
@require_context
|
||||
@oslo_db_api.wrap_db_retry(max_retries=5, retry_on_deadlock=True)
|
||||
def share_network_subnet_update(context, network_subnet_id, values):
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
network_subnet_ref = share_network_subnet_get(context,
|
||||
network_subnet_id,
|
||||
session=session)
|
||||
network_subnet_ref.update(values)
|
||||
network_subnet_ref.save(session=session)
|
||||
return network_subnet_ref
|
||||
|
||||
|
||||
@require_context
|
||||
def share_network_subnet_get(context, network_subnet_id, session=None):
|
||||
result = (_network_subnet_get_query(context, session)
|
||||
.filter_by(id=network_subnet_id)
|
||||
.first())
|
||||
if result is None:
|
||||
raise exception.ShareNetworkSubnetNotFound(
|
||||
share_network_subnet_id=network_subnet_id)
|
||||
return result
|
||||
|
||||
|
||||
@require_context
|
||||
def share_network_subnet_get_all(context):
|
||||
return _network_subnet_get_query(context).all()
|
||||
|
||||
|
||||
@require_context
|
||||
def share_network_subnet_get_all_by_share_network(context, network_id):
|
||||
return _network_subnet_get_query(context).filter_by(
|
||||
share_network_id=network_id).all()
|
||||
|
||||
|
||||
@require_context
|
||||
def share_network_subnet_get_by_availability_zone_id(
|
||||
context, share_network_id, availability_zone_id):
|
||||
result = (_network_subnet_get_query(context).filter_by(
|
||||
share_network_id=share_network_id,
|
||||
availability_zone_id=availability_zone_id).first())
|
||||
# If a specific subnet wasn't found, try get the default one
|
||||
if availability_zone_id and not result:
|
||||
return (_network_subnet_get_query(context).filter_by(
|
||||
share_network_id=share_network_id,
|
||||
availability_zone_id=None).first())
|
||||
return result
|
||||
|
||||
|
||||
@require_context
|
||||
def share_network_subnet_get_default_subnet(context, share_network_id):
|
||||
return share_network_subnet_get_by_availability_zone_id(
|
||||
context, share_network_id, availability_zone_id=None)
|
||||
|
||||
|
||||
###################
|
||||
|
||||
|
||||
def _server_get_query(context, session=None):
|
||||
if session is None:
|
||||
session = get_session()
|
||||
return (model_query(context, models.ShareServer, session=session).
|
||||
options(joinedload('share_instances'),
|
||||
joinedload('network_allocations'),
|
||||
joinedload('share_network')))
|
||||
joinedload('share_network_subnet')))
|
||||
|
||||
|
||||
@require_context
|
||||
@ -3632,11 +3722,22 @@ def share_server_search_by_identifier(context, identifier, session=None):
|
||||
def share_server_get_all_by_host_and_share_net_valid(context, host,
|
||||
share_net_id,
|
||||
session=None):
|
||||
result = (_server_get_query(context, session).filter_by(host=host)
|
||||
.filter_by(share_network_id=share_net_id)
|
||||
# Get subnets by share_net_id
|
||||
subnets = (_network_subnet_get_query(context, session)
|
||||
.filter_by(share_network_id=share_net_id)
|
||||
.options(load_only("id"))
|
||||
.all())
|
||||
subnet_ids = [s.id for s in subnets]
|
||||
|
||||
# Retrieve servers by the retrieved subnet ids
|
||||
result = (_server_get_query(context, session)
|
||||
.filter_by(host=host)
|
||||
.filter(models.ShareServer.share_network_subnet_id.in_(
|
||||
subnet_ids))
|
||||
.filter(models.ShareServer.status.in_(
|
||||
(constants.STATUS_CREATING,
|
||||
constants.STATUS_ACTIVE))).all())
|
||||
(constants.STATUS_CREATING,
|
||||
constants.STATUS_ACTIVE))).all())
|
||||
|
||||
if not result:
|
||||
filters_description = ('share_network_id is "%(share_net_id)s",'
|
||||
' host is "%(host)s" and status in'
|
||||
|
@ -916,14 +916,6 @@ class ShareNetwork(BASE, ManilaBase):
|
||||
deleted = Column(String(36), default='False')
|
||||
project_id = Column(String(255), nullable=False)
|
||||
user_id = Column(String(255), nullable=False)
|
||||
neutron_net_id = Column(String(36), nullable=True)
|
||||
neutron_subnet_id = Column(String(36), nullable=True)
|
||||
network_type = Column(String(32), nullable=True)
|
||||
segmentation_id = Column(Integer, nullable=True)
|
||||
cidr = Column(String(64), nullable=True)
|
||||
gateway = Column(String(64), nullable=True)
|
||||
mtu = Column(Integer, nullable=True)
|
||||
ip_version = Column(Integer, nullable=True)
|
||||
name = Column(String(255), nullable=True)
|
||||
description = Column(String(255), nullable=True)
|
||||
security_services = orm.relationship(
|
||||
@ -945,19 +937,68 @@ class ShareNetwork(BASE, ManilaBase):
|
||||
primaryjoin='and_('
|
||||
'ShareNetwork.id == ShareInstance.share_network_id,'
|
||||
'ShareInstance.deleted == "False")')
|
||||
share_network_subnets = orm.relationship(
|
||||
"ShareNetworkSubnet", backref='share_network', lazy='immediate',
|
||||
primaryjoin='and_'
|
||||
'(ShareNetwork.id == ShareNetworkSubnet.share_network_id,'
|
||||
'ShareNetworkSubnet.deleted == "False")')
|
||||
|
||||
|
||||
class ShareNetworkSubnet(BASE, ManilaBase):
|
||||
"""Represents a share network subnet used by some resources."""
|
||||
|
||||
_extra_keys = ['availability_zone']
|
||||
|
||||
__tablename__ = 'share_network_subnets'
|
||||
id = Column(String(36), primary_key=True, nullable=False)
|
||||
neutron_net_id = Column(String(36), nullable=True)
|
||||
neutron_subnet_id = Column(String(36), nullable=True)
|
||||
network_type = Column(String(32), nullable=True)
|
||||
cidr = Column(String(64), nullable=True)
|
||||
segmentation_id = Column(Integer, nullable=True)
|
||||
gateway = Column(String(64), nullable=True)
|
||||
mtu = Column(Integer, nullable=True)
|
||||
deleted = Column(String(36), default='False')
|
||||
share_network_id = Column(String(36), ForeignKey('share_networks.id'),
|
||||
nullable=False)
|
||||
ip_version = Column(Integer, nullable=True)
|
||||
availability_zone_id = Column(
|
||||
String(36), ForeignKey('availability_zones.id'), nullable=True)
|
||||
|
||||
share_servers = orm.relationship(
|
||||
"ShareServer", backref='share_network',
|
||||
primaryjoin='and_(ShareNetwork.id == ShareServer.share_network_id,'
|
||||
"ShareServer", backref='share_network_subnet',
|
||||
lazy='immediate',
|
||||
primaryjoin='and_(ShareNetworkSubnet.id '
|
||||
'== ShareServer.share_network_subnet_id,'
|
||||
'ShareServer.deleted == "False")')
|
||||
|
||||
_availability_zone = orm.relationship(
|
||||
"AvailabilityZone",
|
||||
lazy='immediate',
|
||||
foreign_keys=availability_zone_id,
|
||||
primaryjoin=(
|
||||
"and_("
|
||||
"ShareNetworkSubnet.availability_zone_id == AvailabilityZone.id, "
|
||||
"AvailabilityZone.deleted == 'False')"))
|
||||
|
||||
@property
|
||||
def availability_zone(self):
|
||||
if self._availability_zone:
|
||||
return self._availability_zone['name']
|
||||
|
||||
@property
|
||||
def is_default(self):
|
||||
return self.availability_zone_id is None
|
||||
|
||||
|
||||
class ShareServer(BASE, ManilaBase):
|
||||
"""Represents share server used by share."""
|
||||
__tablename__ = 'share_servers'
|
||||
id = Column(String(36), primary_key=True, nullable=False)
|
||||
deleted = Column(String(36), default='False')
|
||||
share_network_id = Column(String(36), ForeignKey('share_networks.id'),
|
||||
nullable=True)
|
||||
share_network_subnet_id = Column(
|
||||
String(36), ForeignKey('share_network_subnets.id'),
|
||||
nullable=True)
|
||||
host = Column(String(255), nullable=False)
|
||||
is_auto_deletable = Column(Boolean, default=True)
|
||||
identifier = Column(String(255), nullable=True)
|
||||
|
@ -228,6 +228,11 @@ class ShareNetworkNotFound(NotFound):
|
||||
message = _("Share network %(share_network_id)s could not be found.")
|
||||
|
||||
|
||||
class ShareNetworkSubnetNotFound(NotFound):
|
||||
message = _("Share network subnet %(share_network_subnet_id)s could not be"
|
||||
" found.")
|
||||
|
||||
|
||||
class ShareServerNotFound(NotFound):
|
||||
message = _("Share server %(share_server_id)s could not be found.")
|
||||
|
||||
|
@ -85,6 +85,14 @@ class NetworkBaseAPI(db_base.Base):
|
||||
"'%s'.") % share_server_id
|
||||
raise exception.NetworkBadConfigurationException(reason=msg)
|
||||
|
||||
def _verify_share_network_subnet(self, share_server_id,
|
||||
share_network_subnet):
|
||||
if share_network_subnet is None:
|
||||
msg = _("'Share network subnet' is not provided for setting up "
|
||||
"network interfaces for 'Share server' "
|
||||
"'%s'.") % share_server_id
|
||||
raise exception.NetworkBadConfigurationException(reason=msg)
|
||||
|
||||
def update_network_allocation(self, context, share_server):
|
||||
"""Update network allocation.
|
||||
|
||||
@ -98,7 +106,7 @@ class NetworkBaseAPI(db_base.Base):
|
||||
|
||||
@abc.abstractmethod
|
||||
def allocate_network(self, context, share_server, share_network=None,
|
||||
**kwargs):
|
||||
share_network_subnet=None, **kwargs):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
@ -106,8 +114,9 @@ class NetworkBaseAPI(db_base.Base):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def manage_network_allocations(self, context, allocations, share_server,
|
||||
share_network=None):
|
||||
def manage_network_allocations(
|
||||
self, context, allocations, share_server, share_network=None,
|
||||
share_network_subnet=None):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
|
@ -125,19 +125,21 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
||||
**self._neutron_api_kwargs)
|
||||
return self._neutron_api
|
||||
|
||||
def _store_neutron_net_info(self, context, share_network):
|
||||
self._save_neutron_network_data(context, share_network)
|
||||
self._save_neutron_subnet_data(context, share_network)
|
||||
def _store_neutron_net_info(self, context, share_network_subnet):
|
||||
self._save_neutron_network_data(context, share_network_subnet)
|
||||
self._save_neutron_subnet_data(context, share_network_subnet)
|
||||
|
||||
def allocate_network(self, context, share_server, share_network=None,
|
||||
**kwargs):
|
||||
share_network_subnet=None, **kwargs):
|
||||
"""Allocate network resources using given network information.
|
||||
|
||||
Create neutron ports for a given neutron network and subnet,
|
||||
create manila db records for allocated neutron ports.
|
||||
|
||||
:param context: RequestContext object
|
||||
:param share_server: share server data
|
||||
:param share_network: share network data
|
||||
:param share_network_subnet: share network subnet data
|
||||
:param kwargs: allocations parameters given by the back-end
|
||||
driver. Supported params:
|
||||
'count' - how many allocations should be created
|
||||
@ -149,32 +151,37 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
||||
raise exception.NetworkBadConfigurationException(reason=msg)
|
||||
|
||||
self._verify_share_network(share_server['id'], share_network)
|
||||
self._store_neutron_net_info(context, share_network)
|
||||
self._verify_share_network_subnet(share_server['id'],
|
||||
share_network_subnet)
|
||||
self._store_neutron_net_info(context, share_network_subnet)
|
||||
|
||||
allocation_count = kwargs.get('count', 1)
|
||||
device_owner = kwargs.get('device_owner', 'share')
|
||||
|
||||
ports = []
|
||||
for __ in range(0, allocation_count):
|
||||
ports.append(self._create_port(context, share_server,
|
||||
share_network, device_owner))
|
||||
ports.append(self._create_port(
|
||||
context, share_server, share_network,
|
||||
share_network_subnet, device_owner))
|
||||
|
||||
return ports
|
||||
|
||||
def manage_network_allocations(self, context, allocations, share_server,
|
||||
share_network=None):
|
||||
def manage_network_allocations(
|
||||
self, context, allocations, share_server, share_network=None,
|
||||
share_network_subnet=None):
|
||||
|
||||
self._verify_share_network(share_server['id'], share_network)
|
||||
self._store_neutron_net_info(context, share_network)
|
||||
self._verify_share_network_subnet(share_server['id'],
|
||||
share_network_subnet)
|
||||
self._store_neutron_net_info(context, share_network_subnet)
|
||||
|
||||
# We begin matching the allocations to known neutron ports and
|
||||
# finally return the non-consumed allocations
|
||||
remaining_allocations = list(allocations)
|
||||
|
||||
fixed_ip_filter = 'subnet_id=' + share_network['neutron_subnet_id']
|
||||
fixed_ip_filter = ('subnet_id=' +
|
||||
share_network_subnet['neutron_subnet_id'])
|
||||
|
||||
port_list = self.neutron_api.list_ports(
|
||||
network_id=share_network['neutron_net_id'],
|
||||
network_id=share_network_subnet['neutron_net_id'],
|
||||
device_owner='manila:share',
|
||||
fixed_ips=fixed_ip_filter)
|
||||
|
||||
@ -189,15 +196,15 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
||||
'id': selected_port['port']['id'],
|
||||
'share_server_id': share_server['id'],
|
||||
'ip_address': selected_port['allocation'],
|
||||
'gateway': share_network['gateway'],
|
||||
'gateway': share_network_subnet['gateway'],
|
||||
'mac_address': selected_port['port']['mac_address'],
|
||||
'status': constants.STATUS_ACTIVE,
|
||||
'label': self.label,
|
||||
'network_type': share_network.get('network_type'),
|
||||
'segmentation_id': share_network.get('segmentation_id'),
|
||||
'ip_version': share_network['ip_version'],
|
||||
'cidr': share_network['cidr'],
|
||||
'mtu': share_network['mtu'],
|
||||
'network_type': share_network_subnet.get('network_type'),
|
||||
'segmentation_id': share_network_subnet.get('segmentation_id'),
|
||||
'ip_version': share_network_subnet['ip_version'],
|
||||
'cidr': share_network_subnet['cidr'],
|
||||
'mtu': share_network_subnet['mtu'],
|
||||
}
|
||||
|
||||
# There should not be existing allocations with the same port_id.
|
||||
@ -296,37 +303,38 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
||||
for port in ports:
|
||||
self._delete_port(context, port)
|
||||
|
||||
def _get_port_create_args(self, share_server, share_network,
|
||||
def _get_port_create_args(self, share_server, share_network_subnet,
|
||||
device_owner):
|
||||
return {
|
||||
"network_id": share_network['neutron_net_id'],
|
||||
"subnet_id": share_network['neutron_subnet_id'],
|
||||
"network_id": share_network_subnet['neutron_net_id'],
|
||||
"subnet_id": share_network_subnet['neutron_subnet_id'],
|
||||
"device_owner": 'manila:' + device_owner,
|
||||
"device_id": share_server.get('id'),
|
||||
}
|
||||
|
||||
def _create_port(self, context, share_server, share_network, device_owner):
|
||||
create_args = self._get_port_create_args(share_server, share_network,
|
||||
device_owner)
|
||||
def _create_port(self, context, share_server, share_network,
|
||||
share_network_subnet, device_owner):
|
||||
create_args = self._get_port_create_args(
|
||||
share_server, share_network_subnet, device_owner)
|
||||
|
||||
port = self.neutron_api.create_port(
|
||||
share_network['project_id'], **create_args)
|
||||
|
||||
ip_address = self._get_matched_ip_address(port['fixed_ips'],
|
||||
share_network['ip_version'])
|
||||
ip_address = self._get_matched_ip_address(
|
||||
port['fixed_ips'], share_network_subnet['ip_version'])
|
||||
port_dict = {
|
||||
'id': port['id'],
|
||||
'share_server_id': share_server['id'],
|
||||
'ip_address': ip_address,
|
||||
'gateway': share_network['gateway'],
|
||||
'gateway': share_network_subnet['gateway'],
|
||||
'mac_address': port['mac_address'],
|
||||
'status': constants.STATUS_ACTIVE,
|
||||
'label': self.label,
|
||||
'network_type': share_network.get('network_type'),
|
||||
'segmentation_id': share_network.get('segmentation_id'),
|
||||
'ip_version': share_network['ip_version'],
|
||||
'cidr': share_network['cidr'],
|
||||
'mtu': share_network['mtu'],
|
||||
'network_type': share_network_subnet.get('network_type'),
|
||||
'segmentation_id': share_network_subnet.get('segmentation_id'),
|
||||
'ip_version': share_network_subnet['ip_version'],
|
||||
'cidr': share_network_subnet['cidr'],
|
||||
'mtu': share_network_subnet['mtu'],
|
||||
}
|
||||
return self.db.network_allocation_create(context, port_dict)
|
||||
|
||||
@ -344,19 +352,19 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
||||
extensions = self.neutron_api.list_extensions()
|
||||
return neutron_constants.PROVIDER_NW_EXT in extensions
|
||||
|
||||
def _is_neutron_multi_segment(self, share_network, net_info=None):
|
||||
def _is_neutron_multi_segment(self, share_network_subnet, net_info=None):
|
||||
if net_info is None:
|
||||
net_info = self.neutron_api.get_network(
|
||||
share_network['neutron_net_id'])
|
||||
share_network_subnet['neutron_net_id'])
|
||||
return 'segments' in net_info
|
||||
|
||||
def _save_neutron_network_data(self, context, share_network):
|
||||
def _save_neutron_network_data(self, context, share_network_subnet):
|
||||
net_info = self.neutron_api.get_network(
|
||||
share_network['neutron_net_id'])
|
||||
share_network_subnet['neutron_net_id'])
|
||||
segmentation_id = None
|
||||
network_type = None
|
||||
|
||||
if self._is_neutron_multi_segment(share_network, net_info):
|
||||
if self._is_neutron_multi_segment(share_network_subnet, net_info):
|
||||
# we have a multi segment network and need to identify the
|
||||
# lowest segment used for binding
|
||||
phy_nets = []
|
||||
@ -383,26 +391,26 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
||||
'segmentation_id': segmentation_id,
|
||||
'mtu': net_info['mtu'],
|
||||
}
|
||||
share_network.update(provider_nw_dict)
|
||||
share_network_subnet.update(provider_nw_dict)
|
||||
|
||||
if self.label != 'admin':
|
||||
self.db.share_network_update(
|
||||
context, share_network['id'], provider_nw_dict)
|
||||
self.db.share_network_subnet_update(
|
||||
context, share_network_subnet['id'], provider_nw_dict)
|
||||
|
||||
def _save_neutron_subnet_data(self, context, share_network):
|
||||
def _save_neutron_subnet_data(self, context, share_network_subnet):
|
||||
subnet_info = self.neutron_api.get_subnet(
|
||||
share_network['neutron_subnet_id'])
|
||||
share_network_subnet['neutron_subnet_id'])
|
||||
|
||||
subnet_values = {
|
||||
'cidr': subnet_info['cidr'],
|
||||
'gateway': subnet_info['gateway_ip'],
|
||||
'ip_version': subnet_info['ip_version']
|
||||
}
|
||||
share_network.update(subnet_values)
|
||||
share_network_subnet.update(subnet_values)
|
||||
|
||||
if self.label != 'admin':
|
||||
self.db.share_network_update(
|
||||
context, share_network['id'], subnet_values)
|
||||
self.db.share_network_subnet_update(
|
||||
context, share_network_subnet['id'], subnet_values)
|
||||
|
||||
|
||||
class NeutronSingleNetworkPlugin(NeutronNetworkPlugin):
|
||||
@ -416,36 +424,47 @@ class NeutronSingleNetworkPlugin(NeutronNetworkPlugin):
|
||||
self.subnet = self.neutron_api.configuration.neutron_subnet_id
|
||||
self._verify_net_and_subnet()
|
||||
|
||||
def _select_proper_share_network(self, context, share_network):
|
||||
def _select_proper_share_network_subnet(self, context,
|
||||
share_network_subnet):
|
||||
if self.label != 'admin':
|
||||
share_network = self._update_share_network_net_data(
|
||||
context, share_network)
|
||||
share_network_subnet = self._update_share_network_net_data(
|
||||
context, share_network_subnet)
|
||||
else:
|
||||
share_network = {
|
||||
share_network_subnet = {
|
||||
'project_id': self.neutron_api.admin_project_id,
|
||||
'neutron_net_id': self.net,
|
||||
'neutron_subnet_id': self.subnet,
|
||||
}
|
||||
return share_network
|
||||
return share_network_subnet
|
||||
|
||||
def allocate_network(self, context, share_server, share_network=None,
|
||||
**kwargs):
|
||||
share_network_subnet=None, **kwargs):
|
||||
|
||||
share_network = self._select_proper_share_network(
|
||||
context, share_network)
|
||||
share_network_subnet = self._select_proper_share_network_subnet(
|
||||
context, share_network_subnet)
|
||||
# Update share network project_id info if needed
|
||||
if share_network_subnet.get('project_id', None) is not None:
|
||||
share_network['project_id'] = share_network_subnet.pop(
|
||||
'project_id')
|
||||
|
||||
return super(NeutronSingleNetworkPlugin, self).allocate_network(
|
||||
context, share_server, share_network, **kwargs)
|
||||
context, share_server, share_network, share_network_subnet,
|
||||
**kwargs)
|
||||
|
||||
def manage_network_allocations(self, context, allocations, share_server,
|
||||
share_network=None):
|
||||
|
||||
share_network = self._select_proper_share_network(
|
||||
context, share_network)
|
||||
def manage_network_allocations(
|
||||
self, context, allocations, share_server, share_network=None,
|
||||
share_network_subnet=None):
|
||||
share_network_subnet = self._select_proper_share_network_subnet(
|
||||
context, share_network_subnet)
|
||||
# Update share network project_id info if needed
|
||||
if share_network and share_network_subnet.get('project_id', None):
|
||||
share_network['project_id'] = (
|
||||
share_network_subnet.pop('project_id'))
|
||||
|
||||
return super(NeutronSingleNetworkPlugin,
|
||||
self).manage_network_allocations(
|
||||
context, allocations, share_server, share_network)
|
||||
context, allocations, share_server, share_network,
|
||||
share_network_subnet)
|
||||
|
||||
def _verify_net_and_subnet(self):
|
||||
data = dict(net=self.net, subnet=self.subnet)
|
||||
@ -460,33 +479,33 @@ class NeutronSingleNetworkPlugin(NeutronNetworkPlugin):
|
||||
"Neutron net and subnet are expected to be both set. "
|
||||
"Got: net=%(net)s and subnet=%(subnet)s." % data)
|
||||
|
||||
def _update_share_network_net_data(self, context, share_network):
|
||||
def _update_share_network_net_data(self, context, share_network_subnet):
|
||||
upd = dict()
|
||||
|
||||
if not share_network.get('neutron_net_id') == self.net:
|
||||
if share_network.get('neutron_net_id') is not None:
|
||||
if not share_network_subnet.get('neutron_net_id') == self.net:
|
||||
if share_network_subnet.get('neutron_net_id') is not None:
|
||||
raise exception.NetworkBadConfigurationException(
|
||||
"Using neutron net id different from None or value "
|
||||
"specified in the config is forbidden for "
|
||||
"NeutronSingleNetworkPlugin. Allowed values: (%(net)s, "
|
||||
"None), received value: %(err)s" % {
|
||||
"net": self.net,
|
||||
"err": share_network.get('neutron_net_id')})
|
||||
"err": share_network_subnet.get('neutron_net_id')})
|
||||
upd['neutron_net_id'] = self.net
|
||||
if not share_network.get('neutron_subnet_id') == self.subnet:
|
||||
if share_network.get('neutron_subnet_id') is not None:
|
||||
if not share_network_subnet.get('neutron_subnet_id') == self.subnet:
|
||||
if share_network_subnet.get('neutron_subnet_id') is not None:
|
||||
raise exception.NetworkBadConfigurationException(
|
||||
"Using neutron subnet id different from None or value "
|
||||
"specified in the config is forbidden for "
|
||||
"NeutronSingleNetworkPlugin. Allowed values: (%(snet)s, "
|
||||
"None), received value: %(err)s" % {
|
||||
"snet": self.subnet,
|
||||
"err": share_network.get('neutron_subnet_id')})
|
||||
"err": share_network_subnet.get('neutron_subnet_id')})
|
||||
upd['neutron_subnet_id'] = self.subnet
|
||||
if upd:
|
||||
share_network = self.db.share_network_update(
|
||||
context, share_network['id'], upd)
|
||||
return share_network
|
||||
share_network_subnet = self.db.share_network_subnet_update(
|
||||
context, share_network_subnet['id'], upd)
|
||||
return share_network_subnet
|
||||
|
||||
|
||||
class NeutronBindNetworkPlugin(NeutronNetworkPlugin):
|
||||
@ -541,11 +560,11 @@ class NeutronBindNetworkPlugin(NeutronNetworkPlugin):
|
||||
"ports": inactive_ports}
|
||||
raise exception.NetworkBindException(msg)
|
||||
|
||||
def _get_port_create_args(self, share_server, share_network,
|
||||
def _get_port_create_args(self, share_server, share_network_subnet,
|
||||
device_owner):
|
||||
arguments = super(
|
||||
NeutronBindNetworkPlugin, self)._get_port_create_args(
|
||||
share_network, share_network, device_owner)
|
||||
share_server, share_network_subnet, device_owner)
|
||||
arguments['host_id'] = self.config.neutron_host_id
|
||||
arguments['binding:vnic_type'] = self.config.neutron_vnic_type
|
||||
if self.binding_profiles:
|
||||
@ -561,7 +580,7 @@ class NeutronBindNetworkPlugin(NeutronNetworkPlugin):
|
||||
"local_link_information": local_links}
|
||||
return arguments
|
||||
|
||||
def _save_neutron_network_data(self, context, share_network):
|
||||
def _save_neutron_network_data(self, context, share_network_subnet):
|
||||
"""Store the Neutron network info.
|
||||
|
||||
In case of dynamic multi segments the segment is determined while
|
||||
@ -571,36 +590,37 @@ class NeutronBindNetworkPlugin(NeutronNetworkPlugin):
|
||||
Instead, multi segments network will wait until ports are bound and
|
||||
then store network information (see allocate_network()).
|
||||
"""
|
||||
if self._is_neutron_multi_segment(share_network):
|
||||
if self._is_neutron_multi_segment(share_network_subnet):
|
||||
# In case of dynamic multi segment the segment is determined while
|
||||
# binding the port, only mtu is known and already needed
|
||||
self._save_neutron_network_mtu(context, share_network)
|
||||
self._save_neutron_network_mtu(context, share_network_subnet)
|
||||
return
|
||||
super(NeutronBindNetworkPlugin, self)._save_neutron_network_data(
|
||||
context, share_network)
|
||||
context, share_network_subnet)
|
||||
|
||||
def _save_neutron_network_mtu(self, context, share_network):
|
||||
def _save_neutron_network_mtu(self, context, share_network_subnet):
|
||||
"""Store the Neutron network mtu.
|
||||
|
||||
In case of dynamic multi segments only the mtu needs storing before
|
||||
binding the port.
|
||||
"""
|
||||
net_info = self.neutron_api.get_network(
|
||||
share_network['neutron_net_id'])
|
||||
share_network_subnet['neutron_net_id'])
|
||||
|
||||
mtu_dict = {
|
||||
'mtu': net_info['mtu'],
|
||||
}
|
||||
share_network.update(mtu_dict)
|
||||
share_network_subnet.update(mtu_dict)
|
||||
|
||||
if self.label != 'admin':
|
||||
self.db.share_network_update(
|
||||
context, share_network['id'], mtu_dict)
|
||||
self.db.share_network_subnet_update(
|
||||
context, share_network_subnet['id'], mtu_dict)
|
||||
|
||||
def allocate_network(self, context, share_server, share_network=None,
|
||||
**kwargs):
|
||||
share_network_subnet=None, **kwargs):
|
||||
ports = super(NeutronBindNetworkPlugin, self).allocate_network(
|
||||
context, share_server, share_network, **kwargs)
|
||||
context, share_server, share_network, share_network_subnet,
|
||||
**kwargs)
|
||||
# If vnic type is 'normal' we expect a neutron agent to bind the
|
||||
# ports. This action requires a vnic to be spawned by the driver.
|
||||
# Therefore we do not wait for the port binding here, but
|
||||
@ -609,16 +629,18 @@ class NeutronBindNetworkPlugin(NeutronNetworkPlugin):
|
||||
# order to update the ports with the correct binding.
|
||||
if self.config.neutron_vnic_type != 'normal':
|
||||
self._wait_for_ports_bind(ports, share_server)
|
||||
if self._is_neutron_multi_segment(share_network):
|
||||
if self._is_neutron_multi_segment(share_network_subnet):
|
||||
# update segment information after port bind
|
||||
super(NeutronBindNetworkPlugin,
|
||||
self)._save_neutron_network_data(context, share_network)
|
||||
self)._save_neutron_network_data(context,
|
||||
share_network_subnet)
|
||||
for num, port in enumerate(ports):
|
||||
port_info = {
|
||||
'network_type': share_network['network_type'],
|
||||
'segmentation_id': share_network['segmentation_id'],
|
||||
'cidr': share_network['cidr'],
|
||||
'ip_version': share_network['ip_version'],
|
||||
'network_type': share_network_subnet['network_type'],
|
||||
'segmentation_id':
|
||||
share_network_subnet['segmentation_id'],
|
||||
'cidr': share_network_subnet['cidr'],
|
||||
'ip_version': share_network_subnet['ip_version'],
|
||||
}
|
||||
ports[num] = self.db.network_allocation_update(
|
||||
context, port['id'], port_info)
|
||||
|
@ -264,8 +264,8 @@ class StandaloneNetworkPlugin(network.NetworkBaseAPI):
|
||||
'available': len(ips)}
|
||||
raise exception.NetworkBadConfigurationException(reason=msg)
|
||||
|
||||
def _save_network_info(self, context, share_network):
|
||||
"""Update share-network with plugin specific data."""
|
||||
def _save_network_info(self, context, share_network_subnet):
|
||||
"""Update share-network-subnet with plugin specific data."""
|
||||
data = {
|
||||
'network_type': self.network_type,
|
||||
'segmentation_id': self.segmentation_id,
|
||||
@ -274,14 +274,15 @@ class StandaloneNetworkPlugin(network.NetworkBaseAPI):
|
||||
'ip_version': self.ip_version,
|
||||
'mtu': self.mtu,
|
||||
}
|
||||
share_network.update(data)
|
||||
share_network_subnet.update(data)
|
||||
if self.label != 'admin':
|
||||
self.db.share_network_update(context, share_network['id'], data)
|
||||
self.db.share_network_subnet_update(
|
||||
context, share_network_subnet['id'], data)
|
||||
|
||||
@utils.synchronized(
|
||||
"allocate_network_for_standalone_network_plugin", external=True)
|
||||
def allocate_network(self, context, share_server, share_network=None,
|
||||
**kwargs):
|
||||
share_network_subnet=None, **kwargs):
|
||||
"""Allocate network resources using one dedicated network.
|
||||
|
||||
This one has interprocess lock to avoid concurrency in creation of
|
||||
@ -289,10 +290,11 @@ class StandaloneNetworkPlugin(network.NetworkBaseAPI):
|
||||
"""
|
||||
allocation_count = kwargs.get('count', 1)
|
||||
if self.label != 'admin':
|
||||
self._verify_share_network(share_server['id'], share_network)
|
||||
self._verify_share_network(share_server['id'],
|
||||
share_network_subnet)
|
||||
else:
|
||||
share_network = share_network or {}
|
||||
self._save_network_info(context, share_network)
|
||||
share_network_subnet = share_network_subnet or {}
|
||||
self._save_network_info(context, share_network_subnet)
|
||||
allocations = []
|
||||
ip_addresses = self._get_available_ips(context, allocation_count)
|
||||
for ip_address in ip_addresses:
|
||||
@ -301,12 +303,12 @@ class StandaloneNetworkPlugin(network.NetworkBaseAPI):
|
||||
'ip_address': ip_address,
|
||||
'status': constants.STATUS_ACTIVE,
|
||||
'label': self.label,
|
||||
'network_type': share_network['network_type'],
|
||||
'segmentation_id': share_network['segmentation_id'],
|
||||
'cidr': share_network['cidr'],
|
||||
'gateway': share_network['gateway'],
|
||||
'ip_version': share_network['ip_version'],
|
||||
'mtu': share_network['mtu'],
|
||||
'network_type': share_network_subnet['network_type'],
|
||||
'segmentation_id': share_network_subnet['segmentation_id'],
|
||||
'cidr': share_network_subnet['cidr'],
|
||||
'gateway': share_network_subnet['gateway'],
|
||||
'ip_version': share_network_subnet['ip_version'],
|
||||
'mtu': share_network_subnet['mtu'],
|
||||
}
|
||||
allocations.append(
|
||||
self.db.network_allocation_create(context, data))
|
||||
@ -323,12 +325,14 @@ class StandaloneNetworkPlugin(network.NetworkBaseAPI):
|
||||
self.deallocate_network(context, share_server_id)
|
||||
|
||||
def manage_network_allocations(self, context, allocations, share_server,
|
||||
share_network=None):
|
||||
share_network=None,
|
||||
share_network_subnet=None):
|
||||
if self.label != 'admin':
|
||||
self._verify_share_network(share_server['id'], share_network)
|
||||
self._verify_share_network_subnet(share_server['id'],
|
||||
share_network_subnet)
|
||||
else:
|
||||
share_network = share_network or {}
|
||||
self._save_network_info(context, share_network)
|
||||
share_network_subnet = share_network_subnet or {}
|
||||
self._save_network_info(context, share_network_subnet)
|
||||
|
||||
# We begin matching the allocations to known neutron ports and
|
||||
# finally return the non-consumed allocations
|
||||
@ -350,12 +354,12 @@ class StandaloneNetworkPlugin(network.NetworkBaseAPI):
|
||||
'ip_address': allocation,
|
||||
'status': constants.STATUS_ACTIVE,
|
||||
'label': self.label,
|
||||
'network_type': share_network['network_type'],
|
||||
'segmentation_id': share_network['segmentation_id'],
|
||||
'cidr': share_network['cidr'],
|
||||
'gateway': share_network['gateway'],
|
||||
'ip_version': share_network['ip_version'],
|
||||
'mtu': share_network['mtu'],
|
||||
'network_type': share_network_subnet['network_type'],
|
||||
'segmentation_id': share_network_subnet['segmentation_id'],
|
||||
'cidr': share_network_subnet['cidr'],
|
||||
'gateway': share_network_subnet['gateway'],
|
||||
'ip_version': share_network_subnet['ip_version'],
|
||||
'mtu': share_network_subnet['mtu'],
|
||||
}
|
||||
self.db.network_allocation_create(context, data)
|
||||
remaining_allocations.remove(allocation)
|
||||
|
@ -34,6 +34,7 @@ from manila.policies import share_group_types_spec
|
||||
from manila.policies import share_instance
|
||||
from manila.policies import share_instance_export_location
|
||||
from manila.policies import share_network
|
||||
from manila.policies import share_network_subnet
|
||||
from manila.policies import share_replica
|
||||
from manila.policies import share_replica_export_location
|
||||
from manila.policies import share_server
|
||||
@ -70,6 +71,7 @@ def list_rules():
|
||||
share_replica.list_rules(),
|
||||
share_replica_export_location.list_rules(),
|
||||
share_network.list_rules(),
|
||||
share_network_subnet.list_rules(),
|
||||
security_service.list_rules(),
|
||||
share_export_location.list_rules(),
|
||||
share_instance.list_rules(),
|
||||
|
70
manila/policies/share_network_subnet.py
Normal file
70
manila/policies/share_network_subnet.py
Normal file
@ -0,0 +1,70 @@
|
||||
# Copyright 2019 NetApp, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_policy import policy
|
||||
|
||||
from manila.policies import base
|
||||
|
||||
BASE_POLICY_NAME = 'share_network_subnet:%s'
|
||||
|
||||
|
||||
share_network_subnet_policies = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=BASE_POLICY_NAME % 'create',
|
||||
check_str=base.RULE_DEFAULT,
|
||||
description="Create a new share network subnet.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/share-networks/{share_network_id}/subnets'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=BASE_POLICY_NAME % 'delete',
|
||||
check_str=base.RULE_DEFAULT,
|
||||
description="Delete a share network subnet.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'DELETE',
|
||||
'path': '/share-networks/{share_network_id}/subnets/'
|
||||
'{share_network_subnet_id}'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=BASE_POLICY_NAME % 'show',
|
||||
check_str=base.RULE_DEFAULT,
|
||||
description="Shows a share network subnet.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/share-networks/{share_network_id}/subnets/'
|
||||
'{share_network_subnet_id}'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=BASE_POLICY_NAME % 'index',
|
||||
check_str=base.RULE_DEFAULT,
|
||||
description="Get all share network subnets.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/share-networks/{share_network_id}/subnets'
|
||||
}
|
||||
]),
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return share_network_subnet_policies
|
@ -66,6 +66,16 @@ class API(base.Base):
|
||||
self.share_rpcapi = share_rpcapi.ShareAPI()
|
||||
self.access_helper = access.ShareInstanceAccess(self.db, None)
|
||||
|
||||
def _get_all_availability_zones_with_subnets(self, context,
|
||||
share_network_id):
|
||||
compatible_azs = []
|
||||
for az in self.db.availability_zone_get_all(context):
|
||||
if self.db.share_network_subnet_get_by_availability_zone_id(
|
||||
context, share_network_id=share_network_id,
|
||||
availability_zone_id=az['id']):
|
||||
compatible_azs.append(az['name'])
|
||||
return compatible_azs
|
||||
|
||||
def create(self, context, share_proto, size, name, description,
|
||||
snapshot_id=None, availability_zone=None, metadata=None,
|
||||
share_network_id=None, share_type=None, is_public=False,
|
||||
@ -227,6 +237,25 @@ class API(base.Base):
|
||||
options['source_share_group_snapshot_member_id'] = (
|
||||
share_group_snapshot_member['id'])
|
||||
|
||||
# NOTE(dviroel): If a target availability zone was not provided, the
|
||||
# scheduler will receive a list with all availability zones that
|
||||
# contains a subnet within the selected share network.
|
||||
if share_network_id and not availability_zone:
|
||||
azs_with_subnet = self._get_all_availability_zones_with_subnets(
|
||||
context, share_network_id)
|
||||
if not availability_zones:
|
||||
availability_zones = azs_with_subnet
|
||||
else:
|
||||
availability_zones = (
|
||||
[az for az in availability_zones if az in azs_with_subnet])
|
||||
if not availability_zones:
|
||||
msg = _(
|
||||
"The share network is not supported within any requested "
|
||||
"availability zone. Check the share type's "
|
||||
"'availability_zones' extra-spec and the availability "
|
||||
"zones of the share network subnets")
|
||||
raise exception.InvalidInput(message=msg)
|
||||
|
||||
try:
|
||||
share = self.db.share_create(context, options,
|
||||
create_share_instance=False)
|
||||
@ -484,11 +513,45 @@ class API(base.Base):
|
||||
'az': availability_zone}
|
||||
raise exception.InvalidShare(message=msg % payload)
|
||||
|
||||
if share_network_id:
|
||||
if availability_zone:
|
||||
try:
|
||||
az = self.db.availability_zone_get(context,
|
||||
availability_zone)
|
||||
except exception.AvailabilityZoneNotFound:
|
||||
msg = _("Share replica cannot be created because the "
|
||||
"specified availability zone does not exist.")
|
||||
raise exception.InvalidInput(message=msg)
|
||||
if self.db.share_network_subnet_get_by_availability_zone_id(
|
||||
context, share_network_id, az.get('id')) is None:
|
||||
msg = _("Share replica cannot be created because the "
|
||||
"share network is not available within the "
|
||||
"specified availability zone.")
|
||||
raise exception.InvalidShare(message=msg)
|
||||
else:
|
||||
# NOTE(dviroel): If a target availability zone was not
|
||||
# provided, the scheduler will receive a list with all
|
||||
# availability zones that contains subnets within the
|
||||
# selected share network.
|
||||
azs_subnet = self._get_all_availability_zones_with_subnets(
|
||||
context, share_network_id)
|
||||
if not type_azs:
|
||||
type_azs = azs_subnet
|
||||
else:
|
||||
type_azs = (
|
||||
[az for az in type_azs if az in azs_subnet])
|
||||
if not type_azs:
|
||||
msg = _(
|
||||
"The share network is not supported within any "
|
||||
"requested availability zone. Check the share type's "
|
||||
"'availability_zones' extra-spec and the availability "
|
||||
"zones of the share network subnets")
|
||||
raise exception.InvalidInput(message=msg)
|
||||
|
||||
if share['replication_type'] == constants.REPLICATION_TYPE_READABLE:
|
||||
cast_rules_to_readonly = True
|
||||
else:
|
||||
cast_rules_to_readonly = False
|
||||
|
||||
request_spec, share_replica = (
|
||||
self.create_share_instance_and_get_request_spec(
|
||||
context, share, availability_zone=availability_zone,
|
||||
@ -641,7 +704,9 @@ class API(base.Base):
|
||||
if share_server['status'] != constants.STATUS_ACTIVE:
|
||||
msg = _("Share Server specified is not active.")
|
||||
raise exception.InvalidShareServer(message=msg)
|
||||
share_data['share_network_id'] = share_server['share_network_id']
|
||||
subnet = self.db.share_network_subnet_get(
|
||||
context, share_server['share_network_subnet_id'])
|
||||
share_data['share_network_id'] = subnet['share_network_id']
|
||||
|
||||
share_data.update({
|
||||
'user_id': context.user_id,
|
||||
@ -1019,7 +1084,7 @@ class API(base.Base):
|
||||
self.share_rpcapi.delete_share_server(context, server)
|
||||
|
||||
def manage_share_server(
|
||||
self, context, identifier, host, share_network, driver_opts):
|
||||
self, context, identifier, host, share_net_subnet, driver_opts):
|
||||
"""Manage a share server."""
|
||||
|
||||
try:
|
||||
@ -1037,7 +1102,7 @@ class API(base.Base):
|
||||
|
||||
values = {
|
||||
'host': host,
|
||||
'share_network_id': share_network['id'],
|
||||
'share_network_subnet_id': share_net_subnet['id'],
|
||||
'status': constants.STATUS_MANAGING,
|
||||
'is_auto_deletable': False,
|
||||
'identifier': identifier,
|
||||
|
@ -843,14 +843,15 @@ class ShareDriver(object):
|
||||
share_server)
|
||||
|
||||
def allocate_network(self, context, share_server, share_network,
|
||||
count=None, **kwargs):
|
||||
share_network_subnet, count=None, **kwargs):
|
||||
"""Allocate network resources using given network information."""
|
||||
if count is None:
|
||||
count = self.get_network_allocations_number()
|
||||
if count:
|
||||
kwargs.update(count=count)
|
||||
self.network_api.allocate_network(
|
||||
context, share_server, share_network, **kwargs)
|
||||
context, share_server, share_network=share_network,
|
||||
share_network_subnet=share_network_subnet, **kwargs)
|
||||
|
||||
def allocate_admin_network(self, context, share_server, count=None,
|
||||
**kwargs):
|
||||
|
@ -23,6 +23,7 @@ import copy
|
||||
import datetime
|
||||
import functools
|
||||
import hashlib
|
||||
from operator import xor
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
@ -45,7 +46,7 @@ from manila.message import message_field
|
||||
from manila import quota
|
||||
from manila.share import access
|
||||
from manila.share import api
|
||||
import manila.share.configuration
|
||||
from manila.share import configuration
|
||||
from manila.share import drivers_private_data
|
||||
from manila.share import migration
|
||||
from manila.share import rpcapi as share_rpcapi
|
||||
@ -213,7 +214,7 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
|
||||
def __init__(self, share_driver=None, service_name=None, *args, **kwargs):
|
||||
"""Load the driver from args, or from flags."""
|
||||
self.configuration = manila.share.configuration.Configuration(
|
||||
self.configuration = configuration.Configuration(
|
||||
share_manager_opts,
|
||||
config_group=service_name)
|
||||
super(ShareManager, self).__init__(service_name='share',
|
||||
@ -525,13 +526,11 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
" should be provided. ")
|
||||
raise ValueError(msg)
|
||||
|
||||
parent_share_server = None
|
||||
|
||||
def error(msg, *args):
|
||||
LOG.error(msg, *args)
|
||||
self.db.share_instance_update(context, share_instance['id'],
|
||||
{'status': constants.STATUS_ERROR})
|
||||
|
||||
parent_share_server = None
|
||||
if snapshot:
|
||||
parent_share_server_id = (
|
||||
snapshot['share']['instance']['share_server_id'])
|
||||
@ -553,9 +552,23 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
raise exception.InvalidShareServer(
|
||||
share_server_id=parent_share_server
|
||||
)
|
||||
|
||||
if parent_share_server and not share_network_id:
|
||||
share_network_id = parent_share_server['share_network_id']
|
||||
share_network_subnet_id = None
|
||||
if share_network_id:
|
||||
share_network_subnet = (
|
||||
self.db.share_network_subnet_get_by_availability_zone_id(
|
||||
context, share_network_id,
|
||||
availability_zone_id=share_instance.get(
|
||||
'availability_zone_id')))
|
||||
if not share_network_subnet:
|
||||
raise exception.ShareNetworkSubnetNotFound(
|
||||
share_network_subnet_id=None)
|
||||
share_network_subnet_id = share_network_subnet['id']
|
||||
elif parent_share_server:
|
||||
share_network_subnet_id = (
|
||||
parent_share_server['share_network_subnet_id'])
|
||||
share_network_subnet = self.db.share_network_subnet_get(
|
||||
context, share_network_subnet_id)
|
||||
share_network_id = share_network_subnet['share_network_id']
|
||||
|
||||
def get_available_share_servers():
|
||||
if parent_share_server:
|
||||
@ -566,7 +579,7 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
context, self.host, share_network_id)
|
||||
)
|
||||
|
||||
@utils.synchronized("share_manager_%s" % share_network_id,
|
||||
@utils.synchronized("share_manager_%s" % share_network_subnet_id,
|
||||
external=True)
|
||||
def _wrapped_provide_share_server_for_share():
|
||||
try:
|
||||
@ -595,7 +608,7 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
context,
|
||||
{
|
||||
'host': self.host,
|
||||
'share_network_id': share_network_id,
|
||||
'share_network_subnet_id': share_network_subnet_id,
|
||||
'status': constants.STATUS_CREATING,
|
||||
}
|
||||
)
|
||||
@ -689,7 +702,9 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
|
||||
return share_server['id']
|
||||
|
||||
def _provide_share_server_for_share_group(self, context, share_network_id,
|
||||
def _provide_share_server_for_share_group(self, context,
|
||||
share_network_id,
|
||||
share_network_subnet_id,
|
||||
share_group_ref,
|
||||
share_group_snapshot=None):
|
||||
"""Gets or creates share_server and updates share group with its id.
|
||||
@ -707,6 +722,10 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
:param context: Current context
|
||||
:param share_network_id: Share network where existing share server
|
||||
should be found or created.
|
||||
:param share_network_subnet_id: Share network subnet where
|
||||
existing share server should be found
|
||||
or created. If not specified, the
|
||||
default subnet will be used.
|
||||
:param share_group_ref: Share Group model
|
||||
:param share_group_snapshot: Optional -- ShareGroupSnapshot model. If
|
||||
supplied, driver will use it to choose
|
||||
@ -757,7 +776,7 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
context,
|
||||
{
|
||||
'host': self.host,
|
||||
'share_network_id': share_network_id,
|
||||
'share_network_subnet_id': share_network_subnet_id,
|
||||
'status': constants.STATUS_CREATING
|
||||
}
|
||||
)
|
||||
@ -1831,7 +1850,6 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
request_spec=None, filter_properties=None):
|
||||
"""Create a share replica."""
|
||||
context = context.elevated()
|
||||
|
||||
share_replica = self.db.share_replica_get(
|
||||
context, share_replica_id, with_share_data=True,
|
||||
with_share_server=True)
|
||||
@ -1847,7 +1865,6 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
self.db.share_replicas_get_available_active_replica(
|
||||
context, share_replica['share_id'], with_share_data=True,
|
||||
with_share_server=True))
|
||||
|
||||
if not _active_replica:
|
||||
self.db.share_replica_update(
|
||||
context, share_replica['id'],
|
||||
@ -1868,9 +1885,8 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
# We need the share_network_id in case of
|
||||
# driver_handles_share_server=True
|
||||
share_network_id = share_replica.get('share_network_id', None)
|
||||
|
||||
if (share_network_id and
|
||||
not self.driver.driver_handles_share_servers):
|
||||
if xor(bool(share_network_id),
|
||||
self.driver.driver_handles_share_servers):
|
||||
self.db.share_replica_update(
|
||||
context, share_replica['id'],
|
||||
{'status': constants.STATUS_ERROR,
|
||||
@ -1883,8 +1899,8 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
resource_id=share_replica['id'],
|
||||
detail=message_field.Detail.UNEXPECTED_NETWORK)
|
||||
raise exception.InvalidDriverMode(
|
||||
"Driver does not expect share-network to be provided "
|
||||
"with current configuration.")
|
||||
"The share-network value provided does not match with the "
|
||||
"current driver configuration.")
|
||||
|
||||
if share_network_id:
|
||||
try:
|
||||
@ -2608,12 +2624,14 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
msg = ("Since share %(share)s has been un-managed from share "
|
||||
"server %(server)s. This share server must be removed "
|
||||
"manually, either by un-managing or by deleting it. The "
|
||||
"share network %(network)s cannot be deleted unless this "
|
||||
"share server has been removed.")
|
||||
"share network subnet %(subnet)s and share network "
|
||||
"%(network) cannot be deleted unless this share server has "
|
||||
"been removed.")
|
||||
msg_args = {
|
||||
'share': share_id,
|
||||
'server': share_server['id'],
|
||||
'network': share_server['share_network_id']
|
||||
'subnet': share_server['share_network_subnet_id'],
|
||||
'network': share_instance['share_network_id']
|
||||
}
|
||||
LOG.warning(msg, msg_args)
|
||||
|
||||
@ -2698,10 +2716,11 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
|
||||
server = self.db.share_server_get(context, share_server_id)
|
||||
|
||||
share_network = self.db.share_network_get(
|
||||
context, server['share_network_id'])
|
||||
|
||||
try:
|
||||
share_network_subnet = self.db.share_network_subnet_get(
|
||||
context, server['share_network_subnet_id'])
|
||||
share_network = self.db.share_network_get(
|
||||
context, share_network_subnet['share_network_id'])
|
||||
|
||||
number_allocations = (
|
||||
self.driver.get_network_allocations_number())
|
||||
@ -2733,7 +2752,7 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
self.driver.network_api.
|
||||
manage_network_allocations(
|
||||
context, remaining_allocations, server,
|
||||
share_network))
|
||||
share_network, share_network_subnet))
|
||||
|
||||
# We require that all allocations are managed, else we
|
||||
# may have problems deleting this share server
|
||||
@ -3578,7 +3597,8 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
self._report_driver_status(context)
|
||||
self._publish_service_capabilities(context)
|
||||
|
||||
def _form_server_setup_info(self, context, share_server, share_network):
|
||||
def _form_server_setup_info(self, context, share_server, share_network,
|
||||
share_network_subnet):
|
||||
# Network info is used by driver for setting up share server
|
||||
# and getting server info on share creation.
|
||||
network_allocations = self.db.network_allocations_get_for_share_server(
|
||||
@ -3592,30 +3612,34 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
# They should be removed right after no one uses them.
|
||||
network_info = {
|
||||
'server_id': share_server['id'],
|
||||
'segmentation_id': share_network['segmentation_id'],
|
||||
'cidr': share_network['cidr'],
|
||||
'neutron_net_id': share_network['neutron_net_id'],
|
||||
'neutron_subnet_id': share_network['neutron_subnet_id'],
|
||||
'segmentation_id': share_network_subnet['segmentation_id'],
|
||||
'cidr': share_network_subnet['cidr'],
|
||||
'neutron_net_id': share_network_subnet['neutron_net_id'],
|
||||
'neutron_subnet_id': share_network_subnet['neutron_subnet_id'],
|
||||
'security_services': share_network['security_services'],
|
||||
'network_allocations': network_allocations,
|
||||
'admin_network_allocations': admin_network_allocations,
|
||||
'backend_details': share_server.get('backend_details'),
|
||||
'network_type': share_network['network_type'],
|
||||
'network_type': share_network_subnet['network_type'],
|
||||
}
|
||||
return network_info
|
||||
|
||||
def _setup_server(self, context, share_server, metadata=None):
|
||||
try:
|
||||
share_network_subnet = share_server['share_network_subnet']
|
||||
share_network_subnet_id = share_network_subnet['id']
|
||||
share_network_id = share_network_subnet['share_network_id']
|
||||
share_network = self.db.share_network_get(
|
||||
context, share_server['share_network_id'])
|
||||
self.driver.allocate_network(context, share_server, share_network)
|
||||
context, share_network_id)
|
||||
self.driver.allocate_network(context, share_server, share_network,
|
||||
share_network_subnet)
|
||||
self.driver.allocate_admin_network(context, share_server)
|
||||
|
||||
# Get share_network again in case it was updated.
|
||||
share_network = self.db.share_network_get(
|
||||
context, share_server['share_network_id'])
|
||||
# Get share_network_subnet in case it was updated.
|
||||
share_network_subnet = self.db.share_network_subnet_get(
|
||||
context, share_network_subnet_id)
|
||||
network_info = self._form_server_setup_info(
|
||||
context, share_server, share_network)
|
||||
context, share_server, share_network, share_network_subnet)
|
||||
self._validate_segmentation_id(network_info)
|
||||
|
||||
# NOTE(vponomaryov): Save security services data to share server
|
||||
@ -3735,7 +3759,7 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
def delete_share_server(self, context, share_server):
|
||||
|
||||
@utils.synchronized(
|
||||
"share_manager_%s" % share_server['share_network_id'])
|
||||
"share_manager_%s" % share_server['share_network_subnet_id'])
|
||||
def _wrapped_delete_share_server():
|
||||
# NOTE(vponomaryov): Verify that there are no dependent shares.
|
||||
# Without this verification we can get here exception in next case:
|
||||
@ -3944,7 +3968,8 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
if parent_share_server_id and self.driver.driver_handles_share_servers:
|
||||
share_server = self.db.share_server_get(context,
|
||||
parent_share_server_id)
|
||||
share_network_id = share_server['share_network_id']
|
||||
share_network_subnet = share_server['share_network_subnet']
|
||||
share_network_id = share_network_subnet['share_network_id']
|
||||
|
||||
if share_network_id and not self.driver.driver_handles_share_servers:
|
||||
self.db.share_group_update(
|
||||
@ -3954,10 +3979,17 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
if not share_server and share_network_id:
|
||||
|
||||
availability_zone_id = self._get_az_for_share_group(
|
||||
context, share_group_ref)
|
||||
subnet = self.db.share_network_subnet_get_by_availability_zone_id(
|
||||
context, share_network_id, availability_zone_id)
|
||||
|
||||
try:
|
||||
share_server, share_group_ref = (
|
||||
self._provide_share_server_for_share_group(
|
||||
context, share_network_id, share_group_ref,
|
||||
context, share_network_id, subnet.get('id'),
|
||||
share_group_ref,
|
||||
share_group_snapshot=snap_ref,
|
||||
)
|
||||
)
|
||||
|
@ -270,20 +270,6 @@ fixture_valid_reset_status_body = (
|
||||
({'reset_status': {'status': 'migrating_to'}}, '2.7'),
|
||||
)
|
||||
|
||||
share_network_id = '5dfe0898-e2a1-4740-9177-81c7d26713b0'
|
||||
share_network = {
|
||||
'name': 'share-net-fake',
|
||||
'share_network_id': '5dfe0898-e2a1-4740-9177-81c7d26713b0',
|
||||
'project_id': '5dfe0898-e2a1-4740-9177-81c7d26713b0'
|
||||
}
|
||||
SHARE_SERVER = {
|
||||
'share_network': share_network,
|
||||
'share_network_id': 'c5b3a865-56d0-4d88-abe5-879965e099c9',
|
||||
'host': host,
|
||||
'id': 'c39bb9ae-16a5-40f2-a24f-1cf3f549d3d3',
|
||||
'status': constants.STATUS_ACTIVE
|
||||
}
|
||||
|
||||
|
||||
def mock_fake_admin_check(context, resource_name, action, *args, **kwargs):
|
||||
if context.is_admin:
|
||||
|
@ -150,14 +150,14 @@ class RequestTest(test.TestCase):
|
||||
mock.Mock(return_value=max_version))
|
||||
self.mock_object(api_version, 'min_api_version',
|
||||
mock.Mock(return_value=min_version))
|
||||
headers = {'X-OpenStack-Manila-API-Version': '2.50'}
|
||||
headers = {'X-OpenStack-Manila-API-Version': '2.51'}
|
||||
request = wsgi.Request.blank(
|
||||
'https://openstack.acme.com/v2/shares', method='GET',
|
||||
headers=headers, script_name='/v2/shares')
|
||||
|
||||
self.assertRaises(exception.InvalidGlobalAPIVersion,
|
||||
request.set_api_version_request)
|
||||
self.assertEqual(api_version.APIVersionRequest('2.50'),
|
||||
self.assertEqual(api_version.APIVersionRequest('2.51'),
|
||||
request.api_version_request)
|
||||
|
||||
@ddt.data('', '/share', '/v1', '/v2/shares', '/v1.1/', '/share/v1',
|
||||
|
@ -328,6 +328,21 @@ class MiscFunctionsTest(test.TestCase):
|
||||
policy.check_policy.assert_called_once_with(
|
||||
'fake_context', 'share', 'set_public_share', do_raise=False)
|
||||
|
||||
@ddt.data(({}, True),
|
||||
({'neutron_net_id': 'fake_nn_id'}, False),
|
||||
({'neutron_subnet_id': 'fake_sn_id'}, False),
|
||||
({'neutron_net_id': 'fake_nn_id',
|
||||
'neutron_subnet_id': 'fake_sn_id'}, True))
|
||||
@ddt.unpack
|
||||
def test__check_net_id_and_subnet_id(self, body, expected):
|
||||
if not expected:
|
||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||
common.check_net_id_and_subnet_id,
|
||||
body)
|
||||
else:
|
||||
result = common.check_net_id_and_subnet_id(body)
|
||||
self.assertIsNone(result)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class ViewBuilderTest(test.TestCase):
|
||||
|
@ -13,6 +13,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import ddt
|
||||
import mock
|
||||
from six.moves.urllib import parse
|
||||
import webob
|
||||
@ -25,6 +26,7 @@ from manila import test
|
||||
from manila.tests.api import fakes
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class ShareApiTest(test.TestCase):
|
||||
"""Share Api Test."""
|
||||
def setUp(self):
|
||||
@ -81,6 +83,21 @@ class ShareApiTest(test.TestCase):
|
||||
}, ]
|
||||
}
|
||||
|
||||
self.fake_share_network_list_with_share_servers = [{
|
||||
'id': 'fake_sn_id',
|
||||
'share_network_subnets': [{
|
||||
'id': 'fake_sns_id',
|
||||
'share_servers': [{'id': 'fake_ss_id'}]
|
||||
}]
|
||||
}]
|
||||
self.fake_share_network_list_without_share_servers = [{
|
||||
'id': 'fake_sn_id',
|
||||
'share_network_subnets': [{
|
||||
'id': 'fake_sns_id',
|
||||
'share_servers': []
|
||||
}]
|
||||
}]
|
||||
|
||||
def _stop_started_patcher(self, patcher):
|
||||
if hasattr(patcher, 'is_local'):
|
||||
patcher.stop()
|
||||
@ -163,10 +180,11 @@ class ShareApiTest(test.TestCase):
|
||||
self.mock_object(security_service.policy, 'check_policy')
|
||||
db.security_service_get = mock.Mock(return_value=new)
|
||||
db.security_service_update = mock.Mock(return_value=updated)
|
||||
fake_sns = {'id': 'fake_sns_id', 'share_servers': ['fake_ss']}
|
||||
db.share_network_get_all_by_security_service = mock.Mock(
|
||||
return_value=[{
|
||||
'id': 'fake_id',
|
||||
'share_servers': 'fake_share_server'
|
||||
'share_network_subnets': [fake_sns]
|
||||
}])
|
||||
body = {"security_service": {"name": "new"}}
|
||||
req = fakes.HTTPRequest.blank('/security_service/1')
|
||||
@ -187,10 +205,11 @@ class ShareApiTest(test.TestCase):
|
||||
self.mock_object(security_service.policy, 'check_policy')
|
||||
db.security_service_get = mock.Mock(return_value=new)
|
||||
db.security_service_update = mock.Mock(return_value=updated)
|
||||
fake_sns = {'id': 'fake_sns_id', 'share_servers': ['fake_ss']}
|
||||
db.share_network_get_all_by_security_service = mock.Mock(
|
||||
return_value=[{
|
||||
'id': 'fake_id',
|
||||
'share_servers': 'fake_share_server'
|
||||
'share_network_subnets': [fake_sns]
|
||||
}])
|
||||
body = {"security_service": {"description": "new"}}
|
||||
req = fakes.HTTPRequest.blank('/security_service/1')
|
||||
@ -209,8 +228,9 @@ class ShareApiTest(test.TestCase):
|
||||
mock.Mock())
|
||||
def test_security_service_update_invalid_keys_sh_server_exists(self):
|
||||
self.mock_object(security_service.policy, 'check_policy')
|
||||
fake_sns = {'id': 'fake_sns_id', 'share_servers': ['fake_ss']}
|
||||
db.share_network_get_all_by_security_service.return_value = [
|
||||
{'id': 'fake_id', 'share_servers': 'fake_share_servers'},
|
||||
{'id': 'fake_id', 'share_network_subnets': [fake_sns]},
|
||||
]
|
||||
db.security_service_get.return_value = self.ss_active_directory.copy()
|
||||
body = {'security_service': {'user_id': 'new_user'}}
|
||||
@ -234,8 +254,9 @@ class ShareApiTest(test.TestCase):
|
||||
mock.Mock())
|
||||
def test_security_service_update_valid_keys_sh_server_exists(self):
|
||||
self.mock_object(security_service.policy, 'check_policy')
|
||||
fake_sns = {'id': 'fake_sns_id', 'share_servers': ['fake_ss']}
|
||||
db.share_network_get_all_by_security_service.return_value = [
|
||||
{'id': 'fake_id', 'share_servers': 'fake_share_servers'},
|
||||
{'id': 'fake_id', 'share_network_subnets': [fake_sns]},
|
||||
]
|
||||
old = self.ss_active_directory.copy()
|
||||
updated = self.ss_active_directory.copy()
|
||||
@ -265,6 +286,36 @@ class ShareApiTest(test.TestCase):
|
||||
security_service.RESOURCE_NAME, 'update', old)
|
||||
])
|
||||
|
||||
@mock.patch.object(db, 'security_service_get', mock.Mock())
|
||||
def test_security_service_update_has_share_servers(self):
|
||||
db.security_service_get = mock.Mock()
|
||||
self.mock_object(
|
||||
self.controller, '_share_servers_dependent_on_sn_exist',
|
||||
mock.Mock(return_value=True))
|
||||
body = {"security_service": {"type": "ldap"}}
|
||||
|
||||
req = fakes.HTTPRequest.blank('/security_services/1')
|
||||
self.assertRaises(webob.exc.HTTPForbidden,
|
||||
self.controller.update,
|
||||
req,
|
||||
1,
|
||||
body)
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_security_service_update_share_server_dependent_exists(self,
|
||||
expected):
|
||||
req = fakes.HTTPRequest.blank('/security_services/1')
|
||||
context = req.environ['manila.context']
|
||||
db.security_service_get = mock.Mock()
|
||||
network = (self.fake_share_network_list_with_share_servers if expected
|
||||
else self.fake_share_network_list_without_share_servers)
|
||||
db.share_network_get_all_by_security_service = mock.Mock(
|
||||
return_value=network)
|
||||
|
||||
result = self.controller._share_servers_dependent_on_sn_exist(
|
||||
context, 'fake_id')
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
def test_security_service_list(self):
|
||||
db.security_service_get_all_by_project = mock.Mock(
|
||||
return_value=[self.ss_active_directory.copy()])
|
||||
|
@ -13,9 +13,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import ddt
|
||||
import mock
|
||||
from webob import exc
|
||||
|
||||
from manila.api.openstack import api_version_request as api_version
|
||||
from manila.api.v1 import share_servers
|
||||
from manila.common import constants
|
||||
from manila import context
|
||||
@ -31,23 +33,43 @@ fake_share_server_list = {
|
||||
'status': constants.STATUS_ACTIVE,
|
||||
'updated_at': None,
|
||||
'host': 'fake_host',
|
||||
'share_network_id': 'fake_sn_id',
|
||||
'share_network_name': 'fake_sn_name',
|
||||
'share_network_id': 'fake_sn_id',
|
||||
'share_network_subnet_id': 'fake_sns_id',
|
||||
'project_id': 'fake_project_id',
|
||||
'id': 'fake_server_id',
|
||||
'is_auto_deletable': False,
|
||||
'identifier': 'fake_id'
|
||||
},
|
||||
{
|
||||
'status': constants.STATUS_ERROR,
|
||||
'updated_at': None,
|
||||
'host': 'fake_host_2',
|
||||
'share_network_id': 'fake_sn_id_2',
|
||||
'share_network_name': 'fake_sn_id_2',
|
||||
'share_network_id': 'fake_sn_id_2',
|
||||
'share_network_subnet_id': 'fake_sns_id_2',
|
||||
'project_id': 'fake_project_id_2',
|
||||
'id': 'fake_server_id_2',
|
||||
'is_auto_deletable': True,
|
||||
'identifier': 'fake_id_2'
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
fake_share_network_get_list = {
|
||||
'share_networks': [
|
||||
{
|
||||
'name': 'fake_sn_name',
|
||||
'id': 'fake_sn_id',
|
||||
'project_id': 'fake_project_id',
|
||||
},
|
||||
{
|
||||
'name': None,
|
||||
'id': 'fake_sn_id_2',
|
||||
'project_id': 'fake_project_id_2',
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
fake_share_server_get_result = {
|
||||
'share_server': {
|
||||
@ -57,12 +79,15 @@ fake_share_server_get_result = {
|
||||
'host': 'fake_host',
|
||||
'share_network_name': 'fake_sn_name',
|
||||
'share_network_id': 'fake_sn_id',
|
||||
'share_network_subnet_id': 'fake_sns_id',
|
||||
'project_id': 'fake_project_id',
|
||||
'id': 'fake_server_id',
|
||||
'backend_details': {
|
||||
'fake_key_1': 'fake_value_1',
|
||||
'fake_key_2': 'fake_value_2',
|
||||
}
|
||||
},
|
||||
'is_auto_deletable': False,
|
||||
'identifier': 'fake_id'
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,13 +113,14 @@ class FakeShareServer(object):
|
||||
self.created_at = kwargs.get('created_at', None)
|
||||
self.updated_at = kwargs.get('updated_at', None)
|
||||
self.host = kwargs.get('host', 'fake_host')
|
||||
self.share_network = kwargs.get('share_network', {
|
||||
'name': 'fake_sn_name', 'id': 'fake_sn_id',
|
||||
'project_id': 'fake_project_id'})
|
||||
self.share_network_id = kwargs.get('share_network_id',
|
||||
self.share_network['id'])
|
||||
self.share_network_subnet = kwargs.get('share_network_subnet', {
|
||||
'id': 'fake_sns_id', 'share_network_id': 'fake_sn_id'})
|
||||
self.share_network_subnet_id = kwargs.get(
|
||||
'share_network_subnet_id', self.share_network_subnet['id'])
|
||||
self.status = kwargs.get('status', constants.STATUS_ACTIVE)
|
||||
self.project_id = self.share_network['project_id']
|
||||
self.project_id = 'fake_project_id'
|
||||
self.identifier = kwargs.get('identifier', 'fake_id')
|
||||
self.is_auto_deletable = kwargs.get('is_auto_deletable', False)
|
||||
self.backend_details = share_server_backend_details
|
||||
|
||||
def __getitem__(self, item):
|
||||
@ -106,10 +132,12 @@ def fake_share_server_get_all():
|
||||
FakeShareServer(),
|
||||
FakeShareServer(id='fake_server_id_2',
|
||||
host='fake_host_2',
|
||||
share_network={
|
||||
'name': None,
|
||||
'id': 'fake_sn_id_2',
|
||||
'project_id': 'fake_project_id_2'},
|
||||
share_network_subnet={
|
||||
'id': 'fake_sns_id_2',
|
||||
'share_network_id': 'fake_sn_id_2',
|
||||
},
|
||||
identifier='fake_id_2',
|
||||
is_auto_deletable=True,
|
||||
status=constants.STATUS_ERROR)
|
||||
]
|
||||
return fake_share_servers
|
||||
@ -136,15 +164,10 @@ class FakeRequestWithProjectId(FakeRequestAdmin):
|
||||
GET = {'project_id': fake_share_server_get_all()[0].project_id}
|
||||
|
||||
|
||||
class FakeRequestWithShareNetworkName(FakeRequestAdmin):
|
||||
class FakeRequestWithShareNetworkSubnetId(FakeRequestAdmin):
|
||||
GET = {
|
||||
'share_network': fake_share_server_get_all()[0].share_network['name'],
|
||||
}
|
||||
|
||||
|
||||
class FakeRequestWithShareNetworkId(FakeRequestAdmin):
|
||||
GET = {
|
||||
'share_network': fake_share_server_get_all()[0].share_network['id'],
|
||||
'share_network_subnet_id':
|
||||
fake_share_server_get_all()[0].share_network_subnet_id,
|
||||
}
|
||||
|
||||
|
||||
@ -152,6 +175,7 @@ class FakeRequestWithFakeFilter(FakeRequestAdmin):
|
||||
GET = {'fake_key': 'fake_value'}
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class ShareServerAPITest(test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
@ -163,15 +187,20 @@ class ShareServerAPITest(test.TestCase):
|
||||
self.mock_object(db_api, 'share_server_get_all',
|
||||
mock.Mock(return_value=fake_share_server_get_all()))
|
||||
|
||||
def _prepare_request(self, url, use_admin_context):
|
||||
def _prepare_request(self, url, use_admin_context,
|
||||
version=api_version._MAX_API_VERSION):
|
||||
request = fakes.HTTPRequest.blank(url,
|
||||
use_admin_context=use_admin_context)
|
||||
use_admin_context=use_admin_context,
|
||||
version=version)
|
||||
ctxt = request.environ['manila.context']
|
||||
return request, ctxt
|
||||
|
||||
def test_index_no_filters(self):
|
||||
request, ctxt = self._prepare_request(url='/v2/share-servers/',
|
||||
use_admin_context=True)
|
||||
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
||||
side_effect=[fake_share_network_get_list['share_networks'][0],
|
||||
fake_share_network_get_list['share_networks'][1]]))
|
||||
result = self.controller.index(request)
|
||||
policy.check_policy.assert_called_once_with(
|
||||
ctxt, self.resource_name, 'index')
|
||||
@ -183,6 +212,9 @@ class ShareServerAPITest(test.TestCase):
|
||||
url='/index?host=%s'
|
||||
% fake_share_server_list['share_servers'][0]['host'],
|
||||
use_admin_context=True)
|
||||
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
||||
side_effect=[fake_share_network_get_list['share_networks'][0],
|
||||
fake_share_network_get_list['share_networks'][1]]))
|
||||
result = self.controller.index(request)
|
||||
policy.check_policy.assert_called_once_with(
|
||||
ctxt, self.resource_name, 'index')
|
||||
@ -194,6 +226,9 @@ class ShareServerAPITest(test.TestCase):
|
||||
request, ctxt = self._prepare_request(url='/index?status=%s' %
|
||||
constants.STATUS_ERROR,
|
||||
use_admin_context=True)
|
||||
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
||||
side_effect=[fake_share_network_get_list['share_networks'][0],
|
||||
fake_share_network_get_list['share_networks'][1]]))
|
||||
result = self.controller.index(request)
|
||||
policy.check_policy.assert_called_once_with(
|
||||
ctxt, self.resource_name, 'index')
|
||||
@ -206,10 +241,14 @@ class ShareServerAPITest(test.TestCase):
|
||||
url='/index?project_id=%s'
|
||||
% fake_share_server_get_all()[0].project_id,
|
||||
use_admin_context=True)
|
||||
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
||||
side_effect=[fake_share_network_get_list['share_networks'][0],
|
||||
fake_share_network_get_list['share_networks'][1]]))
|
||||
result = self.controller.index(request)
|
||||
policy.check_policy.assert_called_once_with(
|
||||
ctxt, self.resource_name, 'index')
|
||||
db_api.share_server_get_all.assert_called_once_with(ctxt)
|
||||
|
||||
self.assertEqual([fake_share_server_list['share_servers'][0]],
|
||||
result['share_servers'])
|
||||
|
||||
@ -218,6 +257,9 @@ class ShareServerAPITest(test.TestCase):
|
||||
url='/index?host=%s'
|
||||
% fake_share_server_list['share_servers'][0]['host'],
|
||||
use_admin_context=True)
|
||||
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
||||
side_effect=[fake_share_network_get_list['share_networks'][0],
|
||||
fake_share_network_get_list['share_networks'][1]]))
|
||||
result = self.controller.index(request)
|
||||
policy.check_policy.assert_called_once_with(
|
||||
ctxt, self.resource_name, 'index')
|
||||
@ -228,8 +270,11 @@ class ShareServerAPITest(test.TestCase):
|
||||
def test_index_share_network_filter_by_id(self):
|
||||
request, ctxt = self._prepare_request(
|
||||
url='/index?share_network=%s'
|
||||
% fake_share_server_get_all()[0].share_network['id'],
|
||||
% fake_share_network_get_list['share_networks'][0]['id'],
|
||||
use_admin_context=True)
|
||||
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
||||
side_effect=[fake_share_network_get_list['share_networks'][0],
|
||||
fake_share_network_get_list['share_networks'][1]]))
|
||||
result = self.controller.index(request)
|
||||
policy.check_policy.assert_called_once_with(
|
||||
ctxt, self.resource_name, 'index')
|
||||
@ -240,16 +285,57 @@ class ShareServerAPITest(test.TestCase):
|
||||
def test_index_fake_filter(self):
|
||||
request, ctxt = self._prepare_request(url='/index?fake_key=fake_value',
|
||||
use_admin_context=True)
|
||||
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
||||
side_effect=[fake_share_network_get_list['share_networks'][0],
|
||||
fake_share_network_get_list['share_networks'][1]]))
|
||||
result = self.controller.index(request)
|
||||
policy.check_policy.assert_called_once_with(
|
||||
ctxt, self.resource_name, 'index')
|
||||
db_api.share_server_get_all.assert_called_once_with(ctxt)
|
||||
self.assertEqual(0, len(result['share_servers']))
|
||||
|
||||
def test_index_share_network_not_found(self):
|
||||
request, ctxt = self._prepare_request(
|
||||
url='/index?identifier=%s'
|
||||
% fake_share_server_get_all()[0].identifier,
|
||||
use_admin_context=True)
|
||||
self.mock_object(
|
||||
db_api, 'share_network_get',
|
||||
mock.Mock(side_effect=exception.ShareNetworkNotFound(
|
||||
share_network_id='fake')))
|
||||
|
||||
result = self.controller.index(request)
|
||||
db_api.share_server_get_all.assert_called_once_with(ctxt)
|
||||
policy.check_policy.assert_called_once_with(
|
||||
ctxt, self.resource_name, 'index')
|
||||
exp_share_server = fake_share_server_list['share_servers'][0].copy()
|
||||
exp_share_server['project_id'] = ''
|
||||
exp_share_server['share_network_name'] = ''
|
||||
self.assertEqual([exp_share_server],
|
||||
result['share_servers'])
|
||||
|
||||
def test_index_share_network_not_found_filter_project(self):
|
||||
request, ctxt = self._prepare_request(
|
||||
url='/index?project_id=%s'
|
||||
% fake_share_server_get_all()[0].project_id,
|
||||
use_admin_context=True)
|
||||
self.mock_object(
|
||||
db_api, 'share_network_get',
|
||||
mock.Mock(side_effect=exception.ShareNetworkNotFound(
|
||||
share_network_id='fake')))
|
||||
|
||||
result = self.controller.index(request)
|
||||
db_api.share_server_get_all.assert_called_once_with(ctxt)
|
||||
policy.check_policy.assert_called_once_with(
|
||||
ctxt, self.resource_name, 'index')
|
||||
self.assertEqual(0, len(result['share_servers']))
|
||||
|
||||
def test_show(self):
|
||||
self.mock_object(db_api, 'share_server_get',
|
||||
mock.Mock(return_value=fake_share_server_get()))
|
||||
request, ctxt = self._prepare_request('/show', use_admin_context=True)
|
||||
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
||||
return_value=fake_share_network_get_list['share_networks'][0]))
|
||||
result = self.controller.show(
|
||||
request,
|
||||
fake_share_server_get_result['share_server']['id'])
|
||||
@ -260,6 +346,36 @@ class ShareServerAPITest(test.TestCase):
|
||||
self.assertEqual(fake_share_server_get_result['share_server'],
|
||||
result['share_server'])
|
||||
|
||||
@ddt.data(
|
||||
{'share_server_side_effect': exception.ShareServerNotFound(
|
||||
share_server_id="foo"),
|
||||
'share_net_side_effect': mock.Mock()},
|
||||
{'share_server_side_effect': mock.Mock(
|
||||
return_value=fake_share_server_get()),
|
||||
'share_net_side_effect': exception.ShareNetworkNotFound(
|
||||
share_network_id="foo")})
|
||||
@ddt.unpack
|
||||
def test_show_server_not_found(self, share_server_side_effect,
|
||||
share_net_side_effect):
|
||||
self.mock_object(db_api, 'share_server_get',
|
||||
mock.Mock(side_effect=share_server_side_effect))
|
||||
request, ctxt = self._prepare_request('/show', use_admin_context=True)
|
||||
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
||||
side_effect=share_net_side_effect))
|
||||
self.assertRaises(
|
||||
exc.HTTPNotFound, self.controller.show, request,
|
||||
fake_share_server_get_result['share_server']['id'])
|
||||
|
||||
policy.check_policy.assert_called_once_with(
|
||||
ctxt, self.resource_name, 'show')
|
||||
db_api.share_server_get.assert_called_once_with(
|
||||
ctxt, fake_share_server_get_result['share_server']['id'])
|
||||
if isinstance(share_net_side_effect, exception.ShareNetworkNotFound):
|
||||
exp_share_net_id = (fake_share_server_get()
|
||||
.share_network_subnet['share_network_id'])
|
||||
db_api.share_network_get.assert_called_once_with(
|
||||
ctxt, exp_share_net_id)
|
||||
|
||||
def test_details(self):
|
||||
self.mock_object(db_api, 'share_server_get',
|
||||
mock.Mock(return_value=fake_share_server_get()))
|
||||
@ -274,6 +390,21 @@ class ShareServerAPITest(test.TestCase):
|
||||
self.assertEqual(fake_share_server_backend_details_get_result,
|
||||
result)
|
||||
|
||||
def test_details_share_server_not_found(self):
|
||||
share_server_id = 'fake'
|
||||
self.mock_object(
|
||||
db_api, 'share_server_get',
|
||||
mock.Mock(side_effect=exception.ShareServerNotFound(
|
||||
share_server_id=share_server_id)))
|
||||
self.assertRaises(exc.HTTPNotFound,
|
||||
self.controller.details,
|
||||
FakeRequestAdmin,
|
||||
share_server_id)
|
||||
policy.check_policy.assert_called_once_with(
|
||||
CONTEXT, self.resource_name, 'details')
|
||||
db_api.share_server_get.assert_called_once_with(
|
||||
CONTEXT, share_server_id)
|
||||
|
||||
def test_delete_active_server(self):
|
||||
share_server = FakeShareServer(status=constants.STATUS_ACTIVE)
|
||||
self.mock_object(db_api, 'share_server_get',
|
||||
|
@ -239,6 +239,9 @@ class ShareAPITest(test.TestCase):
|
||||
self.mock_object(share_api.API, 'create', create_mock)
|
||||
self.mock_object(share_api.API, 'get_share_network', mock.Mock(
|
||||
return_value={'id': 'fakenetid'}))
|
||||
self.mock_object(
|
||||
db, 'share_network_subnet_get_by_availability_zone_id',
|
||||
mock.Mock(return_value={'id': 'fakesubnetid'}))
|
||||
|
||||
body = {"share": copy.deepcopy(shr)}
|
||||
req = fakes.HTTPRequest.blank('/shares')
|
||||
@ -249,6 +252,7 @@ class ShareAPITest(test.TestCase):
|
||||
expected = self._get_expected_share_detailed_response(shr)
|
||||
expected['share'].pop('snapshot_support')
|
||||
self.assertEqual(expected, res_dict)
|
||||
# pylint: disable=unsubscriptable-object
|
||||
self.assertEqual("fakenetid",
|
||||
create_mock.call_args[1]['share_network_id'])
|
||||
|
||||
@ -312,6 +316,8 @@ class ShareAPITest(test.TestCase):
|
||||
return_value=parent_share))
|
||||
self.mock_object(share_api.API, 'get_share_network', mock.Mock(
|
||||
return_value={'id': parent_share_net}))
|
||||
self.mock_object(
|
||||
db, 'share_network_subnet_get_by_availability_zone_id')
|
||||
|
||||
body = {"share": copy.deepcopy(shr)}
|
||||
req = fakes.HTTPRequest.blank('/shares')
|
||||
@ -323,6 +329,7 @@ class ShareAPITest(test.TestCase):
|
||||
expected = self._get_expected_share_detailed_response(shr)
|
||||
expected['share'].pop('snapshot_support')
|
||||
self.assertEqual(expected, res_dict)
|
||||
# pylint: disable=unsubscriptable-object
|
||||
self.assertEqual(parent_share_net,
|
||||
create_mock.call_args[1]['share_network_id'])
|
||||
|
||||
@ -356,6 +363,8 @@ class ShareAPITest(test.TestCase):
|
||||
return_value=parent_share))
|
||||
self.mock_object(share_api.API, 'get_share_network', mock.Mock(
|
||||
return_value={'id': parent_share_net}))
|
||||
self.mock_object(
|
||||
db, 'share_network_subnet_get_by_availability_zone_id')
|
||||
|
||||
body = {"share": copy.deepcopy(shr)}
|
||||
req = fakes.HTTPRequest.blank('/shares')
|
||||
@ -367,6 +376,7 @@ class ShareAPITest(test.TestCase):
|
||||
expected = self._get_expected_share_detailed_response(shr)
|
||||
expected['share'].pop('snapshot_support')
|
||||
self.assertEqual(expected, res_dict)
|
||||
# pylint: disable=unsubscriptable-object
|
||||
self.assertEqual(parent_share_net,
|
||||
create_mock.call_args[1]['share_network_id'])
|
||||
|
||||
@ -425,6 +435,8 @@ class ShareAPITest(test.TestCase):
|
||||
return_value=parent_share))
|
||||
self.mock_object(share_api.API, 'get_share_network', mock.Mock(
|
||||
return_value={'id': parent_share_net}))
|
||||
self.mock_object(
|
||||
db, 'share_network_subnet_get_by_availability_zone_id')
|
||||
|
||||
body = {"share": copy.deepcopy(shr)}
|
||||
req = fakes.HTTPRequest.blank('/shares', version=microversion)
|
||||
@ -436,6 +448,7 @@ class ShareAPITest(test.TestCase):
|
||||
expected = self._get_expected_share_detailed_response(shr)
|
||||
expected['share'].pop('snapshot_support')
|
||||
self.assertDictEqual(expected, res_dict)
|
||||
# pylint: disable=unsubscriptable-object
|
||||
self.assertEqual(parent_share_net,
|
||||
create_mock.call_args[1]['share_network_id'])
|
||||
|
||||
@ -478,6 +491,28 @@ class ShareAPITest(test.TestCase):
|
||||
req,
|
||||
body)
|
||||
|
||||
@ddt.data((exception.ShareNetworkNotFound(share_network_id='fake'),
|
||||
webob.exc.HTTPNotFound),
|
||||
(mock.Mock(), webob.exc.HTTPBadRequest))
|
||||
@ddt.unpack
|
||||
def test_share_create_invalid_subnet(self, share_network_side_effect,
|
||||
exception_to_raise):
|
||||
fake_share_with_sn = copy.deepcopy(self.share)
|
||||
fake_share_with_sn['share_network_id'] = 'fakenetid'
|
||||
self.mock_object(db, 'share_network_get',
|
||||
mock.Mock(side_effect=share_network_side_effect))
|
||||
self.mock_object(
|
||||
db, 'share_network_subnet_get_by_availability_zone_id',
|
||||
mock.Mock(return_value=None))
|
||||
|
||||
body = {"share": fake_share_with_sn}
|
||||
|
||||
req = fakes.HTTPRequest.blank('/shares')
|
||||
self.assertRaises(exception_to_raise,
|
||||
self.controller.create,
|
||||
req,
|
||||
body)
|
||||
|
||||
def test_share_show(self):
|
||||
req = fakes.HTTPRequest.blank('/shares/1')
|
||||
expected = self._get_expected_share_detailed_response()
|
||||
|
481
manila/tests/api/v2/test_share_network_subnets.py
Normal file
481
manila/tests/api/v2/test_share_network_subnets.py
Normal file
@ -0,0 +1,481 @@
|
||||
# Copyright 2019 NetApp, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
import ddt
|
||||
import mock
|
||||
from oslo_db import exception as db_exception
|
||||
|
||||
from manila.api import common
|
||||
from manila.api.v2 import share_network_subnets
|
||||
from manila.db import api as db_api
|
||||
from manila import exception
|
||||
from manila import policy
|
||||
from manila import test
|
||||
from manila.tests.api import fakes
|
||||
from manila.tests import db_utils
|
||||
from webob import exc
|
||||
|
||||
fake_az = {
|
||||
'id': 'ae525e12-07e8-4ddc-a2fd-4a89ad4a65ff',
|
||||
'name': 'fake_az_name'
|
||||
}
|
||||
|
||||
fake_default_subnet = {
|
||||
'neutron_net_id': 'fake_nn_id',
|
||||
'neutron_subnet_id': 'fake_nsn_id',
|
||||
'availability_zone_id': None
|
||||
}
|
||||
|
||||
fake_subnet_with_az = {
|
||||
'neutron_net_id': 'fake_nn_id',
|
||||
'neutron_subnet_id': 'fake_nsn_id',
|
||||
'availability_zone_id': 'fake_az_id'
|
||||
}
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class ShareNetworkSubnetControllerTest(test.TestCase):
|
||||
"""Share network subnet api test"""
|
||||
|
||||
def setUp(self):
|
||||
super(ShareNetworkSubnetControllerTest, self).setUp()
|
||||
self.controller = share_network_subnets.ShareNetworkSubnetController()
|
||||
self.mock_policy_check = self.mock_object(
|
||||
policy, 'check_policy', mock.Mock(return_value=True))
|
||||
self.resource_name = self.controller.resource_name
|
||||
self.mock_az_get = self.mock_object(db_api, 'availability_zone_get',
|
||||
mock.Mock(return_value=fake_az))
|
||||
self.share_network = db_utils.create_share_network(
|
||||
name='fake_network', id='fake_sn_id')
|
||||
self.share_server = db_utils.create_share_server(
|
||||
share_network_subnet_id='fake_sns_id')
|
||||
self.subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id=self.share_network['id'])
|
||||
self.share = db_utils.create_share()
|
||||
|
||||
def test_share_network_subnet_delete(self):
|
||||
req = fakes.HTTPRequest.blank('/subnets/%s' % self.subnet['id'],
|
||||
version="2.51")
|
||||
context = req.environ['manila.context']
|
||||
|
||||
mock_sns_get = self.mock_object(
|
||||
db_api, 'share_network_subnet_get',
|
||||
mock.Mock(return_value=self.subnet))
|
||||
mock_all_get_all_shares_by_ss = self.mock_object(
|
||||
db_api, 'share_instances_get_all_by_share_server',
|
||||
mock.Mock(return_value=[]))
|
||||
mock_all_ss_are_auto_deletable = self.mock_object(
|
||||
self.controller, '_all_share_servers_are_auto_deletable',
|
||||
mock.Mock(return_value=True))
|
||||
mock_delete_share_server = self.mock_object(
|
||||
self.controller.share_rpcapi, 'delete_share_server')
|
||||
mock_subnet_delete = self.mock_object(db_api,
|
||||
'share_network_subnet_delete')
|
||||
|
||||
result = self.controller.delete(req, self.share_network['id'],
|
||||
self.subnet['id'])
|
||||
|
||||
self.assertEqual(202, result.status_int)
|
||||
mock_sns_get.assert_called_once_with(
|
||||
context, self.subnet['id'])
|
||||
mock_all_get_all_shares_by_ss.assert_called_once_with(
|
||||
context, self.subnet['share_servers'][0].id
|
||||
)
|
||||
mock_all_ss_are_auto_deletable.assert_called_once_with(
|
||||
self.subnet)
|
||||
mock_delete_share_server.assert_called_once_with(
|
||||
context, self.subnet['share_servers'][0])
|
||||
mock_subnet_delete.assert_called_once_with(
|
||||
context, self.subnet['id'])
|
||||
policy.check_policy.assert_called_once_with(
|
||||
context, self.resource_name, 'delete')
|
||||
|
||||
def test_share_network_subnet_delete_network_not_found(self):
|
||||
req = fakes.HTTPRequest.blank('/subnets/%s' % self.subnet['id'],
|
||||
version="2.51")
|
||||
context = req.environ['manila.context']
|
||||
|
||||
mock_sn_get = self.mock_object(
|
||||
db_api, 'share_network_get',
|
||||
mock.Mock(side_effect=exception.ShareNetworkNotFound(
|
||||
share_network_id=self.share_network['id']
|
||||
)))
|
||||
|
||||
self.assertRaises(exc.HTTPNotFound,
|
||||
self.controller.delete,
|
||||
req,
|
||||
self.share_network['id'],
|
||||
self.subnet['id'])
|
||||
mock_sn_get.assert_called_once_with(
|
||||
context, self.share_network['id'])
|
||||
self.mock_policy_check.assert_called_once_with(
|
||||
context, self.resource_name, 'delete')
|
||||
|
||||
def test_share_network_subnet_delete_subnet_not_found(self):
|
||||
req = fakes.HTTPRequest.blank('/subnets/%s' % self.subnet['id'],
|
||||
version="2.51")
|
||||
context = req.environ['manila.context']
|
||||
|
||||
mock_sns_get = self.mock_object(
|
||||
db_api, 'share_network_subnet_get',
|
||||
mock.Mock(side_effect=exception.ShareNetworkSubnetNotFound(
|
||||
share_network_subnet_id=self.subnet['id']
|
||||
)))
|
||||
|
||||
self.assertRaises(exc.HTTPNotFound,
|
||||
self.controller.delete,
|
||||
req,
|
||||
self.share_network['id'],
|
||||
self.subnet['id'])
|
||||
mock_sns_get.assert_called_once_with(
|
||||
context, self.subnet['id'])
|
||||
self.mock_policy_check.assert_called_once_with(
|
||||
context, self.resource_name, 'delete')
|
||||
|
||||
def test_delete_subnet_with_share_servers_fail(self):
|
||||
req = fakes.HTTPRequest.blank('/subnets/%s' % self.subnet['id'],
|
||||
version="2.51")
|
||||
context = req.environ['manila.context']
|
||||
|
||||
mock_sns_get = self.mock_object(
|
||||
db_api, 'share_network_subnet_get',
|
||||
mock.Mock(return_value=self.subnet))
|
||||
mock_all_get_all_shares_by_ss = self.mock_object(
|
||||
db_api, 'share_instances_get_all_by_share_server',
|
||||
mock.Mock(return_value=[]))
|
||||
mock_all_ss_are_auto_deletable = self.mock_object(
|
||||
self.controller, '_all_share_servers_are_auto_deletable',
|
||||
mock.Mock(return_value=False))
|
||||
|
||||
self.assertRaises(exc.HTTPConflict,
|
||||
self.controller.delete,
|
||||
req,
|
||||
self.share_network['id'],
|
||||
self.subnet['id'])
|
||||
|
||||
mock_sns_get.assert_called_once_with(
|
||||
context, self.subnet['id'])
|
||||
mock_all_get_all_shares_by_ss.assert_called_once_with(
|
||||
context, self.subnet['share_servers'][0].id
|
||||
)
|
||||
mock_all_ss_are_auto_deletable.assert_called_once_with(
|
||||
self.subnet
|
||||
)
|
||||
self.mock_policy_check.assert_called_once_with(
|
||||
context, self.resource_name, 'delete')
|
||||
|
||||
def test_delete_subnet_with_shares_fail(self):
|
||||
req = fakes.HTTPRequest.blank('/subnets/%s' % self.subnet['id'],
|
||||
version="2.51")
|
||||
context = req.environ['manila.context']
|
||||
|
||||
mock_sns_get = self.mock_object(
|
||||
db_api, 'share_network_subnet_get',
|
||||
mock.Mock(return_value=self.subnet))
|
||||
mock_all_get_all_shares_by_ss = self.mock_object(
|
||||
db_api, 'share_instances_get_all_by_share_server',
|
||||
mock.Mock(return_value=[self.share]))
|
||||
|
||||
self.assertRaises(exc.HTTPConflict,
|
||||
self.controller.delete,
|
||||
req,
|
||||
self.share_network['id'],
|
||||
self.subnet['id'])
|
||||
|
||||
mock_sns_get.assert_called_once_with(
|
||||
context, self.subnet['id'])
|
||||
mock_all_get_all_shares_by_ss.assert_called_once_with(
|
||||
context, self.subnet['share_servers'][0].id
|
||||
)
|
||||
self.mock_policy_check.assert_called_once_with(
|
||||
context, self.resource_name, 'delete')
|
||||
|
||||
@ddt.data((None, fake_default_subnet, None),
|
||||
(fake_az, None, fake_subnet_with_az))
|
||||
@ddt.unpack
|
||||
def test__validate_subnet(self, az, default_subnet, subnet_az):
|
||||
req = fakes.HTTPRequest.blank('/subnets', version='2.51')
|
||||
context = req.environ['manila.context']
|
||||
|
||||
mock_get_default_sns = self.mock_object(
|
||||
db_api, 'share_network_subnet_get_default_subnet',
|
||||
mock.Mock(return_value=default_subnet))
|
||||
mock_get_subnet_by_az = self.mock_object(
|
||||
db_api, 'share_network_subnet_get_by_availability_zone_id',
|
||||
mock.Mock(return_value=subnet_az))
|
||||
|
||||
self.assertRaises(exc.HTTPConflict,
|
||||
self.controller._validate_subnet,
|
||||
context,
|
||||
self.share_network['id'],
|
||||
az)
|
||||
if az:
|
||||
mock_get_subnet_by_az.assert_called_once_with(
|
||||
context, self.share_network['id'], az['id'])
|
||||
mock_get_default_sns.assert_not_called()
|
||||
else:
|
||||
mock_get_default_sns.assert_called_once_with(
|
||||
context, self.share_network['id'])
|
||||
mock_get_subnet_by_az.assert_not_called()
|
||||
|
||||
def _setup_create_test_request_body(self):
|
||||
body = {
|
||||
'share_network_id': self.share_network['id'],
|
||||
'availability_zone': fake_az['name'],
|
||||
'neutron_net_id': 'fake_nn_id',
|
||||
'neutron_subnet_id': 'fake_nsn_id'
|
||||
}
|
||||
return body
|
||||
|
||||
def test_subnet_create(self):
|
||||
req = fakes.HTTPRequest.blank('/subnets', version="2.51")
|
||||
context = req.environ['manila.context']
|
||||
body = {
|
||||
'share-network-subnet': self._setup_create_test_request_body()
|
||||
}
|
||||
sn_id = body['share-network-subnet']['share_network_id']
|
||||
|
||||
expected_result = copy.deepcopy(body)
|
||||
expected_result['share-network-subnet']['id'] = self.subnet['id']
|
||||
mock_check_net_and_subnet_id = self.mock_object(
|
||||
common, 'check_net_id_and_subnet_id')
|
||||
mock_validate_subnet = self.mock_object(
|
||||
self.controller, '_validate_subnet')
|
||||
mock_subnet_create = self.mock_object(
|
||||
db_api, 'share_network_subnet_create',
|
||||
mock.Mock(return_value=self.subnet))
|
||||
|
||||
self.controller.create(
|
||||
req, body['share-network-subnet']['share_network_id'], body)
|
||||
|
||||
mock_check_net_and_subnet_id.assert_called_once_with(
|
||||
body['share-network-subnet'])
|
||||
mock_validate_subnet.assert_called_once_with(
|
||||
context, sn_id, az=fake_az)
|
||||
mock_subnet_create.assert_called_once_with(
|
||||
context, body['share-network-subnet'])
|
||||
|
||||
def test_subnet_create_share_network_not_found(self):
|
||||
fake_sn_id = 'fake_id'
|
||||
req = fakes.HTTPRequest.blank('/subnets', version="2.51")
|
||||
context = req.environ['manila.context']
|
||||
body = {
|
||||
'share-network-subnet': self._setup_create_test_request_body()
|
||||
}
|
||||
mock_sn_get = self.mock_object(
|
||||
db_api, 'share_network_get',
|
||||
mock.Mock(side_effect=exception.ShareNetworkNotFound(
|
||||
share_network_id=fake_sn_id)))
|
||||
|
||||
self.assertRaises(exc.HTTPNotFound,
|
||||
self.controller.create,
|
||||
req,
|
||||
fake_sn_id,
|
||||
body)
|
||||
mock_sn_get.assert_called_once_with(context, fake_sn_id)
|
||||
|
||||
def test_subnet_create_az_not_found(self):
|
||||
fake_sn_id = 'fake_id'
|
||||
req = fakes.HTTPRequest.blank('/subnets', version="2.51")
|
||||
context = req.environ['manila.context']
|
||||
body = {
|
||||
'share-network-subnet': self._setup_create_test_request_body()
|
||||
}
|
||||
mock_sn_get = self.mock_object(db_api, 'share_network_get')
|
||||
mock_az_get = self.mock_object(
|
||||
db_api, 'availability_zone_get',
|
||||
mock.Mock(side_effect=exception.AvailabilityZoneNotFound(id='')))
|
||||
|
||||
expected_az = body['share-network-subnet']['availability_zone']
|
||||
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.controller.create,
|
||||
req,
|
||||
fake_sn_id,
|
||||
body)
|
||||
mock_sn_get.assert_called_once_with(context, fake_sn_id)
|
||||
mock_az_get.assert_called_once_with(
|
||||
context, expected_az)
|
||||
|
||||
def test_subnet_create_subnet_default_or_same_az_exists(self):
|
||||
fake_sn_id = 'fake_id'
|
||||
req = fakes.HTTPRequest.blank('/subnets', version="2.51")
|
||||
context = req.environ['manila.context']
|
||||
body = {
|
||||
'share-network-subnet': self._setup_create_test_request_body()
|
||||
}
|
||||
mock_sn_get = self.mock_object(db_api, 'share_network_get')
|
||||
mock__validate_subnet = self.mock_object(
|
||||
self.controller, '_validate_subnet',
|
||||
mock.Mock(side_effect=exc.HTTPConflict(''))
|
||||
)
|
||||
expected_az = body['share-network-subnet']['availability_zone']
|
||||
|
||||
self.assertRaises(exc.HTTPConflict,
|
||||
self.controller.create,
|
||||
req,
|
||||
fake_sn_id,
|
||||
body)
|
||||
mock_sn_get.assert_called_once_with(context, fake_sn_id)
|
||||
self.mock_az_get.assert_called_once_with(context, expected_az)
|
||||
mock__validate_subnet.assert_called_once_with(
|
||||
context, fake_sn_id, az=fake_az)
|
||||
|
||||
def test_subnet_create_subnet_db_error(self):
|
||||
fake_sn_id = 'fake_sn_id'
|
||||
req = fakes.HTTPRequest.blank('/subnets', version="2.51")
|
||||
context = req.environ['manila.context']
|
||||
body = {
|
||||
'share-network-subnet': self._setup_create_test_request_body()
|
||||
}
|
||||
mock_sn_get = self.mock_object(db_api, 'share_network_get')
|
||||
mock__validate_subnet = self.mock_object(
|
||||
self.controller, '_validate_subnet')
|
||||
mock_db_subnet_create = self.mock_object(
|
||||
db_api, 'share_network_subnet_create',
|
||||
mock.Mock(side_effect=db_exception.DBError()))
|
||||
expected_data = copy.deepcopy(body['share-network-subnet'])
|
||||
expected_data['availability_zone_id'] = fake_az['id']
|
||||
expected_data.pop('availability_zone')
|
||||
|
||||
self.assertRaises(exc.HTTPInternalServerError,
|
||||
self.controller.create,
|
||||
req,
|
||||
fake_sn_id,
|
||||
body)
|
||||
|
||||
mock_sn_get.assert_called_once_with(context, fake_sn_id)
|
||||
self.mock_az_get.assert_called_once_with(context, fake_az['name'])
|
||||
mock__validate_subnet.assert_called_once_with(
|
||||
context, fake_sn_id, az=fake_az)
|
||||
mock_db_subnet_create.assert_called_once_with(
|
||||
context, expected_data
|
||||
)
|
||||
|
||||
def test_show_subnet(self):
|
||||
subnet = db_utils.create_share_network_subnet(
|
||||
id='fake_sns_2', share_network_id=self.share_network['id'])
|
||||
expected_result = {
|
||||
'share_network_subnet': {
|
||||
"created_at": subnet['created_at'],
|
||||
"id": subnet['id'],
|
||||
"share_network_id": subnet['share_network_id'],
|
||||
"share_network_name": self.share_network['name'],
|
||||
"availability_zone": subnet['availability_zone'],
|
||||
"segmentation_id": subnet['segmentation_id'],
|
||||
"neutron_subnet_id": subnet['neutron_subnet_id'],
|
||||
"updated_at": subnet['updated_at'],
|
||||
"neutron_net_id": subnet['neutron_net_id'],
|
||||
"ip_version": subnet['ip_version'],
|
||||
"cidr": subnet['cidr'],
|
||||
"network_type": subnet['network_type'],
|
||||
"gateway": subnet['gateway'],
|
||||
"mtu": subnet['mtu'],
|
||||
}
|
||||
}
|
||||
req = fakes.HTTPRequest.blank('/subnets/%s' % subnet['id'],
|
||||
version="2.51")
|
||||
context = req.environ['manila.context']
|
||||
mock_sn_get = self.mock_object(
|
||||
db_api, 'share_network_get', mock.Mock(
|
||||
return_value=self.share_network))
|
||||
mock_sns_get = self.mock_object(
|
||||
db_api, 'share_network_subnet_get', mock.Mock(
|
||||
return_value=subnet))
|
||||
|
||||
result = self.controller.show(req, self.share_network['id'],
|
||||
subnet['id'])
|
||||
|
||||
self.assertEqual(expected_result, result)
|
||||
mock_sn_get.assert_called_once_with(context, self.share_network['id'])
|
||||
mock_sns_get.assert_called_once_with(context, subnet['id'])
|
||||
|
||||
@ddt.data(
|
||||
(mock.Mock(side_effect=exception.ShareNetworkNotFound(
|
||||
share_network_id='fake_net_id')), None),
|
||||
(mock.Mock(), mock.Mock(
|
||||
side_effect=exception.ShareNetworkSubnetNotFound(
|
||||
share_network_subnet_id='fake_subnet_id'))))
|
||||
@ddt.unpack
|
||||
def test_show_subnet_not_found(self, sn_get_side_effect,
|
||||
sns_get_side_effect):
|
||||
req = fakes.HTTPRequest.blank('/subnets/%s' % self.subnet['id'],
|
||||
version="2.51")
|
||||
context = req.environ['manila.context']
|
||||
|
||||
mock_sn_get = self.mock_object(
|
||||
db_api, 'share_network_get', sn_get_side_effect)
|
||||
mock_sns_get = self.mock_object(
|
||||
db_api, 'share_network_subnet_get', sns_get_side_effect)
|
||||
|
||||
self.assertRaises(exc.HTTPNotFound,
|
||||
self.controller.show,
|
||||
req,
|
||||
self.share_network['id'],
|
||||
self.subnet['id'])
|
||||
mock_sn_get.assert_called_once_with(context, self.share_network['id'])
|
||||
if sns_get_side_effect:
|
||||
mock_sns_get.assert_called_once_with(context, self.subnet['id'])
|
||||
|
||||
def test_list_subnet(self):
|
||||
share_network_id = 'fake_id'
|
||||
subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id=share_network_id, id='fake_id')
|
||||
fake_sn = db_utils.create_share_network(id=share_network_id)
|
||||
expected_result = {
|
||||
'share_network_subnets': [{
|
||||
"created_at": subnet['created_at'],
|
||||
"id": subnet['id'],
|
||||
"share_network_id": subnet['id'],
|
||||
"share_network_name": fake_sn["name"],
|
||||
"availability_zone": subnet['availability_zone'],
|
||||
"segmentation_id": subnet['segmentation_id'],
|
||||
"neutron_subnet_id": subnet['neutron_subnet_id'],
|
||||
"updated_at": subnet['updated_at'],
|
||||
"neutron_net_id": subnet['neutron_net_id'],
|
||||
"ip_version": subnet['ip_version'],
|
||||
"cidr": subnet['cidr'],
|
||||
"network_type": subnet['network_type'],
|
||||
"gateway": subnet['gateway'],
|
||||
"mtu": subnet['mtu'],
|
||||
}]
|
||||
}
|
||||
|
||||
req = fakes.HTTPRequest.blank('/subnets/', version="2.51")
|
||||
context = req.environ['manila.context']
|
||||
mock_sn_get = self.mock_object(
|
||||
db_api, 'share_network_get', mock.Mock(
|
||||
return_value=fake_sn))
|
||||
|
||||
result = self.controller.index(req, self.share_network['id'])
|
||||
|
||||
self.assertEqual(expected_result, result)
|
||||
mock_sn_get.assert_called_once_with(context, self.share_network['id'])
|
||||
|
||||
def test_list_subnet_share_network_not_found(self):
|
||||
req = fakes.HTTPRequest.blank('/subnets/', version="2.51")
|
||||
context = req.environ['manila.context']
|
||||
|
||||
mock_sn_get = self.mock_object(
|
||||
db_api, 'share_network_get', mock.Mock(
|
||||
side_effect=exception.ShareNetworkNotFound(
|
||||
share_network_id=self.share_network['id'])))
|
||||
|
||||
self.assertRaises(exc.HTTPNotFound,
|
||||
self.controller.index,
|
||||
req,
|
||||
self.share_network['id'])
|
||||
mock_sn_get.assert_called_once_with(context, self.share_network['id'])
|
@ -13,7 +13,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
import ddt
|
||||
from manila.api import common
|
||||
import mock
|
||||
from oslo_db import exception as db_exception
|
||||
from oslo_utils import timeutils
|
||||
@ -29,23 +31,32 @@ from manila import test
|
||||
from manila.tests.api import fakes
|
||||
|
||||
|
||||
fake_share_network = {
|
||||
'id': 'fake network id',
|
||||
'project_id': 'fake project',
|
||||
'created_at': timeutils.parse_strtime('2002-02-02', fmt="%Y-%m-%d"),
|
||||
'updated_at': None,
|
||||
fake_share_network_subnet = {
|
||||
'id': 'fake subnet id',
|
||||
'neutron_net_id': 'fake net id',
|
||||
'neutron_subnet_id': 'fake subnet id',
|
||||
'network_type': 'vlan',
|
||||
'segmentation_id': 1000,
|
||||
'cidr': '10.0.0.0/24',
|
||||
'ip_version': 4,
|
||||
'share_network_id': 'fake network id',
|
||||
'availability_zone_id': None,
|
||||
'share_servers': [],
|
||||
'availability_zone': []
|
||||
}
|
||||
|
||||
fake_share_network = {
|
||||
'id': 'fake network id',
|
||||
'project_id': 'fake project',
|
||||
'created_at': timeutils.parse_strtime('2002-02-02', fmt="%Y-%m-%d"),
|
||||
'updated_at': None,
|
||||
'name': 'fake name',
|
||||
'description': 'fake description',
|
||||
'share_servers': [],
|
||||
'security_services': []
|
||||
'security_services': [],
|
||||
'share_network_subnets': []
|
||||
}
|
||||
|
||||
|
||||
fake_share_network_shortened = {
|
||||
'id': 'fake network id',
|
||||
'name': 'fake name',
|
||||
@ -56,15 +67,9 @@ fake_share_network_with_ss = {
|
||||
'project_id': 'fake',
|
||||
'created_at': timeutils.parse_strtime('2001-01-01', fmt="%Y-%m-%d"),
|
||||
'updated_at': None,
|
||||
'neutron_net_id': '1111',
|
||||
'neutron_subnet_id': '2222',
|
||||
'network_type': 'local',
|
||||
'segmentation_id': 2000,
|
||||
'cidr': '8.0.0.0/12',
|
||||
'ip_version': 6,
|
||||
'name': 'test-sn',
|
||||
'description': 'fake description',
|
||||
'share_servers': [],
|
||||
'share_network_subnets': [],
|
||||
'security_services': [{'id': 'fake-ss-id'}]
|
||||
}
|
||||
|
||||
@ -95,42 +100,63 @@ class ShareNetworkAPITest(test.TestCase):
|
||||
self.assertEqual(share_nw['project_id'], view['project_id'])
|
||||
self.assertEqual(share_nw['created_at'], view['created_at'])
|
||||
self.assertEqual(share_nw['updated_at'], view['updated_at'])
|
||||
self.assertEqual(share_nw['neutron_net_id'],
|
||||
view['neutron_net_id'])
|
||||
self.assertEqual(share_nw['neutron_subnet_id'],
|
||||
view['neutron_subnet_id'])
|
||||
self.assertEqual(share_nw['network_type'], view['network_type'])
|
||||
self.assertEqual(share_nw['segmentation_id'],
|
||||
view['segmentation_id'])
|
||||
self.assertEqual(share_nw['cidr'], view['cidr'])
|
||||
self.assertEqual(share_nw['ip_version'], view['ip_version'])
|
||||
self.assertEqual(share_nw['name'], view['name'])
|
||||
self.assertEqual(share_nw['description'], view['description'])
|
||||
|
||||
self.assertEqual(share_nw['created_at'], view['created_at'])
|
||||
self.assertEqual(share_nw['updated_at'], view['updated_at'])
|
||||
self.assertNotIn('shares', view)
|
||||
self.assertNotIn('network_allocations', view)
|
||||
self.assertNotIn('security_services', view)
|
||||
|
||||
@ddt.data(
|
||||
{'neutron_net_id': 'fake_neutron_net_id'},
|
||||
{'neutron_subnet_id': 'fake_neutron_subnet_id'},
|
||||
{'neutron_net_id': 'fake', 'neutron_subnet_id': 'fake'})
|
||||
def test_create_valid_cases(self, data):
|
||||
def _setup_body_for_create_test(self, data):
|
||||
data.update({'user_id': 'fake_user_id'})
|
||||
body = {share_networks.RESOURCE_NAME: data}
|
||||
return body
|
||||
|
||||
@ddt.data(
|
||||
{'neutron_net_id': 'fake', 'neutron_subnet_id': 'fake'})
|
||||
def test_create_valid_cases(self, data):
|
||||
body = self._setup_body_for_create_test(data)
|
||||
result = self.controller.create(self.req, body)
|
||||
data.pop('user_id', None)
|
||||
for k, v in data.items():
|
||||
self.assertIn(data[k], result['share_network'][k])
|
||||
|
||||
@ddt.data(
|
||||
{'neutron_net_id': 'fake', 'neutron_subnet_id': 'fake',
|
||||
'availability_zone': 'fake'})
|
||||
def test_create_valid_cases_upper_2_50(self, data):
|
||||
req = fakes.HTTPRequest.blank('/share-networks', version="2.51")
|
||||
context = req.environ['manila.context']
|
||||
body = self._setup_body_for_create_test(data)
|
||||
fake_az = {
|
||||
'name': 'fake',
|
||||
'id': 'fake_id'
|
||||
}
|
||||
self.mock_object(db_api, 'availability_zone_get',
|
||||
mock.Mock(return_value=fake_az))
|
||||
|
||||
result = self.controller.create(req, body)
|
||||
result_subnet = result['share_network']['share_network_subnets'][0]
|
||||
data.pop('user_id', None)
|
||||
data.pop('project_id', None)
|
||||
data.pop('availability_zone_id', None)
|
||||
data.pop('id', None)
|
||||
data['availability_zone'] = result_subnet['availability_zone']
|
||||
|
||||
for k, v in data.items():
|
||||
self.assertIn(k, result_subnet.keys())
|
||||
|
||||
db_api.availability_zone_get.assert_called_once_with(
|
||||
context, fake_az['name']
|
||||
)
|
||||
|
||||
@ddt.data(
|
||||
{'nova_net_id': 'foo', 'neutron_net_id': 'bar'},
|
||||
{'nova_net_id': 'foo', 'neutron_subnet_id': 'quuz'},
|
||||
{'nova_net_id': 'foo', 'neutron_net_id': 'bar',
|
||||
'neutron_subnet_id': 'quuz'},
|
||||
{'nova_net_id': 'fake_nova_net_id'})
|
||||
{'nova_net_id': 'fake_nova_net_id'},
|
||||
{'neutron_net_id': 'bar'},
|
||||
{'neutron_subnet_id': 'quuz'})
|
||||
def test_create_invalid_cases(self, data):
|
||||
data.update({'user_id': 'fake_user_id'})
|
||||
body = {share_networks.RESOURCE_NAME: data}
|
||||
@ -138,9 +164,9 @@ class ShareNetworkAPITest(test.TestCase):
|
||||
webob_exc.HTTPBadRequest, self.controller.create, self.req, body)
|
||||
|
||||
@ddt.data(
|
||||
{'neutron_net_id': 'fake_neutron_net_id'},
|
||||
{'neutron_subnet_id': 'fake_neutron_subnet_id'},
|
||||
{'neutron_net_id': 'fake', 'neutron_subnet_id': 'fake'})
|
||||
{'name': 'new fake name'},
|
||||
{'description': 'new fake description'},
|
||||
{'name': 'new fake name', 'description': 'new fake description'})
|
||||
def test_update_valid_cases(self, data):
|
||||
body = {share_networks.RESOURCE_NAME: {'user_id': 'fake_user'}}
|
||||
created = self.controller.create(self.req, body)
|
||||
@ -172,7 +198,29 @@ class ShareNetworkAPITest(test.TestCase):
|
||||
self.controller.update,
|
||||
self.req, created['share_network']['id'], body)
|
||||
|
||||
@ddt.data(
|
||||
({'share_network_subnets': [
|
||||
{'share_network_id': fake_share_network['id']}]}, True),
|
||||
({'share_network_subnets': []}, False))
|
||||
@ddt.unpack
|
||||
def test__subnet_has_search_opt(self, network, has_search_opt):
|
||||
search_opts = {
|
||||
'share_network_id': fake_share_network['id']
|
||||
}
|
||||
|
||||
result = None
|
||||
|
||||
for key, value in search_opts.items():
|
||||
result = self.controller._subnet_has_search_opt(
|
||||
key, value, network)
|
||||
|
||||
self.assertEqual(has_search_opt, result)
|
||||
|
||||
def test_create_nominal(self):
|
||||
self.mock_object(db_api, 'share_network_subnet_create')
|
||||
self.mock_object(db_api, 'share_network_get',
|
||||
mock.Mock(return_value=fake_share_network))
|
||||
self.mock_object(common, 'check_net_id_and_subnet_id')
|
||||
with mock.patch.object(db_api,
|
||||
'share_network_create',
|
||||
mock.Mock(return_value=fake_share_network)):
|
||||
@ -191,7 +239,7 @@ class ShareNetworkAPITest(test.TestCase):
|
||||
with mock.patch.object(db_api,
|
||||
'share_network_create',
|
||||
mock.Mock(side_effect=db_exception.DBError)):
|
||||
self.assertRaises(webob_exc.HTTPBadRequest,
|
||||
self.assertRaises(webob_exc.HTTPInternalServerError,
|
||||
self.controller.create,
|
||||
self.req,
|
||||
self.body)
|
||||
@ -203,9 +251,55 @@ class ShareNetworkAPITest(test.TestCase):
|
||||
self.req,
|
||||
body)
|
||||
|
||||
@ddt.data(
|
||||
{'availability_zone': 'fake-zone'})
|
||||
def test_create_az_not_found(self, data):
|
||||
req = fakes.HTTPRequest.blank('/share-networks', version="2.51")
|
||||
|
||||
self.mock_object(
|
||||
db_api, 'availability_zone_get',
|
||||
mock.Mock(
|
||||
side_effect=exception.AvailabilityZoneNotFound(id='fake')))
|
||||
|
||||
body = {share_networks.RESOURCE_NAME: data}
|
||||
|
||||
self.assertRaises(webob_exc.HTTPBadRequest,
|
||||
self.controller.create,
|
||||
req,
|
||||
body)
|
||||
|
||||
def test_create_error_on_subnet_creation(self):
|
||||
data = {
|
||||
'neutron_net_id': 'fake',
|
||||
'neutron_subnet_id': 'fake',
|
||||
'id': fake_share_network['id']
|
||||
}
|
||||
subnet_data = copy.deepcopy(data)
|
||||
self.mock_object(db_api, 'share_network_create',
|
||||
mock.Mock(return_value=fake_share_network))
|
||||
self.mock_object(db_api, 'share_network_subnet_create',
|
||||
mock.Mock(side_effect=db_exception.DBError()))
|
||||
self.mock_object(db_api, 'share_network_delete')
|
||||
body = {share_networks.RESOURCE_NAME: data}
|
||||
|
||||
self.assertRaises(webob_exc.HTTPInternalServerError,
|
||||
self.controller.create,
|
||||
self.req,
|
||||
body)
|
||||
|
||||
db_api.share_network_create.assert_called_once_with(self.context, data)
|
||||
subnet_data['share_network_id'] = data['id']
|
||||
subnet_data.pop('id')
|
||||
db_api.share_network_subnet_create.assert_called_once_with(
|
||||
self.context, subnet_data)
|
||||
db_api.share_network_delete.assert_called_once_with(
|
||||
self.context, fake_share_network['id'])
|
||||
|
||||
def test_delete_nominal(self):
|
||||
share_nw = fake_share_network.copy()
|
||||
share_nw['share_servers'] = ['foo', 'bar']
|
||||
subnet = fake_share_network_subnet.copy()
|
||||
subnet['share_servers'] = ['foo', 'bar']
|
||||
share_nw['share_network_subnets'] = [subnet]
|
||||
self.mock_object(db_api, 'share_network_get',
|
||||
mock.Mock(return_value=share_nw))
|
||||
self.mock_object(db_api, 'share_instances_get_all_by_share_network',
|
||||
@ -242,7 +336,9 @@ class ShareNetworkAPITest(test.TestCase):
|
||||
|
||||
def test_quota_delete_reservation_failed(self):
|
||||
share_nw = fake_share_network.copy()
|
||||
share_nw['share_servers'] = ['foo', 'bar']
|
||||
subnet = fake_share_network_subnet.copy()
|
||||
subnet['share_servers'] = ['foo', 'bar']
|
||||
share_nw['share_network_subnets'] = [subnet]
|
||||
share_nw['user_id'] = 'fake_user_id'
|
||||
|
||||
self.mock_object(db_api, 'share_network_get',
|
||||
@ -330,6 +426,53 @@ class ShareNetworkAPITest(test.TestCase):
|
||||
db_api.share_network_get.assert_called_once_with(
|
||||
self.req.environ['manila.context'], share_nw['id'])
|
||||
|
||||
def test_delete_contains_more_than_one_subnet(self):
|
||||
share_nw = fake_share_network.copy()
|
||||
self.mock_object(db_api, 'share_network_get',
|
||||
mock.Mock(return_value=share_nw))
|
||||
self.mock_object(db_api, 'share_instances_get_all_by_share_network',
|
||||
mock.Mock(return_value=None))
|
||||
self.mock_object(db_api, 'count_share_groups_in_share_network',
|
||||
mock.Mock(return_value=None))
|
||||
self.mock_object(self.controller, '_share_network_contains_subnets',
|
||||
mock.Mock(return_value=True))
|
||||
|
||||
self.assertRaises(webob_exc.HTTPConflict,
|
||||
self.controller.delete,
|
||||
self.req,
|
||||
share_nw['id'])
|
||||
|
||||
db_api.share_network_get.assert_called_once_with(
|
||||
self.context, share_nw['id'])
|
||||
(db_api.share_instances_get_all_by_share_network
|
||||
.assert_called_once_with(self.context, share_nw['id']))
|
||||
db_api.count_share_groups_in_share_network.assert_called_once_with(
|
||||
self.context, share_nw['id']
|
||||
)
|
||||
(self.controller._share_network_contains_subnets
|
||||
.assert_called_once_with(share_nw))
|
||||
|
||||
def test_delete_subnet_contains_share_server(self):
|
||||
share_nw = fake_share_network.copy()
|
||||
share_nw['share_network_subnets'].append({
|
||||
'id': 'fake_sns_id',
|
||||
'share_servers': [{'id': 'fake_share_server_id'}]
|
||||
})
|
||||
self.mock_object(db_api, 'share_network_get',
|
||||
mock.Mock(return_value=share_nw))
|
||||
self.mock_object(db_api, 'count_share_groups_in_share_network',
|
||||
mock.Mock(return_value=0))
|
||||
self.mock_object(self.controller, '_share_network_contains_subnets',
|
||||
mock.Mock(return_value=False))
|
||||
self.mock_object(
|
||||
self.controller, '_all_share_servers_are_auto_deletable',
|
||||
mock.Mock(return_value=False))
|
||||
|
||||
self.assertRaises(webob_exc.HTTPConflict,
|
||||
self.controller.delete,
|
||||
self.req,
|
||||
share_nw['id'])
|
||||
|
||||
@ddt.data(
|
||||
({'share_servers': [{'is_auto_deletable': True},
|
||||
{'is_auto_deletable': True}]}, True),
|
||||
@ -344,6 +487,18 @@ class ShareNetworkAPITest(test.TestCase):
|
||||
self.controller._all_share_servers_are_auto_deletable(
|
||||
fake_share_network))
|
||||
|
||||
@ddt.data(
|
||||
({'share_network_subnets': [{'share_servers': [{}, {}]}]}, True),
|
||||
({'share_network_subnets': [{'share_servers': []}]}, False),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test__share_network_subnets_contain_share_servers(self, share_network,
|
||||
expected_result):
|
||||
self.assertEqual(
|
||||
expected_result,
|
||||
self.controller._share_network_subnets_contain_share_servers(
|
||||
share_network))
|
||||
|
||||
def test_show_nominal(self):
|
||||
share_nw = 'fake network id'
|
||||
with mock.patch.object(db_api,
|
||||
@ -552,12 +707,6 @@ class ShareNetworkAPITest(test.TestCase):
|
||||
valid_filter_opts = {
|
||||
'created_before': '2001-02-02',
|
||||
'created_since': '1999-01-01',
|
||||
'neutron_net_id': '1111',
|
||||
'neutron_subnet_id': '2222',
|
||||
'network_type': 'local',
|
||||
'segmentation_id': 2000,
|
||||
'cidr': '8.0.0.0/12',
|
||||
'ip_version': 6,
|
||||
'name': 'test-sn'
|
||||
}
|
||||
db_api.share_network_get_all_by_project.return_value = [
|
||||
@ -614,7 +763,9 @@ class ShareNetworkAPITest(test.TestCase):
|
||||
@mock.patch.object(db_api, 'share_network_get', mock.Mock())
|
||||
def test_update_invalid_key_in_use(self):
|
||||
share_nw = fake_share_network.copy()
|
||||
share_nw['share_servers'] = [{'id': 1}]
|
||||
subnet = fake_share_network_subnet.copy()
|
||||
subnet['share_servers'] = [{'id': 1}]
|
||||
share_nw['share_network_subnets'] = [subnet]
|
||||
|
||||
db_api.share_network_get.return_value = share_nw
|
||||
body = {
|
||||
@ -633,12 +784,15 @@ class ShareNetworkAPITest(test.TestCase):
|
||||
@mock.patch.object(db_api, 'share_network_update', mock.Mock())
|
||||
def test_update_valid_keys_in_use(self):
|
||||
share_nw = fake_share_network.copy()
|
||||
share_nw['share_servers'] = [{'id': 1}]
|
||||
subnet = fake_share_network_subnet.copy()
|
||||
subnet['share_servers'] = [{'id': 1}]
|
||||
share_nw['share_network_subnets'] = [subnet]
|
||||
updated_share_nw = share_nw.copy()
|
||||
updated_share_nw['name'] = 'new name'
|
||||
updated_share_nw['description'] = 'new description'
|
||||
|
||||
db_api.share_network_get.return_value = share_nw
|
||||
db_api.share_network_update.return_value = updated_share_nw
|
||||
body = {
|
||||
share_networks.RESOURCE_NAME: {
|
||||
'name': updated_share_nw['name'],
|
||||
@ -656,6 +810,10 @@ class ShareNetworkAPITest(test.TestCase):
|
||||
share_nw = 'fake network id'
|
||||
db_api.share_network_get.return_value = fake_share_network
|
||||
|
||||
self.mock_object(
|
||||
self.controller, '_share_network_subnets_contain_share_servers',
|
||||
mock.Mock(return_value=False))
|
||||
|
||||
body = {share_networks.RESOURCE_NAME: {'neutron_subnet_id':
|
||||
'new subnet'}}
|
||||
|
||||
@ -672,6 +830,9 @@ class ShareNetworkAPITest(test.TestCase):
|
||||
def test_action_add_security_service(self, microversion):
|
||||
share_network_id = 'fake network id'
|
||||
security_service_id = 'fake ss id'
|
||||
self.mock_object(
|
||||
self.controller, '_share_network_subnets_contain_share_servers')
|
||||
|
||||
body = {'add_security_service': {'security_service_id':
|
||||
security_service_id}}
|
||||
|
||||
@ -692,6 +853,9 @@ class ShareNetworkAPITest(test.TestCase):
|
||||
'type': 'ldap'}
|
||||
body = {'add_security_service': {'security_service_id':
|
||||
security_service['id']}}
|
||||
self.mock_object(
|
||||
self.controller, '_share_network_subnets_contain_share_servers',
|
||||
mock.Mock(return_value=False))
|
||||
|
||||
db_api.security_service_get.return_value = security_service
|
||||
db_api.share_network_get.return_value = share_network
|
||||
@ -716,6 +880,8 @@ class ShareNetworkAPITest(test.TestCase):
|
||||
def test_action_remove_security_service(self, microversion):
|
||||
share_network_id = 'fake network id'
|
||||
security_service_id = 'fake ss id'
|
||||
self.mock_object(
|
||||
self.controller, '_share_network_subnets_contain_share_servers')
|
||||
body = {'remove_security_service': {'security_service_id':
|
||||
security_service_id}}
|
||||
|
||||
@ -730,8 +896,13 @@ class ShareNetworkAPITest(test.TestCase):
|
||||
@mock.patch.object(share_networks.policy, 'check_policy', mock.Mock())
|
||||
def test_action_remove_security_service_forbidden(self):
|
||||
share_network = fake_share_network.copy()
|
||||
share_network['share_servers'] = 'fake share server'
|
||||
subnet = fake_share_network_subnet.copy()
|
||||
subnet['share_servers'] = ['foo']
|
||||
share_network['share_network_subnets'] = [subnet]
|
||||
db_api.share_network_get.return_value = share_network
|
||||
self.mock_object(
|
||||
self.controller, '_share_network_subnets_contain_share_servers',
|
||||
mock.Mock(return_value=True))
|
||||
body = {
|
||||
'remove_security_service': {
|
||||
'security_service_id': 'fake id',
|
||||
@ -758,3 +929,31 @@ class ShareNetworkAPITest(test.TestCase):
|
||||
self.req,
|
||||
share_network_id,
|
||||
body)
|
||||
|
||||
@ddt.data('add_security_service', 'remove_security_service')
|
||||
def test_action_security_service_contains_share_servers(self, action):
|
||||
share_network = fake_share_network.copy()
|
||||
security_service = {'id': ' security_service_2',
|
||||
'type': 'ldap'}
|
||||
body = {
|
||||
action: {
|
||||
'security_service_id': security_service['id']
|
||||
}
|
||||
}
|
||||
self.mock_object(share_networks.policy, 'check_policy')
|
||||
self.mock_object(db_api, 'share_network_get',
|
||||
mock.Mock(return_value=share_network))
|
||||
self.mock_object(
|
||||
self.controller, '_share_network_subnets_contain_share_servers',
|
||||
mock.Mock(return_value=True))
|
||||
|
||||
self.assertRaises(webob_exc.HTTPForbidden,
|
||||
self.controller.action,
|
||||
self.req,
|
||||
share_network['id'],
|
||||
body)
|
||||
db_api.share_network_get.assert_called_once_with(
|
||||
self.req.environ['manila.context'], share_network['id'])
|
||||
share_networks.policy.check_policy.assert_called_once_with(
|
||||
self.req.environ['manila.context'],
|
||||
share_networks.RESOURCE_NAME, action)
|
||||
|
@ -46,7 +46,8 @@ class ShareServerControllerTest(test.TestCase):
|
||||
constants.STATUS_UNMANAGE_ERROR, constants.STATUS_MANAGE_ERROR)
|
||||
def test_share_server_reset_status(self, status):
|
||||
req = fakes.HTTPRequest.blank('/v2/share-servers/fake-share-server/',
|
||||
use_admin_context=True)
|
||||
use_admin_context=True,
|
||||
version="2.49")
|
||||
body = {'reset_status': {'status': status}}
|
||||
|
||||
context = req.environ['manila.context']
|
||||
@ -62,7 +63,8 @@ class ShareServerControllerTest(test.TestCase):
|
||||
context, 'fake_server_id', {'status': status})
|
||||
|
||||
def test_share_reset_server_status_invalid(self):
|
||||
req = fakes.HTTPRequest.blank('/reset_status', use_admin_context=True)
|
||||
req = fakes.HTTPRequest.blank('/reset_status', use_admin_context=True,
|
||||
version="2.49")
|
||||
body = {'reset_status': {'status': constants.STATUS_EXTENDING}}
|
||||
context = req.environ['manila.context']
|
||||
|
||||
@ -74,7 +76,8 @@ class ShareServerControllerTest(test.TestCase):
|
||||
context, self.resource_name, 'reset_status')
|
||||
|
||||
def test_share_server_reset_status_no_body(self):
|
||||
req = fakes.HTTPRequest.blank('/reset_status', use_admin_context=True)
|
||||
req = fakes.HTTPRequest.blank('/reset_status', use_admin_context=True,
|
||||
version="2.49")
|
||||
context = req.environ['manila.context']
|
||||
|
||||
self.assertRaises(
|
||||
@ -85,7 +88,8 @@ class ShareServerControllerTest(test.TestCase):
|
||||
context, self.resource_name, 'reset_status')
|
||||
|
||||
def test_share_server_reset_status_no_status(self):
|
||||
req = fakes.HTTPRequest.blank('/reset_status', use_admin_context=True)
|
||||
req = fakes.HTTPRequest.blank('/reset_status', use_admin_context=True,
|
||||
version="2.49")
|
||||
context = req.environ['manila.context']
|
||||
|
||||
self.assertRaises(
|
||||
@ -98,6 +102,7 @@ class ShareServerControllerTest(test.TestCase):
|
||||
def _setup_manage_test_request_body(self):
|
||||
body = {
|
||||
'share_network_id': 'fake_net_id',
|
||||
'share_network_subnet_id': 'fake_subnet_id',
|
||||
'host': 'fake_host',
|
||||
'identifier': 'fake_identifier',
|
||||
'driver_options': {'opt1': 'fake_opt1', 'opt2': 'fake_opt2'},
|
||||
@ -112,14 +117,18 @@ class ShareServerControllerTest(test.TestCase):
|
||||
version="2.49")
|
||||
context = req.environ['manila.context']
|
||||
share_network = db_utils.create_share_network(name=share_net_name)
|
||||
share_net_subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id=share_network['id'])
|
||||
share_server = db_utils.create_share_server(
|
||||
share_network_id=share_network['id'],
|
||||
share_network_subnet_id=share_net_subnet['id'],
|
||||
host='fake_host',
|
||||
identifier='fake_identifier',
|
||||
is_auto_deletable=False)
|
||||
|
||||
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
||||
return_value=share_network))
|
||||
self.mock_object(db_api, 'share_network_subnet_get_default_subnet',
|
||||
mock.Mock(return_value=share_net_subnet))
|
||||
self.mock_object(utils, 'validate_service_host')
|
||||
|
||||
body = {
|
||||
@ -138,7 +147,8 @@ class ShareServerControllerTest(test.TestCase):
|
||||
'updated_at': None,
|
||||
'status': constants.STATUS_ACTIVE,
|
||||
'host': 'fake_host',
|
||||
'share_network_id': share_server['share_network_id'],
|
||||
'share_network_id':
|
||||
share_server['share_network_subnet']['share_network_id'],
|
||||
'created_at': share_server['created_at'],
|
||||
'backend_details': {},
|
||||
'identifier': share_server['identifier'],
|
||||
@ -150,12 +160,12 @@ class ShareServerControllerTest(test.TestCase):
|
||||
'fake_net_name')
|
||||
else:
|
||||
expected_result['share_server']['share_network_name'] = (
|
||||
share_server['share_network_id'])
|
||||
share_net_subnet['share_network_id'])
|
||||
|
||||
req_params = body['share_server']
|
||||
manage_share_server_mock.assert_called_once_with(
|
||||
context, req_params['identifier'], req_params['host'],
|
||||
share_network, req_params['driver_options'])
|
||||
share_net_subnet, req_params['driver_options'])
|
||||
|
||||
self.assertEqual(expected_result, result)
|
||||
|
||||
@ -164,9 +174,11 @@ class ShareServerControllerTest(test.TestCase):
|
||||
|
||||
def test_manage_invalid(self):
|
||||
req = fakes.HTTPRequest.blank('/manage_share_server',
|
||||
use_admin_context=True)
|
||||
use_admin_context=True, version="2.49")
|
||||
context = req.environ['manila.context']
|
||||
share_network = db_utils.create_share_network()
|
||||
share_net_subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id=share_network['id'])
|
||||
|
||||
body = {
|
||||
'share_server': self._setup_manage_test_request_body()
|
||||
@ -174,6 +186,8 @@ class ShareServerControllerTest(test.TestCase):
|
||||
self.mock_object(utils, 'validate_service_host')
|
||||
self.mock_object(db_api, 'share_network_get',
|
||||
mock.Mock(return_value=share_network))
|
||||
self.mock_object(db_api, 'share_network_subnet_get_default_subnet',
|
||||
mock.Mock(return_value=share_net_subnet))
|
||||
|
||||
manage_share_server_mock = self.mock_object(
|
||||
share_api.API, 'manage_share_server',
|
||||
@ -185,15 +199,24 @@ class ShareServerControllerTest(test.TestCase):
|
||||
req_params = body['share_server']
|
||||
manage_share_server_mock.assert_called_once_with(
|
||||
context, req_params['identifier'], req_params['host'],
|
||||
share_network, req_params['driver_options'])
|
||||
share_net_subnet, req_params['driver_options'])
|
||||
|
||||
def test_manage_forbidden(self):
|
||||
"""Tests share server manage without admin privileges"""
|
||||
req = fakes.HTTPRequest.blank('/manage_share_server')
|
||||
self.mock_object(share_api.API, 'manage_share_server', mock.Mock())
|
||||
req = fakes.HTTPRequest.blank('/manage_share_server', version="2.49")
|
||||
error = mock.Mock(side_effect=exception.PolicyNotAuthorized(action=''))
|
||||
self.mock_object(share_api.API, 'manage_share_server', error)
|
||||
|
||||
share_network = db_utils.create_share_network()
|
||||
share_net_subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id=share_network['id'])
|
||||
|
||||
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
||||
return_value=share_network))
|
||||
self.mock_object(db_api, 'share_network_subnet_get_default_subnet',
|
||||
mock.Mock(return_value=share_net_subnet))
|
||||
self.mock_object(utils, 'validate_service_host')
|
||||
|
||||
body = {
|
||||
'share_server': self._setup_manage_test_request_body()
|
||||
}
|
||||
@ -205,7 +228,7 @@ class ShareServerControllerTest(test.TestCase):
|
||||
|
||||
def test__validate_manage_share_server_validate_no_body(self):
|
||||
"""Tests share server manage"""
|
||||
req = fakes.HTTPRequest.blank('/manage')
|
||||
req = fakes.HTTPRequest.blank('/manage', version="2.49")
|
||||
body = {}
|
||||
|
||||
self.assertRaises(webob.exc.HTTPUnprocessableEntity,
|
||||
@ -223,7 +246,7 @@ class ShareServerControllerTest(test.TestCase):
|
||||
def test__validate_manage_share_server_validate_without_parameters(
|
||||
self, empty, key):
|
||||
"""Tests share server manage without some parameters"""
|
||||
req = fakes.HTTPRequest.blank('/manage_share_server')
|
||||
req = fakes.HTTPRequest.blank('/manage_share_server', version="2.49")
|
||||
self.mock_object(share_api.API, 'manage_share_server', mock.Mock())
|
||||
|
||||
body = {
|
||||
@ -249,11 +272,20 @@ class ShareServerControllerTest(test.TestCase):
|
||||
@ddt.unpack
|
||||
def test__validate_manage_share_server_validate_service_host(
|
||||
self, exception_to_raise, side_effect_exception):
|
||||
req = fakes.HTTPRequest.blank('/manage')
|
||||
req = fakes.HTTPRequest.blank('/manage', version="2.49")
|
||||
context = req.environ['manila.context']
|
||||
error = mock.Mock(side_effect=side_effect_exception)
|
||||
self.mock_object(utils, 'validate_service_host', error)
|
||||
|
||||
share_network = db_utils.create_share_network()
|
||||
share_net_subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id=share_network['id'])
|
||||
|
||||
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
||||
return_value=share_network))
|
||||
self.mock_object(db_api, 'share_network_subnet_get_default_subnet',
|
||||
mock.Mock(return_value=share_net_subnet))
|
||||
|
||||
self.assertRaises(
|
||||
exception_to_raise, self.controller.manage, req,
|
||||
{'share_server': self._setup_manage_test_request_body()})
|
||||
@ -262,7 +294,7 @@ class ShareServerControllerTest(test.TestCase):
|
||||
context, self.resource_name, 'manage_share_server')
|
||||
|
||||
def test__validate_manage_share_server_share_network_not_found(self):
|
||||
req = fakes.HTTPRequest.blank('/manage')
|
||||
req = fakes.HTTPRequest.blank('/manage', version="2.49")
|
||||
context = req.environ['manila.context']
|
||||
self.mock_object(utils, 'validate_service_host')
|
||||
error = mock.Mock(
|
||||
@ -279,7 +311,7 @@ class ShareServerControllerTest(test.TestCase):
|
||||
context, self.resource_name, 'manage_share_server')
|
||||
|
||||
def test__validate_manage_share_server_driver_opts_not_instance_dict(self):
|
||||
req = fakes.HTTPRequest.blank('/manage')
|
||||
req = fakes.HTTPRequest.blank('/manage', version="2.49")
|
||||
context = req.environ['manila.context']
|
||||
self.mock_object(utils, 'validate_service_host')
|
||||
self.mock_object(db_api, 'share_network_get')
|
||||
@ -294,7 +326,7 @@ class ShareServerControllerTest(test.TestCase):
|
||||
context, self.resource_name, 'manage_share_server')
|
||||
|
||||
def test__validate_manage_share_server_error_extract_host(self):
|
||||
req = fakes.HTTPRequest.blank('/manage')
|
||||
req = fakes.HTTPRequest.blank('/manage', version="2.49")
|
||||
context = req.environ['manila.context']
|
||||
body = self._setup_manage_test_request_body()
|
||||
body['host'] = 'fake@backend#pool'
|
||||
@ -306,10 +338,44 @@ class ShareServerControllerTest(test.TestCase):
|
||||
policy.check_policy.assert_called_once_with(
|
||||
context, self.resource_name, 'manage_share_server')
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test__validate_manage_share_server_error_subnet_not_found(
|
||||
self, body_contains_subnet):
|
||||
req = fakes.HTTPRequest.blank('/manage', version="2.51")
|
||||
context = req.environ['manila.context']
|
||||
share_network = db_utils.create_share_network()
|
||||
body = {'share_server': self._setup_manage_test_request_body()}
|
||||
share_net_subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id=share_network['id'])
|
||||
body['share_server']['share_network_subnet_id'] = (
|
||||
share_net_subnet['id'] if body_contains_subnet else None)
|
||||
|
||||
self.mock_object(
|
||||
db_api, 'share_network_subnet_get',
|
||||
mock.Mock(side_effect=exception.ShareNetworkSubnetNotFound(
|
||||
share_network_subnet_id='fake')))
|
||||
self.mock_object(db_api, 'share_network_subnet_get_default_subnet',
|
||||
mock.Mock(return_value=None))
|
||||
|
||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||
self.controller.manage,
|
||||
req,
|
||||
body)
|
||||
|
||||
policy.check_policy.assert_called_once_with(
|
||||
context, self.resource_name, 'manage_share_server')
|
||||
if body_contains_subnet:
|
||||
db_api.share_network_subnet_get.assert_called_once_with(
|
||||
context, share_net_subnet['id'])
|
||||
else:
|
||||
(db_api.share_network_subnet_get_default_subnet
|
||||
.assert_called_once_with(
|
||||
context, body['share_server']['share_network_id']))
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_unmanage(self, force):
|
||||
server = self._setup_unmanage_tests()
|
||||
req = fakes.HTTPRequest.blank('/unmanage')
|
||||
req = fakes.HTTPRequest.blank('/unmanage', version="2.49")
|
||||
context = req.environ['manila.context']
|
||||
mock_get = self.mock_object(
|
||||
db_api, 'share_server_get', mock.Mock(return_value=server))
|
||||
@ -326,7 +392,8 @@ class ShareServerControllerTest(test.TestCase):
|
||||
|
||||
def test_unmanage_share_server_not_found(self):
|
||||
"""Tests unmanaging share servers"""
|
||||
req = fakes.HTTPRequest.blank('/v2/share-servers/fake_server_id/')
|
||||
req = fakes.HTTPRequest.blank('/v2/share-servers/fake_server_id/',
|
||||
version="2.49")
|
||||
context = req.environ['manila.context']
|
||||
share_server_error = mock.Mock(
|
||||
side_effect=exception.ShareServerNotFound(
|
||||
@ -350,7 +417,7 @@ class ShareServerControllerTest(test.TestCase):
|
||||
server = self._setup_unmanage_tests(status=status)
|
||||
get_mock = self.mock_object(db_api, 'share_server_get',
|
||||
mock.Mock(return_value=server))
|
||||
req = fakes.HTTPRequest.blank('/unmanage_share_server')
|
||||
req = fakes.HTTPRequest.blank('/unmanage_share_server', version="2.49")
|
||||
context = req.environ['manila.context']
|
||||
body = {'unmanage': {'force': True}}
|
||||
|
||||
@ -371,7 +438,7 @@ class ShareServerControllerTest(test.TestCase):
|
||||
|
||||
@ddt.data(exception.ShareServerInUse, exception.PolicyNotAuthorized)
|
||||
def test_unmanage_share_server_badrequest(self, exc):
|
||||
req = fakes.HTTPRequest.blank('/unmanage')
|
||||
req = fakes.HTTPRequest.blank('/unmanage', version="2.49")
|
||||
server = self._setup_unmanage_tests()
|
||||
context = req.environ['manila.context']
|
||||
error = mock.Mock(side_effect=exc('foobar'))
|
||||
|
@ -666,6 +666,8 @@ class ShareAPITest(test.TestCase):
|
||||
self.mock_object(share_api.API, 'create', create_mock)
|
||||
self.mock_object(share_api.API, 'get_share_network', mock.Mock(
|
||||
return_value={'id': 'fakenetid'}))
|
||||
self.mock_object(
|
||||
db, 'share_network_subnet_get_by_availability_zone_id')
|
||||
|
||||
body = {"share": copy.deepcopy(shr)}
|
||||
req = fakes.HTTPRequest.blank('/shares', version='2.7')
|
||||
@ -674,6 +676,7 @@ class ShareAPITest(test.TestCase):
|
||||
expected = self._get_expected_share_detailed_response(
|
||||
shr, version='2.7')
|
||||
self.assertDictMatch(expected, res_dict)
|
||||
# pylint: disable=unsubscriptable-object
|
||||
self.assertEqual("fakenetid",
|
||||
create_mock.call_args[1]['share_network_id'])
|
||||
|
||||
@ -1244,6 +1247,8 @@ class ShareAPITest(test.TestCase):
|
||||
return_value=parent_share))
|
||||
self.mock_object(share_api.API, 'get_share_network', mock.Mock(
|
||||
return_value={'id': parent_share_net}))
|
||||
self.mock_object(
|
||||
db, 'share_network_subnet_get_by_availability_zone_id')
|
||||
|
||||
body = {"share": copy.deepcopy(shr)}
|
||||
req = fakes.HTTPRequest.blank('/shares', version='2.7')
|
||||
@ -1253,6 +1258,7 @@ class ShareAPITest(test.TestCase):
|
||||
expected = self._get_expected_share_detailed_response(
|
||||
shr, version='2.7')
|
||||
self.assertEqual(expected, res_dict)
|
||||
# pylint: disable=unsubscriptable-object
|
||||
self.assertEqual(parent_share_net,
|
||||
create_mock.call_args[1]['share_network_id'])
|
||||
|
||||
@ -1286,6 +1292,8 @@ class ShareAPITest(test.TestCase):
|
||||
return_value=parent_share))
|
||||
self.mock_object(share_api.API, 'get_share_network', mock.Mock(
|
||||
return_value={'id': parent_share_net}))
|
||||
self.mock_object(
|
||||
db, 'share_network_subnet_get_by_availability_zone_id')
|
||||
|
||||
body = {"share": copy.deepcopy(shr)}
|
||||
req = fakes.HTTPRequest.blank('/shares', version='2.7')
|
||||
@ -1293,6 +1301,7 @@ class ShareAPITest(test.TestCase):
|
||||
expected = self._get_expected_share_detailed_response(
|
||||
shr, version='2.7')
|
||||
self.assertDictMatch(expected, res_dict)
|
||||
# pylint: disable=unsubscriptable-object
|
||||
self.assertEqual(parent_share_net,
|
||||
create_mock.call_args[1]['share_network_id'])
|
||||
|
||||
|
75
manila/tests/api/views/test_share_network_subnets.py
Normal file
75
manila/tests/api/views/test_share_network_subnets.py
Normal file
@ -0,0 +1,75 @@
|
||||
# Copyright 2019 NetApp, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
import ddt
|
||||
|
||||
from manila.api.views import share_network_subnets
|
||||
from manila import test
|
||||
from manila.tests.api import fakes
|
||||
from manila.tests import db_utils
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class ViewBuilderTestCase(test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ViewBuilderTestCase, self).setUp()
|
||||
self.builder = share_network_subnets.ViewBuilder()
|
||||
self.share_network = db_utils.create_share_network(
|
||||
name='fake_network', id='fake_sn_id')
|
||||
|
||||
def _validate_is_detail_return(self, result):
|
||||
expected_keys = ['id', 'created_at', 'updated_at', 'neutron_net_id',
|
||||
'neutron_subnet_id', 'network_type', 'cidr',
|
||||
'segmentation_id', 'ip_version', 'share_network_id',
|
||||
'availability_zone', 'gateway', 'mtu']
|
||||
|
||||
for key in expected_keys:
|
||||
self.assertIn(key, result)
|
||||
|
||||
def test_build_share_network_subnet(self):
|
||||
req = fakes.HTTPRequest.blank('/subnets', version='2.51')
|
||||
|
||||
subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id=self.share_network['id'])
|
||||
|
||||
result = self.builder.build_share_network_subnet(req, subnet)
|
||||
|
||||
self.assertEqual(1, len(result))
|
||||
self.assertIn('share_network_subnet', result)
|
||||
self.assertEqual(subnet['id'],
|
||||
result['share_network_subnet']['id'])
|
||||
self.assertEqual(subnet['share_network_id'],
|
||||
result['share_network_subnet']['share_network_id'])
|
||||
self.assertIsNone(
|
||||
result['share_network_subnet']['availability_zone'])
|
||||
self._validate_is_detail_return(result['share_network_subnet'])
|
||||
|
||||
def test_build_share_network_subnets(self):
|
||||
req = fakes.HTTPRequest.blank('/subnets', version='2.51')
|
||||
|
||||
share_network = db_utils.create_share_network(
|
||||
name='fake_network', id='fake_sn_id_1')
|
||||
subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id=share_network['id'])
|
||||
|
||||
result = self.builder.build_share_network_subnets(req, [subnet])
|
||||
|
||||
self.assertIn('share_network_subnets', result)
|
||||
self.assertEqual(1, len(result['share_network_subnets']))
|
||||
subnet_list = result['share_network_subnets']
|
||||
for subnet in subnet_list:
|
||||
self._validate_is_detail_return(subnet)
|
@ -34,12 +34,21 @@ class ViewBuilderTestCase(test.TestCase):
|
||||
|
||||
@ddt.data(*itertools.product(
|
||||
[
|
||||
{'id': 'fake_sn_id', 'name': 'fake_sn_name'},
|
||||
{'id': 'fake_sn_id', 'name': 'fake_sn_name',
|
||||
'share_network_subnets': []},
|
||||
{'id': 'fake_sn_id', 'name': 'fake_sn_name',
|
||||
'share_network_subnets': [], 'fake_extra_key': 'foo'},
|
||||
{'id': 'fake_sn_id', 'name': 'fake_sn_name',
|
||||
'share_network_subnets': [
|
||||
{'availability_zone_id': None,
|
||||
'id': 'fake',
|
||||
'availability_zone': None,
|
||||
'is_default': False
|
||||
}],
|
||||
'fake_extra_key': 'foo'},
|
||||
],
|
||||
["1.0", "2.0", "2.18", "2.20", "2.25", "2.26",
|
||||
api_version._MAX_API_VERSION])
|
||||
"2.49", api_version._MAX_API_VERSION])
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_build_share_network(self, share_network_data, microversion):
|
||||
@ -49,17 +58,28 @@ class ViewBuilderTestCase(test.TestCase):
|
||||
api_version.APIVersionRequest('2.20'))
|
||||
nova_net_support = (api_version.APIVersionRequest(microversion) <
|
||||
api_version.APIVersionRequest('2.26'))
|
||||
default_net_info_support = (api_version.APIVersionRequest(microversion)
|
||||
<= api_version.APIVersionRequest('2.49'))
|
||||
subnets_support = (api_version.APIVersionRequest(microversion) >
|
||||
api_version.APIVersionRequest('2.49'))
|
||||
req = fakes.HTTPRequest.blank('/share-networks', version=microversion)
|
||||
expected_keys = {
|
||||
'id', 'name', 'project_id', 'created_at', 'updated_at',
|
||||
'neutron_net_id', 'neutron_subnet_id', 'network_type',
|
||||
'segmentation_id', 'cidr', 'ip_version', 'description'}
|
||||
if gateway_support:
|
||||
expected_keys.add('gateway')
|
||||
if mtu_support:
|
||||
expected_keys.add('mtu')
|
||||
if nova_net_support:
|
||||
expected_keys.add('nova_net_id')
|
||||
'description'}
|
||||
if subnets_support:
|
||||
expected_keys.add('share_network_subnets')
|
||||
else:
|
||||
if default_net_info_support:
|
||||
network_info = {
|
||||
'neutron_net_id', 'neutron_subnet_id', 'network_type',
|
||||
'segmentation_id', 'cidr', 'ip_version'}
|
||||
expected_keys.update(network_info)
|
||||
if gateway_support:
|
||||
expected_keys.add('gateway')
|
||||
if mtu_support:
|
||||
expected_keys.add('mtu')
|
||||
if nova_net_support:
|
||||
expected_keys.add('nova_net_id')
|
||||
|
||||
result = self.builder.build_share_network(req, share_network_data)
|
||||
self.assertEqual(1, len(result))
|
||||
@ -93,7 +113,7 @@ class ViewBuilderTestCase(test.TestCase):
|
||||
{'id': 'fake_id2',
|
||||
'name': 'fake_name2'}],
|
||||
],
|
||||
set(["1.0", "2.0", "2.18", "2.20", "2.25", "2.26",
|
||||
set(["1.0", "2.0", "2.18", "2.20", "2.25", "2.26", "2.49",
|
||||
api_version._MAX_API_VERSION]))
|
||||
)
|
||||
@ddt.unpack
|
||||
@ -105,6 +125,10 @@ class ViewBuilderTestCase(test.TestCase):
|
||||
api_version.APIVersionRequest('2.20'))
|
||||
nova_net_support = (api_version.APIVersionRequest(microversion) <
|
||||
api_version.APIVersionRequest('2.26'))
|
||||
default_net_info_support = (api_version.APIVersionRequest(microversion)
|
||||
<= api_version.APIVersionRequest('2.49'))
|
||||
subnets_support = (api_version.APIVersionRequest(microversion) >
|
||||
api_version.APIVersionRequest('2.49'))
|
||||
req = fakes.HTTPRequest.blank('/share-networks', version=microversion)
|
||||
expected_networks_list = []
|
||||
for share_network in share_networks:
|
||||
@ -114,23 +138,34 @@ class ViewBuilderTestCase(test.TestCase):
|
||||
'project_id': share_network.get('project_id'),
|
||||
'created_at': share_network.get('created_at'),
|
||||
'updated_at': share_network.get('updated_at'),
|
||||
'neutron_net_id': share_network.get('neutron_net_id'),
|
||||
'neutron_subnet_id': share_network.get('neutron_subnet_id'),
|
||||
'network_type': share_network.get('network_type'),
|
||||
'segmentation_id': share_network.get('segmentation_id'),
|
||||
'cidr': share_network.get('cidr'),
|
||||
'ip_version': share_network.get('ip_version'),
|
||||
'description': share_network.get('description'),
|
||||
}
|
||||
if gateway_support:
|
||||
share_network.update({'gateway': 'fake_gateway'})
|
||||
expected_data.update({'gateway': share_network.get('gateway')})
|
||||
if mtu_support:
|
||||
share_network.update({'mtu': 1509})
|
||||
expected_data.update({'mtu': share_network.get('mtu')})
|
||||
if nova_net_support:
|
||||
share_network.update({'nova_net_id': 'fake_nova_net_id'})
|
||||
expected_data.update({'nova_net_id': None})
|
||||
if subnets_support:
|
||||
share_network.update({'share_network_subnets': []})
|
||||
expected_data.update({'share_network_subnets': []})
|
||||
else:
|
||||
if default_net_info_support:
|
||||
network_data = {
|
||||
'neutron_net_id': share_network.get('neutron_net_id'),
|
||||
'neutron_subnet_id': share_network.get(
|
||||
'neutron_subnet_id'),
|
||||
'network_type': share_network.get('network_type'),
|
||||
'segmentation_id': share_network.get(
|
||||
'segmentation_id'),
|
||||
'cidr': share_network.get('cidr'),
|
||||
'ip_version': share_network.get('ip_version'),
|
||||
}
|
||||
expected_data.update(network_data)
|
||||
if gateway_support:
|
||||
share_network.update({'gateway': 'fake_gateway'})
|
||||
expected_data.update({'gateway':
|
||||
share_network.get('gateway')})
|
||||
if mtu_support:
|
||||
share_network.update({'mtu': 1509})
|
||||
expected_data.update({'mtu': share_network.get('mtu')})
|
||||
if nova_net_support:
|
||||
share_network.update({'nova_net_id': 'fake_nova_net_id'})
|
||||
expected_data.update({'nova_net_id': None})
|
||||
expected_networks_list.append(expected_data)
|
||||
expected = {'share_networks': expected_networks_list}
|
||||
|
||||
@ -148,7 +183,7 @@ class ViewBuilderTestCase(test.TestCase):
|
||||
{'id': 'id2', 'name': 'name2',
|
||||
'fake': 'I should not be returned'}]
|
||||
],
|
||||
set(["1.0", "2.0", "2.18", "2.20", "2.25", "2.26",
|
||||
set(["1.0", "2.0", "2.18", "2.20", "2.25", "2.26", "2.49",
|
||||
api_version._MAX_API_VERSION]))
|
||||
)
|
||||
@ddt.unpack
|
||||
|
@ -34,6 +34,7 @@ See BaseMigrationChecks class for more information.
|
||||
"""
|
||||
|
||||
import abc
|
||||
import copy
|
||||
import datetime
|
||||
|
||||
from oslo_db import exception as oslo_db_exc
|
||||
@ -2803,3 +2804,116 @@ class ShareServerIsAutoDeletableAndIdentifierChecks(BaseMigrationChecks):
|
||||
for ss in engine.execute(ss_table.select()):
|
||||
self.test_case.assertFalse(hasattr(ss, 'is_auto_deletable'))
|
||||
self.test_case.assertFalse(hasattr(ss, 'identifier'))
|
||||
|
||||
|
||||
@map_to_migration('805685098bd2')
|
||||
class ShareNetworkSubnetMigrationChecks(BaseMigrationChecks):
|
||||
|
||||
user_id = '6VFQ87wnV24lg1c2q1q0lJkTbQBPFZ1m4968'
|
||||
project_id = '19HAW8w58yeUPBy8zGex4EGulWZHd8zZGtHk'
|
||||
share_network = {
|
||||
'id': uuidutils.generate_uuid(),
|
||||
'user_id': user_id,
|
||||
'project_id': project_id,
|
||||
'neutron_net_id': uuidutils.generate_uuid(),
|
||||
'neutron_subnet_id': uuidutils.generate_uuid(),
|
||||
'cidr': '203.0.113.0/24',
|
||||
'ip_version': 4,
|
||||
'network_type': 'vxlan',
|
||||
'segmentation_id': 100,
|
||||
'gateway': 'fake_gateway',
|
||||
'mtu': 1500,
|
||||
}
|
||||
|
||||
share_networks = [share_network]
|
||||
|
||||
sns_table_name = 'share_network_subnets'
|
||||
sn_table_name = 'share_networks'
|
||||
ss_table_name = 'share_servers'
|
||||
|
||||
expected_keys = ['neutron_net_id', 'neutron_subnet_id', 'cidr',
|
||||
'ip_version', 'network_type', 'segmentation_id',
|
||||
'gateway', 'mtu']
|
||||
|
||||
def _setup_data_for_empty_neutron_net_and_subnet_id_test(self, network):
|
||||
network['id'] = uuidutils.generate_uuid()
|
||||
for key in self.expected_keys:
|
||||
network[key] = None
|
||||
return network
|
||||
|
||||
def setup_upgrade_data(self, engine):
|
||||
share_network_data_without_net_info = (
|
||||
self._setup_data_for_empty_neutron_net_and_subnet_id_test(
|
||||
copy.deepcopy(self.share_network)))
|
||||
self.share_networks.append(share_network_data_without_net_info)
|
||||
# Load the table to be used below
|
||||
sn_table = utils.load_table(self.sn_table_name, engine)
|
||||
ss_table = utils.load_table(self.ss_table_name, engine)
|
||||
|
||||
# Share server data
|
||||
share_server_data = {
|
||||
'host': 'acme@controller-ostk-0',
|
||||
'status': 'active',
|
||||
}
|
||||
|
||||
# Create share share networks and one share server for each of them
|
||||
for network in self.share_networks:
|
||||
share_server_data['share_network_id'] = network['id']
|
||||
share_server_data['id'] = uuidutils.generate_uuid()
|
||||
engine.execute(sn_table.insert(network))
|
||||
engine.execute(ss_table.insert(share_server_data))
|
||||
|
||||
def check_upgrade(self, engine, data):
|
||||
# Load the necessary tables
|
||||
sn_table = utils.load_table(self.sn_table_name, engine)
|
||||
sns_table = utils.load_table(self.sns_table_name, engine)
|
||||
ss_table = utils.load_table(self.ss_table_name, engine)
|
||||
|
||||
for network in self.share_networks:
|
||||
sn_record = engine.execute(sn_table.select().where(
|
||||
sn_table.c.id == network['id'])).first()
|
||||
|
||||
for key in self.expected_keys:
|
||||
self.test_case.assertFalse(hasattr(sn_record, key))
|
||||
|
||||
sns_record = engine.execute(sns_table.select().where(
|
||||
sns_table.c.share_network_id == network['id'])).first()
|
||||
|
||||
for key in self.expected_keys:
|
||||
self.test_case.assertTrue(hasattr(sns_record, key))
|
||||
self.test_case.assertEqual(network[key], sns_record[key])
|
||||
|
||||
ss_record = (
|
||||
engine.execute(
|
||||
ss_table.select().where(
|
||||
ss_table.c.share_network_subnet_id == sns_record['id'])
|
||||
).first())
|
||||
|
||||
self.test_case.assertIs(
|
||||
True, hasattr(ss_record, 'share_network_subnet_id'))
|
||||
self.test_case.assertEqual(
|
||||
ss_record['share_network_subnet_id'], sns_record['id'])
|
||||
self.test_case.assertIs(
|
||||
False, hasattr(ss_record, 'share_network_id'))
|
||||
|
||||
def check_downgrade(self, engine):
|
||||
sn_table = utils.load_table(self.sn_table_name, engine)
|
||||
|
||||
# Check if the share network table contains the expected keys
|
||||
for sn in engine.execute(sn_table.select()):
|
||||
for key in self.expected_keys:
|
||||
self.test_case.assertTrue(hasattr(sn, key))
|
||||
|
||||
ss_table = utils.load_table(self.ss_table_name, engine)
|
||||
for network in self.share_networks:
|
||||
for ss in engine.execute(ss_table.select().where(
|
||||
ss_table.c.share_network_id == network['id'])):
|
||||
self.test_case.assertFalse(hasattr(ss,
|
||||
'share_network_subnet_id'))
|
||||
self.test_case.assertTrue(hasattr(ss, 'share_network_id'))
|
||||
self.test_case.assertEqual(network['id'], ss['id'])
|
||||
|
||||
# Check if the created table doesn't exists anymore
|
||||
self.test_case.assertRaises(
|
||||
sa_exc.NoSuchTableError,
|
||||
utils.load_table, self.sns_table_name, engine)
|
||||
|
@ -577,7 +577,7 @@ class ShareDatabaseAPITestCase(test.TestCase):
|
||||
db_utils.create_share_replica(share_id=share_2['id'])
|
||||
expected_ss_keys = {
|
||||
'backend_details', 'host', 'id',
|
||||
'share_network_id', 'status',
|
||||
'share_network_subnet_id', 'status',
|
||||
}
|
||||
expected_share_keys = {
|
||||
'project_id', 'share_type_id', 'display_name',
|
||||
@ -625,7 +625,7 @@ class ShareDatabaseAPITestCase(test.TestCase):
|
||||
share_server_id=share_server['id'])
|
||||
expected_ss_keys = {
|
||||
'backend_details', 'host', 'id',
|
||||
'share_network_id', 'status',
|
||||
'share_network_subnet_id', 'status',
|
||||
}
|
||||
expected_share_keys = {
|
||||
'project_id', 'share_type_id', 'display_name',
|
||||
@ -690,7 +690,7 @@ class ShareDatabaseAPITestCase(test.TestCase):
|
||||
session = db_api.get_session()
|
||||
expected_ss_keys = {
|
||||
'backend_details', 'host', 'id',
|
||||
'share_network_id', 'status',
|
||||
'share_network_subnet_id', 'status',
|
||||
}
|
||||
expected_share_keys = {
|
||||
'project_id', 'share_type_id', 'display_name',
|
||||
@ -778,7 +778,7 @@ class ShareDatabaseAPITestCase(test.TestCase):
|
||||
)
|
||||
expected_extra_keys = {
|
||||
'backend_details', 'host', 'id',
|
||||
'share_network_id', 'status',
|
||||
'share_network_subnet_id', 'status',
|
||||
}
|
||||
with session.begin():
|
||||
share_replica = db_api.share_replica_get(
|
||||
@ -1941,14 +1941,8 @@ class ShareNetworkDatabaseAPITestCase(BaseDatabaseAPITestCase):
|
||||
def setUp(self):
|
||||
super(ShareNetworkDatabaseAPITestCase, self).setUp()
|
||||
self.share_nw_dict = {'id': 'fake network id',
|
||||
'neutron_net_id': 'fake net id',
|
||||
'neutron_subnet_id': 'fake subnet id',
|
||||
'project_id': self.fake_context.project_id,
|
||||
'user_id': 'fake_user_id',
|
||||
'network_type': 'vlan',
|
||||
'segmentation_id': 1000,
|
||||
'cidr': '10.0.0.0/24',
|
||||
'ip_version': 4,
|
||||
'name': 'whatever',
|
||||
'description': 'fake description'}
|
||||
|
||||
@ -2042,6 +2036,26 @@ class ShareNetworkDatabaseAPITestCase(BaseDatabaseAPITestCase):
|
||||
self._check_fields(expected=service,
|
||||
actual=result['security_services'][index])
|
||||
|
||||
@ddt.data([{'id': 'fake_id_1', 'availability_zone_id': 'None'}],
|
||||
[{'id': 'fake_id_2', 'availability_zone_id': 'None'},
|
||||
{'id': 'fake_id_3', 'availability_zone_id': 'fake_az_id'}])
|
||||
def test_get_with_subnets(self, subnets):
|
||||
db_api.share_network_create(self.fake_context, self.share_nw_dict)
|
||||
|
||||
for subnet in subnets:
|
||||
subnet['share_network_id'] = self.share_nw_dict['id']
|
||||
db_api.share_network_subnet_create(self.fake_context, subnet)
|
||||
|
||||
result = db_api.share_network_get(self.fake_context,
|
||||
self.share_nw_dict['id'])
|
||||
|
||||
self.assertEqual(len(subnets),
|
||||
len(result['share_network_subnets']))
|
||||
|
||||
for index, subnet in enumerate(subnets):
|
||||
self._check_fields(expected=subnet,
|
||||
actual=result['share_network_subnets'][index])
|
||||
|
||||
def test_get_not_found(self):
|
||||
self.assertRaises(exception.ShareNetworkNotFound,
|
||||
db_api.share_network_get,
|
||||
@ -2092,7 +2106,7 @@ class ShareNetworkDatabaseAPITestCase(BaseDatabaseAPITestCase):
|
||||
share_network_dict = dict(self.share_nw_dict)
|
||||
fake_id = 'fake_id%s' % index
|
||||
share_network_dict.update({'id': fake_id,
|
||||
'neutron_subnet_id': fake_id})
|
||||
'project_id': fake_id})
|
||||
share_networks.append(share_network_dict)
|
||||
db_api.share_network_create(self.fake_context, share_network_dict)
|
||||
index += 1
|
||||
@ -2107,7 +2121,6 @@ class ShareNetworkDatabaseAPITestCase(BaseDatabaseAPITestCase):
|
||||
share_nw_dict2 = dict(self.share_nw_dict)
|
||||
share_nw_dict2['id'] = 'fake share nw id2'
|
||||
share_nw_dict2['project_id'] = 'fake project 2'
|
||||
share_nw_dict2['neutron_subnet_id'] = 'fake subnet id2'
|
||||
db_api.share_network_create(self.fake_context, self.share_nw_dict)
|
||||
db_api.share_network_create(self.fake_context, share_nw_dict2)
|
||||
|
||||
@ -2269,6 +2282,155 @@ class ShareNetworkDatabaseAPITestCase(BaseDatabaseAPITestCase):
|
||||
self.assertEqual(0, len(result['share_instances']))
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class ShareNetworkSubnetDatabaseAPITestCase(BaseDatabaseAPITestCase):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ShareNetworkSubnetDatabaseAPITestCase, self).__init__(
|
||||
*args, **kwargs)
|
||||
self.fake_context = context.RequestContext(user_id='fake user',
|
||||
project_id='fake project',
|
||||
is_admin=False)
|
||||
|
||||
def setUp(self):
|
||||
super(ShareNetworkSubnetDatabaseAPITestCase, self).setUp()
|
||||
self.subnet_dict = {'id': 'fake network id',
|
||||
'neutron_net_id': 'fake net id',
|
||||
'neutron_subnet_id': 'fake subnet id',
|
||||
'network_type': 'vlan',
|
||||
'segmentation_id': 1000,
|
||||
'share_network_id': 'fake_id',
|
||||
'cidr': '10.0.0.0/24',
|
||||
'ip_version': 4,
|
||||
'availability_zone_id': None}
|
||||
|
||||
def test_create(self):
|
||||
result = db_api.share_network_subnet_create(
|
||||
self.fake_context, self.subnet_dict)
|
||||
self._check_fields(expected=self.subnet_dict, actual=result)
|
||||
|
||||
def test_create_duplicated_id(self):
|
||||
db_api.share_network_subnet_create(self.fake_context, self.subnet_dict)
|
||||
|
||||
self.assertRaises(db_exception.DBDuplicateEntry,
|
||||
db_api.share_network_subnet_create,
|
||||
self.fake_context,
|
||||
self.subnet_dict)
|
||||
|
||||
def test_get(self):
|
||||
db_api.share_network_subnet_create(self.fake_context, self.subnet_dict)
|
||||
|
||||
result = db_api.share_network_subnet_get(self.fake_context,
|
||||
self.subnet_dict['id'])
|
||||
self._check_fields(expected=self.subnet_dict, actual=result)
|
||||
|
||||
@ddt.data([{'id': 'fake_id_1', 'identifier': 'fake_identifier',
|
||||
'host': 'fake_host'}],
|
||||
[{'id': 'fake_id_2', 'identifier': 'fake_identifier',
|
||||
'host': 'fake_host'},
|
||||
{'id': 'fake_id_3', 'identifier': 'fake_identifier',
|
||||
'host': 'fake_host'}])
|
||||
def test_get_with_share_servers(self, share_servers):
|
||||
db_api.share_network_subnet_create(self.fake_context,
|
||||
self.subnet_dict)
|
||||
|
||||
for share_server in share_servers:
|
||||
share_server['share_network_subnet_id'] = self.subnet_dict['id']
|
||||
db_api.share_server_create(self.fake_context, share_server)
|
||||
|
||||
result = db_api.share_network_subnet_get(self.fake_context,
|
||||
self.subnet_dict['id'])
|
||||
|
||||
self.assertEqual(len(share_servers),
|
||||
len(result['share_servers']))
|
||||
|
||||
for index, share_server in enumerate(share_servers):
|
||||
self._check_fields(expected=share_server,
|
||||
actual=result['share_servers'][index])
|
||||
|
||||
def test_get_not_found(self):
|
||||
db_api.share_network_subnet_create(self.fake_context, self.subnet_dict)
|
||||
|
||||
self.assertRaises(exception.ShareNetworkSubnetNotFound,
|
||||
db_api.share_network_subnet_get,
|
||||
self.fake_context,
|
||||
'fake_id')
|
||||
|
||||
def test_delete(self):
|
||||
db_api.share_network_subnet_create(self.fake_context, self.subnet_dict)
|
||||
db_api.share_network_subnet_delete(self.fake_context,
|
||||
self.subnet_dict['id'])
|
||||
|
||||
self.assertRaises(exception.ShareNetworkSubnetNotFound,
|
||||
db_api.share_network_subnet_delete,
|
||||
self.fake_context,
|
||||
self.subnet_dict['id'])
|
||||
|
||||
def test_delete_not_found(self):
|
||||
self.assertRaises(exception.ShareNetworkSubnetNotFound,
|
||||
db_api.share_network_subnet_delete,
|
||||
self.fake_context,
|
||||
'fake_id')
|
||||
|
||||
def test_update(self):
|
||||
update_dict = {
|
||||
'gateway': 'fake_gateway',
|
||||
'ip_version': 6,
|
||||
'mtu': ''
|
||||
}
|
||||
|
||||
db_api.share_network_subnet_create(self.fake_context, self.subnet_dict)
|
||||
db_api.share_network_subnet_update(
|
||||
self.fake_context, self.subnet_dict['id'], update_dict)
|
||||
|
||||
result = db_api.share_network_subnet_get(self.fake_context,
|
||||
self.subnet_dict['id'])
|
||||
self._check_fields(expected=update_dict, actual=result)
|
||||
|
||||
def test_update_not_found(self):
|
||||
self.assertRaises(exception.ShareNetworkSubnetNotFound,
|
||||
db_api.share_network_subnet_update,
|
||||
self.fake_context,
|
||||
self.subnet_dict['id'],
|
||||
{})
|
||||
|
||||
@ddt.data([{'id': 'sn_id1', 'project_id': 'fake', 'user_id': 'fake'}],
|
||||
[{'id': 'fake_id', 'project_id': 'fake', 'user_id': 'fake'},
|
||||
{'id': 'sn_id2', 'project_id': 'fake', 'user_id': 'fake'}])
|
||||
def test_get_all_by_share_network(self, share_networks):
|
||||
|
||||
for idx, share_network in enumerate(share_networks):
|
||||
self.subnet_dict['share_network_id'] = share_network['id']
|
||||
self.subnet_dict['id'] = 'fake_id%s' % idx
|
||||
|
||||
db_api.share_network_create(self.fake_context, share_network)
|
||||
db_api.share_network_subnet_create(self.fake_context,
|
||||
self.subnet_dict)
|
||||
for share_network in share_networks:
|
||||
subnets = db_api.share_network_subnet_get_all_by_share_network(
|
||||
self.fake_context, share_network['id'])
|
||||
self.assertEqual(1, len(subnets))
|
||||
|
||||
def test_get_by_availability_zone_id(self):
|
||||
az = db_api.availability_zone_create_if_not_exist(self.fake_context,
|
||||
'fake_zone_id')
|
||||
self.subnet_dict['availability_zone_id'] = az['id']
|
||||
db_api.share_network_subnet_create(self.fake_context, self.subnet_dict)
|
||||
|
||||
result = db_api.share_network_subnet_get_by_availability_zone_id(
|
||||
self.fake_context, self.subnet_dict['share_network_id'], az['id'])
|
||||
|
||||
self._check_fields(expected=self.subnet_dict, actual=result)
|
||||
|
||||
def test_get_default_subnet(self):
|
||||
db_api.share_network_subnet_create(self.fake_context, self.subnet_dict)
|
||||
|
||||
result = db_api.share_network_subnet_get_default_subnet(
|
||||
self.fake_context, self.subnet_dict['share_network_id'])
|
||||
|
||||
self._check_fields(expected=self.subnet_dict, actual=result)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class SecurityServiceDatabaseAPITestCase(BaseDatabaseAPITestCase):
|
||||
|
||||
@ -2437,7 +2599,8 @@ class ShareServerDatabaseAPITestCase(test.TestCase):
|
||||
expected = db_utils.create_share_server()
|
||||
server = db_api.share_server_get(self.ctxt, expected['id'])
|
||||
self.assertEqual(expected['id'], server['id'])
|
||||
self.assertEqual(expected.share_network_id, server.share_network_id)
|
||||
self.assertEqual(expected.share_network_subnet_id,
|
||||
server.share_network_subnet_id)
|
||||
self.assertEqual(expected.host, server.host)
|
||||
self.assertEqual(expected.status, server.status)
|
||||
|
||||
@ -2449,7 +2612,8 @@ class ShareServerDatabaseAPITestCase(test.TestCase):
|
||||
def test_create(self):
|
||||
server = db_utils.create_share_server()
|
||||
self.assertTrue(server['id'])
|
||||
self.assertEqual(server.share_network_id, server['share_network_id'])
|
||||
self.assertEqual(server.share_network_subnet_id,
|
||||
server['share_network_subnet_id'])
|
||||
self.assertEqual(server.host, server['host'])
|
||||
self.assertEqual(server.status, server['status'])
|
||||
|
||||
@ -2488,21 +2652,31 @@ class ShareServerDatabaseAPITestCase(test.TestCase):
|
||||
self.ctxt, fake_id, {})
|
||||
|
||||
def test_get_all_by_host_and_share_net_valid(self):
|
||||
valid = {
|
||||
subnet_1 = {
|
||||
'id': '1',
|
||||
'share_network_id': '1',
|
||||
}
|
||||
subnet_2 = {
|
||||
'id': '2',
|
||||
'share_network_id': '2',
|
||||
}
|
||||
valid = {
|
||||
'share_network_subnet_id': '1',
|
||||
'host': 'host1',
|
||||
'status': constants.STATUS_ACTIVE,
|
||||
}
|
||||
invalid = {
|
||||
'share_network_id': '1',
|
||||
'share_network_subnet_id': '2',
|
||||
'host': 'host1',
|
||||
'status': constants.STATUS_ERROR,
|
||||
}
|
||||
other = {
|
||||
'share_network_id': '2',
|
||||
'share_network_subnet_id': '1',
|
||||
'host': 'host2',
|
||||
'status': constants.STATUS_ACTIVE,
|
||||
}
|
||||
db_utils.create_share_network_subnet(**subnet_1)
|
||||
db_utils.create_share_network_subnet(**subnet_2)
|
||||
valid = db_utils.create_share_server(**valid)
|
||||
db_utils.create_share_server(**invalid)
|
||||
db_utils.create_share_server(**other)
|
||||
@ -2572,7 +2746,7 @@ class ShareServerDatabaseAPITestCase(test.TestCase):
|
||||
|
||||
def test_get_with_details(self):
|
||||
values = {
|
||||
'share_network_id': 'fake-share-net-id',
|
||||
'share_network_subnet_id': 'fake-share-net-id',
|
||||
'host': 'hostname',
|
||||
'status': constants.STATUS_ACTIVE,
|
||||
}
|
||||
@ -2584,7 +2758,8 @@ class ShareServerDatabaseAPITestCase(test.TestCase):
|
||||
db_api.share_server_backend_details_set(self.ctxt, srv_id, details)
|
||||
server = db_api.share_server_get(self.ctxt, srv_id)
|
||||
self.assertEqual(srv_id, server['id'])
|
||||
self.assertEqual(values['share_network_id'], server.share_network_id)
|
||||
self.assertEqual(values['share_network_subnet_id'],
|
||||
server.share_network_subnet_id)
|
||||
self.assertEqual(values['host'], server.host)
|
||||
self.assertEqual(values['status'], server.status)
|
||||
self.assertDictMatch(server['backend_details'], details)
|
||||
|
@ -212,7 +212,7 @@ def create_share_server(**kwargs):
|
||||
backend_details = kwargs.pop('backend_details', {})
|
||||
srv = {
|
||||
'host': 'host1',
|
||||
'share_network_id': 'fake_srv_id',
|
||||
'share_network_subnet_id': 'fake_srv_id',
|
||||
'status': constants.STATUS_ACTIVE
|
||||
}
|
||||
share_srv = _create_db_row(db.share_server_create, srv, kwargs)
|
||||
@ -251,19 +251,31 @@ def create_share_network(**kwargs):
|
||||
net = {
|
||||
'user_id': 'fake',
|
||||
'project_id': 'fake',
|
||||
'neutron_net_id': 'fake-neutron-net',
|
||||
'neutron_subnet_id': 'fake-neutron-subnet',
|
||||
'status': 'new',
|
||||
'network_type': 'vlan',
|
||||
'segmentation_id': 1000,
|
||||
'cidr': '10.0.0.0/24',
|
||||
'ip_version': 4,
|
||||
'name': 'whatever',
|
||||
'description': 'fake description',
|
||||
}
|
||||
return _create_db_row(db.share_network_create, net, kwargs)
|
||||
|
||||
|
||||
def create_share_network_subnet(**kwargs):
|
||||
"""Create a share network subnet object."""
|
||||
subnet = {
|
||||
'id': 'fake_sns_id',
|
||||
'neutron_net_id': 'fake-neutron-net',
|
||||
'neutron_subnet_id': 'fake-neutron-subnet',
|
||||
'network_type': 'vlan',
|
||||
'segmentation_id': 1000,
|
||||
'cidr': '10.0.0.0/24',
|
||||
'ip_version': 4,
|
||||
'availability_zone_id': 'fake_zone_id',
|
||||
'share_network_id': 'fake_sn_id',
|
||||
'gateway': None,
|
||||
'mtu': None
|
||||
}
|
||||
return _create_db_row(db.share_network_subnet_create, subnet, kwargs)
|
||||
|
||||
|
||||
def create_security_service(**kwargs):
|
||||
share_network_id = kwargs.pop('share_network_id', None)
|
||||
service = {
|
||||
|
@ -302,7 +302,7 @@ def fake_share_server_get():
|
||||
'status': constants.STATUS_ACTIVE,
|
||||
'updated_at': None,
|
||||
'host': 'fake_host',
|
||||
'share_network_id': 'fake_sn_id',
|
||||
'share_network_subnet_id': 'fake_sn_id',
|
||||
'share_network_name': 'fake_sn_name',
|
||||
'project_id': 'fake_project_id',
|
||||
'id': 'fake_share_server_id',
|
||||
|
@ -79,15 +79,10 @@ fake_neutron_subnet = {
|
||||
'gateway_ip': '10.0.0.1',
|
||||
}
|
||||
|
||||
fake_share_network = {
|
||||
'id': 'fake nw info id',
|
||||
fake_share_network_subnet = {
|
||||
'id': 'fake nw subnet id',
|
||||
'neutron_subnet_id': fake_neutron_network['subnets'][0],
|
||||
'neutron_net_id': fake_neutron_network['id'],
|
||||
'project_id': 'fake project id',
|
||||
'status': 'test_subnet_status',
|
||||
'name': 'fake name',
|
||||
'description': 'fake description',
|
||||
'security_services': [],
|
||||
'network_type': 'fake_network_type',
|
||||
'segmentation_id': 1234,
|
||||
'ip_version': 4,
|
||||
@ -96,6 +91,16 @@ fake_share_network = {
|
||||
'mtu': 1509,
|
||||
}
|
||||
|
||||
fake_share_network = {
|
||||
'id': 'fake nw info id',
|
||||
'project_id': 'fake project id',
|
||||
'status': 'test_subnet_status',
|
||||
'name': 'fake name',
|
||||
'description': 'fake description',
|
||||
'security_services': [],
|
||||
'subnets': [fake_share_network_subnet],
|
||||
}
|
||||
|
||||
fake_share_server = {
|
||||
'id': 'fake nw info id',
|
||||
'status': 'test_server_status',
|
||||
@ -111,11 +116,11 @@ fake_network_allocation = {
|
||||
'mac_address': fake_neutron_port['mac_address'],
|
||||
'status': constants.STATUS_ACTIVE,
|
||||
'label': 'user',
|
||||
'network_type': fake_share_network['network_type'],
|
||||
'segmentation_id': fake_share_network['segmentation_id'],
|
||||
'ip_version': fake_share_network['ip_version'],
|
||||
'cidr': fake_share_network['cidr'],
|
||||
'gateway': fake_share_network['gateway'],
|
||||
'network_type': fake_share_network_subnet['network_type'],
|
||||
'segmentation_id': fake_share_network_subnet['segmentation_id'],
|
||||
'ip_version': fake_share_network_subnet['ip_version'],
|
||||
'cidr': fake_share_network_subnet['cidr'],
|
||||
'gateway': fake_share_network_subnet['gateway'],
|
||||
'mtu': 1509,
|
||||
}
|
||||
|
||||
@ -230,17 +235,18 @@ class NeutronNetworkPluginTest(test.TestCase):
|
||||
self.fake_context,
|
||||
fake_share_server,
|
||||
fake_share_network,
|
||||
fake_share_network_subnet,
|
||||
allocation_info={'count': 1})
|
||||
|
||||
has_provider_nw_ext.assert_any_call()
|
||||
save_nw_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
fake_share_network_subnet)
|
||||
save_subnet_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
fake_share_network_subnet)
|
||||
self.plugin.neutron_api.create_port.assert_called_once_with(
|
||||
fake_share_network['project_id'],
|
||||
network_id=fake_share_network['neutron_net_id'],
|
||||
subnet_id=fake_share_network['neutron_subnet_id'],
|
||||
network_id=fake_share_network_subnet['neutron_net_id'],
|
||||
subnet_id=fake_share_network_subnet['neutron_subnet_id'],
|
||||
device_owner='manila:share',
|
||||
device_id=fake_share_network['id'])
|
||||
db_api.network_allocation_create.assert_called_once_with(
|
||||
@ -270,22 +276,22 @@ class NeutronNetworkPluginTest(test.TestCase):
|
||||
with mock.patch.object(self.plugin.neutron_api, 'create_port',
|
||||
mock.Mock(return_value=fake_neutron_port)):
|
||||
self.plugin.allocate_network(
|
||||
self.fake_context,
|
||||
fake_share_server,
|
||||
fake_share_network,
|
||||
count=2)
|
||||
self.fake_context, fake_share_server, fake_share_network,
|
||||
fake_share_network_subnet, count=2)
|
||||
|
||||
neutron_api_calls = [
|
||||
mock.call(fake_share_network['project_id'],
|
||||
network_id=fake_share_network['neutron_net_id'],
|
||||
subnet_id=fake_share_network['neutron_subnet_id'],
|
||||
device_owner='manila:share',
|
||||
device_id=fake_share_network['id']),
|
||||
mock.call(fake_share_network['project_id'],
|
||||
network_id=fake_share_network['neutron_net_id'],
|
||||
subnet_id=fake_share_network['neutron_subnet_id'],
|
||||
device_owner='manila:share',
|
||||
device_id=fake_share_network['id']),
|
||||
mock.call(
|
||||
fake_share_network['project_id'],
|
||||
network_id=fake_share_network_subnet['neutron_net_id'],
|
||||
subnet_id=fake_share_network_subnet['neutron_subnet_id'],
|
||||
device_owner='manila:share',
|
||||
device_id=fake_share_network['id']),
|
||||
mock.call(
|
||||
fake_share_network['project_id'],
|
||||
network_id=fake_share_network_subnet['neutron_net_id'],
|
||||
subnet_id=fake_share_network_subnet['neutron_subnet_id'],
|
||||
device_owner='manila:share',
|
||||
device_id=fake_share_network['id']),
|
||||
]
|
||||
db_api_calls = [
|
||||
mock.call(self.fake_context, fake_network_allocation),
|
||||
@ -342,7 +348,7 @@ class NeutronNetworkPluginTest(test.TestCase):
|
||||
neutron_ports[3]['fixed_ips'][0]['ip_address'] = '192.168.0.13'
|
||||
neutron_ports[3]['id'] = 'fake_port_id_3'
|
||||
|
||||
self.mock_object(self.plugin, '_verify_share_network')
|
||||
self.mock_object(self.plugin, '_verify_share_network_subnet')
|
||||
self.mock_object(self.plugin, '_store_neutron_net_info')
|
||||
|
||||
self.mock_object(self.plugin.neutron_api, 'list_ports',
|
||||
@ -366,14 +372,15 @@ class NeutronNetworkPluginTest(test.TestCase):
|
||||
|
||||
result = self.plugin.manage_network_allocations(
|
||||
self.fake_context, allocations, fake_share_server,
|
||||
fake_share_network)
|
||||
share_network_subnet=fake_share_network_subnet)
|
||||
|
||||
self.assertEqual(['fd12::2000'], result)
|
||||
|
||||
self.plugin.neutron_api.list_ports.assert_called_once_with(
|
||||
network_id=fake_share_network['neutron_net_id'],
|
||||
network_id=fake_share_network_subnet['neutron_net_id'],
|
||||
device_owner='manila:share',
|
||||
fixed_ips='subnet_id=' + fake_share_network['neutron_subnet_id'])
|
||||
fixed_ips='subnet_id=' +
|
||||
fake_share_network_subnet['neutron_subnet_id'])
|
||||
|
||||
db_api.network_allocation_get.assert_has_calls([
|
||||
mock.call(self.fake_context, 'fake_port_id_1', read_deleted=False),
|
||||
@ -385,15 +392,15 @@ class NeutronNetworkPluginTest(test.TestCase):
|
||||
port_dict_list = [{
|
||||
'share_server_id': fake_share_server['id'],
|
||||
'ip_address': x,
|
||||
'gateway': fake_share_network['gateway'],
|
||||
'gateway': fake_share_network_subnet['gateway'],
|
||||
'mac_address': fake_neutron_port['mac_address'],
|
||||
'status': constants.STATUS_ACTIVE,
|
||||
'label': 'user',
|
||||
'network_type': fake_share_network['network_type'],
|
||||
'segmentation_id': fake_share_network['segmentation_id'],
|
||||
'ip_version': fake_share_network['ip_version'],
|
||||
'cidr': fake_share_network['cidr'],
|
||||
'mtu': fake_share_network['mtu'],
|
||||
'network_type': fake_share_network_subnet['network_type'],
|
||||
'segmentation_id': fake_share_network_subnet['segmentation_id'],
|
||||
'ip_version': fake_share_network_subnet['ip_version'],
|
||||
'cidr': fake_share_network_subnet['cidr'],
|
||||
'mtu': fake_share_network_subnet['mtu'],
|
||||
} for x in ['192.168.0.11', '192.168.0.12']]
|
||||
|
||||
if side_effect:
|
||||
@ -415,11 +422,11 @@ class NeutronNetworkPluginTest(test.TestCase):
|
||||
port_dict_list[1], read_deleted=True)
|
||||
])
|
||||
|
||||
self.plugin._verify_share_network.assert_called_once_with(
|
||||
fake_share_server['id'], fake_share_network)
|
||||
self.plugin._verify_share_network_subnet.assert_called_once_with(
|
||||
fake_share_server['id'], fake_share_network_subnet)
|
||||
|
||||
self.plugin._store_neutron_net_info(
|
||||
self.fake_context, fake_share_network)
|
||||
self.fake_context, fake_share_network_subnet)
|
||||
|
||||
def test__get_ports_respective_to_ips_multiple_fixed_ips(self):
|
||||
self.mock_object(plugin.LOG, 'warning')
|
||||
@ -462,7 +469,8 @@ class NeutronNetworkPluginTest(test.TestCase):
|
||||
self.assertRaises(
|
||||
exception.ManageShareServerError,
|
||||
self.plugin.manage_network_allocations, self.fake_context,
|
||||
allocations, fake_share_server, fake_share_network)
|
||||
allocations, fake_share_server, fake_share_network,
|
||||
fake_share_network_subnet)
|
||||
|
||||
db_api.network_allocation_get.assert_called_once_with(
|
||||
self.fake_context, 'fake_port_id_1', read_deleted=False)
|
||||
@ -533,7 +541,7 @@ class NeutronNetworkPluginTest(test.TestCase):
|
||||
{'status': constants.STATUS_ERROR})
|
||||
delete_port.stop()
|
||||
|
||||
@mock.patch.object(db_api, 'share_network_update', mock.Mock())
|
||||
@mock.patch.object(db_api, 'share_network_subnet_update', mock.Mock())
|
||||
def test_save_neutron_network_data(self):
|
||||
neutron_nw_info = {
|
||||
'provider:network_type': 'vlan',
|
||||
@ -550,16 +558,16 @@ class NeutronNetworkPluginTest(test.TestCase):
|
||||
'get_network',
|
||||
mock.Mock(return_value=neutron_nw_info)):
|
||||
self.plugin._save_neutron_network_data(self.fake_context,
|
||||
fake_share_network)
|
||||
fake_share_network_subnet)
|
||||
|
||||
self.plugin.neutron_api.get_network.assert_called_once_with(
|
||||
fake_share_network['neutron_net_id'])
|
||||
self.plugin.db.share_network_update.assert_called_once_with(
|
||||
fake_share_network_subnet['neutron_net_id'])
|
||||
self.plugin.db.share_network_subnet_update.assert_called_once_with(
|
||||
self.fake_context,
|
||||
fake_share_network['id'],
|
||||
fake_share_network_subnet['id'],
|
||||
share_nw_update_dict)
|
||||
|
||||
@mock.patch.object(db_api, 'share_network_update', mock.Mock())
|
||||
@mock.patch.object(db_api, 'share_network_subnet_update', mock.Mock())
|
||||
def test_save_neutron_network_data_multi_segment(self):
|
||||
share_nw_update_dict = {
|
||||
'network_type': 'vlan',
|
||||
@ -577,13 +585,13 @@ class NeutronNetworkPluginTest(test.TestCase):
|
||||
|
||||
with test_utils.create_temp_config_with_opts(config_data):
|
||||
self.plugin._save_neutron_network_data(self.fake_context,
|
||||
fake_share_network)
|
||||
fake_share_network_subnet)
|
||||
|
||||
self.plugin.neutron_api.get_network.assert_called_once_with(
|
||||
fake_share_network['neutron_net_id'])
|
||||
self.plugin.db.share_network_update.assert_called_once_with(
|
||||
fake_share_network_subnet['neutron_net_id'])
|
||||
self.plugin.db.share_network_subnet_update.assert_called_once_with(
|
||||
self.fake_context,
|
||||
fake_share_network['id'],
|
||||
fake_share_network_subnet['id'],
|
||||
share_nw_update_dict)
|
||||
|
||||
@mock.patch.object(db_api, 'share_network_update', mock.Mock())
|
||||
@ -600,7 +608,7 @@ class NeutronNetworkPluginTest(test.TestCase):
|
||||
with test_utils.create_temp_config_with_opts(config_data):
|
||||
self.assertRaises(exception.NetworkBadConfigurationException,
|
||||
self.plugin._save_neutron_network_data,
|
||||
self.fake_context, fake_share_network)
|
||||
self.fake_context, fake_share_network_subnet)
|
||||
|
||||
@mock.patch.object(db_api, 'share_network_update', mock.Mock())
|
||||
def test_save_neutron_network_data_multi_segment_without_cfg(self):
|
||||
@ -609,9 +617,9 @@ class NeutronNetworkPluginTest(test.TestCase):
|
||||
|
||||
self.assertRaises(exception.NetworkBadConfigurationException,
|
||||
self.plugin._save_neutron_network_data,
|
||||
self.fake_context, fake_share_network)
|
||||
self.fake_context, fake_share_network_subnet)
|
||||
|
||||
@mock.patch.object(db_api, 'share_network_update', mock.Mock())
|
||||
@mock.patch.object(db_api, 'share_network_subnet_update', mock.Mock())
|
||||
def test_save_neutron_subnet_data(self):
|
||||
neutron_subnet_info = fake_neutron_subnet
|
||||
subnet_value = {
|
||||
@ -624,13 +632,13 @@ class NeutronNetworkPluginTest(test.TestCase):
|
||||
'get_subnet',
|
||||
mock.Mock(return_value=neutron_subnet_info)):
|
||||
self.plugin._save_neutron_subnet_data(self.fake_context,
|
||||
fake_share_network)
|
||||
fake_share_network_subnet)
|
||||
|
||||
self.plugin.neutron_api.get_subnet.assert_called_once_with(
|
||||
fake_share_network['neutron_subnet_id'])
|
||||
self.plugin.db.share_network_update.assert_called_once_with(
|
||||
fake_share_network_subnet['neutron_subnet_id'])
|
||||
self.plugin.db.share_network_subnet_update.assert_called_once_with(
|
||||
self.fake_context,
|
||||
fake_share_network['id'],
|
||||
fake_share_network_subnet['id'],
|
||||
subnet_value)
|
||||
|
||||
def test_has_network_provider_extension_true(self):
|
||||
@ -757,13 +765,13 @@ class NeutronSingleNetworkPluginTest(test.TestCase):
|
||||
'neutron_subnet_id': instance.subnet,
|
||||
}
|
||||
self.mock_object(
|
||||
instance.db, 'share_network_update',
|
||||
instance.db, 'share_network_subnet_update',
|
||||
mock.Mock(return_value='foo'))
|
||||
|
||||
instance._update_share_network_net_data(
|
||||
self.context, share_network_input)
|
||||
|
||||
instance.db.share_network_update.assert_called_once_with(
|
||||
instance.db.share_network_subnet_update.assert_called_once_with(
|
||||
self.context, share_network_input['id'], share_network_result)
|
||||
|
||||
@ddt.data(
|
||||
@ -793,23 +801,24 @@ class NeutronSingleNetworkPluginTest(test.TestCase):
|
||||
fake_neutron_port, fake_neutron_port]
|
||||
instance = self._get_neutron_network_plugin_instance()
|
||||
share_server = 'fake_share_server'
|
||||
share_network = 'fake_share_network'
|
||||
share_network_upd = 'updated_fake_share_network'
|
||||
share_network = {'id': 'fake_share_network'}
|
||||
share_network_subnet = {'id': 'fake_share_network_subnet'}
|
||||
share_network_subnet_upd = {'id': 'updated_fake_share_network_subnet'}
|
||||
count = 2
|
||||
device_owner = 'fake_device_owner'
|
||||
self.mock_object(
|
||||
instance, '_update_share_network_net_data',
|
||||
mock.Mock(return_value=share_network_upd))
|
||||
mock.Mock(return_value=share_network_subnet_upd))
|
||||
|
||||
instance.allocate_network(
|
||||
self.context, share_server, share_network, count=count,
|
||||
device_owner=device_owner)
|
||||
self.context, share_server, share_network, share_network_subnet,
|
||||
count=count, device_owner=device_owner)
|
||||
|
||||
instance._update_share_network_net_data.assert_called_once_with(
|
||||
self.context, share_network)
|
||||
self.context, share_network_subnet)
|
||||
plugin.NeutronNetworkPlugin.allocate_network.assert_called_once_with(
|
||||
self.context, share_server, share_network_upd, count=count,
|
||||
device_owner=device_owner)
|
||||
self.context, share_server, share_network,
|
||||
share_network_subnet_upd, count=count, device_owner=device_owner)
|
||||
|
||||
def test_manage_network_allocations(self):
|
||||
allocations = ['192.168.10.10', 'fd12::2000']
|
||||
@ -819,18 +828,20 @@ class NeutronSingleNetworkPluginTest(test.TestCase):
|
||||
mock.Mock(return_value=['fd12::2000']))
|
||||
self.mock_object(
|
||||
instance, '_update_share_network_net_data',
|
||||
mock.Mock(return_value=fake_share_network))
|
||||
mock.Mock(return_value=fake_share_network_subnet))
|
||||
|
||||
result = instance.manage_network_allocations(
|
||||
self.context, allocations, fake_share_server, fake_share_network)
|
||||
self.context, allocations, fake_share_server, fake_share_network,
|
||||
fake_share_network_subnet)
|
||||
|
||||
self.assertEqual(['fd12::2000'], result)
|
||||
|
||||
instance._update_share_network_net_data.assert_called_once_with(
|
||||
self.context, fake_share_network)
|
||||
self.context, fake_share_network_subnet)
|
||||
|
||||
parent.assert_called_once_with(
|
||||
self.context, allocations, fake_share_server, fake_share_network)
|
||||
self.context, allocations, fake_share_server, fake_share_network,
|
||||
fake_share_network_subnet)
|
||||
|
||||
def test_manage_network_allocations_admin(self):
|
||||
allocations = ['192.168.10.10', 'fd12::2000']
|
||||
@ -846,12 +857,14 @@ class NeutronSingleNetworkPluginTest(test.TestCase):
|
||||
}
|
||||
|
||||
result = instance.manage_network_allocations(
|
||||
self.context, allocations, fake_share_server, None)
|
||||
self.context, allocations, fake_share_server,
|
||||
share_network_subnet=share_network_dict)
|
||||
|
||||
self.assertEqual(['fd12::2000'], result)
|
||||
|
||||
parent.assert_called_once_with(
|
||||
self.context, allocations, fake_share_server, share_network_dict)
|
||||
self.context, allocations, fake_share_server, None,
|
||||
share_network_dict)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@ -943,18 +956,19 @@ class NeutronBindNetworkPluginTest(test.TestCase):
|
||||
self.fake_context,
|
||||
fake_share_server,
|
||||
fake_share_network,
|
||||
fake_share_network_subnet,
|
||||
allocation_info={'count': 1})
|
||||
|
||||
self.bind_plugin._has_provider_network_extension.assert_any_call()
|
||||
save_nw_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
fake_share_network_subnet)
|
||||
save_subnet_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
fake_share_network_subnet)
|
||||
expected_kwargs = {
|
||||
'binding:vnic_type': 'baremetal',
|
||||
'host_id': 'foohost1',
|
||||
'network_id': fake_share_network['neutron_net_id'],
|
||||
'subnet_id': fake_share_network['neutron_subnet_id'],
|
||||
'network_id': fake_share_network_subnet['neutron_net_id'],
|
||||
'subnet_id': fake_share_network_subnet['neutron_subnet_id'],
|
||||
'device_owner': 'manila:share',
|
||||
'device_id': fake_share_network['id'],
|
||||
}
|
||||
@ -1020,13 +1034,14 @@ class NeutronBindNetworkPluginTest(test.TestCase):
|
||||
self.mock_object(self.bind_plugin.neutron_api, 'get_subnet')
|
||||
self.bind_plugin.neutron_api.get_subnet.return_value = (
|
||||
fake_neutron_subnet)
|
||||
self.mock_object(db_api, 'share_network_update')
|
||||
self.mock_object(db_api, 'share_network_subnet_update')
|
||||
|
||||
with mock.patch.object(self.bind_plugin.neutron_api, 'create_port',
|
||||
mock.Mock(return_value=fake_neutron_port)):
|
||||
self.bind_plugin.allocate_network(
|
||||
self.fake_context,
|
||||
fake_share_server,
|
||||
fake_share_network,
|
||||
self.fake_share_network_multi,
|
||||
allocation_info={'count': 1})
|
||||
|
||||
@ -1044,7 +1059,7 @@ class NeutronBindNetworkPluginTest(test.TestCase):
|
||||
db_api.network_allocation_create.assert_called_once_with(
|
||||
self.fake_context,
|
||||
fake_network_allocation_multi)
|
||||
db_api.share_network_update.assert_called_with(
|
||||
db_api.share_network_subnet_update.assert_called_with(
|
||||
self.fake_context,
|
||||
fake_share_network_multi['id'],
|
||||
network_update_data)
|
||||
@ -1143,14 +1158,14 @@ class NeutronBindNetworkPluginTest(test.TestCase):
|
||||
instance = self._get_neutron_network_plugin_instance(config_data)
|
||||
|
||||
create_args = instance._get_port_create_args(fake_share_server,
|
||||
fake_share_network,
|
||||
fake_share_network_subnet,
|
||||
fake_device_owner)
|
||||
|
||||
expected_create_args = {
|
||||
'binding:vnic_type': 'baremetal',
|
||||
'host_id': fake_host_id,
|
||||
'network_id': fake_share_network['neutron_net_id'],
|
||||
'subnet_id': fake_share_network['neutron_subnet_id'],
|
||||
'network_id': fake_share_network_subnet['neutron_net_id'],
|
||||
'subnet_id': fake_share_network_subnet['neutron_subnet_id'],
|
||||
'device_owner': 'manila:' + fake_device_owner,
|
||||
'device_id': fake_share_server['id']
|
||||
}
|
||||
@ -1197,14 +1212,14 @@ class NeutronBindNetworkPluginTest(test.TestCase):
|
||||
instance = self._get_neutron_network_plugin_instance(config_data)
|
||||
|
||||
create_args = instance._get_port_create_args(fake_share_server,
|
||||
fake_share_network,
|
||||
fake_share_network_subnet,
|
||||
fake_device_owner)
|
||||
|
||||
expected_create_args = {
|
||||
'binding:vnic_type': 'baremetal',
|
||||
'host_id': fake_host_id,
|
||||
'network_id': fake_share_network['neutron_net_id'],
|
||||
'subnet_id': fake_share_network['neutron_subnet_id'],
|
||||
'network_id': fake_share_network_subnet['neutron_net_id'],
|
||||
'subnet_id': fake_share_network_subnet['neutron_subnet_id'],
|
||||
'device_owner': 'manila:' + fake_device_owner,
|
||||
'device_id': fake_share_server['id']
|
||||
}
|
||||
@ -1253,7 +1268,8 @@ class NeutronBindSingleNetworkPluginTest(test.TestCase):
|
||||
'port1', 'port2']
|
||||
instance = self._get_neutron_network_plugin_instance()
|
||||
share_server = 'fake_share_server'
|
||||
share_network = {'neutron_net_id': {}}
|
||||
share_network = {}
|
||||
share_network_subnet = {'neutron_net_id': {}}
|
||||
share_network_upd = {'neutron_net_id': {'upd': True}}
|
||||
count = 2
|
||||
device_owner = 'fake_device_owner'
|
||||
@ -1263,14 +1279,14 @@ class NeutronBindSingleNetworkPluginTest(test.TestCase):
|
||||
self.mock_object(instance, '_wait_for_ports_bind', mock.Mock())
|
||||
|
||||
instance.allocate_network(
|
||||
self.context, share_server, share_network, count=count,
|
||||
device_owner=device_owner)
|
||||
self.context, share_server, share_network, share_network_subnet,
|
||||
count=count, device_owner=device_owner)
|
||||
|
||||
instance._update_share_network_net_data.assert_called_once_with(
|
||||
self.context, share_network)
|
||||
self.context, share_network_subnet)
|
||||
plugin.NeutronNetworkPlugin.allocate_network.assert_called_once_with(
|
||||
self.context, share_server, share_network_upd, count=count,
|
||||
device_owner=device_owner)
|
||||
self.context, share_server, share_network, share_network_upd,
|
||||
count=count, device_owner=device_owner)
|
||||
instance._wait_for_ports_bind.assert_called_once_with(
|
||||
['port1', 'port2'], share_server)
|
||||
|
||||
@ -1360,7 +1376,7 @@ class NeutronBindSingleNetworkPluginTest(test.TestCase):
|
||||
|
||||
def test___update_share_network_net_data_different_values_empty(self):
|
||||
instance = self._get_neutron_single_network_plugin_instance()
|
||||
share_network_input = {
|
||||
share_network_subnet_input = {
|
||||
'id': 'fake_share_network_id',
|
||||
}
|
||||
share_network_result = {
|
||||
@ -1368,14 +1384,15 @@ class NeutronBindSingleNetworkPluginTest(test.TestCase):
|
||||
'neutron_subnet_id': instance.subnet,
|
||||
}
|
||||
self.mock_object(
|
||||
instance.db, 'share_network_update',
|
||||
instance.db, 'share_network_subnet_update',
|
||||
mock.Mock(return_value='foo'))
|
||||
|
||||
instance._update_share_network_net_data(
|
||||
self.context, share_network_input)
|
||||
self.context, share_network_subnet_input)
|
||||
|
||||
instance.db.share_network_update.assert_called_once_with(
|
||||
self.context, share_network_input['id'], share_network_result)
|
||||
instance.db.share_network_subnet_update.assert_called_once_with(
|
||||
self.context, share_network_subnet_input['id'],
|
||||
share_network_result)
|
||||
|
||||
@ddt.data(
|
||||
{'n': 'fake_net_id', 's': 'bar'},
|
||||
@ -1464,18 +1481,19 @@ class NeutronBindSingleNetworkPluginTest(test.TestCase):
|
||||
self.fake_context,
|
||||
fake_share_server,
|
||||
fake_share_network,
|
||||
fake_share_network_subnet,
|
||||
allocation_info={'count': 1})
|
||||
|
||||
self.bind_plugin._has_provider_network_extension.assert_any_call()
|
||||
save_nw_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
fake_share_network_subnet)
|
||||
save_subnet_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
fake_share_network_subnet)
|
||||
expected_kwargs = {
|
||||
'binding:vnic_type': 'baremetal',
|
||||
'host_id': 'foohost1',
|
||||
'network_id': fake_share_network['neutron_net_id'],
|
||||
'subnet_id': fake_share_network['neutron_subnet_id'],
|
||||
'network_id': fake_share_network_subnet['neutron_net_id'],
|
||||
'subnet_id': fake_share_network_subnet['neutron_subnet_id'],
|
||||
'device_owner': 'manila:share',
|
||||
'device_id': fake_share_network['id'],
|
||||
}
|
||||
@ -1575,14 +1593,14 @@ class NeutronBindSingleNetworkPluginTest(test.TestCase):
|
||||
instance = self._get_neutron_network_plugin_instance(config_data)
|
||||
|
||||
create_args = instance._get_port_create_args(fake_share_server,
|
||||
fake_share_network,
|
||||
fake_share_network_subnet,
|
||||
fake_device_owner)
|
||||
|
||||
expected_create_args = {
|
||||
'binding:vnic_type': 'baremetal',
|
||||
'host_id': fake_host_id,
|
||||
'network_id': fake_share_network['neutron_net_id'],
|
||||
'subnet_id': fake_share_network['neutron_subnet_id'],
|
||||
'network_id': fake_share_network_subnet['neutron_net_id'],
|
||||
'subnet_id': fake_share_network_subnet['neutron_subnet_id'],
|
||||
'device_owner': 'manila:' + fake_device_owner,
|
||||
'device_id': fake_share_server['id']
|
||||
}
|
||||
@ -1629,14 +1647,14 @@ class NeutronBindSingleNetworkPluginTest(test.TestCase):
|
||||
instance = self._get_neutron_network_plugin_instance(config_data)
|
||||
|
||||
create_args = instance._get_port_create_args(fake_share_server,
|
||||
fake_share_network,
|
||||
fake_share_network_subnet,
|
||||
fake_device_owner)
|
||||
|
||||
expected_create_args = {
|
||||
'binding:vnic_type': 'baremetal',
|
||||
'host_id': fake_host_id,
|
||||
'network_id': fake_share_network['neutron_net_id'],
|
||||
'subnet_id': fake_share_network['neutron_subnet_id'],
|
||||
'network_id': fake_share_network_subnet['neutron_net_id'],
|
||||
'subnet_id': fake_share_network_subnet['neutron_subnet_id'],
|
||||
'device_owner': 'manila:' + fake_device_owner,
|
||||
'device_id': fake_share_server['id']
|
||||
}
|
||||
@ -1690,20 +1708,21 @@ class NeutronBindNetworkPluginWithNormalTypeTest(test.TestCase):
|
||||
self.fake_context,
|
||||
fake_share_server,
|
||||
fake_share_network,
|
||||
fake_share_network_subnet,
|
||||
allocation_info={'count': 1})
|
||||
|
||||
self.bind_plugin._has_provider_network_extension.assert_any_call()
|
||||
save_nw_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
fake_share_network_subnet)
|
||||
save_subnet_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
fake_share_network_subnet)
|
||||
expected_kwargs = {
|
||||
'binding:vnic_type': 'normal',
|
||||
'host_id': 'foohost1',
|
||||
'network_id': fake_share_network['neutron_net_id'],
|
||||
'subnet_id': fake_share_network['neutron_subnet_id'],
|
||||
'network_id': fake_share_network_subnet['neutron_net_id'],
|
||||
'subnet_id': fake_share_network_subnet['neutron_subnet_id'],
|
||||
'device_owner': 'manila:share',
|
||||
'device_id': fake_share_network['id'],
|
||||
'device_id': fake_share_server['id'],
|
||||
}
|
||||
self.bind_plugin.neutron_api.create_port.assert_called_once_with(
|
||||
fake_share_network['project_id'], **expected_kwargs)
|
||||
@ -1776,18 +1795,19 @@ class NeutronBindSingleNetworkPluginWithNormalTypeTest(test.TestCase):
|
||||
self.fake_context,
|
||||
fake_share_server,
|
||||
fake_share_network,
|
||||
fake_share_network_subnet,
|
||||
allocation_info={'count': 1})
|
||||
|
||||
self.bind_plugin._has_provider_network_extension.assert_any_call()
|
||||
save_nw_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
fake_share_network_subnet)
|
||||
save_subnet_data.assert_called_once_with(self.fake_context,
|
||||
fake_share_network)
|
||||
fake_share_network_subnet)
|
||||
expected_kwargs = {
|
||||
'binding:vnic_type': 'normal',
|
||||
'host_id': 'foohost1',
|
||||
'network_id': fake_share_network['neutron_net_id'],
|
||||
'subnet_id': fake_share_network['neutron_subnet_id'],
|
||||
'network_id': fake_share_network_subnet['neutron_net_id'],
|
||||
'subnet_id': fake_share_network_subnet['neutron_subnet_id'],
|
||||
'device_owner': 'manila:share',
|
||||
'device_id': fake_share_network['id'],
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ fake_context = context.RequestContext(
|
||||
user_id='fake user', project_id='fake project', is_admin=False)
|
||||
fake_share_server = dict(id='fake_share_server_id')
|
||||
fake_share_network = dict(id='fake_share_network_id')
|
||||
fake_share_network_subnet = dict(id='fake_share_network_subnet_id')
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@ -305,14 +306,15 @@ class StandaloneNetworkPluginTest(test.TestCase):
|
||||
}
|
||||
with test_utils.create_temp_config_with_opts(data):
|
||||
instance = plugin.StandaloneNetworkPlugin()
|
||||
self.mock_object(instance.db, 'share_network_update')
|
||||
self.mock_object(instance.db, 'share_network_subnet_update')
|
||||
|
||||
allocations = instance.allocate_network(
|
||||
fake_context, fake_share_server, fake_share_network, count=0)
|
||||
fake_context, fake_share_server, fake_share_network,
|
||||
fake_share_network_subnet, count=0)
|
||||
|
||||
self.assertEqual([], allocations)
|
||||
instance.db.share_network_update.assert_called_once_with(
|
||||
fake_context, fake_share_network['id'],
|
||||
instance.db.share_network_subnet_update.assert_called_once_with(
|
||||
fake_context, fake_share_network_subnet['id'],
|
||||
dict(network_type=None, segmentation_id=None,
|
||||
cidr=six.text_type(instance.net.cidr),
|
||||
gateway=six.text_type(instance.gateway),
|
||||
@ -329,14 +331,15 @@ class StandaloneNetworkPluginTest(test.TestCase):
|
||||
}
|
||||
with test_utils.create_temp_config_with_opts(data):
|
||||
instance = plugin.StandaloneNetworkPlugin()
|
||||
self.mock_object(instance.db, 'share_network_update')
|
||||
self.mock_object(instance.db, 'share_network_subnet_update')
|
||||
|
||||
allocations = instance.allocate_network(
|
||||
fake_context, fake_share_server, fake_share_network, count=0)
|
||||
fake_context, fake_share_server, fake_share_network,
|
||||
fake_share_network_subnet, count=0)
|
||||
|
||||
self.assertEqual([], allocations)
|
||||
instance.db.share_network_update.assert_called_once_with(
|
||||
fake_context, fake_share_network['id'],
|
||||
instance.db.share_network_subnet_update.assert_called_once_with(
|
||||
fake_context, fake_share_network_subnet['id'],
|
||||
dict(network_type=None, segmentation_id=None,
|
||||
cidr=six.text_type(instance.net.cidr),
|
||||
gateway=six.text_type(instance.gateway),
|
||||
@ -354,14 +357,15 @@ class StandaloneNetworkPluginTest(test.TestCase):
|
||||
}
|
||||
with test_utils.create_temp_config_with_opts(data):
|
||||
instance = plugin.StandaloneNetworkPlugin()
|
||||
self.mock_object(instance.db, 'share_network_update')
|
||||
self.mock_object(instance.db, 'share_network_subnet_update')
|
||||
self.mock_object(instance.db, 'network_allocation_create')
|
||||
self.mock_object(
|
||||
instance.db, 'network_allocations_get_by_ip_address',
|
||||
mock.Mock(return_value=[]))
|
||||
|
||||
allocations = instance.allocate_network(
|
||||
fake_context, fake_share_server, fake_share_network)
|
||||
fake_context, fake_share_server, fake_share_network,
|
||||
fake_share_network_subnet)
|
||||
|
||||
self.assertEqual(1, len(allocations))
|
||||
na_data = {
|
||||
@ -372,8 +376,8 @@ class StandaloneNetworkPluginTest(test.TestCase):
|
||||
'ip_version': 4,
|
||||
'mtu': 1500,
|
||||
}
|
||||
instance.db.share_network_update.assert_called_once_with(
|
||||
fake_context, fake_share_network['id'], na_data)
|
||||
instance.db.share_network_subnet_update.assert_called_once_with(
|
||||
fake_context, fake_share_network_subnet['id'], na_data)
|
||||
instance.db.network_allocations_get_by_ip_address.assert_has_calls(
|
||||
[mock.call(fake_context, '10.0.0.2')])
|
||||
instance.db.network_allocation_create.assert_called_once_with(
|
||||
@ -400,14 +404,15 @@ class StandaloneNetworkPluginTest(test.TestCase):
|
||||
}
|
||||
with test_utils.create_temp_config_with_opts(data):
|
||||
instance = plugin.StandaloneNetworkPlugin()
|
||||
self.mock_object(instance.db, 'share_network_update')
|
||||
self.mock_object(instance.db, 'share_network_subnet_update')
|
||||
self.mock_object(instance.db, 'network_allocation_create')
|
||||
self.mock_object(
|
||||
instance.db, 'network_allocations_get_by_ip_address',
|
||||
mock.Mock(side_effect=fake_get_allocations_by_ip_address))
|
||||
|
||||
allocations = instance.allocate_network(
|
||||
ctxt, fake_share_server, fake_share_network, count=2)
|
||||
ctxt, fake_share_server, fake_share_network,
|
||||
fake_share_network_subnet, count=2)
|
||||
|
||||
self.assertEqual(2, len(allocations))
|
||||
na_data = {
|
||||
@ -418,8 +423,8 @@ class StandaloneNetworkPluginTest(test.TestCase):
|
||||
'ip_version': 4,
|
||||
'mtu': 1500,
|
||||
}
|
||||
instance.db.share_network_update.assert_called_once_with(
|
||||
ctxt, fake_share_network['id'], dict(**na_data))
|
||||
instance.db.share_network_subnet_update.assert_called_once_with(
|
||||
ctxt, fake_share_network_subnet['id'], dict(**na_data))
|
||||
instance.db.network_allocations_get_by_ip_address.assert_has_calls(
|
||||
[mock.call(ctxt, '10.0.0.2'), mock.call(ctxt, '10.0.0.3'),
|
||||
mock.call(ctxt, '10.0.0.4'), mock.call(ctxt, '10.0.0.5')])
|
||||
@ -445,7 +450,7 @@ class StandaloneNetworkPluginTest(test.TestCase):
|
||||
}
|
||||
with test_utils.create_temp_config_with_opts(data):
|
||||
instance = plugin.StandaloneNetworkPlugin()
|
||||
self.mock_object(instance.db, 'share_network_update')
|
||||
self.mock_object(instance.db, 'share_network_subnet_update')
|
||||
self.mock_object(instance.db, 'network_allocation_create')
|
||||
self.mock_object(
|
||||
instance.db, 'network_allocations_get_by_ip_address',
|
||||
@ -454,10 +459,11 @@ class StandaloneNetworkPluginTest(test.TestCase):
|
||||
self.assertRaises(
|
||||
exception.NetworkBadConfigurationException,
|
||||
instance.allocate_network,
|
||||
fake_context, fake_share_server, fake_share_network)
|
||||
fake_context, fake_share_server, fake_share_network,
|
||||
fake_share_network_subnet)
|
||||
|
||||
instance.db.share_network_update.assert_called_once_with(
|
||||
fake_context, fake_share_network['id'],
|
||||
instance.db.share_network_subnet_update.assert_called_once_with(
|
||||
fake_context, fake_share_network_subnet['id'],
|
||||
dict(network_type=None, segmentation_id=None,
|
||||
cidr=six.text_type(instance.net.cidr),
|
||||
gateway=six.text_type(instance.gateway),
|
||||
@ -484,12 +490,13 @@ class StandaloneNetworkPluginTest(test.TestCase):
|
||||
|
||||
instance = self._setup_manage_network_allocations(label=label)
|
||||
if not label:
|
||||
self.mock_object(instance, '_verify_share_network')
|
||||
self.mock_object(instance.db, 'share_network_update')
|
||||
self.mock_object(instance, '_verify_share_network_subnet')
|
||||
self.mock_object(instance.db, 'share_network_subnet_update')
|
||||
self.mock_object(instance.db, 'network_allocation_create')
|
||||
|
||||
result = instance.manage_network_allocations(
|
||||
fake_context, allocations, fake_share_server, fake_share_network)
|
||||
fake_context, allocations, fake_share_server,
|
||||
fake_share_network, fake_share_network_subnet)
|
||||
|
||||
self.assertEqual(['fd12::2000'], result)
|
||||
|
||||
@ -513,10 +520,10 @@ class StandaloneNetworkPluginTest(test.TestCase):
|
||||
data_list[1].update(network_data)
|
||||
|
||||
if not label:
|
||||
instance.db.share_network_update.assert_called_once_with(
|
||||
fake_context, fake_share_network['id'], network_data)
|
||||
instance._verify_share_network.assert_called_once_with(
|
||||
fake_share_server['id'], fake_share_network)
|
||||
instance.db.share_network_subnet_update.assert_called_once_with(
|
||||
fake_context, fake_share_network_subnet['id'], network_data)
|
||||
instance._verify_share_network_subnet.assert_called_once_with(
|
||||
fake_share_server['id'], fake_share_network_subnet)
|
||||
|
||||
instance.db.network_allocation_create.assert_has_calls([
|
||||
mock.call(fake_context, data_list[0]),
|
||||
|
@ -683,6 +683,128 @@ class ShareAPITestCase(test.TestCase):
|
||||
self.assertSubDictMatch(share_data,
|
||||
db_api.share_create.call_args[0][1])
|
||||
|
||||
@ddt.data(
|
||||
{'get_all_azs_return': [], 'subnet_by_az_side_effect': []},
|
||||
{'get_all_azs_return': [{'name': 'az1', 'id': 'az_id_1'}],
|
||||
'subnet_by_az_side_effect': [None]},
|
||||
{'get_all_azs_return': [{'name': 'az1', 'id': 'az_id_1'}],
|
||||
'subnet_by_az_side_effect': ['fake_sns_1']},
|
||||
{'get_all_azs_return': [{'name': 'az1', 'id': 'az_id_1'},
|
||||
{'name': 'az2', 'id': 'az_id_2'}],
|
||||
'subnet_by_az_side_effect': [None, 'fake_sns_2']}
|
||||
)
|
||||
@ddt.unpack
|
||||
def test__get_all_availability_zones_with_subnets(
|
||||
self, get_all_azs_return, subnet_by_az_side_effect):
|
||||
fake_share_network_id = 'fake_sn_id'
|
||||
self.mock_object(db_api, 'availability_zone_get_all',
|
||||
mock.Mock(return_value=get_all_azs_return))
|
||||
self.mock_object(db_api,
|
||||
'share_network_subnet_get_by_availability_zone_id',
|
||||
mock.Mock(side_effect=subnet_by_az_side_effect))
|
||||
expected_az_names = []
|
||||
expected_get_az_calls = []
|
||||
for index, value in enumerate(get_all_azs_return):
|
||||
expected_get_az_calls.append(mock.call(
|
||||
self.context, share_network_id=fake_share_network_id,
|
||||
availability_zone_id=value['id']))
|
||||
if subnet_by_az_side_effect[index] is not None:
|
||||
expected_az_names.append(value['name'])
|
||||
|
||||
get_all_subnets = self.api._get_all_availability_zones_with_subnets
|
||||
compatible_azs = get_all_subnets(self.context, fake_share_network_id)
|
||||
|
||||
db_api.availability_zone_get_all.assert_called_once_with(
|
||||
self.context)
|
||||
db_get_azs_with_subnet = (
|
||||
db_api.share_network_subnet_get_by_availability_zone_id)
|
||||
db_get_azs_with_subnet.assert_has_calls(expected_get_az_calls)
|
||||
|
||||
self.assertEqual(expected_az_names, compatible_azs)
|
||||
|
||||
@ddt.data(
|
||||
{'availability_zones': None, 'azs_with_subnet': ['fake_az_1']},
|
||||
{'availability_zones': ['fake_az_2'],
|
||||
'azs_with_subnet': ['fake_az_2']},
|
||||
{'availability_zones': ['fake_az_1', 'faze_az_2', 'fake_az_3'],
|
||||
'azs_with_subnet': ['fake_az_3']}
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_create_share_with_subnets(self, availability_zones,
|
||||
azs_with_subnet):
|
||||
share, share_data = self._setup_create_mocks()
|
||||
reservation = 'fake'
|
||||
self.mock_object(quota.QUOTAS, 'reserve',
|
||||
mock.Mock(return_value=reservation))
|
||||
self.mock_object(self.api, '_get_all_availability_zones_with_subnets',
|
||||
mock.Mock(return_value=azs_with_subnet))
|
||||
self.mock_object(quota.QUOTAS, 'commit')
|
||||
self.mock_object(self.api, 'create_instance')
|
||||
self.mock_object(db_api, 'share_get')
|
||||
fake_share_network_id = 'fake_sn_id'
|
||||
|
||||
if availability_zones:
|
||||
expected_azs = (
|
||||
[az for az in availability_zones if az in azs_with_subnet])
|
||||
else:
|
||||
expected_azs = azs_with_subnet
|
||||
|
||||
self.api.create(
|
||||
self.context,
|
||||
share_data['share_proto'],
|
||||
share_data['size'],
|
||||
share_data['display_name'],
|
||||
share_data['display_description'],
|
||||
share_network_id=fake_share_network_id,
|
||||
availability_zones=availability_zones)
|
||||
share['status'] = constants.STATUS_CREATING
|
||||
share['host'] = None
|
||||
|
||||
quota.QUOTAS.reserve.assert_called_once()
|
||||
get_all_azs_sns = self.api._get_all_availability_zones_with_subnets
|
||||
get_all_azs_sns.assert_called_once_with(
|
||||
self.context, fake_share_network_id)
|
||||
quota.QUOTAS.commit.assert_called_once()
|
||||
self.api.create_instance.assert_called_once_with(
|
||||
self.context, share, share_network_id=fake_share_network_id,
|
||||
host=None, availability_zone=None, share_group=None,
|
||||
share_group_snapshot_member=None, share_type_id=None,
|
||||
availability_zones=expected_azs
|
||||
)
|
||||
db_api.share_get.assert_called_once()
|
||||
|
||||
@ddt.data(
|
||||
{'availability_zones': None, 'azs_with_subnet': []},
|
||||
{'availability_zones': ['fake_az_1'],
|
||||
'azs_with_subnet': ['fake_az_2']}
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_create_share_with_subnets_invalid_azs(self, availability_zones,
|
||||
azs_with_subnet):
|
||||
share, share_data = self._setup_create_mocks()
|
||||
reservation = 'fake'
|
||||
self.mock_object(quota.QUOTAS, 'reserve',
|
||||
mock.Mock(return_value=reservation))
|
||||
self.mock_object(self.api, '_get_all_availability_zones_with_subnets',
|
||||
mock.Mock(return_value=azs_with_subnet))
|
||||
self.mock_object(quota.QUOTAS, 'commit')
|
||||
self.mock_object(self.api, 'create_instance')
|
||||
self.mock_object(db_api, 'share_get')
|
||||
fake_share_network_id = 'fake_sn_id'
|
||||
|
||||
self.assertRaises(
|
||||
exception.InvalidInput,
|
||||
self.api.create,
|
||||
self.context, share_data['share_proto'], share_data['size'],
|
||||
share_data['display_name'], share_data['display_description'],
|
||||
share_network_id=fake_share_network_id,
|
||||
availability_zones=availability_zones)
|
||||
|
||||
quota.QUOTAS.reserve.assert_called_once()
|
||||
get_all_azs_sns = self.api._get_all_availability_zones_with_subnets
|
||||
get_all_azs_sns.assert_called_once_with(
|
||||
self.context, fake_share_network_id)
|
||||
|
||||
@ddt.data(
|
||||
None, '', 'fake', 'nfsfake', 'cifsfake', 'glusterfsfake', 'hdfsfake')
|
||||
def test_create_share_invalid_protocol(self, proto):
|
||||
@ -868,17 +990,31 @@ class ShareAPITestCase(test.TestCase):
|
||||
self.api.get_share_attributes_from_share_type,
|
||||
share_type)
|
||||
|
||||
@ddt.data('dr', 'readable', None)
|
||||
def test_manage_new(self, replication_type):
|
||||
@ddt.data(
|
||||
{'replication_type': 'dr', 'dhss': False, 'share_server_id': None},
|
||||
{'replication_type': 'readable', 'dhss': False,
|
||||
'share_server_id': None},
|
||||
{'replication_type': None, 'dhss': False, 'share_server_id': None},
|
||||
{'replication_type': None, 'dhss': True, 'share_server_id': 'fake'}
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_manage_new(self, replication_type, dhss, share_server_id):
|
||||
share_data = {
|
||||
'host': 'fake',
|
||||
'export_location': 'fake',
|
||||
'share_proto': 'fake',
|
||||
'share_type_id': 'fake',
|
||||
}
|
||||
if dhss:
|
||||
share_data['share_server_id'] = share_server_id
|
||||
driver_options = {}
|
||||
date = datetime.datetime(1, 1, 1, 1, 1, 1)
|
||||
timeutils.utcnow.return_value = date
|
||||
fake_subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id='fake')
|
||||
share_server = db_utils.create_share_server(
|
||||
status=constants.STATUS_ACTIVE, id=share_server_id,
|
||||
share_network_subnet_id=fake_subnet['id'])
|
||||
fake_share_data = {
|
||||
'id': 'fakeid',
|
||||
'status': constants.STATUS_CREATING,
|
||||
@ -891,7 +1027,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
'create_share_from_snapshot_support': False,
|
||||
'revert_to_snapshot_support': False,
|
||||
'mount_snapshot_support': False,
|
||||
'driver_handles_share_servers': False,
|
||||
'driver_handles_share_servers': dhss,
|
||||
},
|
||||
}
|
||||
|
||||
@ -905,6 +1041,10 @@ class ShareAPITestCase(test.TestCase):
|
||||
mock.Mock(return_value=share))
|
||||
self.mock_object(share_types, 'get_share_type',
|
||||
mock.Mock(return_value=fake_type))
|
||||
self.mock_object(db_api, 'share_server_get',
|
||||
mock.Mock(return_value=share_server))
|
||||
self.mock_object(db_api, 'share_network_subnet_get',
|
||||
mock.Mock(return_value=fake_subnet))
|
||||
self.mock_object(self.api, 'get_all', mock.Mock(return_value=[]))
|
||||
|
||||
self.api.manage(self.context, copy.deepcopy(share_data),
|
||||
@ -929,6 +1069,9 @@ class ShareAPITestCase(test.TestCase):
|
||||
share, fake_type, size=0, share_proto=share_data['share_proto'],
|
||||
host=share_data['host'])
|
||||
|
||||
if dhss:
|
||||
share_data.update({
|
||||
'share_network_id': fake_subnet['share_network_id']})
|
||||
export_location = share_data.pop('export_location')
|
||||
self.api.get_all.assert_called_once_with(self.context, mock.ANY)
|
||||
db_api.share_create.assert_called_once_with(self.context, share_data)
|
||||
@ -938,6 +1081,11 @@ class ShareAPITestCase(test.TestCase):
|
||||
)
|
||||
self.scheduler_rpcapi.manage_share.assert_called_once_with(
|
||||
self.context, share['id'], driver_options, expected_request_spec)
|
||||
if dhss:
|
||||
db_api.share_server_get.assert_called_once_with(
|
||||
self.context, share_data['share_server_id'])
|
||||
db_api.share_network_subnet_get.assert_called_once_with(
|
||||
self.context, share_server['share_network_subnet_id'])
|
||||
|
||||
@ddt.data((True, exception.InvalidInput, True),
|
||||
(True, exception.InvalidInput, False),
|
||||
@ -1387,10 +1535,14 @@ class ShareAPITestCase(test.TestCase):
|
||||
fake_share_network = {
|
||||
'id': 'fake_net_id'
|
||||
}
|
||||
fake_share_net_subnet = {
|
||||
'id': 'fake_subnet_id',
|
||||
'share_network_id': fake_share_network['id']
|
||||
}
|
||||
identifier = 'fake_identifier'
|
||||
values = {
|
||||
'host': host,
|
||||
'share_network_id': fake_share_network['id'],
|
||||
'share_network_subnet_id': fake_share_net_subnet['id'],
|
||||
'status': constants.STATUS_MANAGING,
|
||||
'is_auto_deletable': False,
|
||||
'identifier': identifier,
|
||||
@ -1400,7 +1552,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
'id': 'fake_server_id',
|
||||
'status': constants.STATUS_MANAGING,
|
||||
'host': host,
|
||||
'share_network_id': fake_share_network['id'],
|
||||
'share_network_subnet_id': fake_share_net_subnet['id'],
|
||||
'is_auto_deletable': False,
|
||||
'identifier': identifier,
|
||||
}
|
||||
@ -1419,7 +1571,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
mock.Mock(return_value=server_managing)
|
||||
)
|
||||
result = self.api.manage_share_server(
|
||||
self.context, 'fake_identifier', host, fake_share_network,
|
||||
self.context, 'fake_identifier', host, fake_share_net_subnet,
|
||||
{'opt1': 'val1', 'opt2': 'val2'}
|
||||
)
|
||||
|
||||
@ -1434,7 +1586,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
|
||||
result_dict = {
|
||||
'host': result['host'],
|
||||
'share_network_id': result['share_network_id'],
|
||||
'share_network_subnet_id': result['share_network_subnet_id'],
|
||||
'status': result['status'],
|
||||
'is_auto_deletable': result['is_auto_deletable'],
|
||||
'identifier': result['identifier'],
|
||||
@ -3273,26 +3425,211 @@ class ShareAPITestCase(test.TestCase):
|
||||
self.assertFalse(mock_db_update_call.called)
|
||||
self.assertFalse(mock_scheduler_rpcapi_call.called)
|
||||
|
||||
def test_create_share_replica_subnet_not_found(self):
|
||||
request_spec = fakes.fake_replica_request_spec()
|
||||
replica = request_spec['share_instance_properties']
|
||||
extra_specs = {
|
||||
'availability_zones': 'FAKE_AZ,FAKE_AZ2',
|
||||
'replication_type': constants.REPLICATION_TYPE_DR
|
||||
}
|
||||
share_type = db_utils.create_share_type(extra_specs=extra_specs)
|
||||
share_type = db_api.share_type_get(self.context, share_type['id'])
|
||||
az_name = 'FAKE_AZ'
|
||||
share = db_utils.create_share(
|
||||
id=replica['share_id'], replication_type='dr')
|
||||
self.mock_object(db_api, 'share_replicas_get_available_active_replica',
|
||||
mock.Mock(return_value=mock.Mock(
|
||||
return_value={'host': 'fake_ar_host'})))
|
||||
self.mock_object(share_types, 'get_share_type',
|
||||
mock.Mock(return_value=share_type))
|
||||
self.mock_object(db_api, 'availability_zone_get')
|
||||
self.mock_object(db_api,
|
||||
'share_network_subnet_get_by_availability_zone_id',
|
||||
mock.Mock(return_value=None))
|
||||
|
||||
self.assertRaises(exception.InvalidShare,
|
||||
self.api.create_share_replica,
|
||||
self.context,
|
||||
share,
|
||||
availability_zone=az_name,
|
||||
share_network_id='fake_id')
|
||||
(db_api.share_replicas_get_available_active_replica
|
||||
.assert_called_once_with(self.context, share['id']))
|
||||
self.assertTrue(share_types.get_share_type.called)
|
||||
db_api.availability_zone_get.assert_called_once_with(
|
||||
self.context, az_name)
|
||||
self.assertTrue(
|
||||
db_api.share_network_subnet_get_by_availability_zone_id.called)
|
||||
|
||||
def test_create_share_replica_az_not_found(self):
|
||||
request_spec = fakes.fake_replica_request_spec()
|
||||
replica = request_spec['share_instance_properties']
|
||||
extra_specs = {
|
||||
'availability_zones': 'FAKE_AZ,FAKE_AZ2',
|
||||
'replication_type': constants.REPLICATION_TYPE_DR
|
||||
}
|
||||
share_type = db_utils.create_share_type(extra_specs=extra_specs)
|
||||
share_type = db_api.share_type_get(self.context, share_type['id'])
|
||||
az_name = 'FAKE_AZ'
|
||||
share = db_utils.create_share(
|
||||
id=replica['share_id'], replication_type='dr')
|
||||
self.mock_object(db_api, 'share_replicas_get_available_active_replica',
|
||||
mock.Mock(return_value=mock.Mock(
|
||||
return_value={'host': 'fake_ar_host'})))
|
||||
self.mock_object(share_types, 'get_share_type',
|
||||
mock.Mock(return_value=share_type))
|
||||
side_effect = exception.AvailabilityZoneNotFound(id=az_name)
|
||||
self.mock_object(db_api, 'availability_zone_get',
|
||||
mock.Mock(side_effect=side_effect))
|
||||
|
||||
self.assertRaises(exception.InvalidInput,
|
||||
self.api.create_share_replica,
|
||||
self.context,
|
||||
share,
|
||||
availability_zone=az_name,
|
||||
share_network_id='fake_id')
|
||||
(db_api.share_replicas_get_available_active_replica
|
||||
.assert_called_once_with(self.context, share['id']))
|
||||
self.assertTrue(share_types.get_share_type.called)
|
||||
db_api.availability_zone_get.assert_called_once_with(
|
||||
self.context, az_name)
|
||||
|
||||
@ddt.data(
|
||||
{'availability_zones': '', 'azs_with_subnet': ['fake_az_1']},
|
||||
{'availability_zones': 'fake_az_1,fake_az_2',
|
||||
'azs_with_subnet': ['fake_az_2']}
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_create_share_replica_azs_with_subnets(self, availability_zones,
|
||||
azs_with_subnet):
|
||||
request_spec = fakes.fake_replica_request_spec()
|
||||
replica = request_spec['share_instance_properties']
|
||||
share_network_id = 'fake_share_network_id'
|
||||
extra_specs = {
|
||||
'availability_zones': availability_zones,
|
||||
'replication_type': constants.REPLICATION_TYPE_DR
|
||||
}
|
||||
share_type = db_utils.create_share_type(extra_specs=extra_specs)
|
||||
share_type = db_api.share_type_get(self.context, share_type['id'])
|
||||
share = db_utils.create_share(
|
||||
id=replica['share_id'], replication_type='dr',
|
||||
share_type_id=share_type['id'])
|
||||
cast_rules_to_readonly = (
|
||||
share['replication_type'] == constants.REPLICATION_TYPE_READABLE)
|
||||
fake_replica = fakes.fake_replica(id=replica['id'])
|
||||
fake_request_spec = fakes.fake_replica_request_spec()
|
||||
|
||||
self.mock_object(db_api, 'share_replicas_get_available_active_replica',
|
||||
mock.Mock(return_value={'host': 'fake_ar_host'}))
|
||||
self.mock_object(share_types, 'get_share_type',
|
||||
mock.Mock(return_value=share_type))
|
||||
mock_get_all_az_subnet = self.mock_object(
|
||||
self.api, '_get_all_availability_zones_with_subnets',
|
||||
mock.Mock(return_value=azs_with_subnet))
|
||||
|
||||
if availability_zones == '':
|
||||
expected_azs = azs_with_subnet
|
||||
else:
|
||||
availability_zones = [
|
||||
t for t in availability_zones.split(',') if availability_zones]
|
||||
expected_azs = (
|
||||
[az for az in availability_zones if az in azs_with_subnet])
|
||||
|
||||
self.mock_object(
|
||||
self.api, 'create_share_instance_and_get_request_spec',
|
||||
mock.Mock(return_value=(fake_request_spec, fake_replica)))
|
||||
self.mock_object(db_api, 'share_replica_update')
|
||||
mock_snapshot_get_all_call = self.mock_object(
|
||||
db_api, 'share_snapshot_get_all_for_share',
|
||||
mock.Mock(return_value=[]))
|
||||
mock_sched_rpcapi_call = self.mock_object(
|
||||
self.api.scheduler_rpcapi, 'create_share_replica')
|
||||
|
||||
self.api.create_share_replica(
|
||||
self.context, share, share_network_id=share_network_id)
|
||||
|
||||
(db_api.share_replicas_get_available_active_replica
|
||||
.assert_called_once_with(self.context, share['id']))
|
||||
self.assertTrue(share_types.get_share_type.called)
|
||||
mock_get_all_az_subnet.assert_called_once_with(
|
||||
self.context, share_network_id
|
||||
)
|
||||
(self.api.create_share_instance_and_get_request_spec.
|
||||
assert_called_once_with(
|
||||
self.context, share, availability_zone=None,
|
||||
share_network_id=share_network_id, share_type_id=share_type['id'],
|
||||
availability_zones=expected_azs,
|
||||
cast_rules_to_readonly=cast_rules_to_readonly))
|
||||
db_api.share_replica_update.assert_called_once()
|
||||
mock_snapshot_get_all_call.assert_called_once()
|
||||
mock_sched_rpcapi_call.assert_called_once()
|
||||
|
||||
@ddt.data(
|
||||
{'availability_zones': '', 'azs_with_subnet': []},
|
||||
{'availability_zones': 'fake_az_1,fake_az_2',
|
||||
'azs_with_subnet': ['fake_az_3']}
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_create_share_replica_azs_with_subnets_invalid_input(
|
||||
self, availability_zones, azs_with_subnet):
|
||||
request_spec = fakes.fake_replica_request_spec()
|
||||
replica = request_spec['share_instance_properties']
|
||||
share_network_id = 'fake_share_network_id'
|
||||
extra_specs = {
|
||||
'availability_zones': availability_zones,
|
||||
'replication_type': constants.REPLICATION_TYPE_DR
|
||||
}
|
||||
share_type = db_utils.create_share_type(extra_specs=extra_specs)
|
||||
share_type = db_api.share_type_get(self.context, share_type['id'])
|
||||
share = db_utils.create_share(
|
||||
id=replica['share_id'], replication_type='dr',
|
||||
share_type_id=share_type['id'])
|
||||
|
||||
self.mock_object(db_api, 'share_replicas_get_available_active_replica',
|
||||
mock.Mock(return_value={'host': 'fake_ar_host'}))
|
||||
self.mock_object(share_types, 'get_share_type',
|
||||
mock.Mock(return_value=share_type))
|
||||
mock_get_all_az_subnet = self.mock_object(
|
||||
self.api, '_get_all_availability_zones_with_subnets',
|
||||
mock.Mock(return_value=azs_with_subnet))
|
||||
|
||||
self.assertRaises(
|
||||
exception.InvalidInput,
|
||||
self.api.create_share_replica,
|
||||
self.context, share, share_network_id=share_network_id)
|
||||
|
||||
(db_api.share_replicas_get_available_active_replica
|
||||
.assert_called_once_with(self.context, share['id']))
|
||||
self.assertTrue(share_types.get_share_type.called)
|
||||
mock_get_all_az_subnet.assert_called_once_with(
|
||||
self.context, share_network_id
|
||||
)
|
||||
|
||||
@ddt.data({'has_snapshots': True,
|
||||
'extra_specs': {
|
||||
'replication_type': constants.REPLICATION_TYPE_DR,
|
||||
}},
|
||||
},
|
||||
'share_network_id': None},
|
||||
{'has_snapshots': False,
|
||||
'extra_specs': {
|
||||
'availability_zones': 'FAKE_AZ,FAKE_AZ2',
|
||||
'replication_type': constants.REPLICATION_TYPE_DR,
|
||||
}},
|
||||
},
|
||||
'share_network_id': None},
|
||||
{'has_snapshots': True,
|
||||
'extra_specs': {
|
||||
'availability_zones': 'FAKE_AZ,FAKE_AZ2',
|
||||
'replication_type': constants.REPLICATION_TYPE_READABLE,
|
||||
}},
|
||||
},
|
||||
'share_network_id': None},
|
||||
{'has_snapshots': False,
|
||||
'extra_specs': {
|
||||
'replication_type': constants.REPLICATION_TYPE_READABLE,
|
||||
}})
|
||||
},
|
||||
'share_network_id': 'fake_sn_id'})
|
||||
@ddt.unpack
|
||||
def test_create_share_replica(self, has_snapshots, extra_specs):
|
||||
def test_create_share_replica(self, has_snapshots, extra_specs,
|
||||
share_network_id):
|
||||
request_spec = fakes.fake_replica_request_spec()
|
||||
replication_type = extra_specs['replication_type']
|
||||
replica = request_spec['share_instance_properties']
|
||||
@ -3314,6 +3651,9 @@ class ShareAPITestCase(test.TestCase):
|
||||
mock.Mock(return_value={'host': 'fake_ar_host'}))
|
||||
self.mock_object(share_types, 'get_share_type',
|
||||
mock.Mock(return_value=share_type))
|
||||
self.mock_object(db_api, 'availability_zone_get')
|
||||
self.mock_object(db_api,
|
||||
'share_network_subnet_get_by_availability_zone_id')
|
||||
self.mock_object(
|
||||
share_api.API, 'create_share_instance_and_get_request_spec',
|
||||
mock.Mock(return_value=(fake_request_spec, fake_replica)))
|
||||
@ -3328,7 +3668,8 @@ class ShareAPITestCase(test.TestCase):
|
||||
expected_snap_instance_create_call_count = 2 if has_snapshots else 0
|
||||
|
||||
result = self.api.create_share_replica(
|
||||
self.context, share, availability_zone='FAKE_AZ')
|
||||
self.context, share, availability_zone='FAKE_AZ',
|
||||
share_network_id=share_network_id)
|
||||
|
||||
self.assertTrue(mock_sched_rpcapi_call.called)
|
||||
self.assertEqual(replica, result)
|
||||
@ -3343,7 +3684,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
(share_api.API.create_share_instance_and_get_request_spec.
|
||||
assert_called_once_with(
|
||||
self.context, share, availability_zone='FAKE_AZ',
|
||||
share_network_id=None, share_type_id=share_type['id'],
|
||||
share_network_id=share_network_id, share_type_id=share_type['id'],
|
||||
availability_zones=expected_azs,
|
||||
cast_rules_to_readonly=cast_rules_to_readonly))
|
||||
|
||||
|
@ -713,8 +713,10 @@ class ShareManagerTestCase(test.TestCase):
|
||||
def test_create_share_instance_from_snapshot_with_server(self):
|
||||
"""Test share can be created from snapshot if server exists."""
|
||||
network = db_utils.create_share_network()
|
||||
subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id=network['id'])
|
||||
server = db_utils.create_share_server(
|
||||
share_network_id=network['id'], host='fake_host',
|
||||
share_network_subnet_id=subnet['id'], host='fake_host',
|
||||
backend_details=dict(fake='fake'))
|
||||
parent_share = db_utils.create_share(share_network_id='net-id',
|
||||
share_server_id=server['id'])
|
||||
@ -843,6 +845,9 @@ class ShareManagerTestCase(test.TestCase):
|
||||
|
||||
def test_create_share_replica_with_share_server_exception(self):
|
||||
replica = fake_replica()
|
||||
share_network_subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id=replica['share_network_id'],
|
||||
availability_zone_id=replica['availability_zone_id'])
|
||||
manager.CONF.set_default('driver_handles_share_servers', True)
|
||||
self.mock_object(db, 'share_instance_access_copy',
|
||||
mock.Mock(return_value=[]))
|
||||
@ -850,6 +855,9 @@ class ShareManagerTestCase(test.TestCase):
|
||||
mock.Mock(return_value=fake_replica(id='fake2')))
|
||||
self.mock_object(db, 'share_replica_get',
|
||||
mock.Mock(return_value=replica))
|
||||
self.mock_object(db,
|
||||
'share_network_subnet_get_by_availability_zone_id',
|
||||
mock.Mock(return_value=share_network_subnet))
|
||||
mock_replica_update_call = self.mock_object(db, 'share_replica_update')
|
||||
mock_driver_replica_call = self.mock_object(
|
||||
self.share_manager.driver, 'create_replica')
|
||||
@ -871,7 +879,7 @@ class ShareManagerTestCase(test.TestCase):
|
||||
|
||||
def test_create_share_replica_driver_error_on_creation(self):
|
||||
fake_access_rules = [{'id': '1'}, {'id': '2'}, {'id': '3'}]
|
||||
replica = fake_replica(share_network_id='')
|
||||
replica = fake_replica()
|
||||
replica_2 = fake_replica(id='fake2')
|
||||
self.mock_object(db, 'share_replica_get',
|
||||
mock.Mock(return_value=replica))
|
||||
@ -2038,13 +2046,16 @@ class ShareManagerTestCase(test.TestCase):
|
||||
"""Test share can be created without share server."""
|
||||
|
||||
share_net = db_utils.create_share_network()
|
||||
share_net_subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id=share_net['id'],
|
||||
availability_zone_id=None,
|
||||
)
|
||||
share = db_utils.create_share(share_network_id=share_net['id'])
|
||||
|
||||
share_id = share['id']
|
||||
|
||||
def fake_setup_server(context, share_network, *args, **kwargs):
|
||||
return db_utils.create_share_server(
|
||||
share_network_id=share_network['id'],
|
||||
share_network_subnet_id=share_net_subnet['id'],
|
||||
host='fake_host')
|
||||
|
||||
self.mock_object(manager.LOG, 'info')
|
||||
@ -2058,18 +2069,23 @@ class ShareManagerTestCase(test.TestCase):
|
||||
manager.LOG.info.assert_called_with(mock.ANY, share.instance['id'])
|
||||
|
||||
def test_create_share_instance_with_share_network_server_fail(self):
|
||||
fake_share = db_utils.create_share(share_network_id='fake_sn_id',
|
||||
size=1)
|
||||
fake_server = {
|
||||
'id': 'fake_srv_id',
|
||||
'status': constants.STATUS_CREATING,
|
||||
}
|
||||
share_network = db_utils.create_share_network(id='fake_sn_id')
|
||||
share_net_subnet = db_utils.create_share_network_subnet(
|
||||
id='fake_sns_id', share_network_id=share_network['id']
|
||||
)
|
||||
fake_share = db_utils.create_share(
|
||||
share_network_id=share_network['id'], size=1)
|
||||
fake_server = db_utils.create_share_server(
|
||||
id='fake_srv_id', status=constants.STATUS_CREATING)
|
||||
self.mock_object(db, 'share_server_create',
|
||||
mock.Mock(return_value=fake_server))
|
||||
self.mock_object(db, 'share_instance_update',
|
||||
mock.Mock(return_value=fake_share.instance))
|
||||
self.mock_object(db, 'share_instance_get',
|
||||
mock.Mock(return_value=fake_share.instance))
|
||||
self.mock_object(db,
|
||||
'share_network_subnet_get_by_availability_zone_id',
|
||||
mock.Mock(return_value=share_net_subnet))
|
||||
self.mock_object(manager.LOG, 'error')
|
||||
|
||||
def raise_share_server_not_found(*args, **kwargs):
|
||||
@ -2119,7 +2135,7 @@ class ShareManagerTestCase(test.TestCase):
|
||||
resource_id=fake_share['id'],
|
||||
detail=message_field.Detail.NO_SHARE_SERVER)
|
||||
|
||||
def test_create_share_instance_with_share_network_not_found(self):
|
||||
def test_create_share_instance_with_share_network_subnet_not_found(self):
|
||||
"""Test creation fails if share network not found."""
|
||||
|
||||
self.mock_object(manager.LOG, 'error')
|
||||
@ -2127,7 +2143,7 @@ class ShareManagerTestCase(test.TestCase):
|
||||
share = db_utils.create_share(share_network_id='fake-net-id')
|
||||
share_id = share['id']
|
||||
self.assertRaises(
|
||||
exception.ShareNetworkNotFound,
|
||||
exception.ShareNetworkSubnetNotFound,
|
||||
self.share_manager.create_share_instance,
|
||||
self.context,
|
||||
share.instance['id']
|
||||
@ -2146,9 +2162,14 @@ class ShareManagerTestCase(test.TestCase):
|
||||
def test_create_share_instance_with_share_network_server_exists(self):
|
||||
"""Test share can be created with existing share server."""
|
||||
share_net = db_utils.create_share_network()
|
||||
share_net_subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id=share_net['id'],
|
||||
availability_zone_id=None,
|
||||
)
|
||||
share = db_utils.create_share(share_network_id=share_net['id'])
|
||||
share_srv = db_utils.create_share_server(
|
||||
share_network_id=share_net['id'], host=self.share_manager.host)
|
||||
share_network_subnet_id=share_net_subnet['id'],
|
||||
host=self.share_manager.host)
|
||||
|
||||
share_id = share['id']
|
||||
|
||||
@ -2201,9 +2222,14 @@ class ShareManagerTestCase(test.TestCase):
|
||||
def test_create_share_instance_with_server_created(self):
|
||||
"""Test share can be created and share server is created."""
|
||||
share_net = db_utils.create_share_network()
|
||||
share = db_utils.create_share(share_network_id=share_net['id'])
|
||||
share_net_subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id=share_net['id'],
|
||||
availability_zone_id=None)
|
||||
share = db_utils.create_share(share_network_id=share_net['id'],
|
||||
availability_zone=None)
|
||||
db_utils.create_share_server(
|
||||
share_network_id=share_net['id'], host=self.share_manager.host,
|
||||
share_network_subnet_id=share_net_subnet['id'],
|
||||
host=self.share_manager.host,
|
||||
status=constants.STATUS_ERROR)
|
||||
share_id = share['id']
|
||||
fake_server = {
|
||||
@ -2231,11 +2257,16 @@ class ShareManagerTestCase(test.TestCase):
|
||||
|
||||
def test_create_share_instance_update_replica_state(self):
|
||||
share_net = db_utils.create_share_network()
|
||||
share_net_subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id=share_net['id'],
|
||||
availability_zone_id=None
|
||||
)
|
||||
share = db_utils.create_share(share_network_id=share_net['id'],
|
||||
replication_type='dr')
|
||||
replication_type='dr',
|
||||
availability_zone=None)
|
||||
db_utils.create_share_server(
|
||||
share_network_id=share_net['id'], host=self.share_manager.host,
|
||||
status=constants.STATUS_ERROR)
|
||||
share_network_subnet_id=share_net_subnet['id'],
|
||||
host=self.share_manager.host, status=constants.STATUS_ERROR)
|
||||
share_id = share['id']
|
||||
fake_server = {
|
||||
'id': 'fake_srv_id',
|
||||
@ -2344,9 +2375,16 @@ class ShareManagerTestCase(test.TestCase):
|
||||
|
||||
def test_provide_share_server_for_share_incompatible_servers(self):
|
||||
fake_exception = exception.ManilaException("fake")
|
||||
fake_share_server = {'id': 'fake'}
|
||||
fake_share_network = db_utils.create_share_network(id='fake_sn_id')
|
||||
fake_share_net_subnet = db_utils.create_share_network_subnet(
|
||||
id='fake_sns_id', share_network_id=fake_share_network['id']
|
||||
)
|
||||
fake_share_server = db_utils.create_share_server(id='fake')
|
||||
share = db_utils.create_share()
|
||||
|
||||
db_method_mock = self.mock_object(
|
||||
db, 'share_network_subnet_get_by_availability_zone_id',
|
||||
mock.Mock(return_value=fake_share_net_subnet))
|
||||
self.mock_object(db,
|
||||
'share_server_get_all_by_host_and_share_net_valid',
|
||||
mock.Mock(return_value=[fake_share_server]))
|
||||
@ -2358,7 +2396,13 @@ class ShareManagerTestCase(test.TestCase):
|
||||
|
||||
self.assertRaises(exception.ManilaException,
|
||||
self.share_manager._provide_share_server_for_share,
|
||||
self.context, "fake_id", share.instance)
|
||||
self.context, fake_share_network['id'],
|
||||
share.instance)
|
||||
|
||||
db_method_mock.assert_called_once_with(
|
||||
self.context, fake_share_network['id'],
|
||||
availability_zone_id=share.instance.get('availability_zone_id')
|
||||
)
|
||||
driver_mock = self.share_manager.driver
|
||||
driver_method_mock = (
|
||||
driver_mock.choose_share_server_compatible_with_share
|
||||
@ -2374,6 +2418,7 @@ class ShareManagerTestCase(test.TestCase):
|
||||
|
||||
def test_provide_share_server_for_share_parent_ss_not_found(self):
|
||||
fake_parent_id = "fake_server_id"
|
||||
fake_share_network = db_utils.create_share_network(id='fake_sn_id')
|
||||
fake_exception = exception.ShareServerNotFound("fake")
|
||||
share = db_utils.create_share()
|
||||
fake_snapshot = {
|
||||
@ -2388,14 +2433,15 @@ class ShareManagerTestCase(test.TestCase):
|
||||
|
||||
self.assertRaises(exception.ShareServerNotFound,
|
||||
self.share_manager._provide_share_server_for_share,
|
||||
self.context, "fake_id", share.instance,
|
||||
snapshot=fake_snapshot)
|
||||
self.context, fake_share_network['id'],
|
||||
share.instance, snapshot=fake_snapshot)
|
||||
|
||||
db.share_server_get.assert_called_once_with(
|
||||
self.context, fake_parent_id)
|
||||
|
||||
def test_provide_share_server_for_share_parent_ss_invalid(self):
|
||||
fake_parent_id = "fake_server_id"
|
||||
fake_share_network = db_utils.create_share_network(id='fake_sn_id')
|
||||
share = db_utils.create_share()
|
||||
fake_snapshot = {
|
||||
'share': {
|
||||
@ -2410,8 +2456,8 @@ class ShareManagerTestCase(test.TestCase):
|
||||
|
||||
self.assertRaises(exception.InvalidShareServer,
|
||||
self.share_manager._provide_share_server_for_share,
|
||||
self.context, "fake_id", share.instance,
|
||||
snapshot=fake_snapshot)
|
||||
self.context, fake_share_network['id'],
|
||||
share.instance, snapshot=fake_snapshot)
|
||||
|
||||
db.share_server_get.assert_called_once_with(
|
||||
self.context, fake_parent_id)
|
||||
@ -2433,7 +2479,7 @@ class ShareManagerTestCase(test.TestCase):
|
||||
self.assertRaises(
|
||||
exception.ManilaException,
|
||||
self.share_manager._provide_share_server_for_share_group,
|
||||
self.context, "fake_id", sg)
|
||||
self.context, "fake_sn_id", "fake_sns_id", sg)
|
||||
|
||||
driver_mock = self.share_manager.driver
|
||||
driver_method_mock = (
|
||||
@ -2445,7 +2491,7 @@ class ShareManagerTestCase(test.TestCase):
|
||||
self.assertRaises(
|
||||
exception.InvalidInput,
|
||||
self.share_manager._provide_share_server_for_share_group,
|
||||
self.context, None, None)
|
||||
self.context, None, None, None)
|
||||
|
||||
def test_manage_share_driver_exception(self):
|
||||
self.mock_object(self.share_manager, 'driver')
|
||||
@ -2951,12 +2997,13 @@ class ShareManagerTestCase(test.TestCase):
|
||||
|
||||
def test_setup_server(self):
|
||||
# Setup required test data
|
||||
share_server = {
|
||||
'id': 'fake_id',
|
||||
'share_network_id': 'fake_sn_id',
|
||||
}
|
||||
metadata = {'fake_metadata_key': 'fake_metadata_value'}
|
||||
share_network = {'id': 'fake_sn_id'}
|
||||
share_network = db_utils.create_share_network(id='fake_sn_id')
|
||||
share_net_subnet = db_utils.create_share_network_subnet(
|
||||
id='fake_sns_id', share_network_id=share_network['id']
|
||||
)
|
||||
share_server = db_utils.create_share_server(
|
||||
id='fake_id', share_network_subnet_id=share_net_subnet['id'])
|
||||
network_info = {'security_services': []}
|
||||
for ss_type in constants.SECURITY_SERVICES_ALLOWED_TYPES:
|
||||
network_info['security_services'].append({
|
||||
@ -2974,6 +3021,8 @@ class ShareManagerTestCase(test.TestCase):
|
||||
network_info['network_type'] = 'fake_network_type'
|
||||
|
||||
# mock required stuff
|
||||
self.mock_object(self.share_manager.db, 'share_network_subnet_get',
|
||||
mock.Mock(return_value=share_net_subnet))
|
||||
self.mock_object(self.share_manager.db, 'share_network_get',
|
||||
mock.Mock(return_value=share_network))
|
||||
self.mock_object(self.share_manager.driver, 'allocate_network')
|
||||
@ -2993,14 +3042,15 @@ class ShareManagerTestCase(test.TestCase):
|
||||
|
||||
# verify results
|
||||
self.assertEqual(share_server, result)
|
||||
self.share_manager.db.share_network_get.assert_has_calls([
|
||||
mock.call(self.context, share_server['share_network_id']),
|
||||
mock.call(self.context, share_server['share_network_id']),
|
||||
])
|
||||
self.share_manager.db.share_network_get.assert_called_once_with(
|
||||
self.context, share_net_subnet['share_network_id'])
|
||||
self.share_manager.db.share_network_subnet_get.assert_called_once_with(
|
||||
self.context, share_server['share_network_subnet']['id'])
|
||||
self.share_manager.driver.allocate_network.assert_called_once_with(
|
||||
self.context, share_server, share_network)
|
||||
self.context, share_server, share_network,
|
||||
share_server['share_network_subnet'])
|
||||
self.share_manager._form_server_setup_info.assert_called_once_with(
|
||||
self.context, share_server, share_network)
|
||||
self.context, share_server, share_network, share_net_subnet)
|
||||
self.share_manager._validate_segmentation_id.assert_called_once_with(
|
||||
network_info)
|
||||
self.share_manager.driver.setup_server.assert_called_once_with(
|
||||
@ -3025,12 +3075,14 @@ class ShareManagerTestCase(test.TestCase):
|
||||
|
||||
def test_setup_server_server_info_not_present(self):
|
||||
# Setup required test data
|
||||
share_server = {
|
||||
'id': 'fake_id',
|
||||
'share_network_id': 'fake_sn_id',
|
||||
}
|
||||
metadata = {'fake_metadata_key': 'fake_metadata_value'}
|
||||
share_network = {'id': 'fake_sn_id'}
|
||||
share_net_subnet = {'id': 'fake_sns_id',
|
||||
'share_network_id': share_network['id']}
|
||||
share_server = {
|
||||
'id': 'fake_id',
|
||||
'share_network_subnet': share_net_subnet,
|
||||
}
|
||||
network_info = {
|
||||
'fake_network_info_key': 'fake_network_info_value',
|
||||
'security_services': [],
|
||||
@ -3039,6 +3091,8 @@ class ShareManagerTestCase(test.TestCase):
|
||||
server_info = {}
|
||||
|
||||
# mock required stuff
|
||||
self.mock_object(self.share_manager.db, 'share_network_subnet_get',
|
||||
mock.Mock(return_value=share_net_subnet))
|
||||
self.mock_object(self.share_manager.db, 'share_network_get',
|
||||
mock.Mock(return_value=share_network))
|
||||
self.mock_object(self.share_manager, '_form_server_setup_info',
|
||||
@ -3055,11 +3109,12 @@ class ShareManagerTestCase(test.TestCase):
|
||||
|
||||
# verify results
|
||||
self.assertEqual(share_server, result)
|
||||
self.share_manager.db.share_network_get.assert_has_calls([
|
||||
mock.call(self.context, share_server['share_network_id']),
|
||||
mock.call(self.context, share_server['share_network_id'])])
|
||||
self.share_manager.db.share_network_get.assert_called_once_with(
|
||||
self.context, share_net_subnet['share_network_id'])
|
||||
self.share_manager.db.share_network_subnet_get.assert_called_once_with(
|
||||
self.context, share_server['share_network_subnet']['id'])
|
||||
self.share_manager._form_server_setup_info.assert_called_once_with(
|
||||
self.context, share_server, share_network)
|
||||
self.context, share_server, share_network, share_net_subnet)
|
||||
self.share_manager.driver.setup_server.assert_called_once_with(
|
||||
network_info, metadata=metadata)
|
||||
self.share_manager.db.share_server_update.assert_called_once_with(
|
||||
@ -3067,16 +3122,18 @@ class ShareManagerTestCase(test.TestCase):
|
||||
{'status': constants.STATUS_ACTIVE,
|
||||
'identifier': share_server['id']})
|
||||
self.share_manager.driver.allocate_network.assert_called_once_with(
|
||||
self.context, share_server, share_network)
|
||||
self.context, share_server, share_network, share_net_subnet)
|
||||
|
||||
def setup_server_raise_exception(self, detail_data_proper):
|
||||
# Setup required test data
|
||||
share_server = {
|
||||
'id': 'fake_id',
|
||||
'share_network_id': 'fake_sn_id',
|
||||
}
|
||||
server_info = {'details_key': 'value'}
|
||||
share_network = {'id': 'fake_sn_id'}
|
||||
share_net_subnet = {'id': 'fake_sns_id',
|
||||
'share_network_id': share_network['id']}
|
||||
share_server = {
|
||||
'id': 'fake_id',
|
||||
'share_network_subnet': share_net_subnet
|
||||
}
|
||||
network_info = {
|
||||
'fake_network_info_key': 'fake_network_info_value',
|
||||
'security_services': [],
|
||||
@ -3092,6 +3149,8 @@ class ShareManagerTestCase(test.TestCase):
|
||||
# Mock required parameters
|
||||
self.mock_object(self.share_manager.db, 'share_network_get',
|
||||
mock.Mock(return_value=share_network))
|
||||
self.mock_object(self.share_manager.db, 'share_network_subnet_get',
|
||||
mock.Mock(return_value=share_net_subnet))
|
||||
self.mock_object(self.share_manager.db, 'share_server_update')
|
||||
for m in ['deallocate_network', 'allocate_network']:
|
||||
self.mock_object(self.share_manager.driver, m)
|
||||
@ -3117,15 +3176,17 @@ class ShareManagerTestCase(test.TestCase):
|
||||
assert_called_once_with(
|
||||
self.context, share_server['id'], server_info))
|
||||
self.share_manager._form_server_setup_info.assert_called_once_with(
|
||||
self.context, share_server, share_network)
|
||||
self.context, share_server, share_network, share_net_subnet)
|
||||
self.share_manager.db.share_server_update.assert_called_once_with(
|
||||
self.context, share_server['id'],
|
||||
{'status': constants.STATUS_ERROR})
|
||||
self.share_manager.db.share_network_get.assert_has_calls([
|
||||
mock.call(self.context, share_server['share_network_id']),
|
||||
mock.call(self.context, share_server['share_network_id'])])
|
||||
self.share_manager.db.share_network_get.assert_called_once_with(
|
||||
self.context, share_net_subnet['share_network_id'])
|
||||
self.share_manager.db.share_network_subnet_get.assert_called_once_with(
|
||||
self.context, share_server['share_network_subnet']['id'])
|
||||
self.share_manager.driver.allocate_network.assert_has_calls([
|
||||
mock.call(self.context, share_server, share_network)])
|
||||
mock.call(self.context, share_server, share_network,
|
||||
share_net_subnet)])
|
||||
self.share_manager.driver.deallocate_network.assert_has_calls([
|
||||
mock.call(self.context, share_server['id'])])
|
||||
|
||||
@ -3151,13 +3212,17 @@ class ShareManagerTestCase(test.TestCase):
|
||||
if not isinstance(d, dict):
|
||||
return {}
|
||||
return d
|
||||
|
||||
share_server = {'id': 'fake', 'share_network_id': 'fake'}
|
||||
share_net_subnet = db_utils.create_share_network_subnet(
|
||||
id='fake_subnet_id', share_network_id='fake_share_net_id'
|
||||
)
|
||||
share_server = db_utils.create_share_server(
|
||||
id='fake', share_network_subnet_id=share_net_subnet['id'])
|
||||
details = get_server_details_from_data(data)
|
||||
|
||||
exc_mock = mock.Mock(side_effect=exception.ManilaException(**data))
|
||||
details_mock = mock.Mock(side_effect=exception.ManilaException())
|
||||
self.mock_object(self.share_manager.db, 'share_network_get', exc_mock)
|
||||
self.mock_object(self.share_manager.db, 'share_network_get',
|
||||
exc_mock)
|
||||
self.mock_object(self.share_manager.db,
|
||||
'share_server_backend_details_set', details_mock)
|
||||
self.mock_object(self.share_manager.db, 'share_server_update')
|
||||
@ -3242,28 +3307,31 @@ class ShareManagerTestCase(test.TestCase):
|
||||
fake_share_server = dict(
|
||||
id='fake_share_server_id', backend_details=dict(foo='bar'))
|
||||
fake_share_network = dict(
|
||||
security_services='fake_security_services'
|
||||
)
|
||||
fake_share_network_subnet = dict(
|
||||
segmentation_id='fake_segmentation_id',
|
||||
cidr='fake_cidr',
|
||||
neutron_net_id='fake_neutron_net_id',
|
||||
neutron_subnet_id='fake_neutron_subnet_id',
|
||||
security_services='fake_security_services',
|
||||
network_type='fake_network_type')
|
||||
expected = dict(
|
||||
server_id=fake_share_server['id'],
|
||||
segmentation_id=fake_share_network['segmentation_id'],
|
||||
cidr=fake_share_network['cidr'],
|
||||
neutron_net_id=fake_share_network['neutron_net_id'],
|
||||
neutron_subnet_id=fake_share_network['neutron_subnet_id'],
|
||||
segmentation_id=fake_share_network_subnet['segmentation_id'],
|
||||
cidr=fake_share_network_subnet['cidr'],
|
||||
neutron_net_id=fake_share_network_subnet['neutron_net_id'],
|
||||
neutron_subnet_id=fake_share_network_subnet['neutron_subnet_id'],
|
||||
security_services=fake_share_network['security_services'],
|
||||
network_allocations=(
|
||||
fake_network_allocations_get_for_share_server()),
|
||||
admin_network_allocations=(
|
||||
fake_network_allocations_get_for_share_server(label='admin')),
|
||||
backend_details=fake_share_server['backend_details'],
|
||||
network_type=fake_share_network['network_type'])
|
||||
network_type=fake_share_network_subnet['network_type'])
|
||||
|
||||
network_info = self.share_manager._form_server_setup_info(
|
||||
self.context, fake_share_server, fake_share_network)
|
||||
self.context, fake_share_server, fake_share_network,
|
||||
fake_share_network_subnet)
|
||||
|
||||
self.assertEqual(expected, network_info)
|
||||
(self.share_manager.db.network_allocations_get_for_share_server.
|
||||
@ -3674,12 +3742,20 @@ class ShareManagerTestCase(test.TestCase):
|
||||
'host': "fake_host",
|
||||
'availability_zone_id': 'fake_az',
|
||||
}
|
||||
fake_subnet = {
|
||||
'id': 'fake_subnet_id'
|
||||
}
|
||||
self.mock_object(
|
||||
self.share_manager.db, 'share_group_get',
|
||||
mock.Mock(return_value=fake_group))
|
||||
self.mock_object(
|
||||
self.share_manager.db, 'share_group_update',
|
||||
mock.Mock(return_value=fake_group))
|
||||
self.mock_object(
|
||||
self.share_manager.db,
|
||||
'share_network_subnet_get_by_availability_zone_id',
|
||||
mock.Mock(return_value=fake_subnet)
|
||||
)
|
||||
self.mock_object(
|
||||
self.share_manager, '_provide_share_server_for_share_group',
|
||||
mock.Mock(return_value=({}, fake_group)))
|
||||
@ -3757,7 +3833,9 @@ class ShareManagerTestCase(test.TestCase):
|
||||
'share_server_id': 'fake_ss_id',
|
||||
'availability_zone_id': 'fake_az',
|
||||
}
|
||||
fake_ss = {'id': 'fake_ss_id', 'share_network_id': 'fake_sn'}
|
||||
fake_sn = {'id': 'fake_sn_id'}
|
||||
fake_sns = {'id': 'fake_sns_id', 'share_network_id': fake_sn['id']}
|
||||
fake_ss = {'id': 'fake_ss_id', 'share_network_subnet': fake_sns}
|
||||
fake_snap = {'id': 'fake_snap_id', 'share_group_snapshot_members': [],
|
||||
'share_group': {'share_server_id': fake_ss['id']}}
|
||||
self.mock_object(self.share_manager.db, 'share_group_get',
|
||||
@ -3823,6 +3901,9 @@ class ShareManagerTestCase(test.TestCase):
|
||||
self.mock_object(self.share_manager.driver.configuration, 'safe_get',
|
||||
mock.Mock(return_value=True))
|
||||
share_network_id = 'fake_sn'
|
||||
share_network_subnet = {
|
||||
'id': 'fake_subnet_id'
|
||||
}
|
||||
fake_group = {
|
||||
'id': 'fake_id',
|
||||
'source_share_group_snapshot_id': 'fake_snap_id',
|
||||
@ -3837,6 +3918,9 @@ class ShareManagerTestCase(test.TestCase):
|
||||
mock.Mock(return_value=fake_snap))
|
||||
self.mock_object(self.share_manager.db, 'share_group_update',
|
||||
mock.Mock(return_value=fake_group))
|
||||
self.mock_object(self.share_manager.db,
|
||||
'share_network_subnet_get_by_availability_zone_id',
|
||||
mock.Mock(return_value=share_network_subnet))
|
||||
self.mock_object(
|
||||
self.share_manager, '_provide_share_server_for_share_group',
|
||||
mock.Mock(return_value=({}, fake_group)))
|
||||
@ -5564,6 +5648,8 @@ class ShareManagerTestCase(test.TestCase):
|
||||
share_server = db_utils.create_share_server(**fake_share_server)
|
||||
security_service = db_utils.create_security_service(**ss_data)
|
||||
share_network = db_utils.create_share_network()
|
||||
share_net_subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id=share_network['id'])
|
||||
db.share_network_add_security_service(context.get_admin_context(),
|
||||
share_network['id'],
|
||||
security_service['id'])
|
||||
@ -5577,6 +5663,10 @@ class ShareManagerTestCase(test.TestCase):
|
||||
db, 'share_server_get', mock.Mock(return_value=share_server))
|
||||
mock_share_network_get = self.mock_object(
|
||||
db, 'share_network_get', mock.Mock(return_value=share_network))
|
||||
mock_share_net_subnet_get = self.mock_object(
|
||||
db, 'share_network_subnet_get', mock.Mock(
|
||||
return_value=share_net_subnet)
|
||||
)
|
||||
mock_network_allocations_get = self.mock_object(
|
||||
self.share_manager.driver, 'get_network_allocations_number',
|
||||
mock.Mock(return_value=1))
|
||||
@ -5627,7 +5717,11 @@ class ShareManagerTestCase(test.TestCase):
|
||||
)
|
||||
mock_share_network_get.assert_called_once_with(
|
||||
utils.IsAMatcher(context.RequestContext),
|
||||
fake_share_server['share_network_id']
|
||||
share_net_subnet['share_network_id']
|
||||
)
|
||||
mock_share_net_subnet_get.assert_called_once_with(
|
||||
utils.IsAMatcher(context.RequestContext),
|
||||
fake_share_server['share_network_subnet_id']
|
||||
)
|
||||
mock_network_allocations_get.assert_called_once_with()
|
||||
mock_share_server_net_info.assert_called_once_with(
|
||||
@ -5636,7 +5730,8 @@ class ShareManagerTestCase(test.TestCase):
|
||||
)
|
||||
mock_manage_network_allocations.assert_called_once_with(
|
||||
utils.IsAMatcher(context.RequestContext),
|
||||
fake_list_network_info, share_server, share_network
|
||||
fake_list_network_info, share_server, share_network,
|
||||
share_net_subnet
|
||||
)
|
||||
mock_manage_server.assert_called_once_with(
|
||||
utils.IsAMatcher(context.RequestContext), share_server, identifier,
|
||||
@ -5673,12 +5768,19 @@ class ShareManagerTestCase(test.TestCase):
|
||||
identifier = 'fake_id'
|
||||
share_server = db_utils.create_share_server(**fake_share_server)
|
||||
share_network = db_utils.create_share_network()
|
||||
share_network_subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id=share_network['id']
|
||||
)
|
||||
share_server['share_network_subnet_id'] = share_network_subnet['id']
|
||||
self.share_manager.driver._admin_network_api = mock.Mock()
|
||||
|
||||
mock_share_server_get = self.mock_object(
|
||||
db, 'share_server_get', mock.Mock(return_value=share_server))
|
||||
mock_share_network_get = self.mock_object(
|
||||
db, 'share_network_get', mock.Mock(return_value=share_network))
|
||||
mock_share_net_subnet_get = self.mock_object(
|
||||
db, 'share_network_subnet_get', mock.Mock(
|
||||
return_value=share_network_subnet))
|
||||
mock_network_allocations_get = self.mock_object(
|
||||
self.share_manager.driver, 'get_network_allocations_number',
|
||||
mock.Mock(return_value=1))
|
||||
@ -5697,7 +5799,11 @@ class ShareManagerTestCase(test.TestCase):
|
||||
)
|
||||
mock_share_network_get.assert_called_once_with(
|
||||
utils.IsAMatcher(context.RequestContext),
|
||||
fake_share_server['share_network_id']
|
||||
share_network_subnet['share_network_id']
|
||||
)
|
||||
mock_share_net_subnet_get.assert_called_once_with(
|
||||
utils.IsAMatcher(context.RequestContext),
|
||||
share_server['share_network_subnet_id']
|
||||
)
|
||||
mock_network_allocations_get.assert_called_once_with()
|
||||
mock_get_share_network_info.assert_called_once_with(
|
||||
@ -5712,12 +5818,19 @@ class ShareManagerTestCase(test.TestCase):
|
||||
identifier = 'fake_id'
|
||||
share_server = db_utils.create_share_server(**fake_share_server)
|
||||
share_network = db_utils.create_share_network()
|
||||
share_network_subnet = db_utils.create_share_network_subnet(
|
||||
share_network_id=share_network['id']
|
||||
)
|
||||
share_server['share_network_subnet_id'] = share_network_subnet['id']
|
||||
self.share_manager.driver._admin_network_api = mock.Mock()
|
||||
|
||||
mock_share_server_get = self.mock_object(
|
||||
db, 'share_server_get', mock.Mock(return_value=share_server))
|
||||
mock_share_network_get = self.mock_object(
|
||||
db, 'share_network_get', mock.Mock(return_value=share_network))
|
||||
mock_share_net_subnet_get = self.mock_object(
|
||||
db, 'share_network_subnet_get', mock.Mock(
|
||||
return_value=share_network_subnet))
|
||||
mock_network_allocations_get = self.mock_object(
|
||||
self.share_manager.driver, 'get_network_allocations_number',
|
||||
mock.Mock(return_value=1))
|
||||
@ -5744,7 +5857,11 @@ class ShareManagerTestCase(test.TestCase):
|
||||
)
|
||||
mock_share_network_get.assert_called_once_with(
|
||||
utils.IsAMatcher(context.RequestContext),
|
||||
fake_share_server['share_network_id']
|
||||
share_network_subnet['share_network_id']
|
||||
)
|
||||
mock_share_net_subnet_get.assert_called_once_with(
|
||||
utils.IsAMatcher(context.RequestContext),
|
||||
share_server['share_network_subnet_id']
|
||||
)
|
||||
mock_network_allocations_get.assert_called_once_with()
|
||||
mock_get_share_network_info.assert_called_once_with(
|
||||
@ -5757,7 +5874,8 @@ class ShareManagerTestCase(test.TestCase):
|
||||
)
|
||||
mock_manage_network_allocations.assert_called_once_with(
|
||||
utils.IsAMatcher(context.RequestContext),
|
||||
fake_list_network_info, share_server, share_network
|
||||
fake_list_network_info, share_server, share_network,
|
||||
share_network_subnet
|
||||
)
|
||||
|
||||
def test_manage_snapshot_driver_exception(self):
|
||||
|
@ -303,6 +303,14 @@ class ManilaExceptionResponseCode404(test.TestCase):
|
||||
self.assertEqual(404, e.code)
|
||||
self.assertIn(share_network_id, e.msg)
|
||||
|
||||
def test_share_network_subnet_not_found(self):
|
||||
# Verify response code for exception.ShareNetworkSubnetNotFound
|
||||
share_network_subnet_id = "fake_share_network_subnet_id"
|
||||
e = exception.ShareNetworkSubnetNotFound(
|
||||
share_network_subnet_id=share_network_subnet_id)
|
||||
self.assertEqual(404, e.code)
|
||||
self.assertIn(share_network_subnet_id, e.msg)
|
||||
|
||||
def test_share_server_not_found(self):
|
||||
# Verify response code for exception.ShareServerNotFound
|
||||
share_server_id = "fake_share_server_id"
|
||||
|
@ -0,0 +1,21 @@
|
||||
---
|
||||
features:
|
||||
- Added APIs with default policy set to 'rule:default' that allow the
|
||||
creation of share networks with multiple subnets. This gives the users
|
||||
the ability to create multiple subnets in a share network for different
|
||||
availability zones. Also, users will be able to delete and show
|
||||
existing subnets.
|
||||
- Updated the share server API to make possible to manage share servers
|
||||
in a specific subnet when the driver is operating in
|
||||
``driver_handles_share_servers`` enabled mode.
|
||||
- Share servers are now associated with a single share network subnet, which
|
||||
pertain to a share network.
|
||||
upgrade:
|
||||
- On upgrading to this release, all existing share networks will be updated
|
||||
to accommodate an availability zone assignment. Existing share networks
|
||||
will have their availability zone set to "empty" indicating that they are
|
||||
available across all storage availability zones known to manila.
|
||||
fixes:
|
||||
- A share network cannot be provided while creating a share replica. Replicas
|
||||
will inherit the share's share network if one exists.
|
||||
|
Loading…
Reference in New Issue
Block a user