Initial commit
33
README.md
@ -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
@ -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
1
public/css/github2.css
Normal file
3
public/css/style-ie.css
Normal file
@ -0,0 +1,3 @@
|
||||
#nav {
|
||||
padding-top: 18px;
|
||||
}
|
220
public/css/style.css
Normal 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;
|
||||
}
|
BIN
public/img/add_button_16px.png
Normal file
After Width: | Height: | Size: 523 B |
BIN
public/img/ajax_loader.gif
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
public/img/asc.gif
Normal file
After Width: | Height: | Size: 54 B |
BIN
public/img/bg.gif
Normal file
After Width: | Height: | Size: 64 B |
BIN
public/img/desc.gif
Normal file
After Width: | Height: | Size: 54 B |
BIN
public/img/features_graphic.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
public/img/filter_clear_16px.png
Normal file
After Width: | Height: | Size: 410 B |
BIN
public/img/green_check_16px.png
Normal file
After Width: | Height: | Size: 338 B |
BIN
public/img/green_check_large_16px.png
Normal file
After Width: | Height: | Size: 419 B |
BIN
public/img/hw_000353.jpg
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
public/img/hw_000469.jpg
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
public/img/hw_s_221828.jpg
Normal file
After Width: | Height: | Size: 349 B |
BIN
public/img/hwico.ico.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
public/img/info_icon_16px.png
Normal file
After Width: | Height: | Size: 665 B |
BIN
public/img/openstack_welcome_graphics.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
public/img/openstack_welcome_graphics_std.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
public/img/remove_button_16px.png
Normal file
After Width: | Height: | Size: 493 B |
BIN
public/img/router.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
public/img/server.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
public/img/server_status_mask (#0000FF - 50% transparency).png
Normal file
After Width: | Height: | Size: 315 B |
BIN
public/img/switch.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
public/img/topology_description.png
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
public/img/yellow_arrow_left_16px.png
Normal file
After Width: | Height: | Size: 367 B |
BIN
public/img/yellow_arrow_right_16px.png
Normal file
After Width: | Height: | Size: 269 B |
8981
public/lib/d3.js
vendored
Normal file
5
public/lib/d3.min.js
vendored
Normal file
BIN
public/lib/images/animated-overlay.gif
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
public/lib/images/ui-bg_flat_0_aaaaaa_40x100.png
Normal file
After Width: | Height: | Size: 212 B |
BIN
public/lib/images/ui-bg_flat_75_ffffff_40x100.png
Normal file
After Width: | Height: | Size: 208 B |
BIN
public/lib/images/ui-bg_glass_55_fbf9ee_1x400.png
Normal file
After Width: | Height: | Size: 335 B |
BIN
public/lib/images/ui-bg_glass_65_ffffff_1x400.png
Normal file
After Width: | Height: | Size: 207 B |
BIN
public/lib/images/ui-bg_glass_75_dadada_1x400.png
Normal file
After Width: | Height: | Size: 262 B |
BIN
public/lib/images/ui-bg_glass_75_e6e6e6_1x400.png
Normal file
After Width: | Height: | Size: 262 B |
BIN
public/lib/images/ui-bg_glass_95_fef1ec_1x400.png
Normal file
After Width: | Height: | Size: 332 B |
BIN
public/lib/images/ui-bg_highlight-soft_75_cccccc_1x100.png
Normal file
After Width: | Height: | Size: 280 B |
BIN
public/lib/images/ui-icons_222222_256x240.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
public/lib/images/ui-icons_2e83ff_256x240.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
public/lib/images/ui-icons_454545_256x240.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
public/lib/images/ui-icons_888888_256x240.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
public/lib/images/ui-icons_cd0a0a_256x240.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
6
public/lib/jquery-1.10.1.min.js
vendored
Normal file
1177
public/lib/jquery-ui-1.10.3.custom.css
vendored
Normal file
14971
public/lib/jquery-ui-1.10.3.custom.js
vendored
Normal file
12099
public/lib/jquery.dataTables.js
vendored
Normal file
291
public/lib/jquery.numeric.js
Normal 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
@ -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": ""
|
||||
}
|
||||
}
|
||||
|
||||
};
|
381
public/ods/fixtures/fixtures.js
Normal 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
@ -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>
|
88
public/ods/models/cluster.js
Normal 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
|
||||
});
|
||||
}
|
||||
}, {});
|
||||
|
||||
});
|
4
public/ods/models/models.js
Normal file
@ -0,0 +1,4 @@
|
||||
// steal model files
|
||||
steal("jquery/model",
|
||||
"./servers.js",
|
||||
"./cluster.js")
|
43
public/ods/models/servers.js
Normal 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
71
public/ods/ods.html
Normal 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
@ -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
@ -0,0 +1,3 @@
|
||||
@page index ods
|
||||
|
||||
This is a placeholder for the homepage of your documentation.
|
5
public/ods/production.css
Normal file
1021
public/ods/production.js
Normal file
21
public/ods/qunit.html
Normal 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>
|
21
public/ods/scripts/build.html
Normal 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>
|
6
public/ods/scripts/build.js
Normal 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'});
|
||||
});
|
17
public/ods/scripts/clean.js
Normal 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
|
||||
}
|
||||
});
|
||||
});
|
7
public/ods/scripts/crawl.js
Normal 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")
|
||||
});
|
8
public/ods/scripts/docs.js
Normal 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']
|
||||
});
|
||||
});
|
43
public/ods/ui/features/features.js
Normal 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();
|
||||
}
|
||||
});
|
||||
});
|
27
public/ods/ui/features/features_test.html
Normal 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>
|
||||
|
27
public/ods/ui/features/views/before_begin.ejs
Normal 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>
|
35
public/ods/ui/features/views/init.ejs
Normal 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> 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>
|
7
public/ods/ui/host_config/host_config.css
Normal file
@ -0,0 +1,7 @@
|
||||
.tab_panel{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab_panel_active {
|
||||
display: block;
|
||||
}
|
320
public/ods/ui/host_config/host_config.js
Normal 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();
|
||||
}
|
||||
});
|
||||
});
|
77
public/ods/ui/host_config/host_config_test.html
Normal 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>
|
||||
|
78
public/ods/ui/host_config/views/init.ejs
Normal 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>
|
5
public/ods/ui/host_config/views/server_row.ejs
Normal 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>
|
46
public/ods/ui/install_review/install.css
Normal 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;
|
||||
}
|
64
public/ods/ui/install_review/install_review.css
Normal 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;
|
||||
|
||||
}
|
648
public/ods/ui/install_review/install_review.js
Normal 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();
|
||||
}
|
||||
});
|
||||
});
|
79
public/ods/ui/install_review/install_review_test.html
Normal 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>
|
||||
|
90
public/ods/ui/install_review/views/init.ejs
Normal 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>
|
46
public/ods/ui/install_review/views/install.ejs
Normal 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;"> Errors: 0</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</center></div>
|
||||
|
||||
<div class="clear"></div>
|
9
public/ods/ui/install_review/views/progress_row.ejs
Normal 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
@ -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();
|
||||
}
|
||||
});
|
||||
});
|
9
public/ods/ui/nav/views/init.ejs
Normal 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>
|
43
public/ods/ui/networking/networking.css
Normal 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;
|
||||
}
|
396
public/ods/ui/networking/networking.js
Normal 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();
|
||||
}
|
||||
});
|
||||
});
|
42
public/ods/ui/networking/networking_test.html
Normal 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>
|
||||
|
180
public/ods/ui/networking/views/init.ejs
Normal 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>
|
15
public/ods/ui/security/security.css
Normal 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;
|
||||
}
|
207
public/ods/ui/security/security.js
Normal 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();
|
||||
}
|
||||
});
|
||||
});
|
42
public/ods/ui/security/security_test.html
Normal 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>
|
||||
|
67
public/ods/ui/security/views/init.ejs
Normal 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>
|
105
public/ods/ui/servers/servers.css
Normal 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;
|
||||
}
|
632
public/ods/ui/servers/servers.js
Normal 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();
|
||||
}
|
||||
});
|
||||
});
|
42
public/ods/ui/servers/servers_test.html
Normal 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>
|
||||
|
78
public/ods/ui/servers/views/init.ejs
Normal 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>
|
15
public/ods/ui/servers/views/switch_row.ejs
Normal 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>
|