Continuing my theme of using Python to help with Cisco product administration, here's how to convert timestamps and IP addresses to human-readable format.
Timestamps are pretty easy. They're recorded in UNIX epoch time and there are lots of examples available showing how to convert them using Excel or various scripting tools. In Python:
import time
def time_to_string(time_value):
"""convert Unix epoch time to a human readable string"""
return time.strftime("%m/%d/%Y %H:%M:%S",time.localtime(float(time_value)))
It took me a while to figure out how to convert IPv4 addresses, since CUCM uses signed 32-bit integers to represent IP addresses and Python's long integers can be of infinite length. First, a review of how to do the conversion manually is in order. Let's say that a CUCM CDR lists an IP address as "-2126438902". First, we convert this signed 32-bit integer to hex using Windows calculator:
-2126438902 = 0x81411E0A
Next, we break the hex number into 1-byte chunks, and reverse the order:
0x0A
0x1E
0x41
0x81
Finally, we convert each byte to decimal and put them together into an IP address:
10.30.65.129
Here's the Python function to do the conversion:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def int_to_ip(signed_int): | |
""" convert a 32-bit signed integer to an IP address""" | |
# do preventative type checking because I didn't want to check inputs | |
try: | |
if type(signed_int) == str or type(signed_int) == int: | |
signed_int = long(signed_int) | |
except ValueError: | |
return "err_ip" | |
# CUCM occasionally creates CDRs with an IP of '0'. Bug or feature? Beats me. | |
if signed_int == 0: | |
return "err_ip" | |
# hex conversion for 32-bit signed int; | |
# the slice at the end removes the '0x' and 'L' in the result | |
h = hex(signed_int & 0xffffffff)[2:-1] | |
if len(h) == 7: #pad initial zero if required | |
h = '0' + h | |
hex_ip = [h[6:8],h[4:6],h[2:4],h[:2]] # reverse the octets | |
#put them back together in IPv4 format | |
ip = '.'.join([str(int(n,16)) for n in hex_ip]) | |
return ip |
And here it is in the interpreter showing that it works for reasonable input types:
>>> int_to_ip('-2126438902')
'10.30.65.129'
>>> int_to_ip(-2126438902)
'10.30.65.129'
>>> int_to_ip(-2126438902L)
'10.30.65.129'
I don't have access to an IPv6-aware CUCM install, so you're on your own for that!