YARN-4733. [YARN-3368] Initial commit of new YARN web UI. (wangda)

Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/c04d7e55
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/c04d7e55
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/c04d7e55

Branch: refs/heads/YARN-3368
Commit: c04d7e550c5a0faec191ce36d9a489463f46f392
Parents: ed9fcbe
Author: Wangda Tan <wan...@apache.org>
Authored: Tue Dec 8 16:37:50 2015 -0800
Committer: Wangda Tan <wan...@apache.org>
Committed: Mon Oct 17 11:30:30 2016 -0700

----------------------------------------------------------------------
 .../hadoop-yarn/hadoop-yarn-ui/.bowerrc         |   4 +
 .../hadoop-yarn/hadoop-yarn-ui/.editorconfig    |  34 +++
 .../hadoop-yarn/hadoop-yarn-ui/.ember-cli       |  11 +
 .../hadoop-yarn/hadoop-yarn-ui/.gitignore       |  17 ++
 .../hadoop-yarn/hadoop-yarn-ui/.jshintrc        |  32 +++
 .../hadoop-yarn/hadoop-yarn-ui/.travis.yml      |  23 ++
 .../hadoop-yarn/hadoop-yarn-ui/.watchmanconfig  |   3 +
 .../hadoop-yarn/hadoop-yarn-ui/README.md        |  24 ++
 .../hadoop-yarn-ui/app/adapters/cluster-info.js |  19 ++
 .../app/adapters/cluster-metric.js              |  19 ++
 .../app/adapters/yarn-app-attempt.js            |  31 +++
 .../hadoop-yarn-ui/app/adapters/yarn-app.js     |  25 ++
 .../app/adapters/yarn-container.js              |  42 +++
 .../hadoop-yarn-ui/app/adapters/yarn-queue.js   |  19 ++
 .../hadoop-yarn/hadoop-yarn-ui/app/app.js       |  20 ++
 .../hadoop-yarn-ui/app/components/.gitkeep      |   0
 .../app/components/app-attempt-table.js         |   4 +
 .../hadoop-yarn-ui/app/components/app-table.js  |   4 +
 .../hadoop-yarn-ui/app/components/bar-chart.js  | 104 +++++++
 .../app/components/base-chart-component.js      | 109 ++++++++
 .../app/components/container-table.js           |   4 +
 .../app/components/donut-chart.js               | 148 ++++++++++
 .../app/components/item-selector.js             |  21 ++
 .../app/components/queue-configuration-table.js |   4 +
 .../app/components/queue-navigator.js           |   4 +
 .../hadoop-yarn-ui/app/components/queue-view.js | 272 +++++++++++++++++++
 .../app/components/simple-table.js              |  30 ++
 .../app/components/timeline-view.js             | 250 +++++++++++++++++
 .../app/components/tree-selector.js             | 257 ++++++++++++++++++
 .../hadoop-yarn-ui/app/controllers/.gitkeep     |   0
 .../app/controllers/cluster-overview.js         |   5 +
 .../hadoop-yarn-ui/app/controllers/yarn-apps.js |   4 +
 .../app/controllers/yarn-queue.js               |   6 +
 .../hadoop-yarn-ui/app/helpers/.gitkeep         |   0
 .../hadoop-yarn/hadoop-yarn-ui/app/index.html   |  25 ++
 .../hadoop-yarn-ui/app/models/.gitkeep          |   0
 .../hadoop-yarn-ui/app/models/cluster-info.js   |  13 +
 .../hadoop-yarn-ui/app/models/cluster-metric.js | 115 ++++++++
 .../app/models/yarn-app-attempt.js              |  44 +++
 .../hadoop-yarn-ui/app/models/yarn-app.js       |  65 +++++
 .../hadoop-yarn-ui/app/models/yarn-container.js |  39 +++
 .../hadoop-yarn-ui/app/models/yarn-queue.js     |  76 ++++++
 .../hadoop-yarn-ui/app/models/yarn-user.js      |   8 +
 .../hadoop-yarn/hadoop-yarn-ui/app/router.js    |  16 ++
 .../hadoop-yarn-ui/app/routes/.gitkeep          |   0
 .../app/routes/cluster-overview.js              |  11 +
 .../app/routes/yarn-app-attempt.js              |  21 ++
 .../hadoop-yarn-ui/app/routes/yarn-app.js       |  10 +
 .../hadoop-yarn-ui/app/routes/yarn-apps.js      |   8 +
 .../hadoop-yarn-ui/app/routes/yarn-queue.js     |  20 ++
 .../app/routes/yarn-queues/index.js             |   5 +
 .../app/routes/yarn-queues/queues-selector.js   |   7 +
 .../app/serializers/cluster-info.js             |  29 ++
 .../app/serializers/cluster-metric.js           |  29 ++
 .../app/serializers/yarn-app-attempt.js         |  49 ++++
 .../hadoop-yarn-ui/app/serializers/yarn-app.js  |  66 +++++
 .../app/serializers/yarn-container.js           |  54 ++++
 .../app/serializers/yarn-queue.js               | 127 +++++++++
 .../hadoop-yarn-ui/app/styles/app.css           | 141 ++++++++++
 .../app/templates/application.hbs               |  25 ++
 .../app/templates/cluster-overview.hbs          |  56 ++++
 .../app/templates/components/.gitkeep           |   0
 .../templates/components/app-attempt-table.hbs  |  28 ++
 .../app/templates/components/app-table.hbs      |  62 +++++
 .../templates/components/container-table.hbs    |  36 +++
 .../components/queue-configuration-table.hbs    |  40 +++
 .../templates/components/queue-navigator.hbs    |  18 ++
 .../app/templates/components/timeline-view.hbs  |  35 +++
 .../app/templates/yarn-app-attempt.hbs          |  12 +
 .../hadoop-yarn-ui/app/templates/yarn-app.hbs   | 145 ++++++++++
 .../hadoop-yarn-ui/app/templates/yarn-apps.hbs  |   3 +
 .../hadoop-yarn-ui/app/templates/yarn-queue.hbs |  48 ++++
 .../hadoop-yarn-ui/app/utils/converter.js       |  74 +++++
 .../hadoop-yarn-ui/app/utils/sorter.js          |  15 +
 .../hadoop-yarn/hadoop-yarn-ui/bower.json       |  22 ++
 .../hadoop-yarn-ui/config/environment.js        |  47 ++++
 .../hadoop-yarn-ui/ember-cli-build.js           |  29 ++
 .../hadoop-yarn/hadoop-yarn-ui/jsconfig.json    |   6 +
 .../hadoop-yarn/hadoop-yarn-ui/package.json     |  44 +++
 .../assets/images/datatables/Sorting icons.psd  | Bin 0 -> 27490 bytes
 .../public/assets/images/datatables/favicon.ico | Bin 0 -> 894 bytes
 .../assets/images/datatables/sort_asc.png       | Bin 0 -> 160 bytes
 .../images/datatables/sort_asc_disabled.png     | Bin 0 -> 148 bytes
 .../assets/images/datatables/sort_both.png      | Bin 0 -> 201 bytes
 .../assets/images/datatables/sort_desc.png      | Bin 0 -> 158 bytes
 .../images/datatables/sort_desc_disabled.png    | Bin 0 -> 146 bytes
 .../hadoop-yarn-ui/public/crossdomain.xml       |  15 +
 .../hadoop-yarn-ui/public/robots.txt            |   3 +
 .../hadoop-yarn/hadoop-yarn-ui/testem.json      |  12 +
 .../hadoop-yarn/hadoop-yarn-ui/tests/.jshintrc  |  52 ++++
 .../hadoop-yarn-ui/tests/helpers/resolver.js    |  11 +
 .../hadoop-yarn-ui/tests/helpers/start-app.js   |  18 ++
 .../hadoop-yarn/hadoop-yarn-ui/tests/index.html |  33 +++
 .../hadoop-yarn-ui/tests/test-helper.js         |   6 +
 .../hadoop-yarn-ui/tests/unit/.gitkeep          |   0
 .../tests/unit/adapters/yarn-app-test.js        |  12 +
 .../tests/unit/controllers/yarn-apps-test.js    |  12 +
 .../tests/unit/controllers/yarn-queues-test.js  |  12 +
 .../tests/unit/mixins/charts-test.js            |  12 +
 .../tests/unit/models/yarn-app-test.js          |  12 +
 .../tests/unit/routes/yarn-apps-test.js         |  11 +
 .../tests/unit/serializers/yarn-app-test.js     |  15 +
 .../tests/unit/utils/converter-test.js          |  10 +
 .../hadoop-yarn/hadoop-yarn-ui/vendor/.gitkeep  |   0
 104 files changed, 3518 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.bowerrc
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.bowerrc 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.bowerrc
new file mode 100644
index 0000000..959e169
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.bowerrc
@@ -0,0 +1,4 @@
+{
+  "directory": "bower_components",
+  "analytics": false
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.editorconfig
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.editorconfig 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.editorconfig
new file mode 100644
index 0000000..47c5438
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.editorconfig
@@ -0,0 +1,34 @@
+# EditorConfig helps developers define and maintain consistent
+# coding styles between different editors and IDEs
+# editorconfig.org
+
+root = true
+
+
+[*]
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+indent_style = space
+indent_size = 2
+
+[*.js]
+indent_style = space
+indent_size = 2
+
+[*.hbs]
+insert_final_newline = false
+indent_style = space
+indent_size = 2
+
+[*.css]
+indent_style = space
+indent_size = 2
+
+[*.html]
+indent_style = space
+indent_size = 2
+
+[*.{diff,md}]
+trim_trailing_whitespace = false

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.ember-cli
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.ember-cli 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.ember-cli
new file mode 100644
index 0000000..96bd287
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.ember-cli
@@ -0,0 +1,11 @@
+{
+  /**
+    Ember CLI sends analytics information by default. The data is completely
+    anonymous, but there are times when you might want to disable this 
behavior.
+
+    Setting `disableAnalytics` to true will prevent any data from being sent.
+  */
+  "disableAnalytics": false,
+  "liveReload": true,
+  "watcher": "polling"
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.gitignore
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.gitignore 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.gitignore
new file mode 100644
index 0000000..86fceae
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.gitignore
@@ -0,0 +1,17 @@
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+
+# compiled output
+/dist
+/tmp
+
+# dependencies
+/node_modules
+/bower_components
+
+# misc
+/.sass-cache
+/connect.lock
+/coverage/*
+/libpeerconnection.log
+npm-debug.log
+testem.log

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.jshintrc
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.jshintrc 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.jshintrc
new file mode 100644
index 0000000..08096ef
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.jshintrc
@@ -0,0 +1,32 @@
+{
+  "predef": [
+    "document",
+    "window",
+    "-Promise"
+  ],
+  "browser": true,
+  "boss": true,
+  "curly": true,
+  "debug": false,
+  "devel": true,
+  "eqeqeq": true,
+  "evil": true,
+  "forin": false,
+  "immed": false,
+  "laxbreak": false,
+  "newcap": true,
+  "noarg": true,
+  "noempty": false,
+  "nonew": false,
+  "nomen": false,
+  "onevar": false,
+  "plusplus": false,
+  "regexp": false,
+  "undef": true,
+  "sub": true,
+  "strict": false,
+  "white": false,
+  "eqnull": true,
+  "esnext": true,
+  "unused": true
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.travis.yml
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.travis.yml 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.travis.yml
new file mode 100644
index 0000000..66dd107
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.travis.yml
@@ -0,0 +1,23 @@
+---
+language: node_js
+node_js:
+  - "0.12"
+
+sudo: false
+
+cache:
+  directories:
+    - node_modules
+
+before_install:
+  - export PATH=/usr/local/phantomjs-2.0.0/bin:$PATH
+  - "npm config set spin false"
+  - "npm install -g npm@^2"
+
+install:
+  - npm install -g bower
+  - npm install
+  - bower install
+
+script:
+  - npm test

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.watchmanconfig
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.watchmanconfig 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.watchmanconfig
new file mode 100644
index 0000000..5e9462c
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/.watchmanconfig
@@ -0,0 +1,3 @@
+{
+  "ignore_dirs": ["tmp"]
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/README.md
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/README.md 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/README.md
new file mode 100644
index 0000000..d5cba6e
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/README.md
@@ -0,0 +1,24 @@
+# Yarn-ui
+*This is a WIP project, nobody should use it in production.*
+
+## Prerequisites
+
+You will need the following things properly installed on your computer.
+
+* Install Node.js with NPM: https://nodejs.org/download/
+* After Node.js installed, install bower: `npm install -g bower`.
+* Install Ember-cli: `npm install -g ember-cli`
+
+## Installation
+
+* Goto root directory of yarn-ui project: 
`hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui`
+* `npm install && bower install`, it will take a while to finish.
+
+## Try it
+
+* Packaging and deploying Hadoop in this branch (You can use latest trunk 
after YARN-4417 committed to trunk)
+* Modify `app/adapters/yarn-app.js`, change `host` to your YARN RM web address
+* If you running YARN RM in your localhost, you should install `npm install -g 
corsproxy` and run `corsproxy` to avoid CORS errors. More details: 
`https://www.npmjs.com/package/corsproxy`. And the `host` of 
`app/adapters/yarn-app.js` should start with `localhost:1337`.
+* Run `ember server`
+* Visit your app at [http://localhost:4200](http://localhost:4200).
+

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/cluster-info.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/cluster-info.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/cluster-info.js
new file mode 100644
index 0000000..ef65792
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/cluster-info.js
@@ -0,0 +1,19 @@
+import DS from 'ember-data';
+
+export default DS.JSONAPIAdapter.extend({
+  headers: {
+    Accept: 'application/json'
+  },
+  host: 'http://localhost:1337/localhost:8088', // configurable
+  namespace: 'ws/v1/cluster', // common const
+  pathForType(modelName) {
+    return ''; // move to some common place, return path by modelname.
+  },
+  ajax(url, method, hash) {
+    hash = hash || {};
+    hash.crossDomain = true;
+    hash.xhrFields = {withCredentials: true};
+    hash.targetServer = "RM";
+    return this._super(url, method, hash); 
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/cluster-metric.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/cluster-metric.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/cluster-metric.js
new file mode 100644
index 0000000..d0f084c
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/cluster-metric.js
@@ -0,0 +1,19 @@
+import DS from 'ember-data';
+
+export default DS.JSONAPIAdapter.extend({
+  headers: {
+    Accept: 'application/json'
+  },
+  host: 'http://localhost:1337/localhost:8088', // configurable
+  namespace: 'ws/v1/cluster/metrics', // common const
+  pathForType(modelName) {
+    return ''; // move to some common place, return path by modelname.
+  },
+  ajax(url, method, hash) {
+    hash = hash || {};
+    hash.crossDomain = true;
+    hash.xhrFields = {withCredentials: true};
+    hash.targetServer = "RM";
+    return this._super(url, method, hash); 
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/yarn-app-attempt.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/yarn-app-attempt.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/yarn-app-attempt.js
new file mode 100644
index 0000000..3c95d64
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/yarn-app-attempt.js
@@ -0,0 +1,31 @@
+import DS from 'ember-data';
+import Converter from 'yarn-ui/utils/converter';
+
+export default DS.JSONAPIAdapter.extend({
+  headers: {
+    Accept: 'application/json'
+  },
+  host: 'http://localhost:1337/localhost:8088', // configurable
+  namespace: 'ws/v1/cluster', // common const
+
+  urlForQuery(query, modelName) {
+    var url = this._buildURL();
+    return url + '/apps/' + query.appId + "/appattempts";
+  },
+
+  urlForFindRecord(id, modelName, snapshot) {
+    var url = this._buildURL();
+    var url = url + '/apps/' + 
+           Converter.attemptIdToAppId(id) + "/appattempts/" + id;
+    console.log(url);
+    return url;
+  },
+
+  ajax(url, method, hash) {
+    hash = {};
+    hash.crossDomain = true;
+    hash.xhrFields = {withCredentials: true};
+    hash.targetServer = "RM";
+    return this._super(url, method, hash); 
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/yarn-app.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/yarn-app.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/yarn-app.js
new file mode 100644
index 0000000..e1108be
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/yarn-app.js
@@ -0,0 +1,25 @@
+import DS from 'ember-data';
+
+export default DS.JSONAPIAdapter.extend({
+  headers: {
+    Accept: 'application/json'
+  },
+  host: 'http://localhost:1337/localhost:8088', // configurable
+  namespace: 'ws/v1/cluster', // common const
+  pathForType(modelName) {
+    return 'apps'; // move to some common place, return path by modelname.
+  },
+  /*
+  urlForQuery(query, modelName) {
+    var url = this._buildURL();
+    return url + '/apps/' + query.appId + "/appattempts";
+  },
+  */
+  ajax(url, method, hash) {
+    hash = hash || {};
+    hash.crossDomain = true;
+    hash.xhrFields = {withCredentials: true};
+    hash.targetServer = "RM";
+    return this._super(url, method, hash); 
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/yarn-container.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/yarn-container.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/yarn-container.js
new file mode 100644
index 0000000..fe09f59
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/yarn-container.js
@@ -0,0 +1,42 @@
+import DS from 'ember-data';
+import Converter from 'yarn-ui/utils/converter';
+
+export default DS.JSONAPIAdapter.extend({
+  headers: {
+    Accept: 'application/json'
+  },
+  rmHost: 'http://localhost:1337/localhost:8088',
+  tsHost: 'http://localhost:1337/localhost:8188',
+  host: function() {
+    return undefined
+  }.property(),
+  rmNamespace: 'ws/v1/cluster',
+  tsNamespace: 'ws/v1/applicationhistory',
+  namespace: function() {
+    return undefined
+  }.property(),
+
+  urlForQuery(query, modelName) {
+    if (query.is_rm) {
+      this.set("host", this.rmHost);
+      this.set("namespace", this.rmNamespace);
+    } else {
+      this.set("host", this.tsHost);
+      this.set("namespace", this.tsNamespace);
+    }
+
+    var url = this._buildURL();
+    url = url + '/apps/' + Converter.attemptIdToAppId(query.app_attempt_id) 
+               + "/appattempts/" + query.app_attempt_id + "/containers";
+    console.log(url);
+    return url;
+  },
+
+  ajax(url, method, hash) {
+    hash = {};
+    hash.crossDomain = true;
+    hash.xhrFields = {withCredentials: true};
+    hash.targetServer = "RM";
+    return this._super(url, method, hash); 
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/yarn-queue.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/yarn-queue.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/yarn-queue.js
new file mode 100644
index 0000000..39cf796
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/adapters/yarn-queue.js
@@ -0,0 +1,19 @@
+import DS from 'ember-data';
+
+export default DS.JSONAPIAdapter.extend({
+  headers: {
+    Accept: 'application/json'
+  },
+  host: 'http://localhost:1337/localhost:8088', // configurable
+  namespace: 'ws/v1/cluster', // common const
+  pathForType(modelName) {
+    return 'scheduler'; // move to some common place, return path by modelname.
+  },
+  ajax(url, method, hash) {
+    hash = hash || {};
+    hash.crossDomain = true;
+    hash.xhrFields = {withCredentials: true};
+    hash.targetServer = "RM";
+    return this._super(url, method, hash); 
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/app.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/app.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/app.js
new file mode 100644
index 0000000..ff28ecf
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/app.js
@@ -0,0 +1,20 @@
+import Ember from 'ember';
+import Resolver from 'ember/resolver';
+import loadInitializers from 'ember/load-initializers';
+import config from './config/environment';
+import Sorter from 'yarn-ui/utils/sorter';
+
+var App;
+
+Ember.MODEL_FACTORY_INJECTIONS = true;
+
+App = Ember.Application.extend({
+  modulePrefix: config.modulePrefix,
+  podModulePrefix: config.podModulePrefix,
+  Resolver: Resolver
+});
+
+loadInitializers(App, config.modulePrefix);
+Sorter.initDataTableSorter();
+
+export default App;

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/.gitkeep
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/.gitkeep 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/.gitkeep
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/app-attempt-table.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/app-attempt-table.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/app-attempt-table.js
new file mode 100644
index 0000000..aff0493
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/app-attempt-table.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/app-table.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/app-table.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/app-table.js
new file mode 100644
index 0000000..aff0493
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/app-table.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/bar-chart.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/bar-chart.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/bar-chart.js
new file mode 100644
index 0000000..f24e947
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/bar-chart.js
@@ -0,0 +1,104 @@
+import Ember from 'ember';
+import BaseChartComponent from 'yarn-ui/components/base-chart-component';
+
+export default BaseChartComponent.extend({
+  // data: 
+  //    [{label=label1, value=value1}, ...]
+  //    ...
+  renderBarChart: function(data, title, textWidth = 50) {
+    var g = this.chart.g;
+    var layout = this.getLayout();
+    this.renderTitleAndBG(g, title, layout);
+
+    var maxValue = -1;
+    for (var i = 0; i < data.length; i++) {
+      if (data[i] instanceof Array) {
+        if (data[i][0].value > maxValue) {
+          maxValue = data[i][0].value;
+        }
+      } else {
+        if (data[i].value > maxValue) {
+          maxValue = data[i].value;
+        }
+      }
+    }
+
+    var singleBarHeight = 30;
+
+    // 50 is for text
+    var maxBarWidth = layout.x2 - layout.x1 - 2 * layout.margin - textWidth - 
50;
+
+    // 30 is for title
+    var maxBarsHeight = layout.y2 - layout.y1 - 2 * layout.margin - 30;
+    var gap = (maxBarsHeight - data.length * singleBarHeight) / (data.length -
+      1);
+
+    var xScaler = d3.scale.linear()
+      .domain([0, maxValue])
+      .range([0, maxBarWidth]);
+
+    // show bar text
+    for (var i = 0; i < data.length; i++) {
+      g.append("text")
+        .text(
+          function() {
+            return data[i].label;
+          })
+        .attr("y", function() {
+          return layout.y1 + singleBarHeight / 2 + layout.margin + (gap +
+            singleBarHeight) * i + 30;
+        })
+        .attr("x", layout.x1 + layout.margin);
+    }
+
+    // show bar
+    var bar = g.selectAll("bars")
+      .data(data)
+      .enter()
+      .append("rect")
+      .attr("y", function(d, i) {
+        return layout.y1 + 30 + layout.margin + (gap + singleBarHeight) * i;
+      })
+      .attr("x", layout.x1 + layout.margin + textWidth)
+      .attr("height", singleBarHeight)
+      .attr("fill", function(d, i) {
+        return this.colors[i];
+      }.bind(this))
+      .attr("width", 0);
+
+    this.bindTooltip(bar);
+
+    bar.transition()
+      .duration(500)
+      .attr("width", function(d) {
+        var w;
+        w = xScaler(d.value);
+        // At least each item has 3 px
+        w = Math.max(w, 3);
+        return w;
+      });
+
+    // show bar value
+    for (var i = 0; i < data.length; i++) {
+      g.append("text")
+        .text(
+          function() {
+            return data[i].value;
+          })
+        .attr("y", function() {
+          return layout.y1 + singleBarHeight / 2 + layout.margin + (gap +
+            singleBarHeight) * i + 30;
+        })
+        .attr("x", layout.x1 + layout.margin + textWidth + 15 + 
xScaler(data[i].value));
+    }
+  },
+
+  draw: function() {
+    this.initChart();
+    this.renderBarChart(this.get("data"), this.get("title"), 
this.get("textWidth"));
+  },
+
+  didInsertElement: function() {
+    this.draw();
+  },
+})
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/base-chart-component.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/base-chart-component.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/base-chart-component.js
new file mode 100644
index 0000000..acf2b5f
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/base-chart-component.js
@@ -0,0 +1,109 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+  chart: undefined,
+  tooltip : undefined,
+  colors: d3.scale.category10().range(),
+
+  initChart: function() {
+    this.chart = {
+      svg: undefined,
+      g: undefined,
+      h: 0,
+      w: 0,
+      tooltip: undefined
+    };
+
+    // Init tooltip if it is not initialized
+    this.tooltip = d3.select("#chart-tooltip");
+    if (!this.tooltip) {
+      this.tooltip = d3.select("body")
+        .append("div")
+        .attr("class", "tooltip")
+        .attr("id", "chart-tooltip")
+        .style("opacity", 0);
+    }
+
+    // Init svg
+    var svg = this.chart.svg;
+    if (svg) {
+      svg.remove();
+    }
+
+    var parentId = this.get("parentId");
+    var parent = d3.select("#" + parentId);
+    var bbox = parent.node().getBoundingClientRect();
+    this.chart.w = bbox.width - 30;
+
+    var ratio = 0.75; // 4:3 by default
+    if (this.get("ratio")) {
+      ratio = this.get("ratio");
+    }
+    this.chart.h = bbox.width * ratio;
+
+    if (this.get("maxHeight")) {
+      this.chart.h = Math.min(this.get("maxHeight"), this.chart.h);
+    }
+
+    this.chart.svg = parent.append("svg")
+      .attr("width", this.chart.w)
+      .attr("height", this.chart.h);
+
+    this.chart.g = this.chart.svg.append("g");
+  },
+
+  renderTitleAndBG: function(g, title, layout) {
+    var bg = g.append("g");
+    bg.append("text")
+      .text(title)
+      .attr("x", (layout.x1 + layout.x2) / 2)
+      .attr("y", layout.y1 + layout.margin + 20)
+      .attr("class", "chart-title");
+
+    bg.append("rect")
+      .attr("x", layout.x1)
+      .attr("y", layout.y1)
+      .attr("width", layout.x2 - layout.x1)
+      .attr("height", layout.y2 - layout.y1)
+      .attr("class", "chart-frame");
+  },
+
+  bindTooltip: function(d) {
+    d.on("mouseover", function(d) {
+        this.tooltip
+          .style("left", (d3.event.pageX) + "px")
+          .style("top", (d3.event.pageY - 28) + "px");
+      }.bind(this))
+      .on("mousemove", function(d) {
+        // Handle pie chart case
+        var data = d;
+        if (d.data) {
+          data = d.data;
+        }
+
+        this.tooltip.style("opacity", .9);
+        this.tooltip.html(data.label + " = " + data.value)
+          .style("left", (d3.event.pageX) + "px")
+          .style("top", (d3.event.pageY - 28) + "px");
+      }.bind(this))
+      .on("mouseout", function(d) {
+        this.tooltip.style("opacity", 0);
+      }.bind(this));
+  },
+
+  getLayout: function() {
+    var x1 = 0;
+    var y1 = 0;
+    var x2 = this.chart.w;
+    var y2 = this.chart.h;
+
+    var layout = {
+      x1: x1,
+      y1: y1,
+      x2: x2 - 10,
+      y2: y2 - 10,
+      margin: 10
+    };
+    return layout;
+  },
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/container-table.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/container-table.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/container-table.js
new file mode 100644
index 0000000..aff0493
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/container-table.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/donut-chart.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/donut-chart.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/donut-chart.js
new file mode 100644
index 0000000..608b0c1
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/donut-chart.js
@@ -0,0 +1,148 @@
+import Ember from 'ember';
+import BaseChartComponent from 'yarn-ui/components/base-chart-component';
+
+export default BaseChartComponent.extend({
+  /*
+   * data = [{label="xx", value=},{...}]
+   */
+  renderDonutChart: function(data, title, showLabels = false, 
+    middleLabel = "Total", middleValue = undefined) {
+    var g = this.chart.g;
+    var layout = this.getLayout();
+    this.renderTitleAndBG(g, title, layout);
+
+    var total = 0;
+    var allZero = true;
+    for (var i = 0; i < data.length; i++) {
+      total += data[i].value;
+      if (data[i].value > 1e-6) {
+        allZero = false;
+      }
+    }
+
+    if (!middleValue) {
+      middleValue = total;
+    }
+
+    //Width and height
+    var h = layout.y2 - layout.y1;
+
+    // 50 is for title
+    var outerRadius = (h - 50 - 2 * layout.margin) / 2;
+    var innerRadius = outerRadius * 0.618;
+    var arc = d3.svg.arc()
+      .innerRadius(innerRadius)
+      .outerRadius(outerRadius);
+
+    var cx;
+    var cy = layout.y1 + 50 + layout.margin + outerRadius;
+    if (showLabels) {
+      cx = layout.x1 + layout.margin + outerRadius;
+    } else {
+      cx = (layout.x1 + layout.x2) / 2;
+    }
+
+    var pie = d3.layout.pie();
+    pie.sort(null);
+    pie.value(function(d) {
+      var v = d.value;
+      // make sure it > 0
+      v = Math.max(v, 1e-6);
+      return v;
+    });
+
+    //Set up groups
+    var arcs = g
+      .selectAll("g.arc")
+      .data(pie(data))
+      .enter()
+      .append("g")
+      .attr("class", "arc")
+      .attr("transform", "translate(" + cx + "," + cy + ")");
+
+    function tweenPie(finish) {
+      var start = {
+        startAngle: 0,
+        endAngle: 0
+      };
+      var i = d3.interpolate(start, finish);
+      return function(d) {
+        return arc(i(d));
+      };
+    }
+
+    //Draw arc paths
+    var path = arcs.append("path")
+      .attr("fill", function(d, i) {
+        if (d.value > 1e-6) {
+          return this.colors[i];
+        } else {
+          return "white";
+        }
+      }.bind(this))
+      .attr("d", arc)
+      .attr("stroke", function(d, i) {
+        if (allZero) {
+          return this.colors[i];
+        }
+      }.bind(this))
+      .attr("stroke-dasharray", function(d, i) {
+        if (d.value <= 1e-6) {
+          return "10,10";
+        }
+      }.bind(this));
+    this.bindTooltip(path);
+
+    // Show labels
+    if (showLabels) {
+      var lx = layout.x1 + layout.margin + outerRadius * 2 + 30;
+      var squareW = 15;
+      var margin = 10;
+
+      var select = g.selectAll(".rect")
+        .data(data)
+        .enter();
+      select.append("rect")
+        .attr("fill", function(d, i) {
+          return this.colors[i];
+        }.bind(this))
+        .attr("x", lx)
+        .attr("y", function(d, i) {
+          return layout.y1 + 50 + (squareW + margin) * i + layout.margin;
+        })
+        .attr("width", squareW)
+        .attr("height", squareW);
+      select.append("text")
+        .attr("x", lx + squareW + margin)
+        .attr("y", function(d, i) {
+          return layout.y1 + 50 + (squareW + margin) * i + layout.margin + 
squareW / 2;
+        })
+        .text(function(d) {
+          return d.label + ' = ' + d.value;
+        });
+    }
+
+    if (middleLabel) {
+      var highLightColor = this.colors[0];
+      g.append("text").text(middleLabel).attr("x", cx).attr("y", cy - 10).
+        attr("class", "donut-highlight-text").attr("fill", highLightColor);
+      g.append("text").text(middleValue).attr("x", cx).attr("y", cy + 20).
+        attr("class", "donut-highlight-text").attr("fill", highLightColor).
+        style("font-size", "30px");
+    }
+
+    path.transition()
+      .duration(500)
+      .attrTween('d', tweenPie);
+  },
+
+  draw: function() {
+    this.initChart();
+    this.renderDonutChart(this.get("data"), this.get("title"), 
this.get("showLabels"), 
+                          this.get("middleLabel"), this.get("middleValue"));
+  },
+
+  didInsertElement: function() {
+    this.draw();
+  },
+})
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/item-selector.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/item-selector.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/item-selector.js
new file mode 100644
index 0000000..a18ccae
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/item-selector.js
@@ -0,0 +1,21 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+  didInsertElement: function() {
+    $(".js-example-basic-single").select2(
+      {
+        width: '100%',
+        placeholder: "Select a queue"
+      });
+    var elementId = this.get("element-id");
+    var prefix = this.get("prefix");
+
+    var element = d3.select("#" + elementId);
+
+    if (element) {
+      this.get("model").forEach(function(o) {
+        element.append("option").attr("value", o.get("name")).text(prefix + 
o.get("name"));
+      });
+    }
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/queue-configuration-table.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/queue-configuration-table.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/queue-configuration-table.js
new file mode 100644
index 0000000..aff0493
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/queue-configuration-table.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/queue-navigator.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/queue-navigator.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/queue-navigator.js
new file mode 100644
index 0000000..aff0493
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/queue-navigator.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/queue-view.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/queue-view.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/queue-view.js
new file mode 100644
index 0000000..c1fd8ff
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/queue-view.js
@@ -0,0 +1,272 @@
+import Ember from 'ember';
+import ChartUtilsMixin from 'yarn-ui/mixins/charts-utils';
+
+export default Ember.Component.extend(ChartUtilsMixin, {
+       queues: {
+               data: undefined,
+               foldedQueues: {},
+               selectedQueueCircle: undefined,
+               maxDepth: -1,
+       },
+
+       queueColors: d3.scale.category20().range(),
+
+       renderQueue: function(now, depth, sequence) {
+               if (depth > this.queues.maxDepth) {
+                       this.queues.maxDepth = depth;
+               }
+
+               var cx = 20 + depth * 30;
+               var cy = 20 + sequence * 30;
+               var name = now.get("name");
+
+               var g = this.queues.dataGroup.append("g")
+                       .attr("id", "queue-" + name + "-g");
+
+               var folded = this.queues.foldedQueues[name];
+               var isParentQueue = false;
+
+               // render its children
+               var children = [];
+               var childrenNames = now.get("children");
+               if (childrenNames) {
+                       childrenNames.forEach(function(name) {
+                               isParentQueue = true;
+                               var child = this.queues.data[name];
+                               if (child) {
+                                       children.push(child);
+                               }
+                       }.bind(this));
+               }
+               if (folded) {
+                       children = [];
+               }
+               var linefunction = d3.svg.line()
+                       .interpolate("basis")
+                       .x(function(d) {
+                               return d.x;
+                       })
+                       .y(function(d) {
+                               return d.y;
+                       });
+
+               for (var i = 0; i < children.length; i++) {
+                       sequence = sequence + 1;
+                       // Get center of children queue
+                       var cc = this.renderQueue(children[i],
+                               depth + 1, sequence);
+                       g.append("path")
+                               .attr("class", "queue")
+                               .attr("d", linefunction([{
+                                       x: cx,
+                                       y: cy
+                               }, {
+                                       x: cc.x - 20,
+                                       y: cc.y
+                               }, cc]));
+               }
+
+               var circle = g.append("circle")
+                       .attr("cx", cx)
+                       .attr("cy", cy)
+                       .attr("class", "queue");
+
+               circle.on('mouseover', function() {
+                       circle.style("fill", this.queueColors[1]);
+               }.bind(this));
+               circle.on('mouseout', function() {
+                       if (circle != this.queues.selectedQueueCircle) {
+                               circle.style("fill", this.queueColors[0]);
+                       }
+               }.bind(this));
+               circle.on('click', function() {
+                       circle.style("fill", this.queueColors[2]);
+                       var pre = this.queues.selectedQueueCircle;
+                       this.queues.selectedQueueCircle = circle;
+                       if (pre) {
+                               pre.on('mouseout')();
+                       }
+                       this.renderCharts(name);
+               }.bind(this));
+               circle.on('dblclick', function() {
+                       if (!isParentQueue) {
+                               return;
+                       }
+
+                       if (this.queues.foldedQueues[name]) {
+                               delete this.queues.foldedQueues[name];
+                       } else {
+                               this.queues.foldedQueues[name] = now;
+                       }
+                       this.renderQueues();
+               }.bind(this));
+
+               var text = name;
+               if (folded) {
+                       text = name + " (+)";
+               }
+
+               // print queue's name
+               g.append("text")
+                       .attr("x", cx + 30)
+                       .attr("y", cy + 5)
+                       .text(text)
+                       .attr("class", "queue");
+
+               return {
+                       x: cx,
+                       y: cy
+               };
+       },
+
+       renderQueues: function() {
+               if (this.queues.dataGroup) {
+                       this.queues.dataGroup.remove();
+               }
+               // render queues
+               this.queues.dataGroup = this.canvas.svg.append("g")
+                       .attr("id", "queues-g");
+               var rootQueue = undefined;
+
+               if (this.queues.data) {
+                       this.renderQueue(this.queues.data['root'], 0, 0);
+
+               }
+       },
+
+       draw: function() {
+               this.queues.data = {};
+               this.get("model")
+                       .forEach(function(o) {
+                               this.queues.data[o.id] = o;
+                       }.bind(this));
+
+               // get w/h of the svg
+               var bbox = d3.select("#main-container")
+                       .node()
+                       .getBoundingClientRect();
+               this.canvas.w = bbox.width;
+               this.canvas.h = Math.max(Object.keys(this.queues.data)
+                       .length * 35, 1500);
+
+               this.canvas.svg = d3.select("#main-container")
+                       .append("svg")
+                       .attr("width", this.canvas.w)
+                       .attr("height", this.canvas.h)
+                       .attr("id", "main-svg");
+
+               this.renderBackground();
+
+               this.renderQueues();
+               this.renderCharts("root");
+       },
+
+       didInsertElement: function() {
+               this.draw();
+       },
+
+       /*
+        * data = [{label="xx", value=},{...}]
+        */
+       renderTable: function(data, title, layout) {
+               d3.select("#main-svg")
+                       .append('table')
+                       .selectAll('tr')
+                       .data(data)
+                       .enter()
+                       .append('tr')
+                       .selectAll('td')
+                       .data(function(d) {
+                               return d;
+                       })
+                       .enter()
+                       .append('td')
+                       .text(function(d) {
+                               return d;
+                       });
+       },
+
+       renderQueueCapacities: function(queue, layout) {
+               // Render bar chart
+               this.renderBarChart(this.charts.g, [{
+                       label: "Cap",
+                       value: queue.get("capacity")
+               }, {
+                       label: "MaxCap",
+                       value: queue.get("maxCapacity")
+               }, {
+                       label: "UsedCap",
+                       value: queue.get("usedCapacity")
+               }], "Queue Capacities", layout, 60);
+       },
+
+       renderChildrenCapacities: function(queue, layout) {
+               var data = [];
+               var children = queue.get("children");
+               if (children) {
+                       for (var i = 0; i < children.length; i++) {
+                               var child = this.queues.data[children[i]];
+                               data.push({
+                                       label: child.get("name"),
+                                       value: child.get("capacity")
+                               });
+                       }
+               }
+
+               this.renderDonutChart(this.charts.g, data, "Children 
Capacities", layout, true);
+       },
+
+       renderChildrenUsedCapacities: function(queue, layout) {
+               var data = [];
+               var children = queue.get("children");
+               if (children) {
+                       for (var i = 0; i < children.length; i++) {
+                               var child = this.queues.data[children[i]];
+                               data.push({
+                                       label: child.get("name"),
+                                       value: child.get("usedCapacity")
+                               });
+                       }
+               }
+
+               this.renderDonutChart(this.charts.g, data, "Children Used 
Capacities", layout, true);
+       },
+
+       renderLeafQueueUsedCapacities: function(layout) {
+               var leafQueueUsedCaps = [];
+               for (var queueName in this.queues.data) {
+                       var q = this.queues.data[queueName];
+                       if ((!q.get("children")) || q.get("children")
+                               .length == 0) {
+                               // it's a leafqueue
+                               leafQueueUsedCaps.push({
+                                       label: q.get("name"),
+                                       value: q.get("usedCapacity")
+                               });
+                       }
+               }
+
+               this.renderDonutChart(this.charts.g, leafQueueUsedCaps, 
"LeafQueues Used Capacities",
+                       layout, true);
+       },
+
+       renderCharts: function(queueName) {
+         this.charts.leftBannerLen = this.queues.maxDepth * 30 + 100;
+               this.initCharts();
+
+               var queue = this.queues.data[queueName];
+               var idx = 0;
+
+               if (queue.get("name") == "root") {
+                       
this.renderLeafQueueUsedCapacities(this.getLayout(idx++));
+               }
+               if (queue.get("name") != "root") {
+                       this.renderQueueCapacities(queue, 
this.getLayout(idx++));
+               }
+               if (queue.get("children") && queue.get("children")
+                       .length > 0) {
+                       this.renderChildrenCapacities(queue, 
this.getLayout(idx++));
+                       this.renderChildrenUsedCapacities(queue, 
this.getLayout(idx++));
+               }
+       },
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/simple-table.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/simple-table.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/simple-table.js
new file mode 100644
index 0000000..ed8ff9b
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/simple-table.js
@@ -0,0 +1,30 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+  didInsertElement: function() {
+    var paging = this.get("paging") ? true : this.get("paging");
+    var ordering = this.get("ordering") ? true : this.get("ordering");
+    var info = this.get("info") ? true : this.get("info");
+    var bFilter = this.get("bFilter") ? true : this.get("bFilter");
+
+    var colDefs = [];
+    if (this.get("colTypes")) {
+      var typesArr = this.get("colTypes").split(' ');
+      var targetsArr = this.get("colTargets").split(' ');
+      for (var i = 0; i < typesArr.length; i++) {
+        colDefs.push({
+          type: typesArr[i],
+          targets: parseInt(targetsArr[i])
+        });
+      }
+    }
+
+    $('#' + this.get('table-id')).DataTable({
+      "paging":   paging,
+      "ordering": ordering, 
+      "info":     info,
+      "bFilter": bFilter,
+      columnDefs: colDefs
+    });
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/timeline-view.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/timeline-view.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/timeline-view.js
new file mode 100644
index 0000000..fe402bb
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/timeline-view.js
@@ -0,0 +1,250 @@
+import Ember from 'ember';
+import Converter from 'yarn-ui/utils/converter';
+
+export default Ember.Component.extend({
+  canvas: {
+    svg: undefined,
+    h: 0,
+    w: 0,
+    tooltip: undefined
+  },
+
+  clusterMetrics: undefined,
+  modelArr: [],
+  colors: d3.scale.category10().range(),
+  _selected: undefined,
+
+  selected: function() {
+    return this._selected;
+  }.property(),
+
+  tableComponentName: function() {
+    return "app-attempt-table";
+  }.property(),
+
+  setSelected: function(d) {
+    if (this._selected == d) {
+      return;
+    }
+
+    // restore color
+    if (this._selected) {
+      var dom = d3.select("#timeline-bar-" + this._selected.get("id"));
+      dom.attr("fill", this.colors[0]);
+    }
+
+    this._selected = d;
+    this.set("selected", d);
+    dom = d3.select("#timeline-bar-" + d.get("id"));
+    dom.attr("fill", this.colors[1]);
+  },
+
+  getPerItemHeight: function() {
+    var arrSize = this.modelArr.length;
+
+    if (arrSize < 20) {
+      return 30;
+    } else if (arrSize < 100) {
+      return 10;
+    } else {
+      return 2;
+    }
+  },
+
+  getPerItemGap: function() {
+    var arrSize = this.modelArr.length;
+
+    if (arrSize < 20) {
+      return 5;
+    } else if (arrSize < 100) {
+      return 1;
+    } else {
+      return 1;
+    }
+  },
+
+  getCanvasHeight: function() {
+    return (this.getPerItemHeight() + this.getPerItemGap()) * 
this.modelArr.length + 200;
+  },
+
+  draw: function(start, end) {
+    // get w/h of the svg
+    var bbox = d3.select("#" + this.get("parent-id"))
+      .node()
+      .getBoundingClientRect();
+    this.canvas.w = bbox.width;
+    this.canvas.h = this.getCanvasHeight();
+
+    this.canvas.svg = d3.select("#" + this.get("parent-id"))
+      .append("svg")
+      .attr("width", this.canvas.w)
+      .attr("height", this.canvas.h)
+      .attr("id", this.get("my-id"));
+    this.renderTimeline(start, end);
+  },
+
+  renderTimeline: function(start, end) {
+    var border = 30;
+    var singleBarHeight = this.getPerItemHeight();
+    var gap = this.getPerItemGap();
+    var textWidth = 50;
+    /*
+     start-time                              end-time
+      |--------------------------------------|
+         ==============
+                ==============
+                        ==============
+                              ===============
+     */
+    var xScaler = d3.scale.linear()
+      .domain([start, end])
+      .range([0, this.canvas.w - 2 * border - textWidth]);
+
+    /*
+     * Render frame of timeline view
+     */
+    this.canvas.svg.append("line")
+      .attr("x1", border + textWidth)
+      .attr("y1", border - 5)
+      .attr("x2", this.canvas.w - border)
+      .attr("y2", border - 5)
+      .attr("class", "chart");
+
+    this.canvas.svg.append("line")
+      .attr("x1", border + textWidth)
+      .attr("y1", border - 10)
+      .attr("x2", border + textWidth)
+      .attr("y2", border - 5)
+      .attr("class", "chart");
+
+    this.canvas.svg.append("line")
+      .attr("x1", this.canvas.w - border)
+      .attr("y1", border - 10)
+      .attr("x2", this.canvas.w - border)
+      .attr("y2", border - 5)
+      .attr("class", "chart");
+
+    this.canvas.svg.append("text")
+        .text(Converter.timeStampToDate(start))
+        .attr("y", border - 15)
+        .attr("x", border + textWidth)
+        .attr("class", "bar-chart-text")
+        .attr("text-anchor", "left");
+
+    this.canvas.svg.append("text")
+        .text(Converter.timeStampToDate(end))
+        .attr("y", border - 15)
+        .attr("x", this.canvas.w - border)
+        .attr("class", "bar-chart-text")
+        .attr("text-anchor", "end");
+
+    // show bar
+    var bar = this.canvas.svg.selectAll("bars")
+      .data(this.modelArr)
+      .enter()
+      .append("rect")
+      .attr("y", function(d, i) {
+        return border + (gap + singleBarHeight) * i;
+      })
+      .attr("x", function(d, i) {
+        return border + textWidth + xScaler(d.get("startTs"));
+      })
+      .attr("height", singleBarHeight)
+      .attr("fill", function(d, i) {
+        return this.colors[0];
+      }.bind(this))
+      .attr("width", function(d, i) {
+        var finishedTs = xScaler(d.get("finishedTs"));
+        finishedTs = finishedTs > 0 ? finishedTs : xScaler(end);
+        return finishedTs - xScaler(d.get("startTs"));
+      })
+      .attr("id", function(d, i) {
+        return "timeline-bar-" + d.get("id");
+      });
+    bar.on("click", function(d) {
+      this.setSelected(d);
+    }.bind(this));
+
+    this.bindTooltip(bar);
+
+    if (this.modelArr.length <= 20) {
+      // show bar texts
+      for (var i = 0; i < this.modelArr.length; i++) {
+        this.canvas.svg.append("text")
+          .text(this.modelArr[i].get(this.get("label")))
+          .attr("y", border + (gap + singleBarHeight) * i + singleBarHeight / 
2)
+          .attr("x", border)
+          .attr("class", "bar-chart-text");
+      }
+    }
+  },
+
+  bindTooltip: function(d) {
+    d.on("mouseover", function(d) {
+        this.tooltip
+          .style("left", (d3.event.pageX) + "px")
+          .style("top", (d3.event.pageY - 28) + "px");
+      }.bind(this))
+      .on("mousemove", function(d) {
+        this.tooltip.style("opacity", .9);
+        this.tooltip.html(d.get("tooltipLabel"))
+          .style("left", (d3.event.pageX) + "px")
+          .style("top", (d3.event.pageY - 28) + "px");
+      }.bind(this))
+      .on("mouseout", function(d) {
+        this.tooltip.style("opacity", 0);
+      }.bind(this));
+  },
+
+  initTooltip: function() {
+    this.tooltip = d3.select("body")
+      .append("div")
+      .attr("class", "tooltip")
+      .attr("id", "chart-tooltip")
+      .style("opacity", 0);
+  },
+
+  didInsertElement: function() {
+    // init tooltip
+    this.initTooltip();
+
+    // init model
+    if (this.get("rmModel")) {
+      this.get("rmModel").forEach(function(o) {
+        this.modelArr.push(o);
+      }.bind(this));
+    }
+
+    if (this.get("tsModel")) {
+     this.get("tsModel").forEach(function(o) {
+        this.modelArr.push(o);
+      }.bind(this)); 
+    }
+
+    this.modelArr.sort(function(a, b) {
+      var tsA = a.get("startTs");
+      var tsB = b.get("startTs");
+
+      return tsA - tsB;
+    });
+    if (this.modelArr.length > 0) {
+      var begin = this.modelArr[0].get("startTs");
+    }
+    var end = 0;
+    for (var i = 0; i < this.modelArr.length; i++) {
+      var ts = this.modelArr[i].get("finishedTs");
+      if (ts > end) {
+        end = ts;
+      }
+    }
+    if (end < begin) {
+      end = Date.now();
+    }
+
+    this.draw(begin, end);
+
+    if (this.modelArr.length > 0) {
+      this.setSelected(this.modelArr[0]);
+    }
+  },
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/tree-selector.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/tree-selector.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/tree-selector.js
new file mode 100644
index 0000000..470deaf
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/components/tree-selector.js
@@ -0,0 +1,257 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+  // Map: <queue-name, queue>
+  map : undefined,
+
+  // Normalized data for d3
+  treeData: undefined,
+
+  // folded queues, folded[<queue-name>] == true means <queue-name> is folded
+  foldedQueues: { },
+
+  // maxDepth
+  maxDepth: 0,
+
+  // num of leaf queue, folded queue is treated as leaf queue
+  numOfLeafQueue: 0,
+
+  // mainSvg
+  mainSvg: undefined,
+
+  // Init data
+  initData: function() {
+    this.map = { };
+    this.treeData = { };
+    this.maxDepth = 0;
+    this.numOfLeafQueue = 0;
+
+    this.get("model")
+      .forEach(function(o) {
+        this.map[o.id] = o;
+      }.bind(this));
+
+    var selected = this.get("selected");
+
+    this.initQueue("root", 1, this.treeData);
+  },
+
+  // get Children array of given queue
+  getChildrenNamesArray: function(q) {
+    var namesArr = [];
+
+    // Folded queue's children is empty
+    if (this.foldedQueues[q.get("name")]) {
+      return namesArr;
+    }
+
+    var names = q.get("children");
+    if (names) {
+      names.forEach(function(name) {
+        namesArr.push(name);
+      });
+    }
+
+    return namesArr;
+  },
+
+  // Init queues
+  initQueue: function(queueName, depth, node) {
+    if ((!queueName) || (!this.map[queueName])) {
+      // Queue is not existed
+      return;
+    }
+
+    if (depth > this.maxDepth) {
+      this.maxDepth = this.maxDepth + 1;
+    }
+
+    var queue = this.map[queueName];
+
+    var names = this.getChildrenNamesArray(queue);
+
+    node.name = queueName;
+    node.parent = queue.get("parent");
+    node.queueData = queue;
+
+    if (names.length > 0) {
+      node.children = [];
+
+      names.forEach(function(name) {
+        var childQueueData = {};
+        node.children.push(childQueueData);
+        this.initQueue(name, depth + 1, childQueueData);
+      }.bind(this));
+    } else {
+      this.numOfLeafQueue = this.numOfLeafQueue + 1;
+    }
+  },
+
+  update: function(source, root, tree, diagonal) {
+    var duration = 300;
+    var i = 0;
+
+    // Compute the new tree layout.
+    var nodes = tree.nodes(root).reverse();
+    var links = tree.links(nodes);
+
+    // Normalize for fixed-depth.
+    nodes.forEach(function(d) { d.y = d.depth * 200; });
+
+    // Update the nodes…
+    var node = this.mainSvg.selectAll("g.node")
+      .data(nodes, function(d) { return d.id || (d.id = ++i); });
+
+    // Enter any new nodes at the parent's previous position.
+    var nodeEnter = node.enter().append("g")
+      .attr("class", "node")
+      .attr("transform", function(d) { return "translate(" + source.y0 + "," + 
source.x0 + ")"; })
+      .on("click", function(d,i){
+        if (d.queueData.get("name") != this.get("selected")) {
+            document.location.href = "yarnQueue/" + d.queueData.get("name");
+        }
+      }.bind(this));
+      // .on("click", click);
+
+    nodeEnter.append("circle")
+      .attr("r", 1e-6)
+      .style("fill", function(d) {
+        var usedCap = d.queueData.get("usedCapacity");
+        if (usedCap <= 60.0) {
+          return "LimeGreen";
+        } else if (usedCap <= 100.0) {
+          return "DarkOrange";
+        } else {
+          return "LightCoral";
+        }
+      });
+
+    // append percentage
+    nodeEnter.append("text")
+      .attr("x", function(d) { return 0; })
+      .attr("dy", ".35em")
+      .attr("text-anchor", function(d) { return "middle"; })
+      .text(function(d) {
+        var usedCap = d.queueData.get("usedCapacity");
+        if (usedCap >= 100.0) {
+          return usedCap.toFixed(0) + "%";
+        } else {
+          return usedCap.toFixed(1) + "%";
+        }
+      })
+      .style("fill-opacity", 1e-6);
+
+    // append queue name
+    nodeEnter.append("text")
+      .attr("x", function(d) { return 40; })
+      .attr("dy", ".35em")
+      .attr("text-anchor", function(d) { return "start"; })
+      .text(function(d) { return d.name; })
+      .style("fill-opacity", 1e-6);
+
+    // Transition nodes to their new position.
+    var nodeUpdate = node.transition()
+      .duration(duration)
+      .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + 
")"; });
+
+    nodeUpdate.select("circle")
+      .attr("r", 20)
+      .attr("href", 
+        function(d) {
+          return "yarnQueues/" + d.queueData.get("name");
+        })
+      .style("stroke", function(d) {
+        if (d.queueData.get("name") == this.get("selected")) {
+          return "red";
+        } else {
+          return "gray";
+        }
+      }.bind(this));
+
+    nodeUpdate.selectAll("text")
+      .style("fill-opacity", 1);
+
+    // Transition exiting nodes to the parent's new position.
+    var nodeExit = node.exit().transition()
+      .duration(duration)
+      .attr("transform", function(d) { return "translate(" + source.y + "," + 
source.x + ")"; })
+      .remove();
+
+    nodeExit.select("circle")
+      .attr("r", 1e-6);
+
+    nodeExit.select("text")
+      .style("fill-opacity", 1e-6);
+
+    // Update the links…
+    var link = this.mainSvg.selectAll("path.link")
+      .data(links, function(d) { return d.target.id; });
+
+    // Enter any new links at the parent's previous position.
+    link.enter().insert("path", "g")
+      .attr("class", "link")
+      .attr("d", function(d) {
+      var o = {x: source.x0, y: source.y0};
+      return diagonal({source: o, target: o});
+      });
+
+    // Transition links to their new position.
+    link.transition()
+      .duration(duration)
+      .attr("d", diagonal);
+
+    // Transition exiting nodes to the parent's new position.
+    link.exit().transition()
+      .duration(duration)
+      .attr("d", function(d) {
+      var o = {x: source.x, y: source.y};
+      return diagonal({source: o, target: o});
+      })
+      .remove();
+
+    // Stash the old positions for transition.
+    nodes.forEach(function(d) {
+      d.x0 = d.x;
+      d.y0 = d.y;
+    });
+  },
+
+  reDraw: function() {
+    this.initData();
+
+    var margin = {top: 20, right: 120, bottom: 20, left: 120};
+    var treeWidth = this.maxDepth * 200;
+    var treeHeight = this.numOfLeafQueue * 80;
+    var width = treeWidth + margin.left + margin.right;
+    var height = treeHeight + margin.top + margin.bottom;
+    var layout = { };
+
+    if (this.mainSvg) {
+      this.mainSvg.remove();
+    }
+
+    this.mainSvg = d3.select("#" + this.get("parentId")).append("svg")
+      .attr("width", width)
+      .attr("height", height)
+      .attr("class", "tree-selector")
+      .append("g")
+      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
+
+    var tree = d3.layout.tree().size([treeHeight, treeWidth]);
+
+    var diagonal = d3.svg.diagonal()
+      .projection(function(d) { return [d.y, d.x]; });
+
+    var root = this.treeData;
+    root.x0 = height / 2;
+    root.y0 = 0;
+
+    d3.select(self.frameElement).style("height", height);
+
+    this.update(root, root, tree, diagonal);
+  },
+
+  didInsertElement: function() {
+   this.reDraw();
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/controllers/.gitkeep
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/controllers/.gitkeep 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/controllers/.gitkeep
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/controllers/cluster-overview.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/controllers/cluster-overview.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/controllers/cluster-overview.js
new file mode 100644
index 0000000..5c3c825
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/controllers/cluster-overview.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+
+export default Ember.Controller.extend({
+  loading: true,
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/controllers/yarn-apps.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/controllers/yarn-apps.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/controllers/yarn-apps.js
new file mode 100644
index 0000000..55ff9aa
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/controllers/yarn-apps.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Controller.extend({
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/controllers/yarn-queue.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/controllers/yarn-queue.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/controllers/yarn-queue.js
new file mode 100644
index 0000000..b16864e
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/controllers/yarn-queue.js
@@ -0,0 +1,6 @@
+import Ember from 'ember';
+
+export default Ember.Controller.extend({
+       needReload: true,
+  selectedQueue: undefined,
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/helpers/.gitkeep
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/helpers/.gitkeep 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/helpers/.gitkeep
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/index.html
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/index.html 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/index.html
new file mode 100644
index 0000000..edc4f2e
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/index.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <title>YarnUi</title>
+    <meta name="description" content="">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+
+    {{content-for 'head'}}
+
+    <link rel="stylesheet" href="assets/vendor.css">
+    <link rel="stylesheet" href="assets/yarn-ui.css">
+
+    {{content-for 'head-footer'}}
+  </head>
+  <body>
+    {{content-for 'body'}}
+
+    <script src="assets/vendor.js"></script>
+    <script src="assets/yarn-ui.js"></script>
+
+    {{content-for 'body-footer'}}
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/.gitkeep
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/.gitkeep 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/.gitkeep
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/cluster-info.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/cluster-info.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/cluster-info.js
new file mode 100644
index 0000000..b1f0a88
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/cluster-info.js
@@ -0,0 +1,13 @@
+import DS from 'ember-data';
+
+export default DS.Model.extend({
+  startedOn: DS.attr('string'),
+  state: DS.attr('string'),
+  haState: DS.attr('string'),
+  rmStateStoreName: DS.attr('string'),
+  resourceManagerVersion: DS.attr('string'),
+  resourceManagerBuildVersion: DS.attr('string'),
+  hadoopVersion: DS.attr('string'),
+  hadoopBuildVersion: DS.attr('string'),
+  hadoopVersionBuiltOn: DS.attr('string')
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/cluster-metric.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/cluster-metric.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/cluster-metric.js
new file mode 100644
index 0000000..2dd428c
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/cluster-metric.js
@@ -0,0 +1,115 @@
+import DS from 'ember-data';
+
+export default DS.Model.extend({
+  appsSubmitted: DS.attr('number'),
+  appsCompleted: DS.attr('number'),
+  appsPending: DS.attr('number'),
+  appsRunning: DS.attr('number'),
+  appsFailed: DS.attr('number'),
+  appsKilled: DS.attr('number'),
+  reservedMB: DS.attr('number'),
+  availableMB: DS.attr('number'),
+  allocatedMB: DS.attr('number'),
+  reservedVirtualCores: DS.attr('number'),
+  availableVirtualCores: DS.attr('number'),
+  allocatedVirtualCores: DS.attr('number'),
+  containersAllocated: DS.attr('number'),
+  containersReserved: DS.attr('number'),
+  containersPending: DS.attr('number'),
+  totalMB: DS.attr('number'),
+  totalVirtualCores: DS.attr('number'),
+  totalNodes: DS.attr('number'),
+  lostNodes: DS.attr('number'),
+  unhealthyNodes: DS.attr('number'),
+  decommissionedNodes: DS.attr('number'),
+  rebootedNodes: DS.attr('number'),
+  activeNodes: DS.attr('number'),
+
+  getFinishedAppsDataForDonutChart: function() {
+    var arr = [];
+    arr.push({
+      label: "Completed",
+      value: this.get("appsCompleted")
+    });
+    arr.push({
+      label: "Killed",
+      value: this.get("appsKilled")
+    });
+    arr.push({
+      label: "Failed",
+      value: this.get("appsFailed")
+    });
+
+    return arr;
+  }.property("appsCompleted", "appsKilled", "appsFailed"),
+
+  getRunningAppsDataForDonutChart: function() {
+    var arr = [];
+
+    arr.push({
+      label: "Pending",
+      value: this.get("appsPending")
+    });
+    arr.push({
+      label: "Running",
+      value: this.get("appsRunning")
+    });
+
+    return arr;
+  }.property("appsPending", "appsRunning"),
+
+  getNodesDataForDonutChart: function() {
+    var arr = [];
+    arr.push({
+      label: "Active",
+      value: this.get("activeNodes")
+    });
+    arr.push({
+      label: "Unhealthy",
+      value: this.get("unhealthyNodes")
+    });
+    arr.push({
+      label: "Decomissioned",
+      value: this.get("decommissionedNodes")
+    });
+    return arr;
+  }.property("activeNodes", "unhealthyNodes", "decommissionedNodes"),
+
+  getMemoryDataForDonutChart: function() {
+    var type = "MB";
+    var arr = [];
+    arr.push({
+      label: "Allocated",
+      value: this.get("allocated" + type)
+    });
+    arr.push({
+      label: "Reserved",
+      value: this.get("reserved" + type)
+    });
+    arr.push({
+      label: "Available",
+      value: this.get("available" + type)
+    });
+
+    return arr;
+  }.property("allocatedMB", "reservedMB", "availableMB"),
+
+  getVCoreDataForDonutChart: function() {
+    var type = "VirtualCores";
+    var arr = [];
+    arr.push({
+      label: "Allocated",
+      value: this.get("allocated" + type)
+    });
+    arr.push({
+      label: "Reserved",
+      value: this.get("reserved" + type)
+    });
+    arr.push({
+      label: "Available",
+      value: this.get("available" + type)
+    });
+
+    return arr;
+  }.property("allocatedVirtualCores", "reservedVirtualCores", 
"availableVirtualCores"),
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-app-attempt.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-app-attempt.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-app-attempt.js
new file mode 100644
index 0000000..fcb5134
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-app-attempt.js
@@ -0,0 +1,44 @@
+import DS from 'ember-data';
+import Converter from 'yarn-ui/utils/converter';
+
+export default DS.Model.extend({
+  startTime: DS.attr('string'),
+  finishedTime: DS.attr('string'),
+  containerId: DS.attr('string'),
+  nodeHttpAddress: DS.attr('string'),
+  nodeId: DS.attr('string'),
+  logsLink: DS.attr('string'),
+
+  startTs: function() {
+    return Converter.dateToTimeStamp(this.get("startTime"));
+  }.property("startTime"),
+
+  finishedTs: function() {
+    var ts = Converter.dateToTimeStamp(this.get("finishedTime"));
+    return ts;
+  }.property("finishedTime"),
+
+  shortAppAttemptId: function() {
+    return "attempt_" + 
+           
parseInt(Converter.containerIdToAttemptId(this.get("containerId")).split("_")[3]);
+  }.property("containerId"),
+
+  elapsedTime: function() {
+    var elapsedMs = this.get("finishedTs") - this.get("startTs");
+    if (elapsedMs <= 0) {
+      elapsedMs = Date.now() - this.get("startTs");
+    }
+
+    return Converter.msToElapsedTime(elapsedMs);
+  }.property(),
+
+  tooltipLabel: function() {
+    return "<p>Id:" + this.get("id") + 
+           "</p><p>ElapsedTime:" + 
+           String(this.get("elapsedTime")) + "</p>";
+  }.property(),
+
+  link: function() {
+    return "/yarnAppAttempt/" + this.get("id");
+  }.property(),
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-app.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-app.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-app.js
new file mode 100644
index 0000000..cb79be1
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-app.js
@@ -0,0 +1,65 @@
+import Converter from 'yarn-ui/utils/converter';
+import DS from 'ember-data';
+
+export default DS.Model.extend({
+       appName: DS.attr('string'),
+       user: DS.attr('string'),
+       queue: DS.attr('string'),
+       state: DS.attr('string'),
+       startTime: DS.attr('string'),
+       elapsedTime: DS.attr('string'),
+  finalStatus: DS.attr('string'),
+  finishedTime: DS.attr('finishedTime'),
+  progress: DS.attr('number'),
+  diagnostics: DS.attr('string'),
+  amContainerLogs: DS.attr('string'),
+  amHostHttpAddress: DS.attr('string'),
+  logAggregationStatus: DS.attr('string'),
+  unmanagedApplication: DS.attr('string'),
+  amNodeLabelExpression: DS.attr('string'),
+  applicationTags: DS.attr('string'),
+  priority: DS.attr('number'),
+  allocatedMB: DS.attr('number'),
+  allocatedVCores: DS.attr('number'),
+  runningContainers: DS.attr('number'),
+  memorySeconds: DS.attr('number'),
+  vcoreSeconds: DS.attr('number'),
+  preemptedResourceMB: DS.attr('number'),
+  preemptedResourceVCores: DS.attr('number'),
+  numNonAMContainerPreempted: DS.attr('number'),
+  numAMContainerPreempted: DS.attr('number'),
+
+  isFailed: function() {
+    return this.get('finalStatus') == "FAILED"
+  }.property("finalStatus"),
+
+  allocatedResource: function() {
+    return Converter.resourceToString(this.get("allocatedMB"), 
this.get("allocatedVCores"));
+  }.property("allocatedMB", "allocatedVCores"),
+
+  preemptedResource: function() {
+    return Converter.resourceToString(this.get("preemptedResourceMB"), 
this.get("preemptedResourceVCores"));
+  }.property("preemptedResourceMB", "preemptedResourceVCores"),
+
+  aggregatedResourceUsage: function() {
+    return Converter.resourceToString(this.get("memorySeconds"), 
this.get("vcoreSeconds")) + " (× Secs)";
+  }.property("memorySeconds", "vcoreSeconds"),
+
+  progressStyle: function() {
+    return "width: " + this.get("progress") + "%";
+  }.property("progress"),
+
+  finalStatusStyle: function() {
+    var style = "default";
+    var finalStatus = this.get("finalStatus");
+    if (finalStatus == "KILLED") {
+      style = "warning";
+    } else if (finalStatus == "FAILED") {
+      style = "danger";
+    } else {
+      style = "success";
+    }
+
+    return "label label-" + style;
+  }.property("finalStatus")
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-container.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-container.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-container.js
new file mode 100644
index 0000000..f7977be
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-container.js
@@ -0,0 +1,39 @@
+import DS from 'ember-data';
+import Converter from 'yarn-ui/utils/converter';
+
+export default DS.Model.extend({
+  allocatedMB: DS.attr('number'),
+  allocatedVCores: DS.attr('number'),
+  assignedNodeId: DS.attr('string'),
+  priority: DS.attr('number'),
+  startedTime: DS.attr('number'),
+  finishedTime: DS.attr('number'),
+  logUrl: DS.attr('string'),
+  containerExitStatus: DS.attr('number'),
+  containerState: DS.attr('string'),
+  nodeHttpAddress: DS.attr('string'),
+
+  startTs: function() {
+    return Converter.dateToTimeStamp(this.get("startedTime"));
+  }.property("startedTime"),
+
+  finishedTs: function() {
+    var ts = Converter.dateToTimeStamp(this.get("finishedTime"));
+    return ts;
+  }.property("finishedTime"),
+
+  elapsedTime: function() {
+    var elapsedMs = this.get("finishedTs") - this.get("startTs");
+    if (elapsedMs <= 0) {
+      elapsedMs = Date.now() - this.get("startTs");
+    }
+
+    return Converter.msToElapsedTime(elapsedMs);
+  }.property(),
+
+  tooltipLabel: function() {
+    return "<p>Id:" + this.get("id") + 
+           "</p><p>ElapsedTime:" + 
+           String(this.get("elapsedTime")) + "</p>";
+  }.property(),
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-queue.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-queue.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-queue.js
new file mode 100644
index 0000000..5b91d70
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-queue.js
@@ -0,0 +1,76 @@
+import DS from 'ember-data';
+
+export default DS.Model.extend({
+  name: DS.attr('string'),
+  children: DS.attr('array'),
+  parent: DS.attr('string'),
+  capacity: DS.attr('number'),
+  maxCapacity: DS.attr('number'),
+  usedCapacity: DS.attr('number'),
+  absCapacity: DS.attr('number'),
+  absMaxCapacity: DS.attr('number'),
+  absUsedCapacity: DS.attr('number'),
+  state: DS.attr('string'),
+  userLimit: DS.attr('number'),
+  userLimitFactor: DS.attr('number'),
+  preemptionDisabled: DS.attr('number'),
+  numPendingApplications: DS.attr('number'),
+  numActiveApplications: DS.attr('number'),
+  users: DS.hasMany('YarnUser'),
+
+  isLeafQueue: function() {
+    var len = this.get("children.length");
+    if (!len) {
+      return true;
+    }
+    return len <= 0;
+  }.property("children"),
+
+  capacitiesBarChartData: function() {
+    return [
+      {
+        label: "Absolute Capacity",
+        value: this.get("name") == "root" ? 100 : this.get("absCapacity")
+      },
+      {
+        label: "Absolute Used",
+        value: this.get("name") == "root" ? this.get("usedCapacity") : 
this.get("absUsedCapacity")
+      },
+      {
+        label: "Absolute Max Capacity",
+        value: this.get("name") == "root" ? 100 : this.get("absMaxCapacity")
+      }
+    ]
+  }.property("absCapacity", "absUsedCapacity", "absMaxCapacity"),
+
+  userUsagesDonutChartData: function() {
+    var data = [];
+    if (this.get("users")) {
+      this.get("users").forEach(function(o) {
+        data.push({
+          label: o.get("name"),
+          value: o.get("usedMemoryMB")
+        })
+      });
+    }
+
+    return data;
+  }.property("users"),
+
+  hasUserUsages: function() {
+    return this.get("userUsagesDonutChartData").length > 0;
+  }.property(),
+
+  numOfApplicationsDonutChartData: function() {
+    return [
+      {
+        label: "Pending Apps",
+        value: this.get("numPendingApplications") || 0 // TODO, fix the REST 
API so root will return #applications as well.
+      },
+      {
+        label: "Active Apps",
+        value: this.get("numActiveApplications") || 0
+      }
+    ]
+  }.property(),
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-user.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-user.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-user.js
new file mode 100644
index 0000000..6e9c03c
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/models/yarn-user.js
@@ -0,0 +1,8 @@
+import DS from 'ember-data';
+
+export default DS.Model.extend({
+  name: DS.attr('string'),
+  queueName: DS.attr('string'),
+  usedMemoryMB: DS.attr('number'),
+  usedVCore: DS.attr('number')
+})
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/router.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/router.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/router.js
new file mode 100644
index 0000000..c31190f
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/router.js
@@ -0,0 +1,16 @@
+import Ember from 'ember';
+import config from './config/environment';
+
+var Router = Ember.Router.extend({
+  location: config.locationType
+});
+
+Router.map(function() {
+  this.route('yarnApps');
+  this.route('yarnQueue', { path: '/yarnQueue/:queue_name' });
+  this.route('clusterOverview');
+  this.route('yarnApp', { path: '/yarnApp/:app_id' });
+  this.route('yarnAppAttempt', { path: '/yarnAppAttempt/:app_attempt_id'});
+});
+
+export default Router;

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/.gitkeep
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/.gitkeep 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/.gitkeep
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/cluster-overview.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/cluster-overview.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/cluster-overview.js
new file mode 100644
index 0000000..4ba5dcd
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/cluster-overview.js
@@ -0,0 +1,11 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+  model() {
+    return this.store.findAll('ClusterMetric');
+  },
+
+  afterModel() {
+    this.controllerFor("ClusterOverview").set("loading", false);
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-app-attempt.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-app-attempt.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-app-attempt.js
new file mode 100644
index 0000000..3b6adc7
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-app-attempt.js
@@ -0,0 +1,21 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+  model(param) {
+    return Ember.RSVP.hash({
+      attempt: this.store.findRecord('yarnAppAttempt', param.app_attempt_id),
+      
+      rmContainers: this.store.query('yarnContainer', 
+        {
+          app_attempt_id: param.app_attempt_id,
+          is_rm: true
+        }),
+      
+      tsContainers: this.store.query('yarnContainer', 
+        {
+          app_attempt_id: param.app_attempt_id,
+          is_rm: false
+        }),
+    });
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-app.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-app.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-app.js
new file mode 100644
index 0000000..03092aa
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-app.js
@@ -0,0 +1,10 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+  model(param) {
+    return Ember.RSVP.hash({
+      app: this.store.find('yarnApp', param.app_id),
+      attempts: this.store.query('yarnAppAttempt', { appId: param.app_id})
+    });
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-apps.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-apps.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-apps.js
new file mode 100644
index 0000000..79d184f
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-apps.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+  model() {
+       var apps = this.store.findAll('yarnApp');
+    return apps
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-queue.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-queue.js 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-queue.js
new file mode 100644
index 0000000..9396bac
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-queue.js
@@ -0,0 +1,20 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+  model(param) {
+    return Ember.RSVP.hash({
+      selected : param.queue_name,
+      queues: this.store.findAll('yarnQueue'),
+      selectedQueue : undefined,
+      apps: undefined, // apps of selected queue
+    });
+  },
+
+  afterModel(model) {
+    model.selectedQueue = this.store.peekRecord('yarnQueue', model.selected);
+    model.apps = this.store.findAll('yarnApp');
+    model.apps.forEach(function(o) {
+      console.log(o);
+    })
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-queues/index.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-queues/index.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-queues/index.js
new file mode 100644
index 0000000..9be90b1
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-queues/index.js
@@ -0,0 +1,5 @@
+export default Ember.Route.extend({
+  beforeModel() {
+    this.transitionTo('yarnQueues.root');
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-queues/queues-selector.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-queues/queues-selector.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-queues/queues-selector.js
new file mode 100644
index 0000000..0f6c572
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/routes/yarn-queues/queues-selector.js
@@ -0,0 +1,7 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+  model() {
+    return this.store.findAll('yarnQueue');
+  },
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/c04d7e55/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/serializers/cluster-info.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/serializers/cluster-info.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/serializers/cluster-info.js
new file mode 100644
index 0000000..cc936cb
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/app/serializers/cluster-info.js
@@ -0,0 +1,29 @@
+import DS from 'ember-data';
+
+export default DS.JSONAPISerializer.extend({
+    normalizeSingleResponse(store, primaryModelClass, payload, id,
+      requestType) {
+      var fixedPayload = {
+        id: id,
+        type: primaryModelClass.modelName,
+        attributes: payload
+      };
+
+      return this._super(store, primaryModelClass, fixedPayload, id,
+        requestType);
+    },
+
+    normalizeArrayResponse(store, primaryModelClass, payload, id,
+      requestType) {
+      // return expected is { data: [ {}, {} ] }
+      var normalizedArrayResponse = {};
+
+      // payload has apps : { app: [ {},{},{} ]  }
+      // need some error handling for ex apps or app may not be defined.
+      normalizedArrayResponse.data = [
+        this.normalizeSingleResponse(store, primaryModelClass,
+          payload.clusterInfo, payload.clusterInfo.id, requestType)
+      ];
+      return normalizedArrayResponse;
+    }
+});
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscr...@hadoop.apache.org
For additional commands, e-mail: common-commits-h...@hadoop.apache.org

Reply via email to