Merge "add test for create_backup"
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/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/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)