def test_invoke_api_with_expected_exception(self): api_session = self._create_api_session(True) ret = mock.Mock() responses = [error_util.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'))
def vim_request_handler(managed_object, **kwargs): """Handler for VI SDK calls. Builds the SOAP message and parses the response for fault checking and other errors. :param managed_object:Managed object reference :param kwargs: Keyword arguments of the call :return: Response of the API call """ try: if isinstance(managed_object, str): # For strings use string value for value and type # of the managed object. managed_object = get_moref(managed_object, managed_object) request = getattr(self.client.service, attr_name) response = request(managed_object, **kwargs) if (attr_name.lower() == 'retrievepropertiesex'): retrieve_properties_ex_fault_checker(response) return response except error_util.VimFaultException as excep: raise except suds.WebFault as excep: doc = excep.document detail = doc.childAtPath('/Envelope/Body/Fault/detail') fault_list = [] for child in detail.getChildren(): fault_list.append(child.get('type')) raise error_util.VimFaultException(fault_list, excep) except AttributeError as excep: raise error_util.VimAttributeException( _("No such SOAP method " "%(attr)s. Detailed " "error: %(excep)s.") % { 'attr': attr_name, 'excep': excep }) except (httplib.CannotSendRequest, httplib.ResponseNotReady, httplib.CannotSendHeader) as excep: raise error_util.SessionOverLoadException( _("httplib error in " "%(attr)s: " "%(excep)s.") % { 'attr': attr_name, 'excep': excep }) except (urllib2.URLError, urllib2.HTTPError) as excep: raise error_util.VimConnectionException( _("urllib2 error in %(attr)s: %(excep)s.") % { 'attr': attr_name, 'excep': excep }) except Exception as excep: # Socket errors which need special handling for they # might be caused by server API call overload if (str(excep).find(ADDRESS_IN_USE_ERROR) != -1 or str(excep).find(CONN_ABORT_ERROR)) != -1: raise error_util.SessionOverLoadException( _("Socket error " "in %(attr)s: " "%(excep)s.") % { 'attr': attr_name, 'excep': excep }) # Type error that needs special handling for it might be # caused by server API call overload elif str(excep).find(RESP_NOT_XML_ERROR) != -1: raise error_util.SessionOverLoadException( _("Type error " "in %(attr)s: " "%(excep)s.") % { 'attr': attr_name, 'excep': excep }) else: raise error_util.VimException( _("Error in %(attr)s. " "Detailed error: " "%(excep)s.") % { 'attr': attr_name, 'excep': excep })
def test_select_datastore(self, filter_datastores, get_profile_id): # Test with no hosts. size_bytes = units.Ki req = {self._ds_sel.SIZE_BYTES: size_bytes} self._vops.get_hosts.return_value = mock.Mock(objects=[]) self.assertEqual((), self._ds_sel.select_datastore(req)) self._vops.get_hosts.assert_called_once_with() # Test with single host with no valid datastores. host_1 = mock.sentinel.host_1 self._vops.get_hosts.return_value = mock.Mock( objects=[mock.Mock(obj=host_1)]) self._vops.continue_retrieval.return_value = None self._vops.get_dss_rp.side_effect = error_util.VimException('error') self.assertEqual((), self._ds_sel.select_datastore(req)) self._vops.get_dss_rp.assert_called_once_with(host_1) # Test with three hosts and vCenter connection problem while fetching # datastores for the second host. self._vops.get_dss_rp.reset_mock() host_2 = mock.sentinel.host_2 host_3 = mock.sentinel.host_3 self._vops.get_hosts.return_value = mock.Mock(objects=[ mock.Mock(obj=host_1), mock.Mock(obj=host_2), mock.Mock(obj=host_3) ]) self._vops.get_dss_rp.side_effect = [ error_util.VimException('no valid datastores'), error_util.VimConnectionException('connection error') ] self.assertRaises(error_util.VimConnectionException, self._ds_sel.select_datastore, req) get_dss_rp_exp_calls = [mock.call(host_1), mock.call(host_2)] self.assertEqual(get_dss_rp_exp_calls, self._vops.get_dss_rp.call_args_list) # Modify previous case to return datastores for second and third host, # where none of them meet the requirements which include a storage # profile and affinity requirements. aff_ds_types = [ds_sel.DatastoreType.VMFS] req[ds_sel.DatastoreSelector.HARD_AFFINITY_DS_TYPE] = aff_ds_types ds_1a = mock.sentinel.ds_1a anti_affinity_ds = [ds_1a] req[ds_sel.DatastoreSelector.HARD_ANTI_AFFINITY_DS] = anti_affinity_ds profile_name = mock.sentinel.profile_name req[ds_sel.DatastoreSelector.PROFILE_NAME] = profile_name profile_id = mock.sentinel.profile_id get_profile_id.return_value = profile_id ds_2a = mock.sentinel.ds_2a ds_2b = mock.sentinel.ds_2b ds_3a = mock.sentinel.ds_3a self._vops.get_dss_rp.reset_mock() rp_2 = mock.sentinel.rp_2 rp_3 = mock.sentinel.rp_3 self._vops.get_dss_rp.side_effect = [ error_util.VimException('no valid datastores'), ([ds_2a, ds_2b], rp_2), ([ds_3a], rp_3) ] filter_datastores.return_value = [] self.assertEqual((), self._ds_sel.select_datastore(req)) get_profile_id.assert_called_once_with(profile_name) get_dss_rp_exp_calls.append(mock.call(host_3)) self.assertEqual(get_dss_rp_exp_calls, self._vops.get_dss_rp.call_args_list) filter_datastores_exp_calls = [ mock.call([ds_2a, ds_2b], size_bytes, profile_id, anti_affinity_ds, aff_ds_types), mock.call([ds_3a], size_bytes, profile_id, anti_affinity_ds, aff_ds_types) ] self.assertEqual(filter_datastores_exp_calls, filter_datastores.call_args_list) # Modify previous case to have a non-empty summary list after filtering # with preferred utilization threshold unset. self._vops.get_dss_rp.side_effect = [ error_util.VimException('no valid datastores'), ([ds_2a, ds_2b], rp_2), ([ds_3a], rp_3) ] summary_2b = self._create_summary(ds_2b, free_space=0.5 * units.Mi, capacity=units.Mi) filter_datastores.side_effect = [[summary_2b]] self._vops.get_connected_hosts.return_value = [host_1] self.assertEqual((host_2, rp_2, summary_2b), self._ds_sel.select_datastore(req)) # Modify previous case to have a preferred utilization threshold # satsified by one datastore. self._vops.get_dss_rp.side_effect = [ error_util.VimException('no valid datastores'), ([ds_2a, ds_2b], rp_2), ([ds_3a], rp_3) ] req[ds_sel.DatastoreSelector.PREF_UTIL_THRESH] = 0.4 summary_3a = self._create_summary(ds_3a, free_space=0.7 * units.Mi, capacity=units.Mi) filter_datastores.side_effect = [[summary_2b], [summary_3a]] self.assertEqual((host_3, rp_3, summary_3a), self._ds_sel.select_datastore(req)) # Modify previous case to have a preferred utilization threshold # which cannot be satisfied. self._vops.get_dss_rp.side_effect = [ error_util.VimException('no valid datastores'), ([ds_2a, ds_2b], rp_2), ([ds_3a], rp_3) ] filter_datastores.side_effect = [[summary_2b], [summary_3a]] req[ds_sel.DatastoreSelector.PREF_UTIL_THRESH] = 0.2 summary_2b.freeSpace = 0.75 * units.Mi self.assertEqual((host_2, rp_2, summary_2b), self._ds_sel.select_datastore(req)) # Clear side effects. self._vops.get_dss_rp.side_effect = None