From 79fb905fd71f3e3567d40926f0654954b2e07ed1 Mon Sep 17 00:00:00 2001 From: Matthew Stidham Date: Fri, 7 May 2021 16:58:25 -0700 Subject: [PATCH] Building Grafana automation Signed-off-by: Matthew Stidham --- py-json/cv_test_manager.py | 6 ++- py-scripts/csv_to_influx.py | 8 ++++ py-scripts/dataplane_to_grafana.sh | 15 +++++- py-scripts/grafana_profile.py | 73 ++++++++++++++++++++++++----- py-scripts/lf_dataplane_test.py | 8 +++- py-scripts/lf_wifi_capacity_test.py | 14 ++++-- py-scripts/wifi_cap_to_grafana.sh | 19 ++++++-- 7 files changed, 117 insertions(+), 26 deletions(-) diff --git a/py-json/cv_test_manager.py b/py-json/cv_test_manager.py index fb13663d..c62bc9ae 100644 --- a/py-json/cv_test_manager.py +++ b/py-json/cv_test_manager.py @@ -284,7 +284,7 @@ class cv_test(Realm): # cv_cmds: Array of raw chamber-view commands, such as "cv click 'button-name'" # These (and the sets) are applied after the test is created and before it is started. def create_and_run_test(self, load_old_cfg, test_name, instance_name, config_name, sets, - pull_report, lf_host, lf_user, lf_password, cv_cmds): + pull_report, lf_host, lf_user, lf_password, cv_cmds, graphgroupsfile=None): load_old = "false" if load_old_cfg: load_old = "true" @@ -336,6 +336,10 @@ class cv_test(Realm): location = location.replace('\"Report Location:::', '') location = location.replace('\"', '') report = lf_rpt() + if graphgroupsfile: + filelocation=open(graphgroupsfile, 'w') + filelocation.write(location) + filelocation.close() print(location) self.report_dir = location try: diff --git a/py-scripts/csv_to_influx.py b/py-scripts/csv_to_influx.py index a2f2c160..91adede1 100755 --- a/py-scripts/csv_to_influx.py +++ b/py-scripts/csv_to_influx.py @@ -57,6 +57,10 @@ class CSVtoInflux(): short_description_index = line.index('short-description') graph_group_index = line.index('Graph-Group') units_index = line.index('Units') + testbed_index = line.index('test-rig') + duthwversion = line.index('dut-hw-version') + dutswversion = line.index('dut-sw-version') + dutserialnum = line.index('dut-serial-num') line = fp.readline() while line: line = line.split('\t') #split the line by tabs to separate each item in the string @@ -70,6 +74,10 @@ class CSVtoInflux(): tags['short-description'] = line[short_description_index] tags['test_details'] = line[test_details_index] tags['Graph-Group'] = line[graph_group_index] + tags['DUT-HW-version'] = line[duthwversion] + tags['DUT-SW-version'] = line[dutswversion] + tags['DUT-Serial-Num'] = line[dutserialnum] + tags['testbed'] = line[testbed_index] tags['Units'] = line[units_index] for item in self.influx_tag: # Every item in the influx_tag command needs to be added to the tags variable tags[item[0]] = item[1] diff --git a/py-scripts/dataplane_to_grafana.sh b/py-scripts/dataplane_to_grafana.sh index 2fa3197d..a037b080 100755 --- a/py-scripts/dataplane_to_grafana.sh +++ b/py-scripts/dataplane_to_grafana.sh @@ -8,13 +8,24 @@ Help() } MGR=192.168.1.7 INFLUXTOKEN=Tdxwq5KRbj1oNbZ_ErPL5tw_HUH2wJ1VR4dwZNugJ-APz__mEFIwnqHZdoobmQpt2fa1VdWMlHQClR8XNotwbg== +GRAFANATOKEN=eyJrIjoiZTJwZkZlemhLQVNpY3hiemRjUkNBZ3k2RWc3bWpQWEkiLCJuIjoibWFzdGVyIiwiaWQiOjF9 +TESTBED=Stidmatt-01 +GROUPS=/tmp/lf_cv_rpt_filelocation.txt #Replace my arguments with your setup. Separate your ssid arguments with spaces and ensure the names are lowercase echo "Make new DUT" ./create_chamberview_dut.py --lfmgr ${MGR} --dut_name DUT_TO_GRAFANA_DUT --ssid "ssid_idx=0 ssid=lanforge security=WPA2 password=password bssid=04:f0:21:2c:41:84 traffic=wiphy1" echo "Build Chamber View Scenario" #change the lfmgr to your system, set the radio to a working radio on your LANforge system, same with the ethernet port. -./create_chamberview.py --lfmgr ${MGR} --create_scenario DUT_TO_GRAFANA_SCENARIO --line "Resource=1.1 Profile=default Amount=32 Uses-1=wiphy1 DUT=DUT_TO_GRAFANA_DUT Traffic=wiphy1 Freq=-1" --line "Resource=1.1 Profile=upstream Amount=1 Uses-1=eth1 DUT=DUT_TO_GRAFANA_DUT Traffic=eth1 Freq=-1" +./create_chamberview.py --lfmgr ${MGR} --create_scenario DUT_TO_GRAFANA_SCENARIO \ +--line "Resource=1.1 Profile=default Amount=32 Uses-1=wiphy1 DUT=DUT_TO_GRAFANA_DUT Traffic=wiphy1 Freq=-1" \ +--line "Resource=1.1 Profile=upstream Amount=1 Uses-1=eth1 DUT=DUT_TO_GRAFANA_DUT Traffic=eth1 Freq=-1" #config_name doesn't matter, change the influx_host to your LANforge device, echo "run Dataplane test" -./lf_dataplane_test.py --mgr ${MGR} --instance_name dataplane-instance --config_name test_config --upstream 1.1.eth1 --station 1.1.14 --dut linksys-8450 --influx_host ${MGR} --influx_port 8086 --influx_org Candela --influx_token ${INFLUXTOKEN} --influx_bucket lanforge --influx_tag testbed Stidmatt-01 \ No newline at end of file +./lf_dataplane_test.py --mgr ${MGR} --instance_name dataplane-instance --config_name test_config --upstream 1.1.eth1 \ +--station 1.1.14 --dut linksys-8450 --influx_host ${MGR} --influx_port 8086 --influx_org Candela --influx_token ${INFLUXTOKEN} \ +--influx_bucket lanforge --influx_tag testbed ${TESTBED} --graphgroups ${GROUPS} + +./grafana_profile.py --create_custom --title ${TESTBED} --influx_bucket lanforge --mgr 192.168.1.7 --grafana_token ${GRAFANATOKEN} \ +--grafana_host 192.168.1.7 --testbed ${TESTBED} --graph-groups ${GROUPS} \ +--scripts Dataplane --scripts 'WiFi Capacity' diff --git a/py-scripts/grafana_profile.py b/py-scripts/grafana_profile.py index 0d643258..4f353c06 100755 --- a/py-scripts/grafana_profile.py +++ b/py-scripts/grafana_profile.py @@ -61,7 +61,20 @@ class UseGrafana(LFCliBase): scriptname, groupBy, index, - graph_group): + graph_group, + testbed): + query = ( + 'from(bucket: "%s")\n ' + '|> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n ' + '|> filter(fn: (r) => r["script"] == "%s")\n ' + % (bucket, scriptname)) + queryend = ('|> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n ' + '|> yield(name: "mean")\n ') + if graph_group is not None: + graphgroup = ('|> filter(fn: (r) => r["Graph-Group"] == "%s")\n' % graph_group) + query += graphgroup + if testbed is not None: + query += ('|> filter(fn: (r) => r["testbed"] == "%s")\n' % testbed) targets = dict() targets['delimiter'] = ',' targets['groupBy'] = groupBy @@ -69,9 +82,7 @@ class UseGrafana(LFCliBase): targets['ignoreUnknown'] = False targets['orderByTime'] = 'ASC' targets['policy'] = 'default' - targets['query'] = ( - 'from(bucket: "%s")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r["script"] == "%s")\n |> filter(fn: (r) => r["Graph-Group"] == "%s")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: "mean")\n ' % ( - bucket, scriptname, graph_group)) + targets['query'] = query + queryend targets['refId'] = dict(enumerate(string.ascii_uppercase, 1))[index + 1] targets['resultFormat'] = "time_series" targets['schema'] = list() @@ -82,7 +93,9 @@ class UseGrafana(LFCliBase): def create_custom_dashboard(self, scripts=None, title=None, - bucket=None): + bucket=None, + graph_groups=None, + testbed=None): options = string.ascii_lowercase + string.ascii_uppercase + string.digits uid = ''.join(random.choice(options) for i in range(9)) input1 = dict() @@ -108,9 +121,6 @@ class UseGrafana(LFCliBase): panels = list() index = 1 for scriptname in scripts: - graph_groups = ['Per Stations Rate DL', - 'Per Stations Rate UL', - 'Per Stations Rate UL+DL'] for graph_group in graph_groups: panel = dict() @@ -138,7 +148,7 @@ class UseGrafana(LFCliBase): targets = list() counter = 0 - new_target = self.maketargets(bucket, scriptname, groupBy, counter, graph_group) + new_target = self.maketargets(bucket, scriptname, groupBy, counter, graph_group,testbed) targets.append(new_target) fieldConfig = dict() @@ -201,7 +211,10 @@ class UseGrafana(LFCliBase): panel['timeFrom'] = None panel['timeRegions'] = list() panel['timeShift'] = None - panel['title'] = scriptname+' '+graph_group + if graph_group is not None: + panel['title'] = scriptname + ' ' + graph_group + else: + panel['title'] = scriptname panel['transformations'] = list() panel['transformations'].append(transformation) panel['type'] = "graph" @@ -233,6 +246,22 @@ class UseGrafana(LFCliBase): # print(json.dumps(input1, indent=2)) return self.GR.create_dashboard_from_dict(dictionary=json.dumps(input1)) + def get_graph_groups(self, + target_csvs): + groups = [] + for target_csv in target_csvs: + with open(target_csv) as fp: + line = fp.readline() + line = line.split('\t') + graph_group_index = line.index('Graph-Group') + line = fp.readline() + while line: + line = line.split('\t') #split the line by tabs to separate each item in the string + graphgroup = line[graph_group_index] + groups.append(graphgroup) + line = fp.readline() + print(groups) + return list(set(groups)) def main(): parser = LFCliBase.create_basic_argparse( @@ -247,6 +276,15 @@ def main(): --grafana_token --dashbaord_name --scripts "Wifi Capacity" + + Create a custom dashboard with the following command: + ./grafana_profile.py --create_custom yes + --title Dataplane + --influx_bucket lanforge + --grafana_token TOKEN + --graph_groups 'Per Stations Rate DL' + --graph_groups 'Per Stations Rate UL' + --graph_groups 'Per Stations Rate UL+DL' ''') required = parser.add_argument_group('required arguments') required.add_argument('--grafana_token', help='token to access your Grafana database', required=True) @@ -261,11 +299,15 @@ def main(): optional.add_argument('--grafana_host', help='Grafana host', default='localhost') optional.add_argument('--list_dashboards', help='List dashboards on Grafana server', default=None) optional.add_argument('--dashboard_json', help='JSON of existing Grafana dashboard to import', default=None) - optional.add_argument('--create_custom', help='Guided Dashboard creation', default=None) + optional.add_argument('--create_custom', help='Guided Dashboard creation', action='store_true') optional.add_argument('--dashboard_title', help='Titles of dashboards', default=None, action='append') optional.add_argument('--scripts', help='Scripts to graph in Grafana', default=None, action='append') optional.add_argument('--title', help='title of your Grafana Dashboard', default=None) optional.add_argument('--influx_bucket', help='Name of your Influx Bucket', default=None) + optional.add_argument('--graph-groups', help='How you want to filter your graphs on your dashboard', + action='append', default=[None]) + optional.add_argument('--testbed', help='Which testbed you want to query', default=None) + optional.add_argument('--kpi', help='KPI file(s) which you want to graph form', action='append', default=None) args = parser.parse_args() Grafana = UseGrafana(args.grafana_token, @@ -284,10 +326,15 @@ def main(): if args.dashboard_json is not None: Grafana.create_dashboard_from_data(args.dashboard_json) - if args.create_custom is not None: + if args.kpi is not None: + args.graph_groups = args.graph_groups+Grafana.get_graph_groups(args.graph_groups) + + if args.create_custom: Grafana.create_custom_dashboard(scripts=args.scripts, title=args.title, - bucket=args.grafana_bucket) + bucket=args.influx_bucket, + graph_groups=args.graph_groups, + testbed=args.testbed) if __name__ == "__main__": diff --git a/py-scripts/lf_dataplane_test.py b/py-scripts/lf_dataplane_test.py index 6b951383..a9abefc2 100755 --- a/py-scripts/lf_dataplane_test.py +++ b/py-scripts/lf_dataplane_test.py @@ -134,6 +134,7 @@ class DataplaneTest(cvtest): raw_lines=[], raw_lines_file="", sets=[], + graphgroups=None ): super().__init__(lfclient_host=lf_host, lfclient_port=lf_port) @@ -157,6 +158,7 @@ class DataplaneTest(cvtest): self.raw_lines = raw_lines self.raw_lines_file = raw_lines_file self.sets = sets + self.graphgroups = graphgroups def setup(self): # Nothing to do at this time. @@ -201,7 +203,7 @@ class DataplaneTest(cvtest): self.create_and_run_test(self.load_old_cfg, self.test_name, self.instance_name, self.config_name, self.sets, self.pull_report, self.lf_host, self.lf_user, self.lf_password, - cv_cmds) + cv_cmds, graphgroupsfile=self.graphgroups) self.rm_text_blob(self.config_name, blob_test) # To delete old config with same name @@ -244,6 +246,7 @@ def main(): help="Specify requested upload speed. Percentage of theoretical is also supported. Default: 0") parser.add_argument("--duration", default="", help="Specify duration of each traffic run") + parser.add_argument("--graphgroups", help="File to save graphgroups to", default=None) args = parser.parse_args() @@ -267,7 +270,8 @@ def main(): disables = args.disable, raw_lines = args.raw_line, raw_lines_file = args.raw_lines_file, - sets = args.set + sets = args.set, + graphgroups = args.graphgroups ) CV_Test.setup() CV_Test.run() diff --git a/py-scripts/lf_wifi_capacity_test.py b/py-scripts/lf_wifi_capacity_test.py index 0cd35a24..fda1261e 100755 --- a/py-scripts/lf_wifi_capacity_test.py +++ b/py-scripts/lf_wifi_capacity_test.py @@ -351,7 +351,8 @@ class WiFiCapacityTest(cv_test): sets=[], influx_host="localhost", influx_port=8086, - report_dir="" + report_dir="", + graphgroups=None ): super().__init__(lfclient_host=lfclient_host, lfclient_port=lf_port) @@ -386,7 +387,8 @@ class WiFiCapacityTest(cv_test): self.sets = sets self.influx_host = influx_host, self.influx_port = influx_port - self.report_dir=report_dir + self.report_dir = report_dir + self.graphgroups = graphgroups def setup(self): if self.create_stations and self.stations != "": @@ -460,7 +462,7 @@ class WiFiCapacityTest(cv_test): self.create_and_run_test(self.load_old_cfg, self.test_name, self.instance_name, self.config_name, self.sets, self.pull_report, self.lfclient_host, self.lf_user, self.lf_password, - cv_cmds) + cv_cmds, graphgroupsfile=self.graphgroups) self.rm_text_blob(self.config_name, blob_test) # To delete old config with same name @@ -511,8 +513,9 @@ def main(): help="ssid Security type") parser.add_argument("-paswd", "--paswd", default="[BLANK]", help="ssid Password") - parser.add_argument("--report_dir",default="") - parser.add_argument("--scenario",default="") + parser.add_argument("--report_dir", default="") + parser.add_argument("--scenario", default="") + parser.add_argument("--graphgroups", help="File to save graphgroups to", default=None) args = parser.parse_args() cv_base_adjust_parser(args) @@ -544,6 +547,7 @@ def main(): raw_lines=args.raw_line, raw_lines_file=args.raw_lines_file, sets=args.set, + graphgroups=args.graphgroups ) WFC_Test.setup() WFC_Test.run() diff --git a/py-scripts/wifi_cap_to_grafana.sh b/py-scripts/wifi_cap_to_grafana.sh index b46174ff..79c280b3 100755 --- a/py-scripts/wifi_cap_to_grafana.sh +++ b/py-scripts/wifi_cap_to_grafana.sh @@ -8,13 +8,26 @@ Help() } MGR=192.168.1.7 INFLUXTOKEN=Tdxwq5KRbj1oNbZ_ErPL5tw_HUH2wJ1VR4dwZNugJ-APz__mEFIwnqHZdoobmQpt2fa1VdWMlHQClR8XNotwbg== +TESTBED=Stidmatt-01 +GRAFANATOKEN=eyJrIjoiZTJwZkZlemhLQVNpY3hiemRjUkNBZ3k2RWc3bWpQWEkiLCJuIjoibWFzdGVyIiwiaWQiOjF9 +GROUPS=/tmp/lf_cv_rpt_filelocation.txt + #Replace my arguments with your setup. Separate your ssid arguments with spaces and ensure the names are lowercase echo "Make new DUT" -./create_chamberview_dut.py --lfmgr ${MGR} --dut_name DUT_TO_GRAFANA_DUT --ssid "ssid_idx=0 ssid=lanforge security=WPA2 password=password bssid=04:f0:21:2c:41:84 traffic=wiphy1" +./create_chamberview_dut.py --lfmgr ${MGR} --dut_name DUT_TO_GRAFANA_DUT \ +--ssid "ssid_idx=0 ssid=lanforge security=WPA2 password=password bssid=04:f0:21:2c:41:84 traffic=wiphy1" echo "Build Chamber View Scenario" #change the lfmgr to your system, set the radio to a working radio on your LANforge system, same with the ethernet port. -./create_chamberview.py --lfmgr ${MGR} --create_scenario DUT_TO_GRAFANA_SCENARIO --line "Resource=1.1 Profile=default Amount=32 Uses-1=wiphy1 DUT=DUT_TO_GRAFANA_DUT Traffic=wiphy1 Freq=-1" --line "Resource=1.1 Profile=upstream Amount=1 Uses-1=eth1 DUT=DUT_TO_GRAFANA_DUT Traffic=eth1 Freq=-1" +./create_chamberview.py --lfmgr ${MGR} --create_scenario DUT_TO_GRAFANA_SCENARIO \ +--line "Resource=1.1 Profile=default Amount=32 Uses-1=wiphy1 DUT=DUT_TO_GRAFANA_DUT Traffic=wiphy1 Freq=-1" \ +--line "Resource=1.1 Profile=upstream Amount=1 Uses-1=eth1 DUT=DUT_TO_GRAFANA_DUT Traffic=eth1 Freq=-1" #config_name doesn't matter, change the influx_host to your LANforge device, echo "run wifi capacity test" -./lf_wifi_capacity_test.py --config_name Custom --create_stations --radio wiphy1 --pull_report --influx_host ${MGR} --influx_port 8086 --influx_org Candela --influx_token ${INFLUXTOKEN} --influx_bucket lanforge --mgr ${MGR} --instance_name testing --upstream eth1 --test_rig Testbed-02 +./lf_wifi_capacity_test.py --config_name Custom --create_stations --radio wiphy1 --pull_report --influx_host ${MGR} \ +--influx_port 8086 --influx_org Candela --influx_token ${INFLUXTOKEN} --influx_bucket lanforge --mgr ${MGR} \ +--instance_name testing --upstream eth1 --test_rig ${TESTBED} --graphgroups ${GROUPS} + +./grafana_profile.py --create_custom --title ${TESTBED} --influx_bucket lanforge --mgr 192.168.1.7 --grafana_token ${GRAFANATOKEN} \ +--grafana_host 192.168.1.7 --testbed ${TESTBED} --graph-groups ${GROUPS} --scripts Dataplane --scripts 'WiFi Capacity' +rm filelocation.txt