#!/usr/bin/perl

################################################################################
#
# This UCS-Review script works as follows. You install it on a laptop that can 
# connect to the management network of the FI's. Type the "perl ./ucs-review.pl" 
# command and it will ask for the five parameters it needs. Or provide one 
# (bogus) parameter and it will show the correct syntax for providing the 
# parameters on the command line. The script will then use the UCS Manager API 
# and collect as much as possible information about the UCS configuration. The 
# script will convert this into a regular UCS Layout XML request and write it 
# to the file you specified.
#
# Now disconnect your laptop from the Management network, connect it to your 
# regular network and point your browser to "http://www.ucs4.us/ucs/viewer/".
# On the second page you cut-and-paste the XML from the script. Plus you can
# change options like front or rear, image size, etc. Don't import the XML into
# the regular UCS Layout tool, that will fail. 
#
# The Viewer tool has to make assumptions about the position of devices in the 
# racks, it obviously has no knowledge about that. If you need a Rack Layout 
# image that matches exactly what's in your racks (in other words an elevation
# map), there is a way to do that. 
#
# Open the XML file in a text editor and switch in the header "AUTO" to 
# "MANUAL". Remove the FI config, but leave the <chassis\> configs in place, 
# you will need them later. See how it knows the exact positions of your blades. 
# Add <rack cfg="N"></rack> entries, add again the FI's, but now as <device\> 
# entries and change the server related entries from <server\> to <device\>. 
# Use <space\> entries to position your devices in the racks. If this is all 
# new to you, create a manual config in the regular layout tool and Export to
# to see how it looks like.
#
# Your XML should be including something like this:
# 
#	<chassis model="UCS5108" cfg="1" qty="1" col="BLACK">
#		<blade model="B485" qty="3" />
#		<iomod model="IOM2408" qty="2" />
#		<power qty="4" />
#	</chassis>
#	<chassis model="UCS5108" cfg="2" qty="1" col="BLACK">
#		<blade model="B205" pos="1" />
#		<blade model="B205" pos="3" />
#		<blade model="B205" pos="5" />
#		<blade model="B205" pos="7" />
#		<iomod model="IOM2408" qty="2" />
#		<power qty="4" />
#	</chassis>
#	<rack cfg="1" qty="1">
#		<device model="SPACE1" qty="4" />
#		<device model="FI6454" qty="2" />
#		<device model="UCS-CH1" qty="2" />
#		<device model="UCS-CH2" qty="2" />
#		<device model="SPACE1" qty="1" />
#		<device model="C245S" qty="8" />
#		<device model="SPACE1" qty="1" />
#	</rack>
#	<rack cfg="2" qty="1">
#		<device model="SPACE1" qty="6" />
#		<device model="AFF320" qty="2" />
#		<device model="SPACE1" qty="1" />
#		<device model="DS224C" qty="8" />
#		<device model="SPACE1" qty="1" />
#	</rack>
# 
# As you see you can also add devices that are not controlled by UCS Manager, 
# like network switches, storage arrays, etc. Save the file. Now use one of the 
# bash, perl, python, etc. tools on the UCS Layout API page and send your XML to
# the back-engine of the Layout tool. It will return with the URL of your image.
#
# Running this Perl script in your environment can be very straight forward or 
# can take some more effort to get it to work. It all depends on whether the 
# right Perl packages are installed on your system. Below the Perl modules to 
# be included and in the comments what (for RedHat/Fedora) the corresponding 
# RPM packages are. For other distro's like Ubuntu things will be similar but 
# different.
#
# The biggest hurdle is around SSL encryption. It depends on whether in UCS 
# Manager the auto redirect from http (port 80) to https (port 443) is enabled 
# or not. When disabled, you should simply specify port 80 and all will work 
# fine. However, if the redirect is enabled, you will need to get the use of 
# port 443 to be working. And that depends on whether the right certificates 
# can be found by the script.
#
# An example: I have a CentOS-5 system where SSL works fine. But a Fedora-29
# install on the same system wasn't able to get SSL to work, the HTTP-Request
# complaining about certificates that can't be verified. The ssl_opts parameter
# (see below) should fix that, but does complain about mismatching hostnames. 
# Newer versions of LWP do more rigorous checking of  certificates than older
# versions. If you know of a fix for this, please let me know. If things don't
# work, hopefully you can (temporarily) switch off the https redirect.
#
################################################################################

use IO::Socket;			# yum install perl-IO-Socket-IP & ...-SSL
use LWP::UserAgent;		# yum install perl-LWP-Online
use LWP::Protocol;		# yum install perl-LWP-Protocol-https
use HTTP::Request;		# yum install perl-HTTP-Request-Form
use XML::LibXML;		# yum install perl-XML-LibXML
use XML::Simple;		# yum install perl-XML-Simple
use XML::Parser;		# yum install perl-XML-Parser
use XML::Writer;		# yum install perl-XML-Writer

################################################################################

# HTTP user-agent for POST
my $mHttp = LWP::UserAgent->new(
	ssl_opts => { verify_hostname => 0 }
#	ssl_opts => { SSL_verify_mode => SSL_VERIFY_NONE }	
);

# UCS Layout API
my $mUri = "http://ucs4.us/ucs/engine/ucs-engine.cgi";

################################################################################

sub doGetGearTab;
sub doSetGearIdx;

sub doLogin;
sub doLogout;
sub doGetFabInt;
sub doGetFabExt;
sub doGetChassisList;
sub doGetChassis;
sub doGetChasPSU;
sub doGetChasIOM;
sub doGetChasBlade;
sub doGetServerList;
sub doGetServer;
sub doGetEnclosureList;
sub doGetEnclosure;
sub doGetStorageList;
sub doGetStorage;
sub doGetStorPSU;
sub doGetStorIOC;
sub doGetStorBlade;

sub doCfgStrElem;
sub doCfgSetElem;
sub doQueryUCS;
sub doCreateXml;
sub doPostXml;
sub doDebugXml;

sub doPartToModel;

my $mSeqPict;
my $mRckMode = "auto";

my $mCfgConf;
my $mCfgSyst;
my @aCfgChas = ();

my @aIomMods = ( "",	"IOM2104",	"IOM2204",	"IOM2208",	"IOM2304",	"IOM2408",	"FI6324" );
my $mIomNums = $#aIomMods;

my $mCfgSrvr;

my $mMaxChas = 20;
my $mMaxSlot =  8;

my @aBldMods = ( "",	"B201", "B251", "B231", "B441", "B202", "B252",	"B232", "B442",
						"B022", "B203", "B423", "B204", "B424", "B264", "B464",
						"B205", "B485", "B206" );
my @aBldImgs = ( "",	"b201", "b251", "b231", "b441", "b202", "b252",	"b232", "b442",
						"b022", "b203", "b423", "b204", "b424", "b264", "b464",
						"b205", "b485", "b206" );
my @aBldWths = (  0,	 1    ,	 2    ,	 1    ,	 2    ,	 1    ,	 2    ,	 1    ,	 2    ,	
						 1    ,	 1    ,	 2    ,	 1    ,	 2    ,	 2    ,	 4    ,	
						 1    ,	 2    ,  1 );
my $aBldNums = $#aBldMods;

my @aGearTab = ();
my @aGearIdx = ();

my $mUcsHost;
my $mUcsPort;
my $mUcsNuov;
my $mUcsUser;
my $mUcsPass;
my $mUcsCook;

my @aFabList = ();
my $mNrFIs = 0;
my @aExpList = ();
my @aChsList = ();
my $mNrChas = 0;
my $mIOMType = "4";
my @aFexList = ();
my $mNrFEXs = 0;
my @aSrvList = ();
my $mNrSrvs = 0;
my @aEncList = ();
my $mNrEncs = 0;
my @aStoList = ();
my $mNrStos = 0;

my $mFabFrst, $mFabLast, $mFabNums;
my $mChsFrst, $mChsLast, $mChsNums;
my $mSrvFrst, $mSrvLast, $mSrvNums;
my $mHypFrst, $mHypLast, $mHypNums;
my $mEncFrst, $mEncLast, $mEncNums;
my $mStoFrst, $mStoLast, $mStoNums;

sub max ($$) { $_[$_[0] < $_[1]] }
sub min ($$) { $_[$_[0] > $_[1]] }

MAIN:
{

	# get parameters from arguments or from input
	if (($#ARGV != -1) && ($#ARGV != 4)) {
		print "\n";
		print "Usage: ucs-review.pl\n";
		print "   or: ucs-review.pl <ucs-host> <ucs-port> <username> <password> <xml-file>\n\n";
		exit;
	}

	if ($#ARGV == 4) {
		($mUcsHost, $mUcsPort, $mUcsUser, $mUcsPass, $mUcsFile) = @ARGV;
	}
	else {
		print "UCS host? ";
		chomp($mUcsHost = <>);
		print "UCS port? ";
		chomp($mUcsPort = <>);
		print "username? ";
		chomp($mUcsUser = <>);
		print "password? ";
		chomp($mUcsPass = <>);
		print "XML file? ";
		chomp($mUcsFile = <>);
	}

	# build geartab and reverse index
	doGetGearTab();
	doSetGearIdx();

	# find blocks in gear table
	($mFabFrst, $mFabLast, $mFabNums) = doGetBlockFab();
	($mChsFrst, $mChsLast, $mChsNums) = doGetBlockChs();
	($mSrvFrst, $mSrvLast, $mSrvNums) = doGetBlockSrv();
	($mHypFrst, $mHypLast, $mHypNums) = doGetBlockHyp();
	($mEncFrst, $mEncLast, $mEncNums) = doGetBlockEnc();
	($mStoFrst, $mStoLast, $mStoNums) = doGetBlockSto();

	# url for the xml-api
	if (substr ($mUcsHost, 0, 3) eq "172") {
		$mUri = "http://localhost/ucs/engine/ucs-engine.cgi";
	}
	else {
		$mUri = "http://ucs4.us/ucs/engine/ucs-engine.cgi";
	}

	$mSeqPict = 1000 + 10 * int(rand(890));
	$mCfgConf = "0|N|0|N|N|0|N|0|N|N|N|0|0|0|0|0|0|2|2"; 
	$mCfgSyst = "N|4|0|F|H|Y|Y|C|P|M|N"; 
	for $i (0 .. $mMaxChas) {
		$aCfgChas[$i] = "0|0|0|0|0|0|0"; 
		for $j (1 .. $mMaxSlot) { 
			$aCfgChas[$i] .= "|0"; 
		}
	}
	$mCfgSrvr = "0";
	for $i (2 .. $mSrvNums + $mHypNums + $mEncNums + $mStoNums) {
		$mCfgSrvr .= "|0";
	}

	if ($mUcsHost eq "") {
		$mUcsHost = "172.16.139.227";
	}
	if ($mUcsPort eq "") {
		$mUcsPort = "80";
	}
	if (substr($mUcsPort, -2) eq "43") {
		$mUcsNuov = "https://" . $mUcsHost . ":" . $mUcsPort . "/nuova";
	} else {
		$mUcsNuov = "http://" . $mUcsHost . ":" . $mUcsPort . "/nuova";
	}

	if ($mUcsUser eq "") {
		$mUcsUser = "admin";
	}
	if ($mUcsPass eq "") {
		$mUcsPass = "admin";
	}

	doQueryUCS();

	my $mXmlReq = doCreateXml();

	# my ($mXmlRsp, $mLocation, $mMessage, $mSuccess) = doPostXml($mUri, $mXmlReq);

	# doDebugXml("VIEWER", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	# write XML request to file
	open (FDWR, ">", $mUcsFile) || die "can't open XML-file " . $mUcsFile . "\n";
	print FDWR $mXmlReq;
	close (FDWR);

} 

########################################################################

sub doCfgStrElem
{
	my ($cfgStr, $el) = @_;

	@elem = split(/\|/, $cfgStr);

	return $elem[$el - 1];
}

########################################################################

sub doCfgSetElem
{
	my ($cfgStr, $pos, $el) = @_;

	@elem = split(/\|/, $cfgStr);
	if (($pos >= 1) && ($pos <= ($#elem + 1))) {
		$elem[$pos - 1] = $el;
		$cfgStr = $elem[0];
		for $i (1 .. $#elem) {
			$cfgStr .= '|' . $elem[$i];
		}
	}

	return $cfgStr;
}

########################################################################

sub doQueryUCS
{
	# login to UCS-M
	if ($mUcsCook = doLogin ($mUcsNuov, $mUcsUser, $mUcsPass)) {
	} else {
		exit;
	}

	# get fabint models
	for $n (1 .. 2) {
		$aFabList[$n] = doPartToModel(doGetFabInt($mUcsNuov, $mUcsCook, $n));
		if ($aFabList[$n]) {
			$mNrFIs++;
		}

		# get FI expansion modules
		for $m (1 .. 3) {
			$aExpList[$n][$m] = doPartToModel(doGetExpMod($mUcsNuov, $mUcsCook, $n, $m));
		}
	}

	$mCfgConf = ""; 
	if ($aFabList[2] eq "FI6120") {
		$mCfgConf .= "2";
	}
	elsif ($aFabList[1] eq "FI6120") {
		$mCfgConf .= "1";
	}
	else {
		$mCfgConf .= "0";
	}
	if (($aFabList[1] eq "FI6120") && ($aExpList[1][1] eq "E0080")) {
		$mCfgConf .= "|4";
	}
	elsif (($aFabList[1] eq "FI6120") && ($aExpList[1][1] eq "E0060")) {
		$mCfgConf .= "|8";
	}
	elsif (($aFabList[1] eq "FI6120") && ($aExpList[1][1] eq "E0600")) {
		$mCfgConf .= "|E";
	}
	elsif (($aFabList[1] eq "FI6120") && ($aExpList[1][1] eq "E0440")) {
		$mCfgConf .= "|C";
	}
	else {
		$mCfgConf .= "|N";
	}

	if ($aFabList[2] eq "FI6140") {
		$mCfgConf .= "|2";
	}
	elsif ($aFabList[1] eq "FI6140") {
		$mCfgConf .= "|1";
	}
	else {
		$mCfgConf .= "|0";
	}
	if (($aFabList[1] eq "FI6140") && ($aExpList[2][1] eq "E0080")) {
		$mCfgConf .= "|4";
	}
	elsif (($aFabList[1] eq "FI6140") && ($aExpList[2][1] eq "E0060")) {
		$mCfgConf .= "|8";
	}
	elsif (($aFabList[1] eq "FI6140") && ($aExpList[2][1] eq "E0600")) {
		$mCfgConf .= "|E";
	}
	elsif (($aFabList[1] eq "FI6140") && ($aExpList[2][1] eq "E0440")) {
		$mCfgConf .= "|C";
	}
	else {
		$mCfgConf .= "|N";
	}
	if (($aFabList[1] eq "FI6140") && ($aExpList[2][2] eq "E0080")) {
		$mCfgConf .= "|4";
	}
	elsif (($aFabList[1] eq "FI6140") && ($aExpList[2][2] eq "E0060")) {
		$mCfgConf .= "|8";
	}
	elsif (($aFabList[1] eq "FI6140") && ($aExpList[2][2] eq "E0600")) {
		$mCfgConf .= "|E";
	}
	elsif (($aFabList[1] eq "FI6140") && ($aExpList[2][2] eq "E0440")) {
		$mCfgConf .= "|C";
	}
	else {
		$mCfgConf .= "|N";
	}

	if ($aFabList[2] eq "FI6248") {
		$mCfgConf .= "|2";
	}
	elsif ($aFabList[1] eq "FI6248") {
		$mCfgConf .= "|1";
	}
	else {
		$mCfgConf .= "|0";
	}
	if (($aFabList[1] eq "FI6248") && ($aExpList[3][1] eq "E16UP")) {
		$mCfgConf .= "|U";
	}
	else {
		$mCfgConf .= "|N";
	}

	if ($aFabList[2] eq "FI6296") {
		$mCfgConf .= "|2";
	}
	elsif ($aFabList[1] eq "FI6296") {
		$mCfgConf .= "|1";
	}
	else {
		$mCfgConf .= "|0";
	}
	if (($aFabList[1] eq "FI6296") && ($aExpList[4][1] eq "E16UP")) {
		$mCfgConf .= "|U";
	}
	else {
		$mCfgConf .= "|N";
	}
	if (($aFabList[1] eq "FI6296") && ($aExpList[4][2] eq "E16UP")) {
		$mCfgConf .= "|U";
	}
	else {
		$mCfgConf .= "|N";
	}
	if (($aFabList[1] eq "FI6296") && ($aExpList[4][3] eq "E16UP")) {
		$mCfgConf .= "|U";
	}
	else {
		$mCfgConf .= "|N";
	}

	if ($aFabList[2] eq "FI6332") {
		$mCfgConf .= "|2";
	}
	elsif ($aFabList[1] eq "FI6332") {
		$mCfgConf .= "|1";
	}
	else {
		$mCfgConf .= "|0";
	}
	if ($aFabList[2] eq "FI6340") {
		$mCfgConf .= "|2";
	}
	elsif ($aFabList[1] eq "FI6340") {
		$mCfgConf .= "|1";
	}
	else {
		$mCfgConf .= "|0";
	}

	if ($aFabList[2] eq "FI6324") {
		$mCfgConf .= "|2";
	}
	elsif ($aFabList[1] eq "FI6324") {
		$mCfgConf .= "|1";
	}
	else {
		$mCfgConf .= "|0";
	}

	if ($aFabList[2] eq "FI6454") {
		$mCfgConf .= "|2";
	}
	elsif ($aFabList[1] eq "FI6454") {
		$mCfgConf .= "|1";
	}
	else {
		$mCfgConf .= "|0";
	}

	if ($aFabList[2] eq "FI64108") {
		$mCfgConf .= "|2";
	}
	elsif ($aFabList[1] eq "FI64108") {
		$mCfgConf .= "|1";
	}
	else {
		$mCfgConf .= "|0";
	}

	if ($aFabList[2] eq "FI6536") {
		$mCfgConf .= "|2";
	}
	elsif ($aFabList[1] eq "FI6536") {
		$mCfgConf .= "|1";
	}
	else {
		$mCfgConf .= "|0";
	}

	# get all chassis
	$aCfgChas[0] = "0";
	for $i (1 .. $mMaxChas) {
		$aCfgChas[$i] = "0|0|0|0|0|0|0"; 
		for $j (1 .. $mMaxSlot) { 
			$aCfgChas[$i] .= "|0"; 
		}
	}

	my ($lSuccess, @aChsList) = doGetChassisList($mUcsNuov, $mUcsCook);
	if ($lSuccess) {
		$mNrChas = $#aChsList + 1;
		for $i ( 0 .. $#aChsList ) {
			$ii = $i + 1;
			$ch = $aChsList[$i];
			$dn = $ch->[0];
			if (substr(substr($dn, -2), 0, 1) eq "-"){
				$n = substr($dn, -1);
			}
			else {
				$n = substr($dn, -2);
			}
			$model = $ch->[1];

			$aCfgChas[$ii] = "1";

			# get IO-modules
			for $j (1 .. 2) {
				my ($mPartNr, $mSuccess) = doGetChasIOM($mUcsNuov, $mUcsCook, $n, $j);
				$mModel = doPartToModel($mPartNr);

				if ($mSuccess) {
					$iom = $mModel;

					if ($iom eq "IOM2104") {
						$aCfgChas[$ii] .= "|1";
					}
					elsif ($iom eq "IOM2204") {
						$aCfgChas[$ii] .= "|2";
					}
					elsif ($iom eq "IOM2208") {
						$aCfgChas[$ii] .= "|3";
					}
					elsif ($iom eq "IOM2304") {
						$aCfgChas[$ii] .= "|4";
					}
					elsif ($iom eq "IOM2408") {
						$aCfgChas[$ii] .= "|5";
					}
					else {
						$aCfgChas[$ii] .= "|0";
					}
				}
				else {
					$aCfgChas[$ii] .= "|0";
				}
			}

			# get PSUs
			for $j (1 .. 4) {
				my ($mPresence, $mPower) = doGetChasPSU($mUcsNuov, $mUcsCook, $n, $j);

				if ($mPresence eq "missing") {
					$aCfgChas[$ii] .= "|0";
				}
				elsif ($mPresence eq "equipped") {
					$aCfgChas[$ii] .= "|1";
				}
			}

			# get blade models
			for $j (1 .. 8) {
				my ($mPartNr, $mSuccess) = doGetChasBlade ($mUcsNuov, $mUcsCook, $n, $j);
				$mModel = doPartToModel($mPartNr);
				if ($mSuccess) {
					$mdl = "0";
					for $i (1 .. $#aBldMods) {
						if ($mModel eq $aBldMods[$i]) {
							$mdl = $i;
						}
					}
					$aCfgChas[$ii] .= "|" . $mdl;
				}
				else {
					$aCfgChas[$ii] .= "|0";
				}
			}

		}
	}
	else {
	}

	$aCfgChas[0] = "$mNrChas";

	# get qty FEX's
	my ($lSuccess, @aFexList) = doGetFexList($mUcsNuov, $mUcsCook);
	if ($lSuccess) {
		$mNrFEXs = $#aFexList + 1;
		$mCfgConf .= "|" . $mNrFEXs;
	}
	else {
		$mCfgConf .= '|0';
	}

	# initialize rackmount list
	my @aRckList = ();
	$aRckList[0] = 0;
	for $i (0 .. ($mSrvNums + $mHypNums + $mEncNums + $mStoNums - 1)) {
		$aRckList[$i] = 0;
	}
	$mNrRcks = 0;

	# get servers and hyperflex
	my ($lSuccess, @aSrvList) = doGetServerList($mUcsNuov, $mUcsCook);
	if ($lSuccess) {
		for $i (0 .. $#aSrvList) {
			$sv = $aSrvList[$i];
			$dn = $sv->[0];
			if (substr(substr($dn, -2), 0, 1) eq "-"){
				$n = substr($dn, -1);
			}
			else {
				$n = substr($dn, -2);
			}
			$mModel = doPartToModel($sv->[1]);

			if (($mModel ne "") && ($mModel ne "C125")) {
				if (substr($mModel, 0, 1) eq "C") {		
					for $j (0 .. ($mSrvNums - 1)) {
						$jj = $mSrvFrst + $j;
						if ($mModel eq uc($aGearTab[$jj][2])) {
							$k = $j;
							$aRckList[$k]++;
							$mNrRcks++;
						}
					}
				}
				elsif (substr($mModel, 0, 2) eq "HX") {		
					for $j (0 .. ($mHypNums - 1)) {
						$jj = $mHypFrst + $j;
						if ($mModel eq uc($aGearTab[$jj][2])) {
							$k = $mSrvNums + $j;
							$aRckList[$k]++;
							$mNrRcks++;
						}
					}
				}
			}
		}
	}
	else {
	}

	# get rack enclosures
	my ($lSuccess, @aEncList) = doGetEnclosureList($mUcsNuov, $mUcsCook);
	if ($lSuccess) {
		for $i (0 .. $#aEncList) {
			$ec = $aEncList[$i];
			$dn = $ec->[0];
			if (substr(substr($dn, -2), 0, 1) eq "-"){
				$n = substr($dn, -1);
			}
			else {
				$n = substr($dn, -2);
			}
			$mModel = doPartToModel($ec->[1]);

			if (($mModel ne "") && ($mModel ne "C125")) {
				for $j (0 .. ($mEncNums - 1)) {
					$jj = $mEncFrst + $j;
					if ($mModel eq uc($aGearTab[$jj][2])) {
						$k = $mSrvNums + $mHypNums + $j;
						$aRckList[$k]++;
						$mNrRcks++;
					}
				}
			}
		}
	}
	else {
	}

	# get storage servers
	my ($lSuccess, @aStoList) = doGetStorageList($mUcsNuov, $mUcsCook);
	if ($lSuccess) {
		for $i (0 .. $#aStoList) {
			$st = $aStoList[$i];
			$dn = $st->[0];
			if (substr(substr($dn, -2), 0, 1) eq "-"){
				$n = substr($dn, -1);
			}
			else {
				$n = substr($dn, -2);
			}
			$mModel = doPartToModel($st->[1]);

			if ($mModel ne "") {
				for $j (0 .. ($mStoNums - 1)) {
					$jj = $mStoFrst + $j;
					if ($mModel eq uc($aGearTab[$jj][2])) {
						$k = $mSrvNums + $mHypNums + $mEncNums + $j;
						$aRckList[$k]++;
						$mNrRcks++;
					}
				}
			}

#			# get IO-controllers
#			for $j (1 .. 2) {
#				my ($mPartNr, $mSuccess) = doGetStorIOC($mUcsNuov, $mUcsCook, $n, $j);
#				$mModel = doPartToModel($mPartNr);
#
#				if ($mSuccess) {
#					$ioc = $mModel;
#				}
#			}
#
#			# get PSUs
#			for $j (1 .. 4) {
#				my ($mPresence, $mPower) = doGetChasPSU($mUcsNuov, $mUcsCook, $n, $j);
#			}
#
#			# get blade models
#			for $j (1 .. 2) {
#				my ($mPartNr, $mSuccess) = doGetChasBlade ($mUcsNuov, $mUcsCook, $n, $j);
#				$mModel = doPartToModel($mPartNr);
#
#				if ($mSuccess) {
#					$mdl = $mModel;
#				}
#			}

		}
	}
	else {
	}

	# copy aRckList array to mCfgSrvr
	$mCfgSrvr = $aRckList[0];
	for $n (1 .. $#aRckList) {
		$mCfgSrvr .= "|" . $aRckList[$n];
	}

	# logout of UCS-M
	if (doLogout($mUcsNuov, $mUcsCook)) {
	} else {
	}

	return;
}

########################################################################

sub doCreateXml
{
	my $lReq;

	my $lHdr;
	my $lFtr;
	my $lFab;
	my $lChs;
	my $lFex;
	my $lSrv;
	my $lHyp;
	my $lEnc;
	my $lSto;
	my $lPar;
	my $lTop;
	my @aRck = ();

	my $mNr6120 = doCfgStrElem($mCfgConf, 1);
	my $mNr6140 = doCfgStrElem($mCfgConf, 3);
	my $mNr6248 = doCfgStrElem($mCfgConf, 6);
	my $mNr6296 = doCfgStrElem($mCfgConf, 8);
	my $mNr6332 = doCfgStrElem($mCfgConf, 12);
	my $mNr6340 = doCfgStrElem($mCfgConf, 13);
	my $mNr6324 = doCfgStrElem($mCfgConf, 14);
	my $mNr6454 = doCfgStrElem($mCfgConf, 15);
	my $mNr64108 = doCfgStrElem($mCfgConf, 16);
	my $mNr6536 = doCfgStrElem($mCfgConf, 17);
	my $mNrFabInt = $mNr6120 + $mNr6140 + $mNr6248 + $mNr6296 + $mNr6332 + $mNr6340 + $mNr6324 + $mNr6454 + $mNr64108 + $mNr6536;
	my $mNrFabExt = $mNrFabInt; 
	my $mExp1 = doCfgStrElem($mCfgConf, 2);
	my $mExp2 = doCfgStrElem($mCfgConf, 4);
	my $mExp3 = doCfgStrElem($mCfgConf, 5);
	my $mExp4 = doCfgStrElem($mCfgConf, 7);
	my $mExp5 = doCfgStrElem($mCfgConf, 9);
	my $mExp6 = doCfgStrElem($mCfgConf, 10);
	my $mExp7 = doCfgStrElem($mCfgConf, 11);

	my $mNrNexus = doCfgStrElem($mCfgSyst, 1);
	my $lRckSize = 18 + doCfgStrElem($mCfgSyst, 2) * 6;
	my $lRckXtra = doCfgStrElem($mCfgSyst, 3);
	my $lRckFace = doCfgStrElem($mCfgSyst, 4);
	my $lRckLoad = doCfgStrElem($mCfgSyst, 5);
	my $bAddPnls = (doCfgStrElem($mCfgSyst, 6) eq "Y");
	my $bFrtBezl = (doCfgStrElem($mCfgSyst, 7) eq "Y");
	my $lRckLogo = doCfgStrElem($mCfgSyst, 8);
	my $lImgFrmt = doCfgStrElem($mCfgSyst, 9);
	my $lImgSize = doCfgStrElem($mCfgSyst, 10);
	my $bBckTrns = (doCfgStrElem($mCfgSyst, 11) eq "Y");

	my $mNrChassis = 0;
	for $ch (1 .. $mMaxChas) {
		$mNrChassis += doCfgStrElem($aCfgChas[$ch], 1);
	}

	my @aNrSrvr = ();
	my $mNrServers = 0;
	for $sv (1 .. $mSrvNums + $mHypNums + $mEncNums + $mStoNums) {
		$aNrSrvr[$sv] = doCfgStrElem($mCfgSrvr, $sv);
		$mNrServers += $aNrSrvr[$sv];
		$idx = $aGearIdx[$mSrvFrst] + $sv - 1;
		$img = $aGearTab[$idx][2];
		$rus = $aGearTab[$idx][3];
	}
	if ($mNrServers == 0) {
		$mNrFabExt = 0;
	}

	$lHdr = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
	if ($mRckMode eq 'auto') {
		$lHdr .= '<layout mode="AUTO" src="VWR" seq="' . $mSeqPict . '">' . "\n";
	}
	else {
		$lHdr .= '<layout mode="MANUAL" src="VWR" seq="' . $mSeqPict . '">' . "\n";
	}

	$lFtr = '</layout>' . "\n";

	# in automatic mode
	if ($mRckMode eq 'auto')
	{
		# fabric interconnects
		$lFab = '';
		if ($mNr6120 > 0) {
			$lFab .= '    <fabint model="FI6120" qty="' . $mNr6120 . '">' . "\n";
			if ($mExp1 eq 'E') {
				$lFab .= '        <expmod model="E0600" qty="1" />' . "\n";
			}
			elsif ($mExp1 eq '4') {
				$lFab .= '        <expmod model="E0080" qty="1" />' . "\n";
			}
			elsif ($mExp1 eq '8') {
				$lFab .= '        <expmod model="E0060" qty="1" />' . "\n";
			}
			elsif ($mExp1 eq 'C') {
				$lFab .= '        <expmod model="E0440" qty="1" />' . "\n";
			}
		}

		elsif ($mNr6140 > 0) {
			$lFab .= '    <fabint model="FI6140" qty="' . $mNr6140 . '">' . "\n";
			if (($mExp2 eq 'E') && ($mExp3 eq 'E')) {
				$lFab .= '        <expmod model="E0600" qty="2" />' . "\n";
			}
			elsif (($mExp2 eq '4') && ($mExp3 eq '4')) {
				$lFab .= '        <expmod model="E0080" qty="2" />' . "\n";
			}
			elsif (($mExp2 eq '8') && ($mExp3 eq '8')) {
				$lFab .= '        <expmod model="E0060" qty="2" />' . "\n";
			}
			elsif (($mExp2 eq 'C') && ($mExp3 eq 'C')) {
				$lFab .= '        <expmod model="E0440" qty="2" />' . "\n";
			}
			else {
				if ($mExp2 eq 'E') {
					$lFab .= '        <expmod model="E0600" qty="1" />' . "\n";
				}
				elsif ($mExp2 eq '4') {
					$lFab .= '        <expmod model="E0080" qty="1" />' . "\n";
				}
				elsif ($mExp2 eq '8') {
					$lFab .= '        <expmod model="E0060" qty="1" />' . "\n";
				}
				elsif ($mExp2 eq 'C') {
					$lFab .= '        <expmod model="E0440" qty="1" />' . "\n";
				}
				if ($mExp3 eq 'E') {
					$lFab .= '        <expmod model="E0600" qty="1" />' . "\n";
				}
				elsif ($mExp3 eq '4') {
					$lFab .= '        <expmod model="E0080" qty="1" />' . "\n";
				}
				elsif ($mExp3 eq '8') {
					$lFab .= '        <expmod model="E0060" qty="1" />' . "\n";
				}
				elsif ($mExp3 eq 'C') {
					$lFab .= '        <expmod model="E0440" qty="1" />' . "\n";
				}
			}
		}
		elsif ($mNr6248 > 0) {
			$lFab .= '    <fabint model="FI6248" qty="' . $mNr6248 . '">' . "\n";
			if ($mExp4 eq 'U') {
				$lFab .= '        <expmod model="E16UP" qty="1" />' . "\n";
			}
		}
		elsif ($mNr6296 > 0) {
			$lFab .= '    <fabint model="FI6296" qty="' . $mNr6296 . '">' . "\n";
			$lNr16UP = 0;
			if ($mExp5 eq 'U') {
				$lNr16UP++;
			}
			if ($mExp6 eq 'U') {
				$lNr16UP++;
			}
			if ($mExp7 eq 'U') {
				$lNr16UP++;
			}
			if ($lNr16UP > 0) {
				$lFab .= '        <expmod model="E16UP" qty="' . $lNr16UP . '" />' . "\n";
			}
		}
		elsif ($mNr6332 > 0) {
			$lFab .= '    <fabint model="FI6332" qty="' . $mNr6332 . '">' . "\n";
		}
		elsif ($mNr6340 > 0) {
			$lFab .= '    <fabint model="FI6340" qty="' . $mNr6340 . '">' . "\n";
		}
		elsif ($mNr6324 > 0) {
			$lFab .= '    <fabint model="FI6324" qty="' . $mNr6324 . '">' . "\n";
		}
		elsif ($mNr6454 > 0) {
			$lFab .= '    <fabint model="FI6454" qty="' . $mNr6454 . '">' . "\n";
		}
		elsif ($mNr64108 > 0) {
			$lFab .= '    <fabint model="FI64108" qty="' . $mNr64108 . '">' . "\n";
		}
		elsif ($mNr6536 > 0) {
			$lFab .= '    <fabint model="FI6536" qty="' . $mNr6536 . '">' . "\n";
		}

		if ($mNrFabInt > 0) {
			$lFab .= '        <power qty="2" />' . "\n";
			$lFab .= '    </fabint>' . "\n";
		}

		# blade chassis
		$lChs = '';
		for $ch (1 .. $mMaxChas) {
			$nrCh = doCfgStrElem($aCfgChas[$ch], 1);
			$nrBl = 0;
			for $b (1 .. $aBldNums) {
				$nrBl += doCfgStrElem($aCfgChas[$ch], 2 + $b);
			}

			if (($nrCh > 0) || ($nrBl > 0)) {
				$lChs .= '    <chassis model="UCS5108" cfg="' . $ch . '" qty="' . $nrCh . '">' . "\n";

				for $i (1 .. 2) {
					$iom = doCfgStrElem($aCfgChas[$ch], (1 + $i));
					if ($iom > 0) {
						$lChs .= '        <iomod model="' . $aIomMods[$iom] . '" pos="' . $i . '" />' . "\n";
					}
				}

				for $p (1 .. 4) {
					$psu = doCfgStrElem($aCfgChas[$ch], (3 + $p));
					if ($psu > 0) {
						$lChs .= '        <power pos="' . $p . '" />' . "\n";
					}
				}

				for $b (1 .. 8) {
					$bld = doCfgStrElem($aCfgChas[$ch], (7 + $b));
					if ($bld > 0) {

						if (substr(uc($aBldMods[$bld]), 0, 3) ne "B46") {
							$pos = $b;
						}
						else {
							$pos = $b - 2;  
						}
						$lChs .= '        <blade model="' . $aBldMods[$bld] . '" pos="' . $pos . '" />' . "\n";
					}
				}

				$lChs .= '    </chassis>' . "\n";
			} 
		} 

		# fabric extenders (2232)
		$lFex = '';
		if ($mNrFabExt > 0) {
			$lFex .= '    <fabext model="NX2232PP" qty="' . $mNrFabExt . '" />' . "\n";
		}

		# rackmount servers
		$lSrv = '';
		if ($mNrServers > 0) {
			$lSrv .= '    <rackmount>' . "\n";
			for $sv (1 .. $mSrvNums + $mHypNums + $mEncNums + $mStoNums) {
				if ($aNrSrvr[$sv] > 0) {
					$idx = $aGearIdx[$mSrvFrst] + $sv - 1;
					if ($idx > $mSrvLast) {
						$idx++;
					}
					if ($idx > $mHypLast) {
						$idx++;
					}
					if ($idx > $mEncLast) {
						$idx++;
					}
					$mdl = uc($aGearTab[$idx][2]);
					$lSrv .= '        <server model="' . $mdl . '" qty="' . $aNrSrvr[$sv] . '" />' . "\n";
				}
			}
			$lSrv .= '    </rackmount>' . "\n";
		}

		# parameters

		my $lNrNexus = doCfgStrElem($mCfgSyst, 1);
		my $lRckSize = 18 + doCfgStrElem($mCfgSyst, 2) * 6;
		my $lRckXtra = doCfgStrElem($mCfgSyst, 3);
		my $lRckFace = doCfgStrElem($mCfgSyst, 4);
		my $lRckLoad = doCfgStrElem($mCfgSyst, 5);
		my $bAddPnls = (doCfgStrElem($mCfgSyst, 6) eq "Y");
		my $bFrtBezl = (doCfgStrElem($mCfgSyst, 7) eq "Y");
		my $lRckLogo = doCfgStrElem($mCfgSyst, 8);
		my $lImgFrmt = doCfgStrElem($mCfgSyst, 9);
		my $lImgSize = doCfgStrElem($mCfgSyst, 10);
		my $bBckTrns = (doCfgStrElem($mCfgSyst, 11) eq "Y");

		$lPar = '';
		$lPar .= '    <params';
		$lPar .= ' ru="' . $lRckSize . '"';
		$lPar .= ' extra="' . $lRckXtra . '"';
		if ($lRckFace eq 'F') {
			$lPar .= ' face="FRONT"';
		}
		elsif ($lRckFace eq 'R') {
			$lPar .= ' face="REAR"';
		}
		elsif ($lRckFace eq 'P') {
			$lPar .= ' face="PERSPECTIVE"';
		}
		if ($lRckLoad eq 'H') {
			$lPar .= ' load="HIGH"';
		}
		elsif ($lRckLoad eq 'L') {
			$lPar .= ' load="LOW"';
		}
		elsif ($lRckLoad eq 'N') {
			$lPar .= ' load="NO"';
		}
		if ($bAddPnls) {
			$lPar .= ' panels="YES"';
		}
		else {
			$lPar .= ' panels="NO"';
		}
		if ($bFrtBezl) {
			$lPar .= ' bezel="YES"';
		}
		else {
			$lPar .= ' bezel="NO"';
		}
		if ($lRckLogo eq "N") {
			$lPar .= ' logo="NONE"';
		}
		elsif ($lRckLogo eq "C") {
			$lPar .= ' logo="CISCO"';
		}
		elsif ($lRckLogo eq "P") {
			$lPar .= ' logo="FLEXPOD"';
		}
		elsif ($lRckLogo eq "F") {
			$lPar .= ' logo="FLASH"';
		}
		elsif ($lRckLogo eq "B") {
			$lPar .= ' logo="VBLOCK"';
		}
		elsif ($lRckLogo eq "X") {
			$lPar .= ' logo="VXBLOCK"';
		}
		elsif ($lRckLogo eq "V") {
			$lPar .= ' logo="VERSA"';
		}
		elsif ($lRckLogo eq "I") {
			$lPar .= ' logo="INTELLI"';
		}
		elsif ($lRckLogo eq "S") {
			$lPar .= ' logo="SMART"';
		}
		if ($lImgFrmt eq 'P') {
			$lPar .= ' format="PHOTO"';
		}
		elsif ($lImgFrmt eq 'D') {
			$lPar .= ' format="DRAWING"';
		}
		elsif ($lImgFrmt eq 'O') {
			$lPar .= ' format="OVERLAY"';
		}
		if ($lImgSize eq 'S') {
			$lPar .= ' size="SMALL"';
		}
		elsif ($lImgSize eq 'M') {
			$lPar .= ' size="MEDIUM"';
		}
		elsif ($lImgSize eq 'L') {
			$lPar .= ' size="LARGE"';
		}
		elsif (($lImgSize eq 'E') || ($lImgSize eq 'X')) {
			$lPar .= ' size="EXTRA"';
		}
		if ($bBckTrns) {
			$lPar .= ' trans="YES"';
		}
		else {
			$lPar .= ' trans="NO"';
		}
		$lPar .= ' />' . "\n";
	} 

	# compose the request
	$lReq = $lHdr;
	if ($mRckMode eq 'auto') {
		$lReq .= $lFab . $lChs . $lFex . $lSrv;
	}
	$lReq .= $lPar . $lFtr;

	return $lReq;
}

########################################################################
### include ucs-gear

########################################################################

sub doGetGearTab()
{
	# build gear table
	@aGearTab = (
		[ "",	"-- select --",		"",				"0"		],
		[ "",	"Space 1 RU",		"space1",		"1"		],
		[ "",	"Space 2 RU",		"space2",		"2"		],
		[ "",	"Space 6 RU",		"space6",		"6"		],
		[ "",	"Panel 1 RU",		"panel1",		"1"		],
		[ "",	"Panel 2 RU",		"panel2",		"2"		],
		[ "",	"Panel 6 RU",		"panel6",		"6"		],
		[ "",	"Patch 1 RU",		"patch1",		"1"		],
		[ "",	"Panduit 1 RU",		"panduit1",		"1"		],
		[ "",	"Panduit 2 RU",		"panduit2",		"2"		],
		[ "",	"Panduit 3 RU",		"panduit3",		"3"		],
		[ "",	"Duct 1 RU",		"panduct1",		"1"		],
		[ "",	"Duct 2 RU",		"panduct2",		"2"		],
		[ "",	"D-Rings 1 RU",		"panring1",		"1"		],
		[ "",	"Tray 1 RU",		"pantray1",		"1"		],
		[ "",	"PDU RP208 M1",		"pdu208m1",		"1"		],
		[ "",	"PDU RP208 M3",		"pdu208m3",		"2"		],
		[ "",	"-- UCS Fabric --",	"",				"0"		],
		[ "",	"UCS FI 6120XP",	"fi6120",		"1"		],
		[ "",	"UCS FI 6140XP",	"fi6140",		"2"		],
		[ "",	"UCS FI 6248",		"fi6248",		"1"		],
		[ "",	"UCS FI 6296",		"fi6296",		"2"		],
		[ "",	"UCS FI 6332",		"fi6332",		"1"		],
		[ "",	"UCS FI 6332-16UP",	"fi6340",		"1"		],
		[ "",	"UCS FI 6454",		"fi6454",		"1"		],
		[ "",	"UCS FI 64108",		"fi64108",		"2"		],
		[ "",	"UCS FI 6536",		"fi6536",		"1"		],
		[ "",	"UCS FI 6x8G",		"e0060",		"0"		],
		[ "",	"UCS FI 8x4G",		"e0080",		"0"		],
		[ "",	"UCS FI 10G+4FC",	"e0440",		"0"		],
		[ "",	"UCS FI 6x10G",		"e0600",		"0"		],
		[ "",	"UCS FI 10G+8FC",	"e0660",		"0"		],
		[ "",	"UCS FI 16xUP",		"e16up",		"0"		],
		[ "",	"-- UCS Blades --",	"",				"0"		],
		[ "",	"UCS Chassis 1",	"ucs-ch1",		"6"		],
		[ "",	"UCS Chassis 2",	"ucs-ch2",		"6"		],
		[ "",	"UCS Chassis 3",	"ucs-ch3",		"6"		],
		[ "",	"UCS Chassis 4",	"ucs-ch4",		"6"		],
		[ "",	"UCS Chassis 5",	"ucs-ch5",		"6"		],
		[ "",	"UCS Chassis 6",	"ucs-ch6",		"6"		],
		[ "",	"UCS Chassis 7",	"ucs-ch7",		"6"		],
		[ "",	"UCS Chassis 8",	"ucs-ch8",		"6"		],
		[ "",	"UCS Chassis 9",	"ucs-ch9",		"6"		],
		[ "",	"UCS Chassis 10",	"ucs-cha",		"6"		],
		[ "",	"UCS Chassis 11",	"ucs-chb",		"6"		],
		[ "",	"UCS Chassis 12",	"ucs-chc",		"6"		],
		[ "",	"UCS Chassis 13",	"ucs-chd",		"6"		],
		[ "",	"UCS Chassis 14",	"ucs-che",		"6"		],
		[ "",	"UCS Chassis 15",	"ucs-chf",		"6"		],
		[ "",	"UCS Chassis 16",	"ucs-chg",		"6"		],
		[ "",	"UCS Chassis 17",	"ucs-chh",		"6"		],
		[ "",	"UCS Chassis 18",	"ucs-chi",		"6"		],
		[ "",	"UCS Chassis 19",	"ucs-chj",		"6"		],
		[ "",	"UCS Chassis 20",	"ucs-chk",		"6"		],
		[ "",	"UCS Chassis 21",	"ucs-chl",		"6"		],
		[ "",	"UCS Chassis 22",	"ucs-chm",		"6"		],
		[ "",	"UCS Chassis 23",	"ucs-chn",		"6"		],
		[ "",	"UCS Chassis 24",	"ucs-cho",		"6"		],
		[ "",	"UCS Chassis 25",	"ucs-chp",		"6"		],
		[ "",	"UCS Chassis 26",	"ucs-chq",		"6"		],
		[ "",	"UCS Chassis 27",	"ucs-chr",		"6"		],
		[ "",	"UCS Chassis 28",	"ucs-chs",		"6"		],
		[ "",	"UCS Chassis 29",	"ucs-cht",		"6"		],
		[ "",	"UCS Chassis 30",	"ucs-chu",		"6"		],
		[ "",	"UCS Chassis 31",	"ucs-chv",		"6"		],
		[ "",	"UCS Chassis 32",	"ucs-chw",		"6"		],
		[ "",	"UCS Chassis 33",	"ucs-chx",		"6"		],
		[ "",	"UCS Chassis 34",	"ucs-chy",		"6"		],
		[ "",	"UCS Chassis 35",	"ucs-chz",		"6"		],
		[ "",	"-- Rackmounts --","",				"0"		],
		[ "",	"UCS C200-M1 SFF",	"c201s",		"1"		],
		[ "",	"UCS C200-M1 LFF",	"c201l",		"1"		],
		[ "",	"UCS C210-M1 SFF",	"c211s",		"2"		],
		[ "",	"UCS C210-M1 LFF",	"c211l",		"2"		],
		[ "",	"UCS C200-M2 SFF",	"c202s",		"1"		],
		[ "",	"UCS C200-M2 LFF",	"c202l",		"1"		],
		[ "",	"UCS C210-M2 SFF",	"c212s",		"2"		],
		[ "",	"UCS C210-M2 LFF",	"c212l",		"2"		],
		[ "",	"UCS C250-M2 SFF",	"c252s",		"2"		],
		[ "",	"UCS C260-M2 SFF",	"c262s",		"2"		],
		[ "",	"UCS C460-M2 SFF",	"c462s",		"4"		],
		[ "",	"UCS C22-M3 SFF",	"c022s",		"1"		],
		[ "",	"UCS C22-M3 LFF",	"c022l",		"1"		],
		[ "",	"UCS C24-M3 SFF",	"c024s",		"2"		],
		[ "",	"UCS C24-M3 LFF",	"c024l",		"2"		],
		[ "",	"UCS C220-M3 SFF",	"c223s",		"1"		],
		[ "",	"UCS C220-M3 LFF",	"c223l",		"1"		],
		[ "",	"UCS C240-M3 SFF",	"c243s",		"2"		],
		[ "",	"UCS C240-M3 LFF",	"c243l",		"2"		],
		[ "",	"UCS C420-M3 SFF",	"c423s",		"2"		],
		[ "",	"UCS C220-M4 SFF",	"c224s",		"1"		],
		[ "",	"UCS C220-M4 LFF",	"c224l",		"1"		],
		[ "",	"UCS C240-M4 S08",	"c244s",		"2"		],
		[ "",	"UCS C240-M4 S16",	"c244t",		"2"		],
		[ "",	"UCS C240-M4 S24",	"c244x",		"2"		],
		[ "",	"UCS C240-M4 LFF",	"c244l",		"2"		],
		[ "",	"UCS C460-M4 SFF",	"c464s",		"4"		],
		[ "",	"UCS C220-M5 SFF",	"c225s",		"1"		],
		[ "",	"UCS C220-M5 LFF",	"c225l",		"1"		],
		[ "",	"UCS C240-M5 S08",	"c245s",		"2"		],
		[ "",	"UCS C240-M5 S24",	"c245x",		"2"		],
		[ "",	"UCS C240-M5 LFF",	"c245l",		"2"		],
		[ "",	"UCS C480-M5 S08",	"c485s",		"4"		],
		[ "",	"UCS C480-M5 S16",	"c485t",		"4"		],
		[ "",	"UCS C480-M5 S24",	"c485x",		"4"		],
		[ "",	"UCS C480-M5 DVD",	"c485d",		"4"		],
		[ "",	"UCS C480-M5 ML",	"c485a",		"4"		],
		[ "",	"UCS C240-M5 SD",	"c245d",		"2"		],
		[ "",	"UCS C220-M6 SFF",	"c226s",		"1"		],
		[ "",	"UCS C220-M6 NVMe",	"c226n",		"1"		],
		[ "",	"UCS C225-M6 SFF",	"c256s",		"1"		],
		[ "",	"UCS C225-M6 NVMe",	"c256n",		"1"		],
		[ "",	"UCS C240-M6 S12",	"c246s",		"2"		],
		[ "",	"UCS C240-M6 S24",	"c246x",		"2"		],
		[ "",	"UCS C240-M6 N12",	"c246n",		"2"		],
		[ "",	"UCS C240-M6 N24",	"c246v",		"2"		],
		[ "",	"UCS C240-M6 LFF",	"c246l",		"2"		],
		[ "",	"UCS C245-M6 SFF",	"c456s",		"2"		],
		[ "",	"-- HyperFlex --",	"",				"0"		],
		[ "",	"HX220-M4 Hybrid",	"hx224h",		"1"		],
		[ "",	"HX220-M4 Flash",	"hx224f",		"1"		],
		[ "",	"HX240-M4 Hybrid",	"hx244h",		"2"		],
		[ "",	"HX240-M4 Flash",	"hx244f",		"2"		],
		[ "",	"HX220-M5 Hybrid",	"hx225h",		"1"		],
		[ "",	"HX220-M5 Flash",	"hx225f",		"1"		],
		[ "",	"HX220-M5 NVMe",	"hx225n",		"1"		],
		[ "",	"HX220-M5 Edge",	"hx225e",		"1"		],
		[ "",	"HX240-M5 Hybrid",	"hx245h",		"2"		],
		[ "",	"HX240-M5 LFF",		"hx245l",		"2"		],
		[ "",	"HX240-M5 Flash",	"hx245f",		"2"		],
		[ "",	"HX240-M5 NVMe",	"hx245n",		"2"		],
		[ "",	"-- Enclosures --",	"",				"0"		],
		[ "",	"UCS C4200-M5",		"c4205",		"2"		],
		[ "",	"-- Storage --",	"",				"0"		],
		[ "",	"UCS C3160-M3",		"c3163",		"4"		],
		[ "",	"UCS C3260-M3",		"c3263",		"4"		],
		[ "",	"UCS S3260-M4",		"s3264",		"4"		],
		[ "",	"UCS S3260-M5",		"s3265",		"4"		],
		[ "",	"-- OEM's --",		"",				"0"		],
		[ "",	"C880-M4",			"c880",			"10"	],
		[ "",	"C880-M4 J1",		"c881",			"12"	],
		[ "",	"C880-M4 J2",		"c882",			"14"	],
		[ "",	"C880-M4 J1 S2",	"c883",			"12"	],
		[ "",	"C880-M4 J2 S2",	"c884",			"14"	],
		[ "",	"C880-M5",			"c885",			"5"		],
		[ "",	"C890-M5",			"c895",			"7"		],
		[ "",	"-- Nexus --",		"",				"0"		],
		[ "",	"Nexus 1010",		"nx1010",		"1"		],
		[ "",	"Nexus 1100",		"nx1100",		"1"		],
		[ "",	"Nexus 2148T",		"nx2148t",		"1"		],
		[ "",	"Nexus 2224TP",		"nx2224tp",		"1"		],
		[ "",	"Nexus 2232PP",		"nx2232pp",		"1"		],
		[ "",	"Nexus 2232TM",		"nx2232tm",		"1"		],
		[ "",	"Nexus 2232TP",		"nx2232tp",		"1"		],
		[ "",	"Nexus 2248PQ",		"nx2248pq",		"1"		],
		[ "",	"Nexus 2248TP",		"nx2248tp",		"1"		],
		[ "",	"Nexus 2332TQ",		"nx2332tq",		"1"		],
		[ "",	"Nexus 2348UPQ",	"nx2348upq",	"1"		],
		[ "",	"Nexus 2348TQ",		"nx2348tq",		"1"		],
		[ "",	"Nexus 3016Q",		"nx3016q",		"1"		],
		[ "",	"Nexus 3048TP",		"nx3048tp",		"1"		],
		[ "",	"Nexus 3064PQ",		"nx3064pq",		"1"		],
		[ "",	"Nexus 3064T",		"nx3064t",		"1"		],
		[ "",	"Nexus 3132C",		"nx3132c",		"1"		],
		[ "",	"Nexus 3132Q",		"nx3132qo",		"1"		],
		[ "",	"Nexus 3132QV",		"nx3132qv",		"1"		],
		[ "",	"Nexus 3132QX",		"nx3132qx",		"1"		],
		[ "",	"Nexus 3164Q",		"nx3164q",		"2"		],
		[ "",	"Nexus 3172PQ",		"nx3172pq",		"1"		],
		[ "",	"Nexus 3172TQ",		"nx3172tq",		"1"		],
		[ "",	"Nexus 31108PC",	"nx31108pc",	"1"		],
		[ "",	"Nexus 31108TC",	"nx31108tc",	"1"		],
		[ "",	"Nexus 31128PQ",	"nx31128pq",	"2"		],
		[ "",	"Nexus 3232C",		"nx3232c",		"1"		],
		[ "",	"Nexus 3264C",		"nx3264c",		"2"		],
		[ "",	"Nexus 3264Q",		"nx3264q",		"2"		],
		[ "",	"Nexus 3408",		"nx3408",		"4"		],
		[ "",	"Nexus 3432D",		"nx3432d",		"1"		],
		[ "",	"Nexus 3464C",		"nx3464c",		"2"		],
		[ "",	"Nexus 34180YC",	"nx34180yc",	"1"		],
		[ "",	"Nexus 34200YC",	"nx34200yc",	"1"		],
		[ "",	"Nexus 3524X",		"nx3524x",		"1"		],
		[ "",	"Nexus 3548X",		"nx3548x",		"1"		],
		[ "",	"Nexus 3636C",		"nx3636c",		"1"		],
		[ "",	"Nexus 36180YC",	"nx36180yc",	"1"		],
		[ "",	"Nexus 5010",		"nx5010",		"1"		],
		[ "",	"Nexus 5020",		"nx5020",		"2"		],
		[ "",	"Nexus 5532P",		"nx5532p",		"1"		],
		[ "",	"Nexus 5532UP",		"nx5532up",		"1"		],
		[ "",	"Nexus 5548P",		"nx5548p",		"1"		],
		[ "",	"Nexus 5548UP",		"nx5548up",		"1"		],
		[ "",	"Nexus 5596P",		"nx5596p",		"2"		],
		[ "",	"Nexus 5596UP",		"nx5596up",		"2"		],
		[ "",	"Nexus 5624Q",		"nx5624q",		"1"		],
		[ "",	"Nexus 5648Q",		"nx5648q",		"2"		],
		[ "",	"Nexus 5672UP",		"nx5672up",		"1"		],
		[ "",	"Nexus 5696Q",		"nx5696q",		"4"		],
		[ "",	"Nexus 56128P",		"nx56128p",		"2"		],
		[ "",	"Nexus 6001",		"nx6001",		"1"		],
		[ "",	"Nexus 6004",		"nx6004",		"4"		],
		[ "",	"Nexus 7004",		"nx7004",		"7"		],
		[ "",	"Nexus 7009",		"nx7009",		"14"	],
		[ "",	"Nexus 7010",		"nx7010",		"21"	],
		[ "",	"Nexus 7018",		"nx7018",		"25"	],
		[ "",	"Nexus 7702",		"nx7702",		"3"		],
		[ "",	"Nexus 7706",		"nx7706",		"9"		],
		[ "",	"Nexus 7710",		"nx7710",		"14"	],
		[ "",	"Nexus 7718",		"nx7718",		"26"	],
		[ "",	"Nexus 9236C",		"nx9236c",		"1"		],
		[ "",	"Nexus 9272Q",		"nx9272q",		"2"		],
		[ "",	"Nexus 92160YC",	"nx92160yc",	"1"		],
		[ "",	"Nexus 92300YC",	"nx92300yc",	"1"		],
		[ "",	"Nexus 92304QC",	"nx92304qc",	"2"		],
		[ "",	"Nexus 92348GC",	"nx92348gc",	"1"		],
		[ "",	"Nexus 9316D",		"nx9316d",		"1"		],
		[ "",	"Nexus 9332C",		"nx9332c",		"1"		],
		[ "",	"Nexus 9332D",		"nx9332d",		"1"		],
		[ "",	"Nexus 9332PQ",		"nx9332pq",		"1"		],
		[ "",	"Nexus 9336C",		"nx9336c",		"1"		],
		[ "",	"Nexus 9336PQ",		"nx9336pq",		"2"		],
		[ "",	"Nexus 9348GC",		"nx9348gc",		"1"		],
		[ "",	"Nexus 9364C",		"nx9364c",		"2"		],
		[ "",	"Nexus 9364D",		"nx9364d",		"2"		],
		[ "",	"Nexus 9372PX",		"nx9372px",		"1"		],
		[ "",	"Nexus 9372TX",		"nx9372tx",		"1"		],
		[ "",	"Nexus 9396PX",		"nx9396px",		"2"		],
		[ "",	"Nexus 9396TX",		"nx9396tx",		"2"		],
		[ "",	"Nexus 93108TC",	"nx93108tc",	"1"		],
		[ "",	"Nexus 93120TX",	"nx93120tx",	"2"		],
		[ "",	"Nexus 93128TX",	"nx93128tx",	"3"		],
		[ "",	"Nexus 93180YC",	"nx93180yc",	"1"		],
		[ "",	"Nexus 93180LC",	"nx93180lc",	"1"		],
		[ "",	"Nexus 93216TC",	"nx93216tc",	"2"		],
		[ "",	"Nexus 93240YC",	"nx93240yc",	"1"		],
		[ "",	"Nexus 93360YC",	"nx93360yc",	"2"		],
		[ "",	"Nexus 93400LD",	"nx93400ld",	"1"		],
		[ "",	"Nexus 93600CD",	"nx93600cd",	"1"		],
		[ "",	"Nexus 9504",		"nx9504",		"7"		],
		[ "",	"Nexus 9508",		"nx9508",		"13"	],
		[ "",	"Nexus 9516",		"nx9516",		"21"	],
		[ "",	"-- Cisco MDS --",	"",				"0"		],
		[ "",	"MDS 9124",			"mds9124",		"1"		],
		[ "",	"MDS 9132T",		"mds9132t",		"1"		],
		[ "",	"MDS 9134",			"mds9134",		"1"		],
		[ "",	"MDS 9148",			"mds9148o",		"1"		],
		[ "",	"MDS 9148S",		"mds9148s",		"1"		],
		[ "",	"MDS 9148T",		"mds9148t",		"1"		],
		[ "",	"MDS 9221i",		"mds9221i",		"3"		],
		[ "",	"MDS 9222i",		"mds9222i",		"3"		],
		[ "",	"MDS 9250i",		"mds9250i",		"2"		],
		[ "",	"MDS 9396S",		"mds9396s",		"2"		],
		[ "",	"MDS 9396T",		"mds9396t",		"2"		],
		[ "",	"MDS 9506",			"mds9506",		"7"		],
		[ "",	"MDS 9509",			"mds9509",		"14"	],
		[ "",	"MDS 9513",			"mds9513",		"14"	],
		[ "",	"MDS 9706",			"mds9706",		"9"		],
		[ "",	"MDS 9710",			"mds9710",		"14"	],
		[ "",	"MDS 9718",			"mds9718",		"26"	],
		[ "",	"",					"",				"0"		]
	);
	
	for $i (0 .. $#aGearTab) {
		if (substr($aGearTab[$i][1], 0, 2) eq "--") {
			$aGearTab[$i][0] = "000";
		}
		else {
			$aGearTab[$i][0] = substr(("000" . $i), -3);
		}

	}

	return;
}

########################################################################

sub doSetGearIdx()
{
	# build reverse gear index
	for $i (0 .. $#aGearTab) {
		$aGearIdx[int($aGearTab[$i][0])] = $i;
	}

	return;
}

########################################################################

sub doGetBlockFab()
{
	my ($lFabFrst, $lFabLast) = doLocateBlock("fi6");
	my $lFabNums = $lFabLast - $lFabFrst + 1;

	return ($lFabFrst, $lFabLast, $lFabNums);
}

sub doGetBlockChs()
{
	($lChsFrst, $lChsLast) = doLocateBlock("ucs-ch");
	$lChsNums = $lChsLast - $lChsFrst + 1;

	return ($lChsFrst, $lChsLast, $lChsNums);
}

sub doGetBlockRck()
{
	$lRckFrst = doLocateGear("c201s");
	$lRckLast = doLocateGear("c895");
	$lRckNums = $lRckLast - $lRckFrst + 1;

	return ($lRckFrst, $lRckLast, $lRckNums);
}

sub doGetBlockSrv()
{
	$lSrvFrst = doLocateGear("c201s");
	$lSrvLast = doLocateGear("c456s");
	$lSrvNums = $lSrvLast - $lSrvFrst + 1;

	return ($lSrvFrst, $lSrvLast, $lSrvNums);
}

sub doGetBlockHyp()
{
	($lHypFrst, $lHypLast) = doLocateBlock("hx2");
	$lHypNums = $lHypLast - $lHypFrst + 1;

	return ($lHypFrst, $lHypLast, $lHypNums);
}

sub doGetBlockEnc()
{
	$lEncFrst = doLocateGear("c4205");
	$lEncLast = doLocateGear("c4205");
	$lEncNums = $lEncLast - $lEncFrst + 1;

	return ($lEncFrst, $lEncLast, $lEncNums);
}

sub doGetBlockSto()
{
	$lStoFrst = doLocateGear("c3163");
	$lStoLast = doLocateGear("s3265");
	$lStoNums = $lStoLast - $lStoFrst + 1;

	return ($lStoFrst, $lStoLast, $lStoNums);
}

########################################################################

sub doLocateGear ()
{
	my ($mod) = @_;
	my $idx = 0;

	# find a specific device in gear-tab
	for $i (0 .. $#aGearTab) {
		if (lc($mod) eq $aGearTab[$i][2]) {
			$idx = $i;
			last;
		}
	}

	return $idx;
}

########################################################################

sub doLocateBlock ()
{
	my ($mod) = @_;
	my $len;
	my $frst = 999;
	my $last = 0;

	# find block of similar devices in gear-tab
	$len = length($mod);
	for $i (0 .. $#aGearTab) {
		if (substr(lc($aGearTab[$i][2]), 0, $len) eq $mod) {
			$frst = min($i, $frst);
			$last = max($i, $last);
		}
	}

	return ($frst, $last);
}

########################################################################
### include ucs-parts

sub doPartToModel()
{
	my ($mPartNr) = @_;
	my $mModel = "";

	my @aPartModelTab = (
		# Fabric Interconnects
		[ "N5K-C5010P-BF", "FI6120" ], 
		[ "N5K-C5020P-BF", "FI6140" ],
		[ "N10-S6100", "FI6120" ],
		[ "N10-S6200", "FI6140" ],
		[ "N10-E0060", "E0060" ], 
		[ "N10-E0080", "E0080" ], 
		[ "N10-E0440", "E0440" ], 
		[ "N10-E0600", "E0600" ], 
		[ "UCS-FI-6248UP", "FI6248" ],
		[ "UCS-FI-6296UP", "FI6296" ],
		[ "UCS-FI-E16UP", "E16UP" ],
		[ "UCS-FI-6332", "FI6332" ],
		[ "UCS-FI-6332-16UP", "FI6340" ],
		[ "UCS-FI-6300-E6-16UP", "FI6340" ],
		[ "UCS-FI-M-6324", "FI6324" ],
		[ "UCS-FI-6454", "FI6454" ],
		[ "UCS-FI-64108", "FI64108" ],
		[ "UCS-FI-6536", "FI6536" ],
		# Chassis
		[ "N20-C6508", "UCS5108" ],
		[ "UCSB-5108-AC", "UCS5108" ],
		[ "UCSB-5108-AC2", "UCS5108" ],
		[ "UCSB-5108-DC", "UCS5108" ],
		[ "UCSB-5108-DC2", "UCS5108" ],
		[ "UCSB-5108-HVDC", "UCS5108" ],
		# IO Modules
		[ "N20-I6584", "IOM2104" ],
		[ "UCS-IOM-2204XP", "IOM2204" ],
		[ "UCS-IOM-2208XP", "IOM2208" ],
		[ "UCS-IOM-2304", "IOM2304" ],
		[ "UCS-IOM-2304V2", "IOM2304" ],
		[ "UCS-IOM-2408", "IOM2408" ],
		# Power Supplies
		[ "UCSB-PSU-2500", "PSU2500" ],
		# Blades
		[ "N20-B6620-1", "B201" ],			
		[ "N20-B6620-2", "B251" ],			
		[ "N20-B6730-1", "B231" ],			
		[ "N20-B6740-2", "B441" ],			
		[ "N20-B6625-1", "B202" ],			
		[ "N20-B6625-2", "B252" ],			
		[ "B230-BASE-M2", "B232" ],			
		[ "B440-BASE-M2", "B442" ],			
		[ "UCSB-B22-M3", "B022" ],			
		[ "UCSB-B200-M3", "B203" ],			
		[ "UCSB-B420-M3", "B423" ],			
		[ "UCSB-B200-M4", "B204" ],			
		[ "UCSB-B420-M4", "B424" ],			
		[ "UCSB-EX-M4-1", "B264" ],			
		[ "UCSB-EX-M4-1C", "B264" ],		
		[ "UCSB-EX-M4-1A", "B464" ],		
		[ "UCSB-EX-M4-2", "B464" ],			
		[ "UCSB-EX-M4-3", "B264" ],			
		[ "UCSB-B200-M5", "B205" ],			
		[ "UCSB-B480-M5", "B485" ],			
		[ "UCSB-B200-M6", "B206" ],			
		[ 'UCSX-210C-M6', 'X216' ],			
		[ 'UCSX-210C-M6-GPU', 'G216' ],		
		[ 'UCSX-440C', 'X440' ],			

		# Mezzanine Adapters
		[ "N20-AI0002", "82598KR-CI" ],
		[ "N20-AI0102", "M61KR-I" ],
		[ "N20-AE0002", "M71KR-E" ],
		[ "N20-AQ0002", "M71KR-Q" ],
		[ "N20-AC0002", "M81KR" ],
		[ "UCSB-MEZ-BRC-02", "M61KR-B" ],
		[ "UCSB-MEZ-ELX-03", "M73KR-E" ],
		[ "UCSB-MEZ-QLG-03", "M73KR-Q" ],
		[ "UCSB-MLOM-40G-01", "VIC1240" ],
		[ "UCSB-MLOM-PT-01", "EXP1240" ],
		[ "UCS-VIC-M82-4P", "VIC1280" ],
		[ "UCSB-MLOM-40G-03", "VIC1340" ],
		[ "UCSB-VIC-M83-8P", "VIC1380" ],
		[ "UCSB-F-FIO-365M", "FIO365M" ],
		[ "UCSB-F-FIO-785M", "FIO785M" ],
		# Rackmounts
		[ "R200-1120402", "C201S" ],		
		[ "R210-2121605", "C211S" ],		
		[ "R250-2480805", "C251S" ],		
		[ "R460-4640810", "C461S" ],		
		[ "R200-1120402W", "C202S" ],		
		[ "R210-2121605W", "C212L" ],		
		[ "UCSC-BSE-SFF-C200", "C202S" ],	
		[ "R250-2480805W", "C252S" ],		
		[ "C260-BASE-2646", "C262S" ],		
		[ "UCSC-BASE-M2-C460", "C462S" ],	
		[ "UCSC-C22-M3S", "C022S" ],		
		[ "UCSC-C22-M3L", "C022L" ],		
		[ "UCSC-C24-M3S", "C024S" ],		
		[ "UCSC-C24-M3S2", "C024S" ],		
		[ "UCSC-C24-M3L", "C024L" ],		
		[ "UCSC-C220-M3S", "C223S" ],		
		[ "UCSC-C220-M3L", "C223L" ],		
		[ "UCSC-C240-M3S", "C243S" ],		
		[ "UCSC-C240-M3S2", "C243S" ],		
		[ "UCSC-C240-M3L", "C243L" ],		
		[ "UCSC-C420-M3", "C423S" ],		
		[ "UCSC-C220-M4S", "C224S" ],		
		[ "UCSC-C220-M4L", "C224L" ],		
		[ "UCSC-C240-M4S", "C244S" ],		
		[ "UCSC-C240-M4S2", "C244T" ],		
		[ "UCSC-C240-M4SX", "C244X" ],		
		[ "UCSC-C240-M4L", "C244L" ],		
		[ "UCSC-C460-M4", "C464S" ],		
		[ "UCSC-C125", "C125" ],			
		[ "UCSC-C220-M5S", "C225S" ],		
		[ "UCSC-C220-M5SN", "C225N" ],		
		[ "UCSC-C220-M5L", "C225L" ],		
		[ "UCSC-C240-M5S", "C245S" ],		
		[ "UCSC-C240-M5SX", "C245X" ],		
		[ "UCSC-C240-M5SN", "C245N" ],		
		[ "UCSC-C240-M5L", "C245L" ],		
		[ "UCSC-C240-M5SD", "C245D" ],		
		[ "UCSC-C240-M5-SD", "C245D" ],		
		[ "UCSC-C480-M5", "C485S" ],		
		[ "UCSC-C480-M5ML", "C485A" ],		
		[ "UCSC-C220-M6S", "C226S" ],		
		[ "UCSC-C220-M6N", "C226N" ],		
		[ "UCSC-C225-M6S", "C256S" ],		
		[ "UCSC-C225-M6N", "C256N" ],		
		[ "UCSC-C240-M6S", "C245S" ],		
		[ "UCSC-C240-M6SX", "C245X" ],		
		[ "UCSC-C240-M6N", "C245N" ],		
		[ "UCSC-C240-M6SN", "C245V" ],		
		[ "UCSC-C240-M6L", "C245L" ],		
		[ "UCSC-C245-M6S", "C456S" ],		
		[ "HX220C-M4S", "HX224H" ],			
		[ "HXAF220C-M4S", "HX224F" ],		
		[ "HX240C-M4SX", "HX244H" ],		
		[ "HX240C-M4S2", "HX244H" ],		
		[ "HXAF240C-M4SX", "HX244F" ],		
		[ "HX220C-M5S", "HX225H" ],			
		[ "HX220C-M5SX", "HX225H" ],		
		[ "HXAF220C-M5S", "HX225F" ],		
		[ "HXAF220C-M5SX", "HX225F" ],		
		[ "HXAF220C-M5SN", "HX225N" ],		
		[ "HXNV220C-M5S", "HX225N" ],		
		[ "HXED220C-M5S", "HX225E" ],		
		[ "HX240C-M5SX", "HX245H" ],		
		[ "HX240C-M5SD", "HX245H" ],		
		[ "HX240C-M5L", "HX245L" ],			
		[ "HXAF240C-M5SX", "HX245F" ],		
		[ "HXAF240C-M5SD", "HX245F" ],		
		[ "HXNV240C-M5SX", "HX245N" ],		
		[ "UCSC-C4200-SFF", "C4205" ],		
		[ "UCSC-C3X60-SVRNB", "C3X60-M3" ],	
		[ "UCSC-C3X60-M4SRB", "S3X60-M4" ],	
		[ "UCSC-C3K-M4SRB", "S3X60-M4" ],	
		[ "UCSC-C3K-M5SRB", "S3X60-M5" ],	
		[ "UCS-S3260-M5SRB", "S3X60-M5" ],	
		[ "UCSS-S3260", "S3265" ],			
#		[ "UCSC-C3X60-BASE", "C3X60" ],		# C3160 / C3260
		[ "UCSC-C3X60-BASE", "S3265" ],		
		# PCI Adapters
		[ "N2XX-ACPCI01", "P81E" ],
		[ "N2XX-ABPCI01", "BCM-5709" ],
		[ "N2XX-ABPCI02", "BCM-57711" ],
		[ "N2XX-ABPCI03", "BCM-5709" ],
		[ "N2XX-AEPCI01", "EMX-10102-CNA" ],
		[ "N2XX-AEPCI03", "EMX-11002-HBA" ],
		[ "N2XX-AEPCI05", "EMX-12002-HBA" ],
		[ "N2XX-AIPCI01", "INT-X520" ],
		[ "N2XX-AIPCI02", "INT-E1G44ETG1P20" ],
		[ "N2XX-AMPCI01", "MLX-CX-2-SFP" ],
		[ "N2XX-AQPCI01", "QLC-8152-CNA" ],
		[ "N2XX-AQPCI03", "QLC-2462-HBA" ],
		[ "N2XX-AQPCI05", "QLC-2562-HBA" ],
		[ "UCSC-PCIE-CSC-02", "VIC1225" ],
		[ "UCSC-PCIE-C10T-02", "VIC1225T" ],
		[ "UCSC-PCIE-C40Q-02", "VIC1285" ],
		[ "UCSC-PCIE-BSFP", "BCM-57712-SFP" ],
		[ "UCSC-PCIE-BTG", "BCM-57712-10T" ],
		[ "UCSC-PCIE-B3SFP", "BCM-57810-SFP" ],
		[ "UCSC-PCIE-E14102", "EMX-14102-CNA" ],
		[ "UCSC-PCIE-E16002", "EMX-16002-HBA" ],
		[ "UCSC-PCIE-ESFP", "EMX-11102-CNA" ],
		[ "UCSC-PCIE-IRJ45", "INT-QUAD-GBE" ],
		[ "UCSC-PCIE-ITG", "INT-X540-10T" ],
		[ "UCSC-PCIE-Q2672", "QLC-2672-HBA" ],
		[ "UCSC-PCIE-Q8362", "QLC-8362-CNA" ],
		[ "UCSC-F-FIO-365M", "FIO-365M" ],
		[ "UCSC-F-FIO-785M", "FIO-785M" ],
		[ "UCSC-F-FIO-1000MP", "FIO-1000MP" ],
		[ "UCSC-F-FIO-1000PS", "FIO-1000PS" ],
		[ "UCSC-F-FIO-1205M", "FIO-1205M" ],
		[ "UCSC-F-FIO-1300MP", "FIO-1300MP" ],
		[ "UCSC-F-FIO-1300PS", "FIO-1300PS" ],
		[ "UCSC-F-FIO-2600MP", "FIO-2600MP" ],
		[ "UCSC-F-FIO-2600PS", "FIO-2600PS" ],
		[ "UCSC-F-FIO-3000M", "FIO-3000M" ],
		[ "UCSC-F-FIO-5200MP", "FIO-5200MP" ],
		[ "UCSC-F-FIO-5200PS", "FIO-5200PS" ],
		# Fabric Extenders
		[ "N2K-C2148T", "NX2148" ],
		[ "N2K-C2148T-1GE", "NX2148" ],
		[ "N2K-C2224TP", "NX2224" ],
		[ "N2K-C2224TF", "NX2224" ],		
		[ "N2K-C2232PP", "NX2232" ],
		[ "N2K-C2232PP-10GE", "NX2232" ],
		[ "N2K-C2232PF", "NX2232" ],		
		[ "N2K-C2232TM", "NX2233" ],
		[ "N2K-C2232TM-10GE", "NX2233" ],
		[ "N2K-C2232TM-E-10GE", "NX2233" ],
		[ "N2K-C2232TF", "NX2233" ],		
		[ "N2K-C2232TP", "NX2234" ],		
		[ "N2K-C2248PQ", "NX2248" ],
		[ "N2K-C2248TP", "NX2249" ],
		[ "N2K-C2248T-1GE", "NX2249" ],
		[ "N2K-C2248TPE", "NX2249" ],
		[ "N2K-C2248TP-1GE", "NX2249" ],
		[ "N2K-C2348UPQ", "NX2348" ],
		[ "N2K-C2348UPQ-10GE", "NX2348" ],
		[ "N2K-C2348TP", "NX2349" ],
		# Nexus
		[ "N3K-C3016Q", "NX3016" ],
		[ "N3K-C3048TP", "NX3048" ],
		[ "N3K-C3064PQ", "NX3064" ],
		[ "N3K-C3064T", "NX3065" ],
		[ "N3K-C3132CZ", "NX3132X" ],
		[ "N3K-C3132Q", "NX3132" ],
		[ "N3K-C3132QV", "NX3133" ],
		[ "N3K-C3132QX", "NX3134" ],
		[ "N3K-C3164Q", "NX3164" ],
		[ "N3K-C3172PQ", "NX3172" ],
		[ "N3K-C3172TQ", "NX3173" ],
		[ "N3K-C31128PQ", "NX31128" ],
		[ "N3K-C3232C", "NX3232" ],
		[ "N3K-C3264C", "NX3264C" ],
		[ "N3K-C3264Q", "NX3264Q" ],
		[ "N3K-C3524P", "NX3524" ],
		[ "N3K-C3548P", "NX3548" ],
		[ "N3K-C3548X", "NX3549" ],
		[ "N3K-C36180YC", "NX36180" ],
		[ "N5K-C5548P", "NX5548" ],
		[ "N5K-C5548UP", "NX5549" ],
		[ "N5K-C5596P", "NX5596" ],
		[ "N5K-C5596UP", "NX5597" ],
		[ "N5K-C5624Q", "NX5624" ],
		[ "N5K-C5648Q", "NX5648" ],
		[ "N5K-C5672UP", "NX5672" ],
		[ "N5K-C5696Q", "NX5696" ],
		[ "N5K-C56128P", "NX56128" ],
		[ "N6K-C6001-64", "NX6001" ],
		[ "N6K-C6004-69", "NX6004" ],
		[ "N7K-C7004|", "NX7004" ],
		[ "N7K-C7009|", "NX7009" ],
		[ "N7K-C7010|", "NX7010" ],
		[ "N7K-C7018|", "NX7018" ],
		[ "N77-C7702|", "NX7702" ],
		[ "N77-C7706|", "NX7706" ],
		[ "N77-C7710|", "NX7710" ],
		[ "N77-C7718|", "NX7718" ],
		[ "N9K-C9236C", "NX9236" ],
		[ "N9K-C9272Q", "NX9272" ],
		[ "N9K-C92160YC", "NX92160" ],
		[ "N9K-C92304QC", "NX92304" ],
		[ "N9K-C92348QC", "NX92348" ],
		[ "N9K-C9332PQ", "NX9332" ],
		[ "N9K-C9336PQ", "NX9336" ],
		[ "N9K-C9372PX", "NX9372" ],
		[ "N9K-C9372PX-R", "NX9373" ],
		[ "N9K-C9372TX", "NX9374" ],
		[ "N9K-C9396PX", "NX9396" ],
		[ "N9K-C9396PX-R", "NX9397" ],
		[ "N9K-C9396TX", "NX9398" ],
		[ "N9K-C93108TC", "NX93108" ],
		[ "N9K-C93120TX", "NX93120" ],
		[ "N9K-C93128TX", "NX93128" ],
		[ "N9K-C93180YC", "NX93180" ],
		[ "N9K-C93180LC", "NX93181" ],
		[ "N9K-C93216TC-FX2", "NX93216TC" ],
		[ "N9K-C9504|", "NX9504" ],
		[ "N9K-C9508|", "NX9508" ],
		[ "N9K-C9516|", "NX9516" ],
		# MDS
		[ "DS-C9124", "MDS9124" ],
		[ "DS-C9132", "MDS9132" ],
		[ "DS-C9134", "MDS9134" ],
		[ "DS-C9148D", "MDS9148" ],
		[ "DS-C9148S", "MDS9149" ],
		[ "DS-C9221i", "MDS9221" ],
		[ "DS-C9222I", "MDS9222" ],
		[ "DS-C9250I", "MDS9250" ],
		[ "DS-C9506", "MDS9506" ],
		[ "DS-C9509", "MDS9509" ],
		[ "DS-C9513", "MDS9513" ],
		[ "DS-C9706", "MDS9706" ],
		[ "DS-C9710", "MDS9710" ],
		[ "DS-C9718", "MDS9718" ],
		# Catalyst
		[ "WS-C2960S", "CAT2960" ],
		[ "WS-C2960X", "CAT2961" ],
		[ "WS-C3650", "CAT3650" ],
		[ "WS-C3850", "CAT3850" ],
		[ "WS-C3550", "CAT3851" ],
		[ "C6800", "CAT6800" ],
		[ "C6807", "CAT6807" ],
		[ "C6816", "CAT6816" ],
		[ "C6824", "CAT6824" ],
		[ "C6832", "CAT6832" ],
		[ "C6840", "CAT6840" ],
		[ "C6880", "CAT6880" ],
		[ "C9324", "CAT9324" ],
		[ "C9348", "CAT9348" ],
		[ "C9404", "CAT9404" ],
		[ "C9407", "CAT9407" ],
		[ "C9410", "CAT9410" ],
		[ "C9512", "CAT9512" ],
		[ "C9524", "CAT9524" ],
		[ "C9540", "CAT9540" ],
		# End
		[ "", "" ],
		[ "end", "end" ],
		);

	# $p = $aPartModelTab[17][0];	# UCS5108
	# $m = $aPartModelTab[17][1];

	my $i = 0;
    if (substr ($mPartNr, -1) eq "=") {
        $mPartNr = substr($mPartNr, 0, -1);
    }

	while (($mModel eq "") && ($aPartModelTab[$i][0] ne "end")) {
		if ($aPartModelTab[$i][0] eq substr($mPartNr, 0, length($aPartModelTab[$i][0]))) {
			$mModel = $aPartModelTab[$i][1];
		}
		$i++;
	}

	# remove all dashes from model
	while (index($mModel, "-") > 0) {
		$mModel = substr ($mModel, 0, index($mModel, "-")) . substr ($mModel, (index($mModel, "-") + 1));
	}

	if ($mModel ne "") {
	}

	return ($mModel);
}

########################################################################
### include ucs-lib

sub doLogin()
{
	my ($mUri, $mUid, $mPwd) = @_;

	my $mXmlMethod = 'aaaLogin';
	my $mXmlAttrib = 'inName="' . $mUid . '" ' . 'inPassword="' . $mPwd . '" ';
	my $mIsNested = 0;
	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);

	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("LOGIN", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	$mCookie = undef;
	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			$mCookie = $mConfig->{'outCookie'};
			$mCookie = undef if ($mCookie && $mCookie eq "");
		};
		$mSuccess = undef if ($@);
	}

	return ($mSuccess, $mCookie, $mXmlRsp) if wantarray;
	return ($mCookie);
}

########################################################################

sub doLogout()
{
	my ($mUri, $mCookie) = @_;

	my $mXmlMethod = 'aaaLogout';
	my $mXmlAttrib = 'inCookie="' . $mCookie . '"';
	my $mIsNested = 0;
	my $mXmlReq = prepareXmlQuery($mXmlMethod, $mXmlAttrib, $mIsNested);

	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("LOGOUT", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	my $mStatus = undef;
	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			$mStatus = $mConfig->{'outStatus'};
		};
	}

	return ($mSuccess && ($mStatus eq "success"));
}

########################################################################

sub doRefresh()
{
	my ($mUri, $mUid, $mPwd, $mCookie) = @_;

	my $mXmlMethod = 'aaaRefresh';
	my $mXmlAttrib = 'inName="' . $mUid . '" '
				   . 'inPassword="' . $mPwd . '" '
				   . 'inCookie="' . $mCookie . '" ';
	my $mIsNested = 0;
	my $mXmlReq = prepareXmlQuery($mXmlMethod, $mXmlAttrib, 0);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("REFRESH", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	$mCookie = undef;
	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			$mCookie = $mConfig->{'outCookie'};
			$mCookie = undef if ($mCookie && $mCookie eq "");
		};
		$mSuccess = undef if ($@);
	}

	return ($mSuccess, $mCookie, $mXmlRsp) if wantarray;
	return ($mCookie);
}

########################################################################

sub doGetFabInt()
{
	my ($mUri, $mCookie, $mFabIntNr) = @_;

	my @aFabName = ( '', 'A', 'B' );

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveDn';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'dn="sys/switch-' . $aFabName[$mFabIntNr] . '" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;
	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("FABINT", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	my $mModel = undef;
	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			$mModel = $mConfig->{'outConfig'}->{'networkElement'}->{'model'};
		};
	}

	return ($mModel);
}

########################################################################

sub doGetExpMod()
{
	my ($mUri, $mCookie, $mFabIntNr, $mFabExpNr) = @_;

	my @aFabName = ( '', 'A', 'B' );
	my $mExpSlot = $mFabExpNr + 1;

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveDn';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'dn="sys/switch-' . $aFabName[$mFabIntNr] . '/slot-' . $mExpSlot . '" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;
	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("EXPMOD", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	my $mModel = undef;
	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			$mModel = $mConfig->{'outConfig'}->{'equipmentSwitchCard'}->{'model'};
		};
	}

	return ($mModel);
}

########################################################################

sub doGetChassisList()
{
	my ($mUri, $mCookie) = @_;

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveClass';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'classId="equipmentChassis" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;

	my $ch;
	my $mChDn;
	my $mChModel;

	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("CHASSISLIST", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	my @aListCh = ();
	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			if ($mConfig->{'outConfigs'}->{'equipmentChassis'}->{'dn'}) {
				# we have only a single chassis
				$mChDn = $mConfig->{'outConfigs'}->{'equipmentChassis'}->{'dn'};
				$mChModel = $mConfig->{'outConfigs'}->{'equipmentChassis'}->{'model'};
				if ((substr($mChModel,0,4) eq "N20-") || (substr($mChModel,0,4) eq "UCSB")) {		
					push (@aListCh, [$mChDn, $mChModel]);
				}
			}
			else {
				# we have multiple chassis
				for $ch (sort keys %{$mConfig->{'outConfigs'}->{'equipmentChassis'}}) {
					$mChDn = $mConfig->{'outConfigs'}->{'equipmentChassis'}->{$ch}->{'dn'};
					$mChModel = $mConfig->{'outConfigs'}->{'equipmentChassis'}->{$ch}->{'model'};
					if ((substr($mChModel,0,4) eq "N20-") || (substr($mChModel,0,4) eq "UCSB")) {		
						push (@aListCh, [$mChDn, $mChModel]);
					}
				}
			}
		};
		$mSuccess = undef if ($@);
	}

	return ($mSuccess, @aListCh);
}

########################################################################

sub doGetChassis()
{
	my ($mUri, $mCookie, $mChassisNr) = @_;

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveDn';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'dn="sys/chassis-' . $mChassisNr . '" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;
	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("CHASSIS", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	my $mPresence = undef;
	if ($mSuccess)
	{
		eval {
		my $mParser = XML::Simple->new();
		my $mConfig = $mParser->XMLin($mXmlRsp);
		$mPresence = $mConfig->{'outConfig'}->{'equipmentChassis'}->{'model'};
		};
	}

	if ($mPresence ne '') {
		return 1;
	}
	return 0;
}

########################################################################

sub doGetChasPSU()
{
	my ($mUri, $mCookie, $mChassisNr, $mPsuNr) = @_;

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveDn';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'dn="sys/chassis-' . $mChassisNr . '/psu-' . $mPsuNr . '" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;
	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("CHASPSU", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	$mPresence = undef;
	$mPower = undef;
	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			$mPresence = $mConfig->{'outConfig'}->{'equipmentPsu'}->{'presence'};
			$mPower = $mConfig->{'outConfig'}->{'equipmentPsu'}->{'power'};
		};
		$mSuccess = undef if ($@);
	}

	return ($mPresence, $mPower);
}

########################################################################

sub doGetChasIOM()
{
	my ($mUri, $mCookie, $mChassisNr, $mIOmNr) = @_;

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveDn';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'dn="sys/chassis-' . $mChassisNr . '/slot-' . $mIOmNr . '" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;
	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("CHASIOM", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	$mPresence = undef;
	$mPower = undef;
	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			$mModel = $mConfig->{'outConfig'}->{'equipmentIOCard'}->{'model'};
		};
		$mSuccess = undef if ($@);
	}

	return ($mModel, $mSuccess);
}

########################################################################

sub doGetChasBladeList()
{
	my ($mUri, $mCookie, $mChassisNr) = @_;

	# <configResolveClass cookie="1383780536/b0f3199b-d42f-4e06-a4e1-9b5e3b5749a6" inHierarchical="false" classId="computeBlade"><inFilter><wcard class="computeBlade" property="dn" value="sys/chassis-1/*" /></inFilter> </configResolveClass>
	my $mXmlReq = '<configResolveClass cookie="' . $mCookie . '" inHierarchical="false" classId="computeBlade">'
							. '<inFilter><wcard class="computeBlade" property="dn" value="sys/chassis-' . $mChassisNr . '/*" /></inFilter>'
							. '</configResolveClass>';

	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("BLADELIST", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	$p = index ($mXmlRsp, "name=\"\"");
	while ($p > 0) {
		$mXmlRsp = substr($mXmlRsp, 0, $p) . 'name="' . $p . '" ' . substr($mXmlRsp, ($p + 8));
		$p = index ($mXmlRsp, "name=\"\"");
	}
	# doDebugXML ("BLADELIST", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	my @aListBl = ();
	if ($mSuccess) {
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			if ($mConfig->{'outConfigs'}->{'computeBlade'}->{'dn'}) {
				# we have only a single blade in the chassis
				push (@aListBl, [$mBlDn, $mBlModel]);
			}
			else {
				# we have multiple blades in the chassis
				for $bl (sort keys %{$mConfig->{'outConfigs'}->{'computeBlade'}}) {
					$mBlDn = $mConfig->{'outConfigs'}->{'computeBlade'}->{$bl}->{'dn'};
					$mBlModel = $mConfig->{'outConfigs'}->{'computeBlade'}->{$bl}->{'model'};
					push (@aListBl, [$mBlDn, $mBlModel]);
				} 
			} 
		};
		$mSuccess = undef if ($@);
	}

	return ($mSuccess, @aListBl);
}

########################################################################

sub doGetChasBlade()
{
	my ($mUri, $mCookie, $mChassisNr, $mBladeNr) = @_;

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveDn';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'dn="sys/chassis-' . $mChassisNr . '/blade-' . $mBladeNr . '" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;
	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("BLADE", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			$mModel = $mConfig->{'outConfig'}->{'computeBlade'}->{'model'};
			if ($mModel eq "UCSB-EX-M4-1") {
				$mScale = $mConfig->{'outConfig'}->{'computeBlade'}->{'scaledMode'};
				if ($mScale eq "single") {
					$mModel = "UCSB-EX-M4-1C";
				}
				elsif ($mScale eq "scaled") {
					$mModel = "UCSB-EX-M4-1A";
				}
			}
		};
		$mSuccess = undef if ($@);
	}

	return ($mModel, $mSuccess);
}

########################################################################

sub doGetChasBladeDetails()
{
	my ($mUri, $mCookie, $mChassisNr, $mBladeNr) = @_;

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveDn';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'dn="sys/chassis-' . $mChassisNr . '/blade-' . $mBladeNr . '" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;
	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("CHASBLADEDETAILS", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	$mAssoc = undef;
	$mPower = undef;
	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			$mModel = $mConfig->{'outConfig'}->{'computeBlade'}->{'model'};
			$mMemory = $mConfig->{'outConfig'}->{'computeBlade'}->{'availableMemory'};
			$mAssoc = $mConfig->{'outConfig'}->{'computeBlade'}->{'association'};
			$mPower = $mConfig->{'outConfig'}->{'computeBlade'}->{'operPower'};
			$mProfile = $mConfig->{'outConfig'}->{'computeBlade'}->{'assignedToDn'};
		};
		$mSuccess = undef if ($@);
	}

	my $mCpu = doGetChasBladeCpu($mUri, $mCookie, $mChassisNr, $mBladeNr);

	return ($mModel, $mCpu, $mMemory, $mAssoc, $mPower, $mProfile, $mSuccess);
}

########################################################################

sub doGetChasBladeCpu()
{
	my ($mUri, $mCookie, $mChassisNr, $mBladeNr) = @_;

	my $mXmlReq = '<configResolveChildren'
							. ' cookie="' . $mCookie . '"'
							. ' inHierarchical="false"'
							. ' classId="processorUnit"'
							. ' inDn="sys/chassis-' . $mChassisNr . '/blade-' . $mBladeNr . '/board">'
							. '<inFilter></inFilter>'
							. '</configResolveChildren>';

	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("CPU", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			$mCpu = $mConfig->{'outConfigs'}->{'processorUnit'}->{'1'}->{'model'};
		};
		$mSuccess = undef if ($@);
	}

	return ($mCpu);
}

########################################################################

sub doGetFexList()
{
	my ($mUri, $mCookie) = @_;

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveClass';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'classId="equipmentFex" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;

	my $fx;
	my $mFxDn;
	my $mFxModel;

	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("FEXLIST", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	my @aListFx = ();
	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			if ($mConfig->{'outConfigs'}->{'equipmentFex'}->{'dn'}) {
				# we have only a single fex
				$mFxDn = $mConfig->{'outConfigs'}->{'equipmentFex'}->{'dn'};
				$mFxModel = $mConfig->{'outConfigs'}->{'equipmentFex'}->{'model'};
				push (@aListFx, [$mFxDn, $mFxModel]);
			}
			else {
				# we have multiple fex
				for $fx (sort keys %{$mConfig->{'outConfigs'}->{'equipmentFex'}}) {
				$mFxDn = $mConfig->{'outConfigs'}->{'equipmentFex'}->{$fx}->{'dn'};
				$mFxModel = $mConfig->{'outConfigs'}->{'equipmentFex'}->{$fx}->{'model'};
				push (@aListFx, [$mFxDn, $mFxModel]);
				}
			}
		};
		$mSuccess = undef if ($@);
	}

	return ($mSuccess, @aListFx);
}

########################################################################

sub doGetFabExt()
{
	my ($mUri, $mCookie, $mFabExtNr) = @_;

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveDn';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'dn="sys/fex-' . $mFabExtNr . '" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;
	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("FABEXT", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	my $mModel = undef;
	if ($mSuccess)
	{
		eval {
		my $mParser = XML::Simple->new();
		my $mConfig = $mParser->XMLin($mXmlRsp);
		$mModel = $mConfig->{'outConfig'}->{'equipmentFex'}->{'model'};
		};
	}

	return ($mModel);
}

########################################################################

sub doGetServerList()
{
	my ($mUri, $mCookie) = @_;

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveClass';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'classId="computeRackUnit" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;

	my $sv;
	my $mSvDn;
	my $mSvModel;

	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("SERVERLIST", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	$p = index ($mXmlRsp, "name=\"\"");
	while ($p > 0) {
	# $mXmlRsp = substr($mXmlRsp, 0, $p) . substr($mXmlRsp, ($p + 8));
		$mXmlRsp = substr($mXmlRsp, 0, $p) . 'name="' . $p . '" ' . substr($mXmlRsp, ($p + 8));
		$p = index ($mXmlRsp, "name=\"\"");
	}
	# doDebugXML ("SERVERLIST", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	my @aListSv = ();
	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			if ($mConfig->{'outConfigs'}->{'computeRackUnit'}->{'dn'}) {
				# we have only a single server
				$mSvDn = $mConfig->{'outConfigs'}->{'computeRackUnit'}->{'dn'};
				$mSvModel = $mConfig->{'outConfigs'}->{'computeRackUnit'}->{'model'};
				push (@aListSv, [$mSvDn, $mSvModel]);
			}
			else {
				# we have multiple servers
				for $sv (sort keys %{$mConfig->{'outConfigs'}->{'computeRackUnit'}}) {
					$mSvDn = $mConfig->{'outConfigs'}->{'computeRackUnit'}->{$sv}->{'dn'};
					$mSvModel = $mConfig->{'outConfigs'}->{'computeRackUnit'}->{$sv}->{'model'};
					push (@aListSv, [$mSvDn, $mSvModel]);
				}
			}
		};
		$mSuccess = undef if ($@);
	}

	return ($mSuccess, @aListSv);
}

########################################################################

sub doGetServer()
{
	my ($mUri, $mCookie, $mServerNr) = @_;

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveDn';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'dn="sys/rack-unit-' . $mServerNr . '" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;
	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("SERVER", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	my $mModel = undef;
	if ($mSuccess)
	{
		eval {
		my $mParser = XML::Simple->new();
		my $mConfig = $mParser->XMLin($mXmlRsp);
		$mModel = $mConfig->{'outConfig'}->{'computeRackUnit'}->{'model'};
		};
	}

	return ($mModel);
}

########################################################################

sub doGetEnclosureList()
{
	my ($mUri, $mCookie) = @_;

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveClass';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'classId="equipmentRackEnclosure" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;

	my $en;
	my $mEnDn;
	my $mEnModel;

	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("ENCLOSURELIST", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	my @aListEn = ();
	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			if ($mConfig->{'outConfigs'}->{'equipmentRackEnclosure'}->{'dn'}) {
				# we have only a single enclosure
				$mEnDn = $mConfig->{'outConfigs'}->{'equipmentRackEnclosure'}->{'dn'};
				$mEnModel = $mConfig->{'outConfigs'}->{'equipmentRackEnclosure'}->{'model'};
				if (substr($mEnModel,0,4) eq "UCSC") {		
					push (@aListEn, [$mEnDn, $mEnModel]);
				}
			}
			else {
				# we have multiple enclosure
				for $en (sort keys %{$mConfig->{'outConfigs'}->{'equipmentRackEnclosure'}}) {
					$mEnDn = $mConfig->{'outConfigs'}->{'equipmentRackEnclosure'}->{$en}->{'dn'};
					$mEnModel = $mConfig->{'outConfigs'}->{'equipmentRackEnclosure'}->{$en}->{'model'};
					if (substr($mEnModel,0,4) eq "UCSC") {	
						push (@aListEn, [$mEnDn, $mEnModel]);
					}
				}
			}
		};
		$mSuccess = undef if ($@);
	}

	return ($mSuccess, @aListEn);
}

########################################################################

sub doGetEnclosure()
{
	my ($mUri, $mCookie, $mEnclosureNr) = @_;

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveDn';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'dn="sys/rack-enclosure-' . $mEnclosureNr . '" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;
	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("ENCLOSURE", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	my $mPresence = undef;
	if ($mSuccess)
	{
		eval {
		my $mParser = XML::Simple->new();
		my $mConfig = $mParser->XMLin($mXmlRsp);
		$mPresence = $mConfig->{'outConfig'}->{'equipmentRackEnclosure'}->{'model'};
		};
	}

	if ($mPresence ne '') {
		return 1;
	}
	return 0;
}

########################################################################

sub doGetStorageList()
{
	my ($mUri, $mCookie) = @_;

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveClass';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'classId="equipmentChassis" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;

	my $ch;
	my $mChDn;
	my $mChModel;

	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("STORAGELIST", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	my @aListCh = ();
	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			if ($mConfig->{'outConfigs'}->{'equipmentChassis'}->{'dn'}) {
				# we have only a single chassis
				$mChDn = $mConfig->{'outConfigs'}->{'equipmentChassis'}->{'dn'};
				$mChModel = $mConfig->{'outConfigs'}->{'equipmentChassis'}->{'model'};
				if (substr($mChModel,5,5) eq "C3X60") {
					push (@aListCh, [$mChDn, $mChModel]);
				}
			}
			else {
				# we have multiple chassis
				for $ch (sort keys %{$mConfig->{'outConfigs'}->{'equipmentChassis'}}) {
					$mChDn = $mConfig->{'outConfigs'}->{'equipmentChassis'}->{$ch}->{'dn'};
					$mChModel = $mConfig->{'outConfigs'}->{'equipmentChassis'}->{$ch}->{'model'};
					if (substr($mChModel,5,5) eq "C3X60") {
						push (@aListCh, [$mChDn, $mChModel]);
					}
				}
			}
		};
		$mSuccess = undef if ($@);
	}

	return ($mSuccess, @aListCh);
}

########################################################################

sub doGetStorage()
{
	my ($mUri, $mCookie, $mStorageNr) = @_;

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveDn';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'dn="sys/chassis-' . $mStorageNr . '" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;
	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("STORAGE", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	my $mPresence = undef;
	if ($mSuccess)
	{
		eval {
		my $mParser = XML::Simple->new();
		my $mConfig = $mParser->XMLin($mXmlRsp);
		$mPresence = $mConfig->{'outConfig'}->{'equipmentChassis'}->{'model'};
		};
	}

	if ($mPresence ne '') {
		return 1;
	}
	return 0;
}

########################################################################

sub doGetStorPSU()
{
	my ($mUri, $mCookie, $mChassisNr, $mPsuNr) = @_;

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveDn';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'dn="sys/chassis-' . $mChassisNr . '/psu-' . $mPsuNr . '" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;
	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("STORPSU", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	$mPresence = undef;
	$mPower = undef;
	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			$mPresence = $mConfig->{'outConfig'}->{'equipmentPsu'}->{'presence'};
			$mPower = $mConfig->{'outConfig'}->{'equipmentPsu'}->{'power'};
		};
		$mSuccess = undef if ($@);
	}

	return ($mPresence, $mPower);
}

########################################################################

sub doGetStorIOC()
{
	my ($mUri, $mCookie, $mChassisNr, $mIOcNr) = @_;

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveDn';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'dn="sys/chassis-' . $mChassisNr . '/slot-' . $mIOcNr . '" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;
	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("STORIOC", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	$mPresence = undef;
	$mPower = undef;
	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			$mModel = $mConfig->{'outConfig'}->{'equipmentIOCard'}->{'model'};
		};
		$mSuccess = undef if ($@);
	}

	return ($mModel, $mSuccess);
}

########################################################################

sub doGetProfileList()
{
	my ($mUri, $mCookie) = @_;

	my $Hier = 'false';
	my $mXmlMethod = 'configResolveClass';
	my $mXmlAttrib = 'inHierarchical="' . $Hier . '" '
								 . 'classId="lsServer" '
								 . 'cookie="' . $mCookie . '" ';
	my $mIsNested = 0;

	my $mSrvPr;
	my $mBlade;

	my $mXmlReq = prepareXmlQuery ($mXmlMethod, $mXmlAttrib, $mIsNested);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("PROFILELIST", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	my @aListSP = ();
	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
			if ($mConfig->{'outConfigs'}->{'lsServer'}->{'dn'}) {
				# we have only a single profile
				$mSrvPr = $mConfig->{'outConfigs'}->{'lsServer'}->{'dn'};
				$mBlade = $mConfig->{'outConfigs'}->{'lsServer'}->{'pnDn'};
				push (@aListSP, [$mSrvPr, $mBlade]);
			}
			else {
				# we have multiple profiles
				for $pr (sort keys %{$mConfig->{'outConfigs'}->{'lsServer'}}) {
					$mSrvPr = $mConfig->{'outConfigs'}->{'lsServer'}->{$pr}->{'dn'};
					$mBlade = $mConfig->{'outConfigs'}->{'lsServer'}->{$pr}->{'pnDn'};
					push (@aListSP, [$mSrvPr, $mBlade]);
				}
			}
		};
		$mSuccess = undef if ($@);
	}

	return ($mSuccess, @aListSP);
}

########################################################################

sub doSetAssoc()
{
	my ($mUri, $mChassisNr, $mBladeNr, $mSP, $mAction, $mCookie) = @_;

	if ($mAction eq 'diss') {
		$mAct = 'status="deleted"';
	} elsif ($mAction eq 'asso') {
		$mAct = 'pnDn="sys/chassis-' . $mChassisNr . '/blade-' . $mBladeNr . '"';
	} else {
		$mAct = '';
	}

	my $mXmlMethod = 'configConfMo';
	my $mXmlAttrib = '<lsServer '
								 . 'dn="' . $mSP . '">'
								 . '<lsBinding '
								 . 'rn="pn" '
								 . $mAct . '> '
								 . '</lsBinding>'
								 . '</lsServer>';
	my $mHier = 0;
	my $mXmlReq = prepareXmlWrite ($mXmlMethod, $mXmlAttrib, $mCookie, $mHier);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	if ($mAction eq 'asso') {
		# doDebugXML ("ASSOCIATE", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);
	} elsif ($mAction eq 'diss') {
		# doDebugXML ("DISASSOCIATE", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);
	}

	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
		};
		$mSuccess = undef if ($@);
	}

	return ($mSuccess);
}

########################################################################

sub doSetPower()
{
	my ($mUri, $mChassisNr, $mBladeNr, $mSP, $mAction, $mCookie) = @_;
	my $mAct = '';
	if ($mAction eq 'boot') {
		$mAct = 'admin-up';
	} elsif ($mAction eq 'down') {
		$mAct = 'soft-shut-down';
	}

	my $mXmlMethod = 'configConfMo';
	my $mXmlAttrib = '<lsPower '
								 . 'dn="' . $mSP . '/power" '
								 . 'state="' . $mAct . '">'
								 . '</lsPower>';
	my $mHier = 0;
	my $mXmlReq = prepareXmlWrite ($mXmlMethod, $mXmlAttrib, $mCookie, $mHier);
	my ($mXmlRsp, $mMessage, $mSuccess) = doPostXML($mUri, $mXmlReq);
	# doDebugXML ("POWER", $mXmlReq, $mXmlRsp, $mMessage, $mSuccess);

	if ($mSuccess)
	{
		eval {
			my $mParser = XML::Simple->new();
			my $mConfig = $mParser->XMLin($mXmlRsp);
		};
		$mSuccess = undef if ($@);
	}

	return ($mSuccess);
}

########################################################################

sub prepareXmlQuery()
{
	my ($mXmlMethod, $mXmlAttrib, $mIsNested) = @_;

	my $content = undef;
	if ($mIsNested) {
		$content = '<' . $mXmlMethod . ' '
						 . $mXmlAttrib . '>'
						 . '</' . $mXmlMethod . '>';
	}
	else {
		$content = '<' . $mXmlMethod . ' '
						 . $mXmlAttrib . '/>';
	}

	return $content;
}

########################################################################

sub prepareXmlWrite()
{
	my ($mXmlMethod, $mXmlAttrib, $mCookie, $Hier) = @_;
	
		my $content = undef;
		($Hier) ? $Hier = 'true' : $Hier = 'false';

		$content = '<configConfMo '
						 . 'inHierarchical="' . $Hier . '" '
						 . 'cookie="' . $mCookie . '"> '
						 . '<inConfig> '
						 . $mXmlAttrib
						 . '</inConfig> '
						 . '</configConfMo>';

	return $content;
}

########################################################################

sub doPostXML()
{
	my ($mUri, $mReq) = @_;

	# my $mHttp = LWP::UserAgent->new();
	my $lReq = HTTP::Request->new(POST => $mUri);
	$lReq->content_type("application/x-www-form-urlencoded");
	$lReq->content($mReq);

	my $lRsp = $mHttp->request($lReq);  

	return ($lRsp->content, $lRsp->status_line, $lRsp->is_success, $lRsp) if wantarray;
	return unless $lRsp->is_success;
	return $lRsp->content;
}

########################################################################

sub doDebugXML()
{
	my ($mTopic, $mReq, $mRsp, $mMsg, $mSuc) = @_;

	return;
}

########################################################################
