You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by bm...@apache.org on 2013/07/19 01:45:33 UTC
[34/39] git commit: Moved controllers from globals to the Angular
module.
Moved controllers from globals to the Angular module.
As mentioned in "Setting up the initial state of a scope object"[1],
controllers should be defined in the same module as the rest of your
app instead of being defined as global functions.
This also wraps "controllers.js" in a closure so strict mode is
applied only to that file. Because of that, the global function
"setNavbarActiveTab" moved into "controllers.js" since it was only
referenced there.
[1] http://docs.angularjs.org/guide/dev_guide.mvc.understanding_
controller#settinguptheinitialstateofascopeobject
Original review: https://reviews.apache.org/r/12613/
From: Ross Allen <ro...@mesosphe.re>
Review: https://reviews.apache.org/r/12735
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/4bbcdcbc
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/4bbcdcbc
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/4bbcdcbc
Branch: refs/heads/master
Commit: 4bbcdcbc8a3d581a497f46dc4681d5c6389981e8
Parents: 7349da9
Author: Benjamin Mahler <bm...@twitter.com>
Authored: Thu Jul 18 16:25:38 2013 -0700
Committer: Benjamin Mahler <bm...@twitter.com>
Committed: Thu Jul 18 16:28:03 2013 -0700
----------------------------------------------------------------------
src/webui/master/static/js/app.js | 32 +-
src/webui/master/static/js/controllers.js | 1278 ++++++++++++------------
2 files changed, 661 insertions(+), 649 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/4bbcdcbc/src/webui/master/static/js/app.js
----------------------------------------------------------------------
diff --git a/src/webui/master/static/js/app.js b/src/webui/master/static/js/app.js
index 9ddcf95..235be27 100644
--- a/src/webui/master/static/js/app.js
+++ b/src/webui/master/static/js/app.js
@@ -3,15 +3,24 @@
angular.module('mesos', ['ui.bootstrap']).
config(['$dialogProvider', '$routeProvider', function($dialogProvider, $routeProvider) {
$routeProvider
- .when('/', {templateUrl: 'static/home.html', controller: HomeCtrl})
- .when('/dashboard', {templateUrl: 'static/dashboard.html', controller: DashboardCtrl})
- .when('/frameworks', {templateUrl: 'static/frameworks.html', controller: FrameworksCtrl})
- .when('/frameworks/:id', {templateUrl: 'static/framework.html', controller: FrameworkCtrl})
- .when('/slaves', {templateUrl: 'static/slaves.html', controller: SlavesCtrl})
- .when('/slaves/:slave_id', {templateUrl: 'static/slave.html', controller: SlaveCtrl})
- .when('/slaves/:slave_id/frameworks/:framework_id', {templateUrl: 'static/slave_framework.html', controller: SlaveFrameworkCtrl})
- .when('/slaves/:slave_id/frameworks/:framework_id/executors/:executor_id', {templateUrl: 'static/slave_executor.html', controller: SlaveExecutorCtrl})
- .when('/slaves/:slave_id/browse', {templateUrl: 'static/browse.html', controller: BrowseCtrl})
+ .when('/',
+ {templateUrl: 'static/home.html', controller: 'HomeCtrl'})
+ .when('/dashboard',
+ {templateUrl: 'static/dashboard.html', controller: 'DashboardCtrl'})
+ .when('/frameworks',
+ {templateUrl: 'static/frameworks.html', controller: 'FrameworksCtrl'})
+ .when('/frameworks/:id',
+ {templateUrl: 'static/framework.html', controller: 'FrameworkCtrl'})
+ .when('/slaves',
+ {templateUrl: 'static/slaves.html', controller: 'SlavesCtrl'})
+ .when('/slaves/:slave_id',
+ {templateUrl: 'static/slave.html', controller: 'SlaveCtrl'})
+ .when('/slaves/:slave_id/frameworks/:framework_id',
+ {templateUrl: 'static/slave_framework.html', controller: 'SlaveFrameworkCtrl'})
+ .when('/slaves/:slave_id/frameworks/:framework_id/executors/:executor_id',
+ {templateUrl: 'static/slave_executor.html', controller: 'SlaveExecutorCtrl'})
+ .when('/slaves/:slave_id/browse',
+ {templateUrl: 'static/browse.html', controller: 'BrowseCtrl'})
.otherwise({redirectTo: '/'});
$dialogProvider.options({dialogFade: true});
@@ -184,8 +193,3 @@ angular.module('mesos', ['ui.bootstrap']).
}
};
}]);
-
-function setNavbarActiveTab(tab_name) {
- $('#navbar li').removeClass('active');
- $('#navbar li[data-tabname='+tab_name+']').addClass('active');
-}
http://git-wip-us.apache.org/repos/asf/mesos/blob/4bbcdcbc/src/webui/master/static/js/controllers.js
----------------------------------------------------------------------
diff --git a/src/webui/master/static/js/controllers.js b/src/webui/master/static/js/controllers.js
index 1f58eab..4caa64e 100644
--- a/src/webui/master/static/js/controllers.js
+++ b/src/webui/master/static/js/controllers.js
@@ -1,472 +1,362 @@
-'use strict';
-
-var slaves = [];
-
-
-// Table Object.
-// selected_column: column predicate for the selected column.
-// reverse: boolean indicating sort order.
-function Table(selected_column) {
- if (this instanceof Table) {
- this.selected_column = selected_column;
- this.reverse = true;
- } else {
- return new Table(selected_column);
- }
-}
-
-
-function hasSelectedText () {
- if (window.getSelection) { // All browsers except IE before version 9.
- var range = window.getSelection();
- return range.toString().length > 0;
- }
- return false;
-}
-
-
-// Returns a curried function for returning the HTML 'class=' tag
-// attribute value for sorting table columns in the provided scope.
-function columnClass($scope) {
- // For the given table column, this behaves as follows:
- // Column unselected : 'unselected'
- // Column selected / descending : 'descending'
- // Column selected / ascending : 'ascending'
- return function(table, column) {
- if ($scope.tables[table].selected_column === column) {
- if ($scope.tables[table].reverse) {
- return 'descending';
- } else {
- return 'ascending';
- }
- }
- return 'unselected';
- };
-}
-
-
-// Returns a curried function to be called when a table column is clicked
-// in the provided scope.
-function selectColumn($scope) {
- // Assigns the given table column as the sort column, flipping the
- // sort order if the sort column has not changed.
- return function(table, column) {
- if ($scope.tables[table].selected_column === column) {
- $scope.tables[table].reverse = !$scope.tables[table].reverse;
+(function() {
+ 'use strict';
+
+ var slaves = [];
+ var mesosApp = angular.module('mesos');
+
+ // Table Object.
+ // selected_column: column predicate for the selected column.
+ // reverse: boolean indicating sort order.
+ function Table(selected_column) {
+ if (this instanceof Table) {
+ this.selected_column = selected_column;
+ this.reverse = true;
} else {
- $scope.tables[table].reverse = true;
+ return new Table(selected_column);
}
- $scope.tables[table].selected_column = column;
- };
-}
-
-
-// Invokes the pailer for the specified host and path using the
-// specified window_title.
-function pailer(host, path, window_title) {
- var url = 'http://' + host + '/files/read.json?path=' + path;
- var pailer =
- window.open('/static/pailer.html', url, 'width=580px, height=700px');
-
- // Need to use window.onload instead of document.ready to make
- // sure the title doesn't get overwritten.
- pailer.onload = function() {
- pailer.document.title = window_title + ' (' + host + ')';
- };
-}
-
-
-function updateInterval(num_slaves) {
- // TODO(bmahler): Increasing the update interval for large clusters
- // is done purely to mitigate webui performance issues. Ideally we can
- // keep a consistently fast rate for updating statistical information.
- // For the full system state updates, it may make sense to break
- // it up using pagination and/or splitting the endpoint.
- if (num_slaves < 10) {
- return 3000;
- } else if (num_slaves < 50) {
- return 4000;
- } else if (num_slaves < 100) {
- return 5000;
- } else if (num_slaves < 500) {
- return 10000;
- } else if (num_slaves < 1000) {
- return 20000;
- } else if (num_slaves < 5000) {
- return 30000;
- } else {
- return 60000;
}
-}
-// Update the outermost scope with the new state.
-function update($scope, $timeout, data) {
- // Don't do anything if the data hasn't changed.
- if ($scope.data == data) {
- return true; // Continue polling.
+ function setNavbarActiveTab(tab_name) {
+ $('#navbar li').removeClass('active');
+ $('#navbar li[data-tabname='+tab_name+']').addClass('active');
}
- $scope.state = $.parseJSON(data);
- // Determine if there is a leader (and redirect if not the leader).
- if (!$scope.state.leader) {
- $("#no-leader-alert").show();
- } else {
- $("#no-leader-alert").hide();
+ function hasSelectedText() {
+ if (window.getSelection) { // All browsers except IE before version 9.
+ var range = window.getSelection();
+ return range.toString().length > 0;
+ }
+ return false;
+ }
- // Redirect if we aren't the leader.
- if ($scope.state.leader != $scope.state.pid) {
- $scope.redirect = 6000;
- $scope.leader = $scope.state.leader.split("@")[1];
- $("#not-leader-alert").show();
- var countdown = function() {
- if ($scope.redirect == 0) {
- // TODO(benh): Use '$window'.
- window.location = 'http://' + $scope.leader;
+ // Returns a curried function for returning the HTML 'class=' tag
+ // attribute value for sorting table columns in the provided scope.
+ function columnClass($scope) {
+ // For the given table column, this behaves as follows:
+ // Column unselected : 'unselected'
+ // Column selected / descending : 'descending'
+ // Column selected / ascending : 'ascending'
+ return function(table, column) {
+ if ($scope.tables[table].selected_column === column) {
+ if ($scope.tables[table].reverse) {
+ return 'descending';
} else {
- $scope.redirect = $scope.redirect - 1000;
- $timeout(countdown, 1000);
+ return 'ascending';
}
- };
- countdown();
- return false; // Don't continue polling.
- }
+ }
+ return 'unselected';
+ };
}
- // A cluster is named if the state returns a non-empty string name.
- // Track whether this cluster is named in a Boolean for display purposes.
- $scope.clusterNamed = !!$scope.state.cluster;
- // Check for selected text, and allow up to 20 seconds to pass before
- // potentially wiping the user highlighted text.
- // TODO(bmahler): This is to avoid the annoying loss of highlighting when
- // the tables update. Once we can have tighter granularity control on the
- // angular.js dynamic table updates, we should remove this hack.
- $scope.time_since_update += $scope.delay;
-
- if (hasSelectedText() && $scope.time_since_update < 20000) {
- return true;
+ // Returns a curried function to be called when a table column is clicked
+ // in the provided scope.
+ function selectColumn($scope) {
+ // Assigns the given table column as the sort column, flipping the
+ // sort order if the sort column has not changed.
+ return function(table, column) {
+ if ($scope.tables[table].selected_column === column) {
+ $scope.tables[table].reverse = !$scope.tables[table].reverse;
+ } else {
+ $scope.tables[table].reverse = true;
+ }
+ $scope.tables[table].selected_column = column;
+ };
}
- $scope.data = data;
-
- // Update the maps.
- $scope.slaves = {};
- $scope.frameworks = {};
- $scope.offers = {};
- $scope.completed_frameworks = {};
- _.each($scope.state.slaves, function(slave) {
- $scope.slaves[slave.id] = slave;
- });
-
- _.each($scope.state.frameworks, function(framework) {
- $scope.frameworks[framework.id] = framework;
- _.each(framework.offers, function(offer) {
- $scope.offers[offer.id] = offer;
- });
- });
+ // Invokes the pailer for the specified host and path using the
+ // specified window_title.
+ function pailer(host, path, window_title) {
+ var url = 'http://' + host + '/files/read.json?path=' + path;
+ var pailer =
+ window.open('/static/pailer.html', url, 'width=580px, height=700px');
- _.each($scope.state.completed_frameworks, function(framework) {
- $scope.completed_frameworks[framework.id] = framework;
- });
-
- // Update the stats.
- $scope.cluster = $scope.state.cluster;
- $scope.total_cpus = 0;
- $scope.total_mem = 0;
- $scope.used_cpus = 0;
- $scope.used_mem = 0;
- $scope.offered_cpus = 0;
- $scope.offered_mem = 0;
-
- $scope.staged_tasks = $scope.state.staged_tasks;
- $scope.started_tasks = $scope.state.started_tasks;
- $scope.finished_tasks = $scope.state.finished_tasks;
- $scope.killed_tasks = $scope.state.killed_tasks;
- $scope.failed_tasks = $scope.state.failed_tasks;
- $scope.lost_tasks = $scope.state.lost_tasks;
-
- $scope.activated_slaves = $scope.state.activated_slaves;
- $scope.deactivated_slaves = $scope.state.deactivated_slaves;
-
- _.each($scope.slaves, function(slave) {
- $scope.total_cpus += slave.resources.cpus;
- $scope.total_mem += slave.resources.mem;
- });
-
- _.each($scope.frameworks, function(framework) {
- $scope.used_cpus += framework.resources.cpus;
- $scope.used_mem += framework.resources.mem;
- $scope.active_tasks += framework.tasks.length;
- $scope.completed_tasks += framework.completed_tasks.length;
+ // Need to use window.onload instead of document.ready to make
+ // sure the title doesn't get overwritten.
+ pailer.onload = function() {
+ pailer.document.title = window_title + ' (' + host + ')';
+ };
+ }
- framework.cpus_share = 0;
- if ($scope.total_cpus > 0) {
- framework.cpus_share = framework.resources.cpus / $scope.total_cpus;
- }
- framework.mem_share = 0;
- if ($scope.total_mem > 0) {
- framework.mem_share = framework.resources.mem / $scope.total_mem;
- }
+ function updateInterval(num_slaves) {
+ // TODO(bmahler): Increasing the update interval for large clusters
+ // is done purely to mitigate webui performance issues. Ideally we can
+ // keep a consistently fast rate for updating statistical information.
+ // For the full system state updates, it may make sense to break
+ // it up using pagination and/or splitting the endpoint.
+ if (num_slaves < 10) {
+ return 3000;
+ } else if (num_slaves < 50) {
+ return 4000;
+ } else if (num_slaves < 100) {
+ return 5000;
+ } else if (num_slaves < 500) {
+ return 10000;
+ } else if (num_slaves < 1000) {
+ return 20000;
+ } else if (num_slaves < 5000) {
+ return 30000;
+ } else {
+ return 60000;
+ }
+ }
- framework.max_share = Math.max(framework.cpus_share, framework.mem_share);
- // If the executor ID is empty, this is a command executor with an
- // internal executor ID generated from the task ID.
- // TODO(brenden): Remove this once
- // https://issues.apache.org/jira/browse/MESOS-527 is fixed.
- _.each(framework.tasks, function(task) {
- if (!task.executor_id) {
- task.executor_id = task.id;
- }
- });
- _.each(framework.completed_tasks, function(task) {
- if (!task.executor_id) {
- task.executor_id = task.id;
- }
- });
- });
+ // Update the outermost scope with the new state.
+ function update($scope, $timeout, data) {
+ // Don't do anything if the data hasn't changed.
+ if ($scope.data == data) {
+ return true; // Continue polling.
+ }
- _.each($scope.offers, function(offer) {
- $scope.offered_cpus += offer.resources.cpus;
- $scope.offered_mem += offer.resources.mem;
- offer.framework_name = $scope.frameworks[offer.framework_id].name;
- offer.hostname = $scope.slaves[offer.slave_id].hostname;
- });
+ $scope.state = $.parseJSON(data);
- $scope.used_cpus -= $scope.offered_cpus;
- $scope.used_mem -= $scope.offered_mem;
-
- $scope.idle_cpus = $scope.total_cpus - ($scope.offered_cpus + $scope.used_cpus);
- $scope.idle_mem = $scope.total_mem - ($scope.offered_mem + $scope.used_mem);
-
- $scope.time_since_update = 0;
- $.event.trigger('state_updated');
-
- return true; // Continue polling.
-}
-
-
-// Main controller that can be used to handle "global" events. E.g.,:
-// $scope.$on('$afterRouteChange', function() { ...; });
-//
-// In addition, the MainCntl encapsulates the "view", allowing the
-// active controller/view to easily access anything in scope (e.g.,
-// the state).
-function MainCntl($scope, $http, $route, $routeParams, $location, $timeout) {
- // Turn off the loading gif, turn on the navbar.
- $("#loading").hide();
- $("#navbar").show();
-
- // Adding bindings into scope so that they can be used from within
- // AngularJS expressions.
- $scope._ = _;
- $scope.stringify = JSON.stringify;
- $scope.encodeURIComponent = encodeURIComponent;
- $scope.basename = function(path) {
- // This is only a basic version of basename that handles the cases we care
- // about, rather than duplicating unix basename functionality perfectly.
- if (path === '/') {
- return path; // Handle '/'.
- }
+ // Determine if there is a leader (and redirect if not the leader).
+ if (!$scope.state.leader) {
+ $("#no-leader-alert").show();
+ } else {
+ $("#no-leader-alert").hide();
- // Strip a trailing '/' if present.
- if (path.length > 0 && path.lastIndexOf('/') === (path.length - 1)) {
- path = path.substr(0, path.length - 1);
- }
- return path.substr(path.lastIndexOf('/') + 1);
- };
-
- $scope.$location = $location;
- $scope.delay = 2000;
- $scope.retry = 0;
- $scope.time_since_update = 0;
-
- var poll = function() {
- $http.get('master/state.json',
- {transformResponse: function(data) { return data; }})
- .success(function(data) {
- if (update($scope, $timeout, data)) {
- $scope.delay = updateInterval(_.size($scope.slaves));
- $timeout(poll, $scope.delay);
- }
- })
- .error(function() {
- if ($scope.delay >= 128000) {
- $scope.delay = 2000;
- } else {
- $scope.delay = $scope.delay * 2;
- }
+ // Redirect if we aren't the leader.
+ if ($scope.state.leader != $scope.state.pid) {
+ $scope.redirect = 6000;
+ $scope.leader = $scope.state.leader.split("@")[1];
+ $("#not-leader-alert").show();
- $scope.retry = $scope.delay;
var countdown = function() {
- if ($scope.retry === 0) {
- $scope.errorModalClose();
+ if ($scope.redirect == 0) {
+ // TODO(benh): Use '$window'.
+ window.location = 'http://' + $scope.leader;
} else {
- $scope.retry = $scope.retry - 1000;
- $scope.countdown = $timeout(countdown, 1000);
+ $scope.redirect = $scope.redirect - 1000;
+ $timeout(countdown, 1000);
}
};
-
countdown();
- $scope.errorModalOpen = true;
- });
- };
-
- // Make it such that everytime we hide the error-modal, we stop the
- // countdown and restart the polling.
- $scope.errorModalClose = function() {
- $scope.errorModalOpen = false;
-
- if ($scope.countdown != null) {
- if ($timeout.cancel($scope.countdown)) {
- // Restart since they cancelled the countdown.
- $scope.delay = 2000;
+ return false; // Don't continue polling.
}
}
- // Start polling again, but do it asynchronously (and wait at
- // least a second because otherwise the error-modal won't get
- // properly shown).
- $timeout(poll, 1000);
- };
-
- poll();
-}
-
+ // A cluster is named if the state returns a non-empty string name.
+ // Track whether this cluster is named in a Boolean for display purposes.
+ $scope.clusterNamed = !!$scope.state.cluster;
-function HomeCtrl($dialog, $scope) {
- setNavbarActiveTab('home');
+ // Check for selected text, and allow up to 20 seconds to pass before
+ // potentially wiping the user highlighted text.
+ // TODO(bmahler): This is to avoid the annoying loss of highlighting when
+ // the tables update. Once we can have tighter granularity control on the
+ // angular.js dynamic table updates, we should remove this hack.
+ $scope.time_since_update += $scope.delay;
- $scope.tables = {};
- $scope.tables['frameworks'] = new Table('id');
- $scope.tables['slaves'] = new Table('id');
- $scope.tables['offers'] = new Table('id');
- $scope.tables['completed_frameworks'] = new Table('id');
-
- $scope.columnClass = columnClass($scope);
- $scope.selectColumn = selectColumn($scope);
-
- $scope.log = function($event) {
- if (!$scope.state.log_dir) {
- $dialog.messageBox(
- 'Logging to a file is not enabled',
- "Set the 'log_dir' option if you wish to access the logs.",
- [{label: 'Continue'}]
- ).open();
- } else {
- pailer(
- $scope.$location.host() + ':' + $scope.$location.port(),
- '/master/log',
- 'Mesos Master');
+ if (hasSelectedText() && $scope.time_since_update < 20000) {
+ return true;
}
- };
-}
+ $scope.data = data;
-function DashboardCtrl($scope) {
- setNavbarActiveTab('dashboard');
+ // Update the maps.
+ $scope.slaves = {};
+ $scope.frameworks = {};
+ $scope.offers = {};
+ $scope.completed_frameworks = {};
- var context = cubism.context()
- .step(1000)
- .size(1440);
+ _.each($scope.state.slaves, function(slave) {
+ $scope.slaves[slave.id] = slave;
+ });
+
+ _.each($scope.state.frameworks, function(framework) {
+ $scope.frameworks[framework.id] = framework;
+ _.each(framework.offers, function(offer) {
+ $scope.offers[offer.id] = offer;
+ });
+ });
- // Create a "cpus" horizon.
- horizons.create(context, "cpus", random(context, "cpus"), [0, 10], "cpus");
+ _.each($scope.state.completed_frameworks, function(framework) {
+ $scope.completed_frameworks[framework.id] = framework;
+ });
- // Create a "mem" horizon.
- horizons.create(context, "mem", random(context, "mem"), [0, 10], "mb");
+ // Update the stats.
+ $scope.cluster = $scope.state.cluster;
+ $scope.total_cpus = 0;
+ $scope.total_mem = 0;
+ $scope.used_cpus = 0;
+ $scope.used_mem = 0;
+ $scope.offered_cpus = 0;
+ $scope.offered_mem = 0;
+
+ $scope.staged_tasks = $scope.state.staged_tasks;
+ $scope.started_tasks = $scope.state.started_tasks;
+ $scope.finished_tasks = $scope.state.finished_tasks;
+ $scope.killed_tasks = $scope.state.killed_tasks;
+ $scope.failed_tasks = $scope.state.failed_tasks;
+ $scope.lost_tasks = $scope.state.lost_tasks;
+
+ $scope.activated_slaves = $scope.state.activated_slaves;
+ $scope.deactivated_slaves = $scope.state.deactivated_slaves;
+
+ _.each($scope.slaves, function(slave) {
+ $scope.total_cpus += slave.resources.cpus;
+ $scope.total_mem += slave.resources.mem;
+ });
- // Do any cleanup before we change the route.
- $scope.$on('$beforeRouteChange', function() { context.stop(); });
-}
+ _.each($scope.frameworks, function(framework) {
+ $scope.used_cpus += framework.resources.cpus;
+ $scope.used_mem += framework.resources.mem;
+ $scope.active_tasks += framework.tasks.length;
+ $scope.completed_tasks += framework.completed_tasks.length;
+ framework.cpus_share = 0;
+ if ($scope.total_cpus > 0) {
+ framework.cpus_share = framework.resources.cpus / $scope.total_cpus;
+ }
-function FrameworksCtrl($scope) {
- setNavbarActiveTab('frameworks');
+ framework.mem_share = 0;
+ if ($scope.total_mem > 0) {
+ framework.mem_share = framework.resources.mem / $scope.total_mem;
+ }
- $scope.tables = {};
- $scope.tables['frameworks'] = new Table('id');
+ framework.max_share = Math.max(framework.cpus_share, framework.mem_share);
- $scope.columnClass = columnClass($scope);
- $scope.selectColumn = selectColumn($scope);
-}
+ // If the executor ID is empty, this is a command executor with an
+ // internal executor ID generated from the task ID.
+ // TODO(brenden): Remove this once
+ // https://issues.apache.org/jira/browse/MESOS-527 is fixed.
+ _.each(framework.tasks, function(task) {
+ if (!task.executor_id) {
+ task.executor_id = task.id;
+ }
+ });
+ _.each(framework.completed_tasks, function(task) {
+ if (!task.executor_id) {
+ task.executor_id = task.id;
+ }
+ });
+ });
+ _.each($scope.offers, function(offer) {
+ $scope.offered_cpus += offer.resources.cpus;
+ $scope.offered_mem += offer.resources.mem;
+ offer.framework_name = $scope.frameworks[offer.framework_id].name;
+ offer.hostname = $scope.slaves[offer.slave_id].hostname;
+ });
-function FrameworkCtrl($scope, $routeParams) {
- setNavbarActiveTab('frameworks');
+ $scope.used_cpus -= $scope.offered_cpus;
+ $scope.used_mem -= $scope.offered_mem;
- $scope.tables = {};
- $scope.tables['active_tasks'] = new Table('id');
- $scope.tables['completed_tasks'] = new Table('id');
+ $scope.idle_cpus = $scope.total_cpus - ($scope.offered_cpus + $scope.used_cpus);
+ $scope.idle_mem = $scope.total_mem - ($scope.offered_mem + $scope.used_mem);
- $scope.columnClass = columnClass($scope);
- $scope.selectColumn = selectColumn($scope);
+ $scope.time_since_update = 0;
+ $.event.trigger('state_updated');
- var update = function() {
- if ($routeParams.id in $scope.completed_frameworks) {
- $scope.framework = $scope.completed_frameworks[$routeParams.id];
- $scope.alert_message = 'This framework has terminated!';
- $('#alert').show();
- $('#framework').show();
- } else if ($routeParams.id in $scope.frameworks) {
- $scope.framework = $scope.frameworks[$routeParams.id];
- $('#framework').show();
- } else {
- $scope.alert_message = 'No framework found with ID: ' + $routeParams.id;
- $('#alert').show();
- }
+ return true; // Continue polling.
}
- if ($scope.state) {
- update();
- }
- $(document).on('state_updated', update);
- $scope.$on('$beforeRouteChange', function() {
- $(document).off('state_updated', update);
- });
-}
+ // Main controller that can be used to handle "global" events. E.g.,:
+ // $scope.$on('$afterRouteChange', function() { ...; });
+ //
+ // In addition, the MainCntl encapsulates the "view", allowing the
+ // active controller/view to easily access anything in scope (e.g.,
+ // the state).
+ mesosApp.controller('MainCntl', function($scope, $http, $route, $routeParams, $location, $timeout) {
+ // Turn off the loading gif, turn on the navbar.
+ $("#loading").hide();
+ $("#navbar").show();
+
+ // Adding bindings into scope so that they can be used from within
+ // AngularJS expressions.
+ $scope._ = _;
+ $scope.stringify = JSON.stringify;
+ $scope.encodeURIComponent = encodeURIComponent;
+ $scope.basename = function(path) {
+ // This is only a basic version of basename that handles the cases we care
+ // about, rather than duplicating unix basename functionality perfectly.
+ if (path === '/') {
+ return path; // Handle '/'.
+ }
+ // Strip a trailing '/' if present.
+ if (path.length > 0 && path.lastIndexOf('/') === (path.length - 1)) {
+ path = path.substr(0, path.length - 1);
+ }
+ return path.substr(path.lastIndexOf('/') + 1);
+ };
-function SlavesCtrl($scope) {
- setNavbarActiveTab('slaves');
+ $scope.$location = $location;
+ $scope.delay = 2000;
+ $scope.retry = 0;
+ $scope.time_since_update = 0;
+
+ var poll = function() {
+ $http.get('master/state.json',
+ {transformResponse: function(data) { return data; }})
+ .success(function(data) {
+ if (update($scope, $timeout, data)) {
+ $scope.delay = updateInterval(_.size($scope.slaves));
+ $timeout(poll, $scope.delay);
+ }
+ })
+ .error(function() {
+ if ($scope.delay >= 128000) {
+ $scope.delay = 2000;
+ } else {
+ $scope.delay = $scope.delay * 2;
+ }
- $scope.tables = {};
- $scope.tables['slaves'] = new Table('id');
+ $scope.retry = $scope.delay;
+ var countdown = function() {
+ if ($scope.retry === 0) {
+ $scope.errorModalClose();
+ } else {
+ $scope.retry = $scope.retry - 1000;
+ $scope.countdown = $timeout(countdown, 1000);
+ }
+ };
+
+ countdown();
+ $scope.errorModalOpen = true;
+ });
+ };
- $scope.columnClass = columnClass($scope);
- $scope.selectColumn = selectColumn($scope);
-}
+ // Make it such that everytime we hide the error-modal, we stop the
+ // countdown and restart the polling.
+ $scope.errorModalClose = function() {
+ $scope.errorModalOpen = false;
+ if ($scope.countdown != null) {
+ if ($timeout.cancel($scope.countdown)) {
+ // Restart since they cancelled the countdown.
+ $scope.delay = 2000;
+ }
+ }
-function SlaveCtrl($dialog, $scope, $routeParams, $http, $q) {
- setNavbarActiveTab('slaves');
+ // Start polling again, but do it asynchronously (and wait at
+ // least a second because otherwise the error-modal won't get
+ // properly shown).
+ $timeout(poll, 1000);
+ };
- $scope.slave_id = $routeParams.slave_id;
+ poll();
+ });
- $scope.tables = {};
- $scope.tables['frameworks'] = new Table('id');
- $scope.tables['completed_frameworks'] = new Table('id');
- $scope.columnClass = columnClass($scope);
- $scope.selectColumn = selectColumn($scope);
+ mesosApp.controller('HomeCtrl', function($dialog, $scope) {
+ setNavbarActiveTab('home');
- var update = function() {
- if (!($routeParams.slave_id in $scope.slaves)) {
- $scope.alert_message = 'No slave found with ID: ' + $routeParams.slave_id;
- $('#alert').show();
- return;
- }
+ $scope.tables = {};
+ $scope.tables['frameworks'] = new Table('id');
+ $scope.tables['slaves'] = new Table('id');
+ $scope.tables['offers'] = new Table('id');
+ $scope.tables['completed_frameworks'] = new Table('id');
- var pid = $scope.slaves[$routeParams.slave_id].pid;
- var hostname = $scope.slaves[$routeParams.slave_id].hostname;
- var id = pid.substring(0, pid.indexOf('@'));
- var host = hostname + ":" + pid.substring(pid.lastIndexOf(':') + 1);
+ $scope.columnClass = columnClass($scope);
+ $scope.selectColumn = selectColumn($scope);
$scope.log = function($event) {
if (!$scope.state.log_dir) {
@@ -476,317 +366,435 @@ function SlaveCtrl($dialog, $scope, $routeParams, $http, $q) {
[{label: 'Continue'}]
).open();
} else {
- pailer(host, '/slave/log', 'Mesos Slave');
+ pailer(
+ $scope.$location.host() + ':' + $scope.$location.port(),
+ '/master/log',
+ 'Mesos Master');
}
};
+ });
- var usageRequest = $http.jsonp(
- 'http://' + host + '/monitor/usage.json?jsonp=JSON_CALLBACK');
-
- var stateRequest = $http.jsonp(
- 'http://' + host + '/' + id + '/state.json?jsonp=JSON_CALLBACK');
- $q.all([usageRequest, stateRequest]).then(function (responses) {
- $scope.monitor = responses[0].data;
- $scope.state = responses[1].data;
+ mesosApp.controller('DashboardCtrl', function($scope) {
+ setNavbarActiveTab('dashboard');
- $scope.slave = {};
- $scope.slave.frameworks = {};
- $scope.slave.completed_frameworks = {};
+ var context = cubism.context()
+ .step(1000)
+ .size(1440);
- $scope.slave.staging_tasks = 0;
- $scope.slave.starting_tasks = 0;
- $scope.slave.running_tasks = 0;
+ // Create a "cpus" horizon.
+ horizons.create(context, "cpus", random(context, "cpus"), [0, 10], "cpus");
- // Update the framework map.
- _.each($scope.state.frameworks, function(framework) {
- $scope.slave.frameworks[framework.id] = framework;
- });
+ // Create a "mem" horizon.
+ horizons.create(context, "mem", random(context, "mem"), [0, 10], "mb");
- // Update the completed framework map.
- _.each($scope.state.completed_frameworks, function(framework) {
- $scope.slave.completed_frameworks[framework.id] = framework;
- });
+ // Do any cleanup before we change the route.
+ $scope.$on('$beforeRouteChange', function() { context.stop(); });
+ });
- // Compute the framework stats.
- _.each(_.values($scope.state.frameworks).concat(_.values($scope.state.completed_frameworks)),
- function(framework) {
- framework.num_tasks = 0;
- framework.cpus = 0;
- framework.mem = 0;
-
- _.each(framework.executors, function(executor) {
- framework.num_tasks += _.size(executor.tasks);
- framework.cpus += executor.resources.cpus;
- framework.mem += executor.resources.mem;
- });
- });
- $('#slave').show();
- },
- function (reason) {
- $scope.alert_message = 'Failed to get slave usage / state: ' + reason;
- $('#alert').show();
- });
- };
+ mesosApp.controller('FrameworksCtrl', function($scope) {
+ setNavbarActiveTab('frameworks');
- if ($scope.state) {
- update();
- }
+ $scope.tables = {};
+ $scope.tables['frameworks'] = new Table('id');
- $(document).on('state_updated', update);
- $scope.$on('$beforeRouteChange', function() {
- $(document).off('state_updated', update);
+ $scope.columnClass = columnClass($scope);
+ $scope.selectColumn = selectColumn($scope);
});
-}
-function SlaveFrameworkCtrl($scope, $routeParams, $http, $q) {
- setNavbarActiveTab('slaves');
+ mesosApp.controller('FrameworkCtrl', function($scope, $routeParams) {
+ setNavbarActiveTab('frameworks');
- $scope.slave_id = $routeParams.slave_id;
- $scope.framework_id = $routeParams.framework_id;
+ $scope.tables = {};
+ $scope.tables['active_tasks'] = new Table('id');
+ $scope.tables['completed_tasks'] = new Table('id');
- $scope.tables = {};
- $scope.tables['executors'] = new Table('id');
- $scope.tables['completed_executors'] = new Table('id');
+ $scope.columnClass = columnClass($scope);
+ $scope.selectColumn = selectColumn($scope);
- $scope.columnClass = columnClass($scope);
- $scope.selectColumn = selectColumn($scope);
+ var update = function() {
+ if ($routeParams.id in $scope.completed_frameworks) {
+ $scope.framework = $scope.completed_frameworks[$routeParams.id];
+ $scope.alert_message = 'This framework has terminated!';
+ $('#alert').show();
+ $('#framework').show();
+ } else if ($routeParams.id in $scope.frameworks) {
+ $scope.framework = $scope.frameworks[$routeParams.id];
+ $('#framework').show();
+ } else {
+ $scope.alert_message = 'No framework found with ID: ' + $routeParams.id;
+ $('#alert').show();
+ }
+ };
- var update = function() {
- if (!($routeParams.slave_id in $scope.slaves)) {
- $scope.alert_message = 'No slave found with ID: ' + $routeParams.slave_id;
- $('#alert').show();
- return;
+ if ($scope.state) {
+ update();
}
- var pid = $scope.slaves[$routeParams.slave_id].pid;
- var hostname = $scope.slaves[$routeParams.slave_id].hostname;
- var id = pid.substring(0, pid.indexOf('@'));
- var host = hostname + ":" + pid.substring(pid.lastIndexOf(':') + 1);
+ $(document).on('state_updated', update);
+ $scope.$on('$beforeRouteChange', function() {
+ $(document).off('state_updated', update);
+ });
+ });
+
+
+ mesosApp.controller('SlavesCtrl', function($scope) {
+ setNavbarActiveTab('slaves');
- var usageRequest = $http.jsonp(
- 'http://' + host + '/monitor/usage.json?jsonp=JSON_CALLBACK');
+ $scope.tables = {};
+ $scope.tables['slaves'] = new Table('id');
- var stateRequest = $http.jsonp(
- 'http://' + host + '/' + id + '/state.json?jsonp=JSON_CALLBACK');
+ $scope.columnClass = columnClass($scope);
+ $scope.selectColumn = selectColumn($scope);
+ });
- $q.all([usageRequest, stateRequest]).then(function (responses) {
- var monitor = responses[0].data;
- $scope.state = responses[1].data;
- $scope.slave = {};
+ mesosApp.controller('SlaveCtrl', function($dialog, $scope, $routeParams, $http, $q) {
+ setNavbarActiveTab('slaves');
- // Find the framework; it's either active or completed.
- $scope.framework = _.find($scope.state.frameworks.concat($scope.state.completed_frameworks),
- function(framework) {
- return $scope.framework_id === framework.id;
- });
+ $scope.slave_id = $routeParams.slave_id;
- if (!$scope.framework) {
- $scope.alert_message = 'No framework found with ID: ' + $routeParams.framework_id;
+ $scope.tables = {};
+ $scope.tables['frameworks'] = new Table('id');
+ $scope.tables['completed_frameworks'] = new Table('id');
+
+ $scope.columnClass = columnClass($scope);
+ $scope.selectColumn = selectColumn($scope);
+
+ var update = function() {
+ if (!($routeParams.slave_id in $scope.slaves)) {
+ $scope.alert_message = 'No slave found with ID: ' + $routeParams.slave_id;
$('#alert').show();
return;
}
- // Construct maps of the executors.
- $scope.framework.executors = _.object(
- _.pluck($scope.framework.executors, 'id'), $scope.framework.executors);
- $scope.framework.completed_executors = _.object(
- _.pluck($scope.framework.completed_executors, 'id'), $scope.framework.completed_executors);
-
- // Compute the framework stats.
- $scope.framework.num_tasks = 0;
- $scope.framework.cpus = 0;
- $scope.framework.mem = 0;
-
- _.each($scope.framework.executors, function(executor) {
- $scope.framework.num_tasks += _.size(executor.tasks);
- $scope.framework.cpus += executor.resources.cpus;
- $scope.framework.mem += executor.resources.mem;
- });
-
- // Index the monitoring data.
- $scope.monitor = {};
-
- $scope.framework.resource_usage = {};
- $scope.framework.resource_usage["cpu_time"] = 0.0;
- $scope.framework.resource_usage["cpu_usage"] = 0.0;
- $scope.framework.resource_usage["memory_rss"] = 0.0;
+ var pid = $scope.slaves[$routeParams.slave_id].pid;
+ var hostname = $scope.slaves[$routeParams.slave_id].hostname;
+ var id = pid.substring(0, pid.indexOf('@'));
+ var host = hostname + ":" + pid.substring(pid.lastIndexOf(':') + 1);
- _.each(monitor, function(executor) {
- if (!$scope.monitor[executor.framework_id]) {
- $scope.monitor[executor.framework_id] = {};
+ $scope.log = function($event) {
+ if (!$scope.state.log_dir) {
+ $dialog.messageBox(
+ 'Logging to a file is not enabled',
+ "Set the 'log_dir' option if you wish to access the logs.",
+ [{label: 'Continue'}]
+ ).open();
+ } else {
+ pailer(host, '/slave/log', 'Mesos Slave');
}
- $scope.monitor[executor.framework_id][executor.executor_id] = executor;
-
- $scope.framework.resource_usage["cpu_time"] +=
- executor.resource_usage.cpu_time;
- $scope.framework.resource_usage["cpu_usage"] +=
- executor.resource_usage.cpu_usage;
- $scope.framework.resource_usage["memory_rss"] +=
- executor.resource_usage.memory_rss;
- });
+ };
- $('#slave').show();
- },
- function (reason) {
- $scope.alert_message = 'Failed to get slave usage / state: ' + reason;
- $('#alert').show();
- });
- };
+ var usageRequest = $http.jsonp(
+ 'http://' + host + '/monitor/usage.json?jsonp=JSON_CALLBACK');
- if ($scope.state) {
- update();
- }
+ var stateRequest = $http.jsonp(
+ 'http://' + host + '/' + id + '/state.json?jsonp=JSON_CALLBACK');
- $(document).on('state_updated', update);
- $scope.$on('$beforeRouteChange', function() {
- $(document).off('state_updated', update);
- });
-}
+ $q.all([usageRequest, stateRequest]).then(function (responses) {
+ $scope.monitor = responses[0].data;
+ $scope.state = responses[1].data;
+
+ $scope.slave = {};
+ $scope.slave.frameworks = {};
+ $scope.slave.completed_frameworks = {};
+ $scope.slave.staging_tasks = 0;
+ $scope.slave.starting_tasks = 0;
+ $scope.slave.running_tasks = 0;
-function SlaveExecutorCtrl($scope, $routeParams, $http, $q) {
- setNavbarActiveTab('slaves');
+ // Update the framework map.
+ _.each($scope.state.frameworks, function(framework) {
+ $scope.slave.frameworks[framework.id] = framework;
+ });
- $scope.slave_id = $routeParams.slave_id;
- $scope.framework_id = $routeParams.framework_id;
- $scope.executor_id = $routeParams.executor_id;
+ // Update the completed framework map.
+ _.each($scope.state.completed_frameworks, function(framework) {
+ $scope.slave.completed_frameworks[framework.id] = framework;
+ });
- $scope.tables = {};
- $scope.tables['tasks'] = new Table('id');
- $scope.tables['queued_tasks'] = new Table('id');
- $scope.tables['completed_tasks'] = new Table('id');
+ // Compute the framework stats.
+ _.each(_.values($scope.state.frameworks).concat(_.values($scope.state.completed_frameworks)),
+ function(framework) {
+ framework.num_tasks = 0;
+ framework.cpus = 0;
+ framework.mem = 0;
+
+ _.each(framework.executors, function(executor) {
+ framework.num_tasks += _.size(executor.tasks);
+ framework.cpus += executor.resources.cpus;
+ framework.mem += executor.resources.mem;
+ });
+ });
- $scope.columnClass = columnClass($scope);
- $scope.selectColumn = selectColumn($scope);
+ $('#slave').show();
+ },
+ function (reason) {
+ $scope.alert_message = 'Failed to get slave usage / state: ' + reason;
+ $('#alert').show();
+ });
+ };
- var update = function() {
- if (!($routeParams.slave_id in $scope.slaves)) {
- $scope.alert_message = 'No slave found with ID: ' + $routeParams.slave_id;
- $('#alert').show();
- return;
+ if ($scope.state) {
+ update();
}
- var pid = $scope.slaves[$routeParams.slave_id].pid;
- var hostname = $scope.slaves[$routeParams.slave_id].hostname;
- var id = pid.substring(0, pid.indexOf('@'));
- var host = hostname + ":" + pid.substring(pid.lastIndexOf(':') + 1);
+ $(document).on('state_updated', update);
+ $scope.$on('$beforeRouteChange', function() {
+ $(document).off('state_updated', update);
+ });
+ });
- var usageRequest = $http.jsonp(
- 'http://' + host + '/monitor/usage.json?jsonp=JSON_CALLBACK');
- var stateRequest = $http.jsonp(
- 'http://' + host + '/' + id + '/state.json?jsonp=JSON_CALLBACK');
+ mesosApp.controller('SlaveFrameworkCtrl', function($scope, $routeParams, $http, $q) {
+ setNavbarActiveTab('slaves');
- $q.all([usageRequest, stateRequest]).then(function (responses) {
- var monitor = responses[0].data;
- $scope.state = responses[1].data;
+ $scope.slave_id = $routeParams.slave_id;
+ $scope.framework_id = $routeParams.framework_id;
- $scope.slave = {};
+ $scope.tables = {};
+ $scope.tables['executors'] = new Table('id');
+ $scope.tables['completed_executors'] = new Table('id');
- // Find the framework; it's either active or completed.
- $scope.framework = _.find($scope.state.frameworks.concat($scope.state.completed_frameworks),
- function(framework) {
- return $scope.framework_id === framework.id;
- });
+ $scope.columnClass = columnClass($scope);
+ $scope.selectColumn = selectColumn($scope);
- if (!$scope.framework) {
- $scope.alert_message = 'No framework found with ID: ' + $routeParams.framework_id;
+ var update = function() {
+ if (!($routeParams.slave_id in $scope.slaves)) {
+ $scope.alert_message = 'No slave found with ID: ' + $routeParams.slave_id;
$('#alert').show();
return;
}
- // Look for the executor; it's either active or completed.
- $scope.executor = _.find($scope.framework.executors.concat($scope.framework.completed_executors),
- function(executor) {
- return $scope.executor_id === executor.id;
- });
+ var pid = $scope.slaves[$routeParams.slave_id].pid;
+ var hostname = $scope.slaves[$routeParams.slave_id].hostname;
+ var id = pid.substring(0, pid.indexOf('@'));
+ var host = hostname + ":" + pid.substring(pid.lastIndexOf(':') + 1);
- if (!$scope.executor) {
- $scope.alert_message = 'No executor found with ID: ' + $routeParams.executor_id;
- $('#alert').show();
- return;
- }
+ var usageRequest = $http.jsonp(
+ 'http://' + host + '/monitor/usage.json?jsonp=JSON_CALLBACK');
+
+ var stateRequest = $http.jsonp(
+ 'http://' + host + '/' + id + '/state.json?jsonp=JSON_CALLBACK');
+
+ $q.all([usageRequest, stateRequest]).then(function (responses) {
+ var monitor = responses[0].data;
+ $scope.state = responses[1].data;
- // Index the monitoring data.
- $scope.monitor = {};
+ $scope.slave = {};
- _.each(monitor, function(executor) {
- if (!$scope.monitor[executor.framework_id]) {
- $scope.monitor[executor.framework_id] = {};
+ // Find the framework; it's either active or completed.
+ $scope.framework = _.find($scope.state.frameworks.concat($scope.state.completed_frameworks),
+ function(framework) {
+ return $scope.framework_id === framework.id;
+ });
+
+ if (!$scope.framework) {
+ $scope.alert_message = 'No framework found with ID: ' + $routeParams.framework_id;
+ $('#alert').show();
+ return;
}
- $scope.monitor[executor.framework_id][executor.executor_id] = executor;
+
+ // Construct maps of the executors.
+ $scope.framework.executors = _.object(
+ _.pluck($scope.framework.executors, 'id'), $scope.framework.executors);
+ $scope.framework.completed_executors = _.object(
+ _.pluck($scope.framework.completed_executors, 'id'), $scope.framework.completed_executors);
+
+ // Compute the framework stats.
+ $scope.framework.num_tasks = 0;
+ $scope.framework.cpus = 0;
+ $scope.framework.mem = 0;
+
+ _.each($scope.framework.executors, function(executor) {
+ $scope.framework.num_tasks += _.size(executor.tasks);
+ $scope.framework.cpus += executor.resources.cpus;
+ $scope.framework.mem += executor.resources.mem;
+ });
+
+ // Index the monitoring data.
+ $scope.monitor = {};
+
+ $scope.framework.resource_usage = {};
+ $scope.framework.resource_usage["cpu_time"] = 0.0;
+ $scope.framework.resource_usage["cpu_usage"] = 0.0;
+ $scope.framework.resource_usage["memory_rss"] = 0.0;
+
+ _.each(monitor, function(executor) {
+ if (!$scope.monitor[executor.framework_id]) {
+ $scope.monitor[executor.framework_id] = {};
+ }
+ $scope.monitor[executor.framework_id][executor.executor_id] = executor;
+
+ $scope.framework.resource_usage["cpu_time"] +=
+ executor.resource_usage.cpu_time;
+ $scope.framework.resource_usage["cpu_usage"] +=
+ executor.resource_usage.cpu_usage;
+ $scope.framework.resource_usage["memory_rss"] +=
+ executor.resource_usage.memory_rss;
+ });
+
+ $('#slave').show();
+ },
+ function (reason) {
+ $scope.alert_message = 'Failed to get slave usage / state: ' + reason;
+ $('#alert').show();
});
+ };
- $('#slave').show();
- },
- function (reason) {
- $scope.alert_message = 'Failed to get slave usage / state: ' + reason;
- $('#alert').show();
+ if ($scope.state) {
+ update();
+ }
+
+ $(document).on('state_updated', update);
+ $scope.$on('$beforeRouteChange', function() {
+ $(document).off('state_updated', update);
});
- };
+ });
- if ($scope.state) {
- update();
- }
- $(document).on('state_updated', update);
- $scope.$on('$beforeRouteChange', function() {
- $(document).off('state_updated', update);
- });
-}
+ mesosApp.controller('SlaveExecutorCtrl', function($scope, $routeParams, $http, $q) {
+ setNavbarActiveTab('slaves');
+ $scope.slave_id = $routeParams.slave_id;
+ $scope.framework_id = $routeParams.framework_id;
+ $scope.executor_id = $routeParams.executor_id;
-function BrowseCtrl($scope, $routeParams, $http) {
- setNavbarActiveTab('slaves');
+ $scope.tables = {};
+ $scope.tables['tasks'] = new Table('id');
+ $scope.tables['queued_tasks'] = new Table('id');
+ $scope.tables['completed_tasks'] = new Table('id');
- var update = function() {
- if ($routeParams.slave_id in $scope.slaves && $routeParams.path) {
- $scope.slave_id = $routeParams.slave_id;
- $scope.path = $routeParams.path;
+ $scope.columnClass = columnClass($scope);
+ $scope.selectColumn = selectColumn($scope);
+
+ var update = function() {
+ if (!($routeParams.slave_id in $scope.slaves)) {
+ $scope.alert_message = 'No slave found with ID: ' + $routeParams.slave_id;
+ $('#alert').show();
+ return;
+ }
var pid = $scope.slaves[$routeParams.slave_id].pid;
var hostname = $scope.slaves[$routeParams.slave_id].hostname;
var id = pid.substring(0, pid.indexOf('@'));
var host = hostname + ":" + pid.substring(pid.lastIndexOf(':') + 1);
- var url = 'http://' + host + '/files/browse.json?jsonp=JSON_CALLBACK';
- $scope.slave_host = host;
+ var usageRequest = $http.jsonp(
+ 'http://' + host + '/monitor/usage.json?jsonp=JSON_CALLBACK');
- $scope.pail = function($event, path) {
- pailer(host, path, decodeURIComponent(path));
- };
+ var stateRequest = $http.jsonp(
+ 'http://' + host + '/' + id + '/state.json?jsonp=JSON_CALLBACK');
- // TODO(bmahler): Try to get the error code / body in the error callback.
- // This wasn't working with the current version of angular.
- $http.jsonp(url, {params: {path: $routeParams.path}})
- .success(function(data) {
- $scope.listing = data;
- $('#listing').show();
- })
- .error(function() {
- $scope.alert_message = 'Error browsing path: ' + $routeParams.path;
+ $q.all([usageRequest, stateRequest]).then(function (responses) {
+ var monitor = responses[0].data;
+ $scope.state = responses[1].data;
+
+ $scope.slave = {};
+
+ // Find the framework; it's either active or completed.
+ $scope.framework = _.find($scope.state.frameworks.concat($scope.state.completed_frameworks),
+ function(framework) {
+ return $scope.framework_id === framework.id;
+ });
+
+ if (!$scope.framework) {
+ $scope.alert_message = 'No framework found with ID: ' + $routeParams.framework_id;
+ $('#alert').show();
+ return;
+ }
+
+ // Look for the executor; it's either active or completed.
+ $scope.executor = _.find($scope.framework.executors.concat($scope.framework.completed_executors),
+ function(executor) {
+ return $scope.executor_id === executor.id;
+ });
+
+ if (!$scope.executor) {
+ $scope.alert_message = 'No executor found with ID: ' + $routeParams.executor_id;
$('#alert').show();
+ return;
+ }
+
+ // Index the monitoring data.
+ $scope.monitor = {};
+
+ _.each(monitor, function(executor) {
+ if (!$scope.monitor[executor.framework_id]) {
+ $scope.monitor[executor.framework_id] = {};
+ }
+ $scope.monitor[executor.framework_id][executor.executor_id] = executor;
});
- } else {
- if (!($routeParams.slave_id in $scope.slaves)) {
- $scope.alert_message = 'No slave found with ID: ' + $routeParams.slave_id;
+
+ $('#slave').show();
+ },
+ function (reason) {
+ $scope.alert_message = 'Failed to get slave usage / state: ' + reason;
+ $('#alert').show();
+ });
+ };
+
+ if ($scope.state) {
+ update();
+ }
+
+ $(document).on('state_updated', update);
+ $scope.$on('$beforeRouteChange', function() {
+ $(document).off('state_updated', update);
+ });
+ });
+
+
+ mesosApp.controller('BrowseCtrl', function($scope, $routeParams, $http) {
+ setNavbarActiveTab('slaves');
+
+ var update = function() {
+ if ($routeParams.slave_id in $scope.slaves && $routeParams.path) {
+ $scope.slave_id = $routeParams.slave_id;
+ $scope.path = $routeParams.path;
+
+ var pid = $scope.slaves[$routeParams.slave_id].pid;
+ var hostname = $scope.slaves[$routeParams.slave_id].hostname;
+ var id = pid.substring(0, pid.indexOf('@'));
+ var host = hostname + ":" + pid.substring(pid.lastIndexOf(':') + 1);
+ var url = 'http://' + host + '/files/browse.json?jsonp=JSON_CALLBACK';
+
+ $scope.slave_host = host;
+
+ $scope.pail = function($event, path) {
+ pailer(host, path, decodeURIComponent(path));
+ };
+
+ // TODO(bmahler): Try to get the error code / body in the error callback.
+ // This wasn't working with the current version of angular.
+ $http.jsonp(url, {params: {path: $routeParams.path}})
+ .success(function(data) {
+ $scope.listing = data;
+ $('#listing').show();
+ })
+ .error(function() {
+ $scope.alert_message = 'Error browsing path: ' + $routeParams.path;
+ $('#alert').show();
+ });
} else {
- $scope.alert_message = 'Missing "path" request parameter.';
+ if (!($routeParams.slave_id in $scope.slaves)) {
+ $scope.alert_message = 'No slave found with ID: ' + $routeParams.slave_id;
+ } else {
+ $scope.alert_message = 'Missing "path" request parameter.';
+ }
+ $('#alert').show();
}
- $('#alert').show();
- }
- };
+ };
- if ($scope.state) {
- update();
- }
+ if ($scope.state) {
+ update();
+ }
- $(document).on('state_updated', update);
- $scope.$on('$beforeRouteChange', function() {
- $(document).off('state_updated', update);
+ $(document).on('state_updated', update);
+ $scope.$on('$beforeRouteChange', function() {
+ $(document).off('state_updated', update);
+ });
});
-}
+})();