View Issue Details

IDProjectCategoryView StatusLast Update
745RackTablesVMs/containerspublic2013-05-18 23:23
ReporterMWilkinson Assigned Toadoom42  
PrioritynormalSeveritytweakReproducibilityN/A
Status closedResolutionfixed 
Product Version0.20.3 
Target Version0.20.5Fixed in Version0.20.5 
Summary745: Display Blade servers in Chassis
DescriptionThis patch alters the way the RackTables rendering of racks is performed to show blades mounted in chassis within the rack.

Steps To ReproduceApply the included Patch.

Note : There are 2 versions of this patch, 1 against the Base install of RackTables-0.20.3, the other against RackTables-0.20.3 with my other portlets patch already applied (see http://bugs.racktables.org/view.php?id=691)
Additional InformationCurrently it is hard coded for Servers and Server Chassis's only.
2 New attributes need defining for the Chasses, 'Num Rows' and 'Num Cols'
which define how many rows and cols of blades a chassis can hold - this may be better implemented in a dictionary of standard Chassis Configurations (ie, 1 x 10, 2 x 8, etc)
TagsNo tags attached.

Activities

MWilkinson

MWilkinson

2013-02-13 11:29

reporter  

MWilkinson

MWilkinson

2013-02-13 11:29

reporter  

MWilkinson

MWilkinson

2013-02-13 14:10

reporter   ~0001129

It should be noted that for the Server to appear in the Chassis, the slot number on the server should be set to a value between 1 and (Num Rows * Num Cols)
andriyanov

andriyanov

2013-02-22 12:17

reporter   ~0001153

Aaron, could you please review this patch?
I don't have containers in my environment and so it's hard to decide if it's useful.
mejo

mejo

2013-05-10 10:27

reporter   ~0001389

I really like this patch. May I suggest that it is incorporated into racktables?

Additionally I'd like to propose a small modification: Please accept your own changes from mailinglist post on Feb. 13th 2013: http://www.freelists.org/post/racktables-users/Antwort-Re-Antwort-Patch-to-display-Blades-in-Chassis-in-Rack,1

With all patches applied, rows and columns work like a charm for us.

Thanks for the great work!
MWilkinson

MWilkinson

2013-05-16 14:05

reporter   ~0001419

New versions of the patch - again against stock RackTables 0.20.4 and one with my other patch for the portlets.

Things to note - the 2 extra attributes are no longer needed - it seem daft to have to enter this information in to every chassis when it should only need to be entered once. To this end, this patch adds a '%L' marker which is similar to the '%G' markers already used in the Hardware description. The %L marker is constructed as follows :- '%L<rows>,<cols>[<layout>]%' where <rows> is the number of rows in the chassis, <cols> is the number of columns in the chassis and <layout> is an optional Layout hint, either H for horizonal, or V for vertical. If the layout hint is not supplied, chassis with less than 6 slots will be laid out with horizontal slot names, otherwise vertical slot names will be used.
MWilkinson

MWilkinson

2013-05-16 14:14

reporter  

chassis-0.20.4-base.patch (7,354 bytes)   
diff -urN RackTables-0.20.4-orig/wwwroot/inc/dictionary.php base/wwwroot/inc/dictionary.php
--- RackTables-0.20.4-orig/wwwroot/inc/dictionary.php	2013-04-14 21:27:19.000000000 +0100
+++ base/wwwroot/inc/dictionary.php	2013-05-16 12:49:23.681661125 +0100
@@ -1081,7 +1081,7 @@
 	991 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge%GPASS%R710'),
 	992 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge%GPASS%R805'),
 	993 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge%GPASS%R905'),
-	994 => array ('chapter_id' => 31, 'dict_value' => 'Dell PowerEdge%GPASS%M1000e'),
+	994 => array ('chapter_id' => 31, 'dict_value' => 'Dell PowerEdge%GPASS%M1000e%L2,8V%'),
 	995 => array ('chapter_id' => 18, 'dict_value' => 'Dell PowerVault%GPASS%MD1000'),
 	996 => array ('chapter_id' => 18, 'dict_value' => 'Dell PowerVault%GPASS%MD1120'),
 	997 => array ('chapter_id' => 18, 'dict_value' => 'Dell EqualLogic PS5000'),
@@ -1601,7 +1601,7 @@
 	1514 => array ('chapter_id' => 13, 'dict_value' => 'Xen Hypervisor%GSKIP%XenServer 4.0'),
 	1515 => array ('chapter_id' => 13, 'dict_value' => 'Xen Hypervisor%GSKIP%XenServer 5.0'),
 	1516 => array ('chapter_id' => 13, 'dict_value' => 'Xen Hypervisor%GSKIP%XenServer 5.5'),
-	1517 => array ('chapter_id' => 31, 'dict_value' => 'Dell PowerEdge%GPASS%1855'),
+	1517 => array ('chapter_id' => 31, 'dict_value' => 'Dell PowerEdge%GPASS%1855%L1,10V%'),
 	1518 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge (blade)%GPASS%1955'),
 	1519 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge (blade)%GPASS%M605'),
 	1520 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge (blade)%GPASS%M610'),
diff -urN RackTables-0.20.4-orig/wwwroot/inc/functions.php base/wwwroot/inc/functions.php
--- RackTables-0.20.4-orig/wwwroot/inc/functions.php	2013-04-14 21:27:19.000000000 +0100
+++ base/wwwroot/inc/functions.php	2013-05-16 12:49:23.681661125 +0100
@@ -1055,7 +1055,27 @@
 // FIXME: should this be saved as "P-data"?
 function execGMarker ($line)
 {
-	return preg_replace ('/^.+%GSKIP%/', '', preg_replace ('/^(.+)%GPASS%/', '\\1 ', $line));
+	return preg_replace ('/^.+%GSKIP%/', '',
+		 preg_replace ('/^(.+)%GPASS%/', '\\1 ',
+			preg_replace ('/%L\d+,\d+(H|V|)%/', '', $line)));
+}
+
+// extract the layout information from the %L...% marker in the dictionary info
+// This is somewhat similar to the %GPASS %GSKIP
+//
+function extractLayout (&$record)
+{
+	if ( preg_match ('/%L(\d+),(\d+)(H|V|)%/', $record['value'], $matches) )
+	{
+		$record['rows'] = $matches[1];
+		$record['cols'] = $matches[2];
+		$record['layout'] = $matches[3];
+		if (! strlen($record['layout']) )
+			if ( $record['cols'] >= 4 )
+				$record['layout'] = 'V';
+			else
+				$record['layout'] = 'H';
+	}
 }
 
 // rackspace usage for a single rack
@@ -3327,7 +3347,7 @@
 	$ifname = preg_replace ('@^BE(\d+)$@', 'bundle-ether\\1', $ifname); // IOS XR4
 	$ifname = strtolower ($ifname);
 	$ifname = preg_replace ('/^(e|fa|gi|te|po|xg|lo|ma)\s+(\d.*)/', '$1$2', $ifname);
-	return $ifname;
+	return ucfirst($ifname);
 }
 
 # Produce a list of integers from a string in the following format:
diff -urN RackTables-0.20.4-orig/wwwroot/inc/interface.php base/wwwroot/inc/interface.php
--- RackTables-0.20.4-orig/wwwroot/inc/interface.php	2013-04-14 21:27:19.000000000 +0100
+++ base/wwwroot/inc/interface.php	2013-05-16 12:54:16.711661568 +0100
@@ -594,7 +594,7 @@
 }
 
 // Used by renderRack()
-function printObjectDetailsForRenderRack ($object_id)
+function printObjectDetailsForRenderRack ($object_id, $hl_obj_id = 0)
 {
 	$objectData = spotEntity ('object', $object_id);
 	if (strlen ($objectData['asset_no']))
@@ -607,16 +607,80 @@
 		$body = ", visible label is \"${objectData['label']}\"";
 	// Display list of child objects, if any
 	$objectChildren = getEntityRelatives ('children', 'object', $objectData['id']);
+	$slotInfo = Array();
+	$slotData = Array();
+	$slotTitle = Array();
 	if (count($objectChildren) > 0)
 	{
 		foreach ($objectChildren as $child)
+		{
 			$childNames[] = $child['name'];
+			$childData = spotEntity ('object', $child['entity_id']);
+			$attrData = getAttrValues ($child['entity_id']);
+			if ( $attrData['28'] )
+			{
+				$slot = $attrData['28']['value'];
+				$slotInfo[$slot] = $child['name'];
+				$slotData[$slot] = $child['entity_id'];
+				if ( strlen ($childData['asset_no']) )
+					$slotTitle[$slot] = "<div title='${childData['asset_no']}";
+				else
+					$slotTitle[$slot] = "<div title='no asset tag";
+				if ( $child['name'] != $child['label'] and strlen ($child['label']) )
+					$slotTitle[$slot] .= ", visible label is \"${child['label']}\"";
+				$slotTitle[$slot] .= "'>";
+			}
+		}
 		natsort($childNames);
 		$suffix = sprintf(", contains %s'>", implode(', ', $childNames));
 	}
 	else
 		$suffix = "'>";
 	echo "${prefix}${body}${suffix}" . mkA ($objectData['dname'], 'object', $objectData['id']) . '</div>';
+	if ( in_array ($objectData['objtype_id'], array(1502,1503) ) )
+	{
+		$objAttr = getAttrValues ($objectData['id']);
+		if ( isset ($objAttr[2]) )
+		{
+			extractLayout($objAttr[2]);
+			if ( isset ($objAttr[2]['rows'] ) )
+			{
+				echo "<table width='100%' border='1'>";
+				for ($r=0; $r<$objAttr[2]['rows']; $r++)
+				{
+					echo "<tr>";
+					for ( $c=0; $c<$objAttr[2]['cols']; $c++)
+					{
+						$s = ($r * $objAttr[2]['cols']) + $c + 1;
+						if ( $slotData[$s] )
+						{
+							echo "<td class='state_T";
+							if ( $slotData[$s] == $hl_obj_id )
+								echo "h";
+							echo "'>";
+							echo $slotTitle[$s];
+							if ( $objAttr[2]['layout'] == "V" )
+							{
+								$tmp = substr ($slotInfo[$s], 0, 1);
+								foreach ( str_split (substr ($slotInfo[$s],1) ) as $letter )
+									$tmp .= "<br>" . $letter;
+								$slotInfo[$s] = $tmp;
+							}
+							echo mkA ($slotInfo[$s], 'object', $slotData[$s]);
+							echo "</div></td>";
+						}
+						else
+							echo "<td class='state_F'><div title=\"Free slot\">&nbsp;</div></td>";
+					}
+					echo "</tr>";
+				}
+				echo "</table>";
+			}
+			$fh = fopen("/tmp/rackData.lis","w");
+			fwrite($fh, print_r($objAttr, true));
+			fclose($fh);
+		}
+	}
 }
 
 // This function renders rack as HTML table.
@@ -661,7 +725,7 @@
 			switch ($state)
 			{
 				case 'T':
-					printObjectDetailsForRenderRack($rackData[$i][$locidx]['object_id']);
+					printObjectDetailsForRenderRack($rackData[$i][$locidx]['object_id'], $hl_obj_id);
 					break;
 				case 'A':
 					echo '<div title="This rackspace does not exist">&nbsp;</div>';
@@ -1310,8 +1374,22 @@
 	{
 		// rackspace portlet
 		startPortlet ('rackspace allocation');
-		foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
-			renderRack ($rack_id, $object_id);
+		if ( in_array( $info['objtype_id'], array(4,8) ) ) {
+			$parents = getEntityRelatives ('parents', 'object', $info['id']);
+			if (count ($parents))
+			{
+				foreach ($parents as $parent)
+					foreach (getResidentRacksData($parent['entity_id'], FALSE) as $rack_id)
+						renderRack( $rack_id, $object_id );
+			} 
+			else
+				foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
+					renderRack ($rack_id, $object_id);
+		}
+		else
+			foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
+				renderRack ($rack_id, $object_id);
+
 		echo '<br>';
 		finishPortlet();
 	}
chassis-0.20.4-base.patch (7,354 bytes)   
MWilkinson

MWilkinson

2013-05-16 14:14

reporter  

chassis-0.20.4-enhanced.patch (7,759 bytes)   
diff -urN base/wwwroot/inc/dictionary.php RackTables-0.20.4-dev/wwwroot/inc/dictionary.php
--- base/wwwroot/inc/dictionary.php	2013-05-16 12:37:41.095622580 +0100
+++ RackTables-0.20.4-dev/wwwroot/inc/dictionary.php	2013-05-16 10:30:19.304190879 +0100
@@ -1081,7 +1081,7 @@
 	991 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge%GPASS%R710'),
 	992 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge%GPASS%R805'),
 	993 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge%GPASS%R905'),
-	994 => array ('chapter_id' => 31, 'dict_value' => 'Dell PowerEdge%GPASS%M1000e'),
+	994 => array ('chapter_id' => 31, 'dict_value' => 'Dell PowerEdge%GPASS%M1000e%L2,8V%'),
 	995 => array ('chapter_id' => 18, 'dict_value' => 'Dell PowerVault%GPASS%MD1000'),
 	996 => array ('chapter_id' => 18, 'dict_value' => 'Dell PowerVault%GPASS%MD1120'),
 	997 => array ('chapter_id' => 18, 'dict_value' => 'Dell EqualLogic PS5000'),
@@ -1601,7 +1601,7 @@
 	1514 => array ('chapter_id' => 13, 'dict_value' => 'Xen Hypervisor%GSKIP%XenServer 4.0'),
 	1515 => array ('chapter_id' => 13, 'dict_value' => 'Xen Hypervisor%GSKIP%XenServer 5.0'),
 	1516 => array ('chapter_id' => 13, 'dict_value' => 'Xen Hypervisor%GSKIP%XenServer 5.5'),
-	1517 => array ('chapter_id' => 31, 'dict_value' => 'Dell PowerEdge%GPASS%1855'),
+	1517 => array ('chapter_id' => 31, 'dict_value' => 'Dell PowerEdge%GPASS%1855%L1,10V%'),
 	1518 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge (blade)%GPASS%1955'),
 	1519 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge (blade)%GPASS%M605'),
 	1520 => array ('chapter_id' => 11, 'dict_value' => 'Dell PowerEdge (blade)%GPASS%M610'),
diff -urN base/wwwroot/inc/functions.php RackTables-0.20.4-dev/wwwroot/inc/functions.php
--- base/wwwroot/inc/functions.php	2013-05-16 12:37:51.378492571 +0100
+++ RackTables-0.20.4-dev/wwwroot/inc/functions.php	2013-05-16 11:22:10.801660737 +0100
@@ -1055,7 +1055,27 @@
 // FIXME: should this be saved as "P-data"?
 function execGMarker ($line)
 {
-	return preg_replace ('/^.+%GSKIP%/', '', preg_replace ('/^(.+)%GPASS%/', '\\1 ', $line));
+	return preg_replace ('/^.+%GSKIP%/', '',
+		 preg_replace ('/^(.+)%GPASS%/', '\\1 ',
+			preg_replace ('/%L\d+,\d+(H|V|)%/', '', $line)));
+}
+
+// extract the layout information from the %L...% marker in the dictionary info
+// This is somewhat similar to the %GPASS %GSKIP
+//
+function extractLayout (&$record)
+{
+	if ( preg_match ('/%L(\d+),(\d+)(H|V|)%/', $record['value'], $matches) )
+	{
+		$record['rows'] = $matches[1];
+		$record['cols'] = $matches[2];
+		$record['layout'] = $matches[3];
+		if (! strlen($record['layout']) )
+			if ( $record['cols'] >= 4 )
+				$record['layout'] = 'V';
+			else
+				$record['layout'] = 'H';
+	}
 }
 
 // rackspace usage for a single rack
@@ -3327,7 +3347,7 @@
 	$ifname = preg_replace ('@^BE(\d+)$@', 'bundle-ether\\1', $ifname); // IOS XR4
 	$ifname = strtolower ($ifname);
 	$ifname = preg_replace ('/^(e|fa|gi|te|po|xg|lo|ma)\s+(\d.*)/', '$1$2', $ifname);
-	return $ifname;
+	return ucfirst($ifname);
 }
 
 # Produce a list of integers from a string in the following format:
diff -urN base/wwwroot/inc/interface.php RackTables-0.20.4-dev/wwwroot/inc/interface.php
--- base/wwwroot/inc/interface.php	2013-05-16 12:37:51.401570636 +0100
+++ RackTables-0.20.4-dev/wwwroot/inc/interface.php	2013-05-16 12:32:23.081661201 +0100
@@ -595,7 +595,7 @@
 }
 
 // Used by renderRack()
-function printObjectDetailsForRenderRack ($object_id)
+function printObjectDetailsForRenderRack ($object_id, $hl_obj_id = 0)
 {
 	$objectData = spotEntity ('object', $object_id);
 	if (strlen ($objectData['asset_no']))
@@ -608,16 +608,80 @@
 		$body = ", visible label is \"${objectData['label']}\"";
 	// Display list of child objects, if any
 	$objectChildren = getEntityRelatives ('children', 'object', $objectData['id']);
+	$slotInfo = Array();
+	$slotData = Array();
+	$slotTitle = Array();
 	if (count($objectChildren) > 0)
 	{
 		foreach ($objectChildren as $child)
+		{
 			$childNames[] = $child['name'];
+			$childData = spotEntity ('object', $child['entity_id']);
+			$attrData = getAttrValues ($child['entity_id']);
+			if ( $attrData['28'] )
+			{
+				$slot = $attrData['28']['value'];
+				$slotInfo[$slot] = $child['name'];
+				$slotData[$slot] = $child['entity_id'];
+				if ( strlen ($childData['asset_no']) )
+					$slotTitle[$slot] = "<div title='${childData['asset_no']}";
+				else
+					$slotTitle[$slot] = "<div title='no asset tag";
+				if ( $child['name'] != $child['label'] and strlen ($child['label']) )
+					$slotTitle[$slot] .= ", visible label is \"${child['label']}\"";
+				$slotTitle[$slot] .= "'>";
+			}
+		}
 		natsort($childNames);
 		$suffix = sprintf(", contains %s'>", implode(', ', $childNames));
 	}
 	else
 		$suffix = "'>";
 	echo "${prefix}${body}${suffix}" . mkA ($objectData['dname'], 'object', $objectData['id']) . '</div>';
+	if ( in_array ($objectData['objtype_id'], array(1502,1503) ) )
+	{
+		$objAttr = getAttrValues ($objectData['id']);
+		if ( isset ($objAttr[2]) )
+		{
+			extractLayout($objAttr[2]);
+			if ( isset ($objAttr[2]['rows'] ) )
+			{
+				echo "<table width='100%' border='1'>";
+				for ($r=0; $r<$objAttr[2]['rows']; $r++)
+				{
+					echo "<tr>";
+					for ( $c=0; $c<$objAttr[2]['cols']; $c++)
+					{
+						$s = ($r * $objAttr[2]['cols']) + $c + 1;
+						if ( $slotData[$s] )
+						{
+							echo "<td class='state_T";
+							if ( $slotData[$s] == $hl_obj_id )
+								echo "h";
+							echo "'>";
+							echo $slotTitle[$s];
+							if ( $objAttr[2]['layout'] == "V" )
+							{
+								$tmp = substr ($slotInfo[$s], 0, 1);
+								foreach ( str_split (substr ($slotInfo[$s],1) ) as $letter )
+									$tmp .= "<br>" . $letter;
+								$slotInfo[$s] = $tmp;
+							}
+							echo mkA ($slotInfo[$s], 'object', $slotData[$s]);
+							echo "</div></td>";
+						}
+						else
+							echo "<td class='state_F'><div title=\"Free slot\">&nbsp;</div></td>";
+					}
+					echo "</tr>";
+				}
+				echo "</table>";
+			}
+			$fh = fopen("/tmp/rackData.lis","w");
+			fwrite($fh, print_r($objAttr, true));
+			fclose($fh);
+		}
+	}
 }
 
 // This function renders rack as HTML table.
@@ -662,7 +726,7 @@
 			switch ($state)
 			{
 				case 'T':
-					printObjectDetailsForRenderRack($rackData[$i][$locidx]['object_id']);
+					printObjectDetailsForRenderRack($rackData[$i][$locidx]['object_id'], $hl_obj_id);
 					break;
 				case 'A':
 					echo '<div title="This rackspace does not exist">&nbsp;</div>';
diff -urN base/wwwroot/inc/portlets.php RackTables-0.20.4-dev/wwwroot/inc/portlets.php
--- base/wwwroot/inc/portlets.php	2013-05-16 12:37:51.407668381 +0100
+++ RackTables-0.20.4-dev/wwwroot/inc/portlets.php	2013-05-16 12:02:27.441666890 +0100
@@ -253,14 +264,30 @@
 
 function renderObPortletRackspace( $info )
 {
+	global $virtual_obj_types;
+
 	$object_id = $info['id'];
 
 	if (!in_array($info['objtype_id'], $virtual_obj_types))
 	{
 		// rackspace portlet
 		startPortlet ('rackspace allocation');
-		foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
-			renderRack ($rack_id, $object_id);
+		if ( in_array( $info['objtype_id'], array(4,8) ) ) {
+			$parents = getEntityRelatives ('parents', 'object', $info['id']);
+			if (count ($parents))
+			{
+				foreach ($parents as $parent)
+					foreach (getResidentRacksData($parent['entity_id'], FALSE) as $rack_id)
+						renderRack( $rack_id, $object_id );
+			} 
+			else
+				foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
+					renderRack ($rack_id, $object_id);
+		}
+		else
+			foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
+				renderRack ($rack_id, $object_id);
+
 		echo '<br>';
 		finishPortlet();
 	}
chassis-0.20.4-enhanced.patch (7,759 bytes)   
adoom42

adoom42

2013-05-18 23:23

administrator   ~0001421

This approach doesn't support all use cases. For example, Dell's M1000e chassis accepts both full-height and half-height blades.

But it is definitely an improvement, so it will appear in 0.20.5.

Thanks.

Issue History

Date Modified Username Field Change
2013-02-13 10:41 MWilkinson New Issue
2013-02-13 10:41 MWilkinson File Added: racktables-0-20-3.patch-base
2013-02-13 10:41 MWilkinson File Added: racktables-0-20-3.patch-enhanced
2013-02-13 11:29 MWilkinson File Deleted: racktables-0-20-3.patch-enhanced
2013-02-13 11:29 MWilkinson File Deleted: racktables-0-20-3.patch-base
2013-02-13 11:29 MWilkinson File Added: racktables-0-20-3.patch-base
2013-02-13 11:29 MWilkinson File Added: racktables-0-20-3.patch-enhanced
2013-02-13 14:10 MWilkinson Note Added: 0001129
2013-02-22 12:17 andriyanov Note Added: 0001153
2013-02-22 12:17 andriyanov Assigned To => adoom42
2013-02-22 12:17 andriyanov Status new => assigned
2013-05-10 10:27 mejo Note Added: 0001389
2013-05-13 01:09 adoom42 Category default => VMs/containers
2013-05-16 14:00 MWilkinson File Added: chassis-0.20.4-base.patch
2013-05-16 14:00 MWilkinson File Added: chassis-0.20.4-enhanced.patch
2013-05-16 14:05 MWilkinson Note Added: 0001419
2013-05-16 14:14 MWilkinson File Deleted: chassis-0.20.4-enhanced.patch
2013-05-16 14:14 MWilkinson File Deleted: chassis-0.20.4-base.patch
2013-05-16 14:14 MWilkinson File Added: chassis-0.20.4-base.patch
2013-05-16 14:14 MWilkinson File Added: chassis-0.20.4-enhanced.patch
2013-05-18 23:23 adoom42 Note Added: 0001421
2013-05-18 23:23 adoom42 Status assigned => closed
2013-05-18 23:23 adoom42 Resolution open => fixed
2013-05-18 23:23 adoom42 Fixed in Version => 0.20.5
2013-05-18 23:23 adoom42 Target Version => 0.20.5