<!--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>Storage Scale Test</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><center>[[label]]</center></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' && show_req_rate">
                {{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' && show_req_rate">
                {{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 Storage Test Configuration</h3>
    <div class="panel panel-default">
        <div class="panel-body"  style="word-wrap:break-word">
            <textarea style="font-family:Courier New, Monospace;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 = [[is_config]]) $scope.from_outside_config = JSON.stringify([[config]], null, "\t");

        $scope.from_outside = [[result]];

        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 = 0;
        var has_req_rate = false;
        $scope.xaxisList = [];
        $scope.data = [];
        for (var i = 0; i < countRep; i++) {
            for (var k = 0; k < countRep2; k++) {
                var row_max = 0;
                $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 (!$scope.perrow.rate_iops) {
                        $scope.perrow.rate_iops = 0;
                    }
                    if (!$scope.perrow.rate) {
                        $scope.perrow.rate = 0;
                    }
                    if (mode == "randread") {
                        row_iops = $scope.perrow.read_iops;
                        row_req_rate = $scope.perrow.rate_iops;
                        row_hist = $scope.perrow.read_hist;
                    } else if (mode == "randwrite") {
                        row_iops = $scope.perrow.write_iops;
                        row_req_rate = $scope.perrow.rate_iops;
                        row_hist = $scope.perrow.write_hist;
                    } else if (mode == "read") {
                        row_iops = $scope.perrow.read_bw;
                        row_req_rate = $scope.perrow.rate;
                        row_hist = $scope.perrow.read_hist;
                    } else {
                        row_iops = $scope.perrow.write_bw;
                        row_req_rate = $scope.perrow.rate;
                        row_hist = $scope.perrow.write_hist;
                    }

                    data = {
                        x: $scope.xaxis,
                        "IOPS": row_iops / $scope.perrow.total_client_vms,
                        "latency1": row_hist[2][1] / 1000,
                        "latency2": row_hist[3][1] / 1000,
                        "latency3": row_hist[4][1] / 1000
                    };
                    if (row_req_rate != 0) {
                        data['requested_rate'] = row_req_rate / $scope.perrow.total_client_vms;
                        has_req_rate = true;
                    }
                    $scope.data.push(data);
                    row_max = Math.max(row_req_rate, row_iops)/ $scope.perrow.total_client_vms;
                    max = Math.max(max, row_max);
                    var pickColor = get_color();
                    var chName = "mode-" + $scope.perrow.mode + "_VM-" + $scope.perrow.total_client_vms;
                    $scope.pushTableData(chName, $scope.perrow, pickColor);
                }
            }
        }
        var series_list = [
                {y: "IOPS", color: "#F44336", type: "column", striped: true, label: $scope.current_mode["y_label"]},
                {
                    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%"
                }
            ];
        if (has_req_rate) {
            $scope.show_req_rate = true
            series_list.push({
                    y: "requested_rate",
                    color: "#696969",
                    drawDots: false,
                    thickness: "1px",
                    label: "Requested Rate",
                    lineMode: "dashed"
                })
        } else {
            $scope.show_req_rate = false
        }
        $scope.options = {
            series: series_list,
            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>
