Skip to content

Instantly share code, notes, and snippets.

@asimpkin
Last active March 16, 2018 07:37
Show Gist options
  • Save asimpkin/8047575 to your computer and use it in GitHub Desktop.
Save asimpkin/8047575 to your computer and use it in GitHub Desktop.
Dynamic Rack Generation from ServiceNow CMDB Rack Sys_ID
<?php
include('../common.inc.php'); // Contains defintions for INSTANCE, USER, PASS
//////////////////////////////////
// GET THE RACK FROM sys_id in URL
$q='sys_id='.$_GET[sys_id];
$query=urlencode($q);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://'.INSTANCE.'.service-now.com/cmdb_ci_rack_list.do?XML&useUnloadFormat=true&sysparm_query='.$query);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, USER.':'.PASS); // locate in common.inc.php
$data = curl_exec($ch);
curl_close($ch);
$xmlIterator = new SimpleXMLIterator($data);
for( $xmlIterator->rewind(); $xmlIterator->valid(); $xmlIterator->next() ) {
foreach($xmlIterator->getChildren() as $name => $data) {
$RACK[(string)$name]=(string)$data;
} // end foreach
} // end for
//////////////////////////////
// GET ALL THE CIS IN THE RACK
$q='u_in_rack.sys_id='.$RACK[sys_id];
$query=urlencode($q);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://'.INSTANCE.'.service-now.com/cmdb_ci_hardware_list.do?XML&useUnloadFormat=true&sysparm_query='.$query);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, USER.':'.PASS);
$data = curl_exec($ch);
curl_close($ch);
$xmlIterator = new SimpleXMLIterator($data);
for( $xmlIterator->rewind(); $xmlIterator->valid(); $xmlIterator->next() ) { $K++;
foreach($xmlIterator->getChildren() as $name => $data) {
if ($name=="u_rack_position") $CIS[$K][$name]=(string)$data;
if ($name=="sys_id") $CIS[$K][$name]=(string)$data;
if ($name=="name") $CIS[$K][$name]=(string)$data;
if ($name=="u_rack_units") $CIS[$K][$name]=(string)$data;
} // end for each
} // end for
unset($K);
/////////////////////////////////////
// SORT THE CI ARRAY BY RACK POSITION
function aasort (&$array, $key) {
$sorter=array();
$ret=array();
reset($array);
foreach ($array as $ii => $va) {
$sorter[$ii]=$va[$key];
}
asort($sorter);
foreach ($sorter as $ii => $va) {
$ret[$ii]=$array[$ii];
}
$array=$ret;
}
aasort($CIS,"u_rack_position");
///////////////////////////////
// BUILD THE RACK DISPLAY ARRAY
# Populate with device label, and how many rack units of space it takes up
# Two special cases... 'rackname' gets applied to the top nameplate area
# 'blankXX' append random strings or numbers to avoid a name collision in php arrays
$rack['rackname']=$RACK[name];
for($i=$RACK[rack_units]; $i>=1; $i--){
foreach($CIS as $v) {
if($i==$v[u_rack_position]+$v[u_rack_units]-1) {
$F = array( 'name'=>$v[name], 'units'=>$v[u_rack_units] );
$i=$i-$v[u_rack_units]+1;
}
}// end foreach
if($F) {
$rack[$F[name]]=$F[units];
} else {
$rack['blank'.$i]=1;
} // end if
unset($F);
} // end for
//////////////////////////////////////////////////////////////////////////////////
// DRAW THE RACK
// http://www.jaredwatkins.com/2011/10/dynamic-rack-face-diagrams-with-php-and-gd/
// DOWNLOAD :: http://www.jaredwatkins.com/uploads/DynamicRackFaces1.zip
// All drawRack() code below this point courtesy of Jared Watkins
drawRack($rack, 'BlankRack'.$RACK[rack_units].'u.png');
function drawRack($r, $racktemplate) {
$template = imagecreatefrompng($racktemplate);
# Initial offset from the top left corner to begin placing 'servers'
$dstX = 27;
$dstY = 22;
foreach ($r as $name => $u) {
# This defines the nameplate at the top of the rack
if ($name == 'rackname') {
$nameplate = imagecreate(150,20);
$background = imagecolorallocate( $nameplate, 255, 255, 255 );
$text_colour = imagecolorallocate( $nameplate, 0, 0, 0 );
imageCenterString($nameplate, 5, $u, $text_colour);
imagecopy ($template, $nameplate, 52, 1, 0, 0, 150, 20);
continue;
} // end if
$deviceimg = imagecreate (200, (20*$u));
drawRackDevice(&$deviceimg,$name);
imagecopy($template, $deviceimg, $dstX, $dstY, 0, 0, 200, (20*$u));
$dstY += (20*$u);
imagedestroy($deviceimg);
} // end foreach
# You could also save it to a file on disk
header( "Content-type: image/png" );
imagepng( $template );
imagedestroy($template);
}
function drawRackDevice ($img, $text) {
// sys_class_name color picked from ServiceNow
// extended by AJ Simpkin 2013.12.19 hohoho!
if($sys_class_name=='cmdb_ci_linux_server') { // blue
$background = imagecolorallocate( $img, 100, 150, 200 );
} elseif($sys_class_name=='cmdb_ci_win_server') { // red
$background = imagecolorallocate( $img, 200, 100, 100 );
} else {
$background = imagecolorallocate( $img, 200, 200, 200 );
}
$text_colour = imagecolorallocate( $img, 0, 0, 0 );
$line_colour = imagecolorallocate( $img, 0, 0, 0 );
# If this should be a blank space.. make a transparent 'server' to fill the gap
if ((strlen($text) == 0) or strstr($text, 'blank')) {
imagecolortransparent ($img, $background);
} else {
imageCenterString($img, 5, $text, $text_colour);
imageline ($img, 0,0,200,0, $line_colour);
imageline ($img, 0,imagesy($img)-1,200,imagesy($img)-1, $line_colour);
} // end if
} // end function
function imageCenterString(&$img, $font, $text, $color) {
if($font < 0 || $font > 5){ $font = 0; }
$num = array(array(4.6, 6),
array(4.6, 6),
array(5.6, 12),
array(6.5, 12),
array(7.6, 16),
array(8.5, 16));
$width = ceil(strlen($text) * $num[$font][0]);
$x = imagesx($img) - $width - 8;
$y = Imagesy($img) - ($num[$font][1] + 2);
imagestring($img, $font, $x/2, $y/2, $text, $color);
} // end function
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment