def main(parameters): '''Gets the licenses for our network devices''' text = 'Right now, I found these licenses:\n' devices = apicem.get_network_device() pool = concurrent.futures.ThreadPoolExecutor(max_workers=40) futures = [ pool.submit(apicem.get_licenseinfo_for_network_device, devid['id']) for devid in devices ] results = [r.result() for r in concurrent.futures.as_completed(futures)] for x in range(len(results)): if results[x] != None: licenses = [] for lic in results[x]: if lic['status'] in parameters['LicenseStatus'] or parameters[ 'LicenseStatus'] == '': licenses.append(lic['name']) if licenses != []: text += '- ' + devices[x]['hostname'] + ' (' + devices[x][ 'id'] + '): ' + ','.join(licenses) + '\n' if text == 'Right now, I found these licenses:\n': text = 'Right now, no devices have licenses.' answer = {'text': text, 'markdown': text, 'file': None} return answer
def main(parameters): '''Returns a list of all devices that have a certain license''' devices = apicem.get_network_device_with_license(parameters['licensename']) if 'errorCode' in devices: if devices['detail'] == 'License file name does not exists': nw_devices = apicem.get_network_device() license_names = [] pool = concurrent.futures.ThreadPoolExecutor(max_workers=40) futures = [ pool.submit(apicem.get_licenseinfo_for_network_device, devid['id']) for devid in nw_devices ] results = [ r.result() for r in concurrent.futures.as_completed(futures) ] for devlic in results: if devlic != None: for lic in devlic: license_names.append(lic['name']) license_names = list(set(license_names)) if len(license_names) > 0: text = 'This is not a valid name for a license on any of your devices. Please ask again with a valid license. Currently, the following licenses are available on devices in your network:\n' for x in license_names: text += '- ' + x + '\n' else: text = 'None of your devices have any licenses registered on them .' return text text = 'There are ' + str(len(devices)) + ' devices with this license:\n' pool = concurrent.futures.ThreadPoolExecutor(max_workers=40) futures = [ pool.submit(apicem.get_network_device_by_id, id) for id in devices ] results = [r.result() for r in concurrent.futures.as_completed(futures)] for i in results: text += '- ' + i['hostname'] + ' (' + i['id'] + ')\n' answer = {'text': text, 'markdown': text, 'file': None} return answer
def main(parameters): '''Gets a list of all network devices''' devices = apicem.get_network_device() device_filter = [] for i in parameters['NetworkDevice']: device_filter.append(i) text = '' for i in devices: if i['family'] in device_filter or device_filter == []: text += '- ' + i['hostname'] + ' (' + i['platformId'] + ')\n' answer = {'text': text, 'markdown': text, 'file': None} return answer
def main(parameters): '''Shows what problems are present for network devices - categorizes NW devices by problem in the output''' devices = apicem.get_network_device() errors = {} for i in devices: if i['collectionStatus'] != 'Managed': if i['collectionStatus'] == 'In Progress': if 'In Progress' not in errors: errors['In Progress'] = {'devices': [], 'count': 0} errors['In Progress']['devices'].append('- ' + i['hostname'] + ' (' + i['platformId'] + ')') errors['In Progress']['count'] += 1 else: if i['errorCode'] not in errors: errors[i['errorCode']] = {'devices': [], 'count': 0} errors[i['errorCode']]['devices'].append('- ' + i['hostname'] + ' (' + i['platformId'] + ')') errors[i['errorCode']]['count'] += 1 for e in errors: if e == 'DEV-UNREACHED': errors[ 'Device unreachable: SNMP Timeouts are occurring with these devices'] = errors.pop( e) text = 'I found the following problems with your network devices:\n\n' for e in errors: text += str(e) + ' (' + str(errors[e]['count']) + ')\n' for dev in errors[e]['devices']: text += dev + '\n' text += '\n\n' answer = {'text': text, 'markdown': text, 'file': None} return answer
def main(parameters): ''' Gets the temperature of a specified device NOTE: not implemented yet ''' nw_devices = apicem.get_network_device() all_devices = [] for device in nw_devices: all_devices.append(device['id']) cli = apicem.post_cli_request('root', ['show version'], all_devices, 'test') print cli answer = { 'text': 'This feature is not yet implemented.', 'markdown': 'This feature is not yet implemented.', 'file': None } return answer
def main(parameters): ''' Gets the configuration of a specific device NOTE: not implemented yet ''' devices = apicem.get_network_device() apicem.get_config("8dbd8068-1091-4cde-8cf5-d1b58dc5c9c7") output_text = apicem.get_config("8dbd8068-1091-4cde-8cf5-d1b58dc5c9c7") split_output = output_text.split('\n') while split_output[0] == '' or split_output[ 0] == 'Building configuration...': split_output.pop(0) text = '```' for item in split_output: text += item + '\n' text += '```' answer = {'text': text, 'markdown': text, 'file': None} return answer
def main(parameters): '''Returns a list of 'free' ports - using ports that are currently not up in APIC-EM''' location_req = parameters['location'] role_req = parameters['type'] output_structure = {} all_locations = apicem.get_location() location_available = False if len(all_locations) > 0: for location in all_locations: if location_req == location['locationName']: location_available = True else: if location_req != 'Any' and location_req != 'any': answer = { 'text': 'No locations have been defined! Please either define a location in the controller, or use \"Any\" for the location.', 'markdown': 'No locations have been defined! Please either define a location in the controller, or use \"Any\" for the location.', 'file': None } return answer if location_available == False: if location_req != 'Any' and location_req != 'any': answer = { 'text': 'No locations with this name has been defined! Please either define a location in the controller, or use \"Any\" for the location.', 'markdown': 'No locations with this name has been defined! Please either define a location in the controller, or use \"Any\" for the location.', 'file': None } return answer nw_devices = apicem.get_network_device() for device in nw_devices: output_structure[device['id']] = { 'series': device['series'], 'lineCardCount': device['lineCardCount'], 'interfaceCount': device['interfaceCount'], 'family': device['family'], 'hostname': device['hostname'], 'roleSource': device['roleSource'], 'platformId': device['platformId'], 'role': device['role'], 'location': device['location'], 'type': device['type'], 'lineCardId': device['lineCardId'], 'locationName': device['locationName'], 'available_ports': 0, 'port_list': [], 'port_type_count': None } #Add ports to the devices ports = apicem.get_interface() for port in ports: if port['status'] != 'up' and port['interfaceType'] == 'Physical': output_structure[port['deviceId']]['available_ports'] += 1 output_structure[port['deviceId']]['port_list'].append( port['portName']) #Remove devices that do not have available ports for k in output_structure.keys(): if output_structure[k]['available_ports'] == 0: del output_structure[k] #Remove devices that do not fit the role requirement for k in output_structure.keys(): if output_structure[k]['role'] != role_req: del output_structure[k] #Remove devices that do not fit the location requirement if location_req != 'Any' and location_req != 'any': for k in output_structure.keys(): if output_structure[k]['locationName'] != location_req: del output_structure[k] for device in output_structure: portslist = [] for port in output_structure[device]['port_list']: m = re.search("\d", port) if m: portslist.append(port[:m.start()]) output_structure[device]['port_type_count'] = Counter(portslist) main_dir = os.path.split(os.path.split(os.path.realpath(__file__))[0])[0] font_path = os.path.join(main_dir, 'resources', 'CiscoSansTTExtraLight.ttf') switch_pic_path = os.path.join(main_dir, 'resources', 'switch_ports.png') router_pic_path = os.path.join(main_dir, 'resources', 'router_ports.png') small_font = ImageFont.truetype(font_path, 45) normal_font = ImageFont.truetype(font_path, 50) large_font = ImageFont.truetype(font_path, 115) increment = 0 for device in output_structure: if output_structure[device]['role'] == 'BORDER ROUTER': img = Image.open(router_pic_path) else: img = Image.open(switch_pic_path) draw = ImageDraw.Draw(img) ports_overview = [] for ptype in output_structure[device]['port_type_count']: ports_overview.append( ptype + ': ' + str(output_structure[device]['port_type_count'][ptype])) device_name = output_structure[device]['series'] if device_name[-8:] == 'Switches': device_name = device_name[:-8] draw.multiline_text((265, 40), str(output_structure[device]['available_ports']), (0, 0, 0), font=large_font, align="left") draw.multiline_text((38, 200), device_name, (0, 0, 0), font=normal_font, align="left") for i in range(len(ports_overview)): draw.multiline_text((680, 25 + 50 * i), ports_overview[i], (0, 0, 0), font=small_font, align="left") img.save('port_counts_part' + str(increment) + '.png') increment += 1 if output_structure == {}: text = 'I could not find a device that fits your requirements.' answer = {'text': text, 'markdown': text, 'file': None} else: #Image stitching img_height = 297 * increment background_image = Image.new('RGB', (1289, img_height)) for i in range(increment): background_image.paste( Image.open('port_counts_part' + str(i) + '.png'), (0, 297 * i)) background_image.save('port_counts.png') send_image = open('port_counts.png', 'rb') text = 'Please check manually on the device to verify that nothing is plugged into the ports' answer = {'text': text, 'markdown': text, 'file': send_image} return answer
def main(parameters): ''' Gets information about the status of the APIC-EM controller and about the network devices Returns the result as a picture in Spark ''' text = '' apic_health = 100 reachability_health = 100 status = 'APIC-EM Online' nw_devices = apicem.get_network_device() ok_count = 0 for device in nw_devices: if device['reachabilityStatus'] == 'Reachable': ok_count += 1 if ok_count == len(nw_devices): device_reachability = 'All devices are reachable!' else: reachability_health = 100 * ok_count/len(nw_devices) device_reachability = str(ok_count) + '/' + str(len(nw_devices)) + ' devices reachable' main_dir = os.path.split(os.path.split(os.path.realpath(__file__))[0])[0] font_path = os.path.join(main_dir, 'resources', 'CiscoSansTTExtraLight.ttf') picture_path = os.path.join(main_dir, 'resources', 'status_template.png') img = Image.open(picture_path) draw = ImageDraw.Draw(img) normal_font = ImageFont.truetype(font_path, 56) #DRAW APIC-EM and devices logos img.paste(Image.open(os.path.join(main_dir, 'resources', 'apicem_logo.png'), 'r'), (100, 100)) img.paste(Image.open(os.path.join(main_dir, 'resources', 'devices_logo.png'), 'r'), (1070, 160)) #DRAW APIC-EM health if apic_health == 100: img.paste(Image.open(os.path.join(main_dir, 'resources', 'green_status.png'), 'r'), (580, 60)) elif apic_health > 70: img.paste(Image.open(os.path.join(main_dir, 'resources', 'yellow_status.png'), 'r'), (580, 60)) else: img.paste(Image.open(os.path.join(main_dir, 'resources', 'red_status.png'), 'r'), (580, 60)) #DRAW Device health if reachability_health == 100: img.paste(Image.open(os.path.join(main_dir, 'resources', 'green_status.png'), 'r'), (1600, 60)) elif reachability_health > 70: img.paste(Image.open(os.path.join(main_dir, 'resources', 'yellow_status.png'), 'r'), (1600, 60)) else: img.paste(Image.open(os.path.join(main_dir, 'resources', 'red_status.png'), 'r'), (1600, 60)) # Alignment of text on the picture (first = left/right; second = up/down) draw.multiline_text((45, 420), status, (0, 0, 0), font=normal_font, align="center") draw.multiline_text((1045, 420), device_reachability, (0, 0, 0), font=normal_font, align="center") img.save('apicem_status.png') send_image = open('apicem_status.png', 'rb') answer = { 'text': text, 'markdown': text, 'file': send_image } return answer