Add support of default share type
Implement possibility to set up default share type for share creation. If default share type is set up and in case no share type is specified, a default share type will be provided with the share creation request. It is useful when we want some specific back end to be used in common cases instead of weighed back ends. How to use it: 1) add to manila.conf file following option default_share_type = some_st_name to [DEFAULT] group of config. 2) restart manila API service if was started 3) create share type with name "some_st_name" 4) add some extra specs to share type, for example: share_backend_name = cheap_backend Implements blueprint default-volume-type Change-Id: Ief32825360cbb3e7df9149e8980c11c5018f52f7
This commit is contained in:
parent
00184fbf54
commit
b369f2ba8a
@ -32,6 +32,9 @@ if is_service_enabled manila; then
|
||||
|
||||
echo_summary "Starting Manila"
|
||||
start_manila
|
||||
|
||||
echo_summary "Creating Manila default share type"
|
||||
create_default_share_type
|
||||
fi
|
||||
|
||||
if [[ "$1" == "unstack" ]]; then
|
||||
|
@ -66,6 +66,8 @@ MANILA_CONF_DIR=${MANILA_CONF_DIR:-/etc/manila}
|
||||
MANILA_CONF=$MANILA_CONF_DIR/manila.conf
|
||||
MANILA_API_PASTE_INI=$MANILA_CONF_DIR/api-paste.ini
|
||||
|
||||
MANILA_DEFAULT_SHARE_TYPE=${MANILA_DEFAULT_SHARE_TYPE:-default}
|
||||
|
||||
# Public facing bits
|
||||
MANILA_SERVICE_HOST=${MANILA_SERVICE_HOST:-$SERVICE_HOST}
|
||||
MANILA_SERVICE_PORT=${MANILA_SERVICE_PORT:-8786}
|
||||
@ -246,6 +248,7 @@ function configure_manila {
|
||||
iniset $MANILA_CONF DEFAULT rootwrap_config $MANILA_CONF_DIR/rootwrap.conf
|
||||
iniset $MANILA_CONF DEFAULT osapi_share_extension manila.api.contrib.standard_extensions
|
||||
iniset $MANILA_CONF DEFAULT state_path $MANILA_STATE_PATH
|
||||
iniset $MANILA_CONF DEFAULT default_share_type $MANILA_DEFAULT_SHARE_TYPE
|
||||
|
||||
iniset $MANILA_CONF DEFAULT nova_admin_password $SERVICE_PASSWORD
|
||||
iniset $MANILA_CONF DEFAULT cinder_admin_password $SERVICE_PASSWORD
|
||||
@ -414,6 +417,17 @@ function create_manila_accounts {
|
||||
fi
|
||||
}
|
||||
|
||||
# Create default share type
|
||||
function create_default_share_type {
|
||||
echo "Waiting for Manila API to start..."
|
||||
if ! wait_for_service 60 $MANILA_SERVICE_PROTOCOL://$MANILA_SERVICE_HOST:$MANILA_SERVICE_PORT; then
|
||||
die $LINENO "Manila did not start"
|
||||
fi
|
||||
|
||||
manila type-create $MANILA_DEFAULT_SHARE_TYPE
|
||||
}
|
||||
|
||||
|
||||
# init_manila - Initialize database and volume group
|
||||
function init_manila {
|
||||
|
||||
|
@ -275,6 +275,10 @@ class ShareController(wsgi.Controller):
|
||||
except exception.ShareTypeNotFound:
|
||||
msg = _("Share type not found.")
|
||||
raise exc.HTTPNotFound(explanation=msg)
|
||||
elif not snapshot:
|
||||
def_share_type = share_types.get_default_share_type()
|
||||
if def_share_type:
|
||||
kwargs['share_type'] = def_share_type
|
||||
|
||||
new_share = self.share_api.create(context,
|
||||
share_proto,
|
||||
|
@ -134,6 +134,9 @@ global_opts = [
|
||||
cfg.StrOpt('storage_availability_zone',
|
||||
default='nova',
|
||||
help='Availability zone of this node.'),
|
||||
cfg.StrOpt('default_share_type',
|
||||
default=None,
|
||||
help='Default share type to use.'),
|
||||
cfg.ListOpt('memcached_servers',
|
||||
default=None,
|
||||
help='Memcached servers or None for in process cache.'),
|
||||
|
@ -17,6 +17,7 @@ import copy
|
||||
import datetime
|
||||
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
import webob
|
||||
|
||||
from manila.api import common
|
||||
@ -24,9 +25,13 @@ from manila.api.v1 import shares
|
||||
from manila import context
|
||||
from manila import exception
|
||||
from manila.share import api as share_api
|
||||
from manila.share import share_types
|
||||
from manila import test
|
||||
from manila.tests.api.contrib import stubs
|
||||
from manila.tests.api import fakes
|
||||
from manila import utils
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
class ShareApiTest(test.TestCase):
|
||||
@ -43,12 +48,27 @@ class ShareApiTest(test.TestCase):
|
||||
self.mock_object(share_api.API, 'get_snapshot',
|
||||
stubs.stub_snapshot_get)
|
||||
self.maxDiff = None
|
||||
self.shr_example = {
|
||||
self.share = {
|
||||
"size": 100,
|
||||
"name": "Share Test Name",
|
||||
"display_name": "Updated Desc",
|
||||
"display_description": "Updated Display Desc",
|
||||
"display_name": "Share Test Name",
|
||||
"display_description": "Share Test Desc",
|
||||
"share_proto": "fakeproto",
|
||||
"availability_zone": "zone1:host1",
|
||||
}
|
||||
self.create_mock = mock.Mock(
|
||||
return_value=stubs.stub_share(
|
||||
'1',
|
||||
display_name=self.share['display_name'],
|
||||
display_description=self.share['display_description'],
|
||||
size=100,
|
||||
share_proto=self.share['share_proto'].upper(),
|
||||
availability_zone=self.share['availability_zone'])
|
||||
)
|
||||
self.vt = {
|
||||
'id': 'fake_volume_type_id',
|
||||
'name': 'fake_volume_type_name',
|
||||
}
|
||||
CONF.set_default("default_share_type", None)
|
||||
|
||||
def _get_expected_share_detailed_response(self, values=None, admin=False):
|
||||
share = {
|
||||
@ -80,6 +100,10 @@ class ShareApiTest(test.TestCase):
|
||||
],
|
||||
}
|
||||
if values:
|
||||
if 'display_name' in values:
|
||||
values['name'] = values.pop('display_name')
|
||||
if 'display_description' in values:
|
||||
values['description'] = values.pop('display_description')
|
||||
share.update(values)
|
||||
if share.get('share_proto'):
|
||||
share['share_proto'] = share['share_proto'].upper()
|
||||
@ -88,28 +112,42 @@ class ShareApiTest(test.TestCase):
|
||||
return {'share': share}
|
||||
|
||||
def test_share_create(self):
|
||||
shr = {
|
||||
"size": 100,
|
||||
"name": "Share Test Name",
|
||||
"description": "Share Test Desc",
|
||||
"share_proto": "fakeproto",
|
||||
"availability_zone": "zone1:host1"
|
||||
}
|
||||
create_mock = mock.Mock(return_value=stubs.stub_share('1',
|
||||
display_name=shr['name'],
|
||||
display_description=shr['description'],
|
||||
size=100,
|
||||
share_proto=shr['share_proto'].upper(),
|
||||
availability_zone=shr['availability_zone']))
|
||||
self.mock_object(share_api.API, 'create', create_mock)
|
||||
self.mock_object(share_api.API, 'create', self.create_mock)
|
||||
|
||||
body = {"share": copy.deepcopy(shr)}
|
||||
body = {"share": copy.deepcopy(self.share)}
|
||||
req = fakes.HTTPRequest.blank('/shares')
|
||||
res_dict = self.controller.create(req, body)
|
||||
|
||||
expected = self._get_expected_share_detailed_response(shr)
|
||||
expected = self._get_expected_share_detailed_response(self.share)
|
||||
self.assertEqual(expected, res_dict)
|
||||
|
||||
def test_share_create_with_valid_default_share_type(self):
|
||||
self.mock_object(share_types, 'get_share_type_by_name',
|
||||
mock.Mock(return_value=self.vt))
|
||||
CONF.set_default("default_share_type", self.vt['name'])
|
||||
self.mock_object(share_api.API, 'create', self.create_mock)
|
||||
|
||||
body = {"share": copy.deepcopy(self.share)}
|
||||
req = fakes.HTTPRequest.blank('/shares')
|
||||
res_dict = self.controller.create(req, body)
|
||||
|
||||
expected = self._get_expected_share_detailed_response(self.share)
|
||||
share_types.get_share_type_by_name.assert_called_once_with(
|
||||
utils.IsAMatcher(context.RequestContext), self.vt['name'])
|
||||
self.assertEqual(expected, res_dict)
|
||||
|
||||
def test_share_create_with_invalid_default_share_type(self):
|
||||
self.mock_object(
|
||||
share_types, 'get_default_share_type',
|
||||
mock.Mock(side_effect=exception.ShareTypeNotFoundByName(
|
||||
self.vt['name'])),
|
||||
)
|
||||
CONF.set_default("default_share_type", self.vt['name'])
|
||||
req = fakes.HTTPRequest.blank('/shares')
|
||||
self.assertRaises(exception.ShareTypeNotFoundByName,
|
||||
self.controller.create, req, {'share': self.share})
|
||||
share_types.get_default_share_type.assert_called_once_with()
|
||||
|
||||
def test_share_create_with_share_net(self):
|
||||
shr = {
|
||||
"size": 100,
|
||||
@ -299,31 +337,20 @@ class ShareApiTest(test.TestCase):
|
||||
self.assertEqual(resp.status_int, 202)
|
||||
|
||||
def test_share_updates_description(self):
|
||||
shr = self.shr_example
|
||||
body = {"share": shr}
|
||||
|
||||
req = fakes.HTTPRequest.blank('/share/1')
|
||||
res_dict = self.controller.update(req, 1, body)
|
||||
self.assertEqual(res_dict['share']["name"], shr["display_name"])
|
||||
res_dict = self.controller.update(req, 1, {"share": self.share})
|
||||
self.assertEqual(res_dict["share"]["name"], self.share["display_name"])
|
||||
|
||||
def test_share_updates_display_descr(self):
|
||||
shr = self.shr_example
|
||||
body = {"share": shr}
|
||||
|
||||
req = fakes.HTTPRequest.blank('/share/1')
|
||||
res_dict = self.controller.update(req, 1, body)
|
||||
|
||||
res_dict = self.controller.update(req, 1, {"share": self.share})
|
||||
self.assertEqual(res_dict['share']["description"],
|
||||
shr["display_description"])
|
||||
self.share["display_description"])
|
||||
|
||||
def test_share_not_updates_size(self):
|
||||
shr = self.shr_example
|
||||
body = {"share": shr}
|
||||
|
||||
req = fakes.HTTPRequest.blank('/share/1')
|
||||
res_dict = self.controller.update(req, 1, body)
|
||||
|
||||
self.assertNotEqual(res_dict['share']["size"], shr["size"])
|
||||
res_dict = self.controller.update(req, 1, {"share": self.share})
|
||||
self.assertNotEqual(res_dict['share']["size"], self.share["size"])
|
||||
|
||||
def test_share_delete_no_share(self):
|
||||
self.mock_object(share_api.API, 'get',
|
||||
@ -451,7 +478,6 @@ class ShareApiTest(test.TestCase):
|
||||
'status': 'available',
|
||||
'snapshot_id': 'fake_snapshot_id',
|
||||
'share_type_id': 'fake_share_type_id',
|
||||
'snapshot_id': 'fake_snapshot_id',
|
||||
'host': 'fake_host',
|
||||
'share_network_id': 'fake_share_network_id',
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user