blob: e9a9dc45c2233d81b8c773458b6cf81410ee5afe [file] [log] [blame]
Jeremy Ronquillo6df87812017-08-28 16:17:36 +00001# Copyright 2017 Open Networking Foundation (ONF)
2#
3# Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
4# the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
5# or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
6#
7# TestON is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 2 of the License, or
10# (at your option) any later version.
11#
12# TestON is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with TestON. If not, see <http://www.gnu.org/licenses/>.
19#
20# If you have any questions, or if you don't understand R,
Jeremy Ronquillob6268842017-10-03 13:02:58 -070021# please contact Jeremy Ronquillo: j_ronquillo@u.pacific.edu
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000022
23# **********************************************************
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070024# STEP 1: Data management.
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000025# **********************************************************
26
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070027print( "**********************************************************" )
28print( "STEP 1: Data management." )
29print( "**********************************************************" )
Devin Lim0e967162017-11-03 15:59:53 -070030has_flow_obj = 1
31database_host = 2
32database_port = 3
33database_u_id = 4
34database_pw = 5
35test_name = 6
36branch_name = 7
37has_neighbors = 8
38old_flow = 9
39save_directory = 10
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000040
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070041# Command line arguments are read.
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000042print( "Reading commmand-line args." )
43args <- commandArgs( trailingOnly=TRUE )
44
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070045# ----------------
46# Import Libraries
47# ----------------
48
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000049print( "Importing libraries." )
50library( ggplot2 )
51library( reshape2 )
52library( RPostgreSQL ) # For databases
53
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070054# -------------------
55# Check CLI Arguments
56# -------------------
57
58print( "Verifying CLI args." )
59
Devin Lim0e967162017-11-03 15:59:53 -070060if ( is.na( args[ save_directory ] ) ){
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070061
62 print( paste( "Usage: Rscript SCPFIntentEventTp.R",
63 "<has-flow-obj>",
64 "<database-host>",
65 "<database-port>",
66 "<database-user-id>",
67 "<database-password>",
68 "<test-name>",
69 "<branch-name>",
70 "<has-neighbors>",
Devin Lim0e967162017-11-03 15:59:53 -070071 "<using-old-flow>",
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070072 "<directory-to-save-graphs>",
73 sep=" " ) )
74
Jeremy Ronquillo9ea85d02017-11-27 10:21:03 -080075 quit( status = 1 ) # basically exit(), but in R
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000076}
77
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070078# -----------------
79# Create File Names
80# -----------------
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000081
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070082print( "Creating filenames and title of graph." )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000083
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070084chartTitle <- "Intent Event Throughput"
85fileNeighborsModifier <- "no"
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000086commandNeighborModifier <- ""
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070087fileFlowObjModifier <- ""
88sqlFlowObjModifier <- ""
89
Devin Lim0e967162017-11-03 15:59:53 -070090if ( args[ has_flow_obj ] == 'y' ){
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070091 fileFlowObjModifier <- "_flowObj"
92 sqlFlowObjModifier <- "_fobj"
93 chartTitle <- paste( chartTitle, " with Flow Objectives", sep="" )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +000094}
Jeremy Ronquillo7673f802017-10-30 09:42:44 -070095
96chartTitle <- paste( chartTitle, "\nevents/second with Neighbors =", sep="" )
97
Devin Lim0e967162017-11-03 15:59:53 -070098fileOldFlowModifier <- ""
99if ( args[ has_neighbors ] == 'y' ){
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700100 fileNeighborsModifier <- "all"
Jeremy Ronquillo2d2649d2017-09-14 12:53:06 -0700101 commandNeighborModifier <- "scale=1 OR NOT "
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700102 chartTitle <- paste( chartTitle, "all" )
103} else {
104 chartTitle <- paste( chartTitle, "0" )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000105}
Devin Lim0e967162017-11-03 15:59:53 -0700106if ( args[ old_flow ] == 'y' ){
107 fileOldFlowModifier <- "_OldFlow"
Devin Lim1bba7622017-11-14 16:31:41 -0800108 chartTitle <- paste( chartTitle, "With Eventually Consistent Flow Rule Store", sep="\n" )
Devin Lim0e967162017-11-03 15:59:53 -0700109}
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000110
Devin Lim0e967162017-11-03 15:59:53 -0700111errBarOutputFile <- paste( args[ save_directory ],
112 args[ test_name ],
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700113 "_",
Devin Lim0e967162017-11-03 15:59:53 -0700114 args[ branch_name ],
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700115 "_",
116 fileNeighborsModifier,
117 "-neighbors",
118 fileFlowObjModifier,
Devin Lim0e967162017-11-03 15:59:53 -0700119 fileOldFlowModifier,
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700120 "_graph.jpg",
121 sep="" )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000122
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700123# ------------------
124# SQL Initialization
125# ------------------
126
127print( "Initializing SQL" )
128
129con <- dbConnect( dbDriver( "PostgreSQL" ),
130 dbname = "onostest",
Devin Lim0e967162017-11-03 15:59:53 -0700131 host = args[ database_host ],
132 port = strtoi( args[ database_port ] ),
133 user = args[ database_u_id ],
134 password = args[ database_pw ] )
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700135
136# -----------------------------------
137# Intent Event Throughput SQL Command
138# -----------------------------------
139
140print( "Generating Intent Event Throughput SQL command." )
141
142command <- paste( "SELECT scale, SUM( avg ) as avg FROM intent_tp",
143 sqlFlowObjModifier,
144 "_tests WHERE (",
145 commandNeighborModifier,
146 "neighbors = 0 ) AND branch = '",
Devin Lim0e967162017-11-03 15:59:53 -0700147 args[ branch_name ],
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700148 "' AND date IN ( SELECT max( date ) FROM intent_tp",
149 sqlFlowObjModifier,
150 "_tests WHERE branch='",
Devin Lim0e967162017-11-03 15:59:53 -0700151 args[ branch_name ],
152 "' AND ",
153 ( if( args[ old_flow ] == 'y' ) "" else "NOT " ),
154 "is_old_flow",
155 " ) GROUP BY scale ORDER BY scale",
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700156 sep="" )
157
158print( "Sending SQL command:" )
159print( command )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000160
161fileData <- dbGetQuery( con, command )
162
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000163# **********************************************************
164# STEP 2: Organize data.
165# **********************************************************
166
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700167print( "**********************************************************" )
168print( "STEP 2: Organize Data." )
169print( "**********************************************************" )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000170
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700171# ------------
172# Data Sorting
173# ------------
174
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000175print( "Sorting data." )
Jeremy Ronquillo9ea85d02017-11-27 10:21:03 -0800176
177requiredColumns <- c( "avg" )
178
179tryCatch( avgs <- c( fileData[ requiredColumns] ),
180 error = function( e ) {
181 print( "[ERROR] One or more expected columns are missing from the data. Please check that the data and SQL command are valid, then try again." )
182 print( "Required columns: " )
183 print( requiredColumns )
184 print( "Actual columns: " )
185 print( names( fileData ) )
186 print( "Error dump:" )
187 print( e )
188 quit( status = 1 )
189 }
190 )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000191
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700192# --------------------
193# Construct Data Frame
194# --------------------
195
196print( "Constructing data frame." )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000197dataFrame <- melt( avgs ) # This is where reshape2 comes in. Avgs list is converted to data frame
198dataFrame$scale <- fileData$scale # Add node scaling to the data frame.
199
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700200colnames( dataFrame ) <- c( "throughput",
201 "type",
202 "scale" )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000203
Jeremy Ronquillo2d2649d2017-09-14 12:53:06 -0700204dataFrame <- na.omit( dataFrame ) # Omit any data that doesn't exist
205
206print( "Data Frame Results:" )
207print( dataFrame )
208
209
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000210# **********************************************************
211# STEP 3: Generate graphs.
212# **********************************************************
213
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700214print( "**********************************************************" )
215print( "STEP 3: Generate Graph." )
216print( "**********************************************************" )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000217
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700218# ------------------
219# Generate Main Plot
220# ------------------
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000221
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700222print( "Generating main plot." )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000223# Create the primary plot here.
224# ggplot contains the following arguments:
225# - data: the data frame that the graph will be based off of
226# - aes: the asthetics of the graph which require:
227# - x: x-axis values (usually node scaling)
228# - y: y-axis values (usually time in milliseconds)
229# - fill: the category of the colored side-by-side bars (usually type)
Jeremy Ronquillo2d2649d2017-09-14 12:53:06 -0700230
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700231mainPlot <- ggplot( data = dataFrame, aes( x = scale,
232 y = throughput,
233 fill = type ) )
234# ------------------------------
235# Fundamental Variables Assigned
236# ------------------------------
237
238print( "Generating fundamental graph data." )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000239
240# Formatting the plot
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700241theme_set( theme_grey( base_size = 22 ) ) # set the default text size of the graph.
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000242width <- 0.7 # Width of the bars.
243xScaleConfig <- scale_x_continuous( breaks = dataFrame$scale, label = dataFrame$scale )
244xLabel <- xlab( "Scale" )
245yLabel <- ylab( "Throughput (events/second)" )
246fillLabel <- labs( fill="Type" )
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700247imageWidth <- 15
248imageHeight <- 10
249imageDPI <- 200
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000250
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700251theme <- theme( plot.title = element_text( hjust = 0.5, size = 32, face = 'bold' ),
252 legend.position = "bottom",
253 legend.text = element_text( size = 18, face = "bold" ),
Jeremy Ronquillo94f99dd2018-01-05 11:11:27 -0800254 legend.title = element_blank(),
255 plot.subtitle = element_text( size=16, hjust=1.0 ) )
256
257subtitle <- paste( "Last Updated: ", format( Sys.time(), format = "%b %d, %Y at %I:%M %p %Z" ), sep="" )
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700258
259values <- geom_text( aes( x = dataFrame$scale,
260 y = dataFrame$throughput + 0.03 * max( dataFrame$throughput ),
261 label = format( dataFrame$throughput,
262 digits=3,
263 big.mark = ",",
264 scientific = FALSE ) ),
265 size = 7,
266 fontface = "bold" )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000267
268# Store plot configurations as 1 variable
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700269fundamentalGraphData <- mainPlot +
270 xScaleConfig +
271 xLabel +
272 yLabel +
273 fillLabel +
274 theme +
275 values
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000276
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700277# ---------------------------
278# Generating Bar Graph Format
279# ---------------------------
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000280
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000281print( "Generating bar graph." )
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700282barGraphFormat <- geom_bar( stat = "identity",
283 width = width,
284 fill = "#169EFF" )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000285
Jeremy Ronquillo94f99dd2018-01-05 11:11:27 -0800286title <- labs( title = chartTitle, subtitle = subtitle )
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700287
288result <- fundamentalGraphData +
289 barGraphFormat +
290 title
291
292# -----------------------
293# Exporting Graph to File
294# -----------------------
295
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000296print( paste( "Saving bar chart to", errBarOutputFile ) )
Jeremy Ronquillo6df87812017-08-28 16:17:36 +0000297
Jeremy Ronquillo9ea85d02017-11-27 10:21:03 -0800298tryCatch( ggsave( errBarOutputFile,
299 width = imageWidth,
300 height = imageHeight,
301 dpi = imageDPI ),
302 error = function( e ){
303 print( "[ERROR] There was a problem saving the graph due to a graph formatting exception. Error dump:" )
304 print( e )
305 quit( status = 1 )
306 }
307 )
Jeremy Ronquillo7673f802017-10-30 09:42:44 -0700308
309print( paste( "[SUCCESS] Successfully wrote bar chart out to", errBarOutputFile ) )
Jeremy Ronquillo9ea85d02017-11-27 10:21:03 -0800310quit( status = 0 )