kloudbuster/kb_server/public/ui/scripts/scripts.js

7 lines
219 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

var directive,m,mod,old_m,__indexOf=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};old_m=angular.module("n3-charts.linechart",["n3charts.utils"]),m=angular.module("n3-line-chart",["n3charts.utils"]),directive=function(a,b){return old_m.directive(a,b),m.directive(a,b)},directive("linechart",["n3utils","$window","$timeout",function(a,b,c){var d;return d=function(d,e,f,g){var h,i,j,k,l,m,n,o;o=a,h=o.getEventDispatcher(),i=o.uuid(),e[0].style["font-size"]=0,d.redraw=function(){d.update()},k=!1,j={onSeriesVisibilityChange:function(a){var b,c,e;return e=a.series,b=a.index,c=a.newVisibility,d.options.series[b].visible=c,d.$apply()}},d.update=function(){var a,b,c,g,k,l,m,n,p;return n=o.sanitizeOptions(d.options,f.mode),l=angular.extend(j,o.getTooltipHandlers(n)),c=o.getDataPerSeries(d.data,n),g=o.getDimensions(n,e,f),m="thumbnail"===f.mode,o.clean(e[0]),p=o.bootstrap(e[0],i,g),k=function(a){return n.series.filter(function(b){return b.axis===a&&b.visible!==!1}).length>0},a=o.createAxes(p,g,n.axes).andAddThemIf({all:!m,x:!0,y:k("y"),y2:k("y2")}),c.length&&o.setScalesDomain(a,d.data,n.series,p,n),o.createContent(p,i,n,l),c.length&&(b=o.getBestColumnWidth(a,g,c,n),o.drawData(p,g,a,c,b,n,l,h)),n.drawLegend&&o.drawLegend(p,n.series,g,l,h),"scrubber"===n.tooltip.mode?o.createGlass(p,g,l,a,c,n,h,b):"none"!==n.tooltip.mode&&o.addTooltips(p,g,n.axes),o.createFocus(p,g,n),o.setZoom(p,g,a,c,b,n,l,h)},m=function(){return d.oldclick?h.on("click",d.oldclick):d.click?h.on("click",d.click):h.on("click",null),d.oldhover?h.on("hover",d.oldhover):d.hover?h.on("hover",d.hover):h.on("hover",null),d.mouseenter?h.on("mouseenter",d.mouseenter):h.on("mouseenter",null),d.mouseover?h.on("mouseover",d.mouseover):h.on("mouseover",null),d.mouseout?h.on("mouseout",d.mouseout):h.on("mouseout",null),d.oldfocus?h.on("focus",d.oldfocus):d.focus?h.on("focus",d.focus):h.on("focus",null),d.toggle?h.on("toggle",d.toggle):h.on("toggle",null)},l=void 0,n=function(){return null!=l&&c.cancel(l),l=c(d.redraw,1)},b.addEventListener("resize",n),d.$watch("data",d.redraw,!0),d.$watch("options",d.redraw,!0),d.$watchCollection("[click, hover, focus, toggle]",m),d.$watchCollection("[mouseenter, mouseover, mouseout]",m),d.$watchCollection("[oldclick, oldhover, oldfocus]",m),d.$on("$destroy",function(){return b.removeEventListener("resize",n)})},{replace:!0,restrict:"E",scope:{data:"=",options:"=",oldclick:"=click",oldhover:"=hover",oldfocus:"=focus",click:"=onClick",hover:"=onHover",focus:"=onFocus",toggle:"=onToggle",mouseenter:"=onMouseenter",mouseover:"=onMouseover",mouseout:"=onMouseout"},template:"<div></div>",link:d}}]),mod=angular.module("n3charts.utils",[]),mod.factory("n3utils",["$window","$log","$rootScope",function(a,b,c){return{addPatterns:function(a,b){var c;return c=a.select("defs").selectAll("pattern").data(b.filter(function(a){return a.striped})).enter().append("pattern").attr({id:function(a){return a.type+"Pattern_"+a.index},patternUnits:"userSpaceOnUse",x:0,y:0,width:60,height:60}).append("g").style({fill:function(a){return a.color},"fill-opacity":.9}),c.append("rect").style("fill-opacity",.9).attr("width",60).attr("height",60),c.append("path").attr("d","M 10 0 l10 0 l -20 20 l 0 -10 z"),c.append("path").attr("d","M40 0 l10 0 l-50 50 l0 -10 z"),c.append("path").attr("d","M60 10 l0 10 l-40 40 l-10 0 z"),c.append("path").attr("d","M60 40 l0 10 l-10 10 l -10 0 z")},drawArea:function(a,b,c,d){var e,f,g,h;return g=c.filter(function(a){return"area"===a.type}),this.addPatterns(a,g),h={y:this.createLeftAreaDrawer(b,d.lineMode,d.tension),y2:this.createRightAreaDrawer(b,d.lineMode,d.tension)},f=a.select(".content").selectAll(".areaGroup").data(g),e=f.enter().append("g").attr("class",function(a){return"areaGroup series_"+a.index}),f.each(function(a){var b;return b=d3.select(this).selectAll("path").data([a]),b.enter().append("path").attr("class","area"),b.style("fill",function(a){return a.striped!==!0?a.color:"url(#areaPattern_"+a.index+")"}).style("opacity",function(a){return a.striped?"1":"0.8"}).attr("d",function(a){return h[a.axis](a.values)})}),this},createLeftAreaDrawer:function(a,b,c){return d3.svg.area().x(function(b){return a.xScale(b.x)}).y0(function(b){return a.yScale(b.y0)}).y1(function(b){return a.yScale(b.y0+b.y)}).interpolate(b).tension(c)},createRightAreaDrawer:function(a,b,c){return d3.svg.area().x(function(b){return a.xScale(b.x)}).y0(function(b){return a.y2Scale(b.y0)}).y1(function(b){return a.y2Scale(b.y0+b.y)}).interpolate(b).tension(c)},getPseudoColumns:function(a,b){var c,d;return a=a.filter(function(a){return"column"===a.type}),d={},c=[],a.forEach(function(a){var e,f,g,h,i;return e=b.series.map(function(a){return a.id}).indexOf(a.id),h=null!=(i=b.series)?i[e].visible:void 0,void 0!==h&&h!==!0||(f=!1,b.stacks.forEach(function(b,e){var g;return null!=a.id&&(g=a.id,__indexOf.call(b.series,g)>=0)?(d[a.id]=e,__indexOf.call(c,e)<0&&c.push(e),f=!0):void 0}),f!==!1)?void 0:(e=d[a.id]=g=c.length,c.push(e))}),{pseudoColumns:d,keys:c}},getMinDelta:function(a,b,c,d){return d3.min(a.map(function(a){return a.values.map(function(a){return c(a[b])}).filter(function(a){return d?a>=d[0]&&a<=d[1]:!0}).reduce(function(a,b,c,d){var e;return e=c>0?Math.max(b-d[c-1],0):Number.MAX_VALUE,a>e?e:a},Number.MAX_VALUE)}))},getBestColumnWidth:function(a,b,c,d){var e,f,g,h,i,j,k;return c&&0!==c.length?0===c.filter(function(a){return"column"===a.type}).length?10:(k=this.getPseudoColumns(c,d),j=k.pseudoColumns,h=k.keys,g=b.width-b.left-b.right,e=c.filter(function(a){return j.hasOwnProperty(a.id)}),f=this.getMinDelta(e,"x",a.xScale,[0,g]),f>g&&(f=.25*g),i=h.length,d.columnsHGap<f?Math.max(1,(f-d.columnsHGap)/i):Math.max(1,.8*f/i)):10},getColumnAxis:function(a,b,c){var d,e,f,g;return g=this.getPseudoColumns(a,c),e=g.pseudoColumns,d=g.keys,f=d3.scale.ordinal().domain(d).rangeBands([0,d.length*b],0),function(a){var c;return null==e[a.id]?0:(c=e[a.id],f(c)-d.length*b/2)}},drawColumns:function(a,b,c,d,e,f,g){var h,i,j;return c=c.filter(function(a){return"column"===a.type}),j=this.getColumnAxis(c,d,e),c.forEach(function(a){return a.xOffset=j(a)+.5*d}),i=a.select(".content").selectAll(".columnGroup").data(c),h=i.enter().append("g").attr("class",function(a){return"columnGroup series_"+a.index}),i.attr("transform",function(a){return"translate("+j(a)+",0)"}),i.each(function(c){var h,i,j,k;return i=e.series.map(function(a){return a.id}).indexOf(c.id),j=null!=(k=e.series)?k[i].visible:void 0,void 0===j||j===!0?(h=d3.select(this).selectAll("rect").data(c.values),h.enter().append("rect").on({click:function(a,b){return g.click(a,b,c)}}).on("mouseenter",function(a,b){return g.mouseenter(a,b,c)}).on("mouseover",function(d,h){return"function"==typeof f.onMouseOver&&f.onMouseOver(a,{series:c,x:b.xScale(d.x),y:b[d.axis+"Scale"](d.y0+d.y),datum:d},e.axes),g.hover(d,h,c),g.mouseover(d,h,c)}).on("mouseout",function(b,d){return"function"==typeof f.onMouseOut&&f.onMouseOut(a),g.mouseout(b,d,c)}),h.style({stroke:c.color,fill:c.color,"stroke-opacity":function(a){return 0===a.y?"0":"1"},"stroke-width":"1px","fill-opacity":function(a){return 0===a.y?0:.7}}).attr({width:d,x:function(a){return b.xScale(a.x)},height:function(a){return 0===a.y?b[a.axis+"Scale"].range()[0]:Math.abs(b[a.axis+"Scale"](a.y0+a.y)-b[a.axis+"Scale"](a.y0))},y:function(a){return 0===a.y?0:b[a.axis+"Scale"](Math.max(0,a.y0+a.y))}})):void 0}),this},drawDots:function(a,b,c,d,e,f){var g,h;return h=a.select(".content").selectAll(".dotGroup").data(c.filter(function(a){var b;return("line"===(b=a.type)||"area"===b)&&a.drawDots})),g=h.enter().append("g").attr("class",function(a){return"dotGroup series_"+a.index}),h.attr("fill",function(a){return a.color}),h.each(function(a){var c;return c=d3.select(this).selectAll(".dot").data(a.values),c.enter().append("circle").attr("class","dot").on({click:function(b,c){return f.click(b,c,a)}}).on({mouseenter:function(b,c){return f.mouseenter(b,c,a)}}).on({mouseover:function(b,c){return f.hover(b,c,a),f.mouseover(b,c,a)}}).on({mouseout:function(b,c){return f.mouseout(b,c,a)}}),c.attr({r:function(a){return a.dotSize},cx:function(a){return b.xScale(a.x)},cy:function(a){return b[a.axis+"Scale"](a.y+a.y0)}}).style({stroke:"white","stroke-width":"2px"})}),"none"!==d.tooltip.mode&&g.on("mouseover",function(b){var c,f;return f=d3.select(d3.event.target),c=f.datum(),f.attr("r",function(a){return a.dotSize+2}),"function"==typeof e.onMouseOver?e.onMouseOver(a,{series:b,x:f.attr("cx"),y:f.attr("cy"),datum:c},d.axes):void 0}).on("mouseout",function(b){return d3.select(d3.event.target).attr("r",function(a){return a.dotSize}),"function"==typeof e.onMouseOut?e.onMouseOut(a):void 0}),this},getEventDispatcher:function(){var a;return a=["focus","hover","mouseenter","mouseover","mouseout","click","toggle"],d3.dispatch.apply(this,a)},resetZoom:function(a,b,c,d,e,f,g,h,i){return i.scale(1),i.translate([0,0]),this.getZoomHandler(a,b,c,d,e,f,g,h,!1)()},getZoomHandler:function(a,b,c,d,e,f,g,h,i){var j;return j=this,function(){var k;return k=!1,["x","y","y2"].forEach(function(b){var d;return null!=(null!=(d=f.axes[b])?d.zoomable:void 0)?(a.selectAll("."+b+".axis").call(c[""+b+"Axis"]),k=!0):void 0}),d.length&&(e=j.getBestColumnWidth(c,b,d,f),j.drawData(a,b,c,d,e,f,g,h)),i&&k?j.createZoomResetIcon(a,b,c,d,e,f,g,h,i):void 0}},setZoom:function(a,b,c,d,e,f,g,h){var i;return i=this.getZoomListener(c,f),i?(i.on("zoom",this.getZoomHandler(a,b,c,d,e,f,g,h,i)),a.call(i)):void 0},getZoomListener:function(a,b){var c,d;return d=!1,c=d3.behavior.zoom(),["x","y","y2"].forEach(function(e){var f;return(null!=(f=b.axes[e])?f.zoomable:void 0)?(c[e](a[""+e+"Scale"]),d=!0):void 0}),d?c:!1},computeLegendLayout:function(a,b,c){var d,e,f,g,h,i,j,k,l,m;for(i=10,l=this,h=this.getLegendItemsWidths(a,"y"),g=[0],e=1;e<h.length;)g.push(h[e-1]+g[e-1]+i),e++;if(k=this.getLegendItemsWidths(a,"y2"),!(k.length>0))return[g];for(m=c.width-c.right-c.left,d=0,j=[],f=k.length-1;f>=0;)j.push(m-d-k[f]),d+=k[f]+i,f--;return j.reverse(),[g,j]},getLegendItemsWidths:function(a,b){var c,d,e,f,g;if(f=this,c=function(a){return f.getTextBBox(a).width},e=a.selectAll(".legendItem."+b),!(e.length>0))return[];for(g=[],d=0;d<e[0].length;)g.push(c(e[0][d])),d++;return g},drawLegend:function(a,b,c,d,e){var f,g,h,i,j;return i=this,h=a.append("g").attr("class","legend"),f=16,a.select("defs").append("svg:clipPath").attr("id","legend-clip").append("circle").attr("r",f/2),g=h.selectAll(".legendItem").data(b),g.enter().append("g").on("click",function(a,b){var c;return c=!(a.visible!==!1),e.toggle(a,b,c),"function"==typeof d.onSeriesVisibilityChange?d.onSeriesVisibilityChange({series:a,index:b,newVisibility:c}):void 0}),g.attr({"class":function(a,b){return"legendItem series_"+b+" "+a.axis},opacity:function(b,c){return b.visible===!1?(i.toggleSeries(a,c),"0.2"):"1"}}).each(function(a){var b,c;return b=d3.select(this),b.append("circle").attr({fill:a.color,stroke:a.color,"stroke-width":"2px",r:f/2}),b.append("path").attr({"clip-path":"url(#legend-clip)","fill-opacity":"area"===(c=a.type)||"column"===c?"1":"0",fill:"white",stroke:"white","stroke-width":"2px",d:i.getLegendItemPath(a,f,f)}),b.append("circle").attr({"fill-opacity":0,stroke:a.color,"stroke-width":"2px",r:f/2}),b.append("text").attr({"class":function(a,b){return"legendText series_"+b},"font-family":"Courier","font-size":10,transform:"translate(13, 4)","text-rendering":"geometric-precision"}).text(a.label||a.y)}),j=function(){var d,e,f;return f=i.computeLegendLayout(a,b,c),d=f[0],e=f[1],g.attr({transform:function(a,b){return"y"===a.axis?"translate("+d.shift()+","+(c.height-40)+")":"translate("+e.shift()+","+(c.height-40)+")"}})},j(),setTimeout(j,0),this},getLegendItemPath:function(a,b,c){var d,e;return"column"===a.type?(e="M"+-b/3+" "+-c/8+" l0 "+c+" ",e+="M0 "+-c/3+" l0 "+c+" ",e+="M"+b/3+" "+-c/10+" l0 "+c+" "):(d="M-"+b/2+" 0"+c/3+" l"+b/3+" -"+c/3+" l"+b/3+" "+c/3+" l"+b/3+" -"+2*c/3,"area"===a.type,d)},toggleSeries:function(a,b){var c;return c=!1,a.select(".content").selectAll(".series_"+b).style("display",function(a){return"none"===d3.select(this).style("display")?(c=!0,"initial"):(c=!1,"none")}),c},drawLines:function(a,b,c,d,e){var f,g,h,i;return f={y:this.createLeftLineDrawer(b,d.lineMode,d.tension),y2:this.createRightLineDrawer(b,d.lineMode,d.tension)},i=a.select(".content").selectAll(".lineGroup").data(c.filter(function(a){var b;return"line"===(b=a.type)||"area"===b})),h=i.enter().append("g").attr("class",function(a){return"lineGroup series_"+a.index}),i.style("stroke",function(a){return a.color}),i.each(function(a){var b;return b=d3.select(this).selectAll("path").data([a]),b.enter().append("path").attr("class","line"),b.attr("d",function(a){return f[a.axis](a.values)}).style({fill:"none","stroke-width":function(a){return a.thickness},"stroke-dasharray":function(a){return"dashed"===a.lineMode?"10,3":void 0}})}),d.tooltip.interpolate&&(g=function(c){var f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B;s=d3.select(d3.event.target);try{r=d3.mouse(this)}catch(C){g=C,r=[0,0]}for(t=s.datum().values,h=A=0,B=t.length;B>A;h=++A)f=t[h],u=b.xScale(f.x),x=b.yScale(f.y),("undefined"==typeof n||null===n||n>u)&&(n=u,o=f.x),("undefined"==typeof j||null===j||u>j)&&(j=u,k=f.x),("undefined"==typeof p||null===p||p>x)&&(p=x),("undefined"==typeof l||null===l||x>l)&&(l=x),("undefined"==typeof q||null===q||f.y<q)&&(q=f.y),("undefined"==typeof m||null===m||f.y>m)&&(m=f.y);return v=(r[0]-n)/(j-n),y=(r[1]-p)/(l-p),w=Math.round(v*(k-o)+o),z=Math.round((1-y)*(m-q)+q),i={x:w,y:z},"function"==typeof e.onMouseOver?e.onMouseOver(a,{series:c,x:r[0],y:r[1],datum:i},d.axes):void 0},h.on("mousemove",g).on("mouseout",function(b){return"function"==typeof e.onMouseOut?e.onMouseOut(a):void 0})),this},createLeftLineDrawer:function(a,b,c){return d3.svg.line().x(function(b){return a.xScale(b.x)}).y(function(b){return a.yScale(b.y+b.y0)}).interpolate(b).tension(c)},createRightLineDrawer:function(a,b,c){return d3.svg.line().x(function(b){return a.xScale(b.x)}).y(function(b){return a.y2Scale(b.y+b.y0)}).interpolate(b).tension(c)},getPixelCssProp:function(b,c){var d;return d=a.getComputedStyle(b,null).getPropertyValue(c),+d.replace(/px$/,"")},getDefaultMargins:function(){return{top:20,right:50,bottom:60,left:50}},getDefaultThumbnailMargins:function(){return{top:1,right:1,bottom:2,left:0}},getElementDimensions:function(a,b,c){var d,e,f,g,h,i;return e={},g=a,i=this.getPixelCssProp(g,"padding-top"),d=this.getPixelCssProp(g,"padding-bottom"),f=this.getPixelCssProp(g,"padding-left"),h=this.getPixelCssProp(g,"padding-right"),e.width=+(b||g.offsetWidth||900)-f-h,e.height=+(c||g.offsetHeight||500)-i-d,e},getDimensions:function(a,b,c){var d;return d=this.getElementDimensions(b[0].parentElement,c.width,c.height),d=angular.extend(a.margin,d)},clean:function(a){return d3.select(a).on("keydown",null).on("keyup",null).select("svg").remove()},uuid:function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(a){var b,c;return b=16*Math.random()|0,c="x"===a?b:3&b|8,c.toString(16)})},bootstrap:function(a,b,c){var d,e,f,g;return d3.select(a).classed("chart",!0),g=c.width,e=c.height,f=d3.select(a).append("svg").attr({width:g,height:e}).append("g").attr("transform","translate("+c.left+","+c.top+")"),d=f.append("defs").attr("class","patterns"),d.append("clipPath").attr("class","content-clip").attr("id","content-clip-"+b).append("rect").attr({x:0,y:0,width:g-c.left-c.right,height:e-c.top-c.bottom}),f},createContent:function(a,b,c){var d;return d=a.append("g").attr("class","content"),c.hideOverflow?d.attr("clip-path","url(#content-clip-"+b+")"):void 0},createZoomResetIcon:function(a,b,c,d,e,f,g,h,i){var j,k,l,m,n,o,p;return o=this,m="M22.646,19.307c0.96-1.583,1.523-3.435,1.524-5.421C24.169,8.093,19.478,3.401,13.688,3.399C7.897,3.401,3.204,8.093,3.204,13.885c0,5.789,4.693,10.481,10.484,10.481c1.987,0,3.839-0.563,5.422-1.523l7.128,7.127l3.535-3.537L22.646,19.307zM13.688,20.369c-3.582-0.008-6.478-2.904-6.484-6.484c0.006-3.582,2.903-6.478,6.484-6.486c3.579,0.008,6.478,2.904,6.484,6.486C20.165,17.465,17.267,20.361,13.688,20.369zM8.854,11.884v4.001l9.665-0.001v-3.999L8.854,11.884z",k=a.select(".focus-container").selectAll(".icon.zoom-reset").data([1]),j=k.enter().append("g").attr("class","icon zoom-reset").on("click",function(){return o.resetZoom(a,b,c,d,e,f,g,h,i),d3.select(this).remove()}).on("mouseenter",function(){return d3.select(this).style("fill","steelblue")}).on("mouseout",function(){return d3.select(this).style("fill","black")}),j.append("path").attr("d",m),l=b.width-b.left-b.right-24,p=2,n=.7,k.style({fill:"black",stroke:"white","stroke-width":1.5}).attr({opacity:1,transform:"translate("+l+", "+p+") scale("+n+")"})},createFocus:function(a,b,c){var d;return d=a.append("g").attr({"class":"focus-container"})},createGlass:function(a,b,c,d,e,f,g,h){var i,j,k;return k=this,i=a.append("g").attr({"class":"glass-container",opacity:0}),j=i.selectAll(".scrubberItem").data(e).enter().append("g").attr("class",function(a,b){return"scrubberItem series_"+b}),j.each(function(a,b){var c,d,e;return e=d3.select(this),c=e.append("g").attr({"class":"rightTT"}),c.append("path").attr({"class":"scrubberPath series_"+b,y:"-7px",fill:a.color}),k.styleTooltip(c.append("text").style("text-anchor","start").attr({"class":function(a,b){return"scrubberText series_"+b},height:"14px",transform:"translate(7, 3)","text-rendering":"geometric-precision"})).text(a.label||a.y),d=e.append("g").attr({"class":"leftTT"}),d.append("path").attr({"class":"scrubberPath series_"+b,y:"-7px",fill:a.color}),k.styleTooltip(d.append("text").style("text-anchor","end").attr({"class":"scrubberText series_"+b,height:"14px",transform:"translate(-13, 3)","text-rendering":"geometric-precision"})).text(a.label||a.y),e.append("circle").attr({"class":"scrubberDot series_"+b,fill:"white",stroke:a.color,"stroke-width":"2px",r:4})}),i.append("rect").attr({"class":"glass",width:b.width-b.left-b.right,height:b.height-b.top-b.bottom}).style("fill","white").style("fill-opacity",1e-6).on("mouseover",function(){return c.onChartHover(a,d3.select(this),d,e,f,g,h)})},drawData:function(a,b,c,d,e,f,g,h){return this.drawArea(a,c,d,f,g).drawColumns(a,c,d,e,f,g,h).drawLines(a,c,d,f,g),f.drawDots?this.drawDots(a,c,d,f,g,h):void 0},getDataPerSeries:function(a,b){var c,d,e,f;return e=b.series,c=b.axes,e&&e.length&&a&&a.length?(f=e.map(function(c,d){var e;return e={index:d,name:c.y,values:[],color:c.color,axis:c.axis||"y",xOffset:0,type:c.type,thickness:c.thickness,drawDots:c.drawDots!==!1},null!=c.dotSize&&(e.dotSize=c.dotSize),c.striped===!0&&(e.striped=!0),null!=c.lineMode&&(e.lineMode=c.lineMode),c.id&&(e.id=c.id),a.filter(function(a){return null!=a[c.y]}).forEach(function(a){var d;return d={x:a[b.axes.x.key],y:a[c.y],y0:0,axis:c.axis||"y"},null!=c.dotSize&&(d.dotSize=c.dotSize),e.values.push(d)}),e}),null==b.stacks||0===b.stacks.length?f:(d=d3.layout.stack().values(function(a){return a.values}),b.stacks.forEach(function(a){var b;if(a.series.length>0)return b=f.filter(function(a,b){return void 0===e[b].visible||e[b].visible}).filter(function(b,c){var d;return null!=b.id&&(d=b.id,__indexOf.call(a.series,d)>=0)}),d(b)}),f)):[]},estimateSideTooltipWidth:function(a,b){var c,d;return d=a.append("text"),d.text(""+b),this.styleTooltip(d),c=this.getTextBBox(d[0][0]),d.remove(),c},getTextBBox:function(a){var b;if(null!==a)try{return a.getBBox()}catch(c){return b=c,{height:0,width:0,y:0,x:0}}return{}},getWidestTickWidth:function(a,b){var c,d,e,f;return d=0,c=this.getTextBBox,e=a.select("."+b+".axis").selectAll(".tick"),null!=(f=e[0])&&f.forEach(function(a){return d=Math.max(d,c(a).width)}),d},getWidestOrdinate:function(a,b,c){var d;return d="",a.forEach(function(a){return b.forEach(function(b){var e,f;return e=a[b.y],null!=b.axis&&(null!=(f=c.axes[b.axis])?f.ticksFormatter:void 0)&&(e=c.axes[b.axis].ticksFormatter(e)),null!=e&&(""+e).length>(""+d).length?d=e:void 0})}),d},getDefaultOptions:function(){return{tooltip:{mode:"scrubber"},lineMode:"linear",tension:.7,margin:this.getDefaultMargins(),axes:{x:{type:"linear",key:"x"},y:{type:"linear"}},series:[],drawLegend:!0,drawDots:!0,stacks:[],columnsHGap:5,hideOverflow:!1}},sanitizeOptions:function(a,b){var c;return null==a&&(a={}),"thumbnail"===b&&(a.drawLegend=!1,a.drawDots=!1,a.tooltip={mode:"none",interpolate:!1}),a.series=this.sanitizeSeriesOptions(a.series),a.stacks=this.sanitizeSeriesStacks(a.stacks,a.series),a.axes=this.sanitizeAxes(a.axes,this.haveSecondYAxis(a.series)),a.tooltip=this.sanitizeTooltip(a.tooltip),a.margin=this.sanitizeMargins(a.margin),a.lineMode||(a.lineMode=this.getDefaultOptions().lineMode),a.tension=/^\d+(\.\d+)?$/.test(a.tension)?a.tension:this.getDefaultOptions().tension,a.drawLegend=a.drawLegend!==!1,a.drawDots=a.drawDots!==!1,angular.isNumber(a.columnsHGap)||(a.columnsHGap=5),a.hideOverflow=a.hideOverflow||!1,c="thumbnail"===b?this.getDefaultThumbnailMargins():this.getDefaultMargins(),a.series=angular.extend(this.getDefaultOptions().series,a.series),a.axes=angular.extend(this.getDefaultOptions().axes,a.axes),a.tooltip=angular.extend(this.getDefaultOptions().tooltip,a.tooltip),a.margin=angular.extend(c,a.margin),a},sanitizeMargins:function(a){var b,c,d,e;b=["top","right","bottom","left"],c={};for(d in a)e=a[d],__indexOf.call(b,d)>=0&&(c[d]=parseFloat(e));return c},sanitizeSeriesStacks:function(a,c){var d;return null==a?[]:(d={},c.forEach(function(a){return d[a.id]=a}),a.forEach(function(a){return a.series.forEach(function(c){var e;if(e=d[c],null!=e){if(e.axis!==a.axis)return b.warn("Series "+c+" is not on the same axis as its stack")}else if(!e)return b.warn("Unknown series found in stack : "+c)})}),a)},sanitizeTooltip:function(a){var b;if(!a)return{mode:"scrubber"};if("none"!==(b=a.mode)&&"axes"!==b&&"scrubber"!==b&&(a.mode="scrubber"),"scrubber"===a.mode?delete a.interpolate:a.interpolate=!!a.interpolate,"scrubber"===a.mode&&a.interpolate)throw new Error("Interpolation is not supported for scrubber tooltip mode.");return a},sanitizeSeriesOptions:function(a){var b,c;return null==a?[]:(b=d3.scale.category10(),c={},a.forEach(function(a,b){if(null!=c[a.id])throw new Error("Twice the same ID ("+a.id+") ? Really ?");return null!=a.id?c[a.id]=a:void 0}),a.forEach(function(a,d){var e,f,g,h,i;if(a.axis="y2"!==(null!=(f=a.axis)?f.toLowerCase():void 0)?"y":"y2",a.color||(a.color=b(d)),a.type="line"===(g=a.type)||"area"===g||"column"===g?a.type:"line","column"===a.type?(delete a.thickness,delete a.lineMode,delete a.drawDots,delete a.dotSize):/^\d+px$/.test(a.thickness)||(a.thickness="1px"),"line"!==(h=a.type)&&"area"!==h||("dashed"!==(i=a.lineMode)&&delete a.lineMode,a.drawDots!==!1&&null==a.dotSize&&(a.dotSize=2)),null==a.id){for(e=0;null!=c["series_"+e];)e++;a.id="series_"+e,c[a.id]=a}return a.drawDots===!1?delete a.dotSize:void 0}),a)},sanitizeAxes:function(a,b){var c;return null==a&&(a={}),a.x=this.sanitizeAxisOptions(a.x),(c=a.x).key||(c.key="x"),a.y=this.sanitizeAxisOptions(a.y),b&&(a.y2=this.sanitizeAxisOptions(a.y2)),a},sanitizeExtrema:function(a){var c,d,e,f,g,h;for(g=["min","max"],h=[],e=0,f=g.length;f>e;e++)c=g[e],d=a[c],null!=d?(a[c]=this.sanitizeExtremum(c,a),null==a[c]?h.push(b.warn("Invalid "+c+" value '"+d+"' (parsed as "+a[c]+"), ignoring it.")):h.push(void 0)):h.push(void 0);return h},sanitizeExtremum:function(a,b){var c;return c=this.sanitizeNumber,"date"===b.type&&(c=this.sanitizeDate),c(b[a])},sanitizeDate:function(a){return null!=a&&a instanceof Date&&!isNaN(a.valueOf())?a:void 0},sanitizeNumber:function(a){var b;if(null!=a&&(b=parseFloat(a),!isNaN(b)))return b},sanitizeAxisOptions:function(a){return null==a?{type:"linear"}:(a.type||(a.type="linear"),null!=a.ticksRotate&&(a.ticksRotate=this.sanitizeNumber(a.ticksRotate)),null!=a.zoomable&&(a.zoomable=a.zoomable||!1),null!=a.innerTicks&&(a.innerTicks=a.innerTicks||!1),null!=a.labelFunction&&(a.ticksFormatter=a.labelFunction),null!=a.ticksFormat&&("date"===a.type?a.ticksFormatter=d3.time.format(a.ticksFormat):a.ticksFormatter=d3.format(a.ticksFormat),null==a.tooltipFormatter&&(a.tooltipFormatter=a.ticksFormatter)),null!=a.tooltipFormat&&("date"===a.type?a.tooltipFormatter=d3.time.format(a.tooltipFormat):a.tooltipFormatter=d3.format(a.tooltipFormat)),null!=a.ticksInterval&&(a.ticksInterval=this.sanitizeNumber(a.ticksInterval)),this.sanitizeExtrema(a),a)},createAxes:function(a,b,c){var d,e,f,g,h,i,j,k,l,m;return d=null!=c.y2,g=b.width,e=b.height,g=g-b.left-b.right,e=e-b.top-b.bottom,h=void 0,h="date"===c.x.type?d3.time.scale().rangeRound([0,g]):d3.scale.linear().rangeRound([0,g]),i=this.createAxis(h,"x",c),j=void 0,j="log"===c.y.type?d3.scale.log().clamp(!0).rangeRound([e,0]):d3.scale.linear().rangeRound([e,0]),j.clamp(!0),m=this.createAxis(j,"y",c),k=void 0,k=d&&"log"===c.y2.type?d3.scale.log().clamp(!0).rangeRound([e,0]):d3.scale.linear().rangeRound([e,0]),k.clamp(!0),l=this.createAxis(k,"y2",c),f=function(a){return a.style({font:"10px Courier","shape-rendering":"crispEdges"}),a.selectAll("path").style({fill:"none",stroke:"#000"})},{xScale:h,yScale:j,y2Scale:k,xAxis:i,yAxis:m,y2Axis:l,andAddThemIf:function(b){return b.all&&(b.y&&(a.append("g").attr("class","y grid"),a.append("g").attr("class","y axis").call(m).call(f)),d&&b.y2&&(a.append("g").attr("class","y2 grid").attr("transform","translate("+g+", 0)"),a.append("g").attr("class","y2 axis").attr("transform","translate("+g+", 0)").call(l).call(f)),b.x&&(a.append("g").attr("class","x grid").attr("transform","translate(0,"+e+")"),a.append("g").attr("class","x axis").attr("transform","translate(0,"+e+")").call(i).call(f))),{xScale:h,yScale:j,y2Scale:k,xAxis:i,yAxis:m,y2Axis:l}}}},createAxis:function(a,b,c){var d,e,f;return f={x:"bottom",y:"left",y2:"right"},e=c[b],d=d3.svg.axis().scale(a).orient(f[b]).innerTickSize(4).tickFormat(null!=e?e.ticksFormatter:void 0),null==e?d:(angular.isArray(e.ticks)?d.tickValues(e.ticks):angular.isNumber(e.ticks)?d.ticks(e.ticks):angular.isFunction(e.ticks)&&d.ticks(e.ticks,e.ticksInterval),d)},setDefaultStroke:function(a){return a.attr("stroke","#000").attr("stroke-width",1).style("shape-rendering","crispEdges")},setDefaultGrid:function(a){return a.attr("stroke","#eee").attr("stroke-width",1).style("shape-rendering","crispEdges")},setScalesDomain:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n;return this.setXScale(a.xScale,b,c,e.axes),f=d.selectAll(".x.axis").call(a.xAxis),null!=e.axes.x.innerTicks&&f.selectAll(".tick>line").call(this.setDefaultStroke),null!=e.axes.x.grid&&(h=e.margin.height-e.margin.top-e.margin.bottom,j=a.xAxis.tickSize(-h,0,0),g=d.selectAll(".x.grid").call(j),g.selectAll(".tick>line").call(this.setDefaultGrid)),null!=e.axes.x.ticksRotate&&f.selectAll(".tick>text").attr("dy",null).attr("transform","translate(0,5) rotate("+e.axes.x.ticksRotate+" 0,6)").style("text-anchor",e.axes.x.ticksRotate>=0?"start":"end"),c.filter(function(a){return"y"===a.axis&&a.visible!==!1}).length>0&&(m=this.getVerticalDomain(e,b,c,"y"),a.yScale.domain(m).nice(),f=d.selectAll(".y.axis").call(a.yAxis),null!=e.axes.y.innerTicks&&f.selectAll(".tick>line").call(this.setDefaultStroke),null!=e.axes.y.ticksRotate&&f.selectAll(".tick>text").attr("transform","rotate("+e.axes.y.ticksRotate+" -6,0)").style("text-anchor","end"),null!=e.axes.y.grid&&(i=e.margin.width-e.margin.left-e.margin.right,n=a.yAxis.tickSize(-i,0,0),g=d.selectAll(".y.grid").call(n),g.selectAll(".tick>line").call(this.setDefaultGrid))),c.filter(function(a){return"y2"===a.axis&&a.visible!==!1}).length>0&&(k=this.getVerticalDomain(e,b,c,"y2"),a.y2Scale.domain(k).nice(),f=d.selectAll(".y2.axis").call(a.y2Axis),null!=e.axes.y2.innerTicks&&f.selectAll(".tick>line").call(this.setDefaultStroke),null!=e.axes.y2.ticksRotate&&f.selectAll(".tick>text").attr("transform","rotate("+e.axes.y2.ticksRotate+" 6,0)").style("text-anchor","start"),null!=e.axes.y2.grid)?(i=e.margin.width-e.margin.left-e.margin.right,l=a.y2Axis.tickSize(-i,0,0),g=d.selectAll(".y2.grid").call(l),g.selectAll(".tick>line").call(this.setDefaultGrid)):void 0},getVerticalDomain:function(a,b,c,d){var e,f,g;return(g=a.axes[d])?null!=g.ticks&&angular.isArray(g.ticks)?[g.ticks[0],g.ticks[g.ticks.length-1]]:(f=c.filter(function(a){return a.axis===d&&a.visible!==!1}),e=this.yExtent(c.filter(function(a){return a.axis===d&&a.visible!==!1}),b,a.stacks.filter(function(a){return a.axis===d})),"log"===g.type&&(e[0]=0===e[0]?.001:e[0]),null!=g.min&&(e[0]=g.min),null!=g.max&&(e[1]=g.max),e):[]},yExtent:function(a,b,c){var d,e,f;return f=Number.POSITIVE_INFINITY,e=Number.NEGATIVE_INFINITY,d=[],c.forEach(function(b){return d.push(b.series.map(function(b){return a.filter(function(a){return a.id===b})[0]}))}),a.forEach(function(a,b){var e;return e=!1,c.forEach(function(b){var c;return c=a.id,__indexOf.call(b.series,c)>=0?e=!0:void 0}),e?void 0:d.push([a])}),d.forEach(function(a){return a=a.filter(Boolean),f=Math.min(f,d3.min(b,function(b){return a.reduce(function(a,c){return Math.min(a,b[c.y])},Number.POSITIVE_INFINITY)})),e=Math.max(e,d3.max(b,function(b){return a.reduce(function(a,c){return a+b[c.y]},0)}))}),f===e?f>0?[0,2*f]:[2*f,0]:[f,e]},setXScale:function(a,b,c,d){var e,f;return e=this.xExtent(b,d.x.key,d.x.type),c.filter(function(a){return"column"===a.type}).length&&this.adjustXDomainForColumns(e,b,d.x.key),f=d.x,null!=f.min&&(e[0]=f.min),null!=f.max&&(e[1]=f.max),a.domain(e)},xExtent:function(a,b,c){var d,e,f,g;return g=d3.extent(a,function(a){return a[b]}),e=g[0],f=g[1],e===f?"date"===c?(d=864e5,[new Date(+e-d),new Date(+f+d)]):e>0?[0,2*e]:[2*e,0]:[e,f]},adjustXDomainForColumns:function(a,b,c){var d;return d=this.getAverageStep(b,c),angular.isDate(a[0])?(a[0]=new Date(+a[0]-d),a[1]=new Date(+a[1]+d)):(a[0]=a[0]-d,a[1]=a[1]+d)},getAverageStep:function(a,b){var c,d,e;if(!(a.length>1))return 0;for(e=0,d=a.length-1,c=0;d>c;)e+=a[c+1][b]-a[c][b],c++;return e/d},haveSecondYAxis:function(a){return!a.every(function(a){return"y2"!==a.axis})},showScrubber:function(a,b,c,d,e,f,g){var h;return h=this,b.on("mousemove",function(){return a.selectAll(".glass-container").attr("opacity",1),h.updateScrubber(a,d3.mouse(this),c,d,e,f,g)}),b.on("mouseout",function(){return b.on("mousemove",null),a.selectAll(".glass-container").attr("opacity",0)})},getClosestPoint:function(a,b){var c,d,e,f,g;return g=d3.bisector(function(a){return a.x}).left,f=g(a,b),0===f?a[0]:f>a.length-1?a[a.length-1]:(d=a[f-1],e=a[f],c=b-d.x>e.x-b?e:d)},updateScrubber:function(a,b,c,d,e,f,g){var h,i,j,k,l,m;return l=b[0],m=b[1],h=function(a){return a.transition().duration(50)},j=this,i=[],d.forEach(function(b,d){var g,k,n,o,p,q,r,s,t,u,v,w,x;return k=a.select(".scrubberItem.series_"+d),e.series[d].visible===!1?void k.attr("opacity",0):(k.attr("opacity",1),v=c.xScale.invert(l),x=c.yScale.invert(m),u=j.getClosestPoint(b.values,v),f.focus(u,b.values.indexOf(u),[v,x]),t=u.x+" : "+u.y,e.tooltip.formatter&&(t=e.tooltip.formatter(u.x,u.y,e.series[d])),q=k.select(".rightTT"),p=q.select("text"),p.text(t),o=k.select(".leftTT"),n=o.select("text"),n.text(t),s={right:j.getTextBBox(p[0][0]).width+5,left:j.getTextBBox(n[0][0]).width+5},r="y2"===b.axis?"right":"left",w=c.xScale(u.x),"left"===r?w+j.getTextBBox(n[0][0]).x-10<0&&(r="right"):"right"===r&&w+s.right>j.getTextBBox(a.select(".glass")[0][0]).width&&(r="left"),"left"===r?(h(q).attr("opacity",0),h(o).attr("opacity",1)):(h(q).attr("opacity",1),h(o).attr("opacity",0)),i[d]={index:d,x:w,y:c[u.axis+"Scale"](u.y+u.y0),side:r,sizes:s},g=angular.isFunction(b.color)?b.color(u,b.values.indexOf(u)):b.color,k.selectAll("circle").attr("stroke",g),k.selectAll("path").attr("fill",g))}),i=this.preventOverlapping(i),k=Math.max(15,100/g),d.forEach(function(b,c){var d,f,g,l;if(e.series[c].visible!==!1)return f=i[c],d=a.select(".scrubberItem.series_"+c),g=d.select("."+f.side+"TT"),l="left"===f.side?b.xOffset:-b.xOffset,g.select("text").attr("transform",function(){return"left"===f.side?"translate("+(-3-k-l)+", "+(f.labelOffset+3)+")":"translate("+(4+k+l)+", "+(f.labelOffset+3)+")"}),g.select("path").attr("d",j.getScrubberPath(f.sizes[f.side]+1,f.labelOffset,f.side,k+l)),
h(d).attr({transform:"translate("+(i[c].x+b.xOffset)+", "+i[c].y+")"})})},getScrubberPath:function(a,b,c,d){var e,f,g,h;return e=18,f=d,a=a,g="left"===c?1:-1,h=1,0!==b&&(h=Math.abs(b)/b),b||(b=0),["m0 0","l"+g+" 0","l0 "+(b+h),"l"+-g*(f+1)+" 0","l0 "+(-e/2-h),"l"+-g*a+" 0","l0 "+e,"l"+g*a+" 0","l0 "+(-e/2-h),"l"+g*(f-1)+" 0","l0 "+(-b+h),"l1 0","z"].join("")},preventOverlapping:function(a){var b,c,d,e;return d=18,b={},a.forEach(function(a){var c;return b[c=a.x]||(b[c]={left:[],right:[]}),b[a.x][a.side].push(a)}),c=function(a){var c,e,f,g,h,i,j,k,l;f=[];for(j in b)if(i=b[j],0!==i[a].length){for(g={};i[a].length>0;){h=i[a].pop(),c=!1;for(k in g)e=g[k],+k-d<=(l=h.y)&&+k+d>=l&&(e.push(h),c=!0);c||(g[h.y]=[h])}f.push(g)}return f},e=function(a){var b,c,d,e,f,g,h;f=20;for(b in a){g=a[b];for(h in g)d=g[h],c=d.length,1!==c?(d=d.sort(function(a,b){return a.y-b.y}),e=c%2===0?-(f/2)*(c/2):-(c-1)/2*f,d.forEach(function(a,b){return a.labelOffset=e+f*b})):d[0].labelOffset=0}},e(c("left")),e(c("right")),a},getTooltipHandlers:function(a){return"scrubber"===a.tooltip.mode?{onChartHover:angular.bind(this,this.showScrubber)}:{onMouseOver:angular.bind(this,this.onMouseOver),onMouseOut:angular.bind(this,this.onMouseOut)}},styleTooltip:function(a){return a.attr({"font-family":"monospace","font-size":10,fill:"white","text-rendering":"geometric-precision"})},addTooltips:function(a,b,c){var d,e,f,g,h,i,j,k;return h=b.width,e=b.height,h=h-b.left-b.right,e=e-b.top-b.bottom,g=24,d=18,f=5,i=a.append("g").attr({id:"xTooltip","class":"xTooltip",opacity:0}),i.append("path").attr("transform","translate(0,"+(e+1)+")"),this.styleTooltip(i.append("text").style("text-anchor","middle").attr({width:g,height:d,transform:"translate(0,"+(e+19)+")"})),k=a.append("g").attr({id:"yTooltip","class":"yTooltip",opacity:0}),k.append("path"),this.styleTooltip(k.append("text").attr({width:d,height:g})),null!=c.y2?(j=a.append("g").attr({id:"y2Tooltip","class":"y2Tooltip",opacity:0,transform:"translate("+h+",0)"}),j.append("path"),this.styleTooltip(j.append("text").attr({width:d,height:g}))):void 0},onMouseOver:function(a,b,c){return this.updateXTooltip(a,b,c.x),"y2"===b.series.axis?this.updateY2Tooltip(a,b,c.y2):this.updateYTooltip(a,b,c.y)},onMouseOut:function(a){return this.hideTooltips(a)},updateXTooltip:function(a,b,c){var d,e,f,g,h,i,j,k;return i=b.x,e=b.datum,g=b.series,j=a.select("#xTooltip"),j.transition().attr({opacity:1,transform:"translate("+i+",0)"}),k=c.tooltipFormatter,h=k?k(e.x):e.x,f=j.select("text"),f.text(h),d=angular.isFunction(g.color)?g.color(e,g.values.indexOf(e)):g.color,j.select("path").style("fill",d).attr("d",this.getXTooltipPath(f[0][0]))},getXTooltipPath:function(a){var b,c,d;return d=Math.max(this.getTextBBox(a).width,15),b=18,c=5,"m-"+d/2+" "+c+" l0 "+b+" l"+d+" 0 l0 "+-b+"l"+(-d/2+c)+" 0 l"+-c+" -"+b/4+" l"+-c+" "+b/4+" l"+(-d/2+c)+" 0z"},updateYTooltip:function(a,b,c){var d,e,f,g,h,i,j,k,l;return j=b.y,e=b.datum,g=b.series,k=a.select("#yTooltip"),k.transition().attr({opacity:1,transform:"translate(0, "+j+")"}),l=c.tooltipFormatter,h=l?l(e.y):e.y,f=k.select("text"),f.text(h),i=this.getTextBBox(f[0][0]).width+5,f.attr({transform:"translate("+(-i-2)+",3)",width:i}),d=angular.isFunction(g.color)?g.color(e,g.values.indexOf(e)):g.color,k.select("path").style("fill",d).attr("d",this.getYTooltipPath(i))},updateY2Tooltip:function(a,b,c){var d,e,f,g,h,i,j,k,l;return j=b.y,e=b.datum,g=b.series,k=a.select("#y2Tooltip"),k.transition().attr("opacity",1),l=c.tooltipFormatter,h=l?l(e.y):e.y,f=k.select("text"),f.text(h),i=this.getTextBBox(f[0][0]).width+5,f.attr({transform:"translate(7, "+(parseFloat(j)+3)+")",w:i}),d=angular.isFunction(g.color)?g.color(e,g.values.indexOf(e)):g.color,k.select("path").style("fill",d).attr({d:this.getY2TooltipPath(i),transform:"translate(0, "+j+")"})},getYTooltipPath:function(a){var b,c;return b=18,c=5,"m0 0l"+-c+" "+-c+" l0 "+(-b/2+c)+" l"+-a+" 0 l0 "+b+" l"+a+" 0 l0 "+(-b/2+c)+"l"+-c+" "+c+"z"},getY2TooltipPath:function(a){var b,c;return b=18,c=5,"m0 0l"+c+" "+c+" l0 "+(b/2-c)+" l"+a+" 0 l0 "+-b+" l"+-a+" 0 l0 "+(b/2-c)+" l"+-c+" "+c+"z"},hideTooltips:function(a){return a.select("#xTooltip").transition().attr("opacity",0),a.select("#yTooltip").transition().attr("opacity",0),a.select("#y2Tooltip").transition().attr("opacity",0)}}}]),angular.module("kbWebApp",["ngAnimate","ngCookies","ngResource","ngRoute","ngSanitize","ngTouch","ngTable","ngMessages","ngMaterial","ui.bootstrap","angular-loading-bar","n3-line-chart"]).config(["$routeProvider",function(a){a.when("/About",{templateUrl:"views/about.html",controller:"AboutCtrl",controllerAs:"about"}).when("/Config",{templateUrl:"views/config.html",controller:"ConfigCtrl",controllerAs:"config"}).when("/InteractiveMode",{templateUrl:"views/run.html",controller:"RunCtrl",controllerAs:"run"}).when("/MonitoringMode",{templateUrl:"views/interval.html",controller:"IntervalCtrl",controllerAs:"interval"}).when("/Log",{templateUrl:"views/log.html",controller:"LogCtrl",controllerAs:"log"}).when("/Login",{templateUrl:"views/login.html",controller:"LoginCtrl",controllerAs:"login"}).when("/StorageConfig",{templateUrl:"views/config_storage.html",controller:"StorageConfigCtrl",controllerAs:"config_storage"}).when("/StorageMode",{templateUrl:"views/run_storage.html",controller:"RunStorageCtrl",controllerAs:"run_storage"}).otherwise({redirectTo:"/InteractiveMode"})}]).config(["cfpLoadingBarProvider",function(a){a.latencyThreshold=1}]),angular.module("kbWebApp").controller("AboutCtrl",["$scope","$http","$location","kbHttp","kbCookie","locationChange",function(a,b,c,d,e,f){this.awesomeThings=["HTML5 Boilerplate","AngularJS","Karma"],$(window).on("hashchange",f.change()),d.getMethod("/kloudbuster/version").then(function(b){a.version=b.data},function(a){console.log("get version error:"),console.log(a)})}]).service("locationChange",function(){function a(a){$("#"+a).addClass("active")}function b(){$("#scaletestnav").removeClass("active"),$("#interactivenav").removeClass("active"),$("#monitoringnav").removeClass("active"),$("#confignav").removeClass("active"),$("#lognav").removeClass("active"),$("#loginnav").removeClass("active"),$("#aboutnav").removeClass("active"),$("#storageconfignav").removeClass("active"),$("#storagemodenav").removeClass("active")}var c;this.change=function(){switch(c=$(location).attr("hash"),b(),$("#scaletestname").text("Scale/Performance"),$("#loginname").text("Log Out"),c){case"#/InteractiveMode":a("scaletestnav"),a("interactivenav"),$("#scaletestname").text("Interactive Mode");break;case"#/MonitoringMode":a("scaletestnav"),a("monitoringnav"),$("#scaletestname").text("Monitoring Mode");break;case"#/Config":a("confignav");break;case"#/Log":a("lognav");break;case"#/Login":a("loginnav"),$("#loginname").text("Log In");break;case"#/About":a("aboutnav");break;case"#/StorageConfig":a("storageconfignav");break;case"#/StorageMode":a("storagemodenav")}}}).service("kbHttp",["$http","$q",function(a,b){var c=$(location).attr("protocol")+"//"+$(location).attr("host")+"/api";this.getMethod=function(d){var e=b.defer();return a.get(c+d).then(function(a){e.resolve(a)},function(a){e.reject(a)}),e.promise},this.getMethod2=function(d){var e=b.defer();return a.get(c+d,{ignoreLoadingBar:!0}).then(function(a){e.resolve(a)},function(a){e.reject(a)}),e.promise},this.putMethod=function(d,e){var f=b.defer();return a.defaults.headers.put["Content-Type"]="application/x-www-form-urlencoded;charset=utf-8",a.put(c+d,"arg="+encodeURIComponent(angular.toJson(e))).then(function(a){f.resolve(a)},function(a){f.reject(a)}),f.promise},this.postMethod=function(d,e){var f=b.defer();return e?(a.defaults.headers.post["Content-Type"]="application/x-www-form-urlencoded;charset=utf-8",a.post(c+d,"arg="+encodeURIComponent(angular.toJson(e))).then(function(a){f.resolve(a)},function(a){f.reject(a)}),f.promise):(a.post(c+d).then(function(a){f.resolve(a)},function(a){f.reject(a)}),f.promise)},this.delMethod=function(d){var e=b.defer();return a["delete"](c+d).then(function(a){e.resolve(a)},function(a){e.reject(a)}),e.promise}}]).service("kbCookie",["$location",function(a){this.init=function(){b="",d="",e="",f="",h="",i=0,g="",h="",i=0,j=0,c=""};var b="";this.getSessionID=function(){return b},this.setSessionID=function(a){return b=a};var c="";this.getMode=function(){return c},this.setMode=function(a){return c=a},this.checkMode=function(b){"login"==b?($(".forHttp").hide(),$(".forStorage").show()):"storage"==c?($(".forHttp").hide(),$(".forStorage").show(),c!=b&&a.path("/StorageMode")):"http"==c?($(".forStorage").hide(),$(".forHttp").show(),c!=b&&a.path("/InteractiveMode")):a.path("/Login")};var d="";this.getStatus=function(){return d},this.setStatus=function(a){return d=a};var e="";this.getConfig=function(){return e},this.setConfig=function(a){return e=a};var f="";this.getCredentials=function(){return f},this.setCredentials=function(a){return f=a};var g="";this.getIsOneCloud=function(){return g},this.setIsOneCloud=function(a){return g=a};var h="";this.getTopology=function(){return h},this.setTopology=function(a){return h=a};var i=0;this.getLogOffset=function(){return i},this.setLogOffset=function(a){return i=a};var j=0;this.getLogNum=function(){return j},this.setLogNum=function(a){return j=a}}]).service("showAlert",["$mdDialog",function(a){this.showAlert=function(b,c){var d=a.alert({title:"Attention",content:b,ok:"Close"});a.show(d)["finally"](function(){d=void 0})}}]),angular.module("kbWebApp").controller("ConfigCtrl",["$scope","$http","$location","showAlert","kbHttp","kbCookie","locationChange",function(a,b,c,d,e,f,g){function h(){a.selectedA=[],a.selectedB=[],a.selectedC=[],l=[],a.listA=[],a.listB=[],a.listC=[],a.toggle=!1}function i(a,b,c){for(var d=0,e=a.length;e>d;d++)if(a[d][c]===b)return d;return-1}function j(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1}function k(){a.selectedA=[],a.selectedB=[],a.selectedC=[],a.toggle=!1}this.awesomeThings=["HTML5 Boilerplate","AngularJS","Karma"],""===f.getSessionID()?c.path("/Login"):f.checkMode("http"),$(window).on("hashchange",g.change()),a.sessionID=f.getSessionID(),a.status=f.getStatus(),a.dashstatus1="active",a.dashstatus1vis=!0,a.dashstatus2="",a.dashstatus2vis=!1,a.dashstatus3="",a.dashstatus3vis=!1,a.setDashStatus=function(b){1===b?(a.dashstatus2="",a.dashstatus2vis=!1,a.dashstatus3="",a.dashstatus3vis=!1,a.dashstatus1="active",a.dashstatus1vis=!0):2===b?(a.dashstatus1="",a.dashstatus1vis=!1,a.dashstatus3="",a.dashstatus3vis=!1,a.dashstatus2="active",a.dashstatus2vis=!0):3===b&&(a.dashstatus1="",a.dashstatus1vis=!1,a.dashstatus2="",a.dashstatus2vis=!1,a.dashstatus3="active",a.dashstatus3vis=!0)};var l;a.setUserData=function(b){var c,d=1;for(c in b)l.push({id:d++,firstName:b[c]});a.listA=l.slice(0,l.length),a.items=l},h(),a.aToB=function(){for(var b in a.selectedA){var c=i(a.items,a.selectedA[b],"id");a.listB.push(a.items[c]);var d=i(a.listA,a.selectedA[b],"id");a.listA.splice(d,1)}k()},a.aToC=function(){for(var b in a.selectedA){var c=i(a.items,a.selectedA[b],"id");a.listC.push(a.items[c]);var d=i(a.listA,a.selectedA[b],"id");a.listA.splice(d,1)}k()},a.bToA=function(){for(var b in a.selectedB){var c=i(a.items,a.selectedB[b],"id");a.listA.push(a.items[c]);var d=i(a.listB,a.selectedB[b],"id");a.listB.splice(d,1)}k()},a.cToA=function(){for(var b in a.selectedC){var c=i(a.items,a.selectedC[b],"id");a.listA.push(a.items[c]);var d=i(a.listC,a.selectedC[b],"id");a.listC.splice(d,1)}k()},a.toggleA=function(){if(a.selectedA.length>0)k();else for(var b in a.listA)a.selectedB=[],a.selectedC=[],a.selectedA.push(a.listA[b].id)},a.toggleB=function(){if(a.selectedB.length>0)k();else for(var b in a.listB)a.selectedA=[],a.selectedC=[],a.selectedB.push(a.listB[b].id)},a.toggleC=function(){if(a.selectedC.length>0)k();else for(var b in a.listC)a.selectedA=[],a.selectedB=[],a.selectedC.push(a.listC[b].id)},a.selectA=function(b){var c=j(a.selectedA,b);-1===c?a.selectedA.push(b):a.selectedA.splice(c,1)},a.selectB=function(b){var c=j(a.selectedB,b);-1===c?a.selectedB.push(b):a.selectedB.splice(c,1)},a.selectC=function(b){var c=j(a.selectedC,b);-1===c?a.selectedC.push(b):a.selectedC.splice(c,1)},a.checkStatus=function(){a.sessionID?e.getMethod2("/kloudbuster/status/"+a.sessionID).then(function(b){a.status=b.data.status,f.setStatus(a.status),a.configStatus()},function(a){console.log("status error")}):(a.status="NO SESSION ID",f.setStatus(""))},a.checkStatus();var m=!1;a.disableConfig=function(a){$("#"+a).find("input,button").each(function(){$(this).attr("disabled","disabled")})},a.enableConfig=function(a){$("#"+a).find("input,button").each(function(){$(this).removeAttr("disabled")})},a.configStatus=function(){"READY"===a.status?m===!0&&(m=!1,a.enableConfig("stagingConfig2"),a.enableConfig("getButton"),$("md-radio-button").removeAttr("disabled")):m===!1&&(m=!0,a.disableConfig("stagingConfig2"),a.disableConfig("getButton"),$("md-radio-button").attr("disabled","disabled")),f.getIsOneCloud()===!1&&a.disableConfig("topology")},a.getTopology=function(){e.getMethod("/config/hypervisor_list/"+a.sessionID).then(function(b){a.setUserData(b.data.server)},function(a){console.log("get hypervisor list error:"),console.log(a)})},a.getDefaultConfig=function(){e.getMethod("/config/default_config").then(function(b){f.setConfig(b.data),a.config=b.data,0==a.config.server.flavor.disk?a.choose_disk_size1=0:a.choose_disk_size1=1,0==a.config.client.flavor.disk?a.choose_disk_size2=0:a.choose_disk_size2=1,console.log("get & save default config")},function(a){d.showAlert("Cannot get the Default Configuration!")}),a.getTopology(),f.setTopology(""),a.availability_zone=1,l=[],h()},a.getRunConfig=function(){a.availability_zone=1,e.getMethod("/config/running_config/"+a.sessionID).then(function(b){f.setConfig(b.data),a.config=b.data,0==a.config.server.flavor.disk?a.choose_disk_size1=0:a.choose_disk_size1=1,0==a.config.client.flavor.disk?a.choose_disk_size2=0:a.choose_disk_size2=1,(null!=a.config.server.availability_zone&&""!=a.config.server.availability_zone||null!=a.config.client.availability_zone&&""!=a.client.server.availability_zone)&&(a.availability_zone=2),console.log("get & save running config")},function(a){console.log("get running config error:"),console.log(a)}),e.getMethod("/config/az_list/"+a.sessionID).then(function(b){f.getIsOneCloud()===!1?(a.serversides=b.data.server,a.clientsides=b.data.client):(a.serversides=b.data.server,a.clientsides=b.data.server)},function(a){console.log("get AZ list error:"),console.log(a)}),h(),a.getTopology(),e.getMethod("/config/topology_config/"+a.sessionID).then(function(b){if("null"!=b.data&&(0!=b.data.servers_rack.length||0!=b.data.clients_rack.length)){a.availability_zone=3,a.topology={servers_rack:b.data.servers_rack,clients_rack:b.data.clients_rack},f.setTopology(a.topology),console.log(b.data);for(var c in a.topology.servers_rack){var d=i(a.items,a.topology.servers_rack[c],"firstName");a.listC.push(a.items[d]);var e=i(a.listA,a.topology.servers_rack[c],"firstName");a.listA.splice(e,1)}for(var c in a.topology.clients_rack){var d=i(a.items,a.topology.clients_rack[c],"firstName");a.listB.push(a.items[d]);var e=i(a.listA,a.topology.clients_rack[c],"firstName");a.listA.splice(e,1)}}console.log("get & save topology config")},function(a){console.log("get topology config error:"),console.log(a)})},a.getRunConfig(),a.changeConfig=function(){if("READY"===a.status||""===a.status)if(1==a.server.$valid&&1==a.general.$valid&&1==a.client.$valid){if(f.setConfig(a.config),3==a.availability_zone){a.topology={servers_rack:[],clients_rack:[]};for(var b in a.listC)a.topology.servers_rack.push(a.listC[b].firstName);for(var b in a.listB)a.topology.clients_rack.push(a.listB[b].firstName);f.setTopology(a.topology)}else f.setTopology({servers_rack:"",clients_rack:""});a.chaCon={kb_cfg:{},topo_cfg:{}},a.chaCon.kb_cfg=f.getConfig(),a.chaCon.topo_cfg=f.getTopology(),console.log(a.chaCon),e.putMethod("/config/running_config/"+a.sessionID,a.chaCon).then(function(a){console.log("change running config")},function(a){d.showAlert("Failed to update configuration!")})}else d.showAlert("Please check your inputs!");else d.showAlert("Configuration cannot be changed now!")},a.changeTopology=function(){1==a.availability_zone?(a.config.server.availability_zone="",a.config.client.availability_zone="",a.topology={},f.setTopology({servers_rack:"",clients_rack:""}),h(),a.getTopology()):2==a.availability_zone?(a.topology={},f.setTopology({servers_rack:"",clients_rack:""}),h(),a.getTopology()):3==a.availability_zone&&(a.config.server.availability_zone="",a.config.client.availability_zone="")}}]),angular.module("kbWebApp").controller("RunCtrl",["$scope","$timeout","$location","$http","$q","showAlert","ngTableParams","kbCookie","kbHttp","interactiveMode","color","locationChange",function(a,b,c,d,e,f,g,h,i,j,k,l){function m(a,b){var c=document.createElement("a"),d=new Blob([b]),e=document.createEvent("HTMLEvents");e.initEvent("click",!1,!1),c.download=a,c.href=URL.createObjectURL(d),c.dispatchEvent(e)}function n(a){return 10>a?"0"+a:99>a?""+a:-1}this.awesomeThings=["HTML5 Boilerplate","AngularJS","Karma"],""===h.getSessionID()?c.path("/Login"):h.checkMode("http"),$(window).on("hashchange",l.change()),$("[data-toggle='.container']").click(function(){var a=$(this).data("toggle");$(a).toggleClass("open-sidebar"),$("#littleglyph").toggleClass("glyphicon-triangle-right"),$("#littleglyph").toggleClass("glyphicon-triangle-left")}),$(".swipe-area").swipe({swipeStatus:function(a,b,c,d,e,f){return"move"==b&&"right"==c?($(".container").addClass("open-sidebar"),!1):"move"==b&&"left"==c?($(".container").removeClass("open-sidebar"),!1):void 0}}),a.oneAtATime=!0,a.status1={isFirstOpen:!0,isFirstDisabled:!1},a.status2={isFirstOpen:!0,isFirstDisabled:!1},a.status3={isFirstOpen:!0,isFirstDisabled:!1},a.status1.open=!1,a.status2.open=!0,a.status3.open=!1,a.alerts=[],a.closeAlert=function(b){a.alerts.splice(b,1)},a.sessionID=h.getSessionID(),a.status=h.getStatus(),a.config=h.getConfig(),a.getRunConfig=function(){i.getMethod("/config/running_config/"+a.sessionID).then(function(b){a.config=b.data,h.setConfig(b.data),console.log("get & save config")},function(a){console.log("get running config error:"),console.log(a)})},a.sessionID&&!a.config&&a.getRunConfig(),a.setConfig=function(b){var c=e.defer();return"READY"===a.status?(h.setConfig(a.config),a.chaCon={kb_cfg:{}},a.chaCon.kb_cfg=h.getConfig(),i.putMethod("/config/running_config/"+a.sessionID,a.chaCon).then(function(a){console.log("change running config"),c.resolve(1)},function(a){c.reject(0),1!=b&&(400==a.status?f.showAlert("Error while parsing configurations! Please check your inputs!"):403==a.status?f.showAlert("Cannot update configuration if KloudBuster is busy or in error state"):-1==a.status&&f.showAlert("Error while connecting kloudbuster server!"))})):"STAGED"===a.status?(a.config.client.http_tool_configs.report_interval=0,h.setConfig(a.config),a.chaCon={kb_cfg:{client:{http_tool_configs:{duration:a.config.client.http_tool_configs.duration,rate_limit:a.config.client.http_tool_configs.rate_limit,connections:a.config.client.http_tool_configs.connections,report_interval:0}}}},i.putMethod("/config/running_config/"+a.sessionID,a.chaCon).then(function(a){console.log("change running config"),c.resolve(1)},function(a){c.reject(0),1!=b&&(400==a.status?f.showAlert("Error while parsing configurations! Please check your inputs!"):403==a.status?f.showAlert("Cannot update configuration if KloudBuster is busy or in error state"):-1==a.status&&f.showAlert("Error while connecting kloudbuster server!"))})):(console.log("config not allow to change now!"),c.reject(0)),c.promise};var o=!1,p=!1;a.disableConfig=function(a){$("#"+a).find("input").each(function(){$(this).attr("disabled","disabled")})},a.enableConfig=function(a){$("#"+a).find("input").each(function(){$(this).removeAttr("disabled")})},a.configStatus=function(){"READY"===a.status?(o===!0&&(o=!1,a.enableConfig("stagingConfig"),a.enableConfig("stagingConfig1"),$("#client_progression_enabled").removeAttr("disabled")),p===!0&&(p=!1,a.enableConfig("runningConfig"))):"STAGED"===a.status?(o===!1&&(o=!0,a.disableConfig("stagingConfig"),a.disableConfig("stagingConfig1"),$("#client_progression_enabled").attr("disabled","disabled")),p===!0&&(p=!1,a.enableConfig("runningConfig"))):(o===!1&&(o=!0,a.disableConfig("stagingConfig"),a.disableConfig("stagingConfig1"),$("md-checkbox").attr("disabled","disabled")),p===!1&&(p=!0,a.disableConfig("runningConfig")))};var q=0;a.pointNum=function(){var a=".";q=(q+1)%6;for(var b=0;q>b;b++)a+=" .";return a},a.runButton="Run Test",a.runStatus=!0,a.setStatus=!1,a.stageButton="Stage",a.setUnstage=!0,a.client_vm_count=0,a.server_vm_count=0,a.statusButton="btn-default",a.checkStatus=function(){a.sessionID?i.getMethod2("/kloudbuster/status/"+a.sessionID).then(function(b){a.status=b.data.status,h.setStatus(a.status),a.configStatus(),"READY"===a.status?(a.runButton="Run Test",a.runStatus=!0,a.setStatus=!1,a.stageButton="Stage",a.setUnstage=!1,a.client_vm_count=0,a.server_vm_count=0,$(".loading").addClass("pause"),a.statusButton="btn-success",a.info=""):"STAGING"===a.status?(a.runButton="Run Test",a.runStatus=!0,a.setStatus=!0,a.stageButton="Stage",a.setUnstage=!0,a.client_vm_count=b.data.client_vm_count,a.server_vm_count=b.data.server_vm_count,$(".loading").removeClass("pause"),a.statusButton="btn-info",a.info="KloudBuster is Creating VM(s)"+a.pointNum()):"STAGED"===a.status?(a.runButton="Run Test",a.runStatus=!1,a.setStatus=!1,a.stageButton="Unstage",a.setUnstage=!1,a.client_vm_count=a.config.server.routers_per_tenant*a.config.server.networks_per_router*a.config.server.vms_per_network*a.config.server.number_tenants,a.server_vm_count=a.client_vm_count,a.getReport(),$(".loading").addClass("pause"),a.statusButton="btn-success",a.info=""):"RUNNING"===a.status?(a.runButton="Stop Test",a.runStatus=!1,a.setStatus=!0,a.stageButton="Unstage",a.setUnstage=!0,a.client_vm_count=a.config.server.routers_per_tenant*a.config.server.networks_per_router*a.config.server.vms_per_network*a.config.server.number_tenants,a.server_vm_count=a.client_vm_count,a.config.client.progression.enabled===!0&&a.getReport(),$(".loading").removeClass("pause"),a.statusButton="btn-info",a.info="KloudBuster is Running"+a.pointNum()):"ERROR"===a.status?(a.runButton="Run Test",a.runStatus=!0,a.setStatus=!0,a.stageButton="Unstage",a.setUnstage=!1,a.client_vm_count=a.config.server.routers_per_tenant*a.config.server.networks_per_router*a.config.server.vms_per_network*a.config.server.number_tenants,a.server_vm_count=a.client_vm_count,$(".loading").addClass("pause"),a.statusButton="btn-danger",a.info=""):"CLEANING"!==a.status&&"STOPPING"!==a.status||(a.runButton="Run Test",a.runStatus=!0,a.setStatus=!0,a.stageButton="Unstage",a.setUnstage=!0,a.client_vm_count=a.config.server.routers_per_tenant*a.config.server.networks_per_router*a.config.server.vms_per_network*a.config.server.number_tenants,a.server_vm_count=a.client_vm_count,$(".loading").removeClass("pause"),a.statusButton="btn-info",a.info="Please Wait"+a.pointNum())},function(a){console.log("get status error:"),console.log(a)}):(a.status="NO SESSION ID",h.setStatus(""))},a.checkStatus(),a.setStage=function(){i.postMethod("/kloudbuster/stage/"+a.sessionID).then(function(a){},function(a){console.log("set stage error:"),console.log(a),f.showAlert("Unable to stage resources!")})},a.CleanUp=function(){a.initChart(),!a.sessionID||"ERROR"!==a.status&&"STAGED"!==a.status?console.log("Cannot cleanup!"):i.postMethod("/kloudbuster/cleanup/"+a.sessionID).then(function(b){a.checkStatus()},function(a){console.log("clean error:"),console.log(a)})},a.stage=function(){if("ERROR"===a.status||"STAGED"===a.status)a.CleanUp();else if("READY"===a.status){var b=a.setConfig(1);b.then(function(){a.setStage()})}},a.runKb=function(){i.postMethod("/kloudbuster/run_test/"+a.sessionID).then(function(a){},function(a){console.log("running error:"),console.log(a),f.showAlert("Unable to start test!")})},a.stopKb=function(){i.postMethod("/kloudbuster/stop_test/"+a.sessionID).then(function(a){},function(a){console.log("stop error:"),console.log(a),f.showAlert("Unable to stop test!")})},a.scaleTest=function(){if("RUNNING"===a.status)a.stopKb();else if("STAGED"===a.status){var b=a.setConfig(1);b.then(function(){a.initChart(),a.runKb()})}},a.tabledata=[],a.cols=[{field:"seq",title:"SEQ",sortable:"seq",show:!0},{field:"connection",title:"Connection",sortable:"connection",show:!0},{field:"server_vms",title:"Server VMs",sortable:"server_vms",show:!0},{field:"requests",title:"Requests",sortable:"requests",show:!0},{field:"sock_err",title:"Error",sortable:"sock_err",show:!0},{field:"rps",title:"RPS measured",sortable:"rps",show:!0},{field:"rate_limit",title:"RPS requested",sortable:"rate_limit",show:!0},{field:"throughput",title:"Throughput",sortable:"throughput",show:!0},{field:"action",title:"Action",sortable:"action",show:!0}],a.tableParams=new g({sorting:{name:"asc"},count:10},{counts:[],data:a.tabledata}),a.options={axes:{x:{key:"x",type:"linear",ticksFormatter:function(a){return 0===a?"50%":10===a?"75%":20===a?"90%":30===a?"99%":40===a?"99.9%":50===a?"99.99%":60===a?"99.999%":void 0}},y:{type:"log",ticksFormat:"d",innerTicks:!0,grid:!0}},tooltip:{mode:"scrubber",formatter:function(a,b,c){return c.label+":"+b}},tension:.8,lineMode:"cardinal",series:[{}]},a.initChart=function(){a.data=[{x:0},{x:10},{x:20},{x:30},{x:40},{x:50},{x:60}],a.options.series=[{}],a.isDely=!1,a.tabledata.length=0,a.tableParams.reload(),a.isDely=!1,r=0,k.reset()};var r=0;a.initChart(),a.refreshChart=function(){a.data=[{x:0},{x:10},{x:20},{x:30},{x:40},{x:50},{x:60}],a.options.series=[{}],a.isDely=!1,a.tabledata.length=0,a.tableParams.reload(),k.reset()},a.getReport=function(){i.getMethod2("/kloudbuster/report/"+a.sessionID+"?final=true").then(function(b){if(console.log("get report totally:"+b.data.kb_result.length),b.data.kb_result.length>0&&r<b.data.kb_result.length){r=b.data.kb_result.length,a.refreshChart(),j.setResult(b.data);for(var c=0;r>c;c++){a.result=b.data.kb_result[c];var d=k.getColor();a.config.client.progression.enabled?(console.log("show report"+a.name),a.pushChartData("Connection-"+a.result.total_connections,a.result,d),a.pushTableData("Connection-"+a.result.total_connections,a.result,d)):(console.log("show report"+a.name),a.pushChartData("Final",a.result,d),a.pushTableData("Final",a.result,d))}}},function(a){console.log("get report error:"),console.log(a)})},a.pushChartData=function(b,c,d){a.isDely===!1&&(a.options.series.shift(),a.isDely=!0),a.options.series.push({y:b,label:b,color:d,dotSize:"3",thickness:"2px"});for(var e=0;7>e;e++)a.data[e][b]=c.latency_stats[e][1]/1e3},a.pushTableData=function(b,c,d){var e=8*c.http_throughput_kbytes/1e6;a.tabledata.push({seq:b,connection:c.total_connections,server_vms:c.total_server_vms,requests:c.http_total_req,sock_err:c.http_sock_err+c.http_sock_timeout,rps:c.http_rps,rate_limit:c.http_rate_limit,throughput:e.toFixed(2),description:c.description,color:d}),$("<style>md-checkbox.md-checked."+b+" .md-icon {background-color: "+d+";</style>").appendTo("head"),a.tableParams.reload()},a.saveResult=function(){var a=new Date,b=n(a.getMonth()+1),c=n(a.getDate()),d=n(a.getHours()),e=n(a.getMinutes()),g=""+b+c+d+e+".html",i=j.getResult();if(""!=i){var k='<!--Copyright 2016 Cisco Systems, Inc. All rights reserved.--> <!--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.--> <!DOCTYPE html> <html lang="en-US" ng-app="app"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>KloudBuster Report</title> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.min.js"></script> <script src="https://d3js.org/d3.v3.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/line-chart/2.0.3/LineChart.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/line-chart/2.0.3/LineChart.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ng-table/0.8.3/ng-table.min.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/ng-table/0.8.3/ng-table.min.js"></script> <link rel="stylesheet" href="https://bootswatch.com/flatly/bootstrap.min.css"> <script src="https://code.jquery.com/jquery-2.2.0.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script> <style rel="stylesheet"> .hidden { display: inline !important; } .label { padding: 0; font-size: 110%; font-weight: normal; line-height: 16; color: #000000; text-align: center; } </style> </head> <body ng-controller="MainCtrl"> <nav class="navbar navbar-default"> <div class="container-fluid"> <a class="navbar-brand" ng-href="#/" style="font-family: Arial"> <span style="color:#DF314D">K</span>loudBuster </a> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav" ng-init="tab=0"> <li ng-class="{active:tab==0}" ng-click="tab=0"> <a><span class="glyphicon" aria-hidden="true" ></span>Report</a> </li> <li ng-class="{active:tab==1}" ng-click="tab=1" ng-show="config == true"> <a><span class="glyphicon" aria-hidden="true" ></span>Configuration</a> </li> </ul> <!--<ul class="nav navbar-nav navbar-right">--> <!--<li><a href="#"></a></li>--> <!--</ul>--> </div> </div> </nav> <div class="container" ng-show="tab == 0"> <h3>KloudBuster HTTP Testing Report</h3> <div class="my-chart" style="height: 400px;margin-bottom: 10%"> <linechart data="data" options="options"></linechart> </div> <table ng-table="tableParams" class="table table-responsive table-condensed table-bordered table-striped"> <tr ng-repeat="row in tableParams.data" style="text-align:center;"> <td title="cols[0].title" ng-if="cols[0].show" style="margin:0 auto;padding:0;"> <button class="btn btn-default btn-xs {{row.seq}}" ng-click="" style="height: 22px;width: 24px;"></button> </td> <td title="cols[1].title" data-sortable="cols[1].field" ng-if="cols[1].show">{{row.connection}}</td> <td title="cols[2].title" data-sortable="cols[2].field" ng-if="cols[2].show">{{row.server_vms}}</td> <td title="cols[3].title" data-sortable="cols[3].field" ng-if="cols[3].show">{{row.requests}}</td> <td title="cols[4].title" data-sortable="cols[4].field" ng-if="cols[4].show">{{row.sock_err}}</td> <td title="cols[5].title" data-sortable="cols[5].field" ng-if="cols[5].show">{{row.rps}}</td> <td title="cols[6].title" data-sortable="cols[6].field" ng-if="cols[6].show">{{row.rate_limit}}</td> <td title="cols[7].title" data-sortable="cols[7].field" ng-if="cols[7].show">{{row.throughput}} Gbps</td> </tr> </table> </div> <div class="container" ng-show="tab == 1"> <h3>KloudBuster HTTP Testing Configuration</h3> <div class="panel panel-default"> <div class="panel-body" style="word-wrap:break-word"> <textarea style="width: 100%;height: 900px" disabled> {{from_outside_config}}</textarea> </div> </div> </div> <footer style="text-align: center;"> <hr style="margin:2px"/> <h6 style="color:gray">{{from_outside["time"]}} - KloudBuster {{from_outside["version"]}}</h6> </footer> <script type="text/javascript"> angular.module("app", ["n3-line-chart", "ngTable"]).controller("MainCtrl", function ($scope, color, ngTableParams) { if($scope.config = true) $scope.from_outside_config = JSON.stringify('+JSON.stringify(h.getConfig())+', null, " "); $scope.from_outside = '+JSON.stringify(i)+'; $scope.result = $scope.from_outside["kb_result"]; var countRep = $scope.result.length; $scope.data = {dataset0: [{x: 0}, {x: 10}, {x: 20}, {x: 30}, {x: 40}, {x: 50}, {x: 60}]}; $scope.options = { series: [], axes: { x: { key: "x", type: "linear", tickFormat: function (value) { if (value === 0) { return "50%" } else if (value === 10) { return "75%" } else if (value === 20) { return "90%" } else if (value === 30) { return "99%" } else if (value === 40) { return "99.9%" } else if (value === 50) { return "99.99%" } else if (value === 60) { return "99.999%" } } }, y: { type: "log", ticksFormat: "d", ticks: 10, tickFormat: function (value, index) { return value } } }, margin: {top: 20, right: 30, bottom: 20, left: 30}, grid: {x: false, y: true} }; $scope.tabledata = []; $scope.cols = [{field: "seq", title: "SEQ", sortable: "seq", show: true}, { field: "connection", title: "Connection", sortable: "connection", show: true }, {field: "server_vms", title: "Server VMs", sortable: "server_vms", show: true}, { field: "requests", title: "Requests", sortable: "requests", show: true }, {field: "sock_err", title: "Error", sortable: "sock_err", show: true}, { field: "rps", title: "RPS measured", sortable: "rps", show: true }, {field: "rate_limit", title: "RPS requested", sortable: "rate_limit", show: true}, { field: "throughput", title: "Throughput", sortable: "throughput", show: true },]; $scope.tableParams = new ngTableParams({sorting: {name: "asc"}, "count": 10}, { counts: [], data: $scope.tabledata }); $scope.pushTableData = function (taName, taData, pickColor) { var temThrou = (taData.http_throughput_kbytes * 8) / (1000 * 1000); $scope.tabledata.push({ "seq": taName, "connection": taData.total_connections, "server_vms": taData.total_server_vms, "requests": taData.http_total_req, "sock_err": taData.http_sock_err + taData.http_sock_timeout, "rps": taData.http_rps, "rate_limit": taData.http_rate_limit, "throughput": temThrou.toFixed(2), "description": taData.description, "color": pickColor }); $("<style>button." + taName + " {background-color: " + pickColor + ";</style>").appendTo("head"); $scope.tableParams.reload() }; for (var i = 0; i < countRep; i++) { $scope.perrow = $scope.result[i]; var pickColor = color.getColor(); if (1) { chName = "Connection-" + $scope.perrow.total_connections; $scope.options.series.push({ label: chName, color: pickColor, dotSize: "3", thickness: "2px", axis: "y", dataset: "dataset0", key: chName, type: ["line", "dot"], id: chName, interpolation: {mode: "cardinal", tension: 0.8} }); for (var j = 0; j < 7; j++) { $scope.data.dataset0[j][chName] = $scope.perrow.latency_stats[j][1] / 1000 } $scope.pushTableData("Connection-" + $scope.perrow.total_connections, $scope.perrow, pickColor) } } }).service("color", function () { var self = this; var num = -1; var colorList = ["#F44336", "#673AB7", "#03A9F4", "#4CAF50", "#FFEB3B", "#BF360C", "#795548", "#E91E63", "#3F51B5", "#00BCD4", "#CDDC39", "#FF9800", "#9E9E9E", "#9C27B0", "#009688"]; var length = colorList.length; this.getColor = function () { num = (num + 1) % length; return colorList[num] }; this.reset = function () { num = -1 } }); </script> </body> </html> ';
m(g,k)}else f.showAlert("No result to save!")},setInterval(function(){a.checkStatus()},1e3),$(function(){$('[data-toggle="tooltip"]').tooltip()})}]).service("interactiveMode",function(){var a=[];this.getResult=function(){return a},this.setResult=function(b){return a=b}}).service("color",function(){var a=-1,b=["#F44336","#673AB7","#03A9F4","#4CAF50","#FFEB3B","#BF360C","#795548","#E91E63","#3F51B5","#00BCD4","#CDDC39","#FF9800","#9E9E9E","#9C27B0","#009688"],c=b.length;this.getColor=function(){return a=(a+1)%c,b[a]},this.reset=function(){a=-1}}).directive("convertToNumber",function(){return{require:"ngModel",link:function(a,b,c,d){d.$parsers.push(function(a){return parseFloat(a)}),d.$formatters.push(function(a){return""+a})}}}),angular.module("kbWebApp").controller("LogCtrl",["$scope","$compile","$http","$location","kbHttp","kbCookie","locationChange",function(a,b,c,d,e,f,g){this.awesomeThings=["HTML5 Boilerplate","AngularJS","Karma"],""===f.getSessionID()&&d.path("/Login"),$(window).on("hashchange",g.change()),String.prototype.replaceAll=function(a,b){return this.replace(new RegExp(a,"gm"),b)},a.sessionID=f.getSessionID(),a.status=f.getStatus(),a.logs="",a.logNum=f.getLogNum(),a.logOffset=0,a.delLog=function(){f.setLogOffset(a.logOffset),$("#cc").empty(),a.getLog()},a.getLog=function(){a.sessionID?(f.setLogNum(a.logNum),e.getMethod("/kloudbuster/log/"+a.sessionID+"?offset="+f.getLogOffset()).then(function(b){b.data=b.data.substring(1,b.data.length-1),a.logOffset=f.getLogOffset()+b.data.replace(/\\n/g,"a").length,a.logs=b.data.split("\\n"),$("#cc").empty();var c;c=0==f.getLogNum()?0:a.logs.length-f.getLogNum();for(var d in a.logs)c>0?c--:(a.logs[d]=a.logs[d].replace(/ /g,"&nbsp;"),$("#cc").append(a.logs[d]+"<br/>"))},function(a){console.log("get Log error:"),console.log(a)})):console.log("not connected "+a.status+","+a.sessionID)},a.getLog()}]),angular.module("kbWebApp").controller("IntervalCtrl",["$scope","$http","kbHttp","$q","$location","showAlert","kbCookie","monitorMode","locationChange",function(a,b,c,d,e,f,g,h,i){function j(a,b){var c=document.createElement("a"),d=new Blob([b]),e=document.createEvent("HTMLEvents");e.initEvent("click",!1,!1),c.download=a,c.href=URL.createObjectURL(d),c.dispatchEvent(e)}function k(a){return 10>a?"0"+a:99>a?""+a:-1}this.awesomeThings=["HTML5 Boilerplate","AngularJS","Karma"],""===g.getSessionID()?e.path("/Login"):g.checkMode("http"),$(window).on("hashchange",i.change()),$("[data-toggle='.container']").click(function(){var a=$(this).data("toggle");$(a).toggleClass("open-sidebar"),$("#littleglyph1").toggleClass("glyphicon-triangle-right"),$("#littleglyph1").toggleClass("glyphicon-triangle-left")}),$(".swipe-area").swipe({swipeStatus:function(a,b,c,d,e,f){return"move"==b&&"right"==c?($(".container").addClass("open-sidebar"),!1):"move"==b&&"left"==c?($(".container").removeClass("open-sidebar"),!1):void 0}}),a.oneAtATime=!0,a.status1={isFirstOpen:!0,isFirstDisabled:!1},a.status2={isFirstOpen:!0,isFirstDisabled:!1},a.status1.open=!1,a.status2.open=!0,a.alerts=[],a.closeAlert=function(b){a.alerts.splice(b,1)},a.sessionID=g.getSessionID(),a.status=g.getStatus(),a.config=g.getConfig(),a.getRunConfig=function(){c.getMethod("/config/running_config/"+a.sessionID).then(function(b){a.config=b.data,g.setConfig(b.data),console.log("get & save config")},function(a){console.log("get running config error:"),console.log(a)})},a.sessionID&&!a.config&&a.getRunConfig(),a.setConfig=function(b){var e=d.defer();if("READY"===a.status)a.config.client.progression.enabled=!1,g.setConfig(a.config),a.chaCon={kb_cfg:{}},a.chaCon.kb_cfg=g.getConfig(),c.putMethod("/config/running_config/"+a.sessionID,a.chaCon).then(function(a){console.log("change running config"),e.resolve(1),1!=b&&f.showAlert("Configuration updated successfully!")},function(a){e.reject(0),1!=b&&(400==a.status?f.showAlert("Error while parsing configurations! Please check your inputs!"):403==a.status?f.showAlert("Cannot update configuration if KloudBuster is busy or in error state"):-1==a.status&&f.showAlert("Error while connecting kloudbuster server!"))});else if("STAGED"===a.status){if(a.config.client.progression.enabled===!0)return alert("Can't Run Monitor Test Now! You have chosen Progression Test. Click Unstage Button First!"),e.reject(0),e.promise;if(0===a.config.client.progression.report_interval)return alert("Can't Run Monitor Test Now! Report interval must be a number no less than 1."),e.reject(0),e.promise;g.setConfig(a.config),a.chaCon={kb_cfg:{client:{http_tool_configs:{duration:a.config.client.http_tool_configs.duration,rate_limit:a.config.client.http_tool_configs.rate_limit,connections:a.config.client.http_tool_configs.connections,report_interval:a.config.client.http_tool_configs.report_interval}}}},console.log(a.chaCon),c.putMethod("/config/running_config/"+a.sessionID,a.chaCon).then(function(a){console.log("change running config"),e.resolve(1)},function(a){e.reject(0),1!=b&&(400==a.status?f.showAlert("Error while parsing configurations! Please check your inputs!"):403==a.status?f.showAlert("Cannot update configuration if KloudBuster is busy or in error state"):-1==a.status&&f.showAlert("Error while connecting kloudbuster server!"))})}else console.log("config not allow to change now!"),e.reject(0);return e.promise};var l=!1,m=!1;a.disableConfig=function(a){$("#"+a).find("input").each(function(){$(this).attr("disabled","disabled")})},a.enableConfig=function(a){$("#"+a).find("input").each(function(){$(this).removeAttr("disabled")})},a.configStatus=function(){"READY"===a.status?(l===!0&&(l=!1,a.enableConfig("stagingConfig")),m===!0&&(m=!1,a.enableConfig("runningConfig"))):"STAGED"===a.status?(l===!1&&(l=!0,a.disableConfig("stagingConfig")),m===!0&&(m=!1,a.enableConfig("runningConfig"))):(l===!1&&(l=!0,a.disableConfig("stagingConfig")),m===!1&&(m=!0,a.disableConfig("runningConfig")))};var n=0;a.pointNum=function(){var a=".";n=(n+1)%6;for(var b=0;n>b;b++)a+=" .";return a},a.runButton="Run Test",a.runStatus=!0,a.setStatus=!1,a.stageButton="Stage",a.setUnstage=!0,a.client_vm_count=0,a.server_vm_count=0,a.statusButton="btn-default",a.checkStatus=function(){a.sessionID?c.getMethod2("/kloudbuster/status/"+a.sessionID).then(function(b){a.status=b.data.status,a.configStatus(),g.setStatus(a.status),"READY"===a.status?(a.runButton="Run Test",a.runStatus=!0,a.setStatus=!1,a.stageButton="Stage",a.setUnstage=!1,a.client_vm_count=0,a.server_vm_count=0,$(".loading").addClass("pause"),a.statusButton="btn-success",a.info=""):"STAGING"===a.status?(a.runButton="Run Test",a.runStatus=!0,a.setStatus=!0,a.stageButton="Stage",a.setUnstage=!0,a.client_vm_count=b.data.client_vm_count,a.server_vm_count=b.data.server_vm_count,$(".loading").removeClass("pause"),a.statusButton="btn-info",a.info="KloudBuster is Creating VM(s)"+a.pointNum()):"STAGED"===a.status?(a.runButton="Run Test",a.runStatus=!1,a.setStatus=!1,a.stageButton="Unstage",a.setUnstage=!1,a.client_vm_count=a.config.server.routers_per_tenant*a.config.server.networks_per_router*a.config.server.vms_per_network*a.config.server.number_tenants,a.server_vm_count=a.client_vm_count,$(".loading").addClass("pause"),a.statusButton="btn-success",a.info=""):"RUNNING"===a.status?(a.runButton="Stop Test",a.runStatus=!1,a.setStatus=!0,a.stageButton="Unstage",a.setUnstage=!0,a.getSeqReport(),a.client_vm_count=a.config.server.routers_per_tenant*a.config.server.networks_per_router*a.config.server.vms_per_network*a.config.server.number_tenants,a.server_vm_count=a.client_vm_count,$(".loading").removeClass("pause"),a.statusButton="btn-info",a.info="KloudBuster is Running"+a.pointNum()):"ERROR"===a.status?(a.runButton="Run Test",a.runStatus=!0,a.setStatus=!0,a.stageButton="Unstage",a.setUnstage=!1,a.client_vm_count=a.config.server.routers_per_tenant*a.config.server.networks_per_router*a.config.server.vms_per_network*a.config.server.number_tenants,a.server_vm_count=a.client_vm_count,$(".loading").addClass("pause"),a.statusButton="btn-danger",a.info=""):"CLEANING"!==a.status&&"STOPPING"!==a.status||(a.runButton="Run Test",a.runStatus=!0,a.setStatus=!0,a.stageButton="Unstage",a.setUnstage=!0,a.client_vm_count=a.config.server.routers_per_tenant*a.config.server.networks_per_router*a.config.server.vms_per_network*a.config.server.number_tenants,a.server_vm_count=a.client_vm_count,$(".loading").removeClass("pause"),a.statusButton="btn-info",a.info="Please Wait"+a.pointNum())},function(a){console.log("get status error:"),console.log(a)}):a.status="NO SESSION ID"},a.checkStatus(),a.setStage=function(){c.postMethod("/kloudbuster/stage/"+a.sessionID).then(function(a){},function(a){console.log("set stage error:"),console.log(a),f.showAlert("Unable to stage resources!")})},a.CleanUp=function(){a.initChart(),!a.sessionID||"ERROR"!==a.status&&"STAGED"!==a.status?console.log("Cannot cleanup!"):c.postMethod("/kloudbuster/cleanup/"+a.sessionID).then(function(b){a.checkStatus()},function(a){console.log("clean error:"),console.log(a)})},a.stage=function(){if("ERROR"===a.status||"STAGED"===a.status)a.CleanUp();else if("READY"===a.status){var b=a.setConfig(1);b.then(function(){a.setStage()})}},a.runKb=function(){c.postMethod("/kloudbuster/run_test/"+a.sessionID).then(function(a){},function(a){console.log("running error:"),console.log(a),f.showAlert("Unable to start test!")})},a.stopKb=function(){c.postMethod("/kloudbuster/stop_test/"+a.sessionID).then(function(a){},function(a){console.log("stop error:"),console.log(a),f.showAlert("Unable to stop test!")})},a.scaleTest=function(){if("RUNNING"===a.status)a.stopKb();else{var b=a.setConfig(1);b.then(function(){"STAGED"===a.status&&(a.config.client.progression.enabled===!0?f.showAlert("Can't Run Monitor Test Now! You have chosen Progression Test. Clean Up First!"):0===a.config.client.http_tool_configs.report_interval?f.showAlert("Can't Run Monitor Test Now! Report interval must be a number no less than 1."):(a.initChart(),a.runKb()))})}},a.data=[{x:new Date}],a.isDely=!1;var o=0;a.initChart=function(){a.data=[{x:new Date}],a.isDely=!1,o=0,h.setResult("")},a.options={axes:{x:{type:"date"},y:{type:"log",ticksFormat:"d",innerTicks:!0,grid:!0}},series:[{y:"val_6",label:"99.999%",type:"area",color:"#2e4174",dotSize:"0",thickness:"2px",visible:!1},{y:"val_5",label:"99.99%",type:"area",color:"#084594",dotSize:"0",thickness:"2px",visible:!1},{y:"val_4",label:"99.9%",type:"area",color:"#0074D9",dotSize:"0",thickness:"2px"},{y:"val_3",label:"99%",type:"area",color:"#79afe1",dotSize:"0",thickness:"2px"},{y:"val_2",label:"90%",type:"area",color:"#9ecae1",dotSize:"0",thickness:"2px"},{y:"val_1",label:"75%",type:"area",color:"#c6dbef",dotSize:"0",thickness:"2px",visible:!1},{y:"val_0",label:"50%",type:"area",color:"#eff3ff",dotSize:"0",thickness:"2px"}],tooltip:{mode:"scrubber",formatter:function(a,b,c){return c.label+":"+b}},tension:.9,lineMode:"cardinal"},a.data.forEach(function(a){a.x=new Date(a.x)}),a.getSeqReport=function(){c.getMethod2("/kloudbuster/report/"+a.sessionID).then(function(b){a.result=b.data.report,a.seq=b.data.seq,console.log("get seq report:"+a.seq),a.seq&&a.seq>o&&(o=a.seq,a.data.length>40&&a.data.shift(),a.pushChartData("SEQ_"+a.seq,a.result))},function(a){console.log("get seq report error:"),console.log(a)})},a.pushChartData=function(b,c){a.isDely===!1&&(a.data.shift(),a.isDely=!0),a.data.push({x:new Date,val_0:c.latency_stats[0][1]/1e3,val_1:c.latency_stats[1][1]/1e3,val_2:c.latency_stats[2][1]/1e3,val_3:c.latency_stats[3][1]/1e3,val_4:c.latency_stats[4][1]/1e3,val_5:c.latency_stats[5][1]/1e3,val_6:c.latency_stats[6][1]/1e3}),h.setResult(a.data)},h.getResult()&&(a.data=h.getResult()),a.saveResult=function(){var a=new Date,b=k(a.getMonth()+1),c=k(a.getDate()),d=k(a.getHours()),e=k(a.getMinutes()),g=""+b+c+d+e+".html";if(console.log(g),console.log(h.getResult()),""!=h.getResult()){var i='<!--Copyright 2015 Cisco Systems, Inc. All rights reserved.--> <!--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.--> <!DOCTYPE html> <html lang="en-US" ng-app="app"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>KloudBuster Report</title> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.min.js"></script> <script src="https://d3js.org/d3.v3.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/line-chart/2.0.3/LineChart.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/line-chart/2.0.3/LineChart.min.css"> <link rel="stylesheet" href="https://bootswatch.com/flatly/bootstrap.min.css"> <script src="https://code.jquery.com/jquery-2.2.0.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script> <style rel="stylesheet"> .hidden { display: inline !important; } .label { padding: 0; font-size: 110%; font-weight: normal; line-height: 16; color: #000000; text-align: center; } .chart .area-series { opacity: .9; } </style> </head> <body ng-controller="MainCtrl"> <nav class="navbar navbar-default"> <div class="container-fluid"> <div class="navbar-header"> <a class="navbar-brand" href="#">KloudBuster Report</a> </div> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav navbar-right"> <li><a href="#">'+b+"-"+c+" "+d+":"+e+'</a></li> </ul> </div> </div> </nav> <div class="container"> <div class="my-chart" style="height: 500px;margin-bottom: 10%"> <linechart data="data" options="options"></linechart> </div> </div> <script type="text/javascript"> angular.module("app", ["n3-line-chart"]).controller("MainCtrl", function ($scope) { $scope.result ='+JSON.stringify(h.getResult())+'; var x; for(x in $scope.result) { $scope.result[x]["x"]=new Date($scope.result[x]["x"]); } $scope.data = {dataset0: $scope.result}; $scope.options = { series: [ {axis: "y", dataset: "dataset0",interpolation: {mode: "cardinal", tension: 0.7}, key: "val_6",id: "val_6",label: "99.999%", type: ["line", "area"],color: "#222222"}, {axis: "y", dataset: "dataset0",interpolation: {mode: "cardinal", tension: 0.7}, key: "val_5",id: "val_5",label: "99.99%", type: ["line", "area"], color: "#084594"}, {axis: "y", dataset: "dataset0",interpolation: {mode: "cardinal", tension: 0.7}, key: "val_4",id: "val_4",label: "99.9%", type: ["line", "area"],color: "#0074D9"}, {axis: "y", dataset: "dataset0",interpolation: {mode: "cardinal", tension: 0.7}, key: "val_3",id: "val_3",label: "99%", type: ["line", "area"], color: "#79afe1"}, {axis: "y", dataset: "dataset0",interpolation: {mode: "cardinal", tension: 0.7}, key: "val_2",id: "val_2",label: "90%", type: ["line", "area"], color: "#9ecae1"}, {axis: "y", dataset: "dataset0",interpolation: {mode: "cardinal", tension: 0.7}, key: "val_1",id: "val_1",label: "75%", type: ["line", "area"], color: "#c6dbef"}, {axis: "y", dataset: "dataset0",interpolation: {mode: "cardinal", tension: 0.7}, key: "val_0",id: "val_0",label: "50%", type: ["line", "area"], color: "#eff3ff"} ], axes: { x: { key: "x", type: "date" }, y: { key:"y",type: "log", ticksFormat: "d", ticks: 10, tickFormat: function (value, index) { return value; } } }, margin: {top: 20, right: 30, bottom: 20, left: 30}, grid: {x: false, y: true} }; }); </script> </body> </html>';j(g,i)}else f.showAlert("No result to save!")},setInterval(function(){a.checkStatus()},900)}]).service("monitorMode",function(){var a="";this.getResult=function(){return a},this.setResult=function(b){return a=b}}),angular.module("kbWebApp").controller("LoginCtrl",["$scope","$http","$location","showAlert","$q","kbHttp","kbCookie","locationChange",function(a,b,c,d,e,f,g,h){function i(a){var b=a.target.files,c=b[0],d=new FileReader;d.onload=function(){l=this.result},d.readAsText(c)}function j(a){var b=a.target.files,c=b[0],d=new FileReader;d.onload=function(){m=this.result},d.readAsText(c)}if(this.awesomeThings=["HTML5 Boilerplate","AngularJS","Karma"],g.checkMode("login"),$(window).on("hashchange",h.change()),function(a,b,c){var d=a.querySelectorAll("html")[0];d.className=d.className.replace(/(^|\s)no-js(\s|$)/,"$1js$2")}(document,window,0),function(a,b,c){var d=a.querySelectorAll(".inputfile");Array.prototype.forEach.call(d,function(a){var b=a.nextElementSibling,c=b.innerHTML;a.addEventListener("change",function(a){var d="";d=a.target.value.split("\\").pop(),d?b.querySelector("span").innerHTML=d:b.innerHTML=c}),a.addEventListener("focus",function(){a.classList.add("has-focus")}),a.addEventListener("blur",function(){a.classList.remove("has-focus")})})}(document,window,0),a.deleteSession=function(){f.delMethod("/config/running_config/"+a.sessionID).then(function(a){console.log("del sessionID")},function(a){})},a.CleanUp=function(){var b=e.defer();return"READY"!=g.getStatus()&&"CLEANING"!=g.getStatus()?(f.postMethod("/kloudbuster/cleanup/"+a.sessionID).then(function(a){console.log("clean up successfully")},function(a){}),b.resolve(1)):b.resolve(1),b.promise},""!=g.getSessionID()){a.sessionID=g.getSessionID();var k=a.CleanUp();k.then(function(){a.deleteSession(),g.init()})}a.samecloud=!0,a.clouds=function(){a.samecloud===!0?($("#inputPassword2").attr("disabled",!0),$("#file2").attr("disabled",!0),$("#rcfile2").attr("disabled",!0)):($("#inputPassword2").attr("disabled",!1),$("#file2").attr("disabled",!1),$("#rcfile2").attr("disabled",!1))};var l;document.getElementById("file1").addEventListener("change",i,!1);var m;document.getElementById("file2").addEventListener("change",j,!1),$("#inputPassword1").keydown(function(b){var c=b.which;13==c&&a.setConfig()}),$("#inputPassword2").keydown(function(b){var c=b.which;13==c&&a.setConfig()}),a.setConfig=function(){"storage"==a.mode?(g.setIsOneCloud(!0),a.credentials={"tested-passwd":a.inputPassword1,"tested-rc":l},a.storage_mode=!0):(a.storage_mode=!1,a.samecloud===!0?(g.setIsOneCloud(!0),a.credentials={"tested-passwd":a.inputPassword1,"tested-rc":l}):(g.setIsOneCloud(!1),a.credentials={"tested-passwd":a.inputPassword1,"tested-rc":l,"testing-passwd":inputPassword2,"testing-rc":m})),a.runCon={credentials:{},kb_cfg:"",storage_mode:a.storage_mode},a.runCon.credentials=a.credentials,g.setCredentials(a.credentials),g.setMode(a.mode),f.postMethod("/config/running_config",a.runCon).then(function(b){g.setSessionID(b.data),a.sessionID=g.getSessionID(),console.log("set config & get sesID:"+a.sessionID),"storage"==a.mode?c.path("/StorageMode"):c.path("/InteractiveMode")},function(a){400==a.status?d.showAlert("Error while parsing configurations! Please check your inputs!"):-1==a.status&&d.showAlert("Error while connecting kloudbuster server!")})}}]),angular.module("kbWebApp").controller("StorageConfigCtrl",["$scope","$http","$location","showAlert","kbHttp","kbCookie","locationChange",function(a,b,c,d,e,f,g){this.awesomeThings=["HTML5 Boilerplate","AngularJS","Karma"],""===f.getSessionID()?c.path("/Login"):f.checkMode("storage"),$(window).on("hashchange",g.change()),a.sessionID=f.getSessionID(),a.status=f.getStatus(),a.dash1status1="active",a.dash1status1vis=!0,a.dash1status2="",a.dash1status2vis=!1,a.setDash1Status=function(b){1===b?(a.dash1status2="",a.dash1status2vis=!1,a.dash1status1="active",a.dash1status1vis=!0):2===b&&(a.dash1status1="",a.dash1status1vis=!1,a.dash1status2="active",a.dash1status2vis=!0)},a.parseInt=parseInt,a.checkStatus=function(){a.sessionID?e.getMethod2("/kloudbuster/status/"+a.sessionID).then(function(b){a.status=b.data.status,f.setStatus(a.status),a.configStatus()},function(a){console.log("status error")}):(a.status="NO SESSION ID",f.setStatus(""))};var h=!1;a.disableConfig=function(a){$("#"+a).find("input,button,a").each(function(){$(this).attr("disabled","disabled"),console.log(this)})},a.enableConfig=function(a){$("#"+a).find("input,button,a").each(function(){$(this).removeAttr("disabled")})},a.configStatus=function(){"READY"===a.status?h===!0&&(h=!1,a.enableConfig("stagingConfig3"),a.enableConfig("getButton")):h===!1&&(h=!0,a.disableConfig("stagingConfig3"),a.disableConfig("getButton"))},$("#dropdownrandrw").append('<li class="divider"></li>'),a.storageMode={randread:{name:"Random Read",type:"panel-randread",para:["description","rate_iops","block_size","iodepth","runtime","extra_opts"]},randwrite:{name:"Random Write",type:"panel-randwrite",para:["description","rate_iops","block_size","iodepth","runtime","extra_opts"]},randrw:{name:"Random Read/Write",type:"panel-randrw",para:["description","rate_iops","block_size","iodepth","rwmixread","runtime","extra_opts"]},read:{name:"Seq Read",type:"panel-read",para:["description","rate","block_size","iodepth","runtime","extra_opts"]},write:{name:"Seq Write",type:"panel-write",para:["description","rate","block_size","iodepth","runtime","extra_opts"]},rw:{name:"Seq Read/Write",type:"panel-rw",para:["description","rate","block_size","iodepth","rwmixread","runtime","extra_opts"]}},a.options={description:{name:"Description","default":""},mode:{name:"Mode"},runtime:{name:"Run Time","default":30},block_size:{name:"Block Size (KB)","default":"4k"},iodepth:{name:"IO Depth","default":1},rate_iops:{name:"IOPs","default":100},rate:{name:"BW (MB/s)","default":"60M"},rwmixread:{name:"Read %","default":70},extra_opts:{name:"Extra Options","default":""}},a.switchIndex=function(b,c){var d=a.config.client.storage_tool_configs[b];a.config.client.storage_tool_configs.splice(b,1),1==c?a.config.client.storage_tool_configs.splice(b-1,0,d):-1==c&&a.config.client.storage_tool_configs.splice(b+1,0,d)},a.addMode=function(b){var c={};for(var d in a.storageMode[b].para){var e=a.storageMode[b].para[d];c[e]=a.options[e]["default"]}c.mode=b,a.config.client.storage_tool_configs.splice(0,0,c)},a.getDefaultConfig=function(){e.getMethod("/config/default_config").then(function(b){f.setConfig(b.data),a.config=b.data,0==a.config.client.flavor.disk?a.choose_disk_size=0:a.choose_disk_size=1,console.log("get & save default config")},function(a){d.showAlert("Cannot get the Default Configuration!")})},a.getRunConfig=function(){e.getMethod("/config/running_config/"+a.sessionID).then(function(b){f.setConfig(b.data),a.config=b.data,0==a.config.client.flavor.disk?a.choose_disk_size=0:a.choose_disk_size=1,a.checkStatus(),console.log("get & save running config")},function(a){console.log("get running config error:"),console.log(a)})},a.getRunConfig(),a.changeConfig=function(){"READY"===a.status||""===a.status?1==a.server.$valid&&1==a.general.$valid?(f.setConfig(a.config),a.chaCon={kb_cfg:{},topo_cfg:{}},a.chaCon.kb_cfg=f.getConfig(),f.setTopology({servers_rack:"",clients_rack:""}),a.chaCon.topo_cfg=f.getTopology(),a.config.server.availability_zone="",a.config.client.availability_zone="",console.log(a.chaCon),e.putMethod("/config/running_config/"+a.sessionID,a.chaCon).then(function(a){console.log("change running config")},function(a){d.showAlert("Failed to update configuration!")})):d.showAlert("Please check your inputs!"):d.showAlert("Configuration cannot be changed now!")}}]),angular.module("kbWebApp").controller("RunStorageCtrl",["$scope","$timeout","$location","$http","$q","showAlert","ngTableParams","kbCookie","kbHttp","storageMode","color","locationChange",function(a,b,c,d,e,f,g,h,i,j,k,l){function m(a){var b=Number.POSITIVE_INFINITY;return a.forEach(function(a){a.forEach(function(a){"write_hist"in a&&(b=Math.min(b,a.write_hist[0][1])),"read_hist"in a&&(b=Math.min(b,a.read_hist[0][1]))})}),b}function n(a,b){var c=document.createElement("a"),d=new Blob([b]),e=document.createEvent("HTMLEvents");e.initEvent("click",!1,!1),c.download=a,c.href=URL.createObjectURL(d),c.dispatchEvent(e)}function o(a){return 10>a?"0"+a:99>a?""+a:-1}this.awesomeThings=["HTML5 Boilerplate","AngularJS","Karma"],""===h.getSessionID()?c.path("/Login"):h.checkMode("storage"),$(window).on("hashchange",l.change()),$("[data-toggle='.container']").click(function(){var a=$(this).data("toggle");$(a).toggleClass("open-sidebar"),$("#littleglyph").toggleClass("glyphicon-triangle-right"),$("#littleglyph").toggleClass("glyphicon-triangle-left")}),$(".swipe-area").swipe({swipeStatus:function(a,b,c,d,e,f){return"move"==b&&"right"==c?($(".container").addClass("open-sidebar"),!1):"move"==b&&"left"==c?($(".container").removeClass("open-sidebar"),!1):void 0}}),a.oneAtATime=!1,a.status1={isFirstOpen:!0,isFirstDisabled:!1},a.status2={isFirstOpen:!0,isFirstDisabled:!1},a.status1.open=!0,a.status2.open=!0,a.sessionID=h.getSessionID(),a.status=h.getStatus(),a.getRunConfig=function(){i.getMethod("/config/running_config/"+a.sessionID).then(function(b){a.config=b.data,h.setConfig(b.data),a.current_mode_name=a.config.client.storage_tool_configs[0].mode,a.current_mode_description=a.config.client.storage_tool_configs[0].description,a.getCurrentMode(a.current_mode_name,"read"),console.log("get & save config")},function(a){console.log("get running config error:"),console.log(a)})},a.sessionID&&!a.config&&a.getRunConfig(),a.setConfig=function(b){var c=e.defer();return"READY"===a.status?(h.setConfig(a.config),a.chaCon={kb_cfg:{}},a.chaCon.kb_cfg=h.getConfig(),i.putMethod("/config/running_config/"+a.sessionID,a.chaCon).then(function(a){console.log("change running config"),c.resolve(1)},function(a){c.reject(0),1!=b&&(400==a.status?f.showAlert("Error while parsing configurations! Please check your inputs!"):403==a.status?f.showAlert("Cannot update configuration if KloudBuster is busy or in error state"):-1==a.status&&f.showAlert("Error while connecting kloudbuster server!"))})):"STAGED"===a.status?(a.config.client.http_tool_configs.report_interval=0,h.setConfig(a.config),a.chaCon={kb_cfg:{client:{http_tool_configs:{duration:a.config.client.http_tool_configs.duration,rate_limit:a.config.client.http_tool_configs.rate_limit,connections:a.config.client.http_tool_configs.connections,report_interval:0}}}},i.putMethod("/config/running_config/"+a.sessionID,a.chaCon).then(function(a){console.log("change running config"),c.resolve(1)},function(a){c.reject(0),1!=b&&(400==a.status?f.showAlert("Error while parsing configurations! Please check your inputs!"):403==a.status?f.showAlert("Cannot update configuration if KloudBuster is busy or in error state"):-1==a.status&&f.showAlert("Error while connecting kloudbuster server!"))})):(console.log("config not allow to change now!"),c.reject(0)),c.promise};var p=!1,q=!1;a.disableConfig=function(a){$("#"+a).find("input").each(function(){$(this).attr("disabled","disabled")})},a.enableConfig=function(a){$("#"+a).find("input").each(function(){$(this).removeAttr("disabled")})},a.configStatus=function(){"READY"===a.status?(p===!0&&(p=!1,a.enableConfig("stagingConfig"),a.enableConfig("stagingConfig1"),$("#client_progression_enabled").removeAttr("disabled"),$("#client_progression_vm_start").removeAttr("disabled")),q===!0&&(q=!1,a.enableConfig("runningConfig"))):"STAGED"===a.status?(p===!1&&(p=!0,a.disableConfig("stagingConfig"),a.disableConfig("stagingConfig1"),$("#client_progression_enabled").attr("disabled","disabled"),$("#client_progression_vm_start").attr("disabled","disabled")),q===!0&&(q=!1,a.enableConfig("runningConfig"))):(p===!1&&(p=!0,a.disableConfig("stagingConfig"),a.disableConfig("stagingConfig1"),$("md-checkbox").attr("disabled","disabled")),q===!1&&(q=!0,a.disableConfig("runningConfig")))};var r=0;a.pointNum=function(){var a=".";r=(r+1)%6;for(var b=0;r>b;b++)a+=" .";return a},a.runButton="Run Test",a.runStatus=!0,a.setStatus=!1,a.stageButton="Stage",a.setUnstage=!0,a.client_vm_count=0,a.server_vm_count=0,a.statusButton="btn-default",a.checkStatus=function(){a.sessionID?i.getMethod2("/kloudbuster/status/"+a.sessionID).then(function(b){a.status=b.data.status,h.setStatus(a.status),a.configStatus(),"READY"===a.status?(a.runButton="Run Test",a.runStatus=!0,a.setStatus=!1,a.stageButton="Stage",a.setUnstage=!1,a.client_vm_count=0,$(".loading").addClass("pause"),a.statusButton="btn-success",a.info=""):"STAGING"===a.status?(a.runButton="Run Test",a.runStatus=!0,a.setStatus=!0,a.stageButton="Stage",a.setUnstage=!0,a.client_vm_count=b.data.client_vm_count,$(".loading").removeClass("pause"),a.statusButton="btn-info",a.info="KloudBuster is Creating VM(s)"+a.pointNum()):"STAGED"===a.status?(a.runButton="Run Test",a.runStatus=!1,a.setStatus=!1,a.stageButton="Unstage",a.setUnstage=!1,a.client_vm_count=a.config.server.routers_per_tenant*a.config.server.networks_per_router*a.config.server.vms_per_network*a.config.server.number_tenants,a.getReport(),$(".loading").addClass("pause"),a.statusButton="btn-success",a.info=""):"RUNNING"===a.status?(a.runButton="Stop Test",a.runStatus=!1,a.setStatus=!0,a.stageButton="Unstage",a.setUnstage=!0,a.client_vm_count=a.config.server.routers_per_tenant*a.config.server.networks_per_router*a.config.server.vms_per_network*a.config.server.number_tenants,a.config.client.progression.enabled===!0&&a.getReport(),$(".loading").removeClass("pause"),a.statusButton="btn-info",a.info="KloudBuster is Running"+a.pointNum()):"ERROR"===a.status?(a.runButton="Run Test",a.runStatus=!0,a.setStatus=!0,a.stageButton="Unstage",a.setUnstage=!1,a.client_vm_count=a.config.server.routers_per_tenant*a.config.server.networks_per_router*a.config.server.vms_per_network*a.config.server.number_tenants,$(".loading").addClass("pause"),a.statusButton="btn-danger",a.info=""):"CLEANING"!==a.status&&"STOPPING"!==a.status||(a.runButton="Run Test",a.runStatus=!0,a.setStatus=!0,a.stageButton="Unstage",a.setUnstage=!0,a.client_vm_count=a.config.server.routers_per_tenant*a.config.server.networks_per_router*a.config.server.vms_per_network*a.config.server.number_tenants,$(".loading").removeClass("pause"),a.statusButton="btn-info",a.info="Please Wait"+a.pointNum())},function(a){console.log("get status error:"),console.log(a)}):(a.status="NO SESSION ID",h.setStatus(""))},a.checkStatus(),a.setStage=function(){i.postMethod("/kloudbuster/stage/"+a.sessionID).then(function(a){},function(a){console.log("set stage error:"),console.log(a),f.showAlert("Unable to stage resources!")})},a.CleanUp=function(){a.initChart(),!a.sessionID||"ERROR"!==a.status&&"STAGED"!==a.status?console.log("Cannot cleanup!"):i.postMethod("/kloudbuster/cleanup/"+a.sessionID).then(function(b){a.checkStatus()},function(a){console.log("clean error:"),console.log(a)})},a.stage=function(){if("ERROR"===a.status||"STAGED"===a.status)a.CleanUp();else if("READY"===a.status){var b=a.setConfig(1);b.then(function(){a.setStage()})}},a.runKb=function(){i.postMethod("/kloudbuster/run_test/"+a.sessionID).then(function(a){},function(a){console.log("running error:"),console.log(a),f.showAlert("Unable to start test!")})},a.stopKb=function(){i.postMethod("/kloudbuster/stop_test/"+a.sessionID).then(function(a){},function(a){console.log("stop error:"),console.log(a),f.showAlert("Unable to stop test!")})},a.scaleTest=function(){if("RUNNING"===a.status)a.stopKb();else if("STAGED"===a.status){var b=a.setConfig(1);b.then(function(){a.initChart(),a.runKb()})}},a.modes={randread:{name:"randread",title:"Rand Read",group:["rand","read"],y_axis:"IOPs/VM",y_label:"RATE IOPs Per VM"},randwrite:{name:"randwrite",title:"Rand Write",group:["rand","write"],y_axis:"IOPs/VM",y_label:"RATE IOPs Per VM"},read:{name:"read",title:"Seq Read",group:["seq","read"],y_axis:"BW/VM(KB/s)",y_label:"RATE BW Per VM"},write:{name:"write",title:"Seq Write",group:["seq","write"],y_axis:"BW/VM(KB/s)",y_label:"RATE BW Per VM"},randrw:{name:"randrw",title:"Rand Read/Write",span:"caret",group:["rand","mix"],y_axis:"IOPs/VM",y_label:"RATE IOPs Per VM"},rw:{name:"rw",title:"Seq Read/Write",
span:"caret",group:["seq","mix"],y_axis:"BW/VM(KB/s)",y_label:"RATE BW Per VM"}},a.current_index=0,a.getCurrentMode=function(b,c,d){"rw"==b?(""==c&&(c="read"),a.current_mode=a.modes[c],"read"==c?a.current_title="- "+d+"% Read":a.current_title="- "+(100-d)+"% Write"):"randrw"==b?(""==c&&(c="read"),a.current_mode=a.modes["rand"+c],"read"==c?a.current_title="- "+d+"% Read":a.current_title="- "+(100-d)+"% Write"):(a.current_mode=a.modes[a.current_mode_name],a.current_title="")},(a.config=h.getConfig())&&(a.current_mode_name=a.config.client.storage_tool_configs[0].mode,a.current_mode_description=a.config.client.storage_tool_configs[0].description,a.getCurrentMode(a.current_mode_name,"read")),a.handleEvent=function(b,c,d){a.current_index=c,a.current_mode_name=a.config.client.storage_tool_configs[c].mode,a.current_mode_description=a.config.client.storage_tool_configs[c].description,a.getCurrentMode(a.current_mode_name,d,a.config.client.storage_tool_configs[c].rwmixread),a.refreshChart(),j.getResult().length>0&&a.draw(j.getResult())},a.tabledata=[],a.cols=[{field:"seq",title:"SEQ",sortable:"seq",show:!0},{field:"mode",title:"Mode",sortable:"mode",show:!0},{field:"total_client_vms",title:"Client VMs",sortable:"total_client_vms",show:!0},{field:"block_size",title:"Block Size",sortable:"block_size",show:!0},{field:"iodepth",title:"IO Depth",sortable:"iodepth",show:!0},{field:"rate_iops",title:"Requested IOPS",sortable:"rate_iops",show:!0},{field:"read_iops",title:"Read IOPS",sortable:"read_iops",show:!0},{field:"write_iops",title:"Write IOPS",sortable:"write_iops",show:!0},{field:"rate",title:"Requested BW",sortable:"rate",show:!0},{field:"read_bw",title:"Read BW",sortable:"read_bw",show:!0},{field:"write_bw",title:"Write BW",sortable:"write_bw",show:!0}],a.tableParams=new g({sorting:{name:"asc"},count:10},{counts:[],data:a.tabledata}),a.options={series:[{y:"IOPS",color:"#F44336",type:"column",striped:!0,label:"RATE IOPS/BW PER VM"},{y:"requested_rate",color:"#696969",drawDots:!1,thickness:"1px",label:"Requested Rate",lineMode:"dashed"},{y:"latency1",axis:"y2",color:"#673AB7",drawDots:!0,dotSize:4,thickness:"3px",label:"Latency(ms)--90%"},{y:"latency2",axis:"y2",color:"#03A9F4",drawDots:!0,dotSize:4,thickness:"3px",label:"Latency(ms)--99%"},{y:"latency3",axis:"y2",color:"#E91E63",drawDots:!0,dotSize:4,thickness:"3px",label:"Latency(ms)--99.9%"}],axes:{x:{key:"x",type:"linear",ticks:a.xaxisList,ticksFormatter:function(b){return-1!=$.inArray(b,a.xaxisList)?0==b?"1":b:""}},y:{type:"linear",ticksFormat:"d",innerTicks:!0,min:0},y2:{type:"log",ticksFormat:"d",innerTicks:!1,grid:!0}},tooltip:{mode:"scrubber",formatter:function(a,b,c){return c.label+":"+b}},tension:.8,lineMode:"cardinal",columnsHGap:45},a.initChart=function(){a.data=[],a.isDely=!1,a.tabledata.length=0,a.tableParams.reload(),a.isDely=!1,s=0,k.reset(),j.setResult([])};var s=0;a.initChart(),a.refreshChart=function(){a.data=[],a.isDely=!1,a.tabledata.length=0,a.tableParams.reload(),k.reset()},a.getReport=function(){i.getMethod2("/kloudbuster/report/"+a.sessionID+"?final=true").then(function(b){b.data.kb_result.length>0&&s<b.data.kb_result.length&&(console.log("get report totally:"+b.data.kb_result.length),s=b.data.kb_result.length,j.setResult(b.data),a.refreshChart(),a.draw(b.data))},function(a){console.log("get report error:"),console.log(a)})},a.draw=function(b){a.results=b.kb_result;var c,d=a.results.length,e=a.results[0].length,f=a.current_mode.name;a.xaxisList=[];for(var g=0;d>g;g++)for(var h=0;e>h;h++)if(a.perrow=a.results[g][h],a.perrow.mode==a.current_mode_name&&a.perrow.description==a.current_mode_description){1==a.perrow.total_client_vms&&1!=d?a.xaxis=0:a.xaxis=a.perrow.total_client_vms,a.xaxisList.push(a.xaxis),"randread"==f&&(a.data.push({x:a.xaxis,IOPS:a.perrow.read_iops/a.perrow.total_client_vms,latency1:a.perrow.read_hist[2][1]/1e3,latency2:a.perrow.read_hist[3][1]/1e3,latency3:a.perrow.read_hist[4][1]/1e3,requested_rate:a.perrow.rate_iops/a.perrow.total_client_vms}),c=a.perrow.rate_iops/a.perrow.total_client_vms),"randwrite"==f&&(a.data.push({x:a.xaxis,IOPS:a.perrow.write_iops/a.perrow.total_client_vms,latency1:a.perrow.write_hist[2][1]/1e3,latency2:a.perrow.write_hist[3][1]/1e3,latency3:a.perrow.write_hist[4][1]/1e3,requested_rate:a.perrow.rate_iops/a.perrow.total_client_vms}),c=a.perrow.rate_iops/a.perrow.total_client_vms),"read"==f&&(a.data.push({x:a.xaxis,IOPS:a.perrow.read_bw/a.perrow.total_client_vms,latency1:a.perrow.read_hist[2][1]/1e3,latency2:a.perrow.read_hist[3][1]/1e3,latency3:a.perrow.read_hist[4][1]/1e3,requested_rate:a.perrow.rate/a.perrow.total_client_vms}),c=a.perrow.rate/a.perrow.total_client_vms),"write"==f&&(a.data.push({x:a.xaxis,IOPS:a.perrow.write_bw/a.perrow.total_client_vms,latency1:a.perrow.write_hist[2][1]/1e3,latency2:a.perrow.write_hist[3][1]/1e3,latency3:a.perrow.write_hist[4][1]/1e3,requested_rate:a.perrow.rate/a.perrow.total_client_vms}),c=a.perrow.rate/a.perrow.total_client_vms);var i=k.getColor(),j="mode-"+a.perrow.mode+"_VM-"+a.perrow.total_client_vms;a.pushTableData(j,a.perrow,i)}a.options.axes.y.max=1.0005*c,a.options.axes.y2.min=m(a.results)/1e3,a.options.series[0].label=a.current_mode.y_label},a.pushChartData=function(b,c,d){a.isDely===!1&&(a.options.series.shift(),a.isDely=!0),a.options.series.push({y:b,label:b,color:d,dotSize:"3",thickness:"2px"});for(var e=0;7>e;e++)a.data[e][b]=c.latency_stats[e][1]/1e3},a.pushTableData=function(b,c,d){a.tabledata.push({seq:b,mode:c.mode,total_client_vms:c.total_client_vms,block_size:c.block_size,iodepth:c.iodepth,rate_iops:c.rate_iops,read_bw:c.read_bw,write_bw:c.write_bw,read_iops:c.read_iops,write_iops:c.write_iops,rate:c.rate,color:d}),a.tableParams.reload()},a.saveResult=function(){var a=new Date,b=o(a.getMonth()+1),c=o(a.getDate()),d=o(a.getHours()),e=o(a.getMinutes()),g=""+b+c+d+e+".html",i=j.getResult();if(""!=i){var k='<!--Copyright 2016 Cisco Systems, Inc. All rights reserved.--> <!--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.--> <!DOCTYPE html> <html lang="en-US" ng-app="app"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>KloudBuster Report</title> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.min.js"></script> <script src="https://d3js.org/d3.v3.min.js"></script> <!--<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/line-chart/2.0.3/LineChart.min.css">--> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ng-table/0.8.3/ng-table.min.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/ng-table/0.8.3/ng-table.min.js"></script> <link rel="stylesheet" href="https://bootswatch.com/flatly/bootstrap.min.css"> <script src="https://code.jquery.com/jquery-2.2.0.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/line-chart/1.1.12/line-chart.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script> </head> <body ng-controller="MainCtrl"> <nav class="navbar navbar-default"> <div class="container-fluid"> <a class="navbar-brand" ng-href="#/" style="font-family: Arial"> <span style="color:#DF314D">K</span>loudBuster </a> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav" ng-init="tab=0"> <li ng-class="{active:tab==0}" ng-click="tab=0"> <a><span class="glyphicon" aria-hidden="true" ></span>Report</a> </li> <li ng-class="{active:tab==1}" ng-click="tab=1" ng-show="config == true"> <a><span class="glyphicon" aria-hidden="true" ></span>Configuration</a> </li> </ul> <!--<ul class="nav navbar-nav navbar-right">--> <!--<li><a href="#"></a></li>--> <!--</ul>--> </div> </div> </nav> <div class="container" ng-show="tab == 0"> <h3>KloudBuster Storage Testing Report</h3> <ul class="nav nav-tabs"> <li ng-repeat="title in titleList" ng-class="{active: current_index==$index}" ng-click="handleEvent($event, $index,\'\')"> <a data-toggle="tab" aria-expanded="true"> {{title["description"]}} <span class="{{modes[title[\'mode\']][\'span\']}}"></span> </a> </li> </ul> <ul class="nav nav-tabs" style="margin-top: 5px" ng-style="{height:current_mode_name ==\'rw\' || current_mode_name ==\'randrw\'?\'\':0, width:current_mode_name ==\'rw\' || current_mode_name ==\'randrw\'?\'30%\':0}"> <li ng-show="current_mode_name ==\'rw\' || current_mode_name ==\'randrw\'" ng-class="{active:current_mode[\'name\']==\'read\' || current_mode[\'name\']==\'randread\'}"> <a ng-click="handleEvent($event, current_index,\'read\')">Read</a> </li> <li ng-show="current_mode_name ==\'rw\' || current_mode_name ==\'randrw\'" ng-class="{active:current_mode[\'name\']==\'write\' || current_mode[\'name\']==\'randwrite\'}"> <a ng-click="handleEvent($event, current_index,\'write\')">Write</a> </li> </ul> <h4 style="text-align: center"> {{current_mode_description}}</h4> <h5 style="text-align: center">{{modes[current_mode_name]["title"]}} {{current_title}} ({{storage_target[from_outside.storage_target]}})</h5> <div class="my-chart" style="height: 550px;margin-bottom: 5%"> <h6 style="margin-bottom:0"><span>{{current_mode["y_axis"]}}</span><span style="float:right">Latency(ms)</span></h6> <linechart data="data" options="options"></linechart> </div> <table ng-table="tableParams" class="table table-responsive table-condensed table-bordered table-striped"> <tr ng-repeat="row in tableParams.data" style="text-align:center;"> <td title="cols[2].title" data-sortable="cols[2].field">{{row.total_client_vms}}</td> <td title="cols[3].title" data-sortable="cols[3].field">{{row.block_size}}b</td> <td title="cols[4].title" data-sortable="cols[4].field">{{row.iodepth}}</td> <td title="cols[5].title" data-sortable="cols[5].field" ng-if="current_mode.group[0] == \'rand\'"> {{row.rate_iops}} </td> <td title="cols[6].title" data-sortable="cols[6].field" ng-if="current_mode.group[1] == \'read\'"> {{row.read_iops}} </td> <td title="cols[7].title" data-sortable="cols[7].field" ng-if="current_mode.group[1] == \'write\'"> {{row.write_iops}} </td> <td title="cols[8].title" data-sortable="cols[8].field" ng-if="current_mode.group[0] == \'seq\'"> {{row.rate}} KB/s </td> <td title="cols[9].title" data-sortable="cols[9].field" ng-if="current_mode.group[1] == \'read\'"> {{row.read_bw}} KB/s </td> <td title="cols[10].title" data-sortable="cols[10].field" ng-if="current_mode.group[1] == \'write\'"> {{row.write_bw}} KB/s </td> </tr> </table> </div> <div class="container" ng-show="tab == 1"> <h3>KloudBuster HTTP Testing Configuration</h3> <div class="panel panel-default"> <div class="panel-body" style="word-wrap:break-word"> <textarea style="width: 100%;height: 900px" disabled> {{from_outside_config}}</textarea> </div> </div> </div> <footer style="text-align: center;"> <hr style="margin:2px"/> <h6 style="color:gray">{{from_outside["time"]}} - KloudBuster {{from_outside["version"]}}</h6> </footer> <script type="text/javascript"> var num = -1; var colorList = ["#F44336", "#673AB7", "#03A9F4", "#4CAF50", "#FFEB3B", "#BF360C", "#795548", "#E91E63", "#3F51B5", "#00BCD4", "#CDDC39", "#FF9800", "#9E9E9E", "#9C27B0", "#009688"]; var length = colorList.length; function get_color() { num = (num + 1) % length; return colorList[num]; } var modes = { "randread": { name:"randread", title: "Rand Read", group: ["rand", "read"], y_axis: "IOPs/VM", y_label: "RATE IOPs Per VM" }, "randwrite": { name:"randwrite", title: "Rand Write", group: ["rand", "write"], y_axis: "IOPs/VM", y_label: "RATE IOPs Per VM" }, "read": { name:"read", title: "Seq Read", group: ["seq", "read"], y_axis: "BW/VM(KB/s)", y_label: "RATE BW Per VM" }, "write": { name:"write", title: "Seq Write", group: ["seq", "write"], y_axis: "BW/VM(KB/s)", y_label: "RATE BW Per VM" }, "randrw": { name:"randrw", title: "Rand Read/Write", span:"caret", group: ["rand", "mix"], y_axis: "IOPs/VM", y_label: "RATE IOPs Per VM" }, "rw": { name:"rw", title: "Seq Read/Write", span:"caret", group: ["seq", "mix"], y_axis: "BW/VM(KB/s)", y_label: "RATE BW Per VM" } }; var storage_target = {"volume":"Cinder Volume","ephemeral":"Ephemeral Disk"}; angular.module("app", ["n3-line-chart", "ngTable"]).controller("MainCtrl", function ($scope, ngTableParams) { $scope.current_index = 0; $scope.modes = modes; $scope.storage_target = storage_target; if($scope.config = true) $scope.from_outside_config = JSON.stringify('+JSON.stringify(h.getConfig())+', null, " "); $scope.from_outside = '+JSON.stringify(i)+'; content = $scope.from_outside["kb_result"]; $scope.titleList = []; get_title($scope,content); draw_chart($scope, ngTableParams, content); $scope.handleEvent = function(event, index, formix) { $scope.current_index = index; $scope.current_mode_name = $scope.titleList[index]["mode"]; $scope.current_mode_description = $scope.titleList[index]["description"]; getCurrentMode($scope, $scope.current_mode_name, formix, content[0][index]["rwmixread"]); draw_chart($scope, ngTableParams, content); }; }); function get_title($scope, content){ for( var item in content[0]) { $scope.titleList.push({"mode": content[0][item]["mode"], "description": content[0][item]["description"]}); } $scope.current_mode_name = $scope.titleList[0]["mode"]; $scope.current_mode_description = $scope.titleList[0]["description"]; $scope.current_mode = $scope.modes[$scope.current_mode_name]; getCurrentMode($scope, $scope.current_mode_name, "",content[0][0]["rwmixread"]); } function getCurrentMode($scope, modeName, formix, readpct){ if (modeName == "rw"){ if(formix == "") formix="read"; $scope.current_mode = $scope.modes[formix]; if (formix=="read") $scope.current_title = "- " +readpct +"% Read"; else $scope.current_title = "- " +(100-readpct) +"% Write"; } else if (modeName == "randrw"){ if(formix == "") formix="read"; $scope.current_mode = $scope.modes["rand"+formix]; if (formix=="read") $scope.current_title = "- " +readpct +"% Read"; else $scope.current_title = "- " +(100-readpct) +"% Write"; } else{ $scope.current_mode = $scope.modes[$scope.current_mode_name]; $scope.current_title = ""; } } function get_min_hist(results) { var min = Number.POSITIVE_INFINITY; results.forEach(function (rr) { rr.forEach(function (d) { if ("write_hist" in d) { min = Math.min(min, d.write_hist[0][1]); } if ("read_hist" in d) { min = Math.min(min, d.read_hist[0][1]); } }); }); return min; } function draw_chart($scope, ngTableParams, results) { $scope.results = results; var countRep = $scope.results.length; var countRep2 = $scope.results[0].length; var mode = $scope.current_mode["name"]; $scope.tabledata = []; $scope.cols = [ { field: "seq", title: "SEQ", sortable: "seq", show: true }, { field: "mode", title: "Mode", sortable: "mode", show: true }, { field: "total_client_vms", title: "Client VMs", sortable: "total_client_vms", show: true }, { field: "block_size", title: "Block Size", sortable: "block_size", show: true }, { field: "iodepth", title: "IO Depth", sortable: "iodepth", show: true }, { field: "rate_iops", title: "Requested IOPS", sortable: "rate_iops", show: true }, { field: "read_iops", title: "Read IOPS", sortable: "read_iops", show: true }, { field: "write_iops", title: "Write IOPS", sortable: "write_iops", show: true }, { field: "rate", title: "Requested BW", sortable: "rate", show: true }, { field: "read_bw", title: "Read BW", sortable: "read_bw", show: true }, { field: "write_bw", title: "Write BW", sortable: "write_bw", show: true }]; $scope.tableParams = new ngTableParams({sorting: {name: "asc"}, "count": 10}, { counts: [], data: $scope.tabledata }); $scope.pushTableData = function (taName, taData, pickColor) { $scope.tabledata.push({ "seq": taName, "mode": taData.mode, "total_client_vms": taData.total_client_vms, "block_size": taData.block_size, "iodepth": taData.iodepth, "rate_iops": taData.rate_iops, "read_bw": taData.read_bw, "write_bw": taData.write_bw, "read_iops": taData.read_iops, "write_iops": taData.write_iops, "rate": taData.rate, "color": pickColor }); $scope.tableParams.reload() }; var max; $scope.xaxisList = []; $scope.data = []; for (var i = 0; i < countRep; i++) { for (var k = 0; k < countRep2; k++) { $scope.perrow = $scope.results[i][k]; if ($scope.perrow["mode"] == $scope.current_mode_name && $scope.perrow["description"] == $scope.current_mode_description) { if($scope.perrow.total_client_vms == 1 && countRep!=1) $scope.xaxis = 0; else $scope.xaxis = $scope.perrow.total_client_vms; $scope.xaxisList.push($scope.xaxis); if (mode == "randread") { $scope.data.push({ x: $scope.xaxis, "IOPS": $scope.perrow.read_iops / $scope.perrow.total_client_vms, "latency1": $scope.perrow.read_hist[2][1] / 1000, "latency2": $scope.perrow.read_hist[3][1] / 1000, "latency3": $scope.perrow.read_hist[4][1] / 1000, "requested_rate": $scope.perrow.rate_iops / $scope.perrow.total_client_vms }); max = $scope.perrow.rate_iops / $scope.perrow.total_client_vms; } if (mode == "randwrite") { $scope.data.push({ x: $scope.xaxis, "IOPS": $scope.perrow.write_iops / $scope.perrow.total_client_vms, "latency1": $scope.perrow.write_hist[2][1] / 1000, "latency2": $scope.perrow.write_hist[3][1] / 1000, "latency3": $scope.perrow.write_hist[4][1] / 1000, "requested_rate": $scope.perrow.rate_iops / $scope.perrow.total_client_vms }); max = $scope.perrow.rate_iops / $scope.perrow.total_client_vms; } if (mode == "read") { $scope.data.push({ x: $scope.xaxis, "IOPS": $scope.perrow.read_bw / $scope.perrow.total_client_vms, "latency1": $scope.perrow.read_hist[2][1] / 1000, "latency2": $scope.perrow.read_hist[3][1] / 1000, "latency3": $scope.perrow.read_hist[4][1] / 1000, "requested_rate": $scope.perrow.rate / $scope.perrow.total_client_vms }); max = $scope.perrow.rate / $scope.perrow.total_client_vms; } if (mode == "write") { $scope.data.push({ x: $scope.xaxis, "IOPS": $scope.perrow.write_bw / $scope.perrow.total_client_vms, "latency1": $scope.perrow.write_hist[2][1] / 1000, "latency2": $scope.perrow.write_hist[3][1] / 1000, "latency3": $scope.perrow.write_hist[4][1] / 1000, "requested_rate": $scope.perrow.rate / $scope.perrow.total_client_vms }); max = $scope.perrow.rate / $scope.perrow.total_client_vms; } var pickColor = get_color(); var chName = "mode-" + $scope.perrow.mode + "_VM-" + $scope.perrow.total_client_vms; $scope.pushTableData(chName, $scope.perrow, pickColor) } } } $scope.options = { series: [ {y: "IOPS", color: "#F44336", type: "column", striped: true, label: $scope.current_mode["y_label"]}, { y: "requested_rate", color: "#696969", drawDots: false, thickness: "1px", label: "Requested Rate", lineMode: "dashed" }, { y: "latency1", axis: "y2", color: "#673AB7", drawDots: true, dotSize: 4, thickness: "3px", label: "Latency(ms)--90%" }, { y: "latency2", axis: "y2", color: "#03A9F4", drawDots: true, dotSize: 4, thickness: "3px", label: "Latency(ms)--99%" }, { y: "latency3", axis: "y2", color: "#E91E63", drawDots: true, dotSize: 4, thickness: "3px", label: "Latency(ms)--99.9%" } ], axes: { x: {key: "x", type: "linear", ticks: $scope.xaxisList, ticksFormatter: function(x) { if($.inArray(x, $scope.xaxisList)!=-1) { if (x == 0) return "1"; else return x; } else return ""; }}, y: {type: "linear", ticksFormat: "d", innerTicks: true, max: max * 1.0005, min: 0}, y2: { type: "log", ticksFormat: "d", innerTicks: false, grid: true, min: get_min_hist($scope.results) / 1000 } }, tooltip: { mode: "scrubber", formatter: function (x, y, series) { return series.label + ":" + y; } }, tension: 0.8, lineMode: "cardinal", columnsHGap: 45 }; } </script> </body> </html> ';n(g,k)}else f.showAlert("No result to save!")},setInterval(function(){a.checkStatus()},1e3),$(function(){$('[data-toggle="tooltip"]').tooltip()})}]).service("storageMode",function(){var a=[];this.getResult=function(){return a},this.setResult=function(b){return a=b}}),angular.module("kbWebApp").run(["$templateCache",function(a){"use strict";a.put("views/about.html",'<!--Copyright 2015 Cisco Systems, Inc. All rights reserved.--><!--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.--> <div class="jumbotron"> <h2>KloudBuster</h2> <h5>{{version}}</h5> <!--<p class="lead">--> <!--<img src="images/yeoman.png" alt="I\'m Yeoman"><br>--> <!--Always a pleasure scaffolding your apps.--> <!--</p>--> <p><a class="btn btn-lg btn-success" ng-href="#/">Splendid!<span class="glyphicon glyphicon-ok"></span></a></p> </div> <!--<div class="row marketing">--> <!--<h4>HTML5 Boilerplate</h4>--> <!--<p>--> <!--HTML5 Boilerplate is a professional front-end template for building fast, robust, and adaptable web apps or sites.--> <!--</p>--> <!--<h4>Angular</h4>--> <!--<p>--> <!--AngularJS is a toolset for building the framework most suited to your application development.--> <!--</p>--> <!--<h4>Karma</h4>--> <!--<p>Spectacular Test Runner for JavaScript.</p>--> <!--</div>-->'),a.put("views/config.html",'<!--Copyright 2015 Cisco Systems, Inc. All rights reserved.--><!--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.--><!--<img class="background" src="images/back.jpg">--><!--dialog--> <div class="md-padding dialogdemoBasicUsage" id="popupContainer" ng-cloak=""></div> <div class="row"> <div style="float:right;padding:1px 30px" id="getButton"> <input type="button" value="Default/Reset" class="btn btn-default btn-sm" ng-click="getDefaultConfig()" style="width:110px"> <!--<button type="submit" class="btn btn-default btn-sm" ng-click="getRunConfig()">Get Current Config</button>--> <input type="button" value="Save" class="btn btn-primary btn-sm" ng-click="changeConfig()" style="width:80px"> </div> </div> <br> <div class="row-fluid" id="stagingConfig2"> <div id="dashboard_links" class="col-md-3"> <ul class="nav nav-pills nav-stacked"> <li class="{{dashstatus1}}" ng-click="setDashStatus(1)"><a href="" class="tab-link">GENERAL CONFIGURATION</a></li> <li class="{{dashstatus2}}" ng-click="setDashStatus(2)"><a href="" class="tab-link">SERVER SIDE CONFIG OPTIONS</a> </li> <li class="{{dashstatus3}}" ng-click="setDashStatus(3)"><a href="" class="tab-link">CLIENT SIDE CONFIG OPTIONS</a> </li> </ul> </div> <div id="dashboard_tabs" class="col-md-8"> <!--Start Dashboard Tab 1--> <div id="dashboard-general" class="row" ng-show="dashstatus1vis"> <h4 class="page-header" style="margin-top: 5px">GENERAL CONFIGURATION</h4> <form name="general"> <div class="form-group"> <md-content layout-padding> <md-input-container class="col-md-12"> <label>VM Creation Concurrency</label> <input type="number" min="1" max="1000" step="1" name="vm_creation_concurrency" id="vm_creation_concurrency" ng-model="config.vm_creation_concurrency" ng-pattern="/^[1-9][0-9]{0,2}$/i" required style="text-align:left"> <div ng-messages="general.vm_creation_concurrency.$error" ng-if="general.vm_creation_concurrency.$dirty"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number between 1 and 999</div> </div> </md-input-container> </md-content> <!--<form class="bs-component" name="general">--> <!--<div class="input-group col-sm-12" style="margin:0 auto;"--> <!--popover="Specifies how many VMs will be created at a time. Larger numbers can be used but will not necessarily shorten the overall staging time (this will largely depend on the scalability of the OpenStack control plane). Well tuned control planes with multiple instances of NOVA have shown to support a concurrency level of up to around 50"--> <!--popover-trigger="mouseenter" popover-placement="bottom">--> <!--<span class="input-group-addon">VM Creation Concurrency</span>--> <!--<input type="number" min="1" max="1000" step="1" name="vm_creation_concurrency" class="form-control"--> <!--id="vm_creation_concurrency"--> <!--ng-model="config.vm_creation_concurrency" ng-pattern="/^[1-9][0-9]{0,2}$/i" required/>--> <!--</div>--> <!--<div ng-messages="general.vm_creation_concurrency.$error" ng-if="general.vm_creation_concurrency.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number between 1 and 999</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-11" style="margin:0 auto">--> <!--<span class="input-group-addon">Public Key File:</span>--> <!--<input type="text" class="form-control" id="public_key_file" ng-model="config.public_key_file"/>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-11" style="margin:0 auto">--> <!--<input type="checkbox" id="server_use_floatingip" ng-model="config.server.use_floatingip" ng-change="config.client.use_floatingip=config.server.use_floatingip" /> use floating IP for client and server VMs--> <!--</div>--> <!--<hr>--> <div class="panel panel-default"> <div class="panel-heading">VM Placement</div> <div class="panel-body"> <md-radio-group ng-model="availability_zone" ng-change="changeTopology()"> <md-radio-button value="1" class="md-primary">Let Nova Decide</md-radio-button> <!--<div class="radio">--> <!--<label>--> <!--<input type="radio" ng-model="availability_zone" value="1" ng-change="changeTopology()">--> <!--Let Nova Decide--> <!--</label>--> <!--</div>--> <md-radio-button value="2" class="md-primary">Available Zone</md-radio-button> <!--<div class="radio">--> <!--<label>--> <!--<input type="radio" ng-model="availability_zone" value="2" ng-change="changeTopology()">--> <!--Available Zone--> <!--</label>--> <!--</div>--> <div class="row" ng-show="availability_zone==2;" popover="Leave empty if you prefer to have the Nova scheduler place the server VMs If you want to pick a particular AZ, put that AZ name (e.g. nova) If you want a paticular compute host, put the AZ and compute host names separated by \':\' (e.g. nova:tme100) Note that this is ignored/overriden if you choose \'Use Topology\'" popover-trigger="mouseenter" popover-placement="bottom"> <form name="userForm"> <div class="col-md-6"> <div layout="" layout-sm="column"> <md-input-container flex=""> <label>For Server</label> <md-select ng-model="config.server.availability_zone"> <md-option ng-repeat="serverside in serversides" value="{{serverside}}"> {{serverside}} </md-option> </md-select> </md-input-container> </div> </div> <div class="col-md-6"> <div layout="" layout-sm="column"> <md-input-container flex=""> <label>For Client</label> <md-select ng-model="config.client.availability_zone"> <md-option ng-repeat="clientside in clientsides" value="{{clientside}}"> {{clientside}} </md-option> </md-select> </md-input-container> </div> </div> </form> <!--<div class="col-md-6 col-sm-6">--> <!--<div class="input-group" style="margin:0 auto">--> <!--<span class="input-group-addon">For Server</span>--> <!--<input type="text" class="form-control" ng-model="config.server.availability_zone"/>--> <!--</div>--> <!--</div>--> <!--<div class="col-md-6 col-sm-6">--> <!--<div class="input-group" style="margin:0 auto">--> <!--<span class="input-group-addon">For Client</span>--> <!--<input type="text" class="form-control" ng-model="config.client.availability_zone"/>--> <!--</div>--> <!--</div>--> </div> <md-radio-button value="3" class="md-primary">Use Topology <small> -- customized <cite title="Source Title">VM placement</cite></small> </md-radio-button> <!--<div class="radio" id="topology">--> <!--<label>--> <!--<input type="radio" ng-model="availability_zone" value="3" ng-change="changeTopology()">--> <!--Use Topology--> <!--<small> &#45;&#45; customized <cite title="Source Title">VM placement</cite></small>--> <!--</label>--> <!--</div>--> <div class="row" ng-show="availability_zone==3;"> <div class="col-md-3"> <div class="list-group" id="list3"> <span class="list-group-item active">Server Pool <input title="Toggle all" ng-click="toggleC()" ng-model="toggle" type="checkbox" class="pull-right"> </span> <span ng-repeat="user in listC"> <span class="list-group-item">{{user.firstName}} <input ng-click="selectC(user.id)" name="selectedC[]" value="{{user.id}}" ng-checked="selectedC.indexOf(user.id) > -1" type="checkbox" class="pull-right"> </span> </span> </div> </div> <div class="col-md-1 v-center text-center"> <div class="btn-group-sm"> <button title="Send to list 1" class="btn btn-default btn-sm" ng-click="cToA()" style="margin:10px 0"><i class="glyphicon glyphicon-chevron-right"></i></button> <button title="Send to list 3" class="btn btn-default btn-sm" ng-click="aToC()"><i class="glyphicon glyphicon-chevron-left"></i></button> </div> </div> <div class="col-md-4"> <div class="list-group" id="list1"> <span class="list-group-item active">Available Hypervisors <input title="Toggle all" ng-click="toggleA()" ng-model="toggle" type="checkbox" class="pull-right"> </span> <span ng-repeat="user in listA"> <span class="list-group-item">{{user.firstName}} <input ng-click="selectA(user.id)" name="selectedA[]" value="{{user.id}}" ng-checked="selectedA.indexOf(user.id) > -1" type="checkbox" class="pull-right"> </span> </span> </div> </div> <div class="col-md-1 v-center text-center" style="margin:0px 0px"> <div class="btn-group-sm"> <button title="Send to list 1" class="btn btn-default btn-sm" ng-click="bToA()" style="margin:10px 0"><i class="glyphicon glyphicon-chevron-left"></i></button> <button title="Send to list 2" class="btn btn-default btn-sm" ng-click="aToB()"><i class="glyphicon glyphicon-chevron-right"></i></button> </div> </div> <div class="col-md-3"> <div class="list-group" id="list2"> <span class="list-group-item active">Client Pool <input title="Toggle all" ng-click="toggleB()" ng-model="toggle" type="checkbox" class="pull-right"> </span> <span ng-repeat="user in listB"> <span class="list-group-item">{{user.firstName}} <input ng-click="selectB(user.id)" name="selectedB[]" value="{{user.id}}" ng-checked="selectedB.indexOf(user.id) > -1" type="checkbox" class="pull-right"> </span> </span> </div> </div> <div class="col-md-12" style="text-align: right"> <small><cite title="Source Title">Set hypervisors for both sides!</cite></small> </div> </div> </md-radio-group> </div> </div> <!--<div class="text-center">--> <!--<h4 style="margin-top: 5px">VM PLACEMENT</h4>--> <!--</div>--> </div> </form> </div> <!--End Dashboard Tab 1--> <!--Start Dashboard Tab 2--> <div id="dashboard-server" class="row" ng-show="dashstatus2vis"> <h4 class="page-header" style="margin-top: 5px">SERVER SIDE CONFIG OPTIONS</h4> <form name="server"> <div class="form-group"> <md-content layout-padding> <md-input-container class="col-md-12"> <label>Html Payload Size (Bytes)</label> <input type="number" min="0" step="1024" name="http_server_configs" id="html_size" ng-model="config.server.http_server_configs.html_size" ng-pattern="/^[0-9]*$/i" required style="text-align:left"> <div ng-messages="server.http_server_configs.$error" ng-if="server.http_server_configs.$dirty"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number no less than 0</div> </div> </md-input-container> </md-content> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="The size of HTML page in Bytes"--> <!--popover-trigger="mouseenter" popover-placement="bottom">--> <!--<span class="input-group-addon">Html Payload Size</span>--> <!--<input type="number" min="0" step="1024" name="http_server_configs" class="form-control" id="html_size"--> <!--ng-model="config.server.http_server_configs.html_size" ng-pattern="/^[1-9][0-9]*$/i" required/>--> <!--</div>--> <!--<div ng-messages="server.http_server_configs.$error" ng-if="server.http_server_configs.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number no less than 1</div>--> <!--</div>--> <!--<br/>--> <div class="panel panel-default"> <div class="panel-heading">Flavor (per instance)</div> <div class="panel-body"> <md-content layout-padding> <md-input-container class="col-md-6"> <label>vCPUs</label> <input type="number" min="1" max="999" step="1" name="server_vcpus" id="server_vcpus" ng-model="config.server.flavor.vcpus" ng-pattern="/^[1-9][0-9]{0,2}$/i" required style="text-align:left"> <div ng-messages="server.server_vcpus.$error" ng-if="server.server_vcpus.$dirty"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number between 1 and 999</div> </div> </md-input-container> <md-input-container class="col-md-6"> <label>RAM (MB)</label> <input type="number" min="0" max="" step="128" name="server_ram" id="server_ram" ng-model="config.server.flavor.ram" ng-pattern="/^[0-9]*$/i" required style="text-align:left"> <div ng-messages="server.server_ram.$error" ng-if="server.server_ram.$dirty"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number no less than </div> </div> </md-input-container> </md-content> <div class="panel panel-default" style="margin: 0"> <div class="panel-body"> <md-radio-group ng-model="choose_disk_size1"> <md-radio-button value="0" ng-click="config.server.flavor.disk=20" class="md-primary" style="margin:5px">Use default root disk size</md-radio-button> <md-radio-button value="1" class="md-primary" style="margin:5px">Use specific root disk size</md-radio-button> </md-radio-group> <md-content layout-padding ng-if="choose_disk_size1==1" ng-init="config.server.flavor.disk==0?config.server.flavor.disk=20:\'\'"> <md-input-container class="col-md-6"> <label>Root Disk Size (GB)</label> <input type="number" min="1" max="" step="" name="server_disk" id="server_disk" ng-model="config.server.flavor.disk" ng-pattern="/^[1-9][0-9]*$/i" required style="text-align:left"> <div ng-messages="server.server_disk.$error" role="alert"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number no less than 1</div> </div> </md-input-container> </md-content> </div> </div> </div> </div> <!--<div class="well bs-component">--> <!--<form class="form-horizontal">--> <!--<fieldset>--> <!--<legend>Flavor (per instance)</legend>--> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="Number of vCPUs for the flavor"--> <!--popover-trigger="mouseenter"--> <!--popover-placement="bottom">--> <!--<span class="input-group-addon">vCPUs</span>--> <!--<input type="number" min="1" max="999" step="1" name="server_vcpus" class="form-control"--> <!--id="server_vcpus" ng-model="config.server.flavor.vcpus" ng-pattern="/^[1-9][0-9]{0,2}$/i"--> <!--required/>--> <!--</div>--> <!--<div ng-messages="server.server_vcpus.$error" ng-if="server.server_vcpus.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number between 1 and 999</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="Memory for the flavor"--> <!--popover-trigger="mouseenter"--> <!--popover-placement="bottom">--> <!--<span class="input-group-addon">RAM (MB)</span>--> <!--<input type="number" min="0" max="" step="128" name="server_ram" class="form-control" id="server_ram"--> <!--ng-model="config.server.flavor.ram" ng-pattern="/^[1-9][0-9]*$/i" required/>--> <!--</div>--> <!--<div ng-messages="server.server_ram.$error" ng-if="server.server_ram.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number no less than 1</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="Size of local disk"--> <!--popover-trigger="mouseenter"--> <!--popover-placement="bottom">--> <!--<span class="input-group-addon">Disk (GB)</span>--> <!--<input type="number" min="0" max="" step="" name="server_disk" class="form-control" id="server_disk"--> <!--ng-model="config.server.flavor.disk" ng-pattern="/^[1-9][0-9]*$/i" required/>--> <!--</div>--> <!--<div ng-messages="server.server_disk.$error" ng-if="server.server_disk.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number no less than 1</div>--> <!--</div>--> <!--</fieldset>--> <!--</form>--> <!--</div>--> </div> </form> </div> <!--End Dashboard Tab 2--> <!--Start Dashboard Tab 3--> <div id="dashboard-client" class="row" ng-show="dashstatus3vis"> <h4 class="page-header" style="margin-top: 5px">CLIENT SIDE CONFIG OPTIONS</h4> <form name="client"> <div class="form-group"> <div class="panel panel-default"> <div class="panel-heading">Flavor (per instance)</div> <div class="panel-body"> <md-content layout-padding> <md-input-container class="col-md-6"> <label>vCPUs</label> <input type="number" min="1" max="999" step="1" name="client_vcpus" id="client_vcpus" ng-model="config.client.flavor.vcpus" ng-pattern="/^[1-9][0-9]{0,2}$/i" required style="text-align:left"> <div ng-messages="client.client_vcpus.$error" ng-if="client.client_vcpus.$dirty"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number between 1 and 999</div> </div> </md-input-container> <md-input-container class="col-md-6"> <label>RAM (MB)</label> <input type="number" min="0" max="" step="128" name="client_ram" id="client_ram" ng-model="config.client.flavor.ram" ng-pattern="/^[0-9]*$/i" required style="text-align:left"> <div ng-messages="client.client_ram.$error" ng-if="client.client_ram.$dirty"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number no less than 0</div> </div> </md-input-container> </md-content> <div class="panel panel-default" style="margin: 0"> <div class="panel-body"> <md-radio-group ng-model="choose_disk_size2"> <md-radio-button value="0" ng-click="config.client.flavor.disk=20" class="md-primary" style="margin:5px">Use default root disk size</md-radio-button> <md-radio-button value="1" class="md-primary" style="margin:5px">Use specific root disk size</md-radio-button> </md-radio-group> <md-content layout-padding ng-if="choose_disk_size2==1" ng-init="config.client.flavor.disk==0?config.client.flavor.disk=20:\'\'"> <md-input-container class="col-md-6"> <label>Root Disk Size (GB)</label> <input type="number" min="1" max="" step="" name="client_disk" id="client_disk" ng-model="config.client.flavor.disk" ng-pattern="/^[1-9][0-9]*$/i" required style="text-align:left"> <div ng-messages="client.client_disk.$error" role="alert"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number no less than 1</div> </div> </md-input-container> </md-content> </div> </div> </div> </div> <!--<div class="well bs-component">--> <!--<form class="form-horizontal" >--> <!--<fieldset>--> <!--<legend>flavor</legend>--> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="Number of vCPUs for the flavor"--> <!--popover-trigger="mouseenter"--> <!--popover-placement="bottom">--> <!--<span class="input-group-addon">vCPUs</span>--> <!--<input type="number" min="0" max="1000" step="1" name="client_vcpus" class="form-control"--> <!--id="client_vcpus"--> <!--ng-model="config.client.flavor.vcpus" ng-pattern="/^[1-9][0-9]{0,2}$/i" required/>--> <!--</div>--> <!--<div ng-messages="client.client_vcpus.$error" ng-if="client.client_vcpus.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number between 1 and 999</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="Memory for the flavor"--> <!--popover-trigger="mouseenter"--> <!--popover-placement="bottom">--> <!--<span class="input-group-addon">RAM (MB)</span>--> <!--<input type="number" min="0" max="" step="128" name="client_ram" class="form-control" id="client_ram"--> <!--ng-model="config.client.flavor.ram" ng-pattern="/^[1-9][0-9]*$/i" required/>--> <!--</div>--> <!--<div ng-messages="client.client_ram.$error" ng-if="client.client_ram.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number no less than 1</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="Size of local disk"--> <!--popover-trigger="mouseenter"--> <!--popover-placement="bottom">--> <!--<span class="input-group-addon">Disk (GB)</span>--> <!--<input type="number" min="0" max="" step="" name="client_disk" class="form-control"--> <!--id="client_disk zone"--> <!--ng-model="config.client.flavor.disk" ng-pattern="/^[1-9][0-9]*$/i" required/>--> <!--</div>--> <!--<div ng-messages="client.client_disk.$error" ng-if="client.client_disk.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number no less than 1</div>--> <!--</div>--> <!--</fieldset>--> <!--</form>--> <!--</div>--> <!--</div>--> <!--<div class="input-group col-sm-11" style="margin:0 auto">--> <!--<span class="input-group-addon">Availability Zone:</span>--> <!--<input type="text" class="form-control" id="availability_zone" ng-model="config.client.availability_zone"/>--> <!--</div>--> </div> </form> </div> <!--End Dashboard Tab 3--> </div> </div>'),
a.put("views/config_storage.html",'<!--Copyright 2016 Cisco Systems, Inc. All rights reserved.--><!--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.--> <div class="md-padding dialogdemoBasicUsage" id="popupContainer" ng-cloak=""></div> <div class="row"> <div style="float:right;padding:1px 30px" id="getButton"> <input type="button" value="Default/Reset" class="btn btn-default btn-sm" ng-click="getDefaultConfig()" style="width:110px"> <!--<button type="submit" class="btn btn-default btn-sm" ng-click="getRunConfig()">Get Current Config</button>--> <input type="button" value="Save" class="btn btn-primary btn-sm" ng-click="changeConfig()" style="width:80px" ng-disabled="general.$pristine && server.$pristine"> </div> </div> <br> <div class="row-fluid" id="stagingConfig3"> <div id="dashboard_links" class="col-md-3"> <ul class="nav nav-pills nav-stacked"> <li class="{{dash1status1}}" ng-click="setDash1Status(1)"><a href="" class="tab-link">GENERAL CONFIGURATION</a> </li> <li class="{{dash1status2}}" ng-click="setDash1Status(2)"><a href="" class="tab-link">STORAGE WORKLOADS</a> </li> <!--<li class="{{dash1status3}}" ng-click="setDash1Status(3)"><a href="" class="tab-link">CLIENT SIDE CONFIG--> <!--OPTIONS</a>--> <!--</li>--> </ul> </div> <div id="dashboard_tabs" class="col-md-8"> <!--Start Dashboard Tab 1--> <div id="dashboard-general" class="row" ng-show="dash1status1vis"> <h4 class="page-header" style="margin-top: 5px">GENERAL CONFIGURATION</h4> <form name="general"> <div class="form-group"> <md-content layout-padding> <md-input-container class="col-md-12"> <label>VM Creation Concurrency</label> <input type="number" min="1" max="999" step="1" name="vm_creation_concurrency" id="vm_creation_concurrency" ng-model="config.vm_creation_concurrency" ng-pattern="/^[1-9][0-9]{0,2}$/i" required style="text-align:left"> <div ng-messages="general.vm_creation_concurrency.$error" ng-if="general.vm_creation_concurrency.$dirty"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number between 1 and 999</div> </div> </md-input-container> </md-content> <div class="panel panel-default" style="margin: 0"> <div class="panel-body"> <h6>Volume Types Used for Storage Test:</h6> <md-radio-group ng-model="config.client.storage_stage_configs.target"> <md-radio-button value="volume" class="md-primary" style="display: inline">Cinder Volume (Block Storage)</md-radio-button> <md-radio-button value="ephemeral" class="md-primary" style="display: inline">Ephemeral Volume</md-radio-button> </md-radio-group> <md-content layout-padding> <md-input-container class="col-md-12"> <label>Volume Size (GB)</label> <input type="number" min="1" max="999" step="1" name="disk_size" id="disk_size" ng-model="config.client.storage_stage_configs.disk_size" ng-pattern="/^[1-9][0-9]{0,2}$/i" required style="text-align:left"> <div ng-messages="general.disk_size.$error" ng-if="general.disk_size.$dirty"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number between 1 and 999</div> </div> </md-input-container> </md-content> </div> </div> <md-content layout-padding> <md-input-container class="col-md-12"> <label>Storage Test IO File Size (GB)</label> <input type="number" min="1" max="999" step="1" name="io_file_size" id="io_file_size" ng-model="config.client.storage_stage_configs.io_file_size" ng-pattern="/^[1-9][0-9]{0,2}$/i" required style="text-align:left"> <div ng-messages="general.io_file_size.$error" ng-if="general.io_file_size.$dirty"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number between 1 and 999</div> </div> </md-input-container> </md-content> <div class="panel panel-default"> <div class="panel-heading">Flavor (per instance)</div> <div class="panel-body"> <md-content layout-padding> <md-input-container class="col-md-6"> <label>vCPUs</label> <input type="number" min="1" max="999" step="1" name="client_vcpus" id="client_vcpus" ng-model="config.client.flavor.vcpus" ng-pattern="/^[1-9][0-9]{0,2}$/i" required style="text-align:left"> <div ng-messages="general.client_vcpus.$error" ng-if="general.client_vcpus.$dirty"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number between 1 and 999</div> </div> </md-input-container> <md-input-container class="col-md-6"> <label>RAM (MB)</label> <input type="number" min="0" max="" step="128" name="client_ram" id="client_ram" ng-model="config.client.flavor.ram" ng-pattern="/^[0-9]*$/i" required style="text-align:left"> <div ng-messages="general.client_ram.$error" ng-if="general.client_ram.$dirty"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number no less than 0</div> </div> </md-input-container> </md-content> <div class="panel panel-default" style="margin: 0"> <div class="panel-body"> <md-radio-group ng-model="choose_disk_size"> <md-radio-button value="0" ng-click="config.client.flavor.disk=0" class="md-primary" style="margin:5px">Use default root disk size</md-radio-button> <md-radio-button value="1" class="md-primary" style="margin:5px">Use specific root disk size</md-radio-button> </md-radio-group> <md-content layout-padding ng-if="choose_disk_size==1" ng-init="config.client.flavor.disk==0?config.client.flavor.disk=20:\'\'"> <md-input-container class="col-md-6"> <label>Root Disk Size (GB)</label> <input type="number" min="1" max="" step="" name="client_disk" id="client_disk" ng-model="config.client.flavor.disk" ng-pattern="/^[1-9][0-9]*$/i" required style="text-align:left"> <div ng-messages="general.client_disk.$error" role="alert"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number no less than 1</div> </div> </md-input-container> </md-content> </div> </div> </div> </div> </div> </form> </div> <!--End Dashboard Tab 1--> <!--Start Dashboard Tab 2--> <div id="dashboard-server" class="row" ng-show="dash1status2vis" style="margin-bottom: 2%"> <h4 class="page-header" style="margin-top: 5px">LIST OF STORAGE WORKLOADS TO EXECUTE IN SEQUENCE <div class="btn-group" style="text-align: center;float:right"> <a href="" class="btn btn-xs btn-primary dropdown-toggle" style="width:150px; text-align: center" data-toggle="dropdown" aria-expanded="false"> Add&nbsp;&nbsp;Workload&nbsp;&nbsp;<span class="caret"></span> </a> <ul class="dropdown-menu"> <li id="dropdown{{mode}}" ng-repeat="(mode,detail) in storageMode"> <a ng-click="addMode(mode)">{{detail.name}}</a> </li> </ul> </div> </h4> <form name="server"> <div class="form-group"> <div ng-repeat="item in config.client.storage_tool_configs" class="panel panel-primary {{storageMode[item[\'mode\']][\'type\']}}"> <div class="panel-heading"> <h3 class="panel-title">{{$index+1}}. {{item[\'description\']}} - {{storageMode[item[\'mode\']][\'name\']}}&nbsp; <a style="float:right;text-decoration: none;cursor: pointer; margin-left: 4%" ng-click="switchIndex($index,0)">× </a> <a style="float:right;text-decoration: none;cursor: pointer; margin-left: 2%" ng-show="$index<config.client.storage_tool_configs.length-1" ng-click="switchIndex($index,-1)"> <span class="glyphicon glyphicon-arrow-down" aria-hidden="true"></span> </a> <a style="float:right;text-decoration: none;cursor: pointer" ng-show="$index>0" ng-click="switchIndex($index,1)"> <span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span> </a> </h3> </div> <div class="panel-body"> <md-content layout-gt-sm="row" layout-padding layout-wrap> <md-input-container flex="100"> <label>{{options[\'description\'][\'name\']}}</label> <input id="{{$index}}+description" name="{{$index}}+description" type="text" ng-model="config.client.storage_tool_configs[$index][\'description\']" required style="text-align:left"> <div ng-messages="server[$index+\'+description\'].$error"> <div ng-message="required" style="padding-right: 0">This field is required</div> </div> </md-input-container> <md-input-container flex="33%" ng-if="item[\'mode\'].slice(0,4)==\'rand\'"> <label>{{options[\'rate_iops\'][\'name\']}}</label> <input id="{{$index}}+rate_iops&quot;" name="{{$index}}+rate_iops" type="number" min="1" ng-pattern="/^[1-9][0-9]*$/i" ng-model="config.client.storage_tool_configs[$index][\'rate_iops\']" required style="text-align:left"> <div ng-messages="server[$index+\'+rate_iops\'].$error" ng-if="server[$index+\'+rate_iops\'].$dirty"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number no less than 1</div> </div> </md-input-container> <md-input-container flex="33%" ng-if="item[\'mode\'].slice(0,4)!=\'rand\'"> <label>{{options[\'rate\'][\'name\']}}</label> <input id="{{$index}}+rate&quot;" name="{{$index}}+rate" type="number" min="1" ng-pattern="/^[1-9][0-9]*$/i" ng-model="tem_rate" required ng-init="tem_rate = parseInt(config.client.storage_tool_configs[$index][\'rate\'].slice(0,-1))" ng-change="config.client.storage_tool_configs[$index][\'rate\'] = tem_rate + \'M\'" style="text-align:left"> <div ng-messages="server[$index+\'+rate\'].$error" ng-if="server[$index+\'+rate\'].$dirty"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number no less than 1</div> </div> </md-input-container> <md-input-container flex="33%"> <label>{{options[\'block_size\'][\'name\']}}</label> <input id="{{$index}}+block_size&quot;" name="{{$index}}+block_size" type="number" min="1" ng-pattern="/^[1-9][0-9]*/i" ng-model="tem_block_size" required style="text-align:left" ng-init="tem_block_size = parseInt(config.client.storage_tool_configs[$index][\'block_size\'].slice(0,-1))" ng-change="config.client.storage_tool_configs[$index][\'block_size\'] = tem_block_size + \'k\'"> <div ng-messages="server[$index+\'+block_size\'].$error" ng-if="server[$index+\'+block_size\'].$dirty"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number no less than 1</div> </div> </md-input-container> <md-input-container flex="33%"> <label>{{options[\'iodepth\'][\'name\']}}</label> <input id="{{$index}}+iodepth&quot;" name="{{$index}}+iodepth" type="number" min="1" ng-pattern="/^[1-9][0-9]*$/i" ng-model="config.client.storage_tool_configs[$index][\'iodepth\']" required style="text-align:left"> <div ng-messages="server[$index+\'+iodepth\'].$error" ng-if="server[$index+\'+iodepth\'].$dirty"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number no less than 1</div> </div> </md-input-container> <md-input-container flex="33%" ng-if="item[\'mode\']==\'rw\' || item[\'mode\']==\'randrw\'"> <label>{{options[\'rwmixread\'][\'name\']}}</label> <input id="{{$index}}+rwmixread&quot;" name="{{$index}}+rwmixread" type="number" min="1" max="99" ng-pattern="/^[1-9][0-9]{0,1}$/i" ng-model="config.client.storage_tool_configs[$index][\'rwmixread\']" required style="text-align:left"> <div ng-messages="server[$index+\'+rwmixread\'].$error" ng-if="server[$index+\'+rwmixread\'].$dirty"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number between 1 and 99</div> </div> </md-input-container> <md-input-container flex="33%"> <label>{{options[\'runtime\'][\'name\']}}</label> <input id="{{$index}}+runtime&quot;" name="{{$index}}+runtime" type="number" min="1" ng-pattern="/^[1-9][0-9]{0,2}$/i" ng-model="config.client.storage_tool_configs[$index][\'runtime\']" required style="text-align:left"> <div ng-messages="server[$index+\'+runtime\'].$error" ng-if="server[$index+\'+runtime\'].$dirty"> <div ng-message="required" style="padding-right: 0">This field is required</div> <div ng-message="pattern" style="padding-right: 0">Must be a number between 1 and 999</div> </div> </md-input-container> <md-input-container flex="33%"> <label>{{options[\'extra_opts\'][\'name\']}}</label> <input id="{{$index}}+extra_opts&quot;" name="{{$index}}+extra_opts" ng-model="config.client.storage_tool_configs[$index][\'extra_opts\']" style="text-align:left"> </md-input-container> <!--<md-input-container ng-repeat="(option,result) in item" flex="33%">--> <!--<label>{{options[option][\'name\']}}</label>--> <!--<input id=$parent.$index+{{option}}"--> <!--ng-model="config.client.storage_tool_configs[$parent.$index][option]" required--> <!--style="text-align:left;" ng-disabled="option == \'mode\'"/>--> <!--</md-input-container>--> </md-content> </div> </div> </div> </form> </div> <!--End Dashboard Tab 2--> </div> </div>'),a.put("views/interval.html",'<!--Copyright 2015 Cisco Systems, Inc. All rights reserved.--><!--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.--><!--<alert ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)" style="background-color:#ffcc99;color:white">{{alert.msg}}</alert>--> <div style="text-align:right"> <div class="btn-group"> <a href="" class="btn btn-default" ng-click="stage()" ng-disabled="setUnstage" style="width:100px">{{stageButton}}</a> <!--<a herf="" class="btn btn-default" ng-click="setConfig()" ng-disabled="setStatus">Save Settings</a>--> <a href="" class="btn btn-default" ng-click="scaleTest()" ng-disabled="runStatus" style="width:100px">{{runButton}}</a> </div> <!--<button type="submit" class="btn btn-default" ng-click="CleanUp()">Unstage</button>--> <!--<button type="submit" class="btn btn-warning" ng-click="setConfig()" ng-disabled="setStatus">Save Settings</button>--> <!--<button type="submit" class="btn btn-primary" ng-click="scaleTest()" ng-disabled="runStatus">{{runButton}}</button>--> </div> <div class="supercontainer"> <div class="container"> <div id="sidebar"> <div class=""> <accordion close-others="oneAtATime"> <accordion-group heading="" is-open="status1.open"> <accordion-heading> Staging Settings (VM Count: {{config.server.number_tenants*config.server.routers_per_tenant*config.server.networks_per_router*config.server.vms_per_network*config.server.secgroups_per_network}}) <i class="pull-right glyphicon" ng-class="{\'glyphicon-chevron-down\': !status1.open, \'glyphicon-chevron-up\': status1.open}"></i> </accordion-heading> <div class="col-lg-14" id="stagingConfig"> <form class="bs-component" name="monitoring_staging_settings"> <md-content layout-padding style="padding:0"> <md-input-container class="col-md-12" style="padding-top:0"> <label>Tenants</label> <input type="number" min="1" max="9999" step="1" id="number_tenants" ng-model="config.server.number_tenants" name="number_tenants" ng-pattern="/^[1-9][0-9]{0,3}$/i" required style="text-align:left"> <div ng-messages="interactive_staging_settings.number_tenants.$error" ng-if="interactive_staging_settings.number_tenants.$dirty"> <div ng-message="required" style="text-align:left">This field is required</div> <div ng-message="pattern" style="text-align:left">Must be a number between 1 and 9999</div> </div> </md-input-container> <md-input-container class="col-md-12"> <label>Routers/Tenant</label> <input type="number" min="1" max="999" step="1" id="server_routers_per_tenant" ng-model="config.server.routers_per_tenant" name="server_routers_per_tenant" ng-pattern="/^[1-9][0-9]{0,2}$/i" required style="text-align:left"> <div ng-messages="interactive_staging_settings.server_routers_per_tenant.$error" ng-if="interactive_staging_settings.server_routers_per_tenant.$dirty"> <div ng-message="required" style="text-align:left">This field is required</div> <div ng-message="pattern" style="text-align:left">Must be a number between 1 and 999</div> </div> </md-input-container> <md-input-container class="col-md-12"> <label>Networks/Router</label> <input type="number" min="1" max="999" step="1" id="server_networks_per_router" ng-model="config.server.networks_per_router" name="server_networks_per_router" ng-pattern="/^[1-9][0-9]{0,2}$/i" required style="text-align:left"> <div ng-messages="interactive_staging_settings.server_networks_per_router.$error" ng-if="interactive_staging_settings.server_networks_per_router.$dirty"> <div ng-message="required" style="text-align:left">This field is required</div> <div ng-message="pattern" style="text-align:left">Must be a number between 1 and 999</div> </div> </md-input-container> <md-input-container class="col-md-12"> <label>VMs/Network</label> <input type="number" min="1" max="999" step="1" id="server_vms_per_network" ng-model="config.server.vms_per_network" name="server_vms_per_network" ng-pattern="/^[1-9][0-9]{0,2}$/i" required style="text-align:left"> <div ng-messages="interactive_staging_settings.server_vms_per_network.$error" ng-if="interactive_staging_settings.server_vms_per_network.$dirty"> <div ng-message="required" style="text-align:left">This field is required</div> <div ng-message="pattern" style="text-align:left">Must be a number between 1 and 999</div> </div> </md-input-container> <md-input-container class="col-md-12"> <label>Secgroups/Network</label> <input type="number" min="1" max="999" step="1" id="server_secgroups_per_network" ng-model="config.server.secgroups_per_network" name="server_secgroups_per_network" ng-pattern="/^[1-9][0-9]{0,2}$/i" required style="text-align:left"> <div ng-messages="interactive_staging_settings.server_secgroups_per_network.$error" ng-if="interactive_staging_settings.server_secgroups_per_network.$dirty"> <div ng-message="required" style="text-align:left">This field is required</div> <div ng-message="pattern" style="text-align:left">Must be a number between 1 and 999</div> </div> </md-input-container> </md-content> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="Number of tenants to be created on the cloud" popover-trigger="mouseenter" popover-placement="right">--> <!--<span class="input-group-addon">Tenants</span>--> <!--<input type="number" min="1" max="10000" step="1" class="form-control" id="number_tenants"--> <!--ng-model="config.server.number_tenants" name="number_tenants" ng-pattern="/^[1-9][0-9]{0,3}$/i" required/>--> <!--</div>--> <!--<div ng-messages="monitoring_staging_settings.number_tenants.$error"--> <!--ng-if="monitoring_staging_settings.number_tenants.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number between 1 and 9999</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="Number of routers to be created within the context of each User" popover-trigger="mouseenter" popover-placement="right">--> <!--<span class="input-group-addon">Routers/Tenant</span>--> <!--<input type="number" min="1" max="1000" step="1" class="form-control" id="server_routers_per_tenant"--> <!--ng-model="config.server.routers_per_tenant" name="server_routers_per_tenant"--> <!--ng-pattern="/^[1-9][0-9]{0,2}$/i" required/>--> <!--</div>--> <!--<div ng-messages="monitoring_staging_settings.server_routers_per_tenant.$error"--> <!--ng-if="monitoring_staging_settings.server_routers_per_tenant.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number between 1 and 999</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="Number of networks to be created within the context of each Router" popover-trigger="mouseenter" popover-placement="right">--> <!--<span class="input-group-addon">Networks/Router</span>--> <!--<input type="number" min="1" max="1000" step="1" class="form-control" id="server_networks_per_router"--> <!--ng-model="config.server.networks_per_router" name="server_networks_per_router"--> <!--ng-pattern="/^[1-9][0-9]{0,2}$/i" required/>--> <!--</div>--> <!--<div ng-messages="monitoring_staging_settings.server_networks_per_router.$error"--> <!--ng-if="monitoring_staging_settings.server_networks_per_router.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number between 1 and 999</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="Number of VM instances to be created within the context of each Network" popover-trigger="mouseenter" popover-placement="right">--> <!--<span class="input-group-addon">VMs/Network</span>--> <!--<input type="number" min="1" max="1000" step="1" class="form-control" id="server_vms_per_network"--> <!--ng-model="config.server.vms_per_network" name="server_vms_per_network"--> <!--ng-pattern="/^[1-9][0-9]{0,2}$/i" required/>--> <!--</div>--> <!--<div ng-messages="monitoring_staging_settings.server_vms_per_network.$error"--> <!--ng-if="monitoring_staging_settings.server_vms_per_network.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number between 1 and 999</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="Number of security groups per network" popover-trigger="mouseenter" popover-placement="right">--> <!--<span class="input-group-addon">Secgroups/Network</span>--> <!--<input type="number" min="1" max="1000" step="1" class="form-control"--> <!--id="server_secgroups_per_network" ng-model="config.server.secgroups_per_network"--> <!--name="server_secgroups_per_network" ng-pattern="/^[1-9][0-9]{0,2}$/i" required/>--> <!--</div>--> <!--<div ng-messages="monitoring_staging_settings.server_secgroups_per_network.$error"--> <!--ng-if="monitoring_staging_settings.server_secgroups_per_network.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number between 1 and 999</div>--> <!--</div>--> </form> </div> <!--Run--> </accordion-group> <accordion-group is-open="status2.open"> <accordion-heading> Run Settings <i class="pull-right glyphicon" ng-class="{\'glyphicon-chevron-down\': !status2.open, \'glyphicon-chevron-up\': status2.open}"></i> </accordion-heading> <div class="col-lg-14" id="runningConfig"> <form class="bs-component" name="monitoring_running_settings"> <md-content layout-padding style="padding:0"> <md-input-container class="col-md-12" style="padding-top:0"> <label>Duration/Run (sec)</label> <input type="number" min="1" max="" step="1" id="client_duration" ng-model="config.client.http_tool_configs.duration" name="client_duration" ng-pattern="/^[1-9][0-9]*$/i" required style="text-align:left"> <div ng-messages="interactive_running_settings.client_duration.$error" ng-if="interactive_running_settings.client_duration.$dirty"> <div ng-message="required">This field is required</div> <div ng-message="pattern">Must be a number no less than 1</div> </div> </md-input-container> <md-input-container class="col-md-12" style="padding-top:0"> <label>Reporting Interval (sec)</label> <input type="number" min="1" max="" step="1" id="report_interval" ng-model="config.client.http_tool_configs.report_interval" name="report_interval" ng-pattern="/^[1-9][0-9]*$/i" required style="text-align:left"> <div ng-messages="monitoring_running_settings.report_interval.$error"> <div ng-message="required">This field is required</div> <div ng-message="pattern">Must be a number no less than 1</div> </div> </md-input-container> <md-input-container class="col-md-12"> <label>Rate Limit/VM</label> <input type="number" min="0" max="" step="1000" id="client_rate_limit" ng-model="config.client.http_tool_configs.rate_limit" name="client_rate_limit" ng-pattern="/^[0-9]*$/i" required style="text-align:left"> <div ng-messages="interactive_running_settings.client_rate_limit.$error" ng-if="interactive_running_settings.client_rate_limit.$dirty"> <div ng-message="required">This field is required</div> <div ng-message="pattern">Must be a number no less than 0</div> </div> </md-input-container> <md-input-container class="col-md-12"> <label>Connections/VM</label> <input type="number" min="0" max="" step="1000" id="client_connections" ng-model="config.client.http_tool_configs.connections" name="client_connections" ng-pattern="/^[1-9][0-9]*$/i" required style="text-align:left"> <div ng-messages="interactive_running_settings.client_connections.$error" ng-if="interactive_running_settings.client_connections.$dirty"> <div ng-message="required">This field is required</div> <div ng-message="pattern">Must be a number no less than 1</div> </div> </md-input-container> </md-content> <!--<div class="input-group col-sm-12" style="margin:0 auto">--> <!--<span class="input-group-addon">connection Type:</span>--> <!--<input type="text" class="form-control" id="client_connection_type" ng-model="config.client.http_tool_configs.connection_type"/>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="Duration of testing tools" popover-trigger="mouseenter" popover-placement="right">--> <!--<span class="input-group-addon">Duration/Run (sec)</span>--> <!--<input type="number" min="1" max="" step="1" class="form-control" id="client_duration"--> <!--ng-model="config.client.http_tool_configs.duration" name="client_duration" ng-pattern="/^[1-9][0-9]*$/i" required/>--> <!--</div>--> <!--<div ng-messages="monitoring_running_settings.client_duration.$error" ng-if="monitoring_running_settings.client_duration.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number no less than 1</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="Interval for periodical report in seconds" popover-trigger="mouseenter" popover-placement="right">--> <!--<span class="input-group-addon">Reporting Interval (sec)</span>--> <!--<input type="number" min="1" max="" step="1" class="form-control" id="report_interval"--> <!--ng-model="config.client.http_tool_configs.report_interval" name="report_interval" ng-pattern="/^[1-9][0-9]*$/i" required/>--> <!--</div>--> <!--<div ng-messages="monitoring_running_settings.report_interval.$error">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number no less than 1</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="Rate limit in RPS per client (0 for unlimited)" popover-trigger="mouseenter" popover-placement="right">--> <!--<span class="input-group-addon">Rate Limit/VM</span>--> <!--<input type="number" min="0" max="" step="1000" class="form-control" id="client_rate_limit"--> <!--ng-model="config.client.http_tool_configs.rate_limit" name="client_rate_limit" ng-pattern="/^[1-9][0-9]*$/i" required/>--> <!--</div>--> <!--<div ng-messages="monitoring_running_settings.client_rate_limit.$error" ng-if="monitoring_running_settings.client_rate_limit.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number no less than 1</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="Connections to be kept concurrently per VM. This number also corresponds to the number of HTTP users connected at any time to the matching HTTP server" popover-trigger="mouseenter" popover-placement="right">--> <!--<span class="input-group-addon">Connections/VM</span>--> <!--<input type="number" min="0" max="" step="1000" min="0" max="" step="10" class="form-control"--> <!--id="client_connections" ng-model="config.client.http_tool_configs.connections" name="client_connections" ng-pattern="/^[1-9][0-9]*$/i" required/>--> <!--</div>--> <!--<div ng-messages="monitoring_running_settings.client_connections.$error" ng-if="monitoring_running_settings.client_connections.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number no less than 1</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto">--> <!--<span class="input-group-addon">Threads:</span>--> <!--<input type="number" min="0" max="" step="10" class="form-control" id="client_threads" ng-model="config.client.http_tool_configs.threads"/>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto">--> <!--<span class="input-group-addon">Timeout:</span>--> <!--<input type="number" min="0" max="" step="5" class="form-control" id="client_timeout" ng-model="config.client.http_tool_configs.timeout"/>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto">--> <!--<span class="input-group-addon">Polling Interval:</span>--> <!--<input type="number" min="0" max="" step="5" class="form-control" id="client_polling_interval" ng-model="config.client.polling_interval"/>--> <!--</div>--> </form> </div> </accordion-group> </accordion> </div> </div> <div class="main-content"> <div class="swipe-area"></div> <a href="" data-toggle=".container" id="sidebar-toggle" style="text-decoration:none"> <!--<span class="bar"></span>--> <!--<span class="bar"></span>--> <!--<span class="bar"></span>--> <span id="littleglyph1" class="bar glyphicon glyphicon-triangle-right" style="color:white"></span> </a> <div class="content" id="content"> <div class="row"> <div class=""> <h6>Latency(ms)</h6> <linechart data="data" options="options" mode="" width="" height="500"></linechart> <!--<h6 style="float:right; text-align: right; line-height: 30%">Percentile</h6>--> </div> </div> </div> </div> </div> </div> <div class="row" style="text-align:right;margin: 0 5%"> <button type="submit" class="btn btn-default btn-xs" ng-click="saveResult()">Save Result</button> <button type="submit" class="btn btn-default btn-xs" ng-click="initChart()">Clear Chart</button> </div> <br> <div class="navbar navbar-default navbar-fixed-bottom" role="navigation" style="min-height: 48px;background: transparent"> <div style="height: 12px;background-color: transparent;width: 100%;margin:0;border:0;padding:0"></div> <div style="background: white; width: 52px; height: 52px;border-radius: 50%;position:absolute;z-index: 10;top:0;left:60px"> <div class="loading spin-1"> <div class="loading spin-2"> <div class="loading spin-3"> <div class="loading spin-4"> <div class="loading spin-5"> <div class="loading spin-6"></div> </div> </div> </div> </div> </div> </div> <div style="background: rgb(44,62,80);width: 100%;height: 36px;margin:0;border:0;padding:0"> <div style="margin: 0 80px 0 120px;vertical-align: middle"> <h5> <div class="row"> <div class="col-md-2 col-xs-2" style="line-height:33px; height:20px; color:white"> <!--Status:--> <button class="btn {{statusButton}} btn-xs" ng-click="checkStatus()" style="height:24px">{{status}} </button> </div> <div class="col-md-6 col-xs-6" style="line-height:35px; height:20px; color:white">Created&nbsp; <button class="btn btn-primary btn-xs" ng-click="checkStatus()" style="height:24px">{{server_vm_count}} </button> &nbsp;Server VM(s),&nbsp; <button class="btn btn-primary btn-xs" ng-click="checkStatus()" style="height:24px">{{client_vm_count}} </button> &nbsp;Client VM(s). </div> <div class="col-md-4 col-xs-4" style="line-height:33px; height:20px; color:white" ng-show="info"> <button class="btn btn-xs btn-info" style="width:220px;text-align: left">{{info}}</button> </div> </div> <!--sessionID: <button class="btn btn-info btn-xs" disabled>{{sessionID}}</button>--> <!--<button style="float:right;" type="submit" class="btn btn-default btn-xs" ng-click="deleteSession()" popover="Session can be destroyed only if it is at READY." popover-trigger="mouseenter">Del Ses</button>--> </h5> </div> </div> </div>'),
a.put("views/log.html",'<!--Copyright 2015 Cisco Systems, Inc. All rights reserved.--><!--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.--> <div class="col-lg-14"> <div class="well bs-component"> <form class="form-horizontal"> <fieldset> <!--<legend>Log</legend>--> <table class="table table-striped table-hover"> <thead> <tr> <th> <span class="col-md-2" style="float:left;line-height:25px; height:5px">LOGS</span> <md-radio-group ng-model="logNum" ng-click="getLog()"> <div class="col-md-2"><md-radio-button value="0" class="md-primary" style="margin: 0 0">Show All Logs</md-radio-button></div> <div class="col-md-3"><md-radio-button value="100" class="md-primary" style="margin: 0 0"> Show Last 100 Lines </md-radio-button></div> </md-radio-group> <span style="float:right"> <button type="submit" class="btn btn-default btn-xs" ng-click="delLog()" style="width: 65px">Clear</button> <button type="submit" class="btn btn-primary btn-xs" ng-click="getLog()" style="width: 65px">Refresh</button> </span> </th> </tr> </thead> </table> <div id="cc" style="font-family:Courier New, Monospace;width:100%;overflow: auto;word-wrap: break-word; white-space:pre ;font-size:13px"></div> </fieldset> </form> </div> </div>'),a.put("views/login.html",'<!--Copyright 2015 Cisco Systems, Inc. All rights reserved.--><!--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.--><!--dialog--> <div class="md-padding dialogdemoBasicUsage" id="popupContainer" ng-cloak=""></div> <div id="page-login" class="row"> <div class="col-xs-12 col-md-6 col-md-offset-3 col-sm-6 col-sm-offset-3" style="background:rgb(236,240,241);padding:1px 20px 20px 20px;border-radius: 20px;border: 10px solid rgb(44,62,80)"> <div class="box"> <div class="box-content"> <div class="text-center"> <h3 class="page-header">LOGIN</h3> </div> <hr style="margin: 10px;border-top-color:rgb(44,62,80)"> <md-radio-group ng-model="mode" ng-init="mode=\'storage\'"> <md-radio-button value="http" class="md-primary" style="display: inline;margin-left: 10">Data Plane Scale Test </md-radio-button> <md-radio-button value="storage" class="md-primary" style="display: inline;margin-left: 10">Storage Scale Test </md-radio-button> </md-radio-group> <hr style="margin: 10px;border-top-color:rgb(44,62,80)"> <h4 ng-show="mode==\'http\'">Server Cloud</h4> <h4 ng-show="mode==\'storage\'">Client Cloud</h4> <div class="form-group"> <!--<div>--> <!--<label>admin_openrc.sh:</label>--> <!--<input class="btn" type="file" id="file1" name="file1" enctype="multipart/form-data" />--> <!--</div>--> <div class="input-group" style="margin:0 auto"> <span class="input-group-addon">openrc.sh</span> <button class="form-control no-js" style="position: relative;z-index: 2"></button> <div class="box js" style="position: absolute;z-index: 3;width: 100%;height:100%;left:50%;top:25%"> <input type="file" name="file1" id="file1" class="inputfile inputfile-3" enctype="multipart/form-data"> <label for="file1"><span>Choose openrc.sh file&hellip;</span></label> </div> </div> <br> <div class="input-group" style="margin:0 auto"> <span class="input-group-addon">Password</span> <input type="password" class="form-control" id="inputPassword1" ng-model="inputPassword1" placeholder="Input Your Server Cloud\'s Password"> </div> </div> <div ng-show="mode==\'http\'"> <hr> <h4>Client Cloud</h4> <div class="checkbox"> <h5> <label> <input type="checkbox" ng-model="samecloud" ng-click="clouds()"> Same as Server Cloud </label> </h5> </div> <div class="form-group"> <!--<div>--> <!--<label>admin_openrc.sh:</label>--> <!--<input class="btn" type="file" id="file2" name="file2" enctype="multipart/form-data" disabled/>--> <!--</div>--> <div class="input-group" style="margin:0 auto"> <span class="input-group-addon">openrc.sh</span> <button class="form-control no-js" id="rcfile2" disabled></button> <div class="box js" style="position: absolute;z-index: 3;width: 100%;height:100%;left:50%;top:25%"> <input type="file" name="file2" id="file2" class="inputfile inputfile-3" enctype="multipart/form-data" disabled> <label for="file2"><span>Choose openrc.sh file&hellip;</span></label> </div> </div> <br> <div class="input-group" style="margin:0 auto"> <span class="input-group-addon">Password</span> <input type="password" class="form-control" id="inputPassword2" ng-model="inputPassword2" placeholder="Input Your Client Cloud\'s Password" disabled> </div> </div> </div> <div class="text-center"> <a href="" class="btn btn-primary" ng-click="setConfig()" style="width: 150px"> Sign In </a> </div> </div> </div> </div> </div> <br>'),a.put("views/run.html",'<!--Copyright 2015 Cisco Systems, Inc. All rights reserved.--><!--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.--><!--<alert ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)" style="background-color:#ffcc99;color:white">{{alert.msg}}</alert>--><!--<h6></h6>--> <div class="row"> <div class="col-md-8"> </div> <div class="col-md-4"> <div style="text-align:right"> <div class="btn-group"> <a href="" class="btn btn-default" ng-click="stage()" ng-disabled="setUnstage" style="width:100px">{{stageButton}}</a> <!--<a herf="" class="btn btn-default" ng-click="setConfig()" ng-disabled="setStatus">Save Settings</a>--> <a href="" class="btn btn-default" ng-click="scaleTest()" ng-disabled="runStatus" style="width:100px">{{runButton}}</a> </div> <!--<button type="submit" class="btn btn-default" ng-click="CleanUp()">Unstage</button>--> <!--<button type="submit" class="btn btn-warning" ng-click="setConfig()" ng-disabled="setStatus">Save Settings</button>--> <!--<button type="submit" class="btn btn-primary" ng-click="scaleTest()" ng-disabled="runStatus">{{runButton}}</button>--> </div> </div> </div> <!--<h4>Triggers</h4>--> <!--<p>--> <!--<button popover="I appeared on mouse enter!" popover-trigger="mouseenter" type="button" class="btn btn-default">Mouseenter</button>--> <!--</p>--> <!--<input type="text" value="Click me!" popover="aa" popover-trigger="focus" class="form-control">--> <div class="supercontainer"> <div class="container"> <div id="sidebar"> <div class=""> <!--Staging--> <accordion close-others="oneAtATime"> <accordion-group heading="" is-open="status1.open"> <accordion-heading> Staging Settings (VM Count:{{config.server.number_tenants*config.server.routers_per_tenant*config.server.networks_per_router*config.server.vms_per_network*config.server.secgroups_per_network}}) <i class="pull-right glyphicon" ng-class="{\'glyphicon-chevron-down\': !status1.open, \'glyphicon-chevron-up\': status1.open}"></i> </accordion-heading> <div class="col-lg-14" id="stagingConfig"> <form class="bs-component" name="interactive_staging_settings" novalidate> <md-content layout-padding style="padding:0"> <md-input-container class="col-md-12" style="padding-top:0"> <label>Tenants</label> <input type="number" min="1" max="9999" step="1" id="number_tenants" ng-model="config.server.number_tenants" name="number_tenants" ng-pattern="/^[1-9][0-9]{0,3}$/i" required style="text-align:left"> <div ng-messages="interactive_staging_settings.number_tenants.$error" ng-if="interactive_staging_settings.number_tenants.$dirty"> <div ng-message="required" style="text-align:left">This field is required</div> <div ng-message="pattern" style="text-align:left">Must be a number between 1 and 9999</div> </div> </md-input-container> <md-input-container class="col-md-12"> <label>Routers/Tenant</label> <input type="number" min="1" max="999" step="1" id="server_routers_per_tenant" ng-model="config.server.routers_per_tenant" name="server_routers_per_tenant" ng-pattern="/^[1-9][0-9]{0,2}$/i" required style="text-align:left"> <div ng-messages="interactive_staging_settings.server_routers_per_tenant.$error" ng-if="interactive_staging_settings.server_routers_per_tenant.$dirty"> <div ng-message="required" style="text-align:left">This field is required</div> <div ng-message="pattern" style="text-align:left">Must be a number between 1 and 999</div> </div> </md-input-container> <md-input-container class="col-md-12"> <label>Networks/Router</label> <input type="number" min="1" max="999" step="1" id="server_networks_per_router" ng-model="config.server.networks_per_router" name="server_networks_per_router" ng-pattern="/^[1-9][0-9]{0,2}$/i" required style="text-align:left"> <div ng-messages="interactive_staging_settings.server_networks_per_router.$error" ng-if="interactive_staging_settings.server_networks_per_router.$dirty"> <div ng-message="required" style="text-align:left">This field is required</div> <div ng-message="pattern" style="text-align:left">Must be a number between 1 and 999</div> </div> </md-input-container> <md-input-container class="col-md-12"> <label>VMs/Network</label> <input type="number" min="1" max="999" step="1" id="server_vms_per_network" ng-model="config.server.vms_per_network" name="server_vms_per_network" ng-pattern="/^[1-9][0-9]{0,2}$/i" required style="text-align:left"> <div ng-messages="interactive_staging_settings.server_vms_per_network.$error" ng-if="interactive_staging_settings.server_vms_per_network.$dirty"> <div ng-message="required" style="text-align:left">This field is required</div> <div ng-message="pattern" style="text-align:left">Must be a number between 1 and 999</div> </div> </md-input-container> <md-input-container class="col-md-12"> <label>Secgroups/Network</label> <input type="number" min="1" max="999" step="1" id="server_secgroups_per_network" ng-model="config.server.secgroups_per_network" name="server_secgroups_per_network" ng-pattern="/^[1-9][0-9]{0,2}$/i" required style="text-align:left"> <div ng-messages="interactive_staging_settings.server_secgroups_per_network.$error" ng-if="interactive_staging_settings.server_secgroups_per_network.$dirty"> <div ng-message="required" style="text-align:left">This field is required</div> <div ng-message="pattern" style="text-align:left">Must be a number between 1 and 999</div> </div> </md-input-container> </md-content> <!--<div class="input-group col-sm-12" style="margin:0 auto"--> <!--popover="Number of tenants to be created on the cloud" popover-trigger="mouseenter"--> <!--popover-placement="right">--> <!--<span class="input-group-addon">Tenants</span>--> <!--<input type="number" min="1" max="9999" step="1" class="form-control" id="number_tenants"--> <!--ng-model="config.server.number_tenants" name="number_tenants" ng-pattern="/^[1-9][0-9]{0,3}$/i"--> <!--required/>--> <!--</div>--> <!--<div ng-messages="interactive_staging_settings.number_tenants.$error"--> <!--ng-if="interactive_staging_settings.number_tenants.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number between 1 and 9999</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto"--> <!--popover="Number of routers to be created within the context of each User"--> <!--popover-trigger="mouseenter" popover-placement="right">--> <!--<span class="input-group-addon">Routers/Tenant</span>--> <!--<input type="number" min="1" max="999" step="1" class="form-control" id="server_routers_per_tenant"--> <!--ng-model="config.server.routers_per_tenant" name="server_routers_per_tenant"--> <!--ng-pattern="/^[1-9][0-9]{0,2}$/i" required/>--> <!--</div>--> <!--<div ng-messages="interactive_staging_settings.server_routers_per_tenant.$error"--> <!--ng-if="interactive_staging_settings.server_routers_per_tenant.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number between 1 and 999</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto"--> <!--popover="Number of networks to be created within the context of each Router"--> <!--popover-trigger="mouseenter" popover-placement="right">--> <!--<span class="input-group-addon">Networks/Router</span>--> <!--<input type="number" min="1" max="999" step="1" class="form-control" id="server_networks_per_router"--> <!--ng-model="config.server.networks_per_router" name="server_networks_per_router"--> <!--ng-pattern="/^[1-9][0-9]{0,2}$/i" required/>--> <!--</div>--> <!--<div ng-messages="interactive_staging_settings.server_networks_per_router.$error"--> <!--ng-if="interactive_staging_settings.server_networks_per_router.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number between 1 and 999</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto"--> <!--popover="Number of VM instances to be created within the context of each Network"--> <!--popover-trigger="mouseenter" popover-placement="right">--> <!--<span class="input-group-addon">VMs/Network</span>--> <!--<input type="number" min="1" max="999" step="1" class="form-control" id="server_vms_per_network"--> <!--ng-model="config.server.vms_per_network" name="server_vms_per_network"--> <!--ng-pattern="/^[1-9][0-9]{0,2}$/i" required/>--> <!--</div>--> <!--<div ng-messages="interactive_staging_settings.server_vms_per_network.$error"--> <!--ng-if="interactive_staging_settings.server_vms_per_network.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number between 1 and 999</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="Number of security groups per network"--> <!--popover-trigger="mouseenter" popover-placement="right">--> <!--<span class="input-group-addon">Secgroups/Network</span>--> <!--<input type="number" min="1" max="999" step="1" class="form-control"--> <!--id="server_secgroups_per_network" ng-model="config.server.secgroups_per_network"--> <!--name="server_secgroups_per_network" ng-pattern="/^[1-9][0-9]{0,2}$/i" required/>--> <!--</div>--> <!--<div ng-messages="interactive_staging_settings.server_secgroups_per_network.$error"--> <!--ng-if="interactive_staging_settings.server_secgroups_per_network.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number between 1 and 999</div>--> <!--</div>--> </form> </div> </accordion-group> <!--Run--> <accordion-group heading="" is-open="status2.open"> <accordion-heading> Progression Test <i class="pull-right glyphicon" ng-class="{\'glyphicon-chevron-down\': !status2.open, \'glyphicon-chevron-up\': status2.open}"></i> </accordion-heading> <div class="col-lg-14" id="stagingConfig1"> <form class="bs-component" name="interactive_progression_settings"> <div class="input-group col-sm-12" style="margin:0 auto" popover="If enabled, KloudBuster will give multiple runs (progression) on the cloud, unless it reaches the scale defined in the upper sections, or the stop limit." popover-trigger="mouseenter" popover-placement="right"> <md-checkbox id="client_progression_enabled" ng-model="config.client.progression.enabled" class="md-primary"> Progression Test </md-checkbox> </div> <!--<br/>--> <md-content layout-padding style="padding:0"> <md-input-container class="col-md-12"> <label>Series VM multiple</label> <input type="number" min="1" step="1" id="client_progression_vm_multiple" ng-model="config.client.progression.vm_multiple" ng-disabled="!config.client.progression.enabled" name="client_progression_vm_multiple" ng-pattern="/^[1-9][0-9]*$/i" required style="text-align:left"> <div ng-messages="interactive_progression_settings.client_progression_vm_multiple.$error" ng-if="interactive_progression_settings.client_progression_vm_multiple.$dirty"> <div ng-message="required">This field is required</div> <div ng-message="pattern">Must be a number no less than 1</div> </div> </md-input-container> <div class="input-group col-sm-12" style="margin:0 auto;padding-left: 7px"> <md-checkbox id="client_progression_vm_start" ng-checked="config.client.progression.vm_start==1" ng-click="config.client.progression.vm_start==1? config.client.progression.vm_start=0:config.client.progression.vm_start=1" class="md-primary" ng-disabled="!config.client.progression.enabled"> Start series with 1 VM </md-checkbox> </div> <md-input-container class="col-md-12"> <label>Stop When Num of Err Packets ></label> <input type="number" min="1" step="1" id="client_progression_http_stop_limit0" ng-model="config.client.progression.http_stop_limit[0]" ng-disabled="!config.client.progression.enabled" name="client_progression_http_stop_limit0" ng-pattern="/^[1-9][0-9]*$/i" required style="text-align:left"> <div ng-messages="interactive_progression_settings.client_progression_http_stop_limit0.$error" ng-if="interactive_progression_settings.client_progression_http_stop_limit0.$dirty"> <div ng-message="required">This field is required</div> <div ng-message="pattern">Must be a number no less than 1</div> </div> </md-input-container> </md-content> <span class="label col-md-12" style="color:grey;text-align: left">VM count series: {{config.client.progression.vm_start==1?1:\'\'}} {{config.client.progression.vm_multiple}} {{config.client.progression.vm_multiple*2}} {{config.client.progression.vm_multiple*3}} {{config.client.progression.vm_multiple*4}} {{config.client.progression.vm_multiple*5}}... </span> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="The starting count of VMs"--> <!--popover-trigger="mouseenter" popover-placement="right">--> <!--<span class="input-group-addon">VM Count Start</span>--> <!--<input type="number" min="1" step="1" class="form-control" id="client_progression_vm_start"--> <!--ng-model="config.client.progression.vm_start"--> <!--ng-disabled="!config.client.progression.enabled" name="client_progression_vm_start"--> <!--ng-pattern="/^[1-9][0-9]*$/i" required/>--> <!--</div>--> <!--<div ng-messages="interactive_progression_settings.client_progression_vm_start.$error"--> <!--ng-if="interactive_progression_settings.client_progression_vm_start.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number no less than 1</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto"--> <!--popover="The steping for the VM count for each stage" popover-trigger="mouseenter"--> <!--popover-placement="right">--> <!--<span class="input-group-addon">VM Increment Step</span>--> <!--<input type="number" min="1" step="1" class="form-control" id="client_progression_vm_step"--> <!--ng-model="config.client.progression.vm_step" ng-disabled="!config.client.progression.enabled"--> <!--name="client_progression_vm_step" ng-pattern="/^[1-9][0-9]*$/i" required/>--> <!--</div>--> <!--<div ng-messages="interactive_progression_settings.client_progression_vm_step.$error"--> <!--ng-if="interactive_progression_settings.client_progression_vm_step.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number no less than 1</div>--> <!--</div>--> <!--<br/>--> <!--Stop When--> <!--<div class="input-group col-sm-12" style="margin:0 auto"--> <!--popover="KloudBuster will continue the progression run only if the error count of packets are less or equal than this number"--> <!--popover-trigger="mouseenter" popover-placement="right">--> <!--<span class="input-group-addon">Num of Err Packets > </span>--> <!--<input type="number" min="1" step="1" class="form-control" id="client_progression_stop_limit0"--> <!--ng-model="config.client.progression.stop_limit[0]"--> <!--ng-disabled="!config.client.progression.enabled" name="client_progression_stop_limit0"--> <!--ng-pattern="/^[1-9][0-9]*$/i" required/>--> <!--</div>--> <!--<div ng-messages="interactive_progression_settings.client_progression_stop_limit0.$error"--> <!--ng-if="interactive_progression_settings.client_progression_stop_limit0.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number no less than 1</div>--> <!--</div>--> <!--OR--> <!--<div class="input-group col-sm-12" style="margin:0 auto">--> <!--<span class="input-group-addon">Percentile:</span>--> <!--<select class="form-control" id="client_progression_stop_limit1" ng-model="config.client.progression.stop_limit[1]" ng-disabled="!config.client.progression.enabled" convert-to-number>--> <!--<option value="50">50%</option>--> <!--<option value="75">75%</option>--> <!--<option value="90">90%</option>--> <!--<option value="99">99%</option>--> <!--<option value="99.9">99.9%</option>--> <!--<option value="99.99">99.99%</option>--> <!--<option value="99.999">99.999%</option>--> <!--</select>--> <!--</div>--> </form> </div> <!--Run--> </accordion-group> <accordion-group is-open="status3.open"> <accordion-heading> Run Settings <i class="pull-right glyphicon" ng-class="{\'glyphicon-chevron-down\': !status3.open, \'glyphicon-chevron-up\': status3.open}"></i> </accordion-heading> <div class="col-lg-14" id="runningConfig"> <form class="bs-component" name="interactive_running_settings"> <md-content layout-padding style="padding:0"> <md-input-container class="col-md-12" style="padding-top:0"> <label>Duration/Run (sec)</label> <input type="number" min="1" max="" step="1" id="client_duration" ng-model="config.client.http_tool_configs.duration" name="client_duration" ng-pattern="/^[1-9][0-9]*$/i" required style="text-align:left"> <div ng-messages="interactive_running_settings.client_duration.$error" ng-if="interactive_running_settings.client_duration.$dirty"> <div ng-message="required">This field is required</div> <div ng-message="pattern">Must be a number no less than 1</div> </div> </md-input-container> <md-input-container class="col-md-12"> <label>Rate Limit/VM</label> <input type="number" min="0" max="" step="1000" id="client_rate_limit" ng-model="config.client.http_tool_configs.rate_limit" name="client_rate_limit" ng-pattern="/^[0-9]*$/i" required style="text-align:left"> <div ng-messages="interactive_running_settings.client_rate_limit.$error" ng-if="interactive_running_settings.client_rate_limit.$dirty"> <div ng-message="required">This field is required</div> <div ng-message="pattern">Must be a number no less than 0</div> </div> </md-input-container> <md-input-container class="col-md-12"> <label>Connections/VM</label> <input type="number" min="0" max="" step="1000" id="client_connections" ng-model="config.client.http_tool_configs.connections" name="client_connections" ng-pattern="/^[1-9][0-9]*$/i" required style="text-align:left"> <div ng-messages="interactive_running_settings.client_connections.$error" ng-if="interactive_running_settings.client_connections.$dirty"> <div ng-message="required">This field is required</div> <div ng-message="pattern">Must be a number no less than 1</div> </div> </md-input-container> </md-content> <!--<div class="input-group col-sm-12" style="margin:0 auto">--> <!--<span class="input-group-addon">connection Type:</span>--> <!--<input type="text" class="form-control" id="client_connection_type" ng-model="config.client.http_tool_configs.connection_type"/>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto" popover="Duration of testing tools"--> <!--popover-trigger="mouseenter" popover-placement="right">--> <!--<span class="input-group-addon">Duration/Run (sec)</span>--> <!--<input type="number" min="1" max="" step="1" class="form-control" id="client_duration"--> <!--ng-model="config.client.http_tool_configs.duration" name="client_duration"--> <!--ng-pattern="/^[1-9][0-9]*$/i" required/>--> <!--</div>--> <!--<div ng-messages="interactive_running_settings.client_duration.$error"--> <!--ng-if="interactive_running_settings.client_duration.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number no less than 1</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto">--> <!--<span class="input-group-addon">Reporting Interval:</span>--> <!--<input type="number" min="0" max="" step="10" class="form-control" id="report_interval" ng-model="config.client.http_tool_configs.report_interval"/>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto"--> <!--popover="Rate limit in RPS per client (0 for unlimited)" popover-trigger="mouseenter"--> <!--popover-placement="right">--> <!--<span class="input-group-addon">Rate Limit/VM</span>--> <!--<input type="number" min="0" max="" step="1000" class="form-control" id="client_rate_limit"--> <!--ng-model="config.client.http_tool_configs.rate_limit" name="client_rate_limit"--> <!--ng-pattern="/^[0-9]*$/i" required/>--> <!--</div>--> <!--<div ng-messages="interactive_running_settings.client_rate_limit.$error"--> <!--ng-if="interactive_running_settings.client_rate_limit.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number no less than 0</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto"--> <!--popover="Connections to be kept concurrently per VM. This number also corresponds to the number of HTTP users connected at any time to the matching HTTP server"--> <!--popover-trigger="mouseenter" popover-placement="right">--> <!--<span class="input-group-addon">Connections/VM</span>--> <!--<input type="number" min="0" max="" step="1000" class="form-control"--> <!--id="client_connections" ng-model="config.client.http_tool_configs.connections"--> <!--name="client_connections" ng-pattern="/^[1-9][0-9]*$/i" required/>--> <!--</div>--> <!--<div ng-messages="interactive_running_settings.client_connections.$error"--> <!--ng-if="interactive_running_settings.client_connections.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number no less than 1</div>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto">--> <!--<span class="input-group-addon">Threads:</span>--> <!--<input type="number" min="0" max="" step="10" class="form-control" id="client_threads" ng-model="config.client.http_tool_configs.threads"/>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto">--> <!--<span class="input-group-addon">Timeout:</span>--> <!--<input type="number" min="0" max="" step="5" class="form-control" id="client_timeout" ng-model="config.client.http_tool_configs.timeout"/>--> <!--</div>--> <!--<br/>--> <!--<div class="input-group col-sm-12" style="margin:0 auto">--> <!--<span class="input-group-addon">Polling Interval:</span>--> <!--<input type="number" min="0" max="" step="5" class="form-control" id="client_polling_interval" ng-model="config.client.polling_interval"/>--> <!--</div>--> </form> </div> </accordion-group> </accordion> </div> </div> <div class="main-content"> <div class="swipe-area"></div> <a href="" data-toggle=".container" id="sidebar-toggle" style="text-decoration:none"> <!--<span class="bar"></span>--> <!--<span class="bar"></span>--> <!--<span class="bar"></span>--> <span id="littleglyph" class="bar glyphicon glyphicon-triangle-right" style="color:white"></span> </a> <div class="content" id="content"> <div class="row"> <div class=""> <h6>Latency(ms)</h6> <linechart data="data" options="options" mode="" width="" height="430"></linechart> </div> </div> </div> </div> </div> </div> <!--<div class="btn-group" style="margin-bottom: 20px;float:right;">--> <!--<a href="" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown" aria-expanded="true">--> <!--cols to show--> <!--<span class="caret"></span>--> <!--</a>--> <!--<ul class="dropdown-menu">--> <!--<li class="checkbox-inline" ng-repeat="col in cols" style="margin-left: 5px;">--> <!--<input type="checkbox" ng-model="col.show">{{col.title}}--> <!--</li>--> <!--</ul>--> <!--</div>--> <div class="row" style="text-align:right;margin: 0 1%"> <button type="submit" class="btn btn-default btn-xs" ng-click="saveResult()">Save Result</button> </div> <br> <table ng-table="tableParams" class="table table-responsive table-condensed table-bordered table-striped" style="margin-bottom: 5%"> <tr ng-repeat="row in tableParams.data" style="text-align:center"> <td title="cols[0].title" ng-if="cols[0].show" style="margin:0 auto;padding:0"> <md-checkbox class="{{row.seq}}" ng-click="" popover="{{row.description}}" popover-trigger="mouseenter" popover-placement="right" style="margin:0 auto;width:18px;padding:0" ng-checked="true"></md-checkbox> </td> <td title="cols[1].title" data-sortable="cols[1].field" ng-if="cols[1].show">{{row.connection}}</td> <td title="cols[2].title" data-sortable="cols[2].field" ng-if="cols[2].show">{{row.server_vms}}</td> <td title="cols[3].title" data-sortable="cols[3].field" ng-if="cols[3].show">{{row.requests}}</td> <td title="cols[4].title" data-sortable="cols[4].field" ng-if="cols[4].show">{{row.sock_err}}</td> <td title="cols[5].title" data-sortable="cols[5].field" ng-if="cols[5].show">{{row.rps}}</td> <td title="cols[6].title" data-sortable="cols[6].field" ng-if="cols[6].show">{{row.rate_limit}}</td> <td title="cols[7].title" data-sortable="cols[7].field" ng-if="cols[7].show">{{row.throughput}} Gbps</td> <!--<td title="cols[8].title" ng-if="cols[8].show" width="80px" style="margin:0 auto;padding:0;">--> <!--&lt;!&ndash;{{$index}}&ndash;&gt;--> <!--<button class="btn btn-default btn-xs" ng-click="saveResult($index)" style="height: 22px;width: 24px;"><span--> <!--class="glyphicon glyphicon-floppy-save"></span></button>--> <!--<button class="btn btn-danger btn-xs" ng-click="delData($index)" disabled style="height: 22px;width: 24px;"><span--> <!--class="glyphicon glyphicon-trash"></span></button>--> <!--</td>--> </tr> </table> <div class="navbar navbar-default navbar-fixed-bottom" role="navigation" style="min-height: 48px;background: transparent"> <div style="height: 12px;background-color: transparent;width: 100%;margin:0;border:0;padding:0"></div> <div style="background: white; width: 52px; height: 52px;border-radius: 50%;position:absolute;z-index: 10;top:0;left:60px"> <div class="loading spin-1"> <div class="loading spin-2"> <div class="loading spin-3"> <div class="loading spin-4"> <div class="loading spin-5"> <div class="loading spin-6"></div> </div> </div> </div> </div> </div> </div> <div style="background: rgb(44,62,80);width: 100%;height: 36px;margin:0;border:0;padding:0"> <div style="margin: 0 80px 0 120px;vertical-align: middle"> <h5> <div class="row"> <div class="col-md-2 col-xs-2" style="line-height:33px; height:20px; color:white"> <!--Status:--> <button class="btn {{statusButton}} btn-xs" ng-click="checkStatus()" style="height:24px">{{status}} </button> </div> <div class="col-md-6 col-xs-6" style="line-height:35px; height:20px; color:white">Created&nbsp; <button class="btn btn-primary btn-xs" ng-click="checkStatus()" style="height:24px">{{server_vm_count}} </button> &nbsp;Server VM(s),&nbsp; <button class="btn btn-primary btn-xs" ng-click="checkStatus()" style="height:24px">{{client_vm_count}} </button> &nbsp;Client VM(s). </div> <div class="col-md-4 col-xs-4" style="line-height:33px; height:20px; color:white" ng-show="info"> <button class="btn btn-xs btn-info" style="width:220px;text-align: left">{{info}}</button> </div> </div> <!--sessionID: <button class="btn btn-info btn-xs" disabled>{{sessionID}}</button>--> <!--<button style="float:right;" type="submit" class="btn btn-default btn-xs" ng-click="deleteSession()" popover="Session can be destroyed only if it is at READY." popover-trigger="mouseenter">Del Ses</button>--> </h5> </div> </div> </div> <!--<div class="navbar navbar-default navbar-fixed-bottom" role="navigation" style="min-height: 72px;">--> <!--<div style="height: 32px;background-color: white;width: 100%;position:relative;z-index: 4;"></div>--> <!--<div class=""--> <!--style="background: white; width: 64px;height: 64px;border-radius: 50%;position:absolute;z-index: 10;top:1px;left:60px;">--> <!--<div class=\'loading spin-1\'>--> <!--<div class=\'loading spin-2\'>--> <!--<div class=\'loading spin-3\'>--> <!--<div class=\'loading spin-4\'>--> <!--<div class=\'loading spin-5\'>--> <!--<div class=\'loading spin-6\'></div>--> <!--</div>--> <!--</div>--> <!--</div>--> <!--</div>--> <!--</div>--> <!--</div>--> <!--<div style="margin: 0 100px 0 130px;vertical-align: middle;position:relative;z-index: 4;">--> <!--<h5>--> <!--<div class="row">--> <!--<div class="col-md-2 col-xs-2" style="line-height:20px; height:20px; color:white;">--> <!--&lt;!&ndash;Status:&ndash;&gt;--> <!--<button class="btn {{statusButton}} btn-xs" ng-click="checkStatus()" style="height:24px;">{{status}}</button>--> <!--</div>--> <!--<div class="col-md-6 col-xs-6" style="line-height:20px; height:20px; color:white;">Created&nbsp;--> <!--<button class="btn btn-primary btn-xs" ng-click="checkStatus()" style="height:24px;">{{server_vm_count}}--> <!--</button>--> <!--&nbsp;Server VM(s),&nbsp;--> <!--<button class="btn btn-primary btn-xs" ng-click="checkStatus()" style="height:24px;">{{client_vm_count}}--> <!--</button>--> <!--&nbsp;Client VM(s).--> <!--</div>--> <!--<div class="col-md-4 col-xs-4" style="line-height:20px; height:20px; color:white;" ng-show="info">--> <!--<button class="btn btn-xs btn-info">{{info}}</button>--> <!--</div>--> <!--</div>--> <!--&lt;!&ndash;sessionID: <button class="btn btn-info btn-xs" disabled>{{sessionID}}</button>&ndash;&gt;--> <!--&lt;!&ndash;<button style="float:right;" type="submit" class="btn btn-default btn-xs" ng-click="deleteSession()" popover="Session can be destroyed only if it is at READY." popover-trigger="mouseenter">Del Ses</button>&ndash;&gt;--> <!--</h5>--> <!--</div>--> <!--</div>-->'),
a.put("views/run_storage.html",'<!--Copyright 2016 Cisco Systems, Inc. All rights reserved.--><!--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.--> <div class="row"> <!--<div class="col-md-2">--> <!--<h3>{{current_mode["title"]}}</h3>--> <!--</div>--> <div class="col-md-9"> <!--<a class="btn btn-primary btn-xs" style="margin: 1%;" ng-repeat="mode in modes" ng-class="{active: current_index==$index}"--> <!--ng-click="handleEvent($event, $index)">{{mode.title}}--> <!--</a>--> <!--<ul class="nav nav-tabs">--> <!--<li ng-repeat="mode in modes" ng-class="{active: current_index==$index}" ng-click="handleEvent($event, $index)">--> <!--<a href="" data-toggle="tab" aria-expanded="true">{{mode.title}}</a>--> <!--</li>--> <!--</ul>--> <ul class="nav nav-tabs"> <li ng-repeat="tag in config.client.storage_tool_configs" ng-class="{active: current_index==$index}" ng-click="handleEvent($event, $index,\'\')"> <a data-toggle="tab" aria-expanded="true"> {{tag.description}} <span class="{{modes[tag.mode][\'span\']}}"></span> </a> </li> </ul> </div> <div class="col-md-3"> <div style="text-align:right"> <div class="btn-group"> <a href="" class="btn btn-default" ng-click="stage()" ng-disabled="setUnstage" style="width:100px">{{stageButton}}</a> <a href="" class="btn btn-default" ng-click="scaleTest()" ng-disabled="runStatus" style="width:100px">{{runButton}}</a> </div> </div> </div> </div> <div class="supercontainer"> <div class="container"> <div id="sidebar"> <div class=""> <!--Staging--> <accordion close-others="oneAtATime"> <accordion-group heading="" is-open="status1.open"> <accordion-heading> Settings <!--(VM--> <!--Count:{{config.server.number_tenants*config.server.routers_per_tenant*config.server.networks_per_router*config.server.vms_per_network*config.server.secgroups_per_network}})--> <i class="pull-right glyphicon" ng-class="{\'glyphicon-chevron-down\': !status1.open, \'glyphicon-chevron-up\': status1.open}"></i> </accordion-heading> <div class="col-lg-14" id="stagingConfig"> <form class="bs-component" name="interactive_staging_settings"> <md-content layout-padding style="padding:0"> <md-input-container class="col-md-12"> <label>Max VM</label> <input type="number" min="1" max="999" step="1" id="storage_stage_configs_vm_count" ng-model="config.client.storage_stage_configs.vm_count" name="storage_stage_configs_vm_count" ng-pattern="/^[1-9][0-9]{0,2}$/i" required style="text-align:left"> <div ng-messages="interactive_staging_settings.storage_stage_configs_vm_count.$error" ng-if="interactive_staging_settings.storage_stage_configs_vm_count.$dirty"> <div ng-message="required" style="text-align:left">This field is required</div> <div ng-message="pattern" style="text-align:left">Must be a number between 1 and 999</div> </div> </md-input-container> </md-content> </form> </div> </accordion-group> <!--Run--> <accordion-group heading="" is-open="status2.open"> <accordion-heading> Progression Test <i class="pull-right glyphicon" ng-class="{\'glyphicon-chevron-down\': !status2.open, \'glyphicon-chevron-up\': status2.open}"></i> </accordion-heading> <div class="col-lg-14" id="stagingConfig1"> <form class="bs-component" name="interactive_progression_settings"> <div class="input-group col-sm-12" style="margin:0 auto" popover="If enabled, KloudBuster will give multiple runs (progression) on the cloud, unless it reaches the scale defined in the upper sections, or the stop limit." popover-trigger="mouseenter" popover-placement="right"> <md-checkbox id="client_progression_enabled" ng-model="config.client.progression.enabled" class="md-primary"> Progression Test </md-checkbox> </div> <!--<br/>--> <md-content layout-padding style="padding:0"> <!--<md-input-container class="col-md-12" style="padding-top:0">--> <!--<label>VM Count Start</label>--> <!--<input type="number" min="1" step="1" id="client_progression_vm_start"--> <!--ng-model="config.client.progression.vm_start"--> <!--ng-disabled="!config.client.progression.enabled" name="client_progression_vm_start"--> <!--ng-pattern="/^[1-9][0-9]*$/i" required style="text-align:left;"/>--> <!--<div ng-messages="interactive_progression_settings.client_progression_vm_start.$error"--> <!--ng-if="interactive_progression_settings.client_progression_vm_start.$dirty">--> <!--<div ng-message="required">This field is required</div>--> <!--<div ng-message="pattern">Must be a number no less than 1</div>--> <!--</div>--> <!--</md-input-container>--> <md-input-container class="col-md-12"> <label>Series VM multiple</label> <input type="number" min="1" step="1" id="client_progression_vm_multiple" ng-model="config.client.progression.vm_multiple" ng-disabled="!config.client.progression.enabled" name="client_progression_vm_multiple" ng-pattern="/^[1-9][0-9]*$/i" required style="text-align:left"> <div ng-messages="interactive_progression_settings.client_progression_vm_multiple.$error" ng-if="interactive_progression_settings.client_progression_vm_multiple.$dirty"> <div ng-message="required">This field is required</div> <div ng-message="pattern">Must be a number no less than 1</div> </div> </md-input-container> <div class="input-group col-sm-12" style="margin:0 auto;padding-left: 7px"> <md-checkbox id="client_progression_vm_start" ng-checked="config.client.progression.vm_start==1" ng-click="config.client.progression.vm_start==1? config.client.progression.vm_start=0:config.client.progression.vm_start=1" class="md-primary" ng-disabled="!config.client.progression.enabled"> Start series with 1 VM </md-checkbox> </div> <md-input-container class="col-md-12"> <label>Stop Limit (%)</label> <input type="number" min="1" step="1" id="client_progression_storage_stop_limit" ng-model="config.client.progression.storage_stop_limit" ng-disabled="!config.client.progression.enabled" name="client_progression_http_stop_limit" ng-pattern="/^[1-9][0-9]*$/i" required style="text-align:left"> <div ng-messages="interactive_progression_settings.client_progression_http_stop_limit0.$error" ng-if="interactive_progression_settings.client_progression_http_stop_limit0.$dirty"> <div ng-message="required">This field is required</div> <div ng-message="pattern">Must be a number no less than 1</div> </div> </md-input-container> <span class="label col-md-12" style="color:grey;text-align: left">VM count series: {{config.client.progression.vm_start==1?1:\'\'}} {{config.client.progression.vm_multiple}} {{config.client.progression.vm_multiple*2}} {{config.client.progression.vm_multiple*3}} {{config.client.progression.vm_multiple*4}} {{config.client.progression.vm_multiple*5}}... </span> </md-content> </form> </div> <!--Run--> </accordion-group> </accordion> </div> </div> <div class="main-content"> <div class="swipe-area"></div> <a href="" data-toggle=".container" id="sidebar-toggle" style="text-decoration:none"> <!--<span class="bar"></span>--> <!--<span class="bar"></span>--> <!--<span class="bar"></span>--> <span id="littleglyph" class="bar glyphicon glyphicon-triangle-right" style="color:white"></span> </a> <div class="content" id="content"> <div class="row"> <div class="my-chart" style=""> <!--<ul class="nav nav-pills" ng-style="{height:current_mode_name ==\'rw\' || current_mode_name ==\'randrw\'?\'\':0, width:current_mode_name ==\'rw\' || current_mode_name ==\'randrw\'?\'\':0}">--> <!--<li ng-show="current_mode_name ==\'rw\' || current_mode_name ==\'randrw\'" ng-class="{active:current_mode[\'name\']==\'read\' || current_mode[\'name\']==\'randread\'}">--> <!--<a ng-click="handleEvent($event, current_index,\'read\')">Read</a>--> <!--</li>--> <!--<li ng-show="current_mode_name ==\'rw\' || current_mode_name ==\'randrw\'" ng-class="{active:current_mode[\'name\']==\'write\' || current_mode[\'name\']==\'randwrite\'}">--> <!--<a ng-click="handleEvent($event, current_index,\'write\')">Write</a>--> <!--</li>--> <!--</ul>--> <ul class="nav nav-tabs" ng-style="{height:current_mode_name ==\'rw\' || current_mode_name ==\'randrw\'?\'\':0, width:current_mode_name ==\'rw\' || current_mode_name ==\'randrw\'?\'\':0}"> <li ng-show="current_mode_name ==\'rw\' || current_mode_name ==\'randrw\'" ng-class="{active:current_mode[\'name\']==\'read\' || current_mode[\'name\']==\'randread\'}"> <a ng-click="handleEvent($event, current_index,\'read\')">Read</a> </li> <li ng-show="current_mode_name ==\'rw\' || current_mode_name ==\'randrw\'" ng-class="{active:current_mode[\'name\']==\'write\' || current_mode[\'name\']==\'randwrite\'}"> <a ng-click="handleEvent($event, current_index,\'write\')">Write</a> </li> </ul> <!--<div>--> <!--<a style="text-decoration: none;cursor: pointer;color:black"--> <!--ng-show="current_mode[\'name\']!=current_mode_name && current_mode_name ==\'rw\'" ng-style="current_mode[\'name\']==\'read\'?{\'font-weight\':\'bold\'}:{};">| Read </a>--> <!--<a style="text-decoration: none;cursor: pointer;color:black" ng-click="handleEvent($event, current_index,\'write\')"--> <!--ng-show="current_mode[\'name\']!=current_mode_name && current_mode_name ==\'rw\'" ng-style="current_mode[\'name\']==\'write\'?{\'font-weight\':\'bold\'}:{};">| Write |</a>--> <!--<a style="text-decoration: none;cursor: pointer;color:black" ng-click="handleEvent($event, current_index,\'read\')"--> <!--ng-show="current_mode[\'name\']!=current_mode_name && current_mode_name ==\'randrw\'" ng-style="current_mode[\'name\']==\'randread\'?{\'font-weight\':\'bold\'}:{};">| Read </a>--> <!--<a style="text-decoration: none;cursor: pointer;color:black" ng-click="handleEvent($event, current_index,\'write\')"--> <!--ng-show="current_mode[\'name\']!=current_mode_name && current_mode_name ==\'randrw\'" ng-style="current_mode[\'name\']==\'randwrite\'?{\'font-weight\':\'bold\'}:{};">| Write |</a>--> <!--</div>--> <h4 style="text-align: center">{{modes[current_mode_name][\'title\']}} {{current_title}} ({{current_mode_description}})</h4> <h6 style="margin-bottom:0"><span>{{current_mode["y_axis"]}}</span><span style="float:right">Latency(ms)</span></h6> <linechart data="data" options="options" height="500"></linechart> </div> </div> </div> </div> </div> </div> <div class="row" style="text-align:right;margin: 0 1%"> <button type="submit" class="btn btn-default btn-xs" ng-click="saveResult()">Save Result</button> </div> <br> <table ng-table="tableParams" class="table table-responsive table-condensed table-bordered table-striped"> <tr ng-repeat="row in tableParams.data" style="text-align:center"> <!--<td title="cols[0].title" ng-if="cols[0].show" style="margin:0 auto;padding:0;">--> <!--<button class="btn btn-default btn-xs {{row.seq}}" ng-click=""--> <!--style="height: 22px;width: 24px;"></button>--> <!--</td>--> <!--<td title="cols[1].title" data-sortable="cols[1].field">{{row.mode}}</td>--> <td title="cols[2].title" data-sortable="cols[2].field">{{row.total_client_vms}}</td> <td title="cols[3].title" data-sortable="cols[3].field">{{row.block_size}}b</td> <td title="cols[4].title" data-sortable="cols[4].field">{{row.iodepth}}</td> <td title="cols[5].title" data-sortable="cols[5].field" ng-if="current_mode.group[0] == \'rand\'"> {{row.rate_iops}} </td> <td title="cols[6].title" data-sortable="cols[6].field" ng-if="current_mode.group[1] == \'read\'"> {{row.read_iops}} </td> <td title="cols[7].title" data-sortable="cols[7].field" ng-if="current_mode.group[1] == \'write\'"> {{row.write_iops}} </td> <td title="cols[8].title" data-sortable="cols[8].field" ng-if="current_mode.group[0] == \'seq\'"> {{row.rate}} KB/s </td> <td title="cols[9].title" data-sortable="cols[9].field" ng-if="current_mode.group[1] == \'read\'"> {{row.read_bw}} KB/s </td> <td title="cols[10].title" data-sortable="cols[10].field" ng-if="current_mode.group[1] == \'write\'"> {{row.write_bw}} KB/s </td> </tr> </table> <h6 style="margin-bottom: 3%">&nbsp;</h6> <div class="navbar navbar-default navbar-fixed-bottom" role="navigation" style="min-height: 48px;background: transparent"> <div style="height: 12px;background-color: transparent;width: 100%;margin:0;border:0;padding:0"></div> <div style="background: white; width: 52px; height: 52px;border-radius: 50%;position:absolute;z-index: 10;top:0;left:60px"> <div class="loading spin-1"> <div class="loading spin-2"> <div class="loading spin-3"> <div class="loading spin-4"> <div class="loading spin-5"> <div class="loading spin-6"></div> </div> </div> </div> </div> </div> </div> <div style="background: rgb(44,62,80);width: 100%;height: 36px;margin:0;border:0;padding:0"> <div style="margin: 0 80px 0 120px;vertical-align: middle"> <h5> <div class="row"> <div class="col-md-2 col-xs-2" style="line-height:33px; height:20px; color:white"> <!--Status:--> <button class="btn {{statusButton}} btn-xs" ng-click="checkStatus()" style="height:24px">{{status}} </button> </div> <div class="col-md-6 col-xs-6" style="line-height:35px; height:20px; color:white">Created&nbsp; <!--<button class="btn btn-primary btn-xs" ng-click="checkStatus()" style="height:24px;">{{server_vm_count}}--> <!--</button>--> <!--&nbsp;Server VM(s),&nbsp;--> <button class="btn btn-primary btn-xs" ng-click="checkStatus()" style="height:24px">{{client_vm_count}} </button> &nbsp;Client VM(s). </div> <div class="col-md-4 col-xs-4" style="line-height:33px; height:20px; color:white" ng-show="info"> <button class="btn btn-xs btn-info" style="width:220px;text-align: left">{{info}}</button> </div> </div> <!--sessionID: <button class="btn btn-info btn-xs" disabled>{{sessionID}}</button>--> <!--<button style="float:right;" type="submit" class="btn btn-default btn-xs" ng-click="deleteSession()" popover="Session can be destroyed only if it is at READY." popover-trigger="mouseenter">Del Ses</button>--> </h5> </div> </div> </div>')}]);