Improve wizard steps.

Add flavor for creating cluster

Move subnets from OS Global page to Network page

Add find-new-servers on Server Selection page
(Improve find-new-servers code by using directive)

Combine interface and autofill on Network page

Add OS Global section on Review page

Remove swipe on wizard

Simplify wizard step and commit control

Move monitoring part to an individual module

Change-Id: I8422506270c428a7f84679cfbff542235ccc556f
This commit is contained in:
jiahuay 2014-08-18 16:02:35 -07:00
parent 97643bcd14
commit 5f6e0118b0
29 changed files with 1138 additions and 1178 deletions

View File

@ -231,16 +231,9 @@ button[disabled] {
.wizard-steps li.error .title, .wizard-steps li.error .title {
color: #2b3d53;
}
.popup-alert {
position: fixed;
z-index: 9;
overflow-y: hidden;
}
.popup-alert .message {
color: white;
overflow: hidden;
padding: 10px;
word-wrap: normal;
.wizard-steps li.incomplete:before, li.incomplete .step {
border-color: #d15b47 !important;
font-weight: bold;
}
.padding-left-15 {
padding-left: 15px;
@ -283,6 +276,9 @@ button[disabled] {
line-height: 1.5;
padding: 4px 12px;
}
.btn-xs {
padding: 1px 5px !important;
}
.btn-white {
border-width: 1px !important;
}
@ -441,10 +437,6 @@ a:active {
background-color: #abbac3 !important;
border-color: #abbac3 !important;
}
.first-prev {
cursor: not-allowed !important;
/* padding: 10px !important; */
}
.btn-light {
cursor: not-allowed !important;
}
@ -549,15 +541,3 @@ div.center-align {
min-height: 50px;
padding: 10px;
}
.wizard-steps li.complete:before, .wizard-steps li.complete .step {
/* border-color: #93cbf9 !important;*/}
.a.wizard-steps li.active:before, .wizard-steps li.active .step {
border-color: #80afd4 !important;
color: #87ba21 !important;
transform: scale(1.25) !important;
font-weight: bold;
}
li.incomplete:before, li.incomplete .step {
border-color: #d15b47 !important;
font-weight: bold;
}

View File

@ -20,12 +20,12 @@
"is_promiscuous": false
},
"eth1": {
"subnet_id": 1,
"subnet_id": 2,
"is_mgmt": false,
"is_promiscuous": true
},
"eth2": {
"subnet_id": 2,
"subnet_id": 1,
"is_mgmt": false,
"is_promiscuous": false
},

View File

@ -44,8 +44,10 @@
<script type="text/javascript" src="src/app/wizard/wizard.js"></script>
<script type="text/javascript" src="src/app/cluster/cluster.js"></script>
<script type="text/javascript" src="src/app/cluster/clusterlist.js"></script>
<script type="text/javascript" src="src/app/monitoring/monitoring.js"></script>
<script type="text/javascript" src="src/app/server/server.js"></script>
<script type="text/javascript" src="src/common/charts.js"></script>
<script type="text/javascript" src="src/common/findservers/findservers.js"></script>
</head>
<body ng-app="compass" ng-controller="appController">

View File

@ -5,6 +5,7 @@ var app = angular.module('compass', [
'compass.wizard',
'compass.cluster',
'compass.clusterlist',
'compass.monitoring',
'compass.server',
'ui.router',
'ui.bootstrap',

View File

@ -38,10 +38,10 @@ compassAppDev.run(function($httpBackend, settings, $http) {
}],
"supported_oses": [{
"name": "CentOs",
"os_id": 1
"id": 1
}, {
"name": "Ubuntu",
"os_id": 2
"id": 2
}]
}, {
"id": 2,
@ -61,8 +61,12 @@ compassAppDev.run(function($httpBackend, settings, $http) {
}],
"supported_oses": [{
"name": "CentOs",
"os_id": 1
}]
"id": 1
}, {
"name": "Ubuntu",
"id": 2
}],
"flavors": []
}];
return [200, adapters, {}];
});
@ -90,10 +94,10 @@ compassAppDev.run(function($httpBackend, settings, $http) {
}],
"supported_oses": [{
"name": "CentOs",
"os_id": 1
"id": 1
}, {
"name": "Ubuntu",
"os_id": 2
"id": 2
}]
};
return [200, adapter, {}];
@ -329,31 +333,31 @@ compassAppDev.run(function($httpBackend, settings, $http) {
var switchId = url.substring(index).split("/")[1];
var machines = [{
"id": Math.floor(Math.random() * 100 + 1),
"mac": "28.e5.ee.47.14.92",
"mac": "28.e5.ee.47.14.11",
"switch_ip": "172.29.8." + switchId,
"vlan": "1",
"port": "11"
}, {
"id": Math.floor(Math.random() * 100 + 1),
"mac": "28.e5.ee.47.a2.93",
"mac": "28.e5.ee.47.a2.22",
"switch_ip": "172.29.8." + switchId,
"vlan": "2",
"port": "12"
}, {
"id": Math.floor(Math.random() * 100 + 1),
"mac": "28.e5.ee.47.ee.32",
"mac": "28.e5.ee.47.ee.33",
"switch_ip": "172.29.8." + switchId,
"vlan": "2",
"port": "13"
}, {
"id": Math.floor(Math.random() * 100 + 1),
"mac": "28.e5.ee.47.33.66",
"mac": "28.e5.ee.47.33.44",
"switch_ip": "172.29.8." + switchId,
"vlan": "2",
"port": "14"
}, {
"id": Math.floor(Math.random() * 100 + 1),
"mac": "28.e5.ee.47.2c.22",
"mac": "28.e5.ee.47.2c.55",
"switch_ip": "172.29.8." + switchId,
"vlan": "2",
"port": "15"
@ -669,11 +673,11 @@ compassAppDev.run(function($httpBackend, settings, $http) {
console.log(method, url);
var subnetworks = [{
"id": 1,
"name": "net1",
//"name": "10.172.10.0/24",
"subnet": "10.172.10.0/24"
}, {
"id": 2,
"name": "net2",
//"name": "10.172.20.0/24",
"subnet": "10.172.20.0/24"
}];
return [200, subnetworks, {}];

View File

@ -35,9 +35,7 @@
<label class="col-xs-12 col-sm-3 col-md-3 control-label no-padding-right">Target System</label>
<div class="col-xs-12 col-sm-5">
<select name="targetsystem" class="width-100" ng-model="cluster.adapter_id" required>
<option value=""></option>
<option ng-repeat="adapter in allAdapters" value="{{adapter.id}}"> {{adapter.display_name}}</option>
<select ng-options="adapter.display_name for adapter in allAdapters" ng-model="cluster.adapter" ng-change="updateSelectedAdapter()" name="targetsystem" class="width-100" required>
</select>
</div>
<div class="help-block col-xs-12 col-sm-reset inline"> Required </div>
@ -47,13 +45,20 @@
<label class="col-xs-12 col-sm-3 control-label no-padding-right">OS</label>
<div class="col-xs-12 col-sm-5">
<select name="os" class="width-100" ng-model="cluster.os_id" required>
<option value=""></option>
<option ng-repeat="os in supported_oses" value="{{os.os_id}}"> {{os.name}}</option>
<select ng-options="os.name for os in supported_oses" ng-model="cluster.os" name="os" class="width-100" required>
</select>
</div>
<div class="help-block col-xs-12 col-sm-reset inline"> Required </div>
</div>
<div class="form-group" ng-hide="flavors.length == 0" ng-class="{'has-error':createClusterForm.flavors.$error.required&& !createClusterForm.flavors.$pristine}">
<label class="col-xs-12 col-sm-3 control-label no-padding-right">Flavor</label>
<div class="col-xs-12 col-sm-5">
<select ng-options="flavor.display_name for flavor in flavors" ng-model="cluster.flavor" name="os" class="width-100">
</select>
</div>
</div>
</form>
</div>
<div class="modal-footer">

View File

@ -61,11 +61,6 @@ angular.module('compass.cluster', [
url: '/log',
templateUrl: 'src/app/cluster/cluster-log.tpl.html',
authenticate: true
})
.state('cluster.monitoring', {
url: '/monitoring',
templateUrl: 'src/app/cluster/cluster-monitoring.tpl.html',
authenticate: true
});
})
@ -206,7 +201,13 @@ angular.module('compass.cluster', [
modalInstance.result.then(function(cluster) {
$scope.cluster = cluster;
dataService.createCluster(cluster).success(function(data, status) {
var postClusterData = {
"name": cluster.name,
"adapter_id": cluster.adapter.id,
"os_id": cluster.os.id,
"flavor_id": cluster.flavor.id
};
dataService.createCluster(postClusterData).success(function(data, status) {
wizardFactory.setClusterInfo(data);
angular.forEach($scope.allAdapters, function(adapter) {
if (adapter.id == $scope.cluster.adapter_id) {
@ -227,116 +228,6 @@ angular.module('compass.cluster', [
}
])
.controller('monitoringCtrl', ['$scope',
function($scope) {
$scope.options = {
renderer: 'area'
};
$scope.features = {
hover: {
xFormatter: function(x) {
return 't=' + x;
},
yFormatter: function(y) {
return '$' + y;
}
}
};
$scope.series = [{
name: 'Series 1',
color: 'steelblue',
data: [{
x: 0,
y: 23
}, {
x: 1,
y: 15
}, {
x: 2,
y: 79
}, {
x: 3,
y: 31
}, {
x: 4,
y: 60
}]
}, {
name: 'Series 2',
color: 'lightblue',
data: [{
x: 0,
y: 30
}, {
x: 1,
y: 20
}, {
x: 2,
y: 64
}, {
x: 3,
y: 50
}, {
x: 4,
y: 15
}]
}];
$scope.options2 = {
renderer: 'line'
};
$scope.features2 = {
hover: {
xFormatter: function(x) {
return 't=' + x;
},
yFormatter: function(y) {
return '$' + y;
}
}
};
$scope.series2 = [{
name: 'Series 1',
color: 'steelblue',
data: [{
x: 0,
y: 23
}, {
x: 1,
y: 15
}, {
x: 2,
y: 79
}, {
x: 3,
y: 31
}, {
x: 4,
y: 60
}]
}, {
name: 'Series 2',
color: 'lightblue',
data: [{
x: 0,
y: 30
}, {
x: 1,
y: 20
}, {
x: 2,
y: 64
}, {
x: 3,
y: 50
}, {
x: 4,
y: 15
}]
}];
}
])
.controller('configurationCtrl', ['$scope', 'dataService', '$stateParams', '$filter', 'ngTableParams',
function($scope, dataService, $stateParams, $filter, ngTableParams) {
var clusterId = $stateParams.id;
@ -384,13 +275,13 @@ var ModalInstanceCtrl = function($scope, $modalInstance, allAdapters, cluster) {
$scope.allAdapters = allAdapters;
$scope.cluster = cluster;
$scope.$watch('cluster.adapter_id', function() {
$scope.updateSelectedAdapter = function() {
angular.forEach($scope.allAdapters, function(adapter) {
if (adapter.id == $scope.cluster.adapter_id) {
if(adapter.id == $scope.cluster.adapter.id) {
$scope.supported_oses = adapter.supported_oses;
}
})
});
};
$scope.ok = function() {
$scope.result = 'ok';

View File

@ -4,5 +4,3 @@
<div ui-view></div>
</div>
</div>
<!-- might need this part for monitoring-->
<!--<iframe src="{{currentProjectUrl}}" style="width:500px;height:500px;"></iframe>-->

View File

@ -23,6 +23,8 @@ angular.module('compass.login', [
authService.login(credentials).success(function(data) {
authService.isAuthenticated = true;
$state.transitionTo("clusterList");
}).error(function(response) {
console.log(response);
})
}
})

View File

@ -0,0 +1,126 @@
angular.module('compass.monitoring', [
'ui.router',
'ui.bootstrap',
'compass.charts',
'ngAnimate',
'angular-rickshaw'
])
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('cluster.monitoring', {
url: '/monitoring',
templateUrl: 'src/app/monitoring/cluster-monitoring.tpl.html',
authenticate: true
})
})
.controller('monitoringCtrl', ['$scope',
function($scope) {
$scope.options = {
renderer: 'area'
};
$scope.features = {
hover: {
xFormatter: function(x) {
return 't=' + x;
},
yFormatter: function(y) {
return '$' + y;
}
}
};
$scope.series = [{
name: 'Series 1',
color: 'steelblue',
data: [{
x: 0,
y: 23
}, {
x: 1,
y: 15
}, {
x: 2,
y: 79
}, {
x: 3,
y: 31
}, {
x: 4,
y: 60
}]
}, {
name: 'Series 2',
color: 'lightblue',
data: [{
x: 0,
y: 30
}, {
x: 1,
y: 20
}, {
x: 2,
y: 64
}, {
x: 3,
y: 50
}, {
x: 4,
y: 15
}]
}];
$scope.options2 = {
renderer: 'line'
};
$scope.features2 = {
hover: {
xFormatter: function(x) {
return 't=' + x;
},
yFormatter: function(y) {
return '$' + y;
}
}
};
$scope.series2 = [{
name: 'Series 1',
color: 'steelblue',
data: [{
x: 0,
y: 23
}, {
x: 1,
y: 15
}, {
x: 2,
y: 79
}, {
x: 3,
y: 31
}, {
x: 4,
y: 60
}]
}, {
name: 'Series 2',
color: 'lightblue',
data: [{
x: 0,
y: 30
}, {
x: 1,
y: 20
}, {
x: 2,
y: 64
}, {
x: 3,
y: 50
}, {
x: 4,
y: 15
}]
}];
}
])

View File

@ -1,40 +0,0 @@
<script type="text/ng-template" id="addSwitchModal.html">
<div class="modal-header">
<h3 class="modal-title">Add Switch</h3>
</div>
<div class="modal-body">
<form name="addSwitchForm" class="form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label no-padding-right">Switch IP</label>
<div class="col-sm-9">
<input type="text" ng-model="newswitch.ip" placeholder="Switch IP" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label no-padding-right">Version</label>
<div class="col-sm-9">
<select ng-model="newswitch.credentials.version" required>
<option>1</option>
<option>2c</option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label no-padding-right">Community</label>
<div class="col-sm-9">
<input type="password" ng-model="newswitch.credentials.community" placeholder="Community" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label no-padding-right">Port Filter</label>
<div class="col-sm-9">{{test}}
<input type="text" ng-model="filters.ports" placeholder="Port Filter">
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="addSwitch()" ng-disabled="addSwitchForm.$invalid">Add</button>
<button class="btn btn-grey" ng-click="cancel()">Cancel</button>
</div>
</script>

View File

@ -8,7 +8,7 @@
<i class="ace-icon fa fa-times-circle bigger-120 light-grey"></i>
</span>
<div class="clearfix"></div>
<div ng-include="'src/app/server/find-new-servers.tpl.html'"></div>
<findservers results="foundResults"></findservers>
</div>
</div>
</div>
@ -84,12 +84,12 @@
<table ng-table="tableParams" class="table table-hover table-striped">
<thead>
<tr>
<th>
<!--th>
<label>
<input ng-model="selectall" ng-change="selectAllServers(selectall)" type="checkbox" class="ace">
<span class="lbl"></span>
</label>
</th>
</th-->
<th ng-repeat="column in server_columns" ng-show="column.visible" class="sortable" ng-class="{'sort-asc': tableParams.isSortBy(column.field, 'asc'), 'sort-desc': tableParams.isSortBy(column.field, 'desc')}" ng-click="tableParams.sorting(column.field, tableParams.isSortBy(column.field, 'asc') ? 'desc' : 'asc')">
<div>{{column.title}}</div>
</th>
@ -97,13 +97,13 @@
</thead>
<tbody>
<tr ng-repeat="server in $data | filter:search">
<td>
<tr ng-repeat="server in $data | filter:search" ng-class="{'success': server.new}">
<!--td>
<label>
<input ng-model="server.selected" type="checkbox" class="ace">
<span class="lbl"></span>
</label>
</td>
</td-->
<td ng-repeat="column in server_columns" ng-show="column.visible" sortable="column.field">
<span ng-switch on="column.field">
<span ng-switch-when="clusters">

View File

@ -2,7 +2,8 @@ angular.module('compass.server', [
'ui.router',
'ui.bootstrap',
'compass.charts',
'ngTable',
'compass.findservers',
'ngTable'
])
.config(function config($stateProvider) {
@ -28,7 +29,7 @@ angular.module('compass.server', [
$scope.hideunselected = '';
$scope.search = {};
$scope.allservers = machinesHostsData;
$scope.newFoundServers = [];
$scope.foundResults = [];
dataService.getServerColumns().success(function(data) {
$scope.server_columns = data.machines_hosts;
@ -97,186 +98,24 @@ angular.module('compass.server', [
});
};
$scope.commit = function() {
var selectedServers = [];
var noSelection = true;
angular.forEach($scope.allservers, function(sv) {
if (sv.selected) {
noSelection = false;
selectedServers.push(sv);
// add newly found servers at the top if allservers array
$scope.$watch('foundResults', function(newResults, oldResults) {
if (newResults != oldResults) {
for (var i = 0; i < newResults.length; i++) {
var sv = $filter('filter')($scope.allservers, newResults[i].mac, true);
if (sv.length == 0) {
newResults[i].machine_id = newResults[i].id;
delete newResults[i]['id'];
newResults[i].new = true;
$scope.allservers.unshift(newResults[i]);
}
}
})
if (noSelection) {
alert("Please select at least one server");
wizardFactory.setCommitState({});
} else {
wizardFactory.setServers(selectedServers);
wizardFactory.setAllMachinesHost($scope.allservers);
var commitState = {
"name": "sv_selection",
"state": "success",
"message": ""
};
wizardFactory.setCommitState(commitState);
if ($scope.tableParams) {
$scope.tableParams.$params.count = $scope.allservers.length;
$scope.tableParams.reload();
}
};
}
}, true);
})
.controller('findNewServersCtrl', function($scope, dataService, sortingService, $timeout, $modal, $filter, ngTableParams) {
$scope.switches = [];
$scope.newFoundServers = [];
$scope.findingNewServers = false;
var switchTimer;
var fireTimer = true;
dataService.getServerColumns().success(function(data) {
$scope.server_columns = data.machines;
});
var getSwitches = function() {
dataService.getSwitches().success(function(data) {
$scope.switches = data;
})
};
getSwitches();
$scope.selectAllSwitches = function(flag) {
if (flag) {
angular.forEach($scope.switches, function(sv) {
sv.selected = true;
})
} else {
angular.forEach($scope.switches, function(sv) {
sv.selected = false;
})
}
};
$scope.open = function(size) {
var modalInstance = $modal.open({
templateUrl: 'addSwitchModal.html',
controller: addSwitchCtrl
});
modalInstance.result.then(function(newswitch) {
$scope.switches.push(newswitch);
}, function() {
console.info('Modal dismissed at: ' + new Date());
});
};
$scope.findServers = function() {
var swSelection = false;
angular.forEach($scope.switches, function(sw) {
if (sw.selected) {
swSelection = true;
}
});
if (!swSelection) {
alert("Please select at least one switch")
} else {
$scope.findingNewServers = true;
$scope.newFoundServers = [];
angular.forEach($scope.switches, function(sw) {
if (sw.selected) {
sw.result = "";
sw.finished = false;
sw.polling = true;
}
});
}
};
$scope.tableParamsNewServer = new ngTableParams({
page: 1, // show first page
count: $scope.newFoundServers.length, // count per page
}, {
counts: [], // hide count-per-page box
total: $scope.newFoundServers.length, // length of data
getData: function($defer, params) {
var reverse = false;
var orderBy = params.orderBy()[0];
var orderBySort = "";
var orderByColumn = "";
if (orderBy) {
orderByColumn = orderBy.substring(1);
orderBySort = orderBy.substring(0, 1);
if (orderBySort == "+") {
reverse = false;
} else {
reverse = true;
}
}
var orderedData = params.sorting() ?
$filter('orderBy')($scope.newFoundServers, function(item) {
if (orderByColumn == "switch_ip") {
return sortingService.ipAddressPre(item.switch_ip);
} else {
return item[orderByColumn];
}
}, reverse) : $scope.newFoundServers;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
$scope.$watch('switches', function(val) {
var totalResultReady = true;
if ($scope.findingNewServers) {
angular.forEach($scope.switches, function(sw) {
if (sw.selected && !sw.finished) {
if (sw.result == "success") {
$scope.newFoundServers = $scope.newFoundServers.concat(angular.copy(sw.machines));
sw.finished = true;
if ($scope.tableParamsNewServer) {
$scope.tableParamsNewServer.$params.count = $scope.newFoundServers.length;
$scope.tableParamsNewServer.reload();
}
} else if (sw.result == "error") {
sw.finished = true;
} else {
totalResultReady = false;
}
}
});
if (totalResultReady) {
$scope.findingNewServers = false;
}
}
}, true)
})
var addSwitchCtrl = function($scope, $modalInstance, dataService) {
$scope.newswitch = {}
$scope.newswitch.credentials = {};
$scope.filters = {};
$scope.addSwitch = function() {
dataService.postSwitches($scope.newswitch).success(function(switchData) {
if ($scope.filters) {
var filters = {
"filters": $scope.filters
};
dataService.putSwitchFilters(switchData.id, filters).success(function(filterData) {
switchData.filters = filterData.filters;
$scope.newswitch = {};
$scope.filters = {};
$modalInstance.close(switchData);
})
}
})
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
};

View File

@ -17,7 +17,7 @@ angular.module('compass.services', [])
app.stateProvider.state(pst.name, {
url: pst.url,
//controller: pst.controller,
templateUrl: 'src/app/cluster/cluster-' + pst.url.substring(1) + '.tpl.html'
templateUrl: 'src/app/monitoring/' + pst.url.substring(1) + '.tpl.html'
});
}
alreadyExist = false;

View File

@ -1,12 +1,4 @@
<div ng-controller="globalCtrl">
<div class="row">
<div class="col-xs-12">
<div class="accordion-style1 panel-group accordion-style2" id="accordion">
<accordion close-others="true">
<accordion-group ng-init="status1.open=true" is-open="status1.open">
<accordion-heading>
<i class="ace-icon fa fa-angle-right" ng-class="{'fa-angle-down': status1.open, 'fa-angle-right': !status1.open}"></i> General
</accordion-heading>
<div class="row">
<div class="col-xs-12">
<form id="generalForm" class="form-horizontal" role="form">
@ -171,26 +163,13 @@
</div>
</div>
</div>
</form>
</div>
</div>
</accordion-group>
<accordion-group is-open="status2.open">
<accordion-heading>
<i class="ace-icon fa fa-angle-right" ng-class="{'fa-angle-down': status2.open, 'fa-angle-right': !status2.open}"></i> Subnetwork
</accordion-heading>
<div class="row">
<div class="col-lg-2">
</div>
<div class="col-lg-8">
<table class="table table-hover nowrap">
<!--table class="table table-hover nowrap">
<thead>
<tr>
<th>Name</th>
<th>Subnet</th>
<!--th>Netmask</th-->
<th>Actions</th>
</tr>
</thead>
@ -202,15 +181,12 @@
<td>
<input type="text" ng-model="sub.subnet" placeholder="Subnet" />
</td>
<!--td>
<input type="text" ng-model="sub.netmask" placeholder="Netmask" />
</td-->
<td>
<!--Add Action-->
<span class="action" ng-click="addSubnetwork()">
<i class="fa fa-plus-circle bigger-140 blue"></i>
</span>
<!--Remove Action-->
<span ng-show="subnetworks.length > 1" class="action" ng-click="removeSubnetwork($index)">
<i class="fa fa-minus-circle bigger-140 blue"></i>
</span>
@ -218,66 +194,8 @@
</tr>
</tbody>
</table>
</div>
<div class="col-lg-2">
</div>
</div>
</table!-->
</accordion-group>
<!--Keep routing table for later use-->
<!--<accordion-group is-open="status.open">
<accordion-heading>
<i class="ace-icon fa fa-angle-right" ng-class="{'fa-angle-down': status.open, 'fa-angle-right': !status.open}"></i> Routing Table
</accordion-heading>
<div class="row">
<div class="col-lg-2">
</div>
<div class="col-lg-8">
<table class="table table-hover nowrap">
<thead>
<tr>
<th>Name</th>
<th>Subnet</th>
<th>Netmask</th>
<th>Gateway</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="route in routingtable">
<td>
<input type="text" ng-model="route.name" placeholder="Name" />
</td>
<td>
<input type="text" ng-model="route.subnet" placeholder="Subnet" />
</td>
<td>
<input type="text" ng-model="route.netmask" placeholder="Netmask" />
</td>
<td>
<input type="text" ng-model="route.gateway" placeholder="Gateway" />
</td>
<td>
<span class="action" ng-click="addRoute()">
<i class="fa fa-plus-circle bigger-140 blue"></i>
</span>
<span ng-show="routingtable.length > 1" class="action" ng-click="removeRoute($index)">
<i class="fa fa-minus-circle bigger-140 blue"></i>
</span>
</td>
</tr>
</tbody>
</table>
</div>
<div class="col-sm-2">
</div>
</div>
</accordion-group>-->
</accordion>
</div>
</div>
</div>
</div>

View File

@ -6,15 +6,19 @@
</span>
<div class="clearfix"></div>
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-6">
<h4>Interfaces Management</h4>
<div class="col-sm-12">
<h4>
Autofill IP Address for Each Interface
<button class="btn btn-sm btn-info pull-right" ng-click="openAddSubnetModal()">Add Subnet</button>
</h4>
<table class="table table-hover nowrap">
<thead>
<tr>
<th>Interface</th>
<th>Subnet</th>
<th>Is Mgmt Network</th>
<th>Promisc</th>
<th>Promisc Mode</th>
<th>Subnet</th>
<th>Autofill Rules</th>
<th>Action</th>
</tr>
</thead>
@ -23,29 +27,25 @@
<td>
<input class="input-small" type="text" ng-model="newInterface.name" placeholder="Interface" required />
</td>
<td></td>
<td></td>
<td>
<select ng-model="newInterface.subnet_id" class="max-width-200">
<option ng-repeat="sub in subnetworks" value="{{sub.id}}">
{{sub.name}}
{{sub.subnet}}
</option>
</select>
</td>
<td>-</td>
<td>-</td>
<td></td>
<td>
<span ng-click="addInterface(newInterface)" class="action">
<i class="fa fa-plus-circle bigger-140 blue"></i>
</span>
</td>
</tr>
<tr ng-repeat="(name, value) in interfaces">
<tr ng-repeat="(interface_name, value) in interfaces track by $index">
<td>
{{name}}
</td>
<td>
<span ng-repeat="sub in subnetworks">
<span ng-if="sub.id == value.subnet_id">{{sub.name}}</span>
</span>
{{interface_name}}
</td>
<td>
<label>
@ -60,54 +60,50 @@
</label>
</td>
<td>
<!--Remove Action-->
<span class="action" ng-click="deleteInterface(name)">
<i class="fa fa-minus-circle bigger-140 blue"></i>
</span>
</td>
</tr>
</tbody>
</table>
<div class="space-10"></div>
</div>
<div class="col-lg-6 col-md-6 col-sm-6 autofill-section">
<h4>Autofill</h4>
<form role="form" class="form-horizontal ng-pristine ng-valid" id="autoForm">
<div class="form-group">
<div>
<label class="col-sm-3 control-label no-padding-right">
Hostname
</label>
<div class="col-sm-9">
<select id="hostname-rule" class="input-medium ng-pristine ng-valid">
<option value="host">Host</option>
<option value="switch_ip">Switch IP</option>
<select ng-model="value.subnet_id" class="max-width-200">
<option ng-repeat="sub in subnetworks" value="{{sub.id}}" ng-selected="sub.id == value.subnet_id">
{{sub.subnet}}
</option>
</select>
</div>
</div>
</div>
<div ng-repeat="(name, value) in interfaces" class="form-group">
<label class="col-sm-3 control-label no-padding-right">
{{name}}&nbsp;IP
</label>
<div class="col-sm-9">
<input id="{{name}}-ipstart" type="text" class="input-medium" placeholder="IP Start">
<select id="{{name}}-increase-num">
</td>
<td>
<input id="{{interface_name}}-ipstart" type="text" class="input-medium" placeholder="IP Start">
<select id="{{interface_name}}-increase-num">
<option value="1">Increase by 1</option>
<option value="2">Increase by 2</option>
<option value="3">Increase by 3</option>
<option value="4">Increase by 4</option>
<option value="5">Increase by 5</option>
</select>
</div>
</div>
<div class="col-sm-offset-4">
</td>
<td>
<!--Remove Action-->
<span class="action" ng-click="deleteInterface(interface_name)">
<i class="fa fa-minus-circle bigger-140 blue"></i>
</span>
</td>
</tr>
</tbody>
</table>
<div class="space-10"></div>
<hr>
<div class="space-10"></div>
<h4>Autofill Hostname</h4>
<select id="hostname-rule" class="input-large">
<option value="">Please select a pattern</option>
<option value="host">Host</option>
<option value="switch_ip">Switch IP</option>
</select>
<div class="space-10"></div>
<div class="center">
<button ng-click="autofill()" class="btn btn-sm btn-primary">
Fill Values
</button>
</div>
</form>
<div class="space-10"></div>
</div>
</div>
<div class="space-10"></div>
@ -214,4 +210,52 @@
</tbody>
</table>
</div>
<div>
<script type="text/ng-template" id="addSubnetModal.html">
< div class = "modal-header" >
< h3 class = "modal-title" >
Subnetwork < /h3>
</div >
< div class = "modal-body" >
< alert ng - repeat = "alert in alerts"
type = "danger"
close = "closeAlert()" > {
{
alert.message
}
} < /alert>
<table class="table table-hover nowrap">
<thead>
<tr>
<th>Subnet</th >
< th > Actions < /th>
</tr >
< /thead>
<tbody>
<tr ng-repeat="sub in subnetworks">
<td>
<input type="text" ng-model="sub.subnet" placeholder="Subnet" / >
< /td>
<td>
<span class="action" ng-click="addSubnetwork()">
<i class="fa fa-plus-circle bigger-140 blue"></i >
< /span>
<span ng-show="subnetworks.length > 1" class="action" ng-click="removeSubnetwork($index)">
<i class="fa fa-minus-circle bigger-140 blue"></i >
< /span>
</td >
< /tr>
</tbody >
< /table>
</div >
< div class = "modal-footer" >
< button class = "btn btn-primary"
ng - click = "ok()" > OK < /button>
<button class="btn btn-grey" ng-click="cancel()">Cancel</button >
< /div>
</script>
</div>
</div>

View File

@ -171,45 +171,45 @@
<table class="table table-striped">
<thead>
<tr>
<th> Service </th>
<th>Username</th >
<th> Password </th>
<th>Service</th>
<th>Username</th>
<th>Password</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(key, value) in service_credentials">
<td>{{key}}</td>
<td> {{value.username}}</td>
<td>{{value.username}}</td>
<td>{{value.password}}</td >
</tr>
</tbody >
</tbody>
</table>
</script>
<script type="text/ng-template" id="console.tpl.html">
<table class="table table-striped" >
<table class="table table-striped">
<thead>
<tr>
<th> Service </th>
<th>Username</th >
<th> Password </th>
<th>Service</th>
<th>Username</th>
<th>Password</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(key, value) in management_credentials">
<td>{{key}}</td>
<td>{{key}}</td >
<td>{{value.username}}</td>
<td>{{value.password}}</td>
</tr>
</tbody >
</tbody>
</table>
</script>
<script type="text/ng-template" id="server.tpl.html">
<h6>
<strong> Username: </strong>
<strong>Username:</strong>
{{server_credentials.username}}
</h6>
<h6>
<strong> Password: </strong>
<strong>Password:</strong>
{{server_credentials.password}}
</h6>
</script>
@ -218,5 +218,34 @@
</div>
</div>
</div>
<div class="col-sm-6">
<div class="widget-box transparent margin-top-minus10">
<div class="widget-header widget-header-flat">
<h4 class="widget-title lighter">
<i class="ace-icon fa fa-globe"></i>
OS Global Configurations
</h4>
<div class="widget-toolbar">
<a class="action" ng-click="isPartitionCollapsed = !isPartitionCollapsed">
<i class="ace-icon fa fa-chevron-up" ng-class="{'fa-chevron-up': !isPartitionCollapsed, 'fa-chevron-down': isPartitionCollapsed}"></i>
</a>
</div>
</div>
<div class="widget-body">
<div class="widget-body-inner" style="display: block;">
<div class="widget-main no-padding" collapse="isPartitionCollapsed">
<table class="table table-striped">
<tbody>
<tr ng-repeat="(key, value) in global_config">
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -26,7 +26,7 @@
<div class="form-group">
<label class="col-sm-4 control-label no-padding-right">Confirm Password</label>
<div class="col-sm-8">
<input type="password" class="col-xs-10 col-sm-5" placeholder="Confirm Password" value="{{server_credentials.password}}">
<input type="password" class="col-xs-10 col-sm-5" placeholder="Confirm Password">
</div>
</div>
</form>

View File

@ -1,4 +1,15 @@
<div ng-controller="svSelectCtrl">
<div class="row">
<div collapse="findNewServersPanel.isCollapsed">
<div class="dashed-panel">
<span class="action pull-right" ng-click="findNewServersPanel.isCollapsed = true;">
<i class="ace-icon fa fa-times-circle bigger-120 light-grey"></i>
</span>
<div class="clearfix"></div>
<findservers results="foundResults"></findservers>
</div>
</div>
</div>
<div class="row">
<div class="pull-left">
<!--Search Input-->
@ -25,6 +36,12 @@
</div>
</div>
<div class="pull-right">
<button class="btn btn-info" ng-click="findNewServersPanel.isCollapsed = !findNewServersPanel.isCollapsed" ng-init="findNewServersPanel.isCollapsed = true;">
Discover Servers&nbsp;&nbsp;
<i class="ace-icon fa fa-plus" ng-class="{'fa-minus': !findNewServersPanel.isCollapsed}"></i>
</button>
</div>
<div class="pull-right side-padding-20">
<div class="checkbox">
<label>
<input ng-model="hideunselected" ng-change="hideUnselected()" type="checkbox" class="ace">
@ -54,7 +71,7 @@
</thead>
<tbody>
<tr ng-repeat="server in $data | filter:search">
<tr ng-repeat="server in $data | filter:search" ng-class="{'success': server.new}">
<td>
<label>
<input ng-model="server.selected" type="checkbox" class="ace">

View File

@ -3,6 +3,7 @@ angular.module('compass.wizard', [
'ui.bootstrap',
'ngTable',
'compass.charts',
'compass.findservers',
'ngDragDrop',
'ngTouch',
'angularSpinner'
@ -30,125 +31,103 @@ angular.module('compass.wizard', [
deferred.resolve(data);
});
return deferred.promise;
},
wizardStepsData: function($q, dataService) {
var deferred = $q.defer();
dataService.getWizardSteps().success(function(data) {
deferred.resolve(data);
});
return deferred.promise;
}
}
});
})
.controller('wizardCtrl', function($scope, dataService, wizardFactory, $stateParams, $state, clusterData, machinesHostsData, usSpinnerService) {
.controller('wizardCtrl', function($scope, dataService, wizardFactory, $stateParams, $state, $modal, clusterData, machinesHostsData, wizardStepsData, usSpinnerService) {
$scope.clusterId = $stateParams.id;
$scope.cluster = clusterData;
wizardFactory.setClusterInfo($scope.cluster);
wizardFactory.setAllMachinesHost(machinesHostsData);
// get pre-config data for wizard
if ($stateParams.config == "true") {
dataService.getWizardPreConfig().success(function(data) {
wizardFactory.preConfig(data);
//$scope.cluster = wizardFactory.getClusterInfo();
});
}
$scope.currentStep = 1;
$scope.pendingStep = 1;
$scope.maxStep = 1;
$scope.pendingStep = 1;
// Functions used only in HTML
$scope.startSpin = function() {
usSpinnerService.spin('spinner-1');
}
$scope.stopSpin = function() {
usSpinnerService.stop('spinner-1');
}
$scope.testSpinClick = function() {
//usSpinnerService.stop('spinner-1');
usSpinnerService.spin('spinner-1');
}
// get the wizard steps for create-cluster
dataService.getWizardSteps().success(function(data) {
// get the wizard steps for os, ts or os_and_ts
$scope.steps = data["os_and_ts"];
// get the create-cluster-wizard steps for os, ts or os_and_ts
$scope.steps = wizardStepsData["os_and_ts"];
wizardFactory.setSteps($scope.steps);
$scope.$watch('pendingStep', function(newStep, oldStep) {
if (newStep != oldStep) {
if ($scope.pendingStep <= $scope.maxStep + 1) {
if ((($scope.pendingStep == 6 || $scope.pendingStep == 7) && $scope.steps[2].state == "incomplete") || (($scope.pendingStep == 7 || $scope.pendingStep == 8) && $scope.steps[5].state == "incomplete") || ($scope.pendingStep == 8 && $scope.steps[6].state == "incomplete")) {
usSpinnerService.stop('spinner-1');
alert("Please make sure pre-requisite steps are complete.");
previousStepsComplete = false;
$scope.pendingStep = $scope.currentStep;
return;
} else {
var previousStepsComplete = true;
//usSpinnerService.spin('spinner-1');
if (previousStepsComplete == true) {
if (oldStep != 8) {
var commitState = {
"name": $scope.steps[oldStep - 1].name,
"state": "triggered",
"message": ""
// start loading spinner
$scope.startSpin = function() {
usSpinnerService.spin('spinner-1');
};
wizardFactory.setCommitState(commitState);
} else {
$scope.updateStepProgress($scope.pendingStep, $scope.currentStep);
$scope.currentStep = $scope.pendingStep;
//usSpinnerService.stop('spinner-1');
}
}
}
} else {
usSpinnerService.stop('spinner-1');
alert("Please complete previous steps first");
$scope.pendingStep = $scope.currentStep;
}
}
});
// go to next step
$scope.stepForward = function() {
// trigger commit for current step
var commitState = {
"name": $scope.steps[$scope.currentStep - 1].name,
"state": "triggered",
"message": ""
};
wizardFactory.setCommitState(commitState);
// stop loading spinner
$scope.stopSpin = function() {
usSpinnerService.stop('spinner-1');
};
// Watch commit state change
$scope.$watch(function() {
return wizardFactory.getCommitState()
}, function(newCommitState, oldCommitState) {
if ((newCommitState != oldCommitState) && (newCommitState.name == $scope.steps[$scope.currentStep - 1].name)) {
if (newCommitState != oldCommitState && newCommitState.name == $scope.steps[$scope.currentStep - 1].name) {
if (newCommitState.state == "success") {
console.warn("### catch success in wizardCtrl ###", newCommitState, oldCommitState);
$scope.alert = "";
if (newCommitState.name == "review") {
$state.go("cluster.overview", {
'id': $scope.cluster.id
});
}
$scope.updateStepProgress($scope.pendingStep, $scope.currentStep);
$scope.currentStep = $scope.pendingStep;
$scope.stepControl();
if ($scope.currentStep > $scope.maxStep) {
$scope.maxStep = $scope.currentStep;
}
//usSpinnerService.stop('spinner-1');
} else if (newCommitState.state == "error") {
$scope.pendingStep = $scope.currentStep;
// TODO: error handling / display error message
console.warn("### catch error in wizardCtrl ###", newCommitState, oldCommitState);
$scope.alerts = [];
$scope.alerts.push(newCommitState.message);
usSpinnerService.stop('spinner-1');
$scope.openErrMessageModal(newCommitState.message);
}
}
})
});
$scope.stepControl = function() {
if ($scope.pendingStep <= $scope.maxStep + 1) {
var previousStepsIncomplete = false;
for (var i = 0; i < $scope.pendingStep - 1; i++) {
if ($scope.steps[i].state == "incomplete") {
previousStepsIncomplete = true;
break;
}
}
if (previousStepsIncomplete) {
var message = {
"message": "Please make sure pre-requisite steps are complete."
};
alert(message.message);
} else {
$scope.updateStepProgress($scope.pendingStep, $scope.currentStep);
$scope.currentStep = $scope.pendingStep;
}
} else {
var message = {
"message": "Please complete previous steps first"
};
alert(message.message);
$scope.pendingStep = $scope.currentStep;
}
}
// Updates CSS Classes on Step state change
$scope.updateStepProgress = function(newStep, oldStep) {
@ -173,54 +152,37 @@ angular.module('compass.wizard', [
$scope.steps[6].state = "incomplete";
}
}
if (newStep == 6) {
if ($scope.maxStep > 6) {
$scope.steps[6].state = "incomplete";
}
}
if (oldStep == 8) {
$scope.steps[7].state = "";
}
};
$scope.stepForward = function() {
if ($scope.currentStep == $scope.steps.length) {
usSpinnerService.stop('spinner-1');
}
if ($scope.currentStep != $scope.steps.length) {
if ($scope.pendingStep < $scope.steps.length)
$scope.pendingStep = $scope.pendingStep + 1;
}
$scope.triggerCommit = function(stepId) {
if ($scope.steps[stepId - 1].name != "review") {
var commitState = {
"name": $scope.steps[stepId - 1].name,
"state": "triggered",
"message": {}
};
// go to previous step
$scope.stepBackward = function() {
if ($scope.currentStep == 1) {
usSpinnerService.stop('spinner-1');
wizardFactory.setCommitState(commitState);
} else {
$scope.stepControl();
$scope.updateStepProgress($scope.pendingStep, 8);
//$scope.updateStepProgress($scope.pendingStep, stepId);
}
if ($scope.pendingStep > 1) {
$scope.pendingStep = $scope.pendingStep - 1;
}
};
// go to step by stepId
$scope.skipForward = function(stepId) {
$scope.pendingStep = stepId;
if ($scope.pendingStep == $scope.currentStep) {
usSpinnerService.stop('spinner-1');
}
};
$scope.deploy = function() {
var wizard_complete = true;
for (var i = 0; i < $scope.steps.length; i++)
if ($scope.steps[i].state == "incomplete") {
for (var i = 0; i < $scope.steps.length - 1; i++) {
if ($scope.steps[i].state != "complete") {
wizard_complete = false;
break;
}
if (wizard_complete == true) {
}
if (wizard_complete) {
var commitState = {
"name": $scope.steps[$scope.currentStep - 1].name,
"name": "review",
"state": "triggered",
"message": ""
};
@ -228,19 +190,49 @@ angular.module('compass.wizard', [
}
};
$scope.stepForward = function() {
$scope.triggerCommit($scope.currentStep);
$scope.pendingStep = $scope.currentStep + 1;;
};
// go to previous step
$scope.stepBackward = function() {
$scope.triggerCommit($scope.currentStep);
$scope.pendingStep = $scope.currentStep - 1;
};
// go to step by stepId
$scope.skipForward = function(stepId) {
if ($scope.currentStep != stepId) {
$scope.pendingStep = stepId;
$scope.triggerCommit($scope.currentStep);
}
};
$scope.openErrMessageModal = function(message) {
var modalInstance = $modal.open({
templateUrl: "messagemodal.html",
controller: wizardModalInstanceCtrl,
resolve: {
warning: function() {
return message;
}
}
});
modalInstance.result.then(function() {
}, function() {
console.log("modal dismissed")
})
};
dataService.getSubnetConfig().success(function(data) {
wizardFactory.setSubnetworks(data);
});
})
.controller('svSelectCtrl', function($scope, wizardFactory, dataService, $filter, ngTableParams, sortingService, usSpinnerService) {
.controller('svSelectCtrl', function($scope, wizardFactory, dataService, $filter, ngTableParams, sortingService) {
$scope.hideunselected = '';
$scope.search = {};
@ -248,8 +240,6 @@ angular.module('compass.wizard', [
$scope.allservers = wizardFactory.getAllMachinesHost();
usSpinnerService.stop('spinner-1');
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: $scope.allservers.length // count per page
@ -330,11 +320,13 @@ angular.module('compass.wizard', [
}
})
if (noSelection) {
alert("Please select at least one server");
var message = {
"message": "Please select at least one server"
}
var commitState = {
"name": "sv_selection",
"state": "error",
"message": ""
"message": message
};
wizardFactory.setCommitState(commitState);
} else {
@ -348,12 +340,32 @@ angular.module('compass.wizard', [
wizardFactory.setCommitState(commitState);
}
};
// add newly found servers at the top if allservers array
$scope.$watch('foundResults', function(newResults, oldResults) {
if (newResults != oldResults) {
for (var i = 0; i < newResults.length; i++) {
var sv = $filter('filter')($scope.allservers, newResults[i].mac, true);
if (sv.length == 0) {
newResults[i].machine_id = newResults[i].id;
delete newResults[i]['id'];
newResults[i].new = true;
$scope.allservers.unshift(newResults[i]);
}
}
if ($scope.tableParams) {
$scope.tableParams.$params.count = $scope.allservers.length;
$scope.tableParams.reload();
}
}
}, true);
})
.controller('globalCtrl', function($scope, wizardFactory, dataService, $q, usSpinnerService) {
.controller('globalCtrl', function($scope, wizardFactory, dataService, $q) {
var cluster = wizardFactory.getClusterInfo();
//For General Section
$scope.general = wizardFactory.getGeneralConfig();
if (!$scope.general["dns_servers"]) {
@ -366,8 +378,6 @@ angular.module('compass.wizard', [
$scope.general["no_proxy"] = [""];
}
usSpinnerService.stop('spinner-1');
$scope.addValue = function(key) {
$scope.general[key].push("");
};
@ -376,21 +386,6 @@ angular.module('compass.wizard', [
$scope.timezones = data;
});
//For Subnetworks Section
$scope.subnetworks = wizardFactory.getSubnetworks();
$scope.addSubnetwork = function() {
$scope.subnetworks.push({});
console.log($scope.subnetworks);
};
$scope.removeSubnetwork = function(index) {
$scope.subnetworks.splice(index, 1)
};
$scope.$watch('subnetworks', function() {
if ($scope.subnetworks.length == 0) {
$scope.subnetworks.push({});
}
}, true);
//For Routing Table Section
//keep routing table for later use
/*
@ -420,56 +415,27 @@ angular.module('compass.wizard', [
}
});
$scope.commit = function() {
var promises = [];
var os_global_general = {
"os_config": {
"general": $scope.general
}
};
var updateClusterConfig = dataService.updateClusterConfig(cluster.id, os_global_general).then(function(configData) {
wizardFactory.setGeneralConfig(configData.data["os_config"]["general"]);
}, function(response) {
return $q.reject(response);
});
promises.push(updateClusterConfig);
var subnetworks = [];
angular.forEach($scope.subnetworks, function(subnet) {
if (subnet.id === undefined) {
// post subnetworks
var updateSubnetConfig = dataService.postSubnetConfig(subnet).then(function(subnetData) {
subnetworks.push(subnetData.data);
}, function(response) {
return $q.reject(response);
});
promises.push(updateSubnetConfig);
} else {
// put subnetworks
var updateSubnetConfig = dataService.putSubnetConfig(subnet.id, subnet).then(function(subnetData) {
subnetworks.push(subnetData.data);
}, function(response) {
return $q.reject(response);
});
promises.push(updateSubnetConfig);
}
});
$q.all(promises).then(function() {
$scope.subnetworks = subnetworks;
wizardFactory.setSubnetworks($scope.subnetworks);
dataService.updateClusterConfig(cluster.id, os_global_general).success(function(configData) {
wizardFactory.setGeneralConfig($scope.general);
var commitState = {
"name": "os_global",
"state": "success",
"message": ""
};
wizardFactory.setCommitState(commitState);
}, function(response) {
console.log("promises error", response);
}).error(function(response) {
var commitState = {
"name": "os_global",
"state": "error",
"message": response.data
"message": response
};
wizardFactory.setCommitState(commitState);
});
@ -508,7 +474,7 @@ angular.module('compass.wizard', [
*/
})
.controller('networkCtrl', function($scope, wizardFactory, dataService, $filter, ngTableParams, sortingService, $q, usSpinnerService) {
.controller('networkCtrl', function($scope, wizardFactory, dataService, $filter, ngTableParams, sortingService, $q, $modal) {
var cluster = wizardFactory.getClusterInfo();
$scope.subnetworks = wizardFactory.getSubnetworks();
$scope.interfaces = wizardFactory.getInterfaces();
@ -518,11 +484,9 @@ angular.module('compass.wizard', [
$scope.server_columns = data.showless;
});
usSpinnerService.stop('spinner-1');
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: $scope.servers.length // count per page
count: $scope.servers.length + 1 // count per page
}, {
counts: [], // hide count-per-page box
total: $scope.servers.length, // length of data
@ -566,7 +530,7 @@ angular.module('compass.wizard', [
})
if (!isExist) {
$scope.interfaces[newInterface.name] = {
"subnet_id": newInterface.subnet_id,
"subnet_id": parseInt(newInterface.subnet_id),
"is_mgmt": false
}
}
@ -608,7 +572,6 @@ angular.module('compass.wizard', [
"reinstall_os": server.reinstallos
});
}
usSpinnerService.stop('spinner-1');
});
var interfaceCount = Object.keys($scope.interfaces).length;
@ -647,7 +610,7 @@ angular.module('compass.wizard', [
var network = {
"interface": key,
"ip": value.ip,
"subnet_id": $scope.interfaces[key].subnet_id,
"subnet_id": parseInt($scope.interfaces[key].subnet_id),
"is_mgmt": $scope.interfaces[key].is_mgmt,
"is_promiscuous": $scope.interfaces[key].is_promiscuous
};
@ -699,19 +662,35 @@ angular.module('compass.wizard', [
wizardFactory.setCommitState(commitState);
}, function(response) {
wizardFactory.setServers($scope.servers);
console.info($scope.servers)
var commitState = {
"name": "network",
"state": "error",
"message": response.statusText
"message": response.data
};
console.info(response);
console.info(response.data);
wizardFactory.setCommitState(commitState);
});
});
}
};
$scope.openAddSubnetModal = function() {
var modalInstance = $modal.open({
templateUrl: "addSubnetModal.html",
controller: addSubnetModalInstanceCtrl,
resolve: {
subnets: function() {
return $scope.subnetworks;
}
}
});
modalInstance.result.then(function(subnets) {
$scope.subnetworks = subnets;
}, function() {
console.log("modal dismissed")
})
};
$scope.autofill = function() {
// Autofill IP for each interface
angular.forEach($scope.interfaces, function(value, key) {
@ -725,6 +704,7 @@ angular.module('compass.wizard', [
};
$scope.fillHostname = function(rule) {
if (rule) {
switch (rule) {
case "host":
var server_index = 1;
@ -739,6 +719,7 @@ angular.module('compass.wizard', [
})
break;
}
}
};
$scope.fillIPBySequence = function(ipStart, interval, interface) {
@ -774,7 +755,7 @@ angular.module('compass.wizard', [
}
})
.controller('partitionCtrl', function($scope, wizardFactory, dataService, usSpinnerService) {
.controller('partitionCtrl', function($scope, wizardFactory, dataService) {
var cluster = wizardFactory.getClusterInfo();
$scope.partition = wizardFactory.getPartition();
@ -816,8 +797,6 @@ angular.module('compass.wizard', [
}
});
usSpinnerService.stop('spinner-1');
$scope.commit = function() {
var os_partition = {
"os_config": {
@ -843,7 +822,7 @@ angular.module('compass.wizard', [
};
})
.controller('securityCtrl', function($scope, wizardFactory, dataService, usSpinnerService) {
.controller('securityCtrl', function($scope, wizardFactory, dataService) {
var cluster = wizardFactory.getClusterInfo();
$scope.server_credentials = wizardFactory.getServerCredentials();
$scope.service_credentials = wizardFactory.getServiceCredentials();
@ -978,10 +957,9 @@ angular.module('compass.wizard', [
wizardFactory.setCommitState(commitState);
});
};
usSpinnerService.stop('spinner-1');
})
.controller('roleAssignCtrl', function($scope, wizardFactory, dataService, $filter, ngTableParams, sortingService, $q, usSpinnerService) {
.controller('roleAssignCtrl', function($scope, wizardFactory, dataService, $filter, ngTableParams, sortingService, $q) {
var cluster = wizardFactory.getClusterInfo();
$scope.servers = wizardFactory.getServers();
@ -994,8 +972,6 @@ angular.module('compass.wizard', [
$scope.server_columns = data.showless;
});
usSpinnerService.stop('spinner-1');
$scope.selectAllServers = function(flag) {
if (flag) {
angular.forEach($scope.servers, function(sv) {
@ -1079,7 +1055,7 @@ angular.module('compass.wizard', [
}, true);
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: $scope.servers.length // count per page
count: $scope.servers.length + 1 // count per page
}, {
counts: [], // hide count-per-page box
total: $scope.servers.length, // length of data
@ -1179,13 +1155,11 @@ angular.module('compass.wizard', [
};
})
.controller('networkMappingCtrl', function($scope, wizardFactory, dataService, usSpinnerService) {
.controller('networkMappingCtrl', function($scope, wizardFactory, dataService) {
var cluster = wizardFactory.getClusterInfo();
$scope.interfaces = wizardFactory.getInterfaces();
$scope.networking = wizardFactory.getNetworkMapping();
usSpinnerService.stop('spinner-1');
$scope.pendingInterface = "";
$scope.onDrop = function($event, key) {
@ -1256,7 +1230,7 @@ angular.module('compass.wizard', [
};
})
.controller('reviewCtrl', function($scope, wizardFactory, dataService, $filter, ngTableParams, sortingService, usSpinnerService) {
.controller('reviewCtrl', function($scope, wizardFactory, dataService, $filter, ngTableParams, sortingService) {
var cluster = wizardFactory.getClusterInfo();
$scope.servers = wizardFactory.getServers();
$scope.interfaces = wizardFactory.getInterfaces();
@ -1265,13 +1239,12 @@ angular.module('compass.wizard', [
$scope.server_credentials = wizardFactory.getServerCredentials();
$scope.service_credentials = wizardFactory.getServiceCredentials();
$scope.management_credentials = wizardFactory.getManagementCredentials();
$scope.global_config = wizardFactory.getGeneralConfig();
dataService.getServerColumns().success(function(data) {
$scope.server_columns = data.review;
});
usSpinnerService.stop('spinner-1');
$scope.tabs = [{
title: 'Database & Queue',
url: 'service.tpl.html'
@ -1295,7 +1268,7 @@ angular.module('compass.wizard', [
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: $scope.servers.length // count per page
count: $scope.servers.length + 1// count per page
}, {
counts: [], // hide count-per-page box
total: $scope.servers.length, // length of data
@ -1370,4 +1343,75 @@ angular.module('compass.wizard', [
})
//TODO: error handling
};
})
});
var wizardModalInstanceCtrl = function($scope, $modalInstance, warning) {
$scope.warning = warning;
$scope.ok = function() {
$modalInstance.close();
};
};
var addSubnetModalInstanceCtrl = function($scope, $modalInstance, $q, subnets, dataService) {
$scope.subnetworks = subnets;
$scope.ok = function() {
var subnetworks = [];
var promises = [];
angular.forEach($scope.subnetworks, function(subnet) {
if (subnet.id === undefined) {
// post subnetworks
var updateSubnetConfig = dataService.postSubnetConfig(subnet).then(function(subnetData) {
subnetworks.push(subnetData.data);
}, function(response) {
return $q.reject(response);
});
promises.push(updateSubnetConfig);
} else {
// put subnetworks
var updateSubnetConfig = dataService.putSubnetConfig(subnet.id, subnet).then(function(subnetData) {
subnetworks.push(subnetData.data);
}, function(response) {
return $q.reject(response);
});
promises.push(updateSubnetConfig);
}
});
$q.all(promises).then(function() {
$scope.subnetworks = subnetworks;
$modalInstance.close($scope.subnetworks);
}, function(response) {
console.log("promises error", response);
$scope.alerts = [];
$scope.alerts.push({
"message": response
});
});
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
$scope.closeAlert = function() {
$scope.alerts = [];
};
$scope.addSubnetwork = function() {
$scope.subnetworks.push({});
console.log($scope.subnetworks);
};
$scope.removeSubnetwork = function(index) {
$scope.subnetworks.splice(index, 1)
};
$scope.$watch('subnetworks', function() {
if ($scope.subnetworks.length == 0) {
$scope.subnetworks.push({});
}
}, true);
};

View File

@ -1,6 +1,6 @@
<div class="main-content">
<div class="page-content" ng-swipe-right="startSpin(); stepForward()" ng-swipe-left="startSpin(); stepBackward()">
<!--div class="page-content" ng-swipe-right="stepForward()" ng-swipe-left="stepBackward()"-->
<div class="page-content">
<div class="page-header">
<h1>Create Cluster Wizard</h1>
<span us-spinner="{radius:30, length: 20, lines:13, width:10}" spinner-key="spinner-1"></span>
@ -8,7 +8,7 @@
<div id="create-cluster-wizard">
<ul class="wizard-steps">
<li ng-repeat="step in steps" class="{{step.state}}" ng-click="startSpin(); skipForward(step.id)">
<li ng-repeat="step in steps" class="{{step.state}}" ng-click="skipForward(step.id)">
<span class="step">{{step.id}}</span>
<span class="title">{{step.title}}</span>
</li>
@ -33,53 +33,45 @@
<div class="space-10"></div>
<div class="wizard-actions">
<div class="inline" ng-class="{'first-prev' : currentStep == 1}">
<button ng-click="stepBackward()" ng-disabled="currentStep==1" class="btn btn-grey btn-prev-spacing" ng-class="{'btn-light' : currentStep == 1}">
<button ng-click="stepBackward()" ng-disabled="currentStep == 1" class="btn btn-grey btn-prev-spacing" ng-class="{'btn-light' : currentStep == 1}">
<i class="ace-icon fa fa-arrow-left"></i>
Prev
</button>
</div>
<span ng-if="currentStep < steps.length">
<button ng-click="stepForward()" class="btn btn-success btn-next">
<span ng-if="currentStep<steps.length">
Next
<i class="ace-icon fa fa-arrow-right icon-on-right"></i>
</span>
<span ng-if="currentStep==steps.length">Deploy</span>
</button>
</div>
</div>
<div ng-repeat="alert in alerts" class="popup-alert">
<div class="gritter-item-wrapper gritter-error gritter-center">
<div class="gritter-top"></div>
<div class="gritter-item message">
<div class="gritter-close action pull-right" ng-click="alerts.splice($index, 1)"></div>
<div class="clearfix"></div>
<div class="gritter-without-image">
<p>
<span ng-if="!alert.message">Error</span>
<span ng-if="alert.message">{{alert.message}}</span>
</p>
</div>
<div class="clearfix"></div>
</div>
<div class="gritter-bottom">
</div>
</div>
<span ng-if="currentStep<steps.length">
<button ng-click="startSpin(); stepForward()" class="btn btn-success btn-next">
Next
<i class="ace-icon fa fa-arrow-right icon-on-right"></i>
</button>
</span>
<span ng-if="currentStep==steps.length">
<span ng-if="currentStep == steps.length">
<button ng-click="deploy()" class="btn btn-success btn-next">
<span>Deploy</span>
</button>
</span>
</div>
</div>
</div>
</div>
<div>
<script type="text/ng-template" id="messagemodal.html">
<div class="modal-header">
<h3 class="modal-title">
<i class="ace-icon fa fa-exclamation-triangle orange"></i>
Warning
</h3>
</div>
<div class="modal-body">
<span ng-if="warning.message">
{{warning.message}}
</span>
<span ng-if="warning.message === undefined">
Error occured.
</span>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
</div>
</script>
</div>

View File

@ -78,6 +78,7 @@ angular.module('compass.charts', [])
clusterstate: '=',
progressdata: '@'
},
templateUrl: "src/common/progressbar.tpl.html",
link: function(scope, element, attrs) {
var hostId = scope.hostid;
var clusterId = scope.clusterid;
@ -114,77 +115,7 @@ angular.module('compass.charts', [])
fireTimer = false;
$timeout.cancel(progressTimer);
});
},
templateUrl: "src/common/progressbar.tpl.html"
}
})
.directive('switchrow', function(dataService, $timeout) {
return {
restrict: 'A',
scope: {
polling: '=',
switchinfo: '=',
result: '=',
machines: '='
},
link: function(scope, element, attrs) {
var checkSwitchTimer;
var checkSwitchCount = 0;
//var pollingTriggered = scope.polling;
var fireTimer = true;
var getMachines = function() {
dataService.getSwitchMachines(scope.switchinfo.id).success(function(data) {
scope.polling = false;
scope.result = "success";
scope.machines = data;
}).error(function(data) {
scope.polling = false;
scope.result = "error";
})
};
// check switch state 15 times with the interval of 2 sec
var checkSwitchState = function() {
checkSwitchCount++;
dataService.getSwitchById(scope.switchinfo.id).success(function(data) {
if (data.state == "under_monitoring") {
getMachines();
} else if(data.state === "initialized" || data.state === "repolling")
if (fireTimer && checkSwitchCount < 15) {
checkSwitchTimer = $timeout(checkSwitchState, 2000);
} else {
scope.polling = false;
scope.result = "error";
}
else {
scope.polling = false;
scope.result = "error";
}
})
};
scope.$watch('polling', function(newval, oldval) {
if(newval != oldval) {
if (newval == true) {
checkSwitchCount = 0;
fireTimer = true;
var findingAction = {
"find_machines": null
};
dataService.postSwitchAction(scope.switchinfo.id, findingAction).success(function(data) {
checkSwitchState();
})
}
}
})
element.bind('$destroy', function() {
fireTimer = false;
$timeout.cancel(checkSwitchTimer);
});
}
}
})

View File

@ -1,17 +1,63 @@
<div class="row" ng-controller="findNewServersCtrl">
<div class="col-lg-5 col-md-5">
<div class="row">
<div class="col-lg-6 col-md-6">
<h4>
Add Switches
</h4>
<div>
Enter the IP address for the network switches on which the servers are connected.
</div>
<div class="space-10"></div>
<div>
<form name="addSwitchForm" class="form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label no-padding-right">Switch IP</label>
<div class="col-sm-9">
<input type="text" ng-model="newswitch.ip" placeholder="Switch IP" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label no-padding-right">Version</label>
<div class="col-sm-9">
<select ng-model="newswitch.credentials.version" required>
<option>1</option>
<option>2c</option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label no-padding-right">Community</label>
<div class="col-sm-9">
<input type="password" ng-model="newswitch.credentials.community" placeholder="Community" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label no-padding-right">Port Filter</label>
<div class="col-sm-9">
<input type="text" ng-model="filters.ports" placeholder="Port Filter">
</div>
</div>
</form>
<div class="clearfix">
<div class="col-md-offset-3 col-md-9">
<button class="btn btn-primary" ng-click="addSwitch()" ng-disabled="addSwitchForm.$invalid">Add</button>
</div>
</div>
</div>
</div>
<div class="col-lg-6 col-md-6">
<h4>
Discover available servers
</h4>
<!--span class="help-button pull-left" popover-trigger="mouseenter" popover-placement="right" popover-title="Help" popover="Enter the IP address for the network switches on which the servers are connected. Select as many switches as needed and then click Find Servers.">?</span>
<div class="clearfix"></div-->
<div>
Select as many switches as needed and then click Find Servers.
</div>
<div class="space-10"></div>
<table class="table table-striped table-hover">
<thead>
<tr>
<th>
<label>
<input ng-model="selectall" ng-change="selectAllSwitches(selectall)" type="checkbox" class="ace" ng-disabled="findingNewServers">
<input ng-model="selectall" ng-change="selectAllSwitches(selectall)" type="checkbox" class="ace" ng-disabled="isFindingNewServers">
<span class="lbl"></span>
</label>
</th>
@ -28,7 +74,7 @@
<tr ng-repeat="switch in switches" switchrow polling="switch.polling" machines="switch.machines" result="switch.result" switchinfo="switch">
<td>
<label>
<input type="checkbox" class="ace" ng-model="switch.selected" ng-disabled="findingNewServers && switch.selected && !switch.finished">
<input type="checkbox" class="ace" ng-model="switch.selected" ng-disabled="isFindingNewServers && switch.selected && !switch.finished">
<span class="lbl"></span>
</label>
</td>
@ -39,7 +85,7 @@
<span ng-if="switch.result == 'error'">
<i class="ace-icon fa fa-frown-o bigger-125 red"></i>
</span>
<span ng-if="findingNewServers && switch.selected && !switch.finished">
<span ng-if="isFindingNewServers && switch.selected && !switch.finished">
<i class="ace-icon fa fa-spinner fa-spin bigger-125 orange"></i>
</span>
</td>
@ -53,47 +99,10 @@
</table>
<div class="space-10"></div>
<div class="center">
<button class="btn btn-sm btn-success" ng-click="open()">
<span>
Add Switch
</span>
</button>
<button class="btn btn-sm btn-primary" ng-click="findServers()">
Discover Servers
</button>
</div>
<div ng-include="'src/app/server/add-switch-modal.tpl.html'"></div>
<div class="space-20"></div>
</div>
<div class="col-lg-7 col-md-7">
<h4>
Discover Results
<input class="pull-right" type="text" placeholder="Search" ng-model="search_new_server">
</h4>
<div class="space-10"></div>
<div class="table-responsive new-servers-result">
<table ng-table="tableParamsNewServer" class="table table-striped">
<thead>
<tr>
<th ng-repeat="column in server_columns" ng-show="column.visible" class="sortable" ng-class="{'sort-asc': tableParamsNewServer.isSortBy(column.field, 'asc'), 'sort-desc': tableParamsNewServer.isSortBy(column.field, 'desc')}" ng-click="tableParamsNewServer.sorting(column.field, tableParamsNewServer.isSortBy(column.field, 'asc') ? 'desc' : 'asc')">
<div>{{column.title}}</div>
</th>
</tr>
</thead>
<tbody>
<tr ng-show="tableParamsNewServer.data.length==0">
<td colspan="6" class="center">No results for selected switches</td>
</tr>
<tr ng-repeat="sv in $data | filter:search_new_server">
<td ng-repeat="column in server_columns" ng-show="column.visible">
<span>
{{sv[column.field]}}
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>

View File

@ -0,0 +1,168 @@
angular.module('compass.findservers', [])
.directive('switchrow', function(dataService, $timeout) {
return {
restrict: 'A',
scope: {
polling: '=',
switchinfo: '=',
result: '=',
machines: '='
},
link: function(scope, element, attrs) {
var checkSwitchTimer;
var checkSwitchCount = 0;
//var pollingTriggered = scope.polling;
var fireTimer = true;
var getMachines = function() {
dataService.getSwitchMachines(scope.switchinfo.id).success(function(data) {
scope.polling = false;
scope.result = "success";
scope.machines = data;
}).error(function(data) {
scope.polling = false;
scope.result = "error";
})
};
// check switch state 15 times with the interval of 2 sec
var checkSwitchState = function() {
checkSwitchCount++;
dataService.getSwitchById(scope.switchinfo.id).success(function(data) {
if (data.state == "under_monitoring") {
getMachines();
} else if(data.state === "initialized" || data.state === "repolling")
if (fireTimer && checkSwitchCount < 15) {
checkSwitchTimer = $timeout(checkSwitchState, 2000);
} else {
scope.polling = false;
scope.result = "error";
}
else {
scope.polling = false;
scope.result = "error";
}
})
};
scope.$watch('polling', function(newval, oldval) {
if(newval != oldval) {
if (newval == true) {
checkSwitchCount = 0;
fireTimer = true;
var findingAction = {
"find_machines": null
};
dataService.postSwitchAction(scope.switchinfo.id, findingAction).success(function(data) {
checkSwitchState();
})
}
}
})
element.bind('$destroy', function() {
fireTimer = false;
$timeout.cancel(checkSwitchTimer);
});
}
}
})
.directive('findservers', function(dataService, $modal) {
return {
restrict: 'E',
scope: {
newFoundServers: '=results'
},
templateUrl: "src/common/findservers/find-new-servers.tpl.html",
link: function(scope, element, attrs) {
scope.switches = [];
scope.newFoundServers = [];
scope.isFindingNewServers = false;
dataService.getSwitches().success(function(data) {
scope.switches = data;
});
scope.selectAllSwitches = function(flag) {
if (flag) {
angular.forEach(scope.switches, function(sv) {
sv.selected = true;
})
} else {
angular.forEach(scope.switches, function(sv) {
sv.selected = false;
})
}
};
scope.findServers = function() {
var swSelection = false;
angular.forEach(scope.switches, function(sw) {
if (sw.selected) {
swSelection = true;
}
});
if (!swSelection) {
alert("Please select at least one switch");
} else {
scope.isFindingNewServers = true;
scope.newFoundServers = [];
angular.forEach(scope.switches, function(sw) {
if (sw.selected) {
sw.result = "";
sw.finished = false;
sw.polling = true;
}
});
}
};
scope.$watch('switches', function(val) {
var totalResultReady = true;
if (scope.isFindingNewServers) {
angular.forEach(scope.switches, function(sw) {
if (sw.selected && !sw.finished) {
if (sw.result == "success") {
scope.newFoundServers = scope.newFoundServers.concat(angular.copy(sw.machines));
sw.finished = true;
} else if (sw.result == "error") {
sw.finished = true;
} else {
totalResultReady = false;
}
}
});
if (totalResultReady) {
scope.isFindingNewServers = false;
}
}
}, true);
scope.newswitch = {}
scope.newswitch.credentials = {};
scope.filters = {};
scope.addSwitch = function() {
dataService.postSwitches(scope.newswitch).success(function(switchData) {
if (scope.filters) {
var filters = {
"filters": scope.filters
};
dataService.putSwitchFilters(switchData.id, filters).success(function(filterData) {
switchData.filters = filterData.filters;
scope.newswitch = {};
scope.filters = {};
scope.switches.push(switchData);
})
}
})
};
}
};
})