Created
September 7, 2019 13:33
-
-
Save jasonrahm/f65b3db4280c34bbf23daaaf3b2874e0 to your computer and use it in GitHub Desktop.
This script will grab an iRule and its stats from a BIG-IP and auto-generate the iRuleRuntimeCalculator spreadsheet
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
# coding=utf-8 | |
# | |
# Copyright 2015-2019 F5 Networks Inc. | |
# | |
# Licensed under the Apache License, Version 2.0 (the "License"); | |
# you may not use this file except in compliance with the License. | |
# You may obtain a copy of the License at | |
# | |
# http://www.apache.org/licenses/LICENSE-2.0 | |
# | |
# Unless required by applicable law or agreed to in writing, software | |
# distributed under the License is distributed on an "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
# See the License for the specific language governing permissions and | |
# limitations under the License. | |
# | |
# usage: runtime_calc.py [-h] host username rule | |
######################################################## | |
# Imports | |
######################################################## | |
from f5.bigip import ManagementRoot | |
from xlsxwriter.utility import xl_range | |
import argparse | |
import getpass | |
import re | |
import requests | |
import time | |
import xlsxwriter | |
# Disable cert warnings for lab gear | |
requests.packages.urllib3.disable_warnings() | |
######################################################## | |
# Build CLI options arguments | |
######################################################## | |
# Create parser | |
parser = argparse.ArgumentParser() | |
parser.add_argument('host', nargs=1) | |
parser.add_argument('username', nargs=1) | |
parser.add_argument('rule', nargs=1) | |
args = parser.parse_args() | |
######################################################## | |
# Get the iRule and its stats from BIG-IP | |
######################################################## | |
# Ask user for password | |
pw = getpass.getpass(prompt='\n\tWell hello {}, please enter your password: '.format(args.username[0])) | |
# Connect to BIG-IP | |
obj = ManagementRoot(args.host[0], args.username[0], pw) | |
# System CPU Info from /proc/cpuinfo | |
''' | |
[root@ltm3:Active:Standalone] config # cat /proc/cpuinfo | grep ^cpu.MHz | |
cpu MHz : 3095.158 | |
cpu MHz : 3095.158 | |
''' | |
# Use the REST bash utility to grab that data remotely | |
cpuinfo = obj.tm.util.bash.exec_cmd('run', utilCmdArgs='-c "cat /proc/cpuinfo | grep ^cpu.MHz" ') | |
# Use regex to find the numbers (not digits) in the string, convert them to floats, then add them together | |
cpu_speed = sum(map(float, re.findall(r"[-+]?\d*\.\d+|\d+", cpuinfo.commandResult))) | |
# Multiply by 1,000,000 to get Hz instead of MHz for calculations | |
cpu_speed = cpu_speed * 1000000 | |
# Grab the iRule | |
r1 = args.rule[0] | |
r = obj.tm.ltm.rules.rule.load(name=r1) | |
# Grab the iRule stats | |
rstats = r.stats.load() | |
######################################################## | |
# Create the Excel workbook | |
######################################################## | |
# Get the current time | |
timestr = time.strftime("%Y%m%d-%H%M%S") | |
# Name the workbook iRuleRuntimeCalculator__<rulename>__<timestamp> | |
fname = 'iRulesRuntimeCalculator__{}__{}.xlsx'.format(r.name, timestr) | |
workbook = xlsxwriter.Workbook(fname) | |
# Set the initial Excel window size | |
workbook.set_size(1500,1200) | |
######################################################## | |
# Cell Formatting Information | |
######################################################## | |
# iRule textbox formatting | |
textbox_options = { | |
'width': 1200, | |
'height': 1400, | |
'font': { 'color': 'white', 'size': 16 }, | |
'align': { 'vertical': 'top' }, | |
'gradient': { 'colors': ['#00205f', '#84358e'] } | |
} | |
# Title Block formatting | |
title_format = workbook.add_format({ | |
'bold': 1, | |
'border': 1, | |
'align': 'center', | |
'valign': 'vcenter', | |
}) | |
title_format.set_font_size(20) | |
title_format.set_font_color('white') | |
title_format.set_bg_color('#00205f') | |
# Section Header Formatting | |
secthdr_format = workbook.add_format({ | |
'bold': 1, | |
'border': 1, | |
'align': 'center', | |
'valign': 'vcenter', | |
}) | |
secthdr_format.set_font_size(16) | |
secthdr_format.set_font_color('white') | |
secthdr_format.set_bg_color('#00205f') | |
# Table Data Formatting - BOLD for headers and total | |
tabledata_format = workbook.add_format({ | |
'bold': 1, | |
'border': 1, | |
'align': 'center', | |
'valign': 'vcenter', | |
}) | |
tabledata_format.set_font_size(14) | |
# Table Data Formatting - ints for rule data max requests | |
tabledata2_format = workbook.add_format({ | |
'bold': 1, | |
'border': 1, | |
'align': 'center', | |
'valign': 'vcenter', | |
'num_format': '0', | |
}) | |
tabledata2_format.set_font_size(14) | |
# Table Data Formatting - percentages for rule data | |
tabledata3_format = workbook.add_format({ | |
'bold': 1, | |
'border': 1, | |
'align': 'center', | |
'valign': 'vcenter', | |
'num_format': '0.0000000000000%', | |
}) | |
tabledata3_format.set_font_size(14) | |
######################################################## | |
# Create worksheet one for stats, two for iRule contents | |
######################################################## | |
worksheet1 = workbook.add_worksheet('iRule Stats') | |
worksheet2 = workbook.add_worksheet('iRule Contents') | |
######################################################## | |
# Generate iRule stats worksheet data | |
######################################################## | |
worksheet1.set_column(1, 1, 30) | |
worksheet1.set_column(2, 2, 15) | |
worksheet1.set_column(3, 5, 25) | |
worksheet1.merge_range('B2:F2', 'iRules Runtime Calculator - {}'.format(r.name), title_format) | |
worksheet1.write_string(5, 1, 'For more details, see article "Intermediate iRules: Evaluating Performance" on DevCentral:') | |
worksheet1.write_string(6, 1, 'https://devcentral.f5.com/s/articles/intermediate-irules-evaluating-performance-20433') | |
worksheet1.write_string(8, 1, 'Cycles/Sec', tabledata_format) | |
worksheet1.write_number(8, 3, cpu_speed, tabledata_format) | |
# Write the iRule data into the user data table | |
worksheet1.merge_range('B11:F11', 'Runtime / Request (cycles)', secthdr_format) | |
worksheet1.write_row(11, 1, ('Event Name', '# of Requests', 'MIN', 'AVG', 'MAX'), tabledata_format) | |
rowval = 12 | |
event_list = [] | |
for sl in rstats.entries: | |
raw_data = rstats.entries.get(sl).get('nestedStats').get('entries') | |
event_name = raw_data['eventType']['description'] | |
event_list.append(event_name) | |
executions = raw_data['totalExecutions']['value'] | |
min_cycles = raw_data['minCycles']['value'] | |
avg_cycles = raw_data['avgCycles']['value'] | |
max_cycles = raw_data['maxCycles']['value'] | |
worksheet1.write_row(rowval, 1, (str(event_name), int(executions), int(min_cycles), int(avg_cycles), int(max_cycles)), tabledata_format) | |
rowval += 1 | |
worksheet1.write_string(rowval, 1, 'Total', tabledata_format) | |
worksheet1.write_formula(rowval, 2, '=MAX({})'.format(xl_range(12,2,rowval-1,2)), tabledata_format) | |
worksheet1.write_formula(rowval, 3, '=SUM({})'.format(xl_range(12,3,rowval-1,3)), tabledata_format) | |
worksheet1.write_formula(rowval, 4, '=SUM({})'.format(xl_range(12,4,rowval-1,4)), tabledata_format) | |
worksheet1.write_formula(rowval, 5, '=SUM({})'.format(xl_range(12,5,rowval-1,5)), tabledata_format) | |
# increment rowval to start first analysis table | |
rowval += 3 | |
# Populate the run time /request (microseconds) table based on the rule stats | |
worksheet1.merge_range('B{0}:F{0}'.format(rowval), 'Runtime / Request (microseconds)', secthdr_format) | |
worksheet1.write_row(rowval, 1, ('Event Name', '# of Requests', 'MIN', 'AVG', 'MAX'), tabledata_format) | |
rowval += 1 | |
for event in event_list: | |
worksheet1.write_string(rowval, 1, event, tabledata_format) | |
worksheet1.write_formula(rowval, 2, '=C{}'.format(rowval - (3 + len(event_list))), tabledata_format) | |
worksheet1.write_formula(rowval, 3, '=D{}*1000000/$D$9'.format(rowval - (3 + len(event_list))), tabledata_format) | |
worksheet1.write_formula(rowval, 4, '=E{}*1000000/$D$9'.format(rowval - (3 + len(event_list))), tabledata_format) | |
worksheet1.write_formula(rowval, 5, '=F{}*1000000/$D$9'.format(rowval - (3 + len(event_list))), tabledata_format) | |
rowval += 1 | |
worksheet1.write_string(rowval, 1, 'Total', tabledata_format) | |
worksheet1.write_formula(rowval, 2, '=MAX({})'.format(xl_range(rowval-len(event_list),2,rowval-1,2)), tabledata_format) | |
worksheet1.write_formula(rowval, 3, '=SUM({})'.format(xl_range(rowval-len(event_list),3,rowval-1,3)), tabledata_format) | |
worksheet1.write_formula(rowval, 4, '=SUM({})'.format(xl_range(rowval-len(event_list),4,rowval-1,4)), tabledata_format) | |
worksheet1.write_formula(rowval, 5, '=SUM({})'.format(xl_range(rowval-len(event_list),5,rowval-1,5)), tabledata_format) | |
# increment rowval again to start second analysis table | |
rowval += 3 | |
# Populate the % CPU utilization /request table based on the rule stats | |
worksheet1.merge_range('B{0}:F{0}'.format(rowval), 'CPU Utilization / Request (percent)', secthdr_format) | |
worksheet1.write_row(rowval, 1, ('Event Name', '# of Requests', 'MIN', 'AVG', 'MAX'), tabledata_format) | |
rowval += 1 | |
for event in event_list: | |
worksheet1.write_string(rowval, 1, event, tabledata_format) | |
worksheet1.write_formula(rowval, 2, '=C{}'.format(rowval - 1 - (6 + 2*len(event_list))), tabledata_format) | |
worksheet1.write_formula(rowval, 3, '=D{}/$D$9'.format(rowval - 1 - (6 + 2*len(event_list))), tabledata3_format) | |
worksheet1.write_formula(rowval, 4, '=E{}/$D$9'.format(rowval - 1 - (6 + 2*len(event_list))), tabledata3_format) | |
worksheet1.write_formula(rowval, 5, '=F{}/$D$9'.format(rowval - 1 - (6 + 2*len(event_list))), tabledata3_format) | |
rowval += 1 | |
worksheet1.write_string(rowval, 1, 'Total', tabledata_format) | |
worksheet1.write_formula(rowval, 2, '=MAX({})'.format(xl_range(rowval-len(event_list),2,rowval-1,2)), tabledata_format) | |
worksheet1.write_formula(rowval, 3, '=SUM({})'.format(xl_range(rowval-len(event_list),3,rowval-1,3)), tabledata3_format) | |
worksheet1.write_formula(rowval, 4, '=SUM({})'.format(xl_range(rowval-len(event_list),4,rowval-1,4)), tabledata3_format) | |
worksheet1.write_formula(rowval, 5, '=SUM({})'.format(xl_range(rowval-len(event_list),5,rowval-1,5)), tabledata3_format) | |
# increment rowval again to start third analysis table | |
rowval += 3 | |
# Populate the Max # of requests table based on the rule stats | |
worksheet1.merge_range('B{0}:F{0}'.format(rowval), 'Max Requests', secthdr_format) | |
worksheet1.write_row(rowval, 1, ('Event Name', '# of Requests', 'MIN', 'AVG', 'MAX'), tabledata_format) | |
rowval += 1 | |
for event in event_list: | |
worksheet1.write_string(rowval, 1, event, tabledata_format) | |
worksheet1.write_formula(rowval, 2, '=C{}'.format(rowval - (3 + len(event_list))), tabledata_format) | |
worksheet1.write_formula(rowval, 3, '=1/D{}'.format(rowval - (3 + len(event_list))), tabledata2_format) | |
worksheet1.write_formula(rowval, 4, '=1/E{}'.format(rowval - (3 + len(event_list))), tabledata2_format) | |
worksheet1.write_formula(rowval, 5, '=1/F{}'.format(rowval - (3 + len(event_list))), tabledata2_format) | |
rowval += 1 | |
worksheet1.write_string(rowval, 1, 'Total', tabledata_format) | |
worksheet1.write_formula(rowval, 2, '=MAX({})'.format(xl_range(rowval-len(event_list),2,rowval-1,2)), tabledata_format) | |
worksheet1.write_formula(rowval, 3, '=1/D{}'.format(rowval - (3 + len(event_list))), tabledata2_format) | |
worksheet1.write_formula(rowval, 4, '=1/E{}'.format(rowval - (3 + len(event_list))), tabledata2_format) | |
worksheet1.write_formula(rowval, 5, '=1/F{}'.format(rowval - (3 + len(event_list))), tabledata2_format) | |
######################################################## | |
# Generate iRule contents worksheet data | |
######################################################## | |
worksheet2.insert_textbox('B2', r.apiAnonymous, textbox_options) | |
######################################################## | |
# Finish up! | |
######################################################## | |
print('\n\n\tHoly iRule perfomance analysis, Batman! Your mission file is {}\n\n'.format(fname)) | |
# Close the workbook | |
workbook.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment