'Test volume can be extended at API level.'

@mock.patch.object(QUOTAS, 'limit_check')
@mock.patch.object(QUOTAS, 'reserve')
def test_extend_volume(self, reserve, limit_check):

    volume = tests_utils.create_volume(self.context, size=2, status='in-use', host=CONF.host)
    volume_api = cinder.volume.api.API()
    self.assertRaises(exception.InvalidVolume, volume_api._extend, self.context, volume, 3)
    db.volume_update(self.context, volume.id, {'status': 'available'})
    self.assertRaises(exception.InvalidInput, volume_api._extend, self.context, volume, 1)
    self.assertRaises(exception.InvalidInput, volume_api._extend, self.context, volume, 2)
    reserve.return_value = ['RESERVATION']
    volume_api._extend(self.context, volume, 3)
    volume.refresh()
    self.assertEqual('extending', volume.status)
    reserve.assert_called_once_with(self.context, gigabytes=1, project_id=volume.project_id)
    db.volume_update(self.context, volume.id, {'status': 'available'})
    reserve.side_effect = exception.OverQuota(overs=['gigabytes'], quotas={'gigabytes': 20}, usages={'gigabytes': {'reserved': 5, 'in_use': 15}})
    self.assertRaises(exception.VolumeSizeExceedsAvailableQuota, volume_api._extend, self.context, volume, 3)
    db.volume_update(self.context, volume.id, {'status': 'available'})
    limit_check.side_effect = exception.OverQuota(overs=['per_volume_gigabytes'], quotas={'per_volume_gigabytes': 2})
    self.assertRaises(exception.VolumeSizeExceedsLimit, volume_api._extend, self.context, volume, 3)
    limit_check.side_effect = None
    reserve.side_effect = None
    db.volume_update(self.context, volume.id, {'status': 'available'})
    volume_api.scheduler_rpcapi = mock.MagicMock()
    volume_api.scheduler_rpcapi.extend_volume = mock.MagicMock()
    volume_api._extend(self.context, volume, 3)
    request_spec = {'volume_properties': volume, 'volume_type': {}, 'volume_id': volume.id}
    volume_api.scheduler_rpcapi.extend_volume.assert_called_once_with(self.context, volume, 3, ['RESERVATION'], request_spec)
    self.volume.delete_volume(self.context, volume)
