def test_invoke_api_with_stale_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 = False result = mock.Mock() responses = [ exceptions.VimFaultException([exceptions.NOT_AUTHENTICATED], None), result ] 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'): ret = api_session.invoke_api(module, 'api') self.assertEqual(result, ret) vim_obj.SessionIsActive.assert_called_once_with( vim_obj.service_content.sessionManager, sessionID=api_session._session_id, userName=api_session._session_username) api_session._create_session.assert_called_once_with()
def test_vim_fault_exception_with_cause_and_details(self): vfe = exceptions.VimFaultException([ValueError("example")], "MyMessage", "FooBar", {'foo': 'bar'}) string = str(vfe) self.assertEqual( "MyMessage\n" "Cause: FooBar\n" "Faults: [ValueError('example',)]\n" "Details: {'foo': 'bar'}", string)
def test_logout_with_exception(self): session = mock.Mock() session.key = "12345" api_session = self._create_api_session(False) vim_obj = api_session.vim vim_obj.Login.return_value = session vim_obj.Logout.side_effect = exceptions.VimFaultException([], None) api_session._create_session() api_session.logout() self.assertEqual("12345", api_session._session_id)
def test_invoke_api_with_vim_fault_exception_details(self): api_session = self._create_api_session(True) fault_string = 'Invalid property.' fault_list = [exceptions.INVALID_PROPERTY] details = {u'name': suds.sax.text.Text(u'фира')} module = mock.Mock() module.api.side_effect = exceptions.VimFaultException(fault_list, fault_string, details=details) e = self.assertRaises(exceptions.InvalidPropertyException, api_session.invoke_api, module, 'api') details_str = u"{'name': 'фира'}" expected_str = "%s\nFaults: %s\nDetails: %s" % ( fault_string, fault_list, details_str) self.assertEqual(expected_str, six.text_type(e)) self.assertEqual(details, e.details)
def _retrieve_properties_ex_fault_checker(response): """Checks the RetrievePropertiesEx API response for errors. Certain faults are sent in the SOAP body as a property of missingSet. This method raises VimFaultException when a fault is found in the response. :param response: response from RetrievePropertiesEx API call :raises: VimFaultException """ # TODO(rgerganov) this method doesn't belong here because this fault # checking is specific to the Vim service. We should come up with # a new design that allows extensible fault checking and have the # service specific parts in the corresponding child classes LOG.debug("Checking RetrievePropertiesEx API response for faults.") fault_list = [] if not response: # This is the case when the session has timed out. ESX SOAP # server sends an empty RetrievePropertiesExResponse. Normally # missingSet in the response objects has the specifics about # the error, but that's not the case with a timed out idle # session. It is as bad as a terminated session for we cannot # use the session. Therefore setting fault to NotAuthenticated # fault. LOG.debug( "RetrievePropertiesEx API response is empty; setting " "fault to %s.", exceptions.NOT_AUTHENTICATED) fault_list = [exceptions.NOT_AUTHENTICATED] else: for obj_cont in response.objects: if hasattr(obj_cont, 'missingSet'): for missing_elem in obj_cont.missingSet: fault_type = missing_elem.fault.fault.__class__ fault_list.append(fault_type.__name__) if fault_list: LOG.error( _LE("Faults %s found in RetrievePropertiesEx API " "response."), fault_list) raise exceptions.VimFaultException( fault_list, _("Error occurred while calling" " RetrievePropertiesEx.")) LOG.debug("No faults found in RetrievePropertiesEx API response.")
def _retrieve_properties_ex_fault_checker(response): """Checks the RetrievePropertiesEx API response for errors. Certain faults are sent in the SOAP body as a property of missingSet. This method raises VimFaultException when a fault is found in the response. :param response: response from RetrievePropertiesEx API call :raises: VimFaultException """ fault_list = [] details = {} if not response: # This is the case when the session has timed out. ESX SOAP # server sends an empty RetrievePropertiesExResponse. Normally # missingSet in the response objects has the specifics about # the error, but that's not the case with a timed out idle # session. It is as bad as a terminated session for we cannot # use the session. Therefore setting fault to NotAuthenticated # fault. LOG.debug("RetrievePropertiesEx API response is empty; setting " "fault to %s.", exceptions.NOT_AUTHENTICATED) fault_list = [exceptions.NOT_AUTHENTICATED] else: for obj_cont in response.objects: if hasattr(obj_cont, 'missingSet'): for missing_elem in obj_cont.missingSet: f_type = missing_elem.fault.fault f_name = f_type.__class__.__name__ fault_list.append(f_name) if f_name == exceptions.NO_PERMISSION: details['object'] = f_type.object.value details['privilegeId'] = f_type.privilegeId if fault_list: fault_string = _("Error occurred while calling " "RetrievePropertiesEx.") raise exceptions.VimFaultException(fault_list, fault_string, details=details)
def fake_session_permission_exception(): fault_list = [vexc.NO_PERMISSION] fault_string = 'Permission to perform this operation was denied.' details = {'privilegeId': 'Resource.AssignVMToPool', 'object': 'domain-c7'} raise vexc.VimFaultException(fault_list, fault_string, details=details)
def fake_session_file_exception(): fault_list = [vexc.FILE_ALREADY_EXISTS] raise vexc.VimFaultException(fault_list, Exception('fake'))
def fake_temp_method_exception(): raise vexc.VimFaultException([vexc.NOT_AUTHENTICATED], "Session Empty/Not Authenticated")
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)
def test_vim_fault_exception(self): vfe = exceptions.VimFaultException([ValueError("example")], _("cause")) string = str(vfe) self.assertEqual("cause\nFaults: [ValueError('example',)]", string)
def api(*args, **kwargs): raise exceptions.VimFaultException([exceptions.NOT_AUTHENTICATED], None)
def api(*args, **kwargs): raise exceptions.VimFaultException([], None)