# 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. import datetime import ddt import mock import webob from manila.api.v1 import share_snapshots from manila.share import api as share_api from manila import test from manila.tests.api.contrib import stubs from manila.tests.api import fakes @ddt.ddt class ShareSnapshotApiTest(test.TestCase): """Share Snapshot Api Test.""" def setUp(self): super(ShareSnapshotApiTest, self).setUp() self.controller = share_snapshots.ShareSnapshotsController() self.mock_object(share_api.API, 'get', stubs.stub_share_get) self.mock_object(share_api.API, 'get_all_snapshots', stubs.stub_snapshot_get_all_by_project) self.mock_object(share_api.API, 'get_snapshot', stubs.stub_snapshot_get) self.mock_object(share_api.API, 'snapshot_update', stubs.stub_snapshot_update) self.snp_example = { 'share_id': 100, 'size': 12, 'force': False, 'display_name': 'updated_share_name', 'display_description': 'updated_share_description', } self.maxDiff = None @ddt.data('true', 'True', ' True', '1') def test_snapshot_create(self, snapshot_support): self.mock_object(share_api.API, 'create_snapshot', stubs.stub_snapshot_create) body = { 'snapshot': { 'share_id': 100, 'force': False, 'name': 'fake_share_name', 'description': 'fake_share_description', } } req = fakes.HTTPRequest.blank('/snapshots') res_dict = self.controller.create(req, body) expected = { 'snapshot': { 'id': 200, 'share_id': 100, 'share_size': 1, 'created_at': datetime.datetime(1, 1, 1, 1, 1, 1), 'status': 'fakesnapstatus', 'name': 'fake_share_name', 'size': 1, 'description': 'fake_share_description', 'share_proto': 'fakesnapproto', 'links': [ { 'href': 'http://localhost/v1/fake/snapshots/200', 'rel': 'self', }, { 'href': 'http://localhost/fake/snapshots/200', 'rel': 'bookmark', }, ], } } self.assertEqual(expected, res_dict) @ddt.data(0, False) def test_snapshot_create_no_support(self, snapshot_support): self.mock_object(share_api.API, 'create_snapshot') self.mock_object( share_api.API, 'get', mock.Mock(return_value={'snapshot_support': snapshot_support})) body = { 'snapshot': { 'share_id': 100, 'force': False, 'name': 'fake_share_name', 'description': 'fake_share_description', } } req = fakes.HTTPRequest.blank('/snapshots') self.assertRaises( webob.exc.HTTPUnprocessableEntity, self.controller.create, req, body) self.assertFalse(share_api.API.create_snapshot.called) def test_snapshot_create_no_body(self): body = {} req = fakes.HTTPRequest.blank('/snapshots') self.assertRaises(webob.exc.HTTPUnprocessableEntity, self.controller.create, req, body) def test_snapshot_delete(self): self.mock_object(share_api.API, 'delete_snapshot', stubs.stub_snapshot_delete) req = fakes.HTTPRequest.blank('/snapshots/200') resp = self.controller.delete(req, 200) self.assertEqual(resp.status_int, 202) def test_snapshot_delete_nofound(self): self.mock_object(share_api.API, 'get_snapshot', stubs.stub_snapshot_get_notfound) req = fakes.HTTPRequest.blank('/snapshots/200') self.assertRaises(webob.exc.HTTPNotFound, self.controller.delete, req, 200) def test_snapshot_show(self): req = fakes.HTTPRequest.blank('/snapshots/200') res_dict = self.controller.show(req, 200) expected = { 'snapshot': { 'id': 200, 'share_id': 'fakeshareid', 'share_size': 1, 'created_at': datetime.datetime(1, 1, 1, 1, 1, 1), 'status': 'fakesnapstatus', 'name': 'displaysnapname', 'size': 1, 'description': 'displaysnapdesc', 'share_proto': 'fakesnapproto', 'links': [ { 'href': 'http://localhost/v1/fake/snapshots/200', 'rel': 'self', }, { 'href': 'http://localhost/fake/snapshots/200', 'rel': 'bookmark', }, ], } } self.assertEqual(res_dict, expected) def test_snapshot_show_nofound(self): self.mock_object(share_api.API, 'get_snapshot', stubs.stub_snapshot_get_notfound) req = fakes.HTTPRequest.blank('/snapshots/200') self.assertRaises(webob.exc.HTTPNotFound, self.controller.show, req, '200') def test_snapshot_list_summary(self): self.mock_object(share_api.API, 'get_all_snapshots', stubs.stub_snapshot_get_all_by_project) req = fakes.HTTPRequest.blank('/snapshots') res_dict = self.controller.index(req) expected = { 'snapshots': [ { 'name': 'displaysnapname', 'id': 2, 'links': [ { 'href': 'http://localhost/v1/fake/' 'snapshots/2', 'rel': 'self' }, { 'href': 'http://localhost/fake/snapshots/2', 'rel': 'bookmark' } ], } ] } self.assertEqual(res_dict, expected) def _snapshot_list_summary_with_search_opts(self, use_admin_context): search_opts = { 'name': 'fake_name', 'status': 'fake_status', 'share_id': 'fake_share_id', 'sort_key': 'fake_sort_key', 'sort_dir': 'fake_sort_dir', 'offset': '1', 'limit': '1', } # fake_key should be filtered for non-admin url = '/snapshots?fake_key=fake_value' for k, v in search_opts.items(): url = url + '&' + k + '=' + v req = fakes.HTTPRequest.blank(url, use_admin_context=use_admin_context) snapshots = [ {'id': 'id1', 'display_name': 'n1'}, {'id': 'id2', 'display_name': 'n2'}, {'id': 'id3', 'display_name': 'n3'}, ] self.mock_object(share_api.API, 'get_all_snapshots', mock.Mock(return_value=snapshots)) result = self.controller.index(req) search_opts_expected = { 'display_name': search_opts['name'], 'status': search_opts['status'], 'share_id': search_opts['share_id'], } if use_admin_context: search_opts_expected.update({'fake_key': 'fake_value'}) share_api.API.get_all_snapshots.assert_called_once_with( req.environ['manila.context'], sort_key=search_opts['sort_key'], sort_dir=search_opts['sort_dir'], search_opts=search_opts_expected, ) self.assertEqual(1, len(result['snapshots'])) self.assertEqual(snapshots[1]['id'], result['snapshots'][0]['id']) self.assertEqual( snapshots[1]['display_name'], result['snapshots'][0]['name']) def test_snapshot_list_summary_with_search_opts_by_non_admin(self): self._snapshot_list_summary_with_search_opts(use_admin_context=False) def test_snapshot_list_summary_with_search_opts_by_admin(self): self._snapshot_list_summary_with_search_opts(use_admin_context=True) def _snapshot_list_detail_with_search_opts(self, use_admin_context): search_opts = { 'name': 'fake_name', 'status': 'fake_status', 'share_id': 'fake_share_id', 'sort_key': 'fake_sort_key', 'sort_dir': 'fake_sort_dir', 'limit': '1', 'offset': '1', } # fake_key should be filtered for non-admin url = '/shares/detail?fake_key=fake_value' for k, v in search_opts.items(): url = url + '&' + k + '=' + v req = fakes.HTTPRequest.blank(url, use_admin_context=use_admin_context) snapshots = [ {'id': 'id1', 'display_name': 'n1'}, { 'id': 'id2', 'display_name': 'n2', 'status': 'fake_status', 'share_id': 'fake_share_id', }, {'id': 'id3', 'display_name': 'n3'}, ] self.mock_object(share_api.API, 'get_all_snapshots', mock.Mock(return_value=snapshots)) result = self.controller.detail(req) search_opts_expected = { 'display_name': search_opts['name'], 'status': search_opts['status'], 'share_id': search_opts['share_id'], } if use_admin_context: search_opts_expected.update({'fake_key': 'fake_value'}) share_api.API.get_all_snapshots.assert_called_once_with( req.environ['manila.context'], sort_key=search_opts['sort_key'], sort_dir=search_opts['sort_dir'], search_opts=search_opts_expected, ) self.assertEqual(1, len(result['snapshots'])) self.assertEqual(snapshots[1]['id'], result['snapshots'][0]['id']) self.assertEqual( snapshots[1]['display_name'], result['snapshots'][0]['name']) self.assertEqual( snapshots[1]['status'], result['snapshots'][0]['status']) self.assertEqual( snapshots[1]['share_id'], result['snapshots'][0]['share_id']) def test_share_list_detail_with_search_opts_by_non_admin(self): self._snapshot_list_detail_with_search_opts(use_admin_context=False) def test_share_list_detail_with_search_opts_by_admin(self): self._snapshot_list_detail_with_search_opts(use_admin_context=True) def test_snapshot_list_detail(self): env = {'QUERY_STRING': 'name=Share+Test+Name'} req = fakes.HTTPRequest.blank('/shares/detail', environ=env) res_dict = self.controller.detail(req) expected = { 'snapshots': [ { 'id': 2, 'share_id': 'fakeshareid', 'share_size': 1, 'size': 1, 'created_at': datetime.datetime(1, 1, 1, 1, 1, 1), 'status': 'fakesnapstatus', 'name': 'displaysnapname', 'description': 'displaysnapdesc', 'share_proto': 'fakesnapproto', 'links': [ { 'href': 'http://localhost/v1/fake/snapshots/' '2', 'rel': 'self', }, { 'href': 'http://localhost/fake/snapshots/2', 'rel': 'bookmark', }, ], }, ] } self.assertEqual(res_dict, expected) def test_snapshot_updates_description(self): snp = self.snp_example body = {"snapshot": snp} req = fakes.HTTPRequest.blank('/snapshot/1') res_dict = self.controller.update(req, 1, body) self.assertEqual(res_dict['snapshot']["name"], snp["display_name"]) def test_snapshot_updates_display_descr(self): snp = self.snp_example body = {"snapshot": snp} req = fakes.HTTPRequest.blank('/snapshot/1') res_dict = self.controller.update(req, 1, body) self.assertEqual(res_dict['snapshot']["description"], snp["display_description"]) def test_share_not_updates_size(self): snp = self.snp_example body = {"snapshot": snp} req = fakes.HTTPRequest.blank('/snapshot/1') res_dict = self.controller.update(req, 1, body) self.assertNotEqual(res_dict['snapshot']["size"], snp["size"])