Add possibility to enable/disable some share protocols
It is useful in case we use share backends that do not implement some share protocol or want to disable something for some other reason. For the moment, there is no share driver that supports all share protocols in Manila. Change-Id: I80a6a7927aa897931a84d310b657d0af06f02823 Closes-Bug: #1403161
This commit is contained in:
parent
fd5e0f8eb9
commit
4d19edb989
@ -50,6 +50,7 @@ CONF = cfg.CONF
|
||||
if __name__ == '__main__':
|
||||
CONF(sys.argv[1:], project='manila',
|
||||
version=version.version_string())
|
||||
config.verify_share_protocols()
|
||||
logging.setup("manila")
|
||||
utils.monkey_patch()
|
||||
server = service.WSGIService('osapi_share')
|
||||
|
@ -81,6 +81,7 @@ fi
|
||||
|
||||
# Common opts
|
||||
SHARE_NAME_PREFIX=${SHARE_NAME_PREFIX:-share-}
|
||||
MANILA_ENABLED_SHARE_PROTOCOLS=${ENABLED_SHARE_PROTOCOLS:-"NFS,CIFS"}
|
||||
MANILA_SCHEDULER_DRIVER=${MANILA_SCHEDULER_DRIVER:-manila.scheduler.filter_scheduler.FilterScheduler}
|
||||
MANILA_SERVICE_SECGROUP="manila-service"
|
||||
|
||||
@ -250,6 +251,8 @@ function configure_manila {
|
||||
iniset $MANILA_CONF DEFAULT cinder_admin_password $SERVICE_PASSWORD
|
||||
iniset $MANILA_CONF DEFAULT neutron_admin_password $SERVICE_PASSWORD
|
||||
|
||||
iniset $MANILA_CONF DEFAULT enabled_share_protocols $MANILA_ENABLED_SHARE_PROTOCOLS
|
||||
|
||||
iniset $MANILA_CONF oslo_concurrency lock_path $MANILA_LOCK_PATH
|
||||
|
||||
# Note: set up config group does not mean that this backend will be enabled.
|
||||
|
@ -27,7 +27,10 @@ stepping stone.
|
||||
import socket
|
||||
|
||||
from oslo_config import cfg
|
||||
import six
|
||||
|
||||
from manila.common import constants
|
||||
from manila import exception
|
||||
from manila.i18n import _
|
||||
|
||||
CONF = cfg.CONF
|
||||
@ -172,8 +175,36 @@ global_opts = [
|
||||
help='A list of share backend names to use. These backend '
|
||||
'names should be backed by a unique [CONFIG] group '
|
||||
'with its options.'),
|
||||
cfg.ListOpt('enabled_share_protocols',
|
||||
default=['NFS', 'CIFS'],
|
||||
help="Specify list of protocols to be allowed for share "
|
||||
"creation. Available values are '%s'" % six.text_type(
|
||||
constants.SUPPORTED_SHARE_PROTOCOLS)),
|
||||
cfg.BoolOpt('no_snapshot_gb_quota',
|
||||
default=False,
|
||||
help='Whether snapshots count against Gigabyte quota.'), ]
|
||||
|
||||
CONF.register_opts(global_opts)
|
||||
|
||||
|
||||
def verify_share_protocols():
|
||||
"""Perfom verification of 'enabled_share_protocols'."""
|
||||
msg = None
|
||||
supported_protocols = constants.SUPPORTED_SHARE_PROTOCOLS
|
||||
data = dict(supported=six.text_type(supported_protocols))
|
||||
if CONF.enabled_share_protocols:
|
||||
for share_proto in CONF.enabled_share_protocols:
|
||||
if share_proto not in supported_protocols:
|
||||
data.update({'share_proto': share_proto})
|
||||
msg = _("Unsupported share protocol '%(share_proto)s' "
|
||||
"is set as enabled. Available values are "
|
||||
"%(supported)s. ")
|
||||
break
|
||||
else:
|
||||
msg = _("No share protocols were specified as enabled. "
|
||||
"Available values are %(supported)s. ")
|
||||
if msg:
|
||||
msg += _("Please specify one or more protocols using "
|
||||
"configuration option 'enabled_share_protocols.")
|
||||
msg = msg % data
|
||||
raise exception.ManilaException(message=msg)
|
||||
|
@ -23,6 +23,9 @@ STATUS_INACTIVE = 'INACTIVE'
|
||||
STATUS_ACTIVATING = 'ACTIVATING'
|
||||
STATUS_DEACTIVATING = 'DEACTIVATING'
|
||||
|
||||
SUPPORTED_SHARE_PROTOCOLS = (
|
||||
'NFS', 'CIFS', 'GLUSTERFS', 'HDFS')
|
||||
|
||||
SECURITY_SERVICES_ALLOWED_TYPES = ['active_directory', 'ldap', 'kerberos']
|
||||
|
||||
NFS_EXPORTS_FILE = '/etc/exports'
|
||||
|
@ -106,10 +106,15 @@ class API(base.Base):
|
||||
"You should omit the argument.")
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
# TODO(rushiagr): Find a suitable place to keep all the allowed
|
||||
# share types so that it becomes easier to add one
|
||||
if share_proto.lower() not in ['nfs', 'cifs', 'glusterfs', 'hdfs']:
|
||||
msg = (_("Invalid share type provided: %s") % share_proto)
|
||||
supported_share_protocols = (
|
||||
proto.upper() for proto in CONF.enabled_share_protocols)
|
||||
if not (share_proto and
|
||||
share_proto.upper() in supported_share_protocols):
|
||||
msg = (_("Invalid share protocol provided: %(provided)s. "
|
||||
"It is either disabled or unsupported. Available "
|
||||
"protocols: %(supported)s") % dict(
|
||||
provided=share_proto,
|
||||
supported=CONF.enabled_share_protocols))
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
try:
|
||||
|
0
manila/tests/common/__init__.py
Normal file
0
manila/tests/common/__init__.py
Normal file
42
manila/tests/common/test_config.py
Normal file
42
manila/tests/common/test_config.py
Normal file
@ -0,0 +1,42 @@
|
||||
# Copyright 2015 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.
|
||||
|
||||
import ddt
|
||||
|
||||
from manila.common import config
|
||||
from manila.common import constants
|
||||
from manila import exception
|
||||
from manila import test
|
||||
from manila.tests import utils as test_utils
|
||||
|
||||
VALID_CASES = [proto for proto in constants.SUPPORTED_SHARE_PROTOCOLS]
|
||||
VALID_CASES.append(','.join(case for case in VALID_CASES))
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class VerifyConfigShareProtocolsTestCase(test.TestCase):
|
||||
|
||||
@ddt.data(*VALID_CASES)
|
||||
def test_verify_share_protocols_valid_cases(self, proto):
|
||||
data = dict(DEFAULT=dict(enabled_share_protocols=proto))
|
||||
with test_utils.create_temp_config_with_opts(data):
|
||||
config.verify_share_protocols()
|
||||
|
||||
@ddt.data(None, '', 'fake', [], ['fake'], [VALID_CASES[0] + 'fake'])
|
||||
def test_verify_share_protocols_invalid_cases(self, proto):
|
||||
data = dict(DEFAULT=dict(enabled_share_protocols=proto))
|
||||
with test_utils.create_temp_config_with_opts(data):
|
||||
self.assertRaises(
|
||||
exception.ManilaException, config.verify_share_protocols)
|
@ -26,6 +26,7 @@ from oslo.utils import timeutils as timeutils_old # noqa
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from manila.common import constants
|
||||
from manila import context
|
||||
from manila import db as db_driver
|
||||
from manila import exception
|
||||
@ -34,6 +35,7 @@ from manila import share
|
||||
from manila.share import api as share_api
|
||||
from manila import test
|
||||
from manila.tests.db import fakes as db_fakes
|
||||
from manila.tests import utils as test_utils
|
||||
from manila import utils
|
||||
|
||||
CONF = cfg.CONF
|
||||
@ -419,9 +421,9 @@ class ShareAPITestCase(test.TestCase):
|
||||
def test_get_all_filter_by_invalid_extra_specs(self):
|
||||
self._get_all_filter_metadata_or_extra_specs_invalid(key='extra_specs')
|
||||
|
||||
def test_create(self):
|
||||
date = datetime.datetime(1, 1, 1, 1, 1, 1)
|
||||
timeutils.utcnow.return_value = date
|
||||
@ddt.data(*constants.SUPPORTED_SHARE_PROTOCOLS)
|
||||
def test_create_share_valid_protocol(self, proto):
|
||||
timeutils.utcnow.return_value = datetime.datetime(1, 1, 1, 1, 1, 1)
|
||||
share = fake_share('fakeid',
|
||||
user_id=self.context.user_id,
|
||||
project_id=self.context.project_id,
|
||||
@ -430,31 +432,39 @@ class ShareAPITestCase(test.TestCase):
|
||||
for name in ('id', 'export_location', 'host', 'launched_at',
|
||||
'terminated_at'):
|
||||
options.pop(name, None)
|
||||
with mock.patch.object(db_driver, 'share_create',
|
||||
mock.Mock(return_value=share)):
|
||||
self.api.create(self.context, 'nfs', '1', 'fakename', 'fakedesc',
|
||||
availability_zone='fakeaz')
|
||||
db_driver.share_create.assert_called_once_with(
|
||||
self.context, options)
|
||||
options.update(share_proto=proto)
|
||||
self.mock_object(
|
||||
db_driver, 'share_create', mock.Mock(return_value=share))
|
||||
|
||||
def test_create_glusterfs(self):
|
||||
date = datetime.datetime(1, 1, 1, 1, 1, 1)
|
||||
timeutils.utcnow.return_value = date
|
||||
share = fake_share('fakeid',
|
||||
user_id=self.context.user_id,
|
||||
project_id=self.context.project_id,
|
||||
status='creating')
|
||||
options = share.copy()
|
||||
all_protos = ','.join(
|
||||
proto for proto in constants.SUPPORTED_SHARE_PROTOCOLS)
|
||||
data = dict(DEFAULT=dict(enabled_share_protocols=all_protos))
|
||||
with test_utils.create_temp_config_with_opts(data):
|
||||
self.api.create(
|
||||
self.context, proto, '1', 'fakename', 'fakedesc',
|
||||
availability_zone='fakeaz')
|
||||
|
||||
db_driver.share_create.assert_called_once_with(
|
||||
self.context, options)
|
||||
|
||||
@ddt.data(
|
||||
None, '', 'fake', 'nfsfake', 'cifsfake', 'glusterfsfake', 'hdfsfake')
|
||||
def test_create_share_invalid_protocol(self, proto):
|
||||
options = fake_share(
|
||||
'fakeid', user_id=self.context.user_id,
|
||||
project_id=self.context.project_id, status='creating')
|
||||
for name in ('id', 'export_location', 'host', 'launched_at',
|
||||
'terminated_at'):
|
||||
options.pop(name, None)
|
||||
with mock.patch.object(db_driver, 'share_create',
|
||||
mock.Mock(return_value=share)):
|
||||
options.update(share_proto='glusterfs')
|
||||
self.api.create(self.context, 'glusterfs', '1', 'fakename',
|
||||
'fakedesc', availability_zone='fakeaz')
|
||||
db_driver.share_create.assert_called_once_with(
|
||||
self.context, options)
|
||||
options.update(share_proto=proto)
|
||||
all_protos = ','.join(
|
||||
proto for proto in constants.SUPPORTED_SHARE_PROTOCOLS)
|
||||
data = dict(DEFAULT=dict(enabled_share_protocols=all_protos))
|
||||
with test_utils.create_temp_config_with_opts(data):
|
||||
self.assertRaises(
|
||||
exception.InvalidInput,
|
||||
self.api.create,
|
||||
self.context, proto, '1', 'fakename', 'fakedesc')
|
||||
|
||||
@mock.patch.object(quota.QUOTAS, 'reserve',
|
||||
mock.Mock(return_value='reservation'))
|
||||
|
Loading…
Reference in New Issue
Block a user