Giter Site home page Giter Site logo

levensailor / ciscoaxl Goto Github PK

View Code? Open in Web Editor NEW
83.0 19.0 42.0 4.48 MB

Python SDK for Cisco CUCM AXL API

Home Page: https://pypi.org/project/ciscoaxl

License: MIT License

Python 100.00%
cisco callmanager cucm uc unifiedcommunications collaboration sip sdk ipphones voip

ciscoaxl's Introduction

Python SDK for Cisco CUCM AXL API

PyPi Status

AXL API Documentation

Installation

pip install ciscoaxl

testing in a lab is highly recommended. if you don't have a lab of your own, you can reserve a DevNet Sandbox free of charge!

Reserve a DevNet Sandbox (if required)

The DevNet Sandbox is accessible through Cisco DevNet at http://developer.cisco.com

Select Collaboration on the right hand category menu and then look for the “Collaboration 12.5” tile. Hit reserve.

To connect to the lab, you'll need to use VPN.

VPN Credentials will be sent to your DevNet registered email account, or you can view the OUTPUT from the topology page.

Once connected, you can click on the server, in this case CUCM, and select ATTRIBUTES to find username, password, and hostname / ip address.


Enable AXL SOAP Service on CUCM:

Enable the AXL SOAP interface

Browse to the CUCM Serviceability page on https://<IP_CUCM>/ccmservice

Tools > Service Activation:

Enable the "Cisco AXL Web Service"


Create an AXL Service Account

Step 1 - Create an AXL User Group

CUCM > User Management > User Group > Add.

Step 2 - Assign the AXL role to the group

On the top right drop down list "Related Links".

Select "Assign Role to User Group" and select "Standard AXL API Access"

Step 3 - Create a new Application User

CUCM > User Management > Application User > Add.

Add the User Group "AXL Group" to this user so that after saving the roles of the new Application User appear as in the following screen:

SDK Usage

from ciscoaxl import axl

cucm = '10.10.20.1'
username = 'axlaccess'
password = 'axlpassword'
version = '12.5'
ucm = axl(username=username,password=password,cucm=cucm,cucm_version=version)

Note: all get methods that return more than 1 item have a tagfilter property that can allow more fields to return. Fields are filtered by default to increase performance, but if you need additional fields returned from the axl call, simply add the tagfilter={} to the request. Example:

get_phones(tagfilter={ "name": "",
            "product": "",
            "description": "",
            "protocol": "",
            "locationName": "",
            "callingSearchSpaceName": "",
            "devicePoolName": ""
        })

Users

Get All Users

for user in ucm.get_users():
    print(user.firstName)

Get Specific User

user = ucm.get_user(user_id='mscott')
print(user.email)

Add User

ucm.add_user(user_id='jlevensailor', last_name='Levensailor', first_name='Jeff')

Delete User

ucm.delete_user(user_id='jlevensailor')

Update User

ucm.update_user(user_id='jlevensailor', password='Lagavulin16', pin='5432')

Phones

Get Phones

for phone in ucm.get_phones():
    print(phone.name)

Get Specific Phone

phone = ucm.get_phone(name='SEP001122445566')
print(phone.name)

Add Phone

ucm.add_phone(
    name='SEP0023AF482340',
    description='Robert - 1102',
    product='Cisco 8861',
    device_pool='RTP_DP',
    location='RTP_LOC',
    phone_template='Standard 8861 SIP',
    protocol='SIP',
    css='AVST-CSS',
    subscribe_css='AVST-CSS',
    lines=[
        ('1102', 'ABQ_PT', 'Robert Smith', 'Robert Smith', 'Robert Smith - 1102', '+1408202XXXX')
    ]
)

Delete Phone

ucm.delete_phone(name='SEP004433220043')

Translations and Transformations

Get Translation Patterns

for trans in ucm.get_translations():
    detailed = ucm.get_translation(uuid=trans.uuid)
    print(detailed.description)

Get Specific Translation Pattern

trans = ucm.get_translation(pattern='2XXX', routePartitionName='xlates-pt')
print(trans.description)

Add Translation Pattern

ported = ['12324625544', '12324625545', '12324625546']

for num in ported:
    ucm.add_translation(pattern=num, routePartitionName='pstn_pt',calledPartyTransformationMask='1102', callingSearchSpaceName='GW_CSS')

Delete Translation Pattern

ucm.delete_translation(pattern='34567', routePartitionName='xlates-pt')

Update Translation Pattern

ucm.update_translation(pattern='1234', routePartitionName='xlates-pt', newPattern='4567')

Device Pools

Get Device Pools

for dp in ucm.get_device_pools():
    print(dp.name)

Get Specific Device Pool

dp = ucm.get_device_pool(name='RTP_DP')
print(dp.name)

Add Device Pool

ucm.add_device_pool(device_pool='Hollywood_DP')

Delete Device Pool

ucm.delete_device_pool(device_pool='Hollywood_DP')

Update Device Pool

ucm.update_device_pool(name='RTP_DP', regionName='G711_RGN')

CSS and Partitions

Get Calling Search Spaces

for css in ucm.get_calling_search_spaces():
    print(css.name)

Get Specific Calling Search Space

css = ucm.get_calling_search_space(calling_search_space='pstn-css')
print(css.name)

Add Calling Search Space

ucm.add_calling_search_space(
    calling_search_space='VIP_CSS',
    description='Very Important Stuff'
    members=['losfeliz-pt','silverlake-pt','pstn-pt']
    )

Delete Calling Search Space

ucm.update_calling_search_space(calling_search_space='VIP_CSS')

Delete Calling Search Space

ucm.delete_calling_search_space(calling_search_space='VIP_CSS')

Get Partitions

for pt in ucm.get_partitions():
    print(pt.name)

Get Specific Partition

pt = ucm.get_partition(routePartitionName='pstn-pt')
print(pt.name)

Add Partition

ucm.add_partition(routePartitionName='VIP_PT', description='Very Important Peep')

Delete Partition

ucm.delete_partition(name='VIP_PT')

Regions and Locations

Get Regions

for reg in ucm.get_regions():
    print(reg.uuid)

Get Specific Region

reg = ucm.get_region(region='losfeliz_reg')
print(reg.name)

Add Region

ucm.add_region(region='Hollywood-REG')

Delete Region

ucm.delete_region(region='Hollywood-REG')

Get Locations

for loc in ucm.get_locations():
    print(loc.name)

Get Specific Location

loc = ucm.get_location(name='Shadow')
print(loc.name)

Add Location

ucm.add_location(location='Hollywood-LOC')

Delete Location

ucm.delete_location(location='Hollywood-LOC')

Directory Numbers

Get Directory Numbers

for dn in ucm.get_directory_numbers():
    print(dn.uuid)

Get Specific Directory Number

dn = ucm.get_directory_number(pattern='2888',routePartitionName='losfeliz-pt')
print(dn.uuid)

Add Directory Number

ucm.add_directory_number(
    pattern='1102',
    routePartitionName='ABQ_PT'
    )

Delete Directory Number

ucm.delete_directory_number(uuid='{0B0CDC93-EC9C-7255-1B09-40A3CE727D5A}')

Device Profiles

Get User Device Profiles

for udp in ucm.get_device_profiles():
    print(udp.name)

Get Specific User Device Profile

udp = ucm.get_device_profile(name='udp-bsimpson')
print(udp.name)

Add User Device Profile

ucm.add_device_profile(
    name='UDP_MScott',
    description='Michael Scott - 2901',
    product='Cisco 8861',
    phone_template='Standard 8861 SIP',
    protocol='SIP',
    lines=[
        ('2901', 'losfeliz-pt', 'Michael Scott', 'Michael Scott', 'Michael Scott - 2901', '+1408202XXXX'),
        ('2902', 'losfeliz-pt', 'Pam Beesley', 'Pam Beesley', 'Pam Beesley - 2902', '+1408202XXXX')
    ]
)

Delete User Device Profile

ucm.delete_device_profile('UDP_Mscott')

CTI Route Points

Get CTI Route Points

for cti in ucm.get_cti_route_points():
    print(cti.name)

Get Specific CTI Route Point

cti = ucm.get_cti_route_point(cti_route_point='AutoAttendant')
print(cti.name)

Add CTI Route Point

ucm.add_cti_route_point(
    cti_route_point='aa-pilot',
    description='pilot to unity',
    device_pool='LosFeliz_DP',
    css='allphone-css',
    lines=[
        ('2908', 'losfeliz-pt'),
        ('2909', 'losfeliz-pt')
    ]
)

Delete CTI Route Point

ucm.delete_cti_route_point(name='OneArch')

Route Groups, Lists, and Patterns

List Route Plan

nums = ['19197016707', '19197016712', '19197016713', '19197016706', '191970167016']

for num in nums:
    for route in ucm.list_route_plan(num):
        print(route.dnOrPattern)
for route in ucm.list_route_plan('2901'):
    print(route.uuid)

Get Route Groups

for rg in ucm.get_route_groups():
    print(rg.name)

Get Specific Route Group

rg = ucm.get_route_group(route_group='losfeliz-rg')
print(rg.uuid)

Add Route Group

ucm.add_route_group(
    route_group='hollywood-rg',
    distribution_algorithm='Circular',
    members=[('america-online-sip'), ('h323')])

Delete Route Group

ucm.delete_route_group(route_group='hollywood-rg')

Get Route Lists

for rl in ucm.get_route_lists():
    print(rl.name)

Get Specific Route List

rl = ucm.get_route_list(route_list='stdloc-rl')
print(rl.description)

Add Route List

ucm.add_route_list(
    route_list='hollywood-rl',
    description='hollywood',
    run_on_all_nodes='true',
    cm_group_name='Default',
    members=[
        ('losfeliz-rg'),
        ('silverlake-rg')
    ])

Delete Route List

ucm.delete_route_list(route_list='hollywood-rl')

Get Route Patterns

for rp in ucm.get_route_patterns():
    print(rp.pattern)

Get Specific Route Pattern

rp = ucm.get_route_pattern(pattern='911')
print(rp.description)

Add Route Pattern

ucm.add_route_pattern(
    pattern='999',
    routePartitionName='losfeliz-pt',
    description='Movie Times',
    route_list='stdloc-rl'
    )

Delete Route Pattern

ucm.delete_route_pattern(pattern='999', routePartitionName='losfeliz-pt')

Runs and Dos

Execute SQL Query

for sql in ucm.run_sql_query('select * from device where description like "Bart%"'):
    print(sql.name)

Do LDAP Sync on all agreements

for ldap in ucm.get_ldap_dir():
    ucm.do_ldap_sync(uuid=ldap.uuid)

Reset Device

ucm.do_device_reset(device='SEP001100220033')

Extension Mobility Login

ucm.do_device_login(device='SEP001100220033', userId='bsimpson')

Extension Mobility Logout

ucm.do_device_logout(device='SEP001100220033', userId='bsimpson')

ciscoaxl's People

Contributors

acidpuzzle avatar alksf avatar bradh11 avatar levensailor avatar nkallergis avatar qjarhead avatar rlad78 avatar vyechuri-personal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ciscoaxl's Issues

Get phones - all info

Hello!
Great module!
I have a question - how to get data for all phones, device name + line (pattern) + userid? It's real?

get_users() Not Populating All Data

Might have a bug here. I was recently pulling data from CUCM with get_users() and noticed that there were a bunch of fields not populating data. Several keys were missing values.

Keys I can see missing data:

  • mailid
  • primaryExtension
  • telephoneNumber
  • enableMobility

I can verify this by checking the userid with get_user(userid='xxxxxx'), which does show all the data.

Not a huge issue because I can get around this via other means, but it seems like most of the attributes have None values.

Is there something I'm missing here? These are local accounts on CUCM.

get_directory_number() return missing ["return"]["line"]

This is a bit of a nitpick, but it's something that gave me quite a headscratch. When trying to pull some details from a DN, I noticed that the returned object had an attribute of return. I had been diving into other objects' info using their attributes (didn't know I could just access zeep's objects using dict notation), so I was confused how I was going to get into the DN data like this...

dn = ucm.get_directory_number(pattern='5550001', routePartitionName='my-partition')
print(dn.return.line.associatedDevices.device)

Needless to say, Python didn't like me using the reserved word return to try and access an attribute.

Is there any way this method's return can get the same treatment as something like get_phone()?

https://github.com/PresidioCode/ciscoaxl/blob/d5a40cca2bc829b7d7d78180185c127cd302c0e6/ciscoaxl/axl.py#L1909-L1918

ImportError: cannot import name 'axl' from 'ciscoaxl'

Following the example of the docs, I'm unable to import axl.

Using Python 3.7.3 and ciscoaxl 0.158.

Traceback (most recent call last):
File "./ciscoaxl.py", line 3, in
from ciscoaxl import axl
File "/Users/oletos7j/Projects/onboarding/ciscoaxl.py", line 3, in
from ciscoaxl import axl
ImportError: cannot import name 'axl' from 'ciscoaxl'

add_phone fail to run (lines parameter)

Hi,

I'm trying to write a function for the creation of a SoftPhone device and it fails because there is a missing element for lines.
The exception is: zeep.exceptions.ValidationError: Missing element recordingMediaSource (addPhone.phone.lines)

This is the lines definition as described in the documentation: lines=[(extension, 'Internal', fullname, fullname, fullname, '')]
when "fullname" is the name of the user I'm creating it for and the extension is the directory number.

Adding the function:

`

def createSoftPhoneDevice(self, username):
fullname = self.getUserFullName(username)
extension = self.getUserExtensionNumber(username)
resp = self.ucm.add_phone(name=username,
description=username + ' - CSF',
product='Cisco Unified Client Services Framework',
device_pool='DP_Infinidat',
phone_template='Standard Client Services Framework',
common_device_config='Standard Common Phone Profile',
securityProfileName='Cisco Unified Client Services Framework - '
'Standard SIP Non-Secure Profile',
lines=[(extension, 'Internal', fullname, fullname, fullname, '')],
dev_class='Phone',
protocol='SIP',
softkey_template='',
subscribe_css='Internal',
ehook_enable='0')
return resp`

I will really appreciate your help and guidance
Thanks

Add 14.0 schema

Hello,

is this repository still being maintained? I'd need to use version 14.0 of the AXL schema because of some special fields that are added when using it (e.g. user department, title etc.).

Thanks!

Remote Destination

Hi!
Help me please, how i make a new remote destination profile, i using version 10.5?
In documentations i don't find this

get_users() Not Populating All Data (routePartitionName from primaryExtension)

I tried to get the routePartitionName from the primaryExtension in EndUser but it always shows None
ucm.get_users(tagfilter={'userid':'','primaryExtension':''})

'primaryExtension': {
          'pattern': '1802',
          'routePartitionName': None
      },

EndUsers can have DirectoryNumbers in different partitions

image

There is no way to always check a correct configuration
Reasons:
In the DirectoryNumbers there is no longer a specific mandatory field for the EndUser.
One way would be to get the Enduser from the directoryURIs but this field is optional in the form.
you can get the associatedDevices in the DirectoryNumber and then check that EndUser is in the ownerUserName but this field is not required and an anonymous ownerUser can be used
Therefore, the partitions are essential.

Originally posted by @Letshadow in #13 (comment)

SSL verification disabled

Hi,

You have SSL verification disabled and you are suppressing the warnings. It would be nice if it SSL verification would be part of initializing the class. That way one can choose to enable and provide the path for the certificate.

SQL_Query Return Dict

Wold be nice if SQL Query would return Dict and not unserialized Data. This makes it run:

This is a Function outside of the axl class:

def element_list_to_ordered_dict(elements):
    return [OrderedDict((element.tag, element.text) for element in row) for row in elements]

This replaces the existing function:

    def sql_query(self, query):
        axl_resp = self.client.executeSQLQuery(sql=query)
        try:
            value = element_list_to_ordered_dict(serialize_object(axl_resp)["return"]["rows"])
            jsonList = []    
            for i in range(len(value)):
                jsonList.append(json.loads(json.dumps(value[i])))
            return jsonList

        except KeyError:
            # single tuple response
            value = element_list_to_ordered_dict(serialize_object(axl_resp)["return"]["row"])
            jsonList = []   
            for i in range(len(value)):
                jsonList.append(json.loads(json.dumps(value[i])))
            return jsonList

        except TypeError:
            # no SQL tuples
            return serialize_object(axl_resp)["return"]

Required Libs:

from zeep.helpers import serialize_object
from collections import OrderedDict

add_phone does not use "enableActivationID" and "enableActivationID"

I've noticed during the usage of your library that in the dictionnary in the <add_phone> function, the keys "enableActivationID" and "allowMraMode" are forced to True and the arguments "allowMraMode" and "enableActivationID" are never used.

This makes the creation of certain types of phone impossible.

I've fixed it on my side like so :

req = {
            "name": name,
            "description": description,
            "product": product,
            "class": dev_class,
            "protocol": protocol,
            "protocolSide": "User",
            "commonDeviceConfigName": common_device_config,
            "commonPhoneConfigName": "Standard Common Phone Profile",
	    "softkeyTemplateName": softkey_template,
            "phoneTemplateName": phone_template,
            "devicePoolName": device_pool,
            "locationName": location,
            "useTrustedRelayPoint": "Off",
            "builtInBridgeStatus": "Default",
            "certificateOperation": "No Pending Operation",
            "packetCaptureMode": "None",
            "deviceMobilityMode": "Default",
            "enableExtensionMobility": enable_em,
            "callingSearchSpaceName": css,
            "automatedAlternateRoutingCssName": aar_css,
            "subscribeCallingSearchSpaceName": subscribe_css,
	    "ownerUserName": ownerUserName,
	    "enableActivationID": enableActivationID,  # Here
	    "allowMraMode": allowMraMode,  # And Here
            "lines": {"line": []},
            "services": {"service": []},
            "vendorConfig": [{"ehookEnable": ehook_enable}],
        }

Thanks !

Wrong documentation on get_partition

Error in documentation:
In the documentation, it says to get the specifics of a name of a partition. I was looking for the uuid and couldn't get it to pull up, python error said bad parameter name (routePartitionName).

Here is the current example in the documentation
---------------Begin-----------------------------------------
Get Specific Partition
pt = ucm.get_partition(routePartitionName='pstn-pt')
print(pt.name)
---------------End-----------------------------------------
So the correction should be that to get the query to work, you need to specify "name" instead of "routePartitionName"

pt = ucm.get_partition(name='pstn-pt')
print(pt.name)
print(pt.uuid)

All the parameters available are found by getting the directory of fields in pt...
dir(pt)
['description', 'dialPlanWizardGenId', 'name', 'partitionUsage', 'timeScheduleIdName', 'timeZone', 'useOriginatingDeviceTimeZone', 'uuid']

Thought this might help someone in the future if you updated that documentation, it works fine calling that partition by name.

Failure to updates Lines on a Phone

CUCM version 11.51.15900-18

Have a script that queries information about a phone and its lines, and then attempts to update a Line on that Phone. I feel pretty certain I have the syntax of the update correct, but I am getting the error "TypeError: Choice elements only work with keyword arguments"

Here is the code where I am trying to update the line:

phone_change=ucm.update_phone(
        name=device_name,
        lines=[
            ('70359', 'Internal', 'John Doe', 'John Doe', 'John Doe 70359', '50398XXXXX')
        ]
)

Here is the resulting error:

Traceback (most recent call last):
File "/usr/local/bin/uc_dev_phone_update_mask.py", line 70, in
('70359', 'Internal', 'Rick Atlansky', 'Rick Atlansky', 'Rick Atlansky 70359', '0294127777')
File "/usr/local/lib/python3.6/dist-packages/ciscoaxl/axl.py", line 2084, in update_phone
return self.client.updatePhone(**args)
File "/usr/local/lib/python3.6/dist-packages/zeep/proxy.py", line 45, in call
kwargs,
File "/usr/local/lib/python3.6/dist-packages/zeep/wsdl/bindings/soap.py", line 119, in send
operation, args, kwargs, client=client, options=options
File "/usr/local/lib/python3.6/dist-packages/zeep/wsdl/bindings/soap.py", line 68, in _create
serialized = operation_obj.create(*args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/zeep/wsdl/definitions.py", line 215, in create
return self.input.serialize(*args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/zeep/wsdl/messages/soap.py", line 68, in serialize
body_value = self.body(*args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/element.py", line 57, in call
instance = self.type(*args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/types/complex.py", line 49, in call
return self._value_class(*args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/valueobjects.py", line 95, in init
items = _process_signature(self._xsd_type, args, kwargs)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/valueobjects.py", line 209, in _process_signature
values = element.parse_kwargs(kwargs, None, available_kwargs)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/indicators.py", line 205, in parse_kwargs
sub_result = element.parse_kwargs(kwargs, elm_name, available_kwargs)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/indicators.py", line 457, in parse_kwargs
subresult = choice.parse_kwargs(kwargs, name, temp_kwargs)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/element.py", line 134, in parse_kwargs
return self.type.parse_kwargs(kwargs, name or self.attr_name, available_kwargs)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/types/complex.py", line 309, in parse_kwargs
value = self._create_object(value, name)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/types/complex.py", line 325, in _create_object
return [self._create_object(val, name) for val in value]
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/types/complex.py", line 325, in
return [self._create_object(val, name) for val in value]
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/types/complex.py", line 335, in _create_object
return self(value)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/types/complex.py", line 49, in call
return self._value_class(*args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/valueobjects.py", line 95, in init
items = _process_signature(self._xsd_type, args, kwargs)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/valueobjects.py", line 185, in _process_signature
values, args, index = element.parse_args(args, index)
File "/usr/local/lib/python3.6/dist-packages/zeep/xsd/elements/indicators.py", line 321, in parse_args
raise TypeError("Choice elements only work with keyword arguments")
TypeError: Choice elements only work with keyword arguments

Here is the entire script:

#!/usr/bin/python3
'''
Usage: uc_dev_phone_update_line.py [phone name]
'''


import sys
from ciscoaxl import axl

cucm_fqdn = 'REDACTED'
cucm_username = 'ucmaxl'
cucm_password = "REDACTED"
version = '11.5'
ucm = axl(username=cucm_username,password=cucm_password,cucm=cucm_fqdn,cucm_version=version)

device_name = sys.argv[1]

phone = ucm.get_phone(name=device_name)
line_line = '\nLine : Caller ID Number : Caller ID Name\n'
line_dict = {}
response = {}
response_text = ""

try:
    response['Description'] = str(phone.description)
except:
    print("Problem getting phone.")
    quit()

response['CSS'] = str(phone.callingSearchSpaceName._value_1)
response['DevicePool'] = str(phone.devicePoolName._value_1)
response['Common Device Config'] = str(phone.commonDeviceConfigName._value_1)
response['SIP Profile'] = str(phone.sipProfileName._value_1)
response['Phone Template'] = str(phone.phoneTemplateName._value_1)
response['Owner'] = str(phone.ownerUserName._value_1)
response['Presence Group'] = str(phone.presenceGroupName._value_1)
response['Cert Operation'] = str(phone.certificateOperation)
response['Do Not Disturb active'] = str(phone.dndStatus)
for line in phone.lines.line:
    dn=line['dirn']['pattern']
    callerid=line['display']
    calleridno=line['e164Mask']
    line_dict[dn] = callerid
    line_dict[dn] = calleridno
    line_line = str(line_line) + str(dn) + " : " + str(calleridno) +  " : " + str(callerid) + '\n'
    dn=''
    callerid=''
    calleridno=''
response['Lines'] = line_line

'''
Create a nicely formatted output from the dict we've built
'''

for dict_item_name, dict_item_value in response.items():
    response_text = response_text +  dict_item_name + ": " + dict_item_value + "\n"

print(response_text)

print("-------")

phone_change=ucm.update_phone(
        name=device_name,
        lines=[
            ('70359', 'Internal', 'John Doe', 'John Doe', 'John Doe 70359', '50398XXXXX')
        ]
)

print(phone_change)

list items should return "None" when there are no items to list

Current behavior for most methods is to Fault with a "None is not subscriptable: when running a method to get a list of items (if no items exist). The fix will require changing from

    def get_sip_trunks(
        self, tagfilter={"name": "", "sipProfileName": "", "callingSearchSpaceName": ""}
    ):
        try:
            return self.client.listSipTrunk({"name": "%"}, returnedTags=tagfilter)[
                "return"
            ]["sipTrunk"]
        except Fault as e:
            return e

and change it to the following:

    def get_sip_trunks(
        self, tagfilter={"name": "", "sipProfileName": "", "callingSearchSpaceName": ""}
    ):
        try:
            response = self.client.listSipTrunk({"name": "%"}, returnedTags=tagfilter)["return"]
            if response:
                return response["sipTrunk"]
            else:
                return response
        except Fault as e:
            return e

this would need to be done for all methods to list items

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.