Merge "Test for service type management"
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index de8b312..42cb040 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -231,6 +231,7 @@
cls.servers_client = cls.os.servers_v3_client
cls.images_client = cls.os.image_client
cls.services_client = cls.os.services_v3_client
+ cls.extensions_client = cls.os.extensions_v3_client
@classmethod
def create_image_from_server(cls, server_id, **kwargs):
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 4a1f8e3..b8700ec 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -22,6 +22,7 @@
from tempest.api import compute
from tempest.api.compute import base
+from tempest.common.utils.data_utils import parse_image_id
from tempest.common.utils.data_utils import rand_name
from tempest.common.utils.linux.remote_client import RemoteClient
import tempest.config
@@ -199,6 +200,74 @@
raise exceptions.TimeoutException(message)
@attr(type='gate')
+ def test_create_backup(self):
+ # Positive test:create backup successfully and rotate backups correctly
+ # create the first and the second backup
+ backup1 = rand_name('backup')
+ resp, _ = self.servers_client.create_backup(self.server_id,
+ 'daily',
+ 2,
+ backup1)
+ oldest_backup_exist = True
+
+ # the oldest one should be deleted automatically in this test
+ def _clean_oldest_backup(oldest_backup):
+ if oldest_backup_exist:
+ self.os.image_client.delete_image(oldest_backup)
+
+ image1_id = parse_image_id(resp['location'])
+ self.addCleanup(_clean_oldest_backup, image1_id)
+ self.assertEqual(202, resp.status)
+
+ backup2 = rand_name('backup')
+ self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
+ resp, _ = self.servers_client.create_backup(self.server_id,
+ 'daily',
+ 2,
+ backup2)
+ image2_id = parse_image_id(resp['location'])
+ self.addCleanup(self.os.image_client.delete_image, image2_id)
+ self.assertEqual(202, resp.status)
+
+ # verify they have been created
+ properties = {
+ 'image_type': 'backup',
+ 'backup_type': "daily",
+ 'instance_uuid': self.server_id,
+ }
+ resp, image_list = self.os.image_client.image_list_detail(
+ properties,
+ sort_key='created_at',
+ sort_dir='asc')
+ self.assertEqual(200, resp.status)
+ self.assertEqual(2, len(image_list))
+ self.assertEqual((backup1, backup2),
+ (image_list[0]['name'], image_list[1]['name']))
+
+ # create the third one, due to the rotation is 2,
+ # the first one will be deleted
+ backup3 = rand_name('backup')
+ self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
+ resp, _ = self.servers_client.create_backup(self.server_id,
+ 'daily',
+ 2,
+ backup3)
+ image3_id = parse_image_id(resp['location'])
+ self.addCleanup(self.os.image_client.delete_image, image3_id)
+ self.assertEqual(202, resp.status)
+ # the first back up should be deleted
+ self.os.image_client.wait_for_resource_deletion(image1_id)
+ oldest_backup_exist = False
+ resp, image_list = self.os.image_client.image_list_detail(
+ properties,
+ sort_key='created_at',
+ sort_dir='asc')
+ self.assertEqual(200, resp.status)
+ self.assertEqual(2, len(image_list))
+ self.assertEqual((backup2, backup3),
+ (image_list[0]['name'], image_list[1]['name']))
+
+ @attr(type='gate')
def test_get_console_output(self):
# Positive test:Should be able to GET the console output
# for a given server_id and number of lines
diff --git a/tempest/api/compute/v3/test_extensions.py b/tempest/api/compute/v3/test_extensions.py
index 8f1e446..d7269d1 100644
--- a/tempest/api/compute/v3/test_extensions.py
+++ b/tempest/api/compute/v3/test_extensions.py
@@ -20,7 +20,7 @@
from tempest.test import attr
-class ExtensionsTestJSON(base.BaseV2ComputeTest):
+class ExtensionsV3TestJSON(base.BaseV3ComputeTest):
_interface = 'json'
@attr(type='gate')
@@ -31,5 +31,5 @@
self.assertEqual(200, resp.status)
-class ExtensionsTestXML(ExtensionsTestJSON):
+class ExtensionsV3TestXML(ExtensionsV3TestJSON):
_interface = 'xml'
diff --git a/tempest/clients.py b/tempest/clients.py
index 4c39bb1..a52ed5d 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -48,10 +48,14 @@
TenantUsagesClientJSON
from tempest.services.compute.json.volumes_extensions_client import \
VolumesExtensionsClientJSON
+from tempest.services.compute.v3.json.extensions_client import \
+ ExtensionsV3ClientJSON
from tempest.services.compute.v3.json.servers_client import \
ServersV3ClientJSON
from tempest.services.compute.v3.json.services_client import \
ServicesV3ClientJSON
+from tempest.services.compute.v3.xml.extensions_client import \
+ ExtensionsV3ClientXML
from tempest.services.compute.v3.xml.servers_client import ServersV3ClientXML
from tempest.services.compute.v3.xml.services_client import \
ServicesV3ClientXML
@@ -185,6 +189,7 @@
self.keypairs_client = KeyPairsClientXML(*client_args)
self.quotas_client = QuotasClientXML(*client_args)
self.flavors_client = FlavorsClientXML(*client_args)
+ self.extensions_v3_client = ExtensionsV3ClientXML(*client_args)
self.extensions_client = ExtensionsClientXML(*client_args)
self.volumes_extensions_client = VolumesExtensionsClientXML(
*client_args)
@@ -226,6 +231,7 @@
self.keypairs_client = KeyPairsClientJSON(*client_args)
self.quotas_client = QuotasClientJSON(*client_args)
self.flavors_client = FlavorsClientJSON(*client_args)
+ self.extensions_v3_client = ExtensionsV3ClientJSON(*client_args)
self.extensions_client = ExtensionsClientJSON(*client_args)
self.volumes_extensions_client = VolumesExtensionsClientJSON(
*client_args)
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index f2386b0..87512fb 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -198,6 +198,13 @@
body = json.loads(body)[response_key]
return resp, body
+ def create_backup(self, server_id, backup_type, rotation, name):
+ """Backup a server instance."""
+ return self.action(server_id, "createBackup", None,
+ backup_type=backup_type,
+ rotation=rotation,
+ name=name)
+
def change_password(self, server_id, adminPass):
"""Changes the root password for the server."""
return self.action(server_id, 'changePassword', None,
diff --git a/tempest/services/compute/v3/json/extensions_client.py b/tempest/services/compute/v3/json/extensions_client.py
index ce46a9b..60c0217 100644
--- a/tempest/services/compute/v3/json/extensions_client.py
+++ b/tempest/services/compute/v3/json/extensions_client.py
@@ -20,12 +20,13 @@
from tempest.common.rest_client import RestClient
-class ExtensionsClientJSON(RestClient):
+class ExtensionsV3ClientJSON(RestClient):
def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(ExtensionsClientJSON, self).__init__(config, username, password,
- auth_url, tenant_name)
- self.service = self.config.compute.catalog_type
+ super(ExtensionsV3ClientJSON, self).__init__(config, username,
+ password, auth_url,
+ tenant_name)
+ self.service = self.config.compute.catalog_v3_type
def list_extensions(self):
url = 'extensions'
diff --git a/tempest/services/compute/v3/xml/extensions_client.py b/tempest/services/compute/v3/xml/extensions_client.py
index 1395b5a..e03251c 100644
--- a/tempest/services/compute/v3/xml/extensions_client.py
+++ b/tempest/services/compute/v3/xml/extensions_client.py
@@ -20,12 +20,12 @@
from tempest.services.compute.xml.common import xml_to_json
-class ExtensionsClientXML(RestClientXML):
+class ExtensionsV3ClientXML(RestClientXML):
def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(ExtensionsClientXML, self).__init__(config, username, password,
- auth_url, tenant_name)
- self.service = self.config.compute.catalog_type
+ super(ExtensionsV3ClientXML, self).__init__(config, username, password,
+ auth_url, tenant_name)
+ self.service = self.config.compute.catalog_v3_type
def _parse_array(self, node):
array = []
diff --git a/tempest/services/compute/xml/servers_client.py b/tempest/services/compute/xml/servers_client.py
index d97a659..3319238 100644
--- a/tempest/services/compute/xml/servers_client.py
+++ b/tempest/services/compute/xml/servers_client.py
@@ -420,6 +420,13 @@
body = xml_to_json(etree.fromstring(body))
return resp, body
+ def create_backup(self, server_id, backup_type, rotation, name):
+ """Backup a server instance."""
+ return self.action(server_id, "createBackup", None,
+ backup_type=backup_type,
+ rotation=rotation,
+ name=name)
+
def change_password(self, server_id, password):
return self.action(server_id, "changePassword", None,
adminPass=password)
diff --git a/tempest/services/image/v1/json/image_client.py b/tempest/services/image/v1/json/image_client.py
index 0a7f0e2..9f5a405 100644
--- a/tempest/services/image/v1/json/image_client.py
+++ b/tempest/services/image/v1/json/image_client.py
@@ -187,9 +187,15 @@
body = json.loads(body)
return resp, body['images']
- def image_list_detail(self, **kwargs):
+ def image_list_detail(self, properties=dict(), **kwargs):
url = 'v1/images/detail'
+ params = {}
+ for key, value in properties.items():
+ params['property-%s' % key] = value
+
+ kwargs.update(params)
+
if len(kwargs) > 0:
url += '?%s' % urllib.urlencode(kwargs)