Share servers implementation
Change-Id: I90664235237e25190191a4499e513a9fe589b855
This commit is contained in:
parent
74a41f35a1
commit
2c7595a386
|
@ -184,17 +184,3 @@ class SharesAdminQuotasNegativeTest(base.BaseSharesAdminTest):
|
|||
client.creds["tenant"]["id"],
|
||||
client.creds["user"]["id"],
|
||||
share_networks=bigger_value)
|
||||
|
||||
@test.attr(type=["gate", "smoke", "negative"])
|
||||
def test_try_activate_share_network_with_overlimit(self):
|
||||
client = self.get_client_with_isolated_creads()
|
||||
|
||||
# set new quota for shares
|
||||
resp, __ = client.update_quotas(client.creds["tenant"]["id"],
|
||||
share_networks=0)
|
||||
self.assertIn(int(resp["status"]), test.HTTP_SUCCESS)
|
||||
|
||||
# Try activate share-network without enough quota
|
||||
self.assertRaises(exceptions.OverLimit,
|
||||
client.activate_share_network,
|
||||
sn_id=client.share_network_id)
|
||||
|
|
|
@ -235,14 +235,7 @@ class BaseSharesTest(test.BaseTestCase):
|
|||
client = cls.shares_client
|
||||
if description is None:
|
||||
description = "Tempest's share"
|
||||
if (share_network_id or client.share_network_id):
|
||||
share_network_id = share_network_id or client.share_network_id
|
||||
__, body = client.get_share_network(share_network_id)
|
||||
if body["status"].lower() == "inactive":
|
||||
resp, __ = client.activate_share_network(share_network_id)
|
||||
assert (int(resp["status"]) in test.HTTP_SUCCESS)
|
||||
client.wait_for_share_network_status(share_network_id,
|
||||
"active")
|
||||
share_network_id = share_network_id or client.share_network_id or None
|
||||
r, s = client.create_share(share_protocol=share_protocol, size=size,
|
||||
name=name, snapshot_id=snapshot_id,
|
||||
description=description,
|
||||
|
@ -374,11 +367,6 @@ class BaseSharesTest(test.BaseTestCase):
|
|||
client.delete_snapshot(res_id)
|
||||
client.wait_for_resource_deletion(snapshot_id=res_id)
|
||||
elif res["type"] is "share_network":
|
||||
__, body = client.get_share_network(res_id)
|
||||
if body["status"].lower() == "active":
|
||||
client.deactivate_share_network(res_id)
|
||||
client.wait_for_share_network_status(res_id,
|
||||
"inactive")
|
||||
client.delete_share_network(res_id)
|
||||
client.wait_for_resource_deletion(sn_id=res_id)
|
||||
elif res["type"] is "security_service":
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
# Copyright 2014 mirantis Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.api.share import base
|
||||
from tempest import clients_share as clients
|
||||
from tempest import exceptions
|
||||
from tempest import test
|
||||
|
||||
|
||||
class SharenetworkActivationTest(base.BaseSharesTest):
|
||||
"""For testing activation of share-networks.
|
||||
|
||||
Here all test cases were combined in one test method,
|
||||
because its too expensive to activate new share-network
|
||||
for each test. Activation can take about 2 minutes.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.os = clients.Manager(interface=cls._interface)
|
||||
|
||||
# Redefine share_network_id, because we do not need it
|
||||
cls.os.shares_client.share_network_id = "fake"
|
||||
super(SharenetworkActivationTest, cls).setUpClass()
|
||||
|
||||
@test.attr(type=["gate", ])
|
||||
def test_share_network_activation_deactivation(self):
|
||||
|
||||
# Get isolated client
|
||||
client = self.get_client_with_isolated_creads(type_of_creds="admin")
|
||||
|
||||
# Try create share with inactive share-network
|
||||
self.assertRaises(exceptions.BadRequest,
|
||||
client.create_share,
|
||||
share_network_id=client.share_network_id, )
|
||||
|
||||
# Activate share-network
|
||||
resp, __ = client.activate_share_network(client.share_network_id)
|
||||
self.assertIn(int(resp["status"]), test.HTTP_SUCCESS)
|
||||
client.wait_for_share_network_status(client.share_network_id)
|
||||
|
||||
# Create share
|
||||
resp, share = self.create_share_wait_for_active(client=client)
|
||||
self.assertIn(int(resp["status"]), test.HTTP_SUCCESS)
|
||||
|
||||
# Try deactivate
|
||||
self.assertRaises(exceptions.BadRequest,
|
||||
client.deactivate_share_network,
|
||||
client.share_network_id)
|
||||
|
||||
# Delete share
|
||||
resp, __ = client.delete_share(share["id"])
|
||||
self.assertIn(int(resp["status"]), test.HTTP_SUCCESS)
|
||||
client.wait_for_resource_deletion(share_id=share["id"])
|
||||
|
||||
# Deactivate
|
||||
resp, __ = client.deactivate_share_network(client.share_network_id)
|
||||
self.assertIn(int(resp["status"]), test.HTTP_SUCCESS)
|
||||
client.wait_for_share_network_status(client.share_network_id,
|
||||
"inactive")
|
||||
|
||||
# Try create share with inactive share-network
|
||||
self.assertRaises(exceptions.BadRequest,
|
||||
client.create_share,
|
||||
share_network_id=client.share_network_id, )
|
||||
|
||||
# Verify that no shares exist
|
||||
resp, shares = client.list_shares()
|
||||
self.assertIn(int(resp["status"]), test.HTTP_SUCCESS)
|
||||
self.assertEqual(0, len(shares))
|
|
@ -49,7 +49,6 @@ SHARE_NETWORK_ATTRS = (
|
|||
'ip_version',
|
||||
'name',
|
||||
'description',
|
||||
'status',
|
||||
)
|
||||
|
||||
|
||||
|
@ -107,13 +106,22 @@ class ShareNetworkController(wsgi.Controller):
|
|||
except exception.ShareNetworkNotFound as e:
|
||||
msg = "%s" % e
|
||||
raise exc.HTTPNotFound(explanation=msg)
|
||||
|
||||
if share_network['status'] == constants.STATUS_ACTIVE:
|
||||
msg = "Network %s is in use" % id
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
if share_network['share_servers']:
|
||||
msg = _("Cannot delete share network %s. "
|
||||
"There are share servers using it") % id
|
||||
raise exc.HTTPForbidden(explanation=msg)
|
||||
db_api.share_network_delete(context, id)
|
||||
|
||||
try:
|
||||
reservations = QUOTAS.reserve(
|
||||
context, project_id=share_network['project_id'],
|
||||
share_networks=-1)
|
||||
except Exception:
|
||||
msg = _("Failed to update usages deleting share-network.")
|
||||
LOG.exception(msg)
|
||||
else:
|
||||
QUOTAS.commit(context, reservations,
|
||||
project_id=share_network['project_id'])
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@wsgi.serializers(xml=ShareNetworksTemplate)
|
||||
|
@ -163,9 +171,10 @@ class ShareNetworkController(wsgi.Controller):
|
|||
msg = "%s" % e
|
||||
raise exc.HTTPNotFound(explanation=msg)
|
||||
|
||||
if share_network['status'] == constants.STATUS_ACTIVE:
|
||||
msg = "Network %s is in use" % id
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
if share_network['share_servers']:
|
||||
msg = _("Cannot update share network %s."
|
||||
" It is used by share servers") % share_network['id']
|
||||
raise exc.HTTPForbidden(explanation=msg)
|
||||
|
||||
update_values = body[RESOURCE_NAME]
|
||||
|
||||
|
@ -192,20 +201,39 @@ class ShareNetworkController(wsgi.Controller):
|
|||
values['project_id'] = context.project_id
|
||||
|
||||
try:
|
||||
share_network = db_api.share_network_create(context, values)
|
||||
except exception.DBError:
|
||||
msg = "Could not save supplied data due to database error"
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
reservations = QUOTAS.reserve(context, share_networks=1)
|
||||
except exception.OverQuota as e:
|
||||
overs = e.kwargs['overs']
|
||||
usages = e.kwargs['usages']
|
||||
quotas = e.kwargs['quotas']
|
||||
|
||||
return self._view_builder.build_share_network(share_network)
|
||||
def _consumed(name):
|
||||
return (usages[name]['reserved'] + usages[name]['in_use'])
|
||||
|
||||
if 'share_networks' in overs:
|
||||
msg = _("Quota exceeded for %(s_pid)s, tried to create"
|
||||
" share-network (%(d_consumed)d of %(d_quota)d "
|
||||
"already consumed)")
|
||||
LOG.warn(msg % {'s_pid': context.project_id,
|
||||
'd_consumed': _consumed('share_networks'),
|
||||
'd_quota': quotas['share_networks']})
|
||||
raise exception.ShareNetworksLimitExceeded(
|
||||
allowed=quotas['share_networks'])
|
||||
else:
|
||||
try:
|
||||
share_network = db_api.share_network_create(context, values)
|
||||
except exception.DBError:
|
||||
msg = "Could not save supplied data due to database error"
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
QUOTAS.commit(context, reservations)
|
||||
return self._view_builder.build_share_network(share_network)
|
||||
|
||||
@wsgi.serializers(xml=ShareNetworkTemplate)
|
||||
def action(self, req, id, body):
|
||||
_actions = {
|
||||
'add_security_service': self._add_security_service,
|
||||
'remove_security_service': self._remove_security_service,
|
||||
'activate': self._activate,
|
||||
'deactivate': self._deactivate,
|
||||
'remove_security_service': self._remove_security_service
|
||||
}
|
||||
for action, data in body.iteritems():
|
||||
try:
|
||||
|
@ -218,6 +246,10 @@ class ShareNetworkController(wsgi.Controller):
|
|||
"""Associate share network with a given security service."""
|
||||
context = req.environ['manila.context']
|
||||
policy.check_policy(context, RESOURCE_NAME, 'add_security_service')
|
||||
share_network = db_api.share_network_get(context, id)
|
||||
if share_network['share_servers']:
|
||||
msg = _("Cannot add security services. Share network is used.")
|
||||
raise exc.HTTPForbidden(explanation=msg)
|
||||
try:
|
||||
share_network = db_api.share_network_add_security_service(
|
||||
context,
|
||||
|
@ -256,67 +288,6 @@ class ShareNetworkController(wsgi.Controller):
|
|||
|
||||
return self._view_builder.build_share_network(share_network)
|
||||
|
||||
def _activate(self, req, id, data):
|
||||
"""Activate share network."""
|
||||
context = req.environ['manila.context']
|
||||
policy.check_policy(context, RESOURCE_NAME, 'activate')
|
||||
|
||||
try:
|
||||
reservations = QUOTAS.reserve(context, share_networks=1)
|
||||
except exception.OverQuota as e:
|
||||
overs = e.kwargs['overs']
|
||||
usages = e.kwargs['usages']
|
||||
quotas = e.kwargs['quotas']
|
||||
|
||||
def _consumed(name):
|
||||
return (usages[name]['reserved'] + usages[name]['in_use'])
|
||||
|
||||
if 'share_networks' in overs:
|
||||
msg = _("Quota exceeded for %(s_pid)s, tried to activate"
|
||||
" share-network (%(d_consumed)d of %(d_quota)d "
|
||||
"already consumed)")
|
||||
LOG.warn(msg % {'s_pid': context.project_id,
|
||||
'd_consumed': _consumed('share_networks'),
|
||||
'd_quota': quotas['share_networks']})
|
||||
raise exception.ActivatedShareNetworksLimitExceeded(
|
||||
allowed=quotas['share_networks'])
|
||||
else:
|
||||
try:
|
||||
share_network = db_api.share_network_get(context, id)
|
||||
except exception.ShareNetworkNotFound as e:
|
||||
msg = _("Share-network was not found. %s") % e
|
||||
raise exc.HTTPNotFound(explanation=msg)
|
||||
|
||||
if share_network['status'] != constants.STATUS_INACTIVE:
|
||||
msg = _("Share network should be 'INACTIVE'.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
self.share_rpcapi.activate_network(context, id, data)
|
||||
QUOTAS.commit(context, reservations)
|
||||
return self._view_builder.build_share_network(share_network)
|
||||
|
||||
def _deactivate(self, req, id, data):
|
||||
context = req.environ['manila.context']
|
||||
policy.check_policy(context, RESOURCE_NAME, 'deactivate')
|
||||
|
||||
try:
|
||||
share_network = db_api.share_network_get(context, id)
|
||||
except exception.ShareNetworkNotFound as e:
|
||||
msg = _("Share-network was not found. %s") % e
|
||||
raise exc.HTTPNotFound(explanation=msg)
|
||||
|
||||
if share_network['status'] != constants.STATUS_ACTIVE:
|
||||
msg = _("Share network should be 'ACTIVE'.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
if len(share_network['shares']) > 0:
|
||||
msg = _("Share network is in use.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
self.share_rpcapi.deactivate_network(context, id)
|
||||
|
||||
return self._view_builder.build_share_network(share_network)
|
||||
|
||||
|
||||
def create_resource():
|
||||
return wsgi.Resource(ShareNetworkController())
|
||||
|
|
|
@ -210,12 +210,7 @@ class ShareController(wsgi.Controller):
|
|||
except exception.ShareNetworkNotFound as e:
|
||||
msg = "%s" % e
|
||||
raise exc.HTTPNotFound(explanation=msg)
|
||||
if share_network['status'] != constants.STATUS_ACTIVE:
|
||||
msg = _("Share network '%s' is not in 'ACTIVE' state.")
|
||||
msg = msg % share_network["id"]
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
else:
|
||||
kwargs['share_network_id'] = share_network_id
|
||||
kwargs['share_network_id'] = share_network_id
|
||||
|
||||
display_name = share.get('display_name')
|
||||
display_description = share.get('display_description')
|
||||
|
|
|
@ -30,6 +30,7 @@ from manila.db import base
|
|||
from manila import exception
|
||||
from manila.openstack.common import log as logging
|
||||
|
||||
|
||||
nova_opts = [
|
||||
cfg.StrOpt('nova_catalog_info',
|
||||
default='compute:nova:publicURL',
|
||||
|
|
|
@ -547,6 +547,66 @@ def network_allocation_update(context, id, values):
|
|||
return IMPL.network_allocation_update(context, id, values)
|
||||
|
||||
|
||||
def network_allocations_get_for_share_server(context, share_server_id,
|
||||
session=None):
|
||||
"""Get netwwork allocation for share server."""
|
||||
return IMPL.network_allocations_get_for_share_server(context,
|
||||
share_server_id,
|
||||
session=session)
|
||||
|
||||
|
||||
##################
|
||||
|
||||
|
||||
def share_server_create(context, values):
|
||||
"""Create share server DB record."""
|
||||
return IMPL.share_server_create(context, values)
|
||||
|
||||
|
||||
def share_server_delete(context, id):
|
||||
"""Delete share server DB record."""
|
||||
return IMPL.share_server_delete(context, id)
|
||||
|
||||
|
||||
def share_server_update(context, id, values):
|
||||
"""Update share server DB record."""
|
||||
return IMPL.share_server_update(context, id, values)
|
||||
|
||||
|
||||
def share_server_get(context, id, session=None):
|
||||
"""Get share server DB record by ID."""
|
||||
return IMPL.share_server_get(context, id, session=session)
|
||||
|
||||
|
||||
def share_server_get_by_host(context, host, share_net_id, session=None):
|
||||
"""Get share server DB records by host"""
|
||||
return IMPL.share_server_get_by_host(context, host, share_net_id,
|
||||
session=session)
|
||||
|
||||
|
||||
def share_server_get_by_host_and_share_net(context, host, share_net_id,
|
||||
session=None):
|
||||
"""Get share server DB records by host and share net"""
|
||||
return IMPL.share_server_get_by_host_and_share_net(context, host,
|
||||
share_net_id,
|
||||
session=session)
|
||||
|
||||
|
||||
def share_server_get_by_host_and_share_net_valid(context, host,
|
||||
share_net_id,
|
||||
session=None):
|
||||
"""Get share server DB records by host and share net not error"""
|
||||
return IMPL.share_server_get_by_host_and_share_net_valid(context,
|
||||
host,
|
||||
share_net_id,
|
||||
session=session)
|
||||
|
||||
|
||||
def share_server_get_all(context):
|
||||
"""Get all share server DB records."""
|
||||
return IMPL.share_server_get_all(context)
|
||||
|
||||
|
||||
##################
|
||||
|
||||
|
||||
|
|
|
@ -1511,8 +1511,8 @@ def _network_get_query(context, session=None):
|
|||
session = get_session()
|
||||
return model_query(context, models.ShareNetwork, session=session).\
|
||||
options(joinedload('shares'),
|
||||
joinedload('network_allocations'),
|
||||
joinedload('security_services'))
|
||||
joinedload('security_services'),
|
||||
joinedload('share_servers'))
|
||||
|
||||
|
||||
@require_context
|
||||
|
@ -1599,14 +1599,6 @@ def share_network_add_security_service(context, id, security_service_id):
|
|||
reason=msg)
|
||||
|
||||
share_nw_ref = share_network_get(context, id, session=session)
|
||||
|
||||
if share_nw_ref['status'] == constants.STATUS_ACTIVE:
|
||||
msg = "Share network is active"
|
||||
raise exception.ShareNetworkSecurityServiceAssociationError(
|
||||
share_network_id=id,
|
||||
security_service_id=security_service_id,
|
||||
reason=msg)
|
||||
|
||||
security_service_ref = security_service_get(context,
|
||||
security_service_id,
|
||||
session=session)
|
||||
|
@ -1646,6 +1638,81 @@ def share_network_remove_security_service(context, id, security_service_id):
|
|||
###################
|
||||
|
||||
|
||||
def _server_get_query(context, session=None):
|
||||
if session is None:
|
||||
session = get_session()
|
||||
return model_query(context, models.ShareServer, session=session)
|
||||
|
||||
|
||||
@require_context
|
||||
def share_server_create(context, values):
|
||||
if not values.get('id'):
|
||||
values['id'] = str(uuid.uuid4())
|
||||
server_ref = models.ShareServer()
|
||||
server_ref.update(values)
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
server_ref.save(session=session)
|
||||
return server_ref
|
||||
|
||||
|
||||
@require_context
|
||||
def share_server_delete(context, id):
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
server_ref = share_server_get(context, id, session=session)
|
||||
server_ref.delete(session=session)
|
||||
|
||||
|
||||
@require_context
|
||||
def share_server_update(context, id, values):
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
server_ref = share_server_get(context, id, session=session)
|
||||
server_ref.update(values)
|
||||
server_ref.save(session=session)
|
||||
return server_ref
|
||||
|
||||
|
||||
@require_context
|
||||
def share_server_get(context, server_id, session=None):
|
||||
result = _server_get_query(context, session).filter_by(id=server_id)\
|
||||
.first()
|
||||
if result is None:
|
||||
raise exception.ShareServerNotFound(share_server_id=server_id)
|
||||
return result
|
||||
|
||||
|
||||
@require_context
|
||||
def share_server_get_by_host_and_share_net(context, host, share_net_id,
|
||||
session=None):
|
||||
result = _server_get_query(context, session).filter_by(host=host)\
|
||||
.filter_by(share_network_id=share_net_id).all()
|
||||
if result is None:
|
||||
raise exception.ShareServerNotFound(share_server_id=id)
|
||||
return result
|
||||
|
||||
|
||||
@require_context
|
||||
def share_server_get_by_host_and_share_net_valid(context, host, share_net_id,
|
||||
session=None):
|
||||
result = _server_get_query(context, session).filter_by(host=host)\
|
||||
.filter_by(share_network_id=share_net_id)\
|
||||
.filter(models.ShareServer.status.in_(
|
||||
(constants.STATUS_CREATING, constants.STATUS_ACTIVE))).first()
|
||||
if result is None:
|
||||
raise exception.ShareServerNotFound(share_server_id=id)
|
||||
return result
|
||||
|
||||
|
||||
@require_context
|
||||
def share_server_get_all(context):
|
||||
return _server_get_query(context).all()
|
||||
|
||||
|
||||
###################
|
||||
|
||||
|
||||
@require_context
|
||||
def network_allocation_create(context, values):
|
||||
alloc_ref = models.NetworkAllocation()
|
||||
|
@ -1675,6 +1742,16 @@ def network_allocation_get(context, id, session=None):
|
|||
return result
|
||||
|
||||
|
||||
@require_context
|
||||
def network_allocations_get_for_share_server(context, share_server_id,
|
||||
session=None):
|
||||
if session is None:
|
||||
session = get_session()
|
||||
result = model_query(context, models.NetworkAllocation, session=session).\
|
||||
filter_by(share_server_id=share_server_id).all()
|
||||
return result
|
||||
|
||||
|
||||
@require_context
|
||||
def network_allocation_update(context, id, values):
|
||||
session = get_session()
|
||||
|
|
|
@ -198,6 +198,10 @@ def upgrade(migrate_engine):
|
|||
String(length=36),
|
||||
ForeignKey('share_networks.id'),
|
||||
nullable=True),
|
||||
Column('share_server_id',
|
||||
String(length=36),
|
||||
ForeignKey('share_servers.id'),
|
||||
nullable=True),
|
||||
Column('share_proto', String(255)),
|
||||
Column('export_location', String(255)),
|
||||
Column('volume_type_id', String(length=36)),
|
||||
|
@ -297,6 +301,20 @@ def upgrade(migrate_engine):
|
|||
Column('ip_version', Integer, nullable=True),
|
||||
Column('name', String(length=255), nullable=True),
|
||||
Column('description', String(length=255), nullable=True),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8',
|
||||
)
|
||||
|
||||
share_servers = Table(
|
||||
'share_servers', meta,
|
||||
Column('created_at', DateTime),
|
||||
Column('updated_at', DateTime),
|
||||
Column('deleted_at', DateTime),
|
||||
Column('deleted', String(length=36), default='False'),
|
||||
Column('id', String(length=36), primary_key=True, nullable=False),
|
||||
Column('share_network_id', String(length=36),
|
||||
ForeignKey('share_networks.id'), nullable=True),
|
||||
Column('host', String(length=255), nullable=True),
|
||||
Column('status', String(length=32)),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8',
|
||||
|
@ -311,8 +329,8 @@ def upgrade(migrate_engine):
|
|||
Column('id', String(length=36), primary_key=True, nullable=False),
|
||||
Column('ip_address', String(length=64), nullable=True),
|
||||
Column('mac_address', String(length=32), nullable=True),
|
||||
Column('share_network_id', String(length=36),
|
||||
ForeignKey('share_networks.id'), nullable=False),
|
||||
Column('share_server_id', String(length=36),
|
||||
ForeignKey('share_servers.id'), nullable=False),
|
||||
Column('status', String(length=32)),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8',
|
||||
|
@ -363,9 +381,10 @@ def upgrade(migrate_engine):
|
|||
# Take care on create order for those with FK dependencies
|
||||
tables = [migrations, quotas, services, quota_classes, quota_usages,
|
||||
reservations, project_user_quotas, security_services,
|
||||
share_networks, network_allocations, ss_nw_association,
|
||||
shares, access_map, share_snapshots, share_metadata,
|
||||
volume_types, volume_type_extra_specs]
|
||||
share_networks, ss_nw_association,
|
||||
share_servers, network_allocations, shares, access_map,
|
||||
share_snapshots,
|
||||
share_metadata, volume_types, volume_type_extra_specs]
|
||||
|
||||
for table in tables:
|
||||
try:
|
||||
|
@ -380,8 +399,9 @@ def upgrade(migrate_engine):
|
|||
"quota_classes", "quota_usages", "reservations",
|
||||
"project_user_quotas", "share_access_map", "share_snapshots",
|
||||
"share_metadata", "security_services", "share_networks",
|
||||
"network_allocations", "shares",
|
||||
"share_network_security_service_association"]
|
||||
"network_allocations", "shares", "share_servers",
|
||||
"share_network_security_service_association", "volume_types",
|
||||
"volume_type_extra_specs"]
|
||||
|
||||
sql = "SET foreign_key_checks = 0;"
|
||||
for table in tables:
|
||||
|
|
|
@ -267,6 +267,8 @@ class Share(BASE, ManilaBase):
|
|||
nullable=True)
|
||||
volume_type_id = Column(String(36), ForeignKey('volume_types.id'),
|
||||
nullable=True)
|
||||
share_server_id = Column(String(36), ForeignKey('share_servers.id'),
|
||||
nullable=True)
|
||||
|
||||
|
||||
class VolumeTypes(BASE, ManilaBase):
|
||||
|
@ -387,7 +389,7 @@ class SecurityService(BASE, ManilaBase):
|
|||
|
||||
|
||||
class ShareNetwork(BASE, ManilaBase):
|
||||
"Represents network data used by share."
|
||||
"""Represents network data used by share."""
|
||||
__tablename__ = 'share_networks'
|
||||
id = Column(String(36), primary_key=True, nullable=False)
|
||||
deleted = Column(String(36), default='False')
|
||||
|
@ -401,9 +403,6 @@ class ShareNetwork(BASE, ManilaBase):
|
|||
ip_version = Column(Integer, nullable=True)
|
||||
name = Column(String(255), nullable=True)
|
||||
description = Column(String(255), nullable=True)
|
||||
status = Column(Enum(constants.STATUS_INACTIVE, constants.STATUS_ACTIVE,
|
||||
constants.STATUS_ERROR),
|
||||
default=constants.STATUS_INACTIVE)
|
||||
security_services = relationship("SecurityService",
|
||||
secondary="share_network_security_service_association",
|
||||
backref="share_networks",
|
||||
|
@ -416,15 +415,37 @@ class ShareNetwork(BASE, ManilaBase):
|
|||
'SecurityService.id == '
|
||||
'ShareNetworkSecurityServiceAssociation.security_service_id,'
|
||||
'SecurityService.deleted == "False")')
|
||||
network_allocations = relationship("NetworkAllocation",
|
||||
primaryjoin='and_('
|
||||
'ShareNetwork.id == NetworkAllocation.share_network_id,'
|
||||
'NetworkAllocation.deleted == "False")')
|
||||
shares = relationship("Share",
|
||||
backref='share_network',
|
||||
primaryjoin='and_('
|
||||
'ShareNetwork.id == Share.share_network_id,'
|
||||
'Share.deleted == "False")')
|
||||
share_servers = relationship(
|
||||
"ShareServer", backref='share_network',
|
||||
primaryjoin='and_(ShareNetwork.id == ShareServer.share_network_id,'
|
||||
'ShareServer.deleted == "False")')
|
||||
|
||||
|
||||
class ShareServer(BASE, ManilaBase):
|
||||
"""Represents share server used by share."""
|
||||
__tablename__ = 'share_servers'
|
||||
id = Column(String(36), primary_key=True, nullable=False)
|
||||
deleted = Column(String(36), default='False')
|
||||
share_network_id = Column(String(36), ForeignKey('share_networks.id'),
|
||||
nullable=True)
|
||||
host = Column(String(255), nullable=False)
|
||||
status = Column(Enum(constants.STATUS_INACTIVE, constants.STATUS_ACTIVE,
|
||||
constants.STATUS_ERROR),
|
||||
default=constants.STATUS_INACTIVE)
|
||||
network_allocations = relationship("NetworkAllocation",
|
||||
primaryjoin='and_('
|
||||
'ShareServer.id == NetworkAllocation.share_server_id,'
|
||||
'NetworkAllocation.deleted == "False")')
|
||||
shares = relationship("Share",
|
||||
backref='share_server',
|
||||
primaryjoin='and_('
|
||||
'ShareServer.id == Share.share_server_id,'
|
||||
'Share.deleted == "False")')
|
||||
|
||||
|
||||
class ShareNetworkSecurityServiceAssociation(BASE, ManilaBase):
|
||||
|
@ -442,14 +463,14 @@ class ShareNetworkSecurityServiceAssociation(BASE, ManilaBase):
|
|||
|
||||
|
||||
class NetworkAllocation(BASE, ManilaBase):
|
||||
"Represents network allocation data."
|
||||
"""Represents network allocation data."""
|
||||
__tablename__ = 'network_allocations'
|
||||
id = Column(String(36), primary_key=True, nullable=False)
|
||||
deleted = Column(String(36), default='False')
|
||||
ip_address = Column(String(64), nullable=True)
|
||||
mac_address = Column(String(32), nullable=True)
|
||||
share_network_id = Column(String(36), ForeignKey('share_networks.id'),
|
||||
nullable=False)
|
||||
share_server_id = Column(String(36), ForeignKey('share_servers.id'),
|
||||
nullable=False)
|
||||
status = Column(Enum(constants.STATUS_NEW, constants.STATUS_ACTIVE,
|
||||
constants.STATUS_ERROR),
|
||||
default=constants.STATUS_NEW)
|
||||
|
|
|
@ -235,6 +235,18 @@ class ShareNetworkNotFound(NotFound):
|
|||
message = _("Network %(share_network_id)s could not be found.")
|
||||
|
||||
|
||||
class ShareServerNotFound(NotFound):
|
||||
message = _("Share Server %(share_server_id)s could not be found.")
|
||||
|
||||
|
||||
class ShareServerInUse(InUse):
|
||||
message = _("Share Server %(share_server_id)s is in use.")
|
||||
|
||||
|
||||
class ShareServerNotCreated(ManilaException):
|
||||
message = _("Share Server %(share_server_id)s failed on creation.")
|
||||
|
||||
|
||||
class InvalidImageRef(Invalid):
|
||||
message = _("Invalid image href %(image_href)s.")
|
||||
|
||||
|
@ -388,8 +400,8 @@ class SnapshotLimitExceeded(QuotaError):
|
|||
message = _("Maximum number of snapshots allowed (%(allowed)d) exceeded")
|
||||
|
||||
|
||||
class ActivatedShareNetworksLimitExceeded(QuotaError):
|
||||
message = _("Maximum number of activated share-networks "
|
||||
class ShareNetworksLimitExceeded(QuotaError):
|
||||
message = _("Maximum number of share-networks "
|
||||
"allowed (%(allowed)d) exceeded")
|
||||
|
||||
|
||||
|
|
|
@ -39,9 +39,13 @@ def API():
|
|||
class NetworkBaseAPI(object):
|
||||
|
||||
@abc.abstractmethod
|
||||
def allocate_network(self, context, share_network, **kwargs):
|
||||
def allocate_network(self, context, network_id, subnet_id, **kwargs):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def deallocate_network(self, context, share_network):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_provider_info(self, context, network_id, subnet_id):
|
||||
pass
|
||||
|
|
|
@ -35,7 +35,7 @@ class NeutronNetworkPlugin(manila_network.NetworkBaseAPI, db_base.Base):
|
|||
super(NeutronNetworkPlugin, self).__init__()
|
||||
self.neutron_api = neutron_api.API()
|
||||
|
||||
def allocate_network(self, context, share_network, **kwargs):
|
||||
def allocate_network(self, context, share_server, share_network, **kwargs):
|
||||
"""Allocate network resources using given network information: create
|
||||
neutron ports for a given neutron network and subnet, create manila db
|
||||
records for allocated neutron ports.
|
||||
|
@ -58,12 +58,14 @@ class NeutronNetworkPlugin(manila_network.NetworkBaseAPI, db_base.Base):
|
|||
allocation_count = kwargs.get('count', 1)
|
||||
device_owner = kwargs.get('device_owner', 'share')
|
||||
|
||||
for _ in range(0, allocation_count):
|
||||
self._create_port(context, share_network, device_owner)
|
||||
ports = []
|
||||
for __ in range(0, allocation_count):
|
||||
ports.append(self._create_port(context, share_server,
|
||||
share_network, device_owner))
|
||||
|
||||
return self.db.share_network_get(context, share_network['id'])
|
||||
return ports
|
||||
|
||||
def deallocate_network(self, context, share_network):
|
||||
def deallocate_network(self, context, share_server):
|
||||
"""Deallocate neutron network resources for the given network info:
|
||||
delete previously allocated neutron ports, delete manila db records for
|
||||
deleted ports.
|
||||
|
@ -72,25 +74,26 @@ class NeutronNetworkPlugin(manila_network.NetworkBaseAPI, db_base.Base):
|
|||
:param share_network: share network data
|
||||
:rtype: None
|
||||
"""
|
||||
ports = share_network['network_allocations']
|
||||
ports = self.db.network_allocations_get_for_share_server(
|
||||
context, share_server['id'])
|
||||
|
||||
for port in ports:
|
||||
self._delete_port(context, port)
|
||||
|
||||
def _create_port(self, context, share_network, device_owner):
|
||||
port = self.neutron_api.create_port(share_network['project_id'],
|
||||
def _create_port(self, context, share_server, share_network, device_owner):
|
||||
port = self.neutron_api.create_port(
|
||||
share_network['project_id'],
|
||||
network_id=share_network['neutron_net_id'],
|
||||
subnet_id=share_network['neutron_subnet_id'],
|
||||
device_owner='manila:' + device_owner)
|
||||
port_dict = {
|
||||
'id': port['id'],
|
||||
'share_network_id': share_network['id'],
|
||||
'share_server_id': share_server['id'],
|
||||
'ip_address': port['fixed_ips'][0]['ip_address'],
|
||||
'mac_address': port['mac_address'],
|
||||
'status': constants.STATUS_ACTIVE,
|
||||
}
|
||||
self.db.network_allocation_create(context, port_dict)
|
||||
return port_dict
|
||||
return self.db.network_allocation_create(context, port_dict)
|
||||
|
||||
def _delete_port(self, context, port):
|
||||
try:
|
||||
|
|
|
@ -116,7 +116,7 @@ class FilterScheduler(driver.Scheduler):
|
|||
# 'volume_XX' to 'resource_XX' will make both filters happy.
|
||||
resource_properties = share_properties.copy()
|
||||
volume_type = request_spec.get("volume_type", {})
|
||||
resource_type = request_spec.get("volume_type", {})
|
||||
resource_type = request_spec.get("volume_type") or {}
|
||||
request_spec.update({'resource_properties': resource_properties})
|
||||
|
||||
config_options = self._get_configuration_options()
|
||||
|
|
|
@ -24,7 +24,6 @@ import time
|
|||
|
||||
from oslo.config import cfg
|
||||
|
||||
from manila.common import constants
|
||||
from manila import compute
|
||||
from manila import context
|
||||
from manila import exception
|
||||
|
@ -125,8 +124,9 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
|
|||
if share['share_network_id'] is None:
|
||||
raise exception.ManilaException(
|
||||
_('Share Network is not specified'))
|
||||
server = self.get_service_instance(self.admin_context,
|
||||
share_network_id=share['share_network_id'])
|
||||
server = self.get_service_instance(
|
||||
self.admin_context, share_server_id=share['share_server_id'],
|
||||
share_network_id=share['share_network_id'])
|
||||
volume = self._allocate_container(self.admin_context, share)
|
||||
volume = self._attach_volume(self.admin_context, share, server, volume)
|
||||
self._format_device(server, volume)
|
||||
|
@ -329,8 +329,9 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
|
|||
|
||||
def create_share_from_snapshot(self, context, share, snapshot):
|
||||
"""Is called to create share from snapshot."""
|
||||
server = self.get_service_instance(self.admin_context,
|
||||
share_network_id=share['share_network_id'])
|
||||
server = self.get_service_instance(
|
||||
self.admin_context, share_server_id=share['share_server_id'],
|
||||
share_network_id=share['share_network_id'])
|
||||
volume = self._allocate_container(self.admin_context, share, snapshot)
|
||||
volume = self._attach_volume(self.admin_context, share, server, volume)
|
||||
self._mount_device(context, share, server, volume)
|
||||
|
@ -343,6 +344,7 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
|
|||
if not share['share_network_id']:
|
||||
return
|
||||
server = self.get_service_instance(self.admin_context,
|
||||
share_server_id=share['share_server_id'],
|
||||
share_network_id=share['share_network_id'],
|
||||
return_inactive=True)
|
||||
if server:
|
||||
|
@ -398,8 +400,9 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
|
|||
|
||||
def ensure_share(self, context, share):
|
||||
"""Ensure that storage are mounted and exported."""
|
||||
server = self.get_service_instance(context,
|
||||
share_network_id=share['share_network_id'], create=True)
|
||||
server = self.get_service_instance(
|
||||
context, share_server_id=share['share_server_id'],
|
||||
share_network_id=share['share_network_id'], create=True)
|
||||
volume = self._get_volume(context, share['id'])
|
||||
volume = self._attach_volume(context, share, server, volume)
|
||||
self._mount_device(context, share, server, volume)
|
||||
|
@ -407,9 +410,9 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
|
|||
|
||||
def allow_access(self, context, share, access):
|
||||
"""Allow access to the share."""
|
||||
server = self.get_service_instance(self.admin_context,
|
||||
share_network_id=share['share_network_id'],
|
||||
create=False)
|
||||
server = self.get_service_instance(
|
||||
self.admin_context, share_server_id=share['share_server_id'],
|
||||
share_network_id=share['share_network_id'], create=False)
|
||||
if not server:
|
||||
raise exception.ManilaException('Server not found. Try to '
|
||||
'restart manila share service')
|
||||
|
@ -421,8 +424,9 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
|
|||
"""Deny access to the share."""
|
||||
if not share['share_network_id']:
|
||||
return
|
||||
server = self.get_service_instance(self.admin_context,
|
||||
share_network_id=share['share_network_id'])
|
||||
server = self.get_service_instance(
|
||||
self.admin_context, share_server_id=share['share_server_id'],
|
||||
share_network_id=share['share_network_id'])
|
||||
if server:
|
||||
self._get_helper(share).deny_access(server, share['name'],
|
||||
access['access_type'],
|
||||
|
@ -443,20 +447,23 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
|
|||
# use service instance provided by Nova.
|
||||
return 0
|
||||
|
||||
def setup_network(self, share_network, metadata=None):
|
||||
sn_id = share_network["id"]
|
||||
def setup_network(self, network_info, metadata=None):
|
||||
sn_id = network_info["share_network_id"]
|
||||
srv_id = network_info["id"]
|
||||
msg = "Creating share infrastructure for share network '%s'."
|
||||
LOG.debug(msg % sn_id)
|
||||
self.get_service_instance(context=self.admin_context,
|
||||
share_server_id=srv_id,
|
||||
share_network_id=sn_id,
|
||||
create=True)
|
||||
|
||||
def teardown_network(self, share_network):
|
||||
sn_id = share_network["id"]
|
||||
msg = "Removing share infrastructure for share network '%s'."
|
||||
LOG.debug(msg % sn_id)
|
||||
def teardown_network(self, network_info):
|
||||
sn_id = network_info["share_network_id"]
|
||||
srv_id = network_info["id"]
|
||||
msg = "Removing share infrastructure for share server '%s'."
|
||||
LOG.debug(msg % srv_id)
|
||||
try:
|
||||
self.delete_service_instance(self.admin_context, sn_id)
|
||||
self.delete_service_instance(self.admin_context, sn_id, srv_id)
|
||||
except Exception as e:
|
||||
LOG.debug(e)
|
||||
|
||||
|
|
|
@ -449,12 +449,12 @@ class NetAppClusteredShareDriver(driver.NetAppShareDriver):
|
|||
|
||||
def create_share(self, context, share):
|
||||
"""Creates new share."""
|
||||
if not share.get('network_info'):
|
||||
if not share.get('share_server_id'):
|
||||
msg = _("Cannot create share %s. "
|
||||
"No share network provided") % share['id']
|
||||
"No share server provided") % share['id']
|
||||
LOG.error(msg)
|
||||
raise exception.NetAppException(message=msg)
|
||||
vserver = self._get_vserver_name(share['share_network_id'])
|
||||
vserver = self._get_vserver_name(share['share_server_id'])
|
||||
vserver_client = driver.NetAppApiClient(
|
||||
self.api_version, vserver=vserver,
|
||||
configuration=self.configuration)
|
||||
|
@ -464,7 +464,7 @@ class NetAppClusteredShareDriver(driver.NetAppShareDriver):
|
|||
def create_share_from_snapshot(self, context, share, snapshot,
|
||||
net_details=None):
|
||||
"""Creates new share form snapshot."""
|
||||
vserver = self._get_vserver_name(share['share_network_id'])
|
||||
vserver = self._get_vserver_name(share['share_server_id'])
|
||||
vserver_client = driver.NetAppApiClient(
|
||||
self.api_version, vserver=vserver,
|
||||
configuration=self.configuration)
|
||||
|
@ -543,7 +543,7 @@ class NetAppClusteredShareDriver(driver.NetAppShareDriver):
|
|||
def delete_share(self, context, share):
|
||||
"""Deletes share."""
|
||||
share_name = self._get_valid_share_name(share['id'])
|
||||
vserver = self._get_vserver_name(share['share_network_id'])
|
||||
vserver = self._get_vserver_name(share['share_server_id'])
|
||||
vserver_client = driver.NetAppApiClient(
|
||||
self.api_version, vserver=vserver,
|
||||
configuration=self.configuration)
|
||||
|
|
|
@ -204,14 +204,14 @@ class ServiceInstanceManager(object):
|
|||
else:
|
||||
return networks[0]['id']
|
||||
|
||||
def _get_service_instance_name(self, share_network_id):
|
||||
def _get_service_instance_name(self, share_server_id):
|
||||
"""Returns service vms name."""
|
||||
if self.driver_config:
|
||||
# Make service instance name unique for multibackend installation
|
||||
name = "%s_%s" % (self.driver_config.config_group,
|
||||
share_network_id)
|
||||
share_server_id)
|
||||
else:
|
||||
name = share_network_id
|
||||
name = share_server_id
|
||||
return self.get_config_option("service_instance_name_template") % name
|
||||
|
||||
def _get_server_ip(self, server):
|
||||
|
@ -300,23 +300,24 @@ class ServiceInstanceManager(object):
|
|||
self.max_time_to_build_instance)
|
||||
|
||||
@synchronized()
|
||||
def get_service_instance(self, context, share_network_id, create=False,
|
||||
return_inactive=False):
|
||||
def get_service_instance(self, context, share_server_id, share_network_id,
|
||||
create=False, return_inactive=False):
|
||||
"""Finds or creates and sets up service vm.
|
||||
|
||||
:param context: defines context, that should be used
|
||||
:param share_network_id: it provides network data for service VM
|
||||
:param share_server_id: provides server id for service VM
|
||||
:param create: allow create service VM or not
|
||||
:param return_inactive: allows to return not active VM, without
|
||||
raise of exception
|
||||
:returns: dict with data for service VM
|
||||
:raises: exception.ServiceInstanceException
|
||||
"""
|
||||
server = self.share_networks_servers.get(share_network_id, {})
|
||||
server = self.share_networks_servers.get(share_server_id, {})
|
||||
if self._ensure_server(context, server, update=True):
|
||||
return server
|
||||
else:
|
||||
server = self._discover_service_instance(context, share_network_id)
|
||||
server = self._discover_service_instance(context, share_server_id)
|
||||
old_server_ip = None
|
||||
is_active = False
|
||||
if server:
|
||||
|
@ -328,10 +329,11 @@ class ServiceInstanceManager(object):
|
|||
self._delete_server(context, server)
|
||||
server = self._create_service_instance(context,
|
||||
share_network_id,
|
||||
share_server_id,
|
||||
old_server_ip)
|
||||
is_active = True
|
||||
|
||||
self.share_networks_servers[share_network_id] = server
|
||||
self.share_networks_servers[share_server_id] = server
|
||||
if is_active:
|
||||
server['share_network_id'] = share_network_id
|
||||
server['ip'] = self._get_server_ip(server)
|
||||
|
@ -346,9 +348,9 @@ class ServiceInstanceManager(object):
|
|||
|
||||
return server
|
||||
|
||||
def _discover_service_instance(self, context, share_network_id):
|
||||
def _discover_service_instance(self, context, share_server_id):
|
||||
server = {}
|
||||
instance_name = self._get_service_instance_name(share_network_id)
|
||||
instance_name = self._get_service_instance_name(share_server_id)
|
||||
search_opts = {'name': instance_name}
|
||||
servers = self.compute_api.server_list(context, search_opts, True)
|
||||
if len(servers) == 1:
|
||||
|
@ -413,10 +415,10 @@ class ServiceInstanceManager(object):
|
|||
_('Ambiguous image name.'))
|
||||
|
||||
def _create_service_instance(self, context, share_network_id,
|
||||
old_server_ip):
|
||||
share_server_id, old_server_ip):
|
||||
"""Creates service vm and sets up networking for it."""
|
||||
service_image_id = self._get_service_image(context)
|
||||
instance_name = self._get_service_instance_name(share_network_id)
|
||||
instance_name = self._get_service_instance_name(share_server_id)
|
||||
|
||||
with lock:
|
||||
key_name = self._get_key(context)
|
||||
|
@ -648,12 +650,13 @@ class ServiceInstanceManager(object):
|
|||
else:
|
||||
raise exception.ServiceInstanceException(_('No available cidrs.'))
|
||||
|
||||
def delete_service_instance(self, context, share_network_id):
|
||||
def delete_service_instance(self, context, share_network_id,
|
||||
share_server_id):
|
||||
"""Removes share infrastructure.
|
||||
|
||||
Deletes service vm and subnet, associated to share network.
|
||||
"""
|
||||
server = self._discover_service_instance(context, share_network_id)
|
||||
server = self._discover_service_instance(context, share_server_id)
|
||||
if server:
|
||||
self._delete_server(context, server)
|
||||
subnet = self._get_service_subnet(share_network_id)
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 NetApp
|
||||
# Copyright (c) 2014 NetApp Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
@ -21,6 +19,7 @@
|
|||
:share_driver: Used by :class:`ShareManager`. Defaults to
|
||||
:class:`manila.share.drivers.lvm.LVMShareDriver`.
|
||||
"""
|
||||
import time
|
||||
|
||||
from manila.common import constants
|
||||
from manila import context
|
||||
|
@ -29,6 +28,7 @@ from manila import manager
|
|||
from manila import network
|
||||
from manila.openstack.common import excutils
|
||||
from manila.openstack.common import importutils
|
||||
from manila.openstack.common import lockutils
|
||||
from manila.openstack.common import log as logging
|
||||
from manila.openstack.common import timeutils
|
||||
from manila import quota
|
||||
|
@ -42,6 +42,10 @@ share_manager_opts = [
|
|||
cfg.StrOpt('share_driver',
|
||||
default='manila.share.drivers.lvm.LVMShareDriver',
|
||||
help='Driver to use for share creation'),
|
||||
cfg.BoolOpt('delete_share_server_with_last_share',
|
||||
default=False,
|
||||
help='With this option is set to True share server will'
|
||||
'be deleted on deletion of last share'),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
@ -61,6 +65,7 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||
config_group=service_name)
|
||||
super(ShareManager, self).__init__(service_name='share',
|
||||
*args, **kwargs)
|
||||
|
||||
if not share_driver:
|
||||
share_driver = self.configuration.share_driver
|
||||
self.driver = importutils.import_object(
|
||||
|
@ -93,6 +98,23 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||
|
||||
self.publish_service_capabilities(ctxt)
|
||||
|
||||
def _share_server_get_or_create(self, context, share_network_id):
|
||||
|
||||
@lockutils.synchronized(share_network_id)
|
||||
def _get_or_create_server():
|
||||
try:
|
||||
share_server = \
|
||||
self.db.share_server_get_by_host_and_share_net_valid(
|
||||
context, self.host, share_network_id)
|
||||
except exception.ShareServerNotFound:
|
||||
share_network = self.db.share_network_get(
|
||||
context, share_network_id)
|
||||
share_server = self._setup_server(context, share_network)
|
||||
LOG.info(_("Share server created successfully."))
|
||||
return share_server
|
||||
|
||||
return _get_or_create_server()
|
||||
|
||||
def create_share(self, context, share_id, request_spec=None,
|
||||
filter_properties=None, snapshot_id=None):
|
||||
"""Creates a share."""
|
||||
|
@ -108,13 +130,19 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||
|
||||
share_network_id = share_ref.get('share_network_id', None)
|
||||
if share_network_id:
|
||||
share_network = self.db.share_network_get(context,
|
||||
share_network_id)
|
||||
else:
|
||||
share_network = {}
|
||||
|
||||
share_ref['network_info'] = share_network
|
||||
try:
|
||||
share_server = self._share_server_get_or_create(
|
||||
context, share_network_id)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_("Failed to get share server"
|
||||
" for share creation."))
|
||||
self.db.share_update(context, share_id,
|
||||
{'status': 'error'})
|
||||
|
||||
share_ref = self.db.share_update(
|
||||
context, share_id, {'share_server_id': share_server['id']})
|
||||
LOG.debug("Using share server %s" % share_server['id'])
|
||||
try:
|
||||
if snapshot_ref:
|
||||
export_location = self.driver.create_share_from_snapshot(
|
||||
|
@ -125,8 +153,10 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||
{'export_location': export_location})
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_("Share %s failed on creation.") % share_id)
|
||||
self.db.share_update(context, share_id, {'status': 'error'})
|
||||
else:
|
||||
LOG.info(_("Share created successfully."))
|
||||
self.db.share_update(context, share_id,
|
||||
{'status': 'available',
|
||||
'launched_at': timeutils.utcnow()})
|
||||
|
@ -159,11 +189,17 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||
LOG.exception(_("Failed to update usages deleting share"))
|
||||
|
||||
self.db.share_delete(context, share_id)
|
||||
LOG.info(_("share %s: deleted successfully"), share_ref['name'])
|
||||
LOG.info(_("Share %s: deleted successfully."), share_ref['name'])
|
||||
|
||||
if reservations:
|
||||
QUOTAS.commit(context, reservations, project_id=project_id)
|
||||
|
||||
share_server = self.db.share_server_get(context,
|
||||
share_ref['share_server_id'])
|
||||
if CONF.delete_share_server_with_last_share:
|
||||
if not share_server.shares:
|
||||
self._teardown_server(context, share_server)
|
||||
|
||||
def create_snapshot(self, context, share_id, snapshot_id):
|
||||
"""Create snapshot for share."""
|
||||
snapshot_ref = self.db.share_snapshot_get(context, snapshot_id)
|
||||
|
@ -262,76 +298,74 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||
self._report_driver_status(context)
|
||||
self._publish_service_capabilities(context)
|
||||
|
||||
def activate_network(self, context, share_network_id, metadata=None):
|
||||
share_network = self.db.share_network_get(context, share_network_id)
|
||||
if (hasattr(share_network, 'project_id') and
|
||||
context.project_id != share_network['project_id']):
|
||||
project_id = share_network['project_id']
|
||||
else:
|
||||
project_id = context.project_id
|
||||
def _form_network_info(self, context, share_server, share_network):
|
||||
# Network info is used by driver for setting up share server
|
||||
# and getting server info on share creation.
|
||||
network_allocations = self.db.network_allocations_get_for_share_server(
|
||||
context, share_server['id'])
|
||||
network_info = {
|
||||
'id': share_server['id'],
|
||||
'share_network_id': share_server['share_network_id'],
|
||||
'segmentation_id': share_network['segmentation_id'],
|
||||
'cidr': share_network['cidr'],
|
||||
'security_services': share_network['security_services'],
|
||||
'network_allocations': network_allocations,
|
||||
}
|
||||
return network_info
|
||||
|
||||
reservations = None
|
||||
try:
|
||||
reservations = QUOTAS.reserve(context,
|
||||
project_id=project_id,
|
||||
share_networks=-1)
|
||||
self._activate_share_network(context, share_network, metadata)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
if reservations:
|
||||
QUOTAS.commit(context, reservations, project_id=project_id)
|
||||
|
||||
def deactivate_network(self, context, share_network_id):
|
||||
share_network = self.db.share_network_get(context, share_network_id)
|
||||
self._deactivate_network(context, share_network)
|
||||
self.network_api.deallocate_network(context, share_network)
|
||||
|
||||
if (hasattr(share_network, 'project_id') and
|
||||
context.project_id != share_network['project_id']):
|
||||
project_id = share_network['project_id']
|
||||
else:
|
||||
project_id = context.project_id
|
||||
def _setup_server(self, context, share_network, metadata=None):
|
||||
share_server_val = {
|
||||
'host': self.host,
|
||||
'share_network_id': share_network['id'],
|
||||
'status': constants.STATUS_CREATING
|
||||
}
|
||||
share_server = self.db.share_server_create(context,
|
||||
share_server_val)
|
||||
|
||||
try:
|
||||
reservations = QUOTAS.reserve(context,
|
||||
project_id=project_id,
|
||||
share_networks=-1)
|
||||
except Exception:
|
||||
msg = _("Failed to update usages deactivating share-network.")
|
||||
LOG.exception(msg)
|
||||
else:
|
||||
QUOTAS.commit(context, reservations, project_id=project_id)
|
||||
allocation_number = self.driver.get_network_allocations_number()
|
||||
if allocation_number:
|
||||
self.network_api.allocate_network(
|
||||
context, share_server, share_network,
|
||||
count=allocation_number)
|
||||
|
||||
def _activate_share_network(self, context, share_network, metadata=None):
|
||||
allocation_number = self.driver.get_network_allocations_number()
|
||||
if allocation_number:
|
||||
share_network = self.network_api.allocate_network(
|
||||
context,
|
||||
share_network,
|
||||
count=allocation_number)
|
||||
try:
|
||||
self.db.share_network_update(context, share_network['id'],
|
||||
{'status': constants.STATUS_ACTIVATING})
|
||||
self.driver.setup_network(share_network, metadata=metadata)
|
||||
self.db.share_network_update(context, share_network['id'],
|
||||
share_network = self.db.share_network_get(context,
|
||||
share_network['id'])
|
||||
network_info = self._form_network_info(context, share_server,
|
||||
share_network)
|
||||
self.driver.setup_network(network_info, metadata=metadata)
|
||||
return self.db.share_server_update(context, share_server['id'],
|
||||
{'status': constants.STATUS_ACTIVE})
|
||||
except exception.ManilaException:
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.db.share_network_update(context, share_network['id'],
|
||||
self.db.share_server_update(context, share_server['id'],
|
||||
{'status': constants.STATUS_ERROR})
|
||||
self.network_api.deallocate_network(context, share_network)
|
||||
else:
|
||||
return share_network
|
||||
|
||||
def _deactivate_network(self, context, share_network):
|
||||
self.db.share_network_update(context, share_network['id'],
|
||||
{'status': constants.STATUS_DEACTIVATING})
|
||||
try:
|
||||
self.driver.teardown_network(share_network)
|
||||
except Exception as e:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.db.share_network_update(context, share_network['id'],
|
||||
{'status': constants.STATUS_ERROR})
|
||||
else:
|
||||
self.db.share_network_update(context, share_network['id'],
|
||||
{'status': constants.STATUS_INACTIVE})
|
||||
def _teardown_server(self, context, share_server):
|
||||
|
||||
@lockutils.synchronized(share_server['share_network_id'])
|
||||
def _teardown_server():
|
||||
share_network = self.db.share_network_get(
|
||||
context, share_server['share_network_id'])
|
||||
|
||||
network_info = self._form_network_info(context, share_server,
|
||||
share_network)
|
||||
|
||||
self.db.share_server_update(context, share_server['id'],
|
||||
{'status': constants.STATUS_DELETING})
|
||||
try:
|
||||
LOG.debug("Deleting share server")
|
||||
self.driver.teardown_network(network_info)
|
||||
except Exception as e:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_("Share server %s failed on deletion.")
|
||||
% share_server['id'])
|
||||
self.db.share_server_update(context, share_server['id'],
|
||||
{'status': constants.STATUS_ERROR})
|
||||
else:
|
||||
self.db.share_server_delete(context, share_server['id'])
|
||||
|
||||
_teardown_server()
|
||||
LOG.info(_("Share server deleted successfully."))
|
||||
self.network_api.deallocate_network(context, share_server)
|
||||
|
|
|
@ -40,8 +40,7 @@ fake_share_network = {
|
|||
'name': 'fake name',
|
||||
'description': 'fake description',
|
||||
'status': constants.STATUS_INACTIVE,
|
||||
'shares': [],
|
||||
'network_allocations': [],
|
||||
'share_servers': [],
|
||||
'security_services': []
|
||||
}
|
||||
fake_share_network_shortened = {
|
||||
|
@ -122,10 +121,11 @@ class ShareNetworkAPITest(unittest.TestCase):
|
|||
self.req,
|
||||
body)
|
||||
|
||||
@mock.patch.object(db_api, 'share_network_get',
|
||||
mock.Mock(return_value=fake_share_network))
|
||||
@mock.patch.object(db_api, 'share_network_get', mock.Mock())
|
||||
def test_delete_nominal(self):
|
||||
share_nw = 'fake network id'
|
||||
share_nw = fake_share_network.copy()
|
||||
share_nw['share_servers'] = []
|
||||
db_api.share_network_get.return_value = share_nw
|
||||
|
||||
with mock.patch.object(db_api, 'share_network_delete'):
|
||||
self.controller.delete(self.req, share_nw)
|
||||
|
@ -147,11 +147,12 @@ class ShareNetworkAPITest(unittest.TestCase):
|
|||
@mock.patch.object(db_api, 'share_network_get', mock.Mock())
|
||||
def test_delete_in_use(self):
|
||||
share_nw = fake_share_network.copy()
|
||||
share_nw['status'] = constants.STATUS_ACTIVE
|
||||
share_servers = [{'id': 1}]
|
||||
share_nw['share_servers'] = share_servers
|
||||
|
||||
db_api.share_network_get.return_value = share_nw
|
||||
|
||||
self.assertRaises(webob_exc.HTTPBadRequest,
|
||||
self.assertRaises(webob_exc.HTTPForbidden,
|
||||
self.controller.delete,
|
||||
self.req,
|
||||
share_nw['id'])
|
||||
|
@ -252,11 +253,11 @@ class ShareNetworkAPITest(unittest.TestCase):
|
|||
@mock.patch.object(db_api, 'share_network_get', mock.Mock())
|
||||
def test_update_in_use(self):
|
||||
share_nw = fake_share_network.copy()
|
||||
share_nw['status'] = constants.STATUS_ACTIVE
|
||||
share_nw['share_servers'] = [{'id': 1}]
|
||||
|
||||
db_api.share_network_get.return_value = share_nw
|
||||
|
||||
self.assertRaises(webob_exc.HTTPBadRequest,
|
||||
self.assertRaises(webob_exc.HTTPForbidden,
|
||||
self.controller.update,
|
||||
self.req,
|
||||
share_nw['id'],
|
||||
|
@ -303,41 +304,6 @@ class ShareNetworkAPITest(unittest.TestCase):
|
|||
self.controller._remove_security_service.assert_called_once_with(
|
||||
self.req, share_network_id, body['remove_security_service'])
|
||||
|
||||
def test_action_activate(self):
|
||||
share_network_id = 'fake network id'
|
||||
body = {'activate': {}}
|
||||
|
||||
with mock.patch.object(self.controller, '_activate', mock.Mock()):
|
||||
self.controller.action(self.req, share_network_id, body)
|
||||
self.controller._activate.assert_called_once_with(
|
||||
self.req, share_network_id, body['activate'])
|
||||
|
||||
def test_action_activate_with_overquota(self):
|
||||
share_network_id = 'fake network id'
|
||||
body = {'activate': {}}
|
||||
|
||||
def raise_overquota(*args, **kwargs):
|
||||
usages = {'share_networks': {'reserved': 0, 'in_use': 1, }}
|
||||
quotas = overs = {'share_networks': 1}
|
||||
raise exception.OverQuota(overs=overs,
|
||||
usages=usages,
|
||||
quotas=quotas)
|
||||
|
||||
with mock.patch.object(QUOTAS, 'reserve',
|
||||
mock.Mock(side_effect=raise_overquota)):
|
||||
self.assertRaises(exception.ActivatedShareNetworksLimitExceeded,
|
||||
self.controller.action,
|
||||
self.req, share_network_id, body)
|
||||
|
||||
def test_action_deactivate(self):
|
||||
share_network_id = 'fake network id'
|
||||
body = {'deactivate': {}}
|
||||
|
||||
with mock.patch.object(self.controller, '_deactivate', mock.Mock()):
|
||||
self.controller.action(self.req, share_network_id, body)
|
||||
self.controller._deactivate.assert_called_once_with(
|
||||
self.req, share_network_id, body['deactivate'])
|
||||
|
||||
def test_action_bad_request(self):
|
||||
share_network_id = 'fake network id'
|
||||
body = {'bad_action': {}}
|
||||
|
@ -347,107 +313,3 @@ class ShareNetworkAPITest(unittest.TestCase):
|
|||
self.req,
|
||||
share_network_id,
|
||||
body)
|
||||
|
||||
@mock.patch.object(db_api, 'share_network_get',
|
||||
mock.Mock(return_value=fake_share_network))
|
||||
@mock.patch.object(policy, 'check_policy', mock.Mock())
|
||||
def test_activate(self):
|
||||
share_network_id = 'fake network id'
|
||||
|
||||
with mock.patch.object(self.controller.share_rpcapi,
|
||||
'activate_network', mock.Mock()):
|
||||
self.controller._activate(self.req, share_network_id, {})
|
||||
policy.check_policy.assert_called_once_with(
|
||||
self.context,
|
||||
share_networks.RESOURCE_NAME,
|
||||
'activate')
|
||||
db_api.share_network_get.assert_called_once_with(
|
||||
self.context,
|
||||
share_network_id)
|
||||
self.controller.share_rpcapi.activate_network.\
|
||||
assert_called_once_with(self.context, share_network_id, {})
|
||||
|
||||
@mock.patch.object(db_api, 'share_network_get', mock.Mock())
|
||||
def test_activate_not_found(self):
|
||||
share_network_id = 'fake network id'
|
||||
db_api.share_network_get.side_effect = \
|
||||
exception.ShareNetworkNotFound(share_network_id=share_network_id)
|
||||
|
||||
self.assertRaises(webob_exc.HTTPNotFound,
|
||||
self.controller._activate,
|
||||
self.req,
|
||||
share_network_id,
|
||||
{})
|
||||
|
||||
@mock.patch.object(db_api, 'share_network_get', mock.Mock())
|
||||
def test_activate_not_inactive(self):
|
||||
share_network_id = 'fake network id'
|
||||
share_network = fake_share_network.copy()
|
||||
share_network['status'] = constants.STATUS_ERROR
|
||||
|
||||
db_api.share_network_get.return_value = share_network
|
||||
|
||||
self.assertRaises(webob_exc.HTTPBadRequest,
|
||||
self.controller._activate,
|
||||
self.req,
|
||||
share_network_id,
|
||||
{})
|
||||
|
||||
@mock.patch.object(db_api, 'share_network_get', mock.Mock())
|
||||
@mock.patch.object(policy, 'check_policy', mock.Mock())
|
||||
def test_deactivate(self):
|
||||
share_network_id = 'fake network id'
|
||||
share_network = fake_share_network.copy()
|
||||
share_network['status'] = constants.STATUS_ACTIVE
|
||||
|
||||
db_api.share_network_get.return_value = share_network
|
||||
|
||||
with mock.patch.object(self.controller.share_rpcapi,
|
||||
'deactivate_network', mock.Mock()):
|
||||
self.controller._deactivate(self.req, share_network_id, None)
|
||||
policy.check_policy.assert_called_once_with(
|
||||
self.context,
|
||||
share_networks.RESOURCE_NAME,
|
||||
'deactivate')
|
||||
db_api.share_network_get.assert_called_once_with(
|
||||
self.context,
|
||||
share_network_id)
|
||||
self.controller.share_rpcapi.deactivate_network.\
|
||||
assert_called_once_with(self.context, share_network_id)
|
||||
|
||||
@mock.patch.object(db_api, 'share_network_get', mock.Mock())
|
||||
def test_deactivate_not_found(self):
|
||||
share_network_id = 'fake network id'
|
||||
db_api.share_network_get.side_effect = \
|
||||
exception.ShareNetworkNotFound(share_network_id=share_network_id)
|
||||
|
||||
self.assertRaises(webob_exc.HTTPNotFound,
|
||||
self.controller._deactivate,
|
||||
self.req,
|
||||
share_network_id,
|
||||
None)
|
||||
|
||||
@mock.patch.object(db_api, 'share_network_get',
|
||||
mock.Mock(return_value=fake_share_network))
|
||||
def test_deactivate_not_active(self):
|
||||
share_network_id = 'fake network id'
|
||||
|
||||
self.assertRaises(webob_exc.HTTPBadRequest,
|
||||
self.controller._deactivate,
|
||||
self.req,
|
||||
share_network_id,
|
||||
None)
|
||||
|
||||
@mock.patch.object(db_api, 'share_network_get', mock.Mock())
|
||||
def test_deactivate_in_use(self):
|
||||
share_network_id = 'fake network id'
|
||||
share_network = fake_share_network.copy()
|
||||
share_network['shares'].append('fake share')
|
||||
|
||||
db_api.share_network_get.return_value = share_network
|
||||
|
||||
self.assertRaises(webob_exc.HTTPBadRequest,
|
||||
self.controller._deactivate,
|
||||
self.req,
|
||||
share_network_id,
|
||||
None)
|
||||
|
|
|
@ -47,6 +47,7 @@ class NetAppClusteredDrvTestCase(test.TestCase):
|
|||
'size': 1,
|
||||
'share_proto': 'fake',
|
||||
'share_network_id': 'fake_net_id',
|
||||
'share_server_id': 'fake-share-srv-id',
|
||||
'network_info': {
|
||||
'network_allocations': [
|
||||
{'ip_address': 'ip'}
|
||||
|
@ -406,6 +407,7 @@ class NetAppNFSHelperTestCase(test.TestCase):
|
|||
'name': 'fake_name',
|
||||
'size': 1,
|
||||
'export_location': 'location:/path',
|
||||
'share_server_id': 'fake-share-srv-id',
|
||||
'share_proto': 'fake'}
|
||||
self.helper = driver.NetAppClusteredNFSHelper()
|
||||
self.helper._client = mock.Mock()
|
||||
|
|
|
@ -23,23 +23,23 @@ from manila.network.neutron import constants as neutron_constants
|
|||
from manila.network.neutron import neutron_network_plugin as plugin
|
||||
|
||||
fake_neutron_port = {
|
||||
"status": "test_port_status",
|
||||
"allowed_address_pairs": [],
|
||||
"admin_state_up": True,
|
||||
"network_id": "test_net_id",
|
||||
"tenant_id": "fake_tenant_id",
|
||||
"extra_dhcp_opts": [],
|
||||
"device_owner": "test",
|
||||
"binding:capabilities": {"port_filter": True},
|
||||
"mac_address": "test_mac",
|
||||
"fixed_ips": [
|
||||
{"subnet_id": "test_subnet_id",
|
||||
"ip_address": "test_ip"}
|
||||
],
|
||||
"id": "test_port_id",
|
||||
"security_groups": ["fake_sec_group_id"],
|
||||
"device_id": "fake_device_id"
|
||||
}
|
||||
"status": "test_port_status",
|
||||
"allowed_address_pairs": [],
|
||||
"admin_state_up": True,
|
||||
"network_id": "test_net_id",
|
||||
"tenant_id": "fake_tenant_id",
|
||||
"extra_dhcp_opts": [],
|
||||
"device_owner": "test",
|
||||
"binding:capabilities": {"port_filter": True},
|
||||
"mac_address": "test_mac",
|
||||
"fixed_ips": [
|
||||
{"subnet_id": "test_subnet_id",
|
||||
"ip_address": "test_ip"}
|
||||
],
|
||||
"id": "test_port_id",
|
||||
"security_groups": ["fake_sec_group_id"],
|
||||
"device_id": "fake_device_id"
|
||||
}
|
||||
|
||||
fake_share_network = {'id': 'fake nw info id',
|
||||
'neutron_subnet_id': 'fake subnet id',
|
||||
|
@ -48,20 +48,23 @@ fake_share_network = {'id': 'fake nw info id',
|
|||
'status': 'test_subnet_status',
|
||||
'name': 'fake name',
|
||||
'description': 'fake description',
|
||||
'network_allocations': [],
|
||||
'security_services': [],
|
||||
'shares': []}
|
||||
'security_services': []}
|
||||
|
||||
fake_share_server = {'id': 'fake nw info id',
|
||||
'status': 'test_server_status',
|
||||
'host': 'fake@host',
|
||||
'network_allocations': [],
|
||||
'shares': []}
|
||||
|
||||
fake_network_allocation = \
|
||||
{'id': fake_neutron_port['id'],
|
||||
'share_network_id': fake_share_network['id'],
|
||||
'share_server_id': fake_share_server['id'],
|
||||
'ip_address': fake_neutron_port['fixed_ips'][0]['ip_address'],
|
||||
'mac_address': fake_neutron_port['mac_address'],
|
||||
'status': constants.STATUS_ACTIVE}
|
||||
|
||||
|
||||
class NeutronNetworkPluginTest(unittest.TestCase):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(NeutronNetworkPluginTest, self).__init__(*args, **kwargs)
|
||||
|
||||
|
@ -75,20 +78,23 @@ class NeutronNetworkPluginTest(unittest.TestCase):
|
|||
mock.Mock(return_values=fake_network_allocation))
|
||||
@mock.patch.object(db_api, 'share_network_get',
|
||||
mock.Mock(return_value=fake_share_network))
|
||||
@mock.patch.object(db_api, 'share_server_get',
|
||||
mock.Mock(return_value=fake_share_server))
|
||||
def test_allocate_network_one_allocation(self):
|
||||
has_provider_nw_ext = mock.patch.object(self.plugin,
|
||||
'_has_provider_network_extension').start()
|
||||
has_provider_nw_ext = mock.patch.object(
|
||||
self.plugin, '_has_provider_network_extension').start()
|
||||
has_provider_nw_ext.return_value = True
|
||||
save_nw_data = mock.patch.object(self.plugin,
|
||||
'_save_neutron_network_data').start()
|
||||
'_save_neutron_network_data').start()
|
||||
save_subnet_data = mock.patch.object(
|
||||
self.plugin,
|
||||
'_save_neutron_subnet_data').start()
|
||||
self.plugin,
|
||||
'_save_neutron_subnet_data').start()
|
||||
|
||||
with mock.patch.object(self.plugin.neutron_api, 'create_port',
|
||||
mock.Mock(return_value=fake_neutron_port)):
|
||||
self.plugin.allocate_network(
|
||||
self.fake_context,
|
||||
fake_share_server,
|
||||
fake_share_network,
|
||||
allocation_info={'count': 1})
|
||||
|
||||
|
@ -114,20 +120,23 @@ class NeutronNetworkPluginTest(unittest.TestCase):
|
|||
mock.Mock(return_values=fake_network_allocation))
|
||||
@mock.patch.object(db_api, 'share_network_get',
|
||||
mock.Mock(return_value=fake_share_network))
|
||||
@mock.patch.object(db_api, 'share_server_get',
|
||||
mock.Mock(return_value=fake_share_server))
|
||||
def test_allocate_network_two_allocation(self):
|
||||
has_provider_nw_ext = mock.patch.object(self.plugin,
|
||||
'_has_provider_network_extension').start()
|
||||
has_provider_nw_ext = mock.patch.object(
|
||||
self.plugin, '_has_provider_network_extension').start()
|
||||
has_provider_nw_ext.return_value = True
|
||||
save_nw_data = mock.patch.object(self.plugin,
|
||||
'_save_neutron_network_data').start()
|
||||
'_save_neutron_network_data').start()
|
||||
save_subnet_data = mock.patch.object(
|
||||
self.plugin,
|
||||
'_save_neutron_subnet_data').start()
|
||||
self.plugin,
|
||||
'_save_neutron_subnet_data').start()
|
||||
|
||||
with mock.patch.object(self.plugin.neutron_api, 'create_port',
|
||||
mock.Mock(return_value=fake_neutron_port)):
|
||||
self.plugin.allocate_network(
|
||||
self.fake_context,
|
||||
fake_share_server,
|
||||
fake_share_network,
|
||||
count=2)
|
||||
|
||||
|
@ -142,8 +151,8 @@ class NeutronNetworkPluginTest(unittest.TestCase):
|
|||
device_owner='manila:share'),
|
||||
]
|
||||
db_api_calls = [
|
||||
mock.call(self.fake_context, fake_network_allocation),
|
||||
mock.call(self.fake_context, fake_network_allocation)
|
||||
mock.call(self.fake_context, fake_network_allocation),
|
||||
mock.call(self.fake_context, fake_network_allocation)
|
||||
]
|
||||
self.plugin.neutron_api.create_port.assert_has_calls(
|
||||
neutron_api_calls)
|
||||
|
@ -155,14 +164,14 @@ class NeutronNetworkPluginTest(unittest.TestCase):
|
|||
|
||||
@mock.patch.object(db_api, 'share_network_update', mock.Mock())
|
||||
def test_allocate_network_create_port_exception(self):
|
||||
has_provider_nw_ext = mock.patch.object(self.plugin,
|
||||
'_has_provider_network_extension').start()
|
||||
has_provider_nw_ext = mock.patch.object(
|
||||
self.plugin, '_has_provider_network_extension').start()
|
||||
has_provider_nw_ext.return_value = True
|
||||
save_nw_data = mock.patch.object(self.plugin,
|
||||
'_save_neutron_network_data').start()
|
||||
'_save_neutron_network_data').start()
|
||||
save_subnet_data = mock.patch.object(
|
||||
self.plugin,
|
||||
'_save_neutron_subnet_data').start()
|
||||
self.plugin,
|
||||
'_save_neutron_subnet_data').start()
|
||||
create_port = mock.patch.object(self.plugin.neutron_api,
|
||||
'create_port').start()
|
||||
create_port.side_effect = exception.NetworkException
|
||||
|
@ -170,6 +179,7 @@ class NeutronNetworkPluginTest(unittest.TestCase):
|
|||
self.assertRaises(exception.NetworkException,
|
||||
self.plugin.allocate_network,
|
||||
self.fake_context,
|
||||
fake_share_server,
|
||||
fake_share_network)
|
||||
|
||||
has_provider_nw_ext.stop()
|
||||
|
@ -179,13 +189,15 @@ class NeutronNetworkPluginTest(unittest.TestCase):
|
|||
|
||||
@mock.patch.object(db_api, 'network_allocation_delete', mock.Mock())
|
||||
@mock.patch.object(db_api, 'share_network_update', mock.Mock())
|
||||
@mock.patch.object(db_api, 'network_allocations_get_for_share_server',
|
||||
mock.Mock(return_value=[fake_network_allocation]))
|
||||
def test_deallocate_network_nominal(self):
|
||||
share_nw = {'id': fake_share_network['id']}
|
||||
share_nw['network_allocations'] = [fake_network_allocation]
|
||||
share_srv = {'id': fake_share_server['id']}
|
||||
share_srv['network_allocations'] = [fake_network_allocation]
|
||||
|
||||
with mock.patch.object(self.plugin.neutron_api, 'delete_port',
|
||||
mock.Mock()):
|
||||
self.plugin.deallocate_network(self.fake_context, share_nw)
|
||||
self.plugin.deallocate_network(self.fake_context, share_srv)
|
||||
self.plugin.neutron_api.delete_port.assert_called_once_with(
|
||||
fake_network_allocation['id'])
|
||||
db_api.network_allocation_delete.assert_called_once_with(
|
||||
|
@ -195,9 +207,11 @@ class NeutronNetworkPluginTest(unittest.TestCase):
|
|||
@mock.patch.object(db_api, 'share_network_update',
|
||||
mock.Mock(return_value=fake_share_network))
|
||||
@mock.patch.object(db_api, 'network_allocation_update', mock.Mock())
|
||||
@mock.patch.object(db_api, 'network_allocations_get_for_share_server',
|
||||
mock.Mock(return_value=[fake_network_allocation]))
|
||||
def test_deallocate_network_neutron_api_exception(self):
|
||||
share_nw = {'id': fake_share_network['id']}
|
||||
share_nw['network_allocations'] = [fake_network_allocation]
|
||||
share_srv = {'id': fake_share_server['id']}
|
||||
share_srv['network_allocations'] = [fake_network_allocation]
|
||||
|
||||
delete_port = mock.patch.object(self.plugin.neutron_api,
|
||||
'delete_port').start()
|
||||
|
@ -206,11 +220,11 @@ class NeutronNetworkPluginTest(unittest.TestCase):
|
|||
self.assertRaises(exception.NetworkException,
|
||||
self.plugin.deallocate_network,
|
||||
self.fake_context,
|
||||
share_nw)
|
||||
share_srv)
|
||||
db_api.network_allocation_update.assert_called_once_with(
|
||||
self.fake_context,
|
||||
fake_network_allocation['id'],
|
||||
{'status': constants.STATUS_ERROR})
|
||||
self.fake_context,
|
||||
fake_network_allocation['id'],
|
||||
{'status': constants.STATUS_ERROR})
|
||||
delete_port.stop()
|
||||
|
||||
@mock.patch.object(db_api, 'share_network_update', mock.Mock())
|
||||
|
|
|
@ -44,13 +44,7 @@ class ShareNetworkDBTest(test.TestCase):
|
|||
'cidr': '10.0.0.0/24',
|
||||
'ip_version': 4,
|
||||
'name': 'whatever',
|
||||
'description': 'fake description',
|
||||
'status': constants.STATUS_INACTIVE}
|
||||
self.allocation_dict = {'id': 'fake port id',
|
||||
'share_network_id': self.share_nw_dict['id'],
|
||||
'ip_address': 'fake ip address',
|
||||
'mac_address': 'fake mac address',
|
||||
'status': constants.STATUS_ACTIVE}
|
||||
'description': 'fake description'}
|
||||
|
||||
def test_create_one_network(self):
|
||||
result = db_api.share_network_create(self.fake_context,
|
||||
|
@ -59,7 +53,6 @@ class ShareNetworkDBTest(test.TestCase):
|
|||
self._check_fields(expected=self.share_nw_dict, actual=result)
|
||||
self.assertEqual(len(result['shares']), 0)
|
||||
self.assertEqual(len(result['security_services']), 0)
|
||||
self.assertEqual(len(result['network_allocations']), 0)
|
||||
|
||||
def test_create_two_networks_in_different_tenants(self):
|
||||
share_nw_dict2 = self.share_nw_dict.copy()
|
||||
|
@ -99,7 +92,6 @@ class ShareNetworkDBTest(test.TestCase):
|
|||
self._check_fields(expected=self.share_nw_dict, actual=result)
|
||||
self.assertEqual(len(result['shares']), 0)
|
||||
self.assertEqual(len(result['security_services']), 0)
|
||||
self.assertEqual(len(result['network_allocations']), 0)
|
||||
|
||||
def test_get_with_one_share(self):
|
||||
share_dict1 = {'id': 'fake share id1',
|
||||
|
@ -169,31 +161,6 @@ class ShareNetworkDBTest(test.TestCase):
|
|||
|
||||
self.assertEqual(len(result['security_services']), 2)
|
||||
|
||||
def test_get_with_one_allocation(self):
|
||||
db_api.share_network_create(self.fake_context, self.share_nw_dict)
|
||||
db_api.network_allocation_create(self.fake_context,
|
||||
self.allocation_dict)
|
||||
|
||||
result = db_api.share_network_get(self.fake_context,
|
||||
self.share_nw_dict['id'])
|
||||
|
||||
self.assertEqual(len(result['network_allocations']), 1)
|
||||
self._check_fields(expected=self.allocation_dict,
|
||||
actual=result['network_allocations'][0])
|
||||
|
||||
def test_get_with_two_allocations(self):
|
||||
allocation_dict2 = dict(self.allocation_dict)
|
||||
allocation_dict2['id'] = 'fake port id2'
|
||||
db_api.share_network_create(self.fake_context, self.share_nw_dict)
|
||||
db_api.network_allocation_create(self.fake_context,
|
||||
self.allocation_dict)
|
||||
db_api.network_allocation_create(self.fake_context, allocation_dict2)
|
||||
|
||||
result = db_api.share_network_get(self.fake_context,
|
||||
self.share_nw_dict['id'])
|
||||
|
||||
self.assertEqual(len(result['network_allocations']), 2)
|
||||
|
||||
def test_get_not_found(self):
|
||||
self.assertRaises(exception.ShareNetworkNotFound,
|
||||
db_api.share_network_get,
|
||||
|
@ -217,15 +184,15 @@ class ShareNetworkDBTest(test.TestCase):
|
|||
'fake id')
|
||||
|
||||
def test_update(self):
|
||||
new_status = constants.STATUS_ERROR
|
||||
new_name = 'fake_new_name'
|
||||
db_api.share_network_create(self.fake_context, self.share_nw_dict)
|
||||
result_update = db_api.share_network_update(self.fake_context,
|
||||
self.share_nw_dict['id'],
|
||||
{'status': new_status})
|
||||
{'name': new_name})
|
||||
result_get = db_api.share_network_get(self.fake_context,
|
||||
self.share_nw_dict['id'])
|
||||
|
||||
self.assertEqual(result_update['status'], new_status)
|
||||
self.assertEqual(result_update['name'], new_name)
|
||||
self._check_fields(expected=dict(result_update.iteritems()),
|
||||
actual=dict(result_get.iteritems()))
|
||||
|
||||
|
@ -329,32 +296,6 @@ class ShareNetworkDBTest(test.TestCase):
|
|||
self.share_nw_dict['id'],
|
||||
security_dict1['id'])
|
||||
|
||||
def test_add_security_service_association_error_status_active(self):
|
||||
security_dict1 = {'id': 'fake security service id1',
|
||||
'project_id': self.fake_context.project_id,
|
||||
'type': 'fake type'}
|
||||
|
||||
db_api.share_network_create(self.fake_context, self.share_nw_dict)
|
||||
db_api.share_network_update(self.fake_context,
|
||||
self.share_nw_dict['id'],
|
||||
{'status': constants.STATUS_ACTIVE})
|
||||
db_api.security_service_create(self.fake_context, security_dict1)
|
||||
|
||||
self.assertRaises(
|
||||
exception.ShareNetworkSecurityServiceAssociationError,
|
||||
db_api.share_network_add_security_service,
|
||||
self.fake_context,
|
||||
self.share_nw_dict['id'],
|
||||
security_dict1['id'])
|
||||
|
||||
assoc_ref = sqlalchemy_api.model_query(
|
||||
self.fake_context,
|
||||
models.ShareNetworkSecurityServiceAssociation).\
|
||||
filter_by(security_service_id=security_dict1['id']).\
|
||||
filter_by(share_network_id=self.share_nw_dict['id']).first()
|
||||
|
||||
self.assertTrue(assoc_ref is None)
|
||||
|
||||
def test_remove_security_service(self):
|
||||
security_dict1 = {'id': 'fake security service id1',
|
||||
'project_id': self.fake_context.project_id,
|
||||
|
@ -443,16 +384,3 @@ class ShareNetworkDBTest(test.TestCase):
|
|||
self.share_nw_dict['id'])
|
||||
|
||||
self.assertEqual(len(result['shares']), 0)
|
||||
|
||||
def test_network_allocations_relation(self):
|
||||
db_api.share_network_create(self.fake_context, self.share_nw_dict)
|
||||
|
||||
db_api.network_allocation_create(self.fake_context,
|
||||
self.allocation_dict)
|
||||
db_api.network_allocation_delete(self.fake_context,
|
||||
self.allocation_dict['id'])
|
||||
|
||||
result = db_api.share_network_get(self.fake_context,
|
||||
self.share_nw_dict['id'])
|
||||
|
||||
self.assertEqual(len(result['network_allocations']), 0)
|
||||
|
|
|
@ -193,9 +193,9 @@ class ServiceInstanceManagerTestCase(test.TestCase):
|
|||
self.stubs.Set(self._manager, '_get_ssh_pool',
|
||||
mock.Mock(return_value=mock.Mock()))
|
||||
|
||||
result = self._manager.get_service_instance(self._context,
|
||||
share_network_id='fake_share_network_id',
|
||||
create=True)
|
||||
result = self._manager.get_service_instance(
|
||||
self._context, share_server_id='fake_share_srv_id',
|
||||
share_network_id='fake_share_network_id', create=True)
|
||||
|
||||
self._manager._ensure_server.assert_called_once()
|
||||
self._manager._get_ssh_pool.assert_called_once_with(fake_server)
|
||||
|
@ -206,7 +206,7 @@ class ServiceInstanceManagerTestCase(test.TestCase):
|
|||
|
||||
def test_get_service_instance_existed_in_memory(self):
|
||||
fake_server = fake_compute.FakeServer()
|
||||
self._manager.share_networks_servers = {'fake_share_network_id':
|
||||
self._manager.share_networks_servers = {'fake_share_srv_id':
|
||||
fake_server}
|
||||
self.stubs.Set(self._manager, '_ensure_server',
|
||||
mock.Mock(return_value=True))
|
||||
|
@ -216,8 +216,9 @@ class ServiceInstanceManagerTestCase(test.TestCase):
|
|||
mock.Mock(return_value=mock.Mock()))
|
||||
self.stubs.Set(self._manager, '_create_service_instance', mock.Mock())
|
||||
|
||||
result = self._manager.get_service_instance(self._context,
|
||||
share_network_id='fake_share_network_id')
|
||||
result = self._manager.get_service_instance(
|
||||
self._context, share_server_id='fake_share_srv_id',
|
||||
share_network_id='fake_share_network_id')
|
||||
|
||||
self._manager._ensure_server.assert_called_once()
|
||||
self.assertFalse(self._manager._get_ssh_pool.called)
|
||||
|
@ -229,7 +230,7 @@ class ServiceInstanceManagerTestCase(test.TestCase):
|
|||
def test_get_service_instance_existed_in_memory_non_active(self):
|
||||
old_fake_server = fake_compute.FakeServer(status='ERROR')
|
||||
new_fake_server = fake_compute.FakeServer()
|
||||
self._manager.share_networks_servers = {'fake_share_network_id':
|
||||
self._manager.share_networks_servers = {'fake_share_srv_id':
|
||||
old_fake_server}
|
||||
self.stubs.Set(self._manager, '_ensure_server',
|
||||
mock.Mock(return_value=False))
|
||||
|
@ -243,9 +244,10 @@ class ServiceInstanceManagerTestCase(test.TestCase):
|
|||
self.stubs.Set(self._manager, '_get_ssh_pool',
|
||||
mock.Mock(return_value=mock.Mock()))
|
||||
|
||||
result = self._manager.get_service_instance(self._context,
|
||||
share_network_id='fake_share_network_id',
|
||||
create=True)
|
||||
result = self._manager.get_service_instance(
|
||||
self._context, share_server_id='fake_share_srv_id',
|
||||
share_network_id='fake_share_network_id',
|
||||
create=True)
|
||||
|
||||
self._manager._ensure_server.assert_has_calls(
|
||||
[mock.call(self._context, old_fake_server, update=True)])
|
||||
|
@ -269,8 +271,9 @@ class ServiceInstanceManagerTestCase(test.TestCase):
|
|||
self.stubs.Set(self._manager, '_get_ssh_pool',
|
||||
mock.Mock(return_value=mock.Mock()))
|
||||
|
||||
result = self._manager.get_service_instance(self._context,
|
||||
share_network_id='fake_share_network_id')
|
||||
result = self._manager.get_service_instance(
|
||||
self._context, share_server_id='fake_share_srv_id',
|
||||
share_network_id='fake_share_network_id')
|
||||
|
||||
self._manager._ensure_server.assert_called_once()
|
||||
self._manager._get_ssh_pool.assert_called_once_with(fake_server)
|
||||
|
@ -418,6 +421,7 @@ class ServiceInstanceManagerTestCase(test.TestCase):
|
|||
fake_security_group = fake_compute.FakeSecurityGroup()
|
||||
fake_instance_name = 'fake_instance_name'
|
||||
sn_id = 'fake_sn_id'
|
||||
srv_id = 'fake_srv_id'
|
||||
self.stubs.Set(self._manager, '_get_service_image',
|
||||
mock.Mock(return_value='fake_image_id'))
|
||||
self.stubs.Set(self._manager, '_get_key',
|
||||
|
@ -436,8 +440,8 @@ class ServiceInstanceManagerTestCase(test.TestCase):
|
|||
self.stubs.Set(service_instance.socket, 'socket', mock.Mock())
|
||||
self.stubs.Set(self._manager, '_get_service_instance_name',
|
||||
mock.Mock(return_value=fake_instance_name))
|
||||
result = self._manager._create_service_instance(self._context,
|
||||
sn_id, None)
|
||||
result = self._manager._create_service_instance(self._context, sn_id,
|
||||
srv_id, None)
|
||||
|
||||
self._manager._get_service_image.assert_called_once()
|
||||
self._manager._get_key.assert_called_once()
|
||||
|
@ -474,7 +478,7 @@ class ServiceInstanceManagerTestCase(test.TestCase):
|
|||
|
||||
self.assertRaises(exception.ManilaException,
|
||||
self._manager._create_service_instance,
|
||||
self._context, self.share, None)
|
||||
self._context, self.share, None, None)
|
||||
|
||||
self._manager.compute_api.server_create.assert_called_once()
|
||||
self.assertFalse(self._manager.compute_api.server_get.called)
|
||||
|
@ -504,7 +508,7 @@ class ServiceInstanceManagerTestCase(test.TestCase):
|
|||
|
||||
self.assertRaises(exception.ManilaException,
|
||||
self._manager._create_service_instance,
|
||||
self._context, self.share, None)
|
||||
self._context, self.share, None, None)
|
||||
|
||||
self._manager.neutron_api.delete_port.\
|
||||
assert_called_once_with(fake_port['id'])
|
||||
|
@ -519,7 +523,7 @@ class ServiceInstanceManagerTestCase(test.TestCase):
|
|||
mock.Mock(return_value=None))
|
||||
self.assertRaises(exception.ManilaException,
|
||||
self._manager._create_service_instance,
|
||||
self._context, self.share, None)
|
||||
self._context, self.share, None, None)
|
||||
|
||||
def test_setup_network_for_instance(self):
|
||||
fake_service_net = fake_network.FakeNetwork(subnets=[])
|
||||
|
|
|
@ -93,16 +93,18 @@ class ShareTestCase(test.TestCase):
|
|||
super(ShareTestCase, self).setUp()
|
||||
self.flags(connection_type='fake',
|
||||
share_driver='manila.tests.test_share.FakeShareDriver')
|
||||
self.share = importutils.import_object(CONF.share_manager)
|
||||
self.share_manager = importutils.import_object(CONF.share_manager)
|
||||
self.context = context.get_admin_context()
|
||||
|
||||
@staticmethod
|
||||
def _create_share(status="creating", size=0, snapshot_id=None):
|
||||
def _create_share(status="creating", size=0, snapshot_id=None,
|
||||
share_network_id=None):
|
||||
"""Create a share object."""
|
||||
share = {}
|
||||
share['share_proto'] = "NFS"
|
||||
share['size'] = size
|
||||
share['snapshot_id'] = snapshot_id
|
||||
share['share_network_id'] = share_network_id
|
||||
share['user_id'] = 'fake'
|
||||
share['project_id'] = 'fake'
|
||||
share['metadata'] = {'fake_key': 'fake_value'}
|
||||
|
@ -133,6 +135,26 @@ class ShareTestCase(test.TestCase):
|
|||
access['state'] = state
|
||||
return db.share_access_create(context.get_admin_context(), access)
|
||||
|
||||
@staticmethod
|
||||
def _create_share_server(state='new', share_network_id=None, host=None):
|
||||
"""Create a share server object."""
|
||||
srv = {}
|
||||
srv['host'] = host
|
||||
srv['share_network_id'] = share_network_id
|
||||
srv['status'] = state
|
||||
return db.share_server_create(context.get_admin_context(), srv)
|
||||
|
||||
@staticmethod
|
||||
def _create_share_network(state='new'):
|
||||
"""Create a share network object."""
|
||||
srv = {}
|
||||
srv['user_id'] = 'fake'
|
||||
srv['project_id'] = 'fake'
|
||||
srv['neutron_net_id'] = 'fake-neutron-net'
|
||||
srv['neutron_subnet_id'] = 'fake-neutron-subnet'
|
||||
srv['status'] = state
|
||||
return db.share_network_create(context.get_admin_context(), srv)
|
||||
|
||||
def test_init_host_ensuring_shares(self):
|
||||
"""Test init_host for ensuring shares and access rules."""
|
||||
|
||||
|
@ -148,8 +170,8 @@ class ShareTestCase(test.TestCase):
|
|||
return_value=[share, another_share])
|
||||
driver = mock.Mock()
|
||||
driver.get_share_stats.return_value = {}
|
||||
self.share.driver = driver
|
||||
self.share.init_host()
|
||||
self.share_manager.driver = driver
|
||||
self.share_manager.init_host()
|
||||
driver.ensure_share.assert_called_once_with(self.context, share)
|
||||
driver.allow_access.assert_called_once_with(
|
||||
self.context, share, mock.ANY)
|
||||
|
@ -162,7 +184,7 @@ class ShareTestCase(test.TestCase):
|
|||
snapshot = self._create_snapshot(share_id=share_id)
|
||||
snapshot_id = snapshot['id']
|
||||
|
||||
self.share.create_share(self.context, share_id,
|
||||
self.share_manager.create_share(self.context, share_id,
|
||||
snapshot_id=snapshot_id)
|
||||
self.assertEqual(share_id, db.share_get(context.get_admin_context(),
|
||||
share_id).id)
|
||||
|
@ -185,7 +207,7 @@ class ShareTestCase(test.TestCase):
|
|||
snapshot = self._create_snapshot(share_id=share_id)
|
||||
snapshot_id = snapshot['id']
|
||||
|
||||
self.share.create_snapshot(self.context, share_id, snapshot_id)
|
||||
self.share_manager.create_snapshot(self.context, share_id, snapshot_id)
|
||||
self.assertEqual(share_id,
|
||||
db.share_snapshot_get(context.get_admin_context(),
|
||||
snapshot_id).share_id)
|
||||
|
@ -193,7 +215,7 @@ class ShareTestCase(test.TestCase):
|
|||
snap = db.share_snapshot_get(self.context, snapshot_id)
|
||||
self.assertEqual(snap['status'], 'available')
|
||||
|
||||
self.share.delete_snapshot(self.context, snapshot_id)
|
||||
self.share_manager.delete_snapshot(self.context, snapshot_id)
|
||||
self.assertRaises(exception.NotFound,
|
||||
db.share_snapshot_get,
|
||||
self.context,
|
||||
|
@ -215,13 +237,15 @@ class ShareTestCase(test.TestCase):
|
|||
snapshot = self._create_snapshot(share_id=share_id)
|
||||
snapshot_id = snapshot['id']
|
||||
|
||||
self.assertRaises(exception.NotFound, self.share.create_snapshot,
|
||||
self.assertRaises(exception.NotFound,
|
||||
self.share_manager.create_snapshot,
|
||||
self.context, share_id, snapshot_id)
|
||||
|
||||
snap = db.share_snapshot_get(self.context, snapshot_id)
|
||||
self.assertEqual(snap['status'], 'error')
|
||||
|
||||
self.assertRaises(exception.NotFound, self.share.delete_snapshot,
|
||||
self.assertRaises(exception.NotFound,
|
||||
self.share_manager.delete_snapshot,
|
||||
self.context, snapshot_id)
|
||||
|
||||
self.assertEqual('error_deleting', db.share_snapshot_get(
|
||||
|
@ -239,29 +263,54 @@ class ShareTestCase(test.TestCase):
|
|||
snapshot = self._create_snapshot(share_id='fake_id')
|
||||
snapshot_id = snapshot['id']
|
||||
|
||||
self.share.delete_snapshot(self.context, snapshot_id)
|
||||
self.share_manager.delete_snapshot(self.context, snapshot_id)
|
||||
|
||||
snap = db.share_snapshot_get(self.context, snapshot_id)
|
||||
self.assertEqual(snap['status'], 'available')
|
||||
|
||||
def test_create_delete_share(self):
|
||||
"""Test share can be created and deleted."""
|
||||
share = self._create_share()
|
||||
share_id = share['id']
|
||||
self._create_access(share_id=share_id)
|
||||
def test_create_share_without_server(self):
|
||||
"""Test share can be created without share server."""
|
||||
|
||||
self.share.create_share(self.context, share_id)
|
||||
share_net = self._create_share_network()
|
||||
share = self._create_share(share_network_id=share_net['id'])
|
||||
|
||||
share_id = share['id']
|
||||
|
||||
def fake_setup_server(context, share_network, *args, **kwargs):
|
||||
return self._create_share_server(
|
||||
share_network_id=share_network['id'])
|
||||
|
||||
self.share_manager.driver.create_share = mock.Mock(
|
||||
return_value='fake_location')
|
||||
self.share_manager._setup_server = fake_setup_server
|
||||
self.share_manager.create_share(self.context, share_id)
|
||||
self.assertEqual(share_id, db.share_get(context.get_admin_context(),
|
||||
share_id).id)
|
||||
|
||||
shr = db.share_get(self.context, share_id)
|
||||
self.assertEqual(shr['status'], 'available')
|
||||
self.assertTrue(shr['share_server_id'])
|
||||
|
||||
self.share.delete_share(self.context, share_id)
|
||||
self.assertRaises(exception.NotFound,
|
||||
db.share_get,
|
||||
self.context,
|
||||
share_id)
|
||||
def test_create_share_with_server(self):
|
||||
"""Test share can be created with share server."""
|
||||
share_net = self._create_share_network()
|
||||
share = self._create_share(share_network_id=share_net['id'])
|
||||
share_srv = self._create_share_server(
|
||||
share_network_id=share_net['id'], host=self.share_manager.host,
|
||||
state='ACTIVE')
|
||||
|
||||
share_id = share['id']
|
||||
|
||||
self.share_manager.driver = mock.Mock()
|
||||
self.share_manager.driver.create_share.return_value = "fake_location"
|
||||
self.share_manager.create_share(self.context, share_id)
|
||||
self.assertFalse(self.share_manager.driver.setup_network.called)
|
||||
self.assertEqual(share_id, db.share_get(context.get_admin_context(),
|
||||
share_id).id)
|
||||
|
||||
shr = db.share_get(self.context, share_id)
|
||||
self.assertEquals(shr['status'], 'available')
|
||||
self.assertEquals(shr['share_server_id'], share_srv['id'])
|
||||
|
||||
def test_create_delete_share_error(self):
|
||||
"""Test share can be created and deleted with error."""
|
||||
|
@ -279,14 +328,14 @@ class ShareTestCase(test.TestCase):
|
|||
share = self._create_share()
|
||||
share_id = share['id']
|
||||
self.assertRaises(exception.NotFound,
|
||||
self.share.create_share,
|
||||
self.share_manager.create_share,
|
||||
self.context,
|
||||
share_id)
|
||||
|
||||
shr = db.share_get(self.context, share_id)
|
||||
self.assertEqual(shr['status'], 'error')
|
||||
self.assertRaises(exception.NotFound,
|
||||
self.share.delete_share,
|
||||
self.share_manager.delete_share,
|
||||
self.context,
|
||||
share_id)
|
||||
|
||||
|
@ -299,11 +348,11 @@ class ShareTestCase(test.TestCase):
|
|||
share_id = share['id']
|
||||
access = self._create_access(share_id=share_id)
|
||||
access_id = access['id']
|
||||
self.share.allow_access(self.context, access_id)
|
||||
self.share_manager.allow_access(self.context, access_id)
|
||||
self.assertEqual('active', db.share_access_get(self.context,
|
||||
access_id).state)
|
||||
|
||||
self.share.deny_access(self.context, access_id)
|
||||
self.share_manager.deny_access(self.context, access_id)
|
||||
self.assertRaises(exception.NotFound,
|
||||
db.share_access_get,
|
||||
self.context,
|
||||
|
@ -327,7 +376,7 @@ class ShareTestCase(test.TestCase):
|
|||
access_id = access['id']
|
||||
|
||||
self.assertRaises(exception.NotFound,
|
||||
self.share.allow_access,
|
||||
self.share_manager.allow_access,
|
||||
self.context,
|
||||
access_id)
|
||||
|
||||
|
@ -335,128 +384,9 @@ class ShareTestCase(test.TestCase):
|
|||
self.assertEqual(acs['state'], 'error')
|
||||
|
||||
self.assertRaises(exception.NotFound,
|
||||
self.share.deny_access,
|
||||
self.share_manager.deny_access,
|
||||
self.context,
|
||||
access_id)
|
||||
|
||||
acs = db.share_access_get(self.context, access_id)
|
||||
self.assertEqual(acs['state'], 'error')
|
||||
|
||||
def test_create_delete_share_with_metadata(self):
|
||||
"""Test share can be created with metadata and deleted."""
|
||||
test_meta = {'fake_key': 'fake_value'}
|
||||
share = self._create_share()
|
||||
share_id = share['id']
|
||||
self.share.create_share(self.context, share_id)
|
||||
result_meta = {
|
||||
share.share_metadata[0].key: share.share_metadata[0].value}
|
||||
self.assertEqual(result_meta, test_meta)
|
||||
|
||||
self.share.delete_share(self.context, share_id)
|
||||
self.assertRaises(exception.NotFound,
|
||||
db.share_get,
|
||||
self.context,
|
||||
share_id)
|
||||
|
||||
def test_create_share_with_invalid_metadata(self):
|
||||
"""Test share create with too much metadata fails."""
|
||||
share_api = manila.share.api.API()
|
||||
test_meta = {'fake_key': 'fake_value' * 1025}
|
||||
self.assertRaises(exception.InvalidShareMetadataSize,
|
||||
share_api.create,
|
||||
self.context,
|
||||
'nfs',
|
||||
1,
|
||||
'name',
|
||||
'description',
|
||||
metadata=test_meta)
|
||||
|
||||
def test_setup_share_network(self):
|
||||
share_network = {'id': 'fake_sn_id', 'share_network': 'share_network'}
|
||||
allocation_number = 555
|
||||
self.share.driver.get_network_allocations_number = mock.Mock(
|
||||
return_value=allocation_number)
|
||||
self.share.network_api.allocate_network = mock.Mock(
|
||||
return_value=share_network)
|
||||
self.share.driver.setup_network = mock.Mock()
|
||||
self.share._activate_share_network(context=self.context,
|
||||
share_network=share_network)
|
||||
self.share.network_api.allocate_network.assert_called_once_with(
|
||||
self.context, share_network, count=allocation_number)
|
||||
self.share.driver.setup_network.assert_called_once_with(
|
||||
share_network, metadata=None)
|
||||
|
||||
def test_setup_share_network_error(self):
|
||||
network_info = {'fake': 'fake', 'id': 'fakeid'}
|
||||
drv_allocation_cnt = mock.patch.object(
|
||||
self.share.driver,
|
||||
'get_network_allocations_number').start()
|
||||
drv_allocation_cnt.return_value = 555
|
||||
nw_api_allocate_nw = mock.patch.object(self.share.network_api,
|
||||
'allocate_network').start()
|
||||
nw_api_allocate_nw.return_value = network_info
|
||||
nw_api_deallocate_nw = mock.patch.object(self.share.network_api,
|
||||
'deallocate_network').start()
|
||||
|
||||
with mock.patch.object(self.share.driver, 'setup_network',
|
||||
mock.Mock(side_effect=exception.Invalid)):
|
||||
self.assertRaises(exception.Invalid,
|
||||
self.share._activate_share_network,
|
||||
self.context, network_info)
|
||||
nw_api_deallocate_nw.assert_called_once_with(self.context,
|
||||
network_info)
|
||||
|
||||
drv_allocation_cnt.stop()
|
||||
nw_api_allocate_nw.stop()
|
||||
nw_api_deallocate_nw.stop()
|
||||
|
||||
def test_activate_network(self):
|
||||
share_network = {'id': 'fake network id'}
|
||||
db_share_nw_get = mock.patch.object(self.share.db,
|
||||
'share_network_get').start()
|
||||
db_share_nw_get.return_value = share_network
|
||||
drv_get_alloc_cnt = mock.patch.object(
|
||||
self.share.driver,
|
||||
'get_network_allocations_number').start()
|
||||
drv_get_alloc_cnt.return_value = 1
|
||||
nw_api_allocate_nw = mock.patch.object(self.share.network_api,
|
||||
'allocate_network').start()
|
||||
nw_api_allocate_nw.return_value = share_network
|
||||
|
||||
with mock.patch.object(self.share.driver, 'setup_network',
|
||||
mock.Mock()):
|
||||
self.share.activate_network(self.context, share_network['id'])
|
||||
db_share_nw_get.assert_called_once_with(self.context,
|
||||
share_network['id'])
|
||||
drv_get_alloc_cnt.assert_any_call()
|
||||
nw_api_allocate_nw.assert_called_once_with(self.context,
|
||||
share_network,
|
||||
count=1)
|
||||
self.share.driver.setup_network.assert_called_once_with(
|
||||
share_network,
|
||||
metadata=None)
|
||||
|
||||
db_share_nw_get.stop()
|
||||
drv_get_alloc_cnt.stop()
|
||||
nw_api_allocate_nw.stop()
|
||||
|
||||
def test_deactivate_network(self):
|
||||
share_network = {'id': 'fake network id'}
|
||||
db_share_nw_get = mock.patch.object(self.share.db,
|
||||
'share_network_get').start()
|
||||
db_share_nw_get.return_value = share_network
|
||||
nw_api_deallocate_nw = mock.patch.object(self.share.network_api,
|
||||
'deallocate_network').start()
|
||||
|
||||
with mock.patch.object(self.share.driver, 'teardown_network',
|
||||
mock.Mock()):
|
||||
self.share.deactivate_network(self.context, share_network['id'])
|
||||
db_share_nw_get.assert_called_once_with(self.context,
|
||||
share_network['id'])
|
||||
nw_api_deallocate_nw.assert_called_once_with(self.context,
|
||||
share_network)
|
||||
self.share.driver.teardown_network.assert_called_once_with(
|
||||
share_network)
|
||||
|
||||
db_share_nw_get.stop()
|
||||
nw_api_deallocate_nw.stop()
|
||||
|
|
|
@ -44,6 +44,7 @@ def fake_share(**kwargs):
|
|||
'size': 1,
|
||||
'share_proto': 'NFS',
|
||||
'share_network_id': 'fake share network id',
|
||||
'share_server_id': 'fake share server id',
|
||||
'export_location': '127.0.0.1:/mnt/nfs/volume-00002',
|
||||
}
|
||||
share.update(kwargs)
|
||||
|
@ -100,6 +101,10 @@ class GenericShareDriverTestCase(test.TestCase):
|
|||
self._driver.admin_context = self._context
|
||||
|
||||
self.fake_sn = {"id": "fake_sn_id"}
|
||||
self.fake_net_info = {
|
||||
"id": "fake_srv_id",
|
||||
"share_network_id": "fake_sn_id"
|
||||
}
|
||||
fsim = fake_service_instance.FakeServiceInstanceManager()
|
||||
sim = mock.Mock(return_value=fsim)
|
||||
self._driver.instance_manager = sim
|
||||
|
@ -531,7 +536,9 @@ class GenericShareDriverTestCase(test.TestCase):
|
|||
|
||||
def test_setup_network(self):
|
||||
sim = self._driver.instance_manager
|
||||
self._driver.setup_network(self.fake_sn)
|
||||
net_info = self.fake_sn.copy()
|
||||
net_info['share_network_id'] = net_info['id']
|
||||
self._driver.setup_network(net_info)
|
||||
sim.get_service_instance.assert_called_once()
|
||||
|
||||
def test_setup_network_revert(self):
|
||||
|
@ -539,16 +546,18 @@ class GenericShareDriverTestCase(test.TestCase):
|
|||
def raise_exception(*args, **kwargs):
|
||||
raise exception.ServiceInstanceException
|
||||
|
||||
net_info = self.fake_sn.copy()
|
||||
net_info['share_network_id'] = net_info['id']
|
||||
self.stubs.Set(self._driver, 'get_service_instance',
|
||||
mock.Mock(side_effect=raise_exception))
|
||||
self.assertRaises(exception.ServiceInstanceException,
|
||||
self._driver.setup_network,
|
||||
self.fake_sn)
|
||||
net_info)
|
||||
|
||||
def test_teardown_network(self):
|
||||
sim = self._driver.instance_manager
|
||||
self._driver.service_instance_manager = sim
|
||||
self._driver.teardown_network(self.fake_sn)
|
||||
self._driver.teardown_network(self.fake_net_info)
|
||||
sim.delete_service_instance.assert_called_once()
|
||||
|
||||
|
||||
|
|
|
@ -78,7 +78,8 @@ def cinderclient(context):
|
|||
c = cinder_client.Client(CONF.cinder_admin_username,
|
||||
CONF.cinder_admin_password,
|
||||
CONF.cinder_admin_tenant_name,
|
||||
CONF.cinder_admin_auth_url)
|
||||
CONF.cinder_admin_auth_url,
|
||||
retries=CONF.cinder_http_retries,)
|
||||
c.authenticate()
|
||||
return c
|
||||
|
||||
|
|
Loading…
Reference in New Issue