DNA-C Importing Access Points From Ekahau

For those of you that don’t know much about Cisco’s Product DNA-C there is a good overview/ marking spiel over on the Cisco Website here

One of the features of DNA-C is the ability to display heat maps for the wireless coverage – much like Prime Infrastructure does, but it has the added advantage of being able to see health scores of each of the APs..

CCNA 200-301: Cisco DNA Center

Now to manually add each floor plan, and manually assign the location for each AP can be a real pain especially if you’re doing a large multi story building or a warehouse with hundreds of APs. Fortunately Cisco DNA-C allows you to import these from a Ekahau File directly and magically all your APs are placed on the floor plan with the correct antennas (there is a bug ID that relates to the elevations and Azimuth being out).

This blog piece isn’t about how to import the Ekahau file into Cisco’s DNA-C there is a good one from Ekahau in the video below.

This post is about how if your AP name and AP model don’t match the APs actually deployed that the import doesn’t automatically map the provisioned APs to the real APs and that means you need to manually map potentially 100s of APs.

Now you could open the predictive design, and manually update the name and model (if applicable) of every AP but that would take ages. In the Ekahau Advanced course there was a python script that would update AP names, but it relied on you having a spread sheet of the old and new name, this again isn’t the most practical when 99% of customers have a naming standard.

I built on the Python script that was shown in the Ekahau Advanced Course to update all the names from a naming standard of a prefix before the AP number and then a suffix after the AP number.

Example: <prefex>01<suffix>

import zipfile
import os
import csv
import json
import sys
import shutil
import re

# Get current working directory
working_directory = os.getcwd()
#print(working_directory)

# Get project file name passed into script by user
filename = input('Project file: ')
#print (filename)

# The project name, filename remove the extension (last 4x characters)
project_name = filename[:-4]
#print(project_name)

# Unzip the .esx project file into foler named "project_name"
with zipfile.ZipFile(filename,'r') as zip_ref:
	zip_ref.extractall(project_name)

# Read the accessPoints.json file
with open(working_directory + '/' + project_name + '/accessPoints.json', 'r') as file :
	accessPoints = json.load(file)
	
#Request Naming Convention
NamePrefex = input("Please input the AP Naming prefex (wwmvmfdw): ")
NameSuffix = input("Please input the AP Naming prefex (c91): ")

for ap in accessPoints['accessPoints']:
	old_ap_name = ap['name']
	print(old_ap_name)
	#AP-(\d+)
	new_ap_name = NamePrefex + str(re.search(r'\d+', old_ap_name).group(0)) + NameSuffix
	print(new_ap_name)
	ap['name'] = new_ap_name
	if old_ap_name != new_ap_name:
		print(old_ap_name, 'replaced with', new_ap_name)
	if old_ap_name == new_ap_name:
		print(old_ap_name, 'left unchanged')

try:	
	with open(working_directory + '/' + project_name + '/accessPoints.json', 'w') as file:
		json.dump(accessPoints, file, indent=4)

except Exception as e:
	print(e)

new_file_name = project_name + '_re-zip'

try:
	shutil.make_archive(new_file_name, 'zip', project_name)
	shutil.move(new_file_name + '.zip', new_file_name + '.esx')
	shutil.rmtree(project_name)
except Exception as e:
	print(e)

Now I have also come across a number of predictive lately where the AP model doesn’t match the installed model – yes I know you should always design with the correct AP model, but in this case the designs were all done with 3700/ 2800 series APs and then the customer installed 9100 series APs, but with the same external Antenna models used within the design.

Because that the APs had different heights and antennas it wasn’t as easy as just bulk updating in Ekahau. So I built a script that would take a CSV of old Model and New Model and update all the APs into Ekahau.

import zipfile
import os
import csv
import json
import sys
import shutil
import re

# Get current working directory
working_directory = os.getcwd()
#print(working_directory)

# Get project file name passed into script by user
filename = input('Project file: ')
#print (filename)

# The project name, filename remove the extension (last 4x characters)
project_name = filename[:-4]
#print(project_name)

# Unzip the .esx project file into foler named "project_name"
with zipfile.ZipFile(filename,'r') as zip_ref:
	zip_ref.extractall(project_name)

# Read the accessPoints.json file
with open(working_directory + '/' + project_name + '/accessPoints.json', 'r') as file :
	accessPoints = json.load(file)

# Read CSV as Dictionary
# This CSV file needs to be local to the Python script
try:
	with open('old_models.csv', 'r', encoding='utf-8-sig') as csv_file:
		reader = csv.DictReader(csv_file)
		csv_data = [record for record in reader]
except Exception as e:
	print(e)
	sys.exit()

def find_AP_by_name(old_model: str, csv_data: dict):
	new_model = old_model
	for entry in csv_data:
		if entry['old_ap_model'] == old_model:
			new_model = entry['new_ap_model']
	return new_model	

for ap in accessPoints['accessPoints']:
	old_ap_model = ap['model']
	new_ap_model = find_AP_by_name(ap['model'], csv_data)
	ap['model'] = new_ap_model
	if old_ap_model != new_ap_model:
		print(old_ap_model, 'replaced with', new_ap_model)
#	if old_ap_name == new_ap_name:
#		print(old_ap_name, 'left unchanged')

try:	
	with open(working_directory + '/' + project_name + '/accessPoints.json', 'w') as file:
		json.dump(accessPoints, file, indent=4)

except Exception as e:
	print(e)

new_file_name = project_name + '_re-zip'

try:
	shutil.make_archive(new_file_name, 'zip', project_name)
	shutil.move(new_file_name + '.zip', new_file_name + '.esx')
	shutil.rmtree(project_name)
except Exception as e:
	print(e)

Special thanks to François Vergès @VergesFrancois who provided the base code that I utilised to build these scripts with.

You can find the above scripts and also one combining both the AP rename and model changer on my GitHub site here: https://github.com/TheWlan/Ekahau-Python-Scripts

Leave a comment