Forum Discussion
iControl PoolMember stats returning a calculated negative value.
Hello, I have been working with the iControl for some time now in PowerShell and python. I have recently been working towards gathering statistics values through the iControl api. In testing the controls work well, but once i deploy into production I am seeing negative numbers being calculated. I was wondering if anyone has any thoughts to this. Below is the Posh code that relates to the Stats. I have tried with and without the Invoke-Inline function that I saw from some other examples.
function GetPoolStatisticsAll()
{
param($PoolName);
$value = $(Get-F5.iControl).LocalLBPool.get_all_member_statistics($PoolName)
return $value
} end of function GetPoolStatisticsAll
function Convert-To64Bit()
{
param($high, $low);
Other way to calculate value
return ($high*[Math]::Pow(2,32)) + $low;
return Invoke-Inline "result.Add((Convert.ToUInt64($high)<<32) | (Convert.ToUInt64($low)));"
} end of function Convert-To64Bit
https://devcentral.f5.com/wiki/iControl.PsRateBasedStatistics.ashx
function Invoke-Inline()
{
param(
[string[]] $code,
[object[]] $arguments,
[string[]] $reference = @()
)
Stores a cache of generated inline objects. If this library is dot-sourced
from a script, these objects go away when the script exits.
if(-not (Test-Path Variable:\inlineCode.Cache))
{
${GLOBAL:inlineCode.Cache} = @{}
}
$using = $null;
$source = $null;
if($code.length -eq 1) {
$source = $code[0]
} elseif($code.Length -eq 2){
$using = $code[0]
$source = $code[1]
} else {
Write-Error "You have to pass some code, or this won&39;t do anything ..."
}
un-nesting magic (why do I need this?)
$params = @()
foreach($arg in $arguments) { $params += $arg }
$arguments = $params
The main function to execute inline C.
Pass the argument to the function as a strongly-typed variable. They will
be available from C code as the Object variable, "arg".
Any values assigned to the "returnValue" object by the C code will be
returned to MSH as a return value.
See if the code has already been compiled and cached
$cachedObject = ${inlineCode.Cache}[$source]
Write-Verbose "Type: $($arguments[0].GetType())"
The code has not been compiled or cached
if($cachedObject -eq $null)
{
$codeToCompile =
@"
using System;
using System.Collections.Generic;
$using
public class InlineRunner
{
public List Invoke(Object[] args)
{
List result = new List();
$source
if( result.Count > 0 ) {
return result;
} else {
return null;
}
}
}
"@
Write-Verbose $codeToCompile
Obtains an ICodeCompiler from a CodeDomProvider class.
$provider = New-Object Microsoft.CSharp.CSharpCodeProvider
Get the location for System.Management.Automation DLL
$dllName = [PsObject].Assembly.Location
Configure the compiler parameters
$compilerParameters = New-Object System.CodeDom.Compiler.CompilerParameters
$assemblies = @("System.dll", $dllName)
$compilerParameters.ReferencedAssemblies.AddRange($assemblies)
$compilerParameters.ReferencedAssemblies.AddRange($reference)
$compilerParameters.IncludeDebugInformation = $true
$compilerParameters.GenerateInMemory = $true
Invokes compilation.
$compilerResults =
$provider.CompileAssemblyFromSource($compilerParameters, $codeToCompile)
Write any errors if generated.
if($compilerResults.Errors.Count -gt 0)
{
$errorLines = ""
foreach($error in $compilerResults.Errors)
{
$errorLines += "`n`t" + $error.Line + ":`t" + $error.ErrorText
}
Write-Error $errorLines
}
There were no errors. Store the resulting object in the object
cache.
else
{
${inlineCode.Cache}[$source] =
$compilerResults.CompiledAssembly.CreateInstance("InlineRunner")
}
$cachedObject = ${inlineCode.Cache}[$source]
}
Write-Verbose "Argument $arguments $cachedObject"
Finally invoke the C code
if($cachedObject -ne $null)
{
return $cachedObject.Invoke($arguments)
}
} end function Invoke-Inline
$val = Convert-To64Bit $foo.statistics[$StatTypeCount].value.high $foo.statistics[$StatTypeCount].value.low
6 Replies
- mhite_60883
Cirrocumulus
Hard to read your code since it's all bunched up and not formatted right, but here's what you need to know about decoding statistics.
Values are return with a high order 32-bit signed value and low order 32-bit signed value. You need to combine these and turn them into a 64-bit unsigned integer value.
In Python, it would look something like this:
def convert_to_64_bit(high, low): """ Converts two 32 bit signed integers to a 64-bit unsigned integer. """ if high < 0: high = high + (1 << 32) if low < 0: low = low + (1 << 32) value = long((high << 32) | low) assert(value >= 0) return valueHope this helps.
- mhite_60883
Cirrocumulus
It looks like it munged my code, too! Try this link: https://gist.github.com/mhite/cb01cc23a0fede93f335
- Jason_44516
Nimbostratus
I fixed the formatting as I too see that it was an epic failure on my part for the pasting.
This is the Posh function i was using then with the Invoke-Inline function call.
function Convert-To64Bit() { param($high, $low); return Invoke-Inline "result.Add((Convert.ToUInt64($high)<<32) | (Convert.ToUInt64($low)));" } end of function Convert-To64Bitfunction Invoke-Inline() https://devcentral.f5.com/wiki/iControl.PsRateBasedStatistics.ashx { param( [string[]] $code, [object[]] $arguments, [string[]] $reference = @() ) Stores a cache of generated inline objects. If this library is dot-sourced from a script, these objects go away when the script exits. if(-not (Test-Path Variable:\inlineCode.Cache)) { ${GLOBAL:inlineCode.Cache} = @{} } $using = $null; $source = $null; if($code.length -eq 1) { $source = $code[0] } elseif($code.Length -eq 2){ $using = $code[0] $source = $code[1] } else { Write-Error "You have to pass some code, or this won't do anything ..." } un-nesting magic (why do I need this?) $params = @() foreach($arg in $arguments) { $params += $arg } $arguments = $params The main function to execute inline C. Pass the argument to the function as a strongly-typed variable. They will be available from C code as the Object variable, "arg". Any values assigned to the "returnValue" object by the C code will be returned to MSH as a return value. See if the code has already been compiled and cached $cachedObject = ${inlineCode.Cache}[$source] Write-Verbose "Type: $($arguments[0].GetType())" The code has not been compiled or cached if($cachedObject -eq $null) { $codeToCompile = @" using System; using System.Collections.Generic; $using public class InlineRunner { public List Invoke(Object[] args) { List result = new List(); $source if( result.Count > 0 ) { return result; } else { return null; } } } "@ Write-Verbose $codeToCompile Obtains an ICodeCompiler from a CodeDomProvider class. $provider = New-Object Microsoft.CSharp.CSharpCodeProvider Get the location for System.Management.Automation DLL $dllName = [PsObject].Assembly.Location Configure the compiler parameters $compilerParameters = New-Object System.CodeDom.Compiler.CompilerParameters $assemblies = @("System.dll", $dllName) $compilerParameters.ReferencedAssemblies.AddRange($assemblies) $compilerParameters.ReferencedAssemblies.AddRange($reference) $compilerParameters.IncludeDebugInformation = $true $compilerParameters.GenerateInMemory = $true Invokes compilation. $compilerResults = $provider.CompileAssemblyFromSource($compilerParameters, $codeToCompile) Write any errors if generated. if($compilerResults.Errors.Count -gt 0) { $errorLines = "" foreach($error in $compilerResults.Errors) { $errorLines += "`n`t" + $error.Line + ":`t" + $error.ErrorText } Write-Error $errorLines } There were no errors. Store the resulting object in the object cache. else { ${inlineCode.Cache}[$source] = $compilerResults.CompiledAssembly.CreateInstance("InlineRunner") } $cachedObject = ${inlineCode.Cache}[$source] } Write-Verbose "Argument $arguments`n`n$cachedObject" Finally invoke the C code if($cachedObject -ne $null) { return $cachedObject.Invoke($arguments) } } end function Invoke-Inline- mhite_60883
Cirrocumulus
Maybe you could put it in a gist? The F5 web site still munges it for some reason.
- Jason_44516
Nimbostratus
Good call. I added the formatting tags but apparently they didnt take...
Here is the gist https://gist.github.com/anonymous/6531744
- mhite_60883
Cirrocumulus
Yeah, looks like you are using the same convert to 64-bit function Joe Pruitt has put in all his Powershell statistics example posted on devcentral. I am unfortunately no use advising you with Powershell, but technically the final product should be an unsigned integer. If you see a negative number, I would suspect either a problem with your 64-bit conversion (unlikely, given Joe posted it) or the 64-bit result is being interpreted/displayed as a signed value.
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com