168 lines
5.5 KiB
Python
168 lines
5.5 KiB
Python
# Copyright 2012 NetApp
|
|
# 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.
|
|
"""
|
|
Drivers for shares.
|
|
|
|
"""
|
|
|
|
import time
|
|
|
|
from manila import exception
|
|
from manila.openstack.common import log as logging
|
|
from manila import utils
|
|
|
|
from oslo.config import cfg
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
share_opts = [
|
|
# NOTE(rushiagr): Reasonable to define this option at only one place.
|
|
cfg.IntOpt('num_shell_tries',
|
|
default=3,
|
|
help='Number of times to attempt to run flakey shell '
|
|
'commands.'),
|
|
cfg.IntOpt('reserved_share_percentage',
|
|
default=0,
|
|
help='The percentage of backend capacity reserved.'),
|
|
cfg.StrOpt('share_backend_name',
|
|
default=None,
|
|
help='The backend name for a given driver implementation.'),
|
|
]
|
|
|
|
CONF = cfg.CONF
|
|
CONF.register_opts(share_opts)
|
|
|
|
|
|
class ExecuteMixin(object):
|
|
"""Provides an executable functionality to a driver class."""
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
self.db = None
|
|
self.configuration = kwargs.get('configuration', None)
|
|
if self.configuration:
|
|
self.configuration.append_config_values(share_opts)
|
|
self.set_execute(kwargs.pop('execute', utils.execute))
|
|
|
|
def set_execute(self, execute):
|
|
self._execute = execute
|
|
|
|
def _try_execute(self, *command, **kwargs):
|
|
# NOTE(vish): Volume commands can partially fail due to timing, but
|
|
# running them a second time on failure will usually
|
|
# recover nicely.
|
|
tries = 0
|
|
while True:
|
|
try:
|
|
self._execute(*command, **kwargs)
|
|
return True
|
|
except exception.ProcessExecutionError:
|
|
tries += 1
|
|
if tries >= self.configuration.num_shell_tries:
|
|
raise
|
|
LOG.exception(_("Recovering from a failed execute. "
|
|
"Try number %s"), tries)
|
|
time.sleep(tries ** 2)
|
|
|
|
|
|
class ShareDriver(object):
|
|
"""Class defines interface of NAS driver."""
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(ShareDriver, self).__init__()
|
|
self.configuration = kwargs.get('configuration', None)
|
|
if self.configuration:
|
|
self.configuration.append_config_values(share_opts)
|
|
|
|
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,
|
|
share_server=None):
|
|
"""Is called to create share from snapshot."""
|
|
raise NotImplementedError()
|
|
|
|
def create_snapshot(self, context, snapshot, share_server=None):
|
|
"""Is called to create snapshot."""
|
|
raise NotImplementedError()
|
|
|
|
def delete_share(self, context, share, share_server=None):
|
|
"""Is called to remove share."""
|
|
raise NotImplementedError()
|
|
|
|
def delete_snapshot(self, context, snapshot, share_server=None):
|
|
"""Is called to remove snapshot."""
|
|
raise NotImplementedError()
|
|
|
|
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, share_server=None):
|
|
"""Allow access to the share."""
|
|
raise NotImplementedError()
|
|
|
|
def deny_access(self, context, share, access, share_server=None):
|
|
"""Deny access to the share."""
|
|
raise NotImplementedError()
|
|
|
|
def check_for_setup_error(self):
|
|
"""Check for setup error."""
|
|
pass
|
|
|
|
def do_setup(self, context):
|
|
"""Any initialization the share driver does while starting."""
|
|
pass
|
|
|
|
def get_share_stats(self, refresh=False):
|
|
"""Get share status.
|
|
|
|
If 'refresh' is True, run update the stats first.
|
|
"""
|
|
if refresh:
|
|
self._update_share_status()
|
|
|
|
return self._stats
|
|
|
|
def get_network_allocations_number(self):
|
|
"""Returns number of network allocations for creating VIFs."""
|
|
pass
|
|
|
|
def setup_server(self, network_info, metadata=None):
|
|
"""Set up and configures share server with given network parameters."""
|
|
pass
|
|
|
|
def teardown_server(self, server_details, security_services=None):
|
|
"""Teardown share server."""
|
|
pass
|
|
|
|
def _update_share_status(self):
|
|
"""Retrieve status info from share group."""
|
|
|
|
LOG.debug("Updating share status")
|
|
data = {}
|
|
backend_name = self.configuration.safe_get('share_backend_name')
|
|
data["share_backend_name"] = backend_name or 'Generic_NFS'
|
|
data["vendor_name"] = 'Open Source'
|
|
data["driver_version"] = '1.0'
|
|
data["storage_protocol"] = None
|
|
|
|
data['total_capacity_gb'] = 'infinite'
|
|
data['free_capacity_gb'] = 'infinite'
|
|
data['reserved_percentage'] = 0
|
|
data['QoS_support'] = False
|
|
self._stats = data
|