diff options
author | Jenkins <jenkins@review.openstack.org> | 2015-02-19 22:37:17 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2015-02-19 22:37:17 +0000 |
commit | 45b55585c70e3f073895007cc3b3f0a23f96efb4 (patch) | |
tree | d40c3c36e7cd1e39bb403a574ed5c2fa3e8fe0d1 | |
parent | 138875b7c3051a4f92616df56bffb8c91e669d88 (diff) | |
parent | e1ee81a37fb7504ed482225b73212082e5d7c4b1 (diff) | |
download | glance_store-45b55585c70e3f073895007cc3b3f0a23f96efb4.tar.gz |
Merge "Check VMware session before uploading image"0.1.11
-rw-r--r-- | glance_store/_drivers/vmware_datastore.py | 33 | ||||
-rw-r--r-- | tests/unit/test_vmware_store.py | 37 |
2 files changed, 59 insertions, 11 deletions
diff --git a/glance_store/_drivers/vmware_datastore.py b/glance_store/_drivers/vmware_datastore.py index b5cec78..2ac2413 100644 --- a/glance_store/_drivers/vmware_datastore.py +++ b/glance_store/_drivers/vmware_datastore.py @@ -296,8 +296,11 @@ class Store(glance_store.Store): store_name='vmware_datastore', reason=reason) return result - def _build_vim_cookie_header(self, vim_cookies): + def _build_vim_cookie_header(self, verify_session=False): """Build ESX host session cookie header.""" + if verify_session and not self.session.is_current_session_active(): + self.reset_session(force=True) + vim_cookies = self.session.vim.client.options.transport.cookiejar if len(list(vim_cookies)) > 0: cookie = list(vim_cookies)[0] return cookie.name + '=' + cookie.value @@ -335,18 +338,31 @@ class Store(glance_store.Store): 'datastore_name': self.datastore_name, 'image_id': image_id}, self.conf) # NOTE(arnaud): use a decorator when the config is not tied to self - cookie = self._build_vim_cookie_header( - self.session.vim.client.options.transport.cookiejar) + cookie = self._build_vim_cookie_header(True) headers = dict(headers.items() + {'Cookie': cookie}.items()) + conn_class = self._get_http_conn_class() + conn = conn_class(loc.server_host) + url = urlparse.quote('%s?%s' % (loc.path, loc.query)) try: - conn = self._get_http_conn('PUT', loc, headers, - content=image_file) - res = conn.getresponse() + conn.request('PUT', url, image_file, headers) + except IOError as e: + # When a session is not authenticated, the socket is closed by + # the server after sending the response. httplib has an open + # issue with https that raises Broken Pipe + # error instead of returning the response. + # See http://bugs.python.org/issue16062. Here, we log the error + # and continue to look into the response. + msg = _LE('Communication error sending http %(method)s request' + 'to the url %(url)s.\n' + 'Got IOError %(e)s') % {'method': 'PUT', + 'url': url, + 'e': e} + LOG.error(msg) except Exception: with excutils.save_and_reraise_exception(): LOG.exception(_LE('Failed to upload content of image ' '%(image)s'), {'image': image_id}) - + res = conn.getresponse() if res.status == httplib.CONFLICT: raise exceptions.Duplicate(_("Image file %(image_id)s already " "exists!") % @@ -434,8 +450,7 @@ class Store(glance_store.Store): loc = location.store_location # NOTE(arnaud): use a decorator when the config is not tied to self for i in range(self.api_retry_count + 1): - cookie = self._build_vim_cookie_header( - self.session.vim.client.options.transport.cookiejar) + cookie = self._build_vim_cookie_header() headers = {'Cookie': cookie} try: conn = self._get_http_conn(method, loc, headers) diff --git a/tests/unit/test_vmware_store.py b/tests/unit/test_vmware_store.py index 9f1e0a0..b69a67c 100644 --- a/tests/unit/test_vmware_store.py +++ b/tests/unit/test_vmware_store.py @@ -82,7 +82,7 @@ class FakeHTTPConnection(object): class TestStore(base.StoreBaseTest, test_store_capabilities.TestStoreCapabilitiesChecking): - @mock.patch('oslo.vmware.api.VMwareAPISession', auptospec=True) + @mock.patch('oslo.vmware.api.VMwareAPISession', autospec=True) def setUp(self, mock_session): """Establish a clean test environment.""" super(TestStore, self).setUp() @@ -104,7 +104,6 @@ class TestStore(base.StoreBaseTest, self.store.store_image_dir = ( VMWARE_DS['vmware_store_image_dir']) - vm_store.Store._build_vim_cookie_header = mock.Mock() def test_get(self): """Test a "normal" retrieval of an image in chunks.""" @@ -351,3 +350,37 @@ class TestStore(base.StoreBaseTest, self.assertFalse(mock_api_session.called) self.store.reset_session(force=True) self.assertTrue(mock_api_session.called) + + @mock.patch.object(api, 'VMwareAPISession') + def test_build_vim_cookie_header_active(self, mock_api_session): + self.store.session.is_current_session_active = mock.Mock() + self.store.session.is_current_session_active.return_value = True + self.store._build_vim_cookie_header(True) + self.assertFalse(mock_api_session.called) + + @mock.patch.object(api, 'VMwareAPISession') + def test_build_vim_cookie_header_expired(self, mock_api_session): + self.store.session.is_current_session_active = mock.Mock() + self.store.session.is_current_session_active.return_value = False + self.store._build_vim_cookie_header(True) + self.assertTrue(mock_api_session.called) + + @mock.patch.object(api, 'VMwareAPISession') + def test_build_vim_cookie_header_expired_noverify(self, mock_api_session): + self.store.session.is_current_session_active = mock.Mock() + self.store.session.is_current_session_active.return_value = False + self.store._build_vim_cookie_header() + self.assertFalse(mock_api_session.called) + + @mock.patch.object(api, 'VMwareAPISession') + def test_add_ioerror(self, mock_api_session): + expected_image_id = str(uuid.uuid4()) + expected_size = FIVE_KB + expected_contents = "*" * expected_size + image = six.StringIO(expected_contents) + self.session = mock.Mock() + with mock.patch('httplib.HTTPConnection') as HttpConn: + HttpConn.request.side_effect = IOError + self.assertRaises(exceptions.BackendException, + self.store.add, + expected_image_id, image, expected_size) |