Forum Discussion

Photo_G_84660's avatar
Photo_G_84660
Icon for Nimbostratus rankNimbostratus
Mar 21, 2007

"Unable to cast object of type 'System.Object[]' to type 'iControl.LocalLBPoolMemberMemberSessionState[][]'."

Hi,

 

 

I'm trying to code a method to disable pool members in VB .NET (using the new iControl.dll, THANKS JOE!!!), and it appears (in the debugger) to properly present the [pool_names] string and session_states info [CommonIPPortDefinition] and [session_state] to the set_session_enabled_state method, but I'm getting this error:

 

 


System.InvalidCastException was unhandled
  Message="Unable to cast object of type 'System.Object[]' to type 'iControl.LocalLBPoolMemberMemberSessionState[][]'."

 

 

When the sub below gets to set_session_enabled_state(pool_names, session_states), the error above indicates that set_session_enabled_state will not accept an object for the "list of lists" that makes up the MemberSessionState[][] type.

 

However, if I try to force force it to an array i.e.."Dim session_states() As Array = {member_list(0)(index), (status)}", the array wont accept CommonIPPortDefinition (Unable to cast object of type 'iControl.CommonIPPortDefinition' to type 'System.Array'). So, it appears that I'm missing something about the MemberSessionState[][] type.

 

 

Any hints or suggestions would be greatly appreciated. Thanks in advance!

 

 


    Public Sub lbxNodes_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) _
    Handles lbxNodes.SelectedIndexChanged
        Dim sHostname As String = txt_hostname.Text
        Dim sUsername As String = txt_username.Text
        Dim sPassword As String = txt_password.Text
        Dim m_interfaces As iControl.Interfaces = New iControl.Interfaces
        m_interfaces.initialize(sHostname, sUsername, sPassword)
        Dim pool_names() As String = {"pool1"}
        Dim index As Integer = lbxNodes.SelectedIndex
        Dim checked As Boolean = lbxNodes.GetItemChecked(index)
        Dim member_list()
        member_list = m_interfaces.LocalLBPool.get_member(pool_names)
        Dim status(0) As iControl.CommonEnabledState
        If checked Then
            status(0) = iControl.CommonEnabledState.STATE_ENABLED
        Else
            status(0) = iControl.CommonEnabledState.STATE_DISABLED
        End If
        Dim session_states() = {member_list(0)(index), status}
        m_interfaces.LocalLBPoolMember.set_session_enabled_state(pool_names, session_states)
    End Sub

 

 

Scott H.

10 Replies

  • Ok, I see now that I was not instantiating the session_states object correctly. Now, however, the set_session_enabled_state method has session_states underlined with squigglies, and it says:

    "Value of type 'iControl.LocalLBPoolMemberMemberSessionState' cannot be converted to '1-dimensional array of 1-dimensional array of iControl.LocalLBPoolMemberMemberSessionState'."

    
    Dim session_states As New iControl.LocalLBPoolMemberMemberSessionState
    session_states.member = (member_list(0)(index))
    session_states.session_state = status
    m_interfaces.LocalLBPoolMember.set_session_enabled_state(pool_names, session_states)

    Is this error ocurring because MemberSessionState[][] is an array of lists? If so, how do I get session_states into set_session_enabled_state(pool_names, session_states)?

    Thanks again,

    Scott H.
  • You are a life saver Joe! Thanks a million! It felt really good to see this method work correctly.

     

     

    Your opinion is solid gold. I'm going to start spinning up on C.

     

     

    Take care,

     

    Scott H.
  • Can I get a powershell port of this?

     

     

    I am able to declare this:

     

    $IP = New-Object -TypeName iControl.CommonIPPortDefinition

     

    $IP.address = "1.1.1.1"

     

    $IP.port = 9090

     

     

    But when I try to pull stats I get:

     

     

    PS E:\F5> $pmstat = $ic.locallbpoolmember.get_statistics("CRISA", $IP)

     

    Cannot convert argument "1", with value: "iControl.CommonIPPortDefinition", for "get_statistics" to type "iControl.Comm

     

    onIPPortDefinition[][]": "Cannot convert "iControl.CommonIPPortDefinition" to "iControl.CommonIPPortDefinition[][]"."

     

    At line:1 char:47

     

    + $pmstat = $ic.locallbpoolmember.get_statistics( <<<< "CRISA", $IP)

     

     

    How do I get it of type iControl.CommonIPPortDefinition[][] ?
  • There are a couple of issues with your code. First, you are passing a scalar string as the pool name ("CRISA"). That needs to be an array. Also, you are passing a scalar for the IPPortDefinition structure parameter, which needs to be a 2-D array.

     

     

    This should work for you:

     

     

    $IP = New-Object -TypeName iControl.CommonIPPortDefinition
    $IP.address = "1.1.1.1"
    $IP.port = 9090
     Create single 1-d array with IPPortDefinition
    [iControl.CommonIPPortDefinition[]] $ipdefs = @($IP);
     first parameter is a 1-d array with the pool names
     second parameter is a 2-d array (array of arrays) with members
     for each pool in the first dimension of the array.
    $pmstat = $ic.LocalLBPoolMember(
      (,"CRISA"),
      (,$ipdefs)
    );

     

     

    The way I've been told to coerce a value into an array is to surround it by parenthesis and then delimit the values with commas. For only a single value, prefix the first value with the comma as I've done above.

     

     

    Let me know if this works for you...

     

     

    -Joe
  • Scratching my head here...

     

     

    I'm trying to assemble an array of LocalLBPoolMemberMemberSessionState[][] and compiling it together with an array of pools to modify pool member state.

     

     

    Right now my code is bombing out when I trying to create this:

     

     

    sessionState[ i ][0].member = new iControl.CommonIPPortDefinition(); <--

     

     

    Will this work?

     

     

        
            
        public void ChangePoolMemberState(List members, f5Objects.MemberState state)    
                    {    
                        LocalLBPoolMemberMemberSessionState[][] sessionstate = GetPoolMemberSessionState(members, state);    
                        string[] pools = GetPoolsFromMembers(members);    
                        m_interfaces.LocalLBPoolMember.set_session_enabled_state(pools, sessionstate);    
                    }    
            
                    private string[] GetPoolsFromMembers(List members)    
                    {    
                        List pools = new List();    
                        foreach (f5Objects.PoolMember member in members)     
                        {    
                            if (!pools.Contains(member.Parent))    
                                pools.Add(member.Parent);    
                        }    
                        return pools.ToArray();    
                    }    
            
                    private LocalLBPoolMemberMemberSessionState[][] GetPoolMemberSessionState(List members, f5Objects.MemberState state)     
                    {    
                        LocalLBPoolMemberMemberSessionState[][] sessionState = new LocalLBPoolMemberMemberSessionState[members.Count][];    
                        for (int i = 0; i < members.Count; i++)     
                        {    
                            sessionState[ i ][0].member = new iControl.CommonIPPortDefinition();    
                            sessionState[ i ][0].member.address = members[ i ].IP;    
                            sessionState[ i ][0].member.port = members[ i ].Port;    
                            sessionState[ i ][0].session_state = (CommonEnabledState)state;    
                        }    
                        return sessionState;    
                    }    
        
  • This is a common question that I'll have to write a tech tip up for one day B-).

     

     

    For a 2-D array, you need to first allocate the size of the first dimension and then for each element in there, you need to allocate the second dimensions. In C it looks something like this (In this case I'm creating an a 2x5 array

     

     

     
     long len1 = 2; 
     long len2 = 5; 
      Allocate the 1st dimension array (each element will contain the 2nd dimension arrays). 
     sometype[][] someTypeAofA = new sometype[len1][0]; 
     for(int i=0; i { 
        Allocate the 2nd dimension array for each entry in the 1st dimension 
       sometypeAofA[ i ] = new sometype[len2]; 
       for(int j=0; j   { 
          Allocate the actual object for the array entry. 
         sometypeAofA[ i ][ j ] = new sometype(); 
         // Fill in values in sometype[ i ][ j ] 
       } 
     }

     

     

    Honestly, I'm a big confused on why you are returning a 2-d Array with a single input array. If you are trying to use this as input in one of the iControl methods, we use the first dimension for the main object and then the 2nd dimension for the subobjects (ie. for add pool members, the first dimension would be for each pool and the second dimension would be for all the members for each pool).

     

     

    [0][0] Pool 1, Member 1

     

    [0][1] Pool 1, Member 2

     

    [0][2] Pool 1, Member 3

     

    [1][0] Pool 2, Member 1

     

    [1][1] Pool 2, Member 2

     

    [1][2] Pool 2, Member 3

     

     

     

    If that's the case then you'll you are likely only working with a single pool and you want the first dimension to be of size one and the second dimension to be for each member. Something like this

     

     

    LocalLBPoolMemberMemberSessionState[][] sessionState = new LocalLBPoolMemberMemberSessionState[1][]; 
     sessionState[0] = new LocalLBPoolMemberMemberSessionState[members.Count]; 
     for (int i = 0; i < members.Count; i++) 
     { 
       sessionState[0][ i ] = new LocalLBPoolMemberMemberSessionState(); 
       sessionState[0][ i ].member =  new iControl.CommonIPPortDefinition(); 
       sessionState[0][ i ].member.address = members[ i ].IP; 
       sessionState[0][ i ].member.port = members[ i ].Port; 
       sessionState[0][ i ].session_state = (CommonEnabledState)state; 
     }

     

     

    Now, if you really want the first dimension to be for each member passed in and the second dimension to be of size one for that member, you could do it like this:

     

     

    LocalLBPoolMemberMemberSessionState[][] sessionState = new LocalLBPoolMemberMemberSessionState[members.Count][]; 
     for (int i = 0; i < Members.Count; i++) 
     { 
       sessionState[ i ] = new LocalLBPoolMemberMemberSessionState[1]; 
       sessionState[ i ][0] = new LocalLBPoolMemberMemberSessionState(); 
       sessionState[ i ][0].member =  new iControl.CommonIPPortDefinition(); 
       sessionState[ i ][0].member.address = members[ i ].IP; 
       sessionState[ i ][0].member.port = members[ i ].Port; 
       sessionState[ i ][0].session_state = (CommonEnabledState)state; 
     }

     

     

    Let me know if this answers your question or not. I hope at least some of that made sense B-). BTW, I haven't tested out any of this code so please accept my appologies for any typos.

     

     

    -Joe
  • Thanks Joe.

     

     

    Yeah, I did some more searching and found an example similar to the one you provided. I was obviously missing loading the array with some other required objects. More over, I now really understand how the pools array fits into the LocalLBPoolMember.set_session_enabled_state method. I've made the adjustments and the code is working great.

     

     

    Thanks again!

     

     

    --Beach
  • That's great! Glad I could help out. I know the iControl methods may seem cumbersome with all the arrays you have to deal with, but you'll see the power that it gives you when you are trying to manipulate 100's or even 1000's of objects at a time. If you had to make 1000 calls with a 1s connection overhead, that's 1000 seconds you have to wait just for the webservice call's initiation and teardown. If you are manipulating multiple objects, make sure to use the "bulk" features in the APIs.

     

     

    Oh, and if anything else comes up, please feel free to post again. It's refreshing to do some C once in a while B-)

     

     

    -Joe