Merge "Add possibility to enable/disable some share protocols"

This commit is contained in:
Jenkins 2015-02-14 21:48:57 +00:00 committed by Gerrit Code Review
commit d361c666b5
8 changed files with 123 additions and 28 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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