Merge "add tests for force delete snapshot:"
diff --git a/tempest/api/volume/admin/test_snapshots_actions.py b/tempest/api/volume/admin/test_snapshots_actions.py
index 3211ef8..12fda92 100644
--- a/tempest/api/volume/admin/test_snapshots_actions.py
+++ b/tempest/api/volume/admin/test_snapshots_actions.py
@@ -64,6 +64,19 @@
                                                           status)
         super(SnapshotsActionsTest, self).tearDown()
 
+    def _create_reset_and_force_delete_temp_snapshot(self, status=None):
+        # Create snapshot, reset snapshot status,
+        # and force delete temp snapshot
+        temp_snapshot = self.create_snapshot(self.volume['id'])
+        if status:
+            resp, body = self.admin_snapshots_client.\
+                reset_snapshot_status(temp_snapshot['id'], status)
+            self.assertEqual(202, resp.status)
+        resp_delete, volume_delete = self.admin_snapshots_client.\
+            force_delete_snapshot(temp_snapshot['id'])
+        self.assertEqual(202, resp_delete.status)
+        self.client.wait_for_resource_deletion(temp_snapshot['id'])
+
     def _get_progress_alias(self):
         return 'os-extended-snapshot-attributes:progress'
 
@@ -99,6 +112,26 @@
         self.assertEqual(status, snapshot_get['status'])
         self.assertEqual(progress, snapshot_get[progress_alias])
 
+    @attr(type='gate')
+    def test_snapshot_force_delete_when_snapshot_is_creating(self):
+        # test force delete when status of snapshot is creating
+        self._create_reset_and_force_delete_temp_snapshot('creating')
+
+    @attr(type='gate')
+    def test_snapshot_force_delete_when_snapshot_is_deleting(self):
+        # test force delete when status of snapshot is deleting
+        self._create_reset_and_force_delete_temp_snapshot('deleting')
+
+    @attr(type='gate')
+    def test_snapshot_force_delete_when_snapshot_is_error(self):
+        # test force delete when status of snapshot is error
+        self._create_reset_and_force_delete_temp_snapshot('error')
+
+    @attr(type='gate')
+    def test_snapshot_force_delete_when_snapshot_is_error_deleting(self):
+        # test force delete when status of snapshot is error_deleting
+        self._create_reset_and_force_delete_temp_snapshot('error_deleting')
+
 
 class SnapshotsActionsTestXML(SnapshotsActionsTest):
     _interface = "xml"
diff --git a/tempest/services/volume/json/snapshots_client.py b/tempest/services/volume/json/snapshots_client.py
index a36083b..e8926bd 100644
--- a/tempest/services/volume/json/snapshots_client.py
+++ b/tempest/services/volume/json/snapshots_client.py
@@ -187,3 +187,10 @@
         url = "snapshots/%s/metadata/%s" % (str(snapshot_id), str(id))
         resp, body = self.delete(url, self.headers)
         return resp, body
+
+    def force_delete_snapshot(self, snapshot_id):
+        """Force Delete Snapshot."""
+        post_body = json.dumps({'os-force_delete': {}})
+        resp, body = self.post('snapshots/%s/action' % snapshot_id, post_body,
+                               self.headers)
+        return resp, body
diff --git a/tempest/services/volume/xml/snapshots_client.py b/tempest/services/volume/xml/snapshots_client.py
index 3e85041..5e62b6d 100644
--- a/tempest/services/volume/xml/snapshots_client.py
+++ b/tempest/services/volume/xml/snapshots_client.py
@@ -226,3 +226,12 @@
         """Delete metadata item for the snapshot."""
         url = "snapshots/%s/metadata/%s" % (str(snapshot_id), str(id))
         return self.delete(url)
+
+    def force_delete_snapshot(self, snapshot_id):
+        """Force Delete Snapshot."""
+        post_body = Element("os-force_delete")
+        url = 'snapshots/%s/action' % str(snapshot_id)
+        resp, body = self.post(url, str(Document(post_body)), self.headers)
+        if body:
+            body = xml_to_json(etree.fromstring(body))
+        return resp, body