MediaWiki extensions manual
OOjs UI icon advanced.svg
Release status: experimental
Implementation Special page
Description DataCenter Planning and Asset Tracking System
Author(s) Trevor Parscal
Latest version 0.1.0
License GNU General Public License 2.0
Download Template:WikimediaDownload/svn
Translate the DataCenter extension if it is available at translatewiki.net
Check usage and version matrix.

DataCenter is an extension for data center planning and asset tracking... basically, for keeping track of all our servers. Hey, you try keeping a few hundred boxes straight in your head!

This is primarily intended for Wikimedia's internal use, but of course others may find it useful as well.


The system consists of several kinds of data as well as relationship information that ties it all together.

Facility information includes locations which are named geographical places which contain any number of spaces which are essentially rooms. Spaces contain specific information about their size and power availability, and also may have any number of plans.
The placement of assets in a space can be designed using a plan. Each plan can contain any number of rack assets as well as object assets which are placed inside the racks. In the future this section will include the ability to create connections between objects as well.
Actual physical pieces of equipment are considered assets. All assets have asset tags, serial numbers and a current physical location at which they are located as well as a reference to a model.
Specific information about assets is stored as models, which can be re-used. Object models can contain other objects as well as ports.


  1. Download the extension files from the MediaWiki SVN repository
  2. Run on the command line
    php extensions/DataCenter/CLI/Initialize.php --confirm=yes
  3. If you want to start with an initial dataset for testing purposes, Run on the command line
    php extensions/DataCenter/CLI/Import.php --dummy
  4. Add into your wiki's LocalSettings.php
  5. Set $egDataCenterGoogleMapsAPIKey into your wiki's LocalSettings.php with a Google API key as the value. If you don't have one yet, you can get one from the Google API key signup page.
  6. Installation can now be verified through Special:Version


Browser Version Windows Linux MacOS iPhone
Firefox 3.x OK OK OK N/A
Safari 3.x OK N/A OK OK
Opera 9.x OK OK OK N/A
Internet Explorer 7.x PARTIAL N/A N/A N/A

Internet Explorer supportEdit

Currently DataCenter is compatible with Internet Explorer 7 (and maybe 6?). However in future versions, support will depend on either eventual native support for the canvas HTML element or continued support through exCanvas. Additionally, even in supported versions of Internet Explorer radial gradients are not supported which greatly reduces the rendering quality of scenes and plans. It is unclear when or if this feature will be supported in exCanvas.

Access ControlEdit

To use DataCenter you must be logged in as a user which is a part of one of the following groups depending on what permissions you will need.

Group Name View Export Change Remove
dc-viewer DataCenter Viewers YES YES NO NO
dc-admin DataCenter Administrators YES YES YES YES

To-do listEdit

Planned changesEdit

  • Migrate DataCenterXml, DataCenterCss and DataCenterJs classes to the core Html class, move the CSS into style-sheets and port scripts to jQuery which can get data from an API rather than have it be built by PHP into the page.

Planned featuresEdit

  • Rollback functionality for changes
  • Tags (make list of string values for row/meta fields which already exist available using auto-complete or perhaps a list when typing into a text box)
  • Connections in plans
  • Attachments - ability to upload and link documents (like invoices) to assets
  • Add a table like representation of a rack like in racktables (for individual racks or rows of racks)
  • Streamline planning procedures - perhaps make future plans diffs of present ones
  • Add more explicit concept of rows, along with row viewing in X or Y axes (front/back/side of all racks in a row)

Proposed FeaturesEdit

  • Show units for fields such as meters or watts
    • Space/Power: W/m^2
  • 0 depth rack units render special to denote blank panels
  • Add support for importing data from RackTables to Import script
  • Asset reports (history / status / valuation )
  • Printable 'blueprint' generation from plan
  • More than just racks - tables, desks, shelves etc.


The following information is aimed at familiarizing potential contributors with some of the concepts in DataCenter that are particular to and commonly seen in the DataCenter code.


Everything after "/wiki/Special:DataCenter/" in the URL is taken as a sub-path and interpreted as follows:


Where [ ] indicates optional components and ... indicates variadic arguments. This syntax is decoded to and encoded from an associative array often referred to in code as a path or sometimes as a set of link parameters.

// Echos full URL with sub-path of 'plans:rack:1/view'
echo DataCenterXml::url(
	array( 'page' => 'plans', 'type' => 'rack', 'id' => 1, 'action' => 'view' )

It's the goal to use this format for all pages, and in certain cases it's required to have some sort of redirect to achieve this. Overall the syntax keeps paths short and somewhat user-readable. When processing the path, it is assumed that all fields in the path are present and the lack of a value of the field is stored as a null. This helps prevent having to first check if it exists and then checking the value.

Database abstractionEdit

Data access is fully abstracted through DataCenterDB which returns most results in the form of DataCenterDBRow and subclasses thereof. Tables are acessed using a category and type, which usually corresponds loosely to the page and type concepts in paths.


When a page is navigated to, the path determines the controller to be used. If no appropriate controller can be found then a default is used. The controller is constructed before the view or any other user interface elements are rendered, giving the controller an opportunity to add actions or trail steps to the UI based on the interpretation of the path. Controllers also have a public member called types which is an array of key/value pairs where the key is the string of the name of a page-type and the value is an array of link parameters. The following example is found in the assets controller.

public $types = array(
	'rack' => array( 'page' => 'assets', 'type' => 'rack' ),
	'object' => array( 'page' => 'assets', 'type' => 'object' ),

For each data processing feature of a page there is a corresponding public function which handles it. These functions are called handlers, and are the only public functions that a controller should have other than the __construct function. When a form is sent using the post method the special page catches it and tries to call a function on the controller named whatever the value of the do|parameter is. The handler receives the contents of the row, meta and change array, each corresponding the field names in the form such as row[id] or change[note]. Although the current and previous paths can be accessed at any time using static functions of the special page class the type is of particular importance in the processing of a handler since there is only one handler for all types of a page by any given name - thus it is also provided to the handler by the special page.


When a controller is done constructing a set of destinations (actions and types or trail steps) the view is selected. The most specific view (one which is a part of a type-specific page view class) is used if available, however a more generic view (one that is a part of the general page view class) is used as a fallback. The general naming convention here is to append the type name to the general page view class name - such as DataCenterViewFacilities being the general page view class for facilities and DataCenterViewFacilitiesLocation being the type-specific page view class for facilities of the location type. The system does not rely on this naming convention however - but rather on a registry of page and type names and their corresponding classes which can be found in the special page class.

It is the job of a view to provide functions which generate and return XML content which is used as the body of the page, providing a user-interface to the handlers of the controller. A view class contains any number of public functions which correspond to the action parameter in the path. If no action is specified the default action main is used. Although the action function could build all of the XML output itself, it's much more common and preferred to leave the code generation to layouts, widgets and inputs; making action functions more of a central area of collecting information and defining a structure of layouts, widgets and inputs which render based on that information.


User interface elements are modular. The DataCenterUI class has three rendering functions which provide central, safe and convenient access to the rendering of various user interface elements.


// Renders a 2 column layout
echo DataCenterUI::renderLayout(
	'columns', array( 'contents of column 1', 'contents of column 2 )


// Renders a map with markers for each location in the system
echo DataCenterUI::renderWidget(
	'map', array( 'locations' => DataCenterDB::getLocations() )


// Renders a set of radio buttons which return a 1 or a 0 when submitted
echo DataCenterUI::renderInput(
	'boolean', array( 'value' => true )

Code generationEdit

XML, JavaScript and CSS are all generated by static functions in DataCenterXml, DataCenterJs and DataCenterCss respectively. The key advantage of using these classes can be seen in their use, where XML attributes are defined as arrays which can be the results of merges from a set of builder functions, or in the case of JavaScript the automatic conversion of multi-level associative arrays into JSON format. The following is another example of the general rationale for this style of code generation.

Inline XMLEdit

// Define some stuff
$time = time();
$name = ucwords( $name );
// Print some stuff
echo "<div class=\"time\">{$time}</div>";
echo "<div>{$name}</div>";

Generated XMLEdit

// Print some stuff
echo DataCenterXml::div( array( 'class' => 'time' ), time() );
echo DataCenterXml::div( ucwords( $name ) );

The advantages displayed in the examples of are:

  • Fewer variables to declare
  • Fewer lines of code
  • All code is in PHP, rather than mixed