Interacting with Collaboration Endpoints via SSH using Python – Configuring SNMP & Syslog

There are limitations on the values that can be configured via Cisco Unified Communications Manager Administration for Cisco Video Conference devices. For example, In order to configure SNMP monitoring you would need to login to the endpoint and configure the settings manually which can can take a considerable amount of time for a large number of endpoints.

The following code demonstrates how you can configure the appropriate settings using SSH. The program utilises a csv input file of VC unit FQDN’s or Ip’s in this instance as I had exported a number of other pieces of data such as the device description and Mac address for visibiltiy when running through large numbers of devices. I have also structured the application so that we can take advantage of Pythons multiprocessing support and divide the work up amongst multiple processes.

Commands Applied
 
  1. xConfiguration Logging Internal Mode: On
  2. xConfiguration Logging External Mode: On
  3. xConfiguration Logging External Protocol: Syslog
  4. xConfiguration Logging External Server Port: 514
  5. xConfiguration Logging External Server Address: 2.2.2.2
  6. xconfiguration NetworkServices SNMP Mode: ReadOnly
  7. xconfiguration NetworkServices SNMP CommunityName: mysnmpcommunity
  8. xConfiguration NetworkServices SNMP Host 1 Address: 1.1.1.1
  9. xConfiguration NetworkServices SNMP Host 2 Address: 1.1.1.2
  10. xConfiguration NetworkServices SNMP Host 3 Address: 1.1.1.3
Full Code
 
  1. from netmiko import ConnectHandler
  2. import csv
  3. import time
  4. from multiprocessing import Pool
  5. # Define the SSH Credential
  6. ssh_user = ""
  7. ssh_pass = ""
  8. # Define the VC Hosts File
  9. vc_hosts_file = "vchosts.csv"
  10. # Define the VC Commands File
  11. vc_config_commands = "vccommands.txt"
  12. # Open the input host file
  13. vc_hosts = open(vc_hosts_file, "r")
  14. # Open the input commands file
  15. commands = open(vc_config_commands, "r").read().splitlines()
  16. # Create a list of csv reader objects
  17. hosts = [row for row in csv.DictReader(vc_hosts)]
  18. # Function to return our data object to be passed to the ConnectHandler.
  19. def create_data(ip):
  20. return {
  21. 'device_type': 'cisco_tp',
  22. 'host': ip,
  23. 'username': ssh_user,
  24. 'password': ssh_pass,
  25. }
  26. # Returns a Netmiko ConnectHandler object configured with our parameters.
  27. def create_handler(data):
  28. return ConnectHandler(**data)
  29. # Function actually applies the configuration commands via the ConnectHandler.
  30. def configure_host(handler, commands):
  31. # Define the error place holder
  32. error = None
  33. # Iterate through the commands that we want to apply
  34. for command in commands:
  35. print(f"Sending Command = {command}")
  36. # Send the command to the device via the handler, using "send_command_timing", this function
  37. # will wait an additional two seconds to receive a response from the device.
  38. response = handler.send_command_timing(command)
  39. # Successful commands will receive text containing "OK".
  40. # Print the output if we received an error.
  41. if "OK" not in response:
  42. # print out the
  43. error = response
  44. # Break out of the command loop if an error was received
  45. break
  46. # Return the error value
  47. return error
  48. def run(host):
  49. print("#" * 100)
  50. print(f"Device {hosts.index(host)} / {len(hosts)}")
  51. # Try and Except Block
  52. try:
  53. # Break out the MAC
  54. mac = host["Mac"]
  55. # Break Out the Description
  56. description = host["Description"]
  57. # Break out the IP
  58. ip = host["Ip"]
  59. print(f"Configuring Host - {mac} - {description} - {ip}")
  60. # Create the Data Dictionary for the connect handler
  61. data = create_data(ip)
  62. # Create a handler for each host
  63. handler = create_handler(data)
  64. # Configure the device with the saved commands
  65. error = configure_host(handler, commands)
  66. # Check the value of error
  67. if error != None:
  68. print("Error Received", error)
  69. else:
  70. print("Success")
  71. # Disconnect the Handler
  72. handler.disconnect()
  73. # Exception
  74. except Exception as e:
  75. print(str(e))
  76. pass
  77. def main():
  78. # Define a process pool
  79. pool = Pool(processes=4)
  80. # Map the pool to our function
  81. pool.map(run, hosts)
  82. if __name__ == "__main__":
  83. main()
Mitch

Author Mitch

I am an independent IT Consultant with specialities in Software Development, Enterprise Unified Communication, Network and Security platforms. In addition to my day to day work, I develop bespoke applications and I hope that through ucdevops.com I can build relationships with clients, business partners and fellow engineers by providing solutions to complex problems through the use of programming.

More posts by Mitch
"