Initial commit

This commit is contained in:
Weidong Shao 2013-12-11 19:08:36 +00:00
parent 9326f1b6e7
commit 71fd42f788
103 changed files with 43589 additions and 2 deletions

View File

@ -1,4 +1,33 @@
compass-web
Compass-Web
===========
Web UI for Compass
**Compass-Web** is a web-based UI consuming the Restful API service provided by [Compass](https://github.com/huawei-cloud/compass) to pragmatically deploy an OpenStack system on to a set of raw physical resources. It is used for demo purpose. It can be used as a base to develop a UI for more sophisticated use cases.
Compass-Web is based on [JavaScriptMVC](http://v32.javascriptmvc.com/) framework. It has five modules: Servers, Security, Networking, Host Configuration and Deployment.
1. *Servers Module*. Discover available servers with switch information and add a subset of the servers to a cluster.
2. *Security Module*. Specify credentials for the OpenStack system.
3. *Networking Module*. Specify network addresses needed to facilitate the OpenStack cluster you want to use for your OpenStack servers.
4. *Host Configuration Module* Configure host names of the servers in the cluster.
5. *Deployment Module* Deploy OpenStack onto the servers with the realtime progressbars.
Framework
---------
[JavaScriptMVC v3.2.4](http://v32.javascriptmvc.com/)
JavaScriptMVC is a MIT licensed, client-side, JavaScript framework that builds maintainable, error-free, lightweight applications as quick as possible.
Third-party Libraries
---------------------
* [jQueryUI](http://jqueryui.com/)
jQuery UI is a curated set of user interface interactions, effects, widgets, and themes built on top of the jQuery JavaScript Library. It is included for widgets such as accordion, tabs, dialog and progressbar.
* [d3](http://d3js.org/)
D3.js is a JavaScript library for manipulating documents based on data. It is included for the graph-based progress bars in Deployment module to have a collapsible tree layout for switches and servers.
* [DataTables](http://www.datatables.net/)
DataTables is a plug-in for the jQuery Javascript library to add advanced interaction controls to any HTML table. It is included to have advanced interaction controls to HTML table in Servers and Deployment modules.

278
public/css/base.css Normal file
View File

@ -0,0 +1,278 @@
.float_left {
float: left;
}
.float_right {
float: right;
}
.clear {
clear: both;
}
.bold {
font-weight: bold;
}
.underline {
text-decoration:underline;
}
.italic {
font-style: italic;
}
.right {
text-align: right;
}
.left {
text-align: left;
}
.btn_continue {
/*background gradient*/
background: rgba(190,223,189,1);
background: -moz-linear-gradient(top, rgba(190,223,189,1) 0%, rgba(0,128,0,1) 100%);
background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(190,223,189,1)), color-stop(100%, rgba(0,128,0,1)));
background: -webkit-linear-gradient(top, rgba(190,223,189,1) 0%, rgba(0,128,0,1) 100%);
background: -o-linear-gradient(top, rgba(190,223,189,1) 0%, rgba(0,128,0,1) 100%);
background: -ms-linear-gradient(top, rgba(190,223,189,1) 0%, rgba(0,128,0,1) 100%);
background: linear-gradient(to bottom, rgba(190,223,189,1) 0%, rgba(0,128,0,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#bedfbd', endColorstr='#008000', GradientType=0 );
/*border*/
-moz-border-radius:6px;
-webkit-border-radius:6px;
border-radius:6px;
border:1px solid #aaaaaa;
display:inline-block;
color:#ffffff;
font-family:arial;
font-size:18px;
padding: 8px;
width: 170px;
text-decoration:none;
}
.btn_continue:hover {
/*background gradient*/
background: rgba(0,128,0,1);
background: -moz-linear-gradient(top, rgba(0,128,0,1) 0%, rgba(190,223,189,1) 100%);
background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(0,128,0,1)), color-stop(100%, rgba(190,223,189,1)));
background: -webkit-linear-gradient(top, rgba(0,128,0,1) 0%, rgba(190,223,189,1) 100%);
background: -o-linear-gradient(top, rgba(0,128,0,1) 0%, rgba(190,223,189,1) 100%);
background: -ms-linear-gradient(top, rgba(0,128,0,1) 0%, rgba(190,223,189,1) 100%);
background: linear-gradient(to bottom, rgba(0,128,0,1) 0%, rgba(190,223,189,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#008000', endColorstr='#bedfbd', GradientType=0 );
}
.btn_continue:active {
position:relative;
top:1px;
}
.btn_continue_inactive {
background: rgba(255,255,255,1);
background: -moz-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(246,246,246,1) 47%, rgba(230,230,230,1) 100%);
background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(255,255,255,1)), color-stop(47%, rgba(246,246,246,1)), color-stop(100%, rgba(230,230,230,1)));
background: -webkit-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(246,246,246,1) 47%, rgba(230,230,230,1) 100%);
background: -o-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(246,246,246,1) 47%, rgba(230,230,230,1) 100%);
background: -ms-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(246,246,246,1) 47%, rgba(230,230,230,1) 100%);
background: linear-gradient(to bottom, rgba(255,255,255,1) 0%, rgba(246,246,246,1) 47%, rgba(230,230,230,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0 );
/*border*/
-moz-border-radius:6px;
-webkit-border-radius:6px;
border-radius:6px;
border:1px solid #c0c0c0;
display:inline-block;
color:#969696;
font-family:arial;
font-size:18px;
padding: 8px;
width: 170px;
text-decoration:none;
}
.btn_find {
/*background gradient*/
background: rgba(141,146,251,1);
background: -moz-linear-gradient(top, rgba(141,146,251,1) 0%, rgba(50,54,162,1) 100%);
background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(141,146,251,1)), color-stop(100%, rgba(50,54,162,1)));
background: -webkit-linear-gradient(top, rgba(141,146,251,1) 0%, rgba(50,54,162,1) 100%);
background: -o-linear-gradient(top, rgba(141,146,251,1) 0%, rgba(50,54,162,1) 100%);
background: -ms-linear-gradient(top, rgba(141,146,251,1) 0%, rgba(50,54,162,1) 100%);
background: linear-gradient(to bottom, rgba(141,146,251,1) 0%, rgba(50,54,162,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#8d92fb', endColorstr='#3236a2', GradientType=0 );
/*border*/
-moz-border-radius:4px;
-webkit-border-radius:4px;
border-radius:4px;
border:1px solid #808080;
display:inline-block;
color:#ffffff;
font-family:arial;
font-size:12px;
padding: 3px 20px;
text-decoration:none;
}
.btn_find:hover {
background: rgba(50,54,162,1);
background: -moz-linear-gradient(top, rgba(50,54,162,1) 0%, rgba(141,146,251,1) 100%);
background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(50,54,162,1)), color-stop(100%, rgba(141,146,251,1)));
background: -webkit-linear-gradient(top, rgba(50,54,162,1) 0%, rgba(141,146,251,1) 100%);
background: -o-linear-gradient(top, rgba(50,54,162,1) 0%, rgba(141,146,251,1) 100%);
background: -ms-linear-gradient(top, rgba(50,54,162,1) 0%, rgba(141,146,251,1) 100%);
background: linear-gradient(to bottom, rgba(50,54,162,1) 0%, rgba(141,146,251,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3236a2', endColorstr='#8d92fb', GradientType=0 );
}
.btn_find_inactive {
/*background gradient*/
background: rgba(249,249,249,1);
background: -moz-linear-gradient(top, rgba(249,249,249,1) 0%, rgba(246,246,246,1) 47%, rgba(227,227,227,1) 100%);
background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(249,249,249,1)), color-stop(47%, rgba(246,246,246,1)), color-stop(100%, rgba(227,227,227,1)));
background: -webkit-linear-gradient(top, rgba(249,249,249,1) 0%, rgba(246,246,246,1) 47%, rgba(227,227,227,1) 100%);
background: -o-linear-gradient(top, rgba(249,249,249,1) 0%, rgba(246,246,246,1) 47%, rgba(227,227,227,1) 100%);
background: -ms-linear-gradient(top, rgba(249,249,249,1) 0%, rgba(246,246,246,1) 47%, rgba(227,227,227,1) 100%);
background: linear-gradient(to bottom, rgba(249,249,249,1) 0%, rgba(246,246,246,1) 47%, rgba(227,227,227,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f9f9f9', endColorstr='#e3e3e3', GradientType=0 );
/*border*/
-moz-border-radius:4px;
-webkit-border-radius:4px;
border-radius:4px;
border:1px solid #c0c0c0;
display:inline-block;
color:#3f3f3f;
font-family:arial;
font-size:12px;
padding: 3px 20px;
text-decoration:none;
}
.rounded {
border: 1px solid #aaaaaa;
background-color: rgb(255, 255, 255);
padding: 20px;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
color:#3f3f3f;
font-family:arial;
font-size:14px;
}
div.gradient {
background: rgba(249,249,249,1);
background: -moz-linear-gradient(top, rgba(249,249,249,1) 0%, rgba(246,246,246,1) 47%, rgba(227,227,227,1) 100%);
background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(249,249,249,1)), color-stop(47%, rgba(246,246,246,1)), color-stop(100%, rgba(227,227,227,1)));
background: -webkit-linear-gradient(top, rgba(249,249,249,1) 0%, rgba(246,246,246,1) 47%, rgba(227,227,227,1) 100%);
background: -o-linear-gradient(top, rgba(249,249,249,1) 0%, rgba(246,246,246,1) 47%, rgba(227,227,227,1) 100%);
background: -ms-linear-gradient(top, rgba(249,249,249,1) 0%, rgba(246,246,246,1) 47%, rgba(227,227,227,1) 100%);
background: linear-gradient(to bottom, rgba(249,249,249,1) 0%, rgba(246,246,246,1) 47%, rgba(227,227,227,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f9f9f9', endColorstr='#e3e3e3', GradientType=0 );
}
input.rounded {
border: 1px solid #c0c0c0;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
border-radius: 6px;
-webkit-box-shadow: inset 0px 0px 5px 0px rgba(215,211,207,0.75);
-moz-box-shadow: inset 0px 0px 5px 0px rgba(215,211,207,0.75);
box-shadow: inset 0px 0px 5px 0px rgba(215,211,207,0.75);
padding: 4px 7px;
outline: 0;
-webkit-appearance: none;
}
input.rounded:focus {
border-color: #3A01DF;
}
.tab_nav {
/*background gradient*/
background: rgba(249,249,249,1);
background: -moz-linear-gradient(top, rgba(249,249,249,1) 0%, rgba(227,227,227,1) 100%);
background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(249,249,249,1)), color-stop(100%, rgba(227,227,227,1)));
background: -webkit-linear-gradient(top, rgba(249,249,249,1) 0%, rgba(227,227,227,1) 100%);
background: -o-linear-gradient(top, rgba(249,249,249,1) 0%, rgba(227,227,227,1) 100%);
background: -ms-linear-gradient(top, rgba(249,249,249,1) 0%, rgba(227,227,227,1) 100%);
background: linear-gradient(to bottom, rgba(249,249,249,1) 0%, rgba(227,227,227,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f9f9f9', endColorstr='#e3e3e3', GradientType=0 );
/*border*/
border-radius: 4px 0px 0px 4px;
-moz-border-radius: 4px 0px 0px 4px;
-webkit-border-radius: 4px 0px 0px 4px;
border-left: 1px solid #c0c0c0;
border-top: 1px solid #c0c0c0;
border-bottom: 1px solid #c0c0c0;
display:inline-block;
color:#3f3f3f;
font-family:arial;
font-size:12px;
padding: 1px 5px;
text-decoration:none;
}
.tab_nav:hover {
cursor: pointer;
}
.tab_nav_active {
/*background gradient*/
background: rgba(50,54,162,1) !important;
background: -moz-linear-gradient(top, rgba(50,54,162,1) 0%, rgba(141,146,251,1) 100%) !important;
background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(50,54,162,1)), color-stop(100%, rgba(141,146,251,1))) !important;
background: -webkit-linear-gradient(top, rgba(50,54,162,1) 0%, rgba(141,146,251,1) 100%) !important;
background: -o-linear-gradient(top, rgba(50,54,162,1) 0%, rgba(141,146,251,1) 100%) !important;
background: -ms-linear-gradient(top, rgba(50,54,162,1) 0%, rgba(141,146,251,1) 100%) !important;
background: linear-gradient(to bottom, rgba(50,54,162,1) 0%, rgba(141,146,251,1) 100%) !important;
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3236a2', endColorstr='#8d92fb', GradientType=0 ) !important;
/*border*/
border-radius: 4px 0px 0px 4px;
-moz-border-radius: 4px 0px 0px 4px;
-webkit-border-radius: 4px 0px 0px 4px;
border-left: 1px solid #c0c0c0;
border-top: 1px solid #c0c0c0;
border-bottom: 1px solid #c0c0c0;
display:inline-block;
color:#ffffff !important;
font-family:arial;
font-size:12px;
padding: 1px 5px;
text-decoration:none;
}
.error {
background-color: #FFE6E6 !important;
border-color: red !important;
}
.errhint {
border: 1px solid red;
padding: 4px 8px;
background-color: white;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
color: red;
font-weight: bold;
}

1
public/css/github.css Normal file

File diff suppressed because one or more lines are too long

1
public/css/github2.css Normal file

File diff suppressed because one or more lines are too long

3
public/css/style-ie.css Normal file
View File

@ -0,0 +1,3 @@
#nav {
padding-top: 18px;
}

220
public/css/style.css Normal file
View File

@ -0,0 +1,220 @@
body {
margin: 0;
padding: 0;
font-size: 12px;
font-family: Arial, Helvetica, sans-serif;
line-height: 22px;
}
#header {
height: 60px;
min-width: 1150px;
background-color: rgb(248, 248, 248);
background-image: url("../img/hw_000469.jpg");
border-bottom: 1px solid rgb(255, 255, 255);
background-repeat: repeat-x;
border-bottom-color: rgb(255, 255, 255);
border-bottom-style: solid;
border-bottom-width: 1px;
}
#bound {
overflow: hidden;
margin: 0px auto;
padding: 0 0 0 20px;
}
#logo {
padding-top: 9px;
}
#menu {
height: 46px;
min-width: 1150px;
overflow: hidden;
width: auto !important;
margin: 0px auto;
position: relative;
background: url("../img/hw_s_221828.jpg") repeat-x scroll left bottom rgb(248, 248, 248);
border-top: 1px solid rgb(215, 212, 207);
border-bottom: 1px solid rgb(196, 198, 195);
}
#menu ul {
font-size: 18px;
min-width: 1000px;
color: #5964a1;
}
#menu li:first-child {
padding-left: 0px !important;
}
#menu li {
display: inline;
float: left;
padding-left: 35px;
margin-top: -5px;
font-weight:bold;
}
#nav {
width: 300px;
}
.active {
color: #5964a1;
}
.inactive {
color: #c0c0c0;
}
.passed {
color: #008000;
}
#title {
font-size: 20px;
margin-top: 13px;
padding-left: 20px;
color: #5964a1;
}
p {
font-size: 14px;
color: #5964a1;
}
a {
text-decoration: none;
color: blue;
}
h3 {
color: #5964a1;
font-size: 16px;
margin-bottom: 10px;
}
h2 {
font-weight: 520;
font-size: 20px;
color: #5964a1;
margin-top: 8px;
}
#content {
min-width: 1150px;
min-height: 200px;
overflow-x: hidden;
position: relative;
margin: 0;
background-color: whitesmoke;
/* IE10 Consumer Preview */
background-image: -ms-linear-gradient(top, #FFFFFF 0%, #CCCCCC 100%);
/* Mozilla Firefox */
background-image: -moz-linear-gradient(top, #FFFFFF 0%, #CCCCCC 100%);
/* Opera */
background-image: -o-linear-gradient(top, #FFFFFF 0%, #CCCCCC 100%);
/* Webkit (Safari/Chrome 10) */
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #FFFFFF), color-stop(1, #CCCCCC));
/* Webkit (Chrome 11+) */
background-image: -webkit-linear-gradient(top, #FFFFFF 0%, #CCCCCC 100%);
/* W3C Markup, IE10 Release Preview */
background-image: linear-gradient(to bottom, #FFFFFF 0%, #CCCCCC 100%);
}
.main-box {
padding-top: 20px;
padding-bottom: 20px;
padding-left: 30px;
padding-right:30px;
}
.left-side {
float: left;
width: 48%;
min-width: 460px;
}
.left-side ul {
font-size: 14px;
color: #5964a1;
}
.inside {
padding-left: 20px;
padding-right: 20px;
}
.inside table {
padding-top: 10px;
width: 100%;
border-spacing: 0;
}
.inside th {
text-align: left;
padding-left: 10px;
border-bottom: 1px solid grey;
}
.right-side {
float: left;
width: 48%;
}
.right-side table {
padding-top: 0px;
width: 100%;
border-spacing: 0px 0px;
}
.right-side th:first-child {
padding-left: 0px !important;
}
.right-side th {
text-align: left;
padding-left: 10px;
}
.right-side img {
padding-left: 30px;
}
.continue {
margin-top: 20px;
}
#footer {
width: 100%;
min-width: 1000px;
overflow: hidden;
position: absolute;
bottom: 0px;
padding-bottom: 20px;
text-align:center;
background-color: lightBlue;
}
.unavailable {
opacity: 0.5;
}
.loading {
vertical-align: middle;
opacity: 0;
}
.go-back {
font-size: 15px;
padding-right: 10px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

BIN
public/img/ajax_loader.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
public/img/asc.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 B

BIN
public/img/bg.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 B

BIN
public/img/desc.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 B

BIN
public/img/hw_000353.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
public/img/hw_000469.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
public/img/hw_s_221828.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

BIN
public/img/hwico.ico.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 665 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 B

BIN
public/img/router.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
public/img/server.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

BIN
public/img/switch.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

8981
public/lib/d3.js vendored Normal file

File diff suppressed because it is too large Load Diff

5
public/lib/d3.min.js vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

6
public/lib/jquery-1.10.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1177
public/lib/jquery-ui-1.10.3.custom.css vendored Normal file

File diff suppressed because it is too large Load Diff

14971
public/lib/jquery-ui-1.10.3.custom.js vendored Normal file

File diff suppressed because it is too large Load Diff

12099
public/lib/jquery.dataTables.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,291 @@
/*
*
* Copyright (c) 2006-2011 Sam Collett (http://www.texotela.co.uk)
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
*
* Version 1.3.1
* Demo: http://www.texotela.co.uk/code/jquery/numeric/
*
*/
(function($) {
/*
* Allows only valid characters to be entered into input boxes.
* Note: fixes value when pasting via Ctrl+V, but not when using the mouse to paste
* side-effect: Ctrl+A does not work, though you can still use the mouse to select (or double-click to select all)
*
* @name numeric
* @param config { decimal : "." , negative : true }
* @param callback A function that runs if the number is not valid (fires onblur)
* @author Sam Collett (http://www.texotela.co.uk)
* @example $(".numeric").numeric();
* @example $(".numeric").numeric(","); // use , as separator
* @example $(".numeric").numeric({ decimal : "," }); // use , as separator
* @example $(".numeric").numeric({ negative : false }); // do not allow negative values
* @example $(".numeric").numeric(null, callback); // use default values, pass on the 'callback' function
*
*/
$.fn.numeric = function(config, callback)
{
if(typeof config === 'boolean')
{
config = { decimal: config };
}
config = config || {};
// if config.negative undefined, set to true (default is to allow negative numbers)
if(typeof config.negative == "undefined") { config.negative = true; }
// set decimal point
var decimal = (config.decimal === false) ? "" : config.decimal || ".";
// allow negatives
var negative = (config.negative === true) ? true : false;
// callback function
callback = (typeof(callback) == "function" ? callback : function() {});
// set data and methods
return this.data("numeric.decimal", decimal).data("numeric.negative", negative).data("numeric.callback", callback).keypress($.fn.numeric.keypress).keyup($.fn.numeric.keyup).blur($.fn.numeric.blur);
};
$.fn.numeric.keypress = function(e)
{
// get decimal character and determine if negatives are allowed
var decimal = $.data(this, "numeric.decimal");
var negative = $.data(this, "numeric.negative");
// get the key that was pressed
var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
// allow enter/return key (only when in an input box)
if(key == 13 && this.nodeName.toLowerCase() == "input")
{
return true;
}
else if(key == 13)
{
return false;
}
var allow = false;
// allow Ctrl+A
if((e.ctrlKey && key == 97 /* firefox */) || (e.ctrlKey && key == 65) /* opera */) { return true; }
// allow Ctrl+X (cut)
if((e.ctrlKey && key == 120 /* firefox */) || (e.ctrlKey && key == 88) /* opera */) { return true; }
// allow Ctrl+C (copy)
if((e.ctrlKey && key == 99 /* firefox */) || (e.ctrlKey && key == 67) /* opera */) { return true; }
// allow Ctrl+Z (undo)
if((e.ctrlKey && key == 122 /* firefox */) || (e.ctrlKey && key == 90) /* opera */) { return true; }
// allow or deny Ctrl+V (paste), Shift+Ins
if((e.ctrlKey && key == 118 /* firefox */) || (e.ctrlKey && key == 86) /* opera */ ||
(e.shiftKey && key == 45)) { return true; }
// if a number was not pressed
if(key < 48 || key > 57)
{
var value = $(this).val();
/* '-' only allowed at start and if negative numbers allowed */
if(value.indexOf("-") !== 0 && negative && key == 45 && (value.length === 0 || parseInt($.fn.getSelectionStart(this), 10) === 0)) { return true; }
/* only one decimal separator allowed */
if(decimal && key == decimal.charCodeAt(0) && value.indexOf(decimal) != -1)
{
allow = false;
}
// check for other keys that have special purposes
if(
key != 8 /* backspace */ &&
key != 9 /* tab */ &&
key != 13 /* enter */ &&
key != 35 /* end */ &&
key != 36 /* home */ &&
key != 37 /* left */ &&
key != 39 /* right */ &&
key != 46 /* del */
)
{
allow = false;
}
else
{
// for detecting special keys (listed above)
// IE does not support 'charCode' and ignores them in keypress anyway
if(typeof e.charCode != "undefined")
{
// special keys have 'keyCode' and 'which' the same (e.g. backspace)
if(e.keyCode == e.which && e.which !== 0)
{
allow = true;
// . and delete share the same code, don't allow . (will be set to true later if it is the decimal point)
if(e.which == 46) { allow = false; }
}
// or keyCode != 0 and 'charCode'/'which' = 0
else if(e.keyCode !== 0 && e.charCode === 0 && e.which === 0)
{
allow = true;
}
}
}
// if key pressed is the decimal and it is not already in the field
if(decimal && key == decimal.charCodeAt(0))
{
if(value.indexOf(decimal) == -1)
{
allow = true;
}
else
{
allow = false;
}
}
}
else
{
allow = true;
}
return allow;
};
$.fn.numeric.keyup = function(e)
{
var val = $(this).val();
if(val && val.length > 0)
{
// get carat (cursor) position
var carat = $.fn.getSelectionStart(this);
var selectionEnd = $.fn.getSelectionEnd(this);
// get decimal character and determine if negatives are allowed
var decimal = $.data(this, "numeric.decimal");
var negative = $.data(this, "numeric.negative");
// prepend a 0 if necessary
if(decimal !== "" && decimal !== null)
{
// find decimal point
var dot = val.indexOf(decimal);
// if dot at start, add 0 before
if(dot === 0)
{
this.value = "0" + val;
}
// if dot at position 1, check if there is a - symbol before it
if(dot == 1 && val.charAt(0) == "-")
{
this.value = "-0" + val.substring(1);
}
val = this.value;
}
// if pasted in, only allow the following characters
var validChars = [0,1,2,3,4,5,6,7,8,9,'-',decimal];
// get length of the value (to loop through)
var length = val.length;
// loop backwards (to prevent going out of bounds)
for(var i = length - 1; i >= 0; i--)
{
var ch = val.charAt(i);
// remove '-' if it is in the wrong place
if(i !== 0 && ch == "-")
{
val = val.substring(0, i) + val.substring(i + 1);
}
// remove character if it is at the start, a '-' and negatives aren't allowed
else if(i === 0 && !negative && ch == "-")
{
val = val.substring(1);
}
var validChar = false;
// loop through validChars
for(var j = 0; j < validChars.length; j++)
{
// if it is valid, break out the loop
if(ch == validChars[j])
{
validChar = true;
break;
}
}
// if not a valid character, or a space, remove
if(!validChar || ch == " ")
{
val = val.substring(0, i) + val.substring(i + 1);
}
}
// remove extra decimal characters
var firstDecimal = val.indexOf(decimal);
if(firstDecimal > 0)
{
for(var k = length - 1; k > firstDecimal; k--)
{
var chch = val.charAt(k);
// remove decimal character
if(chch == decimal)
{
val = val.substring(0, k) + val.substring(k + 1);
}
}
}
// set the value and prevent the cursor moving to the end
this.value = val;
$.fn.setSelection(this, [carat, selectionEnd]);
}
};
$.fn.numeric.blur = function()
{
var decimal = $.data(this, "numeric.decimal");
var callback = $.data(this, "numeric.callback");
var val = this.value;
if(val !== "")
{
var re = new RegExp("^\\d+$|^\\d*" + decimal + "\\d+$");
if(!re.exec(val))
{
callback.apply(this);
}
}
};
$.fn.removeNumeric = function()
{
return this.data("numeric.decimal", null).data("numeric.negative", null).data("numeric.callback", null).unbind("keypress", $.fn.numeric.keypress).unbind("blur", $.fn.numeric.blur);
};
// Based on code from http://javascript.nwbox.com/cursor_position/ (Diego Perini <dperini@nwbox.com>)
$.fn.getSelectionStart = function(o)
{
if (o.createTextRange)
{
var r = document.selection.createRange().duplicate();
r.moveEnd('character', o.value.length);
if (r.text === '') { return o.value.length; }
return o.value.lastIndexOf(r.text);
} else { return o.selectionStart; }
};
// Based on code from http://javascript.nwbox.com/cursor_position/ (Diego Perini <dperini@nwbox.com>)
$.fn.getSelectionEnd = function(o)
{
if (o.createTextRange) {
var r = document.selection.createRange().duplicate()
r.moveStart('character', -o.value.length)
return r.text.length
} else return o.selectionEnd
}
// set the selection, o is the object (input), p is the position ([start, end] or just start)
$.fn.setSelection = function(o, p)
{
// if p is number, start and end are the same
if(typeof p == "number") { p = [p, p]; }
// only set if p is an array of length 2
if(p && p.constructor == Array && p.length == 2)
{
if (o.createTextRange)
{
var r = o.createTextRange();
r.collapse(true);
r.moveStart('character', p[0]);
r.moveEnd('character', p[1]);
r.select();
}
else if(o.setSelectionRange)
{
o.focus();
o.setSelectionRange(p[0], p[1]);
}
}
};
})(jQuery);

80
public/ods/config.js Normal file
View File

@ -0,0 +1,80 @@
config = {
"switches": [
{
"switch": {
"ip": "172.29.8.40",
"credential": {
"version": "v2c",
"community": "public"
}
}
},
{
"switch": {
"ip": "172.29.8.41",
"credential": {
"version": "v2c",
"community": "public"
}
}
}
],
"security": {
"server_credentials": {
"username": "root",
"password": "root"
},
"service_credentials": {
"username": "service",
"password": "admin"
},
"console_credentials": {
"username": "console",
"password": "admin"
}
},
"networking": {
"interfaces": {
"management": {
"ip_start": "10.10.10.100",
"ip_end": "10.10.10.255",
"netmask": "255.255.255.0",
"gateway": "10.10.10.1",
"nic": "eth0",
"promisc": 0
},
"tenant": {
"ip_start": "192.168.100.100",
"ip_end": "192.168.100.200",
"netmask": "255.255.255.0",
"gateway": "192.168.100.1",
"nic": "eth1",
"promisc": 0
},
"public": {
"ip_start": "172.29.3.100",
"ip_end": "172.29.3.200",
"netmask": "255.255.255.0",
"gateway": "172.29.3.1",
"nic": "eth2",
"promisc": 0
},
"storage": {
"ip_start": "172.16.128.10",
"ip_end": "172.16.128.200",
"netmask": "255.255.255.0",
"gateway": "172.16.128.1",
"nic": "eth3",
"promisc": 0
}
},
"global": {
"nameservers": "4.4.4.4,8.8.8.8",
"search_path": "ods.com,ods2.com",
"gateway": "172.19.100.1",
"proxy": "",
"ntp_server": ""
}
}
};

View File

@ -0,0 +1,381 @@
// map fixtures for this application
steal("jquery/dom/fixture", "jquery/lang/json", function(){
var self = this;
self.switchIdIndex = 1;
self.servers_data = [];
self.percentage = 0.0;
self.port = 0;
$.fixture('POST /api/switches', function(original, settings, headers) {
var manage_ip = JSON.parse(original.data).switch.ip;
var switchId = 1;
if(manage_ip == "172.29.8.40") {
switchId = 1;
}
else if(manage_ip == "172.29.8.41"){
switchId = 2;
}
var returnData = {
"status": "accepted",
"switch": {
"state": "not_reached",
"link": {
"href": "/switches/"+switchId+"/",
"rel": "self"
},
"id": switchId
}
};
var duplicateErr = {
"status": "duplicate",
"message": "duplicate IP address",
"failedSwitch": 2
};
//var xhr = {responseText: JSON.stringify(duplicateErr), status: 409};
if(switchId == 1) {
return [202, "accepted", returnData, {} ];
//return [202, returnData ];
}
else if(switchId == 2) {
return [409, duplicateErr];
}
});
$.fixture('PUT /api/switches/{id}', function(original, settings, headers) {
var switchId = settings.url.substring(14,15);
var returnData = {
"status": "accepted",
"switch": {
"state": "not_reached",
"link": {
"href": "/switches/"+switchId+"/",
"rel": "self"
},
"id": switchId
}
};
return [202, "accepted", returnData, {} ];
});
$.fixture('GET /api/switches/{id}', function(original, settings, headers) {
var switchId = settings.url.substring(14,15);
var returnData = {
"status": "OK",
"switch": {
"state": switchId == 10 ? "not_reached" : "under_monitoring",
"link": {
"href": settings.url,
"rel": "self"
},
"id": switchId
}
};
return returnData;
});
$.fixture('GET /api/machines', function(original, settings, headers) {
var switchId = settings.url.substring(23);
steal.dev.log("get machines switchId", switchId);
if(switchId == 1) {
var returnData = {
"status": "OK",
"machines": [
{
"mac": "28:6e:31:47:c8:6c",
"vlan": 1,
"link": {
"href": "/api/machines/10",
"rel": "self"
},
"id": 10,
"port": 1,
"switch_ip": "172.29.8.40"
},
{
"mac": "28:6e:55:47:52:e3",
"vlan": 1,
"link": {
"href": "/api/machines/20",
"rel": "self"
},
"id": 20,
"port": 2,
"switch_ip": "172.29.8.40"
},
{
"mac": "28:6e:d4:47:33:5f",
"vlan": 1,
"link": {
"href": "/api/machines/30",
"rel": "self"
},
"id": 30,
"port": 3,
"switch_ip": "172.29.8.40"
},
{
"mac": "28:6e:9b:47:51:aa",
"vlan": 1,
"link": {
"href": "/api/machines/40",
"rel": "self"
},
"id": 40,
"port": 4,
"switch_ip": "172.29.8.40"
}
]
};
return returnData;
}
else if(switchId == 2) {
var returnData = {
"status": "OK",
"machines": [
{
"mac": "28:e5:ee:47:14:92",
"vlan": 2,
"link": {
"href": "/api/machines/50",
"rel": "self"
},
"id": 50,
"port": 1,
"switch_ip": "172.29.8.41"
},
{
"mac": "28:61:15:c2:aa:4a",
"vlan": 2,
"link": {
"href": "/api/machines/60",
"rel": "self"
},
"id": 60,
"port": 2,
"switch_ip": "172.29.8.41"
},
{
"mac": "28:27:f9:c2:51:4a",
"vlan": 2,
"link": {
"href": "/api/machines/70",
"rel": "self"
},
"id": 70,
"port": 3,
"switch_ip": "172.29.8.41"
}
]
};
return returnData;
}
});
$.fixture('POST /api/clusters', function(data) {
var returnData = {
"status": "OK",
"cluster": {
"id": "123",
"name": "clustername",
"link": {
"href": "/api/clusters/123",
"rel": "self"
}
}
};
return returnData;
});
$.fixture('POST /api/clusters/{id}/action', function(original, settings, headers) {
var hostIds = JSON.parse(original.data).addHosts;
if(!hostIds) {
hostIds = JSON.parse(original.data).replaceAllHosts;
}
if(hostIds) { // for addHost and replaceAllHost
steal.dev.log("fixture cluster action hostIds : ", hostIds);
var returnData = {
"status": "OK",
"clusterHosts": []
};
for(var i = 0; i<hostIds.length; i++) {
var tmp = {
"machine_id": hostIds[i],
"id": hostIds[i]*10
}
returnData.clusterHosts.push(tmp);
}
return returnData;
}
else { // for deploy
var returnData = {
"status": "accepted",
"deployment": "/api/progress/cluster/123"
}
return [202, "accepted", returnData, {} ];
}
});
$.fixture('PUT /api/clusters/{id}/security', function(data) {
self.security_data = data.data;
var returnData = {
"status": "OK"
};
return returnData;
});
$.fixture('PUT /api/clusters/{id}/networking', function(original, settings, headers) {
console.log("networking original: ", original);
var returnData = {
"status": "OK"
};
return returnData;
});
$.fixture('PUT /api/clusterhosts/{id}/config', function(original, settings, headers) {
console.log(settings);
var returnData = {
"status": "OK"
};
return returnData;
});
$.fixture('PUT /api/clusters/{id}/partition', function(data) {
self.partition_data = data;
console.log("new partition api: ", self.partition_data);
var returnData = {
"status": "OK"
};
return returnData;
});
/*
// used on Install Review Page
$.fixture('GET /api/logicpartition', function() {
return self.partition_data;
});
// used on Install Review Page
$.fixture('GET /api/security', function() {
return self.security_data;
});
// used on Install Review Page
$.fixture('GET /api/networking', function(data) {
//console.log(data);
return self.networking_data;
});
*/
$.fixture('POST /api/triggerinstall/', function(data) {
console.log(data);
var returnData = {
"status": "OK",
"_data": {},
"type": "triggerinstall"
};
return returnData;
});
$.fixture('GET /api/clusterhosts/{id}/progress', function(original, settings, headers) {
self.percentage += 0.1;
if(self.percentage > 1)
self.percentage = 1;
var message = "Configuring Net Management";
if(self.percentage < 0.3) {
message = "Configuring Net Management";
}
else if(self.percentage < 0.45){
message = "Installing OpenStack";
}
else if(self.percentage < 0.65) {
message = "Configuring Core Virtualization";
}
else if(self.percentage < 0.80) {
message = "Finalizing OpenStack Installation";
}
else if(self.percentage < 1.0) {
message = "Configuring API Database";
}
else {
message = "Completed!";
}
var id = original.url.substring(18, 21);
console.log(id);
console.log(original);
var res = {
"status": "OK",
"progress": {
"id": id,
"state": "",
"hostname": "hostname",
"percentage": self.percentage,
"message": message,
"severity": "INFO" // INFO, WARNING, ERROR
},
"type": "progress"
};
return res;
});
$.fixture('GET /api/clusters/{id}/progress', function(original, settings, headers) {
var returnData = {
"status": "OK",
"progress": {
"state": "",
"percentage": self.percentage,
"messages": [
"Configuring Net Management",
"Configuring Core Virtualization"
],
"severity": "INFO" // INFO, WARNING, ERROR
}
};
return returnData;
});
$.fixture('GET /api/dashboardlinks', function(original, settings, headers) {
console.log("original: ", original);
console.log("settings: ", settings);
var res = {
"status": "OK",
"type": "clusterlinks",
"clusterlinks": {
"os-single-controller": "http://10.145.88.232"
}
};
return res;
});
})

15
public/ods/funcunit.html Normal file
View File

@ -0,0 +1,15 @@
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="../funcunit/qunit/qunit.css" />
<title>ods FuncUnit Test</title>
<script type='text/javascript' src='../steal/steal.js?ods/test/funcunit'></script>
</head>
<body>
<h1 id="qunit-header">ods Test Suite</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
</body>
</html>

View File

@ -0,0 +1,88 @@
steal("jquery/model", "jquery/lang/json",
function() {
$.Model('Ods.Cluster', {
create: function(params, success, error) {
$.ajax({
url: '/api/clusters',
type: 'post',
dataType: 'json',
contentType: "application/json",
data: $.toJSON(params),
success: success,
error: error
});
},
action: function(id, params, success, error) {
$.ajax({
url: '/api/clusters/' + id + '/action',
type: 'post',
dataType: 'json',
data: $.toJSON(params),
contentType: "application/json",
success: success,
error: error
});
},
update: function(id, params, resource, success, error) {
$.ajax({
url: '/api/clusters/' + id + '/' + resource,
type: 'put',
dataType: 'json',
data: $.toJSON(params),
contentType: "application/json",
success: success,
error: error
});
},
progress: function(id, success) {
$.ajax({
url: '/api/clusters/' + id + '/progress',
type: 'GET',
dataType: 'json',
success: success
});
}
}, {});
$.Model('Ods.ClusterHost', {
update: function(id, params, success, error) {
$.ajax({
url: '/api/clusterhosts/' + id + '/config',
type: 'PUT',
dataType: 'json',
contentType: "application/json",
data: $.toJSON(params),
success: success,
error: error
});
},
progress: function(id, success, error) {
$.ajax({
url: '/api/clusterhosts/' + id + '/progress',
type: 'GET',
dataType: 'json',
success: success,
error: error
});
}
}, {});
$.Model('Ods.DashboardLink', {
findOne: function(id, success) {
$.ajax({
url: '/api/dashboardlinks',
type: 'get',
dataType: 'json',
data: {
"cluster_id": id
},
success: success
});
}
}, {});
});

View File

@ -0,0 +1,4 @@
// steal model files
steal("jquery/model",
"./servers.js",
"./cluster.js")

View File

@ -0,0 +1,43 @@
steal("jquery/model", "jquery/lang/json",
function() {
$.Model('Ods.Switch', {
create: function(params, success, error) {
$.ajax({
url: '/api/switches',
type: 'POST',
dataType: 'json',
contentType: "application/json",
data: $.toJSON(params),
success: success,
error: error
});
},
findOne: function(id, success, error) {
$.ajax({
url: '/api/switches/' + id,
type: 'GET',
dataType: 'json',
success: success,
error: error
});
},
update: function(id, params, success, error) {
$.ajax({
url: '/api/switches/' + id,
type: 'PUT',
data: $.toJSON(params),
dataType: 'json',
contentType: "application/json",
success: success,
error: error
});
}
}, {});
$.Model('Ods.Server', {
findAll: 'GET /api/machines'
}, {});
});

0
public/ods/ods.css Normal file
View File

71
public/ods/ods.html Normal file
View File

@ -0,0 +1,71 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Huawei - Compass</title>
<link rel="stylesheet" type="text/css" href="../css/base.css" />
<link rel="stylesheet" type="text/css" href="../css/style.css" />
<script type='text/javascript' src='../lib/d3.min.js'></script>
<!--[if IE 7]>
<link rel="stylesheet" type="text/css" href="/css/style-ie.css">
<![endif]-->
</head>
<body>
<div id="header">
<div id="bound">
<div id="logo">
<img src="../img/hw_000353.jpg" title="Huawei Compass homepage"></img>
</div>
</div>
</div>
<div id="menu">
<div id="title" style="float:left">
Compass
</div>
<div id="nav" style="float:left">
</div>
</div>
<div id="content">
<div class="main-box">
</div>
</div>
<script>
var result = {};
if (window.location.search)
{
// split up the query string and store in an associative array
var params = window.location.search.slice(1).split("&");
for (var i = 0; i < params.length; i++)
{
var tmp = params[i].split("=");
result[tmp[0]] = unescape(tmp[1]);
}
}
if(result.production == "true") {
var library = document.createElement("script");
library.setAttribute("src", "../steal/steal.production.js?ods");
document.body.appendChild(library);
}
else {
var library = document.createElement("script");
library.setAttribute("src", "../steal/steal.js?ods");
document.body.appendChild(library);
}
</script>
</body>
</html>

59
public/ods/ods.js Normal file
View File

@ -0,0 +1,59 @@
steal(
// './ods.css', // application CSS file
'./models/models.js', // steals all your models
'./ui/welcome/welcome.js',
'./ui/nav/nav.js','jquery/lang/observe/delegate',
'./fixtures/fixtures.js', // sets up fixtures for your models
'./config.js',
function(){ // configure your application
var mainBox = $('div.main-box');
var odsState = {
networking: null,
servers: [],
servers_config: null,
cluster_id: null,
security: null,
partition: null,
feature: null,
machines: [],
switches: [],
snmp: 1
};
var state = new $.Observe(odsState);
$('#nav').ods_ui_nav({"mainBox" : mainBox, "odsState" : state});
mainBox.ods_ui_welcome({ nav: $('#nav').controller(), "mainBox" : mainBox, "odsState" : state });
if (!window.location.host) {
$.fixture.on = true;
state.switches = config.switches;
state.security = config.security;
state.networking = config.networking;
} else {
var result = {};
if (window.location.search) {
// split up the query string and store in an associative array
var params = window.location.search.slice(1).split("&");
for (var i = 0; i < params.length; i++) {
var tmp = params[i].split("=");
result[tmp[0]] = unescape(tmp[1]);
}
}
if (result.server == "fixture") {
$.fixture.on = true;
} else {
$.fixture.on = false;
}
if (result.config == "true") {
state.switches = config.switches;
state.security = config.security;
state.networking = config.networking;
}
}
})

3
public/ods/ods.md Normal file
View File

@ -0,0 +1,3 @@
@page index ods
This is a placeholder for the homepage of your documentation.

File diff suppressed because one or more lines are too long

1021
public/ods/production.js Normal file

File diff suppressed because it is too large Load Diff

21
public/ods/qunit.html Normal file
View File

@ -0,0 +1,21 @@
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="../funcunit/qunit/qunit.css" />
<title>ods QUnit Test</title>
<script type='text/javascript'>
steal = {ignoreControllers: true}
</script>
<script type='text/javascript' src='../steal/steal.js?ods/test/qunit'></script>
</head>
<body>
<h1 id="qunit-header">ods Test Suite</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<div id="test-content"></div>
<ol id="qunit-tests"></ol>
<div id="qunit-test-area"></div>
</body>
</html>

View File

@ -0,0 +1,21 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title>ods Build Page</title>
</head>
<body>
<h1>ods Build Page</h1>
<p>This is a dummy page that loads your app so steal can
get all the files.
</p>
<p>If you built your app
to depend on HTML in the page before DOMContent loaded or
onload, you can add the HTML here, or you can change the
build.js script to point to a better html file.
</p>
<script type='text/javascript'
src='../../steal/steal.js?ods'>
</script>
</body>
</html>

View File

@ -0,0 +1,6 @@
//js ods/scripts/build.js
load("steal/rhino/rhino.js");
steal('steal/build').then('steal/build/scripts','steal/build/styles',function(){
steal.build('ods/scripts/build.html',{to: 'ods'});
});

View File

@ -0,0 +1,17 @@
//steal/js ods/scripts/compress.js
load("steal/rhino/rhino.js");
steal('steal/clean',function(){
steal.clean('ods/ods.html',{
indent_size: 1,
indent_char: '\t',
jslint : false,
ignore: /jquery\/jquery.js/,
predefined: {
steal: true,
jQuery: true,
$ : true,
window : true
}
});
});

View File

@ -0,0 +1,7 @@
// load('ods/scripts/crawl.js')
load('steal/rhino/rhino.js')
steal('steal/html/crawl', function(){
steal.html.crawl("ods/ods.html","ods/out")
});

View File

@ -0,0 +1,8 @@
//js ods/scripts/doc.js
load('steal/rhino/rhino.js');
steal("documentjs").then(function(){
DocumentJS('ods/ods.html', {
markdown : ['ods']
});
});

View File

@ -0,0 +1,43 @@
steal(
'jquery/controller',
'jquery/view/ejs',
'jquery/controller/view'
).then(
'./views/init.ejs',
'./views/before_begin.ejs'
).then(function($) {
$.Controller('Ods.Ui.features', {}, {
init: function() {
this.element.html(this.view('init'));
},
'a.btn_continue click': function(el, ev) {
ev.preventDefault();
if (el.data('step') === 'before_begin') {
this.options.nav.gotoStep("2");
} else {
var live_migration = 0;
var high_availability = 0;
if ($('#lm').is(':checked')) {
live_migration = 1;
}
if ($('#ha').is(':checked')) {
high_availability = 1;
}
this.options.odsState.feature = {
"live_migration": live_migration,
"high_availability": high_availability
};
this.element.html(this.view('before_begin'));
}
},
show: function() {
this.element.show();
},
hide: function() {
this.element.hide();
}
});
});

View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>features Widget Unit Test</title>
<link rel="stylesheet" type="text/css" href="../../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../../css/style.css" />
</head>
<body>
<div class="container-fluid">
<div class="row-fluid">
<div id="features-test"> </div>
</div>
</div>
<script type='text/javascript' src='../../../steal/steal.js'></script>
<script type='text/javascript'>
steal('jquery/dom/route', 'ods/ui/features').then(function($) {
$('#features-test').ods_ui_features();
});
</script>
</body>
</html>

View File

@ -0,0 +1,27 @@
<h2>Welcome to Compass</h2>
<div class="left-side">
<p>
Before you begin the deployment of the OpenStack software, you need to make sure that the servers and networking are deployed properly. Compass requires the following configuration:
</p>
<ul>
<li>All servers must have at least <span class="bold underline">two</span> 1 Gbps network ports</li>
<li>One server must have <span class="bold underline">three</span> 1 Gbps network ports</li>
<li>Server NICs must be connected to the same subnet</li>
</ul>
<p>
When you have configured the servers as described above, and shown in the picture to the right, you can begin the OpenStack Deployment by clicking the Continue button. At the next screen you will be asked to identify the switch to which the servers are connected to begin the process.
</p>
<p>
When you're ready to begin, click the Continue button below.
</p>
<p>
<a href="#">Print these instructions</a>
</p>
<div class="continue"><center>
<a href="/web/servers/" class="btn_continue" data-step="before_begin">Continue</a>
</center></div>
</div>
<div class="right-side">
<img title="Descriptive Topological Graphic" src="../img/topology_description.png" height="385px" width="538px"></img>
</div>

View File

@ -0,0 +1,35 @@
<h2>Select the Compass features you want to deploy and configure</h2>
<div class="left-side">
<div class="inside">
<h3><span><img src="../img/green_check_16px.png" height="16px" width="16px"></img></span>&nbsp;&nbsp;OpenStack Virtualization</h3>
<p style="padding-left:40px">
Create and run KVM virtual machines. This feature is the core of OpenStack, and is a required part of the Openstack deployment.
</p>
<h3 class="unavailable">
<input id="lm" type="checkbox" disabled> Live Migration of Virtual Machines
</h3>
<p class="unavailable" style="padding-left:40px">
Live Migration allows virtual machines to be moved from one compute server to another without powering them down.
</p>
<h3 class="unavailable">
<input id="ha" type="checkbox" disabled> High Availability (HA)
</h3>
<p class="unavailable" style="padding-left:40px">
High Availability automatically restarts a virtual machine on a different compute server in the event of its being accidentally powered off due to a compute server failure.
</p>
<div class="continue"><center>
<a id="continue" href="javascript: void(0)" data-step="features" class="btn_continue">Continue</a>
</center></div>
</div>
</div>
<div class="right-side">
<img title="Descriptive Features Graphic" src="../img/features_graphic.png" height="362px" width="559px"></img>
</div>

View File

@ -0,0 +1,7 @@
.tab_panel{
display: none;
}
.tab_panel_active {
display: block;
}

View File

@ -0,0 +1,320 @@
steal(
'jquery/controller',
'jquery/view/ejs',
'jquery/controller/view'
).then(
'./host_config.css',
'./views/init.ejs',
'./views/server_row.ejs',
'ods/models/cluster.js',
'lib/jquery-ui-1.10.3.custom.css',
'lib/jquery-ui-1.10.3.custom.js',
'lib/jquery.numeric.js'
).then(function($) {
$.Controller('Ods.Ui.host_config', {}, {
init: function() {
this.element.html(this.view('init'));
$("#clear").click(function() {
$(".config_hostname input").val("");
});
var self = this;
$("#dialog-confirm").dialog({
autoOpen: false,
resizable: false,
height: 200,
width: 400,
modal: true,
buttons: {
"Fill values": function() {
var pattern = $("#pattern").val();
if (pattern == "Switch IP") {
self.fillHostnameBySwitchIp();
} else if (pattern == "Switch alias") {
self.fillHostnameBySwitchAlias();
} else if (pattern == "Host") {
self.fillHostnameByServer();
}
$(this).dialog("close");
},
Cancel: function() {
$(this).dialog("close");
}
}
});
$(document).tooltip({
items: "[data-geo], [title]",
content: function() {
var element = $(this);
if (element.is("[data-geo]")) {
return "<div><strong>Switch IP: </strong>" + "Use the IP address and port for the switch to which the host is attached </div>" + "<div><strong>Switch alias: </strong>Use the switch alias for the switch and port to which the host is attached</div>" + "<div><strong>Server: </strong>Auto-increment integer value based on the last generated value</div>";
}
}
});
$(".integer").numeric(false, function() {
this.value = "";
this.focus();
});
this.filloutTabs();
this.server_count = this.options.odsState.servers.length;
},
fillHostnameBySwitchIp: function() {
var serverData = this.options.odsState.servers_config;
this.server_count = 0;
for (var key in serverData) {
var servers = serverData[key];
for (var i = 0; i < servers.length; i++) {
servers[i]['hostname'] = key.replace(/\./g, "-") + '-p' + servers[i].port;
serverData[key][i]['hostname'] = servers[i]['hostname'];
this.server_count++;
}
}
this.options.odsState.servers_config = serverData;
this.tabSelected($(".tab_nav_active"));
},
fillHostnameBySwitchAlias: function() {
var serverData = this.options.odsState.servers_config;
var key_index = 1;
this.server_count = 0;
for (var key in serverData) {
var servers = serverData[key];
for (var i = 0; i < servers.length; i++) {
servers[i]['hostname'] = "switch" + key_index + '-p' + servers[i].port;
}
key_index++;
this.server_count++;
}
this.options.odsState.servers_config = serverData;
this.tabSelected($(".tab_nav_active"));
},
fillHostnameByServer: function() {
var serverData = this.options.odsState.servers_config;
var server_index = 1;
this.server_count = 0;
for (var key in serverData) {
var servers = serverData[key];
for (var i = 0; i < servers.length; i++) {
servers[i]['hostname'] = "server" + server_index;
server_index++;
this.server_count++;
}
}
this.options.odsState.servers_config = serverData;
this.tabSelected($(".tab_nav_active"));
},
filloutTabs: function() {
var serverData = this.options.odsState.servers_config;
for (var key in serverData) {
$(".switch-navs").append('<div data-switchIp="' + key + '" class="tab_nav">' + key + '</div><br>');
}
this.tabSelected($(".switch-navs .tab_nav:first-child"));
},
tabSelected: function(el) {
$('#tab1 table tbody tr').remove();
$(".tab_nav_active").removeClass("tab_nav_active");
el.addClass("tab_nav_active");
var switchIp = el.data('switchip');
var serverData = this.options.odsState.servers_config;
var servers = serverData[switchIp];
for (var i = 0; i < servers.length; i++) {
$('#tab1 table tbody').append(this.view('server_row', servers[i]));
}
},
'#auto_fill click': function(el, ev) {
$("#dialog-confirm").dialog("open");
},
'updateServersConfig': function() {
var currentSwitch = $(".tab_nav_active").data('switchip');
for (var i = 0; i < this.options.odsState.servers_config[currentSwitch].length; i++) {
this.options.odsState.servers_config[currentSwitch][i].hostname = $("#hostconfig-table tbody tr").eq(i).find(".hostname").val();
this.options.odsState.servers_config[currentSwitch][i].server_ip = $("#hostconfig-table tbody tr").eq(i).find(".serverIp").val();
}
},
'div.tab_nav click': function(el, ev) {
this.updateServersConfig();
this.tabSelected(el);
},
checkNonEmpty: function(el) {
var value = el.val();
if (!value) {
el.addClass('error');
return false;
}
return true;
},
'.hostconfig-finish click': function(el, ev) {
ev.preventDefault();
var self = this;
var hasError = false;
$('#hostconfig-table').find('.non-empty-value').each(function(index, value) {
if (!self.checkNonEmpty($(value))) {
hasError = true;
}
});
$('.partition-div').find('.non-empty-value').each(function(index, value) {
if (!self.checkNonEmpty($(value))) {
hasError = true;
}
});
if($("#spare").hasClass("error") ) {
hasError = true;
}
if (hasError) {
return;
}
$("#continuing").css("opacity", 1);
this.updateServersConfig();
var serverData = this.options.odsState.servers_config;
for (var key in serverData) {
var servers = serverData[key];
for (var i = 0; i < servers.length; i++) {
//var server_id = servers[i]['server_id'];
var clusterhost_id = servers[i]['clusterhost_id'];
var hostname = servers[i]['hostname'];
var server_ip = servers[i]['server_ip'];
var clusterhostConfigData = {
"hostname": hostname,
"networking": {
"interfaces": {
"management": {
"ip": server_ip
}
}
}
};
Ods.ClusterHost.update(clusterhost_id, clusterhostConfigData, this.proxy('onHostconfigData'), this.proxy('onHostconfigDataErr'));
}
}
},
/************************************/
// cluster host update success callback
/************************************/
onHostconfigData: function(data, textStatus, xhr) {
steal.dev.log(" *** onHostconfigData data *** ", data);
steal.dev.log(" *** onHostconfigData textStatus *** ", textStatus);
steal.dev.log(" *** onHostconfigData xhr *** ", xhr);
$("#hostconfig_continue_err").hide();
if (xhr.status == 200) {
this.server_count--;
}
if (this.server_count == 0) {
var partitionData = {
"partition": "/home " + $("#home").val() + "%;/tmp " + $("#tmp").val() + "%;/var " + $("#var").val() + "%;"
};
this.options.odsState.partition = {
"tmp": $("#tmp").val(),
"slashvar": $("#var").val(),
"home": $("#home").val()
};
Ods.Cluster.update(this.options.odsState.cluster_id, partitionData, "partition", this.proxy('onLogicPartitionAdded'), this.proxy('onLogicPartitionAddedErr'));
}
},
/************************************/
// cluster host update error callback
/************************************/
onHostconfigDataErr: function(xhr, status, statusText) {
steal.dev.log(" *** onHostconfigDataErr xhr *** ", xhr);
steal.dev.log(" *** onHostconfigDataErr status *** ", status);
steal.dev.log(" *** onHostconfigDataErr statusText *** ", xhr);
$("#hostconfig_continue_err").html("<span class='errhint'> Error code: " + xhr.status + " </span>");
$("#hostconfig_continue_err").show();
},
/************************************/
// cluster update (partition) success callback
/************************************/
onLogicPartitionAdded: function(data, textStatus, xhr) {
steal.dev.log(" *** onHostconfigData data *** ", data);
steal.dev.log(" *** onHostconfigData textStatus *** ", textStatus);
steal.dev.log(" *** onHostconfigData xhr *** ", xhr);
$("#hostconfig_continue_err").hide();
if (xhr.status == 200) { // OK
$("#continuing").css("opacity", 0);
this.options.nav.gotoStep("6");
}
},
onLogicPartitionAddedErr: function(xhr, status, statusText) {
steal.dev.log(" *** onLogicPartitionAddedErr xhr *** ", xhr);
steal.dev.log(" *** onLogicPartitionAddedErr status *** ", status);
steal.dev.log(" *** onLogicPartitionAddedErr statusText *** ", xhr);
$("#hostconfig_continue_err").html("<span class='errhint'> Error code: " + xhr.status + " </span>");
$("#hostconfig_continue_err").show();
},
check_partition: function() {
var tmp_percent = parseInt($("#tmp").val());
var var_percent = parseInt($("#var").val());
var home_percent = parseInt($("#home").val());
var total = tmp_percent + var_percent + home_percent;
var spare_percent = 100 - total;
$("#spare").val(spare_percent);
if (spare_percent < 30) {
$("#spare").addClass("error");
$(".errhint").show();
} else {
$("#spare").removeClass("error");
$(".errhint").hide();
}
},
'.integer keyup': function(el, ev) {
if($(el).val()) {
$(el).removeClass("error");
} else {
$(el).addClass("error");
}
this.check_partition();
},
'.hostconfig-back click': function(el, ev) {
this.options.nav.gobackStep("4");
return false;
},
show: function() {
this.element.show();
},
hide: function() {
this.element.hide();
}
});
});

View File

@ -0,0 +1,77 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>host_config Widget Unit Test</title>
<link rel="stylesheet" type="text/css" href="../../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../../css/style.css" />
</head>
<body>
<div class="container-fluid">
<div class="row-fluid">
<div id="host_config-test"> </div>
</div>
</div>
<script type='text/javascript' src='../../../steal/steal.js'></script>
<script type='text/javascript'>
steal('jquery/dom/route', 'ods/fixtures','ods/ui/host_config').then(function($) {
var config = [];
var server1 = {
clusterhost_id: 100,
hostname: "",
id: 10,
mac: "28:6e:31:47:c8:6c",
port: "1",
server_ip: "10.2.172.9",
switch_ip: "172.29.8.40",
vlan: "1"
};
var server2 = {
clusterhost_id: 100,
hostname: "",
id: 10,
mac: "28:6e:31:34:fd:28",
port: "2",
server_ip: "10.2.172.9",
switch_ip: "172.29.8.40",
vlan: "2"
};
if (config["172.29.8.40"] == undefined) {
config["172.29.8.40"] = [server1];
config["172.29.8.40"].push(server2);
} else {
config["172.29.8.40"].push(server1);
config["172.29.8.40"].push(server2);
}
var odsState = {
networking: null,
servers: [],
servers_config: null,
cluster_id: null,
security: null,
partition: null,
feature: null,
machines: [],
switches: [],
snmp: 1
};
var state = new $.Observe(odsState);
state.servers_config = config;
state.cluster_id = 1;
$('#host_config-test').ods_ui_host_config({ "odsState" : state });
});
</script>
</body>
</html>

View File

@ -0,0 +1,78 @@
<h2>Configure host names of the servers you just selected</h2>
<p>
Enter host names and IP addresses for each of the servers attached to the network switches and ports listed.
</p>
<div class="rounded" style="padding-top: 10; padding-bottom: 5px">
<div class="float_left">Switch IP</div>
<div class="float_right">
<a href="#" id="auto_fill" style="padding-right:20px">Auto-fill values</a>
<a href="#">Clear</a>
</div>
<div class="clear"> </div>
<div id="dialog-confirm" title="Auto fill values">
<p>
Host name pattern:
<select id="pattern">
<option>Switch IP</option>
<option>Switch alias</option>
<option>Host</option>
</select>
<span class="ui-icon ui-icon-info" style="float: right; margin: 6px 19px 4px 7px;" data-geo="info-ico">
</p>
</div>
<div class="">
<div class="float_left switch-navs" style="padding-top: 20px;">
</div>
<div class="rounded float_left server-panels">
<div id="tab1" class="tab_panel_active">
<table id="hostconfig-table">
<thead>
<tr>
<th>Port</th>
<th>Host name</th>
<th>IP address</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
<div class="clear"></div>
</div>
</div>
<br>
<div class="rounded partition-div" style="padding-top:10px;">
<p>
Logical Volume Partition (Total partition percentage should not exceed 100%)
</p>
<div class="float_left" style="width: 18%">
tmp: <input id="tmp" class="rounded integer non-empty-value" onkeypress="return isNumber(event)" value="10" style="width: 80px">%
</div>
<div class="float_left" style="width: 18%">
var: <input id="var" class="rounded integer non-empty-value" value="30" style="width: 80px">%
</div>
<div class="float_left" style="width: 18%">
home: <input id="home" class="rounded integer non-empty-value" value="20" style="width: 80px">%
</div>
<div class="float_left" style="width: 18%">
spare: <input id="spare" class="rounded" value="40" style="width: 80px; background-color: lightGrey" disabled="true">%
</div>
<div class="float_left" style="width: 28%">
<div class="errhint" style="display: none">
The spare value should be greater than 30%.
</div>
</div>
<div class="clear"></div>
</div>
<div class="continue"><center>
<a href="#" class="go-back hostconfig-back" >Go back</a>
<a href="/web/install_review/" class="btn_continue hostconfig-finish">Continue</a>
<img id="continuing" class="loading" src="../img/ajax_loader.gif" height="30px" width="30px"></img><br>
<div id="hostconfig_continue_err" style="display:none;padding-top:10px"></div>
</center></div>

View File

@ -0,0 +1,5 @@
<tr data-hostid="<%= clusterhost_id %>">
<td><%= port %></td>
<td><input class="rounded hostname non-empty-value" name="hostname" value="<%= hostname %>"></td>
<td><input class="rounded serverIp non-empty-value" name="serverIp" value="<%= server_ip %>"></td>
</tr>

View File

@ -0,0 +1,46 @@
.ui-progressbar {
position: relative;
}
.progress-label {
position: absolute;
font-size: 12px;
left: 5px;
top: -1px;
font-weight: bold;
text-shadow: 1px 1px 0 #fff;
width: 100%;
text-align: center;
z-index: 10;
}
.node {
cursor: pointer;
}
.node text {
font: 10px sans-serif;
}
.link {
fill: none;
stroke: #999;
stroke-width: 1.5px;
}
#progress-graph {
text-align: center;
}
.dashboard-link {
background-image: linear-gradient(to bottom, #8D92FB 0%, #3236A2 100%);
border: 1px solid #A0A0A0;
border-radius: 5px 5px 5px 5px;
color: #FFFFFF;
font-weight: bold;
padding: 3px 10px;
}
.dashboard-link:hover {
background-image: linear-gradient(to bottom, #3236A2 0%, #8D92FB 100%);
}
.dashboard-link.disabled {
background-image: none;
background-color: #8D92FB;
box-shadow: none;
cursor: default;
opacity: 0.65;
}

View File

@ -0,0 +1,64 @@
#tb_server_review {
background-color: rgb(255, 255, 255);
padding: 5px;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
}
#tb_server_select {
background-color: rgb(255, 255, 255);
padding: 5px;
}
#container {
width: 600px;
margin: 30px auto;
padding: 0;
}
table.display {
margin: 0 auto;
clear: both;
width: 100% !important;
}
table.display thead th {
padding: 3px 18px 3px 5px;
font-weight: bold;
cursor: pointer;
text-align: left;
}
.dataTables_filter {
width: 50%;
float: right;
text-align: right;
}
.dataTables_scrollHeadInner {
width: 100% !important;
background-color: rgb(255, 255, 255);
}
.dataTables_scrollHead {
border: 1px solid grey !important;
border-radius: 6px 6px 0px 0px;
-moz-border-radius: 6px 6px 0px 0px;
-webkit-border-radius: 6px 6px 0px 0px;
}
.dataTables_scrollBody {
border-left: 1px solid grey;
border-right: 1px solid grey;
border-bottom: 1px solid grey;
border-radius: 0px 0px 6px 6px;
-moz-border-radius: 0px 0px 6px 6px;
-webkit-border-radius: 0px 0px 6px 6px;
}
.highlight {
background: #C3C7DD;
}

View File

@ -0,0 +1,648 @@
steal(
'jquery/controller',
'jquery/view/ejs',
'jquery/controller/view'
).then(
'./views/init.ejs',
'./install_review.css',
'./views/install.ejs',
'./views/progress_row.ejs',
'ods/models/cluster.js',
'lib/jquery-ui-1.10.3.custom.css',
'lib/jquery.dataTables.js'
).then(
'lib/jquery-ui-1.10.3.custom.js',
'./install.css'
).then(
function($) {
$.Controller('Ods.Ui.install_review', {}, {
init: function() {
this.element.html(this.view('init'));
this.totalProgress = 0;
this.progressbarPendingCount = 0;
this.serverCount = 0;
this.initServerTable();
this.onSecurityData(this.options.odsState.security);
this.onNetworkingData(this.options.odsState.networking);
this.onLogicPartitionData(this.options.odsState.partition);
},
'.review-back click': function(el, ev) {
this.options.nav.gobackStep("5");
return false;
},
onLogicPartitionData: function(data) {
$("#tmp").html(data.tmp + "%");
$("#var").html(data.slashvar + "%");
$("#home").html(data.home + "%");
},
onSecurityData: function(data) {
var server_uname = data.server_credentials.username;
var service_uname = data.service_credentials.username;
var console_uname = data.console_credentials.username;
var server_pwd = data.server_credentials.password;
var service_pwd = data.service_credentials.password;
var console_pwd = data.console_credentials.password;
var server_pwd_len = server_pwd.length;
var service_pwd_len = service_pwd.length;
var console_pwd_len = console_pwd.length;
$("#server_uname").html(server_uname);
$("#service_uname").html(service_uname);
$("#console_uname").html(console_uname);
var temp = "";
for (i = 0; i < server_pwd_len; i++) {
temp += "*";
}
$("#server_pwd").html(temp);
temp = "";
for (i = 0; i < service_pwd_len; i++) {
temp += "*";
}
$("#service_pwd").html(temp);
temp = "";
for (i = 0; i < console_pwd_len; i++) {
temp += "*";
}
$("#console_pwd").html(temp);
},
onNetworkingData: function(data) {
$("#mgt_start").html(data.interfaces.management.ip_start);
$("#mgt_end").html(data.interfaces.management.ip_end);
$("#vnw_start").html(data.interfaces.tenant.ip_start);
$("#vnw_end").html(data.interfaces.tenant.ip_end);
$("#float_start").html(data.interfaces.public.ip_start);
$("#float_end").html(data.interfaces.public.ip_end);
$("#storage_start").html(data.interfaces.storage.ip_start);
$("#storage_end").html(data.interfaces.storage.ip_end);
},
initServerTable: function() {
this.dataTable = $('#tb_server_review').dataTable({
"sScrollY": "200px",
"bPaginate": false,
"bScrollCollapse": true,
"aoColumns": [{
"mData": "hostname"
}, {
"mData": "mac"
}, {
"mData": "server_ip"
}, {
"mData": "switch_ip"
}, {
"mData": "port"
}],
"aoColumnDefs": [{
bSortable: false,
aTargets: [0, 1, 2]
}],
"aaSorting": [
[3, "asc"],
[4, "asc"]
]
});
$('.dataTables_info').remove();
$('.dataTables_filter input').addClass('rounded');
this.dataTable.fnClearTable();
var serverData = this.options.odsState.servers_config;
for (var key in serverData) {
var servers = serverData[key];
for (var i = 0; i < servers.length; i++) {
this.dataTable.fnAddData(servers[i]);
}
}
},
'a.btn_continue click': function(el, ev) {
ev.preventDefault();
$("#continuing").css("opacity", 1);
var cluster_id = this.options.odsState.cluster_id;
Ods.Cluster.action(cluster_id, {
"deploy": ""
}, this.proxy('onTriggerDeploy'), this.proxy('onTriggerDeployErr'));
},
onTriggerDeploy: function(data, textStatus, xhr) {
steal.dev.log(" *** onTriggerDeploy data *** ", data);
steal.dev.log(" *** onTriggerDeploy textStatus *** ", textStatus);
steal.dev.log(" *** onTriggerDeploy xhr *** ", xhr);
if (xhr.status == 202) { // accepted
$("#continuing").css("opacity", 0);
this.element.html(this.view('install'));
$("#install_tabs").tabs();
this.initProgressbars();
}
},
onTriggerDeployErr: function(xhr, status, statusText) {
steal.dev.log(" *** onTriggerDeployErr xhr *** ", xhr);
steal.dev.log(" *** onTriggerDeployErr status *** ", status);
steal.dev.log(" *** onTriggerDeployErr statusText *** ", statusText);
},
initProgressbars: function() {
this.initTotalProgressbar();
this.serverTreeJson = {
"name": "Compass Server",
"type": "compass",
"children": []
};
for (var key in this.options.odsState.servers_config) {
var switchjson = {
"name": key,
"type": "switch",
"children": []
};
var servers = this.options.odsState.servers_config[key];
for (var i = 0; i < servers.length; i++) {
var serverjson = {
"name": servers[i].hostname,
"hostid": servers[i].clusterhost_id,
"type": "server",
"progress": 0,
"message": "Waiting..."
};
switchjson.children.push(serverjson);
// initiate list based progress bars
this.initListProgressbar(servers[i].clusterhost_id, servers[i].hostname);
}
this.serverTreeJson.children.push(switchjson);
}
// initiate graph based progress bars
this.initGraphProgressbars();
setTimeout(this.proxy('getProgressData'), 1000);
},
initTotalProgressbar: function() {
this.totalProgressbar = $('.totalProgressbar');
this.totalProgressbar.progressbar({
value: false
});
this.totalProgressLabel = this.totalProgressbar.children(".progress-label");
this.totalProgressbarValue = this.totalProgressbar.find(".ui-progressbar-value");
},
initListProgressbar: function(hostid, hostname) {
var initPData = {
"hostname": hostname,
"hostid": hostid,
"message": "Waiting..."
}
$("#tabs-2 table tbody").append(this.view('progress_row', initPData));
var pbar = $('div[data-hostid="' + hostid + '"]');
pbar.progressbar({
value: false
});
},
getProgressData: function() {
if (this.progressbarPendingCount == 0) {
this.serverCount = 0;
}
var serverData = this.options.odsState.servers_config;
for (var key in serverData) {
var servers = serverData[key];
for (var i = 0; i < servers.length; i++) {
Ods.ClusterHost.progress(servers[i].clusterhost_id, this.proxy('updateProgressBar'), this.proxy('updateProgressBarErr'));
this.serverCount++;
}
}
this.progressbarPendingCount = this.serverCount;
},
/********************************************/
// get clusterhost progress success callback
/********************************************/
updateProgressBar: function(data, textStatus, xhr) {
steal.dev.log(" *** onUpdateProgressBar data *** ", data);
steal.dev.log(" *** onUpdateProgressBar textStatus *** ", textStatus);
steal.dev.log(" *** onUpdateProgressBar xhr *** ", xhr);
var progressData = data.progress;
this.progressbarPendingCount--;
// update progress data in serverTreeJson
for (var sw in this.serverTreeJson.children) {
var servers = this.serverTreeJson.children[sw]._children;
if (servers == null) {
servers = this.serverTreeJson.children[sw].children;
}
for (var i = 0; i < servers.length; i++) {
if (servers[i].hostid == progressData.id) {
servers[i].progress = progressData.percentage;
servers[i].message = progressData.message;
}
}
}
// update graph-based progress bar
this.updateGraphBar(progressData);
// update list-based progress bar
this.updateListBar(progressData);
// update total progress bar
this.updateTotalBar(progressData);
},
/********************************************/
// get clusterhost progress error callback
/********************************************/
updateProgressBarErr: function(xhr, status, statusText) {
steal.dev.log(" *** updateProgressBarErr xhr *** ", xhr);
steal.dev.log(" *** updateProgressBarErr status *** ", status);
steal.dev.log(" *** updateProgressBarErr statusText *** ", xhr);
//TODO
},
updateGraphBar: function(progressData) {
// update graph-based progress bar
if ($('rect[data-hostid="' + progressData.id + '"]')) { // check if the node is expanded
if (progressData.percentage > 1.0) {
progressData.percentage = 1.0;
}
$('rect[data-hostid="' + progressData.id + '"]').attr("width", imgWidth * progressData.percentage);
$('text[data-hostid="' + progressData.id + '"]').text(progressData.message);
}
},
updateListBar: function(progressData) {
var pbar = $('div[data-hostid="' + progressData.id + '"]');
var progressLabel = pbar.children(".progress-label");
var progressbarValue = pbar.find(".ui-progressbar-value");
// update list-based progress bar
if (pbar.is(":visible")) {
progressbarValue.css({
"width": progressData.percentage * pbar.width()
});
progressLabel.text(progressData.message);
progressbarValue.css({
"opacity": "0.8"
});
if (progressData.severity == "WARNING") {
progressbarValue.css({
"background": "#FAA732"
});
} else if (progressData.severity == "ERROR") {
progressbarValue.css({
"background": "#BD362F"
});
} else {
progressbarValue.css({
"background": "#49AFCD"
});
}
if (progressData.percentage >= 1.0) {
progressLabel.text("Completed!");
pbar.progressbar("value", 100);
progressbarValue.css({
"background": "#5BB75B"
});
} else {
pbar.progressbar("value", progressData.percentage * 100)
}
}
},
updateTotalBar: function(data) {
if (this.progressbarPendingCount == 0) {
Ods.Cluster.progress(this.options.odsState.cluster_id, this.proxy('onTotalProgressData'), this.proxy('onTotalProgressDataErr'));
}
},
/********************************************/
// get cluster total progress success callback
/********************************************/
onTotalProgressData: function(data, textStatus, xhr) {
steal.dev.log(" *** onTotalProgressData data *** ", data);
steal.dev.log(" *** onTotalProgressData textStatus *** ", textStatus);
steal.dev.log(" *** onTotalProgressData xhr *** ", xhr);
var total = data.progress.percentage;
this.totalProgressbarValue.css({
"background": "#0000ff",
"opacity": 0.5
});
this.totalProgressLabel.text(total * 100 + "%");
this.totalProgressbarValue.css({
"width": total * this.totalProgressbar.width()
});
if (total < 1) {
setTimeout(this.proxy('getProgressData'), 3000);
} else {
this.totalProgressbar.progressbar("value", 100);
Ods.DashboardLink.findOne(this.options.odsState.cluster_id, this.proxy('onFindDashboardLink'));
}
},
/********************************************/
// get cluster total progress error callback
/********************************************/
onTotalProgressDataErr: function(xhr, status, statusText) {
steal.dev.log(" *** onTotalProgressDataErr xhr *** ", xhr);
steal.dev.log(" *** onTotalProgressDataErr status *** ", status);
steal.dev.log(" *** onTotalProgressDataErr statusText *** ", xhr);
//TODO
},
onFindDashboardLink: function(data, textStatus, xhr) {
steal.dev.log(" *** onFindDashboardLink data *** ", data);
steal.dev.log(" *** onFindDashboardLink textStatus *** ", textStatus);
steal.dev.log(" *** onFindDashboardLink xhr *** ", xhr);
if (data.status == "OK") {
$(".dashboard-link").attr("href", data.dashboardlinks["os-single-controller"]);
$(".dashboard-link").attr("target", "_blank");
$(".dashboard-link").removeClass("disabled");
}
},
'.ui-tabs-nav click': function(el, ev) {
if ($("#tabs-2").is(":visible")) {
for (var sw in this.serverTreeJson.children) {
var servers = this.serverTreeJson.children[sw]._children;
if (servers == null) {
servers = this.serverTreeJson.children[sw].children;
}
for (var i = 0; i < servers.length; i++) {
var data = {
"hostname": servers[i].name,
"id": servers[i].hostid,
"percentage": servers[i].progress,
"message": servers[i].message
};
this.updateListBar(data);
}
}
}
},
initGraphProgressbars: function() {
var margin = {
top: 0,
right: 120,
bottom: 0,
left: 130
},
width = 1000 - margin.right - margin.left,
height = 500 - margin.top - margin.bottom;
imgWidth = 163;
imgHeight = 32;
var i = 0,
duration = 750,
root;
var tree = d3.layout.tree()
.size([height, width]);
var diagonal = d3.svg.diagonal()
.projection(function(d) {
return [d.y, d.x];
});
var svg = d3.select("#progress-graph").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
root = this.serverTreeJson;
root.x0 = height / 2;
root.y0 = 0;
update(root);
d3.select(self.frameElement).style("height", "600px");
function update(source) {
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);
// Normalize for fixed-depth.
nodes.forEach(function(d) {
d.y = d.depth * 300;
});
// Update the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function(d) {
return d.id || (d.id = ++i);
});
// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
var transX = parseFloat(source.y0) - 10;
var transY = parseFloat(source.x0) - imgHeight / 2;
return "translate(" + transX + "," + transY + ")";
})
.attr("width", imgWidth)
.attr("height", imgHeight)
.on("click", click);
nodeEnter.append("image")
.attr("xlink:href", function(d) {
if (d.type == "compass")
return "../img/router.png";
else if (d.type == "switch")
return "../img/switch.png";
else
return "../img/server.png";
})
.attr("class", function(d) {
return d.type;
})
.attr("width", imgWidth)
.attr("height", imgHeight);
nodeEnter.append("rect")
.attr("width", function(d) {
if (d.type == "server") {
return imgWidth * d.progress;
} else {
return 0;
}
})
.attr("height", imgHeight)
.attr("data-hostid", function(d) {
return d.hostid;
})
.style("fill", "blue")
.style("opacity", function(d) {
if (d.type == "server")
return 0.4;
else
return 0;
});
nodeEnter.append("text")
.attr("x", function(d) {
if (d.type == "compass")
return -5;
else
return d.children || d._children ? -8 : imgWidth + 10;
})
.attr("y", function(d) {
if (d.type == "compass")
return imgHeight / 2;
else if (d.type == "switch")
return 6;
else
return imgHeight / 2;
})
.attr("dy", ".25em")
.attr("text-anchor", function(d) {
return d.children || d._children ? "end" : "start";
})
.text(function(d) {
return d.name;
})
.style("font-size", "15px")
.style("fill-opacity", 1e-6);
nodeEnter.append("text")
.attr("x", 0)
.attr("y", 45)
.attr("dy", ".25em")
.attr("data-hostid", function(d) {
return d.hostid;
})
.text(function(d) {
if (d.type == "server")
return d.message;
else
return null;
})
.style("font-size", "12px");
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) {
var transX = parseFloat(d.y) - 10;
var transY = parseFloat(d.x) - imgHeight / 2;
return "translate(" + transX + "," + transY + ")";
});
nodeUpdate.select("text")
.style("fill-opacity", 1);
// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) {
var transX = parseFloat(source.y) - 10;
var transY = parseFloat(source.x) - imgHeight / 2;
return "translate(" + transX + "," + transY + ")";
})
.remove();
nodeExit.select("circle")
.attr("r", 1e-6);
nodeExit.select("text")
.style("fill-opacity", 1e-6);
// Update the links…
var link = svg.selectAll("path.link")
.data(links, function(d) {
return d.target.id;
});
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {
x: source.x0,
y: source.y0
};
return diagonal({
source: o,
target: o
});
});
// Transition links to their new position.
link.transition()
.duration(duration)
.attr("d", diagonal);
// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr("d", function(d) {
var o = {
x: source.x,
y: source.y
};
return diagonal({
source: o,
target: o
});
})
.remove();
// Stash the old positions for transition.
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
// Toggle children on click.
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update(d);
}
},
show: function() {
this.element.show();
},
hide: function() {
this.element.hide();
}
});
});

View File

@ -0,0 +1,79 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>install_review Widget Unit Test</title>
<link rel="stylesheet" type="text/css" href="../../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../../css/style.css" />
</head>
<body>
<div class="container-fluid">
<div class="row-fluid">
<div id="install_review-test"> </div>
</div>
</div>
<script type='text/javascript' src='../../../steal/steal.js'></script>
<script type='text/javascript' src='../../../lib/d3.min.js'></script>
<script type='text/javascript'>
steal('jquery/dom/route', 'ods/fixtures', 'ods/ui/install_review').then(function($) {
var config = [];
var server1 = {
clusterhost_id: 100,
hostname: "server01",
id: 10,
mac: "28:6e:31:47:c8:6c",
port: "1",
server_ip: "10.2.172.9",
switch_ip: "172.29.8.40",
vlan: "1"
};
var server2 = {
clusterhost_id: 200,
hostname: "server02",
id: 20,
mac: "28:6e:31:34:fd:28",
port: "2",
server_ip: "10.2.172.9",
switch_ip: "172.29.8.40",
vlan: "2"
};
if (config["172.29.8.40"] == undefined) {
config["172.29.8.40"] = [server1];
config["172.29.8.40"].push(server2);
} else {
config["172.29.8.40"].push(server1);
config["172.29.8.40"].push(server2);
}
var odsState = {
networking: null,
servers: [],
servers_config: null,
cluster_id: null,
security: null,
partition: null,
feature: null,
machines: [],
switches: [],
snmp: 1
};
var state = new $.Observe(odsState);
state.servers_config = config;
state.cluster_id = 1;
$('#install_review-test').ods_ui_install_review({ "odsState" : state });
});
</script>
</body>
</html>

View File

@ -0,0 +1,90 @@
<h2>Ready to deploy OpenStack</h2>
<p style="margin: 0; padding-left: 20px;">Review the configuration shown above and if corrent, click deploy to begin the OpenStack deployment.</p>
<div class="left-side">
<div class="inside">
<h3>IP Pool</h3>
<div class="rounded" style="padding-top: 5px; padding-bottom: 8px;">
<table>
<thead>
<tr>
<th>Network IP range</th>
<th>Start</th>
<th>End</th>
</tr>
</thead>
<tbody>
<tr>
<td>Management</td>
<td id="mgt_start"></td>
<td id="mgt_end"></td>
</tr>
<tr>
<td>Tenant</td>
<td id="vnw_start"></td>
<td id="vnw_end"></td>
</tr>
<tr>
<td>Public</td>
<td id="float_start"></td>
<td id="float_end"></td>
</tr>
<tr>
<td>Storage</td>
<td id="storage_start"></td>
<td id="storage_end"></td>
</tr>
</tbody>
</table>
</div>
<h3>Logical Volume Partition</h3>
<div class="rounded" style="padding-top: 8px; padding-bottom: 5px;">
<div class="float_left" style="padding-right:20px">tmp: <span id="tmp"></span></div>
<div class="float_left" style="padding-right:20px">var: <span id="var"></span></div>
<div class="float_left" style="padding-right:20px">home: <span id="home"></span></div>
<div class="clear"></div>
</div>
<h3>System Credentials </h3>
<div class="rounded" style="padding-top: 0; padding-bottom: 5px;">
<table>
<tr>
<th colspan="2" style="width:33%">Hypervisor</th>
<th colspan="2" style="width:33%">OpenStack Services</th>
<th colspan="2" style="width:33%">OpenStack Management Console</th>
</tr>
<tr>
<td>User name: </td><td id="server_uname"></td>
<td>User name: </td><td id="service_uname"></td>
<td>User name: </td><td id="console_uname"></td>
</tr>
<tr>
<td>Password: </td><td id="server_pwd"></td>
<td>Password: </td><td id="service_pwd"></td>
<td>Password: </td><td id="console_pwd"></td>
</tr>
</table>
</div>
</div>
</div>
<div class="right-side">
<h3>OpenStack Servers</h3>
<div class="">
<table id="tb_server_review" cellpadding="0" cellspacing="0" border="0" class="display">
<thead>
<tr>
<th>Host name</th>
<th>MAC Addr</th>
<th>Server IP</th>
<th>Switch IP</th>
<th>Port</th>
</tr>
</thead>
<tbody> </tbody>
</table>
</div>
</div>
<div class="clear"></div>
<div class="continue"><center>
<a href="#" class="go-back review-back" >Go back</a>
<a href="/web/install/" class="btn_continue">Deploy</a>
<img id="continuing" class="loading" src="../img/ajax_loader.gif" height="30px" width="30px"></img>
</center></div>

View File

@ -0,0 +1,46 @@
<h2>Deploying OpenStack</h2>
<p style="padding-left: 30px; color: black;">Compass is deploying OpenStack onto the servers, and configuring them for use with the following features: <span style="color: #990000; margin-top: -5px; font-weight: bold;">Core virtualization, <span style="opacity:0.3">Live Migration, High Availability</span></span> </p>
<p style="padding-left: 30px; color: black;">Click <a class="dashboard-link disabled">here</a> to go to OpenStack dashboard when deployment is finished.</p>
<div id="install_tabs" style="margin-left: 45px;">
<ul>
<li><a href="#tabs-1">Graph</a></li>
<li><a href="#tabs-2">List</a></li>
</ul>
<div id="tabs-1" class="graph">
<div id="progress-graph">
</div>
</div>
<div id="tabs-2" class="list"><center>
<table id="progress-list" style="width:80%">
<tbody>
</tbody>
</table>
</center></div>
</div>
<br>
<div class="rounded" style="margin-left: 45px;"><center>
<table style="width:80%">
<tbody>
<tr>
<td style="width: 20%;">Total Progress:</td>
<td style="width: 70%;">
<div class="totalProgressbar float_left" style="width:100%; height: 20px; border: 1px solid #aaaaaa;">
<div class="progress-label">Waiting...</div>
<!--<div id="total_percentage" style="position: absolute; z-index: 5; margin-left: 390px;"></div>
<div id="total_bar" style="width:0%; height: 100%; background: #0000ff; opacity: 0.5;"></div>-->
</div>
</td>
<td style="font-size: 13px; font-weight: bold;">&nbsp;&nbsp;Errors: 0</td>
</tr>
</tbody>
</table>
</center></div>
<div class="clear"></div>

View File

@ -0,0 +1,9 @@
<tr name="<%= hostname%>">
<td style="width: 20%;"> <%= hostname %> </td>
<td style="width: 70%;">
<div data-hostid="<%= hostid %>" class="center_gradient server_progress">
<div class="server-progress-label progress-label"> <%= message %> </div>
</div>
</td>
<td><!--<img src="../img/info_icon_16px.png"></img>--></td>
</tr>

127
public/ods/ui/nav/nav.js Normal file
View File

@ -0,0 +1,127 @@
steal(
'jquery/controller',
'jquery/view/ejs',
'jquery/controller/view'
).then(
'ods/ui/welcome',
'ods/ui/features',
'ods/ui/servers',
'ods/ui/security',
'ods/ui/networking',
'ods/ui/host_config',
'ods/ui/install_review',
'./views/init.ejs'
).then(function($) {
$.Controller('Ods.Ui.nav', {}, {
init: function() {
this.element.html(this.view('init'));
this.steps = this.element.find("ul li span");
this.fixupContentSize();
},
gotoStep: function(step) {
var that = this;
$.each(this.steps, function(index, value) {
var el = $(value);
var s = el.data("step");
if (step == s) {
el.removeClass("inactive");
el.addClass("active");
return false;
} else {
el.addClass("passed");
el.removeClass("active");
}
});
var options = {
nav: this,
odsState: this.options.odsState,
mainBox: this.options.mainBox
};
if (step === "1") {
this.options.mainBox.ods_ui_welcome("destroy");
this.options.mainBox.ods_ui_features(options);
} else if (step === "2") {
this.options.mainBox.ods_ui_features("destroy");
this.options.mainBox.ods_ui_servers(options);
} else if (step == "3") {
this.options.mainBox.ods_ui_servers("destroy");
this.options.mainBox.ods_ui_security(options);
} else if (step == "4") {
this.options.mainBox.ods_ui_security("destroy");
this.options.mainBox.ods_ui_networking(options);
} else if (step == "5") {
this.options.mainBox.ods_ui_networking("destroy");
this.options.mainBox.ods_ui_host_config(options);
} else if (step == "6") {
this.options.mainBox.ods_ui_host_config("destroy");
this.options.mainBox.ods_ui_install_review(options);
}
},
gobackStep: function(step) {
var that = this;
$.each(this.steps, function(index, value) {
var el = $(value);
var s = el.data("step");
if (step == s) {
el.removeClass("passed");
el.addClass("active");
} else {
if (el.hasClass("active")) {
el.removeClass("active");
el.addClass("inactive");
}
}
});
var options = {
nav: this,
odsState: this.options.odsState,
mainBox: this.options.mainBox
};
if (step === "1") {
this.options.mainBox.ods_ui_servers("destroy");
this.options.mainBox.ods_ui_features(options);
} else if (step === "2") {
this.options.mainBox.ods_ui_security("destroy");
this.options.mainBox.ods_ui_servers(options);
} else if (step == "3") {
this.options.mainBox.ods_ui_networking("destroy");
this.options.mainBox.ods_ui_security(options);
} else if (step == "4") {
this.options.mainBox.ods_ui_host_config("destroy");
this.options.mainBox.ods_ui_networking(options);
} else if (step == "5") {
this.options.mainBox.ods_ui_install_review("destroy");
this.options.mainBox.ods_ui_host_config(options);
}
},
fixupContentSize: function() {
var header_height = $('#header').outerHeight();
var menu_height = $('#menu').outerHeight();
var footer_height = $('#footer').outerHeight();
var window_height = $(window).outerHeight();
var content_height = window_height - header_height - menu_height - footer_height;
if (content_height > 200) {
$('#content').height(content_height);
}
},
'{window} resize': function(ev) {
this.fixupContentSize();
},
show: function() {
this.element.show();
},
hide: function() {
this.element.hide();
}
});
});

View File

@ -0,0 +1,9 @@
<ul>
<li><span class="active" data-step="welcome">Welcome</span></li>
<li><span class="inactive" data-step="1">1. Features</span></li>
<li><span class="inactive" data-step="2">2. Servers</span></li>
<li><span class="inactive" data-step="3">3. Security</span></li>
<li><span class="inactive" data-step="4">4. Networking</span></li>
<li><span class="inactive" data-step="5">5. Host Configuration</span></li>
<li><span class="inactive" data-step="6">6. Deploy</span></li>
</ul>

View File

@ -0,0 +1,43 @@
#tabs {
border: 0px;
}
.ui-tabs-vertical {
width: 100%;
}
.ui-tabs-vertical .ui-tabs-nav {
padding: .2em .1em .2em .2em;
float: left;
width: 15%;
}
.ui-tabs-vertical .ui-tabs-nav li {
clear: left;
width: 100%;
border-bottom-width: 1px !important;
border-right-width: 0 !important;
margin: 0 -1px .2em 0;
}
.ui-tabs-vertical .ui-tabs-nav li a {
display:block;
}
.ui-tabs-vertical .ui-tabs-nav li.ui-tabs-active {
padding-bottom: 0;
padding-right: .1em;
border-right-width: 1px;
border-right-width: 1px;
}
.ui-tabs-vertical .ui-tabs-panel {
padding: 1em;
float: left;
width: 80%;
}
.nicHint {
padding-left: 10px;
padding-top: 3px;
}

View File

@ -0,0 +1,396 @@
steal(
'jquery/controller',
'jquery/view/ejs',
'jquery/controller/view'
).then(
'./networking.css',
'./views/init.ejs',
'ods/models/cluster.js',
'lib/jquery-ui-1.10.3.custom.css',
'lib/jquery-ui-1.10.3.custom.js'
).then(function($) {
$.Controller('Ods.Ui.networking', {}, {
init: function() {
this.element.html(this.view('init'));
this.initAccordion();
this.nicErr = 0;
this.prefillNetworking();
},
prefillNetworking: function() {
var oldNetworkingData = this.options.odsState.networking;
if (oldNetworkingData) {
$("#global_nameservers").val(oldNetworkingData.global.nameservers);
$("#global_searchpath").val(oldNetworkingData.global.search_path);
$("#global_gateway").val(oldNetworkingData.global.gateway);
$("#global_proxy").val(oldNetworkingData.global.proxy);
$("#global_ntpserver").val(oldNetworkingData.global.ntp_server);
$("#mgt_ip_start").val(oldNetworkingData.interfaces.management.ip_start);
$("#mgt_ip_end").val(oldNetworkingData.interfaces.management.ip_end);
$("#mgt_netmask").val(oldNetworkingData.interfaces.management.netmask);
$("#mgt_gateway").val(oldNetworkingData.interfaces.management.gateway);
$("#mgt_nic").val(oldNetworkingData.interfaces.management.nic);
$("#mgt_promisc").prop("checked", oldNetworkingData.interfaces.management.promisc ? true : false);
$("#vnw_ip_start").val(oldNetworkingData.interfaces.tenant.ip_start);
$("#vnw_ip_end").val(oldNetworkingData.interfaces.tenant.ip_end);
$("#vnw_netmask").val(oldNetworkingData.interfaces.tenant.netmask);
$("#vnw_gateway").val(oldNetworkingData.interfaces.tenant.gateway);
$("#vnw_nic").val(oldNetworkingData.interfaces.tenant.nic);
$("#vnw_promisc").prop("checked", oldNetworkingData.interfaces.tenant.promisc ? true : false);
$("#float_ip_start").val(oldNetworkingData.interfaces.public.ip_start);
$("#float_ip_end").val(oldNetworkingData.interfaces.public.ip_end);
$("#float_netmask").val(oldNetworkingData.interfaces.public.netmask);
$("#float_gateway").val(oldNetworkingData.interfaces.public.gateway);
$("#float_nic").val(oldNetworkingData.interfaces.public.nic);
$("#float_promisc").prop("checked", oldNetworkingData.interfaces.public.promisc ? true : false);
$("#storage_ip_start").val(oldNetworkingData.interfaces.storage.ip_start);
$("#storage_ip_end").val(oldNetworkingData.interfaces.storage.ip_end);
$("#storage_netmask").val(oldNetworkingData.interfaces.storage.netmask);
$("#storage_gateway").val(oldNetworkingData.interfaces.storage.gateway);
$("#storage_nic").val(oldNetworkingData.interfaces.storage.nic);
$("#storage_promisc").prop("checked", oldNetworkingData.interfaces.storage.promisc ? true : false);
}
},
initAccordion: function() {
this.accordion = $("#accordion").accordion({
collapsible: true,
heightStyle: "content"
});
$("#tabs").tabs().addClass("ui-tabs-vertical ui-helper-clearfix");
$("#tabs li").removeClass("ui-corner-top").addClass("ui-corner-left");
},
checkNonEmpty: function(el) {
var value = el.val();
if (!value) {
el.addClass('error');
return false;
}
return true;
},
'.networking-finish click': function(el, ev) {
ev.preventDefault();
var self = this;
var hasError = false;
// remove the error class within the el
$('#accordion').find('.error').removeClass('error');
// return if any required input is empty
$('#accordion').find('.non-empty-value').each(function(index, value) {
if (!self.checkNonEmpty($(value))) {
hasError = true;
}
});
if (hasError) {
return;
}
//global section
var global_nameservers = $("#global_nameservers").val();
var global_searchpath = $("#global_searchpath").val();
var global_gateway = $("#global_gateway").val();
var global_proxy = $("#global_proxy").val();
var global_ntpserver = $("#global_ntpserver").val();
//management section
var mgt_ipstart = $("#mgt_ip_start").val();
var mgt_ipend = $("#mgt_ip_end").val();
var mgt_netmask = $("#mgt_netmask").val();
var mgt_gateway = $("#mgt_gateway").val();
var mgt_nic = $("#mgt_nic").val();
var mgt_promisc = $("#mgt_promisc").attr("checked") ? 1 : 0;
//tenant networks section
var tenant_ipstart = $("#vnw_ip_start").val();
var tenant_ipend = $("#vnw_ip_end").val();
var tenant_netmask = $("#vnw_netmask").val();
var tenant_gateway = $("#vnw_gateway").val();
var tenant_nic = $("#vnw_nic").val();
var tenant_promisc = $("#vnw_promisc").attr("checked") ? 1 : 0;
//public ip range section
var public_ipstart = $("#float_ip_start").val();
var public_ipend = $("#float_ip_end").val();
var public_netmask = $("#float_netmask").val();
var public_gateway = $("#float_gateway").val();
var public_nic = $("#float_nic").val();
var public_promisc = $("#float_promisc").attr("checked") ? 1 : 0;
//storage ip range section
var storage_ipstart = $("#storage_ip_start").val();
var storage_ipend = $("#storage_ip_end").val();
var storage_netmask = $("#storage_netmask").val();
var storage_gateway = $("#storage_gateway").val();
var storage_nic = $("#storage_nic").val();
var storage_promisc = $("#storage_promisc").attr("checked") ? 1 : 0;
// verify IP range
if (!$(".ipaddress").hasClass("error") && this.nicErr == 0) {
this.verifyIpRange(mgt_ipstart, mgt_ipend, this.options.odsState.servers.length);
if (!this.ipRangeValid) {
alert("The management IP range is not valid.");
} else {
// config server ip
var server_count = this.options.odsState.servers.length;
this.serverData = [];
var oldConfigData = this.options.odsState.servers_config;
var isConfiged = false;
for (var key in oldConfigData) {
var servers = oldConfigData[key];
for (var i = 0; i < servers.length; i++) {
isConfiged = true;
}
}
for (var i = 0; i < server_count; i++) {
var server = this.options.odsState.servers[i];
if (!isConfiged) {
server['hostname'] = '';
}
server['server_ip'] = this.startPrefix + (parseInt(this.startLastDigit) + i);
var switchIp = server.switch_ip;
if (this.serverData[switchIp] == undefined) {
this.serverData[switchIp] = [server];
} else {
this.serverData[switchIp].push(server);
}
}
this.options.odsState.servers_config = this.serverData;
var networkingData = {
"networking": {
"interfaces": {
"management": {
"ip_start": mgt_ipstart,
"ip_end": mgt_ipend,
"netmask": mgt_netmask,
"gateway": mgt_gateway,
"nic": mgt_nic,
"promisc": mgt_promisc
},
"tenant": {
"ip_start": tenant_ipstart,
"ip_end": tenant_ipend,
"netmask": tenant_netmask,
"gateway": tenant_gateway,
"nic": tenant_nic,
"promisc": tenant_promisc
},
"public": {
"ip_start": public_ipstart,
"ip_end": public_ipend,
"netmask": public_netmask,
"gateway": public_gateway,
"nic": public_nic,
"promisc": public_promisc
},
"storage": {
"ip_start": storage_ipstart,
"ip_end": storage_ipend,
"netmask": storage_netmask,
"gateway": storage_gateway,
"nic": storage_nic,
"promisc": storage_promisc
}
},
"global": {
"nameservers": global_nameservers,
"search_path": global_searchpath,
"gateway": global_gateway,
"proxy": global_proxy,
"ntp_server": global_ntpserver
}
}
};
this.options.odsState.networking = networkingData.networking;
$("#continuing").css("opacity", 1);
Ods.Cluster.update(this.options.odsState.cluster_id, networkingData, "networking", this.proxy('onNetworkingAdded'), this.proxy('onNetworkingAddedErr'));
}
}
},
/************************************************/
// cluster update (networking) success callback
/************************************************/
onNetworkingAdded: function(data, textStatus, xhr) {
steal.dev.log(" *** onNetworkingAdded data *** ", data);
steal.dev.log(" *** onNetworkingAdded textStatus *** ", textStatus);
steal.dev.log(" *** onNetworkingAdded xhr *** ", xhr);
$("#networking_continue_err").hide();
if (xhr.status == 200) {
$("#continuing").css("opacity", 0);
this.options.nav.gotoStep("5");
}
},
/************************************************/
// cluster update (networking) error callback
/************************************************/
onNetworkingAddedErr: function(xhr, status, statusText) {
steal.dev.log(" *** onNetworkingAddedErr xhr *** ", xhr);
steal.dev.log(" *** onNetworkingAddedErr status *** ", status);
steal.dev.log(" *** onNetworkingAddedErr statusText *** ", xhr);
$("#continuing").css("opacity", 0);
if (xhr.status == 400) { // bad request
var errMessage = JSON.parse(xhr.responseText).message;
$("#networking_continue_err").html("<span class='errhint'>" + errMessage + "</span>");
$("#networking_continue_err").show();
} else if (xhr.status == 500) {
$("#networking_continue_err").html("<span class='errhint'>Error code: 500</span>");
$("#networking_continue_err").show();
}
},
'.nic change': function(el, ev) {
var management_nic = $("#mgt_nic").val();
var tenant_nic = $("#vnw_nic").val();
var public_nic = $("#float_nic").val();
var storage_nic = $("#storage_nic").val();
var nicVals = [public_nic, management_nic, tenant_nic, storage_nic];
var nicConflicts = [0, 0, 0, 0];
for (var i = 1; i < nicVals.length; i++) {
if (nicVals[i] == nicVals[0]) {
nicConflicts[i] = 1;
nicConflicts[0] = 1;
}
}
var okHint = "<img src='../img/green_check_16px.png'></img>";
this.nicErr = 0;
if (nicConflicts[0] == 1) {
this.nicErr = 1;
$("#float_nic_err").html("<span class='errhint'>Public network cannot share nic with any other network. Please choose another one.</span>");
} else {
$("#float_nic_err").html(okHint);
}
if (nicConflicts[1] == 1) {
this.nicErr = 1;
$("#mgt_nic_err").html("<span class='errhint'>Management network cannot share nic with public network. Please choose another one.</span>");
} else {
$("#mgt_nic_err").html(okHint);
}
if (nicConflicts[2] == 1) {
this.nicErr = 1;
$("#vnw_nic_err").html("<span class='errhint'>Tenant network cannot share nic with any other network. Please choose another one.</span>");
} else {
$("#vnw_nic_err").html(okHint);
}
if (nicConflicts[3] == 1) {
this.nicErr = 1;
$("#storage_nic_err").html("<span class='errhint'>Storage network cannot share nic with public network. Please choose another one.</span>");
} else {
$("#storage_nic_err").html(okHint);
}
},
'#mgt_ip_end focus': function(el, ev) {
ev.preventDefault();
this.autofillIpRange($("#mgt_ip_start"), $("#mgt_ip_end"));
},
'#vnw_ip_end focus': function(el, ev) {
ev.preventDefault();
this.autofillIpRange($("#vnw_ip_start"), $("#vnw_ip_end"));
},
'#float_ip_end focus': function(el, ev) {
ev.preventDefault();
this.autofillIpRange($("#float_ip_start"), $("#float_ip_end"));
},
'#storage_ip_end focus': function(el, ev) {
ev.preventDefault();
this.autofillIpRange($("#storage_ip_start"), $("#storage_ip_end"));
},
autofillIpRange: function(elStart, elEnd) {
if (elStart.hasClass("error")) {
return;
}
var lastDotIndex = elStart.val().lastIndexOf(".");
var IpPrefix = elStart.val().substring(0, lastDotIndex + 1);
var IpEndVal = IpPrefix + "255";
elEnd.val(IpEndVal);
var len = IpEndVal.length;
elEnd[0].setSelectionRange(lastDotIndex + 1, len);
},
verifyIpRange: function(start, end, minCount) {
this.ipRangeValid = false;
var rindex = start.lastIndexOf('.') + 1;
this.startPrefix = start.substring(0, rindex);
this.endPrefix = end.substring(0, rindex);
this.startLastDigit = start.substring(rindex);
this.endLastDigit = end.substring(rindex);
if (this.startPrefix != this.endPrefix) {
this.ipRangeValid = false;
} else if (parseInt(this.endLastDigit) - parseInt(this.startLastDigit) < minCount) {
this.ipRangeValid = false;
} else {
this.ipRangeValid = true;
}
},
'input.ipaddress keyup': function(el, ev) {
var isValid = this.validateIpFormat(el.val());
if (!isValid) {
el.addClass("error");
} else {
el.removeClass("error");
}
},
validateIpFormat: function(value) {
var ipformat = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
if (value.match(ipformat)) {
return true;
} else {
return false;
}
},
'.networking-back click': function(el, ev) {
this.options.nav.gobackStep("3");
return false;
},
show: function() {
this.element.show();
},
hide: function() {
this.element.hide();
}
});
});

View File

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>networking Widget Unit Test</title>
<link rel="stylesheet" type="text/css" href="../../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../../css/style.css" />
</head>
<body>
<div class="container-fluid">
<div class="row-fluid">
<div id="networking-test"> </div>
</div>
</div>
<script type='text/javascript' src='../../../steal/steal.js'></script>
<script type='text/javascript'>
steal('jquery/dom/route', 'ods/fixtures','ods/ui/networking').then(function($) {
var odsState = {
networking: null,
servers: [],
servers_config: null,
cluster_id: null,
security: null,
partition: null,
feature: null,
machines: [],
switches: [],
snmp: 1
};
var state = new $.Observe(odsState);
state.cluster_id = 1;
$('#networking-test').ods_ui_networking({ "odsState" : state });
});
</script>
</body>
</html>

View File

@ -0,0 +1,180 @@
<h2>Specify network addresses you want to use for your OpenStack servers</h2>
<p>Provide static network addresses needed to facilitate the OpenStack cluster</p>
<div id="accordion">
<div>Management Network</div>
<div>
<table>
<tr>
<td>IP Range</td>
<td><input id="mgt_ip_start" type="input" class="rounded ipaddress non-empty-value" placeholder="start" value=""><input id="mgt_ip_end" type="input" class="rounded ipaddress non-empty-value" placeholder="end" value=""></td>
</tr>
<tr>
<td>Netmask</td>
<td><input id="mgt_netmask" type="input" class="rounded non-empty-value" value=""></td>
</tr>
<tr>
<td>Gateway (optional)</td>
<td><input id="mgt_gateway" type="input" class="rounded" value=""></td>
</tr>
<tr>
<td>NIC</td>
<td>
<select id="mgt_nic" class="nic float_left">
<option selected>eth0</option>
<option>eth1</option>
<option>eth2</option>
<option>eth3</option>
<option>eth4</option>
</select>
<div id="mgt_nic_err" class="nicHint float_left"></div>
</td>
</tr>
<tr>
<td>Promisc Mode</td>
<td><input id="mgt_promisc" type="checkbox"></td>
</tr>
</table>
</div>
<div>Tenant Network</div>
<div>
<table>
<tr>
<td>IP Range</td>
<td><input id="vnw_ip_start" type="input" class="rounded ipaddress non-empty-value" placeholder="start" value=""><input id="vnw_ip_end" type="input" class="rounded ipaddress non-empty-value" placeholder="end" value=""></td>
</tr>
<tr>
<td>Netmask</td>
<td><input id="vnw_netmask" type="input" class="rounded non-empty-value" value=""></td>
</tr>
<tr>
<td>Gateway (optional)</td>
<td><input id="vnw_gateway" type="input" class="rounded" value=""></td>
</tr>
<tr>
<td>NIC</td>
<td>
<select id="vnw_nic" class="nic float_left">
<option>eth0</option>
<option selected>eth1</option>
<option>eth2</option>
<option>eth3</option>
<option>eth4</option>
</select>
<div id="vnw_nic_err" class="nicHint float_left"></div>
</td>
</tr>
<tr>
<td>Promisc Mode</td>
<td><input id="vnw_promisc" type="checkbox"></td>
</tr>
</table>
</div>
<div>Public Network</div>
<div>
<table>
<tr>
<td>IP Range</td>
<td>
<input id="float_ip_start" type="input" class="rounded ipaddress non-empty-value" placeholder="start" value=""><input id="float_ip_end" type="input" class="rounded ipaddress non-empty-value" placeholder="end" value="">
</td>
</tr>
<tr>
<td>Netmask</td>
<td>
<input id="float_netmask" type="input" class="rounded non-empty-value" value="">
</td>
</tr>
<tr>
<td>Gateway (optional)</td>
<td>
<input id="float_gateway" type="input" class="rounded" value="">
</td>
</tr>
<tr>
<td>NIC</td>
<td>
<select id="float_nic" class="nic float_left">
<option>eth0</option>
<option>eth1</option>
<option selected>eth2</option>
<option>eth3</option>
<option>eth4</option>
</select>
<div id="float_nic_err" class="nicHint float_left"></div>
</td>
</tr>
<tr>
<td>Promisc Mode</td>
<td><input id="float_promisc" type="checkbox"></td>
</tr>
</table>
</div>
<div>Storage Network</div>
<div>
<table>
<tr>
<td>IP Range</td>
<td>
<input id="storage_ip_start" type="input" class="rounded ipaddress non-empty-value" placeholder="start" value=""><input id="storage_ip_end" type="input" class="rounded ipaddress non-empty-value" placeholder="end" value="">
</td>
</tr>
<tr>
<td>Netmask</td>
<td><input id="storage_netmask" type="input" class="rounded non-empty-value" value=""></td>
</tr>
<tr>
<td>Gateway (optional)</td>
<td><input id="storage_gateway" type="input" class="rounded" value=""></td>
</tr>
<tr>
<td>NIC</td>
<td>
<select id="storage_nic" class="nic float_left">
<option>eth0</option>
<option>eth1</option>
<option>eth2</option>
<option selected>eth3</option>
<option>eth4</option>
</select>
<div id="storage_nic_err" class="nicHint float_left"></div>
</td>
</tr>
<tr>
<td>Promisc Mode</td>
<td><input id="storage_promisc" type="checkbox"></td>
</tr>
</table>
</div>
<div>Global Network</div>
<div>
<table>
<tr>
<td>Nameserver</td>
<td><input id="global_nameservers" type="input" class="rounded non-empty-value" value="">e.g. "4.4.4.4,8.8.8.8"</td>
</tr>
<tr>
<td>Search Path</td>
<td><input id="global_searchpath" type="input" class="rounded non-empty-value" value="">e.g. "ods.com,ods2.com"</td>
</tr>
<tr>
<td>Gateway</td>
<td><input id="global_gateway" type="input" class="rounded non-empty-value" value=""></td>
</tr>
<tr>
<td>Proxy (optional)</td>
<td><input id="global_proxy" type="input" class="rounded" value=""></td>
</tr>
<tr>
<td>NTP Server (optional)</td>
<td><input id="global_ntpserver" type="input" class="rounded" value=""></td>
</tr>
</table>
</div>
</div>
<div class="continue"><center>
<a href="#" class="go-back networking-back" >Go back</a>
<a href="/web/host_config/" class="btn_continue networking-finish">Continue</a>
<img id="continuing" class="loading" src="../img/ajax_loader.gif" height="30px" width="30px"></img><br>
<div id="networking_continue_err" style="display:none;padding-top:10px"></div>
</center></div>

View File

@ -0,0 +1,15 @@
.error {
background-color: #FFE6E6;
border-color: red !important;
}
.errhint {
border: 1px solid red;
padding: 4px 8px;
background-color: white;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
color: red;
font-weight: bold;
}

View File

@ -0,0 +1,207 @@
steal(
'jquery/controller',
'jquery/view/ejs',
'jquery/controller/view'
).then(
'./views/init.ejs',
'ods/models/cluster.js'
).then(function($) {
$.Controller('Ods.Ui.security', {}, {
init: function() {
this.element.html(this.view('init'));
this.prefillSecurity();
},
prefillSecurity: function() {
var oldSecurityData = this.options.odsState.security;
if (oldSecurityData) {
$("#server_uname").val(oldSecurityData.server_credentials.username);
$("#server_pwd").val(oldSecurityData.server_credentials.password);
$("#server_confirm").val(oldSecurityData.server_credentials.password);
$("#service_uname").val(oldSecurityData.service_credentials.username);
$("#service_pwd").val(oldSecurityData.service_credentials.password);
$("#service_confirm").val(oldSecurityData.service_credentials.password);
$("#console_uname").val(oldSecurityData.console_credentials.username);
$("#console_pwd").val(oldSecurityData.console_credentials.password);
$("#console_confirm").val(oldSecurityData.console_credentials.password);
}
},
'.security-finish click': function(el, ev) {
ev.preventDefault();
$("#continuing").css("opacity", 1);
this.usernameCheck($("#server_uname"), $("#server_uname_err"));
this.passwordCheck($("#server_pwd"), $("#server_confirm"), $("#server_pwd_err"));
this.usernameCheck($("#service_uname"), $("#service_uname_err"));
this.passwordCheck($("#service_pwd"), $("#service_confirm"), $("#service_pwd_err"));
this.usernameCheck($("#console_uname"), $("#console_uname_err"));
this.passwordCheck($("#console_pwd"), $("#console_confirm"), $("#console_pwd_err"));
if ($("input").hasClass("error") == false) {
var server_username = $("#server_uname").val();
var server_password = $("#server_pwd").val();
var service_username = $("#service_uname").val();
var service_password = $("#service_pwd").val();
var console_username = $("#console_uname").val();
var console_password = $("#console_pwd").val();
var securityData = {
"security": {
"server_credentials": {
"username": server_username,
"password": server_password
},
"service_credentials": {
"username": service_username,
"password": service_password
},
"console_credentials": {
"username": console_username,
"password": console_password
}
}
};
this.options.odsState.security = securityData.security;
Ods.Cluster.update(this.options.odsState.cluster_id, securityData, "security", this.proxy('onSecurityAdded'), this.proxy('onSecurityAddedErr'));
}
},
/************************************************/
// cluster update (security) success callback
/************************************************/
onSecurityAdded: function(data, textStatus, xhr) {
steal.dev.log(" *** onSecurityAdded data *** ", data);
steal.dev.log(" *** onSecurityAdded textStatus *** ", textStatus);
steal.dev.log(" *** onSecurityAdded xhr *** ", xhr);
$("#security_continue_err").hide();
if (xhr.status == 200) { // OK
$("#continuing").css("opacity", 0);
this.options.nav.gotoStep("4");
}
},
/************************************************/
// cluster update (security) error callback
/************************************************/
onSecurityAddedErr: function(xhr, status, statusText) {
steal.dev.log(" *** onSecurityAddedErr xhr *** ", xhr);
steal.dev.log(" *** onSecurityAddedErr status *** ", status);
steal.dev.log(" *** onSecurityAddedErr statusText *** ", xhr);
$("#security_continue_err").html("<span class='errhint'>Error code: " + xhr.status + "</span>");
$("#security_continue_err").show();
},
usernameCheck: function(unameInput, errhint) {
var unameVal = unameInput.val();
var unameErr = false;
if (unameVal == '') {
unameInput.addClass("error");
errhint.html("<span class='errhint'>Please enter a username.</span>");
unameErr = true;
} else if (unameVal.length < 4) {
unameInput.addClass("error");
errhint.html("<span class='errhint'>Username should have at least 4 characters.</span>");
unameErr = true;
}
if (unameErr == false) {
unameInput.removeClass("error");
errhint.html("<img src='../img/green_check_16px.png'></img>");
}
},
'#server_uname keyup': function(el, ev) {
this.usernameCheck($("#server_uname"), $("#server_uname_err"));
},
'#service_uname keyup': function(el, ev) {
this.usernameCheck($("#service_uname"), $("#service_uname_err"));
},
'#console_uname keyup': function(el, ev) {
this.usernameCheck($("#console_uname"), $("#console_uname_err"));
},
passwordCheck: function(pwdInput, confirmInput, errhint) {
var passwordVal = pwdInput.val();
var checkVal = confirmInput.val();
var passwordErr = false;
if (passwordVal == '') {
pwdInput.addClass("error");
errhint.html("<span class='errhint'>Please enter a password.</span>");
passwordErr = true;
} else if (passwordVal.length < 4 || passwordVal.length > 10) {
pwdInput.addClass("error");
errhint.html("<span class='errhint'>Password should have 4-10 characters.</span>");
passwordErr = true;
} else if (checkVal == '') {
confirmInput.addClass("error");
pwdInput.removeClass("error");
errhint.html("<span class='errhint'>Please re-enter your password.</span>");
passwordErr = true;
} else if (passwordVal != checkVal) {
confirmInput.addClass("error");
pwdInput.removeClass("error");
errhint.html("<span class='errhint'>Passwords do not match.</span>");
passwordErr = true;
}
if (passwordErr == false) {
pwdInput.removeClass("error");
confirmInput.removeClass("error");
errhint.html("<img src='../img/green_check_16px.png'></img>");
}
},
'#server_pwd keyup': function(el, ev) {
this.usernameCheck($("#server_uname"), $("#server_uname_err"));
this.passwordCheck($("#server_pwd"), $("#server_confirm"), $("#server_pwd_err"));
},
'#server_confirm keyup': function(el, ev) {
this.usernameCheck($("#server_uname"), $("#server_uname_err"));
this.passwordCheck($("#server_pwd"), $("#server_confirm"), $("#server_pwd_err"));
},
'#service_pwd keyup': function(el, ev) {
this.usernameCheck($("#service_uname"), $("#service_uname_err"));
this.passwordCheck($("#service_pwd"), $("#service_confirm"), $("#service_pwd_err"));
},
'#service_confirm keyup': function(el, ev) {
this.usernameCheck($("#service_uname"), $("#service_uname_err"));
this.passwordCheck($("#service_pwd"), $("#service_confirm"), $("#service_pwd_err"));
},
'#console_pwd keyup': function(el, ev) {
this.usernameCheck($("#console_uname"), $("#console_uname_err"));
this.passwordCheck($("#console_pwd"), $("#console_confirm"), $("#console_pwd_err"));
},
'#console_confirm keyup': function(el, ev) {
this.usernameCheck($("#console_uname"), $("#console_uname_err"));
this.passwordCheck($("#console_pwd"), $("#console_confirm"), $("#console_pwd_err"));
},
'.security-back click': function(el, ev) {
this.options.nav.gobackStep("2");
return false;
},
show: function() {
this.element.show();
},
hide: function() {
this.element.hide();
}
});
});

View File

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>security Widget Unit Test</title>
<link rel="stylesheet" type="text/css" href="../../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../../css/style.css" />
</head>
<body>
<div class="container-fluid">
<div class="row-fluid">
<div id="security-test"> </div>
</div>
</div>
<script type='text/javascript' src='../../../steal/steal.js'></script>
<script type='text/javascript'>
steal('jquery/dom/route', 'ods/fixtures','ods/ui/security').then(function($) {
var odsState = {
networking: null,
servers: [],
servers_config: null,
cluster_id: null,
security: null,
partition: null,
feature: null,
machines: [],
switches: [],
snmp: 1
};
var state = new $.Observe(odsState);
state.cluster_id = 1;
$('#security-test').ods_ui_security({"odsState": state});
});
</script>
</body>
</html>

View File

@ -0,0 +1,67 @@
<h2>Specify credentials you want to use for your OpenStack system</h2>
<div class="rounded" style="padding-top: 0; padding-bottom: 5px">
<h3>OpenStack server credentials</h3>
<div class="rounded gradient">
The default administrator user name and password for each server<br>
<table>
<tr>
<td>User name:</td>
<td><input type="input" class="rounded" id="server_uname" value="root"></td>
<td></td><td></td><td id="server_uname_err"></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="password" class="rounded" id="server_pwd" value=""></td>
<td>Confirm:</td>
<td><input type="password" class="rounded" id="server_confirm" value=""></td>
<td id="server_pwd_err"><img src="../img/yellow_arrow_left_16px.png"></img><span class="italic"> requires password</span></td>
</tr>
</table>
</div>
<h3>OpenStack services credentials</h3>
<div class="rounded gradient">
User name and password for all of the OpenStack services such as management database, queue server, etc.<br>
<table>
<tr>
<td>User name:</td>
<td><input type="input" class="rounded" id="service_uname" value="service"></td>
<td></td><td></td><td id="service_uname_err"></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="password" class="rounded" id="service_pwd" value=""></td>
<td>Confirm:</td>
<td><input type="password" class="rounded" id="service_confirm" value=""></td>
<td id="service_pwd_err"><img src="../img/yellow_arrow_left_16px.png"></img><span class="italic"> requires password</span></td>
</tr>
</table>
</div>
<h3>OpenStack management console credentials</h3>
<div class="rounded gradient">
The default administrator user name and password for the OpenStack management console.<br>
<table>
<tr>
<td>User name:</td>
<td><input type="input" class="rounded" id="console_uname" value="console"></td>
<td></td><td></td><td id="console_uname_err"></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="password" class="rounded" id="console_pwd" value=""></td>
<td>Confirm:</td>
<td><input type="password" class="rounded" id="console_confirm" value=""></td>
<td id="console_pwd_err"><img src="../img/yellow_arrow_left_16px.png"></img><span class="italic"> requires password</span></td>
</tr>
</table>
</div>
<br>
</div>
<div class="continue"><center>
<a href="#" class="go-back security-back" >Go back</a>
<a href="#" class="btn_continue security-finish">Continue</a>
<img id="continuing" class="loading" src="../img/ajax_loader.gif" height="30px" width="30px"></img><br>
<div id="security_continue_err" style="display:none;padding-top:10px"></div>
</center></div>

View File

@ -0,0 +1,105 @@
.add {
width: 16px;
height: 16px;
background-image: url("../../../img/add_button_16px.png");
cursor: hand;
cursor: pointer;
float: left;
}
.remove {
width: 16px;
height: 16px;
background-image: url("../../../img/remove_button_16px.png");
cursor: hand;
cursor: pointer;
float: left;
}
.switch_row input {
width: 100px;
}
.server-result {
min-height: 200px;
}
.server-g-num {
padding: 1px 10px;
margin-top: 2px;
}
#tb_server_select {
/*border: 1px solid #aaaaaa;*/
background-color: rgb(255, 255, 255);
padding: 5px;
}
#container {
width: 600px;
margin: 30px auto;
padding: 0;
}
table.display {
margin: 0 auto;
clear: both;
width: 100% !important;
}
table.display thead th {
padding: 3px 18px 3px 5px;
/*border-bottom: 1px solid grey;*/
font-weight: bold;
cursor: pointer;
text-align: left;
}
.dataTables_filter {
width: 50%;
float: right;
text-align: right;
position: relative;
margin-top: -35px;
}
.dataTables_scrollHeadInner {
width: 100% !important;
background-color: rgb(255, 255, 255);
}
.dataTables_scrollHead {
border: 1px solid grey !important;
border-radius: 6px 6px 0px 0px;
-moz-border-radius: 6px 6px 0px 0px;
-webkit-border-radius: 6px 6px 0px 0px;
}
.dataTables_scrollBody {
border-left: 1px solid grey;
border-right: 1px solid grey;
border-bottom: 1px solid grey;
border-radius: 0px 0px 6px 6px;
-moz-border-radius: 0px 0px 6px 6px;
-webkit-border-radius: 0px 0px 6px 6px;
}
.sorting {
background: url('../../../img/bg.gif') no-repeat center right;
}
.sorting_desc {
background: url('../../../img/desc.gif') no-repeat center right;
}
.sorting_asc {
background: url('../../../img/asc.gif') no-repeat center right;
}
.highlight {
background: #C3C7DD;
}
.server-selection-num {
padding: 5px;
}

View File

@ -0,0 +1,632 @@
steal(
'jquery/controller',
'jquery/view/ejs',
'jquery/controller/view',
'jquery/lang/json'
).then(
'./servers.css',
'./views/init.ejs',
'lib/jquery.dataTables.js',
'./views/switch_row.ejs',
'ods/models/servers.js',
'ods/models/cluster.js'
).then(function($) {
$.Controller('Ods.Ui.servers', {}, {
init: function() {
this.element.html(this.view('init'));
this.pendingSwitchList = [];
// we query up to 10 times. Report an error if any of the switches
// remains in not_reached status.
this.queryCount = 0;
this.initServerTable();
this.checked_num = 0;
this.initServerStep = 1;
this.machines = [];
var oldAllServersData = this.options.odsState.machines;
if (oldAllServersData.length > 0) {
this.initServerStep = 0;
this.element.find('div.right-side').show();
this.dataTable.fnClearTable();
this.dataTable.fnAddData(oldAllServersData);
var oldSelectedServersData = this.options.odsState.servers;
for (var i = 0; i < oldSelectedServersData.length; i++) {
$(".server_check").each(function(index, element) {
if (oldSelectedServersData[i].id == element.value) {
element.checked = true;
$(element).closest("tr").addClass("highlight");
}
});
}
this.countCheckedServers();
}
var oldSwitchesData = this.options.odsState.switches;
if (oldSwitchesData.length > 0) {
var tbody = $(".switchtable tbody");
if (this.options.odsState.snmp) {
$('#useSNMP').prop('checked', true);
} else {
$('#useSNMP').prop('checked', false);
}
for (var i = 0; i < oldSwitchesData.length; i++) {
if (i > 0) {
tbody.append(this.view('switch_row'));
}
if (this.options.odsState.snmp) {
$("#snmpTitle").html("SNMP Version");
$("#communityTitle").html("Community");
$(".switch_row").find(".snmp").show();
$(".switch_row").find(".community").show();
$(".switch_row").find(".username").hide();
$(".switch_row").find(".password").hide();
} else {
$("#snmpTitle").html("Username");
$("#communityTitle").html("Password");
$(".switch_row").find(".snmp").hide();
$(".switch_row").find(".community").hide();
$(".switch_row").find(".username").show();
$(".switch_row").find(".password").show();
}
if (this.options.odsState.snmp) {
$(".switch_row").eq(i).find(".switchIp").val(oldSwitchesData[i].switch.ip);
$(".switch_row").eq(i).find(".snmp").val(oldSwitchesData[i].switch.credential.version);
$(".switch_row").eq(i).find(".community").val(oldSwitchesData[i].switch.credential.community);
} else {
$(".switch_row").eq(i).find(".switchIp").val(oldSwitchesData[i].switch.ip);
$(".switch_row").eq(i).find(".username").val(oldSwitchesData[i].switch.credential.username);
$(".switch_row").eq(i).find(".password").val(oldSwitchesData[i].switch.credential.password);
}
}
}
},
initServerTable: function() {
this.dataTable = $('#tb_server_select').dataTable({
"sScrollY": "200px",
"bPaginate": false,
"bScrollCollapse": true,
"aoColumns": [{
"mData": "id",
"mRender": function(data, type, full) {
return '<input type="checkbox" class="server_check" value="' + data + '"/>';
}
}, {
"mData": "mac"
}, {
"mData": "switch_ip"
}, {
"mData": "vlan"
}, {
"mData": "port"
}],
"aoColumnDefs": [{
bSortable: false,
aTargets: [0, 1, 3]
}],
"aaSorting": [
[2, "asc"],
[4, "asc"]
]
});
$('.dataTables_info').remove();
$('.dataTables_filter input').addClass('serverFilter');
$('.dataTables_filter input').addClass('rounded');
},
'#useSNMP click': function(el, ev) {
if ($("#useSNMP:checked").val()) {
$("#snmpTitle").html("SNMP Version");
$("#communityTitle").html("Community");
$(".snmp").show();
$(".community").show();
$(".username").hide();
$(".password").hide();
} else {
$("#snmpTitle").html("Username");
$("#communityTitle").html("Password");
$(".snmp").hide();
$(".community").hide();
$(".username").show();
$(".password").show();
}
},
'.server-finish click': function(el, ev) {
ev.preventDefault();
if (this.checked_num == 0) {
alert("Please select at least one server");
} else {
$("#continuing").css("opacity", 1);
if (this.initServerStep) {
// create cluster
Ods.Cluster.create({
"cluster": {
"name": "",
"adapter_id": 1
}
}, this.proxy('onClusterCreated'), this.proxy('onClusterCreatedErr'));
} else {
// replace all hosts in current cluster
var cluster_id = this.options.odsState.cluster_id;
Ods.Cluster.action(cluster_id, {
'replaceAllHosts': this.getSelectedServers()
}, this.proxy('onServerAdded'), this.proxy('onServerAddedErr'));
}
}
},
/************************************/
// create cluster success callback
/************************************/
'onClusterCreated': function(data, textStatus, xhr) {
steal.dev.log(" *** onClusterCreated data *** ", data);
steal.dev.log(" *** onClusterCreated textStatus *** ", textStatus);
steal.dev.log(" *** onClusterCreated xhr *** ", xhr);
$("#server_continue_err").hide();
var cluster_id = data.cluster.id;
this.options.odsState.cluster_id = cluster_id;
Ods.Cluster.action(cluster_id, {
'addHosts': this.getSelectedServers()
}, this.proxy('onServerAdded'), this.proxy('onServerAddedErr'));
},
/************************************/
// create cluster error callback
/************************************/
'onClusterCreatedErr': function(xhr, status, statusText) {
var errMessage = JSON.parse(xhr.responseText).message;
$("#server_continue_err").html("<span class='errhint'>" + errMessage + "</span>");
$("#server_continue_err").show();
},
'getSelectedServers': function() {
selectedServers = [];
this.options.odsState.servers = [];
this.options.odsState.servers_config = [];
// loop through dataTable nodes to find selected servers
for (var i = 0; i < this.dataTable.fnGetNodes().length; i++) {
var ckboxTd = $('td', this.dataTable.fnGetNodes()[i])[0];
var server_ckbox = $('input', ckboxTd)[0];
if (server_ckbox.checked == true) {
var checkTd = $('td', this.dataTable.fnGetNodes()[i])[1];
var macTd = $('td', this.dataTable.fnGetNodes()[i])[1];
var switchIpTd = $('td', this.dataTable.fnGetNodes()[i])[2];
var vlanTd = $('td', this.dataTable.fnGetNodes()[i])[3];
var portTd = $('td', this.dataTable.fnGetNodes()[i])[4];
var mac = macTd.textContent || macTd.innerText;
var switch_ip = switchIpTd.textContent || switchIpTd.innerText;
var vlan = vlanTd.textContent || vlanTd.innerText;
var port = portTd.textContent || portTd.innerText;
var server_id = parseInt(server_ckbox.value);
this.options.odsState.servers.push({
"id": server_id,
"mac": mac,
"switch_ip": switch_ip,
"vlan": vlan,
"port": port
});
selectedServers.push(server_id);
}
}
return selectedServers;
},
'div.add click': function(el, ev) {
var tbody = el.closest('tbody');
tbody.append(this.view('switch_row'));
if (!$("#useSNMP:checked").val()) {
$(".switch_row").last().find(".snmp").hide();
$(".switch_row").last().find(".community").hide();
$(".switch_row").last().find(".username").show();
$(".switch_row").last().find(".password").show();
}
},
'div.remove click': function(el, ev) {
var row = el.closest('tr');
row.remove();
},
'a.find_server click': function(el, ev) {
// remove the error class within the el
$('.switchtable').find('.error').removeClass('error');
$(".switchesErr").hide();
var self = this;
var hasError = false;
this.pendingSwitchList.length = 0;
this.queryCount = 0;
// return if the switch_ip/community or username/password input is empty
$('.switchtable').find('.non-empty-value').each(function(index, value) {
if ($(value).is(":visible") && !self.checkNonEmpty($(value))) {
hasError = true;
}
});
$('.switchtable').find('.switchIp').each(function(index, value) {
var isValid = self.validateIpFormat($(value).val());
if (!isValid) {
$(value).addClass("error");
hasError = true;
} else {
$(value).removeClass("error");
}
});
if (hasError) {
return;
}
$("#finding-servers").css("opacity", 1);
var switch_count = $(".switch_row").length;
this.pendingCount = switch_count;
this.switches = [];
// loop through switch rows to create new switches
for (i = 0; i < switch_count; i++) {
var switch_ip = $(".switch_row").eq(i).find(".switchIp");
var snmp_version = null,
community = null;
var username = null,
password = null;
var switchData = {};
if ($("#useSNMP:checked").val()) {
this.options.odsState.snmp = 1;
snmp_version = $(".switch_row").eq(i).find(".snmp");
community = $(".switch_row").eq(i).find(".community");
switchData = {
"switch": {
"ip": switch_ip.val(),
"credential": {
'version': snmp_version.val(),
'community': community.val()
}
}
};
} else {
this.options.odsState.snmp = 0;
username = $(".switch_row").eq(i).find(".username");
password = $(".switch_row").eq(i).find(".password");
switchData = {
"switch": {
"ip": switch_ip.val(),
"credential": {
"username": username.val(),
"password": password.val()
}
}
};
}
this.switches.push(switchData);
Ods.Switch.create(switchData, this.proxy('onSwitchCreated', i), this.proxy('onSwitchCreateErr', i));
}
this.options.odsState.switches = this.switches;
},
'input.switchIp keyup': function(el, ev) {
var isValid = this.validateIpFormat(el.val());
if (!isValid) {
el.addClass("error");
} else {
el.removeClass("error");
}
},
validateIpFormat: function(value) {
var ipformat = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
if (value.match(ipformat)) {
return true;
} else {
return false;
}
},
/************************************/
// switch create success callback
/************************************/
onSwitchCreated: function(switchIndex, data, textStatus, xhr) {
steal.dev.log(" *** onSwitchCreated data *** ", data);
steal.dev.log(" *** onSwitchCreated textStatus *** ", textStatus);
steal.dev.log(" *** onSwitchCreated xhr *** ", xhr);
this.pendingCount--;
if (xhr.status == 202) { // accepted
var switchId = data.
switch.id;
this.pendingSwitchList.push(switchId);
}
if (this.pendingCount == 0) {
this.checkSwitchState();
}
},
/************************************/
// switch create error callback
/************************************/
onSwitchCreateErr: function(switchIndex, xhr, status, statusText) {
steal.dev.log(" *** onSwitchCreatErr xhr *** ", xhr);
steal.dev.log(" *** onSwitchCreatErr status *** ", status);
steal.dev.log(" *** onSwitchCreatErr statusText *** ", xhr);
$("#finding-servers").css("opacity", 0);
if (xhr.status == 409) { // duplicate
var failedSwitchId = 0;
if ($.fixture.on == true) {
failedSwitchId = statusText.failedSwitch;
} else {
failedSwitchId = JSON.parse(xhr.responseText).failedSwitch;
}
steal.dev.log(" *** failed Switch Id *** ", failedSwitchId);
// PUT switches
Ods.Switch.update(failedSwitchId, this.switches[switchIndex],
this.proxy('onSwitchUpdated', switchIndex), this.proxy('onSwitchUpdateErr'));
} else if (xhr.status == 400) { //bad request
$(".switchesErr").html("Switch post error code: 400");
$(".switchesErr").show();
} else if (xhr.status == 500) { // internal server error
$(".switchesErr").html("Switch post error code: 500");
$(".switchesErr").show();
}
},
/************************************/
// switch update success callback
/************************************/
onSwitchUpdated: function(switchIndex, data, textStatus, xhr) {
steal.dev.log(" *** onSwitchUpdated data *** ", data);
steal.dev.log(" *** onSwitchUpdated textStatus *** ", textStatus);
steal.dev.log(" *** onSwitchUpdated xhr *** ", xhr);
this.pendingCount--;
if (xhr.status == 202 || xhr.status == 200) { // accepted or OK
var switchId = data.
switch.id;
this.pendingSwitchList.push(switchId);
}
if (this.pendingCount == 0) {
this.checkSwitchState();
}
},
/************************************/
// switch create error callback
/************************************/
onSwitchUpdateErr: function(xhr, status, statusText) {
steal.dev.log(" *** onSwitchUpdateErr xhr *** ", xhr);
steal.dev.log(" *** onSwitchUpdateErr status *** ", status);
steal.dev.log(" *** onSwitchUpdateErr statusText *** ", statusText);
$("#finding-servers").css("opacity", 0);
if (xhr.status == 404) { // not found
$(".switchesErr").html("Switch update error code: 404");
$(".switchesErr").show();
} else if (xhr.status == 400) { // bad request
$(".switchesErr").html("Switch update error code: 400");
$(".switchesErr").show();
} else if (xhr.status == 500) { // internal server error
$(".switchesErr").html("Switch update error code: 500");
$(".switchesErr").show();
}
},
checkSwitchState: function() {
this.queryCount++;
this.pendingCount = this.pendingSwitchList.length;
if (this.queryCount > 10) {
$(".switchesErr").html("There is(are) " + this.pendingCount + " switch(es) not responding now. Please try again later.")
$(".switchesErr").show();
$("#finding-servers").css("opacity", 0);
return;
}
var switches = this.pendingSwitchList;
this.pendingSwitchList = [];
var count = this.pendingCount;
for (var i = 0; i < count; i++) {
Ods.Switch.findOne(switches[i], this.proxy('onFindOneSwitch'), this.proxy('onFindOneSwitchErr'));
}
},
/************************************/
// find one switch success callback
/************************************/
onFindOneSwitch: function(data, textStatus, xhr) {
steal.dev.log(" *** onFindOneSwitch data *** ", data);
steal.dev.log(" *** onFindOneSwitch textStatus *** ", textStatus);
steal.dev.log(" *** onFindOneSwitch xhr *** ", xhr);
this.pendingCount--;
if (xhr.status == 200) { //OK
if (data.
switch.state === "under_monitoring") {
this.element.find('div.right-side').show();
this.dataTable.fnClearTable();
this.getServersBySwitch(data.
switch.id);
} else {
this.pendingSwitchList.push(data.
switch.id);
}
}
if (this.pendingCount == 0) {
setTimeout(this.proxy('checkSwitchState'), 2000);
}
},
/************************************/
// find one switch error callback
/************************************/
onFindOneSwitchErr: function(xhr, status, statusText) {
steal.dev.log(" *** onFindOneSwitchErr xhr *** ", xhr);
steal.dev.log(" *** onFindOneSwitchErr status *** ", status);
steal.dev.log(" *** onFindOneSwitchErr statusText *** ", statusText);
$("#finding-servers").css("opacity", 0);
if (xhr.status == 404) { // not found
$(".switchesErr").html("Find switch error code: 404");
$(".switchesErr").show();
} else if (xhr.status == 500) {
$(".switchesErr").html("Find switch error code: 500");
$(".switchesErr").show();
}
},
getServersBySwitch: function(id) {
Ods.Server.findAll({
switchId: id
}, this.proxy('onFindAllServers'));
},
/************************************/
// find all servers success callback
/************************************/
onFindAllServers: function(data, textStatus, xhr) {
steal.dev.log(" *** onFindAllServers data *** ", data);
steal.dev.log(" *** onFindAllServers textStatus *** ", textStatus);
steal.dev.log(" *** onFindAllServers xhr *** ", xhr);
this.dataTable.fnAddData(data.machines);
this.machines = this.machines.concat(data.machines);
if (this.pendingCount == 0 && this.pendingSwitchList.length == 0) {
steal.dev.log("loading finished");
$("#finding-servers").css("opacity", 0);
this.options.odsState.machines = this.machines;
}
},
checkNonEmpty: function(el) {
var value = el.val();
if (!value) {
el.addClass('error');
return false;
}
return true;
},
/************************************/
// add server to cluster success callback
/************************************/
onServerAdded: function(data, textStatus, xhr) {
$("#server_continue_err").hide();
if (xhr.status == 200) { // OK
// Assume the machine orders are same in returned data (data.clusterHosts)
// and cached data (this.options.odsState.servers)
for (var i = 0; i < data.clusterHosts.length; i++) {
this.options.odsState.servers[i]['clusterhost_id'] = data.clusterHosts[i].id;
}
$("#continuing").css("opacity", 0);
this.options.nav.gotoStep("3");
}
},
/************************************/
// add server to cluster error callback
/************************************/
onServerAddedErr: function(xhr, status, statusText) {
steal.dev.log(" *** onServerAddedErr xhr *** ", xhr);
steal.dev.log(" *** onServerAddedErr status *** ", status);
steal.dev.log(" *** onServerAddedErr statusText *** ", statusText);
var errMessage = JSON.parse(xhr.responseText).message;
$("#server_continue_err").html("<span class='errhint'>" + errMessage + "</span>");
$("#server_continue_err").show();
},
'.server_check click': function(el, ev) {
el.closest("tr").toggleClass("highlight");
if (el.is(':checked') == false && $("#select_all").is(':checked') == true) {
$("#select_all").prop('checked', false);
}
this.countCheckedServers();
},
'#select_all click': function(el, ev) {
if (el.is(':checked')) { // if select all servers
$(".server_check").prop('checked', true);
$(".server_check").closest("tr").addClass("highlight");
} else {
$(".server_check").prop('checked', false);
$(".server_check").closest("tr").removeClass("highlight");
}
this.countCheckedServers();
},
'countCheckedServers': function() {
this.checked_num = 0;
for (var i = 0; i < this.dataTable.fnGetNodes().length; i++) {
var firstTdInTr = $('td', this.dataTable.fnGetNodes()[i])[0];
var inputInTd = $('input', firstTdInTr)[0];
if (inputInTd.checked == true) {
this.checked_num++;
}
}
$("#selected_num").html(this.checked_num);
},
'.serverFilter keyup': function(el, ev) {
this.countCheckedServers();
},
show: function() {
this.element.show();
},
hide: function() {
this.element.hide();
}
});
});

View File

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>servers Widget Unit Test</title>
<link rel="stylesheet" type="text/css" href="../../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../../css/style.css" />
</head>
<body>
<div class="container-fluid">
<div class="row-fluid">
<div id="servers-test"> </div>
</div>
</div>
<script type='text/javascript' src='../../../steal/steal.js'></script>
<script type='text/javascript'>
steal('jquery/dom/route', 'ods/fixtures', 'ods/ui/servers').then(function($) {
var odsState = {
networking: null,
servers: [],
servers_config: null,
cluster_id: null,
security: null,
partition: null,
feature: null,
machines: [],
switches: [],
snmp: 1
};
var state = new $.Observe(odsState);
$('#servers-test').ods_ui_servers({"odsState": state});
});
</script>
</body>
</html>

View File

@ -0,0 +1,78 @@
<h2>Select the servers you want to use for OpenStack</h2>
<div class="left-side">
<div class="inside">
<h3>To begin, search for available servers</h3>
<div class="rounded">
Enter the IP address or host name for the network switches on which the servers are connected. Enter as many switches as needed and then click Find Servers.
<table class="switchtable">
<thead>
<tr>
<th>Switch IP</th>
<th id="snmpTitle">SNMP Version</th>
<th id="communityTitle">Community</th>
<th><input id="useSNMP" type="checkbox" checked> Use SNMP</th>
</tr>
</thead>
<tbody>
<tr class="switch_row">
<td><input type="input" class="switchIp non-empty-value rounded" placeholder="Switch IP" value=""> </td>
<td style="width:110px">
<select class="snmp">
<option>v1</option>
<option selected>v2c</option>
</select>
<input type="input" class="username non-empty-value rounded" placeholder="Username" value="" style="display:none">
</td>
<td>
<input type="password" class="community non-empty-value rounded" placeholder="Community" value="">
<input type="password" class="password non-empty-value rounded" placeholder="Password" value="" style="display:none;">
</td>
<td width="120px"><div class="add"> </div></td>
</tr>
</tbody>
</table>
<div class="continue">
<center>
<a href="javascript:void(0)" class="find_server btn_find"> Find Servers </a>
<img id="finding-servers" class="loading" src="../img/ajax_loader.gif" height="30px" width="30px"></img>
</center>
<center class="switchesErr errhint" style="margin-top:10px;display:none;">
The switches are not responding. Please try again later.
</center>
</div>
</div>
</div>
</div>
<div class="right-side" style="display:none">
<h3>Select servers onto which to deploy OpenStack</h3>
<div class="server-result">
<table id="tb_server_select" cellpadding="0" cellspacing="0" border="0" class="display">
<thead>
<tr>
<th><input type="checkbox" id="select_all"></th>
<th>MAC Addr</th>
<th>Switch addr</th>
<th>VLAN</th>
<th>Port</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<div class='float_right rounded server-selection-num'>
<span id="selected_num">0</span> items selected
</div>
<div class="clear"></div>
<div class="continue"><center>
<a href="javascript: void(0)" class="btn_continue server-finish">Continue</a>
<img id="continuing" class="loading" src="../img/ajax_loader.gif" height="30px" width="30px"></img><br>
<div id="server_continue_err" style="display:none;padding-top:10px"></div>
</center></div>
</div>

View File

@ -0,0 +1,15 @@
<tr class="switch_row">
<td><input type="input" class="switchIp non-empty-value rounded" placeholder="Switch IP"> </td>
<td>
<select class="snmp">
<option>v1</option>
<option selected>v2c</option>
</select>
<input type="input" class="username non-empty-value rounded" placeholder="Username" style="display:none">
</td>
<td>
<input type="password" class="community non-empty-value rounded" placeholder="Community">
<input type="password" class="password non-empty-value rounded" placeholder="Password" style="display:none">
</td>
<td><div class='add'></div><div class='remove'></div></td>
</tr>

Some files were not shown because too many files have changed in this diff Show More