/* 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. */ "use strict"; angular.module("kbWebApp").controller("RunStorageCtrl", function($scope, $timeout, $location, $http, $q, showAlert, ngTableParams, kbCookie, kbHttp, storageMode, color, locationChange) { function get_min_hist(results) { var min = Number.POSITIVE_INFINITY; return results.forEach(function(rr) { rr.forEach(function(d) { "write_hist" in d && (min = Math.min(min, d.write_hist[0][1])), "read_hist" in d && (min = Math.min(min, d.read_hist[0][1])); }); }), min; } function downloadFile(fileName, content) { var aLink = document.createElement("a"), blob = new Blob([ content ]), evt = document.createEvent("HTMLEvents"); evt.initEvent("click", !1, !1), aLink.download = fileName, aLink.href = URL.createObjectURL(blob), aLink.dispatchEvent(evt); } function to2(num) { return 10 > num ? "0" + num : 99 > num ? "" + num : -1; } this.awesomeThings = [ "HTML5 Boilerplate", "AngularJS", "Karma" ], "" === kbCookie.getSessionID() ? $location.path("/Login") : kbCookie.checkMode("storage"), $(window).on("hashchange", locationChange.change()), $("[data-toggle='.container']").click(function() { var toggle_el = $(this).data("toggle"); $(toggle_el).toggleClass("open-sidebar"), $("#littleglyph").toggleClass("glyphicon-triangle-right"), $("#littleglyph").toggleClass("glyphicon-triangle-left"); }), $(".swipe-area").swipe({ swipeStatus: function(event, phase, direction, distance, duration, fingers) { return "move" == phase && "right" == direction ? ($(".container").addClass("open-sidebar"), !1) : "move" == phase && "left" == direction ? ($(".container").removeClass("open-sidebar"), !1) : void 0; } }), $scope.oneAtATime = !1, $scope.status1 = { isFirstOpen: !0, isFirstDisabled: !1 }, $scope.status2 = { isFirstOpen: !0, isFirstDisabled: !1 }, $scope.status1.open = !0, $scope.status2.open = !0, $scope.sessionID = kbCookie.getSessionID(), $scope.status = kbCookie.getStatus(), $scope.getRunConfig = function() { kbHttp.getMethod("/config/running_config/" + $scope.sessionID).then(function(response) { $scope.config = response.data, kbCookie.setConfig(response.data), $scope.current_mode_name = $scope.config.client.storage_tool_configs[0].mode, $scope.current_mode_description = $scope.config.client.storage_tool_configs[0].description, $scope.getCurrentMode($scope.current_mode_name, "read"), console.log("get & save config"); }, function(response) { console.log("get running config error:"), console.log(response); }); }, $scope.sessionID && !$scope.config && $scope.getRunConfig(), $scope.setConfig = function(ifRun) { var deferred = $q.defer(); return "READY" === $scope.status ? (kbCookie.setConfig($scope.config), $scope.chaCon = { kb_cfg: {} }, $scope.chaCon.kb_cfg = kbCookie.getConfig(), kbHttp.putMethod("/config/running_config/" + $scope.sessionID, $scope.chaCon).then(function(response) { console.log("change running config"), deferred.resolve(1); }, function(response) { deferred.reject(0), 1 != ifRun && (400 == response.status ? showAlert.showAlert("Error while parsing configurations! Please check your inputs!") : 403 == response.status ? showAlert.showAlert("Cannot update configuration if KloudBuster is busy or in error state") : -1 == response.status && showAlert.showAlert("Error while connecting kloudbuster server!")); })) : "STAGED" === $scope.status ? ($scope.config.client.http_tool_configs.report_interval = 0, kbCookie.setConfig($scope.config), $scope.chaCon = { kb_cfg: { client: { http_tool_configs: { duration: $scope.config.client.http_tool_configs.duration, rate_limit: $scope.config.client.http_tool_configs.rate_limit, connections: $scope.config.client.http_tool_configs.connections, report_interval: 0 } } } }, kbHttp.putMethod("/config/running_config/" + $scope.sessionID, $scope.chaCon).then(function(response) { console.log("change running config"), deferred.resolve(1); }, function(response) { deferred.reject(0), 1 != ifRun && (400 == response.status ? showAlert.showAlert("Error while parsing configurations! Please check your inputs!") : 403 == response.status ? showAlert.showAlert("Cannot update configuration if KloudBuster is busy or in error state") : -1 == response.status && showAlert.showAlert("Error while connecting kloudbuster server!")); })) : (console.log("config not allow to change now!"), deferred.reject(0)), deferred.promise; }; var disabledStagingConfig = !1, disabledRunningConfig = !1; $scope.disableConfig = function(disableId) { $("#" + disableId).find("input").each(function() { $(this).attr("disabled", "disabled"); }); }, $scope.enableConfig = function(enableId) { $("#" + enableId).find("input").each(function() { $(this).removeAttr("disabled"); }); }, $scope.configStatus = function() { "READY" === $scope.status ? (disabledStagingConfig === !0 && (disabledStagingConfig = !1, $scope.enableConfig("stagingConfig"), $scope.enableConfig("stagingConfig1"), $("#client_progression_enabled").removeAttr("disabled"), $("#client_progression_vm_start").removeAttr("disabled")), disabledRunningConfig === !0 && (disabledRunningConfig = !1, $scope.enableConfig("runningConfig"))) : "STAGED" === $scope.status ? (disabledStagingConfig === !1 && (disabledStagingConfig = !0, $scope.disableConfig("stagingConfig"), $scope.disableConfig("stagingConfig1"), $("#client_progression_enabled").attr("disabled", "disabled"), $("#client_progression_vm_start").attr("disabled", "disabled")), disabledRunningConfig === !0 && (disabledRunningConfig = !1, $scope.enableConfig("runningConfig"))) : (disabledStagingConfig === !1 && (disabledStagingConfig = !0, $scope.disableConfig("stagingConfig"), $scope.disableConfig("stagingConfig1"), $("md-checkbox").attr("disabled", "disabled")), disabledRunningConfig === !1 && (disabledRunningConfig = !0, $scope.disableConfig("runningConfig"))); }; var pointNumber = 0; $scope.pointNum = function() { var point = "."; pointNumber = (pointNumber + 1) % 6; for (var x = 0; pointNumber > x; x++) point += " ."; return point; }, $scope.runButton = "Run Test", $scope.runStatus = !0, $scope.setStatus = !1, $scope.stageButton = "Stage", $scope.setUnstage = !0, $scope.client_vm_count = 0, $scope.server_vm_count = 0, $scope.statusButton = "btn-default", $scope.checkStatus = function() { $scope.sessionID ? kbHttp.getMethod2("/kloudbuster/status/" + $scope.sessionID).then(function(response) { $scope.status = response.data.status, kbCookie.setStatus($scope.status), $scope.configStatus(), "READY" === $scope.status ? ($scope.runButton = "Run Test", $scope.runStatus = !0, $scope.setStatus = !1, $scope.stageButton = "Stage", $scope.setUnstage = !1, $scope.client_vm_count = 0, $(".loading").addClass("pause"), $scope.statusButton = "btn-success", $scope.info = "") : "STAGING" === $scope.status ? ($scope.runButton = "Run Test", $scope.runStatus = !0, $scope.setStatus = !0, $scope.stageButton = "Stage", $scope.setUnstage = !0, $scope.client_vm_count = response.data.client_vm_count, $(".loading").removeClass("pause"), $scope.statusButton = "btn-info", $scope.info = "KloudBuster is Creating VM(s)" + $scope.pointNum()) : "STAGED" === $scope.status ? ($scope.runButton = "Run Test", $scope.runStatus = !1, $scope.setStatus = !1, $scope.stageButton = "Unstage", $scope.setUnstage = !1, $scope.client_vm_count = $scope.config.client.storage_stage_configs.vm_count, $scope.getReport(), $(".loading").addClass("pause"), $scope.statusButton = "btn-success", $scope.info = "") : "RUNNING" === $scope.status ? ($scope.runButton = "Stop Test", $scope.runStatus = !1, $scope.setStatus = !0, $scope.stageButton = "Unstage", $scope.setUnstage = !0, $scope.client_vm_count = $scope.config.client.storage_stage_configs.vm_count, $scope.config.client.progression.enabled === !0 && $scope.getReport(), $(".loading").removeClass("pause"), $scope.statusButton = "btn-info", $scope.info = "KloudBuster is Running" + $scope.pointNum()) : "ERROR" === $scope.status ? ($scope.runButton = "Run Test", $scope.runStatus = !0, $scope.setStatus = !0, $scope.stageButton = "Unstage", $scope.setUnstage = !1, $scope.client_vm_count = $scope.config.client.storage_stage_configs.vm_count, $(".loading").addClass("pause"), $scope.statusButton = "btn-danger", $scope.info = "") : "CLEANING" !== $scope.status && "STOPPING" !== $scope.status || ($scope.runButton = "Run Test", $scope.runStatus = !0, $scope.setStatus = !0, $scope.stageButton = "Unstage", $scope.setUnstage = !0, $scope.client_vm_count = $scope.config.client.storage_stage_configs.vm_count, $(".loading").removeClass("pause"), $scope.statusButton = "btn-info", $scope.info = "Please Wait" + $scope.pointNum()); }, function(response) { console.log("get status error:"), console.log(response); }) : ($scope.status = "NO SESSION ID", kbCookie.setStatus("")); }, $scope.checkStatus(), $scope.setStage = function() { kbHttp.postMethod("/kloudbuster/stage/" + $scope.sessionID).then(function(response) {}, function(response) { console.log("set stage error:"), console.log(response), showAlert.showAlert("Unable to stage resources!"); }); }, $scope.CleanUp = function() { $scope.initChart(), !$scope.sessionID || "ERROR" !== $scope.status && "STAGED" !== $scope.status ? console.log("Cannot cleanup!") : kbHttp.postMethod("/kloudbuster/cleanup/" + $scope.sessionID).then(function(response) { $scope.checkStatus(); }, function(response) { console.log("clean error:"), console.log(response); }); }, $scope.stage = function() { if ("ERROR" === $scope.status || "STAGED" === $scope.status) $scope.CleanUp(); else if ("READY" === $scope.status) { var promise = $scope.setConfig(1); promise.then(function() { $scope.setStage(); }); } }, $scope.runKb = function() { kbHttp.postMethod("/kloudbuster/run_test/" + $scope.sessionID).then(function(response) {}, function(response) { console.log("running error:"), console.log(response), showAlert.showAlert("Unable to start test!"); }); }, $scope.stopKb = function() { kbHttp.postMethod("/kloudbuster/stop_test/" + $scope.sessionID).then(function(response) {}, function(response) { console.log("stop error:"), console.log(response), showAlert.showAlert("Unable to stop test!"); }); }, $scope.scaleTest = function() { if ("RUNNING" === $scope.status) $scope.stopKb(); else if ("STAGED" === $scope.status) { var promise = $scope.setConfig(1); promise.then(function() { $scope.initChart(), $scope.runKb(); }); } }, $scope.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" } }, $scope.current_index = 0, $scope.getCurrentMode = function(modeName, formix, readpct) { "rw" == modeName ? ("" == formix && (formix = "read"), $scope.current_mode = $scope.modes[formix], "read" == formix ? $scope.current_title = "- " + readpct + "% Read" : $scope.current_title = "- " + (100 - readpct) + "% Write") : "randrw" == modeName ? ("" == formix && (formix = "read"), $scope.current_mode = $scope.modes["rand" + formix], "read" == formix ? $scope.current_title = "- " + readpct + "% Read" : $scope.current_title = "- " + (100 - readpct) + "% Write") : ($scope.current_mode = $scope.modes[$scope.current_mode_name], $scope.current_title = ""); }, ($scope.config = kbCookie.getConfig()) && ($scope.current_mode_name = $scope.config.client.storage_tool_configs[0].mode, $scope.current_mode_description = $scope.config.client.storage_tool_configs[0].description, $scope.getCurrentMode($scope.current_mode_name, "read")), $scope.handleEvent = function(event, index, formix) { $scope.current_index = index, $scope.current_mode_name = $scope.config.client.storage_tool_configs[index].mode, $scope.current_mode_description = $scope.config.client.storage_tool_configs[index].description, $scope.getCurrentMode($scope.current_mode_name, formix, $scope.config.client.storage_tool_configs[index].rwmixread), $scope.refreshChart(), storageMode.getResult().kb_result.length > 0 && $scope.draw(storageMode.getResult()); }, $scope.tabledata = [], $scope.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 } ], $scope.tableParams = new ngTableParams({ sorting: { name: "asc" }, count: 10 }, { counts: [], data: $scope.tabledata }), $scope.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: $scope.xaxisList, ticksFormatter: function(x) { return -1 != $.inArray(x, $scope.xaxisList) ? 0 == x ? "1" : x : ""; } }, y: { type: "linear", ticksFormat: "d", innerTicks: !0, min: 0 }, y2: { type: "log", ticksFormat: "d", innerTicks: !1, grid: !0 } }, tooltip: { mode: "scrubber", formatter: function(x, y, series) { return series.label + ":" + y; } }, tension: .8, lineMode: "cardinal", columnsHGap: 45 }, $scope.initChart = function() { $scope.data = [], $scope.isDely = !1, $scope.tabledata.length = 0, $scope.tableParams.reload(), $scope.isDely = !1, countRep = 0, color.reset(), storageMode.setResult([]); }; var countRep = 0; $scope.initChart(), $scope.refreshChart = function() { $scope.data = [], $scope.isDely = !1, $scope.tabledata.length = 0, $scope.tableParams.reload(), color.reset(); }, $scope.getReport = function() { kbHttp.getMethod2("/kloudbuster/report/" + $scope.sessionID + "?final=true").then(function(response) { response.data.kb_result.length > 0 && countRep < response.data.kb_result.length && (console.log("get report totally:" + response.data.kb_result.length), countRep = response.data.kb_result.length, storageMode.setResult(response.data), $scope.refreshChart(), $scope.draw(response.data)); }, function(response) { console.log("get report error:"), console.log(response); }); }, $scope.draw = function(results) { $scope.results = results.kb_result; var max, countRep = $scope.results.length, countRep2 = $scope.results[0].length, mode = $scope.current_mode.name; $scope.xaxisList = []; for (var i = 0; countRep > i; i++) for (var k = 0; countRep2 > k; k++) if ($scope.perrow = $scope.results[i][k], $scope.perrow.mode == $scope.current_mode_name && $scope.perrow.description == $scope.current_mode_description) { 1 == $scope.perrow.total_client_vms && 1 != countRep ? $scope.xaxis = 0 : $scope.xaxis = $scope.perrow.total_client_vms, $scope.xaxisList.push($scope.xaxis), "randread" == mode && ($scope.data.push({ x: $scope.xaxis, IOPS: $scope.perrow.read_iops / $scope.perrow.total_client_vms, latency1: $scope.perrow.read_hist[2][1] / 1e3, latency2: $scope.perrow.read_hist[3][1] / 1e3, latency3: $scope.perrow.read_hist[4][1] / 1e3, requested_rate: $scope.perrow.rate_iops / $scope.perrow.total_client_vms }), max = $scope.perrow.rate_iops / $scope.perrow.total_client_vms), "randwrite" == mode && ($scope.data.push({ x: $scope.xaxis, IOPS: $scope.perrow.write_iops / $scope.perrow.total_client_vms, latency1: $scope.perrow.write_hist[2][1] / 1e3, latency2: $scope.perrow.write_hist[3][1] / 1e3, latency3: $scope.perrow.write_hist[4][1] / 1e3, requested_rate: $scope.perrow.rate_iops / $scope.perrow.total_client_vms }), max = $scope.perrow.rate_iops / $scope.perrow.total_client_vms), "read" == mode && ($scope.data.push({ x: $scope.xaxis, IOPS: $scope.perrow.read_bw / $scope.perrow.total_client_vms, latency1: $scope.perrow.read_hist[2][1] / 1e3, latency2: $scope.perrow.read_hist[3][1] / 1e3, latency3: $scope.perrow.read_hist[4][1] / 1e3, requested_rate: $scope.perrow.rate / $scope.perrow.total_client_vms }), max = $scope.perrow.rate / $scope.perrow.total_client_vms), "write" == mode && ($scope.data.push({ x: $scope.xaxis, IOPS: $scope.perrow.write_bw / $scope.perrow.total_client_vms, latency1: $scope.perrow.write_hist[2][1] / 1e3, latency2: $scope.perrow.write_hist[3][1] / 1e3, latency3: $scope.perrow.write_hist[4][1] / 1e3, requested_rate: $scope.perrow.rate / $scope.perrow.total_client_vms }), max = $scope.perrow.rate / $scope.perrow.total_client_vms); var pickColor = color.getColor(), chName = "mode-" + $scope.perrow.mode + "_VM-" + $scope.perrow.total_client_vms; $scope.pushTableData(chName, $scope.perrow, pickColor); } $scope.options.axes.y.max = 1.0005 * max, $scope.options.axes.y2.min = get_min_hist($scope.results) / 1e3, $scope.options.series[0].label = $scope.current_mode.y_label; }, $scope.pushChartData = function(chName, chData, pickColor) { $scope.isDely === !1 && ($scope.options.series.shift(), $scope.isDely = !0), $scope.options.series.push({ y: chName, label: chName, color: pickColor, dotSize: "3", thickness: "2px" }); for (var i = 0; 7 > i; i++) $scope.data[i][chName] = chData.latency_stats[i][1] / 1e3; }, $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(); }, $scope.saveResult = function() { var date = new Date(), m = to2(date.getMonth() + 1), d = to2(date.getDate()), h = to2(date.getHours()), min = to2(date.getMinutes()), filename = "" + m + d + h + min + ".html", saveData = storageMode.getResult(); if ("" != saveData) { var myresult = '
{{row.total_client_vms}} | {{row.block_size}}b | {{row.iodepth}} | {{row.rate_iops}} | {{row.read_iops}} | {{row.write_iops}} | {{row.rate}} KB/s | {{row.read_bw}} KB/s | {{row.write_bw}} KB/s |