You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by an...@apache.org on 2015/10/13 05:28:14 UTC
[13/18] ignite git commit: IGNITE-843 Web console initial commit.
http://git-wip-us.apache.org/repos/asf/ignite/blob/bce0deb7/modules/control-center-web/src/main/js/controllers/clusters-controller.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/controllers/clusters-controller.js b/modules/control-center-web/src/main/js/controllers/clusters-controller.js
new file mode 100644
index 0000000..3b95a2e
--- /dev/null
+++ b/modules/control-center-web/src/main/js/controllers/clusters-controller.js
@@ -0,0 +1,560 @@
+/*
+ *
+ * * Licensed to the Apache Software Foundation (ASF) under one or more
+ * * contributor license agreements. See the NOTICE file distributed with
+ * * this work for additional information regarding copyright ownership.
+ * * The ASF licenses this file to You under the Apache License, Version 2.0
+ * * (the "License"); you may not use this file except in compliance with
+ * * the License. You may obtain a copy of the License at
+ * *
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * *
+ * * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ *
+ */
+
+// Controller for Clusters screen.
+consoleModule.controller('clustersController', [
+ '$scope', '$controller', '$http', '$timeout', '$common', '$focus', '$confirm', '$message', '$clone', '$table', '$preview', '$loading', '$unsavedChangesGuard',
+ function ($scope, $controller, $http, $timeout, $common, $focus, $confirm, $message, $clone, $table, $preview, $loading, $unsavedChangesGuard) {
+ $unsavedChangesGuard.install($scope);
+
+ // Initialize the super class and extend it.
+ angular.extend(this, $controller('save-remove', {$scope: $scope}));
+
+ $scope.ui = $common.formUI();
+
+ $scope.showMoreInfo = $message.message;
+
+ $scope.joinTip = $common.joinTip;
+ $scope.getModel = $common.getModel;
+ $scope.compactJavaName = $common.compactJavaName;
+ $scope.saveBtnTipText = $common.saveBtnTipText;
+
+ $scope.tableReset = $table.tableReset;
+ $scope.tableNewItem = $table.tableNewItem;
+ $scope.tableNewItemActive = $table.tableNewItemActive;
+ $scope.tableEditing = $table.tableEditing;
+ $scope.tableStartEdit = $table.tableStartEdit;
+ $scope.tableRemove = function (item, field, index) {
+ $table.tableRemove(item, field, index);
+ };
+
+ $scope.tableSimpleSave = $table.tableSimpleSave;
+ $scope.tableSimpleSaveVisible = $table.tableSimpleSaveVisible;
+ $scope.tableSimpleUp = $table.tableSimpleUp;
+ $scope.tableSimpleDown = $table.tableSimpleDown;
+ $scope.tableSimpleDownVisible = $table.tableSimpleDownVisible;
+
+ var previews = [];
+
+ $scope.previewInit = function (preview) {
+ previews.push(preview);
+
+ $preview.previewInit(preview);
+ };
+
+ $scope.trustManagersConfigured = function() {
+ return $scope.backupItem.sslEnabled && $common.isDefined($scope.backupItem.sslContextFactory)
+ && !$common.isEmptyArray($scope.backupItem.sslContextFactory.trustManagers)
+ };
+
+ $scope.previewChanged = $preview.previewChanged;
+
+ $scope.hidePopover = $common.hidePopover;
+
+ var showPopoverMessage = $common.showPopoverMessage;
+
+ $scope.discoveries = [
+ {value: 'Vm', label: 'static IPs'},
+ {value: 'Multicast', label: 'multicast'},
+ {value: 'S3', label: 'AWS S3'},
+ {value: 'Cloud', label: 'apache jclouds'},
+ {value: 'GoogleStorage', label: 'google cloud storage'},
+ {value: 'Jdbc', label: 'JDBC'},
+ {value: 'SharedFs', label: 'shared filesystem'}
+ ];
+
+ $scope.swapSpaceSpis = [
+ {value: 'FileSwapSpaceSpi', label: 'File-based swap'},
+ {value: undefined, label: 'Not set'}
+ ];
+
+ $scope.events = [];
+
+ for (var eventGroupName in $dataStructures.EVENT_GROUPS) {
+ if ($dataStructures.EVENT_GROUPS.hasOwnProperty(eventGroupName)) {
+ $scope.events.push({value: eventGroupName, label: eventGroupName});
+ }
+ }
+
+ $scope.preview = {
+ general: {xml: '', java: '', allDefaults: true},
+ atomics: {xml: '', java: '', allDefaults: true},
+ communication: {xml: '', java: '', allDefaults: true},
+ deployment: {xml: '', java: '', allDefaults: true},
+ discovery: {xml: '', java: '', allDefaults: true},
+ events: {xml: '', java: '', allDefaults: true},
+ marshaller: {xml: '', java: '', allDefaults: true},
+ metrics: {xml: '', java: '', allDefaults: true},
+ p2p: {xml: '', java: '', allDefaults: true},
+ swap: {xml: '', java: '', allDefaults: true},
+ time: {xml: '', java: '', allDefaults: true},
+ pools: {xml: '', java: '', allDefaults: true},
+ transactions: {xml: '', java: '', allDefaults: true},
+ sslConfiguration: {xml: '', java: '', allDefaults: true}
+ };
+
+ $scope.cacheModes = $common.mkOptions(['LOCAL', 'REPLICATED', 'PARTITIONED']);
+
+ $scope.deploymentModes = $common.mkOptions(['PRIVATE', 'ISOLATED', 'SHARED', 'CONTINUOUS']);
+
+ $scope.transactionConcurrency = $common.mkOptions(['OPTIMISTIC', 'PESSIMISTIC']);
+
+ $scope.transactionIsolation = $common.mkOptions(['READ_COMMITTED', 'REPEATABLE_READ', 'SERIALIZABLE']);
+
+ $scope.segmentationPolicy = $common.mkOptions(['RESTART_JVM', 'STOP', 'NOOP']);
+
+ $scope.marshallers = $common.mkOptions(['OptimizedMarshaller', 'JdkMarshaller']);
+
+ $scope.sslKeyAlgorithms = ['SumX509', 'X509'];
+
+ $scope.sslStoreType = ['JKS', 'PCKS11', 'PCKS12'];
+
+ $scope.sslProtocols = ['TSL', 'SSL'];
+
+ $scope.toggleExpanded = function () {
+ $scope.ui.expanded = !$scope.ui.expanded;
+
+ $common.hidePopover();
+ };
+
+ $scope.panels = {activePanels: [0]};
+
+ var simpleTables = {
+ addresses: {msg: 'Such IP address already exists!', id: 'IpAddress'},
+ regions: {msg: 'Such region already exists!', id: 'Region'},
+ zones: {msg: 'Such zone already exists!', id: 'Zone'},
+ peerClassLoadingLocalClassPathExclude: {msg: 'Such package already exists!', id: 'PeerClsPathExclude'},
+ trustManagers: {msg: 'Such trust manager already exists!', id: 'trustManagers'}
+ };
+
+ $scope.tableSimpleValid = function (item, field, val, index) {
+ var model = $common.getModel(item, field)[field.model];
+
+ if (field.model == 'trustManagers' && !$common.isValidJavaClass('Trust manager', val, false, $table.tableFieldId(index, 'trustManagers'), false))
+ return false;
+
+ if ($common.isDefined(model)) {
+ var idx = _.indexOf(model, val);
+
+ // Found duplicate.
+ if (idx >= 0 && idx != index) {
+ var simpleTable = simpleTables[field.model];
+
+ if (simpleTable) {
+ $common.showPopoverMessage(null, null, $table.tableFieldId(index, 'trustManagers'), simpleTable.msg);
+
+ return $table.tableFocusInvalidField(index, simpleTable.id);
+ }
+ }
+ }
+
+ return true;
+ };
+
+ $scope.clusters = [];
+
+ function selectFirstItem() {
+ if ($scope.clusters.length > 0)
+ $scope.selectItem($scope.clusters[0]);
+ }
+
+ $loading.start('loadingClustersScreen');
+
+ // When landing on the page, get clusters and show them.
+ $http.post('clusters/list')
+ .success(function (data) {
+ $scope.spaces = data.spaces;
+ $scope.clusters = data.clusters;
+ $scope.caches = _.map(data.caches, function (cache) {
+ return {value: cache._id, label: cache.name, cache: cache};
+ });
+
+ // Load page descriptor.
+ $http.get('/models/clusters.json')
+ .success(function (data) {
+ $scope.screenTip = data.screenTip;
+ $scope.moreInfo = data.moreInfo;
+ $scope.general = data.general;
+ $scope.advanced = data.advanced;
+
+ $scope.ui.addGroups(data.general, data.advanced);
+
+ if ($common.getQueryVariable('new'))
+ $scope.createItem();
+ else {
+ var lastSelectedCluster = angular.fromJson(sessionStorage.lastSelectedCluster);
+
+ if (lastSelectedCluster) {
+ var idx = _.findIndex($scope.clusters, function (cluster) {
+ return cluster._id == lastSelectedCluster;
+ });
+
+ if (idx >= 0)
+ $scope.selectItem($scope.clusters[idx]);
+ else {
+ sessionStorage.removeItem('lastSelectedCluster');
+
+ selectFirstItem();
+ }
+ }
+ else
+ selectFirstItem();
+ }
+
+ $scope.$watch('backupItem', function (val) {
+ if (val) {
+ var clusterCaches = _.reduce($scope.caches, function(caches, cache){
+ if (_.contains(val.caches, cache.value)) {
+ caches.push(cache.cache);
+ }
+
+ return caches;
+ }, []);
+
+ var srcItem = $scope.selectedItem ? $scope.selectedItem : prepareNewItem();
+
+ $scope.ui.checkDirty(val, srcItem);
+
+ $scope.preview.general.xml = $generatorXml.clusterCaches(clusterCaches, $generatorXml.clusterGeneral(val)).asString();
+ $scope.preview.general.java = $generatorJava.clusterCaches(clusterCaches, $generatorJava.clusterGeneral(val)).asString();
+ $scope.preview.general.allDefaults = $common.isEmptyString($scope.preview.general.xml);
+
+ $scope.preview.atomics.xml = $generatorXml.clusterAtomics(val).asString();
+ $scope.preview.atomics.java = $generatorJava.clusterAtomics(val).asString();
+ $scope.preview.atomics.allDefaults = $common.isEmptyString($scope.preview.atomics.xml);
+
+ $scope.preview.communication.xml = $generatorXml.clusterCommunication(val).asString();
+ $scope.preview.communication.java = $generatorJava.clusterCommunication(val).asString();
+ $scope.preview.communication.allDefaults = $common.isEmptyString($scope.preview.communication.xml);
+
+ $scope.preview.deployment.xml = $generatorXml.clusterDeployment(val).asString();
+ $scope.preview.deployment.java = $generatorJava.clusterDeployment(val).asString();
+ $scope.preview.deployment.allDefaults = $common.isEmptyString($scope.preview.deployment.xml);
+
+ $scope.preview.discovery.xml = $generatorXml.clusterDiscovery(val.discovery).asString();
+ $scope.preview.discovery.java = $generatorJava.clusterDiscovery(val.discovery).asString();
+ $scope.preview.discovery.allDefaults = $common.isEmptyString($scope.preview.discovery.xml);
+
+ $scope.preview.events.xml = $generatorXml.clusterEvents(val).asString();
+ $scope.preview.events.java = $generatorJava.clusterEvents(val).asString();
+ $scope.preview.events.allDefaults = $common.isEmptyString($scope.preview.events.xml);
+
+ $scope.preview.marshaller.xml = $generatorXml.clusterMarshaller(val).asString();
+ $scope.preview.marshaller.java = $generatorJava.clusterMarshaller(val).asString();
+ $scope.preview.marshaller.allDefaults = $common.isEmptyString($scope.preview.marshaller.xml);
+
+ $scope.preview.metrics.xml = $generatorXml.clusterMetrics(val).asString();
+ $scope.preview.metrics.java = $generatorJava.clusterMetrics(val).asString();
+ $scope.preview.metrics.allDefaults = $common.isEmptyString($scope.preview.metrics.xml);
+
+ $scope.preview.p2p.xml = $generatorXml.clusterP2p(val).asString();
+ $scope.preview.p2p.java = $generatorJava.clusterP2p(val).asString();
+ $scope.preview.p2p.allDefaults = $common.isEmptyString($scope.preview.p2p.xml);
+
+ $scope.preview.swap.xml = $generatorXml.clusterSwap(val).asString();
+ $scope.preview.swap.java = $generatorJava.clusterSwap(val).asString();
+ $scope.preview.swap.allDefaults = $common.isEmptyString($scope.preview.swap.xml);
+
+ $scope.preview.time.xml = $generatorXml.clusterTime(val).asString();
+ $scope.preview.time.java = $generatorJava.clusterTime(val).asString();
+ $scope.preview.time.allDefaults = $common.isEmptyString($scope.preview.time.xml);
+
+ $scope.preview.pools.xml = $generatorXml.clusterPools(val).asString();
+ $scope.preview.pools.java = $generatorJava.clusterPools(val).asString();
+ $scope.preview.pools.allDefaults = $common.isEmptyString($scope.preview.pools.xml);
+
+ $scope.preview.transactions.xml = $generatorXml.clusterTransactions(val).asString();
+ $scope.preview.transactions.java = $generatorJava.clusterTransactions(val).asString();
+ $scope.preview.transactions.allDefaults = $common.isEmptyString($scope.preview.transactions.xml);
+
+ $scope.preview.sslConfiguration.xml = $generatorXml.clusterSsl(val).asString();
+ $scope.preview.sslConfiguration.java = $generatorJava.clusterSsl(val).asString();
+ $scope.preview.sslConfiguration.allDefaults = $common.isEmptyString($scope.preview.sslConfiguration.xml);
+ }
+ }, true);
+ })
+ .error(function (errMsg) {
+ $common.showError(errMsg);
+ });
+ })
+ .error(function (errMsg) {
+ $common.showError(errMsg);
+ })
+ .finally(function () {
+ $scope.ui.ready = true;
+ $loading.finish('loadingClustersScreen');
+ });
+
+ $scope.selectItem = function (item, backup) {
+ function selectItem() {
+ $table.tableReset();
+
+ $scope.selectedItem = angular.copy(item);
+
+ try {
+ if (item && item._id)
+ sessionStorage.lastSelectedCluster = angular.toJson(item._id);
+ else
+ sessionStorage.removeItem('lastSelectedCluster');
+ }
+ catch (error) { }
+
+ _.forEach(previews, function(preview) {
+ preview.attractAttention = false;
+ });
+
+ if (backup)
+ $scope.backupItem = backup;
+ else if (item)
+ $scope.backupItem = angular.copy(item);
+ else
+ $scope.backupItem = undefined;
+ }
+
+ $common.confirmUnsavedChanges($scope.ui.isDirty(), selectItem);
+
+ $scope.ui.formTitle = $common.isDefined($scope.backupItem) && $scope.backupItem._id ?
+ 'Selected cluster: ' + $scope.backupItem.name : 'New cluster';
+ };
+
+ function prepareNewItem() {
+ var newItem = {
+ discovery: {kind: 'Multicast', Vm: {addresses: ['127.0.0.1:47500..47510']}, Multicast: {}},
+ deploymentMode: 'SHARED'
+ };
+
+ newItem.caches = [];
+ newItem.space = $scope.spaces[0]._id;
+
+ return newItem;
+ }
+
+ // Add new cluster.
+ $scope.createItem = function () {
+ $table.tableReset();
+
+ $timeout(function () {
+ $common.ensureActivePanel($scope.panels, "general", 'clusterName');
+ });
+
+ $scope.selectItem(undefined, prepareNewItem());
+ };
+
+ $scope.indexOfCache = function (cacheId) {
+ return _.findIndex($scope.caches, function (cache) {
+ return cache.value == cacheId;
+ });
+ };
+
+ // Check cluster logical consistency.
+ function validate(item) {
+ if ($common.isEmptyString(item.name))
+ return showPopoverMessage($scope.panels, 'general', 'clusterName', 'Name should not be empty');
+
+ var d = item.discovery;
+
+ if (!$common.isEmptyString(d.addressResolver) && !$common.isValidJavaClass('Address resolver', d.addressResolver, false, 'addressResolver', false, $scope.panels, 'discovery'))
+ return false;
+
+ if (!$common.isEmptyString(d.listener) && !$common.isValidJavaClass('Discovery listener', d.listener, false, 'listener', false, $scope.panels, 'discovery'))
+ return false;
+
+ if (!$common.isEmptyString(d.dataExchange) && !$common.isValidJavaClass('Data exchange', d.dataExchange, false, 'dataExchange', false, $scope.panels, 'discovery'))
+ return false;
+
+ if (!$common.isEmptyString(d.metricsProvider) && !$common.isValidJavaClass('Metrics provider', d.metricsProvider, false, 'metricsProvider', false, $scope.panels, 'discovery'))
+ return false;
+
+ if (!$common.isEmptyString(d.authenticator) && !$common.isValidJavaClass('Node authenticator', d.authenticator, false, 'authenticator', false, $scope.panels, 'discovery'))
+ return false;
+
+ if (item.discovery.kind == 'Vm' && item.discovery.Vm.addresses.length == 0)
+ return showPopoverMessage($scope.panels, 'general', 'addresses', 'Addresses are not specified');
+
+ if (item.discovery.kind == 'S3' && $common.isEmptyString(item.discovery.S3.bucketName))
+ return showPopoverMessage($scope.panels, 'general', 'bucketName', 'Bucket name should not be empty');
+
+ if (item.discovery.kind == 'Cloud') {
+ if ($common.isEmptyString(item.discovery.Cloud.identity))
+ return showPopoverMessage($scope.panels, 'general', 'identity', 'Identity should not be empty');
+
+ if ($common.isEmptyString(item.discovery.Cloud.provider))
+ return showPopoverMessage($scope.panels, 'general', 'provider', 'Provider should not be empty');
+ }
+
+ if (item.discovery.kind == 'GoogleStorage') {
+ if ($common.isEmptyString(item.discovery.GoogleStorage.projectName))
+ return showPopoverMessage($scope.panels, 'general', 'projectName', 'Project name should not be empty');
+
+ if ($common.isEmptyString(item.discovery.GoogleStorage.bucketName))
+ return showPopoverMessage($scope.panels, 'general', 'bucketName', 'Bucket name should not be empty');
+
+ if ($common.isEmptyString(item.discovery.GoogleStorage.serviceAccountP12FilePath))
+ return showPopoverMessage($scope.panels, 'general', 'serviceAccountP12FilePath', 'Private key path should not be empty');
+
+ if ($common.isEmptyString(item.discovery.GoogleStorage.serviceAccountId))
+ return showPopoverMessage($scope.panels, 'general', 'serviceAccountId', 'Account ID should not be empty');
+ }
+
+ if (item.sslEnabled) {
+ if (!$common.isDefined(item.sslContextFactory)
+ || $common.isEmptyString(item.sslContextFactory.keyStoreFilePath))
+ return showPopoverMessage($scope.panels, 'sslConfiguration', 'keyStoreFilePath', 'Key store file should not be empty');
+
+ if ($common.isEmptyString(item.sslContextFactory.trustStoreFilePath) && $common.isEmptyArray(item.sslContextFactory.trustManagers))
+ return showPopoverMessage($scope.panels, 'sslConfiguration', 'sslConfiguration-title', 'Trust storage file or managers should be configured');
+ }
+
+ if (!item.swapSpaceSpi || !item.swapSpaceSpi.kind && item.caches) {
+ for (var i = 0; i < item.caches.length; i++) {
+ var idx = $scope.indexOfCache(item.caches[i]);
+
+ if (idx >= 0) {
+ var cache = $scope.caches[idx];
+
+ if (cache.cache.swapEnabled) {
+ $scope.ui.expanded = true;
+
+ return showPopoverMessage($scope.panels, 'swap', 'swapSpaceSpi',
+ 'Swap space SPI is not configured, but cache "' + cache.label + '" configured to use swap!');
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ // Save cluster in database.
+ function save(item) {
+ $http.post('clusters/save', item)
+ .success(function (_id) {
+ $scope.ui.markPristine();
+
+ var idx = _.findIndex($scope.clusters, function (cluster) {
+ return cluster._id == _id;
+ });
+
+ if (idx >= 0)
+ angular.extend($scope.clusters[idx], item);
+ else {
+ item._id = _id;
+ $scope.clusters.push(item);
+ }
+
+ $scope.selectItem(item);
+
+ $common.showInfo('Cluster "' + item.name + '" saved.');
+ })
+ .error(function (errMsg) {
+ $common.showError(errMsg);
+ });
+ }
+
+ // Save cluster.
+ $scope.saveItem = function () {
+ $table.tableReset();
+
+ var item = $scope.backupItem;
+
+ if (validate(item))
+ save(item);
+ };
+
+ // Copy cluster with new name.
+ $scope.cloneItem = function () {
+ $table.tableReset();
+
+ if (validate($scope.backupItem))
+ $clone.confirm($scope.backupItem.name).then(function (newName) {
+ var item = angular.copy($scope.backupItem);
+
+ item._id = undefined;
+ item.name = newName;
+
+ save(item);
+ });
+ };
+
+ // Remove cluster from db.
+ $scope.removeItem = function () {
+ $table.tableReset();
+
+ var selectedItem = $scope.selectedItem;
+
+ $confirm.confirm('Are you sure you want to remove cluster: "' + selectedItem.name + '"?')
+ .then(function () {
+ var _id = selectedItem._id;
+
+ $http.post('clusters/remove', {_id: _id})
+ .success(function () {
+ $common.showInfo('Cluster has been removed: ' + selectedItem.name);
+
+ var clusters = $scope.clusters;
+
+ var idx = _.findIndex(clusters, function (cluster) {
+ return cluster._id == _id;
+ });
+
+ if (idx >= 0) {
+ clusters.splice(idx, 1);
+
+ if (clusters.length > 0)
+ $scope.selectItem(clusters[0]);
+ else
+ $scope.selectItem(undefined, undefined);
+ }
+ })
+ .error(function (errMsg) {
+ $common.showError(errMsg);
+ });
+ });
+ };
+
+ // Remove all clusters from db.
+ $scope.removeAllItems = function () {
+ $table.tableReset();
+
+ $confirm.confirm('Are you sure you want to remove all clusters?')
+ .then(function () {
+ $http.post('clusters/remove/all')
+ .success(function () {
+ $common.showInfo('All clusters have been removed');
+
+ $scope.clusters = [];
+
+ $scope.selectItem(undefined, undefined);
+ })
+ .error(function (errMsg) {
+ $common.showError(errMsg);
+ });
+ });
+ };
+
+ $scope.resetItem = function (group) {
+ var resetTo = $scope.selectedItem;
+
+ if (!$common.isDefined(resetTo))
+ resetTo = prepareNewItem();
+
+ $common.resetItem($scope.backupItem, resetTo, $scope.general, group);
+ $common.resetItem($scope.backupItem, resetTo, $scope.advanced, group);
+ }
+ }]
+);