Share servers implementation

Change-Id: I90664235237e25190191a4499e513a9fe589b855
This commit is contained in:
Yulia Portnova 2014-05-16 16:51:32 +03:00
parent 74a41f35a1
commit 2c7595a386
26 changed files with 637 additions and 787 deletions

View File

@ -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)

View File

@ -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":

View File

@ -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))

View File

@ -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())

View File

@ -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')

View File

@ -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',

View File

@ -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)
##################

View File

@ -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()

View File

@ -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:

View File

@ -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)

View File

@ -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")

View File

@ -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

View File

@ -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:

View File

@ -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()

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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()

View File

@ -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())

View File

@ -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)

View File

@ -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=[])

View File

@ -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()

View File

@ -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()

View File

@ -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