cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
5251
Views
10
Helpful
22
Replies

programming python for Call Manager to Add Trunk

ROBERT WYKOFF
Level 1
Level 1

Trying to add a trunk port using Pythons and suds to do it.  Question is I do not know how to tell it to program the destination in the IPV4 address area within the added trunk call.  Below is a sample of a working sip profile and the none work add sip trunk.

 

code that works:

# Add Sip Profile
    print("")
    print("Adding SIP Profile to Call Manager")
    print("")
    client = Client(wsdl,location=location, username=username, password=password)
    ap = client.service.addSipProfile({

                            'name': sProfileName + " Cisco Unity SIP Profile",
                            'description' : sProfileName + " Cisco Unity SIP Profile",
                            'enableOutboundOptionsPing': 'True'
                            })
    
    print("Command completed successfully! ")

 

code that does not work.

# Add Sip Trunk
    print("")
    print("Adding SIP Trunk to Call Manager")
    print("")
    client = Client(wsdl,location=location, username=username, password=password)
    ap = client.service.addsipTrunk({

                            'name' : sProfileName + " Cisco Unity SIP Trunk",
                            'description' : sProfileName + " Cisco Unity SIP Trunk",
                            'devicePoolName' : "Phoenix",
                            'location' : "Phoenix",
                            'sipProfileName' : sProfileName + " Cisco Unity SIP Trunk",
                            'securityProfileName' : sProfileName + " Cisco Unity SIP Trunk",
                            'addressIpv4' : "10.10.10.10"

                            })

 

Error with code:

Traceback (most recent call last):
  File "C:/Users/rwykoff/Documents/testing/voiceadd.py", line 38, in versioncheck
    login(wsdl,location,username,password,imp)
  File "C:/Users/rwykoff/Documents/testing/voiceadd.py", line 123, in login
    mainMenu(wsdl,location,username,password,imp)
  File "C:/Users/rwykoff/Documents/testing/voiceadd.py", line 148, in mainMenu
    addCiscoUnity(wsdl,location,username,password,newbuild)
  File "C:/Users/rwykoff/Documents/testing/voiceadd.py", line 279, in addCiscoUnity
    'addressIpv4' : "10.10.10.10"
  File "C:\Program Files\Python36\lib\site-packages\suds\client.py", line 521, in __call__
    return client.invoke(args, kwargs)
  File "C:\Program Files\Python36\lib\site-packages\suds\client.py", line 576, in invoke
    soapenv = binding.get_message(self.method, args, kwargs)
  File "C:\Program Files\Python36\lib\site-packages\suds\bindings\binding.py", line 109, in get_message
    content = self.bodycontent(method, args, kwargs)
  File "C:\Program Files\Python36\lib\site-packages\suds\bindings\document.py", line 95, in bodycontent
    add_param, self.options().extraArgumentErrors)
  File "C:\Program Files\Python36\lib\site-packages\suds\argparser.py", line 83, in parse_args
    return arg_parser(args, kwargs, extra_parameter_errors)
  File "C:\Program Files\Python36\lib\site-packages\suds\argparser.py", line 108, in __call__
    self.__process_parameters()
  File "C:\Program Files\Python36\lib\site-packages\suds\argparser.py", line 299, in __process_parameters
    self.__process_parameter(*pdef)
  File "C:\Program Files\Python36\lib\site-packages\suds\argparser.py", line 294, in __process_parameter
    self.__in_choice_context(), value)
  File "C:\Program Files\Python36\lib\site-packages\suds\bindings\document.py", line 86, in add_param
    p = self.mkparam(method, pdef, value)
  File "C:\Program Files\Python36\lib\site-packages\suds\bindings\document.py", line 130, in mkparam
    return Binding.mkparam(self, method, pdef, object)
  File "C:\Program Files\Python36\lib\site-packages\suds\bindings\binding.py", line 225, in mkparam
    return marshaller.process(content)
  File "C:\Program Files\Python36\lib\site-packages\suds\mx\core.py", line 59, in process
    self.append(document, content)
  File "C:\Program Files\Python36\lib\site-packages\suds\mx\core.py", line 72, in append
    self.appender.append(parent, content)
  File "C:\Program Files\Python36\lib\site-packages\suds\mx\appender.py", line 88, in append
    appender.append(parent, content)
  File "C:\Program Files\Python36\lib\site-packages\suds\mx\appender.py", line 229, in append
    Appender.append(self, child, cont)
  File "C:\Program Files\Python36\lib\site-packages\suds\mx\appender.py", line 168, in append
    self.marshaller.append(parent, content)
  File "C:\Program Files\Python36\lib\site-packages\suds\mx\core.py", line 71, in append
    if self.start(content):
  File "C:\Program Files\Python36\lib\site-packages\suds\mx\literal.py", line 86, in start
    raise TypeNotFound(content.tag)
suds.TypeNotFound: Type not found: 'location'

 

Thanks in Advance.

 

 

22 Replies 22

Mark Stover
Cisco Employee
Cisco Employee
Is this camel case right?

addsipTrunk

Sorry, yes it is addSipTrunk but I forgot to add that.  My main issue seems to be that the IPv4 address is in a separate group called destination but I do not know how to add that in Python as I am just a beginner at Python and API.

The portion of the WSDL for the destination shows nested format

allowing for multiple destinations:
      destinations   [ANON-destinations]   
         destination   [XSipTrunkDestination]   Max: 16
            addressIpv4   [String255]   
            addressIpv6   [String255]   
            port   [XInteger]   
            sortOrder   [XInteger] REQUIRED

 

So I think you want to replace the IPv4 argument with something like this

 'destinations': [
    'destination':
    { 'addressIpv4': '1.1.1.1',
      'port': 433,
      'sortOrder': 1}  
      ]

 

( I haven't tested it myself)

 

Did anyone ever get this question solved?  I am also trying to add a sip trunk using the code below and cannot get it to add.  I get a different error, but any help would be very much appreciated.

 

def add_trunk(service,gw,dp,loc,mrgl,vip):
try:
data = {'sipTrunk':{
'name': gw,
'description': gw,
'model': 'SIP Trunk',
'class': 'Trunk',
'callingSearchSpaceName': 'INTERNAL_CSS',
'devicePoolName': dp,
'locationName': loc,
'mediaResourceListName': mrgl,
'securityProfileName': 'Non Secure SIP Voice Gateway Trunk Profile',
'sipProfileName': 'Standard SIP Voice Gateway Profile',
'callingPartySelection': 'First Redirect Number',
'sipTrunkType': 'None(Default)',
'pstnAccess': 1,
'destinations': {'destination': []}
}}
[data['sipTrunk']['destinations']['destination'].append({'addressIpv4':ip,'port': '5060', 'sortOrder': 1})]
resp = service.addSipTrunk( data )
print(resp)
except Fault as err:
resp=''
show_history()
return resp


vip = '1.1.1.1'
dp = 'Test_DP'
srst = siteID + "-" + city + '_SRST'
loc = 'Hub_None'
mrgl = 'Test_MRGL'
gw = 'TestTrunk'

resp=add_trunk(service,gw,dp,loc,mrgl,vip)

 


File "C:\Python37\lib\site-packages\zeep\xsd\elements\element.py", line 248, in validate
"Missing element %s" % (self.name), path=render_path)
zeep.exceptions.ValidationError: Missing element name (addSipTrunk.sipTrunk)

This was a tricky one, as there are some unexpected required fields...here is my complete working sample for 11.5:

from zeep import Client  
from zeep.cache import SqliteCache  
from zeep.transports import Transport  
from zeep.plugins import HistoryPlugin  
from requests import Session  
from requests.auth import HTTPBasicAuth  
from lxml import etree  
import urllib3  
  
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)  
  
username = 'Administrator'  
password = 'ciscopsdt'  
wsdl = 'file:///home/dstaudt/Downloads/Zeep Sample/AXLAPI.wsdl'  
  
session = Session()  
session.verify = False  
session.auth = HTTPBasicAuth(username, password)  
transport = Transport(cache=SqliteCache(), session=session, timeout=20)  
history = HistoryPlugin()  
client = Client(wsdl=wsdl, transport=transport, plugins=[history])  
service = client.create_service("{http://www.cisco.com/AXLAPIService/}AXLAPIBinding", "https://ds-ucm115-1.cisco.com/axl/")

#factory = client.type_factory('ns0')  

# data = factory.XSipTrunk(
#     name = 'testSipTrunk',
#     product = 'SIP Trunk',
#     # _class = 'Trunk',
#     protocol = 'SIP',
#     protocolSide = 'Network',
#     devicePoolName = 'Default',
#     locationName = 'Hub_None',
#     securityProfileName = 'Non Secure SIP Trunk Profile',
#     sipProfileName = 'Standard SIP Profile',
#     callingPartySelection = 'First Redirect Number',
#     pstnAccess = 1,
#     presenceGroupName = 'Standard Presence group',
#     destinations = []
# )

# # Cant specify class in the factory constructor above due to collision with Python 'class' reserved word
# data['class'] = 'Trunk' 

data = {
    'name': 'testSipTrunk',
    'description': 'testDescription',
    'product': 'SIP Trunk',
    'class': 'Trunk',
    'protocol': 'SIP',
    'protocolSide': 'Network',
    'devicePoolName': 'Default',
    'locationName': 'Hub_None',
    'securityProfileName': 'Non Secure SIP Trunk Profile',
    'sipProfileName': 'Standard SIP Profile',
    'presenceGroupName': 'Standard Presence group',
    'callingAndCalledPartyInfoFormat': 'Deliver DN only in connected party',
    'destinations': [],
}

data['destinations'].append( {'destination': 
    {'addressIpv4': '1.1.1.1', 'port': '5060', 'sortOrder': 1}})

result = service.addSipTrunk( data )  
  
#troubleshooting soap envelope  
for hist in [history.last_sent, history.last_received]:  
    print(etree.tostring(hist["envelope"], encoding="unicode", pretty_print=True))

Thank you sooo much!!!  That worked like a charm.

I wonder if you could help me with another issue. I am trying to update a device pool with a few values. I don't get an error and everything updates except it doesn't update the "local router group". It just remains as "Standard Local Route Group" <None>


def update_devpool(service,dp,rg):
try:
#print(rg)
data = {
'name': dp,
'locationName': 'HUB_None',
'localRouteGroupName': {'name': rg}
#'localRouteGroupName': rg,
#'localRouteGroup': rg
}
resp = service.updateDevicePool(**data)
print(dp + ' updated')
except Fault as err:
resp = ''
print(err)
return resp

 

username = 'user'
password = 'pass'
host = '<cucm axl server>'
wsdl = 'file://C:/Documents/Playbooks/axlsqltoolkit/schema/current/AXLAPI.wsdl'
location = 'https://{host}:8443/axl/'.format(host=host)
binding = "{http://www.cisco.com/AXLAPIService/}AXLAPIBinding"
session = Session()
session.verify = False
session.auth = HTTPBasicAuth(username, password)
transport = Transport(cache=SqliteCache(), session=session, timeout=20)
history = HistoryPlugin()
client = Client(wsdl=wsdl, transport=transport, plugins=[history])
service = client.create_service(binding, location)


rg='000-Test' #and this rg does show up as a valid local route group in the drop down in CUCM
update_devpool(service,dp,rg)

Sorry, I forgot to list the error I am getting.  Here it is:

 

Traceback (most recent call last):
File "AddCUCMSite_v3.py", line 445, in <module>
update_devpool(service,dp,uuid,mrgl,srst,rg)
File "AddCUCMSite_v3.py", line 136, in update_devpool
resp = service.updateDevicePool(**data)
File "C:\Python37\lib\site-packages\zeep\proxy.py", line 42, in __call__
self._op_name, args, kwargs)
File "C:\Python37\lib\site-packages\zeep\wsdl\bindings\soap.py", line 121, in send
options=options)
File "C:\Python37\lib\site-packages\zeep\wsdl\bindings\soap.py", line 68, in _create
serialized = operation_obj.create(*args, **kwargs)
File "C:\Python37\lib\site-packages\zeep\wsdl\definitions.py", line 200, in create
return self.input.serialize(*args, **kwargs)
File "C:\Python37\lib\site-packages\zeep\wsdl\messages\soap.py", line 72, in serialize
body_value = self.body(*args, **kwargs)
File "C:\Python37\lib\site-packages\zeep\xsd\elements\element.py", line 48, in __call__
instance = self.type(*args, **kwargs)
File "C:\Python37\lib\site-packages\zeep\xsd\types\complex.py", line 42, in __call__
return self._value_class(*args, **kwargs)
File "C:\Python37\lib\site-packages\zeep\xsd\valueobjects.py", line 90, in __init__
items = _process_signature(self._xsd_type, args, kwargs)
File "C:\Python37\lib\site-packages\zeep\xsd\valueobjects.py", line 204, in _process_signature
values = element.parse_kwargs(kwargs, None, available_kwargs)
File "C:\Python37\lib\site-packages\zeep\xsd\elements\indicators.py", line 204, in parse_kwargs
sub_result = element.parse_kwargs(kwargs, elm_name, available_kwargs)
File "C:\Python37\lib\site-packages\zeep\xsd\elements\element.py", line 118, in parse_kwargs
kwargs, name or self.attr_name, available_kwargs)
File "C:\Python37\lib\site-packages\zeep\xsd\types\complex.py", line 282, in parse_kwargs
value = self._create_object(value, name)
File "C:\Python37\lib\site-packages\zeep\xsd\types\complex.py", line 303, in _create_object
return self(**value)
File "C:\Python37\lib\site-packages\zeep\xsd\types\complex.py", line 42, in __call__
return self._value_class(*args, **kwargs)
File "C:\Python37\lib\site-packages\zeep\xsd\valueobjects.py", line 90, in __init__
items = _process_signature(self._xsd_type, args, kwargs)
File "C:\Python37\lib\site-packages\zeep\xsd\valueobjects.py", line 231, in _process_signature
xsd_type.signature(standalone=False)))
TypeError: {http://www.cisco.com/AXL/API/11.5}XFkType() got an unexpected keyword argument 'name'. Signature: `xsd:string, uuid: {http://www.cisco.com/AXL/API/11.5}XUUID`

I got this working with Zeep, and added the code to this new AXL sample collection project...hope it helps!

https://github.com/CiscoDevNet/axl-python-zeep-sample

Thank you so much for providing the script example.  It worked perfect!

Hi dstaudt,

 

I've gone through your script and I wanted to ask you one thing, Is it possible to update MRGL field using update device pool script ?

Also have you managed to get add route pattern script working using zeep or ciscoaxl.

I tried all possible options with ciscoaxl library but no success so far :(

Please help if you managed to add route pattern using python script.

 

Vikas

Added samples to cover add/update Device Pool MRGL and add Route Pattern: https://github.com/CiscoDevNet/axl-python-zeep-samples

Hi dstaudt,

 

 Your script worked perfect.

 

Thank You very much.

+5

 

Regards,

Vikas

Hi dstaudt,

Two questions please.

 

1. Anything changed in update device pool part of code ? I want to update my MRGL using update device pool code and somehow it is not working with below error.

    173             name = 'DP-'+name+'-IPT',
--> 174             mediaResourceListName = 'MRGL-'+name
NameError: name 'Fault' is not defined
 
 
 
 
 

 

2. Do we've any option to perform bulk jobs using this or any other lib ?

I want to insert phones, update users, etc jobs.

 

Please help.

Thanks.

Vikas