cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Announcements
Walkthrough Wednesdays
504
Views
10
Helpful
5
Replies
Elliot Dierksen
Enthusiast

CUCM AXL addGateway - problems adding vendorConfig

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?

 

5 REPLIES 5
dstaudt
Cisco Employee

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...

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 )

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!

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.

Couldn't reproduce your observations on 12.5, but did add some vendorConfig items in the axl_addGateway.py sample...

Content for Community-Ad

This widget could not be displayed.