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)
Exemple #2
0
    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')]"
     ])
Exemple #4
0
    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
Exemple #5
0
 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)
Exemple #6
0
    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)
Exemple #7
0
 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)
Exemple #8
0
    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)
Exemple #10
0
    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
Exemple #11
0
    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)
Exemple #12
0
        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)
Exemple #13
0
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)
Exemple #14
0
def fake_session_file_exception():
    fault_list = [vexc.FILE_ALREADY_EXISTS]
    raise vexc.VimFaultException(fault_list, Exception('fake'))
Exemple #15
0
def fake_temp_method_exception():
    raise vexc.VimFaultException([vexc.NOT_AUTHENTICATED],
                                 "Session Empty/Not Authenticated")
Exemple #16
0
 def api(*args, **kwargs):
     raise exceptions.VimFaultException([], None)
Exemple #17
0
 def api(*args, **kwargs):
     raise exceptions.VimFaultException([exceptions.NOT_AUTHENTICATED],
                                        None)