CodeShare
Have some code. Share some code.
cancel
Showing results for 
Search instead for 
Did you mean: 

Problem this snippet solves:

This is a simple cli script used to collect all the virtuals name, its VIP details, Pool names, members, all Profiles, Irules, persistence associated to each, in all partitions. A sample output would be like below,


0151T000002dhuTQAQ.png



One can customize the code to extract other fields available too. The same logic can be allowed to pull information's from profiles stats, certificates etc.


Update: 5th Oct 2020


Added Pool members capture in the code. After the Pool-Name, Pool-Members column will be found.

If a pool does not have members - field not present: "members" will shown in the respective Pool-Members column.

If a pool itself is not bound to the VS, then Pool-Name, Pool-Members will have none in the respective columns.


Update: 21st Jan 2021


Added logic to look for multiple partitions & collect configs


Update: 12th Feb 2021


Added logic to add persistence to sheet.


Update: 26th May 2021


Added logic to add state & status to sheet.


Note: The codeshare has multiple version, use the latest version alone. The reason to keep the other versions is for end users to understand & compare, thus helping them to modify to their own requirements. Hope it helps.


How to use this snippet:

Login to the LTM, create your script by running the below commands and paste the code provided in snippet


tmsh create cli script virtual-details


So when you list it, it should look something like below,


[admin@labltm:Active:Standalone] ~ # tmsh list cli script virtual-details
cli script virtual-details {
proc script::run {} {
  puts "Virtual Server,Destination,Pool-Name,Profiles,Rules"
  foreach { obj } [tmsh::get_config ltm virtual all-properties] {
    set profiles [tmsh::get_field_value $obj "profiles"]
    set remprof [regsub -all {\n} [regsub -all "  context" [join $profiles "\n"] "context"] " "]
    set profilelist [regsub -all "profiles " $remprof ""]
    puts "[tmsh::get_name $obj],[tmsh::get_field_value $obj "destination"],[tmsh::get_field_value $obj "pool"],$profilelist,[tmsh::get_field_value $obj "rules"]"
  }
}
  total-signing-status not-all-signed
}
[admin@labltm:Active:Standalone] ~ #



And you can run the script like below,

tmsh run cli script virtual-details > /var/tmp/virtual-details.csv


And get the output from the saved file,

cat /var/tmp/virtual-details.csv


0151T000002dhuUQAQ.png

Code :

cli script virtual-details {
proc script::run {} {
    puts "Virtual Server,Destination,Pool-Name,Profiles,Rules"
    foreach { obj } [tmsh::get_config ltm virtual all-properties] {
        set profiles [tmsh::get_field_value $obj "profiles"]
        set remprof [regsub -all {\n} [regsub -all  "    context" [join $profiles "\n"] "context"] " "]
        set profilelist [regsub -all "profiles " $remprof ""]
        puts "[tmsh::get_name $obj],[tmsh::get_field_value $obj "destination"],[tmsh::get_field_value $obj "pool"],$profilelist,[tmsh::get_field_value $obj "rules"]"
    }
}
    total-signing-status not-all-signed
}

###===================================================
###2.0
###UPDATED CODE BELOW
### DO NOT MIX ABOVE CODE & BELOW CODE TOGETHER
###===================================================

cli script virtual-details {
proc script::run {} {
    puts "Virtual Server,Destination,Pool-Name,Pool-Members,Profiles,Rules"
    foreach { obj } [tmsh::get_config ltm virtual all-properties] {
        set poolname [tmsh::get_field_value $obj "pool"]
        set profiles [tmsh::get_field_value $obj "profiles"]
        set remprof [regsub -all {\n} [regsub -all  "    context" [join $profiles "\n"] "context"] " "]
        set profilelist [regsub -all "profiles " $remprof ""]
        if { $poolname != "none" }{
            set poolconfig [tmsh::get_config /ltm pool $poolname]
            foreach poolinfo $poolconfig {
                if { [catch { set member_name [tmsh::get_field_value $poolinfo "members" ]} err] } {
                    set pool_member $err
                    puts "[tmsh::get_name $obj],[tmsh::get_field_value $obj "destination"],$poolname,$pool_member,$profilelist,[tmsh::get_field_value $obj "rules"]"
                } else {
                    set pool_member ""
                    set member_name [tmsh::get_field_value $poolinfo "members" ]
                    foreach member $member_name {
                        append pool_member "[lindex $member 1] "
                    }
                    puts "[tmsh::get_name $obj],[tmsh::get_field_value $obj "destination"],$poolname,$pool_member,$profilelist,[tmsh::get_field_value $obj "rules"]"
                }
            }
        } else {
                    puts "[tmsh::get_name $obj],[tmsh::get_field_value $obj "destination"],$poolname,none,$profilelist,[tmsh::get_field_value $obj "rules"]"
                            }
    }
}
    total-signing-status not-all-signed
}


###===================================================
### Version 3.0
### UPDATED CODE BELOW FOR MULTIPLE PARTITION 
### DO NOT MIX ABOVE CODE & BELOW CODE TOGETHER
###===================================================
cli script virtual-details {
proc script::run {} {
    puts "Partition,Virtual Server,Destination,Pool-Name,Pool-Members,Profiles,Rules"
    foreach all_partitions [tmsh::get_config auth partition] {
        set partition "[lindex [split $all_partitions " "] 2]"
        tmsh::cd /$partition
        foreach { obj } [tmsh::get_config ltm virtual all-properties] {
            set poolname [tmsh::get_field_value $obj "pool"]
            set profiles [tmsh::get_field_value $obj "profiles"]
            set remprof [regsub -all {\n} [regsub -all  "    context" [join $profiles "\n"] "context"] " "]
            set profilelist [regsub -all "profiles " $remprof ""]
            if { $poolname != "none" }{
                set poolconfig [tmsh::get_config /ltm pool $poolname]
                foreach poolinfo $poolconfig {
                    if { [catch { set member_name [tmsh::get_field_value $poolinfo "members" ]} err] } {
                        set pool_member $err
                        puts "$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj "destination"],$poolname,$pool_member,$profilelist,[tmsh::get_field_value $obj "rules"]"
                    } else {
                        set pool_member ""
                        set member_name [tmsh::get_field_value $poolinfo "members" ]
                        foreach member $member_name {
                            append pool_member "[lindex $member 1] "
                        }
                        puts "$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj "destination"],$poolname,$pool_member,$profilelist,[tmsh::get_field_value $obj "rules"]"
                    }
                }
            } else {
                puts "$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj "destination"],$poolname,none,$profilelist,[tmsh::get_field_value $obj "rules"]"
            }
        }
    }
}
    total-signing-status not-all-signed
}

###===================================================
### Version 4.0
### UPDATED CODE BELOW FOR CAPTURING PERSISTENCE
### DO NOT MIX ABOVE CODE & BELOW CODE TOGETHER
###===================================================
cli script virtual-details {
proc script::run {} {
    puts "Partition,Virtual Server,Destination,Pool-Name,Pool-Members,Profiles,Rules,Persist"
    foreach all_partitions [tmsh::get_config auth partition] {
        set partition "[lindex [split $all_partitions " "] 2]"
        tmsh::cd /$partition
        foreach { obj } [tmsh::get_config ltm virtual all-properties] {
            set poolname [tmsh::get_field_value $obj "pool"]
            set profiles [tmsh::get_field_value $obj "profiles"]
            set remprof [regsub -all {\n} [regsub -all  "    context" [join $profiles "\n"] "context"] " "]
            set profilelist [regsub -all "profiles " $remprof ""]
			set persist [lindex [lindex [tmsh::get_field_value $obj "persist"] 0] 1]
			if { $poolname != "none" }{
                set poolconfig [tmsh::get_config /ltm pool $poolname]
                foreach poolinfo $poolconfig {
                    if { [catch { set member_name [tmsh::get_field_value $poolinfo "members" ]} err] } {
                        set pool_member $err
                        puts "$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj "destination"],$poolname,$pool_member,$profilelist,[tmsh::get_field_value $obj "rules"],$persist"
                    } else {
                        set pool_member ""
                        set member_name [tmsh::get_field_value $poolinfo "members" ]
                        foreach member $member_name {
                            append pool_member "[lindex $member 1] "
                        }
                        puts "$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj "destination"],$poolname,$pool_member,$profilelist,[tmsh::get_field_value $obj "rules"],$persist"
                    }
                }
            } else {
                puts "$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj "destination"],$poolname,none,$profilelist,[tmsh::get_field_value $obj "rules"],$persist"
            }
        }
    }
}
    total-signing-status not-all-signed
}

###===================================================
### 5.0
### UPDATED CODE BELOW
### DO NOT MIX ABOVE CODE & BELOW CODE TOGETHER
###===================================================
cli script virtual-details {
proc script::run {} {
puts "Partition,Virtual Server,Destination,Pool-Name,Pool-Members,Profiles,Rules,Persist,Status,State"
foreach all_partitions [tmsh::get_config auth partition] {
set partition "[lindex [split $all_partitions " "] 2]"
tmsh::cd /$partition
foreach { obj } [tmsh::get_config ltm virtual all-properties] {
foreach { status } [tmsh::get_status ltm virtual [tmsh::get_name $obj]] {
set vipstatus [tmsh::get_field_value $status "status.availability-state"]
set vipstate [tmsh::get_field_value $status "status.enabled-state"]
}
set poolname [tmsh::get_field_value $obj "pool"]
set profiles [tmsh::get_field_value $obj "profiles"]
set remprof [regsub -all {\n} [regsub -all  "    context" [join $profiles "\n"] "context"] " "]
set profilelist [regsub -all "profiles " $remprof ""]
set persist [lindex [lindex [tmsh::get_field_value $obj "persist"] 0] 1]
if { $poolname != "none" }{
set poolconfig [tmsh::get_config /ltm pool $poolname]
foreach poolinfo $poolconfig {
if { [catch { set member_name [tmsh::get_field_value $poolinfo "members" ]} err] } {
set pool_member $err
puts "$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj "destination"],$poolname,$pool_member,$profilelist,[tmsh::get_field_value $obj "rules"],$persist,$vipstatus,$vipstate"
} else {
set pool_member ""
set member_name [tmsh::get_field_value $poolinfo "members" ]
foreach member $member_name {
append pool_member "[lindex $member 1] "
}
puts "$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj "destination"],$poolname,$pool_member,$profilelist,[tmsh::get_field_value $obj "rules"],$persist,$vipstatus,$vipstate"
}
}
} else {
puts "$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj "destination"],$poolname,none,$profilelist,[tmsh::get_field_value $obj "rules"],$persist,$vipstatus,$vipstate"
}
}
}
}
total-signing-status not-all-signed
}

Tested this on version:

13.0
Comments
Eli_Lama_Sabach
Nimbostratus
Nimbostratus

Hi jaikumar_f5,

 

how to locate the cli script file ?

 

Thanks

  - Sorry for the late reply, you can find it on /config/bigip_script.conf file.

chenhaitao02
Nimbostratus
Nimbostratus

halo  jaikumar_f5

Have you update the Script​,can get pool member then export Configuration in CSV.

Sure  will put some time to work on that and update the script.​

 ,

 

The code is updated mate, please feel free to test and comment.

Ankit_Kulshrest
Nimbostratus
Nimbostratus

Hi jai,

 

Thanks for the script,

Can you please let me know how to run this for all partition ?

I am trying to run it but its only giving me output for Common partition.

 

Thanks in advance.

 

 

I have added the partition logic in the script. Please feel free to test it out.

Chaitanya_24
Nimbostratus
Nimbostratus

Hi  

Very informative and useful script. Thanks.

Is it possible to have a script as below,

New virtual server is created from cli with config similar to any existing virtual server and monitors, pools, pool members, one connect, persistence, http, server ssl, client SSL profiles, irule, data group , certs can be added to new virtual server as per requirement from cli.

Hi  ,

Glad it was helpful. Regards to your requirement, it can be done in couple of ways, to what comes to my mind now,

1. Iapp templates, you can still customize them & use.

2. Use the load sys config merge option, list the to be cloned configs ​to a file, edit the parameters wherever required using sed cmd, & simply load it.

3. Go with simple bash or python script, where you'd take inputs using the read cmd & process it & let the backend functions to build your commands automatically. It's all scripting.

​4. Using the rest API method & updating fields wherever required & just pushing it.

I use the 2nd & 3rd method when it's repetitive changes involving same pattern.​

Chaitanya_24
Nimbostratus
Nimbostratus

Hi  

Thanks for the logical explanation!

Regarding the export script when we create it gets added in config/*script.conf​

Is there any way we can remove it from .conf if we no longer need it?

Also can the above export script be converted to simple bash script. Could you let me know what changes would come in script for that.

Thanks Again!​

Hi  ,

 

If you just delete the script & save your configuration, it will get removed from script.conf file.

tmsh delete cli script <scrip-name>

Well converting the script to bash is doable, but i'd say running it against tmos would be resource consuming as there will be multiple commands.

Hence the CLI method is better. The alternate approach would be to use the bigip.conf file & then parse it.

 

Basic bash would something like below article.

https://devcentral.f5.com/s/articles/bash-script-to-find-clientssls-mapped-to-virtual-servers-1143

Chaitanya_24
Nimbostratus
Nimbostratus

​Hi  

Indeed thanks again for the explanation.

Will give it a try.

Ahmed_Zahran
Nimbostratus
Nimbostratus

I tried to make it

But it didont work at all

 

can you please provide more details step by step

 

also i have version 15 of TMOS

 

 

 

Apologies on the late reply, sorry the steps shared above didn't help you.

Here's the steps,

 

Login to the CLI

If you are in bash, get inside tmos by running tmsh command.

tmsh

Once your inside tmos, enter create cmd,

create cli script virtual-details

This should open the editor and there will be multiple default proc blocks like below,

 

0691T00000C1drZQAR.jpgDelete them all & add the one's i've shared in the code, use the code version 4.0 alone. All we need is proc script::run block code alone.

Using vi editor paste it.

 

save & exit.

 

Then when u run the below command. you should see the script.

tmsh list cli script virtual-details

Then using tmsh run command, you can run it.

tmsh run cli script virtual-details > /var/tmp/virtual-details.csv

Output will be in /var/tmp/

 

Please let me know if you want more details.

 

Arthur_P
Nimbostratus
Nimbostratus

i have problem trying to save the file with this error:

Syntax Error: "cli" unexpected argument

There were errors. Continue editing(y) or discard changes(n) (y/n) y

 

 

 

Its my bad, i know why this would had come. After you run the create cli script command, you would had deleted everything & pasted the code.

So it wouldn't had the call of create script virtual-details, so just pasting with code from cli would throw this error.

 

Follow this thread, this would help you understand how to create it.

Export GTM/DNS Configuration in CSV - tmsh cli script

 

If you are still seeing issues, please let me know, I'll put a video tutorial.

Apologies on the late reply. been caught up with the recent vulnerabilities 😕

Arthur_P
Nimbostratus
Nimbostratus

Is there a way this script can parse ASM policy with transparent/blocking mode association to the VIP and other objects?

 

 

Well yes it can be customized to achieve, but this is a ltm parser. So this would have to include block of parsing ASM 1st, & then doing a lookup to which VS that asm profile is mapped too. Let me see if i can make one quick.

Gerry_F5
Nimbostratus
Nimbostratus

hi ,

i need to get the ip address pool member instead of the name

im triying to change the variable but dosnt find the address

 

 

I think your pool members are added with fqdn name,

 

 

I just tested out this, here's how you can do, you can edit the pool_member section of code.

append pool_member "[lindex $member 1]([lindex [lindex $member 2] 1]) "

The result would be something like below,

test-pool-443,dev-app1-node1:443(1.1.1.1) dev-app1-node2:443(1.1.1.2)

Also i dont know why [lindex $member 2 1] is not working straight in F5 tcl. Which is why i had to use lindex inside lindex as above.

 

0691T00000CnbD8QAJ.jpg

Ali_Hyder
Nimbostratus
Nimbostratus

Is it possible to add data group, monitor associated with the VS to the csv

 

Yes its doable, but i dont have a lab box at the moment to explore, will test out soon & update you back.

zenyeti575
Nimbostratus
Nimbostratus

Fantastic info.  Thanks so much.  I used your 5.0 version because having the status and state fields is quite valuable.  I ran this on our lab box and works great - although it only has a few VIPs.  I'm running into errors though on a production box - it might be based on a particular DHCP-RELAY virtual that has a 255.255.255.255 address and the script seems to get stuck at that point:

virtual-details: script failed to complete:
can't eval proc: "script::run"
"DHCP-RELAY" is not accepted by the "show" command
while executing
"tmsh::get_status ltm virtual [tmsh::get_name $obj]"
(procedure "script::run" line 7)
invoked from within
"script::run" line:1
script did not successfully complete, status:1

It seems that I just need to get around this DDHCP-RELAY virtual.  Any ideas how to exclude that virtual in the script?  (or do I have larger issues?)

Thanks!

Version history
Last update:
‎02-May-2020 19:41
Updated by:
Contributors