<commit_before># Copyright (C) 2012 Hewlett-Packard Development Company, L.P.
# 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.

"""
Tests for Backup code.
"""

import json
from xml.dom import minidom

import mock
import webob

# needed for stubs to work
import cinder.backup
from cinder import context
from cinder import db
from cinder import exception
from cinder.i18n import _
from cinder.openstack.common import log as logging
from cinder.openstack.common import timeutils
from cinder import test
from cinder.tests.api import fakes
from cinder.tests import utils
# needed for stubs to work
import cinder.volume


LOG = logging.getLogger(__name__)


class BackupsAPITestCase(test.TestCase):
    """Test Case for backups API."""

    def setUp(self):
        super(BackupsAPITestCase, self).setUp()
        self.volume_api = cinder.volume.API()
        self.backup_api = cinder.backup.API()
        self.context = context.get_admin_context()
        self.context.project_id = 'fake'
        self.context.user_id = 'fake'

    @staticmethod
    def _create_backup(volume_id=1,
                       display_name='test_backup',
                       display_description='this is a test backup',
                       container='volumebackups',
                       status='creating',
                       size=0, object_count=0):
        """Create a backup object."""
        backup = {}
        backup['volume_id'] = volume_id
        backup['user_id'] = 'fake'
        backup['project_id'] = 'fake'
        backup['host'] = 'testhost'
        backup['availability_zone'] = 'az1'
        backup['display_name'] = display_name
        backup['display_description'] = display_description
        backup['container'] = container
        backup['status'] = status
        backup['fail_reason'] = ''
        backup['size'] = size
        backup['object_count'] = object_count
        return db.backup_create(context.get_admin_context(), backup)['id']

    @staticmethod
    def _get_backup_attrib(backup_id, attrib_name):
        return db.backup_get(context.get_admin_context(),
                             backup_id)[attrib_name]

    def test_show_backup(self):
        volume_id = utils.create_volume(self.context, size=5,
                                        status='creating')['id']
        backup_id = self._create_backup(volume_id)
        LOG.debug('Created backup with id %s' % backup_id)
        req = webob.Request.blank('/v2/fake/backups/%s' %
                                  backup_id)
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 200)
        self.assertEqual(res_dict['backup']['availability_zone'], 'az1')
        self.assertEqual(res_dict['backup']['container'], 'volumebackups')
        self.assertEqual(res_dict['backup']['description'],
                         'this is a test backup')
        self.assertEqual(res_dict['backup']['name'], 'test_backup')
        self.assertEqual(res_dict['backup']['id'], backup_id)
        self.assertEqual(res_dict['backup']['object_count'], 0)
        self.assertEqual(res_dict['backup']['size'], 0)
        self.assertEqual(res_dict['backup']['status'], 'creating')
        self.assertEqual(res_dict['backup']['volume_id'], volume_id)

        db.backup_destroy(context.get_admin_context(), backup_id)
        db.volume_destroy(context.get_admin_context(), volume_id)

    def test_show_backup_xml_content_type(self):
        volume_id = utils.create_volume(self.context, size=5,
                                        status='creating')['id']
        backup_id = self._create_backup(volume_id)
        req = webob.Request.blank('/v2/fake/backups/%s' % backup_id)
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/xml'
        req.headers['Accept'] = 'application/xml'
        res = req.get_response(fakes.wsgi_app())
        self.assertEqual(res.status_int, 200)
        dom = minidom.parseString(res.body)
        backup = dom.getElementsByTagName('backup')
        name = backup.item(0).getAttribute('name')
        container_name = backup.item(0).getAttribute('container')
        self.assertEqual(container_name.strip(), "volumebackups")
        self.assertEqual(name.strip(), "test_backup")
        db.backup_destroy(context.get_admin_context(), backup_id)
        db.volume_destroy(context.get_admin_context(), volume_id)

    def test_show_backup_with_backup_NotFound(self):
        req = webob.Request.blank('/v2/fake/backups/9999')
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 404)
        self.assertEqual(res_dict['itemNotFound']['code'], 404)
        self.assertEqual(res_dict['itemNotFound']['message'],
                         'Backup 9999 could not be found.')

    def test_list_backups_json(self):
        backup_id1 = self._create_backup()
        backup_id2 = self._create_backup()
        backup_id3 = self._create_backup()

        req = webob.Request.blank('/v2/fake/backups')
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 200)
        self.assertEqual(len(res_dict['backups'][0]), 3)
        self.assertEqual(res_dict['backups'][0]['id'], backup_id1)
        self.assertEqual(res_dict['backups'][0]['name'], 'test_backup')
        self.assertEqual(len(res_dict['backups'][1]), 3)
        self.assertEqual(res_dict['backups'][1]['id'], backup_id2)
        self.assertEqual(res_dict['backups'][1]['name'], 'test_backup')
        self.assertEqual(len(res_dict['backups'][2]), 3)
        self.assertEqual(res_dict['backups'][2]['id'], backup_id3)
        self.assertEqual(res_dict['backups'][2]['name'], 'test_backup')

        db.backup_destroy(context.get_admin_context(), backup_id3)
        db.backup_destroy(context.get_admin_context(), backup_id2)
        db.backup_destroy(context.get_admin_context(), backup_id1)

    def test_list_backups_xml(self):
        backup_id1 = self._create_backup()
        backup_id2 = self._create_backup()
        backup_id3 = self._create_backup()

        req = webob.Request.blank('/v2/fake/backups')
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/xml'
        req.headers['Accept'] = 'application/xml'
        res = req.get_response(fakes.wsgi_app())

        self.assertEqual(res.status_int, 200)
        dom = minidom.parseString(res.body)
        backup_list = dom.getElementsByTagName('backup')

        self.assertEqual(backup_list.item(0).attributes.length, 2)
        self.assertEqual(backup_list.item(0).getAttribute('id'),
                         backup_id1)
        self.assertEqual(backup_list.item(1).attributes.length, 2)
        self.assertEqual(backup_list.item(1).getAttribute('id'),
                         backup_id2)
        self.assertEqual(backup_list.item(2).attributes.length, 2)
        self.assertEqual(backup_list.item(2).getAttribute('id'),
                         backup_id3)

        db.backup_destroy(context.get_admin_context(), backup_id3)
        db.backup_destroy(context.get_admin_context(), backup_id2)
        db.backup_destroy(context.get_admin_context(), backup_id1)

    def test_list_backups_detail_json(self):
        backup_id1 = self._create_backup()
        backup_id2 = self._create_backup()
        backup_id3 = self._create_backup()

        req = webob.Request.blank('/v2/fake/backups/detail')
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/json'
        req.headers['Accept'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 200)
        self.assertEqual(len(res_dict['backups'][0]), 12)
        self.assertEqual(res_dict['backups'][0]['availability_zone'], 'az1')
        self.assertEqual(res_dict['backups'][0]['container'],
                         'volumebackups')
        self.assertEqual(res_dict['backups'][0]['description'],
                         'this is a test backup')
        self.assertEqual(res_dict['backups'][0]['name'],
                         'test_backup')
        self.assertEqual(res_dict['backups'][0]['id'], backup_id1)
        self.assertEqual(res_dict['backups'][0]['object_count'], 0)
        self.assertEqual(res_dict['backups'][0]['size'], 0)
        self.assertEqual(res_dict['backups'][0]['status'], 'creating')
        self.assertEqual(res_dict['backups'][0]['volume_id'], '1')

        self.assertEqual(len(res_dict['backups'][1]), 12)
        self.assertEqual(res_dict['backups'][1]['availability_zone'], 'az1')
        self.assertEqual(res_dict['backups'][1]['container'],
                         'volumebackups')
        self.assertEqual(res_dict['backups'][1]['description'],
                         'this is a test backup')
        self.assertEqual(res_dict['backups'][1]['name'],
                         'test_backup')
        self.assertEqual(res_dict['backups'][1]['id'], backup_id2)
        self.assertEqual(res_dict['backups'][1]['object_count'], 0)
        self.assertEqual(res_dict['backups'][1]['size'], 0)
        self.assertEqual(res_dict['backups'][1]['status'], 'creating')
        self.assertEqual(res_dict['backups'][1]['volume_id'], '1')

        self.assertEqual(len(res_dict['backups'][2]), 12)
        self.assertEqual(res_dict['backups'][2]['availability_zone'], 'az1')
        self.assertEqual(res_dict['backups'][2]['container'],
                         'volumebackups')
        self.assertEqual(res_dict['backups'][2]['description'],
                         'this is a test backup')
        self.assertEqual(res_dict['backups'][2]['name'],
                         'test_backup')
        self.assertEqual(res_dict['backups'][2]['id'], backup_id3)
        self.assertEqual(res_dict['backups'][2]['object_count'], 0)
        self.assertEqual(res_dict['backups'][2]['size'], 0)
        self.assertEqual(res_dict['backups'][2]['status'], 'creating')
        self.assertEqual(res_dict['backups'][2]['volume_id'], '1')

        db.backup_destroy(context.get_admin_context(), backup_id3)
        db.backup_destroy(context.get_admin_context(), backup_id2)
        db.backup_destroy(context.get_admin_context(), backup_id1)

    def test_list_backups_detail_using_filters(self):
        backup_id1 = self._create_backup(display_name='test2')
        backup_id2 = self._create_backup(status='available')
        backup_id3 = self._create_backup(volume_id=4321)

        req = webob.Request.blank('/v2/fake/backups/detail?name=test2')
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/json'
        req.headers['Accept'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(len(res_dict['backups']), 1)
        self.assertEqual(res.status_int, 200)
        self.assertEqual(res_dict['backups'][0]['id'], backup_id1)

        req = webob.Request.blank('/v2/fake/backups/detail?status=available')
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/json'
        req.headers['Accept'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(len(res_dict['backups']), 1)
        self.assertEqual(res.status_int, 200)
        self.assertEqual(res_dict['backups'][0]['id'], backup_id2)

        req = webob.Request.blank('/v2/fake/backups/detail?volume_id=4321')
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/json'
        req.headers['Accept'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(len(res_dict['backups']), 1)
        self.assertEqual(res.status_int, 200)
        self.assertEqual(res_dict['backups'][0]['id'], backup_id3)

        db.backup_destroy(context.get_admin_context(), backup_id3)
        db.backup_destroy(context.get_admin_context(), backup_id2)
        db.backup_destroy(context.get_admin_context(), backup_id1)

    def test_list_backups_detail_xml(self):
        backup_id1 = self._create_backup()
        backup_id2 = self._create_backup()
        backup_id3 = self._create_backup()

        req = webob.Request.blank('/v2/fake/backups/detail')
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/xml'
        req.headers['Accept'] = 'application/xml'
        res = req.get_response(fakes.wsgi_app())

        self.assertEqual(res.status_int, 200)
        dom = minidom.parseString(res.body)
        backup_detail = dom.getElementsByTagName('backup')

        self.assertEqual(backup_detail.item(0).attributes.length, 11)
        self.assertEqual(
            backup_detail.item(0).getAttribute('availability_zone'), 'az1')
        self.assertEqual(
            backup_detail.item(0).getAttribute('container'), 'volumebackups')
        self.assertEqual(
            backup_detail.item(0).getAttribute('description'),
            'this is a test backup')
        self.assertEqual(
            backup_detail.item(0).getAttribute('name'), 'test_backup')
        self.assertEqual(
            backup_detail.item(0).getAttribute('id'), backup_id1)
        self.assertEqual(
            int(backup_detail.item(0).getAttribute('object_count')), 0)
        self.assertEqual(
            int(backup_detail.item(0).getAttribute('size')), 0)
        self.assertEqual(
            backup_detail.item(0).getAttribute('status'), 'creating')
        self.assertEqual(
            int(backup_detail.item(0).getAttribute('volume_id')), 1)

        self.assertEqual(backup_detail.item(1).attributes.length, 11)
        self.assertEqual(
            backup_detail.item(1).getAttribute('availability_zone'), 'az1')
        self.assertEqual(
            backup_detail.item(1).getAttribute('container'), 'volumebackups')
        self.assertEqual(
            backup_detail.item(1).getAttribute('description'),
            'this is a test backup')
        self.assertEqual(
            backup_detail.item(1).getAttribute('name'), 'test_backup')
        self.assertEqual(
            backup_detail.item(1).getAttribute('id'), backup_id2)
        self.assertEqual(
            int(backup_detail.item(1).getAttribute('object_count')), 0)
        self.assertEqual(
            int(backup_detail.item(1).getAttribute('size')), 0)
        self.assertEqual(
            backup_detail.item(1).getAttribute('status'), 'creating')
        self.assertEqual(
            int(backup_detail.item(1).getAttribute('volume_id')), 1)

        self.assertEqual(backup_detail.item(2).attributes.length, 11)
        self.assertEqual(
            backup_detail.item(2).getAttribute('availability_zone'), 'az1')
        self.assertEqual(
            backup_detail.item(2).getAttribute('container'), 'volumebackups')
        self.assertEqual(
            backup_detail.item(2).getAttribute('description'),
            'this is a test backup')
        self.assertEqual(
            backup_detail.item(2).getAttribute('name'), 'test_backup')
        self.assertEqual(
            backup_detail.item(2).getAttribute('id'), backup_id3)
        self.assertEqual(
            int(backup_detail.item(2).getAttribute('object_count')), 0)
        self.assertEqual(
            int(backup_detail.item(2).getAttribute('size')), 0)
        self.assertEqual(
            backup_detail.item(2).getAttribute('status'), 'creating')
        self.assertEqual(
            int(backup_detail.item(2).getAttribute('volume_id')), 1)

        db.backup_destroy(context.get_admin_context(), backup_id3)
        db.backup_destroy(context.get_admin_context(), backup_id2)
        db.backup_destroy(context.get_admin_context(), backup_id1)

    @mock.patch('cinder.db.service_get_all_by_topic')
    def test_create_backup_json(self, _mock_service_get_all_by_topic):
        _mock_service_get_all_by_topic.return_value = [
            {'availability_zone': "fake_az", 'host': 'test_host',
             'disabled': 0, 'updated_at': timeutils.utcnow()}]

        volume_id = utils.create_volume(self.context, size=5)['id']

        body = {"backup": {"display_name": "nightly001",
                           "display_description":
                           "Nightly Backup 03-Sep-2012",
                           "volume_id": volume_id,
                           "container": "nightlybackups",
                           }
                }
        req = webob.Request.blank('/v2/fake/backups')
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())

        res_dict = json.loads(res.body)
        LOG.info(res_dict)

        self.assertEqual(res.status_int, 202)
        self.assertIn('id', res_dict['backup'])
        self.assertTrue(_mock_service_get_all_by_topic.called)

        db.volume_destroy(context.get_admin_context(), volume_id)

    @mock.patch('cinder.db.service_get_all_by_topic')
    def test_create_backup_xml(self, _mock_service_get_all_by_topic):
        _mock_service_get_all_by_topic.return_value = [
            {'availability_zone': "fake_az", 'host': 'test_host',
             'disabled': 0, 'updated_at': timeutils.utcnow()}]

        volume_id = utils.create_volume(self.context, size=2)['id']

        req = webob.Request.blank('/v2/fake/backups')
        req.body = ('<backup display_name="backup-001" '
                    'display_description="Nightly Backup" '
                    'volume_id="%s" container="Container001"/>' % volume_id)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/xml'
        req.headers['Accept'] = 'application/xml'
        res = req.get_response(fakes.wsgi_app())

        self.assertEqual(res.status_int, 202)
        dom = minidom.parseString(res.body)
        backup = dom.getElementsByTagName('backup')
        self.assertTrue(backup.item(0).hasAttribute('id'))
        self.assertTrue(_mock_service_get_all_by_topic.called)

        db.volume_destroy(context.get_admin_context(), volume_id)

    def test_create_backup_with_no_body(self):
        # omit body from the request
        req = webob.Request.blank('/v2/fake/backups')
        req.body = json.dumps(None)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.headers['Accept'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'The server could not comply with the request since'
                         ' it is either malformed or otherwise incorrect.')

    def test_create_backup_with_body_KeyError(self):
        # omit volume_id from body
        body = {"backup": {"display_name": "nightly001",
                           "display_description":
                           "Nightly Backup 03-Sep-2012",
                           "container": "nightlybackups",
                           }
                }
        req = webob.Request.blank('/v2/fake/backups')
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'Incorrect request body format')

    def test_create_backup_with_VolumeNotFound(self):
        body = {"backup": {"display_name": "nightly001",
                           "display_description":
                           "Nightly Backup 03-Sep-2012",
                           "volume_id": 9999,
                           "container": "nightlybackups",
                           }
                }
        req = webob.Request.blank('/v2/fake/backups')
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 404)
        self.assertEqual(res_dict['itemNotFound']['code'], 404)
        self.assertEqual(res_dict['itemNotFound']['message'],
                         'Volume 9999 could not be found.')

    def test_create_backup_with_InvalidVolume(self):
        # need to create the volume referenced below first
        volume_id = utils.create_volume(self.context, size=5,
                                        status='restoring')['id']
        body = {"backup": {"display_name": "nightly001",
                           "display_description":
                           "Nightly Backup 03-Sep-2012",
                           "volume_id": volume_id,
                           "container": "nightlybackups",
                           }
                }
        req = webob.Request.blank('/v2/fake/backups')
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'Invalid volume: Volume to be backed up must'
                         ' be available')

    @mock.patch('cinder.db.service_get_all_by_topic')
    def test_create_backup_WithOUT_enabled_backup_service(
            self,
            _mock_service_get_all_by_topic):
        # need an enabled backup service available
        _mock_service_get_all_by_topic.return_value = []

        volume_id = utils.create_volume(self.context, size=2)['id']
        req = webob.Request.blank('/v2/fake/backups')
        body = {"backup": {"display_name": "nightly001",
                           "display_description":
                           "Nightly Backup 03-Sep-2012",
                           "volume_id": volume_id,
                           "container": "nightlybackups",
                           }
                }
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.headers['Accept'] = 'application/json'
        req.body = json.dumps(body)

        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)
        self.assertEqual(res.status_int, 500)
        self.assertEqual(res_dict['computeFault']['code'], 500)
        self.assertEqual(res_dict['computeFault']['message'],
                         'Service cinder-backup could not be found.')

        volume = self.volume_api.get(context.get_admin_context(), volume_id)
        self.assertEqual(volume['status'], 'available')

    @mock.patch('cinder.db.service_get_all_by_topic')
    def test_is_backup_service_enabled(self, _mock_service_get_all_by_topic):

        test_host = 'test_host'
        alt_host = 'strange_host'
        empty_service = []
        #service host not match with volume's host
        host_not_match = [{'availability_zone': "fake_az", 'host': alt_host,
                           'disabled': 0, 'updated_at': timeutils.utcnow()}]
        #service az not match with volume's az
        az_not_match = [{'availability_zone': "strange_az", 'host': test_host,
                         'disabled': 0, 'updated_at': timeutils.utcnow()}]
        #service disabled
        disabled_service = []

        #dead service that last reported at 20th century
        dead_service = [{'availability_zone': "fake_az", 'host': alt_host,
                         'disabled': 0, 'updated_at': '1989-04-16 02:55:44'}]

        #first service's host not match but second one works.
        multi_services = [{'availability_zone': "fake_az", 'host': alt_host,
                           'disabled': 0, 'updated_at': timeutils.utcnow()},
                          {'availability_zone': "fake_az", 'host': test_host,
                           'disabled': 0, 'updated_at': timeutils.utcnow()}]

        #Setup mock to run through the following service cases
        _mock_service_get_all_by_topic.side_effect = [empty_service,
                                                      host_not_match,
                                                      az_not_match,
                                                      disabled_service,
                                                      dead_service,
                                                      multi_services]

        volume_id = utils.create_volume(self.context, size=2,
                                        host=test_host)['id']
        volume = self.volume_api.get(context.get_admin_context(), volume_id)

        #test empty service
        self.assertEqual(self.backup_api._is_backup_service_enabled(volume,
                                                                    test_host),
                         False)

        #test host not match service
        self.assertEqual(self.backup_api._is_backup_service_enabled(volume,
                                                                    test_host),
                         False)

        #test az not match service
        self.assertEqual(self.backup_api._is_backup_service_enabled(volume,
                                                                    test_host),
                         False)

        #test disabled service
        self.assertEqual(self.backup_api._is_backup_service_enabled(volume,
                                                                    test_host),
                         False)

        #test dead service
        self.assertEqual(self.backup_api._is_backup_service_enabled(volume,
                                                                    test_host),
                         False)

        #test multi services and the last service matches
        self.assertEqual(self.backup_api._is_backup_service_enabled(volume,
                                                                    test_host),
                         True)

    def test_delete_backup_available(self):
        backup_id = self._create_backup(status='available')
        req = webob.Request.blank('/v2/fake/backups/%s' %
                                  backup_id)
        req.method = 'DELETE'
        req.headers['Content-Type'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())

        self.assertEqual(res.status_int, 202)
        self.assertEqual(self._get_backup_attrib(backup_id, 'status'),
                         'deleting')

        db.backup_destroy(context.get_admin_context(), backup_id)

    def test_delete_backup_error(self):
        backup_id = self._create_backup(status='error')
        req = webob.Request.blank('/v2/fake/backups/%s' %
                                  backup_id)
        req.method = 'DELETE'
        req.headers['Content-Type'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())

        self.assertEqual(res.status_int, 202)
        self.assertEqual(self._get_backup_attrib(backup_id, 'status'),
                         'deleting')

        db.backup_destroy(context.get_admin_context(), backup_id)

    def test_delete_backup_with_backup_NotFound(self):
        req = webob.Request.blank('/v2/fake/backups/9999')
        req.method = 'DELETE'
        req.headers['Content-Type'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 404)
        self.assertEqual(res_dict['itemNotFound']['code'], 404)
        self.assertEqual(res_dict['itemNotFound']['message'],
                         'Backup 9999 could not be found.')

    def test_delete_backup_with_InvalidBackup(self):
        backup_id = self._create_backup()
        req = webob.Request.blank('/v2/fake/backups/%s' %
                                  backup_id)
        req.method = 'DELETE'
        req.headers['Content-Type'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'Invalid backup: Backup status must be '
                         'available or error')

        db.backup_destroy(context.get_admin_context(), backup_id)

    def test_restore_backup_volume_id_specified_json(self):
        backup_id = self._create_backup(status='available')
        # need to create the volume referenced below first
        volume_id = utils.create_volume(self.context, size=5)['id']

        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 202)
        self.assertEqual(res_dict['restore']['backup_id'], backup_id)
        self.assertEqual(res_dict['restore']['volume_id'], volume_id)

    def test_restore_backup_volume_id_specified_xml(self):
        backup_id = self._create_backup(status='available')
        volume_id = utils.create_volume(self.context, size=2)['id']

        req = webob.Request.blank('/v2/fake/backups/%s/restore' % backup_id)
        req.body = '<restore volume_id="%s"/>' % volume_id
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/xml'
        req.headers['Accept'] = 'application/xml'
        res = req.get_response(fakes.wsgi_app())

        self.assertEqual(res.status_int, 202)
        dom = minidom.parseString(res.body)
        restore = dom.getElementsByTagName('restore')
        self.assertEqual(restore.item(0).getAttribute('backup_id'),
                         backup_id)
        self.assertEqual(restore.item(0).getAttribute('volume_id'), volume_id)

        db.backup_destroy(context.get_admin_context(), backup_id)
        db.volume_destroy(context.get_admin_context(), volume_id)

    def test_restore_backup_with_no_body(self):
        # omit body from the request
        backup_id = self._create_backup(status='available')

        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)
        req.body = json.dumps(None)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.headers['Accept'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'Incorrect request body format')

        db.backup_destroy(context.get_admin_context(), backup_id)

    def test_restore_backup_with_body_KeyError(self):
        # omit restore from body
        backup_id = self._create_backup(status='available')

        req = webob.Request.blank('/v2/fake/backups/%s/restore' % backup_id)
        body = {"": {}}
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.headers['Accept'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())

        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'Incorrect request body format')

    @mock.patch('cinder.volume.API.create')
    def test_restore_backup_volume_id_unspecified(self,
                                                  _mock_volume_api_create):

        # intercept volume creation to ensure created volume
        # has status of available
        def fake_volume_api_create(context, size, name, description):
            volume_id = utils.create_volume(self.context, size=size)['id']
            return db.volume_get(context, volume_id)

        _mock_volume_api_create.side_effect = fake_volume_api_create

        backup_id = self._create_backup(size=5, status='available')

        body = {"restore": {}}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 202)
        self.assertEqual(res_dict['restore']['backup_id'], backup_id)

    @mock.patch('cinder.backup.API.restore')
    def test_restore_backup_with_InvalidInput(self,
                                              _mock_volume_api_restore):

        msg = _("Invalid input")
        _mock_volume_api_restore.side_effect = \
            exception.InvalidInput(reason=msg)

        backup_id = self._create_backup(status='available')
        # need to create the volume referenced below first
        volume_id = utils.create_volume(self.context, size=0)['id']
        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)

        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'Invalid input received: Invalid input')

    def test_restore_backup_with_InvalidVolume(self):
        backup_id = self._create_backup(status='available')
        # need to create the volume referenced below first
        volume_id = utils.create_volume(self.context, size=5,
                                        status='attaching')['id']

        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'Invalid volume: Volume to be restored to must '
                         'be available')

        db.volume_destroy(context.get_admin_context(), volume_id)
        db.backup_destroy(context.get_admin_context(), backup_id)

    def test_restore_backup_with_InvalidBackup(self):
        backup_id = self._create_backup(status='restoring')
        # need to create the volume referenced below first
        volume_id = utils.create_volume(self.context, size=5)['id']

        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'Invalid backup: Backup status must be available')

        db.volume_destroy(context.get_admin_context(), volume_id)
        db.backup_destroy(context.get_admin_context(), backup_id)

    def test_restore_backup_with_BackupNotFound(self):
        # need to create the volume referenced below first
        volume_id = utils.create_volume(self.context, size=5)['id']

        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/9999/restore')
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 404)
        self.assertEqual(res_dict['itemNotFound']['code'], 404)
        self.assertEqual(res_dict['itemNotFound']['message'],
                         'Backup 9999 could not be found.')

        db.volume_destroy(context.get_admin_context(), volume_id)

    def test_restore_backup_with_VolumeNotFound(self):
        backup_id = self._create_backup(status='available')

        body = {"restore": {"volume_id": "9999", }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 404)
        self.assertEqual(res_dict['itemNotFound']['code'], 404)
        self.assertEqual(res_dict['itemNotFound']['message'],
                         'Volume 9999 could not be found.')

        db.backup_destroy(context.get_admin_context(), backup_id)

    @mock.patch('cinder.backup.API.restore')
    def test_restore_backup_with_VolumeSizeExceedsAvailableQuota(
            self,
            _mock_backup_restore):

        _mock_backup_restore.side_effect = \
            exception.VolumeSizeExceedsAvailableQuota(requested='2',
                                                      consumed='2',
                                                      quota='3')

        backup_id = self._create_backup(status='available')
        # need to create the volume referenced below first
        volume_id = utils.create_volume(self.context, size=5)['id']

        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)

        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 413)
        self.assertEqual(res_dict['overLimit']['code'], 413)
        self.assertEqual(res_dict['overLimit']['message'],
                         'Requested volume or snapshot exceeds allowed '
                         'Gigabytes quota. Requested 2G, quota is 3G and '
                         '2G has been consumed.')

    @mock.patch('cinder.backup.API.restore')
    def test_restore_backup_with_VolumeLimitExceeded(self,
                                                     _mock_backup_restore):

        _mock_backup_restore.side_effect = \
            exception.VolumeLimitExceeded(allowed=1)

        backup_id = self._create_backup(status='available')
        # need to create the volume referenced below first
        volume_id = utils.create_volume(self.context, size=5)['id']

        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)

        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 413)
        self.assertEqual(res_dict['overLimit']['code'], 413)
        self.assertEqual(res_dict['overLimit']['message'],
                         'Maximum number of volumes allowed (1) exceeded')

    def test_restore_backup_to_undersized_volume(self):
        backup_size = 10
        backup_id = self._create_backup(status='available', size=backup_size)
        # need to create the volume referenced below first
        volume_size = 5
        volume_id = utils.create_volume(self.context, size=volume_size)['id']

        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'Invalid volume: volume size %d is too '
                         'small to restore backup of size %d.'
                         % (volume_size, backup_size))

        db.volume_destroy(context.get_admin_context(), volume_id)
        db.backup_destroy(context.get_admin_context(), backup_id)

    def test_restore_backup_to_oversized_volume(self):
        backup_id = self._create_backup(status='available', size=10)
        # need to create the volume referenced below first
        volume_id = utils.create_volume(self.context, size=15)['id']

        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 202)
        self.assertEqual(res_dict['restore']['backup_id'], backup_id)
        self.assertEqual(res_dict['restore']['volume_id'], volume_id)

        db.volume_destroy(context.get_admin_context(), volume_id)
        db.backup_destroy(context.get_admin_context(), backup_id)

    def test_export_record_as_non_admin(self):
        backup_id = self._create_backup(status='available', size=10)
        req = webob.Request.blank('/v2/fake/backups/%s/export_record' %<commit_msg>Unit test for restore with different hosts<commit_after># Copyright (C) 2012 Hewlett-Packard Development Company, L.P.
# 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.

"""
Tests for Backup code.
"""

import json
from xml.dom import minidom

import mock
import webob

# needed for stubs to work
import cinder.backup
from cinder import context
from cinder import db
from cinder import exception
from cinder.i18n import _
from cinder.openstack.common import log as logging
from cinder.openstack.common import timeutils
from cinder import test
from cinder.tests.api import fakes
from cinder.tests import utils
# needed for stubs to work
import cinder.volume


LOG = logging.getLogger(__name__)


class BackupsAPITestCase(test.TestCase):
    """Test Case for backups API."""

    def setUp(self):
        super(BackupsAPITestCase, self).setUp()
        self.volume_api = cinder.volume.API()
        self.backup_api = cinder.backup.API()
        self.context = context.get_admin_context()
        self.context.project_id = 'fake'
        self.context.user_id = 'fake'

    @staticmethod
    def _create_backup(volume_id=1,
                       display_name='test_backup',
                       display_description='this is a test backup',
                       container='volumebackups',
                       status='creating',
                       size=0, object_count=0, host='testhost'):
        """Create a backup object."""
        backup = {}
        backup['volume_id'] = volume_id
        backup['user_id'] = 'fake'
        backup['project_id'] = 'fake'
        backup['host'] = host
        backup['availability_zone'] = 'az1'
        backup['display_name'] = display_name
        backup['display_description'] = display_description
        backup['container'] = container
        backup['status'] = status
        backup['fail_reason'] = ''
        backup['size'] = size
        backup['object_count'] = object_count
        return db.backup_create(context.get_admin_context(), backup)['id']

    @staticmethod
    def _get_backup_attrib(backup_id, attrib_name):
        return db.backup_get(context.get_admin_context(),
                             backup_id)[attrib_name]

    def test_show_backup(self):
        volume_id = utils.create_volume(self.context, size=5,
                                        status='creating')['id']
        backup_id = self._create_backup(volume_id)
        LOG.debug('Created backup with id %s' % backup_id)
        req = webob.Request.blank('/v2/fake/backups/%s' %
                                  backup_id)
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 200)
        self.assertEqual(res_dict['backup']['availability_zone'], 'az1')
        self.assertEqual(res_dict['backup']['container'], 'volumebackups')
        self.assertEqual(res_dict['backup']['description'],
                         'this is a test backup')
        self.assertEqual(res_dict['backup']['name'], 'test_backup')
        self.assertEqual(res_dict['backup']['id'], backup_id)
        self.assertEqual(res_dict['backup']['object_count'], 0)
        self.assertEqual(res_dict['backup']['size'], 0)
        self.assertEqual(res_dict['backup']['status'], 'creating')
        self.assertEqual(res_dict['backup']['volume_id'], volume_id)

        db.backup_destroy(context.get_admin_context(), backup_id)
        db.volume_destroy(context.get_admin_context(), volume_id)

    def test_show_backup_xml_content_type(self):
        volume_id = utils.create_volume(self.context, size=5,
                                        status='creating')['id']
        backup_id = self._create_backup(volume_id)
        req = webob.Request.blank('/v2/fake/backups/%s' % backup_id)
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/xml'
        req.headers['Accept'] = 'application/xml'
        res = req.get_response(fakes.wsgi_app())
        self.assertEqual(res.status_int, 200)
        dom = minidom.parseString(res.body)
        backup = dom.getElementsByTagName('backup')
        name = backup.item(0).getAttribute('name')
        container_name = backup.item(0).getAttribute('container')
        self.assertEqual(container_name.strip(), "volumebackups")
        self.assertEqual(name.strip(), "test_backup")
        db.backup_destroy(context.get_admin_context(), backup_id)
        db.volume_destroy(context.get_admin_context(), volume_id)

    def test_show_backup_with_backup_NotFound(self):
        req = webob.Request.blank('/v2/fake/backups/9999')
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 404)
        self.assertEqual(res_dict['itemNotFound']['code'], 404)
        self.assertEqual(res_dict['itemNotFound']['message'],
                         'Backup 9999 could not be found.')

    def test_list_backups_json(self):
        backup_id1 = self._create_backup()
        backup_id2 = self._create_backup()
        backup_id3 = self._create_backup()

        req = webob.Request.blank('/v2/fake/backups')
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 200)
        self.assertEqual(len(res_dict['backups'][0]), 3)
        self.assertEqual(res_dict['backups'][0]['id'], backup_id1)
        self.assertEqual(res_dict['backups'][0]['name'], 'test_backup')
        self.assertEqual(len(res_dict['backups'][1]), 3)
        self.assertEqual(res_dict['backups'][1]['id'], backup_id2)
        self.assertEqual(res_dict['backups'][1]['name'], 'test_backup')
        self.assertEqual(len(res_dict['backups'][2]), 3)
        self.assertEqual(res_dict['backups'][2]['id'], backup_id3)
        self.assertEqual(res_dict['backups'][2]['name'], 'test_backup')

        db.backup_destroy(context.get_admin_context(), backup_id3)
        db.backup_destroy(context.get_admin_context(), backup_id2)
        db.backup_destroy(context.get_admin_context(), backup_id1)

    def test_list_backups_xml(self):
        backup_id1 = self._create_backup()
        backup_id2 = self._create_backup()
        backup_id3 = self._create_backup()

        req = webob.Request.blank('/v2/fake/backups')
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/xml'
        req.headers['Accept'] = 'application/xml'
        res = req.get_response(fakes.wsgi_app())

        self.assertEqual(res.status_int, 200)
        dom = minidom.parseString(res.body)
        backup_list = dom.getElementsByTagName('backup')

        self.assertEqual(backup_list.item(0).attributes.length, 2)
        self.assertEqual(backup_list.item(0).getAttribute('id'),
                         backup_id1)
        self.assertEqual(backup_list.item(1).attributes.length, 2)
        self.assertEqual(backup_list.item(1).getAttribute('id'),
                         backup_id2)
        self.assertEqual(backup_list.item(2).attributes.length, 2)
        self.assertEqual(backup_list.item(2).getAttribute('id'),
                         backup_id3)

        db.backup_destroy(context.get_admin_context(), backup_id3)
        db.backup_destroy(context.get_admin_context(), backup_id2)
        db.backup_destroy(context.get_admin_context(), backup_id1)

    def test_list_backups_detail_json(self):
        backup_id1 = self._create_backup()
        backup_id2 = self._create_backup()
        backup_id3 = self._create_backup()

        req = webob.Request.blank('/v2/fake/backups/detail')
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/json'
        req.headers['Accept'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 200)
        self.assertEqual(len(res_dict['backups'][0]), 12)
        self.assertEqual(res_dict['backups'][0]['availability_zone'], 'az1')
        self.assertEqual(res_dict['backups'][0]['container'],
                         'volumebackups')
        self.assertEqual(res_dict['backups'][0]['description'],
                         'this is a test backup')
        self.assertEqual(res_dict['backups'][0]['name'],
                         'test_backup')
        self.assertEqual(res_dict['backups'][0]['id'], backup_id1)
        self.assertEqual(res_dict['backups'][0]['object_count'], 0)
        self.assertEqual(res_dict['backups'][0]['size'], 0)
        self.assertEqual(res_dict['backups'][0]['status'], 'creating')
        self.assertEqual(res_dict['backups'][0]['volume_id'], '1')

        self.assertEqual(len(res_dict['backups'][1]), 12)
        self.assertEqual(res_dict['backups'][1]['availability_zone'], 'az1')
        self.assertEqual(res_dict['backups'][1]['container'],
                         'volumebackups')
        self.assertEqual(res_dict['backups'][1]['description'],
                         'this is a test backup')
        self.assertEqual(res_dict['backups'][1]['name'],
                         'test_backup')
        self.assertEqual(res_dict['backups'][1]['id'], backup_id2)
        self.assertEqual(res_dict['backups'][1]['object_count'], 0)
        self.assertEqual(res_dict['backups'][1]['size'], 0)
        self.assertEqual(res_dict['backups'][1]['status'], 'creating')
        self.assertEqual(res_dict['backups'][1]['volume_id'], '1')

        self.assertEqual(len(res_dict['backups'][2]), 12)
        self.assertEqual(res_dict['backups'][2]['availability_zone'], 'az1')
        self.assertEqual(res_dict['backups'][2]['container'],
                         'volumebackups')
        self.assertEqual(res_dict['backups'][2]['description'],
                         'this is a test backup')
        self.assertEqual(res_dict['backups'][2]['name'],
                         'test_backup')
        self.assertEqual(res_dict['backups'][2]['id'], backup_id3)
        self.assertEqual(res_dict['backups'][2]['object_count'], 0)
        self.assertEqual(res_dict['backups'][2]['size'], 0)
        self.assertEqual(res_dict['backups'][2]['status'], 'creating')
        self.assertEqual(res_dict['backups'][2]['volume_id'], '1')

        db.backup_destroy(context.get_admin_context(), backup_id3)
        db.backup_destroy(context.get_admin_context(), backup_id2)
        db.backup_destroy(context.get_admin_context(), backup_id1)

    def test_list_backups_detail_using_filters(self):
        backup_id1 = self._create_backup(display_name='test2')
        backup_id2 = self._create_backup(status='available')
        backup_id3 = self._create_backup(volume_id=4321)

        req = webob.Request.blank('/v2/fake/backups/detail?name=test2')
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/json'
        req.headers['Accept'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(len(res_dict['backups']), 1)
        self.assertEqual(res.status_int, 200)
        self.assertEqual(res_dict['backups'][0]['id'], backup_id1)

        req = webob.Request.blank('/v2/fake/backups/detail?status=available')
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/json'
        req.headers['Accept'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(len(res_dict['backups']), 1)
        self.assertEqual(res.status_int, 200)
        self.assertEqual(res_dict['backups'][0]['id'], backup_id2)

        req = webob.Request.blank('/v2/fake/backups/detail?volume_id=4321')
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/json'
        req.headers['Accept'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(len(res_dict['backups']), 1)
        self.assertEqual(res.status_int, 200)
        self.assertEqual(res_dict['backups'][0]['id'], backup_id3)

        db.backup_destroy(context.get_admin_context(), backup_id3)
        db.backup_destroy(context.get_admin_context(), backup_id2)
        db.backup_destroy(context.get_admin_context(), backup_id1)

    def test_list_backups_detail_xml(self):
        backup_id1 = self._create_backup()
        backup_id2 = self._create_backup()
        backup_id3 = self._create_backup()

        req = webob.Request.blank('/v2/fake/backups/detail')
        req.method = 'GET'
        req.headers['Content-Type'] = 'application/xml'
        req.headers['Accept'] = 'application/xml'
        res = req.get_response(fakes.wsgi_app())

        self.assertEqual(res.status_int, 200)
        dom = minidom.parseString(res.body)
        backup_detail = dom.getElementsByTagName('backup')

        self.assertEqual(backup_detail.item(0).attributes.length, 11)
        self.assertEqual(
            backup_detail.item(0).getAttribute('availability_zone'), 'az1')
        self.assertEqual(
            backup_detail.item(0).getAttribute('container'), 'volumebackups')
        self.assertEqual(
            backup_detail.item(0).getAttribute('description'),
            'this is a test backup')
        self.assertEqual(
            backup_detail.item(0).getAttribute('name'), 'test_backup')
        self.assertEqual(
            backup_detail.item(0).getAttribute('id'), backup_id1)
        self.assertEqual(
            int(backup_detail.item(0).getAttribute('object_count')), 0)
        self.assertEqual(
            int(backup_detail.item(0).getAttribute('size')), 0)
        self.assertEqual(
            backup_detail.item(0).getAttribute('status'), 'creating')
        self.assertEqual(
            int(backup_detail.item(0).getAttribute('volume_id')), 1)

        self.assertEqual(backup_detail.item(1).attributes.length, 11)
        self.assertEqual(
            backup_detail.item(1).getAttribute('availability_zone'), 'az1')
        self.assertEqual(
            backup_detail.item(1).getAttribute('container'), 'volumebackups')
        self.assertEqual(
            backup_detail.item(1).getAttribute('description'),
            'this is a test backup')
        self.assertEqual(
            backup_detail.item(1).getAttribute('name'), 'test_backup')
        self.assertEqual(
            backup_detail.item(1).getAttribute('id'), backup_id2)
        self.assertEqual(
            int(backup_detail.item(1).getAttribute('object_count')), 0)
        self.assertEqual(
            int(backup_detail.item(1).getAttribute('size')), 0)
        self.assertEqual(
            backup_detail.item(1).getAttribute('status'), 'creating')
        self.assertEqual(
            int(backup_detail.item(1).getAttribute('volume_id')), 1)

        self.assertEqual(backup_detail.item(2).attributes.length, 11)
        self.assertEqual(
            backup_detail.item(2).getAttribute('availability_zone'), 'az1')
        self.assertEqual(
            backup_detail.item(2).getAttribute('container'), 'volumebackups')
        self.assertEqual(
            backup_detail.item(2).getAttribute('description'),
            'this is a test backup')
        self.assertEqual(
            backup_detail.item(2).getAttribute('name'), 'test_backup')
        self.assertEqual(
            backup_detail.item(2).getAttribute('id'), backup_id3)
        self.assertEqual(
            int(backup_detail.item(2).getAttribute('object_count')), 0)
        self.assertEqual(
            int(backup_detail.item(2).getAttribute('size')), 0)
        self.assertEqual(
            backup_detail.item(2).getAttribute('status'), 'creating')
        self.assertEqual(
            int(backup_detail.item(2).getAttribute('volume_id')), 1)

        db.backup_destroy(context.get_admin_context(), backup_id3)
        db.backup_destroy(context.get_admin_context(), backup_id2)
        db.backup_destroy(context.get_admin_context(), backup_id1)

    @mock.patch('cinder.db.service_get_all_by_topic')
    def test_create_backup_json(self, _mock_service_get_all_by_topic):
        _mock_service_get_all_by_topic.return_value = [
            {'availability_zone': "fake_az", 'host': 'test_host',
             'disabled': 0, 'updated_at': timeutils.utcnow()}]

        volume_id = utils.create_volume(self.context, size=5)['id']

        body = {"backup": {"display_name": "nightly001",
                           "display_description":
                           "Nightly Backup 03-Sep-2012",
                           "volume_id": volume_id,
                           "container": "nightlybackups",
                           }
                }
        req = webob.Request.blank('/v2/fake/backups')
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())

        res_dict = json.loads(res.body)
        LOG.info(res_dict)

        self.assertEqual(res.status_int, 202)
        self.assertIn('id', res_dict['backup'])
        self.assertTrue(_mock_service_get_all_by_topic.called)

        db.volume_destroy(context.get_admin_context(), volume_id)

    @mock.patch('cinder.db.service_get_all_by_topic')
    def test_create_backup_xml(self, _mock_service_get_all_by_topic):
        _mock_service_get_all_by_topic.return_value = [
            {'availability_zone': "fake_az", 'host': 'test_host',
             'disabled': 0, 'updated_at': timeutils.utcnow()}]

        volume_id = utils.create_volume(self.context, size=2)['id']

        req = webob.Request.blank('/v2/fake/backups')
        req.body = ('<backup display_name="backup-001" '
                    'display_description="Nightly Backup" '
                    'volume_id="%s" container="Container001"/>' % volume_id)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/xml'
        req.headers['Accept'] = 'application/xml'
        res = req.get_response(fakes.wsgi_app())

        self.assertEqual(res.status_int, 202)
        dom = minidom.parseString(res.body)
        backup = dom.getElementsByTagName('backup')
        self.assertTrue(backup.item(0).hasAttribute('id'))
        self.assertTrue(_mock_service_get_all_by_topic.called)

        db.volume_destroy(context.get_admin_context(), volume_id)

    def test_create_backup_with_no_body(self):
        # omit body from the request
        req = webob.Request.blank('/v2/fake/backups')
        req.body = json.dumps(None)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.headers['Accept'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'The server could not comply with the request since'
                         ' it is either malformed or otherwise incorrect.')

    def test_create_backup_with_body_KeyError(self):
        # omit volume_id from body
        body = {"backup": {"display_name": "nightly001",
                           "display_description":
                           "Nightly Backup 03-Sep-2012",
                           "container": "nightlybackups",
                           }
                }
        req = webob.Request.blank('/v2/fake/backups')
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'Incorrect request body format')

    def test_create_backup_with_VolumeNotFound(self):
        body = {"backup": {"display_name": "nightly001",
                           "display_description":
                           "Nightly Backup 03-Sep-2012",
                           "volume_id": 9999,
                           "container": "nightlybackups",
                           }
                }
        req = webob.Request.blank('/v2/fake/backups')
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 404)
        self.assertEqual(res_dict['itemNotFound']['code'], 404)
        self.assertEqual(res_dict['itemNotFound']['message'],
                         'Volume 9999 could not be found.')

    def test_create_backup_with_InvalidVolume(self):
        # need to create the volume referenced below first
        volume_id = utils.create_volume(self.context, size=5,
                                        status='restoring')['id']
        body = {"backup": {"display_name": "nightly001",
                           "display_description":
                           "Nightly Backup 03-Sep-2012",
                           "volume_id": volume_id,
                           "container": "nightlybackups",
                           }
                }
        req = webob.Request.blank('/v2/fake/backups')
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'Invalid volume: Volume to be backed up must'
                         ' be available')

    @mock.patch('cinder.db.service_get_all_by_topic')
    def test_create_backup_WithOUT_enabled_backup_service(
            self,
            _mock_service_get_all_by_topic):
        # need an enabled backup service available
        _mock_service_get_all_by_topic.return_value = []

        volume_id = utils.create_volume(self.context, size=2)['id']
        req = webob.Request.blank('/v2/fake/backups')
        body = {"backup": {"display_name": "nightly001",
                           "display_description":
                           "Nightly Backup 03-Sep-2012",
                           "volume_id": volume_id,
                           "container": "nightlybackups",
                           }
                }
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.headers['Accept'] = 'application/json'
        req.body = json.dumps(body)

        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)
        self.assertEqual(res.status_int, 500)
        self.assertEqual(res_dict['computeFault']['code'], 500)
        self.assertEqual(res_dict['computeFault']['message'],
                         'Service cinder-backup could not be found.')

        volume = self.volume_api.get(context.get_admin_context(), volume_id)
        self.assertEqual(volume['status'], 'available')

    @mock.patch('cinder.db.service_get_all_by_topic')
    def test_is_backup_service_enabled(self, _mock_service_get_all_by_topic):

        test_host = 'test_host'
        alt_host = 'strange_host'
        empty_service = []
        #service host not match with volume's host
        host_not_match = [{'availability_zone': "fake_az", 'host': alt_host,
                           'disabled': 0, 'updated_at': timeutils.utcnow()}]
        #service az not match with volume's az
        az_not_match = [{'availability_zone': "strange_az", 'host': test_host,
                         'disabled': 0, 'updated_at': timeutils.utcnow()}]
        #service disabled
        disabled_service = []

        #dead service that last reported at 20th century
        dead_service = [{'availability_zone': "fake_az", 'host': alt_host,
                         'disabled': 0, 'updated_at': '1989-04-16 02:55:44'}]

        #first service's host not match but second one works.
        multi_services = [{'availability_zone': "fake_az", 'host': alt_host,
                           'disabled': 0, 'updated_at': timeutils.utcnow()},
                          {'availability_zone': "fake_az", 'host': test_host,
                           'disabled': 0, 'updated_at': timeutils.utcnow()}]

        #Setup mock to run through the following service cases
        _mock_service_get_all_by_topic.side_effect = [empty_service,
                                                      host_not_match,
                                                      az_not_match,
                                                      disabled_service,
                                                      dead_service,
                                                      multi_services]

        volume_id = utils.create_volume(self.context, size=2,
                                        host=test_host)['id']
        volume = self.volume_api.get(context.get_admin_context(), volume_id)

        #test empty service
        self.assertEqual(self.backup_api._is_backup_service_enabled(volume,
                                                                    test_host),
                         False)

        #test host not match service
        self.assertEqual(self.backup_api._is_backup_service_enabled(volume,
                                                                    test_host),
                         False)

        #test az not match service
        self.assertEqual(self.backup_api._is_backup_service_enabled(volume,
                                                                    test_host),
                         False)

        #test disabled service
        self.assertEqual(self.backup_api._is_backup_service_enabled(volume,
                                                                    test_host),
                         False)

        #test dead service
        self.assertEqual(self.backup_api._is_backup_service_enabled(volume,
                                                                    test_host),
                         False)

        #test multi services and the last service matches
        self.assertEqual(self.backup_api._is_backup_service_enabled(volume,
                                                                    test_host),
                         True)

    def test_delete_backup_available(self):
        backup_id = self._create_backup(status='available')
        req = webob.Request.blank('/v2/fake/backups/%s' %
                                  backup_id)
        req.method = 'DELETE'
        req.headers['Content-Type'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())

        self.assertEqual(res.status_int, 202)
        self.assertEqual(self._get_backup_attrib(backup_id, 'status'),
                         'deleting')

        db.backup_destroy(context.get_admin_context(), backup_id)

    def test_delete_backup_error(self):
        backup_id = self._create_backup(status='error')
        req = webob.Request.blank('/v2/fake/backups/%s' %
                                  backup_id)
        req.method = 'DELETE'
        req.headers['Content-Type'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())

        self.assertEqual(res.status_int, 202)
        self.assertEqual(self._get_backup_attrib(backup_id, 'status'),
                         'deleting')

        db.backup_destroy(context.get_admin_context(), backup_id)

    def test_delete_backup_with_backup_NotFound(self):
        req = webob.Request.blank('/v2/fake/backups/9999')
        req.method = 'DELETE'
        req.headers['Content-Type'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 404)
        self.assertEqual(res_dict['itemNotFound']['code'], 404)
        self.assertEqual(res_dict['itemNotFound']['message'],
                         'Backup 9999 could not be found.')

    def test_delete_backup_with_InvalidBackup(self):
        backup_id = self._create_backup()
        req = webob.Request.blank('/v2/fake/backups/%s' %
                                  backup_id)
        req.method = 'DELETE'
        req.headers['Content-Type'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'Invalid backup: Backup status must be '
                         'available or error')

        db.backup_destroy(context.get_admin_context(), backup_id)

    def test_restore_backup_volume_id_specified_json(self):
        backup_id = self._create_backup(status='available')
        # need to create the volume referenced below first
        volume_id = utils.create_volume(self.context, size=5)['id']

        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 202)
        self.assertEqual(res_dict['restore']['backup_id'], backup_id)
        self.assertEqual(res_dict['restore']['volume_id'], volume_id)

    def test_restore_backup_volume_id_specified_xml(self):
        backup_id = self._create_backup(status='available')
        volume_id = utils.create_volume(self.context, size=2)['id']

        req = webob.Request.blank('/v2/fake/backups/%s/restore' % backup_id)
        req.body = '<restore volume_id="%s"/>' % volume_id
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/xml'
        req.headers['Accept'] = 'application/xml'
        res = req.get_response(fakes.wsgi_app())

        self.assertEqual(res.status_int, 202)
        dom = minidom.parseString(res.body)
        restore = dom.getElementsByTagName('restore')
        self.assertEqual(restore.item(0).getAttribute('backup_id'),
                         backup_id)
        self.assertEqual(restore.item(0).getAttribute('volume_id'), volume_id)

        db.backup_destroy(context.get_admin_context(), backup_id)
        db.volume_destroy(context.get_admin_context(), volume_id)

    def test_restore_backup_with_no_body(self):
        # omit body from the request
        backup_id = self._create_backup(status='available')

        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)
        req.body = json.dumps(None)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.headers['Accept'] = 'application/json'
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'Incorrect request body format')

        db.backup_destroy(context.get_admin_context(), backup_id)

    def test_restore_backup_with_body_KeyError(self):
        # omit restore from body
        backup_id = self._create_backup(status='available')

        req = webob.Request.blank('/v2/fake/backups/%s/restore' % backup_id)
        body = {"": {}}
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.headers['Accept'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())

        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'Incorrect request body format')

    @mock.patch('cinder.volume.API.create')
    def test_restore_backup_volume_id_unspecified(self,
                                                  _mock_volume_api_create):

        # intercept volume creation to ensure created volume
        # has status of available
        def fake_volume_api_create(context, size, name, description):
            volume_id = utils.create_volume(self.context, size=size)['id']
            return db.volume_get(context, volume_id)

        _mock_volume_api_create.side_effect = fake_volume_api_create

        backup_id = self._create_backup(size=5, status='available')

        body = {"restore": {}}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 202)
        self.assertEqual(res_dict['restore']['backup_id'], backup_id)

    @mock.patch('cinder.backup.API.restore')
    def test_restore_backup_with_InvalidInput(self,
                                              _mock_volume_api_restore):

        msg = _("Invalid input")
        _mock_volume_api_restore.side_effect = \
            exception.InvalidInput(reason=msg)

        backup_id = self._create_backup(status='available')
        # need to create the volume referenced below first
        volume_id = utils.create_volume(self.context, size=0)['id']
        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)

        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'Invalid input received: Invalid input')

    def test_restore_backup_with_InvalidVolume(self):
        backup_id = self._create_backup(status='available')
        # need to create the volume referenced below first
        volume_id = utils.create_volume(self.context, size=5,
                                        status='attaching')['id']

        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'Invalid volume: Volume to be restored to must '
                         'be available')

        db.volume_destroy(context.get_admin_context(), volume_id)
        db.backup_destroy(context.get_admin_context(), backup_id)

    def test_restore_backup_with_InvalidBackup(self):
        backup_id = self._create_backup(status='restoring')
        # need to create the volume referenced below first
        volume_id = utils.create_volume(self.context, size=5)['id']

        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'Invalid backup: Backup status must be available')

        db.volume_destroy(context.get_admin_context(), volume_id)
        db.backup_destroy(context.get_admin_context(), backup_id)

    def test_restore_backup_with_BackupNotFound(self):
        # need to create the volume referenced below first
        volume_id = utils.create_volume(self.context, size=5)['id']

        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/9999/restore')
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 404)
        self.assertEqual(res_dict['itemNotFound']['code'], 404)
        self.assertEqual(res_dict['itemNotFound']['message'],
                         'Backup 9999 could not be found.')

        db.volume_destroy(context.get_admin_context(), volume_id)

    def test_restore_backup_with_VolumeNotFound(self):
        backup_id = self._create_backup(status='available')

        body = {"restore": {"volume_id": "9999", }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 404)
        self.assertEqual(res_dict['itemNotFound']['code'], 404)
        self.assertEqual(res_dict['itemNotFound']['message'],
                         'Volume 9999 could not be found.')

        db.backup_destroy(context.get_admin_context(), backup_id)

    @mock.patch('cinder.backup.API.restore')
    def test_restore_backup_with_VolumeSizeExceedsAvailableQuota(
            self,
            _mock_backup_restore):

        _mock_backup_restore.side_effect = \
            exception.VolumeSizeExceedsAvailableQuota(requested='2',
                                                      consumed='2',
                                                      quota='3')

        backup_id = self._create_backup(status='available')
        # need to create the volume referenced below first
        volume_id = utils.create_volume(self.context, size=5)['id']

        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)

        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 413)
        self.assertEqual(res_dict['overLimit']['code'], 413)
        self.assertEqual(res_dict['overLimit']['message'],
                         'Requested volume or snapshot exceeds allowed '
                         'Gigabytes quota. Requested 2G, quota is 3G and '
                         '2G has been consumed.')

    @mock.patch('cinder.backup.API.restore')
    def test_restore_backup_with_VolumeLimitExceeded(self,
                                                     _mock_backup_restore):

        _mock_backup_restore.side_effect = \
            exception.VolumeLimitExceeded(allowed=1)

        backup_id = self._create_backup(status='available')
        # need to create the volume referenced below first
        volume_id = utils.create_volume(self.context, size=5)['id']

        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)

        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 413)
        self.assertEqual(res_dict['overLimit']['code'], 413)
        self.assertEqual(res_dict['overLimit']['message'],
                         'Maximum number of volumes allowed (1) exceeded')

    def test_restore_backup_to_undersized_volume(self):
        backup_size = 10
        backup_id = self._create_backup(status='available', size=backup_size)
        # need to create the volume referenced below first
        volume_size = 5
        volume_id = utils.create_volume(self.context, size=volume_size)['id']

        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 400)
        self.assertEqual(res_dict['badRequest']['code'], 400)
        self.assertEqual(res_dict['badRequest']['message'],
                         'Invalid volume: volume size %d is too '
                         'small to restore backup of size %d.'
                         % (volume_size, backup_size))

        db.volume_destroy(context.get_admin_context(), volume_id)
        db.backup_destroy(context.get_admin_context(), backup_id)

    def test_restore_backup_to_oversized_volume(self):
        backup_id = self._create_backup(status='available', size=10)
        # need to create the volume referenced below first
        volume_id = utils.create_volume(self.context, size=15)['id']

        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 202)
        self.assertEqual(res_dict['restore']['backup_id'], backup_id)
        self.assertEqual(res_dict['restore']['volume_id'], volume_id)

        db.volume_destroy(context.get_admin_context(), volume_id)
        db.backup_destroy(context.get_admin_context(), backup_id)

    @mock.patch('cinder.backup.rpcapi.BackupAPI.restore_backup')
    def test_restore_backup_with_different_host(self, mock_restore_backup):
        backup_id = self._create_backup(status='available', size=10,
                                        host='HostA@BackendB#PoolA')
        volume_id = utils.create_volume(self.context, size=10,
                                        host='HostB@BackendB#PoolB')['id']

        body = {"restore": {"volume_id": volume_id, }}
        req = webob.Request.blank('/v2/fake/backups/%s/restore' %
                                  backup_id)
        req.method = 'POST'
        req.headers['Content-Type'] = 'application/json'
        req.body = json.dumps(body)
        res = req.get_response(fakes.wsgi_app())
        res_dict = json.loads(res.body)

        self.assertEqual(res.status_int, 202)
        self.assertEqual(res_dict['restore']['backup_id'], backup_id)
        self.assertEqual(res_dict['restore']['volume_id'], volume_id)
        mock_restore_backup.assert_called_once_with(mock.ANY,
                                                    'HostB',
                                                    backup_id,
                                                    volume_id)

        db.volume_destroy(context.get_admin_context(), volume_id)
        db.backup_destroy(context.get_admin_context(), backup_id)

    def test_export_record_as_non_admin(self):
        backup_id = self._create_backup(status='available', size=10)
        req = webob.Request.blank('/v2/fake/backups/%s/export_record' %
{'fraction_non_alphanumeric': 0.12579617834394904, 'fraction_numerical': 0.012332294348827754, 'mean_word_length': 2.350701933628486, 'pattern_counts': {'":': 94, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 32}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 117, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3419722', 'n_tokens_mistral': 26056, 'n_tokens_neox': 25059, 'n_words': 3912}