Export Virtual Server Configuration in CSV - tmsh cli script
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,
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.
Update: 24th Oct 2023
Added logic to add hostname, Pool Status, Total-Connections & Current-Connections.
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
Old Codes:
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 }
Latest Code:
cli script virtual-details {
proc script::run {} {
set hostconf [tmsh::get_config /sys global-settings hostname]
set hostname [tmsh::get_field_value [lindex $hostconf 0] hostname]
puts "Hostname,Partition,Virtual Server,Destination,Pool-Name,Pool-Status,Pool-Members,Profiles,Rules,Persist,Status,State,Total-Conn,Current-Conn"
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 total_conn [tmsh::get_field_value $status "clientside.tot-conns"]
set curr_conn [tmsh::get_field_value $status "clientside.cur-conns"]
}
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" }{
foreach { p_status } [tmsh::get_status ltm pool $poolname] {
set pool_status [tmsh::get_field_value $p_status "status.availability-state"]
}
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 "$hostname,$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj "destination"],$poolname,$pool_status,$pool_member,$profilelist,[tmsh::get_field_value $obj "rules"],$persist,$vipstatus,$vipstate,$total_conn,$curr_conn"
} else {
set pool_member ""
set member_name [tmsh::get_field_value $poolinfo "members" ]
foreach member $member_name {
append pool_member "[lindex $member 1] "
}
puts "$hostname,$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj "destination"],$poolname,$pool_status,$pool_member,$profilelist,[tmsh::get_field_value $obj "rules"],$persist,$vipstatus,$vipstate,$total_conn,$curr_conn"
}
}
} else {
puts "$hostname,$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj "destination"],$poolname,none,none,$profilelist,[tmsh::get_field_value $obj "rules"],$persist,$vipstatus,$vipstate,$total_conn,$curr_conn"
}
}
}
}
}
Tested this on version:
13.0
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.
- IamGrootNimbostratus
Just wanted to say thanks for this script. Has been exactly what I needed.
Running 13.1.3.1 the only thing I needed to do different was when editing the script after creation, vi had:
modify script virtual-details {
}
I needed to leave that and paste the script starting from 'proc' inside the curlies - Also had to remove 'total-signing-status not-all-signed' for some reason (maybe unique to my set up).
Thanks jaikumar_f5 too for the addition of IPs, worked perfectly and I needed that too. Legends.
- Eli_Lama_SabachNimbostratus
- Sorry for the late reply, you can find it on /config/bigip_script.conf file.
- chenhaitao02Nimbostratus
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_KulshrestNimbostratus
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_24Nimbostratus
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.