Close files on image create
The file opened for --file was never closed. Close it if it is a file object. Change-Id: I7bd120a2413de42339771d01e8fd1894d38c3011
This commit is contained in:
		@@ -15,6 +15,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
"""Image V1 Action Implementations"""
 | 
					"""Image V1 Action Implementations"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import io
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import six
 | 
					import six
 | 
				
			||||||
@@ -214,10 +215,9 @@ class CreateImage(show.ShowOne):
 | 
				
			|||||||
            elif parsed_args.file:
 | 
					            elif parsed_args.file:
 | 
				
			||||||
                # Send an open file handle to glanceclient so it will
 | 
					                # Send an open file handle to glanceclient so it will
 | 
				
			||||||
                # do a chunked transfer
 | 
					                # do a chunked transfer
 | 
				
			||||||
                kwargs["data"] = open(parsed_args.file, "rb")
 | 
					                kwargs["data"] = io.open(parsed_args.file, "rb")
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                # Read file from stdin
 | 
					                # Read file from stdin
 | 
				
			||||||
                kwargs["data"] = None
 | 
					 | 
				
			||||||
                if sys.stdin.isatty() is not True:
 | 
					                if sys.stdin.isatty() is not True:
 | 
				
			||||||
                    if msvcrt:
 | 
					                    if msvcrt:
 | 
				
			||||||
                        msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
 | 
					                        msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
 | 
				
			||||||
@@ -225,6 +225,8 @@ class CreateImage(show.ShowOne):
 | 
				
			|||||||
                    # do a chunked transfer
 | 
					                    # do a chunked transfer
 | 
				
			||||||
                    kwargs["data"] = sys.stdin
 | 
					                    kwargs["data"] = sys.stdin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Wrap the call to catch exceptions in order to close files
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                image = utils.find_resource(
 | 
					                image = utils.find_resource(
 | 
				
			||||||
                    image_client.images,
 | 
					                    image_client.images,
 | 
				
			||||||
@@ -239,8 +241,8 @@ class CreateImage(show.ShowOne):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            except exceptions.CommandError:
 | 
					            except exceptions.CommandError:
 | 
				
			||||||
                if not parsed_args.volume:
 | 
					                if not parsed_args.volume:
 | 
				
			||||||
                # This is normal for a create or reserve (create w/o an image)
 | 
					                    # This is normal for a create or reserve (create w/o
 | 
				
			||||||
                # But skip for create from volume
 | 
					                    # an image), but skip for create from volume
 | 
				
			||||||
                    image = image_client.images.create(**kwargs)
 | 
					                    image = image_client.images.create(**kwargs)
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                # Update an existing reservation
 | 
					                # Update an existing reservation
 | 
				
			||||||
@@ -248,6 +250,11 @@ class CreateImage(show.ShowOne):
 | 
				
			|||||||
                # If an image is specified via --file, --location or
 | 
					                # If an image is specified via --file, --location or
 | 
				
			||||||
                # --copy-from let the API handle it
 | 
					                # --copy-from let the API handle it
 | 
				
			||||||
                image = image_client.images.update(image.id, **kwargs)
 | 
					                image = image_client.images.update(image.id, **kwargs)
 | 
				
			||||||
 | 
					        finally:
 | 
				
			||||||
 | 
					            # Clean up open files - make sure data isn't a string
 | 
				
			||||||
 | 
					            if ('data' in kwargs and hasattr(kwargs['data'], 'close') and
 | 
				
			||||||
 | 
					               kwargs['data'] != sys.stdin):
 | 
				
			||||||
 | 
					                    kwargs['data'].close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        info = {}
 | 
					        info = {}
 | 
				
			||||||
        info.update(image._info)
 | 
					        info.update(image._info)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -139,14 +139,17 @@ class TestImageCreate(TestImage):
 | 
				
			|||||||
        self.assertEqual(image_fakes.IMAGE_columns, columns)
 | 
					        self.assertEqual(image_fakes.IMAGE_columns, columns)
 | 
				
			||||||
        self.assertEqual(image_fakes.IMAGE_data, data)
 | 
					        self.assertEqual(image_fakes.IMAGE_data, data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @mock.patch('six.moves.builtins.open')
 | 
					    @mock.patch('openstackclient.image.v1.image.io.open', name='Open')
 | 
				
			||||||
    def test_image_create_file(self, open_mock):
 | 
					    def test_image_create_file(self, mock_open):
 | 
				
			||||||
 | 
					        mock_file = mock.MagicMock(name='File')
 | 
				
			||||||
 | 
					        mock_open.return_value = mock_file
 | 
				
			||||||
 | 
					        mock_open.read.return_value = image_fakes.image_data
 | 
				
			||||||
        mock_exception = {
 | 
					        mock_exception = {
 | 
				
			||||||
            'find.side_effect': exceptions.CommandError('x'),
 | 
					            'find.side_effect': exceptions.CommandError('x'),
 | 
				
			||||||
            'get.side_effect': exceptions.CommandError('x'),
 | 
					            'get.side_effect': exceptions.CommandError('x'),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        self.images_mock.configure_mock(**mock_exception)
 | 
					        self.images_mock.configure_mock(**mock_exception)
 | 
				
			||||||
        open_mock.return_value = image_fakes.image_data
 | 
					
 | 
				
			||||||
        arglist = [
 | 
					        arglist = [
 | 
				
			||||||
            '--file', 'filer',
 | 
					            '--file', 'filer',
 | 
				
			||||||
            '--unprotected',
 | 
					            '--unprotected',
 | 
				
			||||||
@@ -169,7 +172,11 @@ class TestImageCreate(TestImage):
 | 
				
			|||||||
        # DisplayCommandBase.take_action() returns two tuples
 | 
					        # DisplayCommandBase.take_action() returns two tuples
 | 
				
			||||||
        columns, data = self.cmd.take_action(parsed_args)
 | 
					        columns, data = self.cmd.take_action(parsed_args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        open_mock.assert_called_with('filer', 'rb')
 | 
					        # Ensure input file is opened
 | 
				
			||||||
 | 
					        mock_open.assert_called_with('filer', 'rb')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Ensure the input file is closed
 | 
				
			||||||
 | 
					        mock_file.close.assert_called_with()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # ImageManager.get(name)
 | 
					        # ImageManager.get(name)
 | 
				
			||||||
        self.images_mock.get.assert_called_with(image_fakes.image_name)
 | 
					        self.images_mock.get.assert_called_with(image_fakes.image_name)
 | 
				
			||||||
@@ -185,7 +192,7 @@ class TestImageCreate(TestImage):
 | 
				
			|||||||
                'Alpha': '1',
 | 
					                'Alpha': '1',
 | 
				
			||||||
                'Beta': '2',
 | 
					                'Beta': '2',
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            data=image_fakes.image_data,
 | 
					            data=mock_file,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Verify update() was not called, if it was show the args
 | 
					        # Verify update() was not called, if it was show the args
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user