def request(self, request_name, params=None, context=None, urn=None, opts={}): """ Send a single request to Zimbra; return the response as native python data. """ if 'xml' in opts and opts['xml']: request, response = RequestXml(), ResponseXml() else: request, response = RequestJson(), ResponseJson() try: if urn == None: urn = urn_for_request(request_name) request.add_request(request_name, params or {}, "urn:"+urn) if context: request.set_context_params(context) request.set_auth_token(self.token) except: log.exception("failed to build request: request_name=%s, params=%s, context=%s", request_name, params, context) return None if opts['debug']: if isinstance(request, RequestXml): print xml.dom.minidom.parseString(request.get_request()).toprettyxml(indent=". ") else: pprint.pprint(yaml.load(request.get_request())) try: self.comm.send_request(request, response) except urllib2.HTTPError as e: requestbody = request.get_request() responsebody = e.read() log.error('''send_request HTTP Error %s: %s; request="%s" response="%s"''', e.code, e.reason, requestbody, responsebody) if isinstance(request, RequestXml): requestdoc = xml.dom.minidom.parseString(requestbody) print "REQUEST=", requestdoc.toprettyxml(indent=". ") else: print "REQUEST=\n", pprint.pformat(yaml.load(requestbody)) if isinstance(response, ResponseXml): responsedoc = xml.dom.minidom.parseString(responsebody) print "RESPONSE=", responsedoc.toprettyxml(indent=". ") else: print "RESPONSE=\n", pprint.pformat(yaml.load(responsebody)) return None except Exception as e: log.exception("send_request failed (%s): request=%s", type(e), request.get_request()) return None if response.is_fault(): log.error("send_request returned fault: request=%s, response=%s", request.get_request(), response.get_response()) return None info = response.get_response() return info
class TestRequestXml(TestCase): """ Request tests """ request = None """ The request to be tested against """ def cleanUp(self): """ Clean up after one step to leave a dedicated result for the other test cases. """ self.setUp() def setUp(self): self.request = RequestXml() def test_empty_request(self): """ Create an empty request and check the created xml """ expected_result = '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3' \ '.org/2003/05/soap-envelope"><soap:Header><context' \ ' xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body' \ '/></soap:Envelope>' self.assertEqual(expected_result, self.request.get_request()) def test_set_context_params_failtype(self): """ Add context parameters to the request and expect the method to send an exception """ self.assertRaises( RequestHeaderContextException, self.request.set_context_params, {'invalidParam': { 'invalidAttribute': 'invalidValue' }}) def test_set_context_params(self): """ Add all currently accepted params and check the result """ self.request.set_context_params({ 'authToken': { '_content': '1234567890abcdef' }, 'authTokenControl': { 'voidOnExpired': '1' }, 'session': { 'id': '1234567890abcdef', 'seq': '1234567890', 'type': 'admin' }, 'account': { 'by': 'name', '_content': '*****@*****.**' }, 'change': { 'token': '1234567890abcdef', 'type': 'new' }, 'targetServer': { '_content': 'mailboxserver.zimbra.com' }, 'userAgent': { 'name': 'Mozilla', 'version': '1.0' }, 'via': { '_content': 'proxyserver.zimbra.com' } }) expected_result = '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3' \ '.org/2003/05/soap-envelope"><soap:Header><context ' \ 'xmlns="urn:zimbra"><format ' \ 'type="xml"/><authToken>1234567890abcdef</authToken' \ '><account by="name">user@zimbra' \ '.com</account><session id="1234567890abcdef" ' \ 'seq="1234567890" type="admin"/><authTokenControl ' \ 'voidOnExpired="1"/><targetServer>mailboxserver' \ '.zimbra.com</targetServer><via>proxyserver.zimbra' \ '.com</via><userAgent name="Mozilla" version="1' \ '.0"/><change token="1234567890abcdef" ' \ 'type="new"/></context></soap:Header><soap:Body' \ '/></soap:Envelope>' self.assertEqual(expected_result, self.request.get_request()) # Clean up after this test self.cleanUp() def test_enable_batch_default(self): """ Test enabling batch requests """ # Check with default parameter self.request.enable_batch('urn:zimbra') expected_result = \ '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap' \ ':Header><context xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body><BatchRequest ' \ 'onerror="urn:zimbra" ' \ 'xmlns="urn:zimbra"/></soap:Body></soap:Envelope>' self.assertEqual(expected_result, self.request.get_request()) # Clean up self.cleanUp() def test_enable_batch_stop(self): """ Test enabling batch requests with additional parameter """ self.request.enable_batch('stop') expected_result = '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3' \ '.org/2003/05/soap-envelope"><soap:Header><context ' \ 'xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body' \ '><BatchRequest onerror="stop" ' \ 'xmlns="urn:zimbra"/></soap:Body></soap:Envelope>' self.assertEqual(expected_result, self.request.get_request()) # Clean up self.cleanUp() def test_batch_add_request(self): """ Test adding multiple request to a batch request """ self.request.enable_batch() request_id = self.request.add_request('GetInfoRequest', {'sections': 'mbox,prefs'}, 'urn:zimbra') self.assertIsInstance( request_id, int, msg="Returned request_id for request 1 is not of type int, " "but of type %s" % (type(request_id))) self.assertEqual( 1, request_id, msg="Returned request_id for request 1 is not 1, but %s" % (str(request_id))) expected_result = \ '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap' \ ':Header><context xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body><BatchRequest ' \ 'onerror="continue" xmlns="urn:zimbra"><GetInfoRequest ' \ 'requestId="1" sections="mbox,prefs" ' \ 'xmlns="urn:zimbra"/></BatchRequest></soap:Body></soap:Envelope>' self.assertEqual(expected_result, self.request.get_request()) request_id = self.request.add_request('GetInfoRequest', {'sections': 'zimlets'}, 'urn:zimbra') self.assertIsInstance( request_id, int, msg="Returned request_id for request 2 is not of type int, " "but of type %s" % (type(request_id))) self.assertEqual( 2, request_id, msg="Returned request_id for request 2 is not 2, but %s" % (str(request_id))) expected_result = \ '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap' \ ':Header><context xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body><BatchRequest ' \ 'onerror="continue" xmlns="urn:zimbra"><GetInfoRequest ' \ 'requestId="1" sections="mbox,prefs" ' \ 'xmlns="urn:zimbra"/><GetInfoRequest requestId="2" ' \ 'sections="zimlets" ' \ 'xmlns="urn:zimbra"/></BatchRequest></soap:Body></soap:Envelope>' self.assertEqual(expected_result, self.request.get_request()) # Clean up self.setUp() def test_add_request(self): """ Test adding a request """ request_id = self.request.add_request('GetInfoRequest', {'sections': 'mbox,prefs'}, 'urn:zimbra') self.assertIsNone(request_id, msg="Returned request_id for request 1 is not none, " "but %s" % (str(request_id))) expected_result = '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3' \ '.org/2003/05/soap-envelope"><soap:Header><context ' \ 'xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body' \ '><GetInfoRequest sections="mbox,' \ 'prefs" ' \ 'xmlns="urn:zimbra"/></soap:Body></soap:Envelope>' self.assertEqual(expected_result, self.request.get_request()) # Clean up self.setUp() def tearDown(self): self.request = None
class TestRequestXml(TestCase): """ Request tests """ request = None """ The request to be tested against """ def cleanUp(self): """ Clean up after one step to leave a dedicated result for the other test cases. """ self.setUp() def setUp(self): self.request = RequestXml() def tool_assert_equal_xml(self, xml_a, xml_b, message=None): self.assertEqual( dom_to_dict(minidom.parseString(xml_a).firstChild), dom_to_dict(minidom.parseString(xml_b).firstChild), message ) def test_empty_request(self): """ Create an empty request and check the created xml """ expected_result = '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3' \ '.org/2003/05/soap-envelope"><soap:Header><context' \ ' xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body' \ '/></soap:Envelope>' self.tool_assert_equal_xml( expected_result, self.request.get_request() ) def test_set_context_params_failtype(self): """ Add context parameters to the request and expect the method to send an exception """ self.assertRaises( RequestHeaderContextException, self.request.set_context_params, { 'invalidParam': { 'invalidAttribute': 'invalidValue' } } ) def test_set_context_params(self): """ Add all currently accepted params and check the result """ self.request.set_context_params( { 'authToken': { '_content': '1234567890abcdef' }, 'authTokenControl': { 'voidOnExpired': '1' }, 'session': { 'id': '1234567890abcdef', 'seq': '1234567890', 'type': 'admin' }, 'account': { 'by': 'name', '_content': '*****@*****.**' }, 'change': { 'token': '1234567890abcdef', 'type': 'new' }, 'targetServer': { '_content': 'mailboxserver.zimbra.com' }, 'userAgent': { 'name': 'Mozilla', 'version': '1.0' }, 'via': { '_content': 'proxyserver.zimbra.com' } } ) expected_result = '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3' \ '.org/2003/05/soap-envelope"><soap:Header><context ' \ 'xmlns="urn:zimbra"><format ' \ 'type="xml"/><authToken>1234567890abcdef</authToken' \ '><account by="name">user@zimbra' \ '.com</account><session id="1234567890abcdef" ' \ 'seq="1234567890" type="admin"/><authTokenControl ' \ 'voidOnExpired="1"/><targetServer>mailboxserver' \ '.zimbra.com</targetServer><via>proxyserver.zimbra' \ '.com</via><userAgent name="Mozilla" version="1' \ '.0"/><change token="1234567890abcdef" ' \ 'type="new"/></context></soap:Header><soap:Body' \ '/></soap:Envelope>' self.tool_assert_equal_xml( expected_result, self.request.get_request() ) # Clean up after this test self.cleanUp() def test_enable_batch_default(self): """ Test enabling batch requests """ # Check with default parameter self.request.enable_batch('urn:zimbra') expected_result = \ '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap' \ ':Header><context xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body><BatchRequest ' \ 'onerror="urn:zimbra" ' \ 'xmlns="urn:zimbra"/></soap:Body></soap:Envelope>' self.tool_assert_equal_xml( expected_result, self.request.get_request() ) # Clean up self.cleanUp() def test_enable_batch_stop(self): """ Test enabling batch requests with additional parameter """ self.request.enable_batch('stop') expected_result = '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3' \ '.org/2003/05/soap-envelope"><soap:Header><context ' \ 'xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body' \ '><BatchRequest onerror="stop" ' \ 'xmlns="urn:zimbra"/></soap:Body></soap:Envelope>' self.tool_assert_equal_xml( expected_result, self.request.get_request() ) # Clean up self.cleanUp() def test_batch_add_request(self): """ Test adding multiple request to a batch request """ self.request.enable_batch() request_id = self.request.add_request( 'GetInfoRequest', { 'sections': 'mbox,prefs' }, 'urn:zimbra' ) self.assertIsInstance( request_id, int, msg="Returned request_id for request 1 is not of type int, " "but of type %s" % ( type(request_id) ) ) self.assertEqual( 1, request_id, msg="Returned request_id for request 1 is not 1, but %s" % ( str(request_id) ) ) expected_result = \ '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap' \ ':Header><context xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body><BatchRequest ' \ 'onerror="continue" xmlns="urn:zimbra"><GetInfoRequest ' \ 'requestId="1" sections="mbox,prefs" ' \ 'xmlns="urn:zimbra"/></BatchRequest></soap:Body></soap:Envelope>' self.tool_assert_equal_xml( expected_result, self.request.get_request() ) request_id = self.request.add_request( 'GetInfoRequest', { 'sections': 'zimlets' }, 'urn:zimbra' ) self.assertIsInstance( request_id, int, msg="Returned request_id for request 2 is not of type int, " "but of type %s" % ( type(request_id) ) ) self.assertEqual( 2, request_id, msg="Returned request_id for request 2 is not 2, but %s" % ( str(request_id) ) ) expected_result = \ '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap' \ ':Header><context xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body><BatchRequest ' \ 'onerror="continue" xmlns="urn:zimbra"><GetInfoRequest ' \ 'requestId="1" sections="mbox,prefs" ' \ 'xmlns="urn:zimbra"/><GetInfoRequest requestId="2" ' \ 'sections="zimlets" ' \ 'xmlns="urn:zimbra"/></BatchRequest></soap:Body></soap:Envelope>' self.tool_assert_equal_xml( expected_result, self.request.get_request() ) # Clean up self.setUp() def test_add_request(self): """ Test adding a request """ request_id = self.request.add_request( 'GetInfoRequest', { 'sections': 'mbox,prefs' }, 'urn:zimbra' ) self.assertIsNone( request_id, msg="Returned request_id for request 1 is not none, " "but %s" % ( str(request_id) ) ) expected_result = '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3' \ '.org/2003/05/soap-envelope"><soap:Header><context ' \ 'xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body' \ '><GetInfoRequest sections="mbox,' \ 'prefs" ' \ 'xmlns="urn:zimbra"/></soap:Body></soap:Envelope>' self.tool_assert_equal_xml( expected_result, self.request.get_request() ) # Clean up self.setUp() def tearDown(self): self.request = None