Add multiple subnets per AZ support
Manila can now configure a share network with multiple subnets in an availability zone. Also, it can add a new subnet for an availability that has share servers, which will triger an update share server allocations. Changes: - API: - Bump version to 2.70. - setup share network with multiple subents per az. - Block manage server with multiple subnets. - Allow add subnet for in-use share servers. - `share_network_subnet_id` is dropped from ShareServer view - `share_network_subnet_ids` is added in ShareServer view - `network_allocation_update_support` is added to ShareServer and ShareNetwork views. - Add a check operation for share network subnet create. - DB: - Remove `share_network_subnet_id` from share_servers. - Create mapping table `share_server_share_network_subnet_mappings`. - Fix queries with new db design. - Add migration downgrade and upgrade alembic. - Add `share_network_subnet_id` to the NetworkAllocations. - Scheduler: - Change `AvailabilityZoneFilter` to take in account if the host supports the allocation required by the setup request. - Manager: - Bump RPC API version. - `_setup_server` allocating multiple subnets. - Modify signature of driver `_setup_server` interface, passing a list of `network_info` for each subnet. - Share server DB creation to inform a list of subnets and create with `network_allocation_update_support`. - Implement `check_update_share_server_network_allocations` and `update_share_server_network_allocations`. - Drivers: - For legacy compatibility, all drivers implementing `_setup_server` consume the first element of the `network_ino`. - Dummy Driver: - Implement `_setup_server` with new signature as multiple subnet. - Modify the `backend_details` to save allocations for all subnets. - Report update allocation and share server multiple subnet support. - Implement `check_update_share_server_network_allocations` and `update_share_server_network_allocations` interfaces. Signed-off-by: Felipe Rodrigues <felipefuty01@gmail.com> Co-Authored-By: Andre Beltrami <debeltrami@gmail.com> Co-Authored-By: Fábio Oliveira <fabioaurelio1269@gmail.com> Co-Authored-By: Nahim Alves de Souza <nahimsouza@outlook.com> Co-Authored-By: Caique Mello <caique_mellosbo@hotmail.com> DocImpact APIImpact Partially-Implements: blueprint multiple-share-network-subnets Change-Id: I7de9de4ae509182e9494bba604979cce03acceec
This commit is contained in:
parent
3ce3854ae9
commit
2b57d15c64
@ -25,10 +25,12 @@ from oslo_log import log
|
|||||||
from oslo_utils import encodeutils
|
from oslo_utils import encodeutils
|
||||||
from oslo_utils import strutils
|
from oslo_utils import strutils
|
||||||
import webob
|
import webob
|
||||||
|
from webob import exc
|
||||||
|
|
||||||
from manila.api.openstack import api_version_request as api_version
|
from manila.api.openstack import api_version_request as api_version
|
||||||
from manila.api.openstack import versioned_method
|
from manila.api.openstack import versioned_method
|
||||||
from manila.common import constants
|
from manila.common import constants
|
||||||
|
from manila.db import api as db_api
|
||||||
from manila import exception
|
from manila import exception
|
||||||
from manila.i18n import _
|
from manila.i18n import _
|
||||||
from manila import policy
|
from manila import policy
|
||||||
@ -560,3 +562,53 @@ def validate_public_share_policy(context, api_params, api='create'):
|
|||||||
raise exception.NotAuthorized(message=message)
|
raise exception.NotAuthorized(message=message)
|
||||||
|
|
||||||
return api_params
|
return api_params
|
||||||
|
|
||||||
|
|
||||||
|
def _get_existing_subnets(context, share_network_id, az):
|
||||||
|
"""Return any existing subnets in the requested AZ.
|
||||||
|
|
||||||
|
If az is None, the method will search for an existent default subnet.
|
||||||
|
"""
|
||||||
|
if az is None:
|
||||||
|
return db_api.share_network_subnet_get_default_subnets(
|
||||||
|
context, share_network_id)
|
||||||
|
|
||||||
|
return (
|
||||||
|
db_api.share_network_subnets_get_all_by_availability_zone_id(
|
||||||
|
context, share_network_id, az,
|
||||||
|
fallback_to_default=False)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_subnet_create(context, share_network_id, data,
|
||||||
|
multiple_subnet_support):
|
||||||
|
|
||||||
|
check_net_id_and_subnet_id(data)
|
||||||
|
try:
|
||||||
|
share_network = 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 = {}
|
||||||
|
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)
|
||||||
|
data['availability_zone_id'] = subnet_az.get('id')
|
||||||
|
|
||||||
|
existing_subnets = _get_existing_subnets(
|
||||||
|
context, share_network_id, data['availability_zone_id'])
|
||||||
|
if existing_subnets and not multiple_subnet_support:
|
||||||
|
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)
|
||||||
|
raise exc.HTTPConflict(explanation=msg)
|
||||||
|
|
||||||
|
return share_network, existing_subnets
|
||||||
|
@ -182,13 +182,17 @@ REST_API_VERSION_HISTORY = """
|
|||||||
restore share from recycle bin. Also, a new parameter called
|
restore share from recycle bin. Also, a new parameter called
|
||||||
`is_soft_deleted` was added so users can filter out
|
`is_soft_deleted` was added so users can filter out
|
||||||
shares in the recycle bin while listing shares.
|
shares in the recycle bin while listing shares.
|
||||||
|
* 2.70 - Added support for multiple share network subnets in the same
|
||||||
|
availability zone. Also, users can add subnets for an in-use share
|
||||||
|
network.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# The minimum and maximum versions of the API supported
|
# The minimum and maximum versions of the API supported
|
||||||
# The default api version request is defined to be the
|
# The default api version request is defined to be the
|
||||||
# minimum version of the API supported.
|
# minimum version of the API supported.
|
||||||
_MIN_API_VERSION = "2.0"
|
_MIN_API_VERSION = "2.0"
|
||||||
_MAX_API_VERSION = "2.69"
|
_MAX_API_VERSION = "2.70"
|
||||||
DEFAULT_API_VERSION = _MIN_API_VERSION
|
DEFAULT_API_VERSION = _MIN_API_VERSION
|
||||||
|
|
||||||
|
|
||||||
|
@ -384,3 +384,11 @@ ____
|
|||||||
/v2/shares/{share_id}/action {"soft_delete": null}``. List shares in
|
/v2/shares/{share_id}/action {"soft_delete": null}``. List shares in
|
||||||
Recycle Bin: `` GET /v2/shares?is_soft_deleted=true``. Restore share from
|
Recycle Bin: `` GET /v2/shares?is_soft_deleted=true``. Restore share from
|
||||||
Recycle Bin: `` POST /v2/shares/{share_id}/action {'restore': null}``.
|
Recycle Bin: `` POST /v2/shares/{share_id}/action {'restore': null}``.
|
||||||
|
|
||||||
|
2.70
|
||||||
|
----
|
||||||
|
Added support to configure multiple subnets for a given share network in the
|
||||||
|
same availability zone (or the default one). Users can also add new subnets
|
||||||
|
for an in-use share network. To distinguish this update support a new
|
||||||
|
property called 'network_allocation_update_support' was added in the share
|
||||||
|
network and share server.
|
||||||
|
@ -51,7 +51,6 @@ class ShareServerController(wsgi.Controller):
|
|||||||
share_servers = db_api.share_server_get_all(context)
|
share_servers = db_api.share_server_get_all(context)
|
||||||
for s in share_servers:
|
for s in share_servers:
|
||||||
try:
|
try:
|
||||||
s.share_network_id = s.share_network_subnet['share_network_id']
|
|
||||||
share_network = db_api.share_network_get(
|
share_network = db_api.share_network_get(
|
||||||
context, s.share_network_id)
|
context, s.share_network_id)
|
||||||
s.project_id = share_network['project_id']
|
s.project_id = share_network['project_id']
|
||||||
@ -75,7 +74,9 @@ class ShareServerController(wsgi.Controller):
|
|||||||
(hasattr(s, k) and
|
(hasattr(s, k) and
|
||||||
s[k] == v or k == 'share_network' and
|
s[k] == v or k == 'share_network' and
|
||||||
v in [s.share_network_name,
|
v in [s.share_network_name,
|
||||||
s.share_network_id])]
|
s.share_network_id] or
|
||||||
|
k == 'share_network_subnet_id' and
|
||||||
|
v in s.share_network_subnet_ids)]
|
||||||
return self._view_builder.build_share_servers(req, share_servers)
|
return self._view_builder.build_share_servers(req, share_servers)
|
||||||
|
|
||||||
@wsgi.Controller.authorize
|
@wsgi.Controller.authorize
|
||||||
@ -85,8 +86,7 @@ class ShareServerController(wsgi.Controller):
|
|||||||
try:
|
try:
|
||||||
server = db_api.share_server_get(context, id)
|
server = db_api.share_server_get(context, id)
|
||||||
share_network = db_api.share_network_get(
|
share_network = db_api.share_network_get(
|
||||||
context, server.share_network_subnet['share_network_id'])
|
context, server['share_network_id'])
|
||||||
server.share_network_id = share_network['id']
|
|
||||||
server.project_id = share_network['project_id']
|
server.project_id = share_network['project_id']
|
||||||
if share_network['name']:
|
if share_network['name']:
|
||||||
server.share_network_name = share_network['name']
|
server.share_network_name = share_network['name']
|
||||||
@ -97,7 +97,7 @@ class ShareServerController(wsgi.Controller):
|
|||||||
except exception.ShareNetworkNotFound:
|
except exception.ShareNetworkNotFound:
|
||||||
msg = _("Share server %s could not be found. Its associated "
|
msg = _("Share server %s could not be found. Its associated "
|
||||||
"share network does not "
|
"share network does not "
|
||||||
"exist.") % server.share_network_subnet['share_network_id']
|
"exist.") % server['share_network_id']
|
||||||
raise exc.HTTPNotFound(explanation=msg)
|
raise exc.HTTPNotFound(explanation=msg)
|
||||||
return self._view_builder.build_share_server(req, server)
|
return self._view_builder.build_share_server(req, server)
|
||||||
|
|
||||||
|
@ -355,12 +355,17 @@ class ShareMixin(object):
|
|||||||
common.check_share_network_is_active(share_network)
|
common.check_share_network_is_active(share_network)
|
||||||
|
|
||||||
if availability_zone_id:
|
if availability_zone_id:
|
||||||
if not db.share_network_subnet_get_by_availability_zone_id(
|
subnets = (
|
||||||
|
db.share_network_subnets_get_all_by_availability_zone_id(
|
||||||
context, share_network_id,
|
context, share_network_id,
|
||||||
availability_zone_id=availability_zone_id):
|
availability_zone_id=availability_zone_id))
|
||||||
|
if not subnets:
|
||||||
msg = _("A share network subnet was not found for the "
|
msg = _("A share network subnet was not found for the "
|
||||||
"requested availability zone.")
|
"requested availability zone.")
|
||||||
raise exc.HTTPBadRequest(explanation=msg)
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
|
kwargs['az_request_multiple_subnet_support_map'] = {
|
||||||
|
availability_zone_id: len(subnets) > 1,
|
||||||
|
}
|
||||||
|
|
||||||
display_name = share.get('display_name')
|
display_name = share.get('display_name')
|
||||||
display_description = share.get('display_description')
|
display_description = share.get('display_description')
|
||||||
|
@ -21,11 +21,13 @@ from oslo_log import log
|
|||||||
import webob
|
import webob
|
||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
|
from manila.api.openstack import api_version_request as api_version
|
||||||
from manila.api.openstack import wsgi
|
from manila.api.openstack import wsgi
|
||||||
from manila.api.views import share_network_subnets as subnet_views
|
from manila.api.views import share_network_subnets as subnet_views
|
||||||
from manila.db import api as db_api
|
from manila.db import api as db_api
|
||||||
from manila import exception
|
from manila import exception
|
||||||
from manila.i18n import _
|
from manila.i18n import _
|
||||||
|
from manila import share
|
||||||
from manila.share import rpcapi as share_rpcapi
|
from manila.share import rpcapi as share_rpcapi
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
@ -40,6 +42,7 @@ class ShareNetworkSubnetController(wsgi.Controller):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(ShareNetworkSubnetController, self).__init__()
|
super(ShareNetworkSubnetController, self).__init__()
|
||||||
self.share_rpcapi = share_rpcapi.ShareAPI()
|
self.share_rpcapi = share_rpcapi.ShareAPI()
|
||||||
|
self.share_api = share.API()
|
||||||
|
|
||||||
@wsgi.Controller.api_version("2.51")
|
@wsgi.Controller.api_version("2.51")
|
||||||
@wsgi.Controller.authorize
|
@wsgi.Controller.authorize
|
||||||
@ -104,74 +107,55 @@ class ShareNetworkSubnetController(wsgi.Controller):
|
|||||||
db_api.share_network_subnet_delete(context, share_network_subnet_id)
|
db_api.share_network_subnet_delete(context, share_network_subnet_id)
|
||||||
return webob.Response(status_int=http_client.ACCEPTED)
|
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.api_version("2.51")
|
||||||
@wsgi.Controller.authorize
|
@wsgi.Controller.authorize
|
||||||
def create(self, req, share_network_id, body):
|
def create(self, req, share_network_id, body):
|
||||||
"""Add a new share network subnet into the share network."""
|
"""Add a new share network subnet into the share network."""
|
||||||
context = req.environ['manila.context']
|
context = req.environ['manila.context']
|
||||||
|
|
||||||
if not self.is_valid_body(body, 'share-network-subnet'):
|
if not self.is_valid_body(body, 'share-network-subnet'):
|
||||||
msg = _("Share Network Subnet is missing from the request body.")
|
msg = _("Share Network Subnet is missing from the request body.")
|
||||||
raise exc.HTTPBadRequest(explanation=msg)
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
|
|
||||||
data = body['share-network-subnet']
|
data = body['share-network-subnet']
|
||||||
data['share_network_id'] = share_network_id
|
data['share_network_id'] = share_network_id
|
||||||
|
multiple_subnet_support = (req.api_version_request >=
|
||||||
|
api_version.APIVersionRequest("2.70"))
|
||||||
|
share_network, existing_subnets = common.validate_subnet_create(
|
||||||
|
context, share_network_id, data, multiple_subnet_support)
|
||||||
|
|
||||||
common.check_net_id_and_subnet_id(data)
|
# create subnet operation on subnets with share servers means that an
|
||||||
|
# allocation update is requested.
|
||||||
|
if existing_subnets and existing_subnets[0]['share_servers']:
|
||||||
|
|
||||||
try:
|
# NOTE(felipe_rodrigues): all subnets have the same set of share
|
||||||
db_api.share_network_get(context, share_network_id)
|
# servers, so we can just get the servers from one of them. Not
|
||||||
except exception.ShareNetworkNotFound as e:
|
# necessarily all share servers from the specified AZ will be
|
||||||
raise exc.HTTPNotFound(explanation=e.msg)
|
# updated, only the ones created with subnets in the AZ. Others
|
||||||
|
# created with default AZ will only have its allocations updated
|
||||||
availability_zone = data.pop('availability_zone', None)
|
# when default subnet set is updated.
|
||||||
subnet_az = None
|
data['share_servers'] = existing_subnets[0]['share_servers']
|
||||||
|
|
||||||
if availability_zone:
|
|
||||||
try:
|
try:
|
||||||
subnet_az = db_api.availability_zone_get(context,
|
share_network_subnet = (
|
||||||
availability_zone)
|
self.share_api.update_share_server_network_allocations(
|
||||||
except exception.AvailabilityZoneNotFound:
|
context, share_network, data))
|
||||||
msg = _("The provided availability zone %s does not "
|
except exception.ServiceIsDown as e:
|
||||||
"exist.") % availability_zone
|
msg = _('Could not add the share network subnet.')
|
||||||
raise exc.HTTPBadRequest(explanation=msg)
|
LOG.error(e)
|
||||||
|
raise exc.HTTPInternalServerError(explanation=msg)
|
||||||
|
except exception.InvalidShareNetwork as e:
|
||||||
|
raise exc.HTTPBadRequest(explanation=e.msg)
|
||||||
|
except db_exception.DBError as e:
|
||||||
|
msg = _('Could not add the share network subnet.')
|
||||||
|
LOG.error(e)
|
||||||
|
raise exc.HTTPInternalServerError(explanation=msg)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
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)
|
||||||
|
|
||||||
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(
|
share_network_subnet = db_api.share_network_subnet_get(
|
||||||
context, share_network_subnet['id'])
|
context, share_network_subnet['id'])
|
||||||
return self._view_builder.build_share_network_subnet(
|
return self._view_builder.build_share_network_subnet(
|
||||||
|
@ -279,15 +279,23 @@ class ShareNetworkController(wsgi.Controller, wsgi.AdminActionsMixin):
|
|||||||
try:
|
try:
|
||||||
if ('neutron_net_id' in update_values or
|
if ('neutron_net_id' in update_values or
|
||||||
'neutron_subnet_id' in update_values):
|
'neutron_subnet_id' in update_values):
|
||||||
subnet = db_api.share_network_subnet_get_default_subnet(
|
subnets = db_api.share_network_subnet_get_default_subnets(
|
||||||
context, id)
|
context, id)
|
||||||
if not subnet:
|
if not subnets:
|
||||||
msg = _("The share network %(id)s does not have a "
|
msg = _("The share network %(id)s does not have a "
|
||||||
"'default' subnet that serves all availability "
|
"'default' subnet that serves all availability "
|
||||||
"zones, so subnet details "
|
"zones, so subnet details "
|
||||||
"('neutron_net_id', 'neutron_subnet_id') cannot "
|
"('neutron_net_id', 'neutron_subnet_id') cannot "
|
||||||
"be updated.") % {'id': id}
|
"be updated.") % {'id': id}
|
||||||
raise exc.HTTPBadRequest(explanation=msg)
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
|
if len(subnets) > 1:
|
||||||
|
msg = _("The share network %(id)s does not have an unique "
|
||||||
|
"'default' subnet that serves all availability "
|
||||||
|
"zones, so subnet details "
|
||||||
|
"('neutron_net_id', 'neutron_subnet_id') cannot "
|
||||||
|
"be updated.") % {'id': id}
|
||||||
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
|
subnet = subnets[0]
|
||||||
|
|
||||||
# NOTE(silvacarlose): If the default share network subnet have
|
# NOTE(silvacarlose): If the default share network subnet have
|
||||||
# the fields neutron_net_id and neutron_subnet_id set as None,
|
# the fields neutron_net_id and neutron_subnet_id set as None,
|
||||||
@ -616,6 +624,54 @@ class ShareNetworkController(wsgi.Controller, wsgi.AdminActionsMixin):
|
|||||||
return self._view_builder.build_security_service_update_check(
|
return self._view_builder.build_security_service_update_check(
|
||||||
req, data, result)
|
req, data, result)
|
||||||
|
|
||||||
|
@wsgi.Controller.api_version('2.70')
|
||||||
|
@wsgi.action('share_network_subnet_create_check')
|
||||||
|
@wsgi.response(202)
|
||||||
|
def share_network_subnet_create_check(self, req, id, body):
|
||||||
|
"""Check the feasibility of creating a share network subnet."""
|
||||||
|
context = req.environ['manila.context']
|
||||||
|
if not self.is_valid_body(body, 'share_network_subnet_create_check'):
|
||||||
|
msg = _("Share Network Subnet Create Check is missing from "
|
||||||
|
"the request body.")
|
||||||
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
|
data = body['share_network_subnet_create_check']
|
||||||
|
share_network, existing_subnets = common.validate_subnet_create(
|
||||||
|
context, id, data, True)
|
||||||
|
|
||||||
|
reset_check = utils.get_bool_from_api_params('reset_operation', data)
|
||||||
|
|
||||||
|
# create subnet operation alongside subnets with share servers means
|
||||||
|
# that an allocation update is requested.
|
||||||
|
if existing_subnets and existing_subnets[0]['share_servers']:
|
||||||
|
|
||||||
|
# NOTE(felipe_rodrigues): all subnets within the same az have the
|
||||||
|
# same set of share servers, so we can just get the servers from
|
||||||
|
# one of them. Not necessarily all share servers from the specified
|
||||||
|
# AZ will be updated, only the ones created with subnets in the AZ.
|
||||||
|
# Others created with default AZ will only have its allocations
|
||||||
|
# updated when default subnet set is updated.
|
||||||
|
data['share_servers'] = existing_subnets[0]['share_servers']
|
||||||
|
try:
|
||||||
|
check_result = (
|
||||||
|
self.share_api.
|
||||||
|
check_update_share_server_network_allocations(
|
||||||
|
context, share_network, data, reset_check))
|
||||||
|
except exception.ServiceIsDown as e:
|
||||||
|
msg = _("A share network subnet update check cannot be "
|
||||||
|
"performed at this time.")
|
||||||
|
LOG.error(e)
|
||||||
|
raise exc.HTTPInternalServerError(explanation=msg)
|
||||||
|
except exception.InvalidShareNetwork as e:
|
||||||
|
raise exc.HTTPBadRequest(explanation=e.msg)
|
||||||
|
else:
|
||||||
|
check_result = {
|
||||||
|
'compatible': True,
|
||||||
|
'hosts_check_result': {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self._view_builder.build_share_network_subnet_create_check(
|
||||||
|
req, check_result)
|
||||||
|
|
||||||
@wsgi.Controller.api_version('2.63')
|
@wsgi.Controller.api_version('2.63')
|
||||||
@wsgi.action('reset_status')
|
@wsgi.action('reset_status')
|
||||||
def reset_status(self, req, id, body):
|
def reset_status(self, req, id, body):
|
||||||
|
@ -73,7 +73,6 @@ class ShareServerController(share_servers.ShareServerController,
|
|||||||
raise exc.HTTPForbidden(explanation=e.msg)
|
raise exc.HTTPForbidden(explanation=e.msg)
|
||||||
|
|
||||||
result.project_id = share_network["project_id"]
|
result.project_id = share_network["project_id"]
|
||||||
result.share_network_id = share_network["id"]
|
|
||||||
if share_network['name']:
|
if share_network['name']:
|
||||||
result.share_network_name = share_network['name']
|
result.share_network_name = share_network['name']
|
||||||
else:
|
else:
|
||||||
@ -107,14 +106,12 @@ class ShareServerController(share_servers.ShareServerController,
|
|||||||
except exception.ShareServerNotFound as e:
|
except exception.ShareServerNotFound as e:
|
||||||
raise exc.HTTPNotFound(explanation=e.msg)
|
raise exc.HTTPNotFound(explanation=e.msg)
|
||||||
|
|
||||||
network_subnet_id = share_server.get('share_network_subnet_id', None)
|
if len(share_server['share_network_subnets']) > 1:
|
||||||
if network_subnet_id:
|
msg = _("Cannot unmanage the share server containing multiple "
|
||||||
subnet = db_api.share_network_subnet_get(context,
|
"subnets.")
|
||||||
network_subnet_id)
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
share_network_id = subnet['share_network_id']
|
|
||||||
else:
|
|
||||||
share_network_id = share_server.get('share_network_id')
|
|
||||||
|
|
||||||
|
share_network_id = share_server['share_network_id']
|
||||||
share_network = db_api.share_network_get(context, share_network_id)
|
share_network = db_api.share_network_get(context, share_network_id)
|
||||||
common.check_share_network_is_active(share_network)
|
common.check_share_network_is_active(share_network)
|
||||||
|
|
||||||
@ -169,22 +166,30 @@ class ShareServerController(share_servers.ShareServerController,
|
|||||||
network_subnet_id = data.get('share_network_subnet_id')
|
network_subnet_id = data.get('share_network_subnet_id')
|
||||||
if network_subnet_id:
|
if network_subnet_id:
|
||||||
try:
|
try:
|
||||||
network_subnet = db_api.share_network_subnet_get(
|
network_subnets = (
|
||||||
context, network_subnet_id)
|
db_api.share_network_subnet_get_all_with_same_az(
|
||||||
|
context, network_subnet_id))
|
||||||
except exception.ShareNetworkSubnetNotFound:
|
except exception.ShareNetworkSubnetNotFound:
|
||||||
msg = _("The share network subnet %s does not "
|
msg = _("The share network subnet %s does not "
|
||||||
"exist.") % network_subnet_id
|
"exist.") % network_subnet_id
|
||||||
raise exc.HTTPBadRequest(explanation=msg)
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
else:
|
else:
|
||||||
network_subnet = db_api.share_network_subnet_get_default_subnet(
|
network_subnets = db_api.share_network_subnet_get_default_subnets(
|
||||||
context, share_network_id)
|
context, share_network_id)
|
||||||
|
|
||||||
if network_subnet is None:
|
if not network_subnets:
|
||||||
msg = _("The share network %s does have a default subnet. Create "
|
msg = _("The share network %s does have a default subnet. Create "
|
||||||
"one or use a specific subnet to manage this share server "
|
"one or use a specific subnet to manage this share server "
|
||||||
"with API version >= 2.51.") % share_network_id
|
"with API version >= 2.51.") % share_network_id
|
||||||
raise exc.HTTPBadRequest(explanation=msg)
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
|
|
||||||
|
if len(network_subnets) > 1:
|
||||||
|
msg = _("Cannot manage the share server, since the share network "
|
||||||
|
"subnet %s has more subnets in its availability "
|
||||||
|
"zone and share network.") % network_subnet_id
|
||||||
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
|
|
||||||
|
network_subnet = network_subnets[0]
|
||||||
common.check_share_network_is_active(network_subnet['share_network'])
|
common.check_share_network_is_active(network_subnet['share_network'])
|
||||||
|
|
||||||
if share_utils.extract_host(host, 'pool'):
|
if share_utils.extract_host(host, 'pool'):
|
||||||
@ -260,7 +265,7 @@ class ShareServerController(share_servers.ShareServerController,
|
|||||||
common.check_share_network_is_active(new_share_network)
|
common.check_share_network_is_active(new_share_network)
|
||||||
else:
|
else:
|
||||||
share_network_id = (
|
share_network_id = (
|
||||||
share_server['share_network_subnet']['share_network_id'])
|
share_server['share_network_id'])
|
||||||
current_share_network = db_api.share_network_get(
|
current_share_network = db_api.share_network_get(
|
||||||
context, share_network_id)
|
context, share_network_id)
|
||||||
common.check_share_network_is_active(current_share_network)
|
common.check_share_network_is_active(current_share_network)
|
||||||
@ -387,7 +392,7 @@ class ShareServerController(share_servers.ShareServerController,
|
|||||||
common.check_share_network_is_active(new_share_network)
|
common.check_share_network_is_active(new_share_network)
|
||||||
else:
|
else:
|
||||||
share_network_id = (
|
share_network_id = (
|
||||||
share_server['share_network_subnet']['share_network_id'])
|
share_server['share_network_id'])
|
||||||
current_share_network = db_api.share_network_get(
|
current_share_network = db_api.share_network_get(
|
||||||
context, share_network_id)
|
context, share_network_id)
|
||||||
common.check_share_network_is_active(current_share_network)
|
common.check_share_network_is_active(current_share_network)
|
||||||
|
@ -22,7 +22,8 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
_collection_name = 'share_networks'
|
_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",
|
"add_subnets",
|
||||||
"add_status_and_sec_service_update_fields"]
|
"add_status_and_sec_service_update_fields",
|
||||||
|
"add_network_allocation_update_support_field"]
|
||||||
|
|
||||||
def build_share_network(self, request, share_network):
|
def build_share_network(self, request, share_network):
|
||||||
"""View of a share network."""
|
"""View of a share network."""
|
||||||
@ -55,6 +56,16 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
view['hosts_check_result'] = result['hosts_check_result']
|
view['hosts_check_result'] = result['hosts_check_result']
|
||||||
return view
|
return view
|
||||||
|
|
||||||
|
def build_share_network_subnet_create_check(self, request, result):
|
||||||
|
"""View of share network subnet create check."""
|
||||||
|
context = request.environ['manila.context']
|
||||||
|
view = {
|
||||||
|
'compatible': result['compatible'],
|
||||||
|
}
|
||||||
|
if context.is_admin:
|
||||||
|
view['hosts_check_result'] = result['hosts_check_result']
|
||||||
|
return view
|
||||||
|
|
||||||
def _update_share_network_info(self, request, share_network):
|
def _update_share_network_info(self, request, share_network):
|
||||||
for sns in share_network.get('share_network_subnets') or []:
|
for sns in share_network.get('share_network_subnets') or []:
|
||||||
if sns.get('is_default') and sns.get('is_default') is True:
|
if sns.get('is_default') and sns.get('is_default') is True:
|
||||||
@ -135,3 +146,9 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
network_dict['status'] = network.get('status')
|
network_dict['status'] = network.get('status')
|
||||||
network_dict['security_service_update_support'] = network.get(
|
network_dict['security_service_update_support'] = network.get(
|
||||||
'security_service_update_support')
|
'security_service_update_support')
|
||||||
|
|
||||||
|
@common.ViewBuilder.versioned_method("2.70")
|
||||||
|
def add_network_allocation_update_support_field(
|
||||||
|
self, context, network_dict, network):
|
||||||
|
network_dict['network_allocation_update_support'] = network.get(
|
||||||
|
'network_allocation_update_support')
|
||||||
|
@ -24,7 +24,8 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
"add_is_auto_deletable_and_identifier_fields",
|
"add_is_auto_deletable_and_identifier_fields",
|
||||||
"add_share_network_subnet_id_field",
|
"add_share_network_subnet_id_field",
|
||||||
"add_task_state_and_source_server_fields",
|
"add_task_state_and_source_server_fields",
|
||||||
"add_sec_service_update_fields"
|
"add_sec_service_update_fields",
|
||||||
|
"add_share_network_subnet_ids_and_network_allocation_update_support"
|
||||||
]
|
]
|
||||||
|
|
||||||
def build_share_server(self, request, share_server):
|
def build_share_server(self, request, share_server):
|
||||||
@ -64,11 +65,13 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
|
|
||||||
return share_server_dict
|
return share_server_dict
|
||||||
|
|
||||||
@common.ViewBuilder.versioned_method("2.51")
|
@common.ViewBuilder.versioned_method("2.51", "2.69")
|
||||||
def add_share_network_subnet_id_field(
|
def add_share_network_subnet_id_field(
|
||||||
self, context, share_server_dict, share_server):
|
self, context, share_server_dict, share_server):
|
||||||
|
"""In 2.70, share_network_subnet_id is dropped, it becomes a list."""
|
||||||
share_server_dict['share_network_subnet_id'] = (
|
share_server_dict['share_network_subnet_id'] = (
|
||||||
share_server['share_network_subnet_id'])
|
share_server['share_network_subnet_ids'][0]
|
||||||
|
if share_server['share_network_subnet_ids'] else None)
|
||||||
|
|
||||||
@common.ViewBuilder.versioned_method("2.49")
|
@common.ViewBuilder.versioned_method("2.49")
|
||||||
def add_is_auto_deletable_and_identifier_fields(
|
def add_is_auto_deletable_and_identifier_fields(
|
||||||
@ -89,3 +92,11 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
self, context, share_server_dict, share_server):
|
self, context, share_server_dict, share_server):
|
||||||
share_server_dict['security_service_update_support'] = share_server[
|
share_server_dict['security_service_update_support'] = share_server[
|
||||||
'security_service_update_support']
|
'security_service_update_support']
|
||||||
|
|
||||||
|
@common.ViewBuilder.versioned_method("2.70")
|
||||||
|
def add_share_network_subnet_ids_and_network_allocation_update_support(
|
||||||
|
self, context, share_server_dict, share_server):
|
||||||
|
share_server_dict['share_network_subnet_ids'] = sorted(
|
||||||
|
share_server['share_network_subnet_ids'])
|
||||||
|
share_server_dict['network_allocation_update_support'] = (
|
||||||
|
share_server['network_allocation_update_support'])
|
||||||
|
@ -421,7 +421,8 @@ class ShareServerCommands(object):
|
|||||||
"""
|
"""
|
||||||
share_servers = [server.strip() for server in share_servers.split(",")]
|
share_servers = [server.strip() for server in share_servers.split(",")]
|
||||||
capabilities = [cap.strip() for cap in capabilities.split(",")]
|
capabilities = [cap.strip() for cap in capabilities.split(",")]
|
||||||
supported_capabilities = ['security_service_update_support']
|
supported_capabilities = ['security_service_update_support',
|
||||||
|
'network_allocation_update_support']
|
||||||
|
|
||||||
values = dict()
|
values = dict()
|
||||||
for capability in capabilities:
|
for capability in capabilities:
|
||||||
|
@ -984,29 +984,45 @@ def share_network_subnet_get(context, network_subnet_id, session=None):
|
|||||||
session=session)
|
session=session)
|
||||||
|
|
||||||
|
|
||||||
|
def share_network_subnet_get_all_with_same_az(context, network_subnet_id,
|
||||||
|
session=None):
|
||||||
|
"""Get requested az share network subnets DB record."""
|
||||||
|
return IMPL.share_network_subnet_get_all_with_same_az(
|
||||||
|
context, network_subnet_id, session=session)
|
||||||
|
|
||||||
|
|
||||||
def share_network_subnet_get_all(context):
|
def share_network_subnet_get_all(context):
|
||||||
"""Get all share network subnet DB record."""
|
"""Get all share network subnet DB record."""
|
||||||
return IMPL.share_network_subnet_get_all(context)
|
return IMPL.share_network_subnet_get_all(context)
|
||||||
|
|
||||||
|
|
||||||
def share_network_subnet_get_by_availability_zone_id(context, share_network_id,
|
def share_network_subnets_get_all_by_availability_zone_id(
|
||||||
availability_zone_id):
|
context, share_network_id, availability_zone_id,
|
||||||
"""Get a share network subnet DB record.
|
fallback_to_default=True):
|
||||||
|
"""Get the share network subnets DB record in a given AZ.
|
||||||
|
|
||||||
This method returns a subnet DB record for a given share network id and
|
This method returns list of subnets DB record for a given share network id
|
||||||
an availability zone. If the 'availability_zone_id' is 'None', a record may
|
and an availability zone. If the 'availability_zone_id' is 'None', a
|
||||||
be returned and it will represent the default share network subnet.
|
record may be returned and it will represent the default share network
|
||||||
Be aware that if there is no subnet for a specific availability zone id,
|
subnets. If there is no subnet for a specific availability zone id and
|
||||||
this method will return the default share network subnet, if it exists.
|
"fallback_to_default" is True, this method will return the default share
|
||||||
|
network subnets, if it exists.
|
||||||
"""
|
"""
|
||||||
return IMPL.share_network_subnet_get_by_availability_zone_id(
|
return IMPL.share_network_subnets_get_all_by_availability_zone_id(
|
||||||
context, share_network_id, availability_zone_id)
|
context, share_network_id, availability_zone_id,
|
||||||
|
fallback_to_default=fallback_to_default)
|
||||||
|
|
||||||
|
|
||||||
def share_network_subnet_get_default_subnet(context, share_network_id):
|
def share_network_subnet_get_default_subnets(context, share_network_id):
|
||||||
"""Get the default share network subnet DB record."""
|
"""Get the default share network subnets DB records."""
|
||||||
return IMPL.share_network_subnet_get_default_subnet(context,
|
return IMPL.share_network_subnet_get_default_subnets(context,
|
||||||
share_network_id)
|
share_network_id)
|
||||||
|
|
||||||
|
|
||||||
|
def share_network_subnet_get_all_by_share_server_id(context, share_server_id):
|
||||||
|
"""Get the subnets that are being used by the share server."""
|
||||||
|
return IMPL.share_network_subnet_get_all_by_share_server_id(
|
||||||
|
context, share_server_id)
|
||||||
|
|
||||||
|
|
||||||
##################
|
##################
|
||||||
@ -1035,10 +1051,12 @@ def network_allocation_get(context, id, session=None, read_deleted=None):
|
|||||||
|
|
||||||
|
|
||||||
def network_allocations_get_for_share_server(context, share_server_id,
|
def network_allocations_get_for_share_server(context, share_server_id,
|
||||||
session=None, label=None):
|
session=None, label=None,
|
||||||
|
subnet_id=None):
|
||||||
"""Get network allocations for share server."""
|
"""Get network allocations for share server."""
|
||||||
return IMPL.network_allocations_get_for_share_server(
|
return IMPL.network_allocations_get_for_share_server(
|
||||||
context, share_server_id, label=label, session=session)
|
context, share_server_id, label=label, session=session,
|
||||||
|
subnet_id=subnet_id)
|
||||||
|
|
||||||
|
|
||||||
def network_allocations_get_by_ip_address(context, ip_address):
|
def network_allocations_get_by_ip_address(context, ip_address):
|
||||||
@ -1077,6 +1095,7 @@ def share_server_search_by_identifier(context, identifier, session=None):
|
|||||||
|
|
||||||
def share_server_get_all_by_host_and_share_subnet_valid(context, host,
|
def share_server_get_all_by_host_and_share_subnet_valid(context, host,
|
||||||
share_subnet_id,
|
share_subnet_id,
|
||||||
|
server_status=None,
|
||||||
session=None):
|
session=None):
|
||||||
"""Get share server DB records by host and share net not error."""
|
"""Get share server DB records by host and share net not error."""
|
||||||
return IMPL.share_server_get_all_by_host_and_share_subnet_valid(
|
return IMPL.share_server_get_all_by_host_and_share_subnet_valid(
|
||||||
|
@ -0,0 +1,229 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
"""multiple share server subnets
|
||||||
|
|
||||||
|
Revision ID: a87e0fb17dee
|
||||||
|
Revises: 1946cb97bb8d
|
||||||
|
Create Date: 2022-01-14 06:12:27.596130
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'a87e0fb17dee'
|
||||||
|
down_revision = '1946cb97bb8d'
|
||||||
|
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
from oslo_log import log
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
from manila.db.migrations import utils
|
||||||
|
|
||||||
|
|
||||||
|
SHARE_SERVERS_TABLE = 'share_servers'
|
||||||
|
SHARE_SERVER_SUBNET_MAP_TABLE = 'share_server_share_network_subnet_mappings'
|
||||||
|
NETWORK_ALLOCATIONS_TABLE = 'network_allocations'
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
|
||||||
|
# Create mappings table.
|
||||||
|
context = op.get_context()
|
||||||
|
mysql_dl = context.bind.dialect.name == 'mysql'
|
||||||
|
datetime_type = (sa.dialects.mysql.DATETIME(fsp=6)
|
||||||
|
if mysql_dl else sa.DateTime)
|
||||||
|
try:
|
||||||
|
share_server_fk_name = "fk_ss_sns_m_share_server_id_share_servers"
|
||||||
|
share_network_subnet_fk_name = (
|
||||||
|
"fk_ss_sns_m_share_network_subnet_id_share_network_subnets")
|
||||||
|
server_subnet_mappings_table = op.create_table(
|
||||||
|
SHARE_SERVER_SUBNET_MAP_TABLE,
|
||||||
|
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
|
||||||
|
sa.Column('created_at', datetime_type),
|
||||||
|
sa.Column('updated_at', datetime_type),
|
||||||
|
sa.Column('deleted_at', datetime_type),
|
||||||
|
sa.Column('deleted', sa.Integer, default=0),
|
||||||
|
sa.Column(
|
||||||
|
'share_server_id', sa.String(length=36),
|
||||||
|
sa.ForeignKey('share_servers.id', name=share_server_fk_name),
|
||||||
|
nullable=False),
|
||||||
|
sa.Column(
|
||||||
|
'share_network_subnet_id', sa.String(length=36),
|
||||||
|
sa.ForeignKey('share_network_subnets.id',
|
||||||
|
name=share_network_subnet_fk_name),
|
||||||
|
nullable=False),
|
||||||
|
mysql_engine='InnoDB',
|
||||||
|
mysql_charset='utf8')
|
||||||
|
except Exception:
|
||||||
|
LOG.error('Table %s could not be created.',
|
||||||
|
SHARE_SERVER_SUBNET_MAP_TABLE)
|
||||||
|
raise
|
||||||
|
|
||||||
|
# Populate the mappings table from the share servers table.
|
||||||
|
try:
|
||||||
|
connection = op.get_bind()
|
||||||
|
share_servers_table = utils.load_table(SHARE_SERVERS_TABLE, connection)
|
||||||
|
server_subnet_mappings = []
|
||||||
|
for server in connection.execute(share_servers_table.select()):
|
||||||
|
if server.share_network_subnet_id:
|
||||||
|
server_subnet_mappings.append({
|
||||||
|
'created_at': server.created_at,
|
||||||
|
'updated_at': server.updated_at,
|
||||||
|
'deleted_at': server.deleted_at,
|
||||||
|
'deleted': 0 if server.deleted == 'False' else 1,
|
||||||
|
'share_server_id': server.id,
|
||||||
|
'share_network_subnet_id': server.share_network_subnet_id,
|
||||||
|
})
|
||||||
|
op.bulk_insert(server_subnet_mappings_table, server_subnet_mappings)
|
||||||
|
except Exception:
|
||||||
|
LOG.error('Table %s could not be populated from the %s table.',
|
||||||
|
SHARE_SERVER_SUBNET_MAP_TABLE, SHARE_SERVERS_TABLE)
|
||||||
|
raise
|
||||||
|
|
||||||
|
# add subnet id column to the allocations table.
|
||||||
|
try:
|
||||||
|
network_allocation_fk_name = (
|
||||||
|
"fk_network_allocation_subnet_id_share_network_subnets")
|
||||||
|
op.add_column(
|
||||||
|
NETWORK_ALLOCATIONS_TABLE,
|
||||||
|
sa.Column('share_network_subnet_id', sa.String(length=36),
|
||||||
|
sa.ForeignKey('share_network_subnets.id',
|
||||||
|
name=network_allocation_fk_name))
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
LOG.error("Could not add ForeignKey column 'share_network_subnet_id'"
|
||||||
|
"to table %s.", NETWORK_ALLOCATIONS_TABLE)
|
||||||
|
raise
|
||||||
|
|
||||||
|
# populate the allocation with its subnet id using the share server.
|
||||||
|
network_allocation_table = utils.load_table(NETWORK_ALLOCATIONS_TABLE,
|
||||||
|
connection)
|
||||||
|
for alloc in connection.execute(network_allocation_table.select()):
|
||||||
|
# admin allocations should not contain subnet id.
|
||||||
|
if alloc['label'] == 'admin':
|
||||||
|
continue
|
||||||
|
|
||||||
|
server = connection.execute(
|
||||||
|
share_servers_table.select().where(
|
||||||
|
alloc['share_server_id'] == (
|
||||||
|
share_servers_table.c.id))).first()
|
||||||
|
|
||||||
|
# pylint: disable=no-value-for-parameter
|
||||||
|
op.execute(network_allocation_table.update().where(
|
||||||
|
alloc['id'] == network_allocation_table.c.id).values(
|
||||||
|
{'share_network_subnet_id': server['share_network_subnet_id']}))
|
||||||
|
|
||||||
|
# add a new column to share_servers.
|
||||||
|
try:
|
||||||
|
op.add_column(
|
||||||
|
SHARE_SERVERS_TABLE,
|
||||||
|
sa.Column('network_allocation_update_support', sa.Boolean,
|
||||||
|
nullable=False, server_default=sa.sql.false()))
|
||||||
|
except Exception:
|
||||||
|
LOG.error("Table %s could not add column "
|
||||||
|
"'network_allocation_update_support'.",
|
||||||
|
SHARE_SERVERS_TABLE)
|
||||||
|
raise
|
||||||
|
|
||||||
|
# drop subnet id foreign key from share servers.
|
||||||
|
try:
|
||||||
|
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_TABLE,
|
||||||
|
type_="foreignkey")
|
||||||
|
op.drop_column(SHARE_SERVERS_TABLE, 'share_network_subnet_id')
|
||||||
|
except Exception:
|
||||||
|
LOG.error("Table %s could not drop column 'share_network_subnet_id'.",
|
||||||
|
SHARE_SERVERS_TABLE)
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
"""Remove share_server_share_network_subnet_mapping table and new columns.
|
||||||
|
|
||||||
|
This method can lead to data loss because the share server can have
|
||||||
|
more than one subnet.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
share_serves_fk_name = (
|
||||||
|
"fk_share_servers_share_network_subnet_id_share_network_subnets")
|
||||||
|
op.add_column(
|
||||||
|
SHARE_SERVERS_TABLE,
|
||||||
|
sa.Column(
|
||||||
|
'share_network_subnet_id', sa.String(36),
|
||||||
|
sa.ForeignKey('share_network_subnets.id',
|
||||||
|
name=share_serves_fk_name),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
connection = op.get_bind()
|
||||||
|
server_subnet_mappings_table = utils.load_table(
|
||||||
|
SHARE_SERVER_SUBNET_MAP_TABLE, connection)
|
||||||
|
share_servers_table = utils.load_table(SHARE_SERVERS_TABLE,
|
||||||
|
connection)
|
||||||
|
session = sa.orm.Session(bind=connection.connect())
|
||||||
|
for server in connection.execute(share_servers_table.select()):
|
||||||
|
subnets = session.query(
|
||||||
|
server_subnet_mappings_table).filter(
|
||||||
|
server['id'] == (
|
||||||
|
server_subnet_mappings_table.c.share_server_id)).all()
|
||||||
|
|
||||||
|
if server['deleted'] != 'False' and len(subnets) > 1:
|
||||||
|
LOG.warning('Share server %s is not deleted and it '
|
||||||
|
'has more than one subnet (%s subnets), '
|
||||||
|
'the downgrade may cause an inconsistent '
|
||||||
|
'environment.', server['id'], len(subnets))
|
||||||
|
|
||||||
|
subnet_id = subnets[0].share_network_subnet_id if subnets else None
|
||||||
|
|
||||||
|
# pylint: disable=no-value-for-parameter
|
||||||
|
op.execute(share_servers_table.update().where(
|
||||||
|
server['id'] == share_servers_table.c.id).values(
|
||||||
|
{'share_network_subnet_id': subnet_id}))
|
||||||
|
|
||||||
|
session.close_all()
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
LOG.error("'share_network_subnet_id' field in the %s table could not "
|
||||||
|
"be created and populated from %s table.",
|
||||||
|
SHARE_SERVERS_TABLE, SHARE_SERVER_SUBNET_MAP_TABLE)
|
||||||
|
raise
|
||||||
|
|
||||||
|
try:
|
||||||
|
op.drop_table(SHARE_SERVER_SUBNET_MAP_TABLE)
|
||||||
|
except Exception:
|
||||||
|
LOG.error("Failed to drop table %s.", SHARE_SERVER_SUBNET_MAP_TABLE)
|
||||||
|
raise
|
||||||
|
|
||||||
|
try:
|
||||||
|
op.drop_column(SHARE_SERVERS_TABLE,
|
||||||
|
'network_allocation_update_support')
|
||||||
|
except Exception:
|
||||||
|
LOG.error("Table %s failed to drop the column "
|
||||||
|
"'network_allocation_update_support'.", SHARE_SERVERS_TABLE)
|
||||||
|
raise
|
||||||
|
|
||||||
|
try:
|
||||||
|
network_allocation_fk_name = (
|
||||||
|
"fk_network_allocation_subnet_id_share_network_subnets")
|
||||||
|
if connection.engine.name == 'mysql':
|
||||||
|
op.drop_constraint(network_allocation_fk_name,
|
||||||
|
NETWORK_ALLOCATIONS_TABLE,
|
||||||
|
type_="foreignkey")
|
||||||
|
op.drop_column(NETWORK_ALLOCATIONS_TABLE, 'share_network_subnet_id')
|
||||||
|
except Exception:
|
||||||
|
LOG.error("Column 'network_allocations.share_network_subnet_id' from "
|
||||||
|
"table %s failed to drop.", NETWORK_ALLOCATIONS_TABLE)
|
||||||
|
raise
|
@ -4253,6 +4253,24 @@ def share_network_subnet_get(context, network_subnet_id, session=None):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@require_context
|
||||||
|
def share_network_subnet_get_all_with_same_az(context, network_subnet_id,
|
||||||
|
session=None):
|
||||||
|
subnet = (_network_subnet_get_query(context, session)
|
||||||
|
.filter_by(id=network_subnet_id).subquery())
|
||||||
|
result = (_network_subnet_get_query(context, session)
|
||||||
|
.join(subnet, subnet.c.share_network_id ==
|
||||||
|
models.ShareNetworkSubnet.share_network_id)
|
||||||
|
.filter(func.coalesce(subnet.c.availability_zone_id, '0') ==
|
||||||
|
func.coalesce(
|
||||||
|
models.ShareNetworkSubnet.availability_zone_id, '0'))
|
||||||
|
.all())
|
||||||
|
if not result:
|
||||||
|
raise exception.ShareNetworkSubnetNotFound(
|
||||||
|
share_network_subnet_id=network_subnet_id)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
@require_context
|
@require_context
|
||||||
def share_network_subnet_get_all(context):
|
def share_network_subnet_get_all(context):
|
||||||
return _network_subnet_get_query(context).all()
|
return _network_subnet_get_query(context).all()
|
||||||
@ -4265,25 +4283,55 @@ def share_network_subnet_get_all_by_share_network(context, network_id):
|
|||||||
|
|
||||||
|
|
||||||
@require_context
|
@require_context
|
||||||
def share_network_subnet_get_by_availability_zone_id(
|
def share_network_subnets_get_all_by_availability_zone_id(
|
||||||
context, share_network_id, availability_zone_id):
|
context, share_network_id, availability_zone_id,
|
||||||
|
fallback_to_default=True):
|
||||||
|
"""Get the share network subnets DB records in a given AZ.
|
||||||
|
|
||||||
|
This method returns list of subnets 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
|
||||||
|
subnets. If there is no subnet for a specific availability zone id and
|
||||||
|
"fallback_to_default" is True, this method will return the default share
|
||||||
|
network subnets, if it exists.
|
||||||
|
|
||||||
|
:param context: operation context.
|
||||||
|
:param share_network_id: the share network id to be the subnets.
|
||||||
|
:param availability_zone_id: the availability zone id to be the subnets.
|
||||||
|
:param fallback_to_default: determines in case no subnets found in the
|
||||||
|
given AZ, it will return the "default" subnets.
|
||||||
|
:return: the list of share network subnets in the AZ and share network.
|
||||||
|
"""
|
||||||
result = (_network_subnet_get_query(context).filter_by(
|
result = (_network_subnet_get_query(context).filter_by(
|
||||||
share_network_id=share_network_id,
|
share_network_id=share_network_id,
|
||||||
availability_zone_id=availability_zone_id).first())
|
availability_zone_id=availability_zone_id).all())
|
||||||
# If a specific subnet wasn't found, try get the default one
|
# If a specific subnet wasn't found, try get the default one
|
||||||
if availability_zone_id and not result:
|
if availability_zone_id and not result and fallback_to_default:
|
||||||
return (_network_subnet_get_query(context).filter_by(
|
return (_network_subnet_get_query(context).filter_by(
|
||||||
share_network_id=share_network_id,
|
share_network_id=share_network_id,
|
||||||
availability_zone_id=None).first())
|
availability_zone_id=None).all())
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@require_context
|
@require_context
|
||||||
def share_network_subnet_get_default_subnet(context, share_network_id):
|
def share_network_subnet_get_default_subnets(context, share_network_id):
|
||||||
return share_network_subnet_get_by_availability_zone_id(
|
return share_network_subnets_get_all_by_availability_zone_id(
|
||||||
context, share_network_id, availability_zone_id=None)
|
context, share_network_id, availability_zone_id=None)
|
||||||
|
|
||||||
|
|
||||||
|
@require_context
|
||||||
|
def share_network_subnet_get_all_by_share_server_id(context, share_server_id):
|
||||||
|
result = (_network_subnet_get_query(context)
|
||||||
|
.filter(models.ShareNetworkSubnet.share_servers.any(
|
||||||
|
id=share_server_id))
|
||||||
|
.all())
|
||||||
|
if not result:
|
||||||
|
raise exception.ShareNetworkSubnetNotFoundByShareServer(
|
||||||
|
share_server_id=share_server_id)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
###################
|
###################
|
||||||
|
|
||||||
|
|
||||||
@ -4293,7 +4341,7 @@ def _server_get_query(context, session=None):
|
|||||||
return (model_query(context, models.ShareServer, session=session).
|
return (model_query(context, models.ShareServer, session=session).
|
||||||
options(joinedload('share_instances'),
|
options(joinedload('share_instances'),
|
||||||
joinedload('network_allocations'),
|
joinedload('network_allocations'),
|
||||||
joinedload('share_network_subnet')))
|
joinedload('share_network_subnets')))
|
||||||
|
|
||||||
|
|
||||||
@require_context
|
@require_context
|
||||||
@ -4314,6 +4362,12 @@ def share_server_delete(context, id):
|
|||||||
session = get_session()
|
session = get_session()
|
||||||
with session.begin():
|
with session.begin():
|
||||||
server_ref = share_server_get(context, id, session=session)
|
server_ref = share_server_get(context, id, session=session)
|
||||||
|
model_query(
|
||||||
|
context, models.ShareServerShareNetworkSubnetMapping,
|
||||||
|
session=session
|
||||||
|
).filter_by(
|
||||||
|
share_server_id=id,
|
||||||
|
).soft_delete()
|
||||||
share_server_backend_details_delete(context, id, session=session)
|
share_server_backend_details_delete(context, id, session=session)
|
||||||
server_ref.soft_delete(session=session, update_status=True)
|
server_ref.soft_delete(session=session, update_status=True)
|
||||||
|
|
||||||
@ -4384,12 +4438,19 @@ def share_server_search_by_identifier(context, identifier, session=None):
|
|||||||
@require_context
|
@require_context
|
||||||
def share_server_get_all_by_host_and_share_subnet_valid(context, host,
|
def share_server_get_all_by_host_and_share_subnet_valid(context, host,
|
||||||
share_subnet_id,
|
share_subnet_id,
|
||||||
|
server_status=None,
|
||||||
session=None):
|
session=None):
|
||||||
result = (_server_get_query(context, session).filter_by(host=host)
|
query = (_server_get_query(context, session)
|
||||||
.filter_by(share_network_subnet_id=share_subnet_id)
|
.filter_by(host=host)
|
||||||
.filter(models.ShareServer.status.in_(
|
.filter(models.ShareServer.share_network_subnets.any(
|
||||||
(constants.STATUS_CREATING,
|
id=share_subnet_id)))
|
||||||
constants.STATUS_ACTIVE))).all())
|
if server_status:
|
||||||
|
query.filter_by(status=server_status)
|
||||||
|
else:
|
||||||
|
query.filter(models.ShareServer.status.in_(
|
||||||
|
(constants.STATUS_CREATING, constants.STATUS_ACTIVE)))
|
||||||
|
|
||||||
|
result = query.all()
|
||||||
if not result:
|
if not result:
|
||||||
filters_description = ('share_network_subnet_id is "%(share_net_id)s",'
|
filters_description = ('share_network_subnet_id is "%(share_net_id)s",'
|
||||||
' host is "%(host)s" and status in'
|
' host is "%(host)s" and status in'
|
||||||
@ -4423,9 +4484,13 @@ def share_server_get_all_with_filters(context, filters):
|
|||||||
source_share_server_id=filters.get('source_share_server_id'))
|
source_share_server_id=filters.get('source_share_server_id'))
|
||||||
if filters.get('share_network_id'):
|
if filters.get('share_network_id'):
|
||||||
query = query.join(
|
query = query.join(
|
||||||
|
models.ShareServerShareNetworkSubnetMapping,
|
||||||
|
models.ShareServerShareNetworkSubnetMapping.share_server_id ==
|
||||||
|
models.ShareServer.id
|
||||||
|
).join(
|
||||||
models.ShareNetworkSubnet,
|
models.ShareNetworkSubnet,
|
||||||
models.ShareNetworkSubnet.id ==
|
models.ShareNetworkSubnet.id ==
|
||||||
models.ShareServer.share_network_subnet_id
|
models.ShareServerShareNetworkSubnetMapping.share_network_subnet_id
|
||||||
).filter(
|
).filter(
|
||||||
models.ShareNetworkSubnet.share_network_id ==
|
models.ShareNetworkSubnet.share_network_id ==
|
||||||
filters.get('share_network_id'))
|
filters.get('share_network_id'))
|
||||||
@ -4637,7 +4702,8 @@ def network_allocations_get_by_ip_address(context, ip_address):
|
|||||||
|
|
||||||
@require_context
|
@require_context
|
||||||
def network_allocations_get_for_share_server(context, share_server_id,
|
def network_allocations_get_for_share_server(context, share_server_id,
|
||||||
session=None, label=None):
|
session=None, label=None,
|
||||||
|
subnet_id=None):
|
||||||
if session is None:
|
if session is None:
|
||||||
session = get_session()
|
session = get_session()
|
||||||
|
|
||||||
@ -4655,6 +4721,9 @@ def network_allocations_get_for_share_server(context, share_server_id,
|
|||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
query = query.filter(models.NetworkAllocation.label == label)
|
query = query.filter(models.NetworkAllocation.label == label)
|
||||||
|
if subnet_id:
|
||||||
|
query = query.filter(
|
||||||
|
models.NetworkAllocation.share_network_subnet_id == subnet_id)
|
||||||
|
|
||||||
result = query.all()
|
result = query.all()
|
||||||
return result
|
return result
|
||||||
|
@ -967,6 +967,17 @@ class ShareNetwork(BASE, ManilaBase):
|
|||||||
# set to True.
|
# set to True.
|
||||||
return all(share_servers_support_updating)
|
return all(share_servers_support_updating)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def network_allocation_update_support(self):
|
||||||
|
share_servers_support_updating = []
|
||||||
|
for network_subnet in self.share_network_subnets:
|
||||||
|
for server in network_subnet['share_servers']:
|
||||||
|
share_servers_support_updating.append(
|
||||||
|
server['network_allocation_update_support'])
|
||||||
|
# NOTE(felipe_rodrigues): all share servers within this share network
|
||||||
|
# must support updating in order to have this property set to True.
|
||||||
|
return all(share_servers_support_updating)
|
||||||
|
|
||||||
|
|
||||||
class ShareNetworkSubnet(BASE, ManilaBase):
|
class ShareNetworkSubnet(BASE, ManilaBase):
|
||||||
"""Represents a share network subnet used by some resources."""
|
"""Represents a share network subnet used by some resources."""
|
||||||
@ -990,11 +1001,19 @@ class ShareNetworkSubnet(BASE, ManilaBase):
|
|||||||
String(36), ForeignKey('availability_zones.id'), nullable=True)
|
String(36), ForeignKey('availability_zones.id'), nullable=True)
|
||||||
|
|
||||||
share_servers = orm.relationship(
|
share_servers = orm.relationship(
|
||||||
"ShareServer", backref='share_network_subnet',
|
"ShareServer",
|
||||||
|
secondary="share_server_share_network_subnet_mappings",
|
||||||
|
backref="share_network_subnets",
|
||||||
lazy='immediate',
|
lazy='immediate',
|
||||||
primaryjoin='and_(ShareNetworkSubnet.id '
|
primaryjoin="and_(ShareNetworkSubnet.id == "
|
||||||
'== ShareServer.share_network_subnet_id,'
|
"%(cls_name)s.share_network_subnet_id, "
|
||||||
'ShareServer.deleted == "False")')
|
"%(cls_name)s.deleted == 0)" % {
|
||||||
|
"cls_name": "ShareServerShareNetworkSubnetMapping"},
|
||||||
|
secondaryjoin='and_('
|
||||||
|
'ShareServer.id == '
|
||||||
|
'ShareServerShareNetworkSubnetMapping.share_server_id,'
|
||||||
|
'ShareServerShareNetworkSubnetMapping.deleted == 0)'
|
||||||
|
)
|
||||||
|
|
||||||
_availability_zone = orm.relationship(
|
_availability_zone = orm.relationship(
|
||||||
"AvailabilityZone",
|
"AvailabilityZone",
|
||||||
@ -1024,9 +1043,6 @@ class ShareServer(BASE, ManilaBase):
|
|||||||
__tablename__ = 'share_servers'
|
__tablename__ = 'share_servers'
|
||||||
id = Column(String(36), primary_key=True, nullable=False)
|
id = Column(String(36), primary_key=True, nullable=False)
|
||||||
deleted = Column(String(36), default='False')
|
deleted = Column(String(36), default='False')
|
||||||
share_network_subnet_id = Column(
|
|
||||||
String(36), ForeignKey('share_network_subnets.id'),
|
|
||||||
nullable=True)
|
|
||||||
host = Column(String(255), nullable=False)
|
host = Column(String(255), nullable=False)
|
||||||
is_auto_deletable = Column(Boolean, default=True)
|
is_auto_deletable = Column(Boolean, default=True)
|
||||||
identifier = Column(String(255), nullable=True)
|
identifier = Column(String(255), nullable=True)
|
||||||
@ -1035,6 +1051,8 @@ class ShareServer(BASE, ManilaBase):
|
|||||||
nullable=True)
|
nullable=True)
|
||||||
security_service_update_support = Column(
|
security_service_update_support = Column(
|
||||||
Boolean, nullable=False, default=False)
|
Boolean, nullable=False, default=False)
|
||||||
|
network_allocation_update_support = Column(
|
||||||
|
Boolean, nullable=False, default=False)
|
||||||
status = Column(Enum(
|
status = Column(Enum(
|
||||||
constants.STATUS_INACTIVE, constants.STATUS_ACTIVE,
|
constants.STATUS_INACTIVE, constants.STATUS_ACTIVE,
|
||||||
constants.STATUS_ERROR, constants.STATUS_DELETING,
|
constants.STATUS_ERROR, constants.STATUS_DELETING,
|
||||||
@ -1071,12 +1089,31 @@ class ShareServer(BASE, ManilaBase):
|
|||||||
'ShareServerBackendDetails.share_server_id, '
|
'ShareServerBackendDetails.share_server_id, '
|
||||||
'ShareServerBackendDetails.deleted == "False")')
|
'ShareServerBackendDetails.deleted == "False")')
|
||||||
|
|
||||||
|
_share_network_subnet_ids = orm.relationship(
|
||||||
|
"ShareServerShareNetworkSubnetMapping",
|
||||||
|
lazy='immediate',
|
||||||
|
viewonly=True,
|
||||||
|
primaryjoin='and_('
|
||||||
|
'ShareServer.id == '
|
||||||
|
'ShareServerShareNetworkSubnetMapping.share_server_id,'
|
||||||
|
'ShareServerShareNetworkSubnetMapping.deleted == 0)')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def backend_details(self):
|
def backend_details(self):
|
||||||
return {model['key']: model['value']
|
return {model['key']: model['value']
|
||||||
for model in self._backend_details}
|
for model in self._backend_details}
|
||||||
|
|
||||||
_extra_keys = ['backend_details']
|
@property
|
||||||
|
def share_network_subnet_ids(self):
|
||||||
|
return [model['share_network_subnet_id']
|
||||||
|
for model in self._share_network_subnet_ids]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def share_network_id(self):
|
||||||
|
return (self.share_network_subnets[0]['share_network_id']
|
||||||
|
if self.share_network_subnets else None)
|
||||||
|
|
||||||
|
_extra_keys = ['backend_details', 'share_network_subnet_ids']
|
||||||
|
|
||||||
|
|
||||||
class ShareServerBackendDetails(BASE, ManilaBase):
|
class ShareServerBackendDetails(BASE, ManilaBase):
|
||||||
@ -1090,6 +1127,16 @@ class ShareServerBackendDetails(BASE, ManilaBase):
|
|||||||
nullable=False)
|
nullable=False)
|
||||||
|
|
||||||
|
|
||||||
|
class ShareServerShareNetworkSubnetMapping(BASE, ManilaBase):
|
||||||
|
"""Represents the Share Server and Share Network Subnet mapping."""
|
||||||
|
__tablename__ = 'share_server_share_network_subnet_mappings'
|
||||||
|
id = Column(Integer, primary_key=True)
|
||||||
|
share_server_id = Column(
|
||||||
|
String(36), ForeignKey('share_servers.id'), nullable=False)
|
||||||
|
share_network_subnet_id = Column(
|
||||||
|
String(36), ForeignKey('share_network_subnets.id'), nullable=False)
|
||||||
|
|
||||||
|
|
||||||
class ShareNetworkSecurityServiceAssociation(BASE, ManilaBase):
|
class ShareNetworkSecurityServiceAssociation(BASE, ManilaBase):
|
||||||
"""Association table between compute_zones and compute_nodes tables."""
|
"""Association table between compute_zones and compute_nodes tables."""
|
||||||
|
|
||||||
@ -1121,6 +1168,10 @@ class NetworkAllocation(BASE, ManilaBase):
|
|||||||
share_server_id = Column(String(36), ForeignKey('share_servers.id'),
|
share_server_id = Column(String(36), ForeignKey('share_servers.id'),
|
||||||
nullable=False)
|
nullable=False)
|
||||||
|
|
||||||
|
# NOTE(felipe_rodrigues): admin allocation does not have subnet.
|
||||||
|
share_network_subnet_id = Column(
|
||||||
|
String(36), ForeignKey('share_network_subnets.id'), nullable=True)
|
||||||
|
|
||||||
|
|
||||||
class DriverPrivateData(BASE, ManilaBase):
|
class DriverPrivateData(BASE, ManilaBase):
|
||||||
"""Represents a private data as key-value pairs for a driver."""
|
"""Represents a private data as key-value pairs for a driver."""
|
||||||
|
@ -232,6 +232,11 @@ class ShareNetworkSubnetNotFound(NotFound):
|
|||||||
" found.")
|
" found.")
|
||||||
|
|
||||||
|
|
||||||
|
class ShareNetworkSubnetNotFoundByShareServer(NotFound):
|
||||||
|
message = _("Share network subnet could not be found by "
|
||||||
|
"%(share_server_id)s.")
|
||||||
|
|
||||||
|
|
||||||
class ShareServerNotFound(NotFound):
|
class ShareServerNotFound(NotFound):
|
||||||
message = _("Share server %(share_server_id)s could not be found.")
|
message = _("Share server %(share_server_id)s could not be found.")
|
||||||
|
|
||||||
@ -241,6 +246,11 @@ class ShareServerNotFoundByFilters(ShareServerNotFound):
|
|||||||
"filters: %(filters_description)s.")
|
"filters: %(filters_description)s.")
|
||||||
|
|
||||||
|
|
||||||
|
class AllocationsNotFoundForShareServer(NotFound):
|
||||||
|
message = _("No allocations found for the share server "
|
||||||
|
"%(share_server_id)s on the subnet.")
|
||||||
|
|
||||||
|
|
||||||
class InvalidShareNetwork(Invalid):
|
class InvalidShareNetwork(Invalid):
|
||||||
message = _("Invalid share network: %(reason)s")
|
message = _("Invalid share network: %(reason)s")
|
||||||
|
|
||||||
|
@ -134,3 +134,8 @@ class NetworkBaseAPI(db_base.Base, metaclass=abc.ABCMeta):
|
|||||||
"should be configured to 'True'.")
|
"should be configured to 'True'.")
|
||||||
raise exception.NetworkBadConfigurationException(reason=msg)
|
raise exception.NetworkBadConfigurationException(reason=msg)
|
||||||
return self._enabled_ip_versions
|
return self._enabled_ip_versions
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def include_network_info(self, share_network_subnet):
|
||||||
|
"""Includes share-network-subnet with plugin specific data."""
|
||||||
|
pass
|
||||||
|
@ -121,9 +121,16 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
|||||||
**self._neutron_api_kwargs)
|
**self._neutron_api_kwargs)
|
||||||
return self._neutron_api
|
return self._neutron_api
|
||||||
|
|
||||||
def _store_neutron_net_info(self, context, share_network_subnet):
|
def include_network_info(self, share_network_subnet):
|
||||||
self._save_neutron_network_data(context, share_network_subnet)
|
"""Includes share-network-subnet with plugin specific data."""
|
||||||
self._save_neutron_subnet_data(context, share_network_subnet)
|
self._store_neutron_net_info(None, share_network_subnet, save_db=False)
|
||||||
|
|
||||||
|
def _store_neutron_net_info(self, context, share_network_subnet,
|
||||||
|
save_db=True):
|
||||||
|
self._save_neutron_network_data(context, share_network_subnet,
|
||||||
|
save_db=save_db)
|
||||||
|
self._save_neutron_subnet_data(context, share_network_subnet,
|
||||||
|
save_db=save_db)
|
||||||
|
|
||||||
def allocate_network(self, context, share_server, share_network=None,
|
def allocate_network(self, context, share_server, share_network=None,
|
||||||
share_network_subnet=None, **kwargs):
|
share_network_subnet=None, **kwargs):
|
||||||
@ -202,6 +209,11 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
|||||||
'cidr': share_network_subnet['cidr'],
|
'cidr': share_network_subnet['cidr'],
|
||||||
'mtu': share_network_subnet['mtu'],
|
'mtu': share_network_subnet['mtu'],
|
||||||
}
|
}
|
||||||
|
# NOTE(felipe_rodrigues): admin plugin does not have any Manila
|
||||||
|
# share net subnet, its data is from manila configuration file.
|
||||||
|
if self.label != 'admin':
|
||||||
|
port_dict['share_network_subnet_id'] = (
|
||||||
|
share_network_subnet['id'])
|
||||||
|
|
||||||
# There should not be existing allocations with the same port_id.
|
# There should not be existing allocations with the same port_id.
|
||||||
try:
|
try:
|
||||||
@ -332,6 +344,12 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
|||||||
'cidr': share_network_subnet['cidr'],
|
'cidr': share_network_subnet['cidr'],
|
||||||
'mtu': share_network_subnet['mtu'],
|
'mtu': share_network_subnet['mtu'],
|
||||||
}
|
}
|
||||||
|
# NOTE(felipe_rodrigues): admin plugin does not have any Manila
|
||||||
|
# share net subnet, its data is from manila configuration file.
|
||||||
|
if self.label != 'admin':
|
||||||
|
port_dict['share_network_subnet_id'] = (
|
||||||
|
share_network_subnet['id'])
|
||||||
|
|
||||||
return self.db.network_allocation_create(context, port_dict)
|
return self.db.network_allocation_create(context, port_dict)
|
||||||
|
|
||||||
def _delete_port(self, context, port):
|
def _delete_port(self, context, port):
|
||||||
@ -354,7 +372,8 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
|||||||
share_network_subnet['neutron_net_id'])
|
share_network_subnet['neutron_net_id'])
|
||||||
return 'segments' in net_info
|
return 'segments' in net_info
|
||||||
|
|
||||||
def _save_neutron_network_data(self, context, share_network_subnet):
|
def _save_neutron_network_data(self, context, share_network_subnet,
|
||||||
|
save_db=True):
|
||||||
net_info = self.neutron_api.get_network(
|
net_info = self.neutron_api.get_network(
|
||||||
share_network_subnet['neutron_net_id'])
|
share_network_subnet['neutron_net_id'])
|
||||||
segmentation_id = None
|
segmentation_id = None
|
||||||
@ -389,11 +408,12 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
|||||||
}
|
}
|
||||||
share_network_subnet.update(provider_nw_dict)
|
share_network_subnet.update(provider_nw_dict)
|
||||||
|
|
||||||
if self.label != 'admin':
|
if self.label != 'admin' and save_db:
|
||||||
self.db.share_network_subnet_update(
|
self.db.share_network_subnet_update(
|
||||||
context, share_network_subnet['id'], provider_nw_dict)
|
context, share_network_subnet['id'], provider_nw_dict)
|
||||||
|
|
||||||
def _save_neutron_subnet_data(self, context, share_network_subnet):
|
def _save_neutron_subnet_data(self, context, share_network_subnet,
|
||||||
|
save_db=True):
|
||||||
subnet_info = self.neutron_api.get_subnet(
|
subnet_info = self.neutron_api.get_subnet(
|
||||||
share_network_subnet['neutron_subnet_id'])
|
share_network_subnet['neutron_subnet_id'])
|
||||||
|
|
||||||
@ -404,7 +424,7 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
|||||||
}
|
}
|
||||||
share_network_subnet.update(subnet_values)
|
share_network_subnet.update(subnet_values)
|
||||||
|
|
||||||
if self.label != 'admin':
|
if self.label != 'admin' and save_db:
|
||||||
self.db.share_network_subnet_update(
|
self.db.share_network_subnet_update(
|
||||||
context, share_network_subnet['id'], subnet_values)
|
context, share_network_subnet['id'], subnet_values)
|
||||||
|
|
||||||
@ -576,7 +596,8 @@ class NeutronBindNetworkPlugin(NeutronNetworkPlugin):
|
|||||||
"local_link_information": local_links}
|
"local_link_information": local_links}
|
||||||
return arguments
|
return arguments
|
||||||
|
|
||||||
def _save_neutron_network_data(self, context, share_network_subnet):
|
def _save_neutron_network_data(self, context, share_network_subnet,
|
||||||
|
save_db=True):
|
||||||
"""Store the Neutron network info.
|
"""Store the Neutron network info.
|
||||||
|
|
||||||
In case of dynamic multi segments the segment is determined while
|
In case of dynamic multi segments the segment is determined while
|
||||||
@ -589,12 +610,14 @@ class NeutronBindNetworkPlugin(NeutronNetworkPlugin):
|
|||||||
if self._is_neutron_multi_segment(share_network_subnet):
|
if self._is_neutron_multi_segment(share_network_subnet):
|
||||||
# In case of dynamic multi segment the segment is determined while
|
# In case of dynamic multi segment the segment is determined while
|
||||||
# binding the port, only mtu is known and already needed
|
# binding the port, only mtu is known and already needed
|
||||||
self._save_neutron_network_mtu(context, share_network_subnet)
|
self._save_neutron_network_mtu(context, share_network_subnet,
|
||||||
|
save_db=save_db)
|
||||||
return
|
return
|
||||||
super(NeutronBindNetworkPlugin, self)._save_neutron_network_data(
|
super(NeutronBindNetworkPlugin, self)._save_neutron_network_data(
|
||||||
context, share_network_subnet)
|
context, share_network_subnet, save_db=save_db)
|
||||||
|
|
||||||
def _save_neutron_network_mtu(self, context, share_network_subnet):
|
def _save_neutron_network_mtu(self, context, share_network_subnet,
|
||||||
|
save_db=True):
|
||||||
"""Store the Neutron network mtu.
|
"""Store the Neutron network mtu.
|
||||||
|
|
||||||
In case of dynamic multi segments only the mtu needs storing before
|
In case of dynamic multi segments only the mtu needs storing before
|
||||||
@ -608,7 +631,7 @@ class NeutronBindNetworkPlugin(NeutronNetworkPlugin):
|
|||||||
}
|
}
|
||||||
share_network_subnet.update(mtu_dict)
|
share_network_subnet.update(mtu_dict)
|
||||||
|
|
||||||
if self.label != 'admin':
|
if self.label != 'admin' and save_db:
|
||||||
self.db.share_network_subnet_update(
|
self.db.share_network_subnet_update(
|
||||||
context, share_network_subnet['id'], mtu_dict)
|
context, share_network_subnet['id'], mtu_dict)
|
||||||
|
|
||||||
|
@ -257,7 +257,11 @@ class StandaloneNetworkPlugin(network.NetworkBaseAPI):
|
|||||||
'available': len(ips)}
|
'available': len(ips)}
|
||||||
raise exception.NetworkBadConfigurationException(reason=msg)
|
raise exception.NetworkBadConfigurationException(reason=msg)
|
||||||
|
|
||||||
def _save_network_info(self, context, share_network_subnet):
|
def include_network_info(self, share_network_subnet):
|
||||||
|
"""Includes share-network-subnet with plugin specific data."""
|
||||||
|
self._save_network_info(None, share_network_subnet, save_db=False)
|
||||||
|
|
||||||
|
def _save_network_info(self, context, share_network_subnet, save_db=True):
|
||||||
"""Update share-network-subnet with plugin specific data."""
|
"""Update share-network-subnet with plugin specific data."""
|
||||||
data = {
|
data = {
|
||||||
'network_type': self.network_type,
|
'network_type': self.network_type,
|
||||||
@ -268,7 +272,7 @@ class StandaloneNetworkPlugin(network.NetworkBaseAPI):
|
|||||||
'mtu': self.mtu,
|
'mtu': self.mtu,
|
||||||
}
|
}
|
||||||
share_network_subnet.update(data)
|
share_network_subnet.update(data)
|
||||||
if self.label != 'admin':
|
if self.label != 'admin' and save_db:
|
||||||
self.db.share_network_subnet_update(
|
self.db.share_network_subnet_update(
|
||||||
context, share_network_subnet['id'], data)
|
context, share_network_subnet['id'], data)
|
||||||
|
|
||||||
@ -303,6 +307,9 @@ class StandaloneNetworkPlugin(network.NetworkBaseAPI):
|
|||||||
'ip_version': share_network_subnet['ip_version'],
|
'ip_version': share_network_subnet['ip_version'],
|
||||||
'mtu': share_network_subnet['mtu'],
|
'mtu': share_network_subnet['mtu'],
|
||||||
}
|
}
|
||||||
|
if self.label != 'admin':
|
||||||
|
data['share_network_subnet_id'] = (
|
||||||
|
share_network_subnet['id'])
|
||||||
allocations.append(
|
allocations.append(
|
||||||
self.db.network_allocation_create(context, data))
|
self.db.network_allocation_create(context, data))
|
||||||
return allocations
|
return allocations
|
||||||
@ -354,6 +361,9 @@ class StandaloneNetworkPlugin(network.NetworkBaseAPI):
|
|||||||
'ip_version': share_network_subnet['ip_version'],
|
'ip_version': share_network_subnet['ip_version'],
|
||||||
'mtu': share_network_subnet['mtu'],
|
'mtu': share_network_subnet['mtu'],
|
||||||
}
|
}
|
||||||
|
if self.label != 'admin':
|
||||||
|
data['share_network_subnet_id'] = (
|
||||||
|
share_network_subnet['id'])
|
||||||
self.db.network_allocation_create(context, data)
|
self.db.network_allocation_create(context, data)
|
||||||
remaining_allocations.remove(allocation)
|
remaining_allocations.remove(allocation)
|
||||||
|
|
||||||
|
@ -99,6 +99,11 @@ deprecated_share_network_reset_status = policy.DeprecatedRule(
|
|||||||
deprecated_reason=DEPRECATED_REASON,
|
deprecated_reason=DEPRECATED_REASON,
|
||||||
deprecated_since=versionutils.deprecated.WALLABY
|
deprecated_since=versionutils.deprecated.WALLABY
|
||||||
)
|
)
|
||||||
|
deprecated_share_network_subnet_create_check = policy.DeprecatedRule(
|
||||||
|
name=BASE_POLICY_NAME % 'subnet_create_check',
|
||||||
|
check_str=base.RULE_DEFAULT
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
share_network_policies = [
|
share_network_policies = [
|
||||||
policy.DocumentedRuleDefault(
|
policy.DocumentedRuleDefault(
|
||||||
@ -284,6 +289,20 @@ share_network_policies = [
|
|||||||
],
|
],
|
||||||
deprecated_rule=deprecated_share_network_get_all
|
deprecated_rule=deprecated_share_network_get_all
|
||||||
),
|
),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=BASE_POLICY_NAME % 'subnet_create_check',
|
||||||
|
check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER,
|
||||||
|
scope_types=['system', 'project'],
|
||||||
|
description="Check the feasibility of create a new share network "
|
||||||
|
"subnet for share network.",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'POST',
|
||||||
|
'path': '/share-networks/{share_network_id}/action'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
deprecated_rule=deprecated_share_network_subnet_create_check
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,9 +27,13 @@ class AvailabilityZoneFilter(base_host.BaseHostFilter):
|
|||||||
props = spec.get('resource_properties', {})
|
props = spec.get('resource_properties', {})
|
||||||
request_az_id = props.get('availability_zone_id',
|
request_az_id = props.get('availability_zone_id',
|
||||||
spec.get('availability_zone_id'))
|
spec.get('availability_zone_id'))
|
||||||
|
az_request_multiple_subnet_support_map = spec.get(
|
||||||
|
'az_request_multiple_subnet_support_map', {})
|
||||||
request_azs = spec.get('availability_zones')
|
request_azs = spec.get('availability_zones')
|
||||||
host_az_id = host_state.service['availability_zone_id']
|
host_az_id = host_state.service['availability_zone_id']
|
||||||
host_az = host_state.service['availability_zone']['name']
|
host_az = host_state.service['availability_zone']['name']
|
||||||
|
host_single_subnet_only = (
|
||||||
|
not host_state.share_server_multiple_subnet_support)
|
||||||
|
|
||||||
host_satisfied = True
|
host_satisfied = True
|
||||||
if request_az_id is not None:
|
if request_az_id is not None:
|
||||||
@ -38,4 +42,15 @@ class AvailabilityZoneFilter(base_host.BaseHostFilter):
|
|||||||
if request_azs:
|
if request_azs:
|
||||||
host_satisfied = host_satisfied and host_az in request_azs
|
host_satisfied = host_satisfied and host_az in request_azs
|
||||||
|
|
||||||
|
# Only validates the multiple subnet support in case it can deny the
|
||||||
|
# host:
|
||||||
|
# 1. host is satisfying the AZ
|
||||||
|
# 2. There is a map to be checked
|
||||||
|
# 3. The host does not support a multiple subnet
|
||||||
|
if (host_satisfied and az_request_multiple_subnet_support_map and
|
||||||
|
host_single_subnet_only):
|
||||||
|
host_satisfied = (
|
||||||
|
not az_request_multiple_subnet_support_map.get(host_az_id,
|
||||||
|
False))
|
||||||
|
|
||||||
return host_satisfied
|
return host_satisfied
|
||||||
|
@ -151,6 +151,8 @@ class HostState(object):
|
|||||||
self.ipv4_support = None
|
self.ipv4_support = None
|
||||||
self.ipv6_support = None
|
self.ipv6_support = None
|
||||||
self.security_service_update_support = False
|
self.security_service_update_support = False
|
||||||
|
self.network_allocation_update_support = False
|
||||||
|
self.share_server_multiple_subnet_support = False
|
||||||
|
|
||||||
# PoolState for all pools
|
# PoolState for all pools
|
||||||
self.pools = {}
|
self.pools = {}
|
||||||
@ -346,6 +348,14 @@ class HostState(object):
|
|||||||
pool_cap['security_service_update_support'] = (
|
pool_cap['security_service_update_support'] = (
|
||||||
self.security_service_update_support)
|
self.security_service_update_support)
|
||||||
|
|
||||||
|
if 'network_allocation_update_support' not in pool_cap:
|
||||||
|
pool_cap['network_allocation_update_support'] = (
|
||||||
|
self.network_allocation_update_support)
|
||||||
|
|
||||||
|
if 'share_server_multiple_subnet_support' not in pool_cap:
|
||||||
|
pool_cap['share_server_multiple_subnet_support'] = (
|
||||||
|
self.share_server_multiple_subnet_support)
|
||||||
|
|
||||||
if self.ipv4_support is not None:
|
if self.ipv4_support is not None:
|
||||||
pool_cap['ipv4_support'] = self.ipv4_support
|
pool_cap['ipv4_support'] = self.ipv4_support
|
||||||
|
|
||||||
@ -377,6 +387,10 @@ class HostState(object):
|
|||||||
self.ipv6_support = capability['ipv6_support']
|
self.ipv6_support = capability['ipv6_support']
|
||||||
self.security_service_update_support = capability.get(
|
self.security_service_update_support = capability.get(
|
||||||
'security_service_update_support', False)
|
'security_service_update_support', False)
|
||||||
|
self.network_allocation_update_support = capability.get(
|
||||||
|
'network_allocation_update_support', False)
|
||||||
|
self.share_server_multiple_subnet_support = capability.get(
|
||||||
|
'share_server_multiple_subnet_support', False)
|
||||||
|
|
||||||
def consume_from_share(self, share):
|
def consume_from_share(self, share):
|
||||||
"""Incrementally update host state from an share."""
|
"""Incrementally update host state from an share."""
|
||||||
@ -477,6 +491,10 @@ class PoolState(HostState):
|
|||||||
'sg_consistent_snapshot_support')
|
'sg_consistent_snapshot_support')
|
||||||
self.security_service_update_support = capability.get(
|
self.security_service_update_support = capability.get(
|
||||||
'security_service_update_support', False)
|
'security_service_update_support', False)
|
||||||
|
self.network_allocation_update_support = capability.get(
|
||||||
|
'network_allocation_update_support', False)
|
||||||
|
self.share_server_multiple_subnet_support = capability.get(
|
||||||
|
'share_server_multiple_subnet_support', False)
|
||||||
|
|
||||||
def update_pools(self, capability):
|
def update_pools(self, capability):
|
||||||
# Do nothing, since we don't have pools within pool, yet
|
# Do nothing, since we don't have pools within pool, yet
|
||||||
|
@ -60,7 +60,11 @@ def generate_stats(host_state, properties):
|
|||||||
'ipv4_support': host_state.ipv4_support,
|
'ipv4_support': host_state.ipv4_support,
|
||||||
'ipv6_support': host_state.ipv6_support,
|
'ipv6_support': host_state.ipv6_support,
|
||||||
'security_service_update_support': (
|
'security_service_update_support': (
|
||||||
host_state.security_service_update_support)
|
host_state.security_service_update_support),
|
||||||
|
'network_allocation_update_support': (
|
||||||
|
host_state.network_allocation_update_support),
|
||||||
|
'share_server_multiple_subnet_support': (
|
||||||
|
host_state.share_server_multiple_subnet_support)
|
||||||
}
|
}
|
||||||
|
|
||||||
host_caps = host_state.capabilities
|
host_caps = host_state.capabilities
|
||||||
|
@ -93,6 +93,30 @@ def locked_security_service_update_operation(operation):
|
|||||||
return wrapped
|
return wrapped
|
||||||
|
|
||||||
|
|
||||||
|
def locked_share_server_update_allocations_operation(operation):
|
||||||
|
"""Lock decorator for share server update allocations operation.
|
||||||
|
|
||||||
|
Takes a named lock prior to executing the operation. The lock is named with
|
||||||
|
the ids of the share network and the region to be updated.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def wrapped(*args, **kwargs):
|
||||||
|
az_id = kwargs.get('availability_zone_id')
|
||||||
|
share_net_id = kwargs.get('share_network_id')
|
||||||
|
|
||||||
|
@coordination.synchronized(
|
||||||
|
'locked-share-server-update-allocations-operation-%(net)s-%(az)s'
|
||||||
|
% {
|
||||||
|
'net': share_net_id,
|
||||||
|
'az': az_id,
|
||||||
|
})
|
||||||
|
def locked_share_server_allocations_operation(*_args, **_kwargs):
|
||||||
|
return operation(*_args, **_kwargs)
|
||||||
|
return locked_share_server_allocations_operation(*args, **kwargs)
|
||||||
|
|
||||||
|
return wrapped
|
||||||
|
|
||||||
|
|
||||||
class API(base.Base):
|
class API(base.Base):
|
||||||
"""API for interacting with the share manager."""
|
"""API for interacting with the share manager."""
|
||||||
|
|
||||||
@ -105,13 +129,17 @@ class API(base.Base):
|
|||||||
|
|
||||||
def _get_all_availability_zones_with_subnets(self, context,
|
def _get_all_availability_zones_with_subnets(self, context,
|
||||||
share_network_id):
|
share_network_id):
|
||||||
compatible_azs = []
|
compatible_azs_name = []
|
||||||
|
compatible_azs_multiple = {}
|
||||||
for az in self.db.availability_zone_get_all(context):
|
for az in self.db.availability_zone_get_all(context):
|
||||||
if self.db.share_network_subnet_get_by_availability_zone_id(
|
subnets = (
|
||||||
|
self.db.share_network_subnets_get_all_by_availability_zone_id(
|
||||||
context, share_network_id=share_network_id,
|
context, share_network_id=share_network_id,
|
||||||
availability_zone_id=az['id']):
|
availability_zone_id=az['id']))
|
||||||
compatible_azs.append(az['name'])
|
if subnets:
|
||||||
return compatible_azs
|
compatible_azs_multiple[az['id']] = len(subnets) > 1
|
||||||
|
compatible_azs_name.append(az['name'])
|
||||||
|
return compatible_azs_name, compatible_azs_multiple
|
||||||
|
|
||||||
def _check_if_share_quotas_exceeded(self, context, quota_exception,
|
def _check_if_share_quotas_exceeded(self, context, quota_exception,
|
||||||
share_size, operation='create'):
|
share_size, operation='create'):
|
||||||
@ -189,7 +217,8 @@ class API(base.Base):
|
|||||||
snapshot_id=None, availability_zone=None, metadata=None,
|
snapshot_id=None, availability_zone=None, metadata=None,
|
||||||
share_network_id=None, share_type=None, is_public=False,
|
share_network_id=None, share_type=None, is_public=False,
|
||||||
share_group_id=None, share_group_snapshot_member=None,
|
share_group_id=None, share_group_snapshot_member=None,
|
||||||
availability_zones=None, scheduler_hints=None):
|
availability_zones=None, scheduler_hints=None,
|
||||||
|
az_request_multiple_subnet_support_map=None):
|
||||||
"""Create new share."""
|
"""Create new share."""
|
||||||
|
|
||||||
self._check_metadata_properties(metadata)
|
self._check_metadata_properties(metadata)
|
||||||
@ -345,13 +374,15 @@ class API(base.Base):
|
|||||||
# scheduler will receive a list with all availability zones that
|
# scheduler will receive a list with all availability zones that
|
||||||
# contains a subnet within the selected share network.
|
# contains a subnet within the selected share network.
|
||||||
if share_network_id and not availability_zone:
|
if share_network_id and not availability_zone:
|
||||||
azs_with_subnet = self._get_all_availability_zones_with_subnets(
|
compatible_azs_name, compatible_azs_multiple = (
|
||||||
context, share_network_id)
|
self._get_all_availability_zones_with_subnets(
|
||||||
|
context, share_network_id))
|
||||||
if not availability_zones:
|
if not availability_zones:
|
||||||
availability_zones = azs_with_subnet
|
availability_zones = compatible_azs_name
|
||||||
else:
|
else:
|
||||||
availability_zones = (
|
availability_zones = (
|
||||||
[az for az in availability_zones if az in azs_with_subnet])
|
[az for az in availability_zones
|
||||||
|
if az in compatible_azs_name])
|
||||||
if not availability_zones:
|
if not availability_zones:
|
||||||
msg = _(
|
msg = _(
|
||||||
"The share network is not supported within any requested "
|
"The share network is not supported within any requested "
|
||||||
@ -359,6 +390,12 @@ class API(base.Base):
|
|||||||
"'availability_zones' extra-spec and the availability "
|
"'availability_zones' extra-spec and the availability "
|
||||||
"zones of the share network subnets")
|
"zones of the share network subnets")
|
||||||
raise exception.InvalidInput(message=msg)
|
raise exception.InvalidInput(message=msg)
|
||||||
|
if az_request_multiple_subnet_support_map:
|
||||||
|
az_request_multiple_subnet_support_map.update(
|
||||||
|
compatible_azs_multiple)
|
||||||
|
else:
|
||||||
|
az_request_multiple_subnet_support_map = (
|
||||||
|
compatible_azs_multiple)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
share = self.db.share_create(context, options,
|
share = self.db.share_create(context, options,
|
||||||
@ -391,7 +428,9 @@ class API(base.Base):
|
|||||||
availability_zone=availability_zone, share_group=share_group,
|
availability_zone=availability_zone, share_group=share_group,
|
||||||
share_group_snapshot_member=share_group_snapshot_member,
|
share_group_snapshot_member=share_group_snapshot_member,
|
||||||
share_type_id=share_type_id, availability_zones=availability_zones,
|
share_type_id=share_type_id, availability_zones=availability_zones,
|
||||||
snapshot_host=snapshot_host, scheduler_hints=scheduler_hints)
|
snapshot_host=snapshot_host, scheduler_hints=scheduler_hints,
|
||||||
|
az_request_multiple_subnet_support_map=(
|
||||||
|
az_request_multiple_subnet_support_map))
|
||||||
|
|
||||||
# Retrieve the share with instance details
|
# Retrieve the share with instance details
|
||||||
share = self.db.share_get(context, share['id'])
|
share = self.db.share_get(context, share['id'])
|
||||||
@ -468,7 +507,8 @@ class API(base.Base):
|
|||||||
host=None, availability_zone=None,
|
host=None, availability_zone=None,
|
||||||
share_group=None, share_group_snapshot_member=None,
|
share_group=None, share_group_snapshot_member=None,
|
||||||
share_type_id=None, availability_zones=None,
|
share_type_id=None, availability_zones=None,
|
||||||
snapshot_host=None, scheduler_hints=None):
|
snapshot_host=None, scheduler_hints=None,
|
||||||
|
az_request_multiple_subnet_support_map=None):
|
||||||
request_spec, share_instance = (
|
request_spec, share_instance = (
|
||||||
self.create_share_instance_and_get_request_spec(
|
self.create_share_instance_and_get_request_spec(
|
||||||
context, share, availability_zone=availability_zone,
|
context, share, availability_zone=availability_zone,
|
||||||
@ -476,7 +516,9 @@ class API(base.Base):
|
|||||||
share_network_id=share_network_id,
|
share_network_id=share_network_id,
|
||||||
share_type_id=share_type_id,
|
share_type_id=share_type_id,
|
||||||
availability_zones=availability_zones,
|
availability_zones=availability_zones,
|
||||||
snapshot_host=snapshot_host))
|
snapshot_host=snapshot_host,
|
||||||
|
az_request_multiple_subnet_support_map=(
|
||||||
|
az_request_multiple_subnet_support_map)))
|
||||||
|
|
||||||
if share_group_snapshot_member:
|
if share_group_snapshot_member:
|
||||||
# Inherit properties from the share_group_snapshot_member
|
# Inherit properties from the share_group_snapshot_member
|
||||||
@ -518,7 +560,8 @@ class API(base.Base):
|
|||||||
self, context, share, availability_zone=None,
|
self, context, share, availability_zone=None,
|
||||||
share_group=None, host=None, share_network_id=None,
|
share_group=None, host=None, share_network_id=None,
|
||||||
share_type_id=None, cast_rules_to_readonly=False,
|
share_type_id=None, cast_rules_to_readonly=False,
|
||||||
availability_zones=None, snapshot_host=None):
|
availability_zones=None, snapshot_host=None,
|
||||||
|
az_request_multiple_subnet_support_map=None):
|
||||||
|
|
||||||
availability_zone_id = None
|
availability_zone_id = None
|
||||||
if availability_zone:
|
if availability_zone:
|
||||||
@ -590,6 +633,8 @@ class API(base.Base):
|
|||||||
'share_group': share_group,
|
'share_group': share_group,
|
||||||
'availability_zone_id': availability_zone_id,
|
'availability_zone_id': availability_zone_id,
|
||||||
'availability_zones': availability_zones,
|
'availability_zones': availability_zones,
|
||||||
|
'az_request_multiple_subnet_support_map': (
|
||||||
|
az_request_multiple_subnet_support_map),
|
||||||
}
|
}
|
||||||
return request_spec, share_instance
|
return request_spec, share_instance
|
||||||
|
|
||||||
@ -643,6 +688,7 @@ class API(base.Base):
|
|||||||
except exception.OverQuota as e:
|
except exception.OverQuota as e:
|
||||||
self._check_if_replica_quotas_exceeded(context, e, share['size'])
|
self._check_if_replica_quotas_exceeded(context, e, share['size'])
|
||||||
|
|
||||||
|
az_request_multiple_subnet_support_map = {}
|
||||||
if share_network_id:
|
if share_network_id:
|
||||||
if availability_zone:
|
if availability_zone:
|
||||||
try:
|
try:
|
||||||
@ -652,24 +698,31 @@ class API(base.Base):
|
|||||||
msg = _("Share replica cannot be created because the "
|
msg = _("Share replica cannot be created because the "
|
||||||
"specified availability zone does not exist.")
|
"specified availability zone does not exist.")
|
||||||
raise exception.InvalidInput(message=msg)
|
raise exception.InvalidInput(message=msg)
|
||||||
if self.db.share_network_subnet_get_by_availability_zone_id(
|
az_id = az.get('id')
|
||||||
context, share_network_id, az.get('id')) is None:
|
subnets = (
|
||||||
|
self.db.
|
||||||
|
share_network_subnets_get_all_by_availability_zone_id(
|
||||||
|
context, share_network_id, az_id))
|
||||||
|
if not subnets:
|
||||||
msg = _("Share replica cannot be created because the "
|
msg = _("Share replica cannot be created because the "
|
||||||
"share network is not available within the "
|
"share network is not available within the "
|
||||||
"specified availability zone.")
|
"specified availability zone.")
|
||||||
raise exception.InvalidShare(message=msg)
|
raise exception.InvalidShare(message=msg)
|
||||||
|
az_request_multiple_subnet_support_map[az_id] = (
|
||||||
|
len(subnets) > 1)
|
||||||
else:
|
else:
|
||||||
# NOTE(dviroel): If a target availability zone was not
|
# NOTE(dviroel): If a target availability zone was not
|
||||||
# provided, the scheduler will receive a list with all
|
# provided, the scheduler will receive a list with all
|
||||||
# availability zones that contains subnets within the
|
# availability zones that contains subnets within the
|
||||||
# selected share network.
|
# selected share network.
|
||||||
azs_subnet = self._get_all_availability_zones_with_subnets(
|
compatible_azs_name, compatible_azs_multiple = (
|
||||||
context, share_network_id)
|
self._get_all_availability_zones_with_subnets(
|
||||||
|
context, share_network_id))
|
||||||
if not type_azs:
|
if not type_azs:
|
||||||
type_azs = azs_subnet
|
type_azs = compatible_azs_name
|
||||||
else:
|
else:
|
||||||
type_azs = (
|
type_azs = (
|
||||||
[az for az in type_azs if az in azs_subnet])
|
[az for az in type_azs if az in compatible_azs_name])
|
||||||
if not type_azs:
|
if not type_azs:
|
||||||
msg = _(
|
msg = _(
|
||||||
"The share network is not supported within any "
|
"The share network is not supported within any "
|
||||||
@ -677,6 +730,8 @@ class API(base.Base):
|
|||||||
"'availability_zones' extra-spec and the availability "
|
"'availability_zones' extra-spec and the availability "
|
||||||
"zones of the share network subnets")
|
"zones of the share network subnets")
|
||||||
raise exception.InvalidInput(message=msg)
|
raise exception.InvalidInput(message=msg)
|
||||||
|
az_request_multiple_subnet_support_map.update(
|
||||||
|
compatible_azs_multiple)
|
||||||
|
|
||||||
if share['replication_type'] == constants.REPLICATION_TYPE_READABLE:
|
if share['replication_type'] == constants.REPLICATION_TYPE_READABLE:
|
||||||
cast_rules_to_readonly = True
|
cast_rules_to_readonly = True
|
||||||
@ -690,7 +745,9 @@ class API(base.Base):
|
|||||||
share_network_id=share_network_id,
|
share_network_id=share_network_id,
|
||||||
share_type_id=share['instance']['share_type_id'],
|
share_type_id=share['instance']['share_type_id'],
|
||||||
cast_rules_to_readonly=cast_rules_to_readonly,
|
cast_rules_to_readonly=cast_rules_to_readonly,
|
||||||
availability_zones=type_azs)
|
availability_zones=type_azs,
|
||||||
|
az_request_multiple_subnet_support_map=(
|
||||||
|
az_request_multiple_subnet_support_map))
|
||||||
)
|
)
|
||||||
QUOTAS.commit(
|
QUOTAS.commit(
|
||||||
context, reservations, project_id=share['project_id'],
|
context, reservations, project_id=share['project_id'],
|
||||||
@ -860,9 +917,8 @@ class API(base.Base):
|
|||||||
if share_server['status'] != constants.STATUS_ACTIVE:
|
if share_server['status'] != constants.STATUS_ACTIVE:
|
||||||
msg = _("The provided share server is not active.")
|
msg = _("The provided share server is not active.")
|
||||||
raise exception.InvalidShareServer(reason=msg)
|
raise exception.InvalidShareServer(reason=msg)
|
||||||
subnet = self.db.share_network_subnet_get(
|
share_data['share_network_id'] = (
|
||||||
context, share_server['share_network_subnet_id'])
|
share_server['share_network_id'])
|
||||||
share_data['share_network_id'] = subnet['share_network_id']
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
share_network = self.db.share_network_get(
|
share_network = self.db.share_network_get(
|
||||||
@ -1322,7 +1378,7 @@ class API(base.Base):
|
|||||||
|
|
||||||
values = {
|
values = {
|
||||||
'host': host,
|
'host': host,
|
||||||
'share_network_subnet_id': share_net_subnet['id'],
|
'share_network_subnets': [share_net_subnet],
|
||||||
'status': constants.STATUS_MANAGING,
|
'status': constants.STATUS_MANAGING,
|
||||||
'is_auto_deletable': False,
|
'is_auto_deletable': False,
|
||||||
'identifier': identifier,
|
'identifier': identifier,
|
||||||
@ -2659,11 +2715,11 @@ class API(base.Base):
|
|||||||
# we should deny this operation.
|
# we should deny this operation.
|
||||||
dest_az = self.db.availability_zone_get(
|
dest_az = self.db.availability_zone_get(
|
||||||
context, service['availability_zone']['name'])
|
context, service['availability_zone']['name'])
|
||||||
compatible_subnet = (
|
compatible_subnets = (
|
||||||
self.db.share_network_subnet_get_by_availability_zone_id(
|
self.db.share_network_subnets_get_all_by_availability_zone_id(
|
||||||
context, new_share_network_id, dest_az['id']))
|
context, new_share_network_id, dest_az['id']))
|
||||||
|
|
||||||
if not compatible_subnet:
|
if not compatible_subnets:
|
||||||
msg = _("The share network %(network)s does not have a subnet "
|
msg = _("The share network %(network)s does not have a subnet "
|
||||||
"that spans the destination host availability zone.")
|
"that spans the destination host availability zone.")
|
||||||
payload = {'network': new_share_network_id}
|
payload = {'network': new_share_network_id}
|
||||||
@ -2671,11 +2727,8 @@ class API(base.Base):
|
|||||||
|
|
||||||
net_changes_identified = False
|
net_changes_identified = False
|
||||||
if new_share_network:
|
if new_share_network:
|
||||||
current_subnet = self.db.share_network_subnet_get(
|
net_changes_identified = not share_utils.is_az_subnets_compatible(
|
||||||
context, share_server['share_network_subnet_id'])
|
share_server['share_network_subnets'], compatible_subnets)
|
||||||
for key in ['neutron_net_id', 'neutron_subnet_id']:
|
|
||||||
if current_subnet[key] != compatible_subnet[key]:
|
|
||||||
net_changes_identified = True
|
|
||||||
|
|
||||||
# NOTE(carloss): Refreshing the list of shares since something could've
|
# NOTE(carloss): Refreshing the list of shares since something could've
|
||||||
# changed from the initial list.
|
# changed from the initial list.
|
||||||
@ -3118,28 +3171,44 @@ class API(base.Base):
|
|||||||
'hosts_check', new_security_service_id,
|
'hosts_check', new_security_service_id,
|
||||||
current_security_service_id=current_security_service_id)
|
current_security_service_id=current_security_service_id)
|
||||||
|
|
||||||
# check if there is an entry being processed
|
return self._do_update_validate_hosts(
|
||||||
|
context, share_network['id'], backend_hosts, update_key,
|
||||||
|
new_security_service_id=new_security_service_id,
|
||||||
|
current_security_service_id=current_security_service_id)
|
||||||
|
|
||||||
|
def _do_update_validate_hosts(
|
||||||
|
self, context, share_network_id,
|
||||||
|
backend_hosts, update_key, new_share_network_subnet=None,
|
||||||
|
new_security_service_id=None, current_security_service_id=None):
|
||||||
|
|
||||||
|
# check if there is an entry being processed.
|
||||||
update_value = self.db.async_operation_data_get(
|
update_value = self.db.async_operation_data_get(
|
||||||
context, share_network['id'], update_key)
|
context, share_network_id, update_key)
|
||||||
if not update_value:
|
if not update_value:
|
||||||
# Create a new entry, send all asynchronous rpcs and return
|
# Create a new entry, send all asynchronous rpcs and return.
|
||||||
hosts_to_validate = {}
|
hosts_to_validate = {}
|
||||||
for host in backend_hosts:
|
for host in backend_hosts:
|
||||||
hosts_to_validate[host] = None
|
hosts_to_validate[host] = None
|
||||||
self.db.async_operation_data_update(
|
self.db.async_operation_data_update(
|
||||||
context, share_network['id'],
|
context, share_network_id,
|
||||||
{update_key: json.dumps(hosts_to_validate)})
|
{update_key: json.dumps(hosts_to_validate)})
|
||||||
for host in backend_hosts:
|
for host in backend_hosts:
|
||||||
(self.share_rpcapi.
|
if new_share_network_subnet:
|
||||||
check_update_share_network_security_service(
|
(self.share_rpcapi.
|
||||||
context, host, share_network['id'],
|
check_update_share_server_network_allocations(
|
||||||
new_security_service_id,
|
context, host, share_network_id,
|
||||||
current_security_service_id=(
|
new_share_network_subnet))
|
||||||
current_security_service_id)))
|
else:
|
||||||
|
(self.share_rpcapi.
|
||||||
|
check_update_share_network_security_service(
|
||||||
|
context, host, share_network_id,
|
||||||
|
new_security_service_id,
|
||||||
|
current_security_service_id=(
|
||||||
|
current_security_service_id)))
|
||||||
return None, hosts_to_validate
|
return None, hosts_to_validate
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# process current existing hosts and update them if needed
|
# process current existing hosts and update them if needed.
|
||||||
current_hosts = json.loads(update_value)
|
current_hosts = json.loads(update_value)
|
||||||
hosts_to_include = (
|
hosts_to_include = (
|
||||||
set(backend_hosts).difference(set(current_hosts.keys())))
|
set(backend_hosts).difference(set(current_hosts.keys())))
|
||||||
@ -3147,24 +3216,30 @@ class API(base.Base):
|
|||||||
for host in backend_hosts:
|
for host in backend_hosts:
|
||||||
hosts_to_validate[host] = current_hosts.get(host, None)
|
hosts_to_validate[host] = current_hosts.get(host, None)
|
||||||
|
|
||||||
# Check if there is any unsupported host
|
# Check if there is any unsupported host.
|
||||||
if any(hosts_to_validate[host] is False for host in backend_hosts):
|
if any(hosts_to_validate[host] is False for host in backend_hosts):
|
||||||
return False, hosts_to_validate
|
return False, hosts_to_validate
|
||||||
|
|
||||||
# Update the list of hosts to be validated
|
# Update the list of hosts to be validated.
|
||||||
if hosts_to_include:
|
if hosts_to_include:
|
||||||
self.db.async_operation_data_update(
|
self.db.async_operation_data_update(
|
||||||
context, share_network['id'],
|
context, share_network_id,
|
||||||
{update_key: json.dumps(hosts_to_validate)})
|
{update_key: json.dumps(hosts_to_validate)})
|
||||||
|
|
||||||
for host in hosts_to_include:
|
for host in hosts_to_include:
|
||||||
# send asynchronous check only for new backend hosts
|
# send asynchronous check only for new backend hosts.
|
||||||
(self.share_rpcapi.
|
if new_share_network_subnet:
|
||||||
check_update_share_network_security_service(
|
(self.share_rpcapi.
|
||||||
context, host, share_network['id'],
|
check_update_share_server_network_allocations(
|
||||||
new_security_service_id,
|
context, host, share_network_id,
|
||||||
current_security_service_id=(
|
new_share_network_subnet))
|
||||||
current_security_service_id)))
|
else:
|
||||||
|
(self.share_rpcapi.
|
||||||
|
check_update_share_network_security_service(
|
||||||
|
context, host, share_network_id,
|
||||||
|
new_security_service_id,
|
||||||
|
current_security_service_id=(
|
||||||
|
current_security_service_id)))
|
||||||
|
|
||||||
return None, hosts_to_validate
|
return None, hosts_to_validate
|
||||||
|
|
||||||
@ -3190,7 +3265,6 @@ class API(base.Base):
|
|||||||
curr_sec_serv_id = (
|
curr_sec_serv_id = (
|
||||||
current_security_service['id']
|
current_security_service['id']
|
||||||
if current_security_service else None)
|
if current_security_service else None)
|
||||||
|
|
||||||
key = self.get_security_service_update_key(
|
key = self.get_security_service_update_key(
|
||||||
'hosts_check', new_security_service['id'],
|
'hosts_check', new_security_service['id'],
|
||||||
current_security_service_id=curr_sec_serv_id)
|
current_security_service_id=curr_sec_serv_id)
|
||||||
@ -3306,3 +3380,251 @@ class API(base.Base):
|
|||||||
|
|
||||||
LOG.info('Security service update has been started for share network '
|
LOG.info('Security service update has been started for share network '
|
||||||
'%(share_net_id)s.', {'share_net_id': share_network['id']})
|
'%(share_net_id)s.', {'share_net_id': share_network['id']})
|
||||||
|
|
||||||
|
@locked_share_server_update_allocations_operation
|
||||||
|
def _share_server_update_allocations_validate_hosts(
|
||||||
|
self, context, backend_hosts, update_key, share_network_id=None,
|
||||||
|
neutron_net_id=None, neutron_subnet_id=None,
|
||||||
|
availability_zone_id=None):
|
||||||
|
|
||||||
|
new_share_network_subnet = {
|
||||||
|
'neutron_net_id': neutron_net_id,
|
||||||
|
'neutron_subnet_id': neutron_subnet_id,
|
||||||
|
'availability_zone_id': availability_zone_id,
|
||||||
|
}
|
||||||
|
return self._do_update_validate_hosts(
|
||||||
|
context, share_network_id, backend_hosts, update_key,
|
||||||
|
new_share_network_subnet=new_share_network_subnet)
|
||||||
|
|
||||||
|
def get_share_server_update_allocations_key(
|
||||||
|
self, share_network_id, availability_zone_id):
|
||||||
|
return ('share_server_update_allocations_' + share_network_id + '_' +
|
||||||
|
str(availability_zone_id) + '_' + 'hosts_check')
|
||||||
|
|
||||||
|
def _share_server_update_allocations_initial_checks(
|
||||||
|
self, context, share_network, share_servers):
|
||||||
|
|
||||||
|
api_common.check_share_network_is_active(share_network)
|
||||||
|
if not share_network['network_allocation_update_support']:
|
||||||
|
msg = _("Updating network allocations is not supported on this "
|
||||||
|
"share network (%(sn_id)s) while it has shares. "
|
||||||
|
"See the capability 'network_allocation_update_support'."
|
||||||
|
) % {"sn_id": share_network["id"]}
|
||||||
|
raise exception.InvalidShareNetwork(reason=msg)
|
||||||
|
|
||||||
|
backend_hosts = set()
|
||||||
|
for share_server in share_servers:
|
||||||
|
share_server_id = share_server['id']
|
||||||
|
if share_server['status'] != constants.STATUS_ACTIVE:
|
||||||
|
msg = _('The share server %(server)s in the specified '
|
||||||
|
'availability zone subnet is not currently '
|
||||||
|
'available.') % {'server': share_server_id}
|
||||||
|
raise exception.InvalidShareNetwork(reason=msg)
|
||||||
|
|
||||||
|
# We need an admin context to validate these hosts.
|
||||||
|
admin_ctx = manila_context.get_admin_context()
|
||||||
|
# Make sure the host is in the list of available hosts.
|
||||||
|
utils.validate_service_host(admin_ctx, share_server['host'])
|
||||||
|
|
||||||
|
# Create a set of backend hosts.
|
||||||
|
backend_hosts.add(share_server['host'])
|
||||||
|
|
||||||
|
shares = self.db.share_get_all_by_share_server(
|
||||||
|
context, share_server_id)
|
||||||
|
shares_not_available = [
|
||||||
|
share['id']
|
||||||
|
for share in shares if
|
||||||
|
share['status'] != constants.STATUS_AVAILABLE]
|
||||||
|
|
||||||
|
if shares_not_available:
|
||||||
|
msg = _("The share server (%(server_id)s) in the specified "
|
||||||
|
"availability zone subnet has some shares that are "
|
||||||
|
"not available: "
|
||||||
|
"%(share_ids)s.") % {
|
||||||
|
'server_id': share_server_id,
|
||||||
|
'share_ids': shares_not_available,
|
||||||
|
}
|
||||||
|
raise exception.InvalidShareNetwork(reason=msg)
|
||||||
|
|
||||||
|
shares_rules_not_available = [
|
||||||
|
share['id'] for share in shares if
|
||||||
|
share['instance'][
|
||||||
|
'access_rules_status'] != constants.STATUS_ACTIVE]
|
||||||
|
|
||||||
|
if shares_rules_not_available:
|
||||||
|
msg = _("The share server (%(server_id)s) in the specified "
|
||||||
|
"availability zone subnet has either these shares or "
|
||||||
|
"one of their replicas or migration copies that are "
|
||||||
|
"not available: %(share_ids)s.") % {
|
||||||
|
'server_id': share_server_id,
|
||||||
|
'share_ids': shares_rules_not_available,
|
||||||
|
}
|
||||||
|
raise exception.InvalidShareNetwork(reason=msg)
|
||||||
|
|
||||||
|
busy_shares = []
|
||||||
|
for share in shares:
|
||||||
|
try:
|
||||||
|
self._check_is_share_busy(share)
|
||||||
|
except exception.ShareBusyException:
|
||||||
|
busy_shares.append(share['id'])
|
||||||
|
if busy_shares:
|
||||||
|
msg = _("The share server (%(server_id)s) in the specified "
|
||||||
|
"availability zone subnet has some shares that are "
|
||||||
|
"busy as part of an active task: "
|
||||||
|
"%(share_ids)s.") % {
|
||||||
|
'server_id': share_server_id,
|
||||||
|
'share_ids': busy_shares,
|
||||||
|
}
|
||||||
|
raise exception.InvalidShareNetwork(reason=msg)
|
||||||
|
|
||||||
|
return backend_hosts
|
||||||
|
|
||||||
|
def check_update_share_server_network_allocations(
|
||||||
|
self, context, share_network, new_share_network_subnet,
|
||||||
|
reset_operation):
|
||||||
|
|
||||||
|
backend_hosts = self._share_server_update_allocations_initial_checks(
|
||||||
|
context, share_network, new_share_network_subnet['share_servers'])
|
||||||
|
|
||||||
|
update_key = self.get_share_server_update_allocations_key(
|
||||||
|
share_network['id'],
|
||||||
|
new_share_network_subnet['availability_zone_id'])
|
||||||
|
if reset_operation:
|
||||||
|
self.db.async_operation_data_delete(context, share_network['id'],
|
||||||
|
update_key)
|
||||||
|
try:
|
||||||
|
compatible, hosts_info = (
|
||||||
|
self._share_server_update_allocations_validate_hosts(
|
||||||
|
context, backend_hosts, update_key,
|
||||||
|
share_network_id=share_network['id'],
|
||||||
|
neutron_net_id=(
|
||||||
|
new_share_network_subnet.get('neutron_net_id')),
|
||||||
|
neutron_subnet_id=(
|
||||||
|
new_share_network_subnet.get('neutron_subnet_id')),
|
||||||
|
availability_zone_id=new_share_network_subnet.get(
|
||||||
|
"availability_zone_id")))
|
||||||
|
except Exception as e:
|
||||||
|
LOG.exception(e)
|
||||||
|
# Due to an internal error, we will delete the entry.
|
||||||
|
self.db.async_operation_data_delete(
|
||||||
|
context, share_network['id'], update_key)
|
||||||
|
msg = _(
|
||||||
|
"The server's allocations cannot be updated on availability "
|
||||||
|
"zone %(zone_id)s of the share network %(share_net_id)s, "
|
||||||
|
"since at least one of its backend hosts do not support this "
|
||||||
|
"operation.") % {
|
||||||
|
'share_net_id': share_network['id'],
|
||||||
|
'zone_id': new_share_network_subnet['availability_zone_id']}
|
||||||
|
raise exception.InvalidShareNetwork(reason=msg)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'compatible': compatible,
|
||||||
|
'hosts_check_result': hosts_info
|
||||||
|
}
|
||||||
|
|
||||||
|
def update_share_server_network_allocations(
|
||||||
|
self, context, share_network, new_share_network_subnet):
|
||||||
|
|
||||||
|
backend_hosts = self._share_server_update_allocations_initial_checks(
|
||||||
|
context, share_network, new_share_network_subnet['share_servers'])
|
||||||
|
|
||||||
|
update_key = self.get_share_server_update_allocations_key(
|
||||||
|
share_network['id'],
|
||||||
|
new_share_network_subnet['availability_zone_id'])
|
||||||
|
|
||||||
|
# check if there is an entry being processed at this moment.
|
||||||
|
update_value = self.db.async_operation_data_get(
|
||||||
|
context, share_network['id'], update_key)
|
||||||
|
if not update_value:
|
||||||
|
msg = _(
|
||||||
|
'The share network %(share_net_id)s cannot start the update '
|
||||||
|
'process since no check operation was found. Before starting '
|
||||||
|
'the update operation, a "check" operation must be triggered '
|
||||||
|
'to validate if all backend hosts support the provided '
|
||||||
|
'configuration paramaters.') % {
|
||||||
|
'share_net_id': share_network['id']
|
||||||
|
}
|
||||||
|
raise exception.InvalidShareNetwork(reason=msg)
|
||||||
|
|
||||||
|
subnet_info = {
|
||||||
|
'availability_zone_id':
|
||||||
|
new_share_network_subnet.get("availability_zone_id"),
|
||||||
|
'neutron_net_id':
|
||||||
|
new_share_network_subnet.get('neutron_net_id'),
|
||||||
|
'neutron_subnet_id':
|
||||||
|
new_share_network_subnet.get('neutron_subnet_id'),
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
result, __ = self._share_server_update_allocations_validate_hosts(
|
||||||
|
context, backend_hosts, update_key,
|
||||||
|
share_network_id=share_network['id'],
|
||||||
|
neutron_net_id=(
|
||||||
|
new_share_network_subnet.get('neutron_net_id')),
|
||||||
|
neutron_subnet_id=(
|
||||||
|
new_share_network_subnet.get('neutron_subnet_id')),
|
||||||
|
availability_zone_id=new_share_network_subnet.get(
|
||||||
|
"availability_zone_id"))
|
||||||
|
except Exception:
|
||||||
|
# Due to an internal error, we will delete the entry.
|
||||||
|
self.db.async_operation_data_delete(
|
||||||
|
context, share_network['id'], update_key)
|
||||||
|
msg = _(
|
||||||
|
"The server's allocations cannot be updated on availability "
|
||||||
|
"zone %(zone_id)s of the share network %(share_net_id)s, "
|
||||||
|
"since an internal error occurred."
|
||||||
|
"operation.") % {
|
||||||
|
'share_net_id': share_network['id'],
|
||||||
|
'zone_id': subnet_info['availability_zone_id']
|
||||||
|
}
|
||||||
|
raise exception.InvalidShareNetwork(reason=msg)
|
||||||
|
|
||||||
|
if result is False:
|
||||||
|
msg = _(
|
||||||
|
"The server's allocations cannot be updated on availability "
|
||||||
|
"zone %(zone_id)s of the share network %(share_net_id)s, "
|
||||||
|
"since at least one of its backend hosts do not support this "
|
||||||
|
"operation.") % {
|
||||||
|
'share_net_id': share_network['id'],
|
||||||
|
'zone_id': subnet_info['availability_zone_id']
|
||||||
|
}
|
||||||
|
raise exception.InvalidShareNetwork(reason=msg)
|
||||||
|
elif result is None:
|
||||||
|
msg = _(
|
||||||
|
'Not all of the validation has been completed yet. A '
|
||||||
|
'validation check is in progress. This operation can be '
|
||||||
|
'retried.')
|
||||||
|
raise exception.InvalidShareNetwork(reason=msg)
|
||||||
|
|
||||||
|
# change db to start the update.
|
||||||
|
self.db.share_network_update(
|
||||||
|
context, share_network['id'],
|
||||||
|
{'status': constants.STATUS_NETWORK_CHANGE})
|
||||||
|
share_servers_ids = [ss['id'] for ss in
|
||||||
|
new_share_network_subnet['share_servers']]
|
||||||
|
self.db.share_servers_update(
|
||||||
|
context, share_servers_ids,
|
||||||
|
{'status': constants.STATUS_SERVER_NETWORK_CHANGE})
|
||||||
|
|
||||||
|
# create the new subnet.
|
||||||
|
new_share_network_subnet_db = self.db.share_network_subnet_create(
|
||||||
|
context, new_share_network_subnet)
|
||||||
|
|
||||||
|
# triggering the actual update.
|
||||||
|
for backend_host in backend_hosts:
|
||||||
|
self.share_rpcapi.update_share_server_network_allocations(
|
||||||
|
context, backend_host, share_network['id'],
|
||||||
|
new_share_network_subnet_db['id'])
|
||||||
|
|
||||||
|
# Erase db entry, since we won't need it anymore.
|
||||||
|
self.db.async_operation_data_delete(
|
||||||
|
context, share_network['id'], update_key)
|
||||||
|
|
||||||
|
LOG.info('Share servers allocations update have been started for '
|
||||||
|
'share network %(share_net_id)s on its availability zone '
|
||||||
|
'%(az_id)s with new subnet %(subnet_id)s.',
|
||||||
|
{
|
||||||
|
'share_net_id': share_network['id'],
|
||||||
|
'az_id': new_share_network_subnet['availability_zone_id'],
|
||||||
|
'subnet_id': new_share_network_subnet_db['id'],
|
||||||
|
})
|
||||||
|
return new_share_network_subnet_db
|
||||||
|
@ -277,6 +277,10 @@ class ShareDriver(object):
|
|||||||
# in-use share networks. This property will be saved in every new share
|
# in-use share networks. This property will be saved in every new share
|
||||||
# server.
|
# server.
|
||||||
self.security_service_update_support = False
|
self.security_service_update_support = False
|
||||||
|
# Indicates whether a driver supports adding subnet with its
|
||||||
|
# allocations to an in-use share network availability zone. This
|
||||||
|
# property will be saved in every new share server.
|
||||||
|
self.network_allocation_update_support = False
|
||||||
self.dhss_mandatory_security_service_association = {}
|
self.dhss_mandatory_security_service_association = {}
|
||||||
|
|
||||||
self.pools = []
|
self.pools = []
|
||||||
@ -1323,6 +1327,9 @@ class ShareDriver(object):
|
|||||||
goodness_function=self.get_goodness_function(),
|
goodness_function=self.get_goodness_function(),
|
||||||
security_service_update_support=(
|
security_service_update_support=(
|
||||||
self.security_service_update_support),
|
self.security_service_update_support),
|
||||||
|
network_allocation_update_support=(
|
||||||
|
self.network_allocation_update_support),
|
||||||
|
share_server_multiple_subnet_support=False,
|
||||||
)
|
)
|
||||||
if isinstance(data, dict):
|
if isinstance(data, dict):
|
||||||
common.update(data)
|
common.update(data)
|
||||||
@ -3341,3 +3348,265 @@ class ShareDriver(object):
|
|||||||
otherwise.
|
otherwise.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def check_update_share_server_network_allocations(
|
||||||
|
self, context, share_server, current_network_allocations,
|
||||||
|
new_share_network_subnet, security_services, share_instances,
|
||||||
|
share_instances_rules):
|
||||||
|
""""Check if the share server network allocation update is supported.
|
||||||
|
|
||||||
|
:param context: The 'context.RequestContext' object for the request.
|
||||||
|
:param share_server: Reference to the share server object that will be
|
||||||
|
updated.
|
||||||
|
:param current_network_allocations: All network allocations associated
|
||||||
|
with the share server that will be updated:
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
{
|
||||||
|
'admin_network_allocations':
|
||||||
|
[
|
||||||
|
{
|
||||||
|
'ip_address': '10.193.154.11',
|
||||||
|
'ip_version': 4,
|
||||||
|
'cidr': '10.193.154.0/28',
|
||||||
|
'gateway': '10.193.154.1',
|
||||||
|
'mtu': 1500,
|
||||||
|
'network_type': 'vlan',
|
||||||
|
'segmentation_id': 3000,
|
||||||
|
'mac_address': ' AA:AA:AA:AA:AA:AA',
|
||||||
|
...
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'subnets':
|
||||||
|
[
|
||||||
|
{
|
||||||
|
'share_network_subnet_id': '0bdeaa8c6db3-3bc10d67',
|
||||||
|
'neutron_net_id': '2598-4122-bb62-0bdeaa8c6db3',
|
||||||
|
'neutron_subnet_id': '3bc10d67-2598-4122-bb62',
|
||||||
|
'network_allocations':
|
||||||
|
[
|
||||||
|
{
|
||||||
|
'ip_address': '10.193.154.10',
|
||||||
|
'ip_version': 4,
|
||||||
|
'cidr': '10.193.154.0/28',
|
||||||
|
'gateway': '10.193.154.1',
|
||||||
|
'mtu': 1500,
|
||||||
|
'network_type': 'vlan',
|
||||||
|
'segmentation_id': 3000,
|
||||||
|
'mac_address': ' AA:AA:AA:AA:AA:AA',
|
||||||
|
...
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
:param new_share_network_subnet: dict containing the subnet data that
|
||||||
|
has to be checked if it can be added to the share server:
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
{
|
||||||
|
'availability_zone_id': '0bdeaa8c6db3-3bc10d67',
|
||||||
|
'neutron_net_id': '2598-4122-bb62-0bdeaa8c6db3',
|
||||||
|
'neutron_subnet_id': '3bc10d67-2598-4122-bb62',
|
||||||
|
'ip_version': 4,
|
||||||
|
'cidr': '10.193.154.0/28',
|
||||||
|
'gateway': '10.193.154.1',
|
||||||
|
'mtu': 1500,
|
||||||
|
'network_type': 'vlan',
|
||||||
|
'segmentation_id': 3000,
|
||||||
|
}
|
||||||
|
|
||||||
|
:param security_services: list of security services configured with
|
||||||
|
this share server.
|
||||||
|
:param share_instances: A list of share instances that belong to the
|
||||||
|
share server that is affected by the update.
|
||||||
|
:param share_instances_rules: A list of access rules, grouped by share
|
||||||
|
instance, in the following format.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
'share_instance_id': '3bc10d67-2598-4122-bb62-0bdeaa8c6db3',
|
||||||
|
'access_rules':
|
||||||
|
[
|
||||||
|
{
|
||||||
|
'access_id':'906d0094-3e34-4d6c-a184-d08a908033e3',
|
||||||
|
'access_type':'ip',
|
||||||
|
'access_key':None,
|
||||||
|
'access_to':'10.0.0.1',
|
||||||
|
'access_level':'rw'
|
||||||
|
...
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
:return Boolean indicating whether the update is possible or not. It is
|
||||||
|
the driver responsibility to log the reason why not accepting the
|
||||||
|
update.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def update_share_server_network_allocations(
|
||||||
|
self, context, share_server, current_network_allocations,
|
||||||
|
new_network_allocations, security_services, shares, snapshots):
|
||||||
|
"""Updates a share server's network allocations.
|
||||||
|
|
||||||
|
:param context: The 'context.RequestContext' object for the request.
|
||||||
|
:param share_server: reference to the share server that have to update
|
||||||
|
network allocations.
|
||||||
|
:param current_network_allocations: all network allocations associated
|
||||||
|
with the share server that will be updated
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
{
|
||||||
|
'admin_network_allocations':
|
||||||
|
[
|
||||||
|
{
|
||||||
|
'ip_address': '10.193.154.11',
|
||||||
|
'ip_version': 4,
|
||||||
|
'cidr': '10.193.154.0/28',
|
||||||
|
'gateway': '10.193.154.1',
|
||||||
|
'mtu': 1500,
|
||||||
|
'network_type': 'vlan',
|
||||||
|
'segmentation_id': 3000,
|
||||||
|
'mac_address': ' AA:AA:AA:AA:AA:AA',
|
||||||
|
},
|
||||||
|
...
|
||||||
|
],
|
||||||
|
'subnets':
|
||||||
|
[
|
||||||
|
{
|
||||||
|
'share_network_subnet_id': '0bdeaa8c6db3-3bc10d67',
|
||||||
|
'neutron_net_id': '2598-4122-bb62-0bdeaa8c6db3',
|
||||||
|
'neutron_subnet_id': '3bc10d67-2598-4122-bb62',
|
||||||
|
'network_allocations':
|
||||||
|
[
|
||||||
|
{
|
||||||
|
'ip_address': '10.193.154.10',
|
||||||
|
'ip_version': 4,
|
||||||
|
'cidr': '10.193.154.0/28',
|
||||||
|
'gateway': '10.193.154.1',
|
||||||
|
'mtu': 1500,
|
||||||
|
'network_type': 'vlan',
|
||||||
|
'segmentation_id': 3000,
|
||||||
|
'mac_address': ' AA:AA:AA:AA:AA:AA',
|
||||||
|
},
|
||||||
|
...
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
:param new_network_allocations: allocations that must be configured in
|
||||||
|
the share server.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
{
|
||||||
|
'share_network_subnet_id': '0bdeaa8c6db3-3bc10d67',
|
||||||
|
'neutron_net_id': '2598-4122-bb62-0bdeaa8c6db3',
|
||||||
|
'neutron_subnet_id': '3bc10d67-2598-4122-bb62',
|
||||||
|
'network_allocations':
|
||||||
|
[
|
||||||
|
{
|
||||||
|
'ip_address': '10.193.154.10',
|
||||||
|
'ip_version': 4,
|
||||||
|
'cidr': '10.193.154.0/28',
|
||||||
|
'gateway': '10.193.154.1',
|
||||||
|
'mtu': 1500,
|
||||||
|
'network_type': 'vlan',
|
||||||
|
'segmentation_id': 3000,
|
||||||
|
'mac_address': 'AA:AA:AA:AA:AA:AA',
|
||||||
|
...
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
:param security_services: list of security services configured with
|
||||||
|
this share server.
|
||||||
|
:param shares: All shares in the share server.
|
||||||
|
:param snapshots: All snapshots in the share server.
|
||||||
|
|
||||||
|
:raises: Exception.
|
||||||
|
By raising an exception, the share server and all its shares and
|
||||||
|
snapshots instances will be set to 'error'. The error can contain
|
||||||
|
the field 'details_data' as a dict with the key 'server_details'
|
||||||
|
containing the backend details dict that will be saved to share
|
||||||
|
server.
|
||||||
|
|
||||||
|
:return If the update changes the shares export locations or snapshots
|
||||||
|
export locations, this method should return a dictionary
|
||||||
|
containing a list of share instances and snapshot instances
|
||||||
|
indexed by their id's, where each instance should provide a
|
||||||
|
dict with the relevant information that need to be updated.
|
||||||
|
Also, the returned dict can contain the updated back end
|
||||||
|
details to be saved in the database.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
{
|
||||||
|
'share_updates':
|
||||||
|
{
|
||||||
|
'4363eb92-23ca-4888-9e24-502387816e2a':
|
||||||
|
[
|
||||||
|
{
|
||||||
|
'path': '1.2.3.4:/foo',
|
||||||
|
'metadata': {},
|
||||||
|
'is_admin_only': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'path': '5.6.7.8:/foo',
|
||||||
|
'metadata': {},
|
||||||
|
'is_admin_only': True
|
||||||
|
},
|
||||||
|
],
|
||||||
|
...
|
||||||
|
},
|
||||||
|
'snapshot_updates':
|
||||||
|
{
|
||||||
|
'bc4e3b28-0832-4168-b688-67fdc3e9d408':
|
||||||
|
{
|
||||||
|
'provider_location': '/snapshots/foo/bar_1',
|
||||||
|
'export_locations':
|
||||||
|
[
|
||||||
|
{
|
||||||
|
'path': '1.2.3.4:/snapshots/foo/bar_1',
|
||||||
|
'is_admin_only': False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'path': '5.6.7.8:/snapshots/foo/bar_1',
|
||||||
|
'is_admin_only': True,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'2e62b7ea-4e30-445f-bc05-fd523ca62941':
|
||||||
|
{
|
||||||
|
'provider_location': '/snapshots/foo/bar_2',
|
||||||
|
'export_locations':
|
||||||
|
[
|
||||||
|
{
|
||||||
|
'path': '1.2.3.4:/snapshots/foo/bar_2',
|
||||||
|
'is_admin_only': False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'path': '5.6.7.8:/snapshots/foo/bar_2',
|
||||||
|
'is_admin_only': True,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
'server_details':
|
||||||
|
{
|
||||||
|
'new_share_server_info_key':
|
||||||
|
'new_share_server_info_value',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
@ -296,6 +296,8 @@ class ContainerShareDriver(driver.ShareDriver, driver.ExecuteMixin):
|
|||||||
|
|
||||||
@utils.synchronized("veth-lock", external=True)
|
@utils.synchronized("veth-lock", external=True)
|
||||||
def _setup_server(self, network_info, metadata=None):
|
def _setup_server(self, network_info, metadata=None):
|
||||||
|
# NOTE(felipe_rodrigues): keep legacy network_info support as a dict.
|
||||||
|
network_info = network_info[0]
|
||||||
msg = "Creating share server '%s'."
|
msg = "Creating share server '%s'."
|
||||||
server_id = self._get_container_name(network_info["server_id"])
|
server_id = self._get_container_name(network_info["server_id"])
|
||||||
LOG.debug(msg, server_id)
|
LOG.debug(msg, server_id)
|
||||||
|
@ -290,6 +290,9 @@ class EMCShareDriver(driver.ShareDriver):
|
|||||||
|
|
||||||
def _setup_server(self, network_info, metadata=None):
|
def _setup_server(self, network_info, metadata=None):
|
||||||
"""Set up and configures share server with given network parameters."""
|
"""Set up and configures share server with given network parameters."""
|
||||||
|
# NOTE(felipe_rodrigues): keep legacy network_info support as a dict.
|
||||||
|
network_info = network_info[0]
|
||||||
|
|
||||||
return self.plugin.setup_server(network_info, metadata)
|
return self.plugin.setup_server(network_info, metadata)
|
||||||
|
|
||||||
def _teardown_server(self, server_details, security_services=None):
|
def _teardown_server(self, server_details, security_services=None):
|
||||||
|
@ -892,6 +892,9 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
def _setup_server(self, network_info, metadata=None):
|
def _setup_server(self, network_info, metadata=None):
|
||||||
|
# NOTE(felipe_rodrigues): keep legacy network_info support as a dict.
|
||||||
|
network_info = network_info[0]
|
||||||
|
|
||||||
msg = "Creating share server '%s'."
|
msg = "Creating share server '%s'."
|
||||||
LOG.debug(msg, network_info['server_id'])
|
LOG.debug(msg, network_info['server_id'])
|
||||||
server = self.service_instance_manager.set_up_service_instance(
|
server = self.service_instance_manager.set_up_service_instance(
|
||||||
|
@ -432,6 +432,8 @@ class HPE3ParShareDriver(driver.ShareDriver):
|
|||||||
'vfs': vfs}
|
'vfs': vfs}
|
||||||
|
|
||||||
def _setup_server(self, network_info, metadata=None):
|
def _setup_server(self, network_info, metadata=None):
|
||||||
|
# NOTE(felipe_rodrigues): keep legacy network_info support as a dict.
|
||||||
|
network_info = network_info[0]
|
||||||
|
|
||||||
LOG.debug("begin _setup_server with %s", network_info)
|
LOG.debug("begin _setup_server with %s", network_info)
|
||||||
|
|
||||||
|
@ -223,6 +223,9 @@ class HuaweiNasDriver(driver.ShareDriver):
|
|||||||
|
|
||||||
def _setup_server(self, network_info, metadata=None):
|
def _setup_server(self, network_info, metadata=None):
|
||||||
"""Set up share server with given network parameters."""
|
"""Set up share server with given network parameters."""
|
||||||
|
# NOTE(felipe_rodrigues): keep legacy network_info support as a dict.
|
||||||
|
network_info = network_info[0]
|
||||||
|
|
||||||
return self.plugin.setup_server(network_info, metadata)
|
return self.plugin.setup_server(network_info, metadata)
|
||||||
|
|
||||||
def _teardown_server(self, server_details, security_services=None):
|
def _teardown_server(self, server_details, security_services=None):
|
||||||
|
@ -135,6 +135,8 @@ class NetAppCmodeMultiSvmShareDriver(driver.ShareDriver):
|
|||||||
self.admin_network_api)
|
self.admin_network_api)
|
||||||
|
|
||||||
def _setup_server(self, network_info, metadata=None):
|
def _setup_server(self, network_info, metadata=None):
|
||||||
|
# NOTE(felipe_rodrigues): keep legacy network_info support as a dict.
|
||||||
|
network_info = network_info[0]
|
||||||
return self.library.setup_server(network_info, metadata)
|
return self.library.setup_server(network_info, metadata)
|
||||||
|
|
||||||
def _teardown_server(self, server_details, **kwargs):
|
def _teardown_server(self, server_details, **kwargs):
|
||||||
|
@ -1658,6 +1658,7 @@ class NetAppCmodeMultiSVMFileStorageLibrary(
|
|||||||
2. Build the list of export_locations for each share
|
2. Build the list of export_locations for each share
|
||||||
3. Release all resources from the source share server
|
3. Release all resources from the source share server
|
||||||
"""
|
"""
|
||||||
|
new_network_alloc = new_network_alloc[0]
|
||||||
src_backend_name = share_utils.extract_host(
|
src_backend_name = share_utils.extract_host(
|
||||||
source_share_server['host'], level='backend_name')
|
source_share_server['host'], level='backend_name')
|
||||||
src_vserver, src_client = self._get_vserver(
|
src_vserver, src_client = self._get_vserver(
|
||||||
@ -2013,7 +2014,7 @@ class NetAppCmodeMultiSVMFileStorageLibrary(
|
|||||||
dns_ips = set()
|
dns_ips = set()
|
||||||
domains = set()
|
domains = set()
|
||||||
# Read all dns-ips and domains from other security services
|
# Read all dns-ips and domains from other security services
|
||||||
for sec_svc in network_info['security_services']:
|
for sec_svc in network_info[0]['security_services']:
|
||||||
if sec_svc['type'] == current_type:
|
if sec_svc['type'] == current_type:
|
||||||
# skip the one that we are replacing
|
# skip the one that we are replacing
|
||||||
continue
|
continue
|
||||||
|
@ -243,7 +243,7 @@ def add_hooks(f):
|
|||||||
class ShareManager(manager.SchedulerDependentManager):
|
class ShareManager(manager.SchedulerDependentManager):
|
||||||
"""Manages NAS storages."""
|
"""Manages NAS storages."""
|
||||||
|
|
||||||
RPC_API_VERSION = '1.22'
|
RPC_API_VERSION = '1.23'
|
||||||
|
|
||||||
def __init__(self, share_driver=None, service_name=None, *args, **kwargs):
|
def __init__(self, share_driver=None, service_name=None, *args, **kwargs):
|
||||||
"""Load the driver from args, or from flags."""
|
"""Load the driver from args, or from flags."""
|
||||||
@ -666,20 +666,25 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
raise exception.InvalidShareServer(reason=msg % error_params)
|
raise exception.InvalidShareServer(reason=msg % error_params)
|
||||||
parent_share_same_dest = (snapshot['share']['instance']['host']
|
parent_share_same_dest = (snapshot['share']['instance']['host']
|
||||||
== share_instance['host'])
|
== share_instance['host'])
|
||||||
share_network_subnet_id = None
|
share_network_subnets = None
|
||||||
if share_network_id:
|
if share_network_id:
|
||||||
share_network_subnet = (
|
share_network_subnets = (
|
||||||
self.db.share_network_subnet_get_by_availability_zone_id(
|
self.db.share_network_subnets_get_all_by_availability_zone_id(
|
||||||
context, share_network_id,
|
context, share_network_id,
|
||||||
availability_zone_id=share_instance.get(
|
availability_zone_id=share_instance.get(
|
||||||
'availability_zone_id')))
|
'availability_zone_id')))
|
||||||
if not share_network_subnet:
|
if not share_network_subnets:
|
||||||
raise exception.ShareNetworkSubnetNotFound(
|
raise exception.ShareNetworkSubnetNotFound(
|
||||||
share_network_subnet_id=None)
|
share_network_subnet_id=None)
|
||||||
share_network_subnet_id = share_network_subnet['id']
|
|
||||||
elif parent_share_server:
|
elif parent_share_server:
|
||||||
share_network_subnet_id = (
|
share_network_subnets = (
|
||||||
parent_share_server['share_network_subnet_id'])
|
parent_share_server['share_network_subnets'])
|
||||||
|
|
||||||
|
# NOTE(felipe_rodrigues): it can retrieve the available share
|
||||||
|
# servers using one single subnet_id from the availability zone
|
||||||
|
# subnets, because if the share server has one, it will have
|
||||||
|
# all subnets on that availability zone.
|
||||||
|
share_network_subnet_id = share_network_subnets[0]['id']
|
||||||
|
|
||||||
def get_available_share_servers():
|
def get_available_share_servers():
|
||||||
if parent_share_server and parent_share_same_dest:
|
if parent_share_server and parent_share_same_dest:
|
||||||
@ -725,10 +730,12 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
context,
|
context,
|
||||||
{
|
{
|
||||||
'host': self.host,
|
'host': self.host,
|
||||||
'share_network_subnet_id': share_network_subnet_id,
|
'share_network_subnets': share_network_subnets,
|
||||||
'status': constants.STATUS_CREATING,
|
'status': constants.STATUS_CREATING,
|
||||||
'security_service_update_support': (
|
'security_service_update_support': (
|
||||||
self.driver.security_service_update_support),
|
self.driver.security_service_update_support),
|
||||||
|
'network_allocation_update_support': (
|
||||||
|
self.driver.network_allocation_update_support),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -796,28 +803,29 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
migration.
|
migration.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
share_network_subnet = (
|
share_network_subnets = (
|
||||||
self.db.share_network_subnet_get_by_availability_zone_id(
|
self.db.share_network_subnets_get_all_by_availability_zone_id(
|
||||||
context, new_share_network_id,
|
context, new_share_network_id,
|
||||||
availability_zone_id=availability_zone_id))
|
availability_zone_id=availability_zone_id))
|
||||||
if not share_network_subnet:
|
if not share_network_subnets:
|
||||||
raise exception.ShareNetworkSubnetNotFound(
|
raise exception.ShareNetworkSubnetNotFound(
|
||||||
share_network_subnet_id=None)
|
share_network_subnet_id=None)
|
||||||
share_network_subnet_id = share_network_subnet['id']
|
|
||||||
|
|
||||||
server_metadata = {} if not server_metadata else server_metadata
|
server_metadata = {} if not server_metadata else server_metadata
|
||||||
|
|
||||||
@utils.synchronized("share_manager_%s" % share_network_subnet_id,
|
@utils.synchronized(
|
||||||
external=True)
|
"share_manager_%s" % share_network_subnets[0]['id'], external=True)
|
||||||
def _wrapped_provide_share_server_for_migration():
|
def _wrapped_provide_share_server_for_migration():
|
||||||
destination_share_server = self.db.share_server_create(
|
destination_share_server = self.db.share_server_create(
|
||||||
context,
|
context,
|
||||||
{
|
{
|
||||||
'host': self.host,
|
'host': self.host,
|
||||||
'share_network_subnet_id': share_network_subnet_id,
|
'share_network_subnets': share_network_subnets,
|
||||||
'status': constants.STATUS_CREATING,
|
'status': constants.STATUS_CREATING,
|
||||||
'security_service_update_support': (
|
'security_service_update_support': (
|
||||||
self.driver.security_service_update_support),
|
self.driver.security_service_update_support),
|
||||||
|
'network_allocation_update_support': (
|
||||||
|
self.driver.network_allocation_update_support),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -917,7 +925,7 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
|
|
||||||
def _provide_share_server_for_share_group(self, context,
|
def _provide_share_server_for_share_group(self, context,
|
||||||
share_network_id,
|
share_network_id,
|
||||||
share_network_subnet_id,
|
share_network_subnets,
|
||||||
share_group_ref,
|
share_group_ref,
|
||||||
share_group_snapshot=None):
|
share_group_snapshot=None):
|
||||||
"""Gets or creates share_server and updates share group with its id.
|
"""Gets or creates share_server and updates share group with its id.
|
||||||
@ -935,10 +943,8 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
:param context: Current context
|
:param context: Current context
|
||||||
:param share_network_id: Share network where existing share server
|
:param share_network_id: Share network where existing share server
|
||||||
should be found or created.
|
should be found or created.
|
||||||
:param share_network_subnet_id: Share network subnet where
|
:param share_network_subnets: Share network subnets where existing
|
||||||
existing share server should be found
|
share server should be found or created.
|
||||||
or created. If not specified, the
|
|
||||||
default subnet will be used.
|
|
||||||
:param share_group_ref: Share Group model
|
:param share_group_ref: Share Group model
|
||||||
:param share_group_snapshot: Optional -- ShareGroupSnapshot model. If
|
:param share_group_snapshot: Optional -- ShareGroupSnapshot model. If
|
||||||
supplied, driver will use it to choose
|
supplied, driver will use it to choose
|
||||||
@ -962,6 +968,11 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
@utils.synchronized("share_manager_%s" % share_network_id,
|
@utils.synchronized("share_manager_%s" % share_network_id,
|
||||||
external=True)
|
external=True)
|
||||||
def _wrapped_provide_share_server_for_share_group():
|
def _wrapped_provide_share_server_for_share_group():
|
||||||
|
# NOTE(felipe_rodrigues): it can retrieve the available share
|
||||||
|
# servers using one single subnet_id from the availability zone
|
||||||
|
# subnets, because if the share server has one, it will have
|
||||||
|
# all subnets on that availability zone.
|
||||||
|
share_network_subnet_id = share_network_subnets[0]['id']
|
||||||
try:
|
try:
|
||||||
available_share_servers = (
|
available_share_servers = (
|
||||||
self.db
|
self.db
|
||||||
@ -996,10 +1007,12 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
context,
|
context,
|
||||||
{
|
{
|
||||||
'host': self.host,
|
'host': self.host,
|
||||||
'share_network_subnet_id': share_network_subnet_id,
|
'share_network_subnets': share_network_subnets,
|
||||||
'status': constants.STATUS_CREATING,
|
'status': constants.STATUS_CREATING,
|
||||||
'security_service_update_support': (
|
'security_service_update_support': (
|
||||||
self.driver.security_service_update_support),
|
self.driver.security_service_update_support),
|
||||||
|
'network_allocation_update_support': (
|
||||||
|
self.driver.network_allocation_update_support),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -3037,13 +3050,13 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
msg = ("Since share %(share)s has been un-managed from share "
|
msg = ("Since share %(share)s has been un-managed from share "
|
||||||
"server %(server)s. This share server must be removed "
|
"server %(server)s. This share server must be removed "
|
||||||
"manually, either by un-managing or by deleting it. The "
|
"manually, either by un-managing or by deleting it. The "
|
||||||
"share network subnet %(subnet)s and share network "
|
"share network subnets %(subnets)s and share network "
|
||||||
"%(network)s cannot be deleted unless this share server "
|
"%(network)s cannot be deleted unless this share server "
|
||||||
"has been removed.")
|
"has been removed.")
|
||||||
msg_args = {
|
msg_args = {
|
||||||
'share': share_id,
|
'share': share_id,
|
||||||
'server': share_server['id'],
|
'server': share_server['id'],
|
||||||
'subnet': share_server['share_network_subnet_id'],
|
'subnets': share_server['share_network_subnet_ids'],
|
||||||
'network': share_instance['share_network_id']
|
'network': share_instance['share_network_id']
|
||||||
}
|
}
|
||||||
LOG.warning(msg, msg_args)
|
LOG.warning(msg, msg_args)
|
||||||
@ -3130,8 +3143,11 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
server = self.db.share_server_get(context, share_server_id)
|
server = self.db.share_server_get(context, share_server_id)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# NOTE(felipe_rodrigues): Manila does not support manage share
|
||||||
|
# server with multiple allocations, so it can get the first
|
||||||
|
# subnet_id element.
|
||||||
share_network_subnet = self.db.share_network_subnet_get(
|
share_network_subnet = self.db.share_network_subnet_get(
|
||||||
context, server['share_network_subnet_id'])
|
context, server['share_network_subnet_ids'][0])
|
||||||
share_network = self.db.share_network_get(
|
share_network = self.db.share_network_get(
|
||||||
context, share_network_subnet['share_network_id'])
|
context, share_network_subnet['share_network_id'])
|
||||||
|
|
||||||
@ -3217,7 +3233,9 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
self.db.share_server_update(
|
self.db.share_server_update(
|
||||||
context, share_server_id,
|
context, share_server_id,
|
||||||
{'status': constants.STATUS_ACTIVE,
|
{'status': constants.STATUS_ACTIVE,
|
||||||
'identifier': new_identifier})
|
'identifier': new_identifier,
|
||||||
|
'network_allocation_update_support': (
|
||||||
|
self.driver.network_allocation_update_support)})
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
msg = "Error managing share server %s"
|
msg = "Error managing share server %s"
|
||||||
@ -4039,56 +4057,105 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
self._publish_service_capabilities(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):
|
share_network_subnets):
|
||||||
share_server_id = share_server['id']
|
share_server_id = share_server['id']
|
||||||
# Network info is used by driver for setting up share server
|
# Network info is used by driver for setting up share server
|
||||||
# and getting server info on share creation.
|
# and getting server info on share creation.
|
||||||
network_allocations = self.db.network_allocations_get_for_share_server(
|
|
||||||
context, share_server_id, label='user')
|
|
||||||
admin_network_allocations = (
|
admin_network_allocations = (
|
||||||
self.db.network_allocations_get_for_share_server(
|
self.db.network_allocations_get_for_share_server(
|
||||||
context, share_server_id, label='admin'))
|
context, share_server_id, label='admin'))
|
||||||
# NOTE(vponomaryov): following network_info fields are deprecated:
|
|
||||||
# 'segmentation_id', 'cidr' and 'network_type'.
|
# NOTE(felipe_rodrigues): items in the network_info list contain
|
||||||
# And they should be used from network allocations directly.
|
# same values for the keys: server_id, admin_network_allocations,
|
||||||
# They should be removed right after no one uses them.
|
# security_services and backend_details.
|
||||||
network_info = {
|
network_info = []
|
||||||
'server_id': share_server['id'],
|
for share_network_subnet in share_network_subnets:
|
||||||
'segmentation_id': share_network_subnet['segmentation_id'],
|
network_allocations = (
|
||||||
'cidr': share_network_subnet['cidr'],
|
self.db.network_allocations_get_for_share_server(
|
||||||
'neutron_net_id': share_network_subnet['neutron_net_id'],
|
context, share_server_id, label='user',
|
||||||
'neutron_subnet_id': share_network_subnet['neutron_subnet_id'],
|
subnet_id=share_network_subnet['id']))
|
||||||
'security_services': share_network['security_services'],
|
# NOTE(vponomaryov): following network_info fields are deprecated:
|
||||||
'network_allocations': network_allocations,
|
# 'segmentation_id', 'cidr' and 'network_type'.
|
||||||
'admin_network_allocations': admin_network_allocations,
|
# And they should be used from network allocations directly.
|
||||||
'backend_details': share_server.get('backend_details'),
|
# They should be removed right after no one uses them.
|
||||||
'network_type': share_network_subnet['network_type'],
|
network_info.append({
|
||||||
}
|
'server_id': share_server['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_subnet['network_type'],
|
||||||
|
})
|
||||||
return network_info
|
return network_info
|
||||||
|
|
||||||
|
def _handle_setup_server_error(self, context, share_server_id, e):
|
||||||
|
details = getattr(e, "detail_data", {})
|
||||||
|
if isinstance(details, dict):
|
||||||
|
server_details = details.get("server_details", {})
|
||||||
|
if not isinstance(server_details, dict):
|
||||||
|
LOG.debug(
|
||||||
|
("Cannot save non-dict data (%(data)s) provided as "
|
||||||
|
"'server details' of failed share server '%(server)s'."),
|
||||||
|
{"server": share_server_id, "data": server_details})
|
||||||
|
else:
|
||||||
|
invalid_details = []
|
||||||
|
for key, value in server_details.items():
|
||||||
|
try:
|
||||||
|
self.db.share_server_backend_details_set(
|
||||||
|
context, share_server_id, {key: value})
|
||||||
|
except Exception:
|
||||||
|
invalid_details.append("%(key)s: %(value)s" % {
|
||||||
|
'key': str(key),
|
||||||
|
'value': str(value)
|
||||||
|
})
|
||||||
|
if invalid_details:
|
||||||
|
LOG.debug(
|
||||||
|
("Following server details cannot be written to db : "
|
||||||
|
"%s"), str("\n".join(invalid_details)))
|
||||||
|
else:
|
||||||
|
LOG.debug(
|
||||||
|
("Cannot save non-dict data (%(data)s) provided as 'detail "
|
||||||
|
"data' of failed share server '%(server)s'."),
|
||||||
|
{"server": share_server_id, "data": details})
|
||||||
|
|
||||||
|
self.db.share_server_update(
|
||||||
|
context, share_server_id, {'status': constants.STATUS_ERROR})
|
||||||
|
|
||||||
def _setup_server(self, context, share_server, metadata):
|
def _setup_server(self, context, share_server, metadata):
|
||||||
|
subnets = share_server['share_network_subnets']
|
||||||
|
if not subnets:
|
||||||
|
raise exception.NetworkBadConfigurationException(
|
||||||
|
reason="share server does not have subnet")
|
||||||
|
|
||||||
|
# all subnets reside on same share network, get it from the first one.
|
||||||
|
share_network_id = subnets[0]['share_network_id']
|
||||||
try:
|
try:
|
||||||
share_network_subnet = share_server['share_network_subnet']
|
share_network = self.db.share_network_get(context,
|
||||||
share_network_subnet_id = share_network_subnet['id']
|
share_network_id)
|
||||||
share_network_id = share_network_subnet['share_network_id']
|
for share_network_subnet in subnets:
|
||||||
share_network = self.db.share_network_get(
|
self.driver.allocate_network(
|
||||||
context, share_network_id)
|
context, share_server, share_network, share_network_subnet)
|
||||||
self.driver.allocate_network(context, share_server, share_network,
|
|
||||||
share_network_subnet)
|
|
||||||
self.driver.allocate_admin_network(context, share_server)
|
self.driver.allocate_admin_network(context, share_server)
|
||||||
|
|
||||||
# Get share_network_subnet in case it was updated.
|
# Get share_network_subnets in case they were updated.
|
||||||
share_network_subnet = self.db.share_network_subnet_get(
|
share_network_subnets = (
|
||||||
context, share_network_subnet_id)
|
self.db.share_network_subnet_get_all_by_share_server_id(
|
||||||
network_info = self._form_server_setup_info(
|
context, share_server['id']))
|
||||||
context, share_server, share_network, share_network_subnet)
|
|
||||||
self._validate_segmentation_id(network_info)
|
network_info_list = self._form_server_setup_info(
|
||||||
|
context, share_server, share_network, share_network_subnets)
|
||||||
|
for network_info in network_info_list:
|
||||||
|
self._validate_segmentation_id(network_info)
|
||||||
|
|
||||||
# NOTE(vponomaryov): Save security services data to share server
|
# NOTE(vponomaryov): Save security services data to share server
|
||||||
# details table to remove dependency from share network after
|
# details table to remove dependency from share network after
|
||||||
# creation operation. It will allow us to delete share server and
|
# creation operation. It will allow us to delete share server and
|
||||||
# share network separately without dependency on each other.
|
# share network separately without dependency on each other.
|
||||||
for security_service in network_info['security_services']:
|
for security_service in network_info_list[0]['security_services']:
|
||||||
ss_type = security_service['type']
|
ss_type = security_service['type']
|
||||||
data = {
|
data = {
|
||||||
'name': security_service['name'],
|
'name': security_service['name'],
|
||||||
@ -4105,7 +4172,7 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
{'security_service_' + ss_type: jsonutils.dumps(data)})
|
{'security_service_' + ss_type: jsonutils.dumps(data)})
|
||||||
|
|
||||||
server_info = self.driver.setup_server(
|
server_info = self.driver.setup_server(
|
||||||
network_info, metadata=metadata)
|
network_info_list, metadata=metadata)
|
||||||
|
|
||||||
self.driver.update_network_allocation(context, share_server)
|
self.driver.update_network_allocation(context, share_server)
|
||||||
self.driver.update_admin_network_allocation(context, share_server)
|
self.driver.update_admin_network_allocation(context, share_server)
|
||||||
@ -4120,42 +4187,7 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
'identifier', share_server['id'])})
|
'identifier', share_server['id'])})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
details = getattr(e, "detail_data", {})
|
self._handle_setup_server_error(context, share_server['id'], e)
|
||||||
|
|
||||||
if isinstance(details, dict):
|
|
||||||
server_details = details.get("server_details", {})
|
|
||||||
if not isinstance(server_details, dict):
|
|
||||||
LOG.debug(
|
|
||||||
("Cannot save non-dict data (%(data)s) "
|
|
||||||
"provided as 'server details' of "
|
|
||||||
"failed share server '%(server)s'."),
|
|
||||||
{"server": share_server["id"],
|
|
||||||
"data": server_details})
|
|
||||||
else:
|
|
||||||
invalid_details = []
|
|
||||||
for key, value in server_details.items():
|
|
||||||
try:
|
|
||||||
self.db.share_server_backend_details_set(
|
|
||||||
context, share_server['id'], {key: value})
|
|
||||||
except Exception:
|
|
||||||
invalid_details.append("%(key)s: %(value)s" % {
|
|
||||||
'key': key,
|
|
||||||
'value': value
|
|
||||||
})
|
|
||||||
if invalid_details:
|
|
||||||
LOG.debug(
|
|
||||||
("Following server details "
|
|
||||||
"cannot be written to db : %s"),
|
|
||||||
"\n".join(invalid_details))
|
|
||||||
else:
|
|
||||||
LOG.debug(
|
|
||||||
("Cannot save non-dict data (%(data)s) provided as "
|
|
||||||
"'detail data' of failed share server '%(server)s'."),
|
|
||||||
{"server": share_server["id"], "data": details})
|
|
||||||
|
|
||||||
self.db.share_server_update(
|
|
||||||
context, share_server['id'],
|
|
||||||
{'status': constants.STATUS_ERROR})
|
|
||||||
self.driver.deallocate_network(context, share_server['id'])
|
self.driver.deallocate_network(context, share_server['id'])
|
||||||
|
|
||||||
def _validate_segmentation_id(self, network_info):
|
def _validate_segmentation_id(self, network_info):
|
||||||
@ -4200,8 +4232,11 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
@utils.require_driver_initialized
|
@utils.require_driver_initialized
|
||||||
def delete_share_server(self, context, share_server):
|
def delete_share_server(self, context, share_server):
|
||||||
|
|
||||||
|
subnet_id = (share_server['share_network_subnet_ids'][0]
|
||||||
|
if share_server['share_network_subnet_ids'] else None)
|
||||||
|
|
||||||
@utils.synchronized(
|
@utils.synchronized(
|
||||||
"share_manager_%s" % share_server['share_network_subnet_id'])
|
"share_manager_%s" % subnet_id)
|
||||||
def _wrapped_delete_share_server():
|
def _wrapped_delete_share_server():
|
||||||
# NOTE(vponomaryov): Verify that there are no dependent shares.
|
# NOTE(vponomaryov): Verify that there are no dependent shares.
|
||||||
# Without this verification we can get here exception in next case:
|
# Without this verification we can get here exception in next case:
|
||||||
@ -4443,8 +4478,8 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
if parent_share_server_id and self.driver.driver_handles_share_servers:
|
if parent_share_server_id and self.driver.driver_handles_share_servers:
|
||||||
share_server = self.db.share_server_get(context,
|
share_server = self.db.share_server_get(context,
|
||||||
parent_share_server_id)
|
parent_share_server_id)
|
||||||
share_network_subnet = share_server['share_network_subnet']
|
share_network_id = (
|
||||||
share_network_id = share_network_subnet['share_network_id']
|
share_server['share_network_id'])
|
||||||
|
|
||||||
if share_network_id and not self.driver.driver_handles_share_servers:
|
if share_network_id and not self.driver.driver_handles_share_servers:
|
||||||
self.db.share_group_update(
|
self.db.share_group_update(
|
||||||
@ -4457,14 +4492,17 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
|
|
||||||
availability_zone_id = self._get_az_for_share_group(
|
availability_zone_id = self._get_az_for_share_group(
|
||||||
context, share_group_ref)
|
context, share_group_ref)
|
||||||
subnet = self.db.share_network_subnet_get_by_availability_zone_id(
|
subnets = (
|
||||||
context, share_network_id, availability_zone_id)
|
self.db.share_network_subnets_get_all_by_availability_zone_id(
|
||||||
|
context, share_network_id, availability_zone_id))
|
||||||
|
|
||||||
|
if not subnets:
|
||||||
|
raise exception.ShareNetworkSubnetNotFound(
|
||||||
|
share_network_subnet_id=None)
|
||||||
try:
|
try:
|
||||||
share_server, share_group_ref = (
|
share_server, share_group_ref = (
|
||||||
self._provide_share_server_for_share_group(
|
self._provide_share_server_for_share_group(
|
||||||
context, share_network_id, subnet.get('id'),
|
context, share_network_id, subnets, share_group_ref,
|
||||||
share_group_ref,
|
|
||||||
share_group_snapshot=snap_ref,
|
share_group_snapshot=snap_ref,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -4764,8 +4802,8 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
'share_network_id': share_server.get('share_network_id'),
|
'share_network_id': share_server.get('share_network_id'),
|
||||||
'created_at': share_server.get('created_at'),
|
'created_at': share_server.get('created_at'),
|
||||||
'backend_details': share_server.get('backend_details'),
|
'backend_details': share_server.get('backend_details'),
|
||||||
'share_network_subnet_id':
|
'share_network_subnet_ids':
|
||||||
share_server.get('share_network_subnet_id', None),
|
share_server.get('share_network_subnet_ids', []),
|
||||||
'is_auto_deletable': share_server.get('is_auto_deletable', None),
|
'is_auto_deletable': share_server.get('is_auto_deletable', None),
|
||||||
'identifier': share_server.get('identifier', None),
|
'identifier': share_server.get('identifier', None),
|
||||||
'network_allocations': share_server.get('network_allocations',
|
'network_allocations': share_server.get('network_allocations',
|
||||||
@ -5101,11 +5139,10 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
if not create_server_on_backend:
|
if not create_server_on_backend:
|
||||||
dest_share_server = self.db.share_server_get(
|
dest_share_server = self.db.share_server_get(
|
||||||
context, dest_share_server['id'])
|
context, dest_share_server['id'])
|
||||||
current_subnet = dest_share_server['share_network_subnet']
|
net_changes_identified = (
|
||||||
old_subnet = source_share_server['share_network_subnet']
|
not share_utils.is_az_subnets_compatible(
|
||||||
for key in ['neutron_net_id', 'neutron_subnet_id']:
|
dest_share_server['share_network_subnets'],
|
||||||
if current_subnet.get(key) != old_subnet.get(key):
|
source_share_server['share_network_subnets']))
|
||||||
net_changes_identified = True
|
|
||||||
|
|
||||||
# NOTE(carloss): Even though the share back end won't need to
|
# NOTE(carloss): Even though the share back end won't need to
|
||||||
# create a share server, if a network change was identified,
|
# create a share server, if a network change was identified,
|
||||||
@ -5115,11 +5152,14 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
# In such case, the migration will be disruptive, since the old
|
# In such case, the migration will be disruptive, since the old
|
||||||
# allocations will be replaced by the new ones.
|
# allocations will be replaced by the new ones.
|
||||||
if net_changes_identified:
|
if net_changes_identified:
|
||||||
share_network_subnet = self.db.share_network_subnet_get(
|
share_network_subnets = (
|
||||||
context, dest_share_server['share_network_subnet_id'])
|
self.db.
|
||||||
self.driver.allocate_network(
|
share_network_subnet_get_all_by_share_server_id(
|
||||||
context, dest_share_server, new_share_network,
|
context, dest_share_server['id']))
|
||||||
share_network_subnet)
|
for share_network_subnet in share_network_subnets:
|
||||||
|
self.driver.allocate_network(
|
||||||
|
context, dest_share_server, new_share_network,
|
||||||
|
share_network_subnet)
|
||||||
self.driver.allocate_admin_network(
|
self.driver.allocate_admin_network(
|
||||||
context, dest_share_server)
|
context, dest_share_server)
|
||||||
# Refresh the share server so it will have the network
|
# Refresh the share server so it will have the network
|
||||||
@ -5503,11 +5543,11 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
{'task_state': constants.TASK_STATE_MIGRATION_COMPLETING})
|
{'task_state': constants.TASK_STATE_MIGRATION_COMPLETING})
|
||||||
|
|
||||||
# Retrieve network allocations reserved for the new share server
|
# Retrieve network allocations reserved for the new share server
|
||||||
dest_sns = dest_share_server['share_network_subnet']
|
dest_snss = dest_share_server['share_network_subnets']
|
||||||
dest_sns_id = dest_sns['id']
|
dest_sn_id = dest_snss[0]['share_network_id']
|
||||||
dest_sn_id = dest_sns['share_network_id']
|
|
||||||
dest_sn = self.db.share_network_get(context, dest_sn_id)
|
dest_sn = self.db.share_network_get(context, dest_sn_id)
|
||||||
dest_sns = self.db.share_network_subnet_get(context, dest_sns_id)
|
dest_snss = self.db.share_network_subnet_get_all_by_share_server_id(
|
||||||
|
context, dest_share_server['id'])
|
||||||
|
|
||||||
migration_reused_network_allocations = (len(
|
migration_reused_network_allocations = (len(
|
||||||
self.db.network_allocations_get_for_share_server(
|
self.db.network_allocations_get_for_share_server(
|
||||||
@ -5519,16 +5559,20 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
else source_share_server)
|
else source_share_server)
|
||||||
|
|
||||||
new_network_allocations = self._form_server_setup_info(
|
new_network_allocations = self._form_server_setup_info(
|
||||||
context, server_to_get_allocations, dest_sn, dest_sns)
|
context, server_to_get_allocations, dest_sn, dest_snss)
|
||||||
|
|
||||||
model_update = self.driver.share_server_migration_complete(
|
model_update = self.driver.share_server_migration_complete(
|
||||||
context, source_share_server, dest_share_server, share_instances,
|
context, source_share_server, dest_share_server, share_instances,
|
||||||
snapshot_instances, new_network_allocations)
|
snapshot_instances, new_network_allocations)
|
||||||
|
|
||||||
if not migration_reused_network_allocations:
|
if not migration_reused_network_allocations:
|
||||||
|
network_allocations = []
|
||||||
|
for net_allocation in new_network_allocations:
|
||||||
|
network_allocations += net_allocation['network_allocations']
|
||||||
|
|
||||||
all_allocations = [
|
all_allocations = [
|
||||||
new_network_allocations['network_allocations'],
|
network_allocations,
|
||||||
new_network_allocations['admin_network_allocations']
|
new_network_allocations[0]['admin_network_allocations']
|
||||||
]
|
]
|
||||||
for allocations in all_allocations:
|
for allocations in all_allocations:
|
||||||
for allocation in allocations:
|
for allocation in allocations:
|
||||||
@ -5726,7 +5770,8 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
snapshot_instances)
|
snapshot_instances)
|
||||||
|
|
||||||
@locked_share_network_operation
|
@locked_share_network_operation
|
||||||
def _check_share_network_update_finished(self, context, share_network_id):
|
def _check_share_network_update_finished(
|
||||||
|
self, context, share_network_id=None):
|
||||||
# Check if this share network is already active
|
# Check if this share network is already active
|
||||||
share_network = self.db.share_network_get(context, share_network_id)
|
share_network = self.db.share_network_get(context, share_network_id)
|
||||||
if share_network['status'] == constants.STATUS_NETWORK_ACTIVE:
|
if share_network['status'] == constants.STATUS_NETWORK_ACTIVE:
|
||||||
@ -5775,14 +5820,14 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
filters={'share_network_id': share_network_id})
|
filters={'share_network_id': share_network_id})
|
||||||
|
|
||||||
for share_server in share_servers:
|
for share_server in share_servers:
|
||||||
share_network_subnet = share_server['share_network_subnet']
|
|
||||||
share_network_subnet_id = share_network_subnet['id']
|
|
||||||
|
|
||||||
# Get share_network_subnet in case it was updated.
|
# Get share_network_subnet in case it was updated.
|
||||||
share_network_subnet = self.db.share_network_subnet_get(
|
share_network_subnets = (
|
||||||
context, share_network_subnet_id)
|
self.db.share_network_subnet_get_all_by_share_server_id(
|
||||||
|
context, share_server['id']))
|
||||||
|
|
||||||
network_info = self._form_server_setup_info(
|
network_info = self._form_server_setup_info(
|
||||||
context, share_server, share_network, share_network_subnet)
|
context, share_server, share_network, share_network_subnets)
|
||||||
|
|
||||||
share_instances = (
|
share_instances = (
|
||||||
self.db.share_instances_get_all_by_share_server(
|
self.db.share_instances_get_all_by_share_server(
|
||||||
@ -5883,7 +5928,8 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
|
|
||||||
# Check if all share servers have already finished their updates in
|
# Check if all share servers have already finished their updates in
|
||||||
# order to properly update share network status
|
# order to properly update share network status
|
||||||
self._check_share_network_update_finished(context, share_network['id'])
|
self._check_share_network_update_finished(
|
||||||
|
context, share_network_id=share_network['id'])
|
||||||
|
|
||||||
def update_share_network_security_service(
|
def update_share_network_security_service(
|
||||||
self, context, share_network_id, new_security_service_id,
|
self, context, share_network_id, new_security_service_id,
|
||||||
@ -5925,3 +5971,234 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
LOG.debug('A share network security service check was requested '
|
LOG.debug('A share network security service check was requested '
|
||||||
'but no entries were found in database. Ignoring call '
|
'but no entries were found in database. Ignoring call '
|
||||||
'and returning.')
|
'and returning.')
|
||||||
|
|
||||||
|
@api.locked_share_server_update_allocations_operation
|
||||||
|
def _update_share_server_allocations_check_operation(
|
||||||
|
self, context, is_supported, share_network_id=None,
|
||||||
|
availability_zone_id=None):
|
||||||
|
update_key = self.share_api.get_share_server_update_allocations_key(
|
||||||
|
share_network_id, availability_zone_id)
|
||||||
|
current_hosts_info = self.db.async_operation_data_get(
|
||||||
|
context, share_network_id, update_key)
|
||||||
|
if current_hosts_info:
|
||||||
|
current_hosts = json.loads(current_hosts_info)
|
||||||
|
current_hosts[self.host] = is_supported
|
||||||
|
self.db.async_operation_data_update(
|
||||||
|
context, share_network_id,
|
||||||
|
{update_key: json.dumps(current_hosts)})
|
||||||
|
else:
|
||||||
|
LOG.debug('A share network subnet create check was requested '
|
||||||
|
'but no entries were found in database. Ignoring call '
|
||||||
|
'and returning.')
|
||||||
|
|
||||||
|
def _get_subnet_allocations(self, context, share_server_id,
|
||||||
|
share_network_subnet):
|
||||||
|
|
||||||
|
network_allocations = (
|
||||||
|
self.db.network_allocations_get_for_share_server(
|
||||||
|
context, share_server_id, label='user',
|
||||||
|
subnet_id=share_network_subnet['id']))
|
||||||
|
|
||||||
|
return {
|
||||||
|
'share_network_subnet_id': share_network_subnet['id'],
|
||||||
|
'neutron_net_id': share_network_subnet['neutron_net_id'],
|
||||||
|
'neutron_subnet_id': share_network_subnet['neutron_subnet_id'],
|
||||||
|
'network_allocations': network_allocations,
|
||||||
|
}
|
||||||
|
|
||||||
|
def _form_network_allocations(self, context, share_server_id,
|
||||||
|
share_network_subnets):
|
||||||
|
|
||||||
|
subnet_allocations = []
|
||||||
|
for share_network_subnet in share_network_subnets:
|
||||||
|
subnet_allocations.append(self._get_subnet_allocations(
|
||||||
|
context, share_server_id, share_network_subnet))
|
||||||
|
|
||||||
|
admin_network_allocations = (
|
||||||
|
self.db.network_allocations_get_for_share_server(
|
||||||
|
context, share_server_id, label='admin'))
|
||||||
|
|
||||||
|
return {
|
||||||
|
'admin_network_allocations': admin_network_allocations,
|
||||||
|
'subnets': subnet_allocations,
|
||||||
|
}
|
||||||
|
|
||||||
|
def check_update_share_server_network_allocations(
|
||||||
|
self, context, share_network_id, new_share_network_subnet):
|
||||||
|
|
||||||
|
share_network = self.db.share_network_get(
|
||||||
|
context, share_network_id)
|
||||||
|
az_subnets = (
|
||||||
|
self.db.share_network_subnets_get_all_by_availability_zone_id(
|
||||||
|
context, share_network_id,
|
||||||
|
new_share_network_subnet['availability_zone_id'],
|
||||||
|
fallback_to_default=False)
|
||||||
|
)
|
||||||
|
self.driver.network_api.include_network_info(new_share_network_subnet)
|
||||||
|
|
||||||
|
# all subnets have the same set of share servers, so do the check from
|
||||||
|
# servers in the first subnet.
|
||||||
|
share_servers = az_subnets[0]['share_servers'] if az_subnets else []
|
||||||
|
is_supported = True
|
||||||
|
for share_server in share_servers:
|
||||||
|
|
||||||
|
current_network_allocations = self._form_network_allocations(
|
||||||
|
context, share_server['id'], az_subnets)
|
||||||
|
|
||||||
|
share_instances = (
|
||||||
|
self.db.share_instances_get_all_by_share_server(
|
||||||
|
context, share_server['id'], with_share_data=True))
|
||||||
|
share_instance_ids = [sn.id for sn in share_instances]
|
||||||
|
|
||||||
|
share_instances_rules = []
|
||||||
|
for share_instance_id in share_instance_ids:
|
||||||
|
instance_rules = {
|
||||||
|
'share_instance_id': share_instance_id,
|
||||||
|
'access_rules': (
|
||||||
|
self.db.share_access_get_all_for_instance(
|
||||||
|
context, share_instance_id))
|
||||||
|
}
|
||||||
|
share_instances_rules.append(instance_rules)
|
||||||
|
|
||||||
|
if self.driver.check_update_share_server_network_allocations(
|
||||||
|
context, share_server, current_network_allocations,
|
||||||
|
new_share_network_subnet,
|
||||||
|
share_network['security_services'],
|
||||||
|
share_instances, share_instances_rules):
|
||||||
|
# Check the next share server.
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
# At least one share server doesn't support this update.
|
||||||
|
is_supported = False
|
||||||
|
break
|
||||||
|
|
||||||
|
self._update_share_server_allocations_check_operation(
|
||||||
|
context, is_supported, share_network_id=share_network_id,
|
||||||
|
availability_zone_id=(
|
||||||
|
new_share_network_subnet['availability_zone_id']))
|
||||||
|
|
||||||
|
def _do_update_share_server_network_allocations(
|
||||||
|
self, context, share_server, share_network, new_subnet,
|
||||||
|
current_network_allocations, share_instances,
|
||||||
|
snapshot_instance_ids):
|
||||||
|
|
||||||
|
self.driver.allocate_network(
|
||||||
|
context, share_server, share_network, new_subnet)
|
||||||
|
new_network_allocations = self._get_subnet_allocations(
|
||||||
|
context, share_server['id'], new_subnet)
|
||||||
|
if not new_network_allocations['network_allocations']:
|
||||||
|
raise exception.AllocationsNotFoundForShareServer(
|
||||||
|
share_server_id=share_server['id'])
|
||||||
|
|
||||||
|
# NOTE(felipe_rodrigues): all allocations have the same network
|
||||||
|
# segmentation info, so validation from the first one.
|
||||||
|
self._validate_segmentation_id(
|
||||||
|
new_network_allocations['network_allocations'][0])
|
||||||
|
|
||||||
|
model_update = self.driver.update_share_server_network_allocations(
|
||||||
|
context, share_server, current_network_allocations,
|
||||||
|
new_network_allocations, share_network['security_services'],
|
||||||
|
share_instances, snapshot_instance_ids)
|
||||||
|
|
||||||
|
self.driver.update_network_allocation(context, share_server)
|
||||||
|
|
||||||
|
driver_backend_details = model_update.get('server_details')
|
||||||
|
if driver_backend_details:
|
||||||
|
self.db.share_server_backend_details_set(
|
||||||
|
context, share_server['id'], driver_backend_details)
|
||||||
|
|
||||||
|
share_updates = model_update.get('share_updates', {})
|
||||||
|
for share_instance_id, export_locations in share_updates.items():
|
||||||
|
self.db.share_export_locations_update(
|
||||||
|
context, share_instance_id, export_locations)
|
||||||
|
|
||||||
|
snapshot_updates = model_update.get('snapshot_updates', {})
|
||||||
|
for snap_instance_id, model_update in snapshot_updates.items():
|
||||||
|
snapshot_export_locations = model_update.pop(
|
||||||
|
'export_locations', [])
|
||||||
|
if model_update:
|
||||||
|
self.db.share_snapshot_instance_update(
|
||||||
|
context, snap_instance_id, model_update)
|
||||||
|
|
||||||
|
if snapshot_export_locations:
|
||||||
|
export_locations_update = []
|
||||||
|
for exp_location in snapshot_export_locations:
|
||||||
|
updated_el = {
|
||||||
|
'path': exp_location['path'],
|
||||||
|
'is_admin_only': exp_location['is_admin_only'],
|
||||||
|
}
|
||||||
|
export_locations_update.append(updated_el)
|
||||||
|
self.db.share_snapshot_instance_export_locations_update(
|
||||||
|
context, snap_instance_id, export_locations_update)
|
||||||
|
|
||||||
|
def update_share_server_network_allocations(
|
||||||
|
self, context, share_network_id, new_share_network_subnet_id):
|
||||||
|
|
||||||
|
share_network = self.db.share_network_get(
|
||||||
|
context, share_network_id)
|
||||||
|
new_subnet = self.db.share_network_subnet_get(
|
||||||
|
context, new_share_network_subnet_id)
|
||||||
|
current_subnets = (
|
||||||
|
self.db.share_network_subnets_get_all_by_availability_zone_id(
|
||||||
|
context, share_network_id,
|
||||||
|
new_subnet['availability_zone_id'],
|
||||||
|
fallback_to_default=False)
|
||||||
|
)
|
||||||
|
current_subnets = [subnet for subnet in current_subnets
|
||||||
|
if subnet['id'] != new_share_network_subnet_id]
|
||||||
|
share_servers = (
|
||||||
|
self.db.share_server_get_all_by_host_and_share_subnet_valid(
|
||||||
|
context, self.host, new_share_network_subnet_id,
|
||||||
|
server_status=constants.STATUS_SERVER_NETWORK_CHANGE))
|
||||||
|
for share_server in share_servers:
|
||||||
|
|
||||||
|
share_server_id = share_server['id']
|
||||||
|
current_network_allocations = self._form_network_allocations(
|
||||||
|
context, share_server_id, current_subnets)
|
||||||
|
share_instances = (
|
||||||
|
self.db.share_instances_get_all_by_share_server(
|
||||||
|
context, share_server_id, with_share_data=True))
|
||||||
|
share_instance_ids = [x['id'] for x in share_instances]
|
||||||
|
snapshot_instances = (
|
||||||
|
self.db.share_snapshot_instance_get_all_with_filters(
|
||||||
|
context,
|
||||||
|
{'share_instance_ids': share_instance_ids}))
|
||||||
|
snapshot_instance_ids = [x['id'] for x in snapshot_instances]
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._do_update_share_server_network_allocations(
|
||||||
|
context, share_server, share_network, new_subnet,
|
||||||
|
current_network_allocations, share_instances,
|
||||||
|
snapshot_instances)
|
||||||
|
except Exception as e:
|
||||||
|
msg = ('Failed to update allocations of share server '
|
||||||
|
'%(server_id)s on subnet %(subnet_id)s: %(e)s.')
|
||||||
|
data = {
|
||||||
|
'server_id': share_server_id,
|
||||||
|
'subnet_id': new_share_network_subnet_id,
|
||||||
|
'e': str(e),
|
||||||
|
}
|
||||||
|
LOG.exception(msg, data)
|
||||||
|
|
||||||
|
# Set resources to error. Allocations configuration must be
|
||||||
|
# fixed before restoring it to active again.
|
||||||
|
self._handle_setup_server_error(context, share_server_id, e)
|
||||||
|
self._update_resource_status(
|
||||||
|
context, constants.STATUS_ERROR,
|
||||||
|
share_instance_ids=share_instance_ids,
|
||||||
|
snapshot_instance_ids=snapshot_instance_ids)
|
||||||
|
|
||||||
|
continue
|
||||||
|
|
||||||
|
msg = _(
|
||||||
|
"Network allocations was successfully updated on share "
|
||||||
|
"server %s.") % share_server['id']
|
||||||
|
LOG.info(msg)
|
||||||
|
self.db.share_server_update(
|
||||||
|
context, share_server['id'],
|
||||||
|
{'status': constants.STATUS_ACTIVE})
|
||||||
|
|
||||||
|
# Check if all share servers have already finished their updates in
|
||||||
|
# order to properly update share network status.
|
||||||
|
self._check_share_network_update_finished(
|
||||||
|
context, share_network_id=share_network['id'])
|
||||||
|
@ -81,6 +81,8 @@ class ShareAPI(object):
|
|||||||
and share_server_get_progress()
|
and share_server_get_progress()
|
||||||
1.22 - Add update_share_network_security_service() and
|
1.22 - Add update_share_network_security_service() and
|
||||||
check_update_share_network_security_service()
|
check_update_share_network_security_service()
|
||||||
|
1.23 - Add update_share_server_network_allocations() and
|
||||||
|
check_update_share_server_network_allocations()
|
||||||
"""
|
"""
|
||||||
|
|
||||||
BASE_RPC_API_VERSION = '1.0'
|
BASE_RPC_API_VERSION = '1.0'
|
||||||
@ -89,7 +91,7 @@ class ShareAPI(object):
|
|||||||
super(ShareAPI, self).__init__()
|
super(ShareAPI, self).__init__()
|
||||||
target = messaging.Target(topic=CONF.share_topic,
|
target = messaging.Target(topic=CONF.share_topic,
|
||||||
version=self.BASE_RPC_API_VERSION)
|
version=self.BASE_RPC_API_VERSION)
|
||||||
self.client = rpc.get_client(target, version_cap='1.22')
|
self.client = rpc.get_client(target, version_cap='1.23')
|
||||||
|
|
||||||
def create_share_instance(self, context, share_instance, host,
|
def create_share_instance(self, context, share_instance, host,
|
||||||
request_spec, filter_properties,
|
request_spec, filter_properties,
|
||||||
@ -462,3 +464,25 @@ class ShareAPI(object):
|
|||||||
share_network_id=share_network_id,
|
share_network_id=share_network_id,
|
||||||
new_security_service_id=new_security_service_id,
|
new_security_service_id=new_security_service_id,
|
||||||
current_security_service_id=current_security_service_id)
|
current_security_service_id=current_security_service_id)
|
||||||
|
|
||||||
|
def check_update_share_server_network_allocations(
|
||||||
|
self, context, dest_host, share_network_id,
|
||||||
|
new_share_network_subnet):
|
||||||
|
host = utils.extract_host(dest_host)
|
||||||
|
call_context = self.client.prepare(server=host, version='1.23')
|
||||||
|
call_context.cast(
|
||||||
|
context,
|
||||||
|
'check_update_share_server_network_allocations',
|
||||||
|
share_network_id=share_network_id,
|
||||||
|
new_share_network_subnet=new_share_network_subnet)
|
||||||
|
|
||||||
|
def update_share_server_network_allocations(
|
||||||
|
self, context, dest_host, share_network_id,
|
||||||
|
new_share_network_subnet_id):
|
||||||
|
host = utils.extract_host(dest_host)
|
||||||
|
call_context = self.client.prepare(server=host, version='1.23')
|
||||||
|
call_context.cast(
|
||||||
|
context,
|
||||||
|
'update_share_server_network_allocations',
|
||||||
|
share_network_id=share_network_id,
|
||||||
|
new_share_network_subnet_id=new_share_network_subnet_id)
|
||||||
|
@ -152,3 +152,22 @@ def _usage_from_share(share_ref, share_instance_ref, **extra_usage_info):
|
|||||||
|
|
||||||
def get_recent_db_migration_id():
|
def get_recent_db_migration_id():
|
||||||
return migration.version()
|
return migration.version()
|
||||||
|
|
||||||
|
|
||||||
|
def is_az_subnets_compatible(subnet_list, new_subnet_list):
|
||||||
|
if len(subnet_list) != len(new_subnet_list):
|
||||||
|
return False
|
||||||
|
|
||||||
|
for subnet in subnet_list:
|
||||||
|
found_compatible = False
|
||||||
|
for new_subnet in new_subnet_list:
|
||||||
|
if (subnet.get('neutron_net_id') ==
|
||||||
|
new_subnet.get('neutron_net_id') and
|
||||||
|
subnet.get('neutron_subnet_id') ==
|
||||||
|
new_subnet.get('neutron_subnet_id')):
|
||||||
|
found_compatible = True
|
||||||
|
break
|
||||||
|
if not found_compatible:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
@ -24,6 +24,7 @@ import webob
|
|||||||
import webob.exc
|
import webob.exc
|
||||||
|
|
||||||
from manila.api import common
|
from manila.api import common
|
||||||
|
from manila.db import api as db_api
|
||||||
from manila import exception
|
from manila import exception
|
||||||
from manila import policy
|
from manila import policy
|
||||||
from manila import test
|
from manila import test
|
||||||
@ -354,6 +355,108 @@ class MiscFunctionsTest(test.TestCase):
|
|||||||
common.parse_is_public,
|
common.parse_is_public,
|
||||||
'fakefakefake')
|
'fakefakefake')
|
||||||
|
|
||||||
|
@ddt.data(None, 'fake_az')
|
||||||
|
def test__get_existing_subnets(self, az):
|
||||||
|
default_subnets = 'fake_default_subnets'
|
||||||
|
mock_get_default_subnets = self.mock_object(
|
||||||
|
db_api, 'share_network_subnet_get_default_subnets',
|
||||||
|
mock.Mock(return_value=default_subnets))
|
||||||
|
subnets = 'fake_subnets'
|
||||||
|
mock_get_subnets = self.mock_object(
|
||||||
|
db_api, 'share_network_subnets_get_all_by_availability_zone_id',
|
||||||
|
mock.Mock(return_value=subnets))
|
||||||
|
|
||||||
|
net_id = 'fake_net'
|
||||||
|
context = 'fake_context'
|
||||||
|
res_subnets = common._get_existing_subnets(context, net_id, az)
|
||||||
|
|
||||||
|
if az:
|
||||||
|
self.assertEqual(subnets, res_subnets)
|
||||||
|
mock_get_subnets.assert_called_once_with(context, net_id, az,
|
||||||
|
fallback_to_default=False)
|
||||||
|
mock_get_default_subnets.assert_not_called()
|
||||||
|
else:
|
||||||
|
self.assertEqual(default_subnets, res_subnets)
|
||||||
|
mock_get_subnets.assert_not_called()
|
||||||
|
mock_get_default_subnets.assert_called_once_with(context, net_id)
|
||||||
|
|
||||||
|
def test_validate_subnet_create(self):
|
||||||
|
mock_check_net = self.mock_object(common, 'check_net_id_and_subnet_id')
|
||||||
|
net = 'fake_net'
|
||||||
|
mock_get_net = self.mock_object(db_api, 'share_network_get',
|
||||||
|
mock.Mock(return_value=net))
|
||||||
|
az_id = 'fake_az_id'
|
||||||
|
az = {'id': az_id}
|
||||||
|
mock_get_az = self.mock_object(db_api, 'availability_zone_get',
|
||||||
|
mock.Mock(return_value=az))
|
||||||
|
subnets = 'fake_subnets'
|
||||||
|
mock_get_subnets = self.mock_object(common, '_get_existing_subnets',
|
||||||
|
mock.Mock(return_value=subnets))
|
||||||
|
|
||||||
|
net_id = 'fake_net_id'
|
||||||
|
context = 'fake_context'
|
||||||
|
az_name = 'fake_az'
|
||||||
|
data = {'availability_zone': az_name}
|
||||||
|
res_net, res_subnets = common.validate_subnet_create(
|
||||||
|
context, net_id, data, True)
|
||||||
|
|
||||||
|
self.assertEqual(net, res_net)
|
||||||
|
self.assertEqual(subnets, res_subnets)
|
||||||
|
self.assertEqual(data['availability_zone_id'], az_id)
|
||||||
|
mock_check_net.assert_called_once_with(data)
|
||||||
|
mock_get_net.assert_called_once_with(context, net_id)
|
||||||
|
mock_get_az.assert_called_once_with(context, az_name)
|
||||||
|
mock_get_subnets.assert_called_once_with(context, net_id, az_id)
|
||||||
|
|
||||||
|
def test_validate_subnet_create_net_not_found(self):
|
||||||
|
|
||||||
|
self.mock_object(common, 'check_net_id_and_subnet_id')
|
||||||
|
self.mock_object(db_api, 'share_network_get',
|
||||||
|
mock.Mock(side_effect=exception.ShareNetworkNotFound(
|
||||||
|
share_network_id="fake_id")))
|
||||||
|
|
||||||
|
net_id = 'fake_net_id'
|
||||||
|
context = 'fake_context'
|
||||||
|
az_name = 'fake_az'
|
||||||
|
data = {'availability_zone': az_name}
|
||||||
|
self.assertRaises(webob.exc.HTTPNotFound,
|
||||||
|
common.validate_subnet_create,
|
||||||
|
context, net_id, data, True)
|
||||||
|
|
||||||
|
def test_validate_subnet_create_az_not_found(self):
|
||||||
|
self.mock_object(common, 'check_net_id_and_subnet_id')
|
||||||
|
self.mock_object(db_api, 'share_network_get',
|
||||||
|
mock.Mock(return_value='fake_net'))
|
||||||
|
self.mock_object(
|
||||||
|
db_api, 'availability_zone_get',
|
||||||
|
mock.Mock(side_effect=exception.AvailabilityZoneNotFound(
|
||||||
|
id='fake_id')))
|
||||||
|
|
||||||
|
net_id = 'fake_net_id'
|
||||||
|
context = 'fake_context'
|
||||||
|
az_name = 'fake_az'
|
||||||
|
data = {'availability_zone': az_name}
|
||||||
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
|
common.validate_subnet_create,
|
||||||
|
context, net_id, data, True)
|
||||||
|
|
||||||
|
def test_validate_subnet_create_multiple_subnet_not_support(self):
|
||||||
|
self.mock_object(common, 'check_net_id_and_subnet_id')
|
||||||
|
self.mock_object(db_api, 'share_network_get',
|
||||||
|
mock.Mock(return_value='fake_net'))
|
||||||
|
self.mock_object(db_api, 'availability_zone_get',
|
||||||
|
mock.Mock(return_value={'id': 'fake_az_id'}))
|
||||||
|
self.mock_object(common, '_get_existing_subnets',
|
||||||
|
mock.Mock(return_value='fake_subnets'))
|
||||||
|
|
||||||
|
net_id = 'fake_net_id'
|
||||||
|
context = 'fake_context'
|
||||||
|
az_name = 'fake_az'
|
||||||
|
data = {'availability_zone': az_name}
|
||||||
|
self.assertRaises(webob.exc.HTTPConflict,
|
||||||
|
common.validate_subnet_create,
|
||||||
|
context, net_id, data, False)
|
||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class ViewBuilderTest(test.TestCase):
|
class ViewBuilderTest(test.TestCase):
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
|
import copy
|
||||||
import ddt
|
import ddt
|
||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
@ -36,14 +37,15 @@ fake_share_server_list = {
|
|||||||
'host': 'fake_host',
|
'host': 'fake_host',
|
||||||
'share_network_name': 'fake_sn_name',
|
'share_network_name': 'fake_sn_name',
|
||||||
'share_network_id': 'fake_sn_id',
|
'share_network_id': 'fake_sn_id',
|
||||||
'share_network_subnet_id': 'fake_sns_id',
|
'share_network_subnet_ids': ['fake_sns_id'],
|
||||||
'project_id': 'fake_project_id',
|
'project_id': 'fake_project_id',
|
||||||
'id': 'fake_server_id',
|
'id': 'fake_server_id',
|
||||||
'is_auto_deletable': False,
|
'is_auto_deletable': False,
|
||||||
'task_state': None,
|
'task_state': None,
|
||||||
'source_share_server_id': None,
|
'source_share_server_id': None,
|
||||||
'identifier': 'fake_id',
|
'identifier': 'fake_id',
|
||||||
'security_service_update_support': False
|
'security_service_update_support': False,
|
||||||
|
'network_allocation_update_support': False
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'status': constants.STATUS_ERROR,
|
'status': constants.STATUS_ERROR,
|
||||||
@ -51,14 +53,15 @@ fake_share_server_list = {
|
|||||||
'host': 'fake_host_2',
|
'host': 'fake_host_2',
|
||||||
'share_network_name': 'fake_sn_id_2',
|
'share_network_name': 'fake_sn_id_2',
|
||||||
'share_network_id': 'fake_sn_id_2',
|
'share_network_id': 'fake_sn_id_2',
|
||||||
'share_network_subnet_id': 'fake_sns_id_2',
|
'share_network_subnet_ids': ['fake_sns_id_2'],
|
||||||
'project_id': 'fake_project_id_2',
|
'project_id': 'fake_project_id_2',
|
||||||
'id': 'fake_server_id_2',
|
'id': 'fake_server_id_2',
|
||||||
'is_auto_deletable': True,
|
'is_auto_deletable': True,
|
||||||
'task_state': None,
|
'task_state': None,
|
||||||
'source_share_server_id': None,
|
'source_share_server_id': None,
|
||||||
'identifier': 'fake_id_2',
|
'identifier': 'fake_id_2',
|
||||||
'security_service_update_support': False
|
'security_service_update_support': False,
|
||||||
|
'network_allocation_update_support': False
|
||||||
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -87,7 +90,7 @@ fake_share_server_get_result = {
|
|||||||
'host': 'fake_host',
|
'host': 'fake_host',
|
||||||
'share_network_name': 'fake_sn_name',
|
'share_network_name': 'fake_sn_name',
|
||||||
'share_network_id': 'fake_sn_id',
|
'share_network_id': 'fake_sn_id',
|
||||||
'share_network_subnet_id': 'fake_sns_id',
|
'share_network_subnet_ids': ['fake_sns_id'],
|
||||||
'project_id': 'fake_project_id',
|
'project_id': 'fake_project_id',
|
||||||
'id': 'fake_server_id',
|
'id': 'fake_server_id',
|
||||||
'backend_details': {
|
'backend_details': {
|
||||||
@ -98,7 +101,8 @@ fake_share_server_get_result = {
|
|||||||
'task_state': None,
|
'task_state': None,
|
||||||
'source_share_server_id': None,
|
'source_share_server_id': None,
|
||||||
'identifier': 'fake_id',
|
'identifier': 'fake_id',
|
||||||
'security_service_update_support': False
|
'security_service_update_support': False,
|
||||||
|
'network_allocation_update_support': False
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,10 +128,11 @@ class FakeShareServer(object):
|
|||||||
self.created_at = kwargs.get('created_at', None)
|
self.created_at = kwargs.get('created_at', None)
|
||||||
self.updated_at = kwargs.get('updated_at', None)
|
self.updated_at = kwargs.get('updated_at', None)
|
||||||
self.host = kwargs.get('host', 'fake_host')
|
self.host = kwargs.get('host', 'fake_host')
|
||||||
self.share_network_subnet = kwargs.get('share_network_subnet', {
|
self.share_network_subnets = kwargs.get('share_network_subnets', [{
|
||||||
'id': 'fake_sns_id', 'share_network_id': 'fake_sn_id'})
|
'id': 'fake_sns_id', 'share_network_id': 'fake_sn_id'}])
|
||||||
self.share_network_subnet_id = kwargs.get(
|
self.share_network_subnet_ids = kwargs.get(
|
||||||
'share_network_subnet_id', self.share_network_subnet['id'])
|
'share_network_subnet_ids',
|
||||||
|
[sn['id'] for sn in self.share_network_subnets])
|
||||||
self.status = kwargs.get('status', constants.STATUS_ACTIVE)
|
self.status = kwargs.get('status', constants.STATUS_ACTIVE)
|
||||||
self.project_id = 'fake_project_id'
|
self.project_id = 'fake_project_id'
|
||||||
self.identifier = kwargs.get('identifier', 'fake_id')
|
self.identifier = kwargs.get('identifier', 'fake_id')
|
||||||
@ -137,6 +142,9 @@ class FakeShareServer(object):
|
|||||||
self.backend_details = share_server_backend_details
|
self.backend_details = share_server_backend_details
|
||||||
self.security_service_update_support = kwargs.get(
|
self.security_service_update_support = kwargs.get(
|
||||||
'security_service_update_support', False)
|
'security_service_update_support', False)
|
||||||
|
self.network_allocation_update_support = kwargs.get(
|
||||||
|
'network_allocation_update_support', False)
|
||||||
|
self.share_network_id = kwargs.get('share_network_id', 'fake_sn_id')
|
||||||
|
|
||||||
def __getitem__(self, item):
|
def __getitem__(self, item):
|
||||||
return getattr(self, item)
|
return getattr(self, item)
|
||||||
@ -147,15 +155,17 @@ def fake_share_server_get_all():
|
|||||||
FakeShareServer(),
|
FakeShareServer(),
|
||||||
FakeShareServer(id='fake_server_id_2',
|
FakeShareServer(id='fake_server_id_2',
|
||||||
host='fake_host_2',
|
host='fake_host_2',
|
||||||
share_network_subnet={
|
share_network_subnets=[{
|
||||||
'id': 'fake_sns_id_2',
|
'id': 'fake_sns_id_2',
|
||||||
'share_network_id': 'fake_sn_id_2',
|
'share_network_id': 'fake_sn_id_2',
|
||||||
},
|
}],
|
||||||
|
share_network_id='fake_sn_id_2',
|
||||||
identifier='fake_id_2',
|
identifier='fake_id_2',
|
||||||
task_state=None,
|
task_state=None,
|
||||||
is_auto_deletable=True,
|
is_auto_deletable=True,
|
||||||
status=constants.STATUS_ERROR,
|
status=constants.STATUS_ERROR,
|
||||||
security_service_update_support=False)
|
security_service_update_support=False,
|
||||||
|
network_allocation_update_support=False),
|
||||||
]
|
]
|
||||||
return fake_share_servers
|
return fake_share_servers
|
||||||
|
|
||||||
@ -184,7 +194,7 @@ class FakeRequestWithProjectId(FakeRequestAdmin):
|
|||||||
class FakeRequestWithShareNetworkSubnetId(FakeRequestAdmin):
|
class FakeRequestWithShareNetworkSubnetId(FakeRequestAdmin):
|
||||||
GET = {
|
GET = {
|
||||||
'share_network_subnet_id':
|
'share_network_subnet_id':
|
||||||
fake_share_server_get_all()[0].share_network_subnet_id,
|
fake_share_server_get_all()[0].share_network_subnet_ids,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -347,20 +357,43 @@ class ShareServerAPITest(test.TestCase):
|
|||||||
ctxt, self.resource_name, 'index')
|
ctxt, self.resource_name, 'index')
|
||||||
self.assertEqual(0, len(result['share_servers']))
|
self.assertEqual(0, len(result['share_servers']))
|
||||||
|
|
||||||
def test_show(self):
|
@ddt.data({'version': '2.70', 'share_network_name': ''},
|
||||||
|
{'version': '2.70', 'share_network_name': 'fake_sn_name'},
|
||||||
|
{'version': '2.68', 'share_network_name': 'fake_sn_name'})
|
||||||
|
@ddt.unpack
|
||||||
|
def test_show(self, version, share_network_name):
|
||||||
self.mock_object(db_api, 'share_server_get',
|
self.mock_object(db_api, 'share_server_get',
|
||||||
mock.Mock(return_value=fake_share_server_get()))
|
mock.Mock(return_value=fake_share_server_get()))
|
||||||
request, ctxt = self._prepare_request('/show', use_admin_context=True)
|
request, ctxt = self._prepare_request('/show', use_admin_context=True,
|
||||||
|
version=version)
|
||||||
|
|
||||||
|
share_network = copy.deepcopy(
|
||||||
|
fake_share_network_get_list['share_networks'][0])
|
||||||
|
share_server = copy.deepcopy(
|
||||||
|
fake_share_server_get_result['share_server'])
|
||||||
|
|
||||||
|
if version == '2.68':
|
||||||
|
share_server['share_network_subnet_id'] = \
|
||||||
|
share_server['share_network_subnet_ids'][0]
|
||||||
|
share_server.pop('share_network_subnet_ids')
|
||||||
|
share_server.pop('network_allocation_update_support')
|
||||||
|
|
||||||
|
share_network['name'] = share_network_name
|
||||||
|
if share_network['name']:
|
||||||
|
share_server['share_network_name'] = share_network['name']
|
||||||
|
else:
|
||||||
|
share_server['share_network_name'] = share_network['id']
|
||||||
|
|
||||||
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
||||||
return_value=fake_share_network_get_list['share_networks'][0]))
|
return_value=share_network))
|
||||||
result = self.controller.show(
|
result = self.controller.show(
|
||||||
request,
|
request,
|
||||||
fake_share_server_get_result['share_server']['id'])
|
share_server['id'])
|
||||||
policy.check_policy.assert_called_once_with(
|
policy.check_policy.assert_called_once_with(
|
||||||
ctxt, self.resource_name, 'show')
|
ctxt, self.resource_name, 'show')
|
||||||
db_api.share_server_get.assert_called_once_with(
|
db_api.share_server_get.assert_called_once_with(
|
||||||
ctxt, fake_share_server_get_result['share_server']['id'])
|
ctxt, share_server['id'])
|
||||||
self.assertEqual(fake_share_server_get_result['share_server'],
|
self.assertEqual(share_server,
|
||||||
result['share_server'])
|
result['share_server'])
|
||||||
|
|
||||||
@ddt.data(
|
@ddt.data(
|
||||||
@ -389,7 +422,7 @@ class ShareServerAPITest(test.TestCase):
|
|||||||
ctxt, fake_share_server_get_result['share_server']['id'])
|
ctxt, fake_share_server_get_result['share_server']['id'])
|
||||||
if isinstance(share_net_side_effect, exception.ShareNetworkNotFound):
|
if isinstance(share_net_side_effect, exception.ShareNetworkNotFound):
|
||||||
exp_share_net_id = (fake_share_server_get()
|
exp_share_net_id = (fake_share_server_get()
|
||||||
.share_network_subnet['share_network_id'])
|
.share_network_subnets[0]['share_network_id'])
|
||||||
db_api.share_network_get.assert_called_once_with(
|
db_api.share_network_get.assert_called_once_with(
|
||||||
ctxt, exp_share_net_id)
|
ctxt, exp_share_net_id)
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ class ShareAPITest(test.TestCase):
|
|||||||
self.mock_object(common, 'check_share_network_is_active',
|
self.mock_object(common, 'check_share_network_is_active',
|
||||||
mock.Mock(return_value=True))
|
mock.Mock(return_value=True))
|
||||||
self.mock_object(
|
self.mock_object(
|
||||||
db, 'share_network_subnet_get_by_availability_zone_id',
|
db, 'share_network_subnets_get_all_by_availability_zone_id',
|
||||||
mock.Mock(return_value={'id': 'fakesubnetid'}))
|
mock.Mock(return_value={'id': 'fakesubnetid'}))
|
||||||
|
|
||||||
body = {"share": copy.deepcopy(shr)}
|
body = {"share": copy.deepcopy(shr)}
|
||||||
@ -339,6 +339,8 @@ class ShareAPITest(test.TestCase):
|
|||||||
}
|
}
|
||||||
parent_share_net = 444
|
parent_share_net = 444
|
||||||
fake_share_net = {'id': parent_share_net}
|
fake_share_net = {'id': parent_share_net}
|
||||||
|
share_net_subnets = [db_utils.create_share_network_subnet(
|
||||||
|
id='fake_subnet_id', share_network_id=fake_share_net['id'])]
|
||||||
create_mock = mock.Mock(return_value=stubs.stub_share('1',
|
create_mock = mock.Mock(return_value=stubs.stub_share('1',
|
||||||
display_name=shr['name'],
|
display_name=shr['name'],
|
||||||
display_description=shr['description'],
|
display_description=shr['description'],
|
||||||
@ -361,7 +363,8 @@ class ShareAPITest(test.TestCase):
|
|||||||
self.mock_object(common, 'check_share_network_is_active',
|
self.mock_object(common, 'check_share_network_is_active',
|
||||||
mock.Mock(return_value=True))
|
mock.Mock(return_value=True))
|
||||||
self.mock_object(
|
self.mock_object(
|
||||||
db, 'share_network_subnet_get_by_availability_zone_id')
|
db, 'share_network_subnets_get_all_by_availability_zone_id',
|
||||||
|
mock.Mock(return_value=share_net_subnets))
|
||||||
|
|
||||||
body = {"share": copy.deepcopy(shr)}
|
body = {"share": copy.deepcopy(shr)}
|
||||||
req = fakes.HTTPRequest.blank('/v1/fake/shares')
|
req = fakes.HTTPRequest.blank('/v1/fake/shares')
|
||||||
@ -391,6 +394,8 @@ class ShareAPITest(test.TestCase):
|
|||||||
"share_network_id": parent_share_net
|
"share_network_id": parent_share_net
|
||||||
}
|
}
|
||||||
fake_share_net = {'id': parent_share_net}
|
fake_share_net = {'id': parent_share_net}
|
||||||
|
share_net_subnets = [db_utils.create_share_network_subnet(
|
||||||
|
id='fake_subnet_id', share_network_id=fake_share_net['id'])]
|
||||||
create_mock = mock.Mock(return_value=stubs.stub_share('1',
|
create_mock = mock.Mock(return_value=stubs.stub_share('1',
|
||||||
display_name=shr['name'],
|
display_name=shr['name'],
|
||||||
display_description=shr['description'],
|
display_description=shr['description'],
|
||||||
@ -413,7 +418,8 @@ class ShareAPITest(test.TestCase):
|
|||||||
self.mock_object(share_api.API, 'get_share_network', mock.Mock(
|
self.mock_object(share_api.API, 'get_share_network', mock.Mock(
|
||||||
return_value=fake_share_net))
|
return_value=fake_share_net))
|
||||||
self.mock_object(
|
self.mock_object(
|
||||||
db, 'share_network_subnet_get_by_availability_zone_id')
|
db, 'share_network_subnets_get_all_by_availability_zone_id',
|
||||||
|
mock.Mock(return_value=share_net_subnets))
|
||||||
|
|
||||||
body = {"share": copy.deepcopy(shr)}
|
body = {"share": copy.deepcopy(shr)}
|
||||||
req = fakes.HTTPRequest.blank('/v1/fake/shares')
|
req = fakes.HTTPRequest.blank('/v1/fake/shares')
|
||||||
@ -468,6 +474,8 @@ class ShareAPITest(test.TestCase):
|
|||||||
"share_network_id": parent_share_net
|
"share_network_id": parent_share_net
|
||||||
}
|
}
|
||||||
fake_share_net = {'id': parent_share_net}
|
fake_share_net = {'id': parent_share_net}
|
||||||
|
share_net_subnets = [db_utils.create_share_network_subnet(
|
||||||
|
id='fake_subnet_id', share_network_id=fake_share_net['id'])]
|
||||||
create_mock = mock.Mock(return_value=stubs.stub_share('1',
|
create_mock = mock.Mock(return_value=stubs.stub_share('1',
|
||||||
display_name=shr['name'],
|
display_name=shr['name'],
|
||||||
display_description=shr['description'],
|
display_description=shr['description'],
|
||||||
@ -490,7 +498,8 @@ class ShareAPITest(test.TestCase):
|
|||||||
self.mock_object(share_api.API, 'get_share_network', mock.Mock(
|
self.mock_object(share_api.API, 'get_share_network', mock.Mock(
|
||||||
return_value=fake_share_net))
|
return_value=fake_share_net))
|
||||||
self.mock_object(
|
self.mock_object(
|
||||||
db, 'share_network_subnet_get_by_availability_zone_id')
|
db, 'share_network_subnets_get_all_by_availability_zone_id',
|
||||||
|
mock.Mock(return_value=share_net_subnets))
|
||||||
|
|
||||||
body = {"share": copy.deepcopy(shr)}
|
body = {"share": copy.deepcopy(shr)}
|
||||||
req = fakes.HTTPRequest.blank('/v1/fake/shares', version=microversion)
|
req = fakes.HTTPRequest.blank('/v1/fake/shares', version=microversion)
|
||||||
@ -558,7 +567,7 @@ class ShareAPITest(test.TestCase):
|
|||||||
self.mock_object(db, 'share_network_get',
|
self.mock_object(db, 'share_network_get',
|
||||||
mock.Mock(side_effect=share_network_side_effect))
|
mock.Mock(side_effect=share_network_side_effect))
|
||||||
self.mock_object(
|
self.mock_object(
|
||||||
db, 'share_network_subnet_get_by_availability_zone_id',
|
db, 'share_network_subnets_get_all_by_availability_zone_id',
|
||||||
mock.Mock(return_value=None))
|
mock.Mock(return_value=None))
|
||||||
self.mock_object(common, 'check_share_network_is_active')
|
self.mock_object(common, 'check_share_network_is_active')
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import ddt
|
|||||||
from oslo_db import exception as db_exception
|
from oslo_db import exception as db_exception
|
||||||
|
|
||||||
from manila.api import common
|
from manila.api import common
|
||||||
|
from manila.api.openstack import api_version_request as api_version
|
||||||
from manila.api.v2 import share_network_subnets
|
from manila.api.v2 import share_network_subnets
|
||||||
from manila.db import api as db_api
|
from manila.db import api as db_api
|
||||||
from manila import exception
|
from manila import exception
|
||||||
@ -61,16 +62,17 @@ class ShareNetworkSubnetControllerTest(test.TestCase):
|
|||||||
mock.Mock(return_value=fake_az))
|
mock.Mock(return_value=fake_az))
|
||||||
self.share_network = db_utils.create_share_network(
|
self.share_network = db_utils.create_share_network(
|
||||||
name='fake_network', id='fake_sn_id')
|
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(
|
self.subnet = db_utils.create_share_network_subnet(
|
||||||
share_network_id=self.share_network['id'])
|
share_network_id=self.share_network['id'])
|
||||||
|
self.share_server = db_utils.create_share_server(
|
||||||
|
share_network_subnets=[self.subnet])
|
||||||
self.share = db_utils.create_share()
|
self.share = db_utils.create_share()
|
||||||
|
|
||||||
def test_share_network_subnet_delete(self):
|
def test_share_network_subnet_delete(self):
|
||||||
req = fakes.HTTPRequest.blank('/subnets/%s' % self.subnet['id'],
|
req = fakes.HTTPRequest.blank('/subnets/%s' % self.subnet['id'],
|
||||||
version="2.51")
|
version="2.51")
|
||||||
context = req.environ['manila.context']
|
context = req.environ['manila.context']
|
||||||
|
self.subnet['share_servers'] = [self.share_server]
|
||||||
|
|
||||||
mock_sns_get = self.mock_object(
|
mock_sns_get = self.mock_object(
|
||||||
db_api, 'share_network_subnet_get',
|
db_api, 'share_network_subnet_get',
|
||||||
@ -150,6 +152,7 @@ class ShareNetworkSubnetControllerTest(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('/subnets/%s' % self.subnet['id'],
|
req = fakes.HTTPRequest.blank('/subnets/%s' % self.subnet['id'],
|
||||||
version="2.51")
|
version="2.51")
|
||||||
context = req.environ['manila.context']
|
context = req.environ['manila.context']
|
||||||
|
self.subnet['share_servers'] = [self.share_server]
|
||||||
|
|
||||||
mock_sns_get = self.mock_object(
|
mock_sns_get = self.mock_object(
|
||||||
db_api, 'share_network_subnet_get',
|
db_api, 'share_network_subnet_get',
|
||||||
@ -182,7 +185,10 @@ class ShareNetworkSubnetControllerTest(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank('/subnets/%s' % self.subnet['id'],
|
req = fakes.HTTPRequest.blank('/subnets/%s' % self.subnet['id'],
|
||||||
version="2.51")
|
version="2.51")
|
||||||
context = req.environ['manila.context']
|
context = req.environ['manila.context']
|
||||||
|
self.subnet['share_servers'] = [self.share_server]
|
||||||
|
|
||||||
|
mock_network_get = self.mock_object(
|
||||||
|
db_api, 'share_network_get')
|
||||||
mock_sns_get = self.mock_object(
|
mock_sns_get = self.mock_object(
|
||||||
db_api, 'share_network_subnet_get',
|
db_api, 'share_network_subnet_get',
|
||||||
mock.Mock(return_value=self.subnet))
|
mock.Mock(return_value=self.subnet))
|
||||||
@ -196,6 +202,8 @@ class ShareNetworkSubnetControllerTest(test.TestCase):
|
|||||||
self.share_network['id'],
|
self.share_network['id'],
|
||||||
self.subnet['id'])
|
self.subnet['id'])
|
||||||
|
|
||||||
|
mock_network_get.assert_called_once_with(
|
||||||
|
context, self.share_network['id'])
|
||||||
mock_sns_get.assert_called_once_with(
|
mock_sns_get.assert_called_once_with(
|
||||||
context, self.subnet['id'])
|
context, self.subnet['id'])
|
||||||
mock_all_get_all_shares_by_ss.assert_called_once_with(
|
mock_all_get_all_shares_by_ss.assert_called_once_with(
|
||||||
@ -204,34 +212,6 @@ class ShareNetworkSubnetControllerTest(test.TestCase):
|
|||||||
self.mock_policy_check.assert_called_once_with(
|
self.mock_policy_check.assert_called_once_with(
|
||||||
context, self.resource_name, 'delete')
|
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):
|
def _setup_create_test_request_body(self):
|
||||||
body = {
|
body = {
|
||||||
'share_network_id': self.share_network['id'],
|
'share_network_id': self.share_network['id'],
|
||||||
@ -241,131 +221,145 @@ class ShareNetworkSubnetControllerTest(test.TestCase):
|
|||||||
}
|
}
|
||||||
return body
|
return body
|
||||||
|
|
||||||
def test_subnet_create(self):
|
@ddt.data({'version': "2.51", 'has_share_servers': False},
|
||||||
req = fakes.HTTPRequest.blank('/subnets', version="2.51")
|
{'version': "2.70", 'has_share_servers': False},
|
||||||
|
{'version': "2.70", 'has_share_servers': True})
|
||||||
|
@ddt.unpack
|
||||||
|
def test_subnet_create(self, version, has_share_servers):
|
||||||
|
req = fakes.HTTPRequest.blank('/subnets', version=version)
|
||||||
|
multiple_subnet_support = (req.api_version_request >=
|
||||||
|
api_version.APIVersionRequest("2.70"))
|
||||||
|
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_subnet = copy.deepcopy(self.subnet)
|
||||||
|
if has_share_servers:
|
||||||
|
expected_subnet['share_servers'] = [self.share_server]
|
||||||
|
|
||||||
|
mock_validate_subnet_create = self.mock_object(
|
||||||
|
common, 'validate_subnet_create',
|
||||||
|
mock.Mock(return_value=(self.share_network, [expected_subnet])))
|
||||||
|
mock_subnet_create = self.mock_object(
|
||||||
|
db_api, 'share_network_subnet_create',
|
||||||
|
mock.Mock(return_value=expected_subnet))
|
||||||
|
mock_update_net_allocations = self.mock_object(
|
||||||
|
self.controller.share_api,
|
||||||
|
'update_share_server_network_allocations',
|
||||||
|
mock.Mock(return_value=expected_subnet))
|
||||||
|
mock_share_network_subnet_get = self.mock_object(
|
||||||
|
db_api, 'share_network_subnet_get',
|
||||||
|
mock.Mock(return_value=expected_subnet))
|
||||||
|
|
||||||
|
fake_data = body['share-network-subnet']
|
||||||
|
fake_data['share_network_id'] = self.share_network['id']
|
||||||
|
res = self.controller.create(
|
||||||
|
req, body['share-network-subnet']['share_network_id'], body)
|
||||||
|
|
||||||
|
view_subnet = {
|
||||||
|
'id': expected_subnet.get('id'),
|
||||||
|
'availability_zone': expected_subnet.get('availability_zone'),
|
||||||
|
'share_network_id': expected_subnet.get('share_network_id'),
|
||||||
|
'share_network_name': expected_subnet['share_network_name'],
|
||||||
|
'created_at': expected_subnet.get('created_at'),
|
||||||
|
'segmentation_id': expected_subnet.get('segmentation_id'),
|
||||||
|
'neutron_subnet_id': expected_subnet.get('neutron_subnet_id'),
|
||||||
|
'updated_at': expected_subnet.get('updated_at'),
|
||||||
|
'neutron_net_id': expected_subnet.get('neutron_net_id'),
|
||||||
|
'ip_version': expected_subnet.get('ip_version'),
|
||||||
|
'cidr': expected_subnet.get('cidr'),
|
||||||
|
'network_type': expected_subnet.get('network_type'),
|
||||||
|
'mtu': expected_subnet.get('mtu'),
|
||||||
|
'gateway': expected_subnet.get('gateway')
|
||||||
|
}
|
||||||
|
self.assertEqual(view_subnet, res['share_network_subnet'])
|
||||||
|
mock_share_network_subnet_get.assert_called_once_with(
|
||||||
|
context, expected_subnet['id'])
|
||||||
|
mock_validate_subnet_create.assert_called_once_with(
|
||||||
|
context, sn_id, fake_data, multiple_subnet_support)
|
||||||
|
if has_share_servers:
|
||||||
|
fake_data['share_servers'] = [self.share_server]
|
||||||
|
mock_update_net_allocations.assert_called_once_with(
|
||||||
|
context, self.share_network, fake_data)
|
||||||
|
else:
|
||||||
|
mock_subnet_create.assert_called_once_with(
|
||||||
|
context, fake_data)
|
||||||
|
|
||||||
|
@ddt.data({'exception1': exception.ServiceIsDown(),
|
||||||
|
'exc_raise': exc.HTTPInternalServerError},
|
||||||
|
{'exception1': exception.InvalidShareNetwork(),
|
||||||
|
'exc_raise': exc.HTTPBadRequest},
|
||||||
|
{'exception1': db_exception.DBError(),
|
||||||
|
'exc_raise': exc.HTTPInternalServerError})
|
||||||
|
@ddt.unpack
|
||||||
|
def test_subnet_create_fail_update_network_allocation(self, exception1,
|
||||||
|
exc_raise):
|
||||||
|
req = fakes.HTTPRequest.blank('/subnets', version="2.70")
|
||||||
|
multiple_subnet_support = (req.api_version_request >=
|
||||||
|
api_version.APIVersionRequest("2.70"))
|
||||||
context = req.environ['manila.context']
|
context = req.environ['manila.context']
|
||||||
body = {
|
body = {
|
||||||
'share-network-subnet': self._setup_create_test_request_body()
|
'share-network-subnet': self._setup_create_test_request_body()
|
||||||
}
|
}
|
||||||
sn_id = body['share-network-subnet']['share_network_id']
|
sn_id = body['share-network-subnet']['share_network_id']
|
||||||
|
|
||||||
expected_result = copy.deepcopy(body)
|
expected_subnet = copy.deepcopy(self.subnet)
|
||||||
expected_result['share-network-subnet']['id'] = self.subnet['id']
|
expected_subnet['share_servers'] = [self.share_server]
|
||||||
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(
|
mock_validate_subnet_create = self.mock_object(
|
||||||
req, body['share-network-subnet']['share_network_id'], body)
|
common, 'validate_subnet_create',
|
||||||
|
mock.Mock(return_value=(self.share_network, [expected_subnet])))
|
||||||
|
mock_update_net_allocations = self.mock_object(
|
||||||
|
self.controller.share_api,
|
||||||
|
'update_share_server_network_allocations',
|
||||||
|
mock.Mock(side_effect=exception1))
|
||||||
|
|
||||||
mock_check_net_and_subnet_id.assert_called_once_with(
|
fake_data = body['share-network-subnet']
|
||||||
body['share-network-subnet'])
|
fake_data['share_network_id'] = self.share_network['id']
|
||||||
mock_validate_subnet.assert_called_once_with(
|
fake_data['share_servers'] = [self.share_server]
|
||||||
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):
|
self.assertRaises(exc_raise,
|
||||||
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,
|
self.controller.create,
|
||||||
req,
|
req,
|
||||||
fake_sn_id,
|
body['share-network-subnet']['share_network_id'],
|
||||||
body)
|
body)
|
||||||
mock_sn_get.assert_called_once_with(context, fake_sn_id)
|
|
||||||
|
|
||||||
def test_subnet_create_az_not_found(self):
|
mock_validate_subnet_create.assert_called_once_with(
|
||||||
|
context, sn_id, fake_data, multiple_subnet_support)
|
||||||
|
mock_update_net_allocations.assert_called_once_with(
|
||||||
|
context, self.share_network, fake_data)
|
||||||
|
|
||||||
|
def test_subnet_create_invalid_body(self):
|
||||||
fake_sn_id = 'fake_id'
|
fake_sn_id = 'fake_id'
|
||||||
req = fakes.HTTPRequest.blank('/subnets', version="2.51")
|
req = fakes.HTTPRequest.blank('/subnets', version="2.51")
|
||||||
context = req.environ['manila.context']
|
body = {}
|
||||||
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.assertRaises(exc.HTTPBadRequest,
|
||||||
self.controller.create,
|
self.controller.create,
|
||||||
req,
|
req,
|
||||||
fake_sn_id,
|
fake_sn_id,
|
||||||
body)
|
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):
|
@ddt.data("2.51", "2.70")
|
||||||
fake_sn_id = 'fake_id'
|
def test_subnet_create_subnet_db_error(self, version):
|
||||||
req = fakes.HTTPRequest.blank('/subnets', version="2.51")
|
req = fakes.HTTPRequest.blank('/subnets', version=version)
|
||||||
context = req.environ['manila.context']
|
|
||||||
body = {
|
body = {
|
||||||
'share-network-subnet': self._setup_create_test_request_body()
|
'share-network-subnet': self._setup_create_test_request_body()
|
||||||
}
|
}
|
||||||
mock_sn_get = self.mock_object(db_api, 'share_network_get')
|
expected_subnet = copy.deepcopy(self.subnet)
|
||||||
mock__validate_subnet = self.mock_object(
|
self.mock_object(
|
||||||
self.controller, '_validate_subnet',
|
common, 'validate_subnet_create',
|
||||||
mock.Mock(side_effect=exc.HTTPConflict(''))
|
mock.Mock(return_value=(self.share_network, [expected_subnet])))
|
||||||
)
|
self.mock_object(
|
||||||
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',
|
db_api, 'share_network_subnet_create',
|
||||||
mock.Mock(side_effect=db_exception.DBError()))
|
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.assertRaises(exc.HTTPInternalServerError,
|
||||||
self.controller.create,
|
self.controller.create,
|
||||||
req,
|
req,
|
||||||
fake_sn_id,
|
'fake_sn_id',
|
||||||
body)
|
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):
|
def test_show_subnet(self):
|
||||||
subnet = db_utils.create_share_network_subnet(
|
subnet = db_utils.create_share_network_subnet(
|
||||||
id='fake_sns_2', share_network_id=self.share_network['id'])
|
id='fake_sns_2', share_network_id=self.share_network['id'])
|
||||||
|
@ -776,6 +776,13 @@ class ShareNetworkAPITest(test.TestCase):
|
|||||||
share_nw,
|
share_nw,
|
||||||
self.body)
|
self.body)
|
||||||
|
|
||||||
|
def test_update_invalid_body(self):
|
||||||
|
self.assertRaises(webob_exc.HTTPUnprocessableEntity,
|
||||||
|
self.controller.update,
|
||||||
|
self.req,
|
||||||
|
'fake_sn_id',
|
||||||
|
None)
|
||||||
|
|
||||||
@mock.patch.object(db_api, 'share_network_get', mock.Mock())
|
@mock.patch.object(db_api, 'share_network_get', mock.Mock())
|
||||||
def test_update_invalid_key_in_use(self):
|
def test_update_invalid_key_in_use(self):
|
||||||
share_nw = fake_share_network.copy()
|
share_nw = fake_share_network.copy()
|
||||||
@ -829,8 +836,8 @@ class ShareNetworkAPITest(test.TestCase):
|
|||||||
self.mock_object(
|
self.mock_object(
|
||||||
self.controller, '_share_network_subnets_contain_share_servers',
|
self.controller, '_share_network_subnets_contain_share_servers',
|
||||||
mock.Mock(return_value=False))
|
mock.Mock(return_value=False))
|
||||||
self.mock_object(db_api, 'share_network_subnet_get_default_subnet',
|
self.mock_object(db_api, 'share_network_subnet_get_default_subnets',
|
||||||
mock.Mock(return_value=fake_share_network_subnet))
|
mock.Mock(return_value=[fake_share_network_subnet]))
|
||||||
self.mock_object(db_api, 'share_network_subnet_update')
|
self.mock_object(db_api, 'share_network_subnet_update')
|
||||||
|
|
||||||
body = {share_networks.RESOURCE_NAME: {'neutron_subnet_id':
|
body = {share_networks.RESOURCE_NAME: {'neutron_subnet_id':
|
||||||
@ -844,18 +851,20 @@ class ShareNetworkAPITest(test.TestCase):
|
|||||||
self.req,
|
self.req,
|
||||||
share_nw,
|
share_nw,
|
||||||
body)
|
body)
|
||||||
db_api.share_network_subnet_get_default_subnet.assert_called_once_with(
|
(db_api.share_network_subnet_get_default_subnets.
|
||||||
self.context, share_nw)
|
assert_called_once_with(self.context, share_nw))
|
||||||
db_api.share_network_subnet_update.assert_called_once_with(
|
db_api.share_network_subnet_update.assert_called_once_with(
|
||||||
self.context, fake_share_network_subnet['id'],
|
self.context, fake_share_network_subnet['id'],
|
||||||
body['share_network'])
|
body['share_network'])
|
||||||
|
|
||||||
@ddt.data((webob_exc.HTTPBadRequest, fake_share_network_subnet, None,
|
@ddt.data((webob_exc.HTTPBadRequest, 1, None,
|
||||||
|
'new subnet'),
|
||||||
|
(webob_exc.HTTPBadRequest, 2, None,
|
||||||
'new subnet'),
|
'new subnet'),
|
||||||
(webob_exc.HTTPBadRequest, None, 'neutron net', None))
|
(webob_exc.HTTPBadRequest, None, 'neutron net', None))
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test_update_default_subnet_errors(self, exception_to_raise,
|
def test_update_default_subnet_errors(self, exception_to_raise,
|
||||||
get_default_subnet_return,
|
get_default_subnet_return_length,
|
||||||
neutron_net_id, neutron_subnet_id):
|
neutron_net_id, neutron_subnet_id):
|
||||||
share_nw = 'fake network id'
|
share_nw = 'fake network id'
|
||||||
self.mock_object(db_api, 'share_network_get',
|
self.mock_object(db_api, 'share_network_get',
|
||||||
@ -863,15 +872,21 @@ class ShareNetworkAPITest(test.TestCase):
|
|||||||
self.mock_object(
|
self.mock_object(
|
||||||
self.controller, '_share_network_subnets_contain_share_servers',
|
self.controller, '_share_network_subnets_contain_share_servers',
|
||||||
mock.Mock(return_value=False))
|
mock.Mock(return_value=False))
|
||||||
self.mock_object(db_api, 'share_network_subnet_get_default_subnet',
|
self.mock_object(db_api, 'share_network_subnet_get_default_subnets',
|
||||||
mock.Mock(return_value=get_default_subnet_return))
|
mock.Mock(return_value=None))
|
||||||
|
|
||||||
if get_default_subnet_return:
|
if get_default_subnet_return_length:
|
||||||
fake_subnet = copy.deepcopy(fake_share_network_subnet)
|
fake_subnet = copy.deepcopy(fake_share_network_subnet)
|
||||||
fake_subnet['neutron_net_id'] = None
|
fake_subnet['neutron_net_id'] = None
|
||||||
fake_subnet['neutron_subnet_id'] = None
|
fake_subnet['neutron_subnet_id'] = None
|
||||||
db_api.share_network_subnet_get_default_subnet.return_value = (
|
|
||||||
fake_subnet)
|
if get_default_subnet_return_length == 1:
|
||||||
|
(db_api.share_network_subnet_get_default_subnets.
|
||||||
|
return_value) = [fake_subnet]
|
||||||
|
elif get_default_subnet_return_length == 2:
|
||||||
|
(db_api.share_network_subnet_get_default_subnets.
|
||||||
|
return_value) = [fake_subnet, fake_subnet]
|
||||||
|
|
||||||
body = {
|
body = {
|
||||||
share_networks.RESOURCE_NAME: {
|
share_networks.RESOURCE_NAME: {
|
||||||
'neutron_net_id': neutron_net_id,
|
'neutron_net_id': neutron_net_id,
|
||||||
@ -885,8 +900,8 @@ class ShareNetworkAPITest(test.TestCase):
|
|||||||
share_nw,
|
share_nw,
|
||||||
body)
|
body)
|
||||||
|
|
||||||
db_api.share_network_subnet_get_default_subnet.assert_called_once_with(
|
(db_api.share_network_subnet_get_default_subnets.
|
||||||
self.context, share_nw)
|
assert_called_once_with(self.context, share_nw))
|
||||||
|
|
||||||
@ddt.data(*set(("1.0", "2.25", "2.26", api_version._MAX_API_VERSION)))
|
@ddt.data(*set(("1.0", "2.25", "2.26", api_version._MAX_API_VERSION)))
|
||||||
def test_add_security_service(self, microversion):
|
def test_add_security_service(self, microversion):
|
||||||
@ -1620,3 +1635,82 @@ class ShareNetworkAPITest(test.TestCase):
|
|||||||
db_api.share_network_update.assert_called_once_with(
|
db_api.share_network_update.assert_called_once_with(
|
||||||
request.environ['manila.context'],
|
request.environ['manila.context'],
|
||||||
share_network['id'], {'status': 'active'})
|
share_network['id'], {'status': 'active'})
|
||||||
|
|
||||||
|
@ddt.data([], ['fake_server'])
|
||||||
|
def test_share_network_subnet_create_check(self, servers):
|
||||||
|
body = {
|
||||||
|
'share_network_subnet_create_check': {
|
||||||
|
'reset_operation': False,
|
||||||
|
'availability_zone': 'fake_az',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request = fakes.HTTPRequest.blank(
|
||||||
|
'/share-networks', use_admin_context=True, version='2.70')
|
||||||
|
context = request.environ['manila.context']
|
||||||
|
|
||||||
|
share_net = 'fake_net'
|
||||||
|
subnet = {'share_servers': servers}
|
||||||
|
existing_subnets = [subnet]
|
||||||
|
mock_validate_subnet = self.mock_object(
|
||||||
|
common, 'validate_subnet_create',
|
||||||
|
mock.Mock(return_value=(share_net, existing_subnets)))
|
||||||
|
share_api_return = {
|
||||||
|
'compatible': not bool(servers),
|
||||||
|
'hosts_check_result': {}
|
||||||
|
}
|
||||||
|
mock_check_update = self.mock_object(
|
||||||
|
self.controller.share_api,
|
||||||
|
'check_update_share_server_network_allocations',
|
||||||
|
mock.Mock(return_value=share_api_return))
|
||||||
|
subnet_view = 'fake_subnet'
|
||||||
|
mock_view = self.mock_object(
|
||||||
|
self.controller._view_builder,
|
||||||
|
'build_share_network_subnet_create_check',
|
||||||
|
mock.Mock(return_value=subnet_view))
|
||||||
|
|
||||||
|
net_id = 'fake_net_id'
|
||||||
|
response = self.controller.share_network_subnet_create_check(
|
||||||
|
request, net_id, body)
|
||||||
|
|
||||||
|
self.assertEqual(subnet_view, response)
|
||||||
|
data = body['share_network_subnet_create_check']
|
||||||
|
mock_validate_subnet.assert_called_once_with(
|
||||||
|
context, net_id, data, True)
|
||||||
|
if servers:
|
||||||
|
data['share_servers'] = servers
|
||||||
|
mock_check_update.assert_called_once_with(
|
||||||
|
context, share_net, data, False)
|
||||||
|
else:
|
||||||
|
mock_check_update.assert_not_called()
|
||||||
|
mock_view.assert_called_once_with(request, share_api_return)
|
||||||
|
|
||||||
|
@ddt.data(
|
||||||
|
(exception.ServiceIsDown(message='fake'),
|
||||||
|
webob_exc.HTTPInternalServerError),
|
||||||
|
(exception.InvalidShareNetwork(message='fake'),
|
||||||
|
webob_exc.HTTPBadRequest))
|
||||||
|
@ddt.unpack
|
||||||
|
def test_share_network_subnet_create_check_api_failed(
|
||||||
|
self, captured_exception, exception_to_be_raised):
|
||||||
|
body = {
|
||||||
|
'share_network_subnet_create_check': {
|
||||||
|
'reset_operation': False,
|
||||||
|
'availability_zone': 'fake_az',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request = fakes.HTTPRequest.blank(
|
||||||
|
'/share-networks', use_admin_context=True, version='2.70')
|
||||||
|
share_net = 'fake_net'
|
||||||
|
subnet = {'share_servers': 'fake_server'}
|
||||||
|
existing_subnets = [subnet]
|
||||||
|
self.mock_object(
|
||||||
|
common, 'validate_subnet_create',
|
||||||
|
mock.Mock(return_value=(share_net, existing_subnets)))
|
||||||
|
self.mock_object(
|
||||||
|
self.controller.share_api,
|
||||||
|
'check_update_share_server_network_allocations',
|
||||||
|
mock.Mock(side_effect=captured_exception))
|
||||||
|
|
||||||
|
self.assertRaises(exception_to_be_raised,
|
||||||
|
self.controller.share_network_subnet_create_check,
|
||||||
|
request, 'fake_net_id', body)
|
||||||
|
@ -120,17 +120,18 @@ class ShareServerControllerTest(test.TestCase):
|
|||||||
version="2.49")
|
version="2.49")
|
||||||
context = req.environ['manila.context']
|
context = req.environ['manila.context']
|
||||||
share_network = db_utils.create_share_network(name=share_net_name)
|
share_network = db_utils.create_share_network(name=share_net_name)
|
||||||
share_net_subnet = db_utils.create_share_network_subnet(
|
share_net_subnet = [db_utils.create_share_network_subnet(
|
||||||
share_network_id=share_network['id'])
|
share_network_id=share_network['id'])]
|
||||||
share_server = db_utils.create_share_server(
|
share_server = db_utils.create_share_server(
|
||||||
share_network_subnet_id=share_net_subnet['id'],
|
share_network_subnet_id=share_net_subnet[0]['id'],
|
||||||
host='fake_host',
|
host='fake_host',
|
||||||
identifier='fake_identifier',
|
identifier='fake_identifier',
|
||||||
is_auto_deletable=False)
|
is_auto_deletable=False,
|
||||||
|
share_network_subnets=share_net_subnet)
|
||||||
|
|
||||||
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
||||||
return_value=share_network))
|
return_value=share_network))
|
||||||
self.mock_object(db_api, 'share_network_subnet_get_default_subnet',
|
self.mock_object(db_api, 'share_network_subnet_get_default_subnets',
|
||||||
mock.Mock(return_value=share_net_subnet))
|
mock.Mock(return_value=share_net_subnet))
|
||||||
self.mock_object(utils, 'validate_service_host')
|
self.mock_object(utils, 'validate_service_host')
|
||||||
|
|
||||||
@ -151,7 +152,8 @@ class ShareServerControllerTest(test.TestCase):
|
|||||||
'status': constants.STATUS_ACTIVE,
|
'status': constants.STATUS_ACTIVE,
|
||||||
'host': 'fake_host',
|
'host': 'fake_host',
|
||||||
'share_network_id':
|
'share_network_id':
|
||||||
share_server['share_network_subnet']['share_network_id'],
|
(share_server['share_network_subnets'][0]
|
||||||
|
['share_network_id']),
|
||||||
'created_at': share_server['created_at'],
|
'created_at': share_server['created_at'],
|
||||||
'backend_details': {},
|
'backend_details': {},
|
||||||
'identifier': share_server['identifier'],
|
'identifier': share_server['identifier'],
|
||||||
@ -163,12 +165,12 @@ class ShareServerControllerTest(test.TestCase):
|
|||||||
'fake_net_name')
|
'fake_net_name')
|
||||||
else:
|
else:
|
||||||
expected_result['share_server']['share_network_name'] = (
|
expected_result['share_server']['share_network_name'] = (
|
||||||
share_net_subnet['share_network_id'])
|
share_net_subnet[0]['share_network_id'])
|
||||||
|
|
||||||
req_params = body['share_server']
|
req_params = body['share_server']
|
||||||
manage_share_server_mock.assert_called_once_with(
|
manage_share_server_mock.assert_called_once_with(
|
||||||
context, req_params['identifier'], req_params['host'],
|
context, req_params['identifier'], req_params['host'],
|
||||||
share_net_subnet, req_params['driver_options'])
|
share_net_subnet[0], req_params['driver_options'])
|
||||||
|
|
||||||
self.assertEqual(expected_result, result)
|
self.assertEqual(expected_result, result)
|
||||||
|
|
||||||
@ -178,32 +180,23 @@ class ShareServerControllerTest(test.TestCase):
|
|||||||
def test_manage_invalid(self):
|
def test_manage_invalid(self):
|
||||||
req = fakes.HTTPRequest.blank('/manage_share_server',
|
req = fakes.HTTPRequest.blank('/manage_share_server',
|
||||||
use_admin_context=True, version="2.49")
|
use_admin_context=True, version="2.49")
|
||||||
context = req.environ['manila.context']
|
|
||||||
share_network = db_utils.create_share_network()
|
share_network = db_utils.create_share_network()
|
||||||
share_net_subnet = db_utils.create_share_network_subnet(
|
share_net_subnet = [db_utils.create_share_network_subnet(
|
||||||
share_network_id=share_network['id'])
|
share_network_id=share_network['id'])]
|
||||||
|
|
||||||
body = {
|
body = {
|
||||||
'share_server': self._setup_manage_test_request_body()
|
'share_server': self._setup_manage_test_request_body()
|
||||||
}
|
}
|
||||||
|
body['share_server']['driver_options'] = []
|
||||||
self.mock_object(utils, 'validate_service_host')
|
self.mock_object(utils, 'validate_service_host')
|
||||||
self.mock_object(db_api, 'share_network_get',
|
self.mock_object(db_api, 'share_network_get',
|
||||||
mock.Mock(return_value=share_network))
|
mock.Mock(return_value=share_network))
|
||||||
self.mock_object(db_api, 'share_network_subnet_get_default_subnet',
|
self.mock_object(db_api, 'share_network_subnet_get_default_subnets',
|
||||||
mock.Mock(return_value=share_net_subnet))
|
mock.Mock(return_value=share_net_subnet))
|
||||||
|
|
||||||
manage_share_server_mock = self.mock_object(
|
|
||||||
share_api.API, 'manage_share_server',
|
|
||||||
mock.Mock(side_effect=exception.InvalidInput('foobar')))
|
|
||||||
|
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
self.controller.manage, req, body)
|
self.controller.manage, req, body)
|
||||||
|
|
||||||
req_params = body['share_server']
|
|
||||||
manage_share_server_mock.assert_called_once_with(
|
|
||||||
context, req_params['identifier'], req_params['host'],
|
|
||||||
share_net_subnet, req_params['driver_options'])
|
|
||||||
|
|
||||||
def test_manage_forbidden(self):
|
def test_manage_forbidden(self):
|
||||||
"""Tests share server manage without admin privileges"""
|
"""Tests share server manage without admin privileges"""
|
||||||
req = fakes.HTTPRequest.blank('/manage_share_server', version="2.49")
|
req = fakes.HTTPRequest.blank('/manage_share_server', version="2.49")
|
||||||
@ -211,12 +204,12 @@ class ShareServerControllerTest(test.TestCase):
|
|||||||
self.mock_object(share_api.API, 'manage_share_server', error)
|
self.mock_object(share_api.API, 'manage_share_server', error)
|
||||||
|
|
||||||
share_network = db_utils.create_share_network()
|
share_network = db_utils.create_share_network()
|
||||||
share_net_subnet = db_utils.create_share_network_subnet(
|
share_net_subnet = [db_utils.create_share_network_subnet(
|
||||||
share_network_id=share_network['id'])
|
share_network_id=share_network['id'])]
|
||||||
|
|
||||||
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
||||||
return_value=share_network))
|
return_value=share_network))
|
||||||
self.mock_object(db_api, 'share_network_subnet_get_default_subnet',
|
self.mock_object(db_api, 'share_network_subnet_get_default_subnets',
|
||||||
mock.Mock(return_value=share_net_subnet))
|
mock.Mock(return_value=share_net_subnet))
|
||||||
self.mock_object(utils, 'validate_service_host')
|
self.mock_object(utils, 'validate_service_host')
|
||||||
|
|
||||||
@ -281,12 +274,12 @@ class ShareServerControllerTest(test.TestCase):
|
|||||||
self.mock_object(utils, 'validate_service_host', error)
|
self.mock_object(utils, 'validate_service_host', error)
|
||||||
|
|
||||||
share_network = db_utils.create_share_network()
|
share_network = db_utils.create_share_network()
|
||||||
share_net_subnet = db_utils.create_share_network_subnet(
|
share_net_subnet = [db_utils.create_share_network_subnet(
|
||||||
share_network_id=share_network['id'])
|
share_network_id=share_network['id'])]
|
||||||
|
|
||||||
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
||||||
return_value=share_network))
|
return_value=share_network))
|
||||||
self.mock_object(db_api, 'share_network_subnet_get_default_subnet',
|
self.mock_object(db_api, 'share_network_subnet_get_default_subnets',
|
||||||
mock.Mock(return_value=share_net_subnet))
|
mock.Mock(return_value=share_net_subnet))
|
||||||
self.mock_object(common, 'check_share_network_is_active',
|
self.mock_object(common, 'check_share_network_is_active',
|
||||||
mock.Mock(return_value=True))
|
mock.Mock(return_value=True))
|
||||||
@ -296,7 +289,7 @@ class ShareServerControllerTest(test.TestCase):
|
|||||||
{'share_server': self._setup_manage_test_request_body()})
|
{'share_server': self._setup_manage_test_request_body()})
|
||||||
|
|
||||||
common.check_share_network_is_active.assert_called_once_with(
|
common.check_share_network_is_active.assert_called_once_with(
|
||||||
share_net_subnet['share_network'])
|
share_net_subnet[0]['share_network'])
|
||||||
policy.check_policy.assert_called_once_with(
|
policy.check_policy.assert_called_once_with(
|
||||||
context, self.resource_name, 'manage_share_server')
|
context, self.resource_name, 'manage_share_server')
|
||||||
|
|
||||||
@ -305,12 +298,12 @@ class ShareServerControllerTest(test.TestCase):
|
|||||||
context = req.environ['manila.context']
|
context = req.environ['manila.context']
|
||||||
|
|
||||||
share_network = db_utils.create_share_network()
|
share_network = db_utils.create_share_network()
|
||||||
share_net_subnet = db_utils.create_share_network_subnet(
|
share_net_subnet = [db_utils.create_share_network_subnet(
|
||||||
share_network_id=share_network['id'])
|
share_network_id=share_network['id'])]
|
||||||
|
|
||||||
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
self.mock_object(db_api, 'share_network_get', mock.Mock(
|
||||||
return_value=share_network))
|
return_value=share_network))
|
||||||
self.mock_object(db_api, 'share_network_subnet_get_default_subnet',
|
self.mock_object(db_api, 'share_network_subnet_get_default_subnets',
|
||||||
mock.Mock(return_value=share_net_subnet))
|
mock.Mock(return_value=share_net_subnet))
|
||||||
self.mock_object(utils, 'validate_service_host')
|
self.mock_object(utils, 'validate_service_host')
|
||||||
self.mock_object(common, 'check_share_network_is_active',
|
self.mock_object(common, 'check_share_network_is_active',
|
||||||
@ -321,7 +314,7 @@ class ShareServerControllerTest(test.TestCase):
|
|||||||
{'share_server': self._setup_manage_test_request_body()})
|
{'share_server': self._setup_manage_test_request_body()})
|
||||||
|
|
||||||
common.check_share_network_is_active.assert_called_once_with(
|
common.check_share_network_is_active.assert_called_once_with(
|
||||||
share_net_subnet['share_network'])
|
share_net_subnet[0]['share_network'])
|
||||||
policy.check_policy.assert_called_once_with(
|
policy.check_policy.assert_called_once_with(
|
||||||
context, self.resource_name, 'manage_share_server')
|
context, self.resource_name, 'manage_share_server')
|
||||||
|
|
||||||
@ -377,16 +370,16 @@ class ShareServerControllerTest(test.TestCase):
|
|||||||
context = req.environ['manila.context']
|
context = req.environ['manila.context']
|
||||||
share_network = db_utils.create_share_network()
|
share_network = db_utils.create_share_network()
|
||||||
body = {'share_server': self._setup_manage_test_request_body()}
|
body = {'share_server': self._setup_manage_test_request_body()}
|
||||||
share_net_subnet = db_utils.create_share_network_subnet(
|
share_net_subnet = [db_utils.create_share_network_subnet(
|
||||||
share_network_id=share_network['id'])
|
share_network_id=share_network['id'])]
|
||||||
body['share_server']['share_network_subnet_id'] = (
|
body['share_server']['share_network_subnet_id'] = (
|
||||||
share_net_subnet['id'] if body_contains_subnet else None)
|
share_net_subnet[0]['id'] if body_contains_subnet else None)
|
||||||
|
|
||||||
self.mock_object(
|
self.mock_object(
|
||||||
db_api, 'share_network_subnet_get',
|
db_api, 'share_network_subnet_get_all_with_same_az',
|
||||||
mock.Mock(side_effect=exception.ShareNetworkSubnetNotFound(
|
mock.Mock(side_effect=exception.ShareNetworkSubnetNotFound(
|
||||||
share_network_subnet_id='fake')))
|
share_network_subnet_id='fake')))
|
||||||
self.mock_object(db_api, 'share_network_subnet_get_default_subnet',
|
self.mock_object(db_api, 'share_network_subnet_get_default_subnets',
|
||||||
mock.Mock(return_value=None))
|
mock.Mock(return_value=None))
|
||||||
|
|
||||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
@ -397,10 +390,47 @@ class ShareServerControllerTest(test.TestCase):
|
|||||||
policy.check_policy.assert_called_once_with(
|
policy.check_policy.assert_called_once_with(
|
||||||
context, self.resource_name, 'manage_share_server')
|
context, self.resource_name, 'manage_share_server')
|
||||||
if body_contains_subnet:
|
if body_contains_subnet:
|
||||||
db_api.share_network_subnet_get.assert_called_once_with(
|
(db_api.share_network_subnet_get_all_with_same_az.
|
||||||
context, share_net_subnet['id'])
|
assert_called_once_with(context, share_net_subnet[0]['id']))
|
||||||
else:
|
else:
|
||||||
(db_api.share_network_subnet_get_default_subnet
|
(db_api.share_network_subnet_get_default_subnets
|
||||||
|
.assert_called_once_with(
|
||||||
|
context, body['share_server']['share_network_id']))
|
||||||
|
|
||||||
|
@ddt.data(True, False)
|
||||||
|
def test__validate_manage_share_server_error_multiple_subnet(
|
||||||
|
self, body_contains_subnet):
|
||||||
|
req = fakes.HTTPRequest.blank('/manage', version="2.70")
|
||||||
|
context = req.environ['manila.context']
|
||||||
|
share_network = db_utils.create_share_network()
|
||||||
|
body = {'share_server': self._setup_manage_test_request_body()}
|
||||||
|
share_net_subnets = [
|
||||||
|
db_utils.create_share_network_subnet(
|
||||||
|
share_network_id=share_network['id']),
|
||||||
|
db_utils.create_share_network_subnet(
|
||||||
|
share_network_id=share_network['id'], id='fake_sns_id_2'),
|
||||||
|
]
|
||||||
|
body['share_server']['share_network_subnet_id'] = (
|
||||||
|
share_net_subnets[0]['id'] if body_contains_subnet else None)
|
||||||
|
|
||||||
|
self.mock_object(
|
||||||
|
db_api, 'share_network_subnet_get_all_with_same_az',
|
||||||
|
mock.Mock(return_value=share_net_subnets))
|
||||||
|
self.mock_object(db_api, 'share_network_subnet_get_default_subnets',
|
||||||
|
mock.Mock(return_value=share_net_subnets))
|
||||||
|
|
||||||
|
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_all_with_same_az.
|
||||||
|
assert_called_once_with(context, share_net_subnets[0]['id']))
|
||||||
|
else:
|
||||||
|
(db_api.share_network_subnet_get_default_subnets
|
||||||
.assert_called_once_with(
|
.assert_called_once_with(
|
||||||
context, body['share_server']['share_network_id']))
|
context, body['share_server']['share_network_id']))
|
||||||
|
|
||||||
@ -442,6 +472,23 @@ class ShareServerControllerTest(test.TestCase):
|
|||||||
|
|
||||||
get_mock.assert_called_once_with(context, 'fake_server_id')
|
get_mock.assert_called_once_with(context, 'fake_server_id')
|
||||||
|
|
||||||
|
def test_unmanage_share_server_multiple_subnets_fail(self):
|
||||||
|
"""Tests unmanaging share servers"""
|
||||||
|
server = self._setup_unmanage_tests(multiple_subnets=True)
|
||||||
|
get_mock = self.mock_object(db_api, 'share_server_get',
|
||||||
|
mock.Mock(return_value=server))
|
||||||
|
req = fakes.HTTPRequest.blank('/unmanage_share_server', version="2.70")
|
||||||
|
context = req.environ['manila.context']
|
||||||
|
body = {'unmanage': {'force': True}}
|
||||||
|
|
||||||
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
|
self.controller.unmanage,
|
||||||
|
req,
|
||||||
|
server['id'],
|
||||||
|
body)
|
||||||
|
|
||||||
|
get_mock.assert_called_once_with(context, server['id'])
|
||||||
|
|
||||||
@ddt.data(constants.STATUS_MANAGING, constants.STATUS_DELETING,
|
@ddt.data(constants.STATUS_MANAGING, constants.STATUS_DELETING,
|
||||||
constants.STATUS_CREATING, constants.STATUS_UNMANAGING)
|
constants.STATUS_CREATING, constants.STATUS_UNMANAGING)
|
||||||
def test_unmanage_share_server_invalid_statuses(self, status):
|
def test_unmanage_share_server_invalid_statuses(self, status):
|
||||||
@ -461,18 +508,24 @@ class ShareServerControllerTest(test.TestCase):
|
|||||||
|
|
||||||
get_mock.assert_called_once_with(context, server['id'])
|
get_mock.assert_called_once_with(context, server['id'])
|
||||||
|
|
||||||
def _setup_unmanage_tests(self, status=constants.STATUS_ACTIVE):
|
def _setup_unmanage_tests(self, status=constants.STATUS_ACTIVE,
|
||||||
server = db_utils.create_share_server(
|
multiple_subnets=False):
|
||||||
id='fake_server_id', status=status)
|
|
||||||
share_network = db_utils.create_share_network()
|
share_network = db_utils.create_share_network()
|
||||||
network_subnet = db_utils.create_share_network_subnet(
|
network_subnets = [db_utils.create_share_network_subnet(
|
||||||
share_network_id=share_network['id'])
|
id='fake_sns_id', share_network_id=share_network['id'])]
|
||||||
|
if multiple_subnets:
|
||||||
|
share_network1 = db_utils.create_share_network()
|
||||||
|
network_subnets.append(db_utils.create_share_network_subnet(
|
||||||
|
share_network_id=share_network1['id'], id='fake_sns_id_2'))
|
||||||
|
server = db_utils.create_share_server(
|
||||||
|
id='fake_server_id', status=status,
|
||||||
|
share_network_subnets=network_subnets)
|
||||||
self.mock_object(db_api, 'share_server_get',
|
self.mock_object(db_api, 'share_server_get',
|
||||||
mock.Mock(return_value=server))
|
mock.Mock(return_value=server))
|
||||||
self.mock_object(db_api, 'share_network_get',
|
self.mock_object(db_api, 'share_network_get',
|
||||||
mock.Mock(return_value=share_network))
|
mock.Mock(return_value=share_network))
|
||||||
self.mock_object(db_api, 'share_network_subnet_get',
|
self.mock_object(db_api, 'share_network_subnet_get',
|
||||||
mock.Mock(return_value=network_subnet))
|
mock.Mock(return_value=network_subnets))
|
||||||
return server
|
return server
|
||||||
|
|
||||||
@ddt.data(exception.ShareServerInUse, exception.PolicyNotAuthorized)
|
@ddt.data(exception.ShareServerInUse, exception.PolicyNotAuthorized)
|
||||||
@ -505,13 +558,11 @@ class ShareServerControllerTest(test.TestCase):
|
|||||||
'/v2/share-servers/fake_server_id/', version="2.63")
|
'/v2/share-servers/fake_server_id/', version="2.63")
|
||||||
context = req.environ['manila.context']
|
context = req.environ['manila.context']
|
||||||
share_server = db_utils.create_share_server()
|
share_server = db_utils.create_share_server()
|
||||||
network_subnet = db_utils.create_share_network_subnet()
|
network_subnets = [db_utils.create_share_network_subnet()]
|
||||||
|
share_server['share_network_subnets'] = network_subnets
|
||||||
share_network = db_utils.create_share_network()
|
share_network = db_utils.create_share_network()
|
||||||
get_mock = self.mock_object(
|
get_mock = self.mock_object(
|
||||||
db_api, 'share_server_get', mock.Mock(return_value=share_server))
|
db_api, 'share_server_get', mock.Mock(return_value=share_server))
|
||||||
get_subnet_mock = self.mock_object(
|
|
||||||
db_api, 'share_network_subnet_get',
|
|
||||||
mock.Mock(return_value=network_subnet))
|
|
||||||
get_network_mock = self.mock_object(
|
get_network_mock = self.mock_object(
|
||||||
db_api, 'share_network_get',
|
db_api, 'share_network_get',
|
||||||
mock.Mock(return_value=share_network))
|
mock.Mock(return_value=share_network))
|
||||||
@ -526,10 +577,9 @@ class ShareServerControllerTest(test.TestCase):
|
|||||||
'fake_server_id',
|
'fake_server_id',
|
||||||
body)
|
body)
|
||||||
get_mock.assert_called_once_with(context, 'fake_server_id')
|
get_mock.assert_called_once_with(context, 'fake_server_id')
|
||||||
get_subnet_mock.assert_called_once_with(
|
|
||||||
context, share_server.get('share_network_subnet_id'))
|
|
||||||
get_network_mock.assert_called_once_with(
|
get_network_mock.assert_called_once_with(
|
||||||
context, network_subnet['share_network_id'])
|
context,
|
||||||
|
share_server['share_network_subnets'][0]['share_network_id'])
|
||||||
is_active_mock.assert_called_once_with(share_network)
|
is_active_mock.assert_called_once_with(share_network)
|
||||||
|
|
||||||
def _get_server_migration_request(self, server_id, version='2.57'):
|
def _get_server_migration_request(self, server_id, version='2.57'):
|
||||||
@ -589,11 +639,12 @@ class ShareServerControllerTest(test.TestCase):
|
|||||||
def test__share_server_migration_start_conflict(self, api_exception,
|
def test__share_server_migration_start_conflict(self, api_exception,
|
||||||
expected_exception):
|
expected_exception):
|
||||||
share_network = db_utils.create_share_network()
|
share_network = db_utils.create_share_network()
|
||||||
share_network_subnet = db_utils.create_share_network_subnet(
|
share_network_subnet = [db_utils.create_share_network_subnet(
|
||||||
share_network_id=share_network['id'])
|
share_network_id=share_network['id'])]
|
||||||
server = db_utils.create_share_server(
|
server = db_utils.create_share_server(
|
||||||
id='fake_server_id', status=constants.STATUS_ACTIVE,
|
id='fake_server_id', status=constants.STATUS_ACTIVE,
|
||||||
share_network_subnet_id=share_network_subnet['id'])
|
share_network_subnet_id=share_network_subnet[0]['id'])
|
||||||
|
server['share_network_subnets'] = share_network_subnet
|
||||||
req = self._get_server_migration_request(server['id'])
|
req = self._get_server_migration_request(server['id'])
|
||||||
context = req.environ['manila.context']
|
context = req.environ['manila.context']
|
||||||
body = {
|
body = {
|
||||||
|
@ -715,6 +715,8 @@ class ShareAPITest(test.TestCase):
|
|||||||
"share_network_id": "fakenetid"
|
"share_network_id": "fakenetid"
|
||||||
}
|
}
|
||||||
fake_network = {'id': 'fakenetid'}
|
fake_network = {'id': 'fakenetid'}
|
||||||
|
share_net_subnets = [db_utils.create_share_network_subnet(
|
||||||
|
id='fake_subnet_id', share_network_id=fake_network['id'])]
|
||||||
create_mock = mock.Mock(return_value=stubs.stub_share('1',
|
create_mock = mock.Mock(return_value=stubs.stub_share('1',
|
||||||
display_name=shr['name'],
|
display_name=shr['name'],
|
||||||
display_description=shr['description'],
|
display_description=shr['description'],
|
||||||
@ -728,7 +730,8 @@ class ShareAPITest(test.TestCase):
|
|||||||
self.mock_object(common, 'check_share_network_is_active',
|
self.mock_object(common, 'check_share_network_is_active',
|
||||||
mock.Mock(return_value=True))
|
mock.Mock(return_value=True))
|
||||||
self.mock_object(
|
self.mock_object(
|
||||||
db, 'share_network_subnet_get_by_availability_zone_id')
|
db, 'share_network_subnets_get_all_by_availability_zone_id',
|
||||||
|
mock.Mock(return_value=share_net_subnets))
|
||||||
|
|
||||||
body = {"share": copy.deepcopy(shr)}
|
body = {"share": copy.deepcopy(shr)}
|
||||||
req = fakes.HTTPRequest.blank('/v2/fake/shares', version='2.7')
|
req = fakes.HTTPRequest.blank('/v2/fake/shares', version='2.7')
|
||||||
@ -1342,6 +1345,8 @@ class ShareAPITest(test.TestCase):
|
|||||||
}
|
}
|
||||||
parent_share_net = 444
|
parent_share_net = 444
|
||||||
fake_network = {'id': parent_share_net}
|
fake_network = {'id': parent_share_net}
|
||||||
|
share_net_subnets = [db_utils.create_share_network_subnet(
|
||||||
|
id='fake_subnet_id', share_network_id=fake_network['id'])]
|
||||||
create_mock = mock.Mock(return_value=stubs.stub_share('1',
|
create_mock = mock.Mock(return_value=stubs.stub_share('1',
|
||||||
display_name=shr['name'],
|
display_name=shr['name'],
|
||||||
display_description=shr['description'],
|
display_description=shr['description'],
|
||||||
@ -1364,7 +1369,8 @@ class ShareAPITest(test.TestCase):
|
|||||||
self.mock_object(share_api.API, 'get_share_network', mock.Mock(
|
self.mock_object(share_api.API, 'get_share_network', mock.Mock(
|
||||||
return_value=fake_network))
|
return_value=fake_network))
|
||||||
self.mock_object(
|
self.mock_object(
|
||||||
db, 'share_network_subnet_get_by_availability_zone_id')
|
db, 'share_network_subnets_get_all_by_availability_zone_id',
|
||||||
|
mock.Mock(return_value=share_net_subnets))
|
||||||
|
|
||||||
body = {"share": copy.deepcopy(shr)}
|
body = {"share": copy.deepcopy(shr)}
|
||||||
req = fakes.HTTPRequest.blank('/v2/fake/shares', version='2.7')
|
req = fakes.HTTPRequest.blank('/v2/fake/shares', version='2.7')
|
||||||
@ -1391,6 +1397,8 @@ class ShareAPITest(test.TestCase):
|
|||||||
"snapshot_id": 333,
|
"snapshot_id": 333,
|
||||||
"share_network_id": parent_share_net,
|
"share_network_id": parent_share_net,
|
||||||
}
|
}
|
||||||
|
share_net_subnets = [db_utils.create_share_network_subnet(
|
||||||
|
id='fake_subnet_id', share_network_id=parent_share_net)]
|
||||||
create_mock = mock.Mock(return_value=stubs.stub_share('1',
|
create_mock = mock.Mock(return_value=stubs.stub_share('1',
|
||||||
display_name=shr['name'],
|
display_name=shr['name'],
|
||||||
display_description=shr['description'],
|
display_description=shr['description'],
|
||||||
@ -1413,7 +1421,8 @@ class ShareAPITest(test.TestCase):
|
|||||||
self.mock_object(common, 'check_share_network_is_active',
|
self.mock_object(common, 'check_share_network_is_active',
|
||||||
mock.Mock(return_value=True))
|
mock.Mock(return_value=True))
|
||||||
self.mock_object(
|
self.mock_object(
|
||||||
db, 'share_network_subnet_get_by_availability_zone_id')
|
db, 'share_network_subnets_get_all_by_availability_zone_id',
|
||||||
|
mock.Mock(return_value=share_net_subnets))
|
||||||
|
|
||||||
body = {"share": copy.deepcopy(shr)}
|
body = {"share": copy.deepcopy(shr)}
|
||||||
req = fakes.HTTPRequest.blank('/v2/fake/shares', version='2.7')
|
req = fakes.HTTPRequest.blank('/v2/fake/shares', version='2.7')
|
||||||
|
@ -65,6 +65,9 @@ class ViewBuilderTestCase(test.TestCase):
|
|||||||
status_and_sec_serv_update = (
|
status_and_sec_serv_update = (
|
||||||
api_version.APIVersionRequest(microversion) >=
|
api_version.APIVersionRequest(microversion) >=
|
||||||
api_version.APIVersionRequest('2.63'))
|
api_version.APIVersionRequest('2.63'))
|
||||||
|
network_allocation_update_support = (
|
||||||
|
api_version.APIVersionRequest(microversion) >=
|
||||||
|
api_version.APIVersionRequest('2.69'))
|
||||||
req = fakes.HTTPRequest.blank('/share-networks', version=microversion)
|
req = fakes.HTTPRequest.blank('/share-networks', version=microversion)
|
||||||
expected_keys = {
|
expected_keys = {
|
||||||
'id', 'name', 'project_id', 'created_at', 'updated_at',
|
'id', 'name', 'project_id', 'created_at', 'updated_at',
|
||||||
@ -85,6 +88,8 @@ class ViewBuilderTestCase(test.TestCase):
|
|||||||
expected_keys.add('nova_net_id')
|
expected_keys.add('nova_net_id')
|
||||||
if status_and_sec_serv_update:
|
if status_and_sec_serv_update:
|
||||||
expected_keys.update({'status', 'security_service_update_support'})
|
expected_keys.update({'status', 'security_service_update_support'})
|
||||||
|
if network_allocation_update_support:
|
||||||
|
expected_keys.add('network_allocation_update_support')
|
||||||
|
|
||||||
result = self.builder.build_share_network(req, share_network_data)
|
result = self.builder.build_share_network(req, share_network_data)
|
||||||
self.assertEqual(1, len(result))
|
self.assertEqual(1, len(result))
|
||||||
@ -137,6 +142,10 @@ class ViewBuilderTestCase(test.TestCase):
|
|||||||
status_and_sec_serv_update = (
|
status_and_sec_serv_update = (
|
||||||
api_version.APIVersionRequest(microversion) >=
|
api_version.APIVersionRequest(microversion) >=
|
||||||
api_version.APIVersionRequest('2.63'))
|
api_version.APIVersionRequest('2.63'))
|
||||||
|
network_allocation_update_support = (
|
||||||
|
api_version.APIVersionRequest(microversion) >=
|
||||||
|
api_version.APIVersionRequest('2.69'))
|
||||||
|
|
||||||
req = fakes.HTTPRequest.blank('/share-networks', version=microversion)
|
req = fakes.HTTPRequest.blank('/share-networks', version=microversion)
|
||||||
expected_networks_list = []
|
expected_networks_list = []
|
||||||
for share_network in share_networks:
|
for share_network in share_networks:
|
||||||
@ -181,7 +190,13 @@ class ViewBuilderTestCase(test.TestCase):
|
|||||||
expected_data.update(
|
expected_data.update(
|
||||||
{'status': 'active',
|
{'status': 'active',
|
||||||
'security_service_update_support': False})
|
'security_service_update_support': False})
|
||||||
|
if network_allocation_update_support:
|
||||||
|
share_network.update(
|
||||||
|
{'network_allocation_update_support': None})
|
||||||
|
expected_data.update(
|
||||||
|
{'network_allocation_update_support': None})
|
||||||
expected_networks_list.append(expected_data)
|
expected_networks_list.append(expected_data)
|
||||||
|
|
||||||
expected = {'share_networks': expected_networks_list}
|
expected = {'share_networks': expected_networks_list}
|
||||||
|
|
||||||
result = self.builder.build_share_networks(req, share_networks,
|
result = self.builder.build_share_networks(req, share_networks,
|
||||||
@ -248,3 +263,20 @@ class ViewBuilderTestCase(test.TestCase):
|
|||||||
hosts_result)
|
hosts_result)
|
||||||
|
|
||||||
self.assertEqual(expected, result)
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
@ddt.data(True, False)
|
||||||
|
def test_build_share_network_subnet_create_check(self, is_admin):
|
||||||
|
req = fakes.HTTPRequest.blank('/share-networks',
|
||||||
|
use_admin_context=is_admin)
|
||||||
|
hosts_result = {
|
||||||
|
'compatible': True,
|
||||||
|
'hosts_check_result': {'hostA': True}
|
||||||
|
}
|
||||||
|
expected = {'compatible': True}
|
||||||
|
if is_admin:
|
||||||
|
expected['hosts_check_result'] = hosts_result['hosts_check_result']
|
||||||
|
|
||||||
|
result = self.builder.build_share_network_subnet_create_check(
|
||||||
|
req, hosts_result)
|
||||||
|
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
@ -446,26 +446,28 @@ class ManilaCmdManageTestCase(test.TestCase):
|
|||||||
share_servers = 'server_id_a,server_id_b'
|
share_servers = 'server_id_a,server_id_b'
|
||||||
share_server_list = [server.strip()
|
share_server_list = [server.strip()
|
||||||
for server in share_servers.split(",")]
|
for server in share_servers.split(",")]
|
||||||
capability = 'security_service_update_support'
|
capabilities = "security_service_update_support" \
|
||||||
values_to_update = {
|
",network_allocation_update_support"
|
||||||
capability: True
|
capabilities_list = capabilities.split(",")
|
||||||
}
|
values_to_update = [
|
||||||
|
{capabilities_list[0]: True,
|
||||||
|
capabilities_list[1]: True}]
|
||||||
|
|
||||||
with mock.patch('sys.stdout', new=io.StringIO()) as output:
|
with mock.patch('sys.stdout', new=io.StringIO()) as output:
|
||||||
self.server_cmds.update_share_server_capabilities(
|
self.server_cmds.update_share_server_capabilities(
|
||||||
share_servers, capability, True)
|
share_servers, capabilities, True)
|
||||||
|
|
||||||
expected_op = ("The capability(ies) %(cap)s of the following share "
|
expected_op = ("The capability(ies) %(cap)s of the following share "
|
||||||
"server(s) %(servers)s was(were) updated to "
|
"server(s) %(servers)s was(were) updated to "
|
||||||
"%(value)s.") % {
|
"%(value)s.") % {
|
||||||
'cap': [capability],
|
'cap': capabilities_list,
|
||||||
'servers': share_server_list,
|
'servers': share_server_list,
|
||||||
'value': True,
|
'value': True,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.assertEqual(expected_op, output.getvalue().strip())
|
self.assertEqual(expected_op, output.getvalue().strip())
|
||||||
db.share_servers_update.assert_called_once_with(
|
db.share_servers_update.assert_called_once_with(
|
||||||
'admin_ctxt', share_server_list, values_to_update)
|
'admin_ctxt', share_server_list, values_to_update[0])
|
||||||
|
|
||||||
def test_share_server_update_capability_not_supported(self):
|
def test_share_server_update_capability_not_supported(self):
|
||||||
share_servers = 'server_id_a'
|
share_servers = 'server_id_a'
|
||||||
|
@ -3084,3 +3084,94 @@ class ShareIsSoftDeleted(BaseMigrationChecks):
|
|||||||
self.test_case.assertFalse(hasattr(s, 'is_soft_deleted'))
|
self.test_case.assertFalse(hasattr(s, 'is_soft_deleted'))
|
||||||
self.test_case.assertFalse(hasattr(s,
|
self.test_case.assertFalse(hasattr(s,
|
||||||
'scheduled_to_be_deleted_at'))
|
'scheduled_to_be_deleted_at'))
|
||||||
|
|
||||||
|
|
||||||
|
@map_to_migration('a87e0fb17dee')
|
||||||
|
class ShareServerMultipleSubnets(BaseMigrationChecks):
|
||||||
|
|
||||||
|
def setup_upgrade_data(self, engine):
|
||||||
|
user_id = 'user_id_multiple_subnets'
|
||||||
|
project_id = 'project_id_multiple_subnets'
|
||||||
|
|
||||||
|
# Create share network
|
||||||
|
share_network_data = {
|
||||||
|
'id': uuidutils.generate_uuid(),
|
||||||
|
'user_id': user_id,
|
||||||
|
'project_id': project_id,
|
||||||
|
}
|
||||||
|
sn_table = utils.load_table('share_networks', engine)
|
||||||
|
engine.execute(sn_table.insert(share_network_data))
|
||||||
|
|
||||||
|
# Create share network subnets
|
||||||
|
share_network_subnet_data = {
|
||||||
|
'id': uuidutils.generate_uuid(),
|
||||||
|
'share_network_id': share_network_data['id']
|
||||||
|
}
|
||||||
|
sns_table = utils.load_table('share_network_subnets', engine)
|
||||||
|
engine.execute(sns_table.insert(share_network_subnet_data))
|
||||||
|
|
||||||
|
# Create share server
|
||||||
|
share_server_data = {
|
||||||
|
'id': uuidutils.generate_uuid(),
|
||||||
|
'host': 'fake_host',
|
||||||
|
'status': 'active',
|
||||||
|
'share_network_subnet_id': share_network_subnet_data['id'],
|
||||||
|
}
|
||||||
|
ss_table = utils.load_table('share_servers', engine)
|
||||||
|
engine.execute(ss_table.insert(share_server_data))
|
||||||
|
|
||||||
|
def check_upgrade(self, engine, data):
|
||||||
|
ss_sns_map_table = utils.load_table(
|
||||||
|
'share_server_share_network_subnet_mappings', engine)
|
||||||
|
ss_table = utils.load_table('share_servers', engine)
|
||||||
|
sns_table = utils.load_table('share_network_subnets', engine)
|
||||||
|
na_table = utils.load_table('network_allocations', engine)
|
||||||
|
|
||||||
|
na_record = engine.execute(na_table.select()).first()
|
||||||
|
self.test_case.assertFalse(na_record is None)
|
||||||
|
self.test_case.assertTrue(
|
||||||
|
hasattr(na_record, 'share_network_subnet_id'))
|
||||||
|
|
||||||
|
for map_record in engine.execute(ss_sns_map_table.select()):
|
||||||
|
self.test_case.assertTrue(
|
||||||
|
hasattr(map_record, 'share_network_subnet_id'))
|
||||||
|
self.test_case.assertTrue(
|
||||||
|
hasattr(map_record, 'share_server_id'))
|
||||||
|
|
||||||
|
ss_record = engine.execute(
|
||||||
|
ss_table
|
||||||
|
.select()
|
||||||
|
.where(ss_table.c.id == map_record['share_server_id'])
|
||||||
|
).first()
|
||||||
|
self.test_case.assertFalse(ss_record is None)
|
||||||
|
self.test_case.assertFalse(
|
||||||
|
hasattr(ss_record, 'share_network_subnet_id'))
|
||||||
|
self.test_case.assertTrue(
|
||||||
|
hasattr(ss_record, 'network_allocation_update_support'))
|
||||||
|
|
||||||
|
sns_record = engine.execute(
|
||||||
|
sns_table
|
||||||
|
.select()
|
||||||
|
.where(sns_table.c.id == map_record['share_network_subnet_id'])
|
||||||
|
).first()
|
||||||
|
self.test_case.assertFalse(sns_record is None)
|
||||||
|
|
||||||
|
def check_downgrade(self, engine):
|
||||||
|
ss_table = utils.load_table('share_servers', engine)
|
||||||
|
na_table = utils.load_table('network_allocations', engine)
|
||||||
|
self.test_case.assertRaises(
|
||||||
|
sa_exc.NoSuchTableError, utils.load_table,
|
||||||
|
'share_server_share_network_subnet_mappings', engine)
|
||||||
|
|
||||||
|
for ss_record in engine.execute(ss_table.select()):
|
||||||
|
self.test_case.assertTrue(
|
||||||
|
hasattr(ss_record, 'share_network_subnet_id'))
|
||||||
|
self.test_case.assertFalse(
|
||||||
|
hasattr(ss_record, 'network_allocation_update_support'))
|
||||||
|
|
||||||
|
na_record = engine.execute(
|
||||||
|
na_table
|
||||||
|
.select()
|
||||||
|
).first()
|
||||||
|
self.test_case.assertFalse(
|
||||||
|
hasattr(na_record, 'share_network_subnet_id'))
|
||||||
|
@ -366,8 +366,7 @@ class ShareDatabaseAPITestCase(test.TestCase):
|
|||||||
|
|
||||||
def test_share_filter_all_by_share_server(self):
|
def test_share_filter_all_by_share_server(self):
|
||||||
share_network = db_utils.create_share_network()
|
share_network = db_utils.create_share_network()
|
||||||
share_server = db_utils.create_share_server(
|
share_server = db_utils.create_share_server()
|
||||||
share_network_id=share_network['id'])
|
|
||||||
share = db_utils.create_share(share_server_id=share_server['id'],
|
share = db_utils.create_share(share_server_id=share_server['id'],
|
||||||
share_network_id=share_network['id'])
|
share_network_id=share_network['id'])
|
||||||
|
|
||||||
@ -379,8 +378,7 @@ class ShareDatabaseAPITestCase(test.TestCase):
|
|||||||
|
|
||||||
def test_share_in_recycle_bin_filter_all_by_share_server(self):
|
def test_share_in_recycle_bin_filter_all_by_share_server(self):
|
||||||
share_network = db_utils.create_share_network()
|
share_network = db_utils.create_share_network()
|
||||||
share_server = db_utils.create_share_server(
|
share_server = db_utils.create_share_server()
|
||||||
share_network_id=share_network['id'])
|
|
||||||
share = db_utils.create_share(share_server_id=share_server['id'],
|
share = db_utils.create_share(share_server_id=share_server['id'],
|
||||||
share_network_id=share_network['id'],
|
share_network_id=share_network['id'],
|
||||||
is_soft_deleted=True)
|
is_soft_deleted=True)
|
||||||
@ -393,8 +391,7 @@ class ShareDatabaseAPITestCase(test.TestCase):
|
|||||||
|
|
||||||
def test_share_in_recycle_bin_filter_all_by_share_network(self):
|
def test_share_in_recycle_bin_filter_all_by_share_network(self):
|
||||||
share_network = db_utils.create_share_network()
|
share_network = db_utils.create_share_network()
|
||||||
share_server = db_utils.create_share_server(
|
share_server = db_utils.create_share_server()
|
||||||
share_network_id=share_network['id'])
|
|
||||||
share = db_utils.create_share(share_server_id=share_server['id'],
|
share = db_utils.create_share(share_server_id=share_server['id'],
|
||||||
share_network_id=share_network['id'],
|
share_network_id=share_network['id'],
|
||||||
is_soft_deleted=True)
|
is_soft_deleted=True)
|
||||||
@ -798,7 +795,7 @@ class ShareDatabaseAPITestCase(test.TestCase):
|
|||||||
db_utils.create_share_replica(share_id=share_2['id'])
|
db_utils.create_share_replica(share_id=share_2['id'])
|
||||||
expected_ss_keys = {
|
expected_ss_keys = {
|
||||||
'backend_details', 'host', 'id',
|
'backend_details', 'host', 'id',
|
||||||
'share_network_subnet_id', 'status',
|
'share_network_subnet_ids', 'status',
|
||||||
}
|
}
|
||||||
expected_share_keys = {
|
expected_share_keys = {
|
||||||
'project_id', 'share_type_id', 'display_name',
|
'project_id', 'share_type_id', 'display_name',
|
||||||
@ -846,7 +843,7 @@ class ShareDatabaseAPITestCase(test.TestCase):
|
|||||||
share_server_id=share_server['id'])
|
share_server_id=share_server['id'])
|
||||||
expected_ss_keys = {
|
expected_ss_keys = {
|
||||||
'backend_details', 'host', 'id',
|
'backend_details', 'host', 'id',
|
||||||
'share_network_subnet_id', 'status',
|
'share_network_subnet_ids', 'status',
|
||||||
}
|
}
|
||||||
expected_share_keys = {
|
expected_share_keys = {
|
||||||
'project_id', 'share_type_id', 'display_name',
|
'project_id', 'share_type_id', 'display_name',
|
||||||
@ -911,7 +908,7 @@ class ShareDatabaseAPITestCase(test.TestCase):
|
|||||||
session = db_api.get_session()
|
session = db_api.get_session()
|
||||||
expected_ss_keys = {
|
expected_ss_keys = {
|
||||||
'backend_details', 'host', 'id',
|
'backend_details', 'host', 'id',
|
||||||
'share_network_subnet_id', 'status',
|
'share_network_subnet_ids', 'status',
|
||||||
}
|
}
|
||||||
expected_share_keys = {
|
expected_share_keys = {
|
||||||
'project_id', 'share_type_id', 'display_name',
|
'project_id', 'share_type_id', 'display_name',
|
||||||
@ -999,7 +996,7 @@ class ShareDatabaseAPITestCase(test.TestCase):
|
|||||||
)
|
)
|
||||||
expected_extra_keys = {
|
expected_extra_keys = {
|
||||||
'backend_details', 'host', 'id',
|
'backend_details', 'host', 'id',
|
||||||
'share_network_subnet_id', 'status',
|
'share_network_subnet_ids', 'status',
|
||||||
}
|
}
|
||||||
with session.begin():
|
with session.begin():
|
||||||
share_replica = db_api.share_replica_get(
|
share_replica = db_api.share_replica_get(
|
||||||
@ -2866,11 +2863,12 @@ class ShareNetworkSubnetDatabaseAPITestCase(BaseDatabaseAPITestCase):
|
|||||||
{'id': 'fake_id_3', 'identifier': 'fake_identifier',
|
{'id': 'fake_id_3', 'identifier': 'fake_identifier',
|
||||||
'host': 'fake_host'}])
|
'host': 'fake_host'}])
|
||||||
def test_get_with_share_servers(self, share_servers):
|
def test_get_with_share_servers(self, share_servers):
|
||||||
db_api.share_network_subnet_create(self.fake_context,
|
share_net_subnets = [
|
||||||
self.subnet_dict)
|
db_api.share_network_subnet_create(
|
||||||
|
self.fake_context, self.subnet_dict)]
|
||||||
|
|
||||||
for share_server in share_servers:
|
for share_server in share_servers:
|
||||||
share_server['share_network_subnet_id'] = self.subnet_dict['id']
|
share_server['share_network_subnets'] = share_net_subnets
|
||||||
db_api.share_server_create(self.fake_context, share_server)
|
db_api.share_server_create(self.fake_context, share_server)
|
||||||
|
|
||||||
result = db_api.share_network_subnet_get(self.fake_context,
|
result = db_api.share_network_subnet_get(self.fake_context,
|
||||||
@ -2880,8 +2878,11 @@ class ShareNetworkSubnetDatabaseAPITestCase(BaseDatabaseAPITestCase):
|
|||||||
len(result['share_servers']))
|
len(result['share_servers']))
|
||||||
|
|
||||||
for index, share_server in enumerate(share_servers):
|
for index, share_server in enumerate(share_servers):
|
||||||
self._check_fields(expected=share_server,
|
result = db_api.share_network_subnet_get_all_by_share_server_id(
|
||||||
actual=result['share_servers'][index])
|
self.fake_context, share_server['id'])
|
||||||
|
for key, value in share_server['share_network_subnets'][0].items():
|
||||||
|
if key != 'share_servers':
|
||||||
|
self.assertEqual(value, result[0][key])
|
||||||
|
|
||||||
def test_get_not_found(self):
|
def test_get_not_found(self):
|
||||||
db_api.share_network_subnet_create(self.fake_context, self.subnet_dict)
|
db_api.share_network_subnet_create(self.fake_context, self.subnet_dict)
|
||||||
@ -2967,18 +2968,43 @@ class ShareNetworkSubnetDatabaseAPITestCase(BaseDatabaseAPITestCase):
|
|||||||
self.subnet_dict['availability_zone_id'] = az['id']
|
self.subnet_dict['availability_zone_id'] = az['id']
|
||||||
db_api.share_network_subnet_create(self.fake_context, self.subnet_dict)
|
db_api.share_network_subnet_create(self.fake_context, self.subnet_dict)
|
||||||
|
|
||||||
result = db_api.share_network_subnet_get_by_availability_zone_id(
|
result = db_api.share_network_subnets_get_all_by_availability_zone_id(
|
||||||
self.fake_context, self.subnet_dict['share_network_id'], az['id'])
|
self.fake_context, self.subnet_dict['share_network_id'], az['id'])
|
||||||
|
|
||||||
self._check_fields(expected=self.subnet_dict, actual=result)
|
self._check_fields(expected=self.subnet_dict, actual=result[0])
|
||||||
|
|
||||||
|
def test_get_az_subnets(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_all_with_same_az(
|
||||||
|
self.fake_context, self.subnet_dict['id'])
|
||||||
|
|
||||||
|
self.subnet_dict['share_network'] = None
|
||||||
|
|
||||||
|
self._check_fields(expected=self.subnet_dict, actual=result[0])
|
||||||
|
|
||||||
|
def test_get_az_subnets_not_found(self):
|
||||||
|
self.assertRaises(
|
||||||
|
exception.ShareNetworkSubnetNotFound,
|
||||||
|
db_api.share_network_subnet_get_all_with_same_az,
|
||||||
|
self.fake_context, 'share_network_subnet_id')
|
||||||
|
|
||||||
def test_get_default_subnet(self):
|
def test_get_default_subnet(self):
|
||||||
db_api.share_network_subnet_create(self.fake_context, self.subnet_dict)
|
db_api.share_network_subnet_create(self.fake_context, self.subnet_dict)
|
||||||
|
|
||||||
result = db_api.share_network_subnet_get_default_subnet(
|
result = db_api.share_network_subnet_get_default_subnets(
|
||||||
self.fake_context, self.subnet_dict['share_network_id'])
|
self.fake_context, self.subnet_dict['share_network_id'])
|
||||||
|
|
||||||
self._check_fields(expected=self.subnet_dict, actual=result)
|
self._check_fields(expected=self.subnet_dict, actual=result[0])
|
||||||
|
|
||||||
|
def test_get_by_share_server_id_not_found(self):
|
||||||
|
self.assertRaises(
|
||||||
|
exception.ShareNetworkSubnetNotFoundByShareServer,
|
||||||
|
db_api.share_network_subnet_get_all_by_share_server_id,
|
||||||
|
self.fake_context, 'share_server_id')
|
||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
@ -3144,13 +3170,21 @@ class ShareServerDatabaseAPITestCase(test.TestCase):
|
|||||||
self.ctxt = context.RequestContext(user_id='user_id',
|
self.ctxt = context.RequestContext(user_id='user_id',
|
||||||
project_id='project_id',
|
project_id='project_id',
|
||||||
is_admin=True)
|
is_admin=True)
|
||||||
|
self.share_net_subnets = [
|
||||||
|
db_utils.create_share_network_subnet(
|
||||||
|
id=uuidutils.generate_uuid(),
|
||||||
|
share_network_id=uuidutils.generate_uuid())]
|
||||||
|
|
||||||
def test_share_server_get(self):
|
def test_share_server_get(self):
|
||||||
expected = db_utils.create_share_server()
|
expected = db_utils.create_share_server(
|
||||||
|
share_network_subnets=self.share_net_subnets)
|
||||||
server = db_api.share_server_get(self.ctxt, expected['id'])
|
server = db_api.share_server_get(self.ctxt, expected['id'])
|
||||||
self.assertEqual(expected['id'], server['id'])
|
self.assertEqual(expected['id'], server['id'])
|
||||||
self.assertEqual(expected.share_network_subnet_id,
|
self.assertEqual(expected.share_network_subnets[0]['id'],
|
||||||
server.share_network_subnet_id)
|
server.share_network_subnets[0]['id'])
|
||||||
|
self.assertEqual(
|
||||||
|
expected.share_network_subnets[0]['share_network_id'],
|
||||||
|
server.share_network_subnets[0]['share_network_id'])
|
||||||
self.assertEqual(expected.host, server.host)
|
self.assertEqual(expected.host, server.host)
|
||||||
self.assertEqual(expected.status, server.status)
|
self.assertEqual(expected.status, server.status)
|
||||||
|
|
||||||
@ -3160,10 +3194,14 @@ class ShareServerDatabaseAPITestCase(test.TestCase):
|
|||||||
db_api.share_server_get, self.ctxt, fake_id)
|
db_api.share_server_get, self.ctxt, fake_id)
|
||||||
|
|
||||||
def test_create(self):
|
def test_create(self):
|
||||||
server = db_utils.create_share_server()
|
server = db_utils.create_share_server(
|
||||||
|
share_network_subnets=self.share_net_subnets)
|
||||||
self.assertTrue(server['id'])
|
self.assertTrue(server['id'])
|
||||||
self.assertEqual(server.share_network_subnet_id,
|
self.assertEqual(server.share_network_subnets[0]['id'],
|
||||||
server['share_network_subnet_id'])
|
server['share_network_subnets'][0]['id'])
|
||||||
|
self.assertEqual(
|
||||||
|
server.share_network_subnets[0]['share_network_id'],
|
||||||
|
server['share_network_subnets'][0]['share_network_id'])
|
||||||
self.assertEqual(server.host, server['host'])
|
self.assertEqual(server.host, server['host'])
|
||||||
self.assertEqual(server.status, server['status'])
|
self.assertEqual(server.status, server['status'])
|
||||||
|
|
||||||
@ -3181,17 +3219,23 @@ class ShareServerDatabaseAPITestCase(test.TestCase):
|
|||||||
self.ctxt, fake_id)
|
self.ctxt, fake_id)
|
||||||
|
|
||||||
def test_update(self):
|
def test_update(self):
|
||||||
|
share_net_subnets_update = [
|
||||||
|
db_utils.create_share_network_subnet(
|
||||||
|
id=uuidutils.generate_uuid(),
|
||||||
|
share_network_id=uuidutils.generate_uuid())]
|
||||||
update = {
|
update = {
|
||||||
'share_network_id': 'update_net',
|
'share_network_subnets': share_net_subnets_update,
|
||||||
'host': 'update_host',
|
'host': 'update_host',
|
||||||
'status': constants.STATUS_ACTIVE,
|
'status': constants.STATUS_ACTIVE,
|
||||||
}
|
}
|
||||||
server = db_utils.create_share_server()
|
server = db_utils.create_share_server(
|
||||||
|
share_network_subnets=self.share_net_subnets)
|
||||||
updated_server = db_api.share_server_update(self.ctxt, server['id'],
|
updated_server = db_api.share_server_update(self.ctxt, server['id'],
|
||||||
update)
|
update)
|
||||||
self.assertEqual(server['id'], updated_server['id'])
|
self.assertEqual(server['id'], updated_server['id'])
|
||||||
self.assertEqual(update['share_network_id'],
|
self.assertEqual(
|
||||||
updated_server.share_network_id)
|
update['share_network_subnets'][0]['share_network_id'],
|
||||||
|
updated_server.share_network_subnets[0]['share_network_id'])
|
||||||
self.assertEqual(update['host'], updated_server.host)
|
self.assertEqual(update['host'], updated_server.host)
|
||||||
self.assertEqual(update['status'], updated_server.status)
|
self.assertEqual(update['status'], updated_server.status)
|
||||||
|
|
||||||
@ -3201,7 +3245,8 @@ class ShareServerDatabaseAPITestCase(test.TestCase):
|
|||||||
db_api.share_server_update,
|
db_api.share_server_update,
|
||||||
self.ctxt, fake_id, {})
|
self.ctxt, fake_id, {})
|
||||||
|
|
||||||
def test_get_all_by_host_and_share_net_valid(self):
|
@ddt.data(None, constants.STATUS_SERVER_NETWORK_CHANGE)
|
||||||
|
def test_get_all_by_host_and_share_net_valid(self, server_status):
|
||||||
subnet_1 = {
|
subnet_1 = {
|
||||||
'id': '1',
|
'id': '1',
|
||||||
'share_network_id': '1',
|
'share_network_id': '1',
|
||||||
@ -3210,31 +3255,41 @@ class ShareServerDatabaseAPITestCase(test.TestCase):
|
|||||||
'id': '2',
|
'id': '2',
|
||||||
'share_network_id': '2',
|
'share_network_id': '2',
|
||||||
}
|
}
|
||||||
valid = {
|
share_net_subnets1 = db_utils.create_share_network_subnet(**subnet_1)
|
||||||
'share_network_subnet_id': '1',
|
share_net_subnets2 = db_utils.create_share_network_subnet(**subnet_2)
|
||||||
|
valid_no_status = {
|
||||||
|
'share_network_subnets': [share_net_subnets1],
|
||||||
'host': 'host1',
|
'host': 'host1',
|
||||||
'status': constants.STATUS_ACTIVE,
|
'status': constants.STATUS_ACTIVE,
|
||||||
}
|
}
|
||||||
|
valid_with_status = {
|
||||||
|
'share_network_subnets': [share_net_subnets1],
|
||||||
|
'host': 'host1',
|
||||||
|
'status': constants.STATUS_SERVER_NETWORK_CHANGE,
|
||||||
|
}
|
||||||
invalid = {
|
invalid = {
|
||||||
'share_network_subnet_id': '2',
|
'share_network_subnets': [share_net_subnets2],
|
||||||
'host': 'host1',
|
'host': 'host1',
|
||||||
'status': constants.STATUS_ERROR,
|
'status': constants.STATUS_ERROR,
|
||||||
}
|
}
|
||||||
other = {
|
other = {
|
||||||
'share_network_subnet_id': '1',
|
'share_network_subnets': [share_net_subnets1],
|
||||||
'host': 'host2',
|
'host': 'host2',
|
||||||
'status': constants.STATUS_ACTIVE,
|
'status': constants.STATUS_ACTIVE,
|
||||||
}
|
}
|
||||||
db_utils.create_share_network_subnet(**subnet_1)
|
if server_status:
|
||||||
db_utils.create_share_network_subnet(**subnet_2)
|
valid = db_utils.create_share_server(**valid_with_status)
|
||||||
valid = db_utils.create_share_server(**valid)
|
else:
|
||||||
|
valid = db_utils.create_share_server(**valid_no_status)
|
||||||
db_utils.create_share_server(**invalid)
|
db_utils.create_share_server(**invalid)
|
||||||
db_utils.create_share_server(**other)
|
db_utils.create_share_server(**other)
|
||||||
|
|
||||||
servers = db_api.share_server_get_all_by_host_and_share_subnet_valid(
|
servers = db_api.share_server_get_all_by_host_and_share_subnet_valid(
|
||||||
self.ctxt,
|
self.ctxt,
|
||||||
host='host1',
|
host='host1',
|
||||||
share_subnet_id='1')
|
share_subnet_id='1',
|
||||||
|
server_status=server_status)
|
||||||
|
|
||||||
self.assertEqual(valid['id'], servers[0]['id'])
|
self.assertEqual(valid['id'], servers[0]['id'])
|
||||||
|
|
||||||
def test_get_all_by_host_and_share_net_not_found(self):
|
def test_get_all_by_host_and_share_net_not_found(self):
|
||||||
@ -3246,17 +3301,14 @@ class ShareServerDatabaseAPITestCase(test.TestCase):
|
|||||||
|
|
||||||
def test_get_all(self):
|
def test_get_all(self):
|
||||||
srv1 = {
|
srv1 = {
|
||||||
'share_network_id': '1',
|
|
||||||
'host': 'host1',
|
'host': 'host1',
|
||||||
'status': constants.STATUS_ACTIVE,
|
'status': constants.STATUS_ACTIVE,
|
||||||
}
|
}
|
||||||
srv2 = {
|
srv2 = {
|
||||||
'share_network_id': '1',
|
|
||||||
'host': 'host1',
|
'host': 'host1',
|
||||||
'status': constants.STATUS_ERROR,
|
'status': constants.STATUS_ERROR,
|
||||||
}
|
}
|
||||||
srv3 = {
|
srv3 = {
|
||||||
'share_network_id': '2',
|
|
||||||
'host': 'host2',
|
'host': 'host2',
|
||||||
'status': constants.STATUS_ACTIVE,
|
'status': constants.STATUS_ACTIVE,
|
||||||
}
|
}
|
||||||
@ -3296,7 +3348,10 @@ class ShareServerDatabaseAPITestCase(test.TestCase):
|
|||||||
|
|
||||||
def test_get_with_details(self):
|
def test_get_with_details(self):
|
||||||
values = {
|
values = {
|
||||||
'share_network_subnet_id': 'fake-share-net-id',
|
'share_network_subnets': [
|
||||||
|
db_utils.create_share_network_subnet(
|
||||||
|
id='fake_subnet_id',
|
||||||
|
share_network_id='fake_share_net_id')],
|
||||||
'host': 'hostname',
|
'host': 'hostname',
|
||||||
'status': constants.STATUS_ACTIVE,
|
'status': constants.STATUS_ACTIVE,
|
||||||
}
|
}
|
||||||
@ -3308,8 +3363,11 @@ class ShareServerDatabaseAPITestCase(test.TestCase):
|
|||||||
db_api.share_server_backend_details_set(self.ctxt, srv_id, details)
|
db_api.share_server_backend_details_set(self.ctxt, srv_id, details)
|
||||||
server = db_api.share_server_get(self.ctxt, srv_id)
|
server = db_api.share_server_get(self.ctxt, srv_id)
|
||||||
self.assertEqual(srv_id, server['id'])
|
self.assertEqual(srv_id, server['id'])
|
||||||
self.assertEqual(values['share_network_subnet_id'],
|
self.assertEqual(values['share_network_subnets'][0]['id'],
|
||||||
server.share_network_subnet_id)
|
server.share_network_subnets[0]['id'])
|
||||||
|
self.assertEqual(
|
||||||
|
values['share_network_subnets'][0]['share_network_id'],
|
||||||
|
server.share_network_subnets[0]['share_network_id'])
|
||||||
self.assertEqual(values['host'], server.host)
|
self.assertEqual(values['host'], server.host)
|
||||||
self.assertEqual(values['status'], server.status)
|
self.assertEqual(values['status'], server.status)
|
||||||
self.assertDictEqual(server['backend_details'], details)
|
self.assertDictEqual(server['backend_details'], details)
|
||||||
@ -3331,7 +3389,6 @@ class ShareServerDatabaseAPITestCase(test.TestCase):
|
|||||||
def test_share_server_search_by_identifier(self, identifier):
|
def test_share_server_search_by_identifier(self, identifier):
|
||||||
|
|
||||||
server = {
|
server = {
|
||||||
'share_network_id': 'fake-share-net-id',
|
|
||||||
'host': 'hostname',
|
'host': 'hostname',
|
||||||
'status': constants.STATUS_ACTIVE,
|
'status': constants.STATUS_ACTIVE,
|
||||||
'is_auto_deletable': True,
|
'is_auto_deletable': True,
|
||||||
@ -3360,21 +3417,18 @@ class ShareServerDatabaseAPITestCase(test.TestCase):
|
|||||||
server_3_is_auto_deletable,
|
server_3_is_auto_deletable,
|
||||||
expected_len):
|
expected_len):
|
||||||
server1 = {
|
server1 = {
|
||||||
'share_network_id': 'fake-share-net-id',
|
|
||||||
'host': 'hostname',
|
'host': 'hostname',
|
||||||
'status': constants.STATUS_ACTIVE,
|
'status': constants.STATUS_ACTIVE,
|
||||||
'is_auto_deletable': server_1_is_auto_deletable,
|
'is_auto_deletable': server_1_is_auto_deletable,
|
||||||
'updated_at': datetime.datetime(2018, 5, 1)
|
'updated_at': datetime.datetime(2018, 5, 1)
|
||||||
}
|
}
|
||||||
server2 = {
|
server2 = {
|
||||||
'share_network_id': 'fake-share-net-id',
|
|
||||||
'host': 'hostname',
|
'host': 'hostname',
|
||||||
'status': constants.STATUS_ACTIVE,
|
'status': constants.STATUS_ACTIVE,
|
||||||
'is_auto_deletable': server_2_is_auto_deletable,
|
'is_auto_deletable': server_2_is_auto_deletable,
|
||||||
'updated_at': datetime.datetime(2018, 5, 1)
|
'updated_at': datetime.datetime(2018, 5, 1)
|
||||||
}
|
}
|
||||||
server3 = {
|
server3 = {
|
||||||
'share_network_id': 'fake-share-net-id',
|
|
||||||
'host': 'hostname',
|
'host': 'hostname',
|
||||||
'status': constants.STATUS_ACTIVE,
|
'status': constants.STATUS_ACTIVE,
|
||||||
'is_auto_deletable': server_3_is_auto_deletable,
|
'is_auto_deletable': server_3_is_auto_deletable,
|
||||||
@ -3403,7 +3457,7 @@ class ShareServerDatabaseAPITestCase(test.TestCase):
|
|||||||
share_network_subnet = db_utils.create_share_network_subnet(
|
share_network_subnet = db_utils.create_share_network_subnet(
|
||||||
id=uuidutils.generate_uuid(),
|
id=uuidutils.generate_uuid(),
|
||||||
share_network_id=share_network_id)
|
share_network_id=share_network_id)
|
||||||
server_data['share_network_subnet_id'] = share_network_subnet['id']
|
server_data['share_network_subnets'] = [share_network_subnet]
|
||||||
db_utils.create_share_server(**server_data)
|
db_utils.create_share_server(**server_data)
|
||||||
db_utils.create_share_server()
|
db_utils.create_share_server()
|
||||||
filter_keys = filters.keys()
|
filter_keys = filters.keys()
|
||||||
@ -3417,7 +3471,7 @@ class ShareServerDatabaseAPITestCase(test.TestCase):
|
|||||||
self.assertEqual(share_network_subnet['share_network_id'],
|
self.assertEqual(share_network_subnet['share_network_id'],
|
||||||
filters[key])
|
filters[key])
|
||||||
self.assertEqual(share_network_subnet['id'],
|
self.assertEqual(share_network_subnet['id'],
|
||||||
result['share_network_subnet_id'])
|
result['share_network_subnets'][0]['id'])
|
||||||
else:
|
else:
|
||||||
self.assertEqual(result[key], filters[key])
|
self.assertEqual(result[key], filters[key])
|
||||||
|
|
||||||
@ -3534,27 +3588,32 @@ class NetworkAllocationsDatabaseAPITestCase(test.TestCase):
|
|||||||
self.user_id = 'user_id'
|
self.user_id = 'user_id'
|
||||||
self.project_id = 'project_id'
|
self.project_id = 'project_id'
|
||||||
self.share_server_id = 'foo_share_server_id'
|
self.share_server_id = 'foo_share_server_id'
|
||||||
|
self.share_network_subnet_id = 'foo_share_network_subnet_id'
|
||||||
self.ctxt = context.RequestContext(
|
self.ctxt = context.RequestContext(
|
||||||
user_id=self.user_id, project_id=self.project_id, is_admin=True)
|
user_id=self.user_id, project_id=self.project_id, is_admin=True)
|
||||||
self.user_network_allocations = [
|
self.user_network_allocations = [
|
||||||
{'share_server_id': self.share_server_id,
|
{'share_server_id': self.share_server_id,
|
||||||
'ip_address': '1.1.1.1',
|
'ip_address': '1.1.1.1',
|
||||||
'status': constants.STATUS_ACTIVE,
|
'status': constants.STATUS_ACTIVE,
|
||||||
'label': None},
|
'label': None,
|
||||||
|
'share_network_subnet_id': self.share_network_subnet_id},
|
||||||
{'share_server_id': self.share_server_id,
|
{'share_server_id': self.share_server_id,
|
||||||
'ip_address': '2.2.2.2',
|
'ip_address': '2.2.2.2',
|
||||||
'status': constants.STATUS_ACTIVE,
|
'status': constants.STATUS_ACTIVE,
|
||||||
'label': 'user'},
|
'label': 'user',
|
||||||
|
'share_network_subnet_id': self.share_network_subnet_id},
|
||||||
]
|
]
|
||||||
self.admin_network_allocations = [
|
self.admin_network_allocations = [
|
||||||
{'share_server_id': self.share_server_id,
|
{'share_server_id': self.share_server_id,
|
||||||
'ip_address': '3.3.3.3',
|
'ip_address': '3.3.3.3',
|
||||||
'status': constants.STATUS_ACTIVE,
|
'status': constants.STATUS_ACTIVE,
|
||||||
'label': 'admin'},
|
'label': 'admin',
|
||||||
|
'share_network_subnet_id': None},
|
||||||
{'share_server_id': self.share_server_id,
|
{'share_server_id': self.share_server_id,
|
||||||
'ip_address': '4.4.4.4',
|
'ip_address': '4.4.4.4',
|
||||||
'status': constants.STATUS_ACTIVE,
|
'status': constants.STATUS_ACTIVE,
|
||||||
'label': 'admin'},
|
'label': 'admin',
|
||||||
|
'share_network_subnet_id': None},
|
||||||
]
|
]
|
||||||
|
|
||||||
def _setup_network_allocations_get_for_share_server(self):
|
def _setup_network_allocations_get_for_share_server(self):
|
||||||
@ -3566,10 +3625,17 @@ class NetworkAllocationsDatabaseAPITestCase(test.TestCase):
|
|||||||
}
|
}
|
||||||
db_api.share_network_create(self.ctxt, share_network_data)
|
db_api.share_network_create(self.ctxt, share_network_data)
|
||||||
|
|
||||||
|
# Create share network subnet
|
||||||
|
share_network_subnet_data = {
|
||||||
|
'id': self.share_network_subnet_id,
|
||||||
|
'share_network_id': self.user_id,
|
||||||
|
}
|
||||||
|
db_api.share_network_subnet_create(self.ctxt,
|
||||||
|
share_network_subnet_data)
|
||||||
|
|
||||||
# Create share server
|
# Create share server
|
||||||
share_server_data = {
|
share_server_data = {
|
||||||
'id': self.share_server_id,
|
'id': self.share_server_id,
|
||||||
'share_network_id': share_network_data['id'],
|
|
||||||
'host': 'fake_host',
|
'host': 'fake_host',
|
||||||
'status': 'active',
|
'status': 'active',
|
||||||
}
|
}
|
||||||
@ -3644,6 +3710,20 @@ class NetworkAllocationsDatabaseAPITestCase(test.TestCase):
|
|||||||
self.ctxt,
|
self.ctxt,
|
||||||
id='fake')
|
id='fake')
|
||||||
|
|
||||||
|
def test_network_allocation_get_by_subnet_id(self):
|
||||||
|
self._setup_network_allocations_get_for_share_server()
|
||||||
|
|
||||||
|
result = db_api.network_allocations_get_for_share_server(
|
||||||
|
self.ctxt, self.share_server_id,
|
||||||
|
subnet_id=self.share_network_subnet_id)
|
||||||
|
|
||||||
|
self.assertEqual(2, len(result))
|
||||||
|
|
||||||
|
for network_allocation in result:
|
||||||
|
self.assertIsInstance(network_allocation, models.NetworkAllocation)
|
||||||
|
self.assertEqual(self.share_network_subnet_id,
|
||||||
|
network_allocation.share_network_subnet_id)
|
||||||
|
|
||||||
@ddt.data(True, False)
|
@ddt.data(True, False)
|
||||||
def test_network_allocation_get_read_deleted(self, read_deleted):
|
def test_network_allocation_get_read_deleted(self, read_deleted):
|
||||||
self._setup_network_allocations_get_for_share_server()
|
self._setup_network_allocations_get_for_share_server()
|
||||||
@ -3798,8 +3878,7 @@ class PurgeDeletedTest(test.TestCase):
|
|||||||
# create share server
|
# create share server
|
||||||
db_utils.create_share_server(
|
db_utils.create_share_server(
|
||||||
id=uuidutils.generate_uuid(),
|
id=uuidutils.generate_uuid(),
|
||||||
deleted_at=self._days_ago(start, end),
|
deleted_at=self._days_ago(start, end))
|
||||||
share_network_id=network.id)
|
|
||||||
# create snapshot
|
# create snapshot
|
||||||
db_api.share_snapshot_create(
|
db_api.share_snapshot_create(
|
||||||
self.context, {'share_id': share['id'],
|
self.context, {'share_id': share['id'],
|
||||||
@ -4360,6 +4439,9 @@ class ShareResourcesAPITestCase(test.TestCase):
|
|||||||
share_id = uuidutils.generate_uuid()
|
share_id = uuidutils.generate_uuid()
|
||||||
share_network_id = uuidutils.generate_uuid()
|
share_network_id = uuidutils.generate_uuid()
|
||||||
share_network_subnet_id = uuidutils.generate_uuid()
|
share_network_subnet_id = uuidutils.generate_uuid()
|
||||||
|
share_net_subnets = [db_utils.create_share_network_subnet(
|
||||||
|
id=share_network_subnet_id,
|
||||||
|
share_network_id=share_network_id)]
|
||||||
if '@' in current_host:
|
if '@' in current_host:
|
||||||
if '#' in current_host:
|
if '#' in current_host:
|
||||||
new_host = 'new-controller-X@backendX#poolX'
|
new_host = 'new-controller-X@backendX#poolX'
|
||||||
@ -4400,15 +4482,15 @@ class ShareResourcesAPITestCase(test.TestCase):
|
|||||||
status=constants.STATUS_DELETING),
|
status=constants.STATUS_DELETING),
|
||||||
# share servers
|
# share servers
|
||||||
db_utils.create_share_server(
|
db_utils.create_share_server(
|
||||||
share_network_subnet_id=share_network_subnet_id,
|
share_network_subnets=share_net_subnets,
|
||||||
host='controller-0@fancystore01',
|
host='controller-0@fancystore01',
|
||||||
status=constants.STATUS_ACTIVE),
|
status=constants.STATUS_ACTIVE),
|
||||||
db_utils.create_share_server(
|
db_utils.create_share_server(
|
||||||
share_network_subnet_id=share_network_subnet_id,
|
share_network_subnets=share_net_subnets,
|
||||||
host='controller-0@otherstore02#pool100',
|
host='controller-0@otherstore02#pool100',
|
||||||
status=constants.STATUS_ERROR),
|
status=constants.STATUS_ERROR),
|
||||||
db_utils.create_share_server(
|
db_utils.create_share_server(
|
||||||
share_network_subnet_id=share_network_subnet_id,
|
share_network_subnets=share_net_subnets,
|
||||||
host='controller-2@beststore07',
|
host='controller-2@beststore07',
|
||||||
status=constants.STATUS_DELETING),
|
status=constants.STATUS_DELETING),
|
||||||
|
|
||||||
@ -4425,8 +4507,9 @@ class ShareResourcesAPITestCase(test.TestCase):
|
|||||||
self.context, filters={'share_id': share_id})
|
self.context, filters={'share_id': share_id})
|
||||||
share_groups = db_api.share_group_get_all(
|
share_groups = db_api.share_group_get_all(
|
||||||
self.context, filters={'share_network_id': share_network_id})
|
self.context, filters={'share_network_id': share_network_id})
|
||||||
share_servers = db_api._server_get_query(self.context).filter_by(
|
share_servers = db_api._server_get_query(self.context).filter(
|
||||||
share_network_subnet_id=share_network_subnet_id).all()
|
models.ShareServer.share_network_subnets.any(
|
||||||
|
id=share_net_subnets[0]['id'])).all()
|
||||||
self.assertEqual(3, len(share_instances))
|
self.assertEqual(3, len(share_instances))
|
||||||
self.assertEqual(3, len(share_groups))
|
self.assertEqual(3, len(share_groups))
|
||||||
self.assertEqual(3, len(share_servers))
|
self.assertEqual(3, len(share_servers))
|
||||||
@ -4450,6 +4533,9 @@ class ShareResourcesAPITestCase(test.TestCase):
|
|||||||
share_id = uuidutils.generate_uuid()
|
share_id = uuidutils.generate_uuid()
|
||||||
share_network_id = uuidutils.generate_uuid()
|
share_network_id = uuidutils.generate_uuid()
|
||||||
share_network_subnet_id = uuidutils.generate_uuid()
|
share_network_subnet_id = uuidutils.generate_uuid()
|
||||||
|
share_net_subnets = [db_utils.create_share_network_subnet(
|
||||||
|
id=share_network_subnet_id,
|
||||||
|
share_network_id=share_network_id)]
|
||||||
if '@' in current_host:
|
if '@' in current_host:
|
||||||
if '#' in current_host:
|
if '#' in current_host:
|
||||||
new_host = 'new-controller-X@backendX#poolX'
|
new_host = 'new-controller-X@backendX#poolX'
|
||||||
@ -4493,15 +4579,15 @@ class ShareResourcesAPITestCase(test.TestCase):
|
|||||||
status=constants.STATUS_DELETING),
|
status=constants.STATUS_DELETING),
|
||||||
# share servers
|
# share servers
|
||||||
db_utils.create_share_server(
|
db_utils.create_share_server(
|
||||||
share_network_subnet_id=share_network_subnet_id,
|
share_network_subnets=share_net_subnets,
|
||||||
host='controller-0@fancystore01#pool100',
|
host='controller-0@fancystore01#pool100',
|
||||||
status=constants.STATUS_ACTIVE),
|
status=constants.STATUS_ACTIVE),
|
||||||
db_utils.create_share_server(
|
db_utils.create_share_server(
|
||||||
share_network_subnet_id=share_network_subnet_id,
|
share_network_subnets=share_net_subnets,
|
||||||
host='controller-2@fancystore01',
|
host='controller-2@fancystore01',
|
||||||
status=constants.STATUS_ERROR),
|
status=constants.STATUS_ERROR),
|
||||||
db_utils.create_share_server(
|
db_utils.create_share_server(
|
||||||
share_network_subnet_id=share_network_subnet_id,
|
share_network_subnets=share_net_subnets,
|
||||||
host='controller-2@beststore07#pool200',
|
host='controller-2@beststore07#pool200',
|
||||||
status=constants.STATUS_DELETING),
|
status=constants.STATUS_DELETING),
|
||||||
]
|
]
|
||||||
@ -4513,8 +4599,9 @@ class ShareResourcesAPITestCase(test.TestCase):
|
|||||||
self.context, filters={'share_id': share_id})
|
self.context, filters={'share_id': share_id})
|
||||||
share_groups = db_api.share_group_get_all(
|
share_groups = db_api.share_group_get_all(
|
||||||
self.context, filters={'share_network_id': share_network_id})
|
self.context, filters={'share_network_id': share_network_id})
|
||||||
share_servers = db_api._server_get_query(self.context).filter_by(
|
share_servers = db_api._server_get_query(self.context).filter(
|
||||||
share_network_subnet_id=share_network_subnet_id).all()
|
models.ShareServer.share_network_subnets.any(
|
||||||
|
id=share_net_subnets[0]['id'])).all()
|
||||||
|
|
||||||
updated_resources = [
|
updated_resources = [
|
||||||
res for res in share_instances + share_groups + share_servers
|
res for res in share_instances + share_groups + share_servers
|
||||||
|
@ -214,7 +214,6 @@ def create_share_server(**kwargs):
|
|||||||
backend_details = kwargs.pop('backend_details', {})
|
backend_details = kwargs.pop('backend_details', {})
|
||||||
srv = {
|
srv = {
|
||||||
'host': 'host1',
|
'host': 'host1',
|
||||||
'share_network_subnet_id': 'fake_srv_id',
|
|
||||||
'status': constants.STATUS_ACTIVE
|
'status': constants.STATUS_ACTIVE
|
||||||
}
|
}
|
||||||
share_srv = _create_db_row(db.share_server_create, srv, kwargs)
|
share_srv = _create_db_row(db.share_server_create, srv, kwargs)
|
||||||
|
@ -305,7 +305,6 @@ def fake_share_server_get():
|
|||||||
'status': constants.STATUS_ACTIVE,
|
'status': constants.STATUS_ACTIVE,
|
||||||
'updated_at': None,
|
'updated_at': None,
|
||||||
'host': 'fake_host',
|
'host': 'fake_host',
|
||||||
'share_network_subnet_id': 'fake_sn_id',
|
|
||||||
'share_network_name': 'fake_sn_name',
|
'share_network_name': 'fake_sn_name',
|
||||||
'project_id': 'fake_project_id',
|
'project_id': 'fake_project_id',
|
||||||
'id': 'fake_share_server_id',
|
'id': 'fake_share_server_id',
|
||||||
|
@ -122,6 +122,7 @@ fake_network_allocation = {
|
|||||||
'cidr': fake_share_network_subnet['cidr'],
|
'cidr': fake_share_network_subnet['cidr'],
|
||||||
'gateway': fake_share_network_subnet['gateway'],
|
'gateway': fake_share_network_subnet['gateway'],
|
||||||
'mtu': 1509,
|
'mtu': 1509,
|
||||||
|
'share_network_subnet_id': fake_share_network_subnet['id'],
|
||||||
}
|
}
|
||||||
|
|
||||||
fake_nw_info = {
|
fake_nw_info = {
|
||||||
@ -187,6 +188,7 @@ fake_network_allocation_multi = {
|
|||||||
'cidr': fake_neutron_subnet['cidr'],
|
'cidr': fake_neutron_subnet['cidr'],
|
||||||
'gateway': fake_neutron_subnet['gateway_ip'],
|
'gateway': fake_neutron_subnet['gateway_ip'],
|
||||||
'mtu': fake_neutron_network_multi['mtu'],
|
'mtu': fake_neutron_network_multi['mtu'],
|
||||||
|
'share_network_subnet_id': fake_share_network['id'],
|
||||||
}
|
}
|
||||||
|
|
||||||
fake_binding_profile = {
|
fake_binding_profile = {
|
||||||
@ -240,9 +242,11 @@ class NeutronNetworkPluginTest(test.TestCase):
|
|||||||
|
|
||||||
has_provider_nw_ext.assert_any_call()
|
has_provider_nw_ext.assert_any_call()
|
||||||
save_nw_data.assert_called_once_with(self.fake_context,
|
save_nw_data.assert_called_once_with(self.fake_context,
|
||||||
fake_share_network_subnet)
|
fake_share_network_subnet,
|
||||||
|
save_db=True)
|
||||||
save_subnet_data.assert_called_once_with(self.fake_context,
|
save_subnet_data.assert_called_once_with(self.fake_context,
|
||||||
fake_share_network_subnet)
|
fake_share_network_subnet,
|
||||||
|
save_db=True)
|
||||||
self.plugin.neutron_api.create_port.assert_called_once_with(
|
self.plugin.neutron_api.create_port.assert_called_once_with(
|
||||||
fake_share_network['project_id'],
|
fake_share_network['project_id'],
|
||||||
network_id=fake_share_network_subnet['neutron_net_id'],
|
network_id=fake_share_network_subnet['neutron_net_id'],
|
||||||
@ -401,6 +405,7 @@ class NeutronNetworkPluginTest(test.TestCase):
|
|||||||
'ip_version': fake_share_network_subnet['ip_version'],
|
'ip_version': fake_share_network_subnet['ip_version'],
|
||||||
'cidr': fake_share_network_subnet['cidr'],
|
'cidr': fake_share_network_subnet['cidr'],
|
||||||
'mtu': fake_share_network_subnet['mtu'],
|
'mtu': fake_share_network_subnet['mtu'],
|
||||||
|
'share_network_subnet_id': fake_share_network_subnet['id'],
|
||||||
} for x in ['192.168.0.11', '192.168.0.12']]
|
} for x in ['192.168.0.11', '192.168.0.12']]
|
||||||
|
|
||||||
if side_effect:
|
if side_effect:
|
||||||
@ -961,9 +966,11 @@ class NeutronBindNetworkPluginTest(test.TestCase):
|
|||||||
|
|
||||||
self.bind_plugin._has_provider_network_extension.assert_any_call()
|
self.bind_plugin._has_provider_network_extension.assert_any_call()
|
||||||
save_nw_data.assert_called_once_with(self.fake_context,
|
save_nw_data.assert_called_once_with(self.fake_context,
|
||||||
fake_share_network_subnet)
|
fake_share_network_subnet,
|
||||||
|
save_db=True)
|
||||||
save_subnet_data.assert_called_once_with(self.fake_context,
|
save_subnet_data.assert_called_once_with(self.fake_context,
|
||||||
fake_share_network_subnet)
|
fake_share_network_subnet,
|
||||||
|
save_db=True)
|
||||||
expected_kwargs = {
|
expected_kwargs = {
|
||||||
'binding:vnic_type': 'baremetal',
|
'binding:vnic_type': 'baremetal',
|
||||||
'host_id': 'foohost1',
|
'host_id': 'foohost1',
|
||||||
@ -1486,9 +1493,11 @@ class NeutronBindSingleNetworkPluginTest(test.TestCase):
|
|||||||
|
|
||||||
self.bind_plugin._has_provider_network_extension.assert_any_call()
|
self.bind_plugin._has_provider_network_extension.assert_any_call()
|
||||||
save_nw_data.assert_called_once_with(self.fake_context,
|
save_nw_data.assert_called_once_with(self.fake_context,
|
||||||
fake_share_network_subnet)
|
fake_share_network_subnet,
|
||||||
|
save_db=True)
|
||||||
save_subnet_data.assert_called_once_with(self.fake_context,
|
save_subnet_data.assert_called_once_with(self.fake_context,
|
||||||
fake_share_network_subnet)
|
fake_share_network_subnet,
|
||||||
|
save_db=True)
|
||||||
expected_kwargs = {
|
expected_kwargs = {
|
||||||
'binding:vnic_type': 'baremetal',
|
'binding:vnic_type': 'baremetal',
|
||||||
'host_id': 'foohost1',
|
'host_id': 'foohost1',
|
||||||
@ -1713,9 +1722,11 @@ class NeutronBindNetworkPluginWithNormalTypeTest(test.TestCase):
|
|||||||
|
|
||||||
self.bind_plugin._has_provider_network_extension.assert_any_call()
|
self.bind_plugin._has_provider_network_extension.assert_any_call()
|
||||||
save_nw_data.assert_called_once_with(self.fake_context,
|
save_nw_data.assert_called_once_with(self.fake_context,
|
||||||
fake_share_network_subnet)
|
fake_share_network_subnet,
|
||||||
|
save_db=True)
|
||||||
save_subnet_data.assert_called_once_with(self.fake_context,
|
save_subnet_data.assert_called_once_with(self.fake_context,
|
||||||
fake_share_network_subnet)
|
fake_share_network_subnet,
|
||||||
|
save_db=True)
|
||||||
expected_kwargs = {
|
expected_kwargs = {
|
||||||
'binding:vnic_type': 'normal',
|
'binding:vnic_type': 'normal',
|
||||||
'host_id': 'foohost1',
|
'host_id': 'foohost1',
|
||||||
@ -1800,9 +1811,11 @@ class NeutronBindSingleNetworkPluginWithNormalTypeTest(test.TestCase):
|
|||||||
|
|
||||||
self.bind_plugin._has_provider_network_extension.assert_any_call()
|
self.bind_plugin._has_provider_network_extension.assert_any_call()
|
||||||
save_nw_data.assert_called_once_with(self.fake_context,
|
save_nw_data.assert_called_once_with(self.fake_context,
|
||||||
fake_share_network_subnet)
|
fake_share_network_subnet,
|
||||||
|
save_db=True)
|
||||||
save_subnet_data.assert_called_once_with(self.fake_context,
|
save_subnet_data.assert_called_once_with(self.fake_context,
|
||||||
fake_share_network_subnet)
|
fake_share_network_subnet,
|
||||||
|
save_db=True)
|
||||||
expected_kwargs = {
|
expected_kwargs = {
|
||||||
'binding:vnic_type': 'normal',
|
'binding:vnic_type': 'normal',
|
||||||
'host_id': 'foohost1',
|
'host_id': 'foohost1',
|
||||||
@ -1866,3 +1879,23 @@ class NeutronBindSingleNetworkPluginWithNormalTypeTest(test.TestCase):
|
|||||||
self.assertRaises(exception.NetworkBadConfigurationException,
|
self.assertRaises(exception.NetworkBadConfigurationException,
|
||||||
self.bind_plugin._get_matched_ip_address,
|
self.bind_plugin._get_matched_ip_address,
|
||||||
fix_ips, version)
|
fix_ips, version)
|
||||||
|
|
||||||
|
def _setup_include_network_info(self):
|
||||||
|
data = {
|
||||||
|
'DEFAULT': {
|
||||||
|
'neutron_net_id': 'fake net id',
|
||||||
|
'neutron_subnet_id': 'fake subnet id',
|
||||||
|
'neutron_physical_net_name': 'net1',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
with test_utils.create_temp_config_with_opts(data):
|
||||||
|
instance = plugin.NeutronNetworkPlugin()
|
||||||
|
|
||||||
|
return instance
|
||||||
|
|
||||||
|
def test_include_network_info(self):
|
||||||
|
instance = self._setup_include_network_info()
|
||||||
|
self.mock_object(instance, '_store_neutron_net_info')
|
||||||
|
instance.include_network_info(fake_share_network)
|
||||||
|
instance._store_neutron_net_info.assert_called_once_with(
|
||||||
|
None, fake_share_network, save_db=False)
|
||||||
|
@ -346,7 +346,8 @@ class StandaloneNetworkPluginTest(test.TestCase):
|
|||||||
ip_version=6,
|
ip_version=6,
|
||||||
mtu=1500))
|
mtu=1500))
|
||||||
|
|
||||||
def test_allocate_network_one_ip_address_ipv4_no_usages_exist(self):
|
@ddt.data('admin', 'user')
|
||||||
|
def test_allocate_network_one_ip_address_ipv4_no_usages_exist(self, label):
|
||||||
data = {
|
data = {
|
||||||
'DEFAULT': {
|
'DEFAULT': {
|
||||||
'standalone_network_plugin_network_type': 'vlan',
|
'standalone_network_plugin_network_type': 'vlan',
|
||||||
@ -356,8 +357,9 @@ class StandaloneNetworkPluginTest(test.TestCase):
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
with test_utils.create_temp_config_with_opts(data):
|
with test_utils.create_temp_config_with_opts(data):
|
||||||
instance = plugin.StandaloneNetworkPlugin()
|
instance = plugin.StandaloneNetworkPlugin(label=label)
|
||||||
self.mock_object(instance.db, 'share_network_subnet_update')
|
if label != 'admin':
|
||||||
|
self.mock_object(instance.db, 'share_network_subnet_update')
|
||||||
self.mock_object(instance.db, 'network_allocation_create')
|
self.mock_object(instance.db, 'network_allocation_create')
|
||||||
self.mock_object(
|
self.mock_object(
|
||||||
instance.db, 'network_allocations_get_by_ip_address',
|
instance.db, 'network_allocations_get_by_ip_address',
|
||||||
@ -376,15 +378,18 @@ class StandaloneNetworkPluginTest(test.TestCase):
|
|||||||
'ip_version': 4,
|
'ip_version': 4,
|
||||||
'mtu': 1500,
|
'mtu': 1500,
|
||||||
}
|
}
|
||||||
instance.db.share_network_subnet_update.assert_called_once_with(
|
if label != 'admin':
|
||||||
fake_context, fake_share_network_subnet['id'], na_data)
|
instance.db.share_network_subnet_update.assert_called_once_with(
|
||||||
|
fake_context, fake_share_network_subnet['id'], na_data)
|
||||||
|
na_data['share_network_subnet_id'] = \
|
||||||
|
fake_share_network_subnet['id']
|
||||||
instance.db.network_allocations_get_by_ip_address.assert_has_calls(
|
instance.db.network_allocations_get_by_ip_address.assert_has_calls(
|
||||||
[mock.call(fake_context, '10.0.0.2')])
|
[mock.call(fake_context, '10.0.0.2')])
|
||||||
instance.db.network_allocation_create.assert_called_once_with(
|
instance.db.network_allocation_create.assert_called_once_with(
|
||||||
fake_context,
|
fake_context,
|
||||||
dict(share_server_id=fake_share_server['id'],
|
dict(share_server_id=fake_share_server['id'],
|
||||||
ip_address='10.0.0.2', status=constants.STATUS_ACTIVE,
|
ip_address='10.0.0.2', status=constants.STATUS_ACTIVE,
|
||||||
label='user', **na_data))
|
label=label, **na_data))
|
||||||
|
|
||||||
def test_allocate_network_two_ip_addresses_ipv4_two_usages_exist(self):
|
def test_allocate_network_two_ip_addresses_ipv4_two_usages_exist(self):
|
||||||
ctxt = type('FakeCtxt', (object,), {'fake': ['10.0.0.2', '10.0.0.4']})
|
ctxt = type('FakeCtxt', (object,), {'fake': ['10.0.0.2', '10.0.0.4']})
|
||||||
@ -428,6 +433,7 @@ class StandaloneNetworkPluginTest(test.TestCase):
|
|||||||
instance.db.network_allocations_get_by_ip_address.assert_has_calls(
|
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.2'), mock.call(ctxt, '10.0.0.3'),
|
||||||
mock.call(ctxt, '10.0.0.4'), mock.call(ctxt, '10.0.0.5')])
|
mock.call(ctxt, '10.0.0.4'), mock.call(ctxt, '10.0.0.5')])
|
||||||
|
na_data['share_network_subnet_id'] = fake_share_network_subnet['id']
|
||||||
instance.db.network_allocation_create.assert_has_calls([
|
instance.db.network_allocation_create.assert_has_calls([
|
||||||
mock.call(
|
mock.call(
|
||||||
ctxt,
|
ctxt,
|
||||||
@ -522,6 +528,10 @@ class StandaloneNetworkPluginTest(test.TestCase):
|
|||||||
if not label:
|
if not label:
|
||||||
instance.db.share_network_subnet_update.assert_called_once_with(
|
instance.db.share_network_subnet_update.assert_called_once_with(
|
||||||
fake_context, fake_share_network_subnet['id'], network_data)
|
fake_context, fake_share_network_subnet['id'], network_data)
|
||||||
|
data_list[0]['share_network_subnet_id'] = (
|
||||||
|
fake_share_network_subnet['id'])
|
||||||
|
data_list[1]['share_network_subnet_id'] = (
|
||||||
|
fake_share_network_subnet['id'])
|
||||||
instance._verify_share_network_subnet.assert_called_once_with(
|
instance._verify_share_network_subnet.assert_called_once_with(
|
||||||
fake_share_server['id'], fake_share_network_subnet)
|
fake_share_server['id'], fake_share_network_subnet)
|
||||||
|
|
||||||
@ -536,3 +546,22 @@ class StandaloneNetworkPluginTest(test.TestCase):
|
|||||||
instance.unmanage_network_allocations('context', 'server_id')
|
instance.unmanage_network_allocations('context', 'server_id')
|
||||||
instance.deallocate_network.assert_called_once_with(
|
instance.deallocate_network.assert_called_once_with(
|
||||||
'context', 'server_id')
|
'context', 'server_id')
|
||||||
|
|
||||||
|
def _setup_include_network_info(self):
|
||||||
|
data = {
|
||||||
|
'DEFAULT': {
|
||||||
|
'standalone_network_plugin_gateway': '192.168.0.1',
|
||||||
|
'standalone_network_plugin_mask': '24',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
with test_utils.create_temp_config_with_opts(data):
|
||||||
|
instance = plugin.StandaloneNetworkPlugin()
|
||||||
|
|
||||||
|
return instance
|
||||||
|
|
||||||
|
def test_include_network_info(self):
|
||||||
|
instance = self._setup_include_network_info()
|
||||||
|
self.mock_object(instance, '_save_network_info')
|
||||||
|
instance.include_network_info(fake_share_network)
|
||||||
|
instance._save_network_info.assert_called_once_with(
|
||||||
|
None, fake_share_network, save_db=False)
|
||||||
|
@ -101,6 +101,8 @@ class HostFiltersTestCase(test.TestCase):
|
|||||||
}
|
}
|
||||||
request = self._make_zone_request(None)
|
request = self._make_zone_request(None)
|
||||||
request['request_spec']['availability_zones'] = supported_azs
|
request['request_spec']['availability_zones'] = supported_azs
|
||||||
|
request['request_spec']['az_request_multiple_subnet_support_map'] = \
|
||||||
|
{'zone2': 2}
|
||||||
host = fakes.FakeHostState('host1', {'service': service})
|
host = fakes.FakeHostState('host1', {'service': service})
|
||||||
|
|
||||||
self.assertEqual(host_passes, self.filter.host_passes(host, request))
|
self.assertEqual(host_passes, self.filter.host_passes(host, request))
|
||||||
|
@ -214,6 +214,8 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'replication_domain': None,
|
'replication_domain': None,
|
||||||
'sg_consistent_snapshot_support': None,
|
'sg_consistent_snapshot_support': None,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
'network_allocation_update_support': False,
|
||||||
|
'share_server_multiple_subnet_support': False,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
'name': 'host2@back1#BBB',
|
'name': 'host2@back1#BBB',
|
||||||
@ -244,6 +246,8 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'replication_domain': None,
|
'replication_domain': None,
|
||||||
'sg_consistent_snapshot_support': None,
|
'sg_consistent_snapshot_support': None,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
'network_allocation_update_support': False,
|
||||||
|
'share_server_multiple_subnet_support': False,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
'name': 'host2@back2#CCC',
|
'name': 'host2@back2#CCC',
|
||||||
@ -274,6 +278,8 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'replication_domain': None,
|
'replication_domain': None,
|
||||||
'sg_consistent_snapshot_support': None,
|
'sg_consistent_snapshot_support': None,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
'network_allocation_update_support': False,
|
||||||
|
'share_server_multiple_subnet_support': False,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -326,6 +332,8 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'replication_domain': None,
|
'replication_domain': None,
|
||||||
'sg_consistent_snapshot_support': None,
|
'sg_consistent_snapshot_support': None,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
'network_allocation_update_support': False,
|
||||||
|
'share_server_multiple_subnet_support': False,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
'name': 'host2@BBB#pool2',
|
'name': 'host2@BBB#pool2',
|
||||||
@ -357,6 +365,8 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'replication_domain': None,
|
'replication_domain': None,
|
||||||
'sg_consistent_snapshot_support': None,
|
'sg_consistent_snapshot_support': None,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
'network_allocation_update_support': False,
|
||||||
|
'share_server_multiple_subnet_support': False,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
'name': 'host3@CCC#pool3',
|
'name': 'host3@CCC#pool3',
|
||||||
@ -388,6 +398,8 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'replication_domain': None,
|
'replication_domain': None,
|
||||||
'sg_consistent_snapshot_support': None,
|
'sg_consistent_snapshot_support': None,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
'network_allocation_update_support': False,
|
||||||
|
'share_server_multiple_subnet_support': False,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
'name': 'host4@DDD#pool4a',
|
'name': 'host4@DDD#pool4a',
|
||||||
@ -419,6 +431,8 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'replication_domain': None,
|
'replication_domain': None,
|
||||||
'sg_consistent_snapshot_support': None,
|
'sg_consistent_snapshot_support': None,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
'network_allocation_update_support': False,
|
||||||
|
'share_server_multiple_subnet_support': False,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
'name': 'host4@DDD#pool4b',
|
'name': 'host4@DDD#pool4b',
|
||||||
@ -450,6 +464,8 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'replication_domain': None,
|
'replication_domain': None,
|
||||||
'sg_consistent_snapshot_support': None,
|
'sg_consistent_snapshot_support': None,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
'network_allocation_update_support': False,
|
||||||
|
'share_server_multiple_subnet_support': False,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -514,6 +530,8 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'replication_domain': None,
|
'replication_domain': None,
|
||||||
'sg_consistent_snapshot_support': None,
|
'sg_consistent_snapshot_support': None,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
'network_allocation_update_support': False,
|
||||||
|
'share_server_multiple_subnet_support': False,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
'name': 'host2@back1#BBB',
|
'name': 'host2@back1#BBB',
|
||||||
@ -544,6 +562,8 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'replication_domain': None,
|
'replication_domain': None,
|
||||||
'sg_consistent_snapshot_support': None,
|
'sg_consistent_snapshot_support': None,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
'network_allocation_update_support': False,
|
||||||
|
'share_server_multiple_subnet_support': False,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -602,6 +622,8 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'replication_domain': None,
|
'replication_domain': None,
|
||||||
'sg_consistent_snapshot_support': None,
|
'sg_consistent_snapshot_support': None,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
'network_allocation_update_support': False,
|
||||||
|
'share_server_multiple_subnet_support': False,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -372,7 +372,7 @@ class ContainerShareDriverTestCase(test.TestCase):
|
|||||||
before, after)
|
before, after)
|
||||||
|
|
||||||
def test__setup_server_container_fails(self):
|
def test__setup_server_container_fails(self):
|
||||||
network_info = cont_fakes.fake_network()
|
network_info = [cont_fakes.fake_network()]
|
||||||
self.mock_object(self._driver.container, 'start_container')
|
self.mock_object(self._driver.container, 'start_container')
|
||||||
self._driver.container.start_container.side_effect = KeyError()
|
self._driver.container.start_container.side_effect = KeyError()
|
||||||
|
|
||||||
@ -380,21 +380,21 @@ class ContainerShareDriverTestCase(test.TestCase):
|
|||||||
self._driver._setup_server, network_info)
|
self._driver._setup_server, network_info)
|
||||||
|
|
||||||
def test__setup_server_ok(self):
|
def test__setup_server_ok(self):
|
||||||
network_info = cont_fakes.fake_network()
|
network_info = [cont_fakes.fake_network()]
|
||||||
server_id = self._driver._get_container_name(network_info["server_id"])
|
server_id = self._driver._get_container_name(
|
||||||
|
network_info[0]["server_id"])
|
||||||
self.mock_object(self._driver.container, 'start_container')
|
self.mock_object(self._driver.container, 'start_container')
|
||||||
self.mock_object(self._driver, '_get_veth_state')
|
self.mock_object(self._driver, '_get_veth_state')
|
||||||
self.mock_object(self._driver, '_get_corresponding_veth',
|
self.mock_object(self._driver, '_get_corresponding_veth',
|
||||||
mock.Mock(return_value='veth0'))
|
mock.Mock(return_value='veth0'))
|
||||||
self.mock_object(self._driver, '_connect_to_network')
|
self.mock_object(self._driver, '_connect_to_network')
|
||||||
|
|
||||||
self.assertEqual(network_info['server_id'],
|
self.assertEqual(network_info[0]['server_id'],
|
||||||
self._driver._setup_server(network_info)['id'])
|
self._driver._setup_server(network_info)['id'])
|
||||||
self._driver.container.start_container.assert_called_once_with(
|
self._driver.container.start_container.assert_called_once_with(
|
||||||
server_id)
|
server_id)
|
||||||
self._driver._connect_to_network.assert_called_once_with(server_id,
|
self._driver._connect_to_network.assert_called_once_with(
|
||||||
network_info,
|
server_id, network_info[0], 'veth0')
|
||||||
'veth0')
|
|
||||||
|
|
||||||
def test_manage_existing(self):
|
def test_manage_existing(self):
|
||||||
|
|
||||||
|
@ -145,6 +145,8 @@ class EMCShareFrameworkTestCase(test.TestCase):
|
|||||||
data['max_shares_per_share_server'] = -1
|
data['max_shares_per_share_server'] = -1
|
||||||
data['max_share_server_size'] = -1
|
data['max_share_server_size'] = -1
|
||||||
data['security_service_update_support'] = False
|
data['security_service_update_support'] = False
|
||||||
|
data['share_server_multiple_subnet_support'] = False
|
||||||
|
data['network_allocation_update_support'] = False
|
||||||
self.assertEqual(data, self.driver._stats)
|
self.assertEqual(data, self.driver._stats)
|
||||||
|
|
||||||
def _fake_safe_get(self, value):
|
def _fake_safe_get(self, value):
|
||||||
@ -214,3 +216,9 @@ class EMCShareFrameworkTestCase(test.TestCase):
|
|||||||
expected = None
|
expected = None
|
||||||
actual = self.driver.get_default_filter_function()
|
actual = self.driver.get_default_filter_function()
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
|
def test_setup_server(self):
|
||||||
|
network_info = [{}]
|
||||||
|
expected = None
|
||||||
|
result = self.driver._setup_server(network_info)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
@ -34,6 +34,7 @@ import time
|
|||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
|
from oslo_serialization import jsonutils
|
||||||
from oslo_utils import timeutils
|
from oslo_utils import timeutils
|
||||||
|
|
||||||
from manila.common import constants
|
from manila.common import constants
|
||||||
@ -141,6 +142,7 @@ class DummyDriver(driver.ShareDriver):
|
|||||||
"share_backend_name") or "DummyDriver"
|
"share_backend_name") or "DummyDriver"
|
||||||
self.migration_progress = {}
|
self.migration_progress = {}
|
||||||
self.security_service_update_support = True
|
self.security_service_update_support = True
|
||||||
|
self.network_allocation_update_support = True
|
||||||
|
|
||||||
def _verify_configuration(self):
|
def _verify_configuration(self):
|
||||||
allowed_driver_methods = [m for m in dir(self) if m[0] != '_']
|
allowed_driver_methods = [m for m in dir(self) if m[0] != '_']
|
||||||
@ -184,24 +186,40 @@ class DummyDriver(driver.ShareDriver):
|
|||||||
"s_id": snapshot["snapshot_id"].replace("-", "_"),
|
"s_id": snapshot["snapshot_id"].replace("-", "_"),
|
||||||
"si_id": snapshot["id"].replace("-", "_")}
|
"si_id": snapshot["id"].replace("-", "_")}
|
||||||
|
|
||||||
def _generate_export_locations(self, mountpoint, share_server=None):
|
def _get_export(self, mountpoint, ip, is_admin_only, preferred):
|
||||||
details = share_server["backend_details"] if share_server else {
|
return {
|
||||||
"primary_public_ip": "10.0.0.10",
|
"path": "%(ip)s:%(mp)s" % {"ip": ip, "mp": mountpoint},
|
||||||
"secondary_public_ip": "10.0.0.20",
|
"metadata": {
|
||||||
"service_ip": "11.0.0.11",
|
"preferred": preferred,
|
||||||
|
},
|
||||||
|
"is_admin_only": is_admin_only,
|
||||||
}
|
}
|
||||||
return [
|
|
||||||
{
|
def _generate_export_locations(self, mountpoint, share_server=None):
|
||||||
"path": "%(ip)s:%(mp)s" % {"ip": ip, "mp": mountpoint},
|
if share_server:
|
||||||
"metadata": {
|
subnet_allocations = jsonutils.loads(
|
||||||
"preferred": preferred,
|
share_server["backend_details"]["subnet_allocations"])
|
||||||
},
|
service_ip = share_server["backend_details"]["service_ip"]
|
||||||
"is_admin_only": is_admin_only,
|
else:
|
||||||
} for ip, is_admin_only, preferred in (
|
subnet_allocations = [{
|
||||||
(details["primary_public_ip"], False, True),
|
"primary_public_ip": "10.0.0.10",
|
||||||
(details["secondary_public_ip"], False, False),
|
"secondary_public_ip": "10.0.0.20",
|
||||||
(details["service_ip"], True, False))
|
}]
|
||||||
]
|
service_ip = "11.0.0.11"
|
||||||
|
|
||||||
|
export_locations = [
|
||||||
|
self._get_export(mountpoint, service_ip, True, False)]
|
||||||
|
for subnet_allocation in subnet_allocations:
|
||||||
|
export_locations.append(
|
||||||
|
self._get_export(
|
||||||
|
mountpoint, subnet_allocation["primary_public_ip"],
|
||||||
|
False, True))
|
||||||
|
export_locations.append(
|
||||||
|
self._get_export(
|
||||||
|
mountpoint, subnet_allocation["secondary_public_ip"],
|
||||||
|
False, False))
|
||||||
|
|
||||||
|
return export_locations
|
||||||
|
|
||||||
def _create_share(self, share, share_server=None):
|
def _create_share(self, share, share_server=None):
|
||||||
share_proto = share["share_proto"]
|
share_proto = share["share_proto"]
|
||||||
@ -410,16 +428,25 @@ class DummyDriver(driver.ShareDriver):
|
|||||||
Redefine it within share driver when it is going to handle share
|
Redefine it within share driver when it is going to handle share
|
||||||
servers.
|
servers.
|
||||||
"""
|
"""
|
||||||
|
common_net_info = network_info[0]
|
||||||
server_details = {
|
server_details = {
|
||||||
"primary_public_ip": network_info[
|
"service_ip": common_net_info[
|
||||||
"network_allocations"][0]["ip_address"],
|
|
||||||
"secondary_public_ip": network_info[
|
|
||||||
"network_allocations"][1]["ip_address"],
|
|
||||||
"service_ip": network_info[
|
|
||||||
"admin_network_allocations"][0]["ip_address"],
|
"admin_network_allocations"][0]["ip_address"],
|
||||||
"username": "fake_username",
|
"username": "fake_username",
|
||||||
"server_id": network_info['server_id']
|
"server_id": common_net_info['server_id'],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subnet_allocations = []
|
||||||
|
for subnet_info in network_info:
|
||||||
|
subnet_allocations.append({
|
||||||
|
"primary_public_ip": subnet_info[
|
||||||
|
"network_allocations"][0]["ip_address"],
|
||||||
|
"secondary_public_ip": subnet_info[
|
||||||
|
"network_allocations"][1]["ip_address"]
|
||||||
|
})
|
||||||
|
|
||||||
|
server_details['subnet_allocations'] = jsonutils.dumps(
|
||||||
|
subnet_allocations)
|
||||||
return server_details
|
return server_details
|
||||||
|
|
||||||
@slow_me_down
|
@slow_me_down
|
||||||
@ -460,6 +487,7 @@ class DummyDriver(driver.ShareDriver):
|
|||||||
"share_group_stats": {
|
"share_group_stats": {
|
||||||
"consistent_snapshot_support": "pool",
|
"consistent_snapshot_support": "pool",
|
||||||
},
|
},
|
||||||
|
'share_server_multiple_subnet_support': True,
|
||||||
}
|
}
|
||||||
if self.configuration.replication_domain:
|
if self.configuration.replication_domain:
|
||||||
data["replication_type"] = "readable"
|
data["replication_type"] = "readable"
|
||||||
@ -828,9 +856,12 @@ class DummyDriver(driver.ShareDriver):
|
|||||||
"private storage." % identifier)
|
"private storage." % identifier)
|
||||||
raise exception.ShareBackendException(msg=msg)
|
raise exception.ShareBackendException(msg=msg)
|
||||||
|
|
||||||
return [server_details['primary_public_ip'],
|
ips = [server_details['service_ip']]
|
||||||
server_details['secondary_public_ip'],
|
subnet_allocations = jsonutils.loads(
|
||||||
server_details['service_ip']]
|
server_details['subnet_allocations'])
|
||||||
|
for subnet_allocation in subnet_allocations:
|
||||||
|
ips += list(subnet_allocation.values())
|
||||||
|
return ips
|
||||||
|
|
||||||
@slow_me_down
|
@slow_me_down
|
||||||
def manage_server(self, context, share_server, identifier, driver_options):
|
def manage_server(self, context, share_server, identifier, driver_options):
|
||||||
@ -889,3 +920,65 @@ class DummyDriver(driver.ShareDriver):
|
|||||||
share_instance_rules, new_security_service,
|
share_instance_rules, new_security_service,
|
||||||
current_security_service=None):
|
current_security_service=None):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def check_update_share_server_network_allocations(
|
||||||
|
self, context, share_server, current_network_allocations,
|
||||||
|
new_share_network_subnet, security_services, share_instances,
|
||||||
|
share_instances_rules):
|
||||||
|
|
||||||
|
LOG.debug("Share server %(server)s can be updated with allocations "
|
||||||
|
"from new subnet.", {'server': share_server['id']})
|
||||||
|
return True
|
||||||
|
|
||||||
|
def update_share_server_network_allocations(
|
||||||
|
self, context, share_server, current_network_allocations,
|
||||||
|
new_network_allocations, security_services, shares, snapshots):
|
||||||
|
|
||||||
|
subnet_allocations = jsonutils.loads(
|
||||||
|
share_server['backend_details']['subnet_allocations'])
|
||||||
|
subnet_allocations.append({
|
||||||
|
'primary_public_ip': new_network_allocations[
|
||||||
|
'network_allocations'][0]['ip_address'],
|
||||||
|
'secondary_public_ip': new_network_allocations[
|
||||||
|
'network_allocations'][1]['ip_address'],
|
||||||
|
})
|
||||||
|
new_server = {
|
||||||
|
"backend_details": {
|
||||||
|
"subnet_allocations": jsonutils.dumps(subnet_allocations),
|
||||||
|
"service_ip": share_server["backend_details"]["service_ip"],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shares_updates = {}
|
||||||
|
for instance in shares:
|
||||||
|
|
||||||
|
share_name = self._get_share_name(instance)
|
||||||
|
mountpoint = "/path/to/fake/share/%s" % share_name
|
||||||
|
export_locations = self._generate_export_locations(
|
||||||
|
mountpoint, share_server=new_server)
|
||||||
|
shares_updates.update(
|
||||||
|
{instance['id']: export_locations}
|
||||||
|
)
|
||||||
|
|
||||||
|
snapshot_updates = {}
|
||||||
|
for instance in snapshots:
|
||||||
|
snapshot_name = self._get_snapshot_name(instance)
|
||||||
|
mountpoint = "/path/to/fake/snapshot/%s" % snapshot_name
|
||||||
|
snap_export_locations = self._generate_export_locations(
|
||||||
|
mountpoint, share_server=new_server)
|
||||||
|
snapshot_updates.update(
|
||||||
|
{instance['id']: {
|
||||||
|
'provider_location': mountpoint,
|
||||||
|
'export_locations': snap_export_locations}}
|
||||||
|
)
|
||||||
|
|
||||||
|
LOG.debug(
|
||||||
|
"Network update allocations of dummy share server with ID '%s' "
|
||||||
|
"has been completed.", share_server["id"])
|
||||||
|
return {
|
||||||
|
"share_updates": shares_updates,
|
||||||
|
"snapshot_updates": snapshot_updates,
|
||||||
|
"server_details": {
|
||||||
|
"subnet_allocations": (
|
||||||
|
new_server["backend_details"]["subnet_allocations"])
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@ -270,6 +270,8 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
|
|||||||
'ipv4_support': True,
|
'ipv4_support': True,
|
||||||
'ipv6_support': False,
|
'ipv6_support': False,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
'share_server_multiple_subnet_support': False,
|
||||||
|
'network_allocation_update_support': False,
|
||||||
}
|
}
|
||||||
self.assertEqual(test_data, self._driver._stats)
|
self.assertEqual(test_data, self._driver._stats)
|
||||||
|
|
||||||
|
@ -750,6 +750,8 @@ class HPE3ParDriverTestCase(test.TestCase):
|
|||||||
'max_share_server_size': -1,
|
'max_share_server_size': -1,
|
||||||
'max_shares_per_share_server': -1,
|
'max_shares_per_share_server': -1,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
'share_server_multiple_subnet_support': False,
|
||||||
|
'network_allocation_update_support': False,
|
||||||
}
|
}
|
||||||
|
|
||||||
result = self.driver.get_share_stats(refresh=True)
|
result = self.driver.get_share_stats(refresh=True)
|
||||||
@ -824,6 +826,8 @@ class HPE3ParDriverTestCase(test.TestCase):
|
|||||||
'create_share_from_snapshot_support': True,
|
'create_share_from_snapshot_support': True,
|
||||||
'revert_to_snapshot_support': False,
|
'revert_to_snapshot_support': False,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
'share_server_multiple_subnet_support': False,
|
||||||
|
'network_allocation_update_support': False,
|
||||||
'mount_snapshot_support': False,
|
'mount_snapshot_support': False,
|
||||||
'share_group_stats': {
|
'share_group_stats': {
|
||||||
'consistent_snapshot_support': None,
|
'consistent_snapshot_support': None,
|
||||||
@ -872,6 +876,8 @@ class HPE3ParDriverTestCase(test.TestCase):
|
|||||||
'create_share_from_snapshot_support': True,
|
'create_share_from_snapshot_support': True,
|
||||||
'revert_to_snapshot_support': False,
|
'revert_to_snapshot_support': False,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
'share_server_multiple_subnet_support': False,
|
||||||
|
'network_allocation_update_support': False,
|
||||||
'mount_snapshot_support': False,
|
'mount_snapshot_support': False,
|
||||||
'share_group_stats': {
|
'share_group_stats': {
|
||||||
'consistent_snapshot_support': None,
|
'consistent_snapshot_support': None,
|
||||||
@ -926,7 +932,7 @@ class HPE3ParDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
self.init_driver()
|
self.init_driver()
|
||||||
|
|
||||||
network_info = {
|
network_info = [{
|
||||||
'network_allocations': [
|
'network_allocations': [
|
||||||
{'ip_address': constants.EXPECTED_IP_1234}],
|
{'ip_address': constants.EXPECTED_IP_1234}],
|
||||||
'cidr': '/'.join((constants.EXPECTED_IP_1234,
|
'cidr': '/'.join((constants.EXPECTED_IP_1234,
|
||||||
@ -934,7 +940,7 @@ class HPE3ParDriverTestCase(test.TestCase):
|
|||||||
'network_type': constants.EXPECTED_VLAN_TYPE,
|
'network_type': constants.EXPECTED_VLAN_TYPE,
|
||||||
'segmentation_id': constants.EXPECTED_VLAN_TAG,
|
'segmentation_id': constants.EXPECTED_VLAN_TAG,
|
||||||
'server_id': constants.EXPECTED_SERVER_ID,
|
'server_id': constants.EXPECTED_SERVER_ID,
|
||||||
}
|
}]
|
||||||
|
|
||||||
expected_result = {
|
expected_result = {
|
||||||
'share_server_name': constants.EXPECTED_SERVER_ID,
|
'share_server_name': constants.EXPECTED_SERVER_ID,
|
||||||
@ -964,7 +970,7 @@ class HPE3ParDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
self.init_driver()
|
self.init_driver()
|
||||||
|
|
||||||
network_info = {
|
network_info = [{
|
||||||
'network_allocations': [
|
'network_allocations': [
|
||||||
{'ip_address': constants.EXPECTED_IP_1234}],
|
{'ip_address': constants.EXPECTED_IP_1234}],
|
||||||
'cidr': '/'.join((constants.EXPECTED_IP_1234,
|
'cidr': '/'.join((constants.EXPECTED_IP_1234,
|
||||||
@ -972,7 +978,7 @@ class HPE3ParDriverTestCase(test.TestCase):
|
|||||||
'network_type': constants.EXPECTED_VXLAN_TYPE,
|
'network_type': constants.EXPECTED_VXLAN_TYPE,
|
||||||
'segmentation_id': constants.EXPECTED_VLAN_TAG,
|
'segmentation_id': constants.EXPECTED_VLAN_TAG,
|
||||||
'server_id': constants.EXPECTED_SERVER_ID,
|
'server_id': constants.EXPECTED_SERVER_ID,
|
||||||
}
|
}]
|
||||||
metadata = {'request_host': constants.EXPECTED_HOST}
|
metadata = {'request_host': constants.EXPECTED_HOST}
|
||||||
|
|
||||||
self.assertRaises(exception.NetworkBadConfigurationException,
|
self.assertRaises(exception.NetworkBadConfigurationException,
|
||||||
@ -984,7 +990,7 @@ class HPE3ParDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
self.init_driver()
|
self.init_driver()
|
||||||
|
|
||||||
network_info = {
|
network_info = [{
|
||||||
'network_allocations': [
|
'network_allocations': [
|
||||||
{'ip_address': constants.EXPECTED_IP_1234}],
|
{'ip_address': constants.EXPECTED_IP_1234}],
|
||||||
'cidr': '/'.join((constants.EXPECTED_IP_1234,
|
'cidr': '/'.join((constants.EXPECTED_IP_1234,
|
||||||
@ -992,7 +998,7 @@ class HPE3ParDriverTestCase(test.TestCase):
|
|||||||
'network_type': constants.EXPECTED_VLAN_TYPE,
|
'network_type': constants.EXPECTED_VLAN_TYPE,
|
||||||
'segmentation_id': constants.EXPECTED_VLAN_TAG,
|
'segmentation_id': constants.EXPECTED_VLAN_TAG,
|
||||||
'server_id': constants.EXPECTED_SERVER_ID,
|
'server_id': constants.EXPECTED_SERVER_ID,
|
||||||
}
|
}]
|
||||||
metadata = {'request_host': constants.EXPECTED_HOST}
|
metadata = {'request_host': constants.EXPECTED_HOST}
|
||||||
|
|
||||||
expected_vfs = self.driver.fpgs[
|
expected_vfs = self.driver.fpgs[
|
||||||
|
@ -1181,7 +1181,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
|||||||
'id': 'fake_network_allocation_id',
|
'id': 'fake_network_allocation_id',
|
||||||
'ip_address': '111.111.111.109',
|
'ip_address': '111.111.111.109',
|
||||||
}]
|
}]
|
||||||
self.fake_network_info = {
|
self.fake_network_info = [{
|
||||||
'server_id': '0',
|
'server_id': '0',
|
||||||
'segmentation_id': '2',
|
'segmentation_id': '2',
|
||||||
'cidr': '111.111.111.0/24',
|
'cidr': '111.111.111.0/24',
|
||||||
@ -1190,7 +1190,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
|||||||
'security_services': '',
|
'security_services': '',
|
||||||
'network_allocations': self.fake_network_allocations,
|
'network_allocations': self.fake_network_allocations,
|
||||||
'network_type': 'vlan',
|
'network_type': 'vlan',
|
||||||
}
|
}]
|
||||||
self.fake_active_directory = {
|
self.fake_active_directory = {
|
||||||
'type': 'active_directory',
|
'type': 'active_directory',
|
||||||
'dns_ip': '100.97.5.5',
|
'dns_ip': '100.97.5.5',
|
||||||
@ -2435,6 +2435,8 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
|||||||
"ipv4_support": True,
|
"ipv4_support": True,
|
||||||
"ipv6_support": False,
|
"ipv6_support": False,
|
||||||
"security_service_update_support": False,
|
"security_service_update_support": False,
|
||||||
|
"share_server_multiple_subnet_support": False,
|
||||||
|
"network_allocation_update_support": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
if replication_support:
|
if replication_support:
|
||||||
@ -3323,7 +3325,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
def test_setup_server_invalid_ipv4(self):
|
def test_setup_server_invalid_ipv4(self):
|
||||||
netwot_info_invali_ipv4 = self.fake_network_info
|
netwot_info_invali_ipv4 = self.fake_network_info
|
||||||
netwot_info_invali_ipv4['network_allocations'][0]['ip_address'] = (
|
netwot_info_invali_ipv4[0]['network_allocations'][0]['ip_address'] = (
|
||||||
"::1/128")
|
"::1/128")
|
||||||
self.assertRaises(exception.InvalidInput,
|
self.assertRaises(exception.InvalidInput,
|
||||||
self.driver._setup_server,
|
self.driver._setup_server,
|
||||||
@ -3332,7 +3334,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
|||||||
@dec_driver_handles_share_servers
|
@dec_driver_handles_share_servers
|
||||||
def test_setup_server_network_type_error(self):
|
def test_setup_server_network_type_error(self):
|
||||||
vxlan_netwotk_info = self.fake_network_info
|
vxlan_netwotk_info = self.fake_network_info
|
||||||
vxlan_netwotk_info['network_type'] = 'vxlan'
|
vxlan_netwotk_info[0]['network_type'] = 'vxlan'
|
||||||
self.assertRaises(exception.NetworkBadConfigurationException,
|
self.assertRaises(exception.NetworkBadConfigurationException,
|
||||||
self.driver.setup_server,
|
self.driver.setup_server,
|
||||||
vxlan_netwotk_info)
|
vxlan_netwotk_info)
|
||||||
@ -3412,13 +3414,13 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
|||||||
logical_port='CTE0.A.H0;CTE0.A.H2;CTE0.B.H0;BOND0')
|
logical_port='CTE0.A.H0;CTE0.A.H2;CTE0.B.H0;BOND0')
|
||||||
self.driver.plugin.configuration.manila_huawei_conf_file = (
|
self.driver.plugin.configuration.manila_huawei_conf_file = (
|
||||||
self.fake_conf_file)
|
self.fake_conf_file)
|
||||||
fake_network_info = {
|
fake_network_info = [{
|
||||||
'server_id': '0',
|
'server_id': '0',
|
||||||
'segmentation_id': None,
|
'segmentation_id': None,
|
||||||
'cidr': '111.111.111.0/24',
|
'cidr': '111.111.111.0/24',
|
||||||
'network_allocations': self.fake_network_allocations,
|
'network_allocations': self.fake_network_allocations,
|
||||||
'network_type': None,
|
'network_type': None,
|
||||||
}
|
}]
|
||||||
self.mock_object(self.driver.plugin, '_get_online_port',
|
self.mock_object(self.driver.plugin, '_get_online_port',
|
||||||
mock.Mock(return_value=(['CTE0.A.H0', 'CTE0.A.H2',
|
mock.Mock(return_value=(['CTE0.A.H0', 'CTE0.A.H2',
|
||||||
'CTE0.B.H0'], ['BOND0'])))
|
'CTE0.B.H0'], ['BOND0'])))
|
||||||
@ -3476,7 +3478,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
|||||||
return self.driver.plugin.helper.do_call(*args, **kwargs)
|
return self.driver.plugin.helper.do_call(*args, **kwargs)
|
||||||
|
|
||||||
fake_network_info = self.fake_network_info
|
fake_network_info = self.fake_network_info
|
||||||
fake_network_info['security_services'] = [
|
fake_network_info[0]['security_services'] = [
|
||||||
self.fake_active_directory, self.fake_ldap]
|
self.fake_active_directory, self.fake_ldap]
|
||||||
self.mock_object(self.driver.plugin.helper, "delete_vlan")
|
self.mock_object(self.driver.plugin.helper, "delete_vlan")
|
||||||
self.mock_object(self.driver.plugin.helper, "delete_AD_config")
|
self.mock_object(self.driver.plugin.helper, "delete_AD_config")
|
||||||
@ -3509,7 +3511,8 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
|||||||
@dec_driver_handles_share_servers
|
@dec_driver_handles_share_servers
|
||||||
def test_setup_server_with_ad_domain_success(self):
|
def test_setup_server_with_ad_domain_success(self):
|
||||||
fake_network_info = self.fake_network_info
|
fake_network_info = self.fake_network_info
|
||||||
fake_network_info['security_services'] = [self.fake_active_directory]
|
fake_network_info[0]['security_services'] = (
|
||||||
|
[self.fake_active_directory])
|
||||||
self.mock_object(self.driver.plugin.helper,
|
self.mock_object(self.driver.plugin.helper,
|
||||||
"get_AD_config",
|
"get_AD_config",
|
||||||
mock.Mock(
|
mock.Mock(
|
||||||
@ -3531,8 +3534,8 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
|||||||
@dec_driver_handles_share_servers
|
@dec_driver_handles_share_servers
|
||||||
def test_setup_server_with_ldap_domain_success(self, server_ips):
|
def test_setup_server_with_ldap_domain_success(self, server_ips):
|
||||||
fake_network_info = self.fake_network_info
|
fake_network_info = self.fake_network_info
|
||||||
fake_network_info['security_services'] = [self.fake_ldap]
|
fake_network_info[0]['security_services'] = [self.fake_ldap]
|
||||||
fake_network_info['security_services'][0]['server'] = server_ips
|
fake_network_info[0]['security_services'][0]['server'] = server_ips
|
||||||
self.mock_object(
|
self.mock_object(
|
||||||
self.driver.plugin.helper,
|
self.driver.plugin.helper,
|
||||||
"get_LDAP_config",
|
"get_LDAP_config",
|
||||||
@ -3547,8 +3550,8 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
|||||||
def test_setup_server_with_ldap_domain_fail(self):
|
def test_setup_server_with_ldap_domain_fail(self):
|
||||||
server_ips = "100.97.5.87,100.97.5.88,100.97.5.89,100.97.5.86"
|
server_ips = "100.97.5.87,100.97.5.88,100.97.5.89,100.97.5.86"
|
||||||
fake_network_info = self.fake_network_info
|
fake_network_info = self.fake_network_info
|
||||||
fake_network_info['security_services'] = [self.fake_ldap]
|
fake_network_info[0]['security_services'] = [self.fake_ldap]
|
||||||
fake_network_info['security_services'][0]['server'] = server_ips
|
fake_network_info[0]['security_services'][0]['server'] = server_ips
|
||||||
self.mock_object(
|
self.mock_object(
|
||||||
self.driver.plugin.helper,
|
self.driver.plugin.helper,
|
||||||
"get_LDAP_config",
|
"get_LDAP_config",
|
||||||
@ -3573,7 +3576,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
|||||||
@dec_driver_handles_share_servers
|
@dec_driver_handles_share_servers
|
||||||
def test_setup_server_with_security_service_invalid(self, data):
|
def test_setup_server_with_security_service_invalid(self, data):
|
||||||
fake_network_info = self.fake_network_info
|
fake_network_info = self.fake_network_info
|
||||||
fake_network_info['security_services'] = [data]
|
fake_network_info[0]['security_services'] = [data]
|
||||||
self.assertRaises(exception.InvalidInput,
|
self.assertRaises(exception.InvalidInput,
|
||||||
self.driver.setup_server,
|
self.driver.setup_server,
|
||||||
fake_network_info)
|
fake_network_info)
|
||||||
@ -3592,7 +3595,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
|||||||
'server': '',
|
'server': '',
|
||||||
'domain': ''},
|
'domain': ''},
|
||||||
]
|
]
|
||||||
fake_network_info['security_services'] = ss
|
fake_network_info[0]['security_services'] = ss
|
||||||
self.assertRaises(exception.InvalidInput,
|
self.assertRaises(exception.InvalidInput,
|
||||||
self.driver.setup_server,
|
self.driver.setup_server,
|
||||||
fake_network_info)
|
fake_network_info)
|
||||||
@ -3600,7 +3603,8 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
|||||||
@dec_driver_handles_share_servers
|
@dec_driver_handles_share_servers
|
||||||
def test_setup_server_dns_exist_error(self):
|
def test_setup_server_dns_exist_error(self):
|
||||||
fake_network_info = self.fake_network_info
|
fake_network_info = self.fake_network_info
|
||||||
fake_network_info['security_services'] = [self.fake_active_directory]
|
fake_network_info[0]['security_services'] = (
|
||||||
|
[self.fake_active_directory])
|
||||||
self.mock_object(self.driver.plugin.helper,
|
self.mock_object(self.driver.plugin.helper,
|
||||||
"get_DNS_ip_address",
|
"get_DNS_ip_address",
|
||||||
mock.Mock(return_value=['100.97.5.85']))
|
mock.Mock(return_value=['100.97.5.85']))
|
||||||
@ -3612,7 +3616,8 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
|||||||
@dec_driver_handles_share_servers
|
@dec_driver_handles_share_servers
|
||||||
def test_setup_server_ad_exist_error(self):
|
def test_setup_server_ad_exist_error(self):
|
||||||
fake_network_info = self.fake_network_info
|
fake_network_info = self.fake_network_info
|
||||||
fake_network_info['security_services'] = [self.fake_active_directory]
|
fake_network_info[0]['security_services'] = (
|
||||||
|
[self.fake_active_directory])
|
||||||
self.mock_object(self.driver.plugin.helper,
|
self.mock_object(self.driver.plugin.helper,
|
||||||
"get_AD_config",
|
"get_AD_config",
|
||||||
mock.Mock(
|
mock.Mock(
|
||||||
@ -3626,7 +3631,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
|||||||
@dec_driver_handles_share_servers
|
@dec_driver_handles_share_servers
|
||||||
def test_setup_server_ldap_exist_error(self):
|
def test_setup_server_ldap_exist_error(self):
|
||||||
fake_network_info = self.fake_network_info
|
fake_network_info = self.fake_network_info
|
||||||
fake_network_info['security_services'] = [self.fake_ldap]
|
fake_network_info[0]['security_services'] = [self.fake_ldap]
|
||||||
self.mock_object(self.driver.plugin.helper,
|
self.mock_object(self.driver.plugin.helper,
|
||||||
"get_LDAP_config",
|
"get_LDAP_config",
|
||||||
mock.Mock(
|
mock.Mock(
|
||||||
@ -3642,7 +3647,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
|||||||
fake_active_directory = self.fake_active_directory
|
fake_active_directory = self.fake_active_directory
|
||||||
ip_list = "100.97.5.5,100.97.5.6,100.97.5.7,100.97.5.8"
|
ip_list = "100.97.5.5,100.97.5.6,100.97.5.7,100.97.5.8"
|
||||||
fake_active_directory['dns_ip'] = ip_list
|
fake_active_directory['dns_ip'] = ip_list
|
||||||
fake_network_info['security_services'] = [fake_active_directory]
|
fake_network_info[0]['security_services'] = [fake_active_directory]
|
||||||
self.mock_object(
|
self.mock_object(
|
||||||
self.driver.plugin.helper,
|
self.driver.plugin.helper,
|
||||||
"get_AD_config",
|
"get_AD_config",
|
||||||
@ -3655,7 +3660,8 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
|||||||
@dec_driver_handles_share_servers
|
@dec_driver_handles_share_servers
|
||||||
def test_setup_server_with_ad_domain_fail(self):
|
def test_setup_server_with_ad_domain_fail(self):
|
||||||
fake_network_info = self.fake_network_info
|
fake_network_info = self.fake_network_info
|
||||||
fake_network_info['security_services'] = [self.fake_active_directory]
|
fake_network_info[0]['security_services'] = (
|
||||||
|
[self.fake_active_directory])
|
||||||
self.mock_object(self.driver.plugin,
|
self.mock_object(self.driver.plugin,
|
||||||
'_get_wait_interval',
|
'_get_wait_interval',
|
||||||
mock.Mock(return_value=1))
|
mock.Mock(return_value=1))
|
||||||
|
@ -2852,7 +2852,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
self.fake_src_share_server,
|
self.fake_src_share_server,
|
||||||
self.fake_dest_share_server,
|
self.fake_dest_share_server,
|
||||||
share_instances, [],
|
share_instances, [],
|
||||||
fake.NETWORK_INFO
|
[fake.NETWORK_INFO]
|
||||||
)
|
)
|
||||||
|
|
||||||
expected_share_updates = {
|
expected_share_updates = {
|
||||||
@ -2932,7 +2932,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
self.fake_dest_share_server,
|
self.fake_dest_share_server,
|
||||||
self.fake_src_vserver,
|
self.fake_src_vserver,
|
||||||
self.mock_src_client, [fake.SHARE_INSTANCE],
|
self.mock_src_client, [fake.SHARE_INSTANCE],
|
||||||
fake.NETWORK_INFO)
|
[fake.NETWORK_INFO])
|
||||||
|
|
||||||
dm_session_mock.update_snapmirror_svm.assert_called_once_with(
|
dm_session_mock.update_snapmirror_svm.assert_called_once_with(
|
||||||
self.fake_src_share_server, self.fake_dest_share_server
|
self.fake_src_share_server, self.fake_dest_share_server
|
||||||
@ -2977,7 +2977,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
self.fake_src_share_server,
|
self.fake_src_share_server,
|
||||||
self.fake_dest_share_server,
|
self.fake_dest_share_server,
|
||||||
[fake.SHARE_INSTANCE], [],
|
[fake.SHARE_INSTANCE], [],
|
||||||
fake.NETWORK_INFO)
|
[fake.NETWORK_INFO])
|
||||||
|
|
||||||
self.library._get_vserver.assert_has_calls([
|
self.library._get_vserver.assert_has_calls([
|
||||||
mock.call(share_server=self.fake_src_share_server,
|
mock.call(share_server=self.fake_src_share_server,
|
||||||
@ -3513,7 +3513,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
fake_vserver_client, 'modify_active_directory_security_service')
|
fake_vserver_client, 'modify_active_directory_security_service')
|
||||||
|
|
||||||
self.library.update_share_server_security_service(
|
self.library.update_share_server_security_service(
|
||||||
fake_context, fake.SHARE_SERVER, fake_net_info,
|
fake_context, fake.SHARE_SERVER, [fake_net_info],
|
||||||
new_sec_service, current_security_service=curr_sec_service)
|
new_sec_service, current_security_service=curr_sec_service)
|
||||||
|
|
||||||
dns_ips = set()
|
dns_ips = set()
|
||||||
@ -3530,7 +3530,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
mock_get_vserver.assert_called_once_with(
|
mock_get_vserver.assert_called_once_with(
|
||||||
share_server=fake.SHARE_SERVER)
|
share_server=fake.SHARE_SERVER)
|
||||||
mock_check_update.assert_called_once_with(
|
mock_check_update.assert_called_once_with(
|
||||||
fake_context, fake.SHARE_SERVER, fake_net_info, new_sec_service,
|
fake_context, fake.SHARE_SERVER, [fake_net_info], new_sec_service,
|
||||||
current_security_service=curr_sec_service)
|
current_security_service=curr_sec_service)
|
||||||
|
|
||||||
if curr_sec_service is None:
|
if curr_sec_service is None:
|
||||||
@ -3565,13 +3565,13 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.NetAppException,
|
exception.NetAppException,
|
||||||
self.library.update_share_server_security_service,
|
self.library.update_share_server_security_service,
|
||||||
fake_context, fake.SHARE_SERVER, fake_net_info,
|
fake_context, fake.SHARE_SERVER, [fake_net_info],
|
||||||
new_sec_service, current_security_service=curr_sec_service)
|
new_sec_service, current_security_service=curr_sec_service)
|
||||||
|
|
||||||
mock_get_vserver.assert_called_once_with(
|
mock_get_vserver.assert_called_once_with(
|
||||||
share_server=fake.SHARE_SERVER)
|
share_server=fake.SHARE_SERVER)
|
||||||
mock_check_update.assert_called_once_with(
|
mock_check_update.assert_called_once_with(
|
||||||
fake_context, fake.SHARE_SERVER, fake_net_info,
|
fake_context, fake.SHARE_SERVER, [fake_net_info],
|
||||||
new_sec_service, current_security_service=curr_sec_service)
|
new_sec_service, current_security_service=curr_sec_service)
|
||||||
|
|
||||||
@ddt.data(
|
@ddt.data(
|
||||||
|
@ -1182,23 +1182,23 @@ class GenericShareDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
def test__setup_server(self):
|
def test__setup_server(self):
|
||||||
sim = self._driver.instance_manager
|
sim = self._driver.instance_manager
|
||||||
net_info = {
|
net_info = [{
|
||||||
'server_id': 'fake',
|
'server_id': 'fake',
|
||||||
'neutron_net_id': 'fake-net-id',
|
'neutron_net_id': 'fake-net-id',
|
||||||
'neutron_subnet_id': 'fake-subnet-id',
|
'neutron_subnet_id': 'fake-subnet-id',
|
||||||
}
|
}]
|
||||||
self._driver.setup_server(net_info)
|
self._driver.setup_server(net_info)
|
||||||
sim.set_up_service_instance.assert_called_once_with(
|
sim.set_up_service_instance.assert_called_once_with(
|
||||||
self._context, net_info)
|
self._context, net_info[0])
|
||||||
|
|
||||||
def test__setup_server_revert(self):
|
def test__setup_server_revert(self):
|
||||||
|
|
||||||
def raise_exception(*args, **kwargs):
|
def raise_exception(*args, **kwargs):
|
||||||
raise exception.ServiceInstanceException
|
raise exception.ServiceInstanceException
|
||||||
|
|
||||||
net_info = {'server_id': 'fake',
|
net_info = [{'server_id': 'fake',
|
||||||
'neutron_net_id': 'fake-net-id',
|
'neutron_net_id': 'fake-net-id',
|
||||||
'neutron_subnet_id': 'fake-subnet-id'}
|
'neutron_subnet_id': 'fake-subnet-id'}]
|
||||||
self.mock_object(self._driver.service_instance_manager,
|
self.mock_object(self._driver.service_instance_manager,
|
||||||
'set_up_service_instance',
|
'set_up_service_instance',
|
||||||
mock.Mock(side_effect=raise_exception))
|
mock.Mock(side_effect=raise_exception))
|
||||||
|
@ -447,6 +447,8 @@ class ACCESSShareDriverTestCase(test.TestCase):
|
|||||||
'share_group_stats': {'consistent_snapshot_support': None},
|
'share_group_stats': {'consistent_snapshot_support': None},
|
||||||
'snapshot_support': True,
|
'snapshot_support': True,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
'share_server_multiple_subnet_support': False,
|
||||||
|
'network_allocation_update_support': False,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.assertEqual(data, self._driver._stats)
|
self.assertEqual(data, self._driver._stats)
|
||||||
|
@ -374,6 +374,8 @@ class ZFSonLinuxShareDriverTestCase(test.TestCase):
|
|||||||
'ipv4_support': True,
|
'ipv4_support': True,
|
||||||
'ipv6_support': False,
|
'ipv6_support': False,
|
||||||
'security_service_update_support': False,
|
'security_service_update_support': False,
|
||||||
|
'share_server_multiple_subnet_support': False,
|
||||||
|
'network_allocation_update_support': False,
|
||||||
}
|
}
|
||||||
if replication_domain:
|
if replication_domain:
|
||||||
expected['replication_type'] = 'readable'
|
expected['replication_type'] = 'readable'
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -971,6 +971,37 @@ class ShareDriverTestCase(test.TestCase):
|
|||||||
{'id', 'fake_sec_service_id'},
|
{'id', 'fake_sec_service_id'},
|
||||||
current_security_service=None)
|
current_security_service=None)
|
||||||
|
|
||||||
|
def test_check_update_share_server_network_allocations(self):
|
||||||
|
share_driver = self._instantiate_share_driver(None, True)
|
||||||
|
self.assertRaises(
|
||||||
|
NotImplementedError,
|
||||||
|
share_driver.check_update_share_server_network_allocations,
|
||||||
|
'fake_context',
|
||||||
|
{'id', 'share_server_id'},
|
||||||
|
{'admin_network_allocations': [], 'subnets': []},
|
||||||
|
{"id": "fake_subnet_id"},
|
||||||
|
[{"id": "fake_security_service_id"}],
|
||||||
|
[{'id', 'fake_share_instance_id'}],
|
||||||
|
[{"id": "fake_rule_id"}])
|
||||||
|
|
||||||
|
def test_update_share_server_network_allocations(self):
|
||||||
|
share_driver = self._instantiate_share_driver(None, True)
|
||||||
|
self.assertRaises(
|
||||||
|
NotImplementedError,
|
||||||
|
share_driver.update_share_server_network_allocations,
|
||||||
|
'fake_context',
|
||||||
|
{'id', 'share_server_id'},
|
||||||
|
{'admin_network_allocations': [], 'subnets': []},
|
||||||
|
{
|
||||||
|
'share_network_subnet_id': 'fake_share_network_subnet_id',
|
||||||
|
'neutron_net_id': 'fake_neutron_net_id',
|
||||||
|
'neutron_subnet_id': 'fake_neutron_subnet_id',
|
||||||
|
'network_allocations': []
|
||||||
|
},
|
||||||
|
[{"id": "fake_security_service_id"}],
|
||||||
|
[{"id": "fake_share_id"}],
|
||||||
|
[{"id": "fake_snapshot_id"}])
|
||||||
|
|
||||||
def test_create_share_group_from_sg_snapshot_with_no_members(self):
|
def test_create_share_group_from_sg_snapshot_with_no_members(self):
|
||||||
share_driver = self._instantiate_share_driver(None, False)
|
share_driver = self._instantiate_share_driver(None, False)
|
||||||
fake_share_group_dict = {}
|
fake_share_group_dict = {}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -48,6 +48,17 @@ class ShareRpcAPITestCase(test.TestCase):
|
|||||||
share_group_snapshot = {'id': 'fake_share_group_id'}
|
share_group_snapshot = {'id': 'fake_share_group_id'}
|
||||||
host = 'fake_host'
|
host = 'fake_host'
|
||||||
share_server = db_utils.create_share_server(host=host)
|
share_server = db_utils.create_share_server(host=host)
|
||||||
|
share_network_subnet = {
|
||||||
|
'availability_zone_id': 'fake_az_id',
|
||||||
|
'neutron_net_id': 'fake_neutron_net_id',
|
||||||
|
'neutron_subnet_id': 'fake_neutron_subnet_id',
|
||||||
|
'ip_version': 4,
|
||||||
|
'cidr': '127.0.0.0/28',
|
||||||
|
'gateway': '127.0.0.1',
|
||||||
|
'mtu': 1500,
|
||||||
|
'network_type': 'vlan',
|
||||||
|
'segmentation_id': 3000,
|
||||||
|
}
|
||||||
self.fake_share = jsonutils.to_primitive(share)
|
self.fake_share = jsonutils.to_primitive(share)
|
||||||
# mock out the getattr on the share db model object since jsonutils
|
# mock out the getattr on the share db model object since jsonutils
|
||||||
# doesn't know about those extra attributes to pull in
|
# doesn't know about those extra attributes to pull in
|
||||||
@ -61,6 +72,8 @@ class ShareRpcAPITestCase(test.TestCase):
|
|||||||
self.fake_share_group_snapshot = jsonutils.to_primitive(
|
self.fake_share_group_snapshot = jsonutils.to_primitive(
|
||||||
share_group_snapshot)
|
share_group_snapshot)
|
||||||
self.fake_host = jsonutils.to_primitive(host)
|
self.fake_host = jsonutils.to_primitive(host)
|
||||||
|
self.fake_share_network_subnet = jsonutils.to_primitive(
|
||||||
|
share_network_subnet)
|
||||||
self.ctxt = context.RequestContext('fake_user', 'fake_project')
|
self.ctxt = context.RequestContext('fake_user', 'fake_project')
|
||||||
self.rpcapi = share_rpcapi.ShareAPI()
|
self.rpcapi = share_rpcapi.ShareAPI()
|
||||||
|
|
||||||
@ -476,3 +489,21 @@ class ShareRpcAPITestCase(test.TestCase):
|
|||||||
share_network_id='fake_net_id',
|
share_network_id='fake_net_id',
|
||||||
new_security_service_id='fake_sec_service_id',
|
new_security_service_id='fake_sec_service_id',
|
||||||
current_security_service_id='fake_sec_service_id')
|
current_security_service_id='fake_sec_service_id')
|
||||||
|
|
||||||
|
def test_check_update_share_server_network_allocations(self):
|
||||||
|
self._test_share_api(
|
||||||
|
'check_update_share_server_network_allocations',
|
||||||
|
rpc_method='cast',
|
||||||
|
version='1.23',
|
||||||
|
dest_host=self.fake_host,
|
||||||
|
share_network_id='fake_net_id',
|
||||||
|
new_share_network_subnet=self.fake_share_network_subnet)
|
||||||
|
|
||||||
|
def test_update_share_server_network_allocations(self):
|
||||||
|
self._test_share_api(
|
||||||
|
'update_share_server_network_allocations',
|
||||||
|
rpc_method='cast',
|
||||||
|
version='1.23',
|
||||||
|
dest_host=self.fake_host,
|
||||||
|
share_network_id='fake_net_id',
|
||||||
|
new_share_network_subnet_id='new_share_network_subnet_id')
|
||||||
|
@ -165,6 +165,33 @@ class ShareUtilsTestCase(test.TestCase):
|
|||||||
replica = share_utils.get_active_replica(replica_list)
|
replica = share_utils.get_active_replica(replica_list)
|
||||||
self.assertIsNone(replica)
|
self.assertIsNone(replica)
|
||||||
|
|
||||||
|
@ddt.data(
|
||||||
|
{'fake_subnet': [{'neutron_net_id': 'fake_nn_id',
|
||||||
|
'neutron_subnet_id': 'fake_nsb_id'}],
|
||||||
|
'fake_new_subnet': [{'neutron_net_id': 'fake_nn_id',
|
||||||
|
'neutron_subnet_id': 'fake_nsb_id'}],
|
||||||
|
'is_compatible': True},
|
||||||
|
{'fake_subnet': [{'neutron_net_id': 'fake_nn_id',
|
||||||
|
'neutron_subnet_id': 'fake_nsb_id'}],
|
||||||
|
'fake_new_subnet': [{'neutron_net_id': 'fake_nn_id',
|
||||||
|
'neutron_subnet_id': 'fake_nsb_id2'}],
|
||||||
|
'is_compatible': False},
|
||||||
|
{'fake_subnet': [{'neutron_net_id': 'fake_nn_id',
|
||||||
|
'neutron_subnet_id': 'fake_nsb_id'},
|
||||||
|
{'neutron_net_id': 'fake_nn_id2',
|
||||||
|
'neutron_subnet_id': 'fake_nsb_id2'}],
|
||||||
|
'fake_new_subnet': [{'neutron_net_id': 'fake_nn_id',
|
||||||
|
'neutron_subnet_id': 'fake_nsb_id'}],
|
||||||
|
'is_compatible': False}
|
||||||
|
)
|
||||||
|
@ddt.unpack
|
||||||
|
def test_is_az_subnets_compatible(self, fake_subnet, fake_new_subnet,
|
||||||
|
is_compatible):
|
||||||
|
expected_result = is_compatible
|
||||||
|
result = share_utils.is_az_subnets_compatible(fake_subnet,
|
||||||
|
fake_new_subnet)
|
||||||
|
self.assertEqual(expected_result, result)
|
||||||
|
|
||||||
|
|
||||||
class NotifyUsageTestCase(test.TestCase):
|
class NotifyUsageTestCase(test.TestCase):
|
||||||
@mock.patch('manila.share.utils._usage_from_share')
|
@mock.patch('manila.share.utils._usage_from_share')
|
||||||
|
@ -88,6 +88,9 @@ class NetworkBaseAPITestCase(test.TestCase):
|
|||||||
def unmanage_network_allocations(self, context, share_server_id):
|
def unmanage_network_allocations(self, context, share_server_id):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def include_network_info(self, share_network_subnet):
|
||||||
|
pass
|
||||||
|
|
||||||
self.assertRaises(TypeError, FakeNetworkAPI)
|
self.assertRaises(TypeError, FakeNetworkAPI)
|
||||||
|
|
||||||
def test_inherit_network_base_api_allocate_not_redefined(self):
|
def test_inherit_network_base_api_allocate_not_redefined(self):
|
||||||
@ -103,6 +106,9 @@ class NetworkBaseAPITestCase(test.TestCase):
|
|||||||
def unmanage_network_allocations(self, context, share_server_id):
|
def unmanage_network_allocations(self, context, share_server_id):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def include_network_info(self, share_network_subnet):
|
||||||
|
pass
|
||||||
|
|
||||||
self.assertRaises(TypeError, FakeNetworkAPI)
|
self.assertRaises(TypeError, FakeNetworkAPI)
|
||||||
|
|
||||||
def test_inherit_network_base_api(self):
|
def test_inherit_network_base_api(self):
|
||||||
@ -121,6 +127,9 @@ class NetworkBaseAPITestCase(test.TestCase):
|
|||||||
def unmanage_network_allocations(self, context, share_server_id):
|
def unmanage_network_allocations(self, context, share_server_id):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def include_network_info(self, share_network_subnet):
|
||||||
|
pass
|
||||||
|
|
||||||
result = FakeNetworkAPI()
|
result = FakeNetworkAPI()
|
||||||
|
|
||||||
self.assertTrue(hasattr(result, '_verify_share_network'))
|
self.assertTrue(hasattr(result, '_verify_share_network'))
|
||||||
@ -143,6 +152,9 @@ class NetworkBaseAPITestCase(test.TestCase):
|
|||||||
def unmanage_network_allocations(self, context, share_server_id):
|
def unmanage_network_allocations(self, context, share_server_id):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def include_network_info(self, share_network_subnet):
|
||||||
|
pass
|
||||||
|
|
||||||
result = FakeNetworkAPI()
|
result = FakeNetworkAPI()
|
||||||
|
|
||||||
result._verify_share_network('foo_id', {'id': 'bar_id'})
|
result._verify_share_network('foo_id', {'id': 'bar_id'})
|
||||||
@ -163,6 +175,9 @@ class NetworkBaseAPITestCase(test.TestCase):
|
|||||||
def unmanage_network_allocations(self, context, share_server_id):
|
def unmanage_network_allocations(self, context, share_server_id):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def include_network_info(self, share_network_subnet):
|
||||||
|
pass
|
||||||
|
|
||||||
result = FakeNetworkAPI()
|
result = FakeNetworkAPI()
|
||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
@ -190,10 +205,13 @@ class NetworkBaseAPITestCase(test.TestCase):
|
|||||||
def unmanage_network_allocations(self, context, share_server_id):
|
def unmanage_network_allocations(self, context, share_server_id):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
network.CONF.set_default('network_plugin_ipv6_enabled',
|
def include_network_info(self, share_network_subnet):
|
||||||
network_plugin_ipv6_enabled)
|
pass
|
||||||
network.CONF.set_default('network_plugin_ipv4_enabled',
|
|
||||||
network_plugin_ipv4_enabled)
|
network.CONF.set_default(
|
||||||
|
'network_plugin_ipv6_enabled', network_plugin_ipv6_enabled)
|
||||||
|
network.CONF.set_default(
|
||||||
|
'network_plugin_ipv4_enabled', network_plugin_ipv4_enabled)
|
||||||
|
|
||||||
result = FakeNetworkAPI()
|
result = FakeNetworkAPI()
|
||||||
|
|
||||||
|
@ -89,6 +89,7 @@ class ServiceFlagsTestCase(test.TestCase):
|
|||||||
app = service.Service.create(host=host, binary=binary)
|
app = service.Service.create(host=host, binary=binary)
|
||||||
app.start()
|
app.start()
|
||||||
app.stop()
|
app.stop()
|
||||||
|
app.wait()
|
||||||
ref = db.service_get(context.get_admin_context(), app.service_id)
|
ref = db.service_get(context.get_admin_context(), app.service_id)
|
||||||
db.service_destroy(context.get_admin_context(), app.service_id)
|
db.service_destroy(context.get_admin_context(), app.service_id)
|
||||||
self.assertFalse(ref['disabled'])
|
self.assertFalse(ref['disabled'])
|
||||||
@ -123,6 +124,13 @@ service_create = {
|
|||||||
'report_count': 0,
|
'report_count': 0,
|
||||||
'availability_zone': 'nova',
|
'availability_zone': 'nova',
|
||||||
}
|
}
|
||||||
|
service_create_other_az = {
|
||||||
|
'host': host,
|
||||||
|
'binary': binary,
|
||||||
|
'topic': topic,
|
||||||
|
'report_count': 0,
|
||||||
|
'availability_zone': 'other-zone',
|
||||||
|
}
|
||||||
service_ref = {
|
service_ref = {
|
||||||
'host': host,
|
'host': host,
|
||||||
'binary': binary,
|
'binary': binary,
|
||||||
@ -200,6 +208,58 @@ class ServiceTestCase(test.TestCase):
|
|||||||
service.db.service_update.assert_called_once_with(
|
service.db.service_update.assert_called_once_with(
|
||||||
mock.ANY, service_ref['id'], mock.ANY)
|
mock.ANY, service_ref['id'], mock.ANY)
|
||||||
|
|
||||||
|
@mock.patch.object(service.db, 'service_get_by_args',
|
||||||
|
mock.Mock(side_effect=fake_service_get_by_args))
|
||||||
|
@mock.patch.object(service.db, 'service_create',
|
||||||
|
mock.Mock(return_value=service_ref))
|
||||||
|
@mock.patch.object(service.db, 'service_get',
|
||||||
|
mock.Mock(return_value=service_ref))
|
||||||
|
@mock.patch.object(service.db, 'service_update',
|
||||||
|
mock.Mock(return_value=service_ref.
|
||||||
|
update({'report_count': 1})))
|
||||||
|
def test_report_state_newly_connected_different_az(self):
|
||||||
|
serv = service.Service(host, binary, topic, CONF.fake_manager)
|
||||||
|
serv.availability_zone = 'other-zone'
|
||||||
|
serv.start()
|
||||||
|
serv.model_disconnected = True
|
||||||
|
serv.report_state()
|
||||||
|
self.assertFalse(serv.model_disconnected)
|
||||||
|
service.db.service_get_by_args.assert_called_once_with(
|
||||||
|
mock.ANY, host, binary)
|
||||||
|
service.db.service_create.assert_called_once_with(
|
||||||
|
mock.ANY, service_create_other_az)
|
||||||
|
service.db.service_get.assert_called_once_with(
|
||||||
|
mock.ANY, service_ref['id'])
|
||||||
|
service.db.service_update.assert_called_once_with(
|
||||||
|
mock.ANY, service_ref['id'], mock.ANY)
|
||||||
|
|
||||||
|
@mock.patch.object(service.db, 'service_get_by_args',
|
||||||
|
mock.Mock(side_effect=fake_service_get_by_args))
|
||||||
|
@mock.patch.object(service.db, 'service_create',
|
||||||
|
mock.Mock(return_value=service_ref))
|
||||||
|
@mock.patch.object(service.db, 'service_get',
|
||||||
|
mock.Mock(side_effect=[exception.NotFound,
|
||||||
|
service_ref]))
|
||||||
|
@mock.patch.object(service.db, 'service_update',
|
||||||
|
mock.Mock(return_value=service_ref.
|
||||||
|
update({'report_count': 1})))
|
||||||
|
def test_report_state_newly_connected_not_found(self):
|
||||||
|
serv = service.Service(host, binary, topic, CONF.fake_manager)
|
||||||
|
serv.start()
|
||||||
|
serv.model_disconnected = True
|
||||||
|
serv.report_state()
|
||||||
|
self.assertFalse(serv.model_disconnected)
|
||||||
|
service.db.service_get_by_args.assert_called_once_with(
|
||||||
|
mock.ANY, host, binary)
|
||||||
|
service.db.service_create.assert_has_calls([
|
||||||
|
mock.call(mock.ANY, service_create),
|
||||||
|
mock.call(mock.ANY, service_create)])
|
||||||
|
service.db.service_get.assert_has_calls([
|
||||||
|
mock.call(mock.ANY, service_ref['id']),
|
||||||
|
mock.call(mock.ANY, service_ref['id'])])
|
||||||
|
service.db.service_update.assert_called_once_with(
|
||||||
|
mock.ANY, service_ref['id'], mock.ANY)
|
||||||
|
|
||||||
def test_report_state_service_not_ready(self):
|
def test_report_state_service_not_ready(self):
|
||||||
with mock.patch.object(service, 'db') as mock_db:
|
with mock.patch.object(service, 'db') as mock_db:
|
||||||
mock_db.service_get.return_value = service_ref
|
mock_db.service_get.return_value = service_ref
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Add support for multiple subnet per availability zone. The multiple
|
||||||
|
configuration can be done either on share server deployment or updating
|
||||||
|
a pre-existent share server.
|
||||||
|
|
||||||
|
The new field ``network_allocation_update_support`` was added to share
|
||||||
|
server's model This field defaults to ``False``, and all of the
|
||||||
|
already deployed share servers are going to get the default value even if
|
||||||
|
their backend support it. Administrators will be able to update the field
|
||||||
|
value using ``manila-manage`` commands.
|
||||||
|
|
||||||
|
The driver will report its support for adding a subnet on a pre-existent
|
||||||
|
share server through ``network_allocation_update_support``. Also, it will
|
||||||
|
report the support for creating the server with multiple subnets with the
|
||||||
|
``share_server_multiple_subnet_support``. The scheduler will filter out
|
||||||
|
backend that does not handle this request during some operations. Example,
|
||||||
|
creating a share with a share network containing multiple subnets, only
|
||||||
|
hosts that support this deployment will be selected.
|
||||||
|
deprecations:
|
||||||
|
- |
|
||||||
|
Remove 'share_network_subnet_id' attribute from share server view and
|
||||||
|
add 'share_network_subnet_ids' starting with microversion '2.70'. The share
|
||||||
|
server has a list of subnets.
|
Loading…
Reference in New Issue
Block a user