function CreateIPMIUser($ipmiAddress, $ipmiAdminLogin, $ipmiAdminPassword, $ipmiNewUserLogin, $ipmiNewUserPassword, $ipmiNewUserPrivilege)
{
	Write-Host ($MSG_IPMI_USER_CREATING -f $ipmiNewUserLogin);

	$argumentList = ($IPMI_TOOL_CREATE_USER_ARGUMENTS  -f $ipmiAddress, $ipmiAdminLogin, $ipmiAdminPassword, $ipmiNewUserLogin, $ipmiNewUserPassword, $ipmiNewUserPrivilege);
    $process = start-process -FilePath $IPMI_TOOL_FULL_PATH -ArgumentList $argumentList -Wait -PassThru
	
	if($process.ExitCode -eq 0)
	{
	    Write-Host ($MSG_IPMI_USER_CREATED -f $ipmiNewUserLogin) -ForegroundColor Yellow;
	}
	else
	{
		throw ($MSG_IPMI_USER_CREATE_ERROR -f $ipmiNewUserLogin);
	}
}

function DeleteIPMIUser($ipmiAddress, $ipmiAdminLogin, $ipmiAdminPassword)
{
	Write-Host $MSG_IPMI_USER_DELETING;

	$argumentList = ($IPMI_TOOL_DELETE_USER_ARGUMENTS  -f $ipmiAddress, $ipmiAdminLogin, $ipmiAdminPassword);
    $process = start-process -FilePath $IPMI_TOOL_FULL_PATH -ArgumentList $argumentList -Wait -PassThru
	
	if($process.ExitCode -eq 0)
	{
	    Write-Host $MSG_IPMI_USER_DELETED -ForegroundColor Yellow;
	}
	else
	{
		throw $MSG_IPMI_USER_DELETE_ERROR;
	}
}

function ExecuteCommand([string]$computerName, [int]$port, [string]$login, [string]$password, [string]$command)
{
 	Write-Host ($MSG_IPMI_COMMUTATOR_CONNECTING -f $computerName, $port);
    try
    {
        $socket = New-Object Net.Sockets.TcpClient($computerName, $port);
    }
    catch [System.Exception]
    {
		$exception = New-Object System.Exception ($MSG_IPMI_COMMUTATOR_FAILED -f $computerName,$port);
		throw $exception;
    }
 
    Write-Host ($MSG_IPMI_COMMUTATOR_CONNECTED -f $computerName) -BackgroundColor Yellow;
 
    $stream = $socket.GetStream();

	$encoding = New-Object System.Text.ASCIIEncoding; 
    $writer = New-Object System.IO.StreamWriter $stream,$encoding;
	
	$response = ReadStream -stream $stream;
	SendRequest -stream $stream -writer $writer -message $IPMI_COMMUTATOR_INIT;
	SendRequest -stream $stream -writer $writer -message ($IPMI_COMMUTATOR_AUTH -f $login,$password);
	[xml]$response = ReadStream -stream $stream -computerName $computerName;

	[bool] $AuthSuccess = ParseAuthResponse -xml $response;
	if($AuthSuccess)
	{
		SendRequest -stream $stream -writer $writer -message $IPMI_COMMUTATOR_CREATE_PRIVATE_CONFIG;
		[xml]$response = ReadStream -stream $stream -computerName $computerName;
		
		[bool]$CreatingConfigSuccess = ParseCreatePrivateConfigResponse -xml $response;
		
		SendRequest -stream $stream -writer $writer -message $command;
		$response = ReadStream -stream $stream -computerName $computerName;
		$response.OuterXml;
		SendRequest -stream $stream -writer $writer -message $IPMI_COMMUTATOR_DISCARD_PRIVATE_CONFIG;
		$response = ReadStream -stream $stream -computerName $computerName;
		
		$reply = ParseCommitPrivateConfigResponse -xml $response;
	}
	else
	{
		ThrowException -message $MSG_IPMI_COMMUTATOR_AUTH_FAILED;
	}
	

	SendRequest -stream $stream -writer $writer -message $IPMI_COMMUTATOR_EXIT;
	
    ## Close the streams
    $writer.Close();
    $stream.Close();   
	return $response;
}

function SendRequest($stream, $writer, $message)
{
	if($stream.CanWrite)
	{
		$writer.WriteLine($message);
		$writer.Flush();
	}
	Sleep -Milliseconds 1000;
}
 	
function ReadStream ([System.Net.Sockets.NetworkStream]$stream, [string]$computerName)
{
    $buffer = New-Object System.Byte[] 1024;
    $enc = New-Object System.Text.ASCIIEncoding;

    Start-Sleep -m 1000;
    $output = "";
    while($stream.DataAvailable)
    {  
        $read = $stream.Read($buffer, 0, 1024);    
        $output += $enc.GetString($buffer, 0, $read);
        Start-Sleep -m 100;
    }
    Start-Sleep -m 1000;
	if([string]::IsNullOrEmpty($output)) 
	{
		ThrowException -message ($MSG_IPMI_COMMUTATOR_NO_REPLY -f $computerName);
	}
	
	return $output;
}

function ThrowException([string]$message)
{
	$exception = New-Object System.Exception ($message);
	throw $exception;
}

function ParseAuthResponse([xml]$xml)
{
	$result = $xml.SelectSingleNode($IPMI_COMMUTATOR_AUTH_RESPONSE_XPATH);
	return ($result.InnerText -eq "success");
}

function ParseCreatePrivateConfigResponse([xml]$xml)
{
	[System.Xml.XmlNamespaceManager]$nsmgr = New-Object System.Xml.XmlNamespaceManager ($xml.NameTable);
	$nsmgr.AddNamespace("xnm", "http://xml.juniper.net/xnm/1.1/xnm");
	$result = $xml.SelectSingleNode($IPMI_COMMUTATOR_CHECK_ERROR_XPATH, $nsmgr);
	if($result -eq $null)
	{
		return $true;
	}
	ThrowException $result.InnerText;
}

function ParseCommitPrivateConfigResponse([xml]$xml)
{
	$result = $xml.SelectNodes($IPMI_COMMUTATOR_COMMIT_RESPONSE_XPATH);
	$message = "";
	$commitlst = $result | ForEach-Object { 
		$message += ("{0} : {1}`n" -f $_.ChildNodes[0].InnerText, $_.ChildNodes[1].LocalName); 
		};
	return $message;	
}