├── .gitattributes ├── LICENSE ├── README.md ├── bash ├── esxi_ks_injector │ ├── KS-TEMPLATE.CFG │ ├── KS.CFG │ ├── esxi_customks_iso.sh │ └── esxi_ks_iso.sh └── vcd_get_kubeconfig.sh ├── perl ├── dvswitch-graphite.pl └── nsx-edge-graphite.pl ├── powershell ├── Check-HCL.ps1 ├── check-hcl-poc.ps1 ├── check-iohcl-poc.ps1 ├── check_esxi_65_support.ps1 ├── check_esxi_67_support.ps1 ├── check_esxi_70_support.ps1 ├── check_esxi_endOfSupport_from_json.ps1 ├── check_esxi_version_with_json.ps1 ├── esxi_on_rasperry_pi_functions.ps1 ├── get-cpuid.ps1 ├── io-devices-report.ps1 └── vcd_helper_functions.ps1 ├── python └── check_nsxt_backup.py └── vbs ├── add-vcenter-root-ca.vbs └── add-vcenter65-root-ca.vbs /.gitattributes: -------------------------------------------------------------------------------- 1 | *.psm1 text 2 | *.psd1 text 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 fgrehl 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # virten-scripts 2 | Scripts used at www.virten.net 3 | 4 | -------------------------------------------------------------------------------- /bash/esxi_ks_injector/KS-TEMPLATE.CFG: -------------------------------------------------------------------------------- 1 | vmaccepteula 2 | install --firstdisk --overwritevmfs --novmfsondisk 3 | 4 | network --bootproto=static --ip=KSIPADDRESS --netmask=KSNETMASK --gateway=KSGATEWAY --hostname=KSHOSTNAME --vlanid=KSVLAN --nameserver=KSNAMESERVER 5 | rootpw VMware1! 6 | keyboard German 7 | 8 | reboot 9 | 10 | %firstboot --interpreter=busybox 11 | 12 | # Enable SSH 13 | vim-cmd hostsvc/enable_ssh 14 | vim-cmd hostsvc/start_ssh 15 | 16 | # Enable ESXi Shell 17 | vim-cmd hostsvc/enable_esx_shell 18 | vim-cmd hostsvc/start_esx_shell 19 | 20 | # Suppress Shell warning 21 | esxcli system settings advanced set -o /UserVars/SuppressShellWarning -i 1 22 | 23 | # NTP 24 | esxcli system ntp set -s de.pool.ntp.org 25 | esxcli system ntp set -e 1 26 | -------------------------------------------------------------------------------- /bash/esxi_ks_injector/KS.CFG: -------------------------------------------------------------------------------- 1 | vmaccepteula 2 | install --firstdisk --overwritevmfs --novmfsondisk 3 | 4 | network --bootproto=static --ip=192.168.0.10 --netmask=255.255.255.0 --gateway=192.168.0.1 --hostname=esx1.virten.lab --nameserver=192.168.0.1 5 | rootpw VMware1! 6 | keyboard German 7 | 8 | reboot 9 | 10 | %firstboot --interpreter=busybox 11 | 12 | # Enable SSH 13 | vim-cmd hostsvc/enable_ssh 14 | vim-cmd hostsvc/start_ssh 15 | 16 | # Enable ESXi Shell 17 | vim-cmd hostsvc/enable_esx_shell 18 | vim-cmd hostsvc/start_esx_shell 19 | 20 | # Suppress Shell warning 21 | esxcli system settings advanced set -o /UserVars/SuppressShellWarning -i 1 22 | 23 | # NTP 24 | esxcli system ntp set -s de.pool.ntp.org 25 | esxcli system ntp set -e 1 26 | -------------------------------------------------------------------------------- /bash/esxi_ks_injector/esxi_customks_iso.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Add kickstart configuration to ESXi ISO for automated installation. 3 | # 4 | # Example: 5 | # ./esxi_customks_iso.sh -i VMware-VMvisor-Installer-7.0U2-17630552.x86_64.iso -k KS-TEMPLATE.CFG \ 6 | # -a 192.168.0.10 -m 255.255.255.0 -g 192.168.0.1 -n esx1.virten.lab -v 0 -d 192.168.0.1 7 | 8 | # Check if genisoimage is installed 9 | command -v genisoimage >/dev/null 2>&1 || { echo >&2 "This script requires genisoimage but it's not installed."; exit 1; } 10 | 11 | # Script must be started as root to allow iso mounting 12 | if [ "$EUID" -ne 0 ] ; then echo "Please run as root." ; exit 1 ; fi 13 | 14 | while [[ "$#" -gt 0 ]]; do 15 | case $1 in 16 | -i|--iso) BASEISO="$2"; shift ;; 17 | -k|--ks) KS="$2"; shift ;; 18 | -w|--working-dir) WORKINGDIR="$2"; shift ;; 19 | -a|--ip-address) KSIPADDRESS="$2"; shift ;; 20 | -m|--netmask) KSNETMASK="$2"; shift ;; 21 | -g|--gateway) KSGATEWAY="$2"; shift ;; 22 | -n|--hostname) KSHOSTNAME="$2"; shift ;; 23 | -v|--vlan) KSVLAN="$2"; shift ;; 24 | -d|--dns) KSNAMESERVER="$2"; shift ;; 25 | *) echo "Unknown parameter: $1"; exit 1 ;; 26 | esac 27 | shift 28 | done 29 | 30 | if [[ -z $BASEISO || -z $KS || -z $KSIPADDRESS || -z $KSNETMASK || -z $KSGATEWAY || -z $KSHOSTNAME || -z $KSVLAN || -z $KSNAMESERVER ]]; then 31 | echo 'Usage: esxi_customks_iso.sh -i VMware-VMvisor-Installer-7.0U2-17630552.x86_64.iso -k KS-TEMPLATE.CFG \' 32 | echo ' -a 192.168.0.10 -m 255.255.255.0 -g 192.168.0.1 -n esx1.virten.lab -v 0 -d 192.168.0.1' 33 | echo 'Options:' 34 | echo " -i, --iso Base ISO File" 35 | echo ' -k, --ks Kickstart Configuration File' 36 | echo ' -w, --working-dir Working directory (Optional)' 37 | echo ' -a, --ip-address ESXi IP Address' 38 | echo ' -m, --netmask ESXi Subnet Mask ' 39 | echo ' -g, --gateway ESXi Gateway' 40 | echo ' -n, --hostname ESXi Hostname' 41 | echo ' -v, --vlan ESXi VLAN ID (0 for None) ' 42 | echo ' -d, --dns ESXi DNS Server' 43 | exit 1 44 | fi 45 | 46 | if [[ -z $WORKINGDIR ]]; then 47 | WORKINGDIR="/dev/shm/esxibuilder" 48 | fi 49 | 50 | printf "=== Base ISO: %s ===\n" "$BASEISO" 51 | printf "=== ESXi KS Configuration ===\n" 52 | printf "IP Address: %s\n" "$KSIPADDRESS" 53 | printf "Netmask: %s\n" "$KSNETMASK" 54 | printf "Gateway: %s\n" "$KSGATEWAY" 55 | printf "Hostname: %s\n" "$KSHOSTNAME" 56 | printf "VLAN: %s\n" "$KSVLAN" 57 | 58 | 59 | mkdir -p ${WORKINGDIR}/iso 60 | mount -t iso9660 -o loop,ro ${BASEISO} ${WORKINGDIR}/iso 61 | 62 | mkdir -p ${WORKINGDIR}/isobuild 63 | cp ${KS} ${WORKINGDIR}/isobuild/KS.CFG 64 | cd ${WORKINGDIR}/iso 65 | tar cf - . | (cd ${WORKINGDIR}/isobuild; tar xfp -) 66 | 67 | chmod +w ${WORKINGDIR}/isobuild/boot.cfg 68 | chmod +w ${WORKINGDIR}/isobuild/efi/boot/boot.cfg 69 | sed -i -e 's/cdromBoot/ks=cdrom:\/KS.CFG/g' ${WORKINGDIR}/isobuild/boot.cfg 70 | sed -i -e 's/cdromBoot/ks=cdrom:\/KS.CFG/g' ${WORKINGDIR}/isobuild/efi/boot/boot.cfg 71 | sed -i -e 's/KSIPADDRESS/'"$KSIPADDRESS"'/g' ${WORKINGDIR}/isobuild/KS.CFG 72 | sed -i -e 's/KSNETMASK/'"$KSNETMASK"'/g' ${WORKINGDIR}/isobuild/KS.CFG 73 | sed -i -e 's/KSGATEWAY/'"$KSGATEWAY"'/g' ${WORKINGDIR}/isobuild/KS.CFG 74 | sed -i -e 's/KSHOSTNAME/'"$KSHOSTNAME"'/g' ${WORKINGDIR}/isobuild/KS.CFG 75 | sed -i -e 's/KSVLAN/'"$KSVLAN"'/g' ${WORKINGDIR}/isobuild/KS.CFG 76 | sed -i -e 's/KSNAMESERVER/'"$KSNAMESERVER"'/g' ${WORKINGDIR}/isobuild/KS.CFG 77 | 78 | cd ${WORKINGDIR} 79 | genisoimage -relaxed-filenames -J -R -o ${KSHOSTNAME}.iso -b isolinux.bin -c boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -eltorito-boot efiboot.img -quiet -no-emul-boot ${WORKINGDIR}/isobuild 2>/dev/null 80 | echo "ISO saved at ${WORKINGDIR}/${KSHOSTNAME}.iso" 81 | 82 | umount ${WORKINGDIR}/iso 83 | rm -rf ${WORKINGDIR}/iso 84 | rm -rf ${WORKINGDIR}/isobuild 85 | -------------------------------------------------------------------------------- /bash/esxi_ks_injector/esxi_ks_iso.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Add kickstart configuration to ESXi ISO for automated installation. 3 | # 4 | # Example: 5 | # ./esxi_ks_iso.sh -i VMware-VMvisor-Installer-7.0U2-17630552.x86_64.iso -k KS.CFG 6 | 7 | # Check if genisoimage is installed 8 | command -v genisoimage >/dev/null 2>&1 || { echo >&2 "This script requires genisoimage but it's not installed."; exit 1; } 9 | 10 | # Script must be started as root to allow iso mounting 11 | if [ "$EUID" -ne 0 ] ; then echo "Please run as root." ; exit 1 ; fi 12 | 13 | while [[ "$#" -gt 0 ]]; do 14 | case $1 in 15 | -i|--iso) BASEISO="$2"; shift ;; 16 | -k|--ks) KS="$2"; shift ;; 17 | -w|--working-dir) WORKINGDIR="$2"; shift ;; 18 | *) echo "Unknown parameter: $1"; exit 1 ;; 19 | esac 20 | shift 21 | done 22 | 23 | if [[ -z $BASEISO || -z $KS ]]; then 24 | echo 'Usage: esxi_ks_iso.sh -i VMware-VMvisor-Installer-7.0U2-17630552.x86_64.iso -k KS.CFG' 25 | echo 'Options:' 26 | echo " -i, --iso Base ISO File" 27 | echo ' -k, --ks Kickstart Configuration File' 28 | echo ' -w, --working-dir Working directory (Optional)' 29 | exit 1 30 | fi 31 | 32 | if [[ -z $WORKINGDIR ]]; then 33 | WORKINGDIR="/dev/shm/esxibuilder" 34 | fi 35 | 36 | mkdir -p ${WORKINGDIR}/iso 37 | mount -t iso9660 -o loop,ro ${BASEISO} ${WORKINGDIR}/iso 38 | 39 | mkdir -p ${WORKINGDIR}/isobuild 40 | cp ${KS} ${WORKINGDIR}/isobuild/KS.CFG 41 | cd ${WORKINGDIR}/iso 42 | tar cf - . | (cd ${WORKINGDIR}/isobuild; tar xfp -) 43 | 44 | chmod +w ${WORKINGDIR}/isobuild/boot.cfg 45 | chmod +w ${WORKINGDIR}/isobuild/efi/boot/boot.cfg 46 | sed -i -e 's/cdromBoot/ks=cdrom:\/KS.CFG/g' ${WORKINGDIR}/isobuild/boot.cfg 47 | sed -i -e 's/cdromBoot/ks=cdrom:\/KS.CFG/g' ${WORKINGDIR}/isobuild/efi/boot/boot.cfg 48 | 49 | cd ${WORKINGDIR} 50 | genisoimage -relaxed-filenames -J -R -o esxi-ks.iso -b isolinux.bin -c boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -eltorito-boot efiboot.img -quiet --no-emul-boot ${WORKINGDIR}/isobuild 2>/dev/null 51 | echo "ISO saved at ${WORKINGDIR}/esxi-ks.iso" 52 | 53 | umount ${WORKINGDIR}/iso 54 | rm -rf ${WORKINGDIR}/iso 55 | rm -rf ${WORKINGDIR}/isobuild 56 | -------------------------------------------------------------------------------- /bash/vcd_get_kubeconfig.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get kubeconfig from VMware Cloud Director 10.3 with Container Service Extension 4 | # Usage: vcd_get_kubeconfig.sh --user USER@ORG --password PASSWORD -vcd VCDURL --cluster CLUSTERNAME 5 | 6 | while [[ "$#" -gt 0 ]]; do 7 | case $1 in 8 | -u|--user) USER="$2"; shift ;; 9 | -p|--password) PASSWORD="$2"; shift ;; 10 | -v|--vcd) VCD="$2"; shift ;; 11 | -c|--cluster) CLUSTER="$2"; shift ;; 12 | *) echo "Unknown parameter: $1"; exit 1 ;; 13 | esac 14 | shift 15 | done 16 | 17 | if [[ -z $USER || -z $PASSWORD || -z $CLUSTER || -z $VCD ]]; then 18 | echo 'Missing parameter. Try:' 19 | echo 'vcd_get_kubeconfig.sh -u USER@ORG -p PASSWORD -v VCDURL -c CLUSTERNAME' 20 | echo 'vcd_get_kubeconfig.sh --user USER@ORG --password PASSWORD -vcd VCDURL --cluster CLUSTERNAME' 21 | exit 1 22 | fi 23 | 24 | ACCEPT="Accept: */*;version=36.0" 25 | CRED=$(echo -n $USER:$PASSWORD |base64) 26 | TOKEN=$(curl -sI -k --header "$ACCEPT" --header "Authorization: Basic $CRED" --request POST https://$VCD/api/sessions | tr -d '\r' | sed -En 's/^x-vcloud-authorization: (.*)/\1/p') 27 | CLUSTERID=$(curl -s -k --header "$ACCEPT" --header "x-vcloud-authorization: $TOKEN" --request GET https://$VCD/api/cse/3.0/cluster | jq '.[] | select(.name=="'$CLUSTER'")' | jq -r '.id') 28 | curl -s -k --header "$ACCEPT" --header "x-vcloud-authorization: $TOKEN" --request GET https://$VCD/api/cse/3.0/cluster/$CLUSTERID/config | jq -r '.message' 29 | -------------------------------------------------------------------------------- /perl/dvswitch-graphite.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # Author: Florian Grehl - www.virten.net 3 | # Reference: http://www.virten.net/2016/05/send-dvswitch-port-statistics-to-graphite/ 4 | # Description: 5 | # Sends VMware Distributed Switch Port statistics to a Carbon Cache Relay to 6 | # create graphs with Graphite. Target can be a vCenter Server or ESXi Host. 7 | # Running this script against a vCenter requires triggering "Refresh dvPort state" 8 | # 9 | 10 | use strict; 11 | use warnings; 12 | use VMware::VIRuntime; 13 | use VMware::VILib; 14 | use IO::Socket::INET; 15 | use Data::Dumper; 16 | 17 | my $vcServer = 'vcenter.virten.lab'; 18 | my $vcUser = 'admin'; 19 | my $vcPass = 'password'; 20 | my $carbonServer = 'graphite.virten.lab'; 21 | my $carbonPort = 2003; 22 | my $debug = 0; 23 | 24 | my $time = time(); 25 | 26 | # Connect to vCenter Server 27 | Opts::set_option('server', $vcServer); 28 | Opts::set_option('username', $vcUser); 29 | Opts::set_option('password', $vcPass); 30 | Opts::parse(); 31 | Opts::validate(); 32 | print "Connecting to " . $vcServer . "...\n" if $debug; 33 | Util::connect(); 34 | my $sc = Vim::get_service_content(); 35 | my $vCenterVersion = $sc->about->version; 36 | print "Connected to " . $vcServer . " (" . $sc->about->fullName . ")\n" if $debug; 37 | 38 | # Connect to Carbon Cache Relay 39 | my $sock = new IO::Socket::INET( PeerAddr => $carbonServer, PeerPort => $carbonPort, Proto => 'tcp') unless $debug; 40 | $sock or die "no socket: $!" unless $debug; 41 | 42 | my $dvSwitches = Vim::find_entity_views(view_type => 'DistributedVirtualSwitch'); 43 | foreach my $dvs (@$dvSwitches){ 44 | print "Processing dvSwitch: ".$dvs->name."...\n" if $debug; 45 | 46 | # Refresh Portstate - Required when pulling statistics from vCenter Server 47 | if ($sc->about->apiType eq 'VirtualCenter'){ 48 | print "Refreshing port states...\n" if $debug; 49 | my $dportState = $dvs->RefreshDVPortState; 50 | } 51 | 52 | my $dvsName = $dvs->name; 53 | $dvsName =~ tr/[. ]/_/; 54 | my $prefix = "vcenter.network." . $dvsName . "."; 55 | my $dvsCriteria = DistributedVirtualSwitchPortCriteria->new(connected => 'true'); 56 | my $dvPorts = $dvs->FetchDVPorts(criteria => $dvsCriteria); 57 | 58 | foreach my $dvport (@$dvPorts) { 59 | eval{ 60 | my $connectee; 61 | if ($dvport->connectee->connectedEntity->type eq 'HostSystem'){ 62 | my $connectedEntity = Vim::get_view(mo_ref => $dvport->connectee->connectedEntity); 63 | $connectee = $connectedEntity->name."_".$dvport->connectee->nicKey; 64 | } else { 65 | $connectee = $dvport->state->runtimeInfo->linkPeer; 66 | } 67 | 68 | if ($connectee){ 69 | $connectee =~ tr/[. ]/_/; 70 | sendMetric($prefix.$connectee.".bytesInBroadcast ".$dvport->state->stats->bytesInBroadcast); 71 | sendMetric($prefix.$connectee.".bytesInMulticast ".$dvport->state->stats->bytesInMulticast); 72 | sendMetric($prefix.$connectee.".bytesInUnicast ".$dvport->state->stats->bytesInUnicast); 73 | sendMetric($prefix.$connectee.".bytesOutBroadcast ".$dvport->state->stats->bytesOutBroadcast); 74 | sendMetric($prefix.$connectee.".bytesOutMulticast ".$dvport->state->stats->bytesOutMulticast); 75 | sendMetric($prefix.$connectee.".bytesOutUnicast ".$dvport->state->stats->bytesOutUnicast); 76 | sendMetric($prefix.$connectee.".packetsInBroadcast ".$dvport->state->stats->packetsInBroadcast); 77 | sendMetric($prefix.$connectee.".packetsInDropped ".$dvport->state->stats->packetsInDropped); 78 | sendMetric($prefix.$connectee.".packetsInException ".$dvport->state->stats->packetsInException); 79 | sendMetric($prefix.$connectee.".packetsInMulticast ".$dvport->state->stats->packetsInMulticast); 80 | sendMetric($prefix.$connectee.".packetsInUnicast ".$dvport->state->stats->packetsInUnicast); 81 | sendMetric($prefix.$connectee.".packetsOutBroadcast ".$dvport->state->stats->packetsOutBroadcast); 82 | sendMetric($prefix.$connectee.".packetsOutDropped ".$dvport->state->stats->packetsOutDropped); 83 | sendMetric($prefix.$connectee.".packetsOutException ".$dvport->state->stats->packetsOutException); 84 | sendMetric($prefix.$connectee.".packetsOutMulticast ".$dvport->state->stats->packetsOutMulticast); 85 | sendMetric($prefix.$connectee.".packetsOutUnicast ".$dvport->state->stats->packetsOutUnicast); 86 | } 87 | } 88 | } 89 | } 90 | 91 | Util::disconnect(); 92 | 93 | # Functions 94 | sub sendMetric { 95 | my $metric = $_[0]; 96 | print $metric." ".$time."\n" if $debug; 97 | $sock->send($metric." ".$time."\n") unless $debug; 98 | } 99 | -------------------------------------------------------------------------------- /perl/nsx-edge-graphite.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # Author: Florian Grehl - www.virten.net 3 | # Reference: http://www.virten.net/2016/05/send-nsx-edge-gateway-statistics-to-graphite/ 4 | # Description: 5 | # Gathers NSX Edge Gateway statistics from the REST API and sends them to a 6 | # Carbon Cache Relay to create graphs with Graphite. 7 | # 8 | 9 | use strict; 10 | use REST::Client; 11 | use MIME::Base64; 12 | use XML::LibXML; 13 | use IO::Socket::INET; 14 | use Data::Dumper; 15 | 16 | # Disable SSL server verification 17 | $ENV{'PERL_LWP_SSL_VERIFY_HOSTNAME'} = 0; 18 | 19 | # Configuration 20 | my $nsxUsername = 'admin'; 21 | my $nsxPassword = 'password'; 22 | my $nsxMgt = 'nsg-manager.virten.lab'; 23 | my $prefix = 'nsx.edge.'; 24 | my $carbonServer = 'graphite.virten.lab'; 25 | my $carbonPort = 2003; 26 | my $debug = 0; 27 | # 28 | 29 | # Connect to Carbon Cache Relay 30 | my $sock = new IO::Socket::INET( PeerAddr => $carbonServer, PeerPort => $carbonPort, Proto => 'tcp') unless $debug; 31 | $sock or die "No socket: $!" unless $debug; 32 | 33 | my $client = REST::Client->new(); 34 | $client->getUseragent()->ssl_opts( SSL_verify_mode => 0 ); 35 | my $headers = { 36 | "Accept" => "application/*+xml;version=1.5", 37 | "Authorization" => 'Basic ' . encode_base64($nsxUsername . ':' . $nsxPassword), 38 | }; 39 | 40 | foreach my $edge (callNSX("https://".$nsxMgt."/api/4.0/edges/")->findnodes('/pagedEdgeList/edgePage/edgeSummary')) { 41 | my($edgeId) = $edge->findnodes('./id')->to_literal; 42 | my($edgeName) = $edge->findnodes('./name')->to_literal; 43 | $edgeName=~ tr/[. ]/_/; 44 | 45 | my $vnics = {}; 46 | my $dashboard = callNSX("https://".$nsxMgt."/api/4.0/edges/".$edgeId."/statistics/dashboard/interface?interval=1"); 47 | foreach my $vnic ($dashboard->findnodes('/dashboardStatistics/meta/vnics/vnic')) { 48 | my $index = $vnic->findnodes('./index')->to_literal; 49 | my $name = $vnic->findnodes('./name')->to_literal; 50 | $vnics->{$index} = $name->value; 51 | } 52 | 53 | foreach (sort keys %{$vnics}) { 54 | my $id = $_; 55 | my $intInPkt = "vNic__".$id."__in__pkt"; 56 | my $intInByte = "vNic__".$id."__in__byte"; 57 | my $intOutPkt = "vNic__".$id."__out__pkt"; 58 | my $intOutByte = "vNic__".$id."__out__byte"; 59 | 60 | foreach my $daStInPkt ($dashboard->findnodes('/dashboardStatistics/data/interfaces/'.$intInPkt.'/dashboardStatistic')) { 61 | my $timestamp = $daStInPkt->findnodes('./timestamp')->to_literal; 62 | my $value = $daStInPkt->findnodes('./value')->to_literal; 63 | sendMetric($prefix.$edgeName.".interface.".$vnics->{$id}.".pkt_in ".$value." ".$timestamp); 64 | } 65 | 66 | foreach my $daStInByte ($dashboard->findnodes('/dashboardStatistics/data/interfaces/'.$intInByte.'/dashboardStatistic')) { 67 | my $timestamp = $daStInByte->findnodes('./timestamp')->to_literal; 68 | my $value = $daStInByte->findnodes('./value')->to_literal; 69 | sendMetric($prefix.$edgeName.".interface.".$vnics->{$id}.".byte_in ".$value." ".$timestamp); 70 | } 71 | 72 | foreach my $daStOutPkt ($dashboard->findnodes('/dashboardStatistics/data/interfaces/'.$intOutPkt.'/dashboardStatistic')) { 73 | my $timestamp = $daStOutPkt->findnodes('./timestamp')->to_literal; 74 | my $value = $daStOutPkt->findnodes('./value')->to_literal; 75 | sendMetric($prefix.$edgeName.".interface.".$vnics->{$id}.".pkt_out ".$value." ".$timestamp); 76 | } 77 | 78 | foreach my $daStOutByte ($dashboard->findnodes('/dashboardStatistics/data/interfaces/'.$intOutByte.'/dashboardStatistic')) { 79 | my $timestamp = $daStOutByte->findnodes('./timestamp')->to_literal; 80 | my $value = $daStOutByte->findnodes('./value')->to_literal; 81 | sendMetric($prefix.$edgeName.".interface.".$vnics->{$id}.".byte_out ".$value." ".$timestamp); 82 | } 83 | 84 | } 85 | 86 | my $firewallDashboard = callNSX("https://".$nsxMgt."/api/4.0/edges/".$edgeId."/statistics/dashboard/firewall?interval=1"); 87 | foreach my $fwConnections ($firewallDashboard->findnodes('/dashboardStatistics/data/firewall/connections/dashboardStatistic')) { 88 | my $timestamp = $fwConnections->findnodes('./timestamp')->to_literal; 89 | my $value = $fwConnections->findnodes('./value')->to_literal; 90 | sendMetric($prefix.$edgeName.".firewall.connections ".$value." ".$timestamp); 91 | } 92 | 93 | my $loadbalancerDashboard = callNSX("https://".$nsxMgt."/api/4.0/edges/".$edgeId."/statistics/dashboard/loadbalancer?interval=1"); 94 | 95 | foreach my $lbSessions ($loadbalancerDashboard->findnodes('/dashboardStatistics/data/loadBalancer/lbSessions/dashboardStatistic')) { 96 | my $timestamp = $lbSessions->findnodes('./timestamp')->to_literal; 97 | my $value = $lbSessions->findnodes('./value')->to_literal; 98 | sendMetric($prefix.$edgeName.".loadbalancer.lbSessions ".$value." ".$timestamp); 99 | } 100 | foreach my $lbHttpReqs ($loadbalancerDashboard->findnodes('/dashboardStatistics/data/loadBalancer/lbHttpReqs/dashboardStatistic')) { 101 | my $timestamp = $lbHttpReqs->findnodes('./timestamp')->to_literal; 102 | my $value = $lbHttpReqs->findnodes('./value')->to_literal; 103 | sendMetric($prefix.$edgeName.".loadbalancer.lbHttpReqs ".$value." ".$timestamp); 104 | } 105 | foreach my $lbBpsIn ($loadbalancerDashboard->findnodes('/dashboardStatistics/data/loadBalancer/lbBpsIn/dashboardStatistic')) { 106 | my $timestamp = $lbBpsIn->findnodes('./timestamp')->to_literal; 107 | my $value = $lbBpsIn->findnodes('./value')->to_literal; 108 | sendMetric($prefix.$edgeName.".loadbalancer.lbBpsIn ".$value." ".$timestamp); 109 | } 110 | foreach my $lbBpsOut ($loadbalancerDashboard->findnodes('/dashboardStatistics/data/loadBalancer/lbBpsOut/dashboardStatistic')) { 111 | my $timestamp = $lbBpsOut->findnodes('./timestamp')->to_literal; 112 | my $value = $lbBpsOut->findnodes('./value')->to_literal; 113 | sendMetric($prefix.$edgeName.".loadbalancer.lbBpsOut ".$value." ".$timestamp); 114 | } 115 | 116 | } 117 | 118 | ### Helper Functions ### 119 | 120 | # Call NSX REST API and parse XML 121 | sub callNSX{ 122 | $client->GET($_[0],$headers); 123 | my $parser = XML::LibXML->new(); 124 | my $content = $parser->parse_string($client->responseContent()); 125 | return $content; 126 | } 127 | 128 | # Send Metric to Carbon Cache 129 | sub sendMetric { 130 | my $metric = $_[0]; 131 | print $metric."\n" if $debug; 132 | $sock->send($metric."\n") unless $debug; 133 | } 134 | -------------------------------------------------------------------------------- /powershell/Check-HCL.ps1: -------------------------------------------------------------------------------- 1 | Function Check-HCL { 2 | <# 3 | .NOTES 4 | Author: Florian Grehl - www.virten.net 5 | Reference: http://www.virten.net/2016/05/vmware-hcl-in-json-format/ 6 | 7 | .DESCRIPTION 8 | Verifies server hardware against VMware HCL. 9 | This script uses a JSON based VMware HCL maintained by www.virten.net. 10 | Works well with HP and Dell. Works acceptable with IBM and Cisco. 11 | 12 | Many vendors do not use the same model string in VMware HCL and Server BIOS Information. 13 | Server may then falsely be reported as unsupported. 14 | 15 | .EXAMPLE 16 | Get-VMHost |Check-HCL 17 | Check-HCL 18 | #> 19 | 20 | [CmdletBinding()] 21 | Param ( 22 | [Parameter(ValueFromPipeline=$true)] 23 | $vmHosts 24 | ) 25 | Begin{ 26 | $esxiReleases = Invoke-WebRequest -Uri http://www.virten.net/repo/esxiReleases.json | ConvertFrom-Json 27 | $hcl = Invoke-WebRequest -Uri http://www.virten.net/repo/vmware-hcl.json | ConvertFrom-Json 28 | 29 | # Workaround when json import is > 2 MB 30 | #$hclJson = Invoke-WebRequest -Uri http://www.virten.net/repo/vmware-hcl.json 31 | #[void][System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions") 32 | #$jsonserializer= New-Object -TypeName System.Web.Script.Serialization.JavaScriptSerializer 33 | #$jsonserializer.MaxJsonLength = [int]::MaxValue 34 | #$hcl = $jsonserializer.DeserializeObject($hclJson) 35 | } 36 | Process { 37 | if (-not $vmHosts) { 38 | $vmHosts = Get-VMHost 39 | } 40 | $AllInfo = @() 41 | Foreach ($vmHost in $vmHosts) { 42 | $HostManuf = $($vmHost.Manufacturer) 43 | $HostModel = $($vmHost.model) 44 | $HostCpu = $($vmHost.ProcessorType) 45 | $Info = "" | Select VMHost, Build, ReleaseLevel, Manufacturer, Model, Cpu, Supported, SupportedReleases, Reference, Note 46 | $Info.VMHost = $vmHost.Name 47 | $Info.Build = $vmHost.Build 48 | $Info.Manufacturer = $HostManuf 49 | $Info.Model = $HostModel 50 | $Info.Cpu = $HostCpu 51 | 52 | $release = $esxiReleases.data.esxiReleases |? build -eq $vmHost.Build 53 | if($release) { 54 | $updateRelease = $($release.updateRelease) 55 | $Info.ReleaseLevel = $updateRelease 56 | } else { 57 | $updateRelease = $false 58 | $Info.Note = "ESXi Build $($vmHost.Build) not found in database." 59 | } 60 | 61 | 62 | $Data = @() 63 | Foreach ($server in $hcl.data.server) { 64 | $ModelFound = $false 65 | 66 | if ($HostModel.StartsWith("UCS") -and $ModelMatch.Contains("UCS")){ 67 | $HostLen=$HostModel.Length 68 | $UCS_MODEL=$HostModel.Substring(5,4) 69 | if ($HostLen -eq 12) { 70 | $UCS_GEN=$HostModel.Substring(10,2) 71 | } 72 | if ($HostLen -eq 14) { 73 | $UCS_GEN=$HostModel.Substring(10,3) 74 | } 75 | 76 | $isUCSMODEL=$ModelMatch.Contains($UCS_MODEL) 77 | if ($isUCSMODEL -eq "True") { 78 | $isUCSGEN=$ModelMatch.Contains($UCS_GEN) 79 | if ($isUCSGEN -eq "True") { 80 | $ModelFound = $true 81 | } 82 | } 83 | } 84 | 85 | $ModelMatch = $server.model 86 | $ModelMatch = $ModelMatch -replace "IBM ","" 87 | $ModelMatch = ("*"+$ModelMatch+"*") 88 | if ($HostManuf -eq "HP"){ 89 | If ($HostModel -like $ModelMatch -and $server.manufacturer -eq $HostManuf) { 90 | $ModelFound = $true 91 | } 92 | } else { 93 | If ($HostModel -like $ModelMatch) { 94 | $ModelFound = $true 95 | } 96 | } 97 | 98 | If ($ModelFound) { 99 | If($server.cpuSeries -like "Intel Xeon*"){ 100 | if ($HostCpu -like "*Gold*" -Or $HostCpu -like "*Silver*" -Or $HostCpu -like "*Bronze*" -Or $HostCpu -like "*Platinum*"){ 101 | $HostCpuMatch = $HostCpu -replace " 0 @"," @" -replace "- ","-" -replace " "," " 102 | $HostCpuMatch = $HostCpu -replace '\D+([0-9]*).*','$1' 103 | $HostCpuMatch = "*$($HostCpuMatch.Substring(0,2))00*" 104 | if ($server.cpuSeries -notlike $HostCpuMatch){ 105 | continue 106 | } 107 | } else { 108 | $cpuSeriesMatch = $server.cpuSeries -replace "Intel Xeon ","" -replace " Series","" -replace "00","??" -replace "xx","??" -replace "-v"," v" 109 | $HostCpuMatch = $HostCpu -replace " 0 @"," @" -replace "- ","-" -replace " "," " 110 | $cpuSeriesMatch = ("*"+$cpuSeriesMatch+" @*") 111 | if ($HostCpuMatch -notlike $cpuSeriesMatch){ 112 | continue 113 | } 114 | } 115 | } 116 | $helper = New-Object PSObject 117 | Add-Member -InputObject $helper -MemberType NoteProperty -Name Model $server.model 118 | Add-Member -InputObject $helper -MemberType NoteProperty -Name CPU $server.cpuSeries 119 | Add-Member -InputObject $helper -MemberType NoteProperty -Name Releases $server.releases 120 | Add-Member -InputObject $helper -MemberType NoteProperty -Name URL $server.url 121 | $Data += $helper 122 | } 123 | } 124 | 125 | If ($Data.Count -eq 1){ 126 | Foreach ($obj in $Data) { 127 | $release = $esxiReleases.data.esxiReleases |? build -eq $vmHost.Build 128 | if ($updateRelease -and ($obj.Releases -contains $updateRelease)){ 129 | $Info.Supported = $true 130 | } else { 131 | $Info.Supported = $false 132 | } 133 | $Info.SupportedReleases = $obj.Releases 134 | $Info.Reference = $($obj.url) 135 | } 136 | } elseif ($Data.Count -gt 1){ 137 | $Info.Note = "More than 1 HCL Entries found." 138 | } else { 139 | $Info.supported = $false 140 | $Info.Note = "No HCL Entries found." 141 | } 142 | $AllInfo += $Info 143 | } 144 | $AllInfo 145 | } 146 | } -------------------------------------------------------------------------------- /powershell/check-hcl-poc.ps1: -------------------------------------------------------------------------------- 1 | # Check ESXi Hosts against VMware HCL 2 | # Does not use live VMware HCL data, but a copied JSON based version 3 | # Needs to be connected to a vCenter Server (Connect-VIServer), or can use fake data from a CSV 4 | # Does not upload any sensitive information. Downloads a full HCL copy and compares it locally. 5 | # Script is just a Proof of Concept... 6 | # 7 | # Todo: 8 | # - Match Model when the BIOS string differs from HCL 9 | # - Identify CPU Series based on specific CPU 10 | 11 | # Load ESXiReleases JSON from www.virten.net to match Builds corresponding Update (eg. Esxi 5.5 U1) 12 | $esxiReleases = Invoke-WebRequest -Uri http://www.virten.net/repo/esxiReleases.json | ConvertFrom-Json 13 | # Offline Version (Download the Json and put it locally to test 14 | #$esxiReleases = Get-Content repo/esxiReleases.json | ConvertFrom-Json 15 | 16 | 17 | # Load JSON bases HCL 18 | Write-Host "Loading HCL Data.." 19 | # HCL to large for "ConvertFrom-Json". JavaScriptSerializer must do it... 20 | $hclJson = Invoke-WebRequest -Uri http://www.virten.net/repo/vmware-hcl.json 21 | #$hclJson = Get-Content repo/vmware-hcl.json # Offline Version 22 | [void][System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions") 23 | $jsonserializer= New-Object -TypeName System.Web.Script.Serialization.JavaScriptSerializer 24 | $jsonserializer.MaxJsonLength = [int]::MaxValue 25 | $hcl = $jsonserializer.DeserializeObject($hclJson) 26 | 27 | Write-Host "Loading ESXi Hosts..." 28 | # Can also use a "Fake List" from a CSV File 29 | # Export List with: Get-VMHost |select Name,Build,Manufacturer,Model,ProcessorType |Export-Csv fakehosts.csv -NoTypeInformation 30 | $vmHosts = Get-VMHost 31 | #$vmHosts = Import-Csv 'fakehosts.csv' -Delimiter ';' 32 | 33 | 34 | Foreach ($vmHost in $vmHosts) { 35 | Write-Host "`r`nESXi Host: " -NoNewline 36 | Write-Host $vmHost.Name -ForegroundColor Cyan 37 | Write-Host " - ESXi Build Number: " -NoNewline 38 | Write-Host $vmHost.Build -ForegroundColor Cyan 39 | 40 | # Search local Build in JSON builds from virten.net to find the correct release like ESXi 6.0u2 or ESXi 5.5u1. 41 | # This information is required to match against the HCL. 42 | $release = $esxiReleases.data.esxiReleases |? build -eq $vmHost.Build 43 | if($release) { 44 | $updateRelease = $($release.updateRelease) 45 | $HostManuf = $($vmHost.Manufacturer) 46 | $HostModel = $($vmHost.model) 47 | $HostCpu = $($vmHost.ProcessorType) 48 | Write-Host " - Release Level (To match HCL): " -NoNewline 49 | Write-Host $updateRelease -ForegroundColor Cyan 50 | Write-Host " - Hardware Vendor: " -NoNewline 51 | Write-Host $HostManuf -ForegroundColor Cyan 52 | Write-Host " - Hardware Model: " -NoNewline 53 | Write-Host $HostModel -ForegroundColor Cyan 54 | Write-Host " - CPU Model: " -NoNewline 55 | Write-Host $HostCpu -ForegroundColor Cyan 56 | } else { 57 | # If the build is unknown, and it's not a beta, please contact me flo@virten.net 58 | # ...or wait a couple of days when the release is brand new. 59 | Write-Host " - Build $($vmHost.Build) not found in database!" -ForegroundColor Red 60 | continue 61 | } 62 | 63 | 64 | # Compare Server Model against my JSON HCL. Models can be found in the HCL multiple times 65 | # because Model+CPU is required to match the hardware. 66 | $Data = @() 67 | Foreach ($server in $hcl.data.server) { 68 | # -eq works great with HP and Dell. No Problems at all 69 | # IBM includs Part Numbers. Nice, but bad for comparison. Some fuzzy compare might be required... 70 | # Cisco UCS models do not match either. Also some fuzziness required 71 | # ...need more Hardware to test. 72 | #If ($HostModel -eq $server.model) { # Works vor HP and Dell, where string matches 100% 73 | $ModelFound = $false 74 | if ($HostModel.StartsWith("UCS") -and $ModelMatch.Contains("UCS")){ 75 | $HostLen=$HostModel.Length 76 | 77 | # UCSB - B200 - M 3 78 | # 1234 5 6789 10 11 12 79 | 80 | # UCSC - C240 - M 3 S 2 81 | # 1234 5 6579 10 11 12 13 14 82 | $UCS_MODEL=$HostModel.Substring(5,4) 83 | if ($HostLen -eq 12) { 84 | $UCS_GEN=$HostModel.Substring(10,2) 85 | } 86 | if ($HostLen -eq 14) { 87 | $UCS_GEN=$HostModel.Substring(10,3) 88 | } 89 | 90 | $isUCSMODEL=$ModelMatch.Contains($UCS_MODEL) 91 | if ($isUCSMODEL -eq "True") { 92 | $isUCSGEN=$ModelMatch.Contains($UCS_GEN) 93 | if ($isUCSGEN -eq "True") { 94 | $ModelFound = $true 95 | } 96 | } 97 | } 98 | 99 | $ModelMatch = $server.model 100 | $ModelMatch = $ModelMatch -replace "IBM ","" # IBM writes "IBM" in front of models sometimes. Need to remove it 101 | $ModelMatch = ("*"+$ModelMatch+"*") # Not all entries are 100% matches. Simple wildcard matching 102 | #Write-Host "Model Match String:" $ModelMatch 103 | If ($HostModel -like $ModelMatch) { 104 | $ModelFound = $true 105 | } 106 | 107 | If ($ModelFound) { 108 | # Matching CPU Series to CPU Model requires fuzzy matching 109 | # This filter works with Intel Xenon CPUs: 110 | if($server.cpuSeries -like "Intel Xeon*"){ 111 | $cpuSeriesMatch = $server.cpuSeries -replace "Intel Xeon ","" -replace " Series","" -replace "00","??" -replace "xx","??" -replace "-v"," v" 112 | $cpuSeriesMatch = ("*"+$cpuSeriesMatch+" @*") 113 | #Write-Host "CPU Series Match String:" $cpuSeriesMatch 114 | if ($HostCpu -notlike $cpuSeriesMatch){ 115 | continue 116 | } 117 | } 118 | 119 | 120 | $helper = New-Object PSObject 121 | Add-Member -InputObject $helper -MemberType NoteProperty -Name Model $server.model 122 | Add-Member -InputObject $helper -MemberType NoteProperty -Name CPU $server.cpuSeries 123 | Add-Member -InputObject $helper -MemberType NoteProperty -Name Releases $server.releases 124 | Add-Member -InputObject $helper -MemberType NoteProperty -Name URL $server.url 125 | $Data += $helper 126 | } 127 | } 128 | Write-Host " -- Found $($Data.Count) HCL Entries..." 129 | 130 | # Display matches... 131 | if ($Data.Count){ 132 | Foreach ($obj in $Data) { 133 | Write-Host " -- " -NoNewline 134 | Write-Host "$($obj.Model)" -ForegroundColor Yellow -NoNewline 135 | Write-Host " with CPU " -NoNewline 136 | Write-Host $($obj.CPU) -NoNewline -ForegroundColor Yellow 137 | $relFound = $false 138 | $release = $esxiReleases.data.esxiReleases |? build -eq $vmHost.Build 139 | 140 | if ($obj.Releases -contains $updateRelease){ 141 | Write-Host " is supported in " -NoNewline 142 | Write-Host "$($updateRelease) " -ForegroundColor Green 143 | } else { 144 | Write-Host " is not supported in " -NoNewline 145 | Write-Host "$($updateRelease) " -ForegroundColor Red 146 | } 147 | 148 | # Optional: Display releases that are supported for this Hardware+CPU Combo. 149 | # Maybe useful to check if it's ok to upgrade the server 150 | # Displays only 5.x and 6.x Releases 151 | Write-Host " --- Supported: " -NoNewline 152 | $supportedReleases = "" 153 | $supportedReleases = $obj.Releases|? {$_ -notmatch "Installable|Embedded|ESX "} 154 | if($supportedReleases){ 155 | $supportedReleases.Replace("ESXi ","") -join ", " 156 | } else { 157 | Write-Host "Only systems < vSphere 5 are supported, but they are filtered by the script." 158 | } 159 | 160 | # Optional: Display Original HCL Link for verification 161 | Write-Host " --- HCL Link: $($obj.url)" 162 | } 163 | } 164 | } -------------------------------------------------------------------------------- /powershell/check-iohcl-poc.ps1: -------------------------------------------------------------------------------- 1 | # Check ESXi Host Devices against VMware IO HCL 2 | # Does not use live VMware HCL data, but a copied JSON based version 3 | # Needs to be connected to a vCenter Server (Connect-VIServer) 4 | # Does not upload any sensitive information. Downloads a full HCL copy and compares it locally. 5 | # Script is just a Proof of Concept... 6 | # 7 | # The script uses Get-EsxCli -V2 which requires at least PowerCLI 6.3 R1 8 | 9 | 10 | # Configure device scope. Change the $devices variable to match the host you want to check. 11 | # You can check multiple hosts at once, but please note that the Script needs to call esxcli 12 | # to identify driver and firmware versions. This can take about 30-60 seconds per host. 13 | $devices = Get-VMHost esx01* | Get-VMHostPciDevice | where { $_.DeviceClass -eq "MassStorageController" -or $_.DeviceClass -eq "NetworkController" -or $_.DeviceClass -eq "SerialBusController"} 14 | 15 | $hcl = Invoke-WebRequest -Uri http://www.virten.net/repo/vmware-iohcl.json | ConvertFrom-Json 16 | $AllInfo = @() 17 | Foreach ($device in $devices) { 18 | 19 | # Ignore USB Controller 20 | if ($device.DeviceName -like "*USB*" -or $device.DeviceName -like "*iLO*" -or $device.DeviceName -like "*iDRAC*") { 21 | continue 22 | } 23 | 24 | $DeviceFound = $false 25 | $Info = "" | Select VMHost, Device, DeviceName, VendorName, DeviceClass, vid, did, svid, ssid, Driver, DriverVersion, FirmwareVersion, VibVersion, Supported, Reference 26 | $Info.VMHost = $device.VMHost 27 | $Info.DeviceName = $device.DeviceName 28 | $Info.VendorName = $device.VendorName 29 | $Info.DeviceClass = $device.DeviceClass 30 | $Info.vid = [String]::Format("{0:x}", $device.VendorId) 31 | $Info.did = [String]::Format("{0:x}", $device.DeviceId) 32 | $Info.svid = [String]::Format("{0:x}", $device.SubVendorId) 33 | $Info.ssid = [String]::Format("{0:x}", $device.SubDeviceId) 34 | 35 | if ($device.DeviceClass -eq "NetworkController"){ 36 | # Get NIC list to identify vmnicX from PCI slot Id 37 | $esxcli = $device.VMHost | Get-EsxCli -V2 38 | $niclist = $esxcli.network.nic.list.Invoke(); 39 | $vmnicId = $niclist | where { $_.PCIDevice -like '*'+$device.Id} 40 | $Info.Device = $vmnicId.Name 41 | 42 | # Get NIC driver and firmware information 43 | $vmnicDetail = $esxcli.network.nic.get.Invoke(@{nicname = $vmnicId.Name}) 44 | $Info.Driver = $vmnicDetail.DriverInfo.Driver 45 | $Info.DriverVersion = $vmnicDetail.DriverInfo.Version 46 | $Info.FirmwareVersion = $vmnicDetail.DriverInfo.FirmwareVersion 47 | 48 | # Get driver vib package version 49 | Try{ 50 | $driverVib = $esxcli.software.vib.get.Invoke(@{vibname = "net-"+$vmnicDetail.DriverInfo.Driver}) 51 | }Catch{ 52 | $driverVib = $esxcli.software.vib.get.Invoke(@{vibname = $vmnicDetail.DriverInfo.Driver}) 53 | } 54 | $Info.VibVersion = $driverVib.Version 55 | 56 | 57 | } elseif ($device.DeviceClass -eq "MassStorageController" -or $device.DeviceClass -eq "SerialBusController"){ 58 | # Identify HBA (FC or Local Storage) with PCI slot Id 59 | $vmhbaId = $device.VMHost |Get-VMHostHba | where { $_.PCI -like '*'+$device.Id} 60 | $Info.Device = $vmhbaId.Device 61 | $Info.Driver = $vmhbaId.Driver 62 | 63 | # Get driver vib package version 64 | Try{ 65 | $driverVib = $esxcli.software.vib.get.Invoke(@{vibname = "scsi-"+$vmhbaId.Driver}) 66 | }Catch{ 67 | $driverVib = $esxcli.software.vib.get.Invoke(@{vibname = $vmhbaId.Driver}) 68 | } 69 | $Info.VibVersion = $driverVib.Version 70 | } 71 | 72 | # Search HCL entry with PCI IDs VID, DID, SVID and SSID 73 | Foreach ($entry in $hcl.data.ioDevices) { 74 | If (($Info.vid -eq $entry.vid) -and ($Info.did -eq $entry.did) -and ($Info.svid -eq $entry.svid) -and ($Info.ssid -eq $entry.ssid)) { 75 | $Info.Reference = $entry.url 76 | $DeviceFound = $true 77 | } 78 | } 79 | 80 | $Info.Supported = $DeviceFound 81 | $AllInfo += $Info 82 | } 83 | 84 | # Display all Infos 85 | $AllInfo 86 | 87 | # Display ESXi, DeviceName and supported state 88 | #$AllInfo |select VMHost,Device,DeviceName,Supported,Referece |ft -AutoSize 89 | 90 | # Display device, driver and firmware information 91 | #$AllInfo |select VMHost,Device,DeviceName,Supported,Driver,DriverVersion,FirmwareVersion,VibVersion |ft -AutoSize 92 | 93 | # Expor to CSV 94 | #$AllInfo |Export-Csv -NoTypeInformation deviceList.csv 95 | -------------------------------------------------------------------------------- /powershell/check_esxi_65_support.ps1: -------------------------------------------------------------------------------- 1 | # Author: Florian Grehl - www.virten.net 2 | # Reference: - 3 | # Description: Check ESXi 6.5 support with JSON based HCL provided by www.virten.net 4 | # (http://www.virten.net/2016/05/vmware-hcl-in-json-format/) 5 | # 6 | # Requires Check-HCL function (https://github.com/fgrehl/virten-scripts/blob/master/powershell/Check-HCL.ps1) 7 | 8 | 9 | #$scope = Get-VMHost esx73.virten.lab 10 | #$scope = Get-Cluster Production | Get-VMHost 11 | $scope = Get-VMHost 12 | 13 | (New-Object System.Net.WebClient).DownloadFile("https://raw.githubusercontent.com/fgrehl/virten-scripts/master/powershell/Check-HCL.ps1", "$Env:temp\Check-HCL.ps1") 14 | . $Env:temp\Check-HCL.ps1 15 | $check = Check-HCL $scope 16 | foreach ($esx in $check){ 17 | Write-Host "$($esx.VMHost) ($($esx.Model)): " -NoNewline 18 | if($esx.SupportedReleases){ 19 | if ($esx.SupportedReleases -match "6.5"){ 20 | Write-Host "ESXi 6.5 supported" -ForegroundColor Green 21 | } else { 22 | Write-Host "ESXi 6.5 unsupported" -ForegroundColor Red 23 | } 24 | } else { 25 | Write-Host "unknown" 26 | } 27 | } -------------------------------------------------------------------------------- /powershell/check_esxi_67_support.ps1: -------------------------------------------------------------------------------- 1 | # Author: Florian Grehl - www.virten.net 2 | # Reference: - 3 | # Description: Check ESXi 6.7 support with JSON based HCL provided by www.virten.net 4 | # (http://www.virten.net/2016/05/vmware-hcl-in-json-format/) 5 | # 6 | # Requires Check-HCL function (https://github.com/fgrehl/virten-scripts/blob/master/powershell/Check-HCL.ps1) 7 | 8 | 9 | #$scope = Get-VMHost esx73.virten.lab 10 | #$scope = Get-Cluster Production | Get-VMHost 11 | $scope = Get-VMHost 12 | 13 | (New-Object System.Net.WebClient).DownloadFile("https://raw.githubusercontent.com/fgrehl/virten-scripts/master/powershell/Check-HCL.ps1", "$Env:temp\Check-HCL.ps1") 14 | . $Env:temp\Check-HCL.ps1 15 | $check = Check-HCL $scope 16 | foreach ($esx in $check){ 17 | Write-Host "$($esx.VMHost) ($($esx.Model)): " -NoNewline 18 | if($esx.SupportedReleases){ 19 | if ($esx.SupportedReleases -match "6.7"){ 20 | Write-Host "ESXi 6.7 supported" -ForegroundColor Green 21 | } else { 22 | Write-Host "ESXi 6.7 unsupported" -ForegroundColor Red 23 | } 24 | } else { 25 | Write-Host "unknown" 26 | } 27 | } -------------------------------------------------------------------------------- /powershell/check_esxi_70_support.ps1: -------------------------------------------------------------------------------- 1 | # Author: Florian Grehl - www.virten.net 2 | # Reference: - 3 | # Description: Check ESXi 7.0 support with JSON based HCL provided by www.virten.net 4 | # (http://www.virten.net/2016/05/vmware-hcl-in-json-format/) 5 | # 6 | # Requires Check-HCL function (https://github.com/fgrehl/virten-scripts/blob/master/powershell/Check-HCL.ps1) 7 | 8 | 9 | #$scope = Get-VMHost esx73.virten.lab 10 | #$scope = Get-Cluster Production | Get-VMHost 11 | $scope = Get-VMHost 12 | 13 | (New-Object System.Net.WebClient).DownloadFile("https://raw.githubusercontent.com/fgrehl/virten-scripts/master/powershell/Check-HCL.ps1", "$Env:temp\Check-HCL.ps1") 14 | . $Env:temp\Check-HCL.ps1 15 | $check = Check-HCL $scope 16 | foreach ($esx in $check){ 17 | Write-Host "$($esx.VMHost) ($($esx.Model)): " -NoNewline 18 | if($esx.SupportedReleases){ 19 | if ($esx.SupportedReleases -match "7.0"){ 20 | Write-Host "ESXi 7.0 supported" -ForegroundColor Green 21 | } else { 22 | Write-Host "ESXi 7.0 unsupported" -ForegroundColor Red 23 | } 24 | } else { 25 | Write-Host "unknown" 26 | } 27 | } -------------------------------------------------------------------------------- /powershell/check_esxi_endOfSupport_from_json.ps1: -------------------------------------------------------------------------------- 1 | # Author: Florian Grehl - www.virten.net 2 | # Reference: http://www.virten.net/2016/04/product-end-of-support-matrix-now-available-as-json-incl-script/ 3 | # Description: Displays ESXi end of support date 4 | # 5 | 6 | $vmwareProductLifecycle = Invoke-WebRequest -Uri http://www.virten.net/repo/vmwareProductLifecycle.json | ConvertFrom-Json 7 | $vmHosts = Get-VMHost 8 | 9 | Foreach ($vmHost in $vmHosts) { 10 | $releaseFound = $false 11 | $product = "VMware ESXi $($vmHost.ApiVersion)" 12 | 13 | Write-Host "$($vmHost.Name) is running Version $($product)" 14 | 15 | Foreach ($prod in $vmwareProductLifecycle.data.productLifecycle) { 16 | If ($product -eq $prod.productRelease) { 17 | $TimeSpanEogs = New-TimeSpan –Start (get-date) –End (get-date $prod.endOfGeneralSupport) 18 | $TimeSpanEotg = New-TimeSpan –Start (get-date) –End (get-date $prod.endOfTechnicalGuidance) 19 | Write-Host " - End of Genereal Support: $($prod.endOfGeneralSupport) ($($TimeSpanEogs.days) Days)" 20 | Write-Host " - End of Technical Guidance: $($prod.endOfTechnicalGuidance) ($($TimeSpanEotg.days) Days)" 21 | $releaseFound = $true 22 | } 23 | } 24 | 25 | If (-Not $releaseFound){ 26 | Write-Host " - $($product) not found in database!" -ForegroundColor Red 27 | } 28 | } -------------------------------------------------------------------------------- /powershell/check_esxi_version_with_json.ps1: -------------------------------------------------------------------------------- 1 | # Author: Florian Grehl - www.virten.net 2 | # Reference: http://www.virten.net/2016/04/esxi-version-information-now-available-as-json-incl-script-example/ 3 | # Description: ESXi Build Numbers JSON demonstration 4 | # 5 | 6 | $esxiReleases = Invoke-WebRequest -Uri http://www.virten.net/repo/esxiReleases.json | ConvertFrom-Json 7 | $vmHosts = Get-VMHost 8 | $AllInfo = @() 9 | 10 | Foreach ($vmHost in $vmHosts) { 11 | $buildFound = $false 12 | $Info = "" | Select VMHost, Build, ReleaseLevel, PatchLevel, ReleaseDate, UpdateAvailable, LatestPatch, LatestBuild 13 | Write-Host "ESXi Host $($vmHost.Name) is running on Build $($vmHost.Build)" 14 | $Info.VMHost = $vmHost.Name 15 | $Info.Build = $vmHost.Build 16 | 17 | Foreach ($release in $esxiReleases.data.esxiReleases) { 18 | If ($vmHost.Build -eq $release.Build) { 19 | Write-Host " - Release Level: $($release.releaseLevel)" 20 | $Info.ReleaseLevel = $release.releaseLevel 21 | Write-Host " - Patch Level: $($release.friendlyName)" 22 | $Info.PatchLevel = $release.friendlyName 23 | Write-Host " - Release Date: $($release.releaseDate)" 24 | $Info.ReleaseDate = $release.releaseDate 25 | $minorRelease = $($release.minorRelease) 26 | $buildFound = $true 27 | 28 | Foreach ($rel in $esxiReleases.data.esxiReleases) { 29 | If ($minorRelease -eq $rel.minorRelease) { 30 | $latestBuild = $rel.build 31 | $latestPatch = $rel.friendlyName 32 | break 33 | } 34 | } 35 | 36 | if($latestBuild -eq $vmHost.Build) { 37 | Write-Host " - $($vmHost.Name) is running the latest version!" -ForegroundColor Green 38 | $Info.UpdateAvailable = $false 39 | } else { 40 | Write-Host " - $($vmHost.Name) update available: $($latestPatch) ($($latestBuild))" -ForegroundColor Red 41 | $Info.UpdateAvailable = $true 42 | $Info.LatestPatch = $latestPatch 43 | $Info.LatestBuild = $latestBuild 44 | } 45 | } 46 | } 47 | If (-Not $buildFound){ 48 | Write-Host " - Build $($vmHost.Build) not found in database!" -ForegroundColor Red 49 | } 50 | $AllInfo += $Info 51 | } 52 | 53 | 54 | # $AllInfo | Export-Csv -NoTypeInformation esxi.csv 55 | -------------------------------------------------------------------------------- /powershell/esxi_on_rasperry_pi_functions.ps1: -------------------------------------------------------------------------------- 1 | function Write-RpiEepromToUsb { 2 | [CmdletBinding()] 3 | Param ( 4 | [Parameter(Mandatory=$false)] 5 | [string]$eepromUrl = "https://github.com/raspberrypi/rpi-eeprom/releases/download/v2020.09.03-138a1/rpi-boot-eeprom-recovery-2020-09-03-vl805-000138a1.zip" 6 | ) 7 | 8 | $Elevated = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) 9 | if (-not $Elevated) { 10 | Throw "This Function requires Elevation" 11 | } 12 | 13 | $eepromDisk = Get-Disk | Where-Object {$_.BusType -eq 'USB' -or $_.BusType -eq 7} | Out-GridView -Title 'Select SD Card for RPi EEPROM' -OutputMode Single | Clear-Disk -RemoveData -RemoveOEM -PassThru | New-Partition -UseMaximumSize -IsActive -AssignDriveLetter | Format-Volume -FileSystem FAT32 14 | if($null -eq $eepromDisk) { 15 | Throw "No USB Device found." 16 | } 17 | 18 | # Download EEPROM 19 | $eepromFile = ($env:TEMP)+"\"+(Split-Path $eepromUrl -leaf) 20 | Invoke-WebRequest -Uri $eepromUrl -OutFile $eepromFile 21 | 22 | If (-not (Test-Path $eepromFile)){ 23 | Throw "EEPROM Image Download Error." 24 | } 25 | # Write EEPROM Image to SD Card 26 | Expand-Archive -LiteralPath $eepromFile -DestinationPath "$($eepromDisk.DriveLetter):\" 27 | 28 | Write-Host "Raspberry Pi 4 EEPROM bootloader rescue image written successfully" 29 | Write-Host "1. Remove the SD Card from your PC" 30 | Write-Host "2. Insert the SD Card to your Raspberry Pi" 31 | Write-Host "3. Power on Raspberry Pi" 32 | Write-Host "4. Wait at least 10 seconds." 33 | Write-Host "If successful, the green LED light will blink rapidly (forever), otherwise an error pattern will be displayed." 34 | Write-Host "If a HDMI display is attached then screen will display green for success or red if failure a failure occurs." 35 | } 36 | 37 | 38 | function Write-RpiFirmwareToUsb { 39 | [CmdletBinding()] 40 | Param ( 41 | [Parameter(Mandatory=$false)][string]$rpiFwUrl = "https://github.com/raspberrypi/firmware/archive/master.zip", 42 | [Parameter(Mandatory=$false)][string]$rpiUefiUrl = "https://github.com/pftf/RPi4/releases/download/v1.20/RPi4_UEFI_Firmware_v1.20.zip" 43 | 44 | ) 45 | $Elevated = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) 46 | if (-not $Elevated) { 47 | Throw "This Function requires Elevation" 48 | } 49 | 50 | $firmwareDisk = Get-Disk | Where-Object {$_.BusType -eq 'USB' -or $_.BusType -eq 7} | Out-GridView -Title 'Select SD Card for RPi UEFI Firmware' -OutputMode Single | Clear-Disk -RemoveData -RemoveOEM -PassThru | New-Partition -UseMaximumSize -IsActive -AssignDriveLetter | Format-Volume -FileSystem FAT32 51 | if($null -eq $firmwareDisk) { 52 | Throw "No USB Device found." 53 | } 54 | 55 | # Raspberry Pi Firmware 56 | $rpiFwPath = ($env:TEMP)+"\rpi\" 57 | $rpiFwFile = $rpiFwPath+(Split-Path $rpiFwUrl -leaf) 58 | if (!(Test-Path $rpiFwPath)) {New-Item -Path $rpiFwPath -ItemType Directory |Out-Null} 59 | Invoke-WebRequest -Uri $rpiFwUrl -OutFile $rpiFwFile 60 | Expand-Archive -LiteralPath $rpiFwFile -DestinationPath "$($rpiFwPath)" -ErrorAction "SilentlyContinue" 61 | Remove-Item "$($rpiFwPath)firmware-master\boot\kernel*.img" 62 | Copy-Item -Path "$($rpiFwPath)firmware-master\boot\*" -Destination "$($firmwareDisk.DriveLetter):\" -Recurse 63 | 64 | # Raspberry Pi UEFI Firmware 65 | $rpiUefiFile = $rpiFwPath+(Split-Path $rpiUefiUrl -leaf) 66 | Invoke-WebRequest -Uri $rpiUefiUrl -OutFile $rpiUefiFile 67 | Expand-Archive -LiteralPath $rpiUefiFile -DestinationPath "$($firmwareDisk.DriveLetter):\" -Force 68 | Remove-Item -Path $rpiFwPath -Recurse -Confirm:$false 69 | 70 | Write-Host "Raspberry Pi 4 EFI Firmware written successfully" 71 | Write-Host "1. Remove the SD Card from your PC" 72 | Write-Host "2. Insert the SD Card to your Raspberry Pi" 73 | Write-Host "3. Power on Raspberry Pi" 74 | Write-Host "4. Press ESC to enter Setup" 75 | Write-Host "5. Disable 3 GB RAM Limit (Device Manager > Raspberry Pi Configuration > Advanced Configuration > Limit RAM to 3 GB)" 76 | Write-Host "6. Press F10 to save" 77 | Write-Host "You are now ready to Install ESXi." 78 | 79 | } 80 | -------------------------------------------------------------------------------- /powershell/get-cpuid.ps1: -------------------------------------------------------------------------------- 1 | # PowerShell script to get CPUID information from ESXi Hosts to identify CPU in Intels Security Issues table 2 | # Reference: https://www.intel.com/content/www/us/en/developer/topic-technology/software-security-guidance/processors-affected-consolidated-product-cpu-model.html 3 | 4 | Get-VMHost | ForEach-Object { 5 | $esx = $_ 6 | $(Get-EsxCli -VMhost $esx -V2).hardware.cpu.list.Invoke() | Select-Object -First 1 | Select-Object ` 7 | @{N = "Name"; E = { $esx.Name } }, 8 | @{N = "CPU"; E = { $esx.ProcessorType } }, 9 | @{N = "Family"; E = { '{0:X}' -f ([int]$_.Family) } }, 10 | @{N = "Model"; E = { '{0:X}' -f ([int]$_.Model) } }, 11 | @{N = "CPUID"; E = { "$(('{0:X}' -f ([int]$_.Family)).PadLeft(2, '0'))_$(('{0:X}' -f ([int]$_.Model)).PadLeft(2, '0'))H" } }, 12 | @{N = "stepping"; E = { '{0:X}' -f ([int]$_.Stepping) } } 13 | } | Format-Table -AutoSize 14 | -------------------------------------------------------------------------------- /powershell/io-devices-report.ps1: -------------------------------------------------------------------------------- 1 | # Check ESXi Host Devices against VMware IO HCL 2 | # Does not use live VMware HCL data, but a copied JSON based version 3 | # Needs to be connected to a vCenter Server (Connect-VIServer) 4 | # Does not upload any sensitive information. Downloads a full HCL copy and compares it locally. 5 | # 6 | # The script uses Get-EsxCli -V2 which requires at least PowerCLI 6.3 R1 7 | # 8 | # Author: Florian Grehl - www.virten.net 9 | 10 | # Configure device scope. Change the $devices variable to match the host you want to check. 11 | # You can check multiple hosts at once, but please note that the Script needs to call esxcli 12 | # to identify driver and firmware versions. This can take about 20-40 seconds per host. 13 | $devices = Get-VMHost | Get-VMHostPciDevice | where { $_.DeviceClass -eq "MassStorageController" -or $_.DeviceClass -eq "NetworkController" -or $_.DeviceClass -eq "SerialBusController"} 14 | 15 | # Uncomment this line to enable debug output 16 | #$DebugPreference = "Continue" 17 | 18 | $hcl = Invoke-WebRequest -Uri http://www.virten.net/repo/vmware-iohcl.json | ConvertFrom-Json 19 | $AllInfo = @() 20 | Foreach ($device in $devices) { 21 | 22 | # Ignore USB Controller 23 | if ($device.DeviceName -like "*USB*" -or $device.DeviceName -like "*iLO*" -or $device.DeviceName -like "*iDRAC*") { 24 | continue 25 | } 26 | 27 | $DeviceFound = $false 28 | $Info = "" | Select VMHost, Device, DeviceName, VendorName, DeviceClass, vid, did, svid, ssid, Driver, DriverVersion, FirmwareVersion, VibVersion, Supported, Reference 29 | $Info.VMHost = $device.VMHost 30 | $Info.DeviceName = $device.DeviceName 31 | $Info.VendorName = $device.VendorName 32 | $Info.DeviceClass = $device.DeviceClass 33 | $Info.vid = [String]::Format("{0:x4}", $device.VendorId) 34 | $Info.did = [String]::Format("{0:x4}", $device.DeviceId) 35 | $Info.svid = [String]::Format("{0:x4}", $device.SubVendorId) 36 | $Info.ssid = [String]::Format("{0:x4}", $device.SubDeviceId) 37 | 38 | # Search HCL entry with PCI IDs VID, DID, SVID and SSID 39 | Foreach ($entry in $hcl.data.ioDevices) { 40 | If (($Info.vid -eq $entry.vid) -and ($Info.did -eq $entry.did) -and ($Info.svid -eq $entry.svid) -and ($Info.ssid -eq $entry.ssid)) { 41 | $Info.Reference = $entry.url 42 | $DeviceFound = $true 43 | } 44 | } 45 | 46 | if($DeviceFound){ 47 | if ($device.DeviceClass -eq "NetworkController"){ 48 | # Get NIC list to identify vmnicX from PCI slot Id 49 | $esxcli = $device.VMHost | Get-EsxCli -V2 50 | $niclist = $esxcli.network.nic.list.Invoke(); 51 | $vmnicId = $niclist | where { $_.PCIDevice -like '*'+$device.Id} 52 | $Info.Device = $vmnicId.Name 53 | 54 | # Get NIC driver and firmware information 55 | Write-Debug "Processing $($Info.VMHost.Name) $($Info.Device) $($Info.DeviceName)" 56 | if ($vmnicId.Name){ 57 | $vmnicDetail = $esxcli.network.nic.get.Invoke(@{nicname = $vmnicId.Name}) 58 | $Info.Driver = $vmnicDetail.DriverInfo.Driver 59 | $Info.DriverVersion = $vmnicDetail.DriverInfo.Version 60 | $Info.FirmwareVersion = $vmnicDetail.DriverInfo.FirmwareVersion 61 | 62 | # Get driver vib package version 63 | Try{ 64 | $driverVib = $esxcli.software.vib.get.Invoke(@{vibname = "net-"+$vmnicDetail.DriverInfo.Driver}) 65 | }Catch{ 66 | $driverVib = $esxcli.software.vib.get.Invoke(@{vibname = $vmnicDetail.DriverInfo.Driver}) 67 | } 68 | $Info.VibVersion = $driverVib.Version 69 | } 70 | 71 | } elseif ($device.DeviceClass -eq "MassStorageController" -or $device.DeviceClass -eq "SerialBusController"){ 72 | # Identify HBA (FC or Local Storage) with PCI slot Id 73 | # Todo: Sometimes this call fails with: Get-VMHostHba Object reference not set to an instance of an object. 74 | $vmhbaId = $device.VMHost |Get-VMHostHba -ErrorAction SilentlyContinue | where { $_.PCI -like '*'+$device.Id} 75 | $Info.Device = $vmhbaId.Device 76 | $Info.Driver = $vmhbaId.Driver 77 | 78 | # Get driver vib package version 79 | Try{ 80 | $driverVib = $esxcli.software.vib.get.Invoke(@{vibname = "scsi-"+$vmhbaId.Driver}) 81 | }Catch{ 82 | $driverVib = $esxcli.software.vib.get.Invoke(@{vibname = $vmhbaId.Driver}) 83 | } 84 | $Info.VibVersion = $driverVib.Version 85 | } 86 | $Info.Supported = $DeviceFound 87 | $AllInfo += $Info 88 | } 89 | } 90 | 91 | # Display all Infos 92 | #$AllInfo 93 | 94 | # Display ESXi, DeviceName and supported state 95 | #$AllInfo |select VMHost,Device,DeviceName,Supported,Referece |ft -AutoSize 96 | 97 | # Display device, driver and firmware information 98 | $AllInfo |select VMHost,Device,DeviceName,Driver,DriverVersion,FirmwareVersion,VibVersion |ft -AutoSize 99 | 100 | # Export to CSV 101 | $AllInfo |Export-Csv -NoTypeInformation IO-Device-Report.csv 102 | 103 | # Export to HTML 104 | $css = "table{ Margin: 0px 0px 0px 4px; Border: 1px solid rgb(200, 200, 200); Font-Family: Tahoma; Font-Size: 8pt; Background-Color: rgb(252, 252, 252); }" 105 | $css += "tr:hover td { Background-Color: #6495ED; Color: rgb(255, 255, 255);}" 106 | $css += "tr:nth-child(even) { Background-Color: rgb(242, 242, 242); }" 107 | Set-Content -Value $css -Path IO-Device-Report.css 108 | $AllInfo | ConvertTo-Html -CSSUri "IO-Device-Report.css" | Set-Content "IO-Device-Report.html" 109 | -------------------------------------------------------------------------------- /powershell/vcd_helper_functions.ps1: -------------------------------------------------------------------------------- 1 | # Get-SessionId is a helper function that gets the SessionId of the vCloud 2 | # session (Connect-CIServer) that matches the specified vCD Host endpoint. 3 | # Returns SessionId as a [string] or empty string if matching session is 4 | # not found. 5 | Function Get-SessionId( 6 | [string]$Server 7 | ) { 8 | if ($Global:DefaultCIServers.Count -eq 1) { 9 | if ($Server) { 10 | if ($Global:DefaultCIServers.Name -eq $Server) { 11 | return $Global:DefaultCIServers.SessionID 12 | } 13 | else { 14 | Write-Error("The specified Server is not currently connected, connect first using Connect-CIServer.") 15 | } 16 | } 17 | else { 18 | return $Global:DefaultCIServers.SessionID 19 | } 20 | } 21 | else { 22 | if (!$Server) { 23 | Write-Error("No Server specified and connected to multiple servers, please use the -Server option to specify which connection should be used for this operation.") 24 | return 25 | } 26 | $mySessionID = ($Global:DefaultCIServers | Where-Object { $_.Name -eq $Server }).SessionID 27 | if (!$mySessionID) { 28 | Write-Error("Cannot find a connection that matches Server $Server, connect first using Connect-CIServer.") 29 | return 30 | } 31 | return $mySessionID 32 | } 33 | } 34 | 35 | 36 | # Get-APIVersion is a helper function that retrieves the highest supported 37 | # API version from the given vCD endpoint. This ensures that commands are not 38 | # run against unsupported versions of the vCloud Director API. 39 | Function Get-APIVersion( 40 | [string]$Server 41 | ) { 42 | $Server = Get-Server -Server $Server 43 | 44 | if ($Server) { 45 | try { 46 | [xml]$apiversions = Invoke-WebRequest -Uri "https://$Server/api/versions" -Method Get -Headers @{"Accept" = 'application/*+xml' } 47 | } 48 | catch { 49 | Write-Error ("Could not retrieve API versions, Status Code is $($_.Exception.Response.StatusCode.Value__).") 50 | Write-Error ("This can be caused by an untrusted SSL certificate on your Server.") 51 | return 52 | } 53 | return [int](($apiversions.SupportedVersions.VersionInfo | Where-Object { $_.deprecated -eq $false } | Sort-Object Version -Descending | Select-Object -First 1).Version) 54 | } 55 | else { 56 | Write-Error ("Could not establish Server, if you are connected to multiple servers you must specify -Server option.") 57 | } 58 | } 59 | 60 | 61 | # Get-Server is a helper function to identify the correct Server value to 62 | # be used (specified directly, default if only 1 connection to vCD or empty 63 | # otherwise). 64 | Function Get-Server( 65 | [string]$Server 66 | ) { 67 | if ($Server) { return $Server } 68 | if ($global:DefaultCIServers.Count -gt 1) { return } 69 | return $global:DefaultCIServers.ServiceUri.Host 70 | } 71 | 72 | 73 | # Get-AuthHeader is a helper function to create the authentication header based 74 | # on the receieved Session Secret (Since PowerCLI 13.1 a Bearer Token is used) 75 | Function Get-AuthHeader( 76 | [string]$Server 77 | ) { 78 | $Server = Get-Server -Server $Server 79 | $CISessionId = Get-SessionId($Server) 80 | if ($CISessionId.StartsWith("Bearer ")) { 81 | Write-Debug "Connected to $($Server) using Bearer Token (PowerCLI 13.1 and later)" 82 | return @{ "Authorization" = $CISessionId } 83 | } 84 | else { 85 | Write-Debug "Connected to $($Server) using legacy SID" 86 | return @{ "x-vcloud-authorization" = $CISessionId } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /python/check_nsxt_backup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Nagios check to monitor NSX-T backup status 4 | Florian Grehl - www.virten.net 5 | 6 | usage: check_nsxt_backup.py [-h] -n NSX_HOST [-t TCP_PORT] -u USER -p PASSWORD 7 | [-i] [-a MAX_AGE] 8 | """ 9 | 10 | import requests 11 | import urllib3 12 | import argparse 13 | import json 14 | from datetime import datetime 15 | from time import time 16 | import sys 17 | 18 | def getargs(): 19 | arg_parser = argparse.ArgumentParser() 20 | arg_parser.add_argument('-n', '--nsx_host', type=str, required=True, help='NSX-T Manager host') 21 | arg_parser.add_argument('-t', '--tcp_port', type=int, default=443, help='NSX-T Managet TCP port') 22 | arg_parser.add_argument('-u', '--user', type=str, required=True, help='NSX-T user') 23 | arg_parser.add_argument('-p', '--password', type=str, required=True, help='Password') 24 | arg_parser.add_argument('-i', '--insecure', default=False, action='store_true', help='Ignore SSL errors') 25 | arg_parser.add_argument('-a', '--max_age', type=int, default=1440, help='Backup maximum age (minutes)') 26 | parser = arg_parser 27 | args = parser.parse_args() 28 | return args 29 | 30 | def main(): 31 | args = getargs() 32 | session = requests.session() 33 | 34 | # Disable server certificate verification. 35 | if (args.insecure): 36 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 37 | session.verify = False 38 | 39 | session.auth = (args.user, args.password) 40 | response = session.get('https://' + args.nsx_host + '/api/v1/cluster/backups/history') 41 | if (response.status_code !=200): 42 | print ('Could not connect to NSX-T') 43 | sys.exit(2) 44 | 45 | data = response.json() 46 | now = int(time()) 47 | error = False 48 | for key, value in data.items(): 49 | age = int(now-(value[0]['end_time']/1000))/60 50 | if (age>args.max_age): 51 | print ('NSX-T ' + key.replace('_backup_statuses','') + ' backup is to old (' + str(age) + ' minutes)') 52 | error = True 53 | if (not value[0]['success']): 54 | print ('NSX-T ' + key.replace('_backup_statuses','') + ' backup failed') 55 | error = True 56 | 57 | if (error): 58 | sys.exit(2) 59 | else: 60 | print ('OK') 61 | 62 | if __name__ == "__main__": 63 | main() 64 | -------------------------------------------------------------------------------- /vbs/add-vcenter-root-ca.vbs: -------------------------------------------------------------------------------- 1 | Set objFSO = CreateObject("Scripting.FileSystemObject") 2 | Set objApp = CreateObject("Shell.Application") 3 | Set objShell = CreateObject("WScript.Shell") 4 | 5 | dim vCenterName 6 | vCenterName = inputbox("Add vSphere 6.0 PSC trusted root CA certificates to the local certificate store. Please enter vCenter Server Address (eg. vcenter.example.com)", "Enter vCenter Server URL", "") 7 | if vCenterName = "" then 8 | wscript.quit 9 | end if 10 | 11 | CaCert = "./" & vCenterName & "-cacert.zip" 12 | CaDir = "./" & vCenterName & "-cacert/" 13 | Set newDIR = objFSO.CreateFolder( CaDir ) 14 | 15 | const SXH_SERVER_CERT_IGNORE_ALL_SERVER_ERRORS = 13056 16 | dim xHttp: Set xHttp = createobject("MSXML2.ServerXMLHTTP") 17 | dim bStrm: Set bStrm = createobject("Adodb.Stream") 18 | xHttp.Open "GET", "https://" & vCenterName & "/certs/download", False 19 | xHttp.setOption 2, SXH_SERVER_CERT_IGNORE_ALL_SERVER_ERRORS 20 | xHttp.Send 21 | with bStrm 22 | .type = 1 23 | .open 24 | .write xHttp.responseBody 25 | .savetofile CaCert, 2 26 | end with 27 | 28 | Set unzip=objApp.NameSpace(objFSO.GetAbsolutePathName(CaCert)).Items() 29 | objApp.NameSpace(objFSO.GetAbsolutePathName(CaDir)).copyHere unzip, 16 30 | 31 | CertFolder = CaDir & "certs/" 32 | Set objFolder = objFSO.GetFolder(CertFolder) 33 | Set colFiles = objFolder.Files 34 | For Each objFile in colFiles 35 | objShell.run "certutil.exe -addstore Root "& CertFolder & objFile.Name 36 | Next 37 | 38 | -------------------------------------------------------------------------------- /vbs/add-vcenter65-root-ca.vbs: -------------------------------------------------------------------------------- 1 | ' Script to add vSphere 6.5 CA to root Store 2 | ' Works with Windows 7, Windows 8 & Windows 10 3 | ' Florian Grehl - www.virten.net 4 | 5 | Set objFSO = CreateObject("Scripting.FileSystemObject") 6 | Set objApp = CreateObject("Shell.Application") 7 | Set objShell = CreateObject("WScript.Shell") 8 | 9 | If Not WScript.Arguments.Named.Exists("elevate") Then 10 | CreateObject("Shell.Application").ShellExecute WScript.FullName _ 11 | , """" & WScript.ScriptFullName & """ /elevate", "", "runas", 1 12 | WScript.Quit 13 | End If 14 | 15 | dim vCenterName 16 | vCenterName = inputbox("Add vSphere 6.5 PSC trusted root CA certificates to the local certificate store. Please enter vCenter Server Address (eg. vcenter.example.com)", "Enter vCenter Server URL", "") 17 | if vCenterName = "" then 18 | wscript.quit 19 | end if 20 | 21 | CaCert = "./" & vCenterName & "-cacert.zip" 22 | CaDir = "./" & vCenterName & "-cacert/" 23 | Set newDIR = objFSO.CreateFolder( CaDir ) 24 | 25 | const SXH_SERVER_CERT_IGNORE_ALL_SERVER_ERRORS = 13056 26 | dim xHttp: Set xHttp = createobject("MSXML2.ServerXMLHTTP") 27 | dim bStrm: Set bStrm = createobject("Adodb.Stream") 28 | xHttp.Open "GET", "https://" & vCenterName & "/certs/download.zip", False 29 | xHttp.setOption 2, SXH_SERVER_CERT_IGNORE_ALL_SERVER_ERRORS 30 | xHttp.Send 31 | with bStrm 32 | .type = 1 33 | .open 34 | .write xHttp.responseBody 35 | .savetofile CaCert, 2 36 | end with 37 | 38 | Set unzip=objApp.NameSpace(objFSO.GetAbsolutePathName(CaCert)).Items() 39 | objApp.NameSpace(objFSO.GetAbsolutePathName(CaDir)).copyHere unzip, 16 40 | 41 | CertFolder = CaDir & "certs/win/" 42 | Set objFolder = objFSO.GetFolder(CertFolder) 43 | Set colFiles = objFolder.Files 44 | For Each objFile in colFiles 45 | objShell.run "certutil.exe -addstore Root "& CertFolder & objFile.Name 46 | Next 47 | 48 | --------------------------------------------------------------------------------