diff --git a/html/about/federated.php b/html/about/federated.php
new file mode 100644
index 0000000000..36d9e3f7fe
--- /dev/null
+++ b/html/about/federated.php
@@ -0,0 +1,113 @@
+
+
Federated Open XDMoD
+
+ Federated XDMoD supports the collection and aggregation of data from a number of fully-functional and individually managed XDMoD instances into a single federated instance of XDMoD capable of displaying federation-wide metrics.
+ Each participating institution deploys an XDMoD instance through which local data will be collected and shipped to a central Federation Hub where it is aggregated to provide a federation-wide view of the data.
+ Data particular to an individual center is available from the Hub by applying filters and drill-downs.
+
+
+
+
+
+
+
+ Example data flow from heterogeneous computing resources to an XDMoD federated hub.
+ XDMoD instances X and Y ingest data into their databases from the computing resources that they monitor.
+ Following ingestion on the satellite instances, job data are replicated to the federated hub's database, where they are aggregated for use in the federated XDMoD user interface.
+
+
+
+
+
+
+ A simple example use of the federated module is:
+ Three academic instituitions each with their own HPC resource.
+ Each institution has its own XDMoD instance which contains the accounting data for only their HPC resource.
+ These institutions federate their data to a central hub.
+ HPC accounting data for all three HPC resources is shown on the central hub.
+ This central hub can then be used to report on the combined data.
+
+
+ This example illistrates only one use case.
+ The federated module supports cloud data as well as HPC. Support for other data realms is planned.
+ There are no pre defined limits on the number of instances that can be part of a federation.
+
+
+ For more information see Section II of Federating XDMoD to Monitor Affiliated Computing Resources.
+
+
+ Documentation avialable at https://federated.xdmod.org.
+
+
+ Source code and downloads at https://github.com/ubccr/xdmod-federated.
+
+$key.
+ *
+ * @param str $section the section in which the desired value resides.
+ * @param str $key the key under which the desired value can be found.
+ * @param mixed $default the default value to provide if there is nothing found.
+ *
+ * @return mixed
+ **/
+function getConfigValue($section, $key, $default = null)
+{
+ try {
+ $result = \xd_utilities\getConfiguration($section, $key);
+ } catch(\Exception $e) {
+ $result = $default;
+ }
+ return $result;
+}
+
+$role = getConfigValue('federated', 'role');
+if($role === 'instance'){
+ $hubUrl = getConfigValue('federated', 'huburl');
+ echo 'This instance is part of a federation
';
+ echo 'Federation Hub: ' . $hubUrl .'';
+}
+elseif ($role === 'hub'){
+ $db = DB::factory('datawarehouse');
+ $instanceResults = $db->query('SELECT * FROM federation_instances;');
+ $instances = array();
+ $lastCloudQuery = array();
+ $derived = 1;
+ foreach ($instanceResults as $instance) {
+ $prefix = $instance['prefix'];
+ $extra = json_decode($instance['extra'], true);
+ $instances[$prefix] = array(
+ 'contact' => $extra['contact'],
+ 'url' => $extra['url'],
+ 'lastCloudEvent' => null,
+ 'lastJobTask' => null
+ );
+ unset($extra['contact']);
+ unset($extra['url']);
+ $instances[$prefix]['extra'] = $extra;
+ array_push(
+ $lastCloudQuery,
+ '(SELECT \'' . $prefix . '\' AS prefix, FROM_UNIXTIME(event_time_ts) as event_ts FROM `' . $prefix . '-modw_cloud`.`event` ORDER BY 2 DESC LIMIT 1) `A' . $derived . '`'
+ );
+ $derived++;
+ }
+ $lastCloudResults = $db->query('SELECT * FROM ' . implode($lastCloudQuery, ' UNION ALL SELECT * FROM '));
+ foreach ($lastCloudResults as $result) {
+ $instances[$result['prefix']]['lastCloudEvent'] = $result['event_ts'];
+ }
+ echo 'Instances that are part of this Federation
';
+ foreach($instances as $instance){
+ echo '' . $instance['url'] . '
last event retrieved (' . $instance['lastCloudEvent'] . ') ';
+ }
+ echo '
';
+}
+else {
+ echo 'This installation is not part of a federation.';
+}
diff --git a/html/about/images/federated-diagram-1.gif b/html/about/images/federated-diagram-1.gif
new file mode 100644
index 0000000000..63421fdb38
Binary files /dev/null and b/html/about/images/federated-diagram-1.gif differ
diff --git a/html/gui/js/modules/About.js b/html/gui/js/modules/About.js
index abdaa2d7ab..454f02ba8a 100644
--- a/html/gui/js/modules/About.js
+++ b/html/gui/js/modules/About.js
@@ -2,14 +2,9 @@ XDMoD.Module.About = Ext.extend(XDMoD.PortalModule, {
title: 'About',
module_id: 'about_xdmod',
-
- // ------------------------------------------------------------------
-
initComponent: function () {
-
var basePath = '#main_tab_panel:' + this.module_id + '?';
var lastViewed = 'XDMoD';
-
var contentPanel = new Ext.Panel({
region: 'center',
preventBodyReset: true, // Don't override default css styles in this panel
@@ -17,7 +12,6 @@ XDMoD.Module.About = Ext.extend(XDMoD.PortalModule, {
bodyCssClass: "xdmod-aboutus"
});
-
var treeNodeClick = function(node) {
Ext.History.add(basePath + encodeURIComponent(node.text));
};
@@ -30,7 +24,7 @@ XDMoD.Module.About = Ext.extend(XDMoD.PortalModule, {
icon: '/gui/images/info.png',
leaf: true,
listeners: {
- 'click': treeNodeClick
+ click: treeNodeClick
} // listeners
},
{
@@ -38,7 +32,7 @@ XDMoD.Module.About = Ext.extend(XDMoD.PortalModule, {
icon: '/gui/images/info.png',
leaf: true,
listeners: {
- 'click': treeNodeClick
+ click: treeNodeClick
} // listeners
},
{
@@ -46,7 +40,15 @@ XDMoD.Module.About = Ext.extend(XDMoD.PortalModule, {
icon: '/gui/images/info.png',
leaf: true,
listeners: {
- 'click': treeNodeClick
+ click: treeNodeClick
+ } // listeners
+ },
+ {
+ text: 'Federated',
+ icon: '/gui/images/menu.png',
+ leaf: true,
+ listeners: {
+ click: treeNodeClick
} // listeners
},
{
@@ -54,7 +56,7 @@ XDMoD.Module.About = Ext.extend(XDMoD.PortalModule, {
icon: '/gui/images/lorry.png',
leaf: true,
listeners: {
- 'click': treeNodeClick
+ click: treeNodeClick
} // listeners
},
{
@@ -62,7 +64,7 @@ XDMoD.Module.About = Ext.extend(XDMoD.PortalModule, {
icon: '/gui/images/person.png',
leaf: true,
listeners: {
- 'click': treeNodeClick
+ click: treeNodeClick
} // listeners
},
{
@@ -70,7 +72,7 @@ XDMoD.Module.About = Ext.extend(XDMoD.PortalModule, {
icon: '/gui/images/user_manual_16.png',
leaf: true,
listeners: {
- 'click': treeNodeClick
+ click: treeNodeClick
} // listeners
},
{
@@ -78,7 +80,7 @@ XDMoD.Module.About = Ext.extend(XDMoD.PortalModule, {
icon: '/gui/images/user_manual_16.png',
leaf: true,
listeners: {
- 'click': treeNodeClick
+ click: treeNodeClick
} // listeners
},
{
@@ -86,7 +88,7 @@ XDMoD.Module.About = Ext.extend(XDMoD.PortalModule, {
icon: '/gui/images/arrow_right.png',
leaf: true,
listeners: {
- 'click': treeNodeClick
+ click: treeNodeClick
} // listeners
},
{
@@ -94,7 +96,7 @@ XDMoD.Module.About = Ext.extend(XDMoD.PortalModule, {
icon: '/gui/images/user_manual_16.png',
leaf: true,
listeners: {
- 'click': treeNodeClick
+ click: treeNodeClick
} // listeners
}
] // children
@@ -115,42 +117,36 @@ XDMoD.Module.About = Ext.extend(XDMoD.PortalModule, {
};
var mainArea = new Ext.Panel({
-
layout: 'border',
region: 'center',
items: [
westPanel,
contentPanel
]
-
});//mainArea
this.addListener('activate', function() {
-
var item = decodeURIComponent(CCR.tokenize(Ext.History.getToken()).params);
-
var items = {
- 'XDMoD': '/about/xdmod.php',
+ XDMoD: '/about/xdmod.php',
'Open XDMoD': '/about/openxd.html',
- 'SUPReMM': '/about/supremm.html',
- 'Roadmap': '/about/roadmap.php',
- 'Team': '/about/team.html',
- 'Publications': '/about/publications.html',
- 'Presentations': '/about/presentations.html',
- 'Links': '/about/links.html',
+ SUPReMM: '/about/supremm.html',
+ Federated: '/about/federated.php',
+ Roadmap: '/about/roadmap.php',
+ Team: '/about/team.html',
+ Publications: '/about/publications.html',
+ Presentations: '/about/presentations.html',
+ Links: '/about/links.html',
'Release Notes': '/about/release_notes/' + (CCR.xdmod.features.xsede ? 'xsede.html' : 'xdmod.html')
};
-
if (!item || !items[item]) {
item = lastViewed;
}
-
Ext.Ajax.request({
url: items[item],
- success: function(response) {
+ success: function (response) {
contentPanel.body.update(response.responseText);
lastViewed = item;
-
var treeNode = Ext.getCmp('treepanel').getRootNode().findChild('text', item);
if (treeNode) {
treeNode.select();
@@ -159,19 +155,11 @@ XDMoD.Module.About = Ext.extend(XDMoD.PortalModule, {
}
});
});
-
- // ==============================================
-
Ext.apply(this, {
-
items: [
mainArea
]
-
});//Ext.apply
-
XDMoD.Module.About.superclass.initComponent.apply(this, arguments);
-
} //initComponent
-
}); //XDMoD.Module.NewModule