Set share-type on share created from snapshot
This commit ensures that when one creates a share from a snapshot the new share has the same share-type as the share on which the snapshot is based. Closes-bug: 1420369 Change-Id: Icad04edd3eab6d40e56352a9a7d298b6efd80e93
This commit is contained in:
parent
e7259cb867
commit
ee14370097
|
@ -1,5 +1,5 @@
|
||||||
# Copyright 2014 Mirantis Inc.
|
# Copyright 2014 Mirantis Inc. All Rights Reserved.
|
||||||
# All Rights Reserved.
|
# Copyright (c) 2015 Yogesh Kshirsagar. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
@ -178,7 +178,7 @@ class SharesActionsAdminTest(base.BaseSharesAdminTest):
|
||||||
self.assertTrue(len(shares) > 0)
|
self.assertTrue(len(shares) > 0)
|
||||||
shares_ids = [s["id"] for s in shares]
|
shares_ids = [s["id"] for s in shares]
|
||||||
self.assertTrue(self.share["id"] in shares_ids)
|
self.assertTrue(self.share["id"] in shares_ids)
|
||||||
self.assertFalse(self.share2["id"] in shares_ids)
|
self.assertTrue(self.share2["id"] in shares_ids)
|
||||||
for share in shares:
|
for share in shares:
|
||||||
__, st_list = self.shares_client.list_share_types()
|
__, st_list = self.shares_client.list_share_types()
|
||||||
# find its name or id, get id
|
# find its name or id, get id
|
||||||
|
@ -224,7 +224,9 @@ class SharesActionsAdminTest(base.BaseSharesAdminTest):
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
filters['share_type_id'], st_id)
|
filters['share_type_id'], st_id)
|
||||||
self.assertFalse(self.share2['id'] in [s['id'] for s in shares])
|
share_ids = [share['id'] for share in shares]
|
||||||
|
self.assertTrue(self.share['id'] in share_ids)
|
||||||
|
self.assertTrue(self.share2['id'] in share_ids)
|
||||||
|
|
||||||
@test.attr(type=["gate", ])
|
@test.attr(type=["gate", ])
|
||||||
def test_list_shares_with_detail_filter_by_host(self):
|
def test_list_shares_with_detail_filter_by_host(self):
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# Copyright 2010 United States Government as represented by the
|
# Copyright 2010 United States Government as represented by the
|
||||||
# Administrator of the National Aeronautics and Space Administration.
|
# Administrator of the National Aeronautics and Space Administration.
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
|
# Copyright (c) 2015 Tom Barron. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
@ -36,6 +37,7 @@ from manila import policy
|
||||||
from manila import quota
|
from manila import quota
|
||||||
from manila.scheduler import rpcapi as scheduler_rpcapi
|
from manila.scheduler import rpcapi as scheduler_rpcapi
|
||||||
from manila.share import rpcapi as share_rpcapi
|
from manila.share import rpcapi as share_rpcapi
|
||||||
|
from manila.share import share_types
|
||||||
|
|
||||||
share_api_opts = [
|
share_api_opts = [
|
||||||
cfg.BoolOpt('use_scheduler_creating_share_from_snapshot',
|
cfg.BoolOpt('use_scheduler_creating_share_from_snapshot',
|
||||||
|
@ -99,13 +101,25 @@ class API(base.Base):
|
||||||
"than snapshot size") % size)
|
"than snapshot size") % size)
|
||||||
raise exception.InvalidInput(reason=msg)
|
raise exception.InvalidInput(reason=msg)
|
||||||
|
|
||||||
if snapshot and share_type:
|
if snapshot is None:
|
||||||
|
share_type_id = share_type['id'] if share_type else None
|
||||||
|
else:
|
||||||
source_share = self.db.share_get(context, snapshot['share_id'])
|
source_share = self.db.share_get(context, snapshot['share_id'])
|
||||||
if share_type['id'] != source_share['share_type_id']:
|
if share_type is None:
|
||||||
msg = _("Invalid share_type provided (requested type "
|
share_type_id = source_share['share_type_id']
|
||||||
"must match source snapshot, or be omitted). "
|
if share_type_id is not None:
|
||||||
"You should omit the argument.")
|
share_type = share_types.get_share_type(context,
|
||||||
raise exception.InvalidInput(reason=msg)
|
share_type_id)
|
||||||
|
else:
|
||||||
|
share_type_id = share_type['id']
|
||||||
|
if share_type_id != source_share['share_type_id']:
|
||||||
|
msg = _("Invalid share type specified: the requested "
|
||||||
|
"share type must match the type of the source "
|
||||||
|
"share. If a share type is not specified when "
|
||||||
|
"requesting a new share from a snapshot, the "
|
||||||
|
"share type of the source share will be applied "
|
||||||
|
"to the new share.")
|
||||||
|
raise exception.InvalidInput(reason=msg)
|
||||||
|
|
||||||
supported_share_protocols = (
|
supported_share_protocols = (
|
||||||
proto.upper() for proto in CONF.enabled_share_protocols)
|
proto.upper() for proto in CONF.enabled_share_protocols)
|
||||||
|
@ -165,7 +179,7 @@ class API(base.Base):
|
||||||
'display_name': name,
|
'display_name': name,
|
||||||
'display_description': description,
|
'display_description': description,
|
||||||
'share_proto': share_proto,
|
'share_proto': share_proto,
|
||||||
'share_type_id': share_type['id'] if share_type else None,
|
'share_type_id': share_type_id,
|
||||||
'is_public': is_public,
|
'is_public': is_public,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright 2012 NetApp
|
# Copyright 2012 NetApp. All rights reserved.
|
||||||
# All Rights Reserved.
|
# Copyright (c) 2015 Tom Barron. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
@ -34,6 +34,7 @@ from manila import exception
|
||||||
from manila import quota
|
from manila import quota
|
||||||
from manila import share
|
from manila import share
|
||||||
from manila.share import api as share_api
|
from manila.share import api as share_api
|
||||||
|
from manila.share import share_types
|
||||||
from manila import test
|
from manila import test
|
||||||
from manila.tests.db import fakes as db_fakes
|
from manila.tests.db import fakes as db_fakes
|
||||||
from manila.tests import utils as test_utils
|
from manila.tests import utils as test_utils
|
||||||
|
@ -749,8 +750,12 @@ class ShareAPITestCase(test.TestCase):
|
||||||
CONF.set_default("use_scheduler_creating_share_from_snapshot", False)
|
CONF.set_default("use_scheduler_creating_share_from_snapshot", False)
|
||||||
date = datetime.datetime(1, 1, 1, 1, 1, 1)
|
date = datetime.datetime(1, 1, 1, 1, 1, 1)
|
||||||
timeutils.utcnow.return_value = date
|
timeutils.utcnow.return_value = date
|
||||||
|
original_share = fake_share('fake_original_id',
|
||||||
|
user_id=self.context.user_id,
|
||||||
|
project_id=self.context.project_id,
|
||||||
|
status='available')
|
||||||
snapshot = fake_snapshot('fakesnapshotid',
|
snapshot = fake_snapshot('fakesnapshotid',
|
||||||
share_id='fakeshare_id',
|
share_id=original_share['id'],
|
||||||
status='available')
|
status='available')
|
||||||
share = fake_share('fakeid',
|
share = fake_share('fakeid',
|
||||||
user_id=self.context.user_id,
|
user_id=self.context.user_id,
|
||||||
|
@ -768,6 +773,9 @@ class ShareAPITestCase(test.TestCase):
|
||||||
'share_type': None,
|
'share_type': None,
|
||||||
'snapshot_id': share['snapshot_id'],
|
'snapshot_id': share['snapshot_id'],
|
||||||
}
|
}
|
||||||
|
self.mock_object(db_driver, 'share_get',
|
||||||
|
mock.Mock(return_value=original_share))
|
||||||
|
self.mock_object(share_types, 'get_share_type')
|
||||||
self.mock_object(db_driver, 'share_create',
|
self.mock_object(db_driver, 'share_create',
|
||||||
mock.Mock(return_value=share))
|
mock.Mock(return_value=share))
|
||||||
self.mock_object(db_driver, 'share_update',
|
self.mock_object(db_driver, 'share_update',
|
||||||
|
@ -776,6 +784,9 @@ class ShareAPITestCase(test.TestCase):
|
||||||
self.api.create(self.context, 'nfs', '1', 'fakename', 'fakedesc',
|
self.api.create(self.context, 'nfs', '1', 'fakename', 'fakedesc',
|
||||||
snapshot=snapshot, availability_zone='fakeaz')
|
snapshot=snapshot, availability_zone='fakeaz')
|
||||||
|
|
||||||
|
db_driver.share_get.assert_called_once_with(
|
||||||
|
self.context, snapshot['share_id'])
|
||||||
|
self.assertEqual(0, share_types.get_share_type.call_count)
|
||||||
self.share_rpcapi.create_share.assert_called_once_with(
|
self.share_rpcapi.create_share.assert_called_once_with(
|
||||||
self.context, share, snapshot['share']['host'],
|
self.context, share, snapshot['share']['host'],
|
||||||
request_spec=request_spec, filter_properties={},
|
request_spec=request_spec, filter_properties={},
|
||||||
|
@ -796,8 +807,12 @@ class ShareAPITestCase(test.TestCase):
|
||||||
CONF.set_default("use_scheduler_creating_share_from_snapshot", True)
|
CONF.set_default("use_scheduler_creating_share_from_snapshot", True)
|
||||||
date = datetime.datetime(1, 1, 1, 1, 1, 1)
|
date = datetime.datetime(1, 1, 1, 1, 1, 1)
|
||||||
timeutils.utcnow.return_value = date
|
timeutils.utcnow.return_value = date
|
||||||
|
original_share = fake_share('fake_original_id',
|
||||||
|
user_id=self.context.user_id,
|
||||||
|
project_id=self.context.project_id,
|
||||||
|
status='available')
|
||||||
snapshot = fake_snapshot('fakesnapshotid',
|
snapshot = fake_snapshot('fakesnapshotid',
|
||||||
share_id='fakeshare_id',
|
share_id=original_share['id'],
|
||||||
status='available')
|
status='available')
|
||||||
share = fake_share('fakeid',
|
share = fake_share('fakeid',
|
||||||
user_id=self.context.user_id,
|
user_id=self.context.user_id,
|
||||||
|
@ -815,6 +830,9 @@ class ShareAPITestCase(test.TestCase):
|
||||||
'share_type': None,
|
'share_type': None,
|
||||||
'snapshot_id': share['snapshot_id'],
|
'snapshot_id': share['snapshot_id'],
|
||||||
}
|
}
|
||||||
|
self.mock_object(db_driver, 'share_get',
|
||||||
|
mock.Mock(return_value=original_share))
|
||||||
|
self.mock_object(share_types, 'get_share_type')
|
||||||
self.mock_object(db_driver, 'share_create',
|
self.mock_object(db_driver, 'share_create',
|
||||||
mock.Mock(return_value=share))
|
mock.Mock(return_value=share))
|
||||||
self.mock_object(db_driver, 'share_update',
|
self.mock_object(db_driver, 'share_update',
|
||||||
|
@ -823,6 +841,9 @@ class ShareAPITestCase(test.TestCase):
|
||||||
self.api.create(self.context, 'nfs', '1', 'fakename', 'fakedesc',
|
self.api.create(self.context, 'nfs', '1', 'fakename', 'fakedesc',
|
||||||
snapshot=snapshot, availability_zone='fakeaz')
|
snapshot=snapshot, availability_zone='fakeaz')
|
||||||
|
|
||||||
|
db_driver.share_get.assert_called_once_with(
|
||||||
|
self.context, snapshot['share_id'])
|
||||||
|
self.assertEqual(0, share_types.get_share_type.call_count)
|
||||||
self.scheduler_rpcapi.create_share.assert_called_once_with(
|
self.scheduler_rpcapi.create_share.assert_called_once_with(
|
||||||
self.context, 'manila-share', share['id'],
|
self.context, 'manila-share', share['id'],
|
||||||
share['snapshot_id'], request_spec=request_spec,
|
share['snapshot_id'], request_spec=request_spec,
|
||||||
|
@ -935,6 +956,72 @@ class ShareAPITestCase(test.TestCase):
|
||||||
db_driver.share_get.assert_called_once_with(
|
db_driver.share_get.assert_called_once_with(
|
||||||
self.context, share_id)
|
self.context, share_id)
|
||||||
|
|
||||||
|
@mock.patch.object(quota.QUOTAS, 'reserve',
|
||||||
|
mock.Mock(return_value='reservation'))
|
||||||
|
@mock.patch.object(quota.QUOTAS, 'commit', mock.Mock())
|
||||||
|
def test_create_from_snapshot_share_type_from_original(self):
|
||||||
|
# Prepare data for test
|
||||||
|
CONF.set_default("use_scheduler_creating_share_from_snapshot", False)
|
||||||
|
date = datetime.datetime(1, 1, 1, 1, 1, 1)
|
||||||
|
timeutils.utcnow.return_value = date
|
||||||
|
share_type = {'id': 'fake_share_type'}
|
||||||
|
original_share = fake_share('fake_original_id',
|
||||||
|
user_id=self.context.user_id,
|
||||||
|
project_id=self.context.project_id,
|
||||||
|
share_type_id='fake_share_type_id',
|
||||||
|
status='available')
|
||||||
|
share_id = 'fake_share_id'
|
||||||
|
snapshot = fake_snapshot('fakesnapshotid',
|
||||||
|
share_id=original_share['id'],
|
||||||
|
status='available')
|
||||||
|
share = fake_share(share_id, user_id=self.context.user_id,
|
||||||
|
project_id=self.context.project_id,
|
||||||
|
snapshot_id=snapshot['id'], status='creating',
|
||||||
|
share_type_id=original_share['share_type_id'])
|
||||||
|
options = share.copy()
|
||||||
|
for name in ('id', 'export_location', 'host', 'launched_at',
|
||||||
|
'terminated_at'):
|
||||||
|
options.pop(name, None)
|
||||||
|
request_spec = {
|
||||||
|
'share_properties': options,
|
||||||
|
'share_proto': share['share_proto'],
|
||||||
|
'share_id': share_id,
|
||||||
|
'share_type': share_type,
|
||||||
|
'snapshot_id': share['snapshot_id'],
|
||||||
|
}
|
||||||
|
self.mock_object(db_driver, 'share_get',
|
||||||
|
mock.Mock(return_value=original_share))
|
||||||
|
self.mock_object(share_types, 'get_share_type',
|
||||||
|
mock.Mock(return_value=share_type))
|
||||||
|
self.mock_object(db_driver, 'share_create',
|
||||||
|
mock.Mock(return_value=share))
|
||||||
|
self.mock_object(db_driver, 'share_update',
|
||||||
|
mock.Mock(return_value=share))
|
||||||
|
self.mock_object(db_driver, 'share_get',
|
||||||
|
mock.Mock(return_value=share))
|
||||||
|
|
||||||
|
# Call tested method
|
||||||
|
self.api.create(self.context, 'nfs', '1', 'fakename', 'fakedesc',
|
||||||
|
snapshot=snapshot, availability_zone='fakeaz')
|
||||||
|
|
||||||
|
# Verify results
|
||||||
|
self.share_rpcapi.create_share.assert_called_once_with(
|
||||||
|
self.context, share, snapshot['share']['host'],
|
||||||
|
request_spec=request_spec, filter_properties={},
|
||||||
|
snapshot_id=snapshot['id'])
|
||||||
|
db_driver.share_create.assert_called_once_with(
|
||||||
|
self.context, options)
|
||||||
|
share_api.policy.check_policy.assert_called_once_with(
|
||||||
|
self.context, 'share', 'create')
|
||||||
|
quota.QUOTAS.reserve.assert_called_once_with(
|
||||||
|
self.context, gigabytes=1, shares=1)
|
||||||
|
quota.QUOTAS.commit.assert_called_once_with(
|
||||||
|
self.context, 'reservation')
|
||||||
|
db_driver.share_get.assert_called_once_with(
|
||||||
|
self.context, original_share['id'])
|
||||||
|
db_driver.share_update.assert_called_once_with(
|
||||||
|
self.context, share_id, {'host': snapshot['share']['host']})
|
||||||
|
|
||||||
def test_get_snapshot(self):
|
def test_get_snapshot(self):
|
||||||
fake_get_snap = {'fake_key': 'fake_val'}
|
fake_get_snap = {'fake_key': 'fake_val'}
|
||||||
with mock.patch.object(db_driver, 'share_snapshot_get',
|
with mock.patch.object(db_driver, 'share_snapshot_get',
|
||||||
|
|
Loading…
Reference in New Issue