cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
2260
Views
25
Helpful
6
Replies

Looking to utilize the CER API for version 12.5

bstarr
Level 1
Level 1

Does anyone know if the CER API will be supported in 12.5? So far we have found that only the /discovery status provides a 200 OK message. All other references generate a 404 message.

Looking at https://developer.cisco.com/site/CER/documents/api-reference/

1 Accepted Solution

Accepted Solutions

# Cisco Emergency Responder API
# Get License Status
# 1.0 - ajp26@acsu.buffalo.edu

from requests import Session
from requests.auth import HTTPBasicAuth
from hashlib import sha256
from getpass import getpass
import xmltodict
import os

# Configuration

debug = 0 # Output debug logging for the HTTP transaction
local_input = 0 # Allow local username and password prompting

def get_license_status(username, password, host):

  if debug:

    import logging

    try:
      import http.client as http_client
    except ImportError:
      # Python 2
      import httplib as http_client

    http_client.HTTPConnection.debuglevel = 1

    # You must initialize logging, otherwise you'll not see debug output.
    logging.basicConfig()
    logging.getLogger().setLevel(logging.DEBUG)
    requests_log = logging.getLogger("requests.packages.urllib3")
    requests_log.setLevel(logging.DEBUG)
    requests_log.propagate = True

  # Main

  password = sha256(password.encode('utf-8')).hexdigest()

  session = Session()
  session.auth = HTTPBasicAuth(username, password)

  # This is the typical format for an authenticated endpoint
  url = f'https://{host}/cerappservices/export/e911licensemanager/info/{username}/{password}'

  response = session.get(url)

  xml = xmltodict.parse(response.text)

  if xml['E911LicenseManager']['Status'] != "Exporting the info":
    print(f"License data export failed: {xml['E911LicenseManager']['Status']}")
  else:
    print(f"Gathered license data for {host}:\n")

  # I have to assume all these fields show up, the API documentation doesn't describe what happens when you're not registered or whatever

  cer_number_discovered_phones = xml['E911LicenseManager']['SmartLicenseManager']['NoPhonesDiscovered']
  cer_manually_configured_phones = xml['E911LicenseManager']['SmartLicenseManager']['NoPhonesManuallyConfigured']
  cer_users_tracked = xml['E911LicenseManager']['SmartLicenseManager']['TotalUsersTracked']
  cer_phones_not_tracked = xml['E911LicenseManager']['SmartLicenseManager']['NoPhonesNotToBeTracked']
  cer_licenses_used = xml['E911LicenseManager']['SmartLicenseManager']['User_license_usage_count']

  slm_registration_status = xml['E911LicenseManager']['SmartLicenseManager']['RegistrationStatus']
  slm_authorization_status = xml['E911LicenseManager']['SmartLicenseManager']['AuthorizationStatus']
  slm_compliance_status = xml['E911LicenseManager']['SmartLicenseManager']['LicenseStatus']
  slm_transport_type = xml['E911LicenseManager']['SmartLicenseManager']['TransportSettings']
  slm_license_type = xml['E911LicenseManager']['SmartLicenseManager']['LicenseMode']
  slm_smart_account_name = xml['E911LicenseManager']['SmartLicenseManager']['SmartAccountName']
  slm_virtual_account_name = xml['E911LicenseManager']['SmartLicenseManager']['VirtualAccountName']
  slm_last_sync_time = xml['E911LicenseManager']['SmartLicenseManager']['LastSynchronizationTime']
  slm_export_allowed = xml['E911LicenseManager']['SmartLicenseManager']['ExportControlledFunctionality']


  if slm_export_allowed == "Allowed":
    export_allowed = True
  else:
    export_allowed = False

  # Print some details:

  if slm_compliance_status == "InCompliance":
    print(f"This CER System's license status is: In Compliance")
  else:
    print(f"*** This CER System has a license issue: {slm_compliance_status} ***")

  print("\n")

  print(f"Authoriztion Status: {slm_authorization_status}")
  print(f"Last Synchronization Time: {slm_last_sync_time}")

  print("\n")

  if slm_registration_status != "Registered":
    print(f"*** This CER System is not registered to a Smart License Account ***")
  else:
    if slm_transport_type == "Direct":
      print(f"This system is directly connected to {slm_license_type} licensing.")
    else:
      print(f"This system is connected using the {slm_transport_type} method to {slm_license_type} licensing.")
    print(f"This system is registered to the {slm_smart_account_name} Smart Account.")
    print(f"Licensing is drawn from virtual account {slm_virtual_account_name}.")

  print("\nLicense Details:\n")
  print(f"This system has discovered {cer_number_discovered_phones}, of those {cer_phones_not_tracked} will not be tracked due to address exclusion or peer tracking.")
  print(f"This system also tracks {cer_manually_configured_phones} manually configured phones.")
  print(f"This system is tracking a total of {cer_users_tracked} users/devices.")
  print(f"As of last update, this system is using a total of {cer_licenses_used} licenses.")
  if export_allowed:
    print("Export-Controlled Functionality is allowed")
  else:
    print("Export-Controlled Functionality is NOT allowed")

  return 1

if __name__ == "__main__":

  if local_input:

    print("Cisco Emergency Responder Authentication (Local User Accounts Only)")
    hostname = input("Hostname: ")
    username = input("Username: ")
    password = sha256((getpass()).encode('utf-8')).hexdigest()
    get_license_status(username, password, hostname)

  else:

    get_license_status(os.getenv("CER_API_USER"), os.getenv("CER_API_PASSWORD"), os.getenv("CER_API_HOST"))

Here is a sample mess that works for me.
I know Smart License will email when it doesn't check in, but if it's in eval then it won't. I assume the "InCompliance" will be "Evaluation" but I don't know. Should be easy enough to grab it. Hope this helps.

View solution in original post

6 Replies 6

Adam Pawlowski
VIP Alumni
VIP Alumni

It works, the documentation is wrong. I've asked Cisco if it could be updated several times including opening a ticket with devnet on it and looking now it's been marked Solved but the documentation is actually worse.

 

What do you want to do ?

 

Most of the URLs are going to be in the format of https://{host}/cerappservices/export/switchport/info/{username}/{password} type endpoints. The password is actually a SHA256 hash of the password, but basic auth appears to be required as well. I have no idea who wrote this API.

 

I wrote some lousy python to pull erls, ports, switches, unlocated phones - the API is read only so they're all pretty similar to parse.

Thanks Adam.



We were really only trying to get the /e911licensemanager/info.

We were hoping to be able to get the 12.5 Smarts licensing status as the system doesn't currently give any warnings for systems that are in evaluation mode before halting the phone tracking service.


Okay, it works if you follow that hashed password format:

 

https://{host}/cerappservices/export/e911licensemanager/info/{username}/{password}

 

A "GET" on that will produce XML output that you can parse out. Don't set the content type like the doc does/did say or you get an error back from it.

 

 

# Cisco Emergency Responder API
# Get License Status
# 1.0 - ajp26@acsu.buffalo.edu

from requests import Session
from requests.auth import HTTPBasicAuth
from hashlib import sha256
from getpass import getpass
import xmltodict
import os

# Configuration

debug = 0 # Output debug logging for the HTTP transaction
local_input = 0 # Allow local username and password prompting

def get_license_status(username, password, host):

  if debug:

    import logging

    try:
      import http.client as http_client
    except ImportError:
      # Python 2
      import httplib as http_client

    http_client.HTTPConnection.debuglevel = 1

    # You must initialize logging, otherwise you'll not see debug output.
    logging.basicConfig()
    logging.getLogger().setLevel(logging.DEBUG)
    requests_log = logging.getLogger("requests.packages.urllib3")
    requests_log.setLevel(logging.DEBUG)
    requests_log.propagate = True

  # Main

  password = sha256(password.encode('utf-8')).hexdigest()

  session = Session()
  session.auth = HTTPBasicAuth(username, password)

  # This is the typical format for an authenticated endpoint
  url = f'https://{host}/cerappservices/export/e911licensemanager/info/{username}/{password}'

  response = session.get(url)

  xml = xmltodict.parse(response.text)

  if xml['E911LicenseManager']['Status'] != "Exporting the info":
    print(f"License data export failed: {xml['E911LicenseManager']['Status']}")
  else:
    print(f"Gathered license data for {host}:\n")

  # I have to assume all these fields show up, the API documentation doesn't describe what happens when you're not registered or whatever

  cer_number_discovered_phones = xml['E911LicenseManager']['SmartLicenseManager']['NoPhonesDiscovered']
  cer_manually_configured_phones = xml['E911LicenseManager']['SmartLicenseManager']['NoPhonesManuallyConfigured']
  cer_users_tracked = xml['E911LicenseManager']['SmartLicenseManager']['TotalUsersTracked']
  cer_phones_not_tracked = xml['E911LicenseManager']['SmartLicenseManager']['NoPhonesNotToBeTracked']
  cer_licenses_used = xml['E911LicenseManager']['SmartLicenseManager']['User_license_usage_count']

  slm_registration_status = xml['E911LicenseManager']['SmartLicenseManager']['RegistrationStatus']
  slm_authorization_status = xml['E911LicenseManager']['SmartLicenseManager']['AuthorizationStatus']
  slm_compliance_status = xml['E911LicenseManager']['SmartLicenseManager']['LicenseStatus']
  slm_transport_type = xml['E911LicenseManager']['SmartLicenseManager']['TransportSettings']
  slm_license_type = xml['E911LicenseManager']['SmartLicenseManager']['LicenseMode']
  slm_smart_account_name = xml['E911LicenseManager']['SmartLicenseManager']['SmartAccountName']
  slm_virtual_account_name = xml['E911LicenseManager']['SmartLicenseManager']['VirtualAccountName']
  slm_last_sync_time = xml['E911LicenseManager']['SmartLicenseManager']['LastSynchronizationTime']
  slm_export_allowed = xml['E911LicenseManager']['SmartLicenseManager']['ExportControlledFunctionality']


  if slm_export_allowed == "Allowed":
    export_allowed = True
  else:
    export_allowed = False

  # Print some details:

  if slm_compliance_status == "InCompliance":
    print(f"This CER System's license status is: In Compliance")
  else:
    print(f"*** This CER System has a license issue: {slm_compliance_status} ***")

  print("\n")

  print(f"Authoriztion Status: {slm_authorization_status}")
  print(f"Last Synchronization Time: {slm_last_sync_time}")

  print("\n")

  if slm_registration_status != "Registered":
    print(f"*** This CER System is not registered to a Smart License Account ***")
  else:
    if slm_transport_type == "Direct":
      print(f"This system is directly connected to {slm_license_type} licensing.")
    else:
      print(f"This system is connected using the {slm_transport_type} method to {slm_license_type} licensing.")
    print(f"This system is registered to the {slm_smart_account_name} Smart Account.")
    print(f"Licensing is drawn from virtual account {slm_virtual_account_name}.")

  print("\nLicense Details:\n")
  print(f"This system has discovered {cer_number_discovered_phones}, of those {cer_phones_not_tracked} will not be tracked due to address exclusion or peer tracking.")
  print(f"This system also tracks {cer_manually_configured_phones} manually configured phones.")
  print(f"This system is tracking a total of {cer_users_tracked} users/devices.")
  print(f"As of last update, this system is using a total of {cer_licenses_used} licenses.")
  if export_allowed:
    print("Export-Controlled Functionality is allowed")
  else:
    print("Export-Controlled Functionality is NOT allowed")

  return 1

if __name__ == "__main__":

  if local_input:

    print("Cisco Emergency Responder Authentication (Local User Accounts Only)")
    hostname = input("Hostname: ")
    username = input("Username: ")
    password = sha256((getpass()).encode('utf-8')).hexdigest()
    get_license_status(username, password, hostname)

  else:

    get_license_status(os.getenv("CER_API_USER"), os.getenv("CER_API_PASSWORD"), os.getenv("CER_API_HOST"))

Here is a sample mess that works for me.
I know Smart License will email when it doesn't check in, but if it's in eval then it won't. I assume the "InCompliance" will be "Evaluation" but I don't know. Should be easy enough to grab it. Hope this helps.

Thanks Adam! We were able to get our Postman query to work with the authorization information that you provided!

You totally rock, @Adam Pawlowski