08-14-2020 09:08 AM
I am able to add a gateway through AXL with python, but I am unable to get vendorConfig XML to get saved to the gateway config. Here is what the python fragment looks like when I build it.
XML = "<_value_1><ModemPassthrough>Disable</ModemPassthrough><T3 8FaxRelay>Enable</T38FaxRelay><DtmfRelay>NTE-CA</DtmfRelay></_value_1>" tree = ET.fromstring(XML) gateway = { 'domainName': 'XX.test.local', 'description': 'XX gateway', 'product': 'Cisco ISR 4321', 'protocol': 'MGCP', 'callManagerGroupName': 'Default', 'units': { 'unit': [], 'vendorConfig': tree } }
It adds correctly, and I get this back.
{'domainName': 'XX.test.local', 'description': 'XX gateway', 'product': 'Cisco ISR 4321', 'protocol': 'MGCP', 'callManagerGroupName': 'Default', 'units': {'unit': [{'index': '0', 'product': 'ISR-2NIM-MBRD', 'subunits': {'subunit': [{'index': '1', 'product': 'NIM-1MFT-T1E1-E1', 'beginPort': '0'}]}}], 'vendorConfig': <Element 'vendorConfig' at 0x80a440350>}} { 'return': '{8E7587A3-269D-2D8A-5B98-5CC0ACD11B38}', 'sequence': None }
but when I query it with getGateway, vendorConfig isn't set.
{ 'return': { 'gateway': { 'domainName': 'XX.test.local', 'description': 'XX gateway', 'product': 'Cisco ISR 4321', 'protocol': 'MGCP', 'callManagerGroupName': { '_value_1': 'Default', 'uuid': '{D13C4201-7802-11D3-BDF0-00108302EAD1}' }, 'units': { 'unit': [ { 'index': 0, 'product': 'ISR-2NIM-MBRD', 'subunits': { 'subunit': [ { 'index': 1, 'product': 'NIM-1MFT-T1E1-E1', 'beginPort': 0 } ] } } ] }, 'scratch': None, 'vendorConfig': None, 'versionStamp': '0000000000-c7a6c673-7479-46b0-839e-014d3d093963', 'loadInformation': None, 'uuid': '{873D02F6-5A74-4FA8-6DA7-115ACF8E9BD3}' } }, 'sequence': None }
After I update the gateway through the GUI, it looks like this.
{ 'return': { 'gateway': { 'domainName': 'XX.test.local', 'description': 'XX gateway', 'product': 'Cisco ISR 4321', 'protocol': 'MGCP', 'callManagerGroupName': { '_value_1': 'Default', 'uuid': '{D13C4201-7802-11D3-BDF0-00108302EAD1}' }, 'units': { 'unit': [ { 'index': 0, 'product': 'ISR-2NIM-MBRD', 'subunits': { 'subunit': [ { 'index': 1, 'product': 'NIM-1MFT-T1E1-E1', 'beginPort': 0 } ] } } ] }, 'scratch': None, 'vendorConfig': { '_value_1': [ <Element globalISDNSwitchType at 0x80ea09820>, <Element switchBack at 0x80ea097d0>, <Element switchBackDelay at 0x80ea0c320>, <Element switchBackSchedule at 0x80ea0c410>, <Element DtmfRelay at 0x80ea0c460>, <Element ModemPassthrough at 0x80ea0c4b0>, <Element CiscoFaxRelay at 0x80ea0c500>, <Element T38FaxRelay at 0x80ea0c550>, <Element rtpPackageCapability at 0x80ea0c5a0>, <Element mtPackageCapability at 0x80ea0c5f0>, <Element resPackageCapability at 0x80ea0c640>, <Element prePackageCapability at 0x80ea0c690>, <Element sstPackageCapability at 0x80ea0c6e0>, <Element rtpUnreachableOnOff at 0x80ea0c730>, <Element rtpUnreachableTimeout at 0x80ea0c780>, <Element rtcpReportInterval at 0x80ea0c7d0>, <Element simpleSdpEnable at 0x80ea0c820> ] }, 'versionStamp': '1597420698-715c776e-736d-40e2-bfa6-cb9013092827', 'loadInformation': None, 'uuid': '{873D02F6-5A74-4FA8-6DA7-115ACF8E9BD3}' } }, 'sequence': None }
I suspect that I am not using the right XML tag when I build the tree value. I have tried XML, vendorConfig, and _value_1 but none of those get stored correctly. What should I use?
08-17-2020 01:34 PM
I was able to get this working for <addPhone> using Python+Zeep for CUCM 12.5, see the 'axl_add_Phone_vendorConfig.py` sample in this project: CiscoDevNet/axl-python-zeep-samples
# Create an Element object from scratch with tag 'videoCapability' and text '0' videoCapability = etree.Element( 'videoCapability' ) videoCapability.text = '0' # The some config item Elements must be the child of a 'section' Element, e.g.: # <desktopClient> # <extendAndConnectCapability>0</extendAndConnectCapability> # </desktopClient> desktopClient = etree.Element( 'desktopClient' ) extendAndConnectCapability = etree.SubElement( desktopClient, 'extendAndConnectCapability' ) extendAndConnectCapability.text = '0' problemReportServerUrl = etree.SubElement( desktopClient, 'problemReportServerUrl' ) problemReportServerUrl.text = 'https://report.example.com' # Append each top-level element to an array vendorConfig = [] vendorConfig.append( videoCapability ) vendorConfig.append( desktopClient ) # Create a Zeep xsd type object of type XVendorConfig from the client object xvcType = client.get_type( 'ns0:XVendorConfig' ) # Use the XVendorConfig type object to create a vendorConfig object # using the array of vendorConfig elements from above, and set as # phone.vendorConfig phone[ 'vendorConfig' ] = xvcType( vendorConfig )
I took a more roundabout approach, though comparing the two, possibly the key is that vendorConfig needs to be an array of separate elements, whereas your example is a simple single element. Possibly just wrapping that single element in an array might do it...
08-17-2020 02:52 PM - edited 08-17-2020 02:56 PM
I'll have to beat on that a little more. That is more elegant that what I have done as a work-around. I made a brief try and copying what you did, but it didn't work right away.
gwname = input("Gateway Name: ") gateway = { 'domainName': gwname, } sql = 'update mgcp set xml = \'<ModemPassthrough>Disable</ModemPassthrough><T38FaxRelay>Enable</T38FaxRelay><DtmfRelay>NTE-CA</DtmfRelay>\' where domainname = \'' + gwname + '\'' print(sql) axl, history = axl_bind(server, acct, pw) # Attempt AXL call try: reply = axl.executeSQLUpdate(sql = sql) # Check for error # Return values based on request response except Fault as err: if 'HTTP Status 401' in ET.tostring(history.last_received['envelope']).decode(): print("Server Credential Error") else: print(err) else: if reply["return"] is None: print("Unknown Result - Double Check Values") else: print("Update Success") print(reply)
This is the error I got. Again, I just made a quick stab at it now. I am going to work on it some more since this method seems cleaner.
Traceback (most recent call last): File "gw_ins.py", line 87, in <module> reply = axl.addGateway( gateway ) File "/usr/local/lib/python3.7/site-packages/zeep/proxy.py", line 45, in __call__ kwargs, File "/usr/local/lib/python3.7/site-packages/zeep/wsdl/bindings/soap.py", line 119, in send operation, args, kwargs, client=client, options=options File "/usr/local/lib/python3.7/site-packages/zeep/wsdl/bindings/soap.py", line 68, in _create serialized = operation_obj.create(*args, **kwargs) File "/usr/local/lib/python3.7/site-packages/zeep/wsdl/definitions.py", line 215, in create return self.input.serialize(*args, **kwargs) File "/usr/local/lib/python3.7/site-packages/zeep/wsdl/messages/soap.py", line 74, in serialize self.body.render(body, body_value) File "/usr/local/lib/python3.7/site-packages/zeep/xsd/elements/element.py", line 231, in render self._render_value_item(parent, value, render_path) File "/usr/local/lib/python3.7/site-packages/zeep/xsd/elements/element.py", line 255, in _render_value_item return self.type.render(node, value, None, render_path) File "/usr/local/lib/python3.7/site-packages/zeep/xsd/types/complex.py", line 279, in render element.render(parent, element_value, child_path) File "/usr/local/lib/python3.7/site-packages/zeep/xsd/elements/indicators.py", line 242, in render element.render(parent, element_value, child_path) File "/usr/local/lib/python3.7/site-packages/zeep/xsd/elements/element.py", line 231, in render self._render_value_item(parent, value, render_path) File "/usr/local/lib/python3.7/site-packages/zeep/xsd/elements/element.py", line 255, in _render_value_item return self.type.render(node, value, None, render_path) File "/usr/local/lib/python3.7/site-packages/zeep/xsd/types/complex.py", line 279, in render element.render(parent, element_value, child_path) File "/usr/local/lib/python3.7/site-packages/zeep/xsd/elements/indicators.py", line 242, in render element.render(parent, element_value, child_path) File "/usr/local/lib/python3.7/site-packages/zeep/xsd/elements/element.py", line 231, in render self._render_value_item(parent, value, render_path) File "/usr/local/lib/python3.7/site-packages/zeep/xsd/elements/element.py", line 255, in _render_value_item return self.type.render(node, value, None, render_path) File "/usr/local/lib/python3.7/site-packages/zeep/xsd/types/complex.py", line 279, in render element.render(parent, element_value, child_path) File "/usr/local/lib/python3.7/site-packages/zeep/xsd/elements/indicators.py", line 242, in render element.render(parent, element_value, child_path) File "/usr/local/lib/python3.7/site-packages/zeep/xsd/elements/any.py", line 126, in render self.validate(value, render_path) File "/usr/local/lib/python3.7/site-packages/zeep/xsd/elements/any.py", line 181, in validate self._validate_item(val, render_path) File "/usr/local/lib/python3.7/site-packages/zeep/xsd/elements/any.py", line 216, in _validate_item "See http://docs.python-zeep.org/en/master/datastructures.html" TypeError: Any element received object of type 'Element', expected lxml.etree._Element or builtins.dict or zeep.xsd.valueobjects.AnyObject See http://docs.python-zeep.org/en/master/datastructures.html#any-objects for more information
Here is what I was trying to do
ModemPassthrough = ET.Element( 'ModemPassthrough' ) ModemPassthrough.text = 'Disable' T38FaxRelay = ET.Element( 'T38FaxRelay' ) T38FaxRelay .text = 'Enable' DtmfRelay = ET.Element( 'DtmfRelay' ) DtmfRelay .text = 'NTE-CA' # Append each top-level element to an array vendorConfig = [] vendorConfig.append( ModemPassthrough ) vendorConfig.append( T38FaxRelay ) vendorConfig.append( DtmfRelay ) gateway[ 'vendorConfig' ] = xvcType( vendorConfig )
08-17-2020 03:21 PM
I figured it out. I was using:
from xml.etree import ElementTree as ET
when I should have been using this from your code:
from lxml import etree
Now it works with this section:
ModemPassthrough = etree.Element( 'ModemPassthrough' ) ModemPassthrough.text = 'Disable' T38FaxRelay = etree.Element( 'T38FaxRelay' ) T38FaxRelay .text = 'Enable' DtmfRelay = etree.Element( 'DtmfRelay' ) DtmfRelay .text = 'NTE-CA' # Append each top-level element to an array vendorConfig = [] vendorConfig.append( ModemPassthrough ) vendorConfig.append( T38FaxRelay ) vendorConfig.append( DtmfRelay )
Thanks!
08-17-2020 03:29 PM
One last detail. This doesn't seem to negatively impact anything, but the contents of the XML column in the database look different right after I insert it with python than they do after I update it from the GUI. Here is what it looks like immediately after insert:
admin:run sql ccm select xml from mgcp where domainname = 'XX.test.local' xml ========================================================================================================================================================================================================================================================= <xml-fragment xmlns:ns0="http://www.cisco.com/AXL/API/8.0" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"> <ModemPassthrough>Disable</ModemPassthrough> <T38FaxRelay>Enable</T38FaxRelay> <DtmfRelay>NTE-CA</DtmfRelay> </xml-fragment>
And here is what it looks like after an update from the GUI:
admin:run sql ccm select xml from mgcp where domainname = 'XX.test.local' xml =========================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================== <globalISDNSwitchType>4ESS</globalISDNSwitchType><switchBack>Graceful</switchBack><switchBackDelay>10</switchBackDelay><switchBackSchedule>12:00</switchBackSchedule><DtmfRelay>NTE-CA</DtmfRelay><ModemPassthrough>Disable</ModemPassthrough><CiscoFaxRelay>Disable</CiscoFaxRelay><T38FaxRelay>Enable</T38FaxRelay><rtpPackageCapability>Enable</rtpPackageCapability><mtPackageCapability>Disable</mtPackageCapability><resPackageCapability>Disable</resPackageCapability><prePackageCapability>Enable</prePackageCapability><sstPackageCapability>Enable</sstPackageCapability><rtpUnreachableOnOff>Enable</rtpUnreachableOnOff><rtpUnreachableTimeout>1000</rtpUnreachableTimeout><rtcpReportInterval>0</rtcpReportInterval><simpleSdpEnable>Enable</simpleSdpEnable>
It doesn't appear to make a difference at the moment, but this is just a lab system where I will never end up registering a real gateway.
08-21-2020 02:18 PM
Couldn't reproduce your observations on 12.5, but did add some vendorConfig items in the axl_addGateway.py sample...
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide