Share server details

Change-Id: I0027ab5319bd7d46e42b04f551932d0a55871056
This commit is contained in:
Yulia Portnova 2014-05-22 17:04:28 +03:00
parent 2c7595a386
commit 4c8a658d95
10 changed files with 183 additions and 66 deletions

View File

@ -607,6 +607,17 @@ def share_server_get_all(context):
return IMPL.share_server_get_all(context)
def share_server_backend_details_set(context, share_server_id, server_details):
"""Create DB record with backend details."""
return IMPL.share_server_backend_details_set(context, share_server_id,
server_details)
def share_server_backend_details_get(context, share_server_id):
"""Get all backend details records for share server."""
return IMPL.share_server_backend_details_get(context, share_server_id)
##################

View File

@ -1641,7 +1641,8 @@ 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)
return model_query(context, models.ShareServer, session=session)\
.options(joinedload('shares'))
@require_context
@ -1661,6 +1662,8 @@ def share_server_delete(context, id):
session = get_session()
with session.begin():
server_ref = share_server_get(context, id, session=session)
for item in server_ref['backend_details']:
item.delete(session=session)
server_ref.delete(session=session)
@ -1680,6 +1683,8 @@ def share_server_get(context, server_id, session=None):
.first()
if result is None:
raise exception.ShareServerNotFound(share_server_id=server_id)
result['backend_details'] = share_server_backend_details_get(
context, server_id, session=session)
return result
@ -1710,6 +1715,40 @@ def share_server_get_all(context):
return _server_get_query(context).all()
@require_context
def share_server_backend_details_set(context, share_server_id, server_details):
share_server_get(context, share_server_id)
for meta_key, meta_value in server_details.items():
meta_ref = models.ShareServerBackendDetails()
meta_ref.update({
'key': meta_key,
'value': meta_value,
'share_server_id': share_server_id
})
meta_ref.save()
return server_details
@require_context
def share_server_backend_details_delete(context, share_server_id,
session=None):
if not session:
session = get_session()
share_server_details = share_server_backend_details_get(
context, share_server_id, session=session)
for item in share_server_details:
item.delete(session=session)
@require_context
def share_server_backend_details_get(context, share_server_id,
session=None):
return model_query(context, models.ShareServerBackendDetails,
session=session)\
.filter_by(share_server_id=share_server_id).all()
###################

View File

@ -320,6 +320,22 @@ def upgrade(migrate_engine):
mysql_charset='utf8',
)
share_server_backend_details = Table(
'share_server_backend_details', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('deleted_at', DateTime),
Column('deleted', String(length=36), default=0),
Column('id', Integer, primary_key=True, nullable=False),
Column('share_server_id', String(length=36),
ForeignKey('share_servers.id'),
nullable=False),
Column('key', String(length=255), nullable=False),
Column('value', String(length=1023), nullable=False),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
network_allocations = Table(
'network_allocations', meta,
Column('created_at', DateTime),
@ -383,7 +399,7 @@ def upgrade(migrate_engine):
reservations, project_user_quotas, security_services,
share_networks, ss_nw_association,
share_servers, network_allocations, shares, access_map,
share_snapshots,
share_snapshots, share_server_backend_details,
share_metadata, volume_types, volume_type_extra_specs]
for table in tables:
@ -401,7 +417,7 @@ def upgrade(migrate_engine):
"share_metadata", "security_services", "share_networks",
"network_allocations", "shares", "share_servers",
"share_network_security_service_association", "volume_types",
"volume_type_extra_specs"]
"volume_type_extra_specs", "share_server_backend_details"]
sql = "SET foreign_key_checks = 0;"
for table in tables:

View File

@ -448,6 +448,17 @@ class ShareServer(BASE, ManilaBase):
'Share.deleted == "False")')
class ShareServerBackendDetails(BASE, ManilaBase):
"""Represents a metadata key/value pair for a share server."""
__tablename__ = 'share_server_backend_details'
deleted = Column(String(36), default='False')
id = Column(Integer, primary_key=True)
key = Column(String(255), nullable=False)
value = Column(String(1023), nullable=False)
share_server_id = Column(String(36), ForeignKey('share_servers.id'),
nullable=False)
class ShareNetworkSecurityServiceAssociation(BASE, ManilaBase):
"""" Association table between compute_zones and compute_nodes tables.
"""

View File

@ -91,35 +91,36 @@ class ShareDriver(object):
if self.configuration:
self.configuration.append_config_values(share_opts)
def create_share(self, context, share):
def create_share(self, context, share, share_server=None):
"""Is called to create share."""
raise NotImplementedError()
def create_share_from_snapshot(self, context, share, snapshot):
def create_share_from_snapshot(self, context, share, snapshot,
share_server=None):
"""Is called to create share from snapshot."""
raise NotImplementedError()
def create_snapshot(self, context, snapshot):
def create_snapshot(self, context, snapshot, share_server=None):
"""Is called to create snapshot."""
raise NotImplementedError()
def delete_share(self, context, share):
def delete_share(self, context, share, share_server=None):
"""Is called to remove share."""
raise NotImplementedError()
def delete_snapshot(self, context, snapshot):
def delete_snapshot(self, context, snapshot, share_server=None):
"""Is called to remove snapshot."""
raise NotImplementedError()
def ensure_share(self, context, share):
def ensure_share(self, context, share, share_server=None):
"""Invoked to sure that share is exported."""
raise NotImplementedError()
def allow_access(self, context, share, access):
def allow_access(self, context, share, access, share_server=None):
"""Allow access to the share."""
raise NotImplementedError()
def deny_access(self, context, share, access):
def deny_access(self, context, share, access, share_server=None):
"""Deny access to the share."""
raise NotImplementedError()

View File

@ -119,7 +119,7 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
self.configuration,
self.share_networks_locks)
def create_share(self, context, share):
def create_share(self, context, share, share_server=None):
"""Creates share."""
if share['share_network_id'] is None:
raise exception.ManilaException(
@ -327,7 +327,8 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
self._stats = data
def create_share_from_snapshot(self, context, share, snapshot):
def create_share_from_snapshot(self, context, share, snapshot,
share_server=None):
"""Is called to create share from snapshot."""
server = self.get_service_instance(
self.admin_context, share_server_id=share['share_server_id'],
@ -339,7 +340,7 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
share['name'])
return location
def delete_share(self, context, share):
def delete_share(self, context, share, share_server=None):
"""Deletes share."""
if not share['share_network_id']:
return
@ -354,7 +355,7 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
self._detach_volume(self.admin_context, share, server)
self._deallocate_container(self.admin_context, share)
def create_snapshot(self, context, snapshot):
def create_snapshot(self, context, snapshot, share_server=None):
"""Creates a snapshot."""
volume = self._get_volume(self.admin_context, snapshot['share_id'])
volume_snapshot_name = (self.configuration.
@ -376,7 +377,7 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
'created in %ss. Giving up') %
self.configuration.max_time_to_create_volume)
def delete_snapshot(self, context, snapshot):
def delete_snapshot(self, context, snapshot, share_server=None):
"""Deletes a snapshot."""
volume_snapshot = self._get_volume_snapshot(self.admin_context,
snapshot['id'])
@ -398,7 +399,7 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
'deleted in %ss. Giving up') %
self.configuration.max_time_to_create_volume)
def ensure_share(self, context, share):
def ensure_share(self, context, share, share_server=None):
"""Ensure that storage are mounted and exported."""
server = self.get_service_instance(
context, share_server_id=share['share_server_id'],
@ -408,7 +409,7 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
self._mount_device(context, share, server, volume)
self._get_helper(share).create_export(server, share['name'])
def allow_access(self, context, share, access):
def allow_access(self, context, share, access, share_server=None):
"""Allow access to the share."""
server = self.get_service_instance(
self.admin_context, share_server_id=share['share_server_id'],
@ -420,7 +421,7 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
access['access_type'],
access['access_to'])
def deny_access(self, context, share, access):
def deny_access(self, context, share, access, share_server=None):
"""Deny access to the share."""
if not share['share_network_id']:
return
@ -457,6 +458,8 @@ class GenericShareDriver(driver.ExecuteMixin, driver.ShareDriver):
share_network_id=sn_id,
create=True)
return {}
def teardown_network(self, network_info):
sn_id = network_info["share_network_id"]
srv_id = network_info["id"]

View File

@ -113,6 +113,7 @@ class NetAppClusteredShareDriver(driver.NetAppShareDriver):
"""Creates and configures new vserver."""
LOG.debug('Configuring network %s' % network_info['id'])
self._vserver_create_if_not_exists(network_info)
return {}
def _get_cluster_nodes(self):
"""Get all available cluster nodes."""
@ -447,7 +448,7 @@ class NetAppClusteredShareDriver(driver.NetAppShareDriver):
LOG.debug("Found available aggregates: %r" % aggr_dict)
return aggr_dict
def create_share(self, context, share):
def create_share(self, context, share, share_server=None):
"""Creates new share."""
if not share.get('share_server_id'):
msg = _("Cannot create share %s. "
@ -462,7 +463,7 @@ class NetAppClusteredShareDriver(driver.NetAppShareDriver):
return self._create_export(share, vserver, vserver_client)
def create_share_from_snapshot(self, context, share, snapshot,
net_details=None):
share_server=None):
"""Creates new share form snapshot."""
vserver = self._get_vserver_name(share['share_server_id'])
vserver_client = driver.NetAppApiClient(
@ -540,7 +541,7 @@ class NetAppClusteredShareDriver(driver.NetAppShareDriver):
LOG.debug('Deleting share %s' % share_name)
vserver_client.send_request('volume-destroy', args)
def delete_share(self, context, share):
def delete_share(self, context, share, share_server=None):
"""Deletes share."""
share_name = self._get_valid_share_name(share['id'])
vserver = self._get_vserver_name(share['share_server_id'])
@ -573,7 +574,7 @@ class NetAppClusteredShareDriver(driver.NetAppShareDriver):
export_location = helper.create_share(share_name, ip_address)
return export_location
def create_snapshot(self, context, snapshot):
def create_snapshot(self, context, snapshot, share_server=None):
"""Creates a snapshot of a share."""
vserver = self._get_vserver_name(snapshot['share']['share_network_id'])
vserver_client = driver.NetAppApiClient(
@ -595,7 +596,7 @@ class NetAppClusteredShareDriver(driver.NetAppShareDriver):
if target:
helper.delete_share(share)
def delete_snapshot(self, context, snapshot):
def delete_snapshot(self, context, snapshot, share_server=None):
"""Deletes a snapshot of a share."""
vserver = self._get_vserver_name(snapshot['share']['share_network_id'])
vserver_client = driver.NetAppApiClient(
@ -628,7 +629,7 @@ class NetAppClusteredShareDriver(driver.NetAppShareDriver):
LOG.debug('Unmounting volume %s' % share_name)
vserver_client.send_request('volume-unmount', args)
def allow_access(self, context, share, access):
def allow_access(self, context, share, access, share_server=None):
"""Allows access to a given NAS storage for IPs in access."""
vserver = self._get_vserver_name(share['share_network_id'])
vserver_client = driver.NetAppApiClient(
@ -638,7 +639,7 @@ class NetAppClusteredShareDriver(driver.NetAppShareDriver):
helper.set_client(vserver_client)
return helper.allow_access(context, share, access)
def deny_access(self, context, share, access):
def deny_access(self, context, share, access, share_server=None):
"""Denies access to a given NAS storage for IPs in access."""
vserver = self._get_vserver_name(share['share_network_id'])
vserver_client = driver.NetAppApiClient(

View File

@ -122,16 +122,17 @@ class NetAppShareDriver(driver.ShareDriver):
self._check_licenses()
self._check_vfiler_exists()
def create_share(self, context, share):
def create_share(self, context, share, share_server=None):
"""Creates container for new share and exports it."""
self._allocate_container(share)
return self._create_export(share)
def create_share_from_snapshot(self, context, share, snapshot):
def create_share_from_snapshot(self, context, share, snapshot,
share_server=None):
self._allocate_container_from_snapshot(share, snapshot)
return self._create_export(share)
def ensure_share(self, context, share):
def ensure_share(self, context, share, share_server=None):
""""""
pass
@ -152,7 +153,7 @@ class NetAppShareDriver(driver.ShareDriver):
self._client.send_request('volume-clone-create', args)
def delete_share(self, context, share):
def delete_share(self, context, share, share_server=None):
"""Deletes share."""
share_name = self._get_valid_share_name(share['id'])
if self._share_exists(share_name):
@ -184,7 +185,7 @@ class NetAppShareDriver(driver.ShareDriver):
share_name, self.configuration.netapp_nas_server_hostname)
return export_location
def create_snapshot(self, context, snapshot):
def create_snapshot(self, context, snapshot, share_server=None):
"""Creates a snapshot of a share."""
share_name = self._get_valid_share_name(snapshot['share_id'])
snapshot_name = self._get_valid_snapshot_name(snapshot['id'])
@ -201,7 +202,7 @@ class NetAppShareDriver(driver.ShareDriver):
if target:
helper.delete_share(share)
def delete_snapshot(self, context, snapshot):
def delete_snapshot(self, context, snapshot, share_server=None):
"""Deletes a snapshot of a share."""
share_name = self._get_valid_share_name(snapshot['share_id'])
snapshot_name = self._get_valid_snapshot_name(snapshot['id'])
@ -214,12 +215,12 @@ class NetAppShareDriver(driver.ShareDriver):
LOG.debug('Deleting snapshot %s' % snapshot_name)
self._client.send_request('snapshot-delete', args)
def allow_access(self, context, share, access):
def allow_access(self, context, share, access, share_server=None):
"""Allows access to a given NAS storage for IPs in access."""
helper = self._get_helper(share)
return helper.allow_access(context, share, access)
def deny_access(self, context, share, access):
def deny_access(self, context, share, access, share_server=None):
"""Denies access to a given NAS storage for IPs in access."""
helper = self._get_helper(share)
return helper.deny_access(context, share, access)

View File

@ -19,7 +19,6 @@
: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
@ -115,6 +114,11 @@ class ShareManager(manager.SchedulerDependentManager):
return _get_or_create_server()
def _get_share_server(self, context, share):
if share['share_server_id']:
return self.db.share_server_get(
context, share['share_server_id'])
def create_share(self, context, share_id, request_spec=None,
filter_properties=None, snapshot_id=None):
"""Creates a share."""
@ -143,12 +147,16 @@ class ShareManager(manager.SchedulerDependentManager):
share_ref = self.db.share_update(
context, share_id, {'share_server_id': share_server['id']})
LOG.debug("Using share server %s" % share_server['id'])
else:
share_server = None
try:
if snapshot_ref:
export_location = self.driver.create_share_from_snapshot(
context, share_ref, snapshot_ref)
else:
export_location = self.driver.create_share(context, share_ref)
export_location = self.driver.create_share(
context, share_ref, share_server=share_server)
self.db.share_update(context, share_id,
{'export_location': export_location})
except Exception:
@ -165,6 +173,7 @@ class ShareManager(manager.SchedulerDependentManager):
"""Delete a share."""
context = context.elevated()
share_ref = self.db.share_get(context, share_id)
share_server = self._get_share_server(context, share_ref)
if context.project_id != share_ref['project_id']:
project_id = share_ref['project_id']
@ -173,8 +182,9 @@ class ShareManager(manager.SchedulerDependentManager):
rules = self.db.share_access_get_all_for_share(context, share_id)
try:
for access_ref in rules:
self._deny_access(context, access_ref, share_ref)
self.driver.delete_share(context, share_ref)
self._deny_access(context, access_ref, share_ref, share_server)
self.driver.delete_share(context, share_ref,
share_server=share_server)
except Exception:
with excutils.save_and_reraise_exception():
self.db.share_update(context, share_id,
@ -203,10 +213,11 @@ class ShareManager(manager.SchedulerDependentManager):
def create_snapshot(self, context, share_id, snapshot_id):
"""Create snapshot for share."""
snapshot_ref = self.db.share_snapshot_get(context, snapshot_id)
share_server = self._get_share_server(context,
snapshot_ref['share'])
try:
snap_name = snapshot_ref['name']
model_update = self.driver.create_snapshot(context, snapshot_ref)
model_update = self.driver.create_snapshot(
context, snapshot_ref, share_server=share_server)
if model_update:
self.db.share_snapshot_update(context, snapshot_ref['id'],
model_update)
@ -228,13 +239,17 @@ class ShareManager(manager.SchedulerDependentManager):
context = context.elevated()
snapshot_ref = self.db.share_snapshot_get(context, snapshot_id)
share_server = self._get_share_server(context,
snapshot_ref['share'])
if context.project_id != snapshot_ref['project_id']:
project_id = snapshot_ref['project_id']
else:
project_id = context.project_id
try:
self.driver.delete_snapshot(context, snapshot_ref)
self.driver.delete_snapshot(context, snapshot_ref,
share_server=share_server)
except exception.ShareSnapshotIsBusy:
self.db.share_snapshot_update(context, snapshot_ref['id'],
{'status': 'available'})
@ -261,8 +276,11 @@ class ShareManager(manager.SchedulerDependentManager):
try:
access_ref = self.db.share_access_get(context, access_id)
share_ref = self.db.share_get(context, access_ref['share_id'])
share_server = self._get_share_server(context,
share_ref)
if access_ref['state'] == access_ref.STATE_NEW:
self.driver.allow_access(context, share_ref, access_ref)
self.driver.allow_access(context, share_ref, access_ref,
share_server=share_server)
self.db.share_access_update(
context, access_id, {'state': access_ref.STATE_ACTIVE})
except Exception:
@ -274,12 +292,15 @@ class ShareManager(manager.SchedulerDependentManager):
"""Deny access to some share."""
access_ref = self.db.share_access_get(context, access_id)
share_ref = self.db.share_get(context, access_ref['share_id'])
self._deny_access(context, access_ref, share_ref)
share_server = self._get_share_server(context,
share_ref)
self._deny_access(context, access_ref, share_ref, share_server)
def _deny_access(self, context, access_ref, share_ref):
def _deny_access(self, context, access_ref, share_ref, share_server):
access_id = access_ref['id']
try:
self.driver.deny_access(context, share_ref, access_ref)
self.driver.deny_access(context, share_ref, access_ref,
share_server=share_server)
except Exception:
with excutils.save_and_reraise_exception():
self.db.share_access_update(
@ -333,8 +354,14 @@ class ShareManager(manager.SchedulerDependentManager):
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'],
server_info = self.driver.setup_network(network_info,
metadata=metadata)
if server_info and isinstance(server_info, dict):
self.db.share_server_backend_details_set(context,
share_server['id'],
server_info)
return self.db.share_server_update(
context, share_server['id'],
{'status': constants.STATUS_ACTIVE})
except Exception:
with excutils.save_and_reraise_exception():

View File

@ -43,28 +43,29 @@ class FakeShareDriver(object):
self.db.share_network_update = mock.Mock(
side_effect=share_network_update)
def create_snapshot(self, context, snapshot):
def create_snapshot(self, context, snapshot, share_server=None):
pass
def delete_snapshot(self, context, snapshot):
def delete_snapshot(self, context, snapshot, share_server=None):
pass
def create_share(self, context, share):
def create_share(self, context, share, share_server=None):
pass
def create_share_from_snapshot(self, context, share, snapshot):
def create_share_from_snapshot(self, context, share, snapshot,
share_server=None):
pass
def delete_share(self, context, share):
def delete_share(self, context, share, share_server=None):
pass
def ensure_share(self, context, share):
def ensure_share(self, context, share, share_server=None):
pass
def allow_access(self, context, share, access):
def allow_access(self, context, share, access, share_server=None):
pass
def deny_access(self, context, share, access):
def deny_access(self, context, share, access, share_server=None):
pass
def check_for_setup_error(self):
@ -142,7 +143,13 @@ class ShareTestCase(test.TestCase):
srv['host'] = host
srv['share_network_id'] = share_network_id
srv['status'] = state
return db.share_server_create(context.get_admin_context(), srv)
share_srv = db.share_server_create(context.get_admin_context(), srv)
backend_details = {'fake': 'fake'}
db.share_server_backend_details_set(context.get_admin_context(),
share_srv['id'],
backend_details)
return db.share_server_get(context.get_admin_context(),
share_srv['id'])
@staticmethod
def _create_share_network(state='new'):
@ -195,7 +202,7 @@ class ShareTestCase(test.TestCase):
def test_create_delete_share_snapshot(self):
"""Test share's snapshot can be created and deleted."""
def _fake_create_snapshot(self, context, snapshot):
def _fake_create_snapshot(self, *args, **kwargs):
snapshot['progress'] = '99%'
return snapshot
@ -224,7 +231,7 @@ class ShareTestCase(test.TestCase):
def test_create_delete_share_snapshot_error(self):
"""Test snapshot can be created and deleted with error."""
def _fake_create_delete_snapshot(self, context, snapshot):
def _fake_create_delete_snapshot(self, *args, **kwargs):
raise exception.NotFound()
self.stubs.Set(FakeShareDriver, "create_snapshot",
@ -254,13 +261,13 @@ class ShareTestCase(test.TestCase):
def test_delete_share_if_busy(self):
"""Test snapshot could not be deleted if busy."""
def _fake_delete_snapshot(self, context, snapshot):
def _fake_delete_snapshot(self, *args, **kwargs):
raise exception.ShareSnapshotIsBusy(snapshot_name='fakename')
self.stubs.Set(FakeShareDriver, "delete_snapshot",
_fake_delete_snapshot)
snapshot = self._create_snapshot(share_id='fake_id')
share = self._create_share(status='ACTIVE')
snapshot = self._create_snapshot(share_id=share['id'])
snapshot_id = snapshot['id']
self.share_manager.delete_snapshot(self.context, snapshot_id)
@ -315,10 +322,10 @@ class ShareTestCase(test.TestCase):
def test_create_delete_share_error(self):
"""Test share can be created and deleted with error."""
def _fake_create_share(self, context, share):
def _fake_create_share(self, *args, **kwargs):
raise exception.NotFound()
def _fake_delete_share(self, context, share):
def _fake_delete_share(self, *args, **kwargs):
raise exception.NotFound()
self.stubs.Set(FakeShareDriver, "create_share", _fake_create_share)
@ -361,10 +368,10 @@ class ShareTestCase(test.TestCase):
def test_allow_deny_access_error(self):
"""Test access rules to share can be created and deleted with error."""
def _fake_allow_access(self, context, share, access):
def _fake_allow_access(self, *args, **kwargs):
raise exception.NotFound()
def _fake_deny_access(self, context, share, access):
def _fake_deny_access(self, *args, **kwargs):
raise exception.NotFound()
self.stubs.Set(FakeShareDriver, "allow_access", _fake_allow_access)