def test_translate_fault(self): def fake_task(fault_class_name, error_msg=None): task_info = mock.Mock() task_info.localizedMessage = error_msg if fault_class_name: error_fault = mock.Mock() error_fault.__class__.__name__ = fault_class_name task_info.fault = error_fault return task_info error_msg = "OUCH" task = fake_task(exceptions.FILE_LOCKED, error_msg) actual = exceptions.translate_fault(task) expected = exceptions.FileLockedException(error_msg) self.assertEqual(expected.__class__, actual.__class__) self.assertEqual(expected.message, actual.message) error_msg = "Oopsie" task = fake_task(None, error_msg) actual = exceptions.translate_fault(task) expected = exceptions.VimFaultException(['Mock'], message=error_msg) self.assertEqual(expected.__class__, actual.__class__) self.assertEqual(expected.message, actual.message) self.assertEqual(expected.fault_list, actual.fault_list)
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(self): vfe = exceptions.VimFaultException([ValueError("example")], _("cause")) string = str(vfe) self.assertIn(string, [ "cause\nFaults: [ValueError('example',)]", "cause\nFaults: [ValueError('example')]" ])
def _poll_task(self, task, ctx): """Poll the given task until completion. If the task completes successfully, the method returns the task info using the input event (param done). In case of any error, appropriate exception is set in the event. :param task: managed object reference of the task :param ctx: request context for the corresponding task """ if ctx is not None: ctx.update_store() try: # we poll tasks too often, so skip logging the opID as it generates # too much noise in the logs task_info = self.invoke_api(vim_util, 'get_object_property', self.vim, task, 'info', skip_op_id=True) except exceptions.VimException: with excutils.save_and_reraise_exception(): LOG.exception("Error occurred while reading info of " "task: %s.", task) else: task_detail = {'id': task.value} # some internal tasks do not have 'name' set if getattr(task_info, 'name', None): task_detail['name'] = task_info.name if task_info.state in ['queued', 'running']: if hasattr(task_info, 'progress'): LOG.debug("Task: %(task)s progress is %(progress)s%%.", {'task': task_detail, 'progress': task_info.progress}) elif task_info.state == 'success': def get_completed_task(): complete_time = getattr(task_info, 'completeTime', None) if complete_time: duration = complete_time - task_info.queueTime task_detail['duration_secs'] = duration.total_seconds() return task_detail LOG.debug("Task: %s completed successfully.", get_completed_task()) raise loopingcall.LoopingCallDone(task_info) else: error_msg = six.text_type(task_info.error.localizedMessage) error = task_info.error name = error.fault.__class__.__name__ fault_class = exceptions.get_fault_class(name) if fault_class: task_ex = fault_class(error_msg) else: task_ex = exceptions.VimFaultException([name], error_msg) raise task_ex
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_unknown_fault(self): api_session = self._create_api_session(True) fault_list = ['NotAFile'] module = mock.Mock() module.api.side_effect = exceptions.VimFaultException( fault_list, 'Not a file.') ex = self.assertRaises(exceptions.VimFaultException, api_session.invoke_api, module, 'api') self.assertEqual(fault_list, ex.fault_list)
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_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 test_monitor_events_with_fault_exception(self, time_fn): self.vc_driver.state = constants.DRIVER_READY with mock.patch.object(self.LOG, 'info') as mock_info_log,\ mock.patch.object(self.vc_driver, "dispatch_events", ) as mock_dispatch_events, \ mock.patch.object(self.vc_driver, "_process_update_set", ) as mock_process_update_set, \ mock.patch.object(vim_util, 'wait_for_updates_ex', side_effect=exceptions.VimFaultException( [], None)) as mock_vim_fault_exception, \ mock.patch.object(self.LOG, 'exception') as mock_except_log: self.vc_driver.monitor_events() self.assertTrue(mock_info_log.called) self.assertFalse(mock_dispatch_events.called) self.assertFalse(mock_process_update_set.called) self.assertTrue(mock_vim_fault_exception.called) self.assertTrue(mock_except_log.called)
def _poll_task(self, task): """Poll the given task until completion. If the task completes successfully, the method returns the task info using the input event (param done). In case of any error, appropriate exception is set in the event. :param task: managed object reference of the task """ try: # we poll tasks too often, so skip logging the opID as it generates # too much noise in the logs task_info = self.invoke_api(vim_util, 'get_object_property', self.vim, task, 'info', skip_op_id=True) except exceptions.VimException: with excutils.save_and_reraise_exception(): LOG.exception( _LE("Error occurred while reading info of " "task: %s."), task) else: if task_info.state in ['queued', 'running']: if hasattr(task_info, 'progress'): LOG.debug("Task: %(task)s progress is %(progress)s%%.", { 'task': task, 'progress': task_info.progress }) elif task_info.state == 'success': LOG.debug("Task: %s status is success.", task) raise loopingcall.LoopingCallDone(task_info) else: error_msg = six.text_type(task_info.error.localizedMessage) error = task_info.error name = error.fault.__class__.__name__ fault_class = exceptions.get_fault_class(name) if fault_class: task_ex = fault_class(error_msg) else: task_ex = exceptions.VimFaultException([name], error_msg) raise task_ex
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'] = \ vim_util.get_moref_value(f_type.object) 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 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_type = fault.get('type') if fault_type.endswith(exceptions.SECURITY_ERROR): fault_type = exceptions.NOT_AUTHENTICATED fault_list.append(fault_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 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 api(*args, **kwargs): raise exceptions.VimFaultException([], None)
def api(*args, **kwargs): raise exceptions.VimFaultException([exceptions.NOT_AUTHENTICATED], None)