init commit for Web UI source code

Change-Id: I3b1711cd2f70fd347a42dd0ffa55b721da848d5b
This commit is contained in:
Xin 2015-10-22 11:46:41 -07:00
parent ddd158d4fb
commit 199eec027d
52 changed files with 6059 additions and 0 deletions

BIN
kb_web/.DS_Store vendored Normal file

Binary file not shown.

3
kb_web/.bowerrc Normal file
View File

@ -0,0 +1,3 @@
{
"directory": "bower_components"
}

21
kb_web/.editorconfig Normal file
View File

@ -0,0 +1,21 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
# Change these settings to your own preference
indent_style = space
indent_size = 2
# We recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

1
kb_web/.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
* text=auto

5
kb_web/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
/node_modules
/dist
/.tmp
/.sass-cache
/bower_components

BIN
kb_web/.idea/.DS_Store vendored Normal file

Binary file not shown.

1
kb_web/.idea/.name Normal file
View File

@ -0,0 +1 @@
kb_web

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<file url="file://$PROJECT_DIR$" libraries="{kb_web node_modules}" />
</component>
</project>

9
kb_web/.idea/kb_web.iml Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="kb_web node_modules" level="project" />
</component>
</module>

View File

@ -0,0 +1,14 @@
<component name="libraryTable">
<library name="kb_web node_modules" type="javaScript">
<properties>
<option name="frameworkName" value="node_modules" />
<sourceFilesUrls>
<item url="file://$PROJECT_DIR$/node_modules" />
</sourceFilesUrls>
</properties>
<CLASSES>
<root url="file://$PROJECT_DIR$/node_modules" />
</CLASSES>
<SOURCES />
</library>
</component>

14
kb_web/.idea/misc.xml Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" />
</project>

8
kb_web/.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/kb_web.iml" filepath="$PROJECT_DIR$/.idea/kb_web.iml" />
</modules>
</component>
</project>

6
kb_web/.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="" />
</component>
</project>

1050
kb_web/.idea/workspace.xml Normal file

File diff suppressed because it is too large Load Diff

16
kb_web/.jshintrc Normal file
View File

@ -0,0 +1,16 @@
{
"bitwise": true,
"browser": true,
"curly": true,
"eqeqeq": true,
"esnext": true,
"latedef": true,
"noarg": true,
"node": true,
"strict": true,
"undef": true,
"unused": true,
"globals": {
"angular": false
}
}

9
kb_web/.travis.yml Normal file
View File

@ -0,0 +1,9 @@
sudo: false
language: node_js
node_js:
- 'iojs'
- '0.12'
- '0.10'
before_script:
- 'npm install -g bower grunt-cli'
- 'bower install'

464
kb_web/Gruntfile.js Normal file
View File

@ -0,0 +1,464 @@
// Generated on 2015-09-03 using generator-angular 0.12.1
'use strict';
// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'
module.exports = function (grunt) {
// Time how long tasks take. Can help when optimizing build times
require('time-grunt')(grunt);
// Automatically load required Grunt tasks
require('jit-grunt')(grunt, {
useminPrepare: 'grunt-usemin',
ngtemplates: 'grunt-angular-templates',
cdnify: 'grunt-google-cdn'
});
// Configurable paths for the application
var appConfig = {
app: require('./bower.json').appPath || 'app',
dist: 'dist'
};
// Define the configuration for all the tasks
grunt.initConfig({
// Project settings
yeoman: appConfig,
// Watches files for changes and runs tasks based on the changed files
watch: {
bower: {
files: ['bower.json'],
tasks: ['wiredep']
},
js: {
files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
tasks: ['newer:jshint:all'],
options: {
livereload: '<%= connect.options.livereload %>'
}
},
jsTest: {
files: ['test/spec/{,*/}*.js'],
tasks: ['newer:jshint:test', 'karma']
},
styles: {
files: ['<%= yeoman.app %>/styles/{,*/}*.css'],
tasks: ['newer:copy:styles', 'autoprefixer']
},
gruntfile: {
files: ['Gruntfile.js']
},
livereload: {
options: {
livereload: '<%= connect.options.livereload %>'
},
files: [
'<%= yeoman.app %>/{,*/}*.html',
'.tmp/styles/{,*/}*.css',
'<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
]
}
},
// The actual grunt server settings
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: 'localhost',
livereload: 35729
},
livereload: {
options: {
open: true,
middleware: function (connect) {
return [
connect.static('.tmp'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect().use(
'/app/styles',
connect.static('./app/styles')
),
connect.static(appConfig.app)
];
}
}
},
test: {
options: {
port: 9001,
middleware: function (connect) {
return [
connect.static('.tmp'),
connect.static('test'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect.static(appConfig.app)
];
}
}
},
dist: {
options: {
open: true,
base: '<%= yeoman.dist %>'
}
}
},
// Make sure code styles are up to par and there are no obvious mistakes
jshint: {
options: {
jshintrc: '.jshintrc',
reporter: require('jshint-stylish')
},
all: {
src: [
'Gruntfile.js',
'<%= yeoman.app %>/scripts/{,*/}*.js'
]
},
test: {
options: {
jshintrc: 'test/.jshintrc'
},
src: ['test/spec/{,*/}*.js']
}
},
// Empties folders to start fresh
clean: {
dist: {
files: [{
dot: true,
src: [
'.tmp',
'<%= yeoman.dist %>/{,*/}*',
'!<%= yeoman.dist %>/.git{,*/}*'
]
}]
},
server: '.tmp'
},
// Add vendor prefixed styles
autoprefixer: {
options: {
browsers: ['last 1 version']
},
server: {
options: {
map: true,
},
files: [{
expand: true,
cwd: '.tmp/styles/',
src: '{,*/}*.css',
dest: '.tmp/styles/'
}]
},
dist: {
files: [{
expand: true,
cwd: '.tmp/styles/',
src: '{,*/}*.css',
dest: '.tmp/styles/'
}]
}
},
// Automatically inject Bower components into the app
wiredep: {
app: {
src: ['<%= yeoman.app %>/index.html'],
ignorePath: /\.\.\//
},
test: {
devDependencies: true,
src: '<%= karma.unit.configFile %>',
ignorePath: /\.\.\//,
fileTypes:{
js: {
block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
detect: {
js: /'(.*\.js)'/gi
},
replace: {
js: '\'{{filePath}}\','
}
}
}
}
},
// Renames files for browser caching purposes
filerev: {
dist: {
src: [
'<%= yeoman.dist %>/scripts/{,*/}*.js',
'<%= yeoman.dist %>/styles/{,*/}*.css',
'<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
'<%= yeoman.dist %>/styles/fonts/*'
]
}
},
// Reads HTML for usemin blocks to enable smart builds that automatically
// concat, minify and revision files. Creates configurations in memory so
// additional tasks can operate on them
useminPrepare: {
html: '<%= yeoman.app %>/index.html',
options: {
dest: '<%= yeoman.dist %>',
flow: {
html: {
steps: {
js: ['concat', 'uglifyjs'],
css: ['cssmin']
},
post: {}
}
}
}
},
// Performs rewrites based on filerev and the useminPrepare configuration
usemin: {
html: ['<%= yeoman.dist %>/{,*/}*.html'],
css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
js: ['<%= yeoman.dist %>/scripts/{,*/}*.js'],
options: {
assetsDirs: [
'<%= yeoman.dist %>',
'<%= yeoman.dist %>/images',
'<%= yeoman.dist %>/styles'
],
patterns: {
js: [[/(images\/[^''""]*\.(png|jpg|jpeg|gif|webp|svg))/g, 'Replacing references to images']]
}
}
},
// The following *-min tasks will produce minified files in the dist folder
// By default, your `index.html`'s <!-- Usemin block --> will take care of
// minification. These next options are pre-configured if you do not wish
// to use the Usemin blocks.
// cssmin: {
// dist: {
// files: {
// '<%= yeoman.dist %>/styles/main.css': [
// '.tmp/styles/{,*/}*.css'
// ]
// }
// }
// },
// uglify: {
// dist: {
// files: {
// '<%= yeoman.dist %>/scripts/scripts.js': [
// '<%= yeoman.dist %>/scripts/scripts.js'
// ]
// }
// }
// },
// concat: {
// dist: {}
// },
imagemin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/images',
src: '{,*/}*.{png,jpg,jpeg,gif}',
dest: '<%= yeoman.dist %>/images'
}]
}
},
svgmin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/images',
src: '{,*/}*.svg',
dest: '<%= yeoman.dist %>/images'
}]
}
},
htmlmin: {
dist: {
options: {
collapseWhitespace: true,
conservativeCollapse: true,
collapseBooleanAttributes: true,
removeCommentsFromCDATA: true
},
files: [{
expand: true,
cwd: '<%= yeoman.dist %>',
src: ['*.html'],
dest: '<%= yeoman.dist %>'
}]
}
},
ngtemplates: {
dist: {
options: {
module: 'kbWebApp',
htmlmin: '<%= htmlmin.dist.options %>',
usemin: 'scripts/scripts.js'
},
cwd: '<%= yeoman.app %>',
src: 'views/{,*/}*.html',
dest: '.tmp/templateCache.js'
}
},
// ng-annotate tries to make the code safe for minification automatically
// by using the Angular long form for dependency injection.
ngAnnotate: {
dist: {
files: [{
expand: true,
cwd: '.tmp/concat/scripts',
src: '*.js',
dest: '.tmp/concat/scripts'
}]
}
},
// Replace Google CDN references
cdnify: {
dist: {
html: ['<%= yeoman.dist %>/*.html']
}
},
// Copies remaining files to places other tasks can use
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= yeoman.app %>',
dest: '<%= yeoman.dist %>',
src: [
'*.{ico,png,txt}',
'.htaccess',
'*.html',
'images/{,*/}*.{webp}',
'styles/fonts/{,*/}*.*'
]
}, {
expand: true,
cwd: '.tmp/images',
dest: '<%= yeoman.dist %>/images',
src: ['generated/*']
}, {
expand: true,
cwd: 'bower_components/bootstrap/dist',
src: 'fonts/*',
dest: '<%= yeoman.dist %>'
}]
},
styles: {
expand: true,
cwd: '<%= yeoman.app %>/styles',
dest: '.tmp/styles/',
src: '{,*/}*.css'
}
},
// Run some tasks in parallel to speed up the build process
concurrent: {
server: [
'copy:styles'
],
test: [
'copy:styles'
],
dist: [
'copy:styles',
'imagemin',
'svgmin'
]
},
// Test settings
karma: {
unit: {
configFile: 'test/karma.conf.js',
singleRun: true
}
}
});
grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
if (target === 'dist') {
return grunt.task.run(['build', 'connect:dist:keepalive']);
}
grunt.task.run([
'clean:server',
'wiredep',
'concurrent:server',
'autoprefixer:server',
'connect:livereload',
'watch'
]);
});
grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
grunt.task.run(['serve:' + target]);
});
grunt.registerTask('test', [
'clean:server',
'wiredep',
'concurrent:test',
'autoprefixer',
'connect:test',
'karma'
]);
grunt.registerTask('build', [
'clean:dist',
'wiredep',
'useminPrepare',
'concurrent:dist',
'autoprefixer',
'ngtemplates',
'concat',
'ngAnnotate',
'copy:dist',
'cdnify',
'cssmin',
'uglify',
'filerev',
'usemin',
'htmlmin'
]);
grunt.registerTask('default', [
'newer:jshint',
'test',
'build'
]);
};

8
kb_web/README.md Normal file
View File

@ -0,0 +1,8 @@
# kb-web
This Web is for KloudBuster.
## Build & development
Run `grunt` for building and `grunt serve` for preview.

BIN
kb_web/app/.DS_Store vendored Normal file

Binary file not shown.

1
kb_web/app/.buildignore Normal file
View File

@ -0,0 +1 @@
*.coffee

543
kb_web/app/.htaccess Normal file
View File

@ -0,0 +1,543 @@
# Apache Configuration File
# (!) Using `.htaccess` files slows down Apache, therefore, if you have access
# to the main server config file (usually called `httpd.conf`), you should add
# this logic there: http://httpd.apache.org/docs/current/howto/htaccess.html.
# ##############################################################################
# # CROSS-ORIGIN RESOURCE SHARING (CORS) #
# ##############################################################################
# ------------------------------------------------------------------------------
# | Cross-domain AJAX requests |
# ------------------------------------------------------------------------------
# Enable cross-origin AJAX requests.
# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
# http://enable-cors.org/
# <IfModule mod_headers.c>
# Header set Access-Control-Allow-Origin "*"
# </IfModule>
# ------------------------------------------------------------------------------
# | CORS-enabled images |
# ------------------------------------------------------------------------------
# Send the CORS header for images when browsers request it.
# https://developer.mozilla.org/en/CORS_Enabled_Image
# http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html
# http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
<FilesMatch "\.(gif|ico|jpe?g|png|svg|svgz|webp)$">
SetEnvIf Origin ":" IS_CORS
Header set Access-Control-Allow-Origin "*" env=IS_CORS
</FilesMatch>
</IfModule>
</IfModule>
# ------------------------------------------------------------------------------
# | Web fonts access |
# ------------------------------------------------------------------------------
# Allow access from all domains for web fonts
<IfModule mod_headers.c>
<FilesMatch "\.(eot|font.css|otf|ttc|ttf|woff)$">
Header set Access-Control-Allow-Origin "*"
</FilesMatch>
</IfModule>
# ##############################################################################
# # ERRORS #
# ##############################################################################
# ------------------------------------------------------------------------------
# | 404 error prevention for non-existing redirected folders |
# ------------------------------------------------------------------------------
# Prevent Apache from returning a 404 error for a rewrite if a directory
# with the same name does not exist.
# http://httpd.apache.org/docs/current/content-negotiation.html#multiviews
# http://www.webmasterworld.com/apache/3808792.htm
Options -MultiViews
# ------------------------------------------------------------------------------
# | Custom error messages / pages |
# ------------------------------------------------------------------------------
# You can customize what Apache returns to the client in case of an error (see
# http://httpd.apache.org/docs/current/mod/core.html#errordocument), e.g.:
ErrorDocument 404 /404.html
# ##############################################################################
# # INTERNET EXPLORER #
# ##############################################################################
# ------------------------------------------------------------------------------
# | Better website experience |
# ------------------------------------------------------------------------------
# Force IE to render pages in the highest available mode in the various
# cases when it may not: http://hsivonen.iki.fi/doctype/ie-mode.pdf.
<IfModule mod_headers.c>
Header set X-UA-Compatible "IE=edge"
# `mod_headers` can't match based on the content-type, however, we only
# want to send this header for HTML pages and not for the other resources
<FilesMatch "\.(appcache|crx|css|eot|gif|htc|ico|jpe?g|js|m4a|m4v|manifest|mp4|oex|oga|ogg|ogv|otf|pdf|png|safariextz|svg|svgz|ttf|vcf|webapp|webm|webp|woff|xml|xpi)$">
Header unset X-UA-Compatible
</FilesMatch>
</IfModule>
# ------------------------------------------------------------------------------
# | Cookie setting from iframes |
# ------------------------------------------------------------------------------
# Allow cookies to be set from iframes in IE.
# <IfModule mod_headers.c>
# Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\""
# </IfModule>
# ------------------------------------------------------------------------------
# | Screen flicker |
# ------------------------------------------------------------------------------
# Stop screen flicker in IE on CSS rollovers (this only works in
# combination with the `ExpiresByType` directives for images from below).
# BrowserMatch "MSIE" brokenvary=1
# BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1
# BrowserMatch "Opera" !brokenvary
# SetEnvIf brokenvary 1 force-no-vary
# ##############################################################################
# # MIME TYPES AND ENCODING #
# ##############################################################################
# ------------------------------------------------------------------------------
# | Proper MIME types for all files |
# ------------------------------------------------------------------------------
<IfModule mod_mime.c>
# Audio
AddType audio/mp4 m4a f4a f4b
AddType audio/ogg oga ogg
# JavaScript
# Normalize to standard type (it's sniffed in IE anyways):
# http://tools.ietf.org/html/rfc4329#section-7.2
AddType application/javascript js jsonp
AddType application/json json
# Video
AddType video/mp4 mp4 m4v f4v f4p
AddType video/ogg ogv
AddType video/webm webm
AddType video/x-flv flv
# Web fonts
AddType application/font-woff woff
AddType application/vnd.ms-fontobject eot
# Browsers usually ignore the font MIME types and sniff the content,
# however, Chrome shows a warning if other MIME types are used for the
# following fonts.
AddType application/x-font-ttf ttc ttf
AddType font/opentype otf
# Make SVGZ fonts work on iPad:
# https://twitter.com/FontSquirrel/status/14855840545
AddType image/svg+xml svg svgz
AddEncoding gzip svgz
# Other
AddType application/octet-stream safariextz
AddType application/x-chrome-extension crx
AddType application/x-opera-extension oex
AddType application/x-shockwave-flash swf
AddType application/x-web-app-manifest+json webapp
AddType application/x-xpinstall xpi
AddType application/xml atom rdf rss xml
AddType image/webp webp
AddType image/x-icon ico
AddType text/cache-manifest appcache manifest
AddType text/vtt vtt
AddType text/x-component htc
AddType text/x-vcard vcf
</IfModule>
# ------------------------------------------------------------------------------
# | UTF-8 encoding |
# ------------------------------------------------------------------------------
# Use UTF-8 encoding for anything served as `text/html` or `text/plain`.
AddDefaultCharset utf-8
# Force UTF-8 for certain file formats.
<IfModule mod_mime.c>
AddCharset utf-8 .atom .css .js .json .rss .vtt .webapp .xml
</IfModule>
# ##############################################################################
# # URL REWRITES #
# ##############################################################################
# ------------------------------------------------------------------------------
# | Rewrite engine |
# ------------------------------------------------------------------------------
# Turning on the rewrite engine and enabling the `FollowSymLinks` option is
# necessary for the following directives to work.
# If your web host doesn't allow the `FollowSymlinks` option, you may need to
# comment it out and use `Options +SymLinksIfOwnerMatch` but, be aware of the
# performance impact: http://httpd.apache.org/docs/current/misc/perf-tuning.html#symlinks
# Also, some cloud hosting services require `RewriteBase` to be set:
# http://www.rackspace.com/knowledge_center/frequently-asked-question/why-is-mod-rewrite-not-working-on-my-site
<IfModule mod_rewrite.c>
Options +FollowSymlinks
# Options +SymLinksIfOwnerMatch
RewriteEngine On
# RewriteBase /
</IfModule>
# ------------------------------------------------------------------------------
# | Suppressing / Forcing the "www." at the beginning of URLs |
# ------------------------------------------------------------------------------
# The same content should never be available under two different URLs especially
# not with and without "www." at the beginning. This can cause SEO problems
# (duplicate content), therefore, you should choose one of the alternatives and
# redirect the other one.
# By default option 1 (no "www.") is activated:
# http://no-www.org/faq.php?q=class_b
# If you'd prefer to use option 2, just comment out all the lines from option 1
# and uncomment the ones from option 2.
# IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME!
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Option 1: rewrite www.example.com → example.com
<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
</IfModule>
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Option 2: rewrite example.com → www.example.com
# Be aware that the following might not be a good idea if you use "real"
# subdomains for certain parts of your website.
# <IfModule mod_rewrite.c>
# RewriteCond %{HTTPS} !=on
# RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
# RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# </IfModule>
# ##############################################################################
# # SECURITY #
# ##############################################################################
# ------------------------------------------------------------------------------
# | Content Security Policy (CSP) |
# ------------------------------------------------------------------------------
# You can mitigate the risk of cross-site scripting and other content-injection
# attacks by setting a Content Security Policy which whitelists trusted sources
# of content for your site.
# The example header below allows ONLY scripts that are loaded from the current
# site's origin (no inline scripts, no CDN, etc). This almost certainly won't
# work as-is for your site!
# To get all the details you'll need to craft a reasonable policy for your site,
# read: http://html5rocks.com/en/tutorials/security/content-security-policy (or
# see the specification: http://w3.org/TR/CSP).
# <IfModule mod_headers.c>
# Header set Content-Security-Policy "script-src 'self'; object-src 'self'"
# <FilesMatch "\.(appcache|crx|css|eot|gif|htc|ico|jpe?g|js|m4a|m4v|manifest|mp4|oex|oga|ogg|ogv|otf|pdf|png|safariextz|svg|svgz|ttf|vcf|webapp|webm|webp|woff|xml|xpi)$">
# Header unset Content-Security-Policy
# </FilesMatch>
# </IfModule>
# ------------------------------------------------------------------------------
# | File access |
# ------------------------------------------------------------------------------
# Block access to directories without a default document.
# Usually you should leave this uncommented because you shouldn't allow anyone
# to surf through every directory on your server (which may includes rather
# private places like the CMS's directories).
<IfModule mod_autoindex.c>
Options -Indexes
</IfModule>
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Block access to hidden files and directories.
# This includes directories used by version control systems such as Git and SVN.
<IfModule mod_rewrite.c>
RewriteCond %{SCRIPT_FILENAME} -d [OR]
RewriteCond %{SCRIPT_FILENAME} -f
RewriteRule "(^|/)\." - [F]
</IfModule>
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Block access to backup and source files.
# These files may be left by some text editors and can pose a great security
# danger when anyone has access to them.
<FilesMatch "(^#.*#|\.(bak|config|dist|fla|inc|ini|log|psd|sh|sql|sw[op])|~)$">
Order allow,deny
Deny from all
Satisfy All
</FilesMatch>
# ------------------------------------------------------------------------------
# | Secure Sockets Layer (SSL) |
# ------------------------------------------------------------------------------
# Rewrite secure requests properly to prevent SSL certificate warnings, e.g.:
# prevent `https://www.example.com` when your certificate only allows
# `https://secure.example.com`.
# <IfModule mod_rewrite.c>
# RewriteCond %{SERVER_PORT} !^443
# RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L]
# </IfModule>
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Force client-side SSL redirection.
# If a user types "example.com" in his browser, the above rule will redirect him
# to the secure version of the site. That still leaves a window of opportunity
# (the initial HTTP connection) for an attacker to downgrade or redirect the
# request. The following header ensures that browser will ONLY connect to your
# server via HTTPS, regardless of what the users type in the address bar.
# http://www.html5rocks.com/en/tutorials/security/transport-layer-security/
# <IfModule mod_headers.c>
# Header set Strict-Transport-Security max-age=16070400;
# </IfModule>
# ------------------------------------------------------------------------------
# | Server software information |
# ------------------------------------------------------------------------------
# Avoid displaying the exact Apache version number, the description of the
# generic OS-type and the information about Apache's compiled-in modules.
# ADD THIS DIRECTIVE IN THE `httpd.conf` AS IT WILL NOT WORK IN THE `.htaccess`!
# ServerTokens Prod
# ##############################################################################
# # WEB PERFORMANCE #
# ##############################################################################
# ------------------------------------------------------------------------------
# | Compression |
# ------------------------------------------------------------------------------
<IfModule mod_deflate.c>
# Force compression for mangled headers.
# http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
</IfModule>
</IfModule>
# Compress all output labeled with one of the following MIME-types
# (for Apache versions below 2.3.7, you don't need to enable `mod_filter`
# and can remove the `<IfModule mod_filter.c>` and `</IfModule>` lines
# as `AddOutputFilterByType` is still in the core directives).
<IfModule mod_filter.c>
AddOutputFilterByType DEFLATE application/atom+xml \
application/javascript \
application/json \
application/rss+xml \
application/vnd.ms-fontobject \
application/x-font-ttf \
application/x-web-app-manifest+json \
application/xhtml+xml \
application/xml \
font/opentype \
image/svg+xml \
image/x-icon \
text/css \
text/html \
text/plain \
text/x-component \
text/xml
</IfModule>
</IfModule>
# ------------------------------------------------------------------------------
# | Content transformations |
# ------------------------------------------------------------------------------
# Prevent some of the mobile network providers from modifying the content of
# your site: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5.
# <IfModule mod_headers.c>
# Header set Cache-Control "no-transform"
# </IfModule>
# ------------------------------------------------------------------------------
# | ETag removal |
# ------------------------------------------------------------------------------
# Since we're sending far-future expires headers (see below), ETags can
# be removed: http://developer.yahoo.com/performance/rules.html#etags.
# `FileETag None` is not enough for every server.
<IfModule mod_headers.c>
Header unset ETag
</IfModule>
FileETag None
# ------------------------------------------------------------------------------
# | Expires headers (for better cache control) |
# ------------------------------------------------------------------------------
# The following expires headers are set pretty far in the future. If you don't
# control versioning with filename-based cache busting, consider lowering the
# cache time for resources like CSS and JS to something like 1 week.
<IfModule mod_expires.c>
ExpiresActive on
ExpiresDefault "access plus 1 month"
# CSS
ExpiresByType text/css "access plus 1 year"
# Data interchange
ExpiresByType application/json "access plus 0 seconds"
ExpiresByType application/xml "access plus 0 seconds"
ExpiresByType text/xml "access plus 0 seconds"
# Favicon (cannot be renamed!)
ExpiresByType image/x-icon "access plus 1 week"
# HTML components (HTCs)
ExpiresByType text/x-component "access plus 1 month"
# HTML
ExpiresByType text/html "access plus 0 seconds"
# JavaScript
ExpiresByType application/javascript "access plus 1 year"
# Manifest files
ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"
ExpiresByType text/cache-manifest "access plus 0 seconds"
# Media
ExpiresByType audio/ogg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType video/mp4 "access plus 1 month"
ExpiresByType video/ogg "access plus 1 month"
ExpiresByType video/webm "access plus 1 month"
# Web feeds
ExpiresByType application/atom+xml "access plus 1 hour"
ExpiresByType application/rss+xml "access plus 1 hour"
# Web fonts
ExpiresByType application/font-woff "access plus 1 month"
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
ExpiresByType application/x-font-ttf "access plus 1 month"
ExpiresByType font/opentype "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
</IfModule>
# ------------------------------------------------------------------------------
# | Filename-based cache busting |
# ------------------------------------------------------------------------------
# If you're not using a build process to manage your filename version revving,
# you might want to consider enabling the following directives to route all
# requests such as `/css/style.12345.css` to `/css/style.css`.
# To understand why this is important and a better idea than `*.css?v231`, read:
# http://stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring
# <IfModule mod_rewrite.c>
# RewriteCond %{REQUEST_FILENAME} !-f
# RewriteCond %{REQUEST_FILENAME} !-d
# RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L]
# </IfModule>
# ------------------------------------------------------------------------------
# | File concatenation |
# ------------------------------------------------------------------------------
# Allow concatenation from within specific CSS and JS files, e.g.:
# Inside of `script.combined.js` you could have
# <!--#include file="libs/jquery.js" -->
# <!--#include file="plugins/jquery.idletimer.js" -->
# and they would be included into this single file.
# <IfModule mod_include.c>
# <FilesMatch "\.combined\.js$">
# Options +Includes
# AddOutputFilterByType INCLUDES application/javascript application/json
# SetOutputFilter INCLUDES
# </FilesMatch>
# <FilesMatch "\.combined\.css$">
# Options +Includes
# AddOutputFilterByType INCLUDES text/css
# SetOutputFilter INCLUDES
# </FilesMatch>
# </IfModule>
# ------------------------------------------------------------------------------
# | Persistent connections |
# ------------------------------------------------------------------------------
# Allow multiple requests to be sent over the same TCP connection:
# http://httpd.apache.org/docs/current/en/mod/core.html#keepalive.
# Enable if you serve a lot of static content but, be aware of the
# possible disadvantages!
# <IfModule mod_headers.c>
# Header set Connection Keep-Alive
# </IfModule>

152
kb_web/app/404.html Normal file
View File

@ -0,0 +1,152 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Page Not Found :(</title>
<style>
::-moz-selection {
background: #b3d4fc;
text-shadow: none;
}
::selection {
background: #b3d4fc;
text-shadow: none;
}
html {
padding: 30px 10px;
font-size: 20px;
line-height: 1.4;
color: #737373;
background: #f0f0f0;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
html,
input {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
body {
max-width: 500px;
padding: 30px 20px 50px;
border: 1px solid #b3b3b3;
border-radius: 4px;
margin: 0 auto;
box-shadow: 0 1px 10px #a7a7a7, inset 0 1px 0 #fff;
background: #fcfcfc;
}
h1 {
margin: 0 10px;
font-size: 50px;
text-align: center;
}
h1 span {
color: #bbb;
}
h3 {
margin: 1.5em 0 0.5em;
}
p {
margin: 1em 0;
}
ul {
padding: 0 0 0 40px;
margin: 1em 0;
}
.container {
max-width: 380px;
margin: 0 auto;
}
/* google search */
#goog-fixurl ul {
list-style: none;
padding: 0;
margin: 0;
}
#goog-fixurl form {
margin: 0;
}
#goog-wm-qt,
#goog-wm-sb {
border: 1px solid #bbb;
font-size: 16px;
line-height: normal;
vertical-align: top;
color: #444;
border-radius: 2px;
}
#goog-wm-qt {
width: 220px;
height: 20px;
padding: 5px;
margin: 5px 10px 0 0;
box-shadow: inset 0 1px 1px #ccc;
}
#goog-wm-sb {
display: inline-block;
height: 32px;
padding: 0 10px;
margin: 5px 0 0;
white-space: nowrap;
cursor: pointer;
background-color: #f5f5f5;
background-image: -webkit-linear-gradient(rgba(255,255,255,0), #f1f1f1);
background-image: -moz-linear-gradient(rgba(255,255,255,0), #f1f1f1);
background-image: -ms-linear-gradient(rgba(255,255,255,0), #f1f1f1);
background-image: -o-linear-gradient(rgba(255,255,255,0), #f1f1f1);
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
#goog-wm-sb:hover,
#goog-wm-sb:focus {
border-color: #aaa;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
background-color: #f8f8f8;
}
#goog-wm-qt:hover,
#goog-wm-qt:focus {
border-color: #105cb6;
outline: 0;
color: #222;
}
input::-moz-focus-inner {
padding: 0;
border: 0;
}
</style>
</head>
<body>
<div class="container">
<h1>Not found <span>:(</span></h1>
<p>Sorry, but the page you were trying to view does not exist.</p>
<p>It looks like this was the result of either:</p>
<ul>
<li>a mistyped address</li>
<li>an out-of-date link</li>
</ul>
<script>
var GOOG_FIXURL_LANG = (navigator.language || '').slice(0,2),GOOG_FIXURL_SITE = location.host;
</script>
<script src="//linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js"></script>
</div>
</body>
</html>

BIN
kb_web/app/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
kb_web/app/images/.DS_Store vendored Normal file

Binary file not shown.

BIN
kb_web/app/images/back.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
kb_web/app/images/logo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

130
kb_web/app/index.html Normal file
View File

@ -0,0 +1,130 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>KloudBuster</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
<!-- build:css(.) styles/vendor.css -->
<!-- bower:css -->
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="bower_components/ng-table/dist/ng-table.min.css" />
<link rel="stylesheet" href="bower_components/angular-loading-bar/build/loading-bar.css" />
<!-- endbower -->
<!-- endbuild -->
<!-- build:css(.tmp) styles/main.css -->
<link rel="stylesheet" href="styles/bootstrap.theme.flatly.css" />
<link rel="stylesheet" href="styles/main.css">
<!-- endbuild -->
</head>
<body ng-app="kbWebApp">
<!--<img class="background" src="images/back.jpg">-->
<!--[if lte IE 8]>
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please upgrade your browser to improve your experience.</p>
<![endif]-->
<!-- Add your site or application content here -->
<div class="header">
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
<!--<img class="background" src="images/back.jpg">-->
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#js-navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" ng-href="#/" style="font-family: Arial">
<span style="color:#DF314D">K</span>loudBuster
<!--<img src="images/logo.jpg" alt="LOGO" height="50"/>-->
</a>
</div>
<div class="collapse navbar-collapse" id="js-navbar-collapse">
<ul class="nav navbar-nav">
<!--<li class="{{id1}}" ng-init="id1='active'" ng-click="id1='active';id2='';id3='';id4='';id5='';id6='';"><a href="#/">Home</a></li>-->
<li class="dropdown {{id3||id6}}" ng-init="id3='active'">
<a href="" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Scale Test <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li class="{{id3}}"><a ng-href="#/ScaleTest" ng-click="id3='active';id1='';id2='';id6='';id4='';id5='';">Interactive Mode</a></li>
<li class="divider"></li>
<li class="{{id6}}"><a ng-href="#/IntervalReport" ng-click="id6='active';id1='';id2='';id3='';id4='';id5='';">Monitoring Mode</a></li>
</ul>
</li>
<li class="{{id2}}" ng-click="id2='active';id1='';id3='';id4='';id5='';id6='';"><a ng-href="#/Config">Configuration</a></li>
<li class="{{id4}}" ng-click="id4='active';id1='';id2='';id3='';id5='';id6='';"><a ng-href="#/Log">Log</a></li>
<li class="{{id5}}" ng-click="id5='active';id1='';id2='';id3='';id4='';id6='';"><a ng-href="#/About">About</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a ng-href="#/Login">Log Out</a></li>
</ul>
</div>
</div>
</div>
</div>
<div class="container">
<div ng-view=""></div>
</div>
<div class="footer">
<div class="container" style = "text-align:center;">
<!--<p><span class="glyphicon glyphicon-heart"></span>KloudBuster-->
<!--</p>-->
</div>
</div>
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID -->
<!--<script>-->
<!--!function(A,n,g,u,l,a,r){A.GoogleAnalyticsObject=l,A[l]=A[l]||function(){-->
<!--(A[l].q=A[l].q||[]).push(arguments)},A[l].l=+new Date,a=n.createElement(g),-->
<!--r=n.getElementsByTagName(g)[0],a.src=u,r.parentNode.insertBefore(a,r)-->
<!--}(window,document,'script','https://www.google-analytics.com/analytics.js','ga');-->
<!--ga('create', 'UA-XXXXX-X');-->
<!--ga('send', 'pageview');-->
<!--</script>-->
<!-- build:js(.) scripts/vendor.js -->
<!-- bower:js -->
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-animate/angular-animate.js"></script>
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
<script src="bower_components/angular-cookies/angular-cookies.js"></script>
<script src="bower_components/angular-resource/angular-resource.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
<script src="bower_components/angular-touch/angular-touch.js"></script>
<script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="bower_components/d3/d3.js"></script>
<script src="bower_components/moment/moment.js"></script>
<script src="bower_components/n3-line-chart/build/line-chart.js"></script>
<script src="bower_components/ng-table/dist/ng-table.min.js"></script>
<script src="bower_components/angular-loading-bar/build/loading-bar.js"></script>
<script src="bower_components/jquery-touchswipe/jquery.touchSwipe.js"></script>
<!-- endbower -->
<!-- endbuild -->
<!-- build:js({.tmp,app}) scripts/scripts.js -->
<script src="scripts/app.js"></script>
<script src="scripts/controllers/main.js"></script>
<script src="scripts/controllers/about.js"></script>
<script src="scripts/controllers/config.js"></script>
<script src="scripts/controllers/run.js"></script>
<script src="scripts/controllers/log.js"></script>
<script src="scripts/controllers/interval.js"></script>
<script src="scripts/controllers/login.js"></script>
<!-- endbuild -->
</body>
</html>

4
kb_web/app/robots.txt Normal file
View File

@ -0,0 +1,4 @@
# robotstxt.org
User-agent: *
Disallow:

BIN
kb_web/app/scripts/.DS_Store vendored Normal file

Binary file not shown.

69
kb_web/app/scripts/app.js Normal file
View File

@ -0,0 +1,69 @@
'use strict';
/**
* @ngdoc overview
* @name kbWebApp
* @description
* # kbWebApp
*
* Main module of the application.
*/
angular
.module('kbWebApp', [
'ngAnimate',
'ngCookies',
'ngResource',
'ngRoute',
'ngSanitize',
'ngTouch',
'ngTable',
'ui.bootstrap',
'angular-loading-bar',
'n3-line-chart'
])
.config(function ($routeProvider) {
$routeProvider
//.when('/', {
// templateUrl: 'views/main.html',
// controller: 'MainCtrl',
// controllerAs: 'main'
//})
.when('/About', {
templateUrl: 'views/about.html',
controller: 'AboutCtrl',
controllerAs: 'about'
})
.when('/Config', {
templateUrl: 'views/config.html',
controller: 'ConfigCtrl',
controllerAs: 'config'
})
.when('/ScaleTest', {
templateUrl: 'views/run.html',
controller: 'RunCtrl',
controllerAs: 'run'
})
.when('/IntervalReport', {
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'
})
.otherwise({
redirectTo: '/ScaleTest'
});
})
.config(['cfpLoadingBarProvider', function(cfpLoadingBarProvider) {
cfpLoadingBarProvider.latencyThreshold = 1;
}]);

View File

@ -0,0 +1,191 @@
'use strict';
/**
* @ngdoc function
* @name kbWebApp.controller:AboutCtrl
* @description
* # AboutCtrl
* Controller of the kbWebApp
*/
angular.module('kbWebApp')
.controller('AboutCtrl', function ($scope,$http,$location,kbHttp,kbCookie) {
this.awesomeThings = [
'HTML5 Boilerplate',
'AngularJS',
'Karma'
];
//---------------------------------get version---------------------------------
kbHttp.getMethod("/kloudbuster/version")
.then(
function(response) { // .resolve
$scope.version =response.data;
},
function(response) { // .reject
console.log("get version error:");
console.log(response);
}
);
})
.service('kbHttp', function($http,$q) {
var backendUrl = "http://127.0.0.1:8080/api";
this.getMethod = function(url) {
var deferred = $q.defer(); // declaration
$http.get(backendUrl + url)
.then(function (data) {
deferred.resolve(data); // success
},
function (data) {
deferred.reject(data); //error
});
return deferred.promise; // return promise(API)
};
this.getMethod2 = function(url) {//not show the processing bar
var deferred = $q.defer();
$http.get(backendUrl + url,{
ignoreLoadingBar: true
})
.then(function (data) {
deferred.resolve(data);
},
function (data) {
deferred.reject(data);
});
return deferred.promise;
};
this.putMethod = function(url, arg) {
var deferred = $q.defer(); // 声明延后执行,表示要去监控后面的执行
$http.defaults.headers.put['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
$http.put(backendUrl + url, "arg=" + encodeURIComponent(JSON.stringify(arg)))
.then(function (data) {
deferred.resolve(data); // 声明执行成功即http请求数据成功可以返回数据了
},
function (data) {
deferred.reject(data); // 声明执行失败,即服务器返回错误
});
return deferred.promise; // 返回承诺这里并不是最终数据而是访问最终数据的API
};
this.postMethod = function(url, arg) {
var deferred = $q.defer(); // 声明延后执行,表示要去监控后面的执行
if(arg) {
$http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
$http.post(backendUrl + url, "arg=" + encodeURIComponent(JSON.stringify(arg)))
.then(function (data) {
deferred.resolve(data); // 声明执行成功即http请求数据成功可以返回数据了
},
function (data) {
deferred.reject(data); // 声明执行失败,即服务器返回错误
});
return deferred.promise; // 返回承诺这里并不是最终数据而是访问最终数据的API
}
else
{
$http.post(backendUrl + url)
.then(function (data) {
deferred.resolve(data); // 声明执行成功即http请求数据成功可以返回数据了
},
function (data) {
deferred.reject(data); // 声明执行失败,即服务器返回错误
});
return deferred.promise; // 返回承诺这里并不是最终数据而是访问最终数据的API
}
};
this.delMethod = function(url) {
var deferred = $q.defer(); // 声明延后执行,表示要去监控后面的执行
$http.delete(backendUrl + url)
.then(function (data) {
deferred.resolve(data); // 声明执行成功即http请求数据成功可以返回数据了
},
function (data) {
deferred.reject(data); // 声明执行失败,即服务器返回错误
});
return deferred.promise; // 返回承诺这里并不是最终数据而是访问最终数据的API
};
})
.service('kbCookie', function() {
//var self = this;
this.init = function(){
sessionID = "";
status = "";
config = "";
credentials = "";
topology = "";
logOffset = 0;
isOneCloud="";
topology = "";
logOffset = 0;
};
var sessionID = "";
this.getSessionID = function(){
return sessionID;
};
this.setSessionID = function(session){
sessionID = session;
return sessionID;
};
var status = "";
this.getStatus = function(){
return status;
};
this.setStatus = function(sta){
status = sta;
return status;
};
var config = "";
this.getConfig = function(){
return config;
};
this.setConfig = function(con){
config = con;
return config;
};
var credentials = "";
this.getCredentials = function(){
return credentials;
};
this.setCredentials = function(cred){
credentials = cred;
return credentials;
};
var isOneCloud = "";
this.getIsOneCloud = function(){
return isOneCloud;
};
this.setIsOneCloud = function(one){
isOneCloud = one;
return isOneCloud;
};
var topology = "";
this.getTopology = function(){
return topology;
};
this.setTopology = function(top){
topology = top;
return topology;
};
var logOffset = 0;
this.getLogOffset = function(){
return logOffset;
};
this.setLogOffset = function(offset){
logOffset = offset;
return logOffset;
};
});

View File

@ -0,0 +1,465 @@
'use strict';
/**
* @ngdoc function
* @name kbWebApp.controller:AboutCtrl
* @description
* # ConfigCtrl
* Controller of the kbWebApp
*/
angular.module('kbWebApp')
.controller('ConfigCtrl', function ($scope,$http,$location,kbHttp,kbCookie) {
this.awesomeThings = [
'HTML5 Boilerplate',
'AngularJS',
'Karma'
];
if(kbCookie.getSessionID()==="") $location.path('/Login');
$scope.sessionID=kbCookie.getSessionID();
$scope.status=kbCookie.getStatus();
//------------------------------------------------------
$scope.dashstatus1="active";
$scope.dashstatus1vis=true;
$scope.dashstatus2="";
$scope.dashstatus2vis=false;
$scope.dashstatus3="";
$scope.dashstatus3vis=false;
$scope.setDashStatus = function(dashNum){
if(dashNum===1){
$scope.dashstatus2="";
$scope.dashstatus2vis=false;
$scope.dashstatus3="";
$scope.dashstatus3vis=false;
$scope.dashstatus1="active";
$scope.dashstatus1vis=true;
}
else if (dashNum===2){
$scope.dashstatus1="";
$scope.dashstatus1vis=false;
$scope.dashstatus3="";
$scope.dashstatus3vis=false;
$scope.dashstatus2="active";
$scope.dashstatus2vis=true;
}
else if (dashNum===3){
$scope.dashstatus1="";
$scope.dashstatus1vis=false;
$scope.dashstatus2="";
$scope.dashstatus2vis=false;
$scope.dashstatus3="active";
$scope.dashstatus3vis=true;
}
};
//----------------------------topology------------------------------
var userData;
$scope.setUserData = function(top){
var count = 1;
var x;
for(x in top){
userData.push({"id":count++,"firstName":top[x]});
}
$scope.listA = userData.slice(0,userData.length);
$scope.items = userData;
};
// init
function init()
{
$scope.selectedA = [];
$scope.selectedB = [];
$scope.selectedC = [];
userData=[];
$scope.listA = [];
$scope.listB = [];
$scope.listC = [];
$scope.toggle=false;
}
init();
//$scope.checkedA = false;
//$scope.checkedB = false;
function arrayObjectIndexOf(myArray, searchTerm, property) {
for(var i = 0, len = myArray.length; i < len; i++) {
if (myArray[i][property] === searchTerm) return i;
}
return -1;
}
function arrayObjectIndexOf2(myArray, searchTerm) {
for(var i = 0, len = myArray.length; i < len; i++) {
if (myArray[i] === searchTerm) return i;
}
return -1;
}
$scope.aToB = function() {
for (var i in $scope.selectedA) {
var moveId = arrayObjectIndexOf($scope.items, $scope.selectedA[i], "id");
$scope.listB.push($scope.items[moveId]);
var delId = arrayObjectIndexOf($scope.listA, $scope.selectedA[i], "id");
$scope.listA.splice(delId,1);
}
reset();
};
$scope.aToC = function() {
for (var i in $scope.selectedA) {
var moveId = arrayObjectIndexOf($scope.items, $scope.selectedA[i], "id");
$scope.listC.push($scope.items[moveId]);
var delId = arrayObjectIndexOf($scope.listA, $scope.selectedA[i], "id");
$scope.listA.splice(delId,1);
}
reset();
};
$scope.bToA = function() {
for (var i in $scope.selectedB) {
var moveId = arrayObjectIndexOf($scope.items, $scope.selectedB[i], "id");
$scope.listA.push($scope.items[moveId]);
var delId = arrayObjectIndexOf($scope.listB, $scope.selectedB[i], "id");
$scope.listB.splice(delId,1);
}
reset();
};
$scope.cToA = function() {
for (var i in $scope.selectedC) {
var moveId = arrayObjectIndexOf($scope.items, $scope.selectedC[i], "id");
$scope.listA.push($scope.items[moveId]);
var delId = arrayObjectIndexOf($scope.listC, $scope.selectedC[i], "id");
$scope.listC.splice(delId,1);
}
reset();
};
function reset(){
$scope.selectedA=[];
$scope.selectedB=[];
$scope.selectedC=[];
$scope.toggle=false;
}
$scope.toggleA = function() {
if ($scope.selectedA.length>0) {
reset();
}
else {
for (var i in $scope.listA) {
$scope.selectedB=[];
$scope.selectedC=[];
$scope.selectedA.push($scope.listA[i].id);
}
}
};
$scope.toggleB = function() {
if ($scope.selectedB.length>0) {
reset();
}
else {
for (var i in $scope.listB) {
$scope.selectedA=[];
$scope.selectedC=[];
$scope.selectedB.push($scope.listB[i].id);
}
}
};
$scope.toggleC = function() {
if ($scope.selectedC.length>0) {
reset();
}
else {
for (var i in $scope.listC) {
$scope.selectedA=[];
$scope.selectedB=[];
$scope.selectedC.push($scope.listC[i].id);
}
}
};
$scope.selectA = function(i) {
var delId = arrayObjectIndexOf2($scope.selectedA, i);
//console.log(delId,i);
if(delId===-1)
$scope.selectedA.push(i);
else
$scope.selectedA.splice(delId,1);
};
$scope.selectB = function(i) {
var delId = arrayObjectIndexOf2($scope.selectedB, i);
//console.log(delId,i);
if(delId===-1)
$scope.selectedB.push(i);
else
$scope.selectedB.splice(delId,1);
};
$scope.selectC = function(i) {
var delId = arrayObjectIndexOf2($scope.selectedC, i);
//console.log(delId,i);
if(delId===-1)
$scope.selectedC.push(i);
else
$scope.selectedC.splice(delId,1);
};
//-----------------------end of topology---------------------
$scope.checkStatus = function(){
if($scope.sessionID) {
kbHttp.getMethod2("/kloudbuster/status/" + $scope.sessionID)
.then(
function (response) { // .resolve
$scope.status = response.data.status;
kbCookie.setStatus($scope.status);
$scope.configStatus();
},
function (response) { // .reject
console.log("get status error:");
console.log(response);
}
);
}
else
{
$scope.status = "NO SESSION ID";
kbCookie.setStatus("");
}
};
$scope.checkStatus();
var disabledStagingConfig=false;
$scope.disableConfig = function(disableId){
$("#"+disableId).find("input").each(function() {//show Config
$(this).attr("disabled", "disabled");
//$(this).removeAttr("disabled");
});
};
$scope.enableConfig = function(enableId){
$("#"+enableId).find("input").each(function() {//disable Config
//$(this).attr("disabled", "disabled");
$(this).removeAttr("disabled");
});
};
$scope.configStatus = function(){
if($scope.status === "READY")//show all config
{
if(disabledStagingConfig===true)
{
disabledStagingConfig=false;
$scope.enableConfig("stagingConfig2");
$scope.enableConfig("getButton");
}
}
else//no config can be modified
{
if(disabledStagingConfig===false)
{
disabledStagingConfig=true;
$scope.disableConfig("stagingConfig2");
$scope.disableConfig("getButton");
}
}
if(kbCookie.getIsOneCloud()===false)
{
$scope.disableConfig("topology");
}
};
$scope.getTopology = function() {
kbHttp.getMethod("/config/hypervisor_list/" + $scope.sessionID)
.then(
function (response) { // 调用承诺API获取数据 .resolve
$scope.setUserData(response.data.server);
console.log("get hypervisor list");
},
function (response) { // 处理错误 .reject
console.log("get hypervisor list error:");
console.log(response);
}
)
};
//$scope.getTopology();
$scope.getDefaultConfig = function() {
kbHttp.getMethod("/config/default_config")
.then(
function(response) { // .resolve
kbCookie.setConfig(response.data);
$scope.config =response.data;
console.log("get & save default config");
},
function(response) { // .reject
console.log("get default config error:");
console.log(response);
}
);
//$scope.config =JSON.stringify(response);
$scope.getTopology();
kbCookie.setTopology("");
$scope.availability_zone=1;
userData=[];
init();
};
$scope.getRunConfig = function() {
$scope.availability_zone=1;
kbHttp.getMethod("/config/running_config/" + $scope.sessionID)
.then(
function (response) { // .resolve
kbCookie.setConfig(response.data);
$scope.config = response.data;
if(($scope.config.server.availability_zone!=null && $scope.config.server.availability_zone!="") || ($scope.config.client.availability_zone!=null && $scope.client.server.availability_zone!=""))
{
$scope.availability_zone=2;
}
console.log("get & save running config");
},
function (response) { // .reject
console.log("get running config error:");
console.log(response);
}
);
init();
$scope.getTopology();
kbHttp.getMethod("/config/topology_config/" + $scope.sessionID)
.then(
function (response) { // .resolve
//kbCookie.setConfig(response.data);
//$scope.config = response.data;
if(response.data!="null" && (response.data.servers_rack.length!=0 || response.data.clients_rack.length!=0))
{
$scope.availability_zone=3;
$scope.topology = {"servers_rack": response.data.servers_rack, "clients_rack": response.data.clients_rack};
kbCookie.setTopology($scope.topology);
console.log(response.data);
for (var i in $scope.topology.servers_rack) {
var moveId = arrayObjectIndexOf($scope.items, $scope.topology.servers_rack[i], "firstName");
$scope.listC.push($scope.items[moveId]);
var delId = arrayObjectIndexOf($scope.listA, $scope.topology.servers_rack[i], "firstName");
$scope.listA.splice(delId,1);
}
for (var i in $scope.topology.clients_rack) {
var moveId = arrayObjectIndexOf($scope.items, $scope.topology.clients_rack[i], "firstName");
$scope.listB.push($scope.items[moveId]);
var delId = arrayObjectIndexOf($scope.listA, $scope.topology.clients_rack[i], "firstName");
$scope.listA.splice(delId,1);
}
}
console.log("get & save topology config");
},
function (response) { // .reject
console.log("get topology config error:");
console.log(response);
}
);
};
$scope.getRunConfig();
$scope.changeConfig = function() {
if($scope.status==="READY"|| $scope.status==="") {
kbCookie.setConfig($scope.config);
if($scope.availability_zone==3) {
$scope.topology = {"servers_rack": [], "clients_rack": []};
for (var t in $scope.listC) {
$scope.topology.servers_rack.push($scope.listC[t].firstName);
}
for (var t in $scope.listB) {
$scope.topology.clients_rack.push($scope.listB[t].firstName);
}
kbCookie.setTopology($scope.topology);
console.log($scope.topology);
}
else{
kbCookie.setTopology({"servers_rack":"", "clients_rack": ""});
}
$scope.chaCon = {"kb_cfg": {},"topo_cfg":{}};
$scope.chaCon.kb_cfg = kbCookie.getConfig();
$scope.chaCon.topo_cfg = kbCookie.getTopology();
console.log($scope.chaCon);
kbHttp.putMethod("/config/running_config/" + $scope.sessionID, $scope.chaCon)
.then(
function (response) { // .resolve
console.log("change running config");
},
function (response) { // .reject
console.log("change running config error:");
console.log(response);
}
)
}
else{
console.log("config not allow to change now!");
}
};
$scope.changeTopology = function(){
if($scope.availability_zone==1)
{
$scope.config.server.availability_zone = "";
$scope.config.client.availability_zone = "";
$scope.topology = {};
kbCookie.setTopology({"servers_rack":"", "clients_rack": ""});
init();
$scope.getTopology();
}
else if($scope.availability_zone==2)
{
$scope.topology = {};
kbCookie.setTopology({"servers_rack":"", "clients_rack": ""});
init();
$scope.getTopology();
}
else if($scope.availability_zone==3)
{
$scope.config.server.availability_zone = "";
$scope.config.client.availability_zone = "";
}
};
});

View File

@ -0,0 +1,564 @@
/**
* Created by xiyu3 on 9/8/15.
*/
'use strict';
angular.module('kbWebApp')
.controller('IntervalCtrl', function ($scope, $http, kbHttp, $q, $location, kbCookie, monitorMode) {
this.awesomeThings = [
'HTML5 Boilerplate',
'AngularJS',
'Karma'
];
if(kbCookie.getSessionID()==="") $location.path('/Login');
$("[data-toggle='.container']").click(function() {
var toggle_el1 = $(this).data("toggle");
$(toggle_el1).toggleClass("open-sidebar");
$("#littleglyph1").toggleClass("glyphicon-triangle-right");
$("#littleglyph1").toggleClass("glyphicon-triangle-left");
//$("#content").toggleClass("content-smaller");
});
$(".swipe-area").swipe({
swipeStatus:function(event, phase, direction, distance, duration, fingers)
{
if (phase=="move" && direction =="right") {
$(".container").addClass("open-sidebar");
return false;
}
if (phase=="move" && direction =="left") {
$(".container").removeClass("open-sidebar");
return false;
}
}
});
$scope.oneAtATime = true;
$scope.status1 = {
isFirstOpen: true,
isFirstDisabled: false
};
$scope.status2 = {
isFirstOpen: true,
isFirstDisabled: false
}
$scope.status1.open = false;
$scope.status2.open = true;
$scope.alerts = [];
$scope.closeAlert = function(index) {
$scope.alerts.splice(index, 1);
};
$scope.sessionID=kbCookie.getSessionID();
$scope.status=kbCookie.getStatus();
$scope.config=kbCookie.getConfig();
//$scope.credentials=kbCookie.getCredentials();
$scope.getRunConfig = function() {
kbHttp.getMethod("/config/running_config/" + $scope.sessionID)
.then(
function(response) { // .resolve
$scope.config = response.data;
kbCookie.setConfig(response.data);
console.log("get & save config");
},
function(response) { // .reject
console.log("get running config error:");
console.log(response);
}
);
};
if($scope.sessionID && !$scope.config)
{
$scope.getRunConfig();
}
$scope.setConfig = function() {
var deferred = $q.defer();
if($scope.status==="READY") {
$scope.config.client.progression.enabled = false;//!!
kbCookie.setConfig($scope.config);
$scope.chaCon = {"kb_cfg": {}};
$scope.chaCon.kb_cfg = kbCookie.getConfig();
//$scope.chaCon.kb_cfg.client.progression.enabled = false;//!!
//console.log($scope.chaCon);
kbHttp.putMethod("/config/running_config/" + $scope.sessionID, $scope.chaCon)
.then(
function (response) { // .resolve
console.log("change running config");
deferred.resolve(1);
},
function (response) { // .reject
console.log("change running config error:");
console.log(response);
deferred.reject(0);
}
);
}
else if($scope.status==="STAGED"){
if ($scope.config.client.progression.enabled === true) {
alert("Can't Run Monitor Test Now! You have chosen Progression Test. Click Unstage Button First!");
deferred.reject(0);
return deferred.promise;
}
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":$scope.config.client.http_tool_configs.report_interval}}}};
console.log($scope.chaCon);
kbHttp.putMethod("/config/running_config/" + $scope.sessionID, $scope.chaCon)
.then(
function (response) { // .resolve
console.log("change running config");
deferred.resolve(1);
},
function (response) { // .reject
console.log("change running config error:");
console.log(response);
deferred.reject(0);
}
);
}
else{
console.log("config not allow to change now!");
deferred.reject(0);
}
return deferred.promise;
};
var disabledStagingConfig=false;
var disabledRunningConfig=false;
$scope.disableConfig = function(disableId){
$("#"+disableId).find("input").each(function() {//show Config
$(this).attr("disabled", "disabled");
//$(this).removeAttr("disabled");
});
};
$scope.enableConfig = function(enableId){
$("#"+enableId).find("input").each(function() {//disable Config
//$(this).attr("disabled", "disabled");
$(this).removeAttr("disabled");
});
};
$scope.configStatus = function(){
if($scope.status === "READY")//show all config
{
if(disabledStagingConfig===true)
{
disabledStagingConfig=false;
$scope.enableConfig("stagingConfig");
}
if(disabledRunningConfig===true) {
disabledRunningConfig = false;
$scope.enableConfig("runningConfig");
}
}
else if($scope.status === "STAGED") //show running config
{
if(disabledStagingConfig===false)
{
disabledStagingConfig=true;
$scope.disableConfig("stagingConfig");
}
if(disabledRunningConfig===true) {
disabledRunningConfig = false;
$scope.enableConfig("runningConfig");
}
}
else//no config can be modified
{
if(disabledStagingConfig===false)
{
disabledStagingConfig=true;
$scope.disableConfig("stagingConfig");
}
if(disabledRunningConfig===false) {
disabledRunningConfig = true;
$scope.disableConfig("runningConfig");
}
}
};
var pointNumber = 0;
$scope.pointNum = function(){
var point = ".";
pointNumber = (pointNumber+1)%6;
for(var x = 0; x < pointNumber; x++)
{
point = point + " .";
}
return point;
};
$scope.runButton = "Run Test";
$scope.runStatus = true;//if run Button disabled
$scope.setStatus = false;//if settings Button disabled
$scope.setUnstage = true;//if Unstage Button disabled
$scope.client_vm_count = 0;
$scope.server_vm_count = 0;
$scope.checkStatus = function(){
if($scope.sessionID) {
kbHttp.getMethod2("/kloudbuster/status/" + $scope.sessionID)
.then(
function (response) { // .resolve
$scope.status = response.data.status;
$scope.configStatus();
kbCookie.setStatus($scope.status);
if ($scope.status === "READY") {
$scope.runButton = "Create VMs";
$scope.runStatus = false;//show button
$scope.setStatus = false;//show button
$scope.setUnstage = true;//disable button
$scope.client_vm_count = 0;
$scope.server_vm_count = 0;
$(".loading").addClass("pause");
$scope.info="";
}
else if ($scope.status === "STAGING") {
$scope.runButton = "Run Test";
$scope.runStatus = true;
$scope.setStatus = true;
$scope.setUnstage = true;
$scope.client_vm_count = response.data.client_vm_count;
$scope.server_vm_count = response.data.server_vm_count;
$(".loading").removeClass("pause");
$scope.info="KloudBuster is Creating VM(s)"+$scope.pointNum();
}
else if ($scope.status === "STAGED") {
$scope.runButton = "Run Test";
$scope.runStatus = false;
$scope.setStatus = false;
$scope.setUnstage = false;
$scope.client_vm_count = $scope.config.server.routers_per_tenant * $scope.config.server.networks_per_router * $scope.config.server.vms_per_network * $scope.config.server.number_tenants;
$scope.server_vm_count = $scope.client_vm_count;
$(".loading").addClass("pause");
$scope.info="";
}
else if ($scope.status === "RUNNING") {
$scope.runButton = "Stop Test";
$scope.runStatus = false;
$scope.setStatus = true;
$scope.setUnstage = true;
$scope.getSeqReport();
$scope.client_vm_count = $scope.config.server.routers_per_tenant * $scope.config.server.networks_per_router * $scope.config.server.vms_per_network * $scope.config.server.number_tenants;
$scope.server_vm_count = $scope.client_vm_count;
$(".loading").removeClass("pause");
$scope.info="KloudBuster is Running"+$scope.pointNum();
}
else if ($scope.status === "ERROR") {
$scope.runButton = "Run Test";
$scope.runStatus = true;
$scope.setStatus = true;
$scope.setUnstage = false;
$scope.client_vm_count = $scope.config.server.routers_per_tenant * $scope.config.server.networks_per_router * $scope.config.server.vms_per_network * $scope.config.server.number_tenants;
$scope.server_vm_count = $scope.client_vm_count;
$(".loading").addClass("pause");
$scope.info="";
}
else if($scope.status === "CLEANING" || $scope.status === "STOPPING")
{
$scope.runButton = "Run Test";
$scope.runStatus = true;
$scope.setStatus = true;
$scope.setUnstage = true;
$scope.client_vm_count = $scope.config.server.routers_per_tenant * $scope.config.server.networks_per_router * $scope.config.server.vms_per_network * $scope.config.server.number_tenants;
$scope.server_vm_count = $scope.client_vm_count;
$(".loading").removeClass("pause");
$scope.info="Please Wait"+$scope.pointNum();
}
{
}
},
function (response) { // .reject
console.log("get status error:");
console.log(response);
}
);
}
else
{
$scope.status = "NO SESSION ID";
}
};
$scope.checkStatus();
$scope.setStage = function(){
kbHttp.postMethod("/kloudbuster/stage/" + $scope.sessionID)
.then(
function(response) { // .resolve
$scope.checkStatus();
},
function(response) { // .reject
console.log("set stage error:");
console.log(response);
}
);
};
$scope.runKb = function(){
kbHttp.postMethod("/kloudbuster/run_test/" + $scope.sessionID)
.then(
function(response) { // .resolve
$scope.checkStatus();
},
function(response) { // .reject
console.log("running error:");
console.log(response);
}
);
};
$scope.stopKb = function(){
kbHttp.postMethod("/kloudbuster/stop_test/" + $scope.sessionID)
.then(
function(response) { // .resolve
$scope.checkStatus();
},
function(response) { // .reject
console.log("stop error:");
console.log(response);
}
);
};
$scope.scaleTest = function(){
if($scope.status==="RUNNING"){
//$scope.initChart();
$scope.stopKb();
}
else {
var promise = $scope.setConfig();
promise.then(function () {
if ($scope.status === "READY") {
$scope.setStage();
}
else if ($scope.status === "STAGED") {
if ($scope.config.client.progression.enabled === true) {
alert("Can't Run Monitor Test Now! You have chosen Progression Test. Clean Up First!");
}
else {
$scope.initChart();
$scope.runKb();
}
}
else {
}
});
}
};
$scope.CleanUp = function(){
$scope.initChart();
if($scope.sessionID) {
kbHttp.postMethod("/kloudbuster/cleanup/" + $scope.sessionID)
.then(
function(response) { // .resolve
$scope.checkStatus();
console.log("clean up successfully");
},
function(response) { // .reject
console.log("clean error:");
console.log(response);
}
);
}
else{
console.log("no sessionID");
}
};
//---------------------------chart---------------------------
$scope.data = [
{x: new Date()}
];
$scope.isDely=false;
var count = 0;
$scope.initChart = function() {
$scope.data = [
{x: new Date()}
];
$scope.isDely=false;
count = 0;
monitorMode.setResult("");
};
//$scope.initChart();
//$scope.data = [
// {
// x: new Date(),
// val_0: 23,
// val_1: 4,
// val_2: 16,
// val_3: 270,
// val_4: 8,
// val_5: 97,
// val_6: 57
// }
//];
$scope.options = {
axes: {
x: {type: "date"},
y: {type: 'log', ticksFormat: 'd', innerTicks: true, grid: true}
},
series: [
{y: "val_6", label: "99.999%", type: "area", color: "#084594", dotSize: "0", thickness: "2px"},
{y: "val_5", label: "99.99%", type: "area", color: "#2171b5", dotSize: "0", thickness: "2px",visible:false},
{y: "val_4", label: "99.9%", type: "area", color: "#4292c6", dotSize: "0", thickness: "2px",visible:false},
{y: "val_3", label: "99%", type: "area", color: "#6baed6", 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:false},
{y: "val_0", label: "50%", type: "area", color: "#eff3ff", dotSize: "0", thickness: "2px"}
],
tooltip: {mode: 'scrubber', formatter: function(x, y, series) {return series.label+":"+y;}},
tension: 0.9,
lineMode: "cardinal"
};
$scope.data.forEach(function(row) {
row.x = new Date(row.x);
});
$scope.getSeqReport = function(){
kbHttp.getMethod2("/kloudbuster/report/"+$scope.sessionID)
.then(
function(response) { // .resolve
$scope.result = response.data.report;
$scope.seq = response.data.seq;
console.log("get seq report:"+$scope.seq);
//console.log(response.data);
if($scope.seq && $scope.seq > count) {
count = $scope.seq;
if($scope.data.length>40) $scope.data.shift();
$scope.pushChartData("SEQ_"+$scope.seq, $scope.result);
}
else {}
},
function(response) { // .reject
console.log("get seq report error:");
console.log(response);
}
);
};
$scope.pushChartData = function(chName,chData){
//console.log("chart date"+ chName);
if ($scope.isDely === false) {
$scope.data.shift();
$scope.isDely = true;
}
$scope.data.push({
x:new Date(),
val_0: chData.latency_stats[0][1] / 1000,
val_1: chData.latency_stats[1][1] / 1000,
val_2: chData.latency_stats[2][1] / 1000,
val_3: chData.latency_stats[3][1] / 1000,
val_4: chData.latency_stats[4][1] / 1000,
val_5: chData.latency_stats[5][1] / 1000,
val_6: chData.latency_stats[6][1] / 1000
});
monitorMode.setResult($scope.data);
//console.log($scope.data);
};
if(monitorMode.getResult())
{
$scope.data = monitorMode.getResult();
}
//$scope.aaa = '{"report":{"latency_stats":[[50,1800],[75,2255],[90,2607],[99,3135],[99.9,3487],[99.99,3647],[99.999,3647]],"tool":"wrk2","http_rps":519,"http_throughput_kbytes":16752,"http_sock_timeout":0,"http_total_req":2600,"http_sock_err":0},"seq":5}';
//$scope.pushChartData("SEQ_",JSON.parse($scope.aaa).report);
function downloadFile(fileName, content){
var aLink = document.createElement('a');
var blob = new Blob([content]);
var evt = document.createEvent("HTMLEvents");
evt.initEvent("click", false, false);//initEvent
aLink.download = fileName;
aLink.href = URL.createObjectURL(blob);
aLink.dispatchEvent(evt);
}
$scope.saveResult = function(){
var date = new Date();
var m = date.getMonth()+1;//month (0-11,0 = Jan., remember to add 1)
var d = date.getDate();//day(1-31)
var h = date.getHours();//hour(0-23)
var min = date.getMinutes();//minute(0-59)
var filename = m+d+h+min+".json";
console.log(filename);
if(monitorMode.getResult()!="")
downloadFile(filename, JSON.stringify(monitorMode.getResult()));
else console.log("no file to save");
};
setInterval(function(){
$scope.checkStatus();
},2000);
})
.service('monitorMode', function() {
//var self = this;
var result="";
this.getResult = function(){
return result;
};
this.setResult = function(res){
result = res;
return result;
};
});

View File

@ -0,0 +1,77 @@
/**
* Created by xiyu3 on 9/8/15.
*/
'use strict';
angular.module('kbWebApp')
.controller('LogCtrl', function ($scope, $compile, $http, $location, kbHttp,kbCookie) {
this.awesomeThings = [
'HTML5 Boilerplate',
'AngularJS',
'Karma'
];
if(kbCookie.getSessionID()==="") $location.path('/Login');
String.prototype.replaceAll = function(s1,s2){
return this.replace(new RegExp(s1,"gm"),s2);
};
$scope.sessionID=kbCookie.getSessionID();
$scope.status=kbCookie.getStatus();
$scope.logs="";
//kbCookie.getLogOffset();
$scope.logOffset=0;
$scope.delLog = function() {
kbCookie.setLogOffset($scope.logOffset);
$("#cc").empty();
$scope.getLog();
};
//---------------------------------get LOG---------------------------------
$scope.getLog = function() {
if ($scope.sessionID) {
kbHttp.getMethod("/kloudbuster/log/" + $scope.sessionID + "?offset="+ kbCookie.getLogOffset())
.then(
function (response) { // .resolve
//console.log(response);
response.data = response.data.substring(1,response.data.length-1);
//console.log(response.data);
$scope.logOffset=kbCookie.getLogOffset() + response.data.length -1;
//$scope.logOffset=1529;
//console.log(response.data.length, kbCookie.getLogOffset(),$scope.logOffset);
$scope.logs = response.data.split("\\n");
$("#cc").empty();
for(var row in $scope.logs)
{
$scope.logs[row]=$scope.logs[row].replace(/ /g, "&nbsp;");
$("#cc").append($scope.logs[row]+"<br/>");
//console.log($scope.logs[row]);
}
//$scope.logs[0]= $scope.logs[0].replace(/"/,"");
//$scope.logs.pop();
},
function (response) { // .reject
console.log("get Log error:");
console.log(response);
}
);
}
else{ console.log("not connected "+ $scope.status +","+ $scope.sessionID)}
};
$scope.getLog();
});

View File

@ -0,0 +1,127 @@
/**
* Created by xiyu3 on 10/12/15.
*/
'use strict';
angular.module('kbWebApp')
.controller('LoginCtrl', function ($scope,$http,$location,kbHttp,kbCookie) {
this.awesomeThings = [
'HTML5 Boilerplate',
'AngularJS',
'Karma'
];
//if(kbCookie.getSessionID()!="") $location.path('/');
$scope.deleteSession = function(){
kbHttp.delMethod("/config/running_config/" + $scope.sessionID)
.then(
function (response) { // .resolve
console.log("del sessionID");
},
function (response) { // .reject
console.log("delete error:");
console.log(response);
}
);
};
$scope.CleanUp = function(){
kbHttp.postMethod("/kloudbuster/cleanup/" + $scope.sessionID)
.then(
function(response) { // .resolve
console.log("clean up successfully");
},
function(response) { // .reject
console.log("clean error:");
console.log(response);
}
);
};
if(kbCookie.getSessionID()!="") {
$scope.sessionID=kbCookie.getSessionID();
if(kbCookie.getStatus()!="READY")
{
$scope.CleanUp();
}
$scope.deleteSession();
kbCookie.init();
}
//---------------------------------credentials--------------------------------
$scope.samecloud = true;
$scope.clouds = function() {
if($scope.samecloud===true) {
$('#inputPassword2').attr("disabled",true);
$('#file2').attr("disabled",true);
}
else{
$('#inputPassword2').attr("disabled",false);
$('#file2').attr("disabled",false);
}
//console.log($scope.samecloud);
};
var test_rc;
function readFile (evt) {
var files = evt.target.files;
var file = files[0];
var reader = new FileReader();
reader.onload = function() {
test_rc = this.result;
//console.log(this.result);
};
reader.readAsText(file);
}
document.getElementById('file1').addEventListener('change', readFile, false);
var test_rc2;
function readFile2 (evt) {
var files = evt.target.files;
var file = files[0];
var reader = new FileReader();
reader.onload = function() {
test_rc2 = this.result;
//console.log(this.result);
};
reader.readAsText(file);
}
document.getElementById('file2').addEventListener('change', readFile2, false);
$scope.setConfig = function() {
if($scope.samecloud===true){
kbCookie.setIsOneCloud(true);
$scope.credentials = { "tested-passwd": $scope.inputPassword1, "tested-rc": test_rc, "testing-passwd":"", "testing-rc":""};
}
else{
kbCookie.setIsOneCloud(false);
$scope.credentials = { "tested-passwd": $scope.inputPassword1, "tested-rc": test_rc, "testing-passwd":inputPassword2, "testing-rc":test_rc2};
}
//no sessionID but have cred
$scope.runCon = {"credentials":{},kb_cfg:""};
console.log($scope.credentials);
$scope.runCon.credentials = $scope.credentials;
kbCookie.setCredentials($scope.credentials);
kbHttp.postMethod("/config/running_config", $scope.runCon)
.then(
function(response) { // .resolve
kbCookie.setSessionID(response.data);
$scope.sessionID = kbCookie.getSessionID();
console.log("set config & get sesID:" + $scope.sessionID);
$location.path('/');
},
function(response) { // .reject
console.log("set config error:");
console.log(response);
}
);
}
});

View File

@ -0,0 +1,28 @@
'use strict';
/**
* @ngdoc function
* @name kbWebApp.controller:MainCtrl
* @description
* # MainCtrl
* Controller of the kbWebApp
*/
angular.module('kbWebApp')
.controller('MainCtrl', function ($scope,$http,$location,kbHttp,kbCookie) {
this.awesomeThings = [
'HTML5 Boilerplate',
'AngularJS',
'Karma'
];
//---------------------------------get version---------------------------------
kbHttp.getMethod("/kloudbuster/version")
.then(
function(response) { // .resolve
$scope.version =response.data;
},
function(response) { // .reject
console.log("get version error:");
console.log(response);
}
);
});

View File

@ -0,0 +1,654 @@
/**
* Created by xiyu3 on 9/8/15.
*/
'use strict';
angular.module('kbWebApp')
.controller('RunCtrl', function ($scope, $timeout, $location, $http, $q, ngTableParams, kbCookie, kbHttp, interactiveMode, color) {
this.awesomeThings = [
'HTML5 Boilerplate',
'AngularJS',
'Karma'
];
if(kbCookie.getSessionID()==="") $location.path('/Login');
$("[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");
//$("#content").toggleClass("content-smaller");
});
$(".swipe-area").swipe({
swipeStatus:function(event, phase, direction, distance, duration, fingers)
{
if (phase=="move" && direction =="right") {
$(".container").addClass("open-sidebar");
return false;
}
if (phase=="move" && direction =="left") {
$(".container").removeClass("open-sidebar");
return false;
}
}
});
$scope.oneAtATime = true;
$scope.status1 = {
isFirstOpen: true,
isFirstDisabled: false
};
$scope.status2 = {
isFirstOpen: true,
isFirstDisabled: false
};
$scope.status3 = {
isFirstOpen: true,
isFirstDisabled: false
};
$scope.status1.open = false;
$scope.status2.open = true;
$scope.status3.open = false;
$scope.alerts = [];
$scope.closeAlert = function(index) {
$scope.alerts.splice(index, 1);
};
$scope.sessionID=kbCookie.getSessionID();
$scope.status=kbCookie.getStatus();
$scope.config=kbCookie.getConfig();
//$scope.credentials=kbCookie.getCredentials();
$scope.getRunConfig = function() {
kbHttp.getMethod("/config/running_config/" + $scope.sessionID)
.then(
function(response) { // .resolve
$scope.config = response.data;
kbCookie.setConfig(response.data);
console.log("get & save config");
},
function(response) { // .reject
console.log("get running config error:");
console.log(response);
}
);
};
if($scope.sessionID && !$scope.config)
{
$scope.getRunConfig();
}
//if(!$scope.sessionID && !$scope.config)
// $scope.alerts.push({ type: 'alert', msg: 'Set Configuration First!' });
//$scope.alerts.push({type: 'alert', msg: 'No Configuration!'});
$scope.setConfig = function() {
var deferred = $q.defer();
if($scope.status==="READY") {
kbCookie.setConfig($scope.config);
$scope.chaCon = {"kb_cfg": {}};
$scope.chaCon.kb_cfg = kbCookie.getConfig();
console.log($scope.chaCon);
kbHttp.putMethod("/config/running_config/" + $scope.sessionID, $scope.chaCon)
.then(
function (response) { // .resolve
console.log("change running config");
deferred.resolve(1);
},
function (response) { // .reject
console.log("change running config error:");
console.log(response);
deferred.reject(0);
}
);
}
else if($scope.status==="STAGED"){
$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}}}};
console.log($scope.chaCon);
kbHttp.putMethod("/config/running_config/" + $scope.sessionID, $scope.chaCon)
.then(
function (response) { // .resolve
console.log("change running config");
deferred.resolve(1);
},
function (response) { // .reject
console.log("change running config error:");
console.log(response);
deferred.reject(0);
}
);
}
else{
console.log("config not allow to change now!");
deferred.reject(0);
}
return deferred.promise;
};
var disabledStagingConfig=false;
var disabledRunningConfig=false;
$scope.disableConfig = function(disableId){
$("#"+disableId).find("input").each(function() {//show Config
$(this).attr("disabled", "disabled");
//$(this).removeAttr("disabled");
});
};
$scope.enableConfig = function(enableId){
$("#"+enableId).find("input").each(function() {//disable Config
//$(this).attr("disabled", "disabled");
$(this).removeAttr("disabled");
});
};
$scope.configStatus = function(){
if($scope.status === "READY")//show all config
{
if(disabledStagingConfig===true)
{
disabledStagingConfig=false;
$scope.enableConfig("stagingConfig");
$scope.enableConfig("stagingConfig1");
}
if(disabledRunningConfig===true) {
disabledRunningConfig = false;
$scope.enableConfig("runningConfig");
}
}
else if($scope.status === "STAGED") //show running config
{
if(disabledStagingConfig===false)
{
disabledStagingConfig=true;
$scope.disableConfig("stagingConfig");
$scope.disableConfig("stagingConfig1");
}
if(disabledRunningConfig===true) {
disabledRunningConfig = false;
$scope.enableConfig("runningConfig");
}
}
else//no config can be modified
{
if(disabledStagingConfig===false)
{
disabledStagingConfig=true;
$scope.disableConfig("stagingConfig");
$scope.disableConfig("stagingConfig1");
}
if(disabledRunningConfig===false) {
disabledRunningConfig = true;
$scope.disableConfig("runningConfig");
}
}
};
var pointNumber = 0;
$scope.pointNum = function(){
var point = ".";
pointNumber = (pointNumber+1)%6;
for(var x = 0; x < pointNumber; x++)
{
point = point + " .";
}
return point;
};
$scope.runButton = "Run Test";
$scope.runStatus = true;//if run Button disabled
$scope.setStatus = false;//if settings Button disabled
$scope.setUnstage = true;//if Unstage Button disabled
$scope.client_vm_count = 0;
$scope.server_vm_count = 0;
$scope.checkStatus = function(){
if($scope.sessionID) {
kbHttp.getMethod2("/kloudbuster/status/" + $scope.sessionID)
.then(
function (response) { // .resolve
$scope.status = response.data.status;
kbCookie.setStatus($scope.status);
$scope.configStatus();
if ($scope.status === "READY") {
$scope.runButton = "Create VMs";
$scope.runStatus = false;//show button
$scope.setStatus = false;//show button
$scope.setUnstage = true;//disable button
$scope.client_vm_count = 0;
$scope.server_vm_count = 0;
$(".loading").addClass("pause");
$scope.info="";
}
else if ($scope.status === "STAGING") {
$scope.runButton = "Run Test";
$scope.runStatus = true;
$scope.setStatus = true;
$scope.setUnstage = true;
$scope.client_vm_count = response.data.client_vm_count;
$scope.server_vm_count = response.data.server_vm_count;
$(".loading").removeClass("pause");
$scope.info="KloudBuster is Creating VM(s)"+$scope.pointNum();
}
else if ($scope.status === "STAGED") {
$scope.runButton = "Run Test";
$scope.runStatus = false;
$scope.setStatus = false;
$scope.setUnstage = false;
$scope.client_vm_count = $scope.config.server.routers_per_tenant * $scope.config.server.networks_per_router * $scope.config.server.vms_per_network * $scope.config.server.number_tenants;
$scope.server_vm_count = $scope.client_vm_count;
$scope.getReport();
$(".loading").addClass("pause");
$scope.info="";
}
else if ($scope.status === "RUNNING") {
$scope.runButton = "Stop Test";
$scope.runStatus = false;
$scope.setStatus = true;
$scope.setUnstage = true;
$scope.client_vm_count = $scope.config.server.routers_per_tenant * $scope.config.server.networks_per_router * $scope.config.server.vms_per_network * $scope.config.server.number_tenants;
$scope.server_vm_count = $scope.client_vm_count;
if($scope.config.client.progression.enabled === true) $scope.getReport();
$(".loading").removeClass("pause");
$scope.info="KloudBuster is Running"+$scope.pointNum();
}
else if ($scope.status === "ERROR") {
$scope.runButton = "Run Test";
$scope.runStatus = true;
$scope.setStatus = true;
$scope.setUnstage = false;
$scope.client_vm_count = $scope.config.server.routers_per_tenant * $scope.config.server.networks_per_router * $scope.config.server.vms_per_network * $scope.config.server.number_tenants;
$scope.server_vm_count = $scope.client_vm_count;
$(".loading").addClass("pause");
$scope.info="";
}
else if($scope.status === "CLEANING" || $scope.status === "STOPPING")
{
$scope.runButton = "Run Test";
$scope.runStatus = true;
$scope.setStatus = true;
$scope.setUnstage = true;
$scope.client_vm_count = $scope.config.server.routers_per_tenant * $scope.config.server.networks_per_router * $scope.config.server.vms_per_network * $scope.config.server.number_tenants;
$scope.server_vm_count = $scope.client_vm_count;
$(".loading").removeClass("pause");
$scope.info="Please Wait"+$scope.pointNum();
}
},
function (response) { // .reject
console.log("get status error:");
console.log(response);
}
);
}
else
{
$scope.status = "NO SESSION ID";
kbCookie.setStatus("");
}
};
$scope.checkStatus();
$scope.setStage = function(){
kbHttp.postMethod("/kloudbuster/stage/" + $scope.sessionID)
.then(
function(response) { // .resolve
$scope.checkStatus();
},
function(response) { // .reject
console.log("set stage error:");
console.log(response);
}
);
};
$scope.runKb = function(){
kbHttp.postMethod("/kloudbuster/run_test/" + $scope.sessionID)
.then(
function(response) { // .resolve
$scope.checkStatus();
},
function(response) { // .reject
console.log("running error:");
console.log(response);
}
);
};
$scope.stopKb = function(){
kbHttp.postMethod("/kloudbuster/stop_test/" + $scope.sessionID)
.then(
function(response) { // .resolve
$scope.checkStatus();
},
function(response) { // .reject
console.log("stop error:");
console.log(response);
}
);
};
$scope.scaleTest = function(){
if($scope.status==="RUNNING"){
//$scope.initChart();
$scope.stopKb();
}
else {
var promise = $scope.setConfig();
promise.then(function () {
if ($scope.status === "READY") {
$scope.setStage();
}
else if ($scope.status === "STAGED") {
$scope.initChart();
$scope.runKb();
}
else {
}
});
}
};
$scope.CleanUp = function(){
$scope.initChart();
if($scope.sessionID) {
kbHttp.postMethod("/kloudbuster/cleanup/" + $scope.sessionID)
.then(
function(response) { // .resolve
$scope.checkStatus();
console.log("clean up successfully");
},
function(response) { // .reject
console.log("clean error:");
console.log(response);
}
);
}
else{
console.log("no sessionID");
}
};
//---------------------------table---------------------------
$scope.tabledata =[];
//$scope.tabledata =[
// {"seq":"a","connection": 1000, "server_vms": 1, "requests": 14200, "sock_err": 0, "rps": 473, "rate_limit": 5001, "throughput": 0.1 }
// ,{"seq":"b","connection": 1000, "server_vms": 1, "requests": 1200, "sock_err": 0, "rps": 473, "rate_limit": 5001, "throughput": 0.1 }
//];
$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 },
{ field: "action", title: "Action", sortable:"action", show: true }
];
$scope.tableParams = new ngTableParams(
{
sorting: { name: "asc" },
"count":10
},
{
counts:[],
data: $scope.tabledata
});
//console.log($scope.tableParams);
//---------------------------chart---------------------------
$scope.options = {
axes: {
x: {key: 'x', type: 'linear',
ticksFormatter: function(x) {
if (x === 0) {return "50%";}
else if (x === 10) {return "75%";}
else if (x === 20) {return "90%";}
else if (x === 30) {return "99%";}
else if (x === 40) {return "99.9%";}
else if (x === 50) {return "99.99%";}
else if (x === 60) {return "99.999%";}
}
},
y: {type: 'log', ticksFormat: 'd', innerTicks: true,grid: true}
},
tooltip: {mode: 'scrubber', formatter: function(x, y, series) {return series.label+":"+y;}},
tension: 0.8,
lineMode: "cardinal",
series: [{}]
};
//---------------------------init---------------------------
$scope.initChart = function() {
$scope.data = [
{x: 0},
{x: 10},
{x: 20},
{x: 30},
{x: 40},
{x: 50},
{x: 60}
];
$scope.options.series = [{}];
$scope.isDely = false;
$scope.tabledata.length = 0;
$scope.tableParams.reload();
$scope.isDely = false;
countRep = 0;
color.reset();
};
var countRep = 0;
$scope.initChart();
$scope.refreshChart = function() {
$scope.data = [
{x: 0},
{x: 10},
{x: 20},
{x: 30},
{x: 40},
{x: 50},
{x: 60}
];
$scope.options.series = [{}];
$scope.isDely = false;
$scope.tabledata.length = 0;
$scope.tableParams.reload();
color.reset();
};
$scope.getReport = function(){
kbHttp.getMethod2("/kloudbuster/report/"+$scope.sessionID+"?final=true")
.then(
function(response) { // .resolve
console.log("get report totally:"+response.data.length);
console.log(response.data);
if(response.data.length>0 && countRep < response.data.length) {
countRep = response.data.length;
$scope.refreshChart();
console.log($scope.data);
interactiveMode.setResult(response.data);
for(var i = 0 ; i < countRep; i++)
{
$scope.result = response.data[i];
var pickColor = color.getColor();
if($scope.config.client.progression.enabled) {
//$scope.name = $scope.config.client.progression.vm_start + $scope.config.client.progression.vm_step * i;
console.log("show report" + $scope.name);
$scope.pushChartData("Connection-"+$scope.result.total_connections, $scope.result, pickColor);
$scope.pushTableData("Connection-"+$scope.result.total_connections, $scope.result, pickColor);
}
else{
console.log("show report" + $scope.name);
$scope.pushChartData("Final", $scope.result, pickColor);
$scope.pushTableData("Final", $scope.result, pickColor);
}
}
}
},
function(response) { // .reject
console.log("get report error:");
console.log(response);
}
);
// $scope.aa='{"latency_stats": [[50, 1727], [75, 2111], [90, 2447], [99, 3023], [99.9, 3263], [99.99, 3295], [99.999, 3327]], "tool": "wrk2", "http_rps": 499, "http_throughput_kbytes": 16122, "http_sock_timeout": 0, "http_total_req": 5002, "http_sock_err": 0}';
//$scope.aa = '{ "http_rate_limit": 500, "http_rps": 473, "http_sock_err": 0, "http_sock_timeout": 0, "http_throughput_kbytes": 15257, "http_total_req": 14200, "latency_stats": [ [ 50, 1855 ], [ 75, 2655 ], [ 90, 14911 ], [ 99, 18815 ], [ 99.9, 27263 ], [ 99.99, 28159 ], [ 99.999, 28415 ] ], "tool": "wrk2", "total_client_vms": 1, "total_connections": 1000, "total_server_vms": 1}';
//$scope.result=JSON.parse($scope.aa);
};
$scope.pushChartData = function(chName,chData,pickColor){
console.log("chart date"+ chName);
if ($scope.isDely === false) {
$scope.options.series.shift();
$scope.isDely = true;
}
$scope.options.series.push({
y: chName,
label: chName,
//color: '#'+ ('000000' + (Math.random()*0xFFFFFF<<0).toString(16)).slice(-6),
color: pickColor,
dotSize: "3",
thickness: "2px"
});
//console.log( $scope.options.series);
for (var i = 0; i < 7; i++) {
$scope.data[i][chName] = chData.latency_stats[i][1] / 1000;
//console.log( $scope.data[i]["chName"]);
}
};
$scope.pushTableData = function(taName,taData,pickColor){
console.log("table date:"+ taName);
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}
);
//console.log($scope.tableParams);
$scope.tableParams.reload();
};
function downloadFile(fileName, content){
var aLink = document.createElement('a');
var blob = new Blob([content]);
var evt = document.createEvent("HTMLEvents");
evt.initEvent("click", false, false);//initEvent
aLink.download = fileName;
aLink.href = URL.createObjectURL(blob);
aLink.dispatchEvent(evt);
}
$scope.saveResult = function(index){
var date = new Date();
var m = date.getMonth()+1;//month (0-11,0 = Jan., remember to add 1)
var d = date.getDate();//day(1-31)
var h = date.getHours();//hour(0-23)
var min = date.getMinutes();//minute(0-59)
var filename = m+d+h+min+index+".json";
//console.log(filename);
var saveData = interactiveMode.getResult();
if(saveData[index]!="")
downloadFile(filename, JSON.stringify(saveData[index]));
else console.log("no file to save");
};
setInterval(function(){
$scope.checkStatus();
},2000);
})
.service('interactiveMode', function() {
var self = this;
var result=[];
this.getResult = function(){
return result;
};
this.setResult = function(res){
result = res;
return result;
};
})
.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;
};
})
.directive('convertToNumber', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
ngModel.$parsers.push(function(val) {
return parseFloat(val);
});
ngModel.$formatters.push(function(val) {
return '' + val;
});
}
};
});

File diff suppressed because one or more lines are too long

443
kb_web/app/styles/main.css Normal file
View File

@ -0,0 +1,443 @@
.browsehappy {
margin: 0.2em 0;
background: #ccc;
color: #000;
padding: 0.2em 0;
}
/*body {*/
/*padding: 0;*/
/*}*/
body {
padding-top: 60px;
padding-bottom: 40px;
}
.background {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-size: cover;
opacity: 0.1;
}
/* Everything but the jumbotron gets side spacing for mobile first views */
.header,
.marketing,
.footer {
padding-left: 15px;
padding-right: 15px;
}
/* Custom page header */
.header {
border-bottom: 1px solid #e5e5e5;
margin-bottom: 10px;
}
/* Make the masthead heading the same height as the navigation */
.header h3 {
margin-top: 0;
margin-bottom: 0;
line-height: 40px;
padding-bottom: 19px;
}
/* Custom page footer */
.footer {
padding-top: 19px;
color: #777;
border-top: 1px solid #e5e5e5;
}
.container-narrow > hr {
margin: 30px 0;
}
/* Main marketing message and sign up button */
.jumbotron {
text-align: center;
border-bottom: 1px solid #e5e5e5;
}
.jumbotron .btn {
font-size: 21px;
padding: 14px 24px;
}
/* Supporting marketing content */
.marketing {
margin: 40px 0;
}
.marketing p + h4 {
margin-top: 28px;
}
/* Responsive: Portrait tablets and up */
@media screen and (min-width: 768px) {
.container {
max-width: 1152px;
}
/* Remove the padding we set earlier */
.header,
.marketing,
.footer {
padding-left: 0;
padding-right: 0;
}
/* Space out the masthead */
.header {
margin-bottom: 30px;
}
/* Remove the bottom border on the jumbotron for visual effect */
.jumbotron {
border-bottom: 0;
}
}
input {
text-align:center;
}
.input-group-addon {
min-width:150px;
}
/*--------------------------top loading bar----------------------------*/
#loading-bar-spinner {
top: 70px;
}
#loading-bar .bar {
top: 60px;
height: 5px;
}
#loading-bar-spinner .spinner-icon {
width: 20px;
height: 20px;
}
/*--------------------------------pause--------------------------------*/
.pause {
-webkit-animation-play-state: paused !important;
-moz-animation-play-state: paused !important;
-o-animation-play-state: paused !important;
animation-play-state: paused !important;
}
/*--------------------------------side bar---------------------------------*/
body, html {
/*height: 100%;*/
/*margin: 0;*/
/*overflow:hidden;*/
/*font-family: helvetica;*/
font-weight: 100;
}
.container {
position: relative;
height: 100%;
width: 100%;
left: 0;
-webkit-transition: left 0.4s ease-in-out;
-moz-transition: left 0.4s ease-in-out;
-ms-transition: left 0.4s ease-in-out;
-o-transition: left 0.4s ease-in-out;
transition: left 0.4s ease-in-out;
}
.container .open-sidebar {
left: 300px;
}
.swipe-area {
position: absolute;
width: 50px;
left: 0;
top: 0;
height: 100%;
/*background: #f3f3f3;*/
z-index: 0;
}
#sidebar {
/*background: #DF314D;*/
position: absolute;
width: 300px;
height: 100%;
left: -300px;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
#sidebar ul {
margin: 0;
padding: 0;
list-style: none;
}
#sidebar ul li {
margin: 0;
}
#sidebar ul li a {
padding: 15px 20px;
font-size: 16px;
font-weight: 100;
color: white;
text-decoration: none;
display: block;
/*border-bottom: 1px solid #C9223D;*/
-webkit-transition: background 0.3s ease-in-out;
-moz-transition: background 0.3s ease-in-out;
-ms-transition: background 0.3s ease-in-out;
-o-transition: background 0.3s ease-in-out;
transition: background 0.3s ease-in-out;
}
#sidebar ul li:hover a {
/*background: #C9223D;*/
}
#content.content-smaller {
width: 70%;
height: 100%;
}
.main-content {
width: 100%;
height: 100%;
padding: 10px;
box-sizing: border-box;
-moz-box-sizing: border-box;
position: relative;
}
.main-content .content{
box-sizing: border-box;
-moz-box-sizing: border-box;
padding-left: 60px;
width: 100%;
}
.main-content .content h1{
font-weight: 100;
}
.main-content .content p{
width: 100%;
line-height: 160%;
}
.main-content #sidebar-toggle {
background: #DF314D;
border-radius: 3px;
display: block;
position: relative;
padding: 10px 7px;
float: left;
}
.main-content #sidebar-toggle .bar{
display: block;
/*width: 18px;*/
/*margin-bottom: 3px;*/
/*height: 2px;*/
/*background-color: #fff;*/
/*border-radius: 1px;*/
}
/*.main-content #sidebar-toggle .bar:last-child{*/
/*margin-bottom: 0;*/
/*}*/
.supercontainer {
position: relative;
height: 100%;
width: 100%;
left: 0;
overflow: hidden;
}
/*------------------------------loading bar---------------------------*/
.loader,
.loader:before,
.loader:after {
background: #ffffff;
-webkit-animation: load1 1s infinite ease-in-out;
animation: load1 1s infinite ease-in-out;
width: 1em;
height: 4em;
}
.loader:before,
.loader:after {
position: absolute;
top: 0;
content: '';
}
.loader:before {
left: -1.5em;
-webkit-animation-delay: -0.32s;
animation-delay: -0.32s;
}
.loader {
text-indent: -9999em;
margin: 6px auto;
position: relative;
font-size: 3px;
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation-delay: -0.16s;
animation-delay: -0.16s;
}
.loader:after {
left: 1.5em;
}
@-webkit-keyframes load1 {
0%,
80%,
100% {
box-shadow: 0 0 #ffffff;
height: 4em;
}
40% {
box-shadow: 0 -2em #ffffff;
height: 5em;
}
}
@keyframes load1 {
0%,
80%,
100% {
box-shadow: 0 0 #ffffff;
height: 4em;
}
40% {
box-shadow: 0 -2em #ffffff;
height: 5em;
}
}
/*------------------------------loading bar a---------------------------*/
.loadera:before,
.loadera:after,
.loadera {
border-radius: 50%;
width: 2.5em;
height: 2.5em;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
-webkit-animation: load7 1.8s infinite ease-in-out;
animation: load7 1.8s infinite ease-in-out;
}
.loadera {
font-size: 2px;
margin: 15px 5px;
position: relative;
text-indent: -9999em;
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation-delay: -0.16s;
animation-delay: -0.16s;
}
.loadera:before {
left: -3.5em;
-webkit-animation-delay: -0.32s;
animation-delay: -0.32s;
}
.loadera:after {
left: 3.5em;
}
.loadera:before,
.loadera:after {
content: '';
position: absolute;
top: 0;
}
@-webkit-keyframes load7 {
0%,
80%,
100% {
box-shadow: 0 2.5em 0 -1.3em #ffffff;
}
40% {
box-shadow: 0 2.5em 0 0 #ffffff;
}
}
@keyframes load7 {
0%,
80%,
100% {
box-shadow: 0 2.5em 0 -1.3em #ffffff;
}
40% {
box-shadow: 0 2.5em 0 0 #ffffff;
}
}
/*---------------------loading spinner---------------------*/
@keyframes loading {
0% {
transform: rotate(0deg);
}
25%{
transform: rotate(160deg);
}
50%{
transform: rotate(0deg);
}
75%{
transform: rotate(160deg);
}
100% {
transform: rotate(0deg);
}
}
.loading {
background-color: transparent;
border-radius: 50%;
margin: 2px auto;
animation: loading 5s infinite linear;
}
.spin-1{
border: 1px solid #c00353 ;
border-top: 1px solid transparent;
border-left: 1px solid transparent;
width: 32px;
height: 32px;
}
.spin-2{
border: 1px solid #05bbc3 ;
border-top: 1px solid transparent;
border-left: 1px solid transparent;
width: 26px;
height: 26px;
animation-delay: 1s;
}
.spin-3{
border: 1px solid #d2d947 ;
border-top: 1px solid transparent;
border-left: 1px solid transparent;
width: 20px;
height: 20px;
animation-delay: 1s;
}
.spin-4{
border: 1px solid #f2a342 ;
border-top: 1px solid transparent;
border-left: 1px solid transparent;
width: 14px;
height: 14px;
animation-delay: 1s;
}
.spin-5{
border: 1px solid #f34d51 ;
border-top: 1px solid transparent;
border-left: 1px solid transparent;
width: 8px;
height: 8px;
animation-delay: 1s;
}
.spin-6{
border: 1px solid #000000 ;
width: 2px;
height: 2px;
animation-delay: 1s;
}

View File

@ -0,0 +1,24 @@
<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>-->

View File

@ -0,0 +1,221 @@
<!--<img class="background" src="images/back.jpg">-->
<div class="row">
<div style="float:right;" id="getButton">
<input type="button" value="Default/Reset" class="btn btn-default btn-sm" ng-click="getDefaultConfig()"></input>
<!--<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()"></button>
</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 class="bs-component">
<div class="input-group col-sm-11" style="margin:0 auto;">
<span class="input-group-addon">VM Creation Concurrency:</span>
<input type="number" min="0" max="1000" step="1" class="form-control" id="vm_creation_concurrency" ng-model="config.vm_creation_concurrency"/>
</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="text-center">-->
<h4 style="margin-top: 5px">VM PLACEMENT</h4><br/>
<!--</div>-->
<div class="radio">
<label>
<input type="radio" ng-model="availability_zone" value="1" ng-change="changeTopology()">
Let Nova Decide
</label>
</div>
<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;">
<div class="col-md-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">
<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>
<div class="radio" id="topology">
<label>
<input type="radio" ng-model="availability_zone" value="3" ng-change="changeTopology()">
Use Topology
<small> -- 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>
</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>
<div class="form-group">
<div class="input-group col-sm-11" style="margin:0 auto">
<span class="input-group-addon">Html Payload Size:</span>
<input type="number" min="0" step="1024" class="form-control" id="html_size" ng-model="config.server.http_server_configs.html_size"/>
</div>
<br/>
<div class="well bs-component">
<form class="form-horizontal">
<fieldset>
<legend>flavor</legend>
<div class="input-group col-sm-11" style="margin:0 auto">
<span class="input-group-addon">vCPUs:</span>
<input type="number" min="0" max="1000" step="1" class="form-control" id="server_vcpus" ng-model="config.server.flavor.vcpus"/>
</div>
<br/>
<div class="input-group col-sm-11" style="margin:0 auto">
<span class="input-group-addon">RAM (KB):</span>
<input type="number" min="0" max="" step="128" class="form-control" id="server_ram" ng-model="config.server.flavor.ram"/>
</div>
<br/>
<div class="input-group col-sm-11" style="margin:0 auto">
<span class="input-group-addon">Disk (GB):</span>
<input type="number" min="0" max="" step="" class="form-control" id="server_disk" ng-model="config.server.flavor.disk"/>
</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.server.availability_zone"/>-->
<!--</div>-->
</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>
<div class="form-group">
<div class="well bs-component">
<form class="form-horizontal">
<fieldset>
<legend>flavor</legend>
<div class="input-group col-sm-11" style="margin:0 auto">
<span class="input-group-addon">vCPUs:</span>
<input type="number" min="0" max="1000" step="1" class="form-control" id="client_vcpus" ng-model="config.client.flavor.vcpus"/>
</div>
<br/>
<div class="input-group col-sm-11" style="margin:0 auto">
<span class="input-group-addon">RAM (KB):</span>
<input type="number" min="0" max="" step="128" class="form-control" id="client_ram" ng-model="config.client.flavor.ram"/>
</div>
<br/>
<div class="input-group col-sm-11" style="margin:0 auto">
<span class="input-group-addon">Disk (GB):</span>
<input type="number" min="0" max="" step="" class="form-control" id="client_disk zone" ng-model="config.client.flavor.disk"/>
</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>
<!--End Dashboard Tab 3-->
</div>
</div>

View File

@ -0,0 +1,193 @@
<!--<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="CleanUp()" ng-disabled="setUnstage">Unstage</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">{{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 <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">
<div class="input-group col-sm-11" style="margin:0 auto">
<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"/>
</div>
<br/>
<div class="input-group col-sm-11" style="margin:0 auto">
<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"/>
</div>
<br/>
<div class="input-group col-sm-11" style="margin:0 auto">
<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"/>
</div>
<br/>
<div class="input-group col-sm-11" style="margin:0 auto">
<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"/>
</div>
<br/>
<div class="input-group col-sm-11" style="margin:0 auto">
<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"/>
</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">
<!--<div class="input-group col-sm-11" 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-11" style="margin:0 auto">
<span class="input-group-addon">Duration/Run (sec):</span>
<input type="number" min="1" max="" step="1" class="form-control" id="client_uduration"
ng-model="config.client.http_tool_configs.duration"/>
</div>
<br/>
<div class="input-group col-sm-11" style="margin:0 auto">
<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"/>
</div>
<br/>
<div class="input-group col-sm-11" style="margin:0 auto">
<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"/>
</div>
<br/>
<div class="input-group col-sm-11" style="margin:0 auto">
<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"/>
</div>
<!--<br/>-->
<!--<div class="input-group col-sm-11" 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-11" 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-11" 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">
<div style="margin: 0 8%;vertical-align: middle;">
<h5>
<div class="row">
<div class="" style="float:left;background: white; width: 35px;height: 35px;border-radius: 50%;">
<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 class="col-md-2" style="line-height:40px; height:40px;color:white;">Status:
<button class="btn btn-default btn-xs" ng-click="checkStatus()">{{status}}</button>
</div>
<div class="col-md-3" style="line-height:40px; height:40px;color:white;">Created Server VM(s):
<button class="btn btn-default btn-xs" ng-click="checkStatus()">{{server_vm_count}}</button>
</div>
<div class="col-md-3" style="line-height:40px; height:40px;color:white;">Created Client VM(s):
<button class="btn btn-default btn-xs" ng-click="checkStatus()">{{client_vm_count}}</button>
</div>
<div class="col-md-3" style="line-height:40px; height:40px; color:white;">
<!--<div class="loader" style="float:left;">Loading...</div>-->
{{info}}
</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>

26
kb_web/app/views/log.html Normal file
View File

@ -0,0 +1,26 @@
<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>LOGS</span>
<span style="float:right;">
<button type="submit" class="btn btn-default btn-xs" ng-click="delLog()">Clear</button>
<button type="submit" class="btn btn-primary btn-xs" ng-click="getLog()">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>

View File

@ -0,0 +1,56 @@
<img class="background" src="images/back.jpg">
<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">
<div class="box">
<div class="box-content">
<div class="text-center">
<h3 class="page-header">Login</h3>
</div>
<h4>Server 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">Password</span>
<input type="password" class="form-control" id="inputPassword1" ng-model="inputPassword1" placeholder="Input Your Server Cloud's Password">
</div>
</div>
<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">Password</span>
<input type="password" class="form-control" id="inputPassword2" ng-model="inputPassword2" placeholder="Input Your Client Cloud's Password" disabled>
</div>
</div>
<div class="text-center">
<a href="" class="btn btn-primary" ng-click="setConfig()">Sign in</a>
</div>
</div>
</div>
</div>
</div>
<br/>

View File

@ -0,0 +1,5 @@
<div class="jumbotron">
<h2>KloudBuster</h2>
<h5>{{version}}</h5>
<p><a class="btn btn-lg btn-success" ng-href="#/">Splendid!<span class="glyphicon glyphicon-ok"></span></a></p>
</div>

286
kb_web/app/views/run.html Normal file
View File

@ -0,0 +1,286 @@
<!--<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="CleanUp()" ng-disabled="setUnstage">Unstage</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">{{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 <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">
<div class="input-group col-sm-11" style="margin:0 auto">
<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"/>
</div>
<br/>
<div class="input-group col-sm-11" style="margin:0 auto">
<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"/>
</div>
<br/>
<div class="input-group col-sm-11" style="margin:0 auto">
<span class="input-group-addon">Networks/Router:</span>
<input type="number" min="1" max="1000" step="11" class="form-control" id="server_networks_per_router"
ng-model="config.server.networks_per_router"/>
</div>
<br/>
<div class="input-group col-sm-11" style="margin:0 auto">
<span class="input-group-addon">VMs/Network:</span>
<input type="number" min="1" max="1000" step="11" class="form-control" id="server_vms_per_network"
ng-model="config.server.vms_per_network"/>
</div>
<br/>
<div class="input-group col-sm-11" style="margin:0 auto">
<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"/>
</div>
</form>
</div>
<!--Run-->
</accordion-group>
<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">
<div class="input-group col-sm-11" style="margin:0 auto">
<input type="checkbox" id="client_progression_enabled" ng-model="config.client.progression.enabled"/>
Progression Test
</div>
<br/>
<div class="input-group col-sm-11" style="margin:0 auto">
<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"/>
</div>
<br/>
<div class="input-group col-sm-11" style="margin:0 auto">
<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"/>
</div>
<br/>
Stop When
<div class="input-group col-sm-11" style="margin:0 auto">
<span class="input-group-addon">Num of Err Packets > </span>
<input type="number" min="0" step="1" class="form-control" id="client_progression_stop_limit0"
ng-model="config.client.progression.stop_limit[0]"
ng-disabled="!config.client.progression.enabled"/>
</div>
<!--OR-->
<!--<div class="input-group col-sm-11" 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">
<!--<div class="input-group col-sm-11" 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-11" style="margin:0 auto">
<span class="input-group-addon">Duration/Run (sec):</span>
<input type="number" min="1" max="" step="1" class="form-control" id="client_uduration"
ng-model="config.client.http_tool_configs.duration"/>
</div>
<br/>
<!--<div class="input-group col-sm-11" 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-11" style="margin:0 auto">
<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"/>
</div>
<br/>
<div class="input-group col-sm-11" style="margin:0 auto">
<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"/>
</div>
<!--<br/>-->
<!--<div class="input-group col-sm-11" 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-11" 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-11" 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="420"></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>
<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" sortable="cols[0].field" ng-if="cols[0].show">
<input type="checkbox" class="btn btn-default" ng-click="">
<span style="background-color:{{row.color}};margin:1px 1px" popover="{{row.description}}"
popover-trigger="mouseenter"> &nbsp; &nbsp; &nbsp;&nbsp;
<!--{{row.seq}}-->
</span>
</input>
</td>
<td title="cols[1].title" sortable="cols[1].field" ng-if="cols[1].show">{{row.connection}}</td>
<td title="cols[2].title" sortable="cols[2].field" ng-if="cols[2].show">{{row.server_vms}}</td>
<td title="cols[3].title" sortable="cols[3].field" ng-if="cols[3].show">{{row.requests}}</td>
<td title="cols[4].title" sortable="cols[4].field" ng-if="cols[4].show">{{row.sock_err}}</td>
<td title="cols[5].title" sortable="cols[5].field" ng-if="cols[5].show">{{row.rps}}</td>
<td title="cols[6].title" sortable="cols[6].field" ng-if="cols[6].show">{{row.rate_limit}}</td>
<td title="cols[7].title" 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">
<!--{{$index}}-->
<button class="btn btn-default btn-xs" ng-click="saveResult($index)"><span
class="glyphicon glyphicon-floppy-save"></span></button>
<button class="btn btn-danger btn-xs" ng-click="delData($index)" disabled><span
class="glyphicon glyphicon-trash"></span></button>
</td>
</tr>
</table>
<div class="navbar navbar-default navbar-fixed-bottom" role="navigation">
<div style="margin: 0 8%;vertical-align: middle;">
<h5>
<div class="row">
<div class="" style="float:left;background: white; width: 35px;height: 35px;border-radius: 50%;">
<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 class="col-md-2" style="line-height:40px; height:40px; color:white;">Status:
<button class="btn btn-default btn-xs" ng-click="checkStatus()">{{status}}</button>
</div>
<div class="col-md-3" style="line-height:40px; height:40px; color:white;">Created Server VM(s):
<button class="btn btn-default btn-xs" ng-click="checkStatus()">{{server_vm_count}}</button>
</div>
<div class="col-md-3" style="line-height:40px; height:40px; color:white;">Created Client VM(s):
<button class="btn btn-default btn-xs" ng-click="checkStatus()">{{client_vm_count}}</button>
</div>
<div class="col-md-3" style="line-height:40px; height:40px; color:white;">
{{info}}
</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>

BIN
kb_web/test/.DS_Store vendored Normal file

Binary file not shown.

18
kb_web/test/.jshintrc Normal file
View File

@ -0,0 +1,18 @@
{
"bitwise": true,
"browser": true,
"curly": true,
"eqeqeq": true,
"esnext": true,
"jasmine": true,
"latedef": true,
"noarg": true,
"node": true,
"strict": true,
"undef": true,
"unused": true,
"globals": {
"angular": false,
"inject": false
}
}

90
kb_web/test/karma.conf.js Normal file
View File

@ -0,0 +1,90 @@
// Karma configuration
// http://karma-runner.github.io/0.12/config/configuration-file.html
// Generated on 2015-09-03 using
// generator-karma 1.0.0
module.exports = function(config) {
'use strict';
config.set({
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// base path, that will be used to resolve files and exclude
basePath: '../',
// testing framework to use (jasmine/mocha/qunit/...)
// as well as any additional frameworks (requirejs/chai/sinon/...)
frameworks: [
"jasmine"
],
// list of files / patterns to load in the browser
files: [
// bower:js
'bower_components/jquery/dist/jquery.js',
'bower_components/angular/angular.js',
'bower_components/angular-animate/angular-animate.js',
'bower_components/angular-bootstrap/ui-bootstrap-tpls.js',
'bower_components/angular-cookies/angular-cookies.js',
'bower_components/angular-resource/angular-resource.js',
'bower_components/angular-route/angular-route.js',
'bower_components/angular-sanitize/angular-sanitize.js',
'bower_components/angular-touch/angular-touch.js',
'bower_components/bootstrap/dist/js/bootstrap.js',
'bower_components/d3/d3.js',
'bower_components/moment/moment.js',
'bower_components/n3-line-chart/build/line-chart.js',
'bower_components/ng-table/dist/ng-table.min.js',
'bower_components/angular-loading-bar/build/loading-bar.js',
'bower_components/jquery-touchswipe/jquery.touchSwipe.js',
'bower_components/angular-mocks/angular-mocks.js',
// endbower
"app/scripts/**/*.js",
"test/mock/**/*.js",
"test/spec/**/*.js"
],
// list of files / patterns to exclude
exclude: [
],
// web server port
port: 8080,
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera
// - Safari (only Mac)
// - PhantomJS
// - IE (only Windows)
browsers: [
"PhantomJS"
],
// Which plugins to enable
plugins: [
"karma-phantomjs-launcher",
"karma-jasmine"
],
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: false,
colors: true,
// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel: config.LOG_INFO,
// Uncomment the following lines if you are using grunt's server to run the tests
// proxies: {
// '/': 'http://localhost:9000/'
// },
// URL root prevent conflicts with the site root
// urlRoot: '_karma_'
});
};

BIN
kb_web/test/spec/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,23 @@
'use strict';
describe('Controller: AboutCtrl', function () {
// load the controller's module
beforeEach(module('kbWebApp'));
var AboutCtrl,
scope;
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
AboutCtrl = $controller('AboutCtrl', {
$scope: scope
// place here mocked dependencies
});
}));
it('should attach a list of awesomeThings to the scope', function () {
expect(AboutCtrl.awesomeThings.length).toBe(3);
});
});

View File

@ -0,0 +1,23 @@
'use strict';
describe('Controller: MainCtrl', function () {
// load the controller's module
beforeEach(module('kbWebApp'));
var MainCtrl,
scope;
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
MainCtrl = $controller('MainCtrl', {
$scope: scope
// place here mocked dependencies
});
}));
it('should attach a list of awesomeThings to the scope', function () {
expect(MainCtrl.awesomeThings.length).toBe(3);
});
});