Merge intree freezer-api tempest plugin into freezer tempest plugin

* It merges the freezer-api tempest plugin into freezer tempest
  plugin by moving freezer and freezer-api tempest tests in
  freezer_tempest_plugin/tests/freezer and
  freezer_tempest_plugin/tests/freezer_api.

* clients.py is moved under main root folder.

Change-Id: I66cc2507b0bbd9dda9d6279f9b8d74c546d1b0a6
This commit is contained in:
Chandan Kumar 2017-12-10 13:36:29 +05:30
parent 65bdf3bcf9
commit 84b0c74205
23 changed files with 1296 additions and 7 deletions

View File

@ -0,0 +1,24 @@
# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP
#
# 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.
from tempest import clients
from freezer_tempest_plugin.services import freezer_api_client
class Manager(clients.Manager):
def __init__(self, credentials=None):
super(Manager, self).__init__(credentials)
self.freezer_api_client = freezer_api_client.FreezerApiClient(
self.auth_provider)

View File

@ -19,3 +19,32 @@ service_option = cfg.BoolOpt('freezer',
default=True,
help="Whether or not freezer is expected to be "
"available")
ServiceAvailableGroup = [
cfg.BoolOpt("freezer-api",
default=True,
help="Whether or not Freezer API is expected to be available"),
]
service_available_group = cfg.OptGroup(name="service_available",
title="Available OpenStack Services")
freezer_api_group = cfg.OptGroup(name="backup",
title="Freezer API Service Options")
FreezerApiGroup = [
cfg.StrOpt("region",
default="",
help="The freezer api region name to use. If empty, the value "
"of identity.region is used instead. If no such region "
"is found in the service catalog, the first found one is "
"used."),
cfg.StrOpt("catalog_type",
default="backup",
help="Catalog type of the freezer-api service."),
cfg.StrOpt('endpoint_type',
default='publicURL',
choices=['public', 'admin', 'internal',
'publicURL', 'adminURL', 'internalURL'],
help="The endpoint type to use for the freezer-api service.")
]

View File

@ -15,6 +15,7 @@
import os
from tempest import config as tempest_config
from tempest.test_discover import plugins
from freezer_tempest_plugin import config as freezer_config
@ -29,8 +30,16 @@ class FreezerTempestPlugin(plugins.TempestPlugin):
return full_test_dir, base_path
def register_opts(self, conf):
tempest_config.register_opt_group(
conf, freezer_config.service_available_group,
freezer_config.ServiceAvailableGroup)
tempest_config.register_opt_group(
conf, freezer_config.freezer_api_group,
freezer_config.FreezerApiGroup)
conf.register_opt(freezer_config.service_option,
group='service_available')
def get_opt_lists(self):
return [('service_available', [freezer_config.service_option])]
return [('service_available', [freezer_config.service_option]),
(freezer_config.freezer_api_group.name,
freezer_config.FreezerApiGroup)]

View File

@ -0,0 +1,184 @@
# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP
#
# 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 urllib
from oslo_serialization import jsonutils as json
from tempest import config
from tempest.lib.common import rest_client
CONF = config.CONF
class FreezerApiClient(rest_client.RestClient):
def __init__(self, auth_provider):
super(FreezerApiClient, self).__init__(
auth_provider,
CONF.backup.catalog_type,
CONF.backup.region or CONF.identity.region,
endpoint_type=CONF.backup.endpoint_type
)
def get_version(self):
resp, response_body = self.get('/')
return resp, response_body
def get_version_v1(self):
resp, response_body = self.get('/v1')
return resp, response_body
def get_version_v2(self):
resp, response_body = self.get('/v2')
return resp, response_body
def get_backups(self, backup_id=None, **params):
if backup_id is None:
uri = '/v1/backups'
if params:
uri += '?%s' % urllib.urlencode(params)
else:
uri = '/v1/backups/' + backup_id
resp, response_body = self.get(uri)
return resp, json.loads(response_body)
def post_backups(self, metadata, backup_id=None):
uri = '/v1/backups'
if backup_id is not None:
uri += '/' + backup_id
request_body = json.dumps(metadata)
resp, response_body = self.post(uri, request_body)
return resp, json.loads(response_body)
def delete_backups(self, backup_id):
uri = '/v1/backups/' + backup_id
resp, response_body = self.delete(uri)
return resp, response_body
def get_clients(self, client_id=None, **params):
if client_id is None:
uri = '/v1/clients'
if params:
uri += '?%s' % urllib.urlencode(params)
else:
uri = 'v1/clients/' + client_id
resp, response_body = self.get(uri)
return resp, response_body
def post_clients(self, client):
request_body = json.dumps(client)
resp, response_body = self.post('/v1/clients', request_body)
return resp, json.loads(response_body)
def delete_clients(self, client_id):
uri = '/v1/clients/' + client_id
resp, response_body = self.delete(uri)
return resp, response_body
def get_jobs(self, job_id=None, **params):
if job_id is None:
uri = '/v1/jobs'
if params:
uri += '?%s' % urllib.urlencode(params)
else:
uri = '/v1/jobs/' + job_id
resp, response_body = self.get(uri)
return resp, response_body
def post_jobs(self, job):
request_body = json.dumps(job)
resp, response_body = self.post('/v1/jobs', request_body)
return resp, json.loads(response_body)
def delete_jobs(self, job_id):
uri = '/v1/jobs/' + job_id
resp, response_body = self.delete(uri)
return resp, response_body
def get_actions(self, action_id=None, **params):
if action_id is None:
uri = '/v1/actions'
if params:
uri += '?%s' % urllib.urlencode(params)
else:
uri = '/v1/actions/' + action_id
resp, response_body = self.get(uri)
return resp, response_body
def post_actions(self, action, action_id=None):
request_body = json.dumps(action)
if action_id is None:
uri = '/v1/actions'
else:
uri = '/v1/actions/' + action_id
resp, response_body = self.post(uri, request_body)
return resp, json.loads(response_body)
def patch_actions(self, action, action_id):
request_body = json.dumps(action)
uri = '/v1/actions/' + action_id
resp, response_body = self.patch(uri, request_body)
return resp, json.loads(response_body)
def delete_actions(self, id):
uri = '/v1/actions/' + id
resp, response_body = self.delete(uri)
return resp, response_body
def get_sessions(self, session_id=None, **params):
if session_id is None:
uri = '/v1/sessions'
if params:
uri += '?%s' % urllib.urlencode(params)
else:
uri = 'v1/sessions/' + session_id
resp, response_body = self.get(uri)
return resp, response_body
def post_sessions(self, session):
request_body = json.dumps(session)
resp, response_body = self.post('/v1/sessions', request_body)
return resp, json.loads(response_body)
def delete_sessions(self, session_id):
uri = '/v1/sessions/' + session_id
resp, response_body = self.delete(uri)
return resp, response_body

View File

@ -19,7 +19,7 @@ import subprocess
from tempest.lib import decorators
from freezer_tempest_plugin import common
from freezer_tempest_plugin.tests.api import base
from freezer_tempest_plugin.tests.freezer.api import base
class TestFreezerCompressGzip(base.BaseFreezerTest):

View File

@ -18,7 +18,7 @@ import shutil
from oslo_utils import uuidutils
from tempest.lib import decorators
from freezer_tempest_plugin.tests.api import base
from freezer_tempest_plugin.tests.freezer.api import base
class TestFreezerFSBackup(base.BaseFreezerTest):

View File

@ -16,7 +16,7 @@ import subprocess
from tempest.lib import decorators
from freezer_tempest_plugin import common
from freezer_tempest_plugin.tests.api import base
from freezer_tempest_plugin.tests.freezer.api import base
class TestFreezerMetadataChecksum(base.BaseFreezerTest):

View File

@ -18,7 +18,7 @@ import shutil
from oslo_utils import uuidutils
from tempest.lib import decorators
from freezer_tempest_plugin.tests.api import base
from freezer_tempest_plugin.tests.freezer.api import base
class TestFreezerSwiftBackup(base.BaseFreezerTest):

View File

@ -14,7 +14,7 @@
from tempest.lib import decorators
from freezer_tempest_plugin.tests.api import base
from freezer_tempest_plugin.tests.freezer.api import base
class TestFreezerTestsRunning(base.BaseFreezerTest):

View File

@ -22,7 +22,7 @@ import time
from tempest.lib.cli import base as cli_base
from tempest.lib.cli import output_parser
from freezer_tempest_plugin.tests.api import base
from freezer_tempest_plugin.tests.freezer.api import base
JOB_TABLE_RESULT_COLUMN = 3

View File

@ -0,0 +1,33 @@
# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP
#
# 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.
from tempest import config
from tempest import test
from freezer_tempest_plugin import clients
CONF = config.CONF
class BaseFreezerApiTest(test.BaseTestCase):
"""Base test case class for all Freezer API tests."""
credentials = ['primary']
client_manager = clients.Manager
@classmethod
def setup_clients(cls):
super(BaseFreezerApiTest, cls).setup_clients()
cls.freezer_api_client = cls.os_primary.freezer_api_client

View File

@ -0,0 +1,219 @@
# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP
#
# 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 json
from tempest.lib import decorators
from tempest.lib import exceptions
from freezer_tempest_plugin.tests.freezer_api.api import base
class TestFreezerApiActions(base.BaseFreezerApiTest):
@classmethod
def resource_setup(cls):
super(TestFreezerApiActions, cls).resource_setup()
@classmethod
def resource_cleanup(cls):
super(TestFreezerApiActions, cls).resource_cleanup()
@decorators.attr(type="gate")
def test_api_actions(self):
resp, response_body = self.freezer_api_client.get_actions()
self.assertEqual(200, resp.status)
resp_body_json = json.loads(response_body)
self.assertIn('actions', resp_body_json)
actions = resp_body_json['actions']
self.assertEqual(actions, [])
@decorators.attr(type="gate")
def test_api_actions_get_limit(self):
# limits > 0 should return successfully
for valid_limit in [2, 1]:
resp, body = self.freezer_api_client.get_actions(limit=valid_limit)
self.assertEqual(200, resp.status)
# limits <= 0 should raise a bad request error
for bad_limit in [0, -1, -2]:
self.assertRaises(exceptions.BadRequest,
self.freezer_api_client.get_actions,
limit=bad_limit)
@decorators.attr(type="gate")
def test_api_actions_get_offset(self):
# offsets >= 0 should return 200
for valid_offset in [1, 0]:
resp, body = self.freezer_api_client.get_actions(
offset=valid_offset)
self.assertEqual(200, resp.status)
# offsets < 0 should return 400
for bad_offset in [-1, -2]:
self.assertRaises(exceptions.BadRequest,
self.freezer_api_client.get_actions,
offset=bad_offset)
@decorators.attr(type="gate")
def test_api_actions_post(self):
action = {
'freezer_action':
{
'actions': 'backup',
'mode': 'fs',
'src_file': '/dev/null',
'backup_name': 'test freezer api actions',
'container': 'test_freezer_api_actions_container',
'max_backup_level': 1,
'always_backup_level': 0,
'no_incremental': True,
'encrypt_pass_file': '/dev/null',
'log_file': '/dev/null',
'hostname': False,
'max_cpu_priority': False
}
}
# Create the action with POST
resp, response_body = self.freezer_api_client.post_actions(action)
self.assertEqual(201, resp.status)
self.assertIn('action_id', response_body)
action_id = response_body['action_id']
# Check that the action has the correct values
resp, response_body = self.freezer_api_client.get_actions(action_id)
self.assertEqual(200, resp.status)
resp_body_json = json.loads(response_body)
freezer_action_json = resp_body_json['freezer_action']
self.assertIn('backup_name', freezer_action_json)
backup_name = freezer_action_json['backup_name']
self.assertEqual('test freezer api actions', backup_name)
self.assertIn('container', freezer_action_json)
container = freezer_action_json['container']
self.assertEqual('test_freezer_api_actions_container', container)
self.assertIn('no_incremental', freezer_action_json)
no_incremental = freezer_action_json['no_incremental']
self.assertEqual(True, no_incremental)
self.assertIn('max_backup_level', freezer_action_json)
max_backup_level = freezer_action_json['max_backup_level']
self.assertEqual(1, max_backup_level)
self.assertIn('hostname', freezer_action_json)
hostname = freezer_action_json['hostname']
self.assertEqual(False, hostname)
self.assertIn('_version', response_body)
_version = resp_body_json['_version']
self.assertEqual(1, _version)
self.assertIn('actions', freezer_action_json)
actions = freezer_action_json['actions']
self.assertEqual('backup', actions)
self.assertIn('src_file', freezer_action_json)
src_file = freezer_action_json['src_file']
self.assertEqual('/dev/null', src_file)
self.assertIn('always_backup_level', freezer_action_json)
always_backup_level = freezer_action_json['always_backup_level']
self.assertEqual(0, always_backup_level)
self.assertIn('mode', freezer_action_json)
mode = freezer_action_json['mode']
self.assertEqual('fs', mode)
self.assertIn('encrypt_pass_file', freezer_action_json)
encrypt_pass_file = freezer_action_json['encrypt_pass_file']
self.assertEqual('/dev/null', encrypt_pass_file)
self.assertIn('max_cpu_priority', freezer_action_json)
max_cpu_priority = freezer_action_json['max_cpu_priority']
self.assertEqual(False, max_cpu_priority)
self.assertIn('user_id', response_body)
self.assertIn('log_file', freezer_action_json)
log_file = freezer_action_json['log_file']
self.assertEqual('/dev/null', log_file)
self.assertIn('action_id', response_body)
action_id_in_resp_body = resp_body_json['action_id']
self.assertEqual(action_id, action_id_in_resp_body)
# Update the action backup_name with POST
action['freezer_action']['backup_name'] = \
'test freezer api actions update with post'
resp, response_body = self.freezer_api_client.post_actions(
action, action_id)
self.assertEqual(201, resp.status)
self.assertIn('version', response_body)
version = response_body['version']
self.assertEqual(2, version)
self.assertIn('action_id', response_body)
action_id_in_resp_body = response_body['action_id']
self.assertEqual(action_id, action_id_in_resp_body)
resp, response_body = self.freezer_api_client.get_actions(action_id)
self.assertEqual(200, resp.status)
resp_body_json = json.loads(response_body)
freezer_action_json = resp_body_json['freezer_action']
self.assertIn('backup_name', freezer_action_json)
backup_name = freezer_action_json['backup_name']
self.assertEqual('test freezer api actions update with post',
backup_name)
# Update the action backup_name with PATCH
action['freezer_action']['backup_name'] = \
'test freezer api actions update with patch'
resp, response_body = self.freezer_api_client.patch_actions(
action, action_id)
self.assertEqual(200, resp.status)
self.assertIn('version', response_body)
version = response_body['version']
self.assertEqual(3, version)
self.assertIn('action_id', response_body)
action_id_in_resp_body = response_body['action_id']
self.assertEqual(action_id, action_id_in_resp_body)
resp, response_body = self.freezer_api_client.get_actions(action_id)
self.assertEqual(200, resp.status)
resp_body_json = json.loads(response_body)
freezer_action_json = resp_body_json['freezer_action']
self.assertIn('backup_name', freezer_action_json)
backup_name = freezer_action_json['backup_name']
self.assertEqual('test freezer api actions update with patch',
backup_name)
# Delete the action
resp, response_body = self.freezer_api_client.delete_actions(
action_id)
self.assertEqual(204, resp.status)

View File

@ -0,0 +1,300 @@
# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP
#
# 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 json
import tempest
from tempest.lib import decorators
from freezer_tempest_plugin.tests.freezer_api.api import base
class TestFreezerApiBackups(base.BaseFreezerApiTest):
credentials = ['primary', 'alt']
@decorators.attr(type="gate")
def test_api_backups_list(self):
for i in range(1, 4):
self._create_temporary_backup(
self._build_metadata("test_freezer_backups_" + str(i)))
resp, response_body = self.freezer_api_client.get_backups()
self.assertEqual(200, resp.status)
self.assertIn('backups', response_body)
backups = response_body['backups']
self.assertEqual(3, len(backups))
backup_names = [b['backup_metadata']['backup_name'] for b in backups]
for i in range(1, 4):
self.assertIn("test_freezer_backups_" + str(i), backup_names)
@decorators.attr(type="gate")
def test_api_backups_list_other_users_backups(self):
# Test if it is not possible to list backups
# from a different user
self._create_temporary_backup(
self._build_metadata("test_freezer_backups"))
# Switching to alt_user here
resp, response_body = self.os_alt.freezer_api_client.get_backups()
self.assertEqual(200, resp.status)
self.assertEmpty(response_body['backups'])
@decorators.attr(type="gate")
def test_api_backups_list_empty(self):
resp, response_body = self.freezer_api_client.get_backups()
self.assertEqual(200, resp.status)
self.assertEmpty(response_body['backups'])
@decorators.attr(type="gate")
def test_api_backups_list_limit(self):
for i in range(1, 9):
self._create_temporary_backup(
self._build_metadata("test_freezer_backups_" + str(i)))
resp, response_body = self.freezer_api_client.get_backups(limit=5)
self.assertEqual(200, resp.status)
self.assertIn('backups', response_body)
backups = response_body['backups']
self.assertEqual(5, len(backups))
# limits <= 0 should return an error (bad request)
for bad_limit in [0, -1, -2]:
self.assertRaises(tempest.lib.exceptions.BadRequest,
self.freezer_api_client.get_actions,
limit=bad_limit)
@decorators.attr(type="gate")
def test_api_backups_list_offset(self):
for i in range(1, 9):
self._create_temporary_backup(
self._build_metadata("test_freezer_backups_" + str(i)))
# valid offsets should return the correct number of entries
resp, response_body = self.freezer_api_client.get_backups(offset=0)
self.assertEqual(200, resp.status)
self.assertEqual(8, len(response_body['backups']))
resp, response_body = self.freezer_api_client.get_backups(offset=5)
self.assertEqual(200, resp.status)
self.assertEqual(3, len(response_body['backups']))
resp, response_body = self.freezer_api_client.get_backups(offset=8)
self.assertEqual(200, resp.status)
self.assertEqual(0, len(response_body['backups']))
# an offset greater than the number of entries should successfully
# return no entries
resp, response_body = self.freezer_api_client.get_backups(offset=10)
self.assertEqual(200, resp.status)
self.assertEqual(0, len(response_body['backups']))
# negative offsets should raise an error
self.assertRaises(tempest.lib.exceptions.BadRequest,
self.freezer_api_client.get_backups, offset=-1)
self.assertRaises(tempest.lib.exceptions.BadRequest,
self.freezer_api_client.get_backups, offset=-2)
@decorators.attr(type="gate")
def test_api_backups_list_limit_offset(self):
""" Test pagination by grabbing the backups in two steps and
comparing to the list of all backups.
"""
for i in range(1, 9):
self._create_temporary_backup(
self._build_metadata("test_freezer_backups_" + str(i)))
resp, response_body = self.freezer_api_client.get_backups(limit=5)
self.assertEqual(200, resp.status)
self.assertIn('backups', response_body)
first_5_backups = response_body['backups']
self.assertEqual(5, len(first_5_backups))
resp, response_body = self.freezer_api_client.get_backups(limit=3,
offset=5)
second_3_backups = response_body['backups']
self.assertEqual(3, len(second_3_backups))
resp, response_body = self.freezer_api_client.get_backups()
all_backups = response_body['backups']
self.assertEqual(len(all_backups),
len(first_5_backups + second_3_backups))
self.assertEqual(all_backups, first_5_backups + second_3_backups)
@decorators.attr(type="gate")
def test_api_backups_post(self):
metadata = self._build_metadata("test_freezer_backups")
backup_id = self._create_temporary_backup(metadata)
resp, response_body = self._workaround_get_backup(backup_id)
expected = self._build_expected_data(backup_id, metadata)
# backup_id is generated automatically, we can't know it
del(response_body['backup_id'])
self.assertEqual(200, resp.status)
self.assertEqual(expected, response_body)
@decorators.attr(type="gate")
def test_api_backups_post_without_content_type(self):
""" Test the backup endpoint without content-type=application/json.
It's expected to work regardless of whether content-type is set or not.
"""
metadata = self._build_metadata("test_freezer_backups")
uri = '/v1/backups'
request_body = json.dumps(metadata)
# Passing in an empty dict for headers to avoid automatically
# generating headers
resp, response_body = self.freezer_api_client.post(uri, request_body,
headers={})
self.assertEqual(resp.status, 201)
@decorators.attr(type="gate")
def test_api_backups_post_incomplete(self):
metadata = self._build_metadata("test_freezer_backups")
del (metadata['container'])
self.assertRaises(tempest.lib.exceptions.BadRequest,
self.freezer_api_client.post_backups, metadata)
@decorators.attr(type="gate")
def test_api_backups_post_minimal(self):
metadata = {
"curr_backup_level": 0,
"container": "test_freezer_api_backups_container",
"hostname": "localhost",
"backup_name": "test_freezer_backups",
"time_stamp": 1459349846,
}
backup_id = self._create_temporary_backup(metadata)
resp, response_body = self._workaround_get_backup(backup_id)
expected = self._build_expected_data(backup_id, metadata)
# backup_id is generated automatically, we can't know it
del(response_body['backup_id'])
self.assertEqual(200, resp.status)
self.assertEqual(expected, response_body)
@decorators.attr(type="gate")
def test_api_backups_delete(self):
metadata = self._build_metadata("test_freezer_backups")
backup_id = self._create_temporary_backup(metadata)
self.freezer_api_client.delete_backups(backup_id)
resp, response_body = self.freezer_api_client.get_backups()
self.assertEqual(0, len(response_body['backups']))
@decorators.attr(type="gate")
def test_api_backups_delete_other_users_backups(self):
metadata = self._build_metadata("test_freezer_backups")
backup_id = self._create_temporary_backup(metadata)
# Switching user
resp, response_body = self.os_alt.freezer_api_client.delete_backups(
backup_id)
self.assertEqual('204', resp['status'])
self.assertEmpty(response_body)
# Switching back to original user
resp, response_body = self.freezer_api_client.get_backups()
self.assertEqual(1, len(response_body['backups']))
def _build_expected_data(self, backup_id, metadata):
return {
'user_name': self.os_primary.credentials.username,
'user_id': self.os_primary.credentials.user_id,
'backup_metadata': metadata
}
def _build_metadata(self, backup_name):
return {
"action": "backup",
"always_level": "",
"backup_media": "fs",
"client_id": "freezer",
"client_version": "1.2.18",
"container_segments": "",
"curr_backup_level": 0,
"dry_run": "",
"log_file": "",
"job_id": "76cf6739ca2e4dc58b2215632c2a0b49",
"os_auth_version": "",
"path_to_backup": "/dev/null",
"proxy": "",
"ssh_host": "",
"ssh_key": "",
"ssh_port": 22,
"ssh_username": "",
"storage": "swift",
"container": "test_freezer_api_backups_container",
"hostname": "localhost",
"backup_name": backup_name,
"time_stamp": 1459349846,
"level": 1,
"max_level": 14,
"mode": "fs",
"fs_real_path": "/dev/null",
"vol_snap_path": "",
"total_broken_links": 1,
"total_fs_files": 100,
"total_directories": 100,
"backup_size_uncompressed": 10000,
"backup_size_compressed": 1000,
"compression": "gzip",
"encrypted": False,
"client_os": "linux2",
"broken_links": [],
"excluded_files": [],
"cli": "freezer",
"version": "1.0"
}
def _create_temporary_backup(self, metadata):
resp, response_body = self.freezer_api_client.post_backups(metadata)
self.assertEqual('201', resp['status'])
self.assertIn('backup_id', response_body)
backup_id = response_body['backup_id']
self.addCleanup(self.freezer_api_client.delete_backups, backup_id)
return backup_id
def _workaround_get_backup(self, backup_id):
# TODO(JonasPf): Use the following line, once this bug is fixed:
# https://bugs.launchpad.net/freezer/+bug/1564649
# resp, response_body = self.freezer_api_client.get_backups(backup_id)
resp, response_body = self.freezer_api_client.get_backups()
result = next((b for b in response_body['backups'] if
b['backup_id'] == backup_id))
return resp, result

View File

@ -0,0 +1,96 @@
# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP
#
# 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 json
import time
from tempest.lib import decorators
from tempest.lib import exceptions
from freezer_tempest_plugin.tests.freezer_api.api import base
class TestFreezerApiClients(base.BaseFreezerApiTest):
@classmethod
def resource_setup(cls):
super(TestFreezerApiClients, cls).resource_setup()
@classmethod
def resource_cleanup(cls):
super(TestFreezerApiClients, cls).resource_cleanup()
@decorators.attr(type="gate")
def test_api_clients(self):
resp, response_body = self.freezer_api_client.get_clients()
self.assertEqual(200, resp.status)
response_body_json = json.loads(response_body)
self.assertIn('clients', response_body_json)
clients = response_body_json['clients']
self.assertEmpty(clients)
@decorators.attr(type="gate")
def test_api_clients_get_limit(self):
# limits > 0 should return successfully
for valid_limit in [2, 1]:
resp, body = self.freezer_api_client.get_clients(limit=valid_limit)
self.assertEqual(200, resp.status)
# limits <= 0 should raise a bad request error
for bad_limit in [0, -1, -2]:
self.assertRaises(exceptions.BadRequest,
self.freezer_api_client.get_clients,
limit=bad_limit)
@decorators.attr(type="gate")
def test_api_clients_get_offset(self):
# offsets >= 0 should return 200
for valid_offset in [1, 0]:
resp, body = self.freezer_api_client.get_clients(
offset=valid_offset)
self.assertEqual(200, resp.status)
# offsets < 0 should return 400
for bad_offset in [-1, -2]:
self.assertRaises(exceptions.BadRequest,
self.freezer_api_client.get_clients,
offset=bad_offset)
@decorators.attr(type="gate")
def test_api_clients_post(self):
client = {'client_id': 'test-client-id',
'hostname': 'test-host-name',
'description': 'a test client',
'uuid': 'test-client-uuid'}
# Create the client with POST
resp, response_body = self.freezer_api_client.post_clients(client)
self.assertEqual(201, resp.status)
self.assertIn('client_id', response_body)
client_id = response_body['client_id']
# Check that the client has the correct values
# Give the DB some time to catch up
time.sleep(5)
resp, response_body = self.freezer_api_client.get_clients(client_id)
self.assertEqual(200, resp.status)
# Delete the client
resp, response_body = self.freezer_api_client.delete_clients(
client_id)
self.assertEqual(204, resp.status)

View File

@ -0,0 +1,154 @@
# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP
#
# 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 json
from tempest.lib import decorators
from tempest.lib import exceptions
from freezer_tempest_plugin.tests.freezer_api.api import base
fake_job = {
"job_actions":
[
{
"freezer_action":
{
"action": "backup",
"mode": "fs",
"src_file": "/home/tylerdurden/project_mayhem",
"backup_name": "project_mayhem_backup",
"container": "my_backup_container",
},
"exit_status": "success",
"max_retries": 1,
"max_retries_interval": 1,
"mandatory": True
}
],
"job_schedule":
{
"time_created": 1234,
"time_started": 1234,
"time_ended": 0,
"status": "stop",
"schedule_date": "2015-06-02T16:20:00",
"schedule_month": "1-6, 9-12",
"schedule_day": "mon, wed, fri",
"schedule_hour": "03",
"schedule_minute": "25",
},
"job_id": "blabla",
"client_id": "01b0f00a-4ce2-11e6-beb8-9e71128cae77_myhost.mydomain.mytld",
"user_id": "blabla",
"description": "scheduled one shot"
}
class TestFreezerApiJobs(base.BaseFreezerApiTest):
@classmethod
def resource_setup(cls):
super(TestFreezerApiJobs, cls).resource_setup()
@classmethod
def resource_cleanup(cls):
super(TestFreezerApiJobs, cls).resource_cleanup()
@decorators.attr(type="gate")
def test_api_jobs(self):
resp, response_body = self.freezer_api_client.get_jobs()
self.assertEqual(200, resp.status)
response_body_json = json.loads(response_body)
self.assertIn('jobs', response_body_json)
jobs = response_body_json['jobs']
self.assertEmpty(jobs)
@decorators.attr(type="gate")
def test_api_jobs_get_limit(self):
# limits > 0 should return successfully
for valid_limit in [2, 1]:
resp, body = self.freezer_api_client.get_jobs(limit=valid_limit)
self.assertEqual(200, resp.status)
# limits <= 0 should raise a bad request error
for bad_limit in [0, -1, -2]:
self.assertRaises(exceptions.BadRequest,
self.freezer_api_client.get_jobs,
limit=bad_limit)
@decorators.attr(type="gate")
def test_api_jobs_get_offset(self):
# offsets >= 0 should return 200
for valid_offset in [1, 0]:
resp, body = self.freezer_api_client.get_jobs(offset=valid_offset)
self.assertEqual(200, resp.status)
# offsets < 0 should return 400
for bad_offset in [-1, -2]:
self.assertRaises(exceptions.BadRequest,
self.freezer_api_client.get_jobs,
offset=bad_offset)
@decorators.attr(type="gate")
def test_api_jobs_post(self):
# Create the job with POST
resp, response_body = self.freezer_api_client.post_jobs(fake_job)
self.assertEqual(201, resp.status)
self.assertIn('job_id', response_body)
job_id = response_body['job_id']
# Check that the job has the correct values
resp, response_body = self.freezer_api_client.get_jobs(job_id)
self.assertEqual(200, resp.status)
# Delete the job
resp, response_body = self.freezer_api_client.delete_jobs(
job_id)
self.assertEqual(204, resp.status)
@decorators.attr(type="gate")
def test_api_jobs_with_invalid_client_project_id_fail(self):
"""Ensure that a job submitted with a bad client_id project id fails"""
fake_bad_job = fake_job
fake_bad_job['client_id'] = 'bad%project$id_host.domain.tld'
# Create the job with POST
self.assertRaises(exceptions.BadRequest,
lambda: self.freezer_api_client.post_jobs(
fake_bad_job))
@decorators.attr(type="gate")
def test_api_jobs_with_invalid_client_host_fail(self):
"""Ensure that a job submitted with a bad client_id hostname fails"""
fake_bad_job = fake_job
fake_bad_job['client_id'] = ("01b0f00a-4ce2-11e6-beb8-9e71128cae77"
"_bad_hostname.bad/domain.b")
# Create the job with POST
self.assertRaises(exceptions.BadRequest,
lambda: self.freezer_api_client.post_jobs(
fake_bad_job))
def test_api_jobs_with_only_fqdn_succeeds(self):
"""Ensure that a job submitted with only an FQDN succeeds"""
fqdn_only_job = fake_job
fqdn_only_job['client_id'] = 'padawan-ccp-c1-m1-mgmt'
# Attempt to post the job, should succeed
resp, response_body = self.freezer_api_client.post_jobs(fqdn_only_job)
self.assertEqual(201, resp.status)

View File

@ -0,0 +1,131 @@
# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP
#
# 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 json
from tempest.lib import decorators
from tempest.lib import exceptions
from freezer_tempest_plugin.tests.freezer_api.api import base
class TestFreezerApiSessions(base.BaseFreezerApiTest):
@classmethod
def resource_setup(cls):
super(TestFreezerApiSessions, cls).resource_setup()
@classmethod
def resource_cleanup(cls):
super(TestFreezerApiSessions, cls).resource_cleanup()
@decorators.attr(type="gate")
def test_api_sessions(self):
resp, response_body = self.freezer_api_client.get_sessions()
self.assertEqual(200, resp.status)
response_body_json = json.loads(response_body)
self.assertIn('sessions', response_body_json)
sessions = response_body_json['sessions']
self.assertEmpty(sessions)
@decorators.attr(type="gate")
def test_api_sessions_get_limit(self):
# limits > 0 should return successfully
for valid_limit in [2, 1]:
resp, body = self.freezer_api_client.get_sessions(
limit=valid_limit)
self.assertEqual(200, resp.status)
# limits <= 0 should raise a bad request error
for bad_limit in [0, -1, -2]:
self.assertRaises(exceptions.BadRequest,
self.freezer_api_client.get_sessions,
limit=bad_limit)
@decorators.attr(type="gate")
def test_api_sessions_get_offset(self):
# offsets >= 0 should return 200
for valid_offset in [1, 0]:
resp, body = self.freezer_api_client.get_sessions(
offset=valid_offset)
self.assertEqual(200, resp.status)
# offsets < 0 should return 400
for bad_offset in [-1, -2]:
self.assertRaises(exceptions.BadRequest,
self.freezer_api_client.get_sessions,
offset=bad_offset)
@decorators.attr(type="gate")
def test_api_sessions_post(self):
session = {
"session_id": "test-session",
"session_tag": 1,
"description": "a test session",
"hold_off": 5,
"schedule": {
"time_created": 1234,
"time_started": 1234,
"time_ended": 0,
"status": "stop",
"schedule_date": "2015-06-02T16:20:00",
"schedule_month": "1-6, 9-12",
"schedule_day": "mon, wed, fri",
"schedule_hour": "03",
"schedule_minute": "25",
},
"jobs": [
{
'job_id_1': {
"client_id": "client-id-1",
"status": "stop",
"result": "success",
"time_started": 1234,
"time_ended": 1234
},
'job_id_2': {
"client_id": "client-id-1",
"status": "stop",
"result": "success",
"time_started": 1234,
"time_ended": 1234,
}
}
],
"time_start": 1234,
"time_end": 1234,
"time_started": 1234,
"time_ended": 1234,
"status": "completed",
"result": "success",
"user_id": "user-id-1"
}
# Create the session with POST
resp, response_body = self.freezer_api_client.post_sessions(session)
self.assertEqual(201, resp.status)
self.assertIn('session_id', response_body)
session_id = response_body['session_id']
# Check that the session has the correct values
resp, response_body = self.freezer_api_client.get_sessions(session_id)
self.assertEqual(200, resp.status)
# Delete the session
resp, response_body = self.freezer_api_client.delete_sessions(
session_id)
self.assertEqual(204, resp.status)

View File

@ -0,0 +1,110 @@
# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP
#
# 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 json
from tempest.lib import decorators
from freezer_tempest_plugin.tests.freezer_api.api import base
class TestFreezerApiVersion(base.BaseFreezerApiTest):
@classmethod
def resource_setup(cls):
super(TestFreezerApiVersion, cls).resource_setup()
@classmethod
def resource_cleanup(cls):
super(TestFreezerApiVersion, cls).resource_cleanup()
@decorators.attr(type="gate")
def test_api_version(self):
resp, response_body = self.freezer_api_client.get_version()
self.assertEqual(300, resp.status)
resp_body_json = json.loads(response_body)
self.assertIn('versions', resp_body_json)
current_version = resp_body_json['versions'][1]
self.assertEqual(len(current_version), 4)
self.assertIn('id', current_version)
self.assertEqual(current_version['id'], 'v1')
self.assertIn('links', current_version)
links = current_version['links'][0]
self.assertIn('href', links)
href = links['href']
self.assertIn('/v1/', href)
self.assertIn('rel', links)
rel = links['rel']
self.assertEqual('self', rel)
self.assertIn('status', current_version)
status = current_version['status']
self.assertEqual('CURRENT', status)
self.assertIn('updated', current_version)
@decorators.attr(type="gate")
def test_api_version_v1(self):
resp, response_body = self.freezer_api_client.get_version_v1()
self.assertEqual(200, resp.status)
response_body_jason = json.loads(response_body)
self.assertIn('resources', response_body_jason)
resource = response_body_jason['resources']
self.assertIn('rel/backups', resource)
rel_backups = resource['rel/backups']
self.assertIn('href-template', rel_backups)
href_template = rel_backups['href-template']
self.assertEqual('/v1/backups/{backup_id}', href_template)
self.assertIn('href-vars', rel_backups)
href_vars = rel_backups['href-vars']
self.assertIn('backup_id', href_vars)
backup_id = href_vars['backup_id']
self.assertEqual('param/backup_id', backup_id)
self.assertIn('hints', rel_backups)
hints = rel_backups['hints']
self.assertIn('allow', hints)
allow = hints['allow']
self.assertEqual('GET', allow[0])
self.assertIn('formats', hints)
formats = hints['formats']
self.assertIn('application/json', formats)
@decorators.attr(type="gate")
def test_api_version_v2(self):
resp, response_body = self.freezer_api_client.get_version_v2()
self.assertEqual(200, resp.status)
response_body_jason = json.loads(response_body)
self.assertIn('resources', response_body_jason)
resource = response_body_jason['resources']
self.assertIn('rel/backups', resource)
rel_backups = resource['rel/backups']
self.assertIn('href-template', rel_backups)
href_template = rel_backups['href-template']
self.assertEqual('/v2/{project_id}/backups/{backup_id}', href_template)
self.assertIn('href-vars', rel_backups)
href_vars = rel_backups['href-vars']
self.assertIn('backup_id', href_vars)
self.assertIn('project_id', href_vars)
backup_id = href_vars['backup_id']
self.assertEqual('param/backup_id', backup_id)
project_id = href_vars['project_id']
self.assertEqual('param/project_id', project_id)
self.assertIn('hints', rel_backups)
hints = rel_backups['hints']
self.assertIn('allow', hints)
allow = hints['allow']
self.assertEqual('GET', allow[0])
self.assertIn('formats', hints)
formats = hints['formats']
self.assertIn('application/json', formats)