def write(self, data): """Write data to the file. :param data: data to be written :raises: VimConnectionException, VimException """ LOG.debug("Writing data to VMDK file with URL = %s.", self._url) try: self._file_handle.send(data) self._bytes_written += len(data) LOG.debug( "Total %(bytes_written)d bytes written to VMDK file " "with URL = %(url)s.", { 'bytes_written': self._bytes_written, 'url': self._url }) except (socket.error, httplib.NotConnected) as excep: excep_msg = _("Connection error occurred while writing data to" " %s.") % self._url LOG.exception(excep_msg) raise exceptions.VimConnectionException(excep_msg, excep) except Exception as excep: # TODO(vbala) We need to catch and raise specific exceptions # related to connection problems, invalid request and invalid # arguments. excep_msg = _("Error occurred while writing data to" " %s.") % self._url LOG.exception(excep_msg) raise exceptions.VimException(excep_msg, excep)
def _create_connection(self, url, file_size, cookies): """Create HTTP connection to write to the file with given URL.""" LOG.debug( "Creating HTTP connection to write to file with " "size = %(file_size)d and URL = %(url)s.", { 'file_size': file_size, 'url': url }) _urlparse = urlparse.urlparse(url) scheme, netloc, path, params, query, fragment = _urlparse try: if scheme == 'http': conn = httplib.HTTPConnection(netloc) elif scheme == 'https': conn = httplib.HTTPSConnection(netloc) else: excep_msg = _("Invalid scheme: %s.") % scheme LOG.error(excep_msg) raise ValueError(excep_msg) conn.putrequest('PUT', path + '?' + query) conn.putheader('User-Agent', USER_AGENT) conn.putheader('Content-Length', file_size) conn.putheader('Cookie', self._build_vim_cookie_header(cookies)) conn.endheaders() return conn except (httplib.InvalidURL, httplib.CannotSendRequest, httplib.CannotSendHeader) as excep: excep_msg = _("Error occurred while creating HTTP connection " "to write to file with URL = %s.") % url LOG.exception(excep_msg) raise exceptions.VimConnectionException(excep_msg, excep)
def connect(self, method, content_length, cookie): try: if self._scheme == 'http': conn = httplib.HTTPConnection(self._server) elif self._scheme == 'https': conn = httplib.HTTPSConnection(self._server) else: excep_msg = _("Invalid scheme: %s.") % self._scheme LOG.error(excep_msg) raise ValueError(excep_msg) conn.putrequest(method, '/folder/%s?%s' % (self.path, self._query)) conn.putheader('User-Agent', constants.USER_AGENT) conn.putheader('Content-Length', content_length) conn.putheader('Cookie', cookie) conn.endheaders() LOG.debug( "Created HTTP connection to transfer the file with " "URL = %s.", str(self)) return conn except (httplib.InvalidURL, httplib.CannotSendRequest, httplib.CannotSendHeader) as excep: excep_msg = _("Error occurred while creating HTTP connection " "to write to file with URL = %s.") % str(self) LOG.exception(excep_msg) raise exceptions.VimConnectionException(excep_msg, excep)
def _invoke_api(module, method, *args, **kwargs): try: api_method = getattr(module, method) return api_method(*args, **kwargs) except exceptions.VimFaultException as excep: # If this is due to an inactive session, we should re-create # the session and retry. if exceptions.NOT_AUTHENTICATED in excep.fault_list: # The NotAuthenticated fault is set by the fault checker # due to an empty response. An empty response could be a # valid response; for e.g., response for the query to # return the VMs in an ESX server which has no VMs in it. # Also, the server responds with an empty response in the # case of an inactive session. Therefore, we need a way to # differentiate between these two cases. if self._is_current_session_active(): LOG.debug( "Returning empty response for " "%(module)s.%(method)s invocation.", { 'module': module, 'method': method }) return [] else: # empty response is due to an inactive session excep_msg = ( _("Current session: %(session)s is inactive; " "re-creating the session while invoking " "method %(module)s.%(method)s.") % { 'session': _trunc_id(self._session_id), 'module': module, 'method': method }) LOG.warn(excep_msg, exc_info=True) self._create_session() raise exceptions.VimConnectionException( excep_msg, excep) else: # no need to retry for other VIM faults like # InvalidArgument # Raise specific exceptions here if possible if excep.fault_list: LOG.debug("Fault list: %s", excep.fault_list) fault = excep.fault_list[0] clazz = exceptions.get_fault_class(fault) raise clazz(unicode(excep), excep.details) raise except exceptions.VimConnectionException: with excutils.save_and_reraise_exception(): # Re-create the session during connection exception. LOG.warn(_LW("Re-creating session due to connection " "problems while invoking method " "%(module)s.%(method)s."), { 'module': module, 'method': method }, exc_info=True) self._create_session()
def test_invoke_api_with_expected_exception(self): api_session = self._create_api_session(True) ret = mock.Mock() responses = [exceptions.VimConnectionException(None), ret] def api(*args, **kwargs): response = responses.pop(0) if isinstance(response, Exception): raise response return response module = mock.Mock() module.api = api self.assertEqual(ret, api_session.invoke_api(module, 'api'))
def test_invoke_api_not_recreate_session(self): api_session = self._create_api_session(True) api_session._create_session = mock.Mock() vim_obj = api_session.vim vim_obj.SessionIsActive.return_value = True ret = mock.Mock() responses = [exceptions.VimConnectionException(None), ret] def api(*args, **kwargs): response = responses.pop(0) if isinstance(response, Exception): raise response return response module = mock.Mock() module.api = api with mock.patch.object(greenthread, 'sleep'): self.assertEqual(ret, api_session.invoke_api(module, 'api')) self.assertFalse(api_session._create_session.called)
def _create_connection(self, session, url, vmdk_size): """Create HTTP connection to write to VMDK file.""" LOG.debug( "Creating HTTP connection to write to VMDK file with " "size = %(vmdk_size)d and URL = %(url)s.", { 'vmdk_size': vmdk_size, 'url': url }) cookies = session.vim.client.options.transport.cookiejar _urlparse = urlparse.urlparse(url) scheme, netloc, path, params, query, fragment = _urlparse try: if scheme == 'http': conn = httplib.HTTPConnection(netloc) elif scheme == 'https': conn = httplib.HTTPSConnection(netloc) else: excep_msg = _("Invalid scheme: %s.") % scheme LOG.error(excep_msg) raise ValueError(excep_msg) if query: path = path + '?' + query conn.putrequest('PUT', path) conn.putheader('User-Agent', USER_AGENT) conn.putheader('Content-Length', str(vmdk_size)) conn.putheader('Overwrite', 't') conn.putheader('Cookie', self._build_vim_cookie_header(cookies)) conn.putheader('Content-Type', 'binary/octet-stream') conn.endheaders() LOG.debug( "Created HTTP connection to write to VMDK file with " "URL = %s.", url) return conn except (httplib.InvalidURL, httplib.CannotSendRequest, httplib.CannotSendHeader) as excep: excep_msg = _("Error occurred while creating HTTP connection " "to write to VMDK file with URL = %s.") % url LOG.exception(excep_msg) raise exceptions.VimConnectionException(excep_msg, excep)
def write(self, data): """Write data to the file. :param data: data to be written :raises: VimConnectionException, VimException """ try: self._file_handle.send(data) except (socket.error, httplib.NotConnected) as excep: excep_msg = _("Connection error occurred while writing data to" " %s.") % self._url LOG.exception(excep_msg) raise exceptions.VimConnectionException(excep_msg, excep) except Exception as excep: # TODO(vbala) We need to catch and raise specific exceptions # related to connection problems, invalid request and invalid # arguments. excep_msg = _("Error occurred while writing data to" " %s.") % self._url LOG.exception(excep_msg) raise exceptions.VimException(excep_msg, excep)
def fake_temp_session_exception(): raise vexc.VimConnectionException("it's a fake!", "Session Exception")
def vim_request_handler(managed_object, **kwargs): """Handler for VIM API calls. Invokes the API and parses the response for fault checking and other errors. :param managed_object: managed object reference argument of the API call :param kwargs: keyword arguments of the API call :returns: response of the API call :raises: VimException, VimFaultException, VimAttributeException, VimSessionOverLoadException, VimConnectionException """ try: if isinstance(managed_object, str): # For strings, use string value for value and type # of the managed object. managed_object = vim_util.get_moref( managed_object, managed_object) request = getattr(self.client.service, attr_name) LOG.debug(_("Invoking %(attr_name)s on %(moref)s."), { 'attr_name': attr_name, 'moref': managed_object }) response = request(managed_object, **kwargs) if (attr_name.lower() == 'retrievepropertiesex'): Vim._retrieve_properties_ex_fault_checker(response) LOG.debug( _("Invocation of %(attr_name)s on %(moref)s " "completed successfully."), { 'attr_name': attr_name, 'moref': managed_object }) return response except exceptions.VimFaultException: # Catch the VimFaultException that is raised by the fault # check of the SOAP response. raise except suds.WebFault as excep: doc = excep.document detail = doc.childAtPath('/Envelope/Body/Fault/detail') fault_list = [] if detail: for child in detail.getChildren(): fault_list.append(child.get('type')) raise exceptions.VimFaultException( fault_list, _("Web fault in %s.") % attr_name, excep) except AttributeError as excep: raise exceptions.VimAttributeException( _("No such SOAP method %s.") % attr_name, excep) except (httplib.CannotSendRequest, httplib.ResponseNotReady, httplib.CannotSendHeader) as excep: raise exceptions.VimSessionOverLoadException( _("httplib error in %s.") % attr_name, excep) except (urllib2.URLError, urllib2.HTTPError) as excep: raise exceptions.VimConnectionException( _("urllib2 error in %s.") % attr_name, excep) except Exception as excep: # TODO(vbala) should catch specific exceptions and raise # appropriate VimExceptions. # Socket errors which need special handling; some of these # might be caused by server API call overload. if (six.text_type(excep).find(ADDRESS_IN_USE_ERROR) != -1 or six.text_type(excep).find(CONN_ABORT_ERROR)) != -1: raise exceptions.VimSessionOverLoadException( _("Socket error in %s.") % attr_name, excep) # Type error which needs special handling; it might be caused # by server API call overload. elif six.text_type(excep).find(RESP_NOT_XML_ERROR) != -1: raise exceptions.VimSessionOverLoadException( _("Type error in %s.") % attr_name, excep) else: raise exceptions.VimException( _("Exception in %s.") % attr_name, excep)
def request_handler(managed_object, **kwargs): """Handler for vSphere API calls. Invokes the API and parses the response for fault checking and other errors. :param managed_object: managed object reference argument of the API call :param kwargs: keyword arguments of the API call :returns: response of the API call :raises: VimException, VimFaultException, VimAttributeException, VimSessionOverLoadException, VimConnectionException """ try: if isinstance(managed_object, str): # For strings, use string value for value and type # of the managed object. managed_object = vim_util.get_moref(managed_object, managed_object) if managed_object is None: return request = getattr(self.client.service, attr_name) response = request(managed_object, **kwargs) if (attr_name.lower() == 'retrievepropertiesex'): Service._retrieve_properties_ex_fault_checker(response) return response except exceptions.VimFaultException: # Catch the VimFaultException that is raised by the fault # check of the SOAP response. raise except suds.WebFault as excep: fault_string = None if excep.fault: fault_string = excep.fault.faultstring doc = excep.document detail = None if doc is not None: detail = doc.childAtPath('/detail') if not detail: # NOTE(arnaud): this is needed with VC 5.1 detail = doc.childAtPath('/Envelope/Body/Fault/detail') fault_list = [] details = {} if detail: for fault in detail.getChildren(): fault_list.append(fault.get("type")) for child in fault.getChildren(): details[child.name] = child.getText() raise exceptions.VimFaultException(fault_list, fault_string, excep, details) except AttributeError as excep: raise exceptions.VimAttributeException( _("No such SOAP method %s.") % attr_name, excep) except (httplib.CannotSendRequest, httplib.ResponseNotReady, httplib.CannotSendHeader) as excep: raise exceptions.VimSessionOverLoadException( _("httplib error in %s.") % attr_name, excep) except requests.RequestException as excep: raise exceptions.VimConnectionException( _("requests error in %s.") % attr_name, excep) except Exception as excep: # TODO(vbala) should catch specific exceptions and raise # appropriate VimExceptions. # Socket errors which need special handling; some of these # might be caused by server API call overload. if (six.text_type(excep).find(ADDRESS_IN_USE_ERROR) != -1 or six.text_type(excep).find(CONN_ABORT_ERROR)) != -1: raise exceptions.VimSessionOverLoadException( _("Socket error in %s.") % attr_name, excep) # Type error which needs special handling; it might be caused # by server API call overload. elif six.text_type(excep).find(RESP_NOT_XML_ERROR) != -1: raise exceptions.VimSessionOverLoadException( _("Type error in %s.") % attr_name, excep) else: raise exceptions.VimException( _("Exception in %s.") % attr_name, excep)