def setUp(self, mock_session):
        """Establish a clean test environment"""

        self.config(default_store='file')

        # NOTE(flaper87): Each store should test
        # this in their test suite.
        self.config(known_stores=VMWARE_DATASTORE_CONF['known_stores'])

        super(TestStore, self).setUp()

        Store.CHUNKSIZE = 2
        self.store = Store()

        class FakeSession:
            def __init__(self):
                self.vim = FakeVim()

        class FakeVim:
            def __init__(self):
                self.client = FakeClient()

        class FakeClient:
            def __init__(self):
                self.options = FakeOptions()

        class FakeOptions:
            def __init__(self):
                self.transport = FakeTransport()

        class FakeTransport:
            def __init__(self):
                self.cookiejar = FakeCookieJar()

        class FakeCookieJar:
            pass

        self.store.scheme = VMWARE_DATASTORE_CONF['default_store']
        self.store.server_host = (VMWARE_DATASTORE_CONF['vmware_server_host'])
        self.store.datacenter_path = (
            VMWARE_DATASTORE_CONF['vmware_datacenter_path'])
        self.store.datastore_name = (
            VMWARE_DATASTORE_CONF['vmware_datastore_name'])
        self.store.api_insecure = (
            VMWARE_DATASTORE_CONF['vmware_api_insecure'])
        self.store.api_retry_count = (
            VMWARE_DATASTORE_CONF['vmware_api_retry_count'])
        self.store._session = FakeSession()
        self.store._session.invoke_api = mock.Mock()
        self.store._session.wait_for_task = mock.Mock()

        self.store.store_image_dir = (
            VMWARE_DATASTORE_CONF['vmware_store_image_dir'])
        Store._build_vim_cookie_header = mock.Mock()
        self.addCleanup(self.stubs.UnsetAll)
    def setUp(self, mock_session):
        """Establish a clean test environment"""

        self.config(default_store='file')

        # NOTE(flaper87): Each store should test
        # this in their test suite.
        self.config(known_stores=VMWARE_DATASTORE_CONF['known_stores'])

        super(TestStore, self).setUp()

        Store.CHUNKSIZE = 2
        self.store = Store()

        class FakeSession:
            def __init__(self):
                self.vim = FakeVim()

        class FakeVim:
            def __init__(self):
                self.client = FakeClient()

        class FakeClient:
            def __init__(self):
                self.options = FakeOptions()

        class FakeOptions:
            def __init__(self):
                self.transport = FakeTransport()

        class FakeTransport:
            def __init__(self):
                self.cookiejar = FakeCookieJar()

        class FakeCookieJar:
            pass

        self.store.scheme = VMWARE_DATASTORE_CONF['default_store']
        self.store.server_host = (
            VMWARE_DATASTORE_CONF['vmware_server_host'])
        self.store.datacenter_path = (
            VMWARE_DATASTORE_CONF['vmware_datacenter_path'])
        self.store.datastore_name = (
            VMWARE_DATASTORE_CONF['vmware_datastore_name'])
        self.store.api_insecure = (
            VMWARE_DATASTORE_CONF['vmware_api_insecure'])
        self.store.api_retry_count = (
            VMWARE_DATASTORE_CONF['vmware_api_retry_count'])
        self.store._session = FakeSession()
        self.store._session.invoke_api = mock.Mock()
        self.store._session.wait_for_task = mock.Mock()

        self.store.store_image_dir = (
            VMWARE_DATASTORE_CONF['vmware_store_image_dir'])
        Store._build_vim_cookie_header = mock.Mock()
        self.addCleanup(self.stubs.UnsetAll)
Beispiel #3
0
class TestStore(base.StoreClearingUnitTest):
    @mock.patch('oslo.vmware.api.VMwareAPISession', autospec=True)
    def setUp(self, mock_session):
        """Establish a clean test environment"""

        self.config(default_store='file')

        # NOTE(flaper87): Each store should test
        # this in their test suite.
        self.config(known_stores=VMWARE_DATASTORE_CONF['known_stores'])

        super(TestStore, self).setUp()

        Store.CHUNKSIZE = 2
        self.store = Store()

        class FakeSession:
            def __init__(self):
                self.vim = FakeVim()

        class FakeVim:
            def __init__(self):
                self.client = FakeClient()

        class FakeClient:
            def __init__(self):
                self.options = FakeOptions()

        class FakeOptions:
            def __init__(self):
                self.transport = FakeTransport()

        class FakeTransport:
            def __init__(self):
                self.cookiejar = FakeCookieJar()

        class FakeCookieJar:
            pass

        self.store.scheme = VMWARE_DATASTORE_CONF['default_store']
        self.store.server_host = (VMWARE_DATASTORE_CONF['vmware_server_host'])
        self.store.datacenter_path = (
            VMWARE_DATASTORE_CONF['vmware_datacenter_path'])
        self.store.datastore_name = (
            VMWARE_DATASTORE_CONF['vmware_datastore_name'])
        self.store.api_insecure = (
            VMWARE_DATASTORE_CONF['vmware_api_insecure'])
        self.store._session = FakeSession()
        self.store._session.invoke_api = mock.Mock()
        self.store._session.wait_for_task = mock.Mock()

        self.store.store_image_dir = (
            VMWARE_DATASTORE_CONF['vmware_store_image_dir'])
        Store._build_vim_cookie_header = mock.Mock()
        self.addCleanup(self.stubs.UnsetAll)

    def test_get(self):
        """Test a "normal" retrieval of an image in chunks"""
        expected_image_size = 31
        expected_returns = [
            'I ', 'am', ' a', ' t', 'ea', 'po', 't,', ' s', 'ho', 'rt', ' a',
            'nd', ' s', 'to', 'ut', '\n'
        ]
        loc = get_location_from_uri(
            "vsphere://127.0.0.1/folder/openstack_glance/%s"
            "?dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection()
            (image_file, image_size) = self.store.get(loc)
        self.assertEqual(image_size, expected_image_size)
        chunks = [c for c in image_file]
        self.assertEqual(chunks, expected_returns)

    def test_get_non_existing(self):
        """
        Test that trying to retrieve an image that doesn't exist
        raises an error
        """
        loc = get_location_from_uri("vsphere://127.0.0.1/folder/openstack_glan"
                                    "ce/%s?dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection(status=404)
            self.assertRaises(exception.NotFound, self.store.get, loc)

    @mock.patch.object(vm_store._Reader, 'size')
    def test_add(self, fake_size):
        """Test that we can add an image via the VMware backend"""
        expected_image_id = str(uuid.uuid4())
        expected_size = FIVE_KB
        expected_contents = "*" * expected_size
        hash_code = hashlib.md5(expected_contents)
        expected_checksum = hash_code.hexdigest()
        fake_size.__get__ = mock.Mock(return_value=expected_size)
        with mock.patch('hashlib.md5') as md5:
            md5.return_value = hash_code
            expected_location = format_location(
                VMWARE_DATASTORE_CONF['vmware_server_host'],
                VMWARE_DATASTORE_CONF['vmware_store_image_dir'],
                expected_image_id,
                VMWARE_DATASTORE_CONF['vmware_datacenter_path'],
                VMWARE_DATASTORE_CONF['vmware_datastore_name'])
            image = six.StringIO(expected_contents)
            with mock.patch('httplib.HTTPConnection') as HttpConn:
                HttpConn.return_value = FakeHTTPConnection()
                location, size, checksum, _ = self.store.add(
                    expected_image_id, image, expected_size)
        self.assertEqual(unit_utils.sort_url_by_qs_keys(expected_location),
                         unit_utils.sort_url_by_qs_keys(location))
        self.assertEqual(expected_size, size)
        self.assertEqual(expected_checksum, checksum)

    @mock.patch.object(vm_store._Reader, 'size')
    def test_add_size_zero(self, fake_size):
        """
        Test that when specifying size zero for the image to add,
        the actual size of the image is returned.
        """
        expected_image_id = str(uuid.uuid4())
        expected_size = FIVE_KB
        expected_contents = "*" * expected_size
        hash_code = hashlib.md5(expected_contents)
        expected_checksum = hash_code.hexdigest()
        fake_size.__get__ = mock.Mock(return_value=expected_size)
        with mock.patch('hashlib.md5') as md5:
            md5.return_value = hash_code
            expected_location = format_location(
                VMWARE_DATASTORE_CONF['vmware_server_host'],
                VMWARE_DATASTORE_CONF['vmware_store_image_dir'],
                expected_image_id,
                VMWARE_DATASTORE_CONF['vmware_datacenter_path'],
                VMWARE_DATASTORE_CONF['vmware_datastore_name'])
            image = six.StringIO(expected_contents)
            with mock.patch('httplib.HTTPConnection') as HttpConn:
                HttpConn.return_value = FakeHTTPConnection()
                location, size, checksum, _ = self.store.add(
                    expected_image_id, image, 0)
        self.assertEqual(unit_utils.sort_url_by_qs_keys(expected_location),
                         unit_utils.sort_url_by_qs_keys(location))
        self.assertEqual(expected_size, size)
        self.assertEqual(expected_checksum, checksum)

    def test_delete(self):
        """Test we can delete an existing image in the VMware store"""
        loc = get_location_from_uri(
            "vsphere://127.0.0.1/folder/openstack_glance/%s?"
            "dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection()
            Store._service_content = mock.Mock()
            self.store.delete(loc)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection(status=404)
            self.assertRaises(exception.NotFound, self.store.get, loc)

    def test_get_size(self):
        """Test we can get the size of an existing image in the VMware store"""
        loc = get_location_from_uri(
            "vsphere://127.0.0.1/folder/openstack_glance/%s"
            "?dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection()
            image_size = self.store.get_size(loc)
        self.assertEqual(image_size, 31)

    def test_get_size_non_existing(self):
        """
        Test that trying to retrieve an image size that doesn't exist
        raises an error
        """
        loc = get_location_from_uri("vsphere://127.0.0.1/folder/openstack_glan"
                                    "ce/%s?dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection(status=404)
            self.assertRaises(exception.NotFound, self.store.get_size, loc)
Beispiel #4
0
class TestStore(base.StoreClearingUnitTest):

    @mock.patch('oslo.vmware.api.VMwareAPISession', autospec=True)
    def setUp(self, mock_session):
        """Establish a clean test environment"""

        self.config(default_store='file')

        # NOTE(flaper87): Each store should test
        # this in their test suite.
        self.config(known_stores=VMWARE_DATASTORE_CONF['known_stores'])

        super(TestStore, self).setUp()

        Store.CHUNKSIZE = 2
        self.store = Store()

        class FakeSession:
            def __init__(self):
                self.vim = FakeVim()

        class FakeVim:
            def __init__(self):
                self.client = FakeClient()

        class FakeClient:
            def __init__(self):
                self.options = FakeOptions()

        class FakeOptions:
            def __init__(self):
                self.transport = FakeTransport()

        class FakeTransport:
            def __init__(self):
                self.cookiejar = FakeCookieJar()

        class FakeCookieJar:
            pass

        self.store.scheme = VMWARE_DATASTORE_CONF['default_store']
        self.store.server_host = (
            VMWARE_DATASTORE_CONF['vmware_server_host'])
        self.store.datacenter_path = (
            VMWARE_DATASTORE_CONF['vmware_datacenter_path'])
        self.store.datastore_name = (
            VMWARE_DATASTORE_CONF['vmware_datastore_name'])
        self.store.api_insecure = (
            VMWARE_DATASTORE_CONF['vmware_api_insecure'])
        self.store._session = FakeSession()
        self.store._session.invoke_api = mock.Mock()
        self.store._session.wait_for_task = mock.Mock()

        self.store.store_image_dir = (
            VMWARE_DATASTORE_CONF['vmware_store_image_dir'])
        Store._build_vim_cookie_header = mock.Mock()
        self.addCleanup(self.stubs.UnsetAll)

    def test_get(self):
        """Test a "normal" retrieval of an image in chunks"""
        expected_image_size = 31
        expected_returns = ['I ', 'am', ' a', ' t', 'ea', 'po', 't,', ' s',
                            'ho', 'rt', ' a', 'nd', ' s', 'to', 'ut', '\n']
        loc = get_location_from_uri(
            "vsphere://127.0.0.1/folder/openstack_glance/%s"
            "?dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection()
            (image_file, image_size) = self.store.get(loc)
        self.assertEqual(image_size, expected_image_size)
        chunks = [c for c in image_file]
        self.assertEqual(chunks, expected_returns)

    def test_get_non_existing(self):
        """
        Test that trying to retrieve an image that doesn't exist
        raises an error
        """
        loc = get_location_from_uri("vsphere://127.0.0.1/folder/openstack_glan"
                                    "ce/%s?dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection(status=404)
            self.assertRaises(exception.NotFound, self.store.get, loc)

    @mock.patch.object(vm_store._Reader, 'size')
    def test_add(self, fake_size):
        """Test that we can add an image via the VMware backend"""
        expected_image_id = str(uuid.uuid4())
        expected_size = FIVE_KB
        expected_contents = "*" * expected_size
        hash_code = hashlib.md5(expected_contents)
        expected_checksum = hash_code.hexdigest()
        fake_size.__get__ = mock.Mock(return_value=expected_size)
        with mock.patch('hashlib.md5') as md5:
            md5.return_value = hash_code
            expected_location = format_location(
                VMWARE_DATASTORE_CONF['vmware_server_host'],
                VMWARE_DATASTORE_CONF['vmware_store_image_dir'],
                expected_image_id,
                VMWARE_DATASTORE_CONF['vmware_datacenter_path'],
                VMWARE_DATASTORE_CONF['vmware_datastore_name'])
            image = six.StringIO(expected_contents)
            with mock.patch('httplib.HTTPConnection') as HttpConn:
                HttpConn.return_value = FakeHTTPConnection()
                location, size, checksum, _ = self.store.add(expected_image_id,
                                                             image,
                                                             expected_size)
        self.assertEqual(expected_location, location)
        self.assertEqual(expected_size, size)
        self.assertEqual(expected_checksum, checksum)

    @mock.patch.object(vm_store._Reader, 'size')
    def test_add_size_zero(self, fake_size):
        """
        Test that when specifying size zero for the image to add,
        the actual size of the image is returned.
        """
        expected_image_id = str(uuid.uuid4())
        expected_size = FIVE_KB
        expected_contents = "*" * expected_size
        hash_code = hashlib.md5(expected_contents)
        expected_checksum = hash_code.hexdigest()
        fake_size.__get__ = mock.Mock(return_value=expected_size)
        with mock.patch('hashlib.md5') as md5:
            md5.return_value = hash_code
            expected_location = format_location(
                VMWARE_DATASTORE_CONF['vmware_server_host'],
                VMWARE_DATASTORE_CONF['vmware_store_image_dir'],
                expected_image_id,
                VMWARE_DATASTORE_CONF['vmware_datacenter_path'],
                VMWARE_DATASTORE_CONF['vmware_datastore_name'])
            image = six.StringIO(expected_contents)
            with mock.patch('httplib.HTTPConnection') as HttpConn:
                HttpConn.return_value = FakeHTTPConnection()
                location, size, checksum, _ = self.store.add(expected_image_id,
                                                             image, 0)
        self.assertEqual(expected_location, location)
        self.assertEqual(expected_size, size)
        self.assertEqual(expected_checksum, checksum)

    def test_delete(self):
        """Test we can delete an existing image in the VMware store"""
        loc = get_location_from_uri(
            "vsphere://127.0.0.1/folder/openstack_glance/%s?"
            "dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection()
            Store._service_content = mock.Mock()
            self.store.delete(loc)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection(status=404)
            self.assertRaises(exception.NotFound, self.store.get, loc)

    def test_get_size(self):
        """Test we can get the size of an existing image in the VMware store"""
        loc = get_location_from_uri(
            "vsphere://127.0.0.1/folder/openstack_glance/%s"
            "?dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection()
            image_size = self.store.get_size(loc)
        self.assertEqual(image_size, 31)

    def test_get_size_non_existing(self):
        """
        Test that trying to retrieve an image size that doesn't exist
        raises an error
        """
        loc = get_location_from_uri("vsphere://127.0.0.1/folder/openstack_glan"
                                    "ce/%s?dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection(status=404)
            self.assertRaises(exception.NotFound, self.store.get_size, loc)

    def test_reader_image_fits_in_blocksize(self):
        """
        Test that the image file reader returns the expected chunk of data
        when the block size is larger than the image.
        """
        content = 'XXX'
        image = six.StringIO(content)
        expected_checksum = hashlib.md5(content).hexdigest()
        checksum = hashlib.md5()
        reader = vm_store._Reader(image, checksum)
        ret = reader.read()
        expected_chunk = '%x\r\n%s\r\n' % (len(content), content)
        last_chunk = '0\r\n\r\n'
        self.assertEqual('%s%s' % (expected_chunk, last_chunk), ret)
        self.assertEqual(image.len, reader.size)
        self.assertEqual(expected_checksum, reader.checksum.hexdigest())
        self.assertTrue(reader.closed)
        ret = reader.read()
        self.assertEqual(image.len, reader.size)
        self.assertEqual(expected_checksum, reader.checksum.hexdigest())
        self.assertTrue(reader.closed)
        self.assertEqual('', ret)

    def test_reader_image_larger_blocksize(self):
        """
        Test that the image file reader returns the expected chunks when
        the block size specified is smaller than the image.
        """
        content = 'XXX'
        image = six.StringIO(content)
        expected_checksum = hashlib.md5(content).hexdigest()
        checksum = hashlib.md5()
        last_chunk = '0\r\n\r\n'
        reader = vm_store._Reader(image, checksum, blocksize=1)
        ret = reader.read()
        expected_chunk = '1\r\nX\r\n'
        self.assertEqual('%s%s%s%s' % (expected_chunk, expected_chunk,
                                       expected_chunk, last_chunk), ret)
        self.assertEqual(expected_checksum, reader.checksum.hexdigest())
        self.assertEqual(image.len, reader.size)
        self.assertTrue(reader.closed)

    def test_reader_size(self):
        """Test that the image reader takes into account the specified size."""
        content = 'XXX'
        image = six.StringIO(content)
        expected_checksum = hashlib.md5(content).hexdigest()
        checksum = hashlib.md5()
        reader = vm_store._Reader(image, checksum, blocksize=1)
        ret = reader.read(size=3)
        self.assertEqual('1\r\n', ret)
        ret = reader.read(size=1)
        self.assertEqual('X', ret)
        ret = reader.read()
        self.assertEqual(expected_checksum, reader.checksum.hexdigest())
        self.assertEqual(image.len, reader.size)
        self.assertTrue(reader.closed)
class TestStore(base.StoreClearingUnitTest):
    @mock.patch('oslo.vmware.api.VMwareAPISession', autospec=True)
    def setUp(self, mock_session):
        """Establish a clean test environment"""

        self.config(default_store='file')

        # NOTE(flaper87): Each store should test
        # this in their test suite.
        self.config(known_stores=VMWARE_DATASTORE_CONF['known_stores'])

        super(TestStore, self).setUp()

        Store.CHUNKSIZE = 2
        self.store = Store()

        class FakeSession:
            def __init__(self):
                self.vim = FakeVim()

        class FakeVim:
            def __init__(self):
                self.client = FakeClient()

        class FakeClient:
            def __init__(self):
                self.options = FakeOptions()

        class FakeOptions:
            def __init__(self):
                self.transport = FakeTransport()

        class FakeTransport:
            def __init__(self):
                self.cookiejar = FakeCookieJar()

        class FakeCookieJar:
            pass

        self.store.scheme = VMWARE_DATASTORE_CONF['default_store']
        self.store.server_host = (VMWARE_DATASTORE_CONF['vmware_server_host'])
        self.store.datacenter_path = (
            VMWARE_DATASTORE_CONF['vmware_datacenter_path'])
        self.store.datastore_name = (
            VMWARE_DATASTORE_CONF['vmware_datastore_name'])
        self.store.api_insecure = (
            VMWARE_DATASTORE_CONF['vmware_api_insecure'])
        self.store.api_retry_count = (
            VMWARE_DATASTORE_CONF['vmware_api_retry_count'])
        self.store._session = FakeSession()
        self.store._session.invoke_api = mock.Mock()
        self.store._session.wait_for_task = mock.Mock()

        self.store.store_image_dir = (
            VMWARE_DATASTORE_CONF['vmware_store_image_dir'])
        Store._build_vim_cookie_header = mock.Mock()
        self.addCleanup(self.stubs.UnsetAll)

    def test_get(self):
        """Test a "normal" retrieval of an image in chunks"""
        expected_image_size = 31
        expected_returns = [
            'I ', 'am', ' a', ' t', 'ea', 'po', 't,', ' s', 'ho', 'rt', ' a',
            'nd', ' s', 'to', 'ut', '\n'
        ]
        loc = get_location_from_uri(
            "vsphere://127.0.0.1/folder/openstack_glance/%s"
            "?dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection()
            (image_file, image_size) = self.store.get(loc)
        self.assertEqual(image_size, expected_image_size)
        chunks = [c for c in image_file]
        self.assertEqual(chunks, expected_returns)

    def test_get_non_existing(self):
        """
        Test that trying to retrieve an image that doesn't exist
        raises an error
        """
        loc = get_location_from_uri("vsphere://127.0.0.1/folder/openstack_glan"
                                    "ce/%s?dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection(status=404)
            self.assertRaises(exception.NotFound, self.store.get, loc)

    @mock.patch.object(vm_store._Reader, 'size')
    def test_add(self, fake_size):
        """Test that we can add an image via the VMware backend"""
        expected_image_id = str(uuid.uuid4())
        expected_size = FIVE_KB
        expected_contents = "*" * expected_size
        hash_code = hashlib.md5(expected_contents)
        expected_checksum = hash_code.hexdigest()
        fake_size.__get__ = mock.Mock(return_value=expected_size)
        with mock.patch('hashlib.md5') as md5:
            md5.return_value = hash_code
            expected_location = format_location(
                VMWARE_DATASTORE_CONF['vmware_server_host'],
                VMWARE_DATASTORE_CONF['vmware_store_image_dir'],
                expected_image_id,
                VMWARE_DATASTORE_CONF['vmware_datacenter_path'],
                VMWARE_DATASTORE_CONF['vmware_datastore_name'])
            image = six.StringIO(expected_contents)
            with mock.patch('httplib.HTTPConnection') as HttpConn:
                HttpConn.return_value = FakeHTTPConnection()
                location, size, checksum, _ = self.store.add(
                    expected_image_id, image, expected_size)
        self.assertEqual(expected_location, location)
        self.assertEqual(expected_size, size)
        self.assertEqual(expected_checksum, checksum)

    @mock.patch.object(vm_store._Reader, 'size')
    def test_add_size_zero(self, fake_size):
        """
        Test that when specifying size zero for the image to add,
        the actual size of the image is returned.
        """
        expected_image_id = str(uuid.uuid4())
        expected_size = FIVE_KB
        expected_contents = "*" * expected_size
        hash_code = hashlib.md5(expected_contents)
        expected_checksum = hash_code.hexdigest()
        fake_size.__get__ = mock.Mock(return_value=expected_size)
        with mock.patch('hashlib.md5') as md5:
            md5.return_value = hash_code
            expected_location = format_location(
                VMWARE_DATASTORE_CONF['vmware_server_host'],
                VMWARE_DATASTORE_CONF['vmware_store_image_dir'],
                expected_image_id,
                VMWARE_DATASTORE_CONF['vmware_datacenter_path'],
                VMWARE_DATASTORE_CONF['vmware_datastore_name'])
            image = six.StringIO(expected_contents)
            with mock.patch('httplib.HTTPConnection') as HttpConn:
                HttpConn.return_value = FakeHTTPConnection()
                location, size, checksum, _ = self.store.add(
                    expected_image_id, image, 0)
        self.assertEqual(expected_location, location)
        self.assertEqual(expected_size, size)
        self.assertEqual(expected_checksum, checksum)

    def test_delete(self):
        """Test we can delete an existing image in the VMware store"""
        loc = get_location_from_uri(
            "vsphere://127.0.0.1/folder/openstack_glance/%s?"
            "dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection()
            Store._service_content = mock.Mock()
            self.store.delete(loc)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection(status=404)
            self.assertRaises(exception.NotFound, self.store.get, loc)

    def test_get_size(self):
        """Test we can get the size of an existing image in the VMware store"""
        loc = get_location_from_uri(
            "vsphere://127.0.0.1/folder/openstack_glance/%s"
            "?dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection()
            image_size = self.store.get_size(loc)
        self.assertEqual(image_size, 31)

    def test_get_size_non_existing(self):
        """
        Test that trying to retrieve an image size that doesn't exist
        raises an error
        """
        loc = get_location_from_uri("vsphere://127.0.0.1/folder/openstack_glan"
                                    "ce/%s?dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection(status=404)
            self.assertRaises(exception.NotFound, self.store.get_size, loc)

    def test_reader_image_fits_in_blocksize(self):
        """
        Test that the image file reader returns the expected chunk of data
        when the block size is larger than the image.
        """
        content = 'XXX'
        image = six.StringIO(content)
        expected_checksum = hashlib.md5(content).hexdigest()
        checksum = hashlib.md5()
        reader = vm_store._Reader(image, checksum)
        ret = reader.read()
        expected_chunk = '%x\r\n%s\r\n' % (len(content), content)
        last_chunk = '0\r\n\r\n'
        self.assertEqual('%s%s' % (expected_chunk, last_chunk), ret)
        self.assertEqual(image.len, reader.size)
        self.assertEqual(expected_checksum, reader.checksum.hexdigest())
        self.assertTrue(reader.closed)
        ret = reader.read()
        self.assertEqual(image.len, reader.size)
        self.assertEqual(expected_checksum, reader.checksum.hexdigest())
        self.assertTrue(reader.closed)
        self.assertEqual('', ret)

    def test_reader_image_larger_blocksize(self):
        """
        Test that the image file reader returns the expected chunks when
        the block size specified is smaller than the image.
        """
        content = 'XXX'
        image = six.StringIO(content)
        expected_checksum = hashlib.md5(content).hexdigest()
        checksum = hashlib.md5()
        last_chunk = '0\r\n\r\n'
        reader = vm_store._Reader(image, checksum, blocksize=1)
        ret = reader.read()
        expected_chunk = '1\r\nX\r\n'
        self.assertEqual(
            '%s%s%s%s' %
            (expected_chunk, expected_chunk, expected_chunk, last_chunk), ret)
        self.assertEqual(expected_checksum, reader.checksum.hexdigest())
        self.assertEqual(image.len, reader.size)
        self.assertTrue(reader.closed)

    def test_reader_size(self):
        """Test that the image reader takes into account the specified size."""
        content = 'XXX'
        image = six.StringIO(content)
        expected_checksum = hashlib.md5(content).hexdigest()
        checksum = hashlib.md5()
        reader = vm_store._Reader(image, checksum, blocksize=1)
        ret = reader.read(size=3)
        self.assertEqual('1\r\n', ret)
        ret = reader.read(size=1)
        self.assertEqual('X', ret)
        ret = reader.read()
        self.assertEqual(expected_checksum, reader.checksum.hexdigest())
        self.assertEqual(image.len, reader.size)
        self.assertTrue(reader.closed)

    def test_sanity_check_api_retry_count(self):
        """Test that sanity check raises if api_retry_count is <= 0."""
        vm_store.CONF.vmware_api_retry_count = -1
        self.assertRaises(exception.BadStoreConfiguration,
                          self.store._sanity_check)
        vm_store.CONF.vmware_api_retry_count = 0
        self.assertRaises(exception.BadStoreConfiguration,
                          self.store._sanity_check)
        vm_store.CONF.vmware_api_retry_count = 1
        try:
            self.store._sanity_check()
        except exception.BadStoreConfiguration:
            self.fail()

    def test_sanity_check_task_poll_interval(self):
        """Test that sanity check raises if task_poll_interval is <= 0."""
        vm_store.CONF.vmware_task_poll_interval = -1
        self.assertRaises(exception.BadStoreConfiguration,
                          self.store._sanity_check)
        vm_store.CONF.vmware_task_poll_interval = 0
        self.assertRaises(exception.BadStoreConfiguration,
                          self.store._sanity_check)
        vm_store.CONF.vmware_task_poll_interval = 1
        try:
            self.store._sanity_check()
        except exception.BadStoreConfiguration:
            self.fail()

    def test_retry_count(self):
        expected_image_id = str(uuid.uuid4())
        expected_size = FIVE_KB
        expected_contents = "*" * expected_size
        image = six.StringIO(expected_contents)
        self.store._create_session = mock.Mock()
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection(status=401)
            try:
                location, size, checksum, _ = self.store.add(
                    expected_image_id, image, expected_size)
            except exception.NotAuthenticated:
                pass
        self.assertEqual(VMWARE_DATASTORE_CONF['vmware_api_retry_count'] + 1,
                         self.store._create_session.call_count)
Beispiel #6
0
class TestStore(base.StoreClearingUnitTest):

    @mock.patch('glance.store.vmware.api.VMwareAPISession', autospec=True)
    def setUp(self, mock_session):
        """Establish a clean test environment"""
        super(TestStore, self).setUp()
        Store.CHUNKSIZE = 2
        self.store = Store()

        class FakeSession:
            def __init__(self):
                self.vim = FakeVim()

        class FakeVim:
            def __init__(self):
                self.client = FakeClient()

        class FakeClient:
            def __init__(self):
                self.options = FakeOptions()

        class FakeOptions:
            def __init__(self):
                self.transport = FakeTransport()

        class FakeTransport:
            def __init__(self):
                self.cookiejar = FakeCookieJar()

        class FakeCookieJar:
            pass

        self.store.scheme = VMWARE_DATASTORE_CONF['default_store']
        self.store.server_host = (
            VMWARE_DATASTORE_CONF['vmware_server_host'])
        self.store.datacenter_path = (
            VMWARE_DATASTORE_CONF['vmware_datacenter_path'])
        self.store.datastore_name = (
            VMWARE_DATASTORE_CONF['vmware_datastore_name'])
        self.store.api_insecure = (
            VMWARE_DATASTORE_CONF['vmware_api_insecure'])
        self.store._session = FakeSession()
        self.store._session.invoke_api = mock.Mock()
        self.store._session.wait_for_task = mock.Mock()

        self.store.store_image_dir = (
            VMWARE_DATASTORE_CONF['vmware_store_image_dir'])
        Store._build_vim_cookie_header = mock.Mock()
        self.addCleanup(self.stubs.UnsetAll)

    def test_get(self):
        """Test a "normal" retrieval of an image in chunks"""
        expected_image_size = 31
        expected_returns = ['I ', 'am', ' a', ' t', 'ea', 'po', 't,', ' s',
                            'ho', 'rt', ' a', 'nd', ' s', 'to', 'ut', '\n']
        loc = get_location_from_uri(
            "vsphere://127.0.0.1/folder/openstack_glance/%s"
            "?dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection()
            (image_file, image_size) = self.store.get(loc)
        self.assertEqual(image_size, expected_image_size)
        chunks = [c for c in image_file]
        self.assertEqual(chunks, expected_returns)

    def test_get_non_existing(self):
        """
        Test that trying to retrieve an image that doesn't exist
        raises an error
        """
        loc = get_location_from_uri("vsphere://127.0.0.1/folder/openstack_glan"
                                    "ce/%s?dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection(status=404)
            self.assertRaises(exception.NotFound, self.store.get, loc)

    def test_add(self):
        """Test that we can add an image via the VMware backend"""
        expected_image_id = str(uuid.uuid4())
        expected_size = FIVE_KB
        expected_contents = "*" * expected_size
        hash_code = hashlib.md5(expected_contents)
        expected_checksum = hash_code.hexdigest()
        with mock.patch('hashlib.md5') as md5:
            md5.return_value = hash_code
            expected_location = format_location(
                VMWARE_DATASTORE_CONF['vmware_server_host'],
                VMWARE_DATASTORE_CONF['vmware_store_image_dir'],
                expected_image_id,
                VMWARE_DATASTORE_CONF['vmware_datacenter_path'],
                VMWARE_DATASTORE_CONF['vmware_datastore_name'])
            image = six.StringIO(expected_contents)
            with mock.patch('httplib.HTTPConnection') as HttpConn:
                HttpConn.return_value = FakeHTTPConnection()
                location, size, checksum, _ = self.store.add(expected_image_id,
                                                             image,
                                                             expected_size)
        self.assertEqual(expected_location, location)
        self.assertEqual(expected_size, size)
        self.assertEqual(expected_checksum, checksum)

    def test_delete(self):
        """Test we can delete an existing image in the VMware store"""
        loc = get_location_from_uri(
            "vsphere://127.0.0.1/folder/openstack_glance/%s?"
            "dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection()
            Store._service_content = mock.Mock()
            self.store.delete(loc)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection(status=404)
            self.assertRaises(exception.NotFound, self.store.get, loc)

    def test_get_size(self):
        """Test we can get the size of an existing image in the VMware store"""
        loc = get_location_from_uri(
            "vsphere://127.0.0.1/folder/openstack_glance/%s"
            "?dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection()
            image_size = self.store.get_size(loc)
        self.assertEqual(image_size, 31)

    def test_get_size_non_existing(self):
        """
        Test that trying to retrieve an image size that doesn't exist
        raises an error
        """
        loc = get_location_from_uri("vsphere://127.0.0.1/folder/openstack_glan"
                                    "ce/%s?dsName=ds1&dcPath=dc1" % FAKE_UUID)
        with mock.patch('httplib.HTTPConnection') as HttpConn:
            HttpConn.return_value = FakeHTTPConnection(status=404)
            self.assertRaises(exception.NotFound, self.store.get_size, loc)
Beispiel #7
0
class TestStore(base.StoreClearingUnitTest):
    @mock.patch("oslo.vmware.api.VMwareAPISession", autospec=True)
    def setUp(self, mock_session):
        """Establish a clean test environment"""

        self.config(default_store="file")

        # NOTE(flaper87): Each store should test
        # this in their test suite.
        self.config(known_stores=VMWARE_DATASTORE_CONF["known_stores"])

        super(TestStore, self).setUp()

        Store.READ_CHUNKSIZE = 2
        self.store = Store()

        class FakeSession:
            def __init__(self):
                self.vim = FakeVim()

        class FakeVim:
            def __init__(self):
                self.client = FakeClient()

        class FakeClient:
            def __init__(self):
                self.options = FakeOptions()

        class FakeOptions:
            def __init__(self):
                self.transport = FakeTransport()

        class FakeTransport:
            def __init__(self):
                self.cookiejar = FakeCookieJar()

        class FakeCookieJar:
            pass

        self.store.scheme = VMWARE_DATASTORE_CONF["default_store"]
        self.store.server_host = VMWARE_DATASTORE_CONF["vmware_server_host"]
        self.store.datacenter_path = VMWARE_DATASTORE_CONF["vmware_datacenter_path"]
        self.store.datastore_name = VMWARE_DATASTORE_CONF["vmware_datastore_name"]
        self.store.api_insecure = VMWARE_DATASTORE_CONF["vmware_api_insecure"]
        self.store.api_retry_count = VMWARE_DATASTORE_CONF["vmware_api_retry_count"]
        self.store._session = FakeSession()
        self.store._session.invoke_api = mock.Mock()
        self.store._session.wait_for_task = mock.Mock()

        self.store.store_image_dir = VMWARE_DATASTORE_CONF["vmware_store_image_dir"]
        Store._build_vim_cookie_header = mock.Mock()
        self.addCleanup(self.stubs.UnsetAll)

    def test_get(self):
        """Test a "normal" retrieval of an image in chunks"""
        expected_image_size = 31
        expected_returns = [
            "I ",
            "am",
            " a",
            " t",
            "ea",
            "po",
            "t,",
            " s",
            "ho",
            "rt",
            " a",
            "nd",
            " s",
            "to",
            "ut",
            "\n",
        ]
        loc = get_location_from_uri(
            "vsphere://127.0.0.1/folder/openstack_glance/%s" "?dsName=ds1&dcPath=dc1" % FAKE_UUID
        )
        with mock.patch("httplib.HTTPConnection") as HttpConn:
            HttpConn.return_value = FakeHTTPConnection()
            (image_file, image_size) = self.store.get(loc)
        self.assertEqual(image_size, expected_image_size)
        chunks = [c for c in image_file]
        self.assertEqual(chunks, expected_returns)

    def test_get_non_existing(self):
        """
        Test that trying to retrieve an image that doesn't exist
        raises an error
        """
        loc = get_location_from_uri(
            "vsphere://127.0.0.1/folder/openstack_glan" "ce/%s?dsName=ds1&dcPath=dc1" % FAKE_UUID
        )
        with mock.patch("httplib.HTTPConnection") as HttpConn:
            HttpConn.return_value = FakeHTTPConnection(status=404)
            self.assertRaises(exception.NotFound, self.store.get, loc)

    @mock.patch.object(vm_store._Reader, "size")
    def test_add(self, fake_size):
        """Test that we can add an image via the VMware backend"""
        expected_image_id = str(uuid.uuid4())
        expected_size = FIVE_KB
        expected_contents = "*" * expected_size
        hash_code = hashlib.md5(expected_contents)
        expected_checksum = hash_code.hexdigest()
        fake_size.__get__ = mock.Mock(return_value=expected_size)
        with mock.patch("hashlib.md5") as md5:
            md5.return_value = hash_code
            expected_location = format_location(
                VMWARE_DATASTORE_CONF["vmware_server_host"],
                VMWARE_DATASTORE_CONF["vmware_store_image_dir"],
                expected_image_id,
                VMWARE_DATASTORE_CONF["vmware_datacenter_path"],
                VMWARE_DATASTORE_CONF["vmware_datastore_name"],
            )
            image = six.StringIO(expected_contents)
            with mock.patch("httplib.HTTPConnection") as HttpConn:
                HttpConn.return_value = FakeHTTPConnection()
                location, size, checksum, _ = self.store.add(expected_image_id, image, expected_size)
        self.assertEqual(expected_location, location)
        self.assertEqual(expected_size, size)
        self.assertEqual(expected_checksum, checksum)

    @mock.patch.object(vm_store._Reader, "size")
    def test_add_size_zero(self, fake_size):
        """
        Test that when specifying size zero for the image to add,
        the actual size of the image is returned.
        """
        expected_image_id = str(uuid.uuid4())
        expected_size = FIVE_KB
        expected_contents = "*" * expected_size
        hash_code = hashlib.md5(expected_contents)
        expected_checksum = hash_code.hexdigest()
        fake_size.__get__ = mock.Mock(return_value=expected_size)
        with mock.patch("hashlib.md5") as md5:
            md5.return_value = hash_code
            expected_location = format_location(
                VMWARE_DATASTORE_CONF["vmware_server_host"],
                VMWARE_DATASTORE_CONF["vmware_store_image_dir"],
                expected_image_id,
                VMWARE_DATASTORE_CONF["vmware_datacenter_path"],
                VMWARE_DATASTORE_CONF["vmware_datastore_name"],
            )
            image = six.StringIO(expected_contents)
            with mock.patch("httplib.HTTPConnection") as HttpConn:
                HttpConn.return_value = FakeHTTPConnection()
                location, size, checksum, _ = self.store.add(expected_image_id, image, 0)
        self.assertEqual(expected_location, location)
        self.assertEqual(expected_size, size)
        self.assertEqual(expected_checksum, checksum)

    def test_delete(self):
        """Test we can delete an existing image in the VMware store"""
        loc = get_location_from_uri(
            "vsphere://127.0.0.1/folder/openstack_glance/%s?" "dsName=ds1&dcPath=dc1" % FAKE_UUID
        )
        with mock.patch("httplib.HTTPConnection") as HttpConn:
            HttpConn.return_value = FakeHTTPConnection()
            Store._service_content = mock.Mock()
            self.store.delete(loc)
        with mock.patch("httplib.HTTPConnection") as HttpConn:
            HttpConn.return_value = FakeHTTPConnection(status=404)
            self.assertRaises(exception.NotFound, self.store.get, loc)

    def test_get_size(self):
        """Test we can get the size of an existing image in the VMware store"""
        loc = get_location_from_uri(
            "vsphere://127.0.0.1/folder/openstack_glance/%s" "?dsName=ds1&dcPath=dc1" % FAKE_UUID
        )
        with mock.patch("httplib.HTTPConnection") as HttpConn:
            HttpConn.return_value = FakeHTTPConnection()
            image_size = self.store.get_size(loc)
        self.assertEqual(image_size, 31)

    def test_get_size_non_existing(self):
        """
        Test that trying to retrieve an image size that doesn't exist
        raises an error
        """
        loc = get_location_from_uri(
            "vsphere://127.0.0.1/folder/openstack_glan" "ce/%s?dsName=ds1&dcPath=dc1" % FAKE_UUID
        )
        with mock.patch("httplib.HTTPConnection") as HttpConn:
            HttpConn.return_value = FakeHTTPConnection(status=404)
            self.assertRaises(exception.NotFound, self.store.get_size, loc)

    def test_reader_full(self):
        content = "XXX"
        image = six.StringIO(content)
        expected_checksum = hashlib.md5(content).hexdigest()
        reader = vm_store._Reader(image)
        ret = reader.read()
        self.assertEqual(content, ret)
        self.assertEqual(expected_checksum, reader.checksum.hexdigest())
        self.assertEqual(len(content), reader.size)

    def test_reader_partial(self):
        content = "XXX"
        image = six.StringIO(content)
        expected_checksum = hashlib.md5("X").hexdigest()
        reader = vm_store._Reader(image)
        ret = reader.read(1)
        self.assertEqual("X", ret)
        self.assertEqual(expected_checksum, reader.checksum.hexdigest())
        self.assertEqual(1, reader.size)

    def test_rewind(self):
        content = "XXX"
        image = six.StringIO(content)
        expected_checksum = hashlib.md5(content).hexdigest()
        reader = vm_store._Reader(image)
        reader.read(1)
        ret = reader.read()
        self.assertEqual("XX", ret)
        self.assertEqual(expected_checksum, reader.checksum.hexdigest())
        self.assertEqual(len(content), reader.size)
        reader.rewind()
        ret = reader.read()
        self.assertEqual(content, ret)
        self.assertEqual(expected_checksum, reader.checksum.hexdigest())
        self.assertEqual(len(content), reader.size)

    def test_chunkreader_image_fits_in_blocksize(self):
        """
        Test that the image file reader returns the expected chunk of data
        when the block size is larger than the image.
        """
        content = "XXX"
        image = six.StringIO(content)
        expected_checksum = hashlib.md5(content).hexdigest()
        reader = vm_store._ChunkReader(image)
        ret = reader.read()
        expected_chunk = "%x\r\n%s\r\n" % (len(content), content)
        last_chunk = "0\r\n\r\n"
        self.assertEqual("%s%s" % (expected_chunk, last_chunk), ret)
        self.assertEqual(image.len, reader.size)
        self.assertEqual(expected_checksum, reader.checksum.hexdigest())
        self.assertTrue(reader.closed)
        ret = reader.read()
        self.assertEqual(image.len, reader.size)
        self.assertEqual(expected_checksum, reader.checksum.hexdigest())
        self.assertTrue(reader.closed)
        self.assertEqual("", ret)

    def test_chunkreader_image_larger_blocksize(self):
        """
        Test that the image file reader returns the expected chunks when
        the block size specified is smaller than the image.
        """
        content = "XXX"
        image = six.StringIO(content)
        expected_checksum = hashlib.md5(content).hexdigest()
        last_chunk = "0\r\n\r\n"
        reader = vm_store._ChunkReader(image, blocksize=1)
        ret = reader.read()
        expected_chunk = "1\r\nX\r\n"
        self.assertEqual("%s%s%s%s" % (expected_chunk, expected_chunk, expected_chunk, last_chunk), ret)
        self.assertEqual(expected_checksum, reader.checksum.hexdigest())
        self.assertEqual(image.len, reader.size)
        self.assertTrue(reader.closed)

    def test_chunkreader_size(self):
        """Test that the image reader takes into account the specified size."""
        content = "XXX"
        image = six.StringIO(content)
        expected_checksum = hashlib.md5(content).hexdigest()
        reader = vm_store._ChunkReader(image, blocksize=1)
        ret = reader.read(size=3)
        self.assertEqual("1\r\n", ret)
        ret = reader.read(size=1)
        self.assertEqual("X", ret)
        ret = reader.read()
        self.assertEqual(expected_checksum, reader.checksum.hexdigest())
        self.assertEqual(image.len, reader.size)
        self.assertTrue(reader.closed)

    def test_sanity_check_api_retry_count(self):
        """Test that sanity check raises if api_retry_count is <= 0."""
        vm_store.CONF.vmware_api_retry_count = -1
        self.assertRaises(exception.BadStoreConfiguration, self.store._sanity_check)
        vm_store.CONF.vmware_api_retry_count = 0
        self.assertRaises(exception.BadStoreConfiguration, self.store._sanity_check)
        vm_store.CONF.vmware_api_retry_count = 1
        try:
            self.store._sanity_check()
        except exception.BadStoreConfiguration:
            self.fail()

    def test_sanity_check_task_poll_interval(self):
        """Test that sanity check raises if task_poll_interval is <= 0."""
        vm_store.CONF.vmware_task_poll_interval = -1
        self.assertRaises(exception.BadStoreConfiguration, self.store._sanity_check)
        vm_store.CONF.vmware_task_poll_interval = 0
        self.assertRaises(exception.BadStoreConfiguration, self.store._sanity_check)
        vm_store.CONF.vmware_task_poll_interval = 1
        try:
            self.store._sanity_check()
        except exception.BadStoreConfiguration:
            self.fail()

    def test_retry_count(self):
        expected_image_id = str(uuid.uuid4())
        expected_size = FIVE_KB
        expected_contents = "*" * expected_size
        image = six.StringIO(expected_contents)
        self.store._create_session = mock.Mock()
        with mock.patch("httplib.HTTPConnection") as HttpConn:
            HttpConn.return_value = FakeHTTPConnection(status=401)
            try:
                location, size, checksum, _ = self.store.add(expected_image_id, image, expected_size)
            except exception.NotAuthenticated:
                pass
        self.assertEqual(VMWARE_DATASTORE_CONF["vmware_api_retry_count"] + 1, self.store._create_session.call_count)