You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ak...@apache.org on 2014/01/14 19:25:49 UTC

git commit: AMBARI-4289. Mirroring: datasets loading integration with API. (akovalenko)

Updated Branches:
  refs/heads/trunk ab0c39c07 -> 88ddc9222


AMBARI-4289. Mirroring: datasets loading integration with API.  (akovalenko)


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

Branch: refs/heads/trunk
Commit: 88ddc9222a4629f0f6f798fdae0305ac48648e2b
Parents: ab0c39c
Author: Aleksandr Kovalenko <ak...@hortonworks.com>
Authored: Tue Jan 14 20:25:31 2014 +0200
Committer: Aleksandr Kovalenko <ak...@hortonworks.com>
Committed: Tue Jan 14 20:25:31 2014 +0200

----------------------------------------------------------------------
 .../data/mirroring/dataset1_definition.xml      |  23 ++
 .../data/mirroring/dataset1_instances.json      |  42 ++++
 .../data/mirroring/dataset2_definition.xml      |  23 ++
 .../data/mirroring/dataset2_instances.json      |  42 ++++
 .../data/mirroring/dataset3_definition.xml      |  23 ++
 .../data/mirroring/dataset3_instances.json      |   1 +
 .../app/assets/data/mirroring/datasets.json     |  16 ++
 .../controllers/global/cluster_controller.js    |  25 ---
 .../main/mirroring/jobs_controller.js           |  16 +-
 .../controllers/main/mirroring_controller.js    | 112 +++++++++-
 ambari-web/app/mappers/dataset_mapper.js        | 210 +++----------------
 ambari-web/app/models/dataset.js                |  53 +----
 ambari-web/app/models/dataset_job.js            |  28 +--
 ambari-web/app/routes/main.js                   |  11 -
 .../app/templates/main/mirroring/datasets.hbs   |  46 ++--
 .../app/templates/main/mirroring/jobs.hbs       |  12 +-
 ambari-web/app/utils/ajax.js                    |  20 ++
 ambari-web/app/utils/misc.js                    |  39 +++-
 .../app/views/main/mirroring/datasets_view.js   |  14 +-
 .../app/views/main/mirroring/jobs_view.js       |  61 +-----
 ambari-web/app/views/main/mirroring_view.js     |   7 +-
 21 files changed, 453 insertions(+), 371 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/assets/data/mirroring/dataset1_definition.xml
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/data/mirroring/dataset1_definition.xml b/ambari-web/app/assets/data/mirroring/dataset1_definition.xml
new file mode 100644
index 0000000..2b0c4d8
--- /dev/null
+++ b/ambari-web/app/assets/data/mirroring/dataset1_definition.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<feed xmlns="uri:falcon:feed:0.1" name="dataset1" description=""><frequency>hours(1)</frequency>
+    <clusters>
+        <cluster name="source-cluster" type="source">
+            <validity end="2014-12-31T00:00Z" start="2013-10-24T00:00Z"/>
+            <retention action="delete" limit="days(7)"/>
+        </cluster>
+
+        <cluster name="target-cluster1" type="target">
+            <validity end="2014-12-31T00:00Z" start="2013-10-24T00:00Z"/>
+            <retention action="delete" limit="months(1)"/>-
+            <locations>
+                <location type="data" path="/backup/app-logs1"/>
+            </locations>
+        </cluster>
+    </clusters>
+
+    <locations>
+        <location type="data" path="/app-logs1"/>
+    </locations>
+    <ACL permission="0755" group="users" owner="hue"/>
+    <schema provider="none" location="/none"/>
+</feed>

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/assets/data/mirroring/dataset1_instances.json
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/data/mirroring/dataset1_instances.json b/ambari-web/app/assets/data/mirroring/dataset1_instances.json
new file mode 100644
index 0000000..bc748e8
--- /dev/null
+++ b/ambari-web/app/assets/data/mirroring/dataset1_instances.json
@@ -0,0 +1,42 @@
+{"status": "SUCCEEDED", "message": "default/STATUS\n", "requestId": "default/a7463898-4d2a-4857-866d-15fdf65da84f\n", "instances": [
+  {
+    "instance": "2013-10-24T00:00Z",
+    "status": "KILLED",
+    "logFile": "http://c6407.ambari.apache.org:11000/oozie?job=0000004-140108205147729-oozie-oozi-W",
+    "cluster": "mcluster-bcp",
+    "sourceCluster": "mcluster",
+    "startTime": "2014-01-14T06:23:33Z",
+    "endTime": "2014-01-09T06:24:29Z",
+    "details": ""
+  },
+  {
+    "instance": "2013-10-24T01:00Z",
+    "status": "KILLED",
+    "logFile": "http://c6407.ambari.apache.org:11000/oozie?job=0000005-140108205147729-oozie-oozi-W",
+    "cluster": "mcluster-bcp",
+    "sourceCluster": "mcluster",
+    "startTime": "2014-01-09T06:25:35Z",
+    "endTime": "2014-01-09T06:26:02Z",
+    "details": ""
+  },
+  {
+    "instance": "2013-10-24T02:00Z",
+    "status": "KILLED",
+    "logFile": "http://c6407.ambari.apache.org:11000/oozie?job=0000006-140108205147729-oozie-oozi-W",
+    "cluster": "mcluster-bcp",
+    "sourceCluster": "mcluster",
+    "startTime": "2014-01-09T06:30:35Z",
+    "endTime": "2014-01-07T06:31:03Z",
+    "details": ""
+  },
+  {
+    "instance": "2013-10-24T03:00Z",
+    "status": "KILLED",
+    "logFile": "http://c6407.ambari.apache.org:11000/oozie?job=0000007-140108205147729-oozie-oozi-W",
+    "cluster": "mcluster-bcp",
+    "sourceCluster": "mcluster",
+    "startTime": "2014-01-09T06:35:35Z",
+    "endTime": "2014-01-02T06:36:03Z",
+    "details": ""
+  }
+]}

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/assets/data/mirroring/dataset2_definition.xml
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/data/mirroring/dataset2_definition.xml b/ambari-web/app/assets/data/mirroring/dataset2_definition.xml
new file mode 100644
index 0000000..a9e4c25
--- /dev/null
+++ b/ambari-web/app/assets/data/mirroring/dataset2_definition.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<feed xmlns="uri:falcon:feed:0.1" name="dataset2" description=""><frequency>hours(1)</frequency>
+    <clusters>
+        <cluster name="source-cluster" type="source">
+            <validity end="2014-12-31T00:00Z" start="2013-10-24T00:00Z"/>
+            <retention action="delete" limit="days(7)"/>
+        </cluster>
+
+        <cluster name="target-cluster1" type="target">
+            <validity end="2014-12-31T00:00Z" start="2013-10-24T00:00Z"/>
+            <retention action="delete" limit="months(1)"/>-
+            <locations>
+                <location type="data" path="/backup/app-logs2"/>
+            </locations>
+        </cluster>
+    </clusters>
+
+    <locations>
+        <location type="data" path="/app-logs2"/>
+    </locations>
+    <ACL permission="0755" group="users" owner="hue"/>
+    <schema provider="none" location="/none"/>
+</feed>

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/assets/data/mirroring/dataset2_instances.json
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/data/mirroring/dataset2_instances.json b/ambari-web/app/assets/data/mirroring/dataset2_instances.json
new file mode 100644
index 0000000..efa8d88
--- /dev/null
+++ b/ambari-web/app/assets/data/mirroring/dataset2_instances.json
@@ -0,0 +1,42 @@
+{"status": "SUCCEEDED", "message": "default/STATUS\n", "requestId": "default/a7463898-4d2a-4857-866d-15fdf65da84f\n", "instances": [
+  {
+    "instance": "2012-10-24T00:00Z",
+    "status": "RUNNING",
+    "logFile": "http://c6407.ambari.apache.org:11000/oozie?job=0000004-140108205147729-oozie-oozi-W",
+    "cluster": "mcluster-bcp",
+    "sourceCluster": "mcluster",
+    "startTime": "2014-01-09T06:23:33Z",
+    "endTime": "2014-01-09T06:24:29Z",
+    "details": ""
+  },
+  {
+    "instance": "2012-10-24T01:00Z",
+    "status": "SUCCEEDED",
+    "logFile": "http://c6407.ambari.apache.org:11000/oozie?job=0000005-140108205147729-oozie-oozi-W",
+    "cluster": "mcluster-bcp",
+    "sourceCluster": "mcluster",
+    "startTime": "2014-01-09T06:25:35Z",
+    "endTime": "2014-01-09T06:26:02Z",
+    "details": ""
+  },
+  {
+    "instance": "2012-10-24T02:00Z",
+    "status": "FAILED",
+    "logFile": "http://c6407.ambari.apache.org:11000/oozie?job=0000006-140108205147729-oozie-oozi-W",
+    "cluster": "mcluster-bcp",
+    "sourceCluster": "mcluster",
+    "startTime": "2014-01-09T06:30:35Z",
+    "endTime": "2014-01-09T06:31:03Z",
+    "details": ""
+  },
+  {
+    "instance": "2012-10-24T03:00Z",
+    "status": "SUSPENDED",
+    "logFile": "http://c6407.ambari.apache.org:11000/oozie?job=0000007-140108205147729-oozie-oozi-W",
+    "cluster": "mcluster-bcp",
+    "sourceCluster": "mcluster",
+    "startTime": "2014-01-09T06:35:35Z",
+    "endTime": "2014-01-09T06:36:03Z",
+    "details": ""
+  }
+]}

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/assets/data/mirroring/dataset3_definition.xml
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/data/mirroring/dataset3_definition.xml b/ambari-web/app/assets/data/mirroring/dataset3_definition.xml
new file mode 100644
index 0000000..6c94071
--- /dev/null
+++ b/ambari-web/app/assets/data/mirroring/dataset3_definition.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<feed xmlns="uri:falcon:feed:0.1" name="dataset3" description=""><frequency>hours(1)</frequency>
+    <clusters>
+        <cluster name="source-cluster" type="source">
+            <validity end="2014-12-31T00:00Z" start="2013-10-24T00:00Z"/>
+            <retention action="delete" limit="days(7)"/>
+        </cluster>
+
+        <cluster name="target-cluster2" type="target">
+            <validity end="2014-12-31T00:00Z" start="2013-10-24T00:00Z"/>
+            <retention action="delete" limit="months(1)"/>-
+            <locations>
+                <location type="data" path="/backup/app-logs3"/>
+            </locations>
+        </cluster>
+    </clusters>
+
+    <locations>
+        <location type="data" path="/app-logs3"/>
+    </locations>
+    <ACL permission="0755" group="users" owner="hue"/>
+    <schema provider="none" location="/none"/>
+</feed>

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/assets/data/mirroring/dataset3_instances.json
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/data/mirroring/dataset3_instances.json b/ambari-web/app/assets/data/mirroring/dataset3_instances.json
new file mode 100644
index 0000000..6d4afd5
--- /dev/null
+++ b/ambari-web/app/assets/data/mirroring/dataset3_instances.json
@@ -0,0 +1 @@
+{"status": "SUCCEEDED", "message": "default/STATUS\n", "requestId": "default/a7463898-4d2a-4857-866d-15fdf65da84f\n", "instances": []}

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/assets/data/mirroring/datasets.json
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/data/mirroring/datasets.json b/ambari-web/app/assets/data/mirroring/datasets.json
new file mode 100644
index 0000000..6b4dd90
--- /dev/null
+++ b/ambari-web/app/assets/data/mirroring/datasets.json
@@ -0,0 +1,16 @@
+{
+  "entity": [
+    {
+      "name": "dataset1",
+      "type": "feed"
+    },
+    {
+      "name": "dataset2",
+      "type": "feed"
+    },
+    {
+      "name": "dataset3",
+      "type": "feed"
+    }
+  ]
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/controllers/global/cluster_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/global/cluster_controller.js b/ambari-web/app/controllers/global/cluster_controller.js
index caca14b..98f6b68 100644
--- a/ambari-web/app/controllers/global/cluster_controller.js
+++ b/ambari-web/app/controllers/global/cluster_controller.js
@@ -59,8 +59,6 @@ App.ClusterController = Em.Controller.extend({
     'racks':false,
     'alerts':false,
     'users':false,
-    'datasets':false,
-    'targetclusters':false,
     'status': false,
     'componentConfigs': false
   }),
@@ -332,29 +330,6 @@ App.ClusterController = Em.Controller.extend({
       '&minimal_response=true';
     var usersUrl = App.testMode ? '/data/users/users.json' : App.apiPrefix + '/users/?fields=*';
     var racksUrl = "/data/racks/racks.json";
-    var dataSetUrl = "/data/mirroring/all_datasets.json";
-    var targetClusterUrl = "/data/mirroring/target_clusters.json";
-
-    if (App.supports.mirroring) {
-      App.HttpClient.get(targetClusterUrl, App.targetClusterMapper, {
-        complete: function (jqXHR, textStatus) {
-          self.updateLoadStatus('targetclusters');
-        }
-      }, function (jqXHR, textStatus) {
-        self.updateLoadStatus('targetclusters');
-      });
-
-      App.HttpClient.get(dataSetUrl, App.dataSetMapper, {
-        complete: function (jqXHR, textStatus) {
-          self.updateLoadStatus('datasets');
-        }
-      }, function (jqXHR, textStatus) {
-        self.updateLoadStatus('datasets');
-      });
-    } else {
-      self.updateLoadStatus('targetclusters');
-      self.updateLoadStatus('datasets');
-    }
 
     App.HttpClient.get(racksUrl, App.racksMapper, {
       complete:function (jqXHR, textStatus) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/controllers/main/mirroring/jobs_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/mirroring/jobs_controller.js b/ambari-web/app/controllers/main/mirroring/jobs_controller.js
index 01fd720..603cfb1 100644
--- a/ambari-web/app/controllers/main/mirroring/jobs_controller.js
+++ b/ambari-web/app/controllers/main/mirroring/jobs_controller.js
@@ -20,14 +20,16 @@ var App = require('app');
 
 App.MainJobsController = Em.Controller.extend({
   name: 'mainJobsController',
+
+  isLoaded: function () {
+    return App.router.get('mainMirroringController.isLoaded');
+  }.property('App.router.mainMirroringController.isLoaded'),
+
   jobs: function () {
-    var jobs = App.DataSetJob.find().filterProperty('dataset', this.get('content')).sort(
-      function(a, b) {
-        return a.get('id') < b.get('id');
-      }
-    );
-    return jobs;
-  }.property('content'),
+    var mainMirroringController = App.router.get('mainMirroringController');
+    return (this.get('isLoaded')) ?
+        mainMirroringController.get('datasets').findProperty('name', this.get('content.id')).get('datasetJobs') : [];
+  }.property('content', 'isLoaded'),
 
   actionDesc: function () {
     var dataset_status = this.get('content.status');

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/controllers/main/mirroring_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/mirroring_controller.js b/ambari-web/app/controllers/main/mirroring_controller.js
index 459b43f..fb66899 100644
--- a/ambari-web/app/controllers/main/mirroring_controller.js
+++ b/ambari-web/app/controllers/main/mirroring_controller.js
@@ -17,13 +17,118 @@
  */
 
 var App = require('app');
+var misc = require('utils/misc');
 
 App.MainMirroringController = Em.ArrayController.extend({
   name: 'mainMirroringController',
 
-  datasets: function () {
-    return App.Dataset.find();
-  }.property(),
+  datasetsData: [],
+
+  datasetCount: 0,
+
+  datasets: [],
+
+  isLoaded: false,
+
+  loadDatasets: function () {
+    this.set('isLoaded', false);
+    this.get('datasetsData').clear();
+    this.set('datasetCount', 0);
+    this.set('datasets', []);
+    App.ajax.send({
+      name: 'mirroring.get_all_datasets',
+      sender: this,
+      success: 'onLoadDatasetsListSuccess',
+      error: 'onLoadDatasetsListError'
+    });
+  },
+
+  onLoadDatasetsListSuccess: function (data) {
+    if (data && data.entity) {
+      this.set('datasetCount', data.entity.length);
+      data.entity.mapProperty('name').forEach(function (dataset) {
+        App.ajax.send({
+          name: 'mirroring.get_dataset_definition',
+          sender: this,
+          data: {
+            dataset: dataset
+          },
+          success: 'onLoadDatasetDefinitionSuccess',
+          error: 'onLoadDatasetDefinitionError'
+        });
+      }, this);
+    } else {
+      this.onLoadDatasetsListError();
+    }
+  },
+
+  onLoadDatasetsListError: function () {
+    console.error('Failed to load datasets list.');
+  },
+
+  onLoadDatasetDefinitionSuccess: function (data) {
+    var parsedData = misc.xmlToObject(data);
+    var clusters = parsedData.feed.clusters;
+    var targetCluster, sourceCluster;
+
+    if (clusters.cluster[0].locations) {
+      targetCluster = clusters.cluster[0];
+      sourceCluster = clusters.cluster[1];
+    } else {
+      targetCluster = clusters.cluster[1];
+      sourceCluster = clusters.cluster[0];
+    }
+    this.get('datasetsData').push(
+        Ember.Object.create({
+          name: parsedData.feed['@attributes'].name,
+          sourceClusterName: sourceCluster['@attributes'].name,
+          targetClusterName: targetCluster['@attributes'].name,
+          sourceDir: parsedData.feed.locations.location['@attributes'].path,
+          targetDir: targetCluster.locations.location['@attributes'].path,
+          instances: []
+        })
+    );
+    App.ajax.send({
+      name: 'mirroring.dataset.get_all_instances',
+      sender: this,
+      data: {
+        dataset: parsedData.feed['@attributes'].name
+      },
+      success: 'onLoadDatasetInstancesSuccess',
+      error: 'onLoadDatasetsInstancesError'
+    });
+  },
+
+  onLoadDatasetDefinitionError: function () {
+    console.error('Failed to load dataset definition.');
+  },
+
+  onLoadDatasetInstancesSuccess: function (data, sender, opts) {
+    var datasetJobs = [];
+    data.instances.forEach(function (instance) {
+      datasetJobs.push({
+        dataset: opts.dataset,
+        id: instance.instance,
+        status: instance.status,
+        endTime: new Date(instance.endTime).getTime(),
+        startTime: new Date(instance.startTime).getTime()
+      });
+    }, this);
+    this.get('datasetsData').findProperty('name', opts.dataset).set('instances', datasetJobs);
+    this.set('datasetCount', this.get('datasetCount') - 1);
+    if (this.get('datasetCount') < 1) {
+      App.Dataset.find().clear();
+      App.dataSetMapper.map(this.get('datasetsData'));
+      this.set('datasets', App.Dataset.find().toArray().sort(function(a,b){
+        return a.get('name') - b.get('name');
+      }));
+      this.set('isLoaded', true);
+    }
+  },
+
+  onLoadDatasetsInstancesError: function () {
+    console.error('Failed to load dataset instances.');
+  },
 
   targetClusters: function () {
     return App.TargetCluster.find();
@@ -46,5 +151,4 @@ App.MainMirroringController = Em.ArrayController.extend({
       }
     });
   }
-
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/mappers/dataset_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/dataset_mapper.js b/ambari-web/app/mappers/dataset_mapper.js
index c542039..7495a51 100644
--- a/ambari-web/app/mappers/dataset_mapper.js
+++ b/ambari-web/app/mappers/dataset_mapper.js
@@ -22,197 +22,45 @@ App.dataSetMapper = App.QuickDataMapper.create({
   model: App.Dataset,
   Jobs_model: App.DataSetJob,
   config: {
-    id: 'id', // approach 2 : to be calculated (TBC1)
-    name: 'Feeds.name', // from json
-    status: 'Feeds.status', // from json
-    source_cluster_name: 'Feeds.clusters.cluster[0].name', // approach1 : from json
-    $target_cluster: 'none', // will be loaded outside parser ( TBC2 ),
-    source_dir: 'Feeds.locations.location.path',
-    $schedule_id: 'none', // will be loaded outside parser
-    dataset_jobs: 'dataset_jobs', // TBC3 ( set of ids will be added )
-
-    // all below are unknown at present and may be blank
-    last_failed_date: 'last_failed_date', // TBC4
-    last_succeeded_date: 'last_succeeded_date', // TBC5
-    last_duration: 'last_duration', // TBC6
-    avg_data: 'avg_data', // TBC7
-    created_date: 'created_date', // TBC8
-    target_dir: 'target_dir'
-
+    id: 'name',
+    name: 'name',
+    status: 'status',
+    source_cluster_name: 'sourceClusterName',
+    target_cluster_name: 'targetClusterName',
+    source_dir: 'sourceDir',
+    target_dir: 'targetDir',
+    dataset_jobs_key: 'instances',
+    dataset_jobs_type: 'array',
+    dataset_jobs: {
+      item: 'id'
+    }
   },
   jobs_config: {
-    $dataset_id: 'none', // will be loaded outside parser
-    id: 'Instances.id',
-    status : 'Instances.status',
-    start_date: 'start_date',
-    end_date: 'end_date',
-    duration: 'duration'
-    //data: 'Instances.details'
-  },
-
-  schedule_config: {
-    $dataset_id: 'none', // will be loaded outside parser
     id: 'id',
-    start_date : 'start_date',
-    end_date :  'end_date',
-    start_time : 'start_time',
-    end_time : 'end_time',
-    timezone : 'timezone',
-    frequency : 'frequency'
-  },
-
-  loadSchedule: function (datasetItemFromJson) {
-    App.store.load(App.Dataset.Schedule, this.parseSchedule(datasetItemFromJson));
-  },
-
-  parseSchedule: function(datasetItemFromJson) {
-    var schedule = {};
-    schedule.id = datasetItemFromJson.id;
-    var source_cluster = datasetItemFromJson.Feeds.clusters.cluster.findProperty("type", "source");
-    var start_date = new Date(source_cluster.validity.start);
-    var end_date = new Date(source_cluster.validity.end);
-
-    var d = new Date();
-    var start_mm = start_date.getMonth() + 1; // In future may consider using getUTCMonth()
-    var start_dd = start_date.getDay();
-    var start_yyyy = start_date.getFullYear();
-    var end_mm = end_date.getMonth() + 1;
-    var end_dd = end_date.getDay();
-    var end_yyyy = end_date.getFullYear();
-
-    schedule.start_date = start_mm + "/" + start_dd + "/" + start_yyyy;
-    schedule.end_date = end_mm + "/" + end_dd + "/" + end_yyyy;
-
-    var start_hh = start_date.getHours();
-    var start_mi = start_date.getMinutes();
-    var start_ampm = (start_hh < 12 ? 'AM' : 'PM');
-    var end_hh = end_date.getHours();
-    var end_mi = end_date.getMinutes();
-    var end_ampm = (end_hh < 12 ? 'AM' : 'PM');
-
-    if (start_hh) {
-      start_hh %= 12;
-    }
-
-    if (end_hh) {
-      end_hh %= 12;
-    }
-
-    schedule.start_time = start_hh + ":" + start_mi + ":" + start_ampm;
-    schedule.end_time = end_hh + ":" + end_mi + ":" + end_ampm;
-
-    schedule.frequency = datasetItemFromJson.Feeds.frequency;
-    schedule.timezone = datasetItemFromJson.Feeds.timezone;
-    schedule.dataset_id = datasetItemFromJson.id;
-    return schedule;
+    name: 'id',
+    status : 'status',
+    start_date: 'startTime',
+    end_date: 'endTime',
+    dataset_id: 'dataset'
   },
 
   map: function (json) {
     if (!this.get('model')) {
       return;
     }
-    if (json && json.items && json.items.length > 0) {
-      var dataset_results = [];
-      json.items.forEach(function (item) {
-
-        try {
-          // TBC1
-          item.id = this.getId(item.Feeds.name);
-
-          // TBC3
-          item.dataset_jobs = [];
-
-          var last_failed_date = null;
-          var last_succeeded_date = null;
-          var last_end_date = null;
-          item.instances.forEach(function (job) {
-            var end_date = new Date(job.Instances.end);
-
-            if (!last_end_date) {
-              last_end_date = end_date;
-              item.last_job = job;
-            }
-            else if (end_date > last_end_date) {
-              last_end_date = end_date;
-              item.last_job = job;
-            }
-            if (job.Instances.status === 'FAILED') {
-              if (last_failed_date == null || last_failed_date < end_date) {
-                item.last_failed_date = end_date.getTime();
-                last_failed_date = end_date;
-              }
-            }
-            else if (job.Instances.status === 'SUCCESSFUL') {
-              if (last_succeeded_date == null || last_succeeded_date < end_date) {
-                item.last_succeeded_date = end_date.getTime();
-                last_succeeded_date = end_date;
-              }
-            }
-
-            item.dataset_jobs.push(job.Instances.id);
-          });
-
-          // calculate last_duration
-
-          var last_end_date = new Date(item.last_job.Instances.end);
-          var last_start_date = new Date(item.last_job.Instances.start);
-          item.last_duration = last_end_date - last_start_date;
-
-
-          item.avg_data = '';
-          item.created_date = '';
-          item.target_dir = '';
-
-          var newitem = this.parseIt(item, this.config);
-
-          // TBC2 - but shd be loaded after parsing
-          var target_cluster_name = (item.Feeds.clusters.cluster.findProperty("type", "target")).name;
-          var target_cluster_id = (item.Feeds.clusters.cluster.findProperty("type", "target")).name;
-
-          newitem.target_cluster_id = this.getId(target_cluster_id);
-
-          newitem.schedule_id = newitem.id;
-
-          this.loadSchedule(item);
-
-          dataset_results.push(newitem);
-        } catch (ex) {
-          console.debug('Exception occured : ' + ex);
-        }
-      }, this);
-
-      App.store.loadMany(this.get('model'), dataset_results);
-
-      try {
-        // Child records
-        var dataset_job_results = [];
-        json.items.forEach(function (item) {
-          item.instances.forEach(function (instance) {
-            instance.Instances.start = new Date(instance.Instances.start); // neeed to be calulated end -start
-            instance.Instances.end = new Date(instance.Instances.end); // neeed to be calulated end -start
-            instance.duration = instance.Instances.end - instance.Instances.start;
-            instance.start_date = instance.Instances.start;
-            instance.end_date = instance.Instances.end;
-
-            var result = this.parseIt(instance, this.jobs_config);
-            result.dataset_id = item.id;
-            dataset_job_results.push(result);
-
-
-          }, this)
+    if (json && json.length > 0) {
+      var datasetResults = [];
+      var dataSetJobResults = [];
+      json.forEach(function (item) {
+        item.instances.forEach(function (job) {
+          var newInstance = this.parseIt(job, this.get('jobs_config'));
+          dataSetJobResults.push(newInstance);
         }, this);
-
-        App.store.loadMany(this.get('Jobs_model'), dataset_job_results);
-      }
-      catch (ex) {
-        console.debug('Exception occured : ' + ex);
-      }
+        var newitem = this.parseIt(item, this.get('config'));
+            datasetResults.push(newitem);
+      }, this);
+      App.store.loadMany(this.get('Jobs_model'), dataSetJobResults);
+      App.store.loadMany(this.get('model'), datasetResults);
     }
-  },
-
-  getId: function(n) {
-    var re = new RegExp(" ", "g");
-    return n.replace(re, "_");
   }
-
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/models/dataset.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/dataset.js b/ambari-web/app/models/dataset.js
index a48c77e..89e9e99 100644
--- a/ambari-web/app/models/dataset.js
+++ b/ambari-web/app/models/dataset.js
@@ -20,31 +20,24 @@
 var App = require('app');
 
 App.Dataset = DS.Model.extend({
-  id: DS.attr('string'),
   name: DS.attr('string'),
   status: DS.attr('string'),
   sourceClusterName: DS.attr('string'),
-  targetCluster: DS.belongsTo('App.TargetCluster'),
+  targetClusterName: DS.attr('string'),
   sourceDir: DS.attr('string'),
   targetDir: DS.attr('string'),
-  schedule: DS.belongsTo('App.Dataset.Schedule'),
-  lastSucceededDate: DS.attr('number'),
-  lastFailedDate: DS.attr('number'),
-  lastDuration: DS.attr('number'),
-  avgData: DS.attr('string'),
-  createdDate: DS.attr('string'),
   datasetJobs: DS.hasMany('App.DataSetJob'),
 
+  //Last succeeded date. Will be calculated later.
+  lastSucceededDate: function () {
+    return '';
+  }.property(),
+
   //Next instance to run. Will be calculated later.
   nextInstance: function () {
     return '';
   }.property(),
 
-  //Name of target cluster related to dataset
-  cluster: function () {
-    return this.get('targetCluster.clusterName');
-  }.property('targetCluster.clusterName'),
-
   //Class name for dataset health status indicator
   healthClass: function () {
     var jobs = this.get('datasetJobs').toArray();
@@ -56,36 +49,4 @@ App.Dataset = DS.Model.extend({
   }.property('datasetJobs', 'datasetJobs.@each.status')
 });
 
-
-App.Dataset.Schedule = DS.Model.extend({
-  id: DS.attr('string'),
-  startDate: DS.attr('string'),
-  endDate: DS.attr('string'),
-  startTime: DS.attr('string'),
-  endTime: DS.attr('string'),
-  timezone: DS.attr('string'),
-  frequency: DS.attr('string'),
-  dataset: DS.belongsTo('App.Dataset')
-});
-
-App.Dataset.FIXTURES = [/*
- {
- id: 1,
- cluster_name: 'cluster1',
- stack_name: 'HDP',
- hosts: [1, 2, 3, 4],
- racks: [1, 2, 3, 4, 5, 6],
- max_hosts_per_rack: 10
- }*/
-];
-
-App.Dataset.Schedule.FIXTURES = [/*
- {
- id: 1,
- cluster_name: 'cluster1',
- stack_name: 'HDP',
- hosts: [1, 2, 3, 4],
- racks: [1, 2, 3, 4, 5, 6],
- max_hosts_per_rack: 10
- }*/
-];
\ No newline at end of file
+App.Dataset.FIXTURES = [];
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/models/dataset_job.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/dataset_job.js b/ambari-web/app/models/dataset_job.js
index 5ad698d..156ca80 100644
--- a/ambari-web/app/models/dataset_job.js
+++ b/ambari-web/app/models/dataset_job.js
@@ -21,28 +21,28 @@ var App = require('app');
 var date = require('utils/date');
 
 App.DataSetJob = DS.Model.extend({
+  name: DS.attr('string'),
   dataset: DS.belongsTo('App.Dataset'),
   status: DS.attr('string'),
   startDate: DS.attr('number'),
   endDate: DS.attr('number'),
-  duration: DS.attr('number'),
-  startDateFormatted: function () {
-    return date.dateFormatShort(this.get('startDate'));
+
+  startFormatted: function () {
+    if (this.get('startDate')) {
+      return $.timeago(this.get('startDate'));
+    }
   }.property('startDate'),
-  //data : DS.attr('string')
+
+  endFormatted: function () {
+    if (this.get('endDate')) {
+      return $.timeago(this.get('endDate'));
+    }
+  }.property('endDate'),
+
   healthClass: function () {
     return this.get('status') === 'FAILED' ? 'health-status-DEAD-RED' : 'health-status-LIVE';
   }.property('status')
 });
 
 
-App.DataSetJob.FIXTURES = [/*
- {
- id: 1,
- cluster_name: 'cluster1',
- stack_name: 'HDP',
- hosts: [1, 2, 3, 4],
- racks: [1, 2, 3, 4, 5, 6],
- max_hosts_per_rack: 10
- }*/
-];
+App.DataSetJob.FIXTURES = [];

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/routes/main.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/routes/main.js b/ambari-web/app/routes/main.js
index 8062583..bcefd43 100644
--- a/ambari-web/app/routes/main.js
+++ b/ambari-web/app/routes/main.js
@@ -114,22 +114,11 @@ module.exports = Em.Route.extend({
     route: '/mirroring',
     index: Ember.Route.extend({
       route: '/',
-      enter: function () {
-        this.setupController()
-      },
-      setupController: function () {
-        var controller = App.router.get('mainMirroringController');
-        var datasets = App.Dataset.find();
-        controller.set('datasets', datasets);
-      },
       connectOutlets: function (router, context) {
         router.get('mainController').connectOutlet('mainMirroring');
       }
     }),
 
-    gotoMirroringHome: function (router) {
-      router.transitionTo('mirroring/index');
-    },
     addNewDataset: function (router) {
       router.transitionTo('addNewDatasetRoute');
     },

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/templates/main/mirroring/datasets.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/mirroring/datasets.hbs b/ambari-web/app/templates/main/mirroring/datasets.hbs
index 2c8c3d5..23f8ef1 100644
--- a/ambari-web/app/templates/main/mirroring/datasets.hbs
+++ b/ambari-web/app/templates/main/mirroring/datasets.hbs
@@ -62,30 +62,38 @@
     </tr>
     </thead>
     <tbody>
-    {{#if view.pageContent}}
-      {{#each dataset in view.pageContent}}
-        {{#view view.DatasetView contentBinding="dataset"}}
-          <td class="first">
-            <span {{bindAttr class="dataset.healthClass"}}></span>
+    {{#if controller.isLoaded}}
+      {{#if view.pageContent}}
+        {{#each dataset in view.pageContent}}
+          {{#view view.DatasetView contentBinding="dataset"}}
+            <td class="first">
+              <span {{bindAttr class="dataset.healthClass"}}></span>
+            </td>
+            <td class="name">
+              <a title="{{unbound dataset.name}}" href="#" {{action "gotoShowJobs" dataset}}>{{unbound dataset.name}}</a>
+            </td>
+            <td>{{dataset.sourceDir}}</td>
+            <td>{{dataset.targetDir}}</td>
+            <td>{{dataset.targetClusterName}}</td>
+            <td>{{view.lastSucceededDateFormatted}}</td>
+            <td>{{dataset.nextInstance}}</td>
+          {{/view}}
+        {{/each}}
+      {{else}}
+        <tr>
+          <td class="first"></td>
+          <td colspan="6">
+            {{t mirroring.table.noDatasets}}
           </td>
-          <td class="name">
-            <a title="{{unbound dataset.name}}" href="#" {{action "gotoShowJobs" dataset}}>{{unbound dataset.name}}</a>
-          </td>
-          <td>{{dataset.sourceDir}}</td>
-          <td>{{dataset.targetDir}}</td>
-          <td>{{dataset.cluster}}</td>
-          <td>{{view.lastSucceededDateFormatted}}</td>
-          <td>{{dataset.nextInstance}}</td>
-        {{/view}}
-      {{/each}}
+        </tr>
+      {{/if}}
     {{else}}
       <tr>
-        <td class="first"></td>
-        <td colspan="6">
-          {{t mirroring.table.noDatasets}}
+        <td colspan="7">
+          <div class="spinner"></div>
         </td>
       </tr>
-    {{/if}}
+      {{/if}}
     </tbody>
   </table>
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/templates/main/mirroring/jobs.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/mirroring/jobs.hbs b/ambari-web/app/templates/main/mirroring/jobs.hbs
index bed8ae3..8c937cf 100644
--- a/ambari-web/app/templates/main/mirroring/jobs.hbs
+++ b/ambari-web/app/templates/main/mirroring/jobs.hbs
@@ -75,6 +75,7 @@
                 </tr>
                 </thead>
                 <tbody>
+                {{#if controller.isLoaded}}
                   {{#if view.pageContent}}
                     {{#each job in view.pageContent}}
                       {{#view view.JobView contentBinding="job"}}
@@ -84,8 +85,8 @@
                       </td>
 
                       <td>{{unbound job.id}}</td>
-                      <td>{{view.startFormatted}}</td>
-                      <td>{{view.endFormatted}}</td>
+                      <td>{{unbound job.startFormatted}}</td>
+                      <td>{{unbound job.endFormatted}}</td>
                       {{/view}}
                     {{/each}}
                   {{else}}
@@ -96,6 +97,13 @@
                       </td>
                   </tr>
                   {{/if}}
+                {{else}}
+                  <tr>
+                    <td colspan="7">
+                      <div class="spinner"></div>
+                    </td>
+                  </tr>
+                {{/if}}
                 </tbody>
             </table>
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/utils/ajax.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/ajax.js b/ambari-web/app/utils/ajax.js
index 9b98a3b..fcb0d11 100644
--- a/ambari-web/app/utils/ajax.js
+++ b/ambari-web/app/utils/ajax.js
@@ -1342,6 +1342,26 @@ var urls = {
         })
       }
     }
+  },
+
+  'mirroring.get_all_datasets': {
+    'real': 'falcon/entities/list/feed',
+    'mock': '/data/mirroring/datasets.json'
+  },
+
+  'mirroring.get_dataset_definition': {
+    'real': 'falcon/entities/definition/feed/{dataset}',
+    'mock': '/data/mirroring/{dataset}_definition.xml',
+    'format': function (data) {
+      return {
+        dataType: 'xml'
+      }
+    }
+  },
+
+  'mirroring.dataset.get_all_instances': {
+    'real': 'falcon/instance/status/feed/{dataset}',
+    'mock': '/data/mirroring/{dataset}_instances.json'
   }
 };
 /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/utils/misc.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/misc.js b/ambari-web/app/utils/misc.js
index 008345b..994397d 100644
--- a/ambari-web/app/utils/misc.js
+++ b/ambari-web/app/utils/misc.js
@@ -63,6 +63,43 @@ module.exports = {
         }
       }
     return sorted;
+  },
+
+  /**
+   * Convert XML document to Object
+   * @param xml
+   * @return {Object}
+   */
+  xmlToObject: function (xml) {
+    var obj = {};
+    if (xml.nodeType == 1) {
+      if (xml.attributes.length > 0) {
+        obj["@attributes"] = {};
+        for (var j = 0; j < xml.attributes.length; j++) {
+          var attribute = xml.attributes.item(j);
+          obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
+        }
+      }
+    } else if (xml.nodeType == 3) {
+      obj = xml.nodeValue;
+    }
+    if (xml.hasChildNodes()) {
+      for (var i = 0; i < xml.childNodes.length; i++) {
+        var item = xml.childNodes.item(i);
+        var nodeName = item.nodeName;
+        if (typeof (obj[nodeName]) == "undefined") {
+          obj[nodeName] = this.xmlToObject(item);
+        } else {
+          if (typeof (obj[nodeName].push) == "undefined") {
+            var old = obj[nodeName];
+            obj[nodeName] = [];
+            obj[nodeName].push(old);
+          }
+          obj[nodeName].push(this.xmlToObject(item));
+        }
+      }
+    }
+    return obj;
   }
-  
+
 };

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/views/main/mirroring/datasets_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/mirroring/datasets_view.js b/ambari-web/app/views/main/mirroring/datasets_view.js
index 52edcaa..9af9a40 100644
--- a/ambari-web/app/views/main/mirroring/datasets_view.js
+++ b/ambari-web/app/views/main/mirroring/datasets_view.js
@@ -55,17 +55,17 @@ App.MainDatasetsView = App.TableView.extend({
   }),
 
   sourceSort: sort.fieldView.extend({
-    name: 'source',
+    name: 'sourceDir',
     displayName: Em.I18n.t('mirroring.table.datasetSource')
   }),
 
   targetSort: sort.fieldView.extend({
-    name: 'target',
+    name: 'targetDir',
     displayName: Em.I18n.t('mirroring.table.datasetTarget')
   }),
 
   clusterSort: sort.fieldView.extend({
-    name: 'cluster',
+    name: 'targetClusterName',
     displayName: Em.I18n.t('common.cluster')
   }),
 
@@ -112,7 +112,7 @@ App.MainDatasetsView = App.TableView.extend({
     fieldType: 'input-medium',
     column: 4,
     content: function () {
-      return ['Any'].concat(this.get('parentView.content').mapProperty('targetCluster.clusterName'));
+      return ['Any'].concat(this.get('parentView.content').mapProperty('targetClusterName').uniq());
     }.property('this.parentView.content'),
     onClearValue: function () {
       if (this.get('value') === '') {
@@ -176,9 +176,9 @@ App.MainDatasetsView = App.TableView.extend({
   colPropAssoc: function () {
     var associations = [];
     associations[1] = 'name';
-    associations[2] = 'source';
-    associations[3] = 'target';
-    associations[4] = 'cluster';
+    associations[2] = 'sourceDir';
+    associations[3] = 'targetDir';
+    associations[4] = 'targetClusterName';
     associations[5] = 'lastSucceededDate';
     associations[6] = 'nextInstance';
     return associations;

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/views/main/mirroring/jobs_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/mirroring/jobs_view.js b/ambari-web/app/views/main/mirroring/jobs_view.js
index bd9579c..7a97cf4 100644
--- a/ambari-web/app/views/main/mirroring/jobs_view.js
+++ b/ambari-web/app/views/main/mirroring/jobs_view.js
@@ -27,7 +27,10 @@ App.MainJobsView = App.TableView.extend({
   }.property('controller.jobs'),
 
   didInsertElement: function () {
-    this.set('content', this.get('controller.jobs'));
+    var mainMirroringController = App.router.get('mainMirroringController');
+    if (!mainMirroringController.get('isLoaded')) {
+      mainMirroringController.loadDatasets();
+    }
   },
 
   dataset: function () {
@@ -36,9 +39,9 @@ App.MainJobsView = App.TableView.extend({
 
   sortView: sort.wrapperView,
   idSort: sort.fieldView.extend({
-    name: 'id',
+    name: 'name',
     displayName: Em.I18n.t('mirroring.table.jobId'),
-    type: 'number'
+    type: 'string'
   }),
   startSort: sort.fieldView.extend({
     name: 'startDate',
@@ -50,16 +53,6 @@ App.MainJobsView = App.TableView.extend({
     displayName: Em.I18n.t('mirroring.table.end'),
     type: 'number'
   }),
-  durationSort: sort.fieldView.extend({
-    name: 'duration',
-    displayName: Em.I18n.t('mirroring.table.duration'),
-    type: 'number'
-  }),
-  dataSort: sort.fieldView.extend({
-    name: 'data',
-    displayName: Em.I18n.t('mirroring.table.data'),
-    type: 'number'
-  }),
 
   /**
    * Filter view for name column
@@ -91,22 +84,6 @@ App.MainJobsView = App.TableView.extend({
     }
   }),
 
-  durationFilterView: filters.createTextView({
-    fieldType: 'input-medium',
-    column: 4,
-    onChangeValue: function () {
-      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'duration');
-    }
-  }),
-
-  dataFilterView: filters.createTextView({
-    fieldType: 'input-small',
-    column: 5,
-    onChangeValue: function () {
-      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'ambari-bandwidth');
-    }
-  }),
-
   JobView: Em.View.extend({
     content: null,
     tagName: 'tr',
@@ -187,27 +164,7 @@ App.MainJobsView = App.TableView.extend({
             break;
         }
       });
-    },
-
-    durationFormatted: function () {
-      var milliseconds = this.get('content.duration');
-      var h = Math.floor(milliseconds / 3600000);
-      var m = Math.floor((milliseconds % 3600000) / 60000);
-      var s = Math.floor(((milliseconds % 360000) % 60000) / 1000);
-      return (h == 0 ? '' : h + 'hr ') + (m == 0 ? '' : m + 'mins ') + (s == 0 ? '' : s + 'secs ');
-    }.property('content.duration'),
-
-    startFormatted: function () {
-      if (this.get('content.startDate')) {
-        return $.timeago(this.get('content.startDate'));
-      }
-    }.property('content.startDate'),
-
-    endFormatted: function () {
-      if (this.get('content.endDate')) {
-        return $.timeago(this.get('content.endDate'));
-      }
-    }.property('content.endDate')
+    }
   }),
 
   /**
@@ -215,11 +172,9 @@ App.MainJobsView = App.TableView.extend({
    */
   colPropAssoc: function () {
     var associations = [];
-    associations[1] = 'id';
+    associations[1] = 'name';
     associations[2] = 'startDate';
     associations[3] = 'endDate';
-    associations[4] = 'duration';
-    associations[5] = 'data';
     return associations;
   }.property()
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/88ddc922/ambari-web/app/views/main/mirroring_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/mirroring_view.js b/ambari-web/app/views/main/mirroring_view.js
index 76e5a9b..8c465f0 100644
--- a/ambari-web/app/views/main/mirroring_view.js
+++ b/ambari-web/app/views/main/mirroring_view.js
@@ -20,5 +20,10 @@ var App = require('app');
 
 App.MainMirroringView = Em.View.extend({
 
-  templateName: require('templates/main/mirroring')
+  templateName: require('templates/main/mirroring'),
+
+  didInsertElement: function () {
+    var controller = this.get('controller');
+    controller.loadDatasets();
+  }
 });