blob: e9a9dc45c2233d81b8c773458b6cf81410ee5afe [file] [log] [blame]
Jeremy Ronquillodae11042018-02-21 09:21:44 -08001# 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,
21# please contact Jeremy Ronquillo: j_ronquillo@u.pacific.edu
22
23# **********************************************************
24# STEP 1: Data management.
25# **********************************************************
26
27print( "**********************************************************" )
28print( "STEP 1: Data management." )
29print( "**********************************************************" )
30has_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
40
41# Command line arguments are read.
42print( "Reading commmand-line args." )
43args <- commandArgs( trailingOnly=TRUE )
44
45# ----------------
46# Import Libraries
47# ----------------
48
49print( "Importing libraries." )
50library( ggplot2 )
51library( reshape2 )
52library( RPostgreSQL ) # For databases
53
54# -------------------
55# Check CLI Arguments
56# -------------------
57
58print( "Verifying CLI args." )
59
60if ( is.na( args[ save_directory ] ) ){
61
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>",
71 "<using-old-flow>",
72 "<directory-to-save-graphs>",
73 sep=" " ) )
74
75 quit( status = 1 ) # basically exit(), but in R
76}
77
78# -----------------
79# Create File Names
80# -----------------
81
82print( "Creating filenames and title of graph." )
83
84chartTitle <- "Intent Event Throughput"
85fileNeighborsModifier <- "no"
86commandNeighborModifier <- ""
87fileFlowObjModifier <- ""
88sqlFlowObjModifier <- ""
89
90if ( args[ has_flow_obj ] == 'y' ){
91 fileFlowObjModifier <- "_flowObj"
92 sqlFlowObjModifier <- "_fobj"
93 chartTitle <- paste( chartTitle, " with Flow Objectives", sep="" )
94}
95
96chartTitle <- paste( chartTitle, "\nevents/second with Neighbors =", sep="" )
97
98fileOldFlowModifier <- ""
99if ( args[ has_neighbors ] == 'y' ){
100 fileNeighborsModifier <- "all"
101 commandNeighborModifier <- "scale=1 OR NOT "
102 chartTitle <- paste( chartTitle, "all" )
103} else {
104 chartTitle <- paste( chartTitle, "0" )
105}
106if ( args[ old_flow ] == 'y' ){
107 fileOldFlowModifier <- "_OldFlow"
108 chartTitle <- paste( chartTitle, "With Eventually Consistent Flow Rule Store", sep="\n" )
109}
110
111errBarOutputFile <- paste( args[ save_directory ],
112 args[ test_name ],
113 "_",
114 args[ branch_name ],
115 "_",
116 fileNeighborsModifier,
117 "-neighbors",
118 fileFlowObjModifier,
119 fileOldFlowModifier,
120 "_graph.jpg",
121 sep="" )
122
123# ------------------
124# SQL Initialization
125# ------------------
126
127print( "Initializing SQL" )
128
129con <- dbConnect( dbDriver( "PostgreSQL" ),
130 dbname = "onostest",
131 host = args[ database_host ],
132 port = strtoi( args[ database_port ] ),
133 user = args[ database_u_id ],
134 password = args[ database_pw ] )
135
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 = '",
147 args[ branch_name ],
148 "' AND date IN ( SELECT max( date ) FROM intent_tp",
149 sqlFlowObjModifier,
150 "_tests WHERE branch='",
151 args[ branch_name ],
152 "' AND ",
153 ( if( args[ old_flow ] == 'y' ) "" else "NOT " ),
154 "is_old_flow",
155 " ) GROUP BY scale ORDER BY scale",
156 sep="" )
157
158print( "Sending SQL command:" )
159print( command )
160
161fileData <- dbGetQuery( con, command )
162
163# **********************************************************
164# STEP 2: Organize data.
165# **********************************************************
166
167print( "**********************************************************" )
168print( "STEP 2: Organize Data." )
169print( "**********************************************************" )
170
171# ------------
172# Data Sorting
173# ------------
174
175print( "Sorting data." )
176
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 )
191
192# --------------------
193# Construct Data Frame
194# --------------------
195
196print( "Constructing data frame." )
197dataFrame <- 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
200colnames( dataFrame ) <- c( "throughput",
201 "type",
202 "scale" )
203
204dataFrame <- na.omit( dataFrame ) # Omit any data that doesn't exist
205
206print( "Data Frame Results:" )
207print( dataFrame )
208
209
210# **********************************************************
211# STEP 3: Generate graphs.
212# **********************************************************
213
214print( "**********************************************************" )
215print( "STEP 3: Generate Graph." )
216print( "**********************************************************" )
217
218# ------------------
219# Generate Main Plot
220# ------------------
221
222print( "Generating main plot." )
223# 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)
230
231mainPlot <- ggplot( data = dataFrame, aes( x = scale,
232 y = throughput,
233 fill = type ) )
234# ------------------------------
235# Fundamental Variables Assigned
236# ------------------------------
237
238print( "Generating fundamental graph data." )
239
240# Formatting the plot
241theme_set( theme_grey( base_size = 22 ) ) # set the default text size of the graph.
242width <- 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" )
247imageWidth <- 15
248imageHeight <- 10
249imageDPI <- 200
250
251theme <- 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" ),
254 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="" )
258
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" )
267
268# Store plot configurations as 1 variable
269fundamentalGraphData <- mainPlot +
270 xScaleConfig +
271 xLabel +
272 yLabel +
273 fillLabel +
274 theme +
275 values
276
277# ---------------------------
278# Generating Bar Graph Format
279# ---------------------------
280
281print( "Generating bar graph." )
282barGraphFormat <- geom_bar( stat = "identity",
283 width = width,
284 fill = "#169EFF" )
285
286title <- labs( title = chartTitle, subtitle = subtitle )
287
288result <- fundamentalGraphData +
289 barGraphFormat +
290 title
291
292# -----------------------
293# Exporting Graph to File
294# -----------------------
295
296print( paste( "Saving bar chart to", errBarOutputFile ) )
297
298tryCatch( 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 )
308
309print( paste( "[SUCCESS] Successfully wrote bar chart out to", errBarOutputFile ) )
310quit( status = 0 )