Browse Source

Merge "Image deletion returns 500 if 'file' store is not enabled" into stable/stein

stable/stein
Zuul 2 weeks ago
parent
commit
0e8f37c35a
2 changed files with 51 additions and 10 deletions
  1. 19
    4
      glance/api/v2/images.py
  2. 32
    6
      glance/tests/unit/v2/test_images_resource.py

+ 19
- 4
glance/api/v2/images.py View File

@@ -14,6 +14,7 @@
14 14
 #    under the License.
15 15
 
16 16
 import hashlib
17
+import os
17 18
 import re
18 19
 
19 20
 import glance_store
@@ -336,11 +337,25 @@ class ImagesController(object):
336 337
             image = image_repo.get(image_id)
337 338
 
338 339
             if image.status == 'uploading':
339
-                file_path = str(CONF.node_staging_uri + '/' + image.image_id)
340
-                if CONF.enabled_backends:
341
-                    self.store_api.delete(file_path, None)
340
+                file_path = str(
341
+                    CONF.node_staging_uri + '/' + image.image_id)[7:]
342
+                if os.path.exists(file_path):
343
+                    try:
344
+                        LOG.debug(
345
+                            "After upload to the backend, deleting staged "
346
+                            "image data from %(fn)s", {'fn': file_path})
347
+                        os.unlink(file_path)
348
+                    except OSError as e:
349
+                        LOG.error(
350
+                            "After upload to backend, deletion of staged "
351
+                            "image data from %(fn)s has failed because "
352
+                            "[Errno %(en)d]", {'fn': file_path,
353
+                                               'en': e.errno})
342 354
                 else:
343
-                    self.store_api.delete_from_backend(file_path)
355
+                    LOG.warning(_(
356
+                        "After upload to backend, deletion of staged "
357
+                        "image data has failed because "
358
+                        "it cannot be found at %(fn)s"), {'fn': file_path})
344 359
 
345 360
             image.delete()
346 361
             image_repo.remove(image)

+ 32
- 6
glance/tests/unit/v2/test_images_resource.py View File

@@ -16,6 +16,7 @@
16 16
 import datetime
17 17
 import eventlet
18 18
 import hashlib
19
+import os
19 20
 import uuid
20 21
 
21 22
 import glance_store as store
@@ -2635,17 +2636,42 @@ class TestImagesController(base.IsolatedUnitTest):
2635 2636
                           request, UUID1)
2636 2637
 
2637 2638
     def test_delete_uploading_status_image(self):
2638
-        """Ensure status of uploading image is updated (LP bug #1733289)"""
2639
+        """Ensure uploading image is deleted (LP bug #1733289)
2640
+        Ensure image stuck in uploading state is deleted (LP bug #1836140)
2641
+        """
2642
+        request = unit_test_utils.get_fake_request(is_admin=True)
2643
+        image = self.db.image_create(request.context, {'status': 'uploading'})
2644
+        image_id = image['id']
2645
+        with mock.patch.object(os.path, 'exists') as mock_exists:
2646
+            mock_exists.return_value = True
2647
+            with mock.patch.object(os, "unlink") as mock_unlik:
2648
+                self.controller.delete(request, image_id)
2649
+
2650
+                self.assertEqual(1, mock_exists.call_count)
2651
+                self.assertEqual(1, mock_unlik.call_count)
2652
+
2653
+        # Ensure that image is deleted
2654
+        image = self.db.image_get(request.context, image_id,
2655
+                                  force_show_deleted=True)
2656
+        self.assertTrue(image['deleted'])
2657
+        self.assertEqual('deleted', image['status'])
2658
+
2659
+    def test_deletion_of_staging_data_failed(self):
2660
+        """Ensure uploading image is deleted (LP bug #1733289)
2661
+        Ensure image stuck in uploading state is deleted (LP bug #1836140)
2662
+        """
2639 2663
         request = unit_test_utils.get_fake_request(is_admin=True)
2640 2664
         image = self.db.image_create(request.context, {'status': 'uploading'})
2641 2665
         image_id = image['id']
2642
-        with mock.patch.object(self.store,
2643
-                               'delete_from_backend') as mock_store:
2644
-            self.controller.delete(request, image_id)
2666
+        with mock.patch.object(os.path, 'exists') as mock_exists:
2667
+            mock_exists.return_value = False
2668
+            with mock.patch.object(os, "unlink") as mock_unlik:
2669
+                self.controller.delete(request, image_id)
2645 2670
 
2646
-        # Ensure delete_from_backend is called
2647
-        self.assertEqual(1, mock_store.call_count)
2671
+                self.assertEqual(1, mock_exists.call_count)
2672
+                self.assertEqual(0, mock_unlik.call_count)
2648 2673
 
2674
+        # Ensure that image is deleted
2649 2675
         image = self.db.image_get(request.context, image_id,
2650 2676
                                   force_show_deleted=True)
2651 2677
         self.assertTrue(image['deleted'])

Loading…
Cancel
Save