From 501bfa7fd2b5ea1111f321caab418faf9a7d8f35 Mon Sep 17 00:00:00 2001 From: Gerasimos Alexiou Date: Tue, 9 Oct 2018 22:48:07 +0300 Subject: [PATCH 01/43] backup-esxi-host-configuration backup-esxi-host-configuration powershell script --- Scripts/backup-esxi-host-configuration.ps1 | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 Scripts/backup-esxi-host-configuration.ps1 diff --git a/Scripts/backup-esxi-host-configuration.ps1 b/Scripts/backup-esxi-host-configuration.ps1 new file mode 100644 index 0000000..924ca06 --- /dev/null +++ b/Scripts/backup-esxi-host-configuration.ps1 @@ -0,0 +1,22 @@ +<# +Script name: backup-esxi-host-configuration.ps1 +Created on: 09/10/2018 +Author: Gerasimos Alexiou, @jerrak0s +Description: The purpose of the script is to backup esxi host configuration for restore purposes. +Dependencies: None known + +===Tested Against Environment==== +vSphere Version: 6.5 U2 +PowerCLI Version: PowerCLI 10.1.1 +PowerShell Version: 5.1 +OS Version: Windows 10 +Keyword: Backup Configuration ESXi Host +#> + + +$serverIp = Read-Host 'What is the server ip address:' +$path = Read-Host 'Give path where backup configuration will be stored:' +$serverPass = Read-Host 'What is the server root password:' -AsSecureString +Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false +Connect-VIServer serverip -user "root" -password $serverPass +Get-VMHostFirmware -vmhost serverip -BackupConfiguration -DestinationPath $path \ No newline at end of file From 0743c67799b35e155f5e7aaf93b0facdb9a80884 Mon Sep 17 00:00:00 2001 From: Zhoulin Dai Date: Mon, 19 Nov 2018 22:41:26 +0800 Subject: [PATCH 02/43] Initial commit of VMware.VCGChecker module --- .../VMware.VCGChecker/Export-VCGReport.ps1 | 1057 +++++++++++++++++ Modules/VMware.VCGChecker/Get-VCGHWInfo.ps1 | 310 +++++ Modules/VMware.VCGChecker/Get-VCGStatus.ps1 | 168 +++ Modules/VMware.VCGChecker/README.md | 41 + .../VMware.VCGChecker/Save-VCGJsonFile.ps1 | 17 + .../VMware.VCGChecker/VMware.VCGChecker.psd1 | 90 ++ Modules/VMware.VCGChecker/logger.ps1 | 112 ++ 7 files changed, 1795 insertions(+) create mode 100644 Modules/VMware.VCGChecker/Export-VCGReport.ps1 create mode 100644 Modules/VMware.VCGChecker/Get-VCGHWInfo.ps1 create mode 100644 Modules/VMware.VCGChecker/Get-VCGStatus.ps1 create mode 100644 Modules/VMware.VCGChecker/README.md create mode 100644 Modules/VMware.VCGChecker/Save-VCGJsonFile.ps1 create mode 100644 Modules/VMware.VCGChecker/VMware.VCGChecker.psd1 create mode 100644 Modules/VMware.VCGChecker/logger.ps1 diff --git a/Modules/VMware.VCGChecker/Export-VCGReport.ps1 b/Modules/VMware.VCGChecker/Export-VCGReport.ps1 new file mode 100644 index 0000000..1b1253d --- /dev/null +++ b/Modules/VMware.VCGChecker/Export-VCGReport.ps1 @@ -0,0 +1,1057 @@ +# +# Generate the html report and save it to the report folder +# TODO: change to the class +Function Export-VCGReport { + Param( + [Parameter(Mandatory=$true)] $Data, + [Parameter(Mandatory=$true)] $Dir + ) + if (!(Test-Path $Dir)) { + New-Item -Type directory -Confirm:$false -Path $Dir -Force |Out-Null + } + + $Data,$flag = refactorData $Data + + $null=Generate_CsvReport $Data $Dir + $null=Generate_HtmlReport $Data $Dir + $null=Generate_SummaryReport $Data $Dir +} +Function Generate_HtmlReport($Data, $Dir) { + info ("Generating compatibility detail report...") + $content = $generalHead + $content += '

ESXi Hardware Compatibility Report for {0}

' -f $Data.hostname + $content += $generalBodyBase + if (-not(checkVersion($Data))) { + $content += 'Installed Release' + } + else { + $content += 'Checked Release' + } + $content += $generalBodyRest + foreach ($VCResource in $Data) { + $checkVersion = $VCResource.checkRelease + $Count1 = $VCResource.DCResource.HostResource.ComponentResource.Count + $Process = '' + if ($VCResource.hostname -ne 'null') { + $Process += '{1}' -f $Count1, [string]$VCResource.hostname + } + else { + $Process += '{1}' -f $Count1, '/' + } + foreach ($DCResource in $VCResource.DCResource) { + $Count2 = $DCResource.HostResource.ComponentResource.Count + if ($DCResource.dcname -ne 'null') { + $Process += '{1}' -f [string]$Count2, [string]$DCResource.dcname + } + else { + $Process += '{1}' -f [string]$Count2, '/' + } + foreach ($HostResourceOne in $DCResource.HostResource) { + $Count = $HostResourceOne.ComponentResource.count + $Process += '{1}' -f $Count, $HostResourceOne.HostName + foreach ($OneDevice in $HostResourceOne.ComponentResource) { + if ($OneDevice.type -eq 'Server') { + # $InfoServer = "" | Select HostName, Manufacturer, Model, CPU, Version, Bios, CpuFeature, Uuid, VcgLink, Status, FoundRelease, MatchResult, Warnings + $InfoServer = @{} + $InfoServer.HostName = $HostResourceOne.hostname + $InfoServer.Version = $HostResourceOne.version + $InfoServer.Manufacturer = $OneDevice.vendor + $InfoServer.Model = $OneDevice.model + $InfoServer.CPU = $OneDevice.cpumodel + $InfoServer.Bios = $OneDevice.biosversion + $InfoServer.CpuFeature = $OneDevice.cpufeatureid + $InfoServer.Uuid = $OneDevice.uuid + $InfoServer.VcgLink = $OneDevice.vcgLink + $InfoServer.Status = formatStatus($OneDevice.status) + $InfoServer.MatchResult = $OneDevice.matchResult + $InfoServer.Warnings = (([string]$OneDevice.warnings) -split "More information")[0] + # server info + $Process += 'Server' + $Process += '{0}' -f $InfoServer.Model + $Process += '{0}' -f $InfoServer.Manufacturer + if (-not $checkVersion) { + $Process += '{0}' -f $InfoServer.Version + } + else { + $Process += '{0}' -f $checkVersion + } + $Process += '{0}' -f $InfoServer.Status + $Process += '{0},
CpuFeature:{1},
Bios:{2}' -f $InfoServer.CPU, $InfoServer.CpuFeature, $InfoServer.Bios + if ($InfoServer.VcgLink.Count -gt 0) { + $Process += '{0}
' -f $InfoServer.Warnings + foreach ($link in $InfoServer.VcgLink) { + $Process += ' VCG link
' -f $link + } + $Process += '' + } + else + {$Process += '{0}
N/A' -f $InfoServer.Warnings} + $Process += '' + } + else { + # $InfoPci = "" | Select model, vendor, Vid, Did, Svid, Ssid, Driver, DriverVersion, Version, Pccid, VcgLink, Status, FoundRelease, MatchResult, Warnings + $InfoPci = @{} + $InfoPci.model = $OneDevice.model + $InfoPci.vendor = $OneDevice.vendor + $InfoPci.Vid = $OneDevice.vid + $InfoPci.Did = $OneDevice.did + $InfoPci.Svid = $OneDevice.svid + $InfoPci.Ssid = $OneDevice.ssid + $InfoPci.Driver = $OneDevice.driver + $InfoPci.DriverVersion = $OneDevice.driverversion + $InfoPci.Version = $HostResourceOne.version + $InfoPci.Pccid = $OneDevice.pciid + $InfoPci.VcgLink = $OneDevice.vcgLink + $InfoPci.Status = formatStatus($OneDevice.status) + $InfoPci.MatchResult = $OneDevice.matchResult + $InfoPci.Warnings = (([string]$OneDevice.warnings) -split "More information")[0] + # IO info + # TODO:Variable information coverage, need to be modified + $Process += '' + $Process += 'IO Device' + $Process += '{0}' -f $InfoPci.model + $Process += '{0}' -f $InfoPci.vendor + if (-not $checkVersion) { + $Process += '{0}' -f $InfoPci.Version + } + else { + $Process += '{0}' -f $checkVersion + } + $Process += '{0}' -f $InfoPci.Status + $Process += 'PCI ID:{0}
Driver:{1} Version:{2}' -f $InfoPci.Pccid, $InfoPci.Driver, $InfoPci.DriverVersion + if ($InfoPci.VcgLink.Count -gt 0) { + $Process += '{0}
' -f $InfoPci.Warnings + foreach ($link in $InfoPci.VcgLink) { + $Process += ' VCG link
' -f $link + } + $Process += '' + } + else + {$Process += '{0}
N/A' -f $InfoPci.Warnings} + $Process += '' + } + } + } + } + $content += $Process + } + $content += $generalFooter + #define filename and filepath + $dataTime = Get-Date -Format 'yyyy-M-d_h-m' + $vcName = vcName($Data) + $filename = 'compreport_' + $vcName + $dataTime + '.html' + $filePath = $Dir + $filename + #save report + $content |Out-File -FilePath $filePath -Encoding utf8| Out-Null + info ("Report " + "'" + $Dir + $filename + "'" + " has been created!") +} + +Function Generate_SummaryReport($Data, $Dir) { + info ("Generating compatibility summary report...") + $content = $summaryHead + $vcCount = $Data.length + $barsWidth = 45 / ($vcCount+1) + $content += 'var barsWidth = {0};' -f $barsWidth + # get vCName arry and host count + $vcNameArray = @() + foreach ($DCResource in $Data) { + $vcNameArray += $DCResource.DCResource[0].vcname + } + + $content += "var vCname = [" + foreach ($vc in $vcNameArray) { + $content += '"{0}",' -f $vc + } + $content += "];" + # Count Compatible or unpgrade + $compatibleCountFormat = '[' + $mayNotCompatibleCountFormat = '[' + $UnabletoUpgradeCountFormat = '[' + foreach ($VCResource in $Data) { + $checkVersion = $VCResource.checkRelease + $compatibleCount = 0 + $notcompatibleCount = 0 + $UnabletoUpgradeCount = 0 + foreach ($DCResource in $VCResource.DCResource) { + foreach ($HostResourceOne in $DCResource.HostResource) { + foreach ($OneDevice in $HostResourceOne.ComponentResource) { + $flagcompatible = 0 + # if($checkVersion){ + # if(-not($OneDevice.upgrade)){ + # $flagcompatible = 'null' + # break + # } + # } + #whether compatible + if ($OneDevice.status -ne 'Compatible') { + $flagcompatible = 0 + break + } + else { + $flagcompatible = 1 + } + #whether upgrade + } + + if ($flagcompatible -eq 1) { + $compatibleCount += 1 + } + elseif($flagcompatible -eq 0){ + $notcompatibleCount += 1 + } + + elseif($flagcompatible -eq 'null') { + $UnabletoUpgradeCount += 1 + } + } + } + $compatibleCountFormat += $compatibleCount + $compatibleCountFormat += ',' + $mayNotCompatibleCountFormat += $notcompatibleCount + $mayNotCompatibleCountFormat += ',' + $UnabletoUpgradeCountFormat += $UnabletoUpgradeCount + $UnabletoUpgradeCountFormat += ',' + } + $compatibleCountFormat += ',]' + $mayNotCompatibleCountFormat += ',]' + $UnabletoUpgradeCountFormat += ']' + + $dataDict = [Ordered]@{} + + if (-not(checkVersion($Data))) { + $content += 'var lengendSeries = ["Compatible","May Not Compatible"];' + $content += $hostCountHead + + $dataDict.Insert(0, "Compatible", $compatibleCountFormat) + $dataDict.Insert(1, "May Not Compatible", $mayNotCompatibleCountFormat) + } + else { + $content += 'var lengendSeries = ["Compatible","May Not Compatible","Unable to upgrade"];' + $content += $hostCountHead + + $dataDict.Insert(0, "Compatible", $compatibleCountFormat) + $dataDict.Insert(1, "May Not Compatible", $mayNotCompatibleCountFormat) + $dataDict.Insert(2, "Unable to upgrade", $UnabletoUpgradeCountFormat) + } + [System.Collections.IEnumerator]$dataDict = $dataDict.Keys.GetEnumerator(); + $formatContent = formatHostCountGraphic $dataDict + + $content += $formatContent + $content += $hostCountRest + + + # Host Compatibility + $compatibleCount = 0 + $mayNotcompatibleCount = 0 + $unableUpgradeCount = 0 + foreach ($VCResource in $Data) { + foreach ($DCResource in $VCResource.DCResource) { + foreach ($HostResourceOne in $DCResource.HostResource) { + foreach ($OneDevice in $HostResourceOne.ComponentResource) { + #whether compatible + $flagcompatible = 0 + # if ($checkVersion){ + # if (-not($OneDevice.upgrade)){ + # $flagcompatible = 'null' + # break + # } + # } + if ($OneDevice.status -ne 'Compatible') { + $flagcompatible = 0 + break + } + else { + $flagcompatible = 1 + } + + } + if ($flagcompatible -eq 1) { + $compatibleCount += 1 + } + elseif ($flagcompatible -eq 0) { + $mayNotcompatibleCount += 1 + } + elseif ($flagcompatible -eq 'null') { + $unableUpgradeCount += 1 + } + } + } + } + + if (-not(checkVersion($Data))) { + $content += "var seriesCount = {'Compatible':$compatibleCount, 'May Not Compatible':$mayNotcompatibleCount,};" + $content += "var lengendSeries = ['Compatible','May Not Compatible'];" + $content += "var catalog = [ + {value:seriesCount['Compatible'], name:'Compatible'}, + {value:seriesCount['May Not Compatible'], name:'May Not Compatible'}, + ];" + $content += "var colors = [colorsC,colorsM];" + } + else { + $content += "var seriesCount = {'Compatible':$compatibleCount, 'May Not Compatible':$mayNotcompatibleCount,'Unable to Upgrade':$unableUpgradeCount};" + $content += "var lengendSeries = ['Compatible','May Not Compatible','Unable to Upgrade'];" + $content += "var catalog = [ + {value:seriesCount['Compatible'], name:'Compatible'}, + {value:seriesCount['May Not Compatible'], name:'May Not Compatible'}, + {value:seriesCount['Unable to Upgrade'], name:'Unable to Upgrade'}, + ];" + $content += "var colors = [colorsC,colorsM,colorsU];" + } + + $content += $hostCompatible + + + #Host Model Compatibility by vCenter + if (-not(checkVersion($Data))) { + $serverSource = "[['series', 'Compatible', 'May Not Compatible',]," + } + else { + $serverSource = "[['series', 'Compatible','May Not compatible','No Upgrade Path']," + } + + foreach ($VCResource in $Data) { + $compatibleCount = 0 + $mayNotCompatibleCount = 0 + $unableUpgradeCount = 0 + $checkVersion = $VCResource.checkRelease + foreach ($DCResourceOne in $VCResource.DCResource) { + foreach ($HostResourceOne in $DCResourceOne.HostResource) { + $flagcompatible = 0 + foreach ($ComoenentResourceOne in $HostResourceOne.ComponentResource) { + #whether compatible + if ($ComoenentResourceOne.type -eq 'Server') { + # if ($checkVersion) { + # if (-not($ComoenentResourceOne.upgrade)) { + # $flagcompatible = 'null' + # break + # } + # } + if ($ComoenentResourceOne.status -ne 'Compatible') { + $flagcompatible = 0 + } + else { + $flagcompatible = 1 + } + break + + } + } + if ($flagcompatible -eq 1) { + $compatibleCount += 1 + } + elseif ($flagcompatible -eq 0) { + $mayNotcompatibleCount += 1 + } + elseif ($flagcompatible -eq 'null') { + $unableUpgradeCount += 1 + } + } + } + if (-not $checkVersion) { + $serverSource += '["{0}",{1},{2}],' -f $DCResourceOne.vcname, $compatibleCount, $mayNotCompatibleCount + } + else { + $serverSource += '["{0}",{1},{2},{3}],' -f $DCResourceOne.vcname, $compatibleCount, $mayNotCompatibleCount, $unableUpgradeCount + } + } + $serverSource += '];' + $content += 'var serverSource = {0}' -f $serverSource + $content += $hostModelCompatibleHead + + if (-not $checkVersion) { + $colorsArray = 'colorsC', 'colorsM' + } + else { + $colorsArray = 'colorsC', 'colorsM', 'colorsU' + } + foreach ($colors in $colorsArray) { + $content += $hostModelCompatibleBody + $content += "color:$colors}," + } + $content += $hostModelCompatibleRest + + #count IO Device compatibility by vCenter + if (-not(checkVersion($Data))) { + $ioSource = "[['series', 'Compatible', 'May Not Compatible',]," + } + else { + $ioSource = "[['series', 'Compatible','May Not Compatible','No Upgrade Path',]," + } + + foreach ($VCResource in $Data) { + $compatibleCount = 0 + $mayNotCompatibleCount = 0 + $unableUpgradeCount = 0 + $checkVersion = $VCResource.checkRelease + foreach ($DCResourceOne in $VCResource.DCResource) { + foreach ($HostResourceOne in $DCResourceOne.HostResource) { + $flagcompatible = 0 + foreach ($ComoenentResourceOne in $HostResourceOne.ComponentResource) { + if ($ComoenentResourceOne.type -eq 'IO Device') { + # if ($checkVersion) { + # if (-not($ComoenentResourceOne.upgrade)) { + # $flagcompatible = 'null' + # } + # } + if ($ComoenentResourceOne.status -ne 'Compatible') { + $flagcompatible = 0 + } + else { + $flagcompatible = 1 + } + + if ($flagcompatible -eq 1) { + $compatibleCount += 1 + } + elseif ($flagcompatible -eq 0) { + $mayNotCompatibleCount += 1 + } + elseif ($flagcompatible -eq 'null') { + $unableUpgradeCount += 1 + } + } + } + + } + } + if (-not $checkVersion) { + $ioSource += '["{0}",{1},{2}],' -f $DCResourceOne.vcname, $compatibleCount, $mayNotCompatibleCount + } + else { + $ioSource += '["{0}",{1},{2},{3}],' -f $DCResourceOne.vcname, $compatibleCount, $mayNotCompatibleCount, $unableUpgradeCount + } + } + + $ioSource += '];' + $content += 'var ioSource = {0}' -f $ioSource + $content += $ioCompatibleHead + if (-not $checkVersion) { + $colorsArray = 'colorsC', 'colorsM' + } + else { + $colorsArray = 'colorsC', 'colorsM', 'colorsU' + } + foreach ($colors in $colorsArray) { + $content += $ioCompatibleBody + $content += "color:$colors}," + } + $content += $ioCompatibleRest + + $dataTime = Get-Date -Format 'yyyy-M-d_h-m' + $vcName = vcName($Data) + $filename = 'sumreport_' + $vcName + $dataTime + '.html' + $filePath = $Dir + $filename + # Out-put a html report + $content |Out-File -FilePath $filePath -Encoding utf8| Out-Null + info ("Report " + "'" + $Dir + $filename + "'" + " has been created!") +} + +Function Generate_CsvReport($Data, $Dir) { + info("Generating compatibility csv report") + #define header + $content = '' + $content += "VC," + $content += "DataCenter," + $content += "Host," + $content += "Type," + $content += "Model Name," + $content += "Vendor," + if (-not(checkVersion($Data))) { + $content += "Installed Release," + } + else { + $content += "Checked Release," + } + $content += "Compatible Status," + $content += "Hardware Detail," + $content += "Comments," + $content += 'VCG Link,' + $content += "`n" + + #formate content + foreach ($VCResource in $Data) { + $checkVersion = $VCResource.checkRelease + foreach ($DCResourceOne in $VCResource.DCResource) { + foreach ($HostResourceOne in $DCResourceOne.HostResource) { + $installVersion = $HostResourceOne.version + foreach ($ComoenentResourceOne in $HostResourceOne.ComponentResource) { + if ($DCResourceOne.vcname -ne 'null') { + $content += "{0}," -f $DCResourceOne.vcname + } + else { + $content += "{0}," -f '/' + } + #DataCenterDetail + if ($DCResourceOne.dcname -ne 'null') { + $content += "{0}," -f $DCResourceOne.dcname + } + else { + $content += "{0}," -f '/' + } + #Host + $content += "{0}," -f $HostResourceOne.hostname + #Type + $content += "{0}," -f $ComoenentResourceOne.type + #Model Name + $content += '"{0}",' -f $ComoenentResourceOne.model + #Vendor + $content += '"{0}",' -f $ComoenentResourceOne.vendor + if (-not $checkVersion) { + #Installed Release + $content += '"{0}",' -f $installVersion + } + else { + $content += '"{0}",' -f $checkVersion + } + #Status + $content += '"{0}",' -f (formatStatus($ComoenentResourceOne.status)) + #CompatibleHardware + if ($ComoenentResourceOne.type -eq 'IO Device') { + $CompatibleHardware = "'PCI ID:{0}, Driver:{1} {2}" -f $ComoenentResourceOne.pciid, $ComoenentResourceOne.Driver, $ComoenentResourceOne.DriverVersion + } + else { + $CompatibleHardware = "'CPU: {0}(Feature:{1}) BIOS:{2}" -f $ComoenentResourceOne.cpumodel, $ComoenentResourceOne.cpufeatureid, $ComoenentResourceOne.biosversion + } + $content += '"{0}",' -f $CompatibleHardware + + #Comments + + if ($ComoenentResourceOne.Warnings.Count -gt 0) { + $Comments = $ComoenentResourceOne.Warnings + } + else { + $Comments ='N/A' + } + + $content += '"{0}",' -f $Comments + + #VCG Link + $VCGLink = '' + foreach ($link in $ComoenentResourceOne.VcgLink) { + $VCGLink += $link + $VCGLink += ' ' + } + $content += '"{0}",' -f $VCGLink + $content += "`n" + } + } + } + } + + #define filename and path + $dataTime = Get-Date -Format 'yyyy-M-d_h-m' + $vcName = vcName($Data) + $filename = 'compreport_' + $vcName + $dataTime + '.csv' + $filePath = $Dir + $filename + #save csv report + info ("Report " + "'" + $Dir + $filename + "'" + " has been created!") + $content |Out-File -FilePath $filePath -Encoding utf8| Out-Null + return $content +} +Function refactorData ($data) { + $DCResource,$flag = refactorDC $data + $data,$flag = refactorVC $DCResource + return $data, $true +} + +Function refactorDC($data) { + $DCResource = @() + $HostResource = @() + $HR = @{} + $DC = @{} + + $ReData = $data + + $HR.__type__ = $ReData[0].__type__ + $HR.vcname = $ReData[0].vcname + $HR.dcname = $ReData[0].dcname + $HR.hostname = $ReData[0].hostname + $HR.apitype = $ReData[0].apitype + $HR.powerstatus = $ReData[0].powerstatus + $HR.version = $ReData[0].version + $HR.fullname = $ReData[0].fullname + $HR.connectionstatus = $ReData[0].connectionstatus + $HR.ComponentResource = $ReData[0].ComponentResource + $HostResource += $HR # HostResource = [{'hostname':'10.110.126.170'}] + $DC.dcname = $ReData[0].dcname #$DC={'dcname':'ha-datacenter'} + $DC.vcname = $ReData[0].vcname + $DC.HostResource = $HostResource #$DC={'dcname':'ha-datacenter','HostResource':[{'hostname':'10.110.126.170'}]} + $DC.checkRelease = $ReData[0].checkRelease + + $DCResource += $DC #$DCResource = [{'dcname':'ha-datacenter','HostResource':[{'hostname':'10.110.126.170'},]}] + $dcname = $ReData[0].dcname + $vcname = $ReData[0].vcname + $DcIndex = 0 + for ($i = 1; $i -lt $ReData.Count; $i++) { + $temp = $ReData[$i] + $HR = @{} + if ($temp.dcname -eq $dcname -and $temp.vcname -eq $vcname) { + $HR.__type__ = $temp.__type__ + $HR.vcname = $temp.vcname + $HR.dcname = $temp.dcname + $HR.hostname = $temp.hostname + $HR.apitype = $temp.apitype + $HR.powerstatus = $temp.powerstatus + $HR.version = $temp.version + $HR.fullname = $temp.fullname + $HR.connectionstatus = $temp.connectionstatus + $HR.ComponentResource = $temp.ComponentResource + $DCResource[$DcIndex].HostResource += $HR + } + else { + $DcIndex += 1 + $DCResource += @{} #$DCResource = [{'dcname':'ha-datacenter','HostResource':[{'hostname':'10.110.126.170'},{'hostname':'10.110.126.171'}]},{}] + $DCResource[$DcIndex].dcname = $temp.dcname # [{'dcname':'ha-datacenter','HostResource':[{'hostname':'10.110.126.170'},{'hostname':'10.110.126.171'}]},{'dcname':'hw-datacenter'}] + $DCResource[$DcIndex].vcname = $temp.vcname + $DCResource[$DcIndex].checkRelease = $temp.checkRelease + $DCResource[$DcIndex].HostResource = @() # [{'dcname':'ha-datacenter','HostResource':[{'hostname':'10.110.126.170'},{'hostname':'10.110.126.171'}]},{'dcname':'hw-datacenter','HostResource':[]}] + $HR = @{} + $HR.__type__ = $temp.__type__ + $HR.vcname = $temp.vcname + $HR.dcname = $temp.dcname + $HR.hostname = $temp.hostname + $HR.apitype = $temp.apitype + $HR.powerstatus = $temp.powerstatus + $HR.version = $temp.version + $HR.fullname = $temp.fullname + $HR.connectionstatus = $temp.connectionstatus + $HR.ComponentResource = $temp.ComponentResource + $DCResource[$DcIndex].HostResource += $HR # [{'dcname':'ha-datacenter','HostResource':[{'hostname':'10.110.126.170'},{'hostname':'10.110.126.171'}]},{'dcname':'hw-datacenter','HostResource':[{'hostname':'10.110.126.173'}]}] + $dcname = $temp.dcname + $vcname = $temp.vcname + } + } + return $DCResource,$true + # return $DCResource +} + +Function refactorVC ($data) { + $VCResource = @() + $DCResource = @() + $VC = @{} + $DCResource += $data[0] + $VC.DCResource = $DCResource + $VC.hostname = $data[0].vcName + $VC.checkRelease = $data[0].checkRelease + + $VCResource += $VC + $vcname = $data[0].vcname + $VcIndex = 0 + for ($i = 1 ; $i -lt $data.Count; $i++){ + $temp = $data[$i] + if ($vcname -eq $temp.vcname) { + $VCResource[$VcIndex].DCResource += $temp + } + else { + $VcIndex += 1 + $DCResource = @() + $VC = @{} + $DCResource += $temp + $VC.hostname = $temp.vcName + $VC.DCResource = $DCResource + $VC.checkRelease = $temp.checkRelease + $VCResource += $VC + $vcname = $temp.vcname + } + } + return $VCResource,$true +} + +Function vcName($Data) { + $vcName = '' + foreach ($VCResource in $Data) { + $vcName += $VCResource.hostname + $vcName += '_' + } + return $vcName +} + +Function checkVersion($Data) { + foreach ($VCResource in $Data) { + $checkVersion = $VCResource.checkRelease + return $checkVersion + } +} + +Function formatStatus($status) { + if ($status -eq 'MayNotBeCompatible') { + return 'May Not Be Compatible' + } + else { + return $status + } +} + +Function formatHostCountGraphic($dataDict) { + while ($dataDict.MoveNext()) { + $items = $dataDict.Key + + if ($items -eq 'Compatible') { + $colors = 'colorsC' + } + elseif ($items -eq 'May Not Compatible') { + $colors = 'colorsM' + } + elseif ($items -eq 'Unable to upgrade') { + $colors = 'colorsU' + } + + $content += $hostCountBody + $items = "'{0}'" -f $items + $content += 'name: {0},' -f $items + $content += 'data: {0},' -f $dataDict.Value + $content += 'color: {0},' -f $colors + $content += '},' + } + + return $content +} + + +#Detail report +$generalHead = @' + + + + + + + + + ESXi Compatible Report + + + +'@ + +$generalBodyBase = @' +

[WARNING] The compatible status may not be fully accurate, please validate it with the official VMware Compatibility Guide

+ + +
+ + + + + + + + + + +'@ + +$generalBodyRest = @' + + + + + + +'@ + +$generalFooter = @' + +
VCDataCenterHostTypeModel NameVendorCompatible StatusHardware DetailComments
+
+ + + +'@ + + +#Summary report +$summaryHead = @' + + + + + Summary Report + + + + + + + +
+
+
+
+
+ +
+ + +'@ + diff --git a/Modules/VMware.VCGChecker/Get-VCGHWInfo.ps1 b/Modules/VMware.VCGChecker/Get-VCGHWInfo.ps1 new file mode 100644 index 0000000..229608f --- /dev/null +++ b/Modules/VMware.VCGChecker/Get-VCGHWInfo.ps1 @@ -0,0 +1,310 @@ +<# +Copyright 2018 VMware, Inc. All rights reserved. +#> + +# Class to manage Host resources +Class HostResource { + [VMware.VimAutomation.Types.VMHost] $vmhost + [string] $vcname + [string] $clustername + [string] $dcname + [string] $hostname + [string] $apitype + [string] $powerstatus + [string] $productname + [string] $version + [string] $fullname + [string] $connectionstatus + [string] $checkRelease + [int] $port + [Array] $ComponentResource = @() + [Array] $JsonProperties = @('__type__', 'dcname', 'vcname','clustername','hostname', 'apitype', + 'powerstatus', 'productname', 'version', 'fullname', 'connectionstatus','checkRelease') + + HostResource( + [VMware.VimAutomation.Types.VMHost] $vmhost) { + $this.vmhost = $vmhost + $view =$vmhost|Get-View + $vCenter_IP = $view.Summary.ManagementServerIp + if($vCenter_IP){ + $this.vcname =$vCenter_IP + $this.dcname = (Get-Datacenter -VMHost $vmhost).Name + $this.clustername = (Get-Cluster -VMHost $vmhost).Name + }else{ + $this.vcname =$this.vmhost.Name + } + $this.hostname = $this.vmhost.Name + $summary = $this.vmhost.ExtensionData.Summary + $this.powerstatus = $summary.runtime.powerState + $this.connectionstatus = $summary.runtime.connectionState + $this.apitype = $summary.Config.Product.apiType + $this.fullname = $summary.Config.Product.FullName + $this.version = $summary.Config.Product.version + $this.productname = $summary.Config.Product.licenseProductName + $this.port = 443 + } + + [Array] query_components() { + if ($this.ComponentResource.Count -eq 0) { + # Get server info + for($count_retry=0;$count_retry -lt 3;$count_retry ++){ + try{ + $svrResoure = [ServerResource]::new() + $svrResoure.set_data($this.vmhost) + $this.ComponentResource += $svrResoure + break + }catch{ + error('query components server for '+$this.vmhost.Name +' error, retry it ' +($count_retry+1) +' times') + } + } + # Get PCI devices + for($count_retry=0;$count_retry -lt 3;$count_retry ++){ + try{ + $this.query_pcidevices() + break + }catch{ + error('query components pcidevice for '+$this.vmhost.Name +' error, retry it ' +($count_retry+1) +' times') + if($count_retry -eq 2){ + error('query components pcidevice for '+$this.vmhost.Name +' faild') + } + } + } + } + return $this.ComponentResource + } + + [void] query_pcidevices() { + $EsxCliV2 = Get-EsxCli -V2 -VMHost $this.vmhost + $AllPciDevice = $EsxCliV2.hardware.pci.list.invoke() + foreach ($Pci in $AllPciDevice) { + # Ignore USB controllers, iLO/iDRAC devices + if ($Pci.DeviceName -like "*USB*" -or $Pci.DeviceName -like "*iLO*" -or $Pci.DeviceName -like "*iDRAC*") { + continue + } + # Get the NICs and storage adapters. + # We found NIC and storage adapters usually have module ID other than 0 or 1 + $pciDevice = [IoDeviceResource]::new() + if ($Pci.ModuleID -ne 0 -and $Pci.ModuleID -ne -1) { + if (!$this.is_pcidevice_exist($Pci)) { + $pciDevice.set_data($Pci, $EsxCliV2) + $this.ComponentResource += $pciDevice + } + } + } + } + + [boolean] is_pcidevice_exist($device) { + foreach ($pci in $this.ComponentResource) { + if ($pci.psobject.TypeNames[0] -eq "IoDeviceResource") { + $vid = [String]::Format("{0:x4}", [int]$device.VendorID) + $did = [String]::Format("{0:x4}", [int]$device.DeviceID) + $svid = [String]::Format("{0:x4}", [int]$device.SubVendorID) + $ssid = [String]::Format("{0:x4}", [int]$device.SubDeviceID) + if ($pci.vid -eq $vid -and $pci.did -eq $did -and + $pci.svid -eq $svid -and $pci.ssid -eq $ssid) { + return $true + } + } + } + return $false + } + + [object] to_jsonobj() { + $Json = $this | Select-Object -Property $this.JsonProperties + $ComponentChildren = @() + $this.ComponentResource | ForEach-Object {$ComponentChildren += $_.to_jsonobj()} + $Json | Add-Member -Name "ComponentResource" -Value $ComponentChildren -MemberType NoteProperty + + return $Json + } + + [string] get_host_status() { + if ($this.powerstatus -and $this.powerstatus -ne 'unknown') { + return $this.powerstatus + } + if ($this.connectionstatus) { + return ("Server " + $this.connectionstatus) + } + else { + return "Server status is unknown" + } + } + + [string] get_prompt_name() { + if ($this.apitype) { + $start = $this.apitype + } + else { + $start = "Host" + } + return $start + " " + $this.hostname + } +} + + +# Class to manage server resources +Class ServerResource { + [string] $type + [string] $model + [string] $vendor + [string] $biosversion + [string] $cpumodel + [string] $cpufeatureid + [string] $uuid + [string] $status + [array] $matchResult + [array] $warnings + [string] $vcgLink + [array] $updateRelease + + [VMware.VimAutomation.Types.VMHost] $vmhost + [Array] $JsonProperties = @('__type__','type', 'model', 'vendor', 'biosversion', + 'cpumodel', 'cpufeatureid', 'uuid','status','matchResult','warnings','vcgLink','updateRelease') + + + [void] set_data( + [VMware.VimAutomation.Types.VMHost] $vmhost) { + $this.vmhost = $vmhost + $this.type = "Server" + $this.model = $this.vmhost.Model + $this.vendor = $this.vmhost.Manufacturer + $this.biosversion = $this.vmhost.ExtensionData.Hardware.BiosInfo.BiosVersion + $this.cpumodel = $this.vmhost.ProcessorType + $cpuFeature = $this.vmhost.ExtensionData.Hardware.CpuFeature + if ($cpuFeature -and $cpuFeature.Count -gt 2) { + $this.cpufeatureid = $this.vmhost.ExtensionData.Hardware.CpuFeature[1].Eax + } + $this.uuid = $this.vmhost.ExtensionData.Hardware.systeminfo.uuid + } + + [object] to_jsonobj() { + return $this | Select-Object -Property $this.JsonProperties + } + +} + +# Class to manage each IO device +Class IoDeviceResource { + + [string] $type + [string] $model + [string] $deviceid + [string] $device + [string] $comptype + [string] $vid + [string] $did + [string] $svid + [string] $ssid + [string] $pciid + [string] $vendor + [string] $driver + [string] $driverversion + [string] $firmware + [string] $status + [array] $matchResult + [array] $warnings + [string] $vcgLink + [array] $updateRelease + + [Array] $JsonProperties = @('__type__','type', 'model', 'deviceid', 'device', + 'comptype', 'vid', 'did', 'svid', 'ssid', 'pciid', + 'vendor', 'driver', 'driverversion', 'firmware','status','matchResult','warnings','vcgLink','updateRelease') + + [void] set_data( + [object] $pci, + [object] $EsxCli) { + $this.type = "IO Device" + $this.model = $Pci.DeviceName + $this.deviceid = $pci.Address + $this.device = $pci.VMKernelName + $this.vid = [String]::Format("{0:x4}", [int]$Pci.VendorID) + $this.did = [String]::Format("{0:x4}", [int]$Pci.DeviceID) + $this.svid = [String]::Format("{0:x4}", [int]$Pci.SubVendorID) + $this.ssid = [String]::Format("{0:x4}", [int]$Pci.SubDeviceID) + $this.pciid = $this.vid + ":" + $this.did + ":" + $this.svid + ":" + $this.ssid + $this.vendor = $pci.VendorName + $this.driver = $Pci.ModuleName + $this.driverversion = "N/A" + $this.firmware = "N/A" + + + # Set component type and driverversion, firmware + if ($this.device -match 'nic') { + $arg = @{} + $arg['nicname'] = $this.device + $nic = $EsxCli.network.nic.get.invoke($arg) + $this.comptype = "Physical NIC" + $this.driverversion = $nic.driverinfo.Version + $this.firmware = $nic.driverinfo.FirmwareVersion + } + elseif ($this.device -match 'hba') { + $arg = @{} + $arg['module'] = $this.driver + $module = $EsxCli.system.module.get.invoke($arg) + $this.comptype = "Storage Adapter" + $this.driverversion = $module.Version + } + } + + [object] to_jsonobj() { + return $this | Select-Object -Property $this.JsonProperties + } + + [string] get_id_detail() { + return $this.driver + " (PCIId:" + $this.pciid + ")" + } +} + +# Class to manage IO device group +Class IoDeviceResourceGroup { + [Array] $iodevices = @() + [Array] $nics = @() + [Array] $adapters = @() + + [void] append_nic([IODeviceResource] $nic) { + $this.iodevices += $nic + $this.nics += $nic + } + + [void] append_storage_adapter([IODeviceResource] $adapter) { + $this.iodevices += $adapter + $this.adapters += $adapter + } + + [boolean] has_nics() { + return $this.nics.Count > 0 + } + + [boolean] has_storage_adapters() { + return $this.adapters.Count > 0 + } + +} + + +# +# Collect hardware inventory data from all the hosts +# +Function Get-VCGHWInfo { + Param( + [Parameter(Mandatory=$true)] $vmHosts + ) + # Collect the hardware data + $Data = @() + foreach($vmHost in $vmHosts) { + $vm = [HostResource]::new($vmHost) + try { + info ("Collecting hardware data from " + $vm.hostname) + $null = $vm.query_components() + if($vm.powerstatus -eq 'poweredOn' -and $vm.connectionstatus -eq 'connected'){ + $Data += $vm + info ("Collecting hardware data from " + $vm.hostname +' success') + } + } + catch { + error ("Failed to collect hardware data from " + $vm.hostname) + } + } + + return $Data +} \ No newline at end of file diff --git a/Modules/VMware.VCGChecker/Get-VCGStatus.ps1 b/Modules/VMware.VCGChecker/Get-VCGStatus.ps1 new file mode 100644 index 0000000..0f7a5de --- /dev/null +++ b/Modules/VMware.VCGChecker/Get-VCGStatus.ps1 @@ -0,0 +1,168 @@ +$Uuid = [guid]::NewGuid() +$Headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" +$Headers.add("x-request-id", $Uuid) +$Headers.add("x-api-toolid", "180209100001") +$Headers.add("x-api-key", "SJyb8QjK2L") +$Url_Perfix = 'https://apigw.vmware.com/m4/compatibility/v1' +$Url = $Url_Perfix + "/compatible/servers/search?" +$UrlPci = $Url_Perfix + "/compatible/iodevices/search?" +$apiQurryDict=@{} + +# +# Ping remote api server. +# +Function PingApiServer(){ + $apiServerIp='apigw.vmware.com' + $results =Test-NetConnection $apiServerIp -InformationLevel 'Quiet' + if($results -ne $true){ + error ("Failed to access VMware Compatibility API, + Unable to use comparison function, only view basic hardware information; + you can use 'Get-VCGHWInfo -g ' create hardware json, + then use 'Check-VCGStatus -f ' load hardware json file to comapre when connect an available network") + Exit(1) + } +} + +# +# Get the web request. +# +Function Get-WebRequest($VCGurl) { + try { + $req = Invoke-WebRequest -Headers $Headers -Uri $VCGUrl -ErrorVariable $err -UseBasicParsing + } + catch { + if ($err[0].errorrecord.exception.response) { + error ("WebReponse code:" + $err[0].errorrecord.exception.response.statuscode.value__) + error ($exitScript) + Exit(1) + } + else { + error ("Failed to check " + $type + " data for " + $HostResource.hostname) + error ("Failed to access VMware Compatibility API, please check your Internet connection or contact VMware Compatibility API administrator") + error ("Exit the script") + Exit(1) + } + } + return $req +} + +Function Get-RemoteApiTitleString([object]$device,$EsxiVersion){ + if ($device.type -eq 'Server') { + $Title = $device.model + $device.vendor + $device.cpufeatureid + $device.biosversion +$EsxiVersion + } + else{ + $Title = $device.vid + $device.did + $device.Svid + $device.Ssid + $EsxiVersion + } + return $Title +} + +Function Get-ResponseFromApi([object]$device,$EsxiVersion){ + if ($device.type -eq 'Server') { + $VCGUrl = $Url + "model=" + $device.model + "&releaseversion=" + $EsxiVersion ` + + "&vendor=" + $device.vendor + "&cpuFeatureId=" + $device.cpufeatureid ` + + "&bios=" + $device.biosversion + debug ("Model:" + $device.model) + debug ("VCG Url:" + $VCGUrl) + $Headers.GetEnumerator() | ForEach-Object {debug ("Req Header:" + $_.key + ":" + $_.value)} + $request = Get-WebRequest $VCGUrl + $Response = ConvertFrom-Json -InputObject $request -Erroraction 'silentlycontinue' + } + elseif ($device.type -eq 'IO Device') { + $VCGUrl = $UrlPci + "vid=0X" + $device.vid + "&did=0X" + $device.did + "&svid=0X" + $device.Svid ` + + "&ssid=0X" + $device.Ssid + "&releaseversion=" + $EsxiVersion ` + + "&driver=" + $device.Driver + "&driverversion=" + $device.driverversion + "&firmware=N/A" + debug ("Model:" + $device.model) + debug ("VCG Url:" + $VCGUrl) + $Headers.GetEnumerator() | ForEach-Object {debug ("Req Header:" + $_.key + ":" + $_.value)} + $request = Get-WebRequest $VCGUrl + $Response = ConvertFrom-Json -InputObject $request -Erroraction 'silentlycontinue' + } + return $Response +} +# +# Get the data from api +# +Function Get-VCGData($HostResource) { + foreach ($device in $HostResource.ComponentResource) { + if ($HostResource.checkRelease) { + $EsxiVersion = $HostResource.checkRelease + } + else { + $EsxiVersion = $HostResource.version + } + $temp=0 + $title=Get-RemoteApiTitleString $device $EsxiVersion + if($apiQurryDict.Count -eq 0){ + $Response= Get-ResponseFromApi $device $EsxiVersion + $apiQurryDict.Add($title,$Response) + }else{ + foreach($onetitle in $apiQurryDict.keys){ + if($onetitle -eq $title){ + $Response= $apiQurryDict[$onetitle] + $temp=1 + break + } + } + if($temp -eq 0){ + $Response= Get-ResponseFromApi $device $EsxiVersion + $apiQurryDict.Add($title,$Response) + } + } + + if ($Response.matches) { + foreach ($match in $Response.matches) { + $device.vcgLink += [string]$match.vcgLink + } + } + else { + foreach ($potentialMatche in $Response.potentialMatches) { + $device.vcgLink += [string]$potentialMatche.vcgLink + } + } + $device.status = [string]$Response.searchResult.status + $device.matchResult = [string]$Response.searchResult.matchResult + $device.warnings = $Response.searchResult.warnings + $device.updateRelease = [string]$Response.searchOption.foundRelease + } +} + +# +# Send the hardware data to VCG API and handle returned result +# +Function Get-DataFromRemoteApi([object]$servers) { + info ("Checking hardware compatibility result with VMware Compatibility Guide API...") + info ("This may take a few minutes depending on your network.") + for ($idx = 0; $idx -lt $servers.Count; $idx++) { + $server = $servers[$idx] + $i = $idx + 1 + info ([string]$i + "/" + [string]$servers.Count + " - Checking hardware compatibility results for " + $server.hostname) + if (!$server -or $server.ComponentResource.Count -eq 0) { + error('Failed to get the hardware info.') + Exit(1) + } + Get-VCGData $server + } + return $servers +} + +Function Get-VCGStatus{ + Param( + [Parameter(Mandatory=$true)] $Data, + [Parameter(Mandatory=$false)] $Version + ) + $checkRelease = $Version + PingApiServer + + foreach ($vmHost in $Data) { + # $vmHost|add-member -Name "checkRelease" -value $checkRelease -MemberType NoteProperty -Force + $vmHost.checkRelease=$checkRelease + } + + $results = Get-DataFromRemoteApi($Data) + if ($results.Count -eq 0) { + error ("Failed to get compatibility results. No report will be generated") + error ("Exit the script") + Exit(1) + } + return $results +} \ No newline at end of file diff --git a/Modules/VMware.VCGChecker/README.md b/Modules/VMware.VCGChecker/README.md new file mode 100644 index 0000000..a38c064 --- /dev/null +++ b/Modules/VMware.VCGChecker/README.md @@ -0,0 +1,41 @@ +# About +This module is designed to ease the work of collecting hardware inventory data and compare it with VMware's official VCG data. Before deploying vSphere, it is required to validate your physical machines with VCG to make sure all the devices in your physical machines are compatible with the vSphere version you want to install. It is a time-consuming and painful experience to collect hardware/driver/firmware data from all of the machines, especially when you have a huge number of machines in your data center. + +# How It Works +By using this module, it will automate the data collection and comparison work. + +When running the module, it will connect to the target vCenter or ESXi to read the hardware data. It is a read-only operation and nothing on the target hosts will be changed. There is almost no impact on the machine's performance as the read operation takes just few seconds. + +The module will then send your hardware inventory data to VMware's offical website to conduct a compatibility check. The result will be 'Compatible', 'May not be compatible' or 'Not compatible'. +* Compatible: the hardware is compatible with the given vSphere release. Link to that VCG page will be provided. +* May not be compatible: manual check is required to confirm the compatibility status of this hardware. A few potential matching VCG records will be provided. +* Not compatible: the hardware is not compatible with the given vSphere release. + +After the checking is completed, the module will generate reports in different formats for your review and future use. A summary view in html will give you an overview of your machines compatibility status; an html file with device details to view each device/driver/firmware you have, their compatibility with vSphere version you specified and links to the corresponding VCG documents online; a csv file with device details to allow customization on report in Excel or by your own tool. + +# Usage +Considering many data center may have control on internet access, we create 3 cmdlets to meet various situations. +* Get-VCGHWInfo: cmdlet to collect hardware info +* Get-VCGStatus: cmdlet to check hardware compatibility by query VCG website +* Export-VCGReport: cmdlet to export the summary/html/csv reports + +1. You need to first import this module after you import PowerCLI module +PS> Import-Module + +2. Connect to the target vSphere hosts using Connect-VIServer and get VMHosts +PS> Connect-VIServer -Server -User -Password +PS> $vmhosts = Get-VMHost + +3. Collect the hardware data +PS> $hwdata = Get-VCGHWInfo -vmHosts $vmhosts +Note: if you don't have internet access, you need to connect your client to internet before proceeding to the next step. + +4. Specify the target vSphere release you want to check and submit the hardware data to VMware website +PS> $vcgdata= Get-VCGStatus -Data $hwdata -Version '' + +5. Save the compatibility reports +PS> Export-VCGReport -Data $vcgdata -Dir + +# Known Limitation +* The module is not able to get the firmware version for HBA devices. +* The module is not able to get the HDD/SSD data. \ No newline at end of file diff --git a/Modules/VMware.VCGChecker/Save-VCGJsonFile.ps1 b/Modules/VMware.VCGChecker/Save-VCGJsonFile.ps1 new file mode 100644 index 0000000..785fc00 --- /dev/null +++ b/Modules/VMware.VCGChecker/Save-VCGJsonFile.ps1 @@ -0,0 +1,17 @@ +Function Save-VCGJsonFile{ + Param( + [Parameter(Mandatory=$true)] $FileName, + [Parameter(Mandatory=$true)] $Data, + [Parameter(Mandatory=$true)] $Dir + ) + $json = @() + $Data | ForEach-Object { $json += $_.to_jsonobj()} + + if (!(Test-Path $Dir)) { + New-Item -Type directory -Confirm:$false -Path $Dir -Force |Out-Null + } + + $Path= $Dir + '\' + $FileName + '.json' + info ("Saving data to " + $Path) + ConvertTo-Json -Depth 10 -Compress $json | Out-File -encoding 'UTF8' -FilePath $Path +} \ No newline at end of file diff --git a/Modules/VMware.VCGChecker/VMware.VCGChecker.psd1 b/Modules/VMware.VCGChecker/VMware.VCGChecker.psd1 new file mode 100644 index 0000000..12493af --- /dev/null +++ b/Modules/VMware.VCGChecker/VMware.VCGChecker.psd1 @@ -0,0 +1,90 @@ +# +# Module manifest for module 'VMware.VCGChecker' +# +# Generated by: fdai@vmware.com, zhangta@vmware.com, linweij@vmware.com +# +# Generated on: 11/15/18 +# + +@{ + + # Script module or binary module file associated with this manifest. + # RootModule = 'VMware.VCGChecker.psm1' + + # Version number of this module. + ModuleVersion = '1.0.0' + + # Supported PSEditions + # CompatiblePSEditions = @() + + # ID used to uniquely identify this module + # GUID = '' + + # Author of this module + Author = 'Frank Dai, Tao Zhang, Linwei Jiang' + + # Company or vendor of this module + CompanyName = 'VMware' + + # Copyright statement for this module + Copyright = '(c) 2018 VMware. All rights reserved.' + + # Description of the functionality provided by this module + Description = 'PowerShell Module for Checking Hardware Compatibility Status' + + RequiredModules = @('VMware.VimAutomation.Core') + + # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess + NestedModules = 'Get-VCGHWInfo.ps1','Get-VCGStatus.ps1','Export-VCGReport.ps1', 'Save-VCGJsonFile.ps1', 'logger.ps1' + + # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. + FunctionsToExport = 'Get-VCGHWInfo', 'Get-VCGStatus', 'Export-VCGReport', 'Save-VCGJsonFile' + # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. + CmdletsToExport = @() + + # Variables to export from this module + VariablesToExport = '*' + + # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. + AliasesToExport = @() + + # DSC resources to export from this module + # DscResourcesToExport = @() + + # List of all modules packaged with this module + # ModuleList = @() + + # List of all files packaged with this module + # FileList = @() + + # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. + PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + # Tags = @() + + # A URL to the license for this module. + # LicenseUri = '' + + # A URL to the main website for this project. + # ProjectUri = '' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + # ReleaseNotes = '' + + } # End of PSData hashtable + + } # End of PrivateData hashtable + + # HelpInfo URI of this module + # HelpInfoURI = '' + + # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. + # DefaultCommandPrefix = '' + + } \ No newline at end of file diff --git a/Modules/VMware.VCGChecker/logger.ps1 b/Modules/VMware.VCGChecker/logger.ps1 new file mode 100644 index 0000000..686611a --- /dev/null +++ b/Modules/VMware.VCGChecker/logger.ps1 @@ -0,0 +1,112 @@ +<# +Copyright 2018 VMware, Inc. All rights reserved. + +#> + +# Messages +$HEADER_OK = "[OK] " +$HEADER_INFO = "[INFO] " +$HEADER_WARNING = "[WARNING] " +$HEADER_ERR = "[ERROR] " + +Class DebugLog +{ + # Static variables of the logger class + static [string] $CAFILE_PATH = "./.certs/" + + [boolean] $debug + [string] $logfile + + DebugLog() + { + $this.debug = $false + $this.logfile = $null + if (!(Test-Path $this::CAFILE_PATH)) + { + New-Item -Type directory -Confirm:$false -Path $this::CAFILE_PATH + } + } + + [void] SetDebug( + [boolean] $debug, + [string] $hostname + ){ + if (!$hostname) {$hostname = ''} + $this.debug = $debug + if ($this.debug) + { + $this.logfile = $this::CAFILE_PATH + $hostname + [DateTime]::Now.ToString("_yyyy-MM-dd_HH-mm") + ".log" + }else{ + $this.logfile = $null + } + } + + [void] log_vars( + [string] $message, + [object] $var + ){ + $this.log($message + $var) + } + + [void] log( + [string] $message + ){ + if (!$this.debug -or !$this.logfile) {return} + try + { + $message | Out-File $this.logfile -Append + }catch { + Out-Host -InputObject ("[Exception] Failed to write to a logfile: " + $this.logfile) + Out-Host -InputObject $_ + } + } +} + +Function debug_vars( + [string] $message, + [object] $var) +{ + $logger.log_vars($message, $var) +} + +Function debug( + [string] $message) +{ + $logger.log($message) +} + +Function vcglog( + [string] $message, + [string] $header="") +{ + $msg = $header + $message + $logger.log($msg) + Out-Host -InputObject $msg +} + +Function ok( + [string] $message) +{ + vcglog $message $HEADER_OK +} + +Function warning( + [string] $message) +{ + vcglog $message $HEADER_WARNING +} + +Function info( + [string] $message) +{ + vcglog $message $HEADER_INFO +} + +Function error( + [string] $message) +{ + vcglog $message $HEADER_ERR +} + +$logger = [DebugLog]::new() +$logger.SetDebug($true, "vcc-debug") \ No newline at end of file From 82b32df293620cc3c4cb41dfac018467ac21e143 Mon Sep 17 00:00:00 2001 From: Adrian Moseley Date: Wed, 21 Nov 2018 16:53:37 -0600 Subject: [PATCH 03/43] Verbage for DeleteFromDisk if False --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index c58e1c0..06527a4 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -10171,7 +10171,7 @@ $deleteSpec.DeleteFromDisk = $DeleteFromDisk $deleteSpec.ArchivePersistentDisk = $false #Delete the machines -write-host "Attempting to Delete:" +if($DeleteFromDisk){write-host "Attempting to Delete:"}else{write-host "Attempting to remove from inventory:"} Write-Output ($deleteMachine.base.Name -join "`n") $bye = $machineService.Machine_DeleteMachines($services,$deleteMachine.id,$deleteSpec) From 1ce8b927ce6d890013df8036ed8167f42df6f424 Mon Sep 17 00:00:00 2001 From: dzl84 Date: Tue, 27 Nov 2018 17:17:46 +0800 Subject: [PATCH 04/43] Update README.md --- Modules/VMware.VCGChecker/README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Modules/VMware.VCGChecker/README.md b/Modules/VMware.VCGChecker/README.md index a38c064..1aa9a58 100644 --- a/Modules/VMware.VCGChecker/README.md +++ b/Modules/VMware.VCGChecker/README.md @@ -19,23 +19,23 @@ Considering many data center may have control on internet access, we create 3 cm * Get-VCGStatus: cmdlet to check hardware compatibility by query VCG website * Export-VCGReport: cmdlet to export the summary/html/csv reports -1. You need to first import this module after you import PowerCLI module +1. You need to first import this module after you import PowerCLI module PS> Import-Module -2. Connect to the target vSphere hosts using Connect-VIServer and get VMHosts -PS> Connect-VIServer -Server -User -Password +2. Connect to the target vSphere hosts using Connect-VIServer and get VMHosts +PS> Connect-VIServer -Server <server> -User <username> -Password <password> PS> $vmhosts = Get-VMHost -3. Collect the hardware data -PS> $hwdata = Get-VCGHWInfo -vmHosts $vmhosts +3. Collect the hardware data +PS> $hwdata = Get-VCGHWInfo -vmHosts $vmhosts Note: if you don't have internet access, you need to connect your client to internet before proceeding to the next step. -4. Specify the target vSphere release you want to check and submit the hardware data to VMware website -PS> $vcgdata= Get-VCGStatus -Data $hwdata -Version '' +4. Specify the target vSphere release you want to check and submit the hardware data to VMware website +PS> $vcgdata= Get-VCGStatus -Data $hwdata -Version '<release>' -5. Save the compatibility reports -PS> Export-VCGReport -Data $vcgdata -Dir +5. Save the compatibility reports +PS> Export-VCGReport -Data $vcgdata -Dir <dir> # Known Limitation * The module is not able to get the firmware version for HBA devices. -* The module is not able to get the HDD/SSD data. \ No newline at end of file +* The module is not able to get the HDD/SSD data. From 3e28c516a7b88bd3964876a04c66743a9e09501a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maik=20St=C3=BCbner?= Date: Fri, 30 Nov 2018 09:12:16 +0100 Subject: [PATCH 05/43] removed brake for issue vmware#74 --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index c58e1c0..d407e2d 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -7173,7 +7173,6 @@ function Get-HVMachine { $machineList = Find-HVMachine -Param $PSBoundParameters if (!$machineList) { Write-Host "Get-HVMachine: No Virtual Machine(s) Found with given search parameters" - break } $queryResults = @() $desktop_helper = New-Object VMware.Hv.MachineService From 560739222dae6638a0612f33cfa3607b62b8da72 Mon Sep 17 00:00:00 2001 From: Zhoulin Dai Date: Fri, 30 Nov 2018 17:15:13 +0800 Subject: [PATCH 06/43] Fix bugs --- .../VMware.VCGChecker/Export-VCGReport.ps1 | 14 ++++++------ Modules/VMware.VCGChecker/Get-VCGStatus.ps1 | 2 +- Modules/VMware.VCGChecker/README.md | 22 +++++++++---------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Modules/VMware.VCGChecker/Export-VCGReport.ps1 b/Modules/VMware.VCGChecker/Export-VCGReport.ps1 index 1b1253d..3774915 100644 --- a/Modules/VMware.VCGChecker/Export-VCGReport.ps1 +++ b/Modules/VMware.VCGChecker/Export-VCGReport.ps1 @@ -140,10 +140,10 @@ Function Generate_HtmlReport($Data, $Dir) { $dataTime = Get-Date -Format 'yyyy-M-d_h-m' $vcName = vcName($Data) $filename = 'compreport_' + $vcName + $dataTime + '.html' - $filePath = $Dir + $filename + $filePath = $Dir + '\' + $filename #save report $content |Out-File -FilePath $filePath -Encoding utf8| Out-Null - info ("Report " + "'" + $Dir + $filename + "'" + " has been created!") + info ("Report " + "'" + $filePath + "'" + " has been created!") } Function Generate_SummaryReport($Data, $Dir) { @@ -440,10 +440,10 @@ Function Generate_SummaryReport($Data, $Dir) { $dataTime = Get-Date -Format 'yyyy-M-d_h-m' $vcName = vcName($Data) $filename = 'sumreport_' + $vcName + $dataTime + '.html' - $filePath = $Dir + $filename + $filePath = $Dir + '\' + $filename # Out-put a html report $content |Out-File -FilePath $filePath -Encoding utf8| Out-Null - info ("Report " + "'" + $Dir + $filename + "'" + " has been created!") + info ("Report " + "'" + $filePath + "'" + " has been created!") } Function Generate_CsvReport($Data, $Dir) { @@ -542,9 +542,9 @@ Function Generate_CsvReport($Data, $Dir) { $dataTime = Get-Date -Format 'yyyy-M-d_h-m' $vcName = vcName($Data) $filename = 'compreport_' + $vcName + $dataTime + '.csv' - $filePath = $Dir + $filename + $filePath = $Dir + '\' + $filename #save csv report - info ("Report " + "'" + $Dir + $filename + "'" + " has been created!") + info ("Report " + "'" + $filePath + "'" + " has been created!") $content |Out-File -FilePath $filePath -Encoding utf8| Out-Null return $content } @@ -785,7 +785,7 @@ $summaryHead = @' height: 100%; background-size: cover; background-repeat: no-repeat; - background-image: url(https://myvmware.workspaceair.com:443/SAAS/jersey/manager/api/images/510495) + background-image: url(https://myvmware.workspaceair.com/SAAS/jersey/manager/api/images/520470) } #header{ margin: 0 auto; diff --git a/Modules/VMware.VCGChecker/Get-VCGStatus.ps1 b/Modules/VMware.VCGChecker/Get-VCGStatus.ps1 index 0f7a5de..426d6ce 100644 --- a/Modules/VMware.VCGChecker/Get-VCGStatus.ps1 +++ b/Modules/VMware.VCGChecker/Get-VCGStatus.ps1 @@ -13,7 +13,7 @@ $apiQurryDict=@{} # Function PingApiServer(){ $apiServerIp='apigw.vmware.com' - $results =Test-NetConnection $apiServerIp -InformationLevel 'Quiet' + $results =Test-Connection $apiServerIp -Quiet if($results -ne $true){ error ("Failed to access VMware Compatibility API, Unable to use comparison function, only view basic hardware information; diff --git a/Modules/VMware.VCGChecker/README.md b/Modules/VMware.VCGChecker/README.md index a38c064..79007d4 100644 --- a/Modules/VMware.VCGChecker/README.md +++ b/Modules/VMware.VCGChecker/README.md @@ -19,23 +19,23 @@ Considering many data center may have control on internet access, we create 3 cm * Get-VCGStatus: cmdlet to check hardware compatibility by query VCG website * Export-VCGReport: cmdlet to export the summary/html/csv reports -1. You need to first import this module after you import PowerCLI module -PS> Import-Module +1. You need to first import this module after you import PowerCLI module +PS> Import-Module <path_to_VMware.VCGChecker.psd1> -2. Connect to the target vSphere hosts using Connect-VIServer and get VMHosts -PS> Connect-VIServer -Server -User -Password +2. Connect to the target vSphere hosts using Connect-VIServer and get VMHosts +PS> Connect-VIServer -Server <server> -User <username> -Password <password> PS> $vmhosts = Get-VMHost -3. Collect the hardware data -PS> $hwdata = Get-VCGHWInfo -vmHosts $vmhosts +3. Collect the hardware data +PS> $hwdata = Get-VCGHWInfo -vmHosts $vmhosts Note: if you don't have internet access, you need to connect your client to internet before proceeding to the next step. -4. Specify the target vSphere release you want to check and submit the hardware data to VMware website -PS> $vcgdata= Get-VCGStatus -Data $hwdata -Version '' +4. Specify the target vSphere release you want to check and submit the hardware data to VMware website +PS> $vcgdata= Get-VCGStatus -Data $hwdata -Version '<release>' -5. Save the compatibility reports -PS> Export-VCGReport -Data $vcgdata -Dir +5. Save the compatibility reports +PS> Export-VCGReport -Data $vcgdata -Dir <dir> # Known Limitation * The module is not able to get the firmware version for HBA devices. -* The module is not able to get the HDD/SSD data. \ No newline at end of file +* The module is not able to get the HDD/SSD data. From 971e4aeec76e83c7b43ae2694428cd2c1a68d9f9 Mon Sep 17 00:00:00 2001 From: jpgrall <33696799+jpgrall@users.noreply.github.com> Date: Fri, 30 Nov 2018 09:43:40 -0600 Subject: [PATCH 07/43] Adding file path to Get-ContentLibraryItemFiles Adding the support to display the actual path of the file on the datastore. This is useful when needing to mount an ISO that is hosted on the Content Library. Also, replaced references of "Libary" to "Library" throughout. --- Modules/ContentLibrary/ContentLibrary.psm1 | 113 +++++++++++---------- 1 file changed, 60 insertions(+), 53 deletions(-) diff --git a/Modules/ContentLibrary/ContentLibrary.psm1 b/Modules/ContentLibrary/ContentLibrary.psm1 index 318b999..d85bd54 100644 --- a/Modules/ContentLibrary/ContentLibrary.psm1 +++ b/Modules/ContentLibrary/ContentLibrary.psm1 @@ -20,12 +20,12 @@ [Parameter(Mandatory=$false)][String]$LibraryName ) - $contentLibaryService = Get-CisService com.vmware.content.library - $libaryIDs = $contentLibaryService.list() + $contentLibraryService = Get-CisService com.vmware.content.library + $LibraryIDs = $contentLibraryService.list() $results = @() - foreach($libraryID in $libaryIDs) { - $library = $contentLibaryService.get($libraryID) + foreach($libraryID in $LibraryIDs) { + $library = $contentLibraryService.get($libraryID) # Use vCenter REST API to retrieve name of Datastore that is backing the Content Library $datastoreService = Get-CisService com.vmware.vcenter.datastore @@ -108,18 +108,18 @@ Function Get-ContentLibraryItems { [Parameter(Mandatory=$false)][String]$LibraryItemName ) - $contentLibaryService = Get-CisService com.vmware.content.library - $libaryIDs = $contentLibaryService.list() + $contentLibraryService = Get-CisService com.vmware.content.library + $LibraryIDs = $contentLibraryService.list() $results = @() - foreach($libraryID in $libaryIDs) { - $library = $contentLibaryService.get($libraryId) + foreach($libraryID in $LibraryIDs) { + $library = $contentLibraryService.get($libraryId) if($library.name -eq $LibraryName) { - $contentLibaryItemService = Get-CisService com.vmware.content.library.item - $itemIds = $contentLibaryItemService.list($libraryID) + $contentLibraryItemService = Get-CisService com.vmware.content.library.item + $itemIds = $contentLibraryItemService.list($libraryID) foreach($itemId in $itemIds) { - $item = $contentLibaryItemService.get($itemId) + $item = $contentLibraryItemService.get($itemId) if(!$LibraryItemName) { $itemResult = [pscustomobject] @{ @@ -179,28 +179,34 @@ Function Get-ContentLibraryItemFiles { [Parameter(Mandatory=$false)][String]$LibraryItemName ) - $contentLibaryService = Get-CisService com.vmware.content.library - $libaryIDs = $contentLibaryService.list() + $contentLibraryService = Get-CisService com.vmware.content.library + $libraryIDs = $contentLibraryService.list() $results = @() - foreach($libraryID in $libaryIDs) { - $library = $contentLibaryService.get($libraryId) + foreach($libraryID in $libraryIDs) { + $library = $contentLibraryService.get($libraryId) if($library.name -eq $LibraryName) { - $contentLibaryItemService = Get-CisService com.vmware.content.library.item - $itemIds = $contentLibaryItemService.list($libraryID) - + $contentLibraryItemService = Get-CisService com.vmware.content.library.item + $itemIds = $contentLibraryItemService.list($libraryID) + $DatastoreID = $library.storage_backings.datastore_id.Value + $Datastore = get-datastore -id "Datastore-$DatastoreID" + foreach($itemId in $itemIds) { - $itemName = ($contentLibaryItemService.get($itemId)).name - $contenLibraryItemFileSerice = Get-CisService com.vmware.content.library.item.file - $files = $contenLibraryItemFileSerice.list($itemId) + $itemName = ($contentLibraryItemService.get($itemId)).name + $contentLibraryItemFileSerice = Get-CisService com.vmware.content.library.item.file + $files = $contentLibraryItemFileSerice.list($itemId) + $contentLibraryItemStorageService = Get-CisService com.vmware.content.library.item.storage foreach($file in $files) { + $filepath = $contentLibraryItemStorageService.get($itemId, $($file.name)).storage_uris.AbsolutePath.split("/")[5..7] -join "/" + $fullfilepath = "[$($datastore.name)] $filepath" if(!$LibraryItemName) { $fileResult = [pscustomobject] @{ Name = $file.name; Version = $file.version; Size = $file.size; Stored = $file.cached; + Path = $fullfilepath; } $results+=$fileResult } else { @@ -210,6 +216,7 @@ Function Get-ContentLibraryItemFiles { Version = $file.version; Size = $file.size; Stored = $file.cached; + Path = $fullfilepath; } $results+=$fileResult } @@ -245,12 +252,12 @@ Function Set-ContentLibrary { [Parameter(Mandatory=$false)][Switch]$JSONPersistenceDisabled ) - $contentLibaryService = Get-CisService com.vmware.content.library - $libaryIDs = $contentLibaryService.list() + $contentLibraryService = Get-CisService com.vmware.content.library + $LibraryIDs = $contentLibraryService.list() $found = $false - foreach($libraryID in $libaryIDs) { - $library = $contentLibaryService.get($libraryId) + foreach($libraryID in $LibraryIDs) { + $library = $contentLibraryService.get($libraryId) if($library.name -eq $LibraryName) { $found = $true break @@ -361,12 +368,12 @@ Function Remove-SubscribedContentLibrary { [Parameter(Mandatory=$true)][String]$LibraryName ) - $contentLibaryService = Get-CisService com.vmware.content.library - $libaryIDs = $contentLibaryService.list() + $contentLibraryService = Get-CisService com.vmware.content.library + $LibraryIDs = $contentLibraryService.list() $found = $false - foreach($libraryID in $libaryIDs) { - $library = $contentLibaryService.get($libraryId) + foreach($libraryID in $LibraryIDs) { + $library = $contentLibraryService.get($libraryId) if($library.name -eq $LibraryName) { $found = $true break @@ -460,12 +467,12 @@ Function Remove-LocalContentLibrary { [Parameter(Mandatory=$true)][String]$LibraryName ) - $contentLibaryService = Get-CisService com.vmware.content.library - $libaryIDs = $contentLibaryService.list() + $contentLibraryService = Get-CisService com.vmware.content.library + $LibraryIDs = $contentLibraryService.list() $found = $false - foreach($libraryID in $libaryIDs) { - $library = $contentLibaryService.get($libraryId) + foreach($libraryID in $LibraryIDs) { + $library = $contentLibraryService.get($libraryId) if($library.name -eq $LibraryName) { $found = $true break @@ -493,49 +500,49 @@ Function Copy-ContentLibrary { =========================================================================== .DESCRIPTION This function copies all library items from one Content Library to another - .PARAMETER SourceLibaryName + .PARAMETER SourceLibraryName The name of the source Content Library to copy from - .PARAMETER DestinationLibaryName + .PARAMETER DestinationLibraryName The name of the desintation Content Library to copy to .PARAMETER DeleteSourceFile Whther or not to delete library item from the source Content Library after copy .EXAMPLE - Copy-ContentLibrary -SourceLibaryName Foo -DestinationLibaryName Bar + Copy-ContentLibrary -SourceLibraryName Foo -DestinationLibraryName Bar .EXAMPLE - Copy-ContentLibrary -SourceLibaryName Foo -DestinationLibaryName Bar -DeleteSourceFile $true + Copy-ContentLibrary -SourceLibraryName Foo -DestinationLibraryName Bar -DeleteSourceFile $true #> param( - [Parameter(Mandatory=$true)][String]$SourceLibaryName, - [Parameter(Mandatory=$true)][String]$DestinationLibaryName, + [Parameter(Mandatory=$true)][String]$SourceLibraryName, + [Parameter(Mandatory=$true)][String]$DestinationLibraryName, [Parameter(Mandatory=$false)][Boolean]$DeleteSourceFile=$false ) - $sourceLibraryId = (Get-ContentLibrary -LibraryName $SourceLibaryName).Id + $sourceLibraryId = (Get-ContentLibrary -LibraryName $SourceLibraryName).Id if($sourceLibraryId -eq $null) { - Write-Host -ForegroundColor red "Unable to find Source Content Library named $SourceLibaryName" + Write-Host -ForegroundColor red "Unable to find Source Content Library named $SourceLibraryName" exit } - $destinationLibraryId = (Get-ContentLibrary -LibraryName $DestinationLibaryName).Id + $destinationLibraryId = (Get-ContentLibrary -LibraryName $DestinationLibraryName).Id if($destinationLibraryId -eq $null) { - Write-Host -ForegroundColor Red "Unable to find Destination Content Library named $DestinationLibaryName" + Write-Host -ForegroundColor Red "Unable to find Destination Content Library named $DestinationLibraryName" break } - $sourceItemFiles = Get-ContentLibraryItems -LibraryName $SourceLibaryName + $sourceItemFiles = Get-ContentLibraryItems -LibraryName $SourceLibraryName if($sourceItemFiles -eq $null) { - Write-Host -ForegroundColor red "Unable to retrieve Content Library Items from $SourceLibaryName" + Write-Host -ForegroundColor red "Unable to retrieve Content Library Items from $SourceLibraryName" break } - $contentLibaryItemService = Get-CisService com.vmware.content.library.item + $contentLibraryItemService = Get-CisService com.vmware.content.library.item foreach ($sourceItemFile in $sourceItemFiles) { # Check to see if file already exists in destination Content Library - $result = Get-ContentLibraryItems -LibraryName $DestinationLibaryName -LibraryItemName $sourceItemFile.Name + $result = Get-ContentLibraryItems -LibraryName $DestinationLibraryName -LibraryItemName $sourceItemFile.Name if($result -eq $null) { # Create CopySpec - $copySpec = $contentLibaryItemService.Help.copy.destination_create_spec.Create() + $copySpec = $contentLibraryItemService.Help.copy.destination_create_spec.Create() $copySpec.library_id = $destinationLibraryId $copySpec.name = $sourceItemFile.Name $copySpec.description = $sourceItemFile.Description @@ -545,7 +552,7 @@ Function Copy-ContentLibrary { # Perform Copy try { Write-Host -ForegroundColor Cyan "Copying" $sourceItemFile.Name "..." - $copyResult = $contentLibaryItemService.copy($UniqueChangeId, $sourceItemFile.Id, $copySpec) + $copyResult = $contentLibraryItemService.copy($UniqueChangeId, $sourceItemFile.Id, $copySpec) } catch { Write-Host -ForegroundColor Red "Failed to copy" $sourceItemFile.Name $Error[0] @@ -556,7 +563,7 @@ Function Copy-ContentLibrary { if($DeleteSourceFile) { try { Write-Host -ForegroundColor Magenta "Deleteing" $sourceItemFile.Name "..." - $deleteResult = $contentLibaryItemService.delete($sourceItemFile.Id) + $deleteResult = $contentLibraryItemService.delete($sourceItemFile.Id) } catch { Write-Host -ForegroundColor Red "Failed to delete" $sourceItemFile.Name $Error[0] @@ -570,7 +577,7 @@ Function Copy-ContentLibrary { if($DeleteSourceFile) { try { Write-Host -ForegroundColor Magenta "Deleteing" $sourceItemFile.Name "..." - $deleteResult = $contentLibaryItemService.delete($sourceItemFile.Id) + $deleteResult = $contentLibraryItemService.delete($sourceItemFile.Id) } catch { Write-Host -ForegroundColor Red "Failed to delete" $sourceItemFile.Name break @@ -597,7 +604,7 @@ Function New-VMTX { The name of the VM Template in Content Library .PARAMETER Description Description of the VM template - .PARAMETER LibaryName + .PARAMETER LibraryName The name of the Content Library to clone to .PARAMETER FolderName The name of vSphere Folder (Defaults to Workloads for VMC) @@ -696,4 +703,4 @@ Function New-VMFromVMTX { Write-Host "`nDeploying new VM $NewVMName from VMTX Template $VMTXName ..." $results = $vmtxService.deploy($vmtxId,$vmtxDeploySpec) -} \ No newline at end of file +} \ No newline at end of file From 7c7f8d3fbf49e04ed6e3e72dbac104067091af5c Mon Sep 17 00:00:00 2001 From: jpgrall <33696799+jpgrall@users.noreply.github.com> Date: Fri, 30 Nov 2018 09:55:46 -0600 Subject: [PATCH 08/43] Update ContentLibrary.psm1 Adding logic incase backing isn't a datastore. --- Modules/ContentLibrary/ContentLibrary.psm1 | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Modules/ContentLibrary/ContentLibrary.psm1 b/Modules/ContentLibrary/ContentLibrary.psm1 index d85bd54..9a8574b 100644 --- a/Modules/ContentLibrary/ContentLibrary.psm1 +++ b/Modules/ContentLibrary/ContentLibrary.psm1 @@ -198,8 +198,14 @@ Function Get-ContentLibraryItemFiles { $contentLibraryItemStorageService = Get-CisService com.vmware.content.library.item.storage foreach($file in $files) { - $filepath = $contentLibraryItemStorageService.get($itemId, $($file.name)).storage_uris.AbsolutePath.split("/")[5..7] -join "/" - $fullfilepath = "[$($datastore.name)] $filepath" + if($contentLibraryItemStorageService.get($itemId, $($file.name)).storage_backing.type -eq "DATASTORE"){ + $filepath = $contentLibraryItemStorageService.get($itemId, $($file.name)).storage_uris.AbsolutePath.split("/")[5..7] -join "/" + $fullfilepath = "[$($datastore.name)] $filepath" + } + else{ + $fullfilepath = "UNKNOWN" + } + if(!$LibraryItemName) { $fileResult = [pscustomobject] @{ Name = $file.name; @@ -703,4 +709,4 @@ Function New-VMFromVMTX { Write-Host "`nDeploying new VM $NewVMName from VMTX Template $VMTXName ..." $results = $vmtxService.deploy($vmtxId,$vmtxDeploySpec) -} \ No newline at end of file +} From 937f21345150233d6ce15d2ca0f5cc781f63e4ab Mon Sep 17 00:00:00 2001 From: Jack McMichael Date: Sat, 1 Dec 2018 17:15:38 -0700 Subject: [PATCH 09/43] Update VMware.HV.Helper.psm1 Added functions to starting and starting Instant Clone maintenance operations on a host for Horizon 7.x --- .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 115 +++++++++++++++++- 1 file changed, 114 insertions(+), 1 deletion(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index c58e1c0..9eb2254 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11478,4 +11478,117 @@ function Get-HVlicense { [System.gc]::collect() } -Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, New-HVPodfederation, Remove-HVPodFederation, Get-HVPodFederation, Register-HVPod, Unregister-HVPod, Set-HVPodFederation,Get-HVSite,New-HVSite,Set-HVSite,Remove-HVSite,New-HVHomeSite,Get-HVHomeSite,Set-HVEventDatabase,Get-HVEventDatabase,Clear-HVEventDatabase,Get-HVlicense,Set-HVlicense +function Start-HVMaintenance { + <# + .Synopsis + Puts a host in instant clone maintanence mode + + .DESCRIPTION + Puts a host in instant clone maintanence mode + + + .PARAMETER Host + ESXi Host name to modify the InstantClone.Maintenance attribute + + .EXAMPLE + Start-HvMaintenance -Host + + .NOTES + Author : Jack McMichael + Author email : @jackwmc4 / jackwmc4@gmail.com + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.6 + PowerCLI Version : PowerCLI 11 + PowerShell Version : 5.1 + #> + + [CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High')] + + param( + [Parameter(Mandatory=$true, Position=0)] + [string]$Server, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + if ((Get-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance").Value -eq ""){ + Set-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance" -Value "1" | Out-Null + } + while ((Get-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance").Value -ne "2") { + shouldcontinue() + Start-Sleep -Seconds 10 + } + [System.gc]::collect() + } +} + +function Stop-HVMaintenance { + <# + .Synopsis + Takes a host out of instant clone maintanence mode + + .DESCRIPTION + Takes a host out of instant clone maintanence mode + + + .PARAMETER Host + ESXi Host name to clear the InstantClone.Maintenance attribute + + .EXAMPLE + Stop-HvMaintenance -Host + + .NOTES + Author : Jack McMichael + Author email : @jackwmc4 / jackwmc4@gmail.com + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.6 + PowerCLI Version : PowerCLI 11 + PowerShell Version : 5.1 + #> + [CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High')] + + param( + [Parameter(Mandatory=$true, Position=0)] + [string]$Server, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + if (-not (Get-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance").Value -eq "") { + Set-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance" -Value "" | Out-Null + } + Set-VMhost $Host -State Connected | Out-Null + [System.gc]::collect() + } + + +} +Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, New-HVPodfederation, Remove-HVPodFederation, Get-HVPodFederation, Register-HVPod, Unregister-HVPod, Set-HVPodFederation,Get-HVSite,New-HVSite,Set-HVSite,Remove-HVSite,New-HVHomeSite,Get-HVHomeSite,Set-HVEventDatabase,Get-HVEventDatabase,Clear-HVEventDatabase,Get-HVlicense,Set-HVlicense, Start-HVMaintenance, Stop-HVMaintenance \ No newline at end of file From f9953ec994ebfe26997656d5292b90c12d9c8e95 Mon Sep 17 00:00:00 2001 From: Jack McMichael Date: Sat, 1 Dec 2018 20:55:50 -0700 Subject: [PATCH 10/43] Update VMware.HV.Helper.psm1 Added Set-HVInstantCloneMaintenance function. --- .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 111 ++++++------------ 1 file changed, 38 insertions(+), 73 deletions(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 9eb2254..3f0fe30 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11478,20 +11478,26 @@ function Get-HVlicense { [System.gc]::collect() } -function Start-HVMaintenance { +function Set-HVInstantCloneMaintenance { <# .Synopsis - Puts a host in instant clone maintanence mode + Enable or disable instant clone maintanence mode .DESCRIPTION - Puts a host in instant clone maintanence mode + Toggles a host in instant clone maintanence mode. Specify the VMHost name and enable or disable to toggle. + .PARAMETER VMHost + ESXi Host name to modify the InstantClone.Maintenance attribute - .PARAMETER Host - ESXi Host name to modify the InstantClone.Maintenance attribute - + .PARAMETER Enable + Enable Instant Clone maintenance mode. + + .PARAMETER Disable + Disable Instant Clone maintenance mode + .EXAMPLE - Start-HvMaintenance -Host + Set-HvInstantCloneMaintenance -VMHost -Enable $true + Set-HvInstantCloneMaintenance -VMHost -Disable $true .NOTES Author : Jack McMichael @@ -11510,11 +11516,20 @@ function Start-HVMaintenance { param( [Parameter(Mandatory=$true, Position=0)] - [string]$Server, + [string] + $VMHost, + + [Parameter(Mandatory = $false)] + [boolean] + $Enable, + + [Parameter(Mandatory = $false)] + [boolean] + $Disable, [Parameter(Mandatory = $false)] $HvServer = $null - ) + ) begin { $services = Get-ViewAPIService -hvServer $hvServer @@ -11525,70 +11540,20 @@ function Start-HVMaintenance { } process { - if ((Get-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance").Value -eq ""){ - Set-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance" -Value "1" | Out-Null + if ($Enable) { + if ((Get-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance").Value -eq ""){ + Set-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance" -Value "1" | Out-Null + } + while ((Get-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance").Value -ne "2") { + Start-Sleep -Seconds 10 + } + } elseif ($Disable) { + if (-not (Get-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance").Value -eq "") { + Set-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance" -Value "" | Out-Null + } + Set-VMhost $VMHost -State Connected | Out-Null } - while ((Get-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance").Value -ne "2") { - shouldcontinue() - Start-Sleep -Seconds 10 - } - [System.gc]::collect() + [System.gc]::collect() } } - -function Stop-HVMaintenance { - <# - .Synopsis - Takes a host out of instant clone maintanence mode - - .DESCRIPTION - Takes a host out of instant clone maintanence mode - - - .PARAMETER Host - ESXi Host name to clear the InstantClone.Maintenance attribute - - .EXAMPLE - Stop-HvMaintenance -Host - - .NOTES - Author : Jack McMichael - Author email : @jackwmc4 / jackwmc4@gmail.com - Version : 1.0 - - ===Tested Against Environment==== - Horizon View Server Version : 7.6 - PowerCLI Version : PowerCLI 11 - PowerShell Version : 5.1 - #> - [CmdletBinding( - SupportsShouldProcess = $true, - ConfirmImpact = 'High')] - - param( - [Parameter(Mandatory=$true, Position=0)] - [string]$Server, - - [Parameter(Mandatory = $false)] - $HvServer = $null - ) - - begin { - $services = Get-ViewAPIService -hvServer $hvServer - if ($null -eq $services) { - Write-Error "Could not retrieve ViewApi services from connection object" - break - } - } - - process { - if (-not (Get-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance").Value -eq "") { - Set-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance" -Value "" | Out-Null - } - Set-VMhost $Host -State Connected | Out-Null - [System.gc]::collect() - } - - -} -Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, New-HVPodfederation, Remove-HVPodFederation, Get-HVPodFederation, Register-HVPod, Unregister-HVPod, Set-HVPodFederation,Get-HVSite,New-HVSite,Set-HVSite,Remove-HVSite,New-HVHomeSite,Get-HVHomeSite,Set-HVEventDatabase,Get-HVEventDatabase,Clear-HVEventDatabase,Get-HVlicense,Set-HVlicense, Start-HVMaintenance, Stop-HVMaintenance \ No newline at end of file +Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, New-HVPodfederation, Remove-HVPodFederation, Get-HVPodFederation, Register-HVPod, Unregister-HVPod, Set-HVPodFederation,Get-HVSite,New-HVSite,Set-HVSite,Remove-HVSite,New-HVHomeSite,Get-HVHomeSite,Set-HVEventDatabase,Get-HVEventDatabase,Clear-HVEventDatabase,Get-HVlicense,Set-HVlicense, Set-HVInstantCloneMaintenance \ No newline at end of file From 53b8377c5395c2b699881a09084679561bccd7a2 Mon Sep 17 00:00:00 2001 From: Jack McMichael Date: Sat, 1 Dec 2018 20:59:06 -0700 Subject: [PATCH 11/43] Update VMware.HV.Helper.psm1 --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 3f0fe30..32322e7 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11479,14 +11479,14 @@ function Get-HVlicense { } function Set-HVInstantCloneMaintenance { - <# - .Synopsis + <# + .Synopsis Enable or disable instant clone maintanence mode - - .DESCRIPTION + + .DESCRIPTION Toggles a host in instant clone maintanence mode. Specify the VMHost name and enable or disable to toggle. - .PARAMETER VMHost + .PARAMETER VMHost ESXi Host name to modify the InstantClone.Maintenance attribute .PARAMETER Enable From 4ef4cce5efcc2dce3260058b98e81a71f70f5484 Mon Sep 17 00:00:00 2001 From: Jack McMichael Date: Sat, 1 Dec 2018 21:01:25 -0700 Subject: [PATCH 12/43] Update VMware.HV.Helper.psm1 --- .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 32322e7..4379f31 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11495,19 +11495,19 @@ function Set-HVInstantCloneMaintenance { .PARAMETER Disable Disable Instant Clone maintenance mode - .EXAMPLE + .EXAMPLE Set-HvInstantCloneMaintenance -VMHost -Enable $true Set-HvInstantCloneMaintenance -VMHost -Disable $true - - .NOTES - Author : Jack McMichael - Author email : @jackwmc4 / jackwmc4@gmail.com - Version : 1.0 + + .NOTES + Author : Jack McMichael + Author email : @jackwmc4 / jackwmc4@gmail.com + Version : 1.0 - ===Tested Against Environment==== - Horizon View Server Version : 7.6 - PowerCLI Version : PowerCLI 11 - PowerShell Version : 5.1 + ===Tested Against Environment==== + Horizon View Server Version : 7.6 + PowerCLI Version : PowerCLI 11 + PowerShell Version : 5.1 #> [CmdletBinding( From e5920d40f5069537042f1be5e538f0e8fcb30d2f Mon Sep 17 00:00:00 2001 From: Jack McMichael Date: Sat, 1 Dec 2018 21:15:51 -0700 Subject: [PATCH 13/43] Update VMware.HV.Helper.psm1 Updating exports to be more organized --- .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 4379f31..e42b8e2 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11556,4 +11556,22 @@ function Set-HVInstantCloneMaintenance { [System.gc]::collect() } } -Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, New-HVPodfederation, Remove-HVPodFederation, Get-HVPodFederation, Register-HVPod, Unregister-HVPod, Set-HVPodFederation,Get-HVSite,New-HVSite,Set-HVSite,Remove-HVSite,New-HVHomeSite,Get-HVHomeSite,Set-HVEventDatabase,Get-HVEventDatabase,Clear-HVEventDatabase,Get-HVlicense,Set-HVlicense, Set-HVInstantCloneMaintenance \ No newline at end of file +# Object related +Export-ModuleMember -Function Get-HVMachine, Get-HVMachineSummary, Get-HVQueryResult, Get-HVQueryFilter, Get-HVInternalName +# RDS Farm related +Export-ModuleMember -Function Get-HVFarmSummary, Start-HVFarm, Start-HVPool, New-HVFarm, Remove-HVFarm, Get-HVFarm, Set-HVFarm, Add-HVRDSServer +# Desktop Pool related +Export-ModuleMember -Function Get-HVPoolSummary, New-HVPool, Remove-HVPool, Get-HVPool, Set-HVPool, Get-HVPoolSpec, Add-HVDesktop +# Entitlement related +Export-ModuleMember -Function New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement +Export-ModuleMember -Function Set-HVMachine, Reset-HVMachine, Remove-HVMachine +# Cloud Pod Architecture related +Export-ModuleMember -Function New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVGlobalEntitlement, New-HVPodFederation, Remove-HVPodFederation, Get-HVPodFederation, Set-HVPodFederation +Export-ModuleMember -Function Get-HVSite, New-HVSite, New-HVHomeSite, Remove-HVSite, Get-HVHomeSite, Set-HVSite, Register-HVPod, Unregister-HVPod +# Published App related +Export-ModuleMember -Function Get-HVGlobalSettings, Set-HVApplicationIcon, Remove-HVApplicationIcon, Set-HVGlobalSettings +Export-ModuleMember -Function Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession +# Event Database related +Export-ModuleMember -Function Get-HVEventDatabase, Set-HVEventDatabase, Clear-HVEventDatabase, Get-HVEvent, Connect-HVEvent, Disconnect-HVEvent +# Misc/other related +Export-ModuleMember -Function Get-HVlicense, Set-HVlicense, Get-HVHealth, Set-HVInstantCloneMaintenance \ No newline at end of file From c7a19c795e2af4bcb578b1710423c14bca62aab0 Mon Sep 17 00:00:00 2001 From: Jack McMichael Date: Sun, 2 Dec 2018 17:01:26 -0700 Subject: [PATCH 14/43] Update VMware.HV.Helper.psm1 Changed booleans to switches after looking at other uses in the code. --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index e42b8e2..30336f5 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11520,11 +11520,11 @@ function Set-HVInstantCloneMaintenance { $VMHost, [Parameter(Mandatory = $false)] - [boolean] + [switch] $Enable, [Parameter(Mandatory = $false)] - [boolean] + [switch] $Disable, [Parameter(Mandatory = $false)] From cea57f11d5f72becdb63f4f29c60b04fae720808 Mon Sep 17 00:00:00 2001 From: Jack McMichael Date: Tue, 4 Dec 2018 14:05:08 -0700 Subject: [PATCH 15/43] Update VMware.HV.Helper.psm1 Added per feedback --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 30336f5..0a4efe9 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11545,11 +11545,13 @@ function Set-HVInstantCloneMaintenance { Set-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance" -Value "1" | Out-Null } while ((Get-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance").Value -ne "2") { + Write-Host "Instant Clone Maintenance Mode: Enabling for $VMHost...(This could take some time)" Start-Sleep -Seconds 10 } } elseif ($Disable) { if (-not (Get-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance").Value -eq "") { Set-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance" -Value "" | Out-Null + Write-Host "Instant Clone Maintenance Mode: Disabling for $VMHost" } Set-VMhost $VMHost -State Connected | Out-Null } From bd983dcd7fc5a7436de6c6243601d38d62f5ecb4 Mon Sep 17 00:00:00 2001 From: Jack McMichael Date: Wed, 5 Dec 2018 13:00:12 -0700 Subject: [PATCH 16/43] Update VMware.HV.Helper.psm1 Moving messaging so it doesn't repeat over and over. --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 0a4efe9..eee2b67 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11543,9 +11543,9 @@ function Set-HVInstantCloneMaintenance { if ($Enable) { if ((Get-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance").Value -eq ""){ Set-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance" -Value "1" | Out-Null + Write-Host "Instant Clone Maintenance Mode: Enabling for $VMHost...(This could take some time)" } while ((Get-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance").Value -ne "2") { - Write-Host "Instant Clone Maintenance Mode: Enabling for $VMHost...(This could take some time)" Start-Sleep -Seconds 10 } } elseif ($Disable) { From 76eadeba8a2afcafd9dc96b83e2d5bf3921b968e Mon Sep 17 00:00:00 2001 From: Jase McCarty Date: Fri, 7 Dec 2018 16:11:18 -0700 Subject: [PATCH 17/43] Initial vSAN Encryption Module vSAN Encryption Module --- Modules/VMware.VsanEncryption/README.md | 7 + .../VMware.VsanEncryption.psd1 | Bin 0 -> 5098 bytes .../VMware.VsanEncryption.psm1 | 340 ++++++++++++++++++ 3 files changed, 347 insertions(+) create mode 100644 Modules/VMware.VsanEncryption/README.md create mode 100644 Modules/VMware.VsanEncryption/VMware.VsanEncryption.psd1 create mode 100644 Modules/VMware.VsanEncryption/VMware.VsanEncryption.psm1 diff --git a/Modules/VMware.VsanEncryption/README.md b/Modules/VMware.VsanEncryption/README.md new file mode 100644 index 0000000..8037171 --- /dev/null +++ b/Modules/VMware.VsanEncryption/README.md @@ -0,0 +1,7 @@ +Prerequisites/Steps to use this module: + +1. This module only works for vSphere products that support vSAN Encryption. E.g. vSAN 6.6 and later with a vSAN Enterprise license +2. All the functions in this module only work for KMIP Servers. +3. Install the latest version of Powershell and PowerCLI(11). +4. Import this module by running: Import-Module -Name "location of this module" +5. Get-Command -Module "This module Name" to list all available functions. \ No newline at end of file diff --git a/Modules/VMware.VsanEncryption/VMware.VsanEncryption.psd1 b/Modules/VMware.VsanEncryption/VMware.VsanEncryption.psd1 new file mode 100644 index 0000000000000000000000000000000000000000..47b0ca30d0fd967f4a1e9ee3b4b69b6b61d2b73d GIT binary patch literal 5098 zcmcgwSx-|@5T57$ikt8N7}*p7O-v;02_PwmzP7iEH+Hj&)foS}`h7D!oO60xX`4z& zxyv~-^UXfz{`tKk1zC|quB0s$8AwB_cxp;XT9Qc(Pd(}5O%3Z^T?zNC$~`ED*xkj> zO+59K@&wc=-u;jcs58*EWK|`Zv@`5(;n&6PKCTsTE@Sr_TtklBJ)MGFNwFg@WJ~t( zdm-C+Iv7bR$UFIod*g7ch%!Y)4MROlw=$5nRF@w)O>0;)+mxVV57a5%c=SU&_2o0@ z_&>vrycIV`NQ$6tV_$6Zx1d;6D;eHbKJ?tc?$>y?4X>6*ekJWrfcX%(DBb+`FPju3-fM`$ zSYv#e<&VIxi8x^nP-El%O|`DfBrE1{4Ngr^Cz6-?9B(fmCxtg+1Rcok!p3#z#|&g1 zTD*}L?eDX4ng@tuoR49cw6X>i>)`6LD9*(YX##6D@RtM#8S$(FjGwO1T9rtrV_joa zupD%8?Y%||)imN#XlLssNMUBt4;|39!Pz3v)r>gf!uVSO%`~ZI1#j^yaAl-7A-@Sa z;_pJ2$tXYSZpOk8dlI?PJ5t=jTg(*NhF+@cPHINmFpo05n+^RWzLT@rYvQ9Vw(M+} znM+pjmxcFy#L?q=3fuobJsz|Fe37&%*K#6vh>ugmh1H26EY_7T3&zYbsQchr#s56d z<)Tj^tBF7BPz~T`#1C+-Lq21k{e!t|^>0m%8^~pUW-Vf;=G?*w zCDqQ%d4u(3fH%ar23rw-RaoIZq2ui7-61enaKF1S+B}ZKsVMR};VT&{3@bdVKc@=z zXx?!aU_WNBqLyxwVkNWgO)BoGqaL-fpVidr600b!)Kbq_H(`Bcy`#O1KIBcVbzSlE zjmK!6vj}NnjSHs`YC$dE!Q$%=z4lOjR0WDMuw|hCx3<)yq!S1$=<*Ry#*@b#Pm^vs zB=$9Qy$-b4(YWz`vl-dt1pUUT&Uq+R-*Ce0Vh$i5c8_Iy$xWak`W~uJ8yzgnnMt0y zLl5o%6??SJ!m+mB;lsvAXHJe5ow2`$8jsX_-pF#&XGMFeam;g!%}Gy>I7Bcj>hXNZ zXCW&Y?aq3|DqyoZE3iAgaW(Gz;VS1ydXc9W`qAhu7K@-8KbLGpCy9Kd6tvSgB;)v9 z-pq4OwCri>obT(zsdf@S7g9^JPF21`BddRmO~x@NIA)eRhk5H1&=c8{LQd4`B;sP# z_*pcOvl}o!`)dEiWFG;U=Q4}jd-$7Gxuo^cRY&I6yn5$3%_5(3KBaT2U)<&~ms#Xq zs_&S)7R&5h>|J3j6Aw>mDP|>`IM@>=pTvCxxEdJ7s+Z;>)<>RSi;;v?aDEilFHfN* zW6I0O%V%ZI&r1TTBcIQIIW``m%(#h4G8!Ji&4YLfNwJ7wLd4jd6jc&MQs*lk=4S- zD##}Iy&s(q=^1_vv1-FBpQhvBInvoke-VsanEncryptionRekey -Cluster "ClusterName" -DeepRekey $true/$false -ReducedRedundancy $true/$false + + #> + + # Set our Parameters + [CmdletBinding()]Param( + [Parameter(Mandatory = $True)][String]$Cluster, + [Parameter(Mandatory = $False)][Boolean]$DeepRekey, + [Parameter(Mandatory = $False)][Boolean]$ReducedRedundancy + ) + + # Get the Cluster + $VsanCluster = Get-Cluster -Name $Cluster + + # Get the vSAN Cluster Configuration View + $VsanVcClusterConfig = Get-VsanView -Id "VsanVcClusterConfigSystem-vsan-cluster-config-system" + + # Get Encryption State + $EncryptedVsan = $VsanVcClusterConfig.VsanClusterGetConfig($VsanCluster.ExtensionData.MoRef).DataEncryptionConfig + + # If vSAN is enabled and it is Encrypted + If($VsanCluster.vSanEnabled -And $EncryptedVsan.EncryptionEnabled){ + + # Get a count of hosts to guarantee reduced redundancy for 2 and 3 node clusters + $HostCount = $VsanCluster | Select @{n="count";e={($_ | Get-VMHost).Count}} + + # If reduced redundancy is specified, or there are less than 4 hosts, force reduced redundancy + If (($ReducedRedundancy -eq $true) -or ($HostCount.Value -lt 4)) { + + } + # Determine Rekey Type for messaging + Switch ($DeepRekey) { + $true { $ReKeyType = "deep"} + default { $ReKeyType = "shallow"} + } + + # Determine Reduced Redundancy for messaging + Switch ($ReducedRedundancy) { + $true { $RRMessage = "with reduced redundancy"} + default { $RRMessage = ""} + } + + # Echo task being performed + Write-Host "Executing $ReKeyType rekey of vSAN Cluster $VsanCluster $RRMessage" + + # Execute the rekeying task + $ReKeyTask = $VsanVcClusterConfig.VsanEncryptedClusterRekey_Task($VsanCluster.ExtensionData.MoRef,$DeepRekey,$ReducedRedundancy) + } +} + +Function Set-VsanEncryptionKms { + <# + .SYNOPSIS + This function will set the KMS to be used with vSAN Encryption + + .DESCRIPTION + This function will set the KMS to be used with vSAN Encryption + + .PARAMETER Cluster + Specifies the Cluster to set the KMS server for + + .PARAMETER KmsCluster + Use to set the KMS Cluster to be used with vSAN Encryption + + .EXAMPLE + C:\PS>Set-VsanEncryptionKms -Cluster "ClusterName" -KmsCluster "vCenter KMS Cluster Entry" + + #> + + # Set our Parameters + [CmdletBinding()]Param( + [Parameter(Mandatory = $True)][String]$Cluster, + [Parameter(Mandatory = $False)][String]$KmsCluster + ) + + # Get the Cluster + $VsanCluster = Get-Cluster -Name $Cluster + + # Get the list of KMS Servers that are included + $KmsClusterList = Get-KmsCluster + + # Was a KMS Cluster Specified? + # Specified: Is it in the list? + # Is it not in the list? + # Not Specified: Present a list + If ($KmsCluster) { + If ($KmsClusterList.Name.Contains($KmsCluster)) { + Write-Host "$KmsCluster In the list, proceeding" -ForegroundColor Green + $KmsClusterProfile = $KmsClusterList | Where-Object {$_.Name -eq $KmsCluster} + } else { + + $Count = 0 + Foreach ($KmsClusterItem in $KmsClusterList) { + Write-Host "$Count) $KmsClusterItem " + $Count = $Count + 1 + } + $KmsClusterEntry = Read-Host -Prompt "$KmsCluster is not valid, please select one of the existing KMS Clusters to use" + Write-Host $KmsClusterList[$KmsClusterEntry] + $KmsClusterProfile = $KmsClusterList[$KmsClusterEntry] + } + } else { + + $Count = 0 + Foreach ($KmsClusterItem in $KmsClusterList) { + Write-Host "$Count) $KmsClusterItem " + $Count = $Count + 1 + } + $KmsClusterEntry = Read-Host -Prompt "No KMS provided, please select one of the existing KMS Clusters to use" + Write-Host $KmsClusterList[$KmsClusterEntry] + $KmsClusterProfile = $KmsClusterList[$KmsClusterEntry] + } + + # Get the vSAN Cluster Configuration View + $VsanVcClusterConfig = Get-VsanView -Id "VsanVcClusterConfigSystem-vsan-cluster-config-system" + + # Get Encryption State + $EncryptedVsan = $VsanVcClusterConfig.VsanClusterGetConfig($VsanCluster.ExtensionData.MoRef).DataEncryptionConfig + + # If vSAN is enabled and it is Encrypted + If($VsanCluster.vSanEnabled -And $EncryptedVsan.EncryptionEnabled){ + + If ($EncryptedVsan.KmsProviderId.Id -eq $KmsClusterProfile.Name) { + # If the Specified KMS Profile is the KMS Profile being used, then don't do anything + Write-Host $EncryptedVsan.KmsProviderId.Id "is already the assigned KMS Cluster Profile, exiting" + } else { + Write-Host "Changing the KMS Profile to $KmsClusterProfile on Cluster $VsanCluster" + + # Setup the KMS Provider Id Specification + $KmsProviderIdSpec = New-Object VMware.Vim.KeyProviderId + $KmsProviderIdSpec.Id = $KmsClusterProfile.Name + + # Setup the Data Encryption Configuration Specification + $DataEncryptionConfigSpec = New-Object VMware.Vsan.Views.VsanDataEncryptionConfig + $DataEncryptionConfigSpec.KmsProviderId = $KmsProviderIdSpec + $DataEncryptionConfigSpec.EncryptionEnabled = $true + + # Set the Reconfigure Specification to use the Data Encryption Configuration Spec + $vsanReconfigSpec = New-Object VMware.Vsan.Views.VimVsanReconfigSpec + $vsanReconfigSpec.DataEncryptionConfig = $DataEncryptionConfigSpec + + # Execute the task of changing the KMS Cluster Profile Being Used + $ChangeKmsTask = $VsanVcClusterConfig.VsanClusterReconfig($VsanCluster.ExtensionData.MoRef,$vsanReconfigSpec) + } + + } + } + + Function Get-VsanEncryptionKms { + <# + .SYNOPSIS + This function will set the KMS to be used with vSAN Encryption + + .DESCRIPTION + This function will set the KMS to be used with vSAN Encryption + + .PARAMETER Cluster + Specifies the Cluster to set the KMS server for + + .EXAMPLE + C:\PS>Get-VsanEncryptionKms -Cluster "ClusterName" + #> + + # Set our Parameters + [CmdletBinding()]Param([Parameter(Mandatory = $True)][String]$Cluster) + + # Get the Cluster + $VsanCluster = Get-Cluster -Name $Cluster + + # Get the vSAN Cluster Configuration View + $VsanVcClusterConfig = Get-VsanView -Id "VsanVcClusterConfigSystem-vsan-cluster-config-system" + + # Get Encryption State + $EncryptedVsan = $VsanVcClusterConfig.VsanClusterGetConfig($VsanCluster.ExtensionData.MoRef).DataEncryptionConfig + + # If vSAN is enabled and it is Encrypted + If($VsanCluster.vSanEnabled -And $EncryptedVsan.EncryptionEnabled){ + + $EncryptedVsan.KmsProviderId.Id + } +} + +Function Set-VsanEncryptionDiskWiping { + <# + .SYNOPSIS + This function will update the Disk Wiping option in vSAN Encryption + + .DESCRIPTION + This function will update the Disk Wiping option in vSAN Encryption + + .PARAMETER Cluster + Specifies the Cluster set the Disk Wiping Setting on + + .PARAMETER DiskWiping + Use to set the Disk Wiping setting for vSAN Encryption + + .EXAMPLE + C:\PS>Set-VsanEncryptionDiskWiping -Cluster "ClusterName" -DiskWiping $true + + .EXAMPLE + C:\PS>Set-VsanEncryptionDiskWiping -Cluster "ClusterName" -DiskWiping $false + + #> + + # Set our Parameters + [CmdletBinding()]Param( + [Parameter(Mandatory = $True)][String]$Cluster, + [Parameter(Mandatory = $True)][Boolean]$DiskWiping + ) + + # Get the Cluster + $VsanCluster = Get-Cluster -Name $Cluster + + # Get the vSAN Cluster Configuration View + $VsanVcClusterConfig = Get-VsanView -Id "VsanVcClusterConfigSystem-vsan-cluster-config-system" + + # Get Encryption State + $EncryptedVsan = $VsanVcClusterConfig.VsanClusterGetConfig($VsanCluster.ExtensionData.MoRef).DataEncryptionConfig + + # If vSAN is enabled and it is Encrypted + If($VsanCluster.vSanEnabled -And $EncryptedVsan.EncryptionEnabled){ + + # Determine Rekey Type for messaging + Switch ($DiskWiping) { + $true { $DiskWipingSetting = "enabled" } + default { $DiskWipingSetting = "disabled" } + } + + # Check to see the current Disk Wiping value + If ($DiskWiping -eq $EncryptedVsan.EraseDisksBeforeUse) { + Write-Host "Disk Wiping is already $DiskWipingSetting" -ForegroundColor "Green" + Write-Host "No action necessary" -ForegroundColor "Green" + + } else { + + Write-Host "Disk Wiping is not set to $DiskWipingSetting" -ForegroundColor "Yellow" + Write-Host "Changing Disk Wiping setting on Cluster $VsanCluster" -ForegroundColor "Blue" + + # Setup the Data Encryption Configuration Specification + $DataEncryptionConfigSpec = New-Object VMware.Vsan.Views.VsanDataEncryptionConfig + $DataEncryptionConfigSpec.EncryptionEnabled = $true + $DataEncryptionConfigSpec.EraseDisksBeforeUse = $DiskWiping + + # Set the Reconfigure Specification to use the Data Encryption Configuration Spec + $vsanReconfigSpec = New-Object VMware.Vsan.Views.VimVsanReconfigSpec + $vsanReconfigSpec.DataEncryptionConfig = $DataEncryptionConfigSpec + + # Execute the task of changing the KMS Cluster Profile Being Used + $VsanVcClusterConfig.VsanClusterReconfig($VsanCluster.ExtensionData.MoRef,$vsanReconfigSpec) + + } + } +} + +Function Get-VsanEncryptionDiskWiping { + <# + .SYNOPSIS + This function will retrieve the Disk Wiping option setting in vSAN Encryption + + .DESCRIPTION + This function will retrieve the Disk Wiping option setting in vSAN Encryption + + .PARAMETER Cluster + Specifies the Cluster set the Disk Wiping Setting on + + .EXAMPLE + C:\PS>Get-VsanEncryptionDiskWiping -Cluster "ClusterName" + + #> + + # Set our Parameters + [CmdletBinding()]Param([Parameter(Mandatory = $True)][String]$Cluster) + + # Get the Cluster + $VsanCluster = Get-Cluster -Name $Cluster + + # Get the vSAN Cluster Configuration View + $VsanVcClusterConfig = Get-VsanView -Id "VsanVcClusterConfigSystem-vsan-cluster-config-system" + + # Get Encryption State + $EncryptedVsan = $VsanVcClusterConfig.VsanClusterGetConfig($VsanCluster.ExtensionData.MoRef).DataEncryptionConfig + + # If vSAN is enabled and it is Encrypted + If($VsanCluster.vSanEnabled -And $EncryptedVsan.EncryptionEnabled){ + + $EncryptedVsan.EraseDisksBeforeUse + } +} + + + +# Export Function for vSAN Rekeying +Export-ModuleMember -Function Invoke-VsanEncryptionRekey +Export-ModuleMember -Function Set-VsanEncryptionKms +Export-ModuleMember -Function Get-VsanEncryptionKms +Export-ModuleMember -Function Set-VsanEncryptionDiskWiping +Export-ModuleMember -Function Get-VsanEncryptionDiskWiping \ No newline at end of file From 82c7889cec7c140eae66d9f0f16cbf8776286680 Mon Sep 17 00:00:00 2001 From: Jase McCarty Date: Mon, 10 Dec 2018 13:36:22 -0700 Subject: [PATCH 18/43] Initial Push This is an initial push to PowerCLI-Example-Tools --- Modules/VMware.VsanEncryption/VMware.VsanEncryption.psm1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/VMware.VsanEncryption/VMware.VsanEncryption.psm1 b/Modules/VMware.VsanEncryption/VMware.VsanEncryption.psm1 index e45ab91..870bd44 100644 --- a/Modules/VMware.VsanEncryption/VMware.VsanEncryption.psm1 +++ b/Modules/VMware.VsanEncryption/VMware.VsanEncryption.psm1 @@ -326,6 +326,7 @@ Function Get-VsanEncryptionDiskWiping { # If vSAN is enabled and it is Encrypted If($VsanCluster.vSanEnabled -And $EncryptedVsan.EncryptionEnabled){ + # Change the setting $EncryptedVsan.EraseDisksBeforeUse } } From faa125fd83db28e453ecb57748ccc17df52e9f65 Mon Sep 17 00:00:00 2001 From: William Lam Date: Fri, 14 Dec 2018 05:54:25 -0800 Subject: [PATCH 19/43] Updated URLs to new NSX-T Policy API endpoints --- Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 index 3bfdfe3..dff421a 100644 --- a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 +++ b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 @@ -83,7 +83,7 @@ Function Get-NSXTSegment { If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { $method = "GET" - $segmentsURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/networks/cgw/segments" + $segmentsURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/tier-1s/cgw/segments" if($Troubleshoot) { Write-Host -ForegroundColor cyan "`n[DEBUG] - $METHOD`n$segmentsURL`n" @@ -178,7 +178,7 @@ Function New-NSXTSegment { $body = $payload | ConvertTo-Json -depth 4 $method = "PUT" - $newSegmentsURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/networks/cgw/segments/$Name" + $newSegmentsURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/tier-1s/cgw/segments/$Name" if($Troubleshoot) { Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$newSegmentsURL`n" @@ -231,7 +231,7 @@ Function Remove-NSXTSegment { If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { $method = "DELETE" - $deleteSegmentsURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/networks/cgw/segments/$Id" + $deleteSegmentsURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/tier-1s/cgw/segments/$Id" if($Troubleshoot) { Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$deleteSegmentsURL`n" @@ -285,7 +285,7 @@ Function Get-NSXTFirewall { If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { $method = "GET" - $edgeFirewallURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/$($GatewayType.toLower())/edge-communication-maps/default" + $edgeFirewallURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/$($GatewayType.toLower())/gateway-policies/default" if($Troubleshoot) { Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$edgeFirewallURL`n" @@ -303,7 +303,7 @@ Function Get-NSXTFirewall { } if($requests.StatusCode -eq 200) { - $rules = ($requests.Content | ConvertFrom-Json).communication_entries + $rules = ($requests.Content | ConvertFrom-Json).rules if ($PSBoundParameters.ContainsKey("Name")){ $rules = $rules | where {$_.display_name -eq $Name} @@ -467,7 +467,7 @@ Function New-NSXTFirewall { $body = $payload | ConvertTo-Json -depth 5 $method = "PUT" - $newFirewallURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/$($GatewayType.toLower())/edge-communication-maps/default/communication-entries/$Id" + $newFirewallURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/$($GatewayType.toLower())/gateway-policies/default/rules/$Id" if($Troubleshoot) { Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$newFirewallURL`n" @@ -520,7 +520,7 @@ Function Remove-NSXTFirewall { If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { $method = "DELETE" - $deleteGgroupURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/$($GatewayType.toLower())/edge-communication-maps/default/communication-entries/$Id" + $deleteGgroupURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/$($GatewayType.toLower())/gateway-policies/default/rules/$Id" if($Troubleshoot) { Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$deleteGgroupURL`n" From 3372f3faf39dda82d7082dbf30e4ae79288c3a14 Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Tue, 18 Dec 2018 11:16:26 -0500 Subject: [PATCH 20/43] Introduction of a new Tagging module Introduction of a new module which uses the REST based CIS API to perform tagging operations. More info: http://blogs.vmware.com/PowerCLI/2018/12/new-module-for-tag-management.html --- .../VMware.Community.CISTag.psd1 | 123 ++++ .../VMware.Community.CISTag.psm1 | 693 ++++++++++++++++++ 2 files changed, 816 insertions(+) create mode 100644 Modules/VMware.Community.CISTag/VMware.Community.CISTag.psd1 create mode 100644 Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 diff --git a/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psd1 b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psd1 new file mode 100644 index 0000000..b20f2de --- /dev/null +++ b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psd1 @@ -0,0 +1,123 @@ +# +# Module manifest for module 'VMware.Community.CISTag' +# +# Generated by: Kyle Ruddy +# +# Generated on: 12/14/18 +# + +@{ + +# Script module or binary module file associated with this manifest. +RootModule = 'VMware.Community.CISTag.psm1' + +# Version number of this module. +ModuleVersion = '1.0.0' + +# Supported PSEditions +# CompatiblePSEditions = @() + +# ID used to uniquely identify this module +GUID = 'a0803efd-6017-4049-bfc9-5983a5a0c348' + +# Author of this module +Author = 'Kyle Ruddy' + +# Company or vendor of this module +CompanyName = 'VMware' + +# Copyright statement for this module +Copyright = '(c) VMware. All rights reserved.' + +# Description of the functionality provided by this module +Description = 'Community sourced PowerShell Module for managing vSphere Tags via the CIS Endpoint' + +# Minimum version of the PowerShell engine required by this module +PowerShellVersion = '4.0' + +# Name of the PowerShell host required by this module +# PowerShellHostName = '' + +# Minimum version of the PowerShell host required by this module +# PowerShellHostVersion = '' + +# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# DotNetFrameworkVersion = '' + +# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# CLRVersion = '' + +# Processor architecture (None, X86, Amd64) required by this module +# ProcessorArchitecture = '' + +# Modules that must be imported into the global environment prior to importing this module +# RequiredModules = @() + +# Assemblies that must be loaded prior to importing this module +# RequiredAssemblies = @() + +# Script files (.ps1) that are run in the caller's environment prior to importing this module. +# ScriptsToProcess = @() + +# Type files (.ps1xml) to be loaded when importing this module +# TypesToProcess = @() + +# Format files (.ps1xml) to be loaded when importing this module +# FormatsToProcess = @() + +# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess +# NestedModules = @() + +# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. +FunctionsToExport = 'Get-CISTag', 'Get-CISTagCategory', 'Get-CISTagAssignment', 'New-CISTag', 'New-CISTagCategory', 'New-CISTagAssignment', 'Remove-CISTag', 'Remove-CISTagCategory', 'Remove-CISTagAssignment' + +# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. +# CmdletsToExport = '*' + +# Variables to export from this module +# VariablesToExport = '*' + +# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. +# AliasesToExport = '*' + +# DSC resources to export from this module +# DscResourcesToExport = @() + +# List of all modules packaged with this module +# ModuleList = @() + +# List of all files packaged with this module +# FileList = @() + +# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. +PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + # Tags = @() + + # A URL to the license for this module. + # LicenseUri = '' + + # A URL to the main website for this project. + # ProjectUri = '' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + # ReleaseNotes = '' + + } # End of PSData hashtable + +} # End of PrivateData hashtable + +# HelpInfo URI of this module +# HelpInfoURI = '' + +# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. +# DefaultCommandPrefix = '' + +} + diff --git a/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 new file mode 100644 index 0000000..4dd9c0f --- /dev/null +++ b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 @@ -0,0 +1,693 @@ +function Get-CISTag { +<# +.SYNOPSIS + Gathers tag information from the CIS REST API endpoint +.DESCRIPTION + Will provide a list of tags +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Name + Tag name which should be retreived +.PARAMETER Category + Tag category name which should be retreived +.PARAMETER Id + Tag ID which should be retreived +.EXAMPLE + Get-CISTag + Retreives all tag information +.EXAMPLE + Get-CISTag -Name tagName + Retreives the tag information based on the specified name +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Low')] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + [String]$Name, + [Parameter(Mandatory=$false,Position=1,ValueFromPipelineByPropertyName=$true)] + [String]$Category, + [Parameter(Mandatory=$false,Position=2,ValueFromPipelineByPropertyName=$true)] + [String]$Id + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagSvc = Get-CisService -Name com.vmware.cis.tagging.tag + if ($PSBoundParameters.ContainsKey("Id")) { + $tagOutput = $tagSvc.get($Id) + } else { + $tagArray = @() + $tagIdList = $tagSvc.list() | Select-Object -ExpandProperty Value + foreach ($t in $tagIdList) { + $tagArray += $tagSvc.get($t) + } + if ($PSBoundParameters.ContainsKey("Name")) { + $tagOutput = $tagArray | Where {$_.Name -eq $Name} + } elseif ($PSBoundParameters.ContainsKey("Category")) { + $tagCatid = Get-CISTagCategory -Name $Category | Select-Object -ExpandProperty Id + $tagIdList = $tagSvc.list_tags_for_category($tagCatid) + $tagArray2 = @() + foreach ($t in $tagIdList) { + $tagArray2 += $tagSvc.get($t) + } + $tagOutput = $tagArray2 + } else { + $tagOutput = $tagArray + } + } + $tagOutput | Select-Object Id, Name, Description + } + +} + +function New-CISTag { +<# +.SYNOPSIS + Creates a new tag from the CIS REST API endpoint +.DESCRIPTION + Will create a new tag +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Name + Tag name which should be created +.PARAMETER Category + Category name where the new tag should be associated +.PARAMETER Description + Description for the new tag +.PARAMETER CategoryID + Category ID where the new tag should be associated +.EXAMPLE + New-CISTag -Name tagName -Category categoryName -Description "Tag Descrition" + Creates a new tag based on the specified name +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Medium')] + param( + [Parameter(Mandatory=$true,Position=0)] + [String]$Name, + [Parameter(Mandatory=$false,Position=1)] + [String]$Category, + [Parameter(Mandatory=$false,Position=2)] + [String]$Description, + [Parameter(Mandatory=$false,Position=3)] + [String]$CategoryID + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagSvc = Get-CisService -Name com.vmware.cis.tagging.tag + $tagCreateHelper = $tagSvc.Help.create.create_spec.Create() + $tagCreateHelper.name = $Name + if ($PSBoundParameters.ContainsKey("Category")) { + $tagCreateHelper.category_id = Get-CISTagCategory -Name $Category | Select-Object -ExpandProperty Id + } elseif ($PSBoundParameters.ContainsKey("CategoryId")) { + $tagCreateHelper.category_id = $CategoryID + } else {Write-Warning "No Category input found. Add a Category name or ID."; break} + if ($PSBoundParameters.ContainsKey("Description")) { + $tagCreateHelper.description = $Description + } else { + $tagCreateHelper.description = "" + } + $tagNewId = $tagSvc.create($tagCreateHelper) + Get-CISTag -Id $tagNewId + } + +} + +function Remove-CISTag { +<# +.SYNOPSIS + Removes a tag from the CIS REST API endpoint +.DESCRIPTION + Will delete a new tag +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Name + Tag name which should be removed +.PARAMETER ID + Tag ID which should be removed +.EXAMPLE + Remove-CISTag -Name tagName + Removes a new tag based on the specified name +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + [String]$Name, + [Parameter(Mandatory=$false,Position=1,ValueFromPipelineByPropertyName=$true)] + [String]$ID + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagSvc = Get-CisService -Name com.vmware.cis.tagging.tag + if ($ID) { + $tagSvc.delete($ID) + } else { + $tagId = Get-CISTag -Name $Name | select -ExpandProperty Id + if ($tagId) {$tagSvc.delete($tagId)} + else {Write-Warning "No valid tag found."} + } + } +} + +function Get-CISTagCategory { +<# +.SYNOPSIS + Gathers tag category information from the CIS REST API endpoint +.DESCRIPTION + Will provide a list of tag categories +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Name + Tag category name which should be retreived +.PARAMETER Id + Tag category ID which should be retreived +.EXAMPLE + Get-CISTagCategory + Retreives all tag category information +.EXAMPLE + Get-CISTagCategory -Name tagCategoryName + Retreives the tag category information based on the specified name +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Low')] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + [String]$Name, + [Parameter(Mandatory=$false,Position=2,ValueFromPipelineByPropertyName=$true)] + [String]$Id + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagCatSvc = Get-CisService -Name com.vmware.cis.tagging.category + if ($PSBoundParameters.ContainsKey("Id")) { + $tagCatOutput = $tagCatSvc.get($Id) + } else { + $tagCatArray = @() + $tagCatIdList = $tagCatSvc.list() | Select-Object -ExpandProperty Value + foreach ($tc in $tagCatIdList) { + $tagCatArray += $tagCatSvc.get($tc) + } + if ($PSBoundParameters.ContainsKey("Name")) { + $tagCatOutput = $tagCatArray | Where {$_.Name -eq $Name} + } else { + $tagCatOutput = $tagCatArray + } + } + $tagCatOutput | Select-Object Id, Name, Description, Cardinality + } + +} + +function New-CISTagCategory { +<# +.SYNOPSIS + Creates a new tag category from the CIS REST API endpoint +.DESCRIPTION + Will create a new tag category +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Name + Tag category name which should be created +.PARAMETER Description + Tag category ID which should be retreived +.PARAMETER Cardinality + Tag category ID which should be retreived +.PARAMETER AssociableTypes + Tag category ID which should be retreived +.EXAMPLE + New-CISTagCategory -Name NewTagCategoryName -Description "New Tag Category Description" -Cardinality "Single" -AssociableTypes + Creates a new tag category with the specified information +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Medium')] + param( + [Parameter(Mandatory=$true,Position=0)] + [String]$Name, + [Parameter(Mandatory=$false,Position=1)] + [String]$Description, + [Parameter(Mandatory=$false,Position=2)] + [ValidateSet("SINGLE","MULTIPLE")] + [String]$Cardinality = "SINGLE", + [Parameter(Mandatory=$false,Position=3)] + [ValidateSet("All", "Cluster", "Datacenter", "Datastore", "DatastoreCluster", "DistributedPortGroup", "DistributedSwitch", "Folder", "ResourcePool", "VApp", "VirtualPortGroup", "VirtualMachine", "VMHost")] + [String]$AssociableTypes = "All" + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagCatSvc = Get-CisService -Name com.vmware.cis.tagging.category + $tagCatCreateHelper = $tagCatSvc.Help.create.create_spec.Create() + $tagCatCreateHelper.name = $Name + if ($PSBoundParameters.ContainsKey("Description")) { + $tagCatCreateHelper.description = $Description + } else {$tagCatCreateHelper.description = ""} + $tagCatCreateHelper.cardinality = $Cardinality + $tagCatCreateAssocTypeHelper = $tagCatSvc.help.create.create_spec.associable_types.create() + $tagCatCreateAssocTypeHelper.Add($AssociableTypes) + $tagCatCreateHelper.associable_types = $tagCatCreateAssocTypeHelper + $tagCatNewId = $tagCatSvc.create($tagCatCreateHelper) + Get-CISTagCategory -Id $tagCatNewId + } + +} + +function Remove-CISTagCategory { +<# +.SYNOPSIS + Gathers tag category information from the CIS REST API endpoint +.DESCRIPTION + Will provide a list of tag categories +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Name + Tag category name which should be removed +.PARAMETER Id + Tag category ID which should be removed +.EXAMPLE + Get-CISTagCategory + Retreives all tag category information +.EXAMPLE + Get-CISTagCategory -Name tagCategoryName + Retreives the tag category information based on the specified name + +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + [String]$Name, + [Parameter(Mandatory=$false,Position=2,ValueFromPipelineByPropertyName=$true)] + [String]$Id + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagCatSvc = Get-CisService -Name com.vmware.cis.tagging.category + if ($PSBoundParameters.ContainsKey("Id")) { + $tagCatSvc.delete($Id) + } elseif ($PSBoundParameters.ContainsKey("Name")) { + $tagCatId = Get-CISTagCategory -Name $Name | Select-Object -ExpandProperty Id + $tagCatSvc.delete($tagCatId) + } else {Write-Warning "No tag category found."} + } +} + +function Get-CISTagAssignment { +<# +.SYNOPSIS + Displays a list of the tag assignments from the CIS REST API endpoint +.DESCRIPTION + Will provide a list of the tag assignments +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Category + Tag category name which should be referenced +.PARAMETER Entity + Object name which should be retreived +.PARAMETER ObjectId + Object ID which should be retreived +.EXAMPLE + Get-CISTagAssignment + Retreives all tag assignment information +.EXAMPLE + Get-CISTagAssignment -Entity VMName + Retreives all tag assignments for the VM name +.EXAMPLE + Get-CISTagAssignment -ObjectId 'vm-11' + Retreives all tag assignments for the VM object +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Low')] + param( + [Parameter(Mandatory=$false,Position=0)] + [String]$Category, + [Parameter(Mandatory=$false,Position=1)] + [String]$Entity, + [Parameter(Mandatory=$false,Position=2,ValueFromPipelineByPropertyName=$true)] + [String]$ObjectId + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagOutput = @() + [Boolean]$vCenterConn = $false + $tagAssocSvc = Get-CisService -Name com.vmware.cis.tagging.tag_association + if ($PSBoundParameters.ContainsKey("ObjectId")) { + if ($ObjectId.split('-')[0] -eq 'vm') { + $objType = 'VirtualMachine' + } else {Write-Warning 'Only VirtualMachine types currently supported.'; break} + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $ObjectId + $objObject.type = $objType + $tagIdOutput = $tagAssocSvc.list_attached_tags($objObject) + } elseif ($PSBoundParameters.ContainsKey("Entity")) { + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + [Boolean]$vCenterConn = $true + $viObject = (Get-Inventory -Name $Entity).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $objId + $objObject.type = $objType + } + $tagIdOutput = $tagAssocSvc.list_attached_tags($objObject) + } else { + $tagSvc = Get-CisService -Name com.vmware.cis.tagging.tag + $tagIdOutput = @() + $tagCategories = Get-CISTagCategory | Sort-Object -Property Name + if ($Category) { + $tagCatId = $tagCategories | where {$_.Name -eq $Category} | Select-Object -ExpandProperty Id + $tagIdOutput += $tagSvc.list_tags_for_category($tagCatId) + } else { + foreach ($tagCat in $tagCategories) { + $tagIdOutput += $tagSvc.list_tags_for_category($tagCat.id) + } + } + } + $tagReference = Get-CISTag + + if ($Entity -or $ObjectId) { + foreach ($tagId in $tagIdOutput) { + $tagAttObj = @() + if ($Entity) { + $tagAttObj += $tagAssocSvc.list_attached_objects($tagId) | where {$_.type -eq $viObject.type -and $_.id -eq $viObject.Value} + } else { + $tagAttObj += $tagAssocSvc.list_attached_objects($tagId) | where {$_.id -eq $ObjectId} + } + foreach ($obj in $tagAttObj) { + if ($obj.type -eq "VirtualMachine") { + if (-Not $vmSvc) {$vmSvc = Get-CisService -Name com.vmware.vcenter.vm} + $filterVmObj = $vmsvc.help.list.filter.create() + $filterVmObj.vms.add($obj.Id) | Out-Null + $objName = $vmSvc.list($filterVmObj) | Select-Object -ExpandProperty Name + } + else {$objName = 'Object Not Found'} + $tempObject = "" | Select-Object Tag, Entity + $tempObject.Tag = $tagReference | where {$_.id -eq $tagId} | Select-Object -ExpandProperty Name + $tempObject.Entity = $objName + $tagOutput += $tempObject + } + } + } else { + foreach ($tagId in $tagIdOutput) { + $tagAttObj = @() + $tagAttObj += $tagAssocSvc.list_attached_objects($tagId) + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + [Boolean]$vCenterConn = $true + } elseif ($tagAttObj.Type -contains 'VirtualMachine') { + if (-Not $vmSvc) {$vmSvc = Get-CisService -Name com.vmware.vcenter.vm} + } + foreach ($obj in $tagAttObj) { + if ($vCenterConn) { + $newViObj = New-Object -TypeName VMware.Vim.ManagedObjectReference + $newViObj.Type = $obj.type + $newViObj.Value = $obj.id + $objName = Get-View -Id $newViObj -Property Name | Select-Object -ExpandProperty Name + } elseif ($obj.type -eq "VirtualMachine") { + $filterVmObj = $vmsvc.help.list.filter.create() + $filterVmObj.vms.add($obj.Id) | Out-Null + $objName = $vmSvc.list($filterVmObj) | Select-Object -ExpandProperty Name + } else {$objName = 'Object Not Found'} + $tempObject = "" | Select-Object Tag, Entity + $tempObject.Tag = $tagReference | where {$_.id -eq $tagId} | Select-Object -ExpandProperty Name + $tempObject.Entity = $objName + $tagOutput += $tempObject + } + } + } + return $tagOutput + } +} + +function New-CISTagAssignment { +<# +.SYNOPSIS + Creates new tag assignments from the CIS REST API endpoint +.DESCRIPTION + Will create new tag assignments +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Tag + Tag name which should be referenced +.PARAMETER Entity + Object name which should be retreived +.PARAMETER TagId + Tag ID/s which should be referenced +.PARAMETER ObjectId + Object ID which/s should be retreived +.EXAMPLE + New-CISTagAssignment -Tag TagName -Entity VMName + Creates a tag assignment between the Tag name and the VM name +.EXAMPLE + New-CISTagAssignment -TagId $tagId -ObjectId 'vm-11' + Creates a tag assignment between the Tag ID and the Object ID +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Medium')] + param( + [Parameter(Mandatory=$false,Position=0)] + $Tag, + [Parameter(Mandatory=$false,Position=1)] + $Entity, + [Parameter(Mandatory=$false,Position=2)] + $TagId, + [Parameter(Mandatory=$false,Position=3)] + $ObjectId + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagAssocSvc = Get-CisService -Name com.vmware.cis.tagging.tag_association + if ($PSBoundParameters.ContainsKey("Tag") -and $PSBoundParameters.ContainsKey("Entity")) { + if ($Tag -is [array] -and $Entity -isnot [array]) { + $tagIdList = $tagAssocSvc.help.attach_multiple_tags_to_object.tag_ids.create() + foreach ($t in $Tag) { + $tempId = Get-CISTag -Name $t | Select-Object -ExpandProperty Id + $tagIdList.add($tempId) | Out-Null + } + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + $viObject = (Get-Inventory -Name $Entity).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $objId + $objObject.type = $objType + } + $tagAssocSvc.attach_multiple_tags_to_object($objObject,$tagIdList) | Out-Null + } elseif ($Tag -isnot [array] -and $Entity -is [array]) { + $tagId = Get-CISTag -Name $Tag | Select-Object -ExpandProperty Id + $objList = $tagAssocSvc.help.attach_tag_to_multiple_objects.object_ids.create() + foreach ($e in $Entity) { + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + $viObject = (Get-Inventory -Name $e).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $objId + $objObject.type = $objType + } + $objList.add($objObject) | Out-Null + } + $tagAssocSvc.attach_tag_to_multiple_objects($TagId,$objList) | Out-Null + } elseif ($Tag -isnot [array] -and $Entity -isnot [array]) { + $tagId = Get-CISTag -Name $Tag | Select-Object -ExpandProperty Id + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + $viObject = (Get-Inventory -Name $Entity).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $objId + $objObject.type = $objType + } + $tagAssocSvc.attach($TagId,$objObject) | Out-Null + } + } elseif ($PSBoundParameters.ContainsKey("TagId") -and $PSBoundParameters.ContainsKey("ObjectId")) { + if ($ObjectId.split('-')[0] -eq 'vm') { + $objType = 'VirtualMachine' + } else {Write-Warning 'Only VirtualMachine types currently supported.'; break} + if ($TagId -is [array] -and $ObjectId -isnot [array]) { + $objObject = $tagAssocSvc.help.attach_multiple_tags_to_object.object_id.create() + $objObject.id = $ObjectId + $objObject.type = $objType + $tagIdList = $tagAssocSvc.help.attach_multiple_tags_to_object.tag_ids.create() + foreach ($tId in $TagId) { + $tagIdList.add($tId) | Out-Null + } + $tagAssocSvc.attach_multiple_tags_to_object($objObject,$tagIdList) | Out-Null + } elseif ($TagId -isnot [array] -and $ObjectId -is [array]) { + $objList = $tagAssocSvc.help.attach_tag_to_multiple_objects.object_ids.create() + foreach ($obj in $ObjectId) { + $objObject = $tagAssocSvc.help.attach_tag_to_multiple_objects.object_ids.element.create() + $objObject.id = $obj + $objObject.type = $objType + $objList.add($objObject) | Out-Null + } + $tagAssocSvc.attach_tag_to_multiple_objects($TagId,$objList) | Out-Null + } elseif ($TagId -isnot [array] -and $ObjectId -isnot [array]) { + $objObject = $tagAssocSvc.help.attach.object_id.create() + $objObject.id = $ObjectId + $objObject.type = $objType + $tagAssocSvc.attach($TagId,$objObject) | Out-Null + } + + } else {Write-Output "Multiple tags with multiple objects are not a supported call."} + + } +} + +function Remove-CISTagAssignment { +<# +.SYNOPSIS + Displays a list of the tag assignments from the CIS REST API endpoint +.DESCRIPTION + Will provide a list of the tag assignments +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Tag + Tag name which should be removed +.PARAMETER Entity + Object name which should be removed +.PARAMETER TagId + Tag ID/s which should be removed +.PARAMETER ObjectId + Object ID which/s should be removed +.EXAMPLE + Remove-CISTagAssignment -TagId $tagId -ObjectId 'vm-11' + Removes the tag assignment between the Tag ID and the Object ID +.EXAMPLE + Remove-CISTagAssignment -Tag TagName -Entity VMName + Removes the tag assignment between the Tag name and the Entity name +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + $Tag, + [Parameter(Mandatory=$false,Position=1,ValueFromPipelineByPropertyName=$true)] + $Entity, + [Parameter(Mandatory=$false,Position=2)] + $TagId, + [Parameter(Mandatory=$false,Position=3)] + $ObjectId + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagAssocSvc = Get-CisService -Name com.vmware.cis.tagging.tag_association + if ($PSBoundParameters.ContainsKey("Tag") -and $PSBoundParameters.ContainsKey("Entity")) { + if ($Tag -is [array] -and $Entity -isnot [array]) { + $tagIdList = $tagAssocSvc.help.detach_multiple_tags_from_object.tag_ids.create() + foreach ($t in $Tag) { + $tempId = Get-CISTag -Name $t | Select-Object -ExpandProperty Id + $tagIdList.add($tempId) | Out-Null + } + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + $viObject = (Get-Inventory -Name $Entity).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.detach_multiple_tags_from_object.object_id.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.detach_multiple_tags_from_object.object_id.create() + $objObject.id = $objId + $objObject.type = $objType + } + $tagAssocSvc.detach_multiple_tags_from_object($objObject,$tagIdList) | Out-Null + } elseif ($Tag -isnot [array] -and $Entity -is [array]) { + $tagId = Get-CISTag -Name $Tag | Select-Object -ExpandProperty Id + $objList = $tagAssocSvc.help.detach_tag_from_multiple_objects.object_ids.create() + foreach ($e in $Entity) { + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + $viObject = (Get-Inventory -Name $e).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.detach_tag_from_multiple_objects.object_ids.element.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.detach_tag_from_multiple_objects.object_ids.element.create() + $objObject.id = $objId + $objObject.type = $objType + } + $objList.add($objObject) | Out-Null + } + $tagAssocSvc.detach_tag_from_multiple_objects($TagId,$objList) | Out-Null + } elseif ($Tag -isnot [array] -and $Entity -isnot [array]) { + $tagId = Get-CISTag -Name $Tag | Select-Object -ExpandProperty Id + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + $viObject = (Get-Inventory -Name $Entity).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.detach.object_id.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.detach.object_id.create() + $objObject.id = $objId + $objObject.type = $objType + } + $tagAssocSvc.detach($TagId,$objObject) | Out-Null + } + } elseif ($PSBoundParameters.ContainsKey("TagId") -and $PSBoundParameters.ContainsKey("ObjectId")) { + if ($ObjectId.split('-')[0] -eq 'vm') { + $objType = 'VirtualMachine' + } else {Write-Warning 'Only VirtualMachine types currently supported.'; break} + if ($TagId -is [array] -and $ObjectId -isnot [array]) { + $objObject = $tagAssocSvc.help.detach_multiple_tags_from_object.object_id.create() + $objObject.id = $ObjectId + $objObject.type = $objType + $tagIdList = $tagAssocSvc.help.detach_multiple_tags_from_object.tag_ids.create() + foreach ($tId in $TagId) { + $tagIdList.add($tId) | Out-Null + } + $tagAssocSvc.detach_multiple_tags_from_object($objObject,$tagIdList) | Out-Null + } elseif ($TagId -isnot [array] -and $ObjectId -is [array]) { + $objList = $tagAssocSvc.help.detach_tag_from_multiple_objects.object_ids.create() + foreach ($obj in $ObjectId) { + $objObject = $tagAssocSvc.help.detach_tag_from_multiple_objects.object_ids.element.create() + $objObject.id = $obj + $objObject.type = $objType + $objList.add($objObject) | Out-Null + } + $tagAssocSvc.detach_tag_from_multiple_objects($TagId,$objList) | Out-Null + } elseif ($TagId -isnot [array] -and $ObjectId -isnot [array]) { + $objObject = $tagAssocSvc.help.detach.object_id.create() + $objObject.id = $ObjectId + $objObject.type = $objType + $tagAssocSvc.detach($TagId,$objObject) | Out-Null + } + } else {Write-Output "Multiple tags with multiple objects are not a supported call."} + + } +} \ No newline at end of file From 44879d8c25df1e3b0165d9441be6b236aaaab099 Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Tue, 18 Dec 2018 15:00:39 -0500 Subject: [PATCH 21/43] Update VMware.Community.CISTag.psm1 Updated Synopsis and Examples --- .../VMware.Community.CISTag.psm1 | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 index 4dd9c0f..837a595 100644 --- a/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 +++ b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 @@ -248,9 +248,9 @@ function New-CISTagCategory { function Remove-CISTagCategory { <# .SYNOPSIS - Gathers tag category information from the CIS REST API endpoint + Removes tag category information from the CIS REST API endpoint .DESCRIPTION - Will provide a list of tag categories + Will remove a tag categorie .NOTES Author: Kyle Ruddy, @kmruddy .PARAMETER Name @@ -258,11 +258,8 @@ function Remove-CISTagCategory { .PARAMETER Id Tag category ID which should be removed .EXAMPLE - Get-CISTagCategory - Retreives all tag category information -.EXAMPLE - Get-CISTagCategory -Name tagCategoryName - Retreives the tag category information based on the specified name + Remove-CISTagCategory -Name tagCategoryName + Removes the tag category information based on the specified name #> [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')] @@ -558,9 +555,9 @@ function New-CISTagAssignment { function Remove-CISTagAssignment { <# .SYNOPSIS - Displays a list of the tag assignments from the CIS REST API endpoint + Removes a tag assignment from the CIS REST API endpoint .DESCRIPTION - Will provide a list of the tag assignments + Will remove provided tag assignments .NOTES Author: Kyle Ruddy, @kmruddy .PARAMETER Tag From bfbcbc8faa185709cfa7a527cdc3083da99c9d7a Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Tue, 18 Dec 2018 19:37:42 -0500 Subject: [PATCH 22/43] Update VMware.Community.CISTag.psm1 Add VIServer capabilities to Get-CISTag --- .../VMware.Community.CISTag.psm1 | 41 +++++++++++++------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 index 837a595..05594e4 100644 --- a/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 +++ b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 @@ -34,23 +34,38 @@ function Get-CISTag { if ($PSBoundParameters.ContainsKey("Id")) { $tagOutput = $tagSvc.get($Id) } else { - $tagArray = @() - $tagIdList = $tagSvc.list() | Select-Object -ExpandProperty Value - foreach ($t in $tagIdList) { - $tagArray += $tagSvc.get($t) + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + [Boolean]$vCenterConn = $true + $vCTagList = Get-Tag + } else { + $tagArray = @() + $tagIdList = $tagSvc.list() | Select-Object -ExpandProperty Value + [integer]$counter = 1 + foreach ($t in $tagIdList) { + $tagArray += $tagSvc.get($t) + $counter++ + if ($counter -gt 200) {Start-Sleep -Milliseconds 1; $counter = 1} + } } if ($PSBoundParameters.ContainsKey("Name")) { - $tagOutput = $tagArray | Where {$_.Name -eq $Name} + if ($vCenterConn){ + $tagOutput = $vCTagList | where {$_.Name -eq $Name} + } else {$tagOutput = $tagArray | Where {$_.Name -eq $Name}} } elseif ($PSBoundParameters.ContainsKey("Category")) { - $tagCatid = Get-CISTagCategory -Name $Category | Select-Object -ExpandProperty Id - $tagIdList = $tagSvc.list_tags_for_category($tagCatid) - $tagArray2 = @() - foreach ($t in $tagIdList) { - $tagArray2 += $tagSvc.get($t) + if ($vCenterConn){ + $tagOutput = $vCTagList | where {$_.Category -eq $Category} + } else { + $tagCatid = Get-CISTagCategory -Name $Category | Select-Object -ExpandProperty Id + $tagIdList = $tagSvc.list_tags_for_category($tagCatid) + $tagArray2 = @() + foreach ($t in $tagIdList) { + $tagArray2 += $tagSvc.get($t) + } + $tagOutput = $tagArray2 } - $tagOutput = $tagArray2 } else { - $tagOutput = $tagArray + if ($vCenterConn){$tagOutput = $vCTagList} + else {$tagOutput = $tagArray} } } $tagOutput | Select-Object Id, Name, Description @@ -250,7 +265,7 @@ function Remove-CISTagCategory { .SYNOPSIS Removes tag category information from the CIS REST API endpoint .DESCRIPTION - Will remove a tag categorie + Will remove a tag category .NOTES Author: Kyle Ruddy, @kmruddy .PARAMETER Name From 4652495ece548970cb8b43c6b03f53bb2b27d94a Mon Sep 17 00:00:00 2001 From: William Lam Date: Thu, 20 Dec 2018 06:35:45 -0800 Subject: [PATCH 23/43] Fixing Get/New-NSXTSegment due to NSX-T Policy API change --- Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 index dff421a..6a4204f 100644 --- a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 +++ b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 @@ -112,7 +112,7 @@ Function Get-NSXTSegment { $subnets = $segment.subnets $network = $subnets.network - $gateway = $subnets.gateway_addresses + $gateway = $subnets.gateway_address $dhcpRange = $subnets.dhcp_ranges $tmp = [pscustomobject] @{ @@ -147,12 +147,12 @@ Function New-NSXTSegment { .DESCRIPTION This cmdlet creates a new NSX-T Segment (Logical Networks) .EXAMPLE - New-NSXTSegment -Name "sddc-cgw-network-4" -Gateway "192.168.4.1" -Prefix "24" -DHCP -DHCPRange "192.168.4.2-192.168.4.254" + New-NSXTSegment -Name "sddc-cgw-network-4" -Gateway "192.168.4.1/24" -Network "192.168.0/24" -DHCP -DHCPRange "192.168.4.2-192.168.4.254" #> Param ( [Parameter(Mandatory=$True)]$Name, [Parameter(Mandatory=$True)]$Gateway, - [Parameter(Mandatory=$True)]$Prefix, + [Parameter(Mandatory=$True)]$Network, [Parameter(Mandatory=$False)]$DHCPRange, [Switch]$DHCP, [Switch]$Troubleshoot @@ -166,9 +166,9 @@ Function New-NSXTSegment { } $subnets = @{ - gateway_addresses = @($gateway); - prefix_len = $Prefix; - dhcp_ranges = $dhcpConf + gateway_address = $gateway; + network = $Network; + dhcp_ranges = $dhcpConf; } $payload = @{ From 81e60245d03e981a57ca944b9e20d754fd7d770b Mon Sep 17 00:00:00 2001 From: William Lam Date: Fri, 21 Dec 2018 09:58:37 -0800 Subject: [PATCH 24/43] Fixing New-NSXTSegment (Network property not required) --- Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 index 6a4204f..5a30156 100644 --- a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 +++ b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 @@ -147,12 +147,11 @@ Function New-NSXTSegment { .DESCRIPTION This cmdlet creates a new NSX-T Segment (Logical Networks) .EXAMPLE - New-NSXTSegment -Name "sddc-cgw-network-4" -Gateway "192.168.4.1/24" -Network "192.168.0/24" -DHCP -DHCPRange "192.168.4.2-192.168.4.254" + New-NSXTSegment -Name "sddc-cgw-network-4" -Gateway "192.168.4.1/24" -DHCP -DHCPRange "192.168.4.2-192.168.4.254" #> Param ( [Parameter(Mandatory=$True)]$Name, [Parameter(Mandatory=$True)]$Gateway, - [Parameter(Mandatory=$True)]$Network, [Parameter(Mandatory=$False)]$DHCPRange, [Switch]$DHCP, [Switch]$Troubleshoot @@ -167,7 +166,6 @@ Function New-NSXTSegment { $subnets = @{ gateway_address = $gateway; - network = $Network; dhcp_ranges = $dhcpConf; } From 06d018c7a6abd4657f0b057a31358e008de3dcb1 Mon Sep 17 00:00:00 2001 From: PARAMESHO Date: Wed, 2 Jan 2019 21:55:26 +0530 Subject: [PATCH 25/43] Set-HVApplicationIcon not behaving correctly with .ico and .bmp files When bmp/ico image files are used as customized application icons, short cuts feature on Horizon Client is facing the issues in rendering. Bug 2168320 has been reported for this issue. We have decided to block all the non-png image files for the customization of application icons. Testing: Tested with the changes. Working as expected. Refer review https://reviewboard.eng.vmware.com/r/1446121 for more details. --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 5b68b9f..7717e40 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -8819,6 +8819,16 @@ function Set-HVApplicationIcon { } process { + if (!(Test-Path $IconPath)) { + Write-Error "File:[$IconPath] does not exist." + break + } + + if ([IO.Path]::GetExtension($IconPath) -ne '.png') { + Write-Error "Unsupported file format:[$IconPath]. Only PNG image files are supported." + break + } + try { $appInfo = Get-HVQueryResult -EntityType ApplicationInfo -Filter (Get-HVQueryFilter data.name -Eq $ApplicationName) -HvServer $HvServer } catch { @@ -8832,11 +8842,6 @@ function Set-HVApplicationIcon { break } - if (!(Test-Path $IconPath)) { - Write-Error "File:[$IconPath] does not exists" - break - } - $spec = New-Object VMware.Hv.ApplicationIconSpec $base = New-Object VMware.Hv.ApplicationIconBase From 25cfffa14f343f799fc236d6e1108297aaea0c49 Mon Sep 17 00:00:00 2001 From: William Lam Date: Wed, 2 Jan 2019 10:07:40 -0800 Subject: [PATCH 26/43] Adding "Get" functions for Distribugted FW rules --- Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 | 282 +++++++++++++++++-- 1 file changed, 266 insertions(+), 16 deletions(-) diff --git a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 index 5a30156..426a357 100644 --- a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 +++ b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 @@ -126,7 +126,8 @@ Function Get-NSXTSegment { } $results } else { - Write-Error "Failed to retrieve NSX-T Segments" + Write-Error "Error in retrieving NSX-T Segments" + Write-Error "Return code: " $requests.StatusCode } } } @@ -198,8 +199,8 @@ Function New-NSXTSegment { Write-Host "Succesfully created new NSX-T Segment $Name" ($requests.Content | ConvertFrom-Json) | select display_name, id } else { - Write-Error "Failed to create new NSX-T Segment" - + Write-Error "Error in creating new NSX-T Segment" + Write-Error "Return code: " $requests.StatusCode } } } @@ -249,8 +250,8 @@ Function Remove-NSXTSegment { if($requests.StatusCode -eq 200) { Write-Host "Succesfully removed NSX-T Segment $Name" } else { - Write-Error "Failed to remove NSX-T Segments" - + Write-Error "Error in removing NSX-T Segments" + Write-Error "Return code: " $requests.StatusCode } } } @@ -321,7 +322,11 @@ Function Get-NSXTFirewall { Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$sourceGroupURL`n" } try { - $requests = Invoke-WebRequest -Uri $sourceGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $sourceGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $sourceGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers + } } catch { Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" break @@ -343,7 +348,11 @@ Function Get-NSXTFirewall { Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$destionationGroupURL`n" } try { - $requests = Invoke-WebRequest -Uri $destionationGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $destionationGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $destionationGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers + } } catch { Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" break @@ -365,7 +374,11 @@ Function Get-NSXTFirewall { Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$serviceGroupURL`n" } try { - $requests = Invoke-WebRequest -Uri $serviceGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $serviceGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $serviceGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers + } } catch { Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" break @@ -389,7 +402,8 @@ Function Get-NSXTFirewall { $results } else { - Write-Error "Failed to retrieve NSX-T Firewall Rules" + Write-Error "Error in retrieving NSX-T Firewall Rules" + Write-Error "Return code: " $requests.StatusCode } } } @@ -487,7 +501,8 @@ Function New-NSXTFirewall { Write-Host "Succesfully created new NSX-T Firewall Rule $Name" ($requests.Content | ConvertFrom-Json) | select display_name, id } else { - Write-Error "Failed to create new NSX-T Firewall Rule" + Write-Error "Error in creating new NSX-T Firewall Rule" + Write-Error "Return code: " $requests.StatusCode } } } @@ -538,7 +553,8 @@ Function Remove-NSXTFirewall { if($requests.StatusCode -eq 200) { Write-Host "Succesfully removed NSX-T Firewall Rule $Name" } else { - Write-Error "Failed to create new NSX-T Firewall Rule" + Write-Error "Error in creating new NSX-T Firewall Rule" + Write-Error "Return code: " $requests.StatusCode } } } @@ -622,7 +638,8 @@ Function Get-NSXTGroup { } $results } else { - Write-Error "Failed to retrieve NSX-T Groups" + Write-Error "Error in retrieving NSX-T Groups" + Write-Error "Return code: " $requests.StatusCode } } } @@ -687,7 +704,8 @@ Function New-NSXTGroup { Write-Host "Succesfully created new NSX-T Group $Name" ($requests.Content | ConvertFrom-Json) | select display_name, id } else { - Write-Error "Failed to create new NSX-T Group" + Write-Error "Error in creating new NSX-T Group" + Write-Error "Return code: " $requests.StatusCode } } } @@ -738,7 +756,8 @@ Function Remove-NSXTGroup { if($requests.StatusCode -eq 200) { Write-Host "Succesfully removed NSX-T Group $Name" } else { - Write-Error "Failed to create new NSX-T Group" + Write-Error "Error in creating new NSX-T Group" + Write-Error "Return code: " $requests.StatusCode } } } @@ -812,7 +831,8 @@ Function Get-NSXTService { } $results } else { - Write-Error "Failed to retrieve NSX-T Services" + Write-Error "Error in retrieving NSX-T Services" + Write-Error "Return code: " $requests.StatusCode } } } @@ -881,7 +901,237 @@ Function New-NSXTService { Write-Host "Succesfully created new NSX-T Service $Name" ($requests.Content | ConvertFrom-Json) | select display_name, id } else { - Write-Error "Failed to create new NSX-T Service" + Write-Error "Error in creating new NSX-T Service" + Write-Error "Return code: " $requests.StatusCode + } + } +} + +Function Get-NSXTDistFirewallSection { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 12/31/2018 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Returns all NSX-T Distributed Firewall Groups + .DESCRIPTION + This cmdlet retrieves all NSX-T Distributed Firewall Sections + .EXAMPLE + Get-NSXTDistFirewallSection + .EXAMPLE + Get-NSXTDistFirewallSection -Name "App Section 1" + .EXAMPLE + et-NSXTDistFirewallSection -Category Emergency +#> + param( + [Parameter(Mandatory=$false)][String]$Name, + [Parameter(Mandatory=$false)][ValidateSet("Emergency","Infrastructure","Environment","Application")][String]$Category, + [Switch]$Troubleshoot + ) + + If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { + $method = "GET" + $distFirewallGroupURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/cgw/communication-maps" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$distFirewallGroupURL`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $distFirewallGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $distFirewallGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers + } + } catch { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } + + if($requests.StatusCode -eq 200) { + $groups = ($requests.Content | ConvertFrom-Json).results + + if ($PSBoundParameters.ContainsKey("Name")){ + $groups = $groups | where {$_.display_name -eq $Name} + } + + if ($PSBoundParameters.ContainsKey("Category")){ + $groups = $groups | where {$_.category -eq $Category} + } + + $results = @() + foreach ($group in $groups | Sort-Object -Property category) { + $tmp = [pscustomobject] @{ + Id = $group.id; + Section = $group.display_name; + Category = $group.category; + Precedence = $group.precedence; + } + $results+=$tmp + } + $results + + } else { + Write-Error "Error in retrieving NSX-T Distributed Firewall Sections" + Write-Error "Return code: " $requests.StatusCode + } + } +} + +Function Get-NSXTDistFirewall { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 09/11/2018 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Returns all NSX-T Distributed Firewall Rules for a given Section + .DESCRIPTION + This cmdlet retrieves all NSX-T Distributed Firewall Rules for a given Section + .EXAMPLE + Get-NSXTDistFirewall -Name "App Section 1" +#> + param( + [Parameter(Mandatory=$true)][String]$Name, + [Switch]$Troubleshoot + ) + + If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { + try { + $distGroupId = (Get-NSXTDistFirewallSection -Name $Name).Id + } + catch { + Write-Host -ForegroundColor Red "`nUnable to find NSX-T Distributed Firewall Group named $Name`n" + break + } + + $method = "GET" + $distFirewallURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/cgw/communication-maps/$distGroupId" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$distFirewallURL`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $distFirewallURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $distFirewallURL -Method $method -Headers $global:nsxtProxyConnection.headers + } + } catch { + Write-Host -ForegroundColor Red "`nFailed to retrieve Distributed Firewall Rules`n" + break + } + + if($requests.StatusCode -eq 200) { + $rules = ($requests.Content | ConvertFrom-Json).communication_entries + + $results = @() + foreach ($rule in $rules | Sort-Object -Property sequence_number) { + $sourceGroups = $rule.source_groups + $source = @() + foreach ($sourceGroup in $sourceGroups) { + if($sourceGroup -eq "ANY") { + $source += $sourceGroup + break + } else { + $sourceGroupURL = $global:nsxtProxyConnection.Server + "/policy/api/v1" + $sourceGroup + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$sourceGroupURL`n" + } + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $sourceGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $sourceGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers + } + } catch { + Write-Host -ForegroundColor Red "`nFailed to retrieve Source Group Rule mappings`n" + break + } + $group = ($requests.Content | ConvertFrom-Json) + $source += $group.display_name + } + } + + $destinationGroups = $rule.destination_groups + $destination = @() + foreach ($destinationGroup in $destinationGroups) { + if($destinationGroup -eq "ANY") { + $destination += $destinationGroup + break + } else { + $destionationGroupURL = $global:nsxtProxyConnection.Server + "/policy/api/v1" + $destinationGroup + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$destionationGroupURL`n" + } + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $destionationGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $destionationGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers + } + } catch { + Write-Host -ForegroundColor Red "`nFailed to retireve Destination Group Rule mappings`n" + break + } + $group = ($requests.Content | ConvertFrom-Json) + $destination += $group.display_name + } + } + + $serviceGroups = $rule.services + $service = @() + foreach ($serviceGroup in $serviceGroups) { + if($serviceGroup -eq "ANY") { + $service += $serviceGroup + break + } else { + $serviceGroupURL = $global:nsxtProxyConnection.Server + "/policy/api/v1" + $serviceGroup + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$serviceGroupURL`n" + } + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $serviceGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $serviceGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers + } + } catch { + Write-Host -ForegroundColor Red "`nFailed to retrieve Services Rule mappings`n" + break + } + $group = ($requests.Content | ConvertFrom-Json) + $service += $group.display_name + } + } + + $tmp = [pscustomobject] @{ + SequenceNumber = $rule.sequence_number; + Name = $rule.display_name; + ID = $rule.id; + Source = $source; + Destination = $destination; + Services = $service; + Action = $rule.action; + } + $results+=$tmp + } + $results + } else { + Write-Error "Error in retrieving NSX-T Distributed Firewall Rules" + Write-Error "Return code: " $requests.StatusCode } } } \ No newline at end of file From 5571a8900a4d39c5a8739e6f3a13276a05fe0734 Mon Sep 17 00:00:00 2001 From: William Lam Date: Thu, 3 Jan 2019 12:21:50 -0800 Subject: [PATCH 27/43] Added {New,Remove}-NSXTDisFirewall functions --- Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 | 411 ++++++++++++++----- 1 file changed, 319 insertions(+), 92 deletions(-) diff --git a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 index 426a357..ef83777 100644 --- a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 +++ b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 @@ -96,8 +96,14 @@ Function Get-NSXTSegment { $requests = Invoke-WebRequest -Uri $segmentsURL -Method $method -Headers $global:nsxtProxyConnection.headers } } catch { - Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" - break + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in retrieving NSX-T Segments" + Write-Error "`n($_.Exception.Message)`n" + break + } } if($requests.StatusCode -eq 200) { @@ -125,9 +131,6 @@ Function Get-NSXTSegment { $results+=$tmp } $results - } else { - Write-Error "Error in retrieving NSX-T Segments" - Write-Error "Return code: " $requests.StatusCode } } } @@ -191,16 +194,19 @@ Function New-NSXTSegment { $requests = Invoke-WebRequest -Uri $newSegmentsURL -Body $body -Method $method -Headers $global:nsxtProxyConnection.headers } } catch { - Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" - break + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in creating new NSX-T Segment" + Write-Error "`n($_.Exception.Message)`n" + break + } } if($requests.StatusCode -eq 200) { Write-Host "Succesfully created new NSX-T Segment $Name" ($requests.Content | ConvertFrom-Json) | select display_name, id - } else { - Write-Error "Error in creating new NSX-T Segment" - Write-Error "Return code: " $requests.StatusCode } } } @@ -243,15 +249,18 @@ Function Remove-NSXTSegment { $requests = Invoke-WebRequest -Uri $deleteSegmentsURL -Method $method -Headers $global:nsxtProxyConnection.headers } } catch { - Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" - break + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in removing NSX-T Segments" + Write-Error "`n($_.Exception.Message)`n" + break + } } if($requests.StatusCode -eq 200) { Write-Host "Succesfully removed NSX-T Segment $Name" - } else { - Write-Error "Error in removing NSX-T Segments" - Write-Error "Return code: " $requests.StatusCode } } } @@ -297,8 +306,14 @@ Function Get-NSXTFirewall { $requests = Invoke-WebRequest -Uri $edgeFirewallURL -Method $method -Headers $global:nsxtProxyConnection.headers } } catch { - Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" - break + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in retrieving NSX-T Firewall Rules" + Write-Error "`n($_.Exception.Message)`n" + break + } } if($requests.StatusCode -eq 200) { @@ -401,9 +416,6 @@ Function Get-NSXTFirewall { } $results - } else { - Write-Error "Error in retrieving NSX-T Firewall Rules" - Write-Error "Return code: " $requests.StatusCode } } } @@ -424,15 +436,14 @@ Function New-NSXTFirewall { .DESCRIPTION This cmdlet creates a new NSX-T Firewall Rule on MGW or CGW .EXAMPLE - New-NSXTFirewall -GatewayType MGW -Name TEST -Id TEST -SourceGroupId ESXI -DestinationGroupId ANY -Service ANY -Logged $true -SequenceNumber 7 -Action ALLOW + New-NSXTFirewall -GatewayType MGW -Name TEST -SourceGroup @("ANY") -DestinationGroup @("ESXI") -Service ANY -Logged $true -SequenceNumber 0 -Action ALLOW #> Param ( [Parameter(Mandatory=$True)]$Name, [Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType, - [Parameter(Mandatory=$True)]$Id, [Parameter(Mandatory=$True)]$SequenceNumber, - [Parameter(Mandatory=$True)]$SourceGroupId, - [Parameter(Mandatory=$True)]$DestinationGroupId, + [Parameter(Mandatory=$True)]$SourceGroup, + [Parameter(Mandatory=$True)]$DestinationGroup, [Parameter(Mandatory=$True)]$Service, [Parameter(Mandatory=$True)][ValidateSet("ALLOW","DENY")]$Action, [Parameter(Mandatory=$false)][Boolean]$Logged=$false, @@ -441,34 +452,43 @@ Function New-NSXTFirewall { If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { - if($DestinationGroupId -eq "ANY") { - $destinationGroups = $DestinationGroupId - } else { - $destinationGroups = "/infra/domains/$($GatewayType.toLower())/groups/$DestinationGroupId" + $generatedId = (New-Guid).Guid + + $destinationGroups = @() + foreach ($group in $DestinationGroup) { + if($group -eq "ANY") { + $destinationGroups = @("ANY") + } else { + $tmp = (Get-NSXTGroup -GatewayType $GatewayType -Name $group).Path + $destinationGroups+= $tmp + } } $sourceGroups = @() - foreach ($group in $SourceGroupId) { - $tmp = "/infra/domains/$($GatewayType.toLower())/groups/$group" - $sourceGroups+= $tmp + foreach ($group in $SourceGroup) { + if($group -eq "ANY") { + $sourceGroups = @("ANY") + } else { + $tmp = (Get-NSXTGroup -GatewayType $GatewayType -Name $group).Path + $sourceGroups+= $tmp + } } $services = @() foreach ($serviceName in $Service) { - if($serviceName -eq "ANY") { - $tmp = "ANY" + if($group -eq "ANY") { + $services = @("ANY") } else { $tmp = "/infra/services/$serviceName" + $services+=$tmp } - $services+=$tmp } $payload = @{ display_name = $Name; resource_type = "CommunicationEntry"; - id = $Id; sequence_number = $SequenceNumber; - destination_groups = @($destinationGroups); + destination_groups = $destinationGroups; source_groups = $sourceGroups; logged = $Logged; scope = @("/infra/labels/$($GatewayType.toLower())"); @@ -479,7 +499,7 @@ Function New-NSXTFirewall { $body = $payload | ConvertTo-Json -depth 5 $method = "PUT" - $newFirewallURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/$($GatewayType.toLower())/gateway-policies/default/rules/$Id" + $newFirewallURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/$($GatewayType.toLower())/gateway-policies/default/rules/$generatedId" if($Troubleshoot) { Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$newFirewallURL`n" @@ -493,16 +513,19 @@ Function New-NSXTFirewall { $requests = Invoke-WebRequest -Uri $newFirewallURL -Body $body -Method $method -Headers $global:nsxtProxyConnection.headers } } catch { - Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" - break + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in creating new NSX-T Firewall Rule" + Write-Error "`n($_.Exception.Message)`n" + break + } } if($requests.StatusCode -eq 200) { Write-Host "Succesfully created new NSX-T Firewall Rule $Name" ($requests.Content | ConvertFrom-Json) | select display_name, id - } else { - Write-Error "Error in creating new NSX-T Firewall Rule" - Write-Error "Return code: " $requests.StatusCode } } } @@ -546,15 +569,18 @@ Function Remove-NSXTFirewall { $requests = Invoke-WebRequest -Uri $deleteGgroupURL -Method $method -Headers $global:nsxtProxyConnection.headers } } catch { - Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" - break + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in creating new NSX-T Firewall Rule" + Write-Error "`n($_.Exception.Message)`n" + break + } } if($requests.StatusCode -eq 200) { - Write-Host "Succesfully removed NSX-T Firewall Rule $Name" - } else { - Write-Error "Error in creating new NSX-T Firewall Rule" - Write-Error "Return code: " $requests.StatusCode + Write-Host "Succesfully removed NSX-T Firewall Rule" } } } @@ -600,8 +626,14 @@ Function Get-NSXTGroup { $requests = Invoke-WebRequest -Uri $edgeFirewallGroupsURL -Method $method -Headers $global:nsxtProxyConnection.headers } } catch { - Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" - break + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in retrieving NSX-T Groups" + Write-Error "`n($_.Exception.Message)`n" + break + } } if($requests.StatusCode -eq 200) { @@ -633,13 +665,11 @@ Function Get-NSXTGroup { ID = $group.id; Type = $groupType; Members = $members; + Path = $group.path; } $results+=$tmp } $results - } else { - Write-Error "Error in retrieving NSX-T Groups" - Write-Error "Return code: " $requests.StatusCode } } } @@ -682,7 +712,8 @@ Function New-NSXTGroup { $body = $payload | ConvertTo-Json -depth 5 $method = "PUT" - $newGroupURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/$($GatewayType.toLower())/groups/$Name" + $generatedId = (New-Guid).Guid + $newGroupURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/$($GatewayType.toLower())/groups/$generatedId" if($Troubleshoot) { Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$newGroupURL`n" @@ -696,16 +727,19 @@ Function New-NSXTGroup { $requests = Invoke-WebRequest -Uri $newGroupURL -Body $body -Method $method -Headers $global:nsxtProxyConnection.headers } } catch { - Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" - break + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in creating new NSX-T Group" + Write-Error "`n($_.Exception.Message)`n" + break + } } if($requests.StatusCode -eq 200) { Write-Host "Succesfully created new NSX-T Group $Name" ($requests.Content | ConvertFrom-Json) | select display_name, id - } else { - Write-Error "Error in creating new NSX-T Group" - Write-Error "Return code: " $requests.StatusCode } } } @@ -749,15 +783,18 @@ Function Remove-NSXTGroup { $requests = Invoke-WebRequest -Uri $deleteGgroupURL -Method $method -Headers $global:nsxtProxyConnection.headers } } catch { - Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" - break + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in creating new NSX-T Group" + Write-Error "`n($_.Exception.Message)`n" + break + } } if($requests.StatusCode -eq 200) { Write-Host "Succesfully removed NSX-T Group $Name" - } else { - Write-Error "Error in creating new NSX-T Group" - Write-Error "Return code: " $requests.StatusCode } } } @@ -802,8 +839,14 @@ Function Get-NSXTService { $requests = Invoke-WebRequest -Uri $serviceGroupsURL -Method $method -Headers $global:nsxtProxyConnection.headers } } catch { - Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" - break + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in retrieving NSX-T Services" + Write-Error "`n($_.Exception.Message)`n" + break + } } if($requests.StatusCode -eq 200) { @@ -830,9 +873,6 @@ Function Get-NSXTService { $results += $tmp } $results - } else { - Write-Error "Error in retrieving NSX-T Services" - Write-Error "Return code: " $requests.StatusCode } } } @@ -893,16 +933,19 @@ Function New-NSXTService { $requests = Invoke-WebRequest -Uri $newServiceURL -Body $body -Method $method -Headers $global:nsxtProxyConnection.headers } } catch { - Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" - break + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in creating new NSX-T Service" + Write-Error "`n($_.Exception.Message)`n" + break + } } if($requests.StatusCode -eq 200) { Write-Host "Succesfully created new NSX-T Service $Name" ($requests.Content | ConvertFrom-Json) | select display_name, id - } else { - Write-Error "Error in creating new NSX-T Service" - Write-Error "Return code: " $requests.StatusCode } } } @@ -912,7 +955,7 @@ Function Get-NSXTDistFirewallSection { .NOTES =========================================================================== Created by: William Lam - Date: 12/31/2018 + Date: 01/01/2019 Organization: VMware Blog: http://www.virtuallyghetto.com Twitter: @lamw @@ -950,8 +993,14 @@ Function Get-NSXTDistFirewallSection { $requests = Invoke-WebRequest -Uri $distFirewallGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers } } catch { - Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" - break + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in retrieving NSX-T Distributed Firewall Sections" + Write-Error "`n($_.Exception.Message)`n" + break + } } if($requests.StatusCode -eq 200) { @@ -976,10 +1025,6 @@ Function Get-NSXTDistFirewallSection { $results+=$tmp } $results - - } else { - Write-Error "Error in retrieving NSX-T Distributed Firewall Sections" - Write-Error "Return code: " $requests.StatusCode } } } @@ -989,7 +1034,7 @@ Function Get-NSXTDistFirewall { .NOTES =========================================================================== Created by: William Lam - Date: 09/11/2018 + Date: 01/01/2019 Organization: VMware Blog: http://www.virtuallyghetto.com Twitter: @lamw @@ -1000,20 +1045,26 @@ Function Get-NSXTDistFirewall { .DESCRIPTION This cmdlet retrieves all NSX-T Distributed Firewall Rules for a given Section .EXAMPLE - Get-NSXTDistFirewall -Name "App Section 1" + Get-NSXTDistFirewall -SectionName "App Section 1" #> param( - [Parameter(Mandatory=$true)][String]$Name, + [Parameter(Mandatory=$true)][String]$SectionName, [Switch]$Troubleshoot ) If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { try { - $distGroupId = (Get-NSXTDistFirewallSection -Name $Name).Id + $distGroupId = (Get-NSXTDistFirewallSection -Name $SectionName).Id } catch { - Write-Host -ForegroundColor Red "`nUnable to find NSX-T Distributed Firewall Group named $Name`n" - break + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Host -ForegroundColor Red "`nUnable to find NSX-T Distributed Firewall Section named $SectionName`n" + Write-Error "`n($_.Exception.Message)`n" + break + } } $method = "GET" @@ -1030,8 +1081,14 @@ Function Get-NSXTDistFirewall { $requests = Invoke-WebRequest -Uri $distFirewallURL -Method $method -Headers $global:nsxtProxyConnection.headers } } catch { - Write-Host -ForegroundColor Red "`nFailed to retrieve Distributed Firewall Rules`n" - break + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in retrieving NSX-T Distributed Firewall Rules" + Write-Error "`n($_.Exception.Message)`n" + break + } } if($requests.StatusCode -eq 200) { @@ -1129,9 +1186,179 @@ Function Get-NSXTDistFirewall { $results+=$tmp } $results - } else { - Write-Error "Error in retrieving NSX-T Distributed Firewall Rules" - Write-Error "Return code: " $requests.StatusCode + } + } +} + +Function New-NSXTDistFirewall { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 01/03/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Creates a new NSX-T Distribuged Firewall Rule + .DESCRIPTION + This cmdlet creates a new NSX-T Distribuged Firewall Rule + .EXAMPLE + New-NSXTDistFirewall -Name "App1 to Web1" -Section "App Section 1" ` + -SourceGroup "App Server 1" ` + -DestinationGroup "Web Server 1" ` + -Service HTTPS -Logged $true ` + -SequenceNumber 10 ` + -Action ALLOW +#> + Param ( + [Parameter(Mandatory=$True)]$Name, + [Parameter(Mandatory=$True)]$Section, + [Parameter(Mandatory=$True)]$SequenceNumber, + [Parameter(Mandatory=$True)]$SourceGroup, + [Parameter(Mandatory=$True)]$DestinationGroup, + [Parameter(Mandatory=$True)]$Service, + [Parameter(Mandatory=$True)][ValidateSet("ALLOW","DENY")]$Action, + [Parameter(Mandatory=$false)][Boolean]$Logged=$false, + [Switch]$Troubleshoot + ) + + If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { + + $sectionId = (Get-NSXTDistFirewallSection -Name $Section).Id + + $destinationGroups = @() + foreach ($group in $DestinationGroup) { + if($group -eq "ANY") { + $destinationGroups = @("ANY") + } else { + $tmp = (Get-NSXTGroup -GatewayType CGW -Name $group).Path + $destinationGroups+= $tmp + } + } + + $sourceGroups = @() + foreach ($group in $SourceGroup) { + if($group -eq "ANY") { + $sourceGroups = @("ANY") + } else { + $tmp = (Get-NSXTGroup -GatewayType CGW -Name $group).Path + $sourceGroups+= $tmp + } + } + + $services = @() + foreach ($serviceName in $Service) { + if($serviceName -eq "ANY") { + $services = @("ANY") + } else { + $tmp = "/infra/services/$serviceName" + $services+=$tmp + } + } + + $payload = @{ + display_name = $Name; + sequence_number = $SequenceNumber; + destination_groups = $destinationGroups; + source_groups = $sourceGroups; + logged = $Logged; + scope = @("ANY"); + services = $services; + action = $Action; + } + + $body = $payload | ConvertTo-Json -depth 5 + + $method = "PUT" + $generatedId = (New-Guid).Guid + $newDistFirewallURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/cgw/communication-maps/$sectionId/communication-entries/$generatedId" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$newDistFirewallURL`n" + Write-Host -ForegroundColor cyan "[DEBUG]`n$body`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $newDistFirewallURL -Body $body -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $newDistFirewallURL -Body $body -Method $method -Headers $global:nsxtProxyConnection.headers + } + } catch { + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in creating new NSX-T Distribugted Firewall Rule" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + Write-Host "Succesfully created new NSX-T Distributed Firewall Rule $Name" + ($requests.Content | ConvertFrom-Json) | select display_name, id + } + } +} + +Function Remove-NSXTDistFirewall { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 01/03/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Removes an NSX-T Distribugted Firewall Rule + .DESCRIPTION + This cmdlet removes an NSX-T Distribugted Firewall Rule + .EXAMPLE + Remove-NSXTFirewall -Id TEST -Troubleshoot +#> + Param ( + [Parameter(Mandatory=$True)]$Id, + [Parameter(Mandatory=$True)]$Section, + [Switch]$Troubleshoot + ) + + If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { + $sectionId = (Get-NSXTDistFirewallSection -Name $Section).Id + $dfwId = (Get-NSXTDistFirewall -SectionName $Section).Id + + $method = "DELETE" + $deleteDistFirewallURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/cgw/communication-maps/$sectionId/communication-entries/$dfwId" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$deleteDistFirewallURL`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $deleteDistFirewallURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $deleteDistFirewallURL -Method $method -Headers $global:nsxtProxyConnection.headers + } + } catch { + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in creating new NSX-T Firewall Rule" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + Write-Host "Succesfully removed NSX-T Distribugted Firewall Rule" } } } \ No newline at end of file From a2c896b81b1cd7728b3009b8894be39312893ea7 Mon Sep 17 00:00:00 2001 From: William Lam Date: Fri, 4 Jan 2019 06:52:09 -0800 Subject: [PATCH 28/43] Fixing typo + Remove-NSXTDistFirewall function --- Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 index ef83777..f15379f 100644 --- a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 +++ b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 @@ -1292,7 +1292,7 @@ Function New-NSXTDistFirewall { Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" break } else { - Write-Error "Error in creating new NSX-T Distribugted Firewall Rule" + Write-Error "Error in creating new NSX-T Distributed Firewall Rule" Write-Error "`n($_.Exception.Message)`n" break } @@ -1331,7 +1331,7 @@ Function Remove-NSXTDistFirewall { If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { $sectionId = (Get-NSXTDistFirewallSection -Name $Section).Id - $dfwId = (Get-NSXTDistFirewall -SectionName $Section).Id + $dfwId = (Get-NSXTDistFirewall -SectionName $Section | where { $_.id -eq $Id}).Id $method = "DELETE" $deleteDistFirewallURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/cgw/communication-maps/$sectionId/communication-entries/$dfwId" @@ -1351,14 +1351,14 @@ Function Remove-NSXTDistFirewall { Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" break } else { - Write-Error "Error in creating new NSX-T Firewall Rule" + Write-Error "Error in removing NSX-T Distributed Firewall Rule" Write-Error "`n($_.Exception.Message)`n" break } } if($requests.StatusCode -eq 200) { - Write-Host "Succesfully removed NSX-T Distribugted Firewall Rule" + Write-Host "Succesfully removed NSX-T Distributed Firewall Rule" } } } \ No newline at end of file From 0d75606d99faa3104ea76e0c17de2ce5a31d6791 Mon Sep 17 00:00:00 2001 From: William Lam Date: Fri, 4 Jan 2019 06:54:17 -0800 Subject: [PATCH 29/43] Updating psd1 --- Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psd1 | 2 +- Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psd1 b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psd1 index 9eca367..ef45018 100644 --- a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psd1 +++ b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psd1 @@ -36,7 +36,7 @@ Description = 'PowerShell Module for Managing NSX-T on VMware Cloud on AWS' PowerShellVersion = '6.0' # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. -FunctionsToExport = 'Connect-NSXTProxy', 'Get-NSXTSegment', 'New-NSXTSegment', 'Remove-NSXTSegment', 'Get-NSXTGroup', 'New-NSXTGroup', 'Remove-NSXTGroup', 'Get-NSXTService', 'New-NSXTService', 'Get-NSXTFirewall', 'New-NSXTFirewall', 'Remove-NSXTFirewall' +FunctionsToExport = 'Connect-NSXTProxy', 'Get-NSXTSegment', 'New-NSXTSegment', 'Remove-NSXTSegment', 'Get-NSXTGroup', 'New-NSXTGroup', 'Remove-NSXTGroup', 'Get-NSXTService', 'New-NSXTService', 'Get-NSXTFirewall', 'New-NSXTFirewall', 'Remove-NSXTFirewall', 'Get-NSXTDistFirewallSection', 'Get-NSXTDistFirewall', 'New-NSXTDistFirewall', 'Remove-NSXTDistFirewall' # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. CmdletsToExport = @() diff --git a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 index f15379f..72bc1e3 100644 --- a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 +++ b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 @@ -1317,9 +1317,9 @@ Function Remove-NSXTDistFirewall { =========================================================================== .SYNOPSIS - Removes an NSX-T Distribugted Firewall Rule + Removes an NSX-T Distributed Firewall Rule .DESCRIPTION - This cmdlet removes an NSX-T Distribugted Firewall Rule + This cmdlet removes an NSX-T Distributed Firewall Rule .EXAMPLE Remove-NSXTFirewall -Id TEST -Troubleshoot #> From 9073d8f3b23fa1763f68d812f5564ed0a4e7fe32 Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Thu, 10 Jan 2019 09:42:14 -0500 Subject: [PATCH 30/43] Create Save-PowerCLI.ps1 Adding function to download specific versions of PowerCLI from an online repository --- Scripts/Save-PowerCLI.ps1 | 57 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 Scripts/Save-PowerCLI.ps1 diff --git a/Scripts/Save-PowerCLI.ps1 b/Scripts/Save-PowerCLI.ps1 new file mode 100644 index 0000000..8aa3230 --- /dev/null +++ b/Scripts/Save-PowerCLI.ps1 @@ -0,0 +1,57 @@ +function Save-PowerCLI { +<# +.SYNOPSIS + Function which can be used to easily download specific versions of PowerCLI from an online gallery +.DESCRIPTION + Downloads a specific version of PowerCLI and all the dependencies at the appropriate version +.NOTES + Author: 1.0 - Dimitar Milov +.PARAMETER RequiredVersion + Specify the PowerCLI version +.PARAMETER Path + Directory path where the modules should be downloaded +.PARAMETER Repository + Repository to access the PowerCLI modules +.EXAMPLE + Save-PowerCLI -RequiredVersion '10.0.0.7895300' -Path .\Downloads\ + Downloads PowerCLI 10.0.0 to the Downloads folder +#> + param( + [Parameter(Mandatory = $true)] + [version]$RequiredVersion, + + [Parameter(Mandatory = $true)] + [ValidateScript( { Test-Path $_} )] + [string] + $Path, + + [Parameter()] + [string]$Repository = 'PSGallery' + ) + $powercliModuleName = 'VMware.PowerCLI' + $desiredPowerCLIModule = Find-Module -Name $powercliModuleName -RequiredVersion $RequiredVersion + if (-not $desiredPowerCLIModule) { + throw "'VMware.PowerCLI' with version $RequiredVersion' was not found." + } + + $depsOrder = 'VMware.VimAutomation.Sdk', 'VMware.VimAutomation.Common', 'VMware.Vim', 'VMware.VimAutomation.Cis.Core', 'VMware.VimAutomation.Core', 'VMware.VimAutomation.Nsxt', 'VMware.VimAutomation.Vmc', 'VMware.VimAutomation.Vds', 'VMware.VimAutomation.Srm', 'VMware.ImageBuilder', 'VMware.VimAutomation.Storage', 'VMware.VimAutomation.StorageUtility', 'VMware.VimAutomation.License', 'VMware.VumAutomation', 'VMware.VimAutomation.HorizonView', 'VMware.DeployAutomation', 'VMware.VimAutomation.vROps', 'VMware.VimAutomation.PCloud' + $orderedDependncies = @() + foreach ($depModuleName in $depsOrder) { + $orderedDependncies += $desiredPowerCLIModule.Dependencies | ? {$_.Name -eq $depModuleName} + } + + # Save PowerCLI Module Version + Find-Module -Name $powercliModuleName -RequiredVersion $RequiredVersion | Save-Module -Path $Path + + # Save dependencies with minimum version + foreach ($dependency in $orderedDependncies) { + Find-Module $dependency.Name -RequiredVersion $dependency.MinimumVersion | Save-Module -Path $Path + } + + # Remove newer dependencies versoin + foreach ($dependency in $orderedDependncies) { + Get-ChildItem -Path (Join-Path $path $dependency.Name) | ` + Where-Object {$_.Name -ne $dependency.MinimumVersion} | ` + Remove-Item -Confirm:$false -Force -Recurse + } +} \ No newline at end of file From e35e17a04dea99a56123908cda4f29444d2aaaf3 Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Thu, 10 Jan 2019 09:44:58 -0500 Subject: [PATCH 31/43] Update Save-PowerCLI.ps1 Updating function with v2 additions: - Dynamic RequiredVersion parameter - Simple parameter to handle the nested version folders - Address the potential of downloading multiple module folders twice --- Scripts/Save-PowerCLI.ps1 | 202 +++++++++++++++++++++++++++----------- 1 file changed, 146 insertions(+), 56 deletions(-) diff --git a/Scripts/Save-PowerCLI.ps1 b/Scripts/Save-PowerCLI.ps1 index 8aa3230..e9127bc 100644 --- a/Scripts/Save-PowerCLI.ps1 +++ b/Scripts/Save-PowerCLI.ps1 @@ -1,57 +1,147 @@ function Save-PowerCLI { -<# -.SYNOPSIS - Function which can be used to easily download specific versions of PowerCLI from an online gallery -.DESCRIPTION - Downloads a specific version of PowerCLI and all the dependencies at the appropriate version -.NOTES - Author: 1.0 - Dimitar Milov -.PARAMETER RequiredVersion - Specify the PowerCLI version -.PARAMETER Path - Directory path where the modules should be downloaded -.PARAMETER Repository - Repository to access the PowerCLI modules -.EXAMPLE - Save-PowerCLI -RequiredVersion '10.0.0.7895300' -Path .\Downloads\ - Downloads PowerCLI 10.0.0 to the Downloads folder -#> - param( - [Parameter(Mandatory = $true)] - [version]$RequiredVersion, - - [Parameter(Mandatory = $true)] - [ValidateScript( { Test-Path $_} )] - [string] - $Path, - - [Parameter()] - [string]$Repository = 'PSGallery' - ) - $powercliModuleName = 'VMware.PowerCLI' - $desiredPowerCLIModule = Find-Module -Name $powercliModuleName -RequiredVersion $RequiredVersion - if (-not $desiredPowerCLIModule) { - throw "'VMware.PowerCLI' with version $RequiredVersion' was not found." - } - - $depsOrder = 'VMware.VimAutomation.Sdk', 'VMware.VimAutomation.Common', 'VMware.Vim', 'VMware.VimAutomation.Cis.Core', 'VMware.VimAutomation.Core', 'VMware.VimAutomation.Nsxt', 'VMware.VimAutomation.Vmc', 'VMware.VimAutomation.Vds', 'VMware.VimAutomation.Srm', 'VMware.ImageBuilder', 'VMware.VimAutomation.Storage', 'VMware.VimAutomation.StorageUtility', 'VMware.VimAutomation.License', 'VMware.VumAutomation', 'VMware.VimAutomation.HorizonView', 'VMware.DeployAutomation', 'VMware.VimAutomation.vROps', 'VMware.VimAutomation.PCloud' - $orderedDependncies = @() - foreach ($depModuleName in $depsOrder) { - $orderedDependncies += $desiredPowerCLIModule.Dependencies | ? {$_.Name -eq $depModuleName} - } - - # Save PowerCLI Module Version - Find-Module -Name $powercliModuleName -RequiredVersion $RequiredVersion | Save-Module -Path $Path - - # Save dependencies with minimum version - foreach ($dependency in $orderedDependncies) { - Find-Module $dependency.Name -RequiredVersion $dependency.MinimumVersion | Save-Module -Path $Path - } - - # Remove newer dependencies versoin - foreach ($dependency in $orderedDependncies) { - Get-ChildItem -Path (Join-Path $path $dependency.Name) | ` - Where-Object {$_.Name -ne $dependency.MinimumVersion} | ` - Remove-Item -Confirm:$false -Force -Recurse - } -} \ No newline at end of file + <# + .SYNOPSIS + Advanced function which can be used to easily download specific versions of PowerCLI from an online gallery + .DESCRIPTION + Downloads a specific version of PowerCLI and all the dependencies at the appropriate version + .NOTES + Author: 1.0 - Dimitar Milov + Author: 2.0 - Kyle Ruddy, @kmruddy + .PARAMETER RequiredVersion + Dynamic parameter used to specify the PowerCLI version + .PARAMETER Path + Directory path where the modules should be downloaded + .PARAMETER Repository + Repository to access the PowerCLI modules + .PARAMETER Simple + Switch used to specify the nested version folders should be removed (therefore adding PowerShell 3/4 compatibility) + .EXAMPLE + Save-PowerCLI -RequiredVersion '10.0.0.7895300' -Path .\Downloads\ + Downloads PowerCLI 10.0.0 to the Downloads folder + .EXAMPLE + Save-PowerCLI -RequiredVersion '6.5.2.6268016' -Path .\Downloads\ -Simple + Downloads PowerCLI 6.5.2 to the Downloads folder and removes the nested version folders + #> + [CmdletBinding(SupportsShouldProcess = $True)] + param( + [Parameter(Mandatory = $true, Position = 1)] + [ValidateScript( { Test-Path $_} )] + $Path, + [Parameter(Mandatory = $false, Position = 2)] + [string]$Repository = 'PSGallery', + [Parameter(Mandatory = $false, Position = 3)] + [Switch]$Simple + ) + DynamicParam + { + # Set the dynamic parameters name + $ParameterName = 'RequiredVersion' + + # Create the dictionary + $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary + + # Create the collection of attributes + $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] + + # Create and set the parameters' attributes + $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute + $ParameterAttribute.ValueFromPipeline = $true + $ParameterAttribute.ValueFromPipelineByPropertyName = $true + $ParameterAttribute.Mandatory = $true + $ParameterAttribute.Position = 0 + + # Add the attributes to the attributes collection + $AttributeCollection.Add($ParameterAttribute) + + # Generate and set the ValidateSet + $pcliVersions = Find-Module -Name 'VMware.PowerCLI' -AllVersions + $arrSet = $pcliVersions | select-Object -ExpandProperty Version + $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($arrSet) + + # Add the ValidateSet to the attributes collection + $AttributeCollection.Add($ValidateSetAttribute) + + # Create and return the dynamic parameter + $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection) + $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter) + return $RuntimeParameterDictionary + } + + begin { + $powercliModuleName = 'VMware.PowerCLI' + $desiredPowerCLIModule = Find-Module -Name $powercliModuleName -RequiredVersion $RequiredVersion -Repository $Repository + + $depsOrder = 'VMware.VimAutomation.Sdk', 'VMware.VimAutomation.Common', 'VMware.Vim', 'VMware.VimAutomation.Cis.Core', 'VMware.VimAutomation.Core', 'VMware.VimAutomation.Nsxt', 'VMware.VimAutomation.Vmc', 'VMware.VimAutomation.Vds', 'VMware.VimAutomation.Srm', 'VMware.ImageBuilder', 'VMware.VimAutomation.Storage', 'VMware.VimAutomation.StorageUtility', 'VMware.VimAutomation.License', 'VMware.VumAutomation', 'VMware.VimAutomation.HorizonView', 'VMware.DeployAutomation', 'VMware.VimAutomation.vROps', 'VMware.VimAutomation.PCloud' + $orderedDependencies = @() + foreach ($depModuleName in $depsOrder) { + $orderedDependencies += $desiredPowerCLIModule.Dependencies | Where-Object {$_.Name -eq $depModuleName} + } + + foreach ($remainingDep in $desiredPowerCLIModule.Dependencies) { + if ($orderedDependencies.Name -notcontains $remainingDep.Name) { + $orderedDependencies += $remainingDep + } + + } + } + + process { + # Save PowerCLI Module Version + $desiredPowerCLIModule | Save-Module -Path $Path + + # Working with the depenent modules + foreach ($dependency in $orderedDependencies) { + if (Get-ChildItem -Path (Join-Path $path $dependency.Name) | Where-Object {$_.Name -ne $dependency.MinimumVersion}) { + # Save dependencies with minimum version + Find-Module $dependency.Name -RequiredVersion $dependency.MinimumVersion | Save-Module -Path $Path + + # Remove newer dependencies version + Get-ChildItem -Path (Join-Path $path $dependency.Name) | Where-Object {$_.Name -ne $dependency.MinimumVersion} | Remove-Item -Confirm:$false -Force -Recurse + } + } + } + + end { + if ($Simple) { + + function FolderCleanup { + param( + [Parameter(Mandatory = $true, Position = 0)] + [ValidateScript( { Test-Path $_} )] + $ParentFolder, + [Parameter(Mandatory = $true, Position = 1)] + [String]$ModuleName, + [Parameter(Mandatory = $true, Position = 2)] + $Version + ) + + + $topFolder = Get-Item -Path (Join-Path $ParentFolder $ModuleName) + $versionFolder = $topFolder | Get-ChildItem -Directory | Where-Object {$_.Name -eq $Version} + $versionFolder | Get-ChildItem | Copy-Item -Destination $topFolder + + # Checking for any nested folders within the PowerCLI module version folder + if ($versionFolder| Get-ChildItem -Directory) { + + # Obtaining and storing the child items to a variable, then copying the items to the parent folder's nested folder + $nestFolder = $versionFolder| Get-ChildItem -Directory + foreach ($nestDir in $nestFolder) { + $nestDir | Get-ChildItem | Copy-Item -Destination (Join-Path $topFolder $nestDir.Name) + } + + } + + # Removing any of the former, no longer needed, directory structure + $versionFolder| Remove-Item -Recurse -Force + } + + FolderCleanup -ParentFolder $Path -ModuleName $desiredPowerCLIModule.Name -Version $desiredPowerCLIModule.Version + foreach ($cleanUp in $orderedDependencies) { + + FolderCleanup -ParentFolder $Path -ModuleName $cleanUp.Name -Version $cleanUp.MinimumVersion + } + + } + + } + } \ No newline at end of file From 24556bbe195a7fec85b124b3387d5cd67fbbaf9a Mon Sep 17 00:00:00 2001 From: William Lam Date: Thu, 10 Jan 2019 15:48:43 -0800 Subject: [PATCH 32/43] Fixed CSP Auth due to API change + Refresh Token expiry info --- Modules/VMware.CSP/VMware.CSP.psm1 | 44 ++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/Modules/VMware.CSP/VMware.CSP.psm1 b/Modules/VMware.CSP/VMware.CSP.psm1 index b4b4515..0562950 100644 --- a/Modules/VMware.CSP/VMware.CSP.psm1 +++ b/Modules/VMware.CSP/VMware.CSP.psm1 @@ -21,7 +21,8 @@ [Parameter(Mandatory=$true)][String]$RefreshToken ) - $results = Invoke-WebRequest -Uri "https://console.cloud.vmware.com/csp/gateway/am/api/auth/api-tokens/authorize?refresh_token=$RefreshToken" -Method POST -ContentType "application/json" -UseBasicParsing -Headers @{"csp-auth-token"="$RefreshToken"} + $body = "refresh_token=$RefreshToken" + $results = Invoke-WebRequest -Uri "https://console.cloud.vmware.com/csp/gateway/am/api/auth/api-tokens/authorize" -Method POST -ContentType "application/x-www-form-urlencoded" -UseBasicParsing -Body $body if($results.StatusCode -ne 200) { Write-Host -ForegroundColor Red "Failed to retrieve Access Token, please ensure your VMC Refresh Token is valid and try again" break @@ -51,4 +52,43 @@ Function Get-CSPServices { $results = Invoke-WebRequest -Uri "https://console.cloud.vmware.com/csp/gateway/slc/api/definitions?expand=1" -Method GET -ContentType "application/json" -UseBasicParsing -Headers @{"csp-auth-token"="$env:cspAuthToken"} ((($results.Content) | ConvertFrom-Json).results | where {$_.visible -eq $true}).displayName } -} \ No newline at end of file +} + +Function Get-CSPRefreshTokenExpiry { + <# + .NOTES + =========================================================================== + Created by: William Lam + Date: 01/10/2019 + Organization: VMware + Blog: https://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .DESCRIPTION + Retrieve the expiry for a given CSP Refresh Token + .PARAMETER RefreshToken + Retrieve the expiry for a given CSP Refresh Token + .EXAMPLE + Get-CSPRefreshTokenExpiry -RefreshToken $RefreshToken + #> + Param ( + [Parameter(Mandatory=$true)][String]$RefreshToken + ) + + $body = @{"tokenValue"="$RefreshToken"} + $json = $body | ConvertTo-Json + $results = Invoke-WebRequest -Uri "https://console.cloud.vmware.com/csp/gateway/am/api/auth/api-tokens/details" -Method POST -ContentType "application/json" -UseBasicParsing -Body $json + $tokenDetails = (($results.Content) | ConvertFrom-Json) + + $createDate = (Get-Date -Date "01/01/1970").AddMilliseconds($tokenDetails.createdAt).ToLocalTime() + $usedDate = (Get-Date -Date "01/01/1970").AddMilliseconds($tokenDetails.lastUsedAt).ToLocalTime() + $expiryDate = (Get-Date -Date "01/01/1970").AddMilliseconds($tokenDetails.expiresAt).ToLocalTime() + + $tmp = [pscustomobject] @{ + LastUsedDate = $usedDate; + CreatedDate = $createDate; + ExpiryDate = $expiryDate; + } + $tmp | Format-List +} From 59ab2785e3b2d466672d48f7ae41c53df18d4886 Mon Sep 17 00:00:00 2001 From: William Lam Date: Sat, 12 Jan 2019 15:56:50 -0800 Subject: [PATCH 33/43] Added Set-VMCSDDC function to rename SDDC --- Modules/VMware.VMC/VMware.VMC.psm1 | 117 +++++++++++++++++++---------- 1 file changed, 77 insertions(+), 40 deletions(-) diff --git a/Modules/VMware.VMC/VMware.VMC.psm1 b/Modules/VMware.VMC/VMware.VMC.psm1 index 6605a14..b6c8541 100644 --- a/Modules/VMware.VMC/VMware.VMC.psm1 +++ b/Modules/VMware.VMC/VMware.VMC.psm1 @@ -918,23 +918,23 @@ Function Get-VMCPublicIP { .EXAMPLE Get-VMCPublicIP -OrgName $OrgName -SDDCName $SDDCName #> - Param ( - [Parameter(Mandatory=$True)]$OrgName, - [Parameter(Mandatory=$True)]$SDDCName - ) + Param ( + [Parameter(Mandatory=$True)]$OrgName, + [Parameter(Mandatory=$True)]$SDDCName + ) - If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { - $orgId = (Get-VMCOrg -Name $OrgName).Id - $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id - $publicIPService = Get-VmcService "com.vmware.vmc.orgs.sddcs.publicips" - $publicIPs = $publicIPService.list($orgId,$sddcId) + $publicIPService = Get-VmcService "com.vmware.vmc.orgs.sddcs.publicips" + $publicIPs = $publicIPService.list($orgId,$sddcId) - $publicIPs | select public_ip, name, allocation_id - } + $publicIPs | select public_ip, name, allocation_id } +} - Function New-VMCPublicIP { +Function New-VMCPublicIP { <# .NOTES =========================================================================== @@ -952,28 +952,28 @@ Function Get-VMCPublicIP { .EXAMPLE New-VMCPublicIP -OrgName $OrgName -SDDCName $SDDCName -Description "Test for Randy" #> - Param ( - [Parameter(Mandatory=$True)]$OrgName, - [Parameter(Mandatory=$True)]$SDDCName, - [Parameter(Mandatory=$False)]$Description - ) + Param ( + [Parameter(Mandatory=$True)]$OrgName, + [Parameter(Mandatory=$True)]$SDDCName, + [Parameter(Mandatory=$False)]$Description + ) - If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { - $orgId = (Get-VMCOrg -Name $OrgName).Id - $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id - $publicIPService = Get-VmcService "com.vmware.vmc.orgs.sddcs.publicips" + $publicIPService = Get-VmcService "com.vmware.vmc.orgs.sddcs.publicips" - $publicIPSpec = $publicIPService.Help.create.spec.Create() - $publicIPSpec.count = 1 - $publicIPSpec.names = @($Description) + $publicIPSpec = $publicIPService.Help.create.spec.Create() + $publicIPSpec.count = 1 + $publicIPSpec.names = @($Description) - Write-Host "Requesting a new public IP Address for your SDDC ..." - $results = $publicIPService.create($orgId,$sddcId,$publicIPSpec) - } + Write-Host "Requesting a new public IP Address for your SDDC ..." + $results = $publicIPService.create($orgId,$sddcId,$publicIPSpec) } +} - Function Remove-VMCPublicIP { +Function Remove-VMCPublicIP { <# .NOTES =========================================================================== @@ -991,21 +991,58 @@ Function Get-VMCPublicIP { .EXAMPLE Remove-VMCPublicIP -OrgName $OrgName -SDDCName $SDDCName -AllocationId "eipalloc-0567acf34e436c01f" #> - Param ( - [Parameter(Mandatory=$True)]$OrgName, - [Parameter(Mandatory=$True)]$SDDCName, - [Parameter(Mandatory=$True)]$AllocationId - ) + Param ( + [Parameter(Mandatory=$True)]$OrgName, + [Parameter(Mandatory=$True)]$SDDCName, + [Parameter(Mandatory=$True)]$AllocationId + ) - If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { - $orgId = (Get-VMCOrg -Name $OrgName).Id - $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id - $publicIPService = Get-VmcService "com.vmware.vmc.orgs.sddcs.publicips" + $publicIPService = Get-VmcService "com.vmware.vmc.orgs.sddcs.publicips" - Write-Host "Deleting public IP Address with ID $AllocationId ..." - $results = $publicIPService.delete($orgId,$sddcId,$AllocationId) + Write-Host "Deleting public IP Address with ID $AllocationId ..." + $results = $publicIPService.delete($orgId,$sddcId,$AllocationId) + } +} + +Function Set-VMCSDDC { + <# + .NOTES + =========================================================================== + Created by: William Lam + Date: 01/12/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Rename an SDDC + .DESCRIPTION + This cmdlet renames an SDDC + .EXAMPLE + Set-VMCSDDC -SDDC $SDDCName -OrgName $OrgName -Name $NewSDDCName + #> + Param ( + [Parameter(Mandatory=$True)]$SDDCName, + [Parameter(Mandatory=$True)]$OrgName, + [Parameter(Mandatory=$True)]$Name + ) + + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + $sddc = Get-VMCSDDC -Org $OrgName -Name $SDDCName + if($sddc) { + $sddcService = Get-VmcService com.vmware.vmc.orgs.sddcs + $renameSpec = $sddcService.help.patch.sddc_patch_request.Create() + $renameSpec.name = $Name + + Write-Host "`nRenaming SDDC `'$SDDCName`' to `'$Name`' ...`n" + $results = $sddcService.patch($sddc.org_id,$sddc.id,$renameSpec) } } +} -Export-ModuleMember -Function 'Get-VMCCommand', 'Connect-VMCVIServer', 'Get-VMCOrg', 'Get-VMCSDDC', 'Get-VMCTask', 'Get-VMCSDDCDefaultCredential', 'Get-VMCSDDCPublicIP', 'Get-VMCVMHost', 'Get-VMCSDDCVersion', 'Get-VMCFirewallRule', 'Export-VMCFirewallRule', 'Import-VMCFirewallRule', 'Remove-VMCFirewallRule', 'Get-VMCLogicalNetwork', 'Remove-VMCLogicalNetwork', 'New-VMCLogicalNetwork', 'Get-VMCSDDCSummary', 'Get-VMCPublicIP', 'New-VMCPublicIP', 'Remove-VMCPublicIP' +Export-ModuleMember -Function 'Get-VMCCommand', 'Connect-VMCVIServer', 'Get-VMCOrg', 'Get-VMCSDDC', 'Get-VMCTask', 'Get-VMCSDDCDefaultCredential', 'Get-VMCSDDCPublicIP', 'Get-VMCVMHost', 'Get-VMCSDDCVersion', 'Get-VMCFirewallRule', 'Export-VMCFirewallRule', 'Import-VMCFirewallRule', 'Remove-VMCFirewallRule', 'Get-VMCLogicalNetwork', 'Remove-VMCLogicalNetwork', 'New-VMCLogicalNetwork', 'Get-VMCSDDCSummary', 'Get-VMCPublicIP', 'New-VMCPublicIP', 'Remove-VMCPublicIP', 'Set-VMCSDDC' From ff3d297e697e943611b7fe4845c47f810b5dbcee Mon Sep 17 00:00:00 2001 From: William Lam Date: Thu, 17 Jan 2019 08:07:15 -0800 Subject: [PATCH 34/43] Fixing typo for creating NSX-T GW Firewall --- Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 index 72bc1e3..5466e41 100644 --- a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 +++ b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 @@ -476,7 +476,7 @@ Function New-NSXTFirewall { $services = @() foreach ($serviceName in $Service) { - if($group -eq "ANY") { + if($serviceName -eq "ANY") { $services = @("ANY") } else { $tmp = "/infra/services/$serviceName" From 216ee7386fecda5cfa1589c599739cdf7f75a7ba Mon Sep 17 00:00:00 2001 From: William Lam Date: Wed, 23 Jan 2019 05:25:14 -0800 Subject: [PATCH 35/43] Module for managing vCenter CEIP Settings --- Modules/vCenterCEIP/vCenterCEIP.psm1 | 74 ++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100755 Modules/vCenterCEIP/vCenterCEIP.psm1 diff --git a/Modules/vCenterCEIP/vCenterCEIP.psm1 b/Modules/vCenterCEIP/vCenterCEIP.psm1 new file mode 100755 index 0000000..3d5e903 --- /dev/null +++ b/Modules/vCenterCEIP/vCenterCEIP.psm1 @@ -0,0 +1,74 @@ +Function Get-VCenterCEIP { + <# + .NOTES + =========================================================================== + Created by: William Lam + Date: 01/23/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Retrieves the the Customer Experience Improvement Program (CEIP) setting for vCenter Server + .DESCRIPTION + This cmdlet retrieves the the CEIP setting for vCenter Server + .EXAMPLE + Get-VCenterCEIP + #> + If (-Not $global:DefaultVIServer.IsConnected) { Write-error "No valid VC Connection found, please use the Connect-VIServer to connect"; break } Else { + $ceipSettings = (Get-AdvancedSetting -Entity $global:DefaultVIServer -Name VirtualCenter.DataCollector.ConsentData).Value.toString() | ConvertFrom-Json + $ceipEnabled = $ceipSettings.consentConfigurations[0].consentAccepted + + $tmp = [pscustomobject] @{ + VCENTER = $global:DefaultVIServer.Name; + CEIP = $ceipEnabled; + } + $tmp + } +} +Function Set-VCenterCEIP { + <# + .NOTES + =========================================================================== + Created by: William Lam + Date: 01/23/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Enables or Disables the Customer Experience Improvement Program (CEIP) setting for vCenter Server + .DESCRIPTION + This cmdlet enables or disables the CEIP setting for vCenter Server + .EXAMPLE + Set-VCenterCEIP -Enabled + .EXAMPLE + Set-VCenterCEIP -Disabled + #> + Param ( + [Switch]$Enabled, + [Switch]$Disabled + ) + If (-Not $global:DefaultVIServer.IsConnected) { Write-error "No valid VC Connection found, please use the Connect-VIServer to connect"; break } Else { + $ceipSettings = (Get-AdvancedSetting -Entity $global:DefaultVIServer -Name VirtualCenter.DataCollector.ConsentData).Value.toString() | ConvertFrom-Json + If($Enabled) { + $originalVersion = $ceipSettings.version + $ceipSettings.version = [int]$originalVersion + 1 + $ceipSettings.consentConfigurations[0].consentAccepted = $True + $ceipSettings.consentConfigurations[1].consentAccepted = $True + $updatedceipSettings = $ceipSettings | ConvertTo-Json + Write-Host "Enabling Customer Experience Improvement Program (CEIP) ..." + Get-AdvancedSetting -Entity $global:DefaultVIServer -Name VirtualCenter.DataCollector.ConsentData | Set-AdvancedSetting -Value $updatedceipSettings -Confirm:$false + } else { + $originalVersion = $ceipSettings.version + $ceipSettings.version = [int]$originalVersion + 1 + $ceipSettings.consentConfigurations[0].consentAccepted = $False + $ceipSettings.consentConfigurations[1].consentAccepted = $False + $updatedceipSettings = $ceipSettings | ConvertTo-Json + Write-Host "Disablng Customer Experience Improvement Program (CEIP) ..." + Get-AdvancedSetting -Entity $global:DefaultVIServer -Name VirtualCenter.DataCollector.ConsentData | Set-AdvancedSetting -Value $updatedceipSettings -Confirm:$false + } + } +} From 6cc6634628e5e5c53c7e0c36eea46d410d584910 Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Fri, 1 Feb 2019 14:19:32 -0500 Subject: [PATCH 36/43] Create Set-NetworkAdapterOpaqueNetwork.ps1 Code sample provided as part of KB 65149: https://kb.vmware.com/s/article/65149 --- Scripts/Set-NetworkAdapterOpaqueNetwork.ps1 | 50 +++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 Scripts/Set-NetworkAdapterOpaqueNetwork.ps1 diff --git a/Scripts/Set-NetworkAdapterOpaqueNetwork.ps1 b/Scripts/Set-NetworkAdapterOpaqueNetwork.ps1 new file mode 100644 index 0000000..1310734 --- /dev/null +++ b/Scripts/Set-NetworkAdapterOpaqueNetwork.ps1 @@ -0,0 +1,50 @@ +function Set-NetworkAdapterOpaqueNetwork { +param( + [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 1)] + [VMware.VimAutomation.Types.NetworkAdapter] + $NetworkAdapter, + + [Parameter(Mandatory = $true, Position = 2)] + [string] + $OpaqueNetworkName, + + [Parameter()] + [switch] + $Connected, + + [Parameter()] + [switch] + $StartConnected +) +process { + $opaqueNetwork = Get-View -ViewType OpaqueNetwork | ? {$_.Name -eq $OpaqueNetworkName} + if (-not $opaqueNetwork) { + throw "'$OpaqueNetworkName' network not found." + } + + $opaqueNetworkBacking = New-Object VMware.Vim.VirtualEthernetCardOpaqueNetworkBackingInfo + $opaqueNetworkBacking.OpaqueNetworkId = $opaqueNetwork.Summary.OpaqueNetworkId + $opaqueNetworkBacking.OpaqueNetworkType = $opaqueNetwork.Summary.OpaqueNetworkType + + $device = $NetworkAdapter.ExtensionData + $device.Backing = $opaqueNetworkBacking + + if ($StartConnected) { + $device.Connectable.StartConnected = $true + } + + if ($Connected) { + $device.Connectable.Connected = $true + } + + $spec = New-Object VMware.Vim.VirtualDeviceConfigSpec + $spec.Operation = [VMware.Vim.VirtualDeviceConfigSpecOperation]::edit + $spec.Device = $device + $configSpec = New-Object VMware.Vim.VirtualMachineConfigSpec + $configSpec.DeviceChange = @($spec) + $NetworkAdapter.Parent.ExtensionData.ReconfigVM($configSpec) + + # Output + Get-NetworkAdapter -Id $NetworkAdapter.Id + } +} From 407be173e404bf388e93698a8695206bc7b8e06c Mon Sep 17 00:00:00 2001 From: William Lam Date: Sat, 2 Feb 2019 07:34:16 -0800 Subject: [PATCH 37/43] Adding NSX-T Routing Table --- Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 | 79 ++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 index 5466e41..bc2cebd 100644 --- a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 +++ b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 @@ -1361,4 +1361,83 @@ Function Remove-NSXTDistFirewall { Write-Host "Succesfully removed NSX-T Distributed Firewall Rule" } } +} + +Function Get-NSXTRouteTable { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 02/02/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Retrieves NSX-T Routing Table + .DESCRIPTION + This cmdlet retrieves NSX-T Routing Table. By default, it shows all routes but you can filter by BGP, CONNECTED or STATIC routes + .EXAMPLE + Get-NSXTRouteTable + .EXAMPLE + Get-NSXTRouteTable -RouteSource BGP + .EXAMPLE + Get-NSXTRouteTable -RouteSource CONNECTED + .EXAMPLE + Get-NSXTRouteTable -RouteSource STATIC + .EXAMPLE + Get-NSXTRouteTable -RouteSource BGP -Troubleshoot +#> + Param ( + [Parameter(Mandatory=$False)][ValidateSet("BGP","CONNECTED","STATIC")]$RouteSource, + [Switch]$Troubleshoot + ) + + If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { + $method = "GET" + $routeTableURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/tier-0s/vmc/routing-table?enforcement_point_path=/infra/deployment-zones/default/enforcement-points/vmc-enforcementpoint" + + if($RouteSource) { + $routeTableURL = $routeTableURL + "&route_source=$RouteSource" + } + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$routeTableURL`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $routeTableURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $routeTableURL -Method $method -Headers $global:nsxtProxyConnection.headers + } + } catch { + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in retrieving NSX-T Routing Table" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + Write-Host "Succesfully retrieved NSX-T Routing Table`n" + $routeTables = ($requests.Content | ConvertFrom-Json).results + + foreach ($routeTable in $routeTables) { + Write-Host "EdgeNode: $($routeTable.edge_node)" + Write-Host "Entries: $($routeTable.count)" + + $routeEntries = $routeTable.route_entries + $routeEntryResults = @() + foreach ($routeEntry in $routeEntries) { + $routeEntryResults += $routeEntry + } + $routeEntryResults | select network,next_hop,admin_distance,route_type | ft + } + } + } } \ No newline at end of file From 2212477dff9ca34a0e16d34dcd792ad6978993d8 Mon Sep 17 00:00:00 2001 From: William Lam Date: Fri, 8 Feb 2019 05:28:10 -0800 Subject: [PATCH 38/43] Added NSX-T Overview Info --- Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psd1 | 2 +- Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 | 55 ++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psd1 b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psd1 index ef45018..b74bad7 100644 --- a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psd1 +++ b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psd1 @@ -36,7 +36,7 @@ Description = 'PowerShell Module for Managing NSX-T on VMware Cloud on AWS' PowerShellVersion = '6.0' # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. -FunctionsToExport = 'Connect-NSXTProxy', 'Get-NSXTSegment', 'New-NSXTSegment', 'Remove-NSXTSegment', 'Get-NSXTGroup', 'New-NSXTGroup', 'Remove-NSXTGroup', 'Get-NSXTService', 'New-NSXTService', 'Get-NSXTFirewall', 'New-NSXTFirewall', 'Remove-NSXTFirewall', 'Get-NSXTDistFirewallSection', 'Get-NSXTDistFirewall', 'New-NSXTDistFirewall', 'Remove-NSXTDistFirewall' +FunctionsToExport = 'Connect-NSXTProxy', 'Get-NSXTSegment', 'New-NSXTSegment', 'Remove-NSXTSegment', 'Get-NSXTGroup', 'New-NSXTGroup', 'Remove-NSXTGroup', 'Get-NSXTService', 'New-NSXTService', 'Get-NSXTFirewall', 'New-NSXTFirewall', 'Remove-NSXTFirewall', 'Get-NSXTDistFirewallSection', 'Get-NSXTDistFirewall', 'New-NSXTDistFirewall', 'Remove-NSXTDistFirewall', 'Get-NSXTRouteTable', 'Get-NSXTOverviewInfo' # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. CmdletsToExport = @() diff --git a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 index bc2cebd..d120086 100644 --- a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 +++ b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 @@ -1440,4 +1440,59 @@ Function Get-NSXTRouteTable { } } } +} + +Function Get-NSXTOverviewInfo { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 02/02/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Retrieves NSX-T Overview including the VPN internet IP Address and SDDC Infra/Mgmt Subnets, etc. + .DESCRIPTION + This cmdlet retrieves NSX-T Overview details including the VPN internet IP Address and SDDC Infra/Mgmt Subnets, etc. + .EXAMPLE + Get-NSXTOverviewInfo +#> +Param ( + [Parameter(Mandatory=$False)][ValidateSet("BGP","CONNECTED","STATIC")]$RouteSource, + [Switch]$Troubleshoot +) + +If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { + $method = "GET" + $overviewURL = $global:nsxtProxyConnection.Server + "/cloud-service/api/v1/infra/sddc-user-config" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$overviewURL`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $overviewURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $overviewURL -Method $method -Headers $global:nsxtProxyConnection.headers + } + } catch { + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in retrieving NSX-T Overview Information" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + Write-Host "Succesfully retrieved NSX-T Overview Information" + ($requests.Content | ConvertFrom-Json) + } +} } \ No newline at end of file From 0e318d3e07debd3a6275ad3a0a6ca9fabaa05b3d Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Wed, 13 Feb 2019 15:57:51 -0800 Subject: [PATCH 39/43] Create Move-DatastoreCluster.ps1 Moves a datastore cluster to a new location --- Scripts/Move-DatastoreCluster.ps1 | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 Scripts/Move-DatastoreCluster.ps1 diff --git a/Scripts/Move-DatastoreCluster.ps1 b/Scripts/Move-DatastoreCluster.ps1 new file mode 100644 index 0000000..a01d3bb --- /dev/null +++ b/Scripts/Move-DatastoreCluster.ps1 @@ -0,0 +1,34 @@ +function Move-DatastoreCluster { +<# +.SYNOPSIS + Moves a datastore cluster to a new location +.DESCRIPTION + Will move a datastore cluster to a new location +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER DatastoreCluster + Specifies the datastore cluster you want to move. +.PARAMETER Destination + Specifies a destination where you want to place the datastore cluster +.EXAMPLE + Move-DatastoreCluster -DatastoreCluster $DSCluster -Destination $DSClusterFolder + Moves the $DSCluster datastore cluster to the specified $DSClusterFolder folder. +#> +[CmdletBinding(SupportsShouldProcess = $True)] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.DatastoreCluster]$DatastoreCluster, + [Parameter(Mandatory=$false,Position=1,ValueFromPipelineByPropertyName=$true)] + [VMware.VimAutomation.ViCore.Types.V1.Inventory.Folder]$Destination + ) + + if ($Global:DefaultVIServer.IsConnected -eq $false) { + Write-Warning -Message "No vCenter Server connection found." + break + } + + If ($Pscmdlet.ShouldProcess($DatastoreCluster,"Move Datastore Cluster")) { + $Destination.ExtensionData.MoveIntoFolder($DatastoreCluster.ExtensionData.MoRef) + } + +} \ No newline at end of file From ecc12a18847ae884c7ef41018d2bb3bfeeb7b9e6 Mon Sep 17 00:00:00 2001 From: Matt Frey Date: Wed, 13 Mar 2019 14:43:33 -0500 Subject: [PATCH 40/43] Address Issue #269 Both flash parameters for `New-HVPool` were limited to the validate set of `LINKED_CLONE`. This updates them to be valid for all desktop types, since it is applicable to all desktop types. See https://vdc-download.vmware.com/vmwb-repository/dcr-public/3721109b-48a5-4ffb-a0ad-6d6a44f2f288/ff45dfca-1050-4265-93ef-4e7d702322e4/vdi.resources.Desktop.AdobeFlashSettings.html for details. --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index c150c5f..14972ca 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -3667,13 +3667,19 @@ function New-HVPool { # flashSettings #desktopSpec.desktopSettings.flashSettings.quality [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'MANUAL')] [ValidateSet('NO_CONTROL', 'LOW', 'MEDIUM', 'HIGH')] - [string]$quality = 'NO_CONTROL', + [string]$Quality = 'NO_CONTROL', #desktopSpec.desktopSettings.flashSettings.throttling [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'MANUAL')] [ValidateSet('DISABLED', 'CONSERVATIVE', 'MODERATE', 'AGGRESSIVE')] - [string]$throttling = 'DISABLED', + [string]$Throttling = 'DISABLED', #mirageConfigurationOverrides #desktopSpec.desktopSettings.mirageConfigurationOverrides.overrideGlobalSetting @@ -11580,4 +11586,4 @@ Export-ModuleMember -Function Get-HVResourceStructure, Get-HVLocalSession, Get-H # Event Database related Export-ModuleMember -Function Get-HVEventDatabase, Set-HVEventDatabase, Clear-HVEventDatabase, Get-HVEvent, Connect-HVEvent, Disconnect-HVEvent # Misc/other related -Export-ModuleMember -Function Get-HVlicense, Set-HVlicense, Get-HVHealth, Set-HVInstantCloneMaintenance \ No newline at end of file +Export-ModuleMember -Function Get-HVlicense, Set-HVlicense, Get-HVHealth, Set-HVInstantCloneMaintenance From fe603f60d65096cfa443fbee846ad81fbdd12517 Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Tue, 26 Mar 2019 23:55:29 -0400 Subject: [PATCH 41/43] Add SDDC Cluster Functions Added the following functions: Get-VMCSDDCCluster New-VMCSDDCCluster Remove-VMCSDDCCluster --- Modules/VMware.VMC/VMware.VMC.psd1 | Bin 8558 -> 8696 bytes Modules/VMware.VMC/VMware.VMC.psm1 | 203 ++++++++++++++++++++++++++++- 2 files changed, 199 insertions(+), 4 deletions(-) diff --git a/Modules/VMware.VMC/VMware.VMC.psd1 b/Modules/VMware.VMC/VMware.VMC.psd1 index 105fec0612b9384cc68ec1d1240ff768945cef05..020717c99a0e06de49d27ef6235b0a50c69faad1 100755 GIT binary patch delta 111 zcmaFo^uu|B6ceNIW@)Bm;mJOtB9r@sI4qqRau`Y(iWy26QW=UE)ERUb6o8~3kXO#2 h%Mixk%izoq%-{lq&OnHycCx*QtSDBQ&DElxxdDP27(f63 delta 19 acmez2{LX2E6ceM-W@)Bm;msUkAGiTZ8wPy< diff --git a/Modules/VMware.VMC/VMware.VMC.psm1 b/Modules/VMware.VMC/VMware.VMC.psm1 index de3d1ab..d7a824f 100644 --- a/Modules/VMware.VMC/VMware.VMC.psm1 +++ b/Modules/VMware.VMC/VMware.VMC.psm1 @@ -690,7 +690,7 @@ Function Get-VMCLogicalNetwork { Created by: Kyle Ruddy Date: 03/06/2018 Organization: VMware - Blog: https://thatcouldbeaproblem.com + Blog: https://www.kmruddy.com Twitter: @kmruddy =========================================================================== @@ -761,7 +761,7 @@ Function Remove-VMCLogicalNetwork { Created by: Kyle Ruddy Date: 03/06/2018 Organization: VMware - Blog: https://thatcouldbeaproblem.com + Blog: https://www.kmruddy.com Twitter: @kmruddy =========================================================================== @@ -808,7 +808,7 @@ Function New-VMCLogicalNetwork { Created by: Kyle Ruddy Date: 03/06/2018 Organization: VMware - Blog: https://thatcouldbeaproblem.com + Blog: https://www.kmruddy.com Twitter: @kmruddy =========================================================================== @@ -1299,10 +1299,205 @@ Twitter: @LucD22 } } } +Function New-VMCSDDCCluster { + <# + .NOTES + =========================================================================== + Created by: Kyle Ruddy + Date: 03/16/2019 + Organization: VMware + Blog: https://www.kmruddy.com + Twitter: @kmruddy + =========================================================================== + + .SYNOPSIS + Creates a new cluster for the designated SDDC + .DESCRIPTION + Creates a new cluster + .EXAMPLE + New-VMCSDDCCluster -OrgName -SDDCName -HostCount 1 -CPUCoreCount 8 + #> + [cmdletbinding(SupportsShouldProcess = $true,ConfirmImpact='High')] + param( + [Parameter(Mandatory=$true)][String]$OrgName, + [Parameter(Mandatory=$true)][String]$SDDCName, + [Parameter(Mandatory=$true)][Int]$HostCount, + [Parameter(Mandatory=$true)][ValidateSet("8","16","32")]$CPUCoreCount + ) + + if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } + + $orgId = Get-VMCOrg -Name $OrgName | Select-Object -ExpandProperty Id + $sddcId = Get-VMCSDDC -Name $SDDCName -Org $OrgName | Select-Object -ExpandProperty Id + + if(-not $orgId) { + Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" + break + } + if(-not $sddcId) { + Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" + break + } + + $sddcClusterSvc = Get-VmcService -Name com.vmware.vmc.orgs.sddcs.clusters + + $sddcClusterCreateSpec = $sddcClusterSvc.Help.create.cluster_config.Create() + $sddcClusterCreateSpec.host_cpu_cores_count = $CPUCoreCount + $sddcClusterCreateSpec.num_hosts = $HostCount + + $sddcClusterTask = $sddcClusterSvc.Create($org.Id, $sddc.Id, $sddcClusterCreateSpec) + $sddcClusterTask | Select-Object Id,Task_Type,Status,Created | Format-Table +} +Function Get-VMCSDDCCluster { + <# + .NOTES + =========================================================================== + Created by: Kyle Ruddy + Date: 03/16/2019 + Organization: VMware + Blog: https://www.kmruddy.com + Twitter: @kmruddy + =========================================================================== + + .SYNOPSIS + Retreives cluster information for the designated SDDC + .DESCRIPTION + Lists cluster information for an SDDC + .EXAMPLE + Get-VMCSDDCCluster -OrgName -SDDCName -HostCount 1 -CPUCoreCount 8 + #> + [cmdletbinding(SupportsShouldProcess = $true,ConfirmImpact='Low')] + param( + [Parameter(Mandatory=$true)][String]$OrgName, + [Parameter(Mandatory=$true)][String]$SddcName + ) + + if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } + + $orgId = Get-VMCOrg -Name $OrgName | Select-Object -ExpandProperty Id + $sddcId = Get-VMCSDDC -Name $SDDCName -Org $OrgName | Select-Object -ExpandProperty Id + + if(-not $orgId) { + Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" + break + } + if(-not $sddcId) { + Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" + break + } + + $clusterOutput = @() + $sddcClusters = Get-VMCSDDC -Org $OrgName -Name $SDDCName | Select-Object -ExpandProperty resource_config | Select-Object -ExpandProperty clusters + foreach ($c in $sddcClusters) { + $tempCluster = "" | Select-Object Id, Name, State + $tempCluster.Id = $c.cluster_id + $tempCluster.Name = $c.cluster_name + $tempCluster.State = $c.cluster_state + $clusterOutput += $tempCluster + } + return $clusterOutput +} +Function New-VMCSDDCCluster { + <# + .NOTES + =========================================================================== + Created by: Kyle Ruddy + Date: 03/16/2019 + Organization: VMware + Blog: https://www.kmruddy.com + Twitter: @kmruddy + =========================================================================== + + .SYNOPSIS + Creates a new cluster for the designated SDDC + .DESCRIPTION + Creates a new cluster + .EXAMPLE + New-VMCSDDCCluster -OrgName -SDDCName -HostCount 1 -CPUCoreCount 8 + #> + [cmdletbinding(SupportsShouldProcess = $true,ConfirmImpact='High')] + param( + [Parameter(Mandatory=$true)][String]$OrgName, + [Parameter(Mandatory=$true)][String]$SddcName, + [Parameter(Mandatory=$true)][Int]$HostCount, + [Parameter(Mandatory=$false)][ValidateSet("8","16","36","48")]$CPUCoreCount + ) + + if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } + + $orgId = Get-VMCOrg -Name $OrgName | Select-Object -ExpandProperty Id + $sddcId = Get-VMCSDDC -Name $SDDCName -Org $OrgName | Select-Object -ExpandProperty Id + + if(-not $orgId) { + Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" + break + } + if(-not $sddcId) { + Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" + break + } + + $sddcClusterSvc = Get-VmcService -Name com.vmware.vmc.orgs.sddcs.clusters + + $sddcClusterCreateSpec = $sddcClusterSvc.Help.create.cluster_config.Create() + $sddcClusterCreateSpec.host_cpu_cores_count = $CPUCoreCount + $sddcClusterCreateSpec.num_hosts = $HostCount + + $sddcClusterTask = $sddcClusterSvc.Create($org.Id, $sddc.Id, $sddcClusterCreateSpec) + $sddcClusterTask | Select-Object Id,Task_Type,Status,Created | Format-Table +} +Function Remove-VMCSDDCCluster { + <# + .NOTES + =========================================================================== + Created by: Kyle Ruddy + Date: 03/16/2019 + Organization: VMware + Blog: https://www.kmruddy.com + Twitter: @kmruddy + =========================================================================== + + .SYNOPSIS + Removes a specified cluster from the designated SDDC + .DESCRIPTION + Deletes a cluster from an SDDC + .EXAMPLE + Remove-VMCSDDCCluster -OrgName -SDDCName -Cluster + #> + [cmdletbinding(SupportsShouldProcess = $true,ConfirmImpact='High')] + param( + [Parameter(Mandatory=$true)][String]$OrgName, + [Parameter(Mandatory=$true)][String]$SDDCName, + [Parameter(Mandatory=$true)][String]$ClusterName + ) + + if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } + + $orgId = Get-VMCOrg -Name $OrgName | Select-Object -ExpandProperty Id + $sddcId = Get-VMCSDDC -Name $SDDCName -Org $OrgName | Select-Object -ExpandProperty Id + $clusterId = Get-VMCSDDCCluster -SddcName $SDDCName -OrgName $OrgName | Where-Object {$_.Name -eq $ClusterName} | Select-Object -ExpandProperty Id + + if(-not $orgId) { + Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" + break + } + if(-not $sddcId) { + Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" + break + } + if(-not $clusterId) { + Write-Host -ForegroundColor red "Unable to find cluster $ClusterName, please verify input" + break + } + + $sddcClusterTask = $sddcClusterSvc.Delete($orgId, $sddcId, $clusterId) + $sddcClusterTask | Select-Object Id,Task_Type,Status,Created | Format-Table +} Export-ModuleMember -Function 'Get-VMCCommand', 'Connect-VMCVIServer', 'Get-VMCOrg', 'Get-VMCSDDC', 'Get-VMCTask', 'Get-VMCSDDCDefaultCredential', 'Get-VMCSDDCPublicIP', 'Get-VMCVMHost', 'Get-VMCSDDCVersion', 'Get-VMCFirewallRule', 'Export-VMCFirewallRule', 'Import-VMCFirewallRule', 'Remove-VMCFirewallRule', 'Get-VMCLogicalNetwork', 'Remove-VMCLogicalNetwork', 'New-VMCLogicalNetwork', 'Get-VMCSDDCSummary', 'Get-VMCPublicIP', 'New-VMCPublicIP', 'Remove-VMCPublicIP', - 'Get-VMCEdge', 'Get-VMCEdgeNic', 'Get-VMCEdgeStatus', 'Get-VMCEdgeNicStat', 'Get-VMCEdgeUplinkStat' + 'Get-VMCEdge', 'Get-VMCEdgeNic', 'Get-VMCEdgeStatus', 'Get-VMCEdgeNicStat', 'Get-VMCEdgeUplinkStat', + 'Get-VMCSDDCCluster', 'New-VMCSDDCCluster', 'Remove-VMCSDDCCluster' From 45ac4a47fb73b2d850266cbcff8836645ae389a3 Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Wed, 27 Mar 2019 00:00:01 -0400 Subject: [PATCH 42/43] Revert "Add SDDC Cluster Functions" This reverts commit fe603f60d65096cfa443fbee846ad81fbdd12517. --- Modules/VMware.VMC/VMware.VMC.psd1 | Bin 8696 -> 8558 bytes Modules/VMware.VMC/VMware.VMC.psm1 | 203 +---------------------------- 2 files changed, 4 insertions(+), 199 deletions(-) diff --git a/Modules/VMware.VMC/VMware.VMC.psd1 b/Modules/VMware.VMC/VMware.VMC.psd1 index 020717c99a0e06de49d27ef6235b0a50c69faad1..105fec0612b9384cc68ec1d1240ff768945cef05 100755 GIT binary patch delta 19 acmez2{LX2E6ceM-W@)Bm;msUkAGiTZ8wPy< delta 111 zcmaFo^uu|B6ceNIW@)Bm;mJOtB9r@sI4qqRau`Y(iWy26QW=UE)ERUb6o8~3kXO#2 h%Mixk%izoq%-{lq&OnHycCx*QtSDBQ&DElxxdDP27(f63 diff --git a/Modules/VMware.VMC/VMware.VMC.psm1 b/Modules/VMware.VMC/VMware.VMC.psm1 index d7a824f..de3d1ab 100644 --- a/Modules/VMware.VMC/VMware.VMC.psm1 +++ b/Modules/VMware.VMC/VMware.VMC.psm1 @@ -690,7 +690,7 @@ Function Get-VMCLogicalNetwork { Created by: Kyle Ruddy Date: 03/06/2018 Organization: VMware - Blog: https://www.kmruddy.com + Blog: https://thatcouldbeaproblem.com Twitter: @kmruddy =========================================================================== @@ -761,7 +761,7 @@ Function Remove-VMCLogicalNetwork { Created by: Kyle Ruddy Date: 03/06/2018 Organization: VMware - Blog: https://www.kmruddy.com + Blog: https://thatcouldbeaproblem.com Twitter: @kmruddy =========================================================================== @@ -808,7 +808,7 @@ Function New-VMCLogicalNetwork { Created by: Kyle Ruddy Date: 03/06/2018 Organization: VMware - Blog: https://www.kmruddy.com + Blog: https://thatcouldbeaproblem.com Twitter: @kmruddy =========================================================================== @@ -1299,205 +1299,10 @@ Twitter: @LucD22 } } } -Function New-VMCSDDCCluster { - <# - .NOTES - =========================================================================== - Created by: Kyle Ruddy - Date: 03/16/2019 - Organization: VMware - Blog: https://www.kmruddy.com - Twitter: @kmruddy - =========================================================================== - - .SYNOPSIS - Creates a new cluster for the designated SDDC - .DESCRIPTION - Creates a new cluster - .EXAMPLE - New-VMCSDDCCluster -OrgName -SDDCName -HostCount 1 -CPUCoreCount 8 - #> - [cmdletbinding(SupportsShouldProcess = $true,ConfirmImpact='High')] - param( - [Parameter(Mandatory=$true)][String]$OrgName, - [Parameter(Mandatory=$true)][String]$SDDCName, - [Parameter(Mandatory=$true)][Int]$HostCount, - [Parameter(Mandatory=$true)][ValidateSet("8","16","32")]$CPUCoreCount - ) - - if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } - - $orgId = Get-VMCOrg -Name $OrgName | Select-Object -ExpandProperty Id - $sddcId = Get-VMCSDDC -Name $SDDCName -Org $OrgName | Select-Object -ExpandProperty Id - - if(-not $orgId) { - Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" - break - } - if(-not $sddcId) { - Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" - break - } - - $sddcClusterSvc = Get-VmcService -Name com.vmware.vmc.orgs.sddcs.clusters - - $sddcClusterCreateSpec = $sddcClusterSvc.Help.create.cluster_config.Create() - $sddcClusterCreateSpec.host_cpu_cores_count = $CPUCoreCount - $sddcClusterCreateSpec.num_hosts = $HostCount - - $sddcClusterTask = $sddcClusterSvc.Create($org.Id, $sddc.Id, $sddcClusterCreateSpec) - $sddcClusterTask | Select-Object Id,Task_Type,Status,Created | Format-Table -} -Function Get-VMCSDDCCluster { - <# - .NOTES - =========================================================================== - Created by: Kyle Ruddy - Date: 03/16/2019 - Organization: VMware - Blog: https://www.kmruddy.com - Twitter: @kmruddy - =========================================================================== - - .SYNOPSIS - Retreives cluster information for the designated SDDC - .DESCRIPTION - Lists cluster information for an SDDC - .EXAMPLE - Get-VMCSDDCCluster -OrgName -SDDCName -HostCount 1 -CPUCoreCount 8 - #> - [cmdletbinding(SupportsShouldProcess = $true,ConfirmImpact='Low')] - param( - [Parameter(Mandatory=$true)][String]$OrgName, - [Parameter(Mandatory=$true)][String]$SddcName - ) - - if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } - - $orgId = Get-VMCOrg -Name $OrgName | Select-Object -ExpandProperty Id - $sddcId = Get-VMCSDDC -Name $SDDCName -Org $OrgName | Select-Object -ExpandProperty Id - - if(-not $orgId) { - Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" - break - } - if(-not $sddcId) { - Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" - break - } - - $clusterOutput = @() - $sddcClusters = Get-VMCSDDC -Org $OrgName -Name $SDDCName | Select-Object -ExpandProperty resource_config | Select-Object -ExpandProperty clusters - foreach ($c in $sddcClusters) { - $tempCluster = "" | Select-Object Id, Name, State - $tempCluster.Id = $c.cluster_id - $tempCluster.Name = $c.cluster_name - $tempCluster.State = $c.cluster_state - $clusterOutput += $tempCluster - } - return $clusterOutput -} -Function New-VMCSDDCCluster { - <# - .NOTES - =========================================================================== - Created by: Kyle Ruddy - Date: 03/16/2019 - Organization: VMware - Blog: https://www.kmruddy.com - Twitter: @kmruddy - =========================================================================== - - .SYNOPSIS - Creates a new cluster for the designated SDDC - .DESCRIPTION - Creates a new cluster - .EXAMPLE - New-VMCSDDCCluster -OrgName -SDDCName -HostCount 1 -CPUCoreCount 8 - #> - [cmdletbinding(SupportsShouldProcess = $true,ConfirmImpact='High')] - param( - [Parameter(Mandatory=$true)][String]$OrgName, - [Parameter(Mandatory=$true)][String]$SddcName, - [Parameter(Mandatory=$true)][Int]$HostCount, - [Parameter(Mandatory=$false)][ValidateSet("8","16","36","48")]$CPUCoreCount - ) - - if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } - - $orgId = Get-VMCOrg -Name $OrgName | Select-Object -ExpandProperty Id - $sddcId = Get-VMCSDDC -Name $SDDCName -Org $OrgName | Select-Object -ExpandProperty Id - - if(-not $orgId) { - Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" - break - } - if(-not $sddcId) { - Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" - break - } - - $sddcClusterSvc = Get-VmcService -Name com.vmware.vmc.orgs.sddcs.clusters - - $sddcClusterCreateSpec = $sddcClusterSvc.Help.create.cluster_config.Create() - $sddcClusterCreateSpec.host_cpu_cores_count = $CPUCoreCount - $sddcClusterCreateSpec.num_hosts = $HostCount - - $sddcClusterTask = $sddcClusterSvc.Create($org.Id, $sddc.Id, $sddcClusterCreateSpec) - $sddcClusterTask | Select-Object Id,Task_Type,Status,Created | Format-Table -} -Function Remove-VMCSDDCCluster { - <# - .NOTES - =========================================================================== - Created by: Kyle Ruddy - Date: 03/16/2019 - Organization: VMware - Blog: https://www.kmruddy.com - Twitter: @kmruddy - =========================================================================== - - .SYNOPSIS - Removes a specified cluster from the designated SDDC - .DESCRIPTION - Deletes a cluster from an SDDC - .EXAMPLE - Remove-VMCSDDCCluster -OrgName -SDDCName -Cluster - #> - [cmdletbinding(SupportsShouldProcess = $true,ConfirmImpact='High')] - param( - [Parameter(Mandatory=$true)][String]$OrgName, - [Parameter(Mandatory=$true)][String]$SDDCName, - [Parameter(Mandatory=$true)][String]$ClusterName - ) - - if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } - - $orgId = Get-VMCOrg -Name $OrgName | Select-Object -ExpandProperty Id - $sddcId = Get-VMCSDDC -Name $SDDCName -Org $OrgName | Select-Object -ExpandProperty Id - $clusterId = Get-VMCSDDCCluster -SddcName $SDDCName -OrgName $OrgName | Where-Object {$_.Name -eq $ClusterName} | Select-Object -ExpandProperty Id - - if(-not $orgId) { - Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" - break - } - if(-not $sddcId) { - Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" - break - } - if(-not $clusterId) { - Write-Host -ForegroundColor red "Unable to find cluster $ClusterName, please verify input" - break - } - - $sddcClusterTask = $sddcClusterSvc.Delete($orgId, $sddcId, $clusterId) - $sddcClusterTask | Select-Object Id,Task_Type,Status,Created | Format-Table -} Export-ModuleMember -Function 'Get-VMCCommand', 'Connect-VMCVIServer', 'Get-VMCOrg', 'Get-VMCSDDC', 'Get-VMCTask', 'Get-VMCSDDCDefaultCredential', 'Get-VMCSDDCPublicIP', 'Get-VMCVMHost', 'Get-VMCSDDCVersion', 'Get-VMCFirewallRule', 'Export-VMCFirewallRule', 'Import-VMCFirewallRule', 'Remove-VMCFirewallRule', 'Get-VMCLogicalNetwork', 'Remove-VMCLogicalNetwork', 'New-VMCLogicalNetwork', 'Get-VMCSDDCSummary', 'Get-VMCPublicIP', 'New-VMCPublicIP', 'Remove-VMCPublicIP', - 'Get-VMCEdge', 'Get-VMCEdgeNic', 'Get-VMCEdgeStatus', 'Get-VMCEdgeNicStat', 'Get-VMCEdgeUplinkStat', - 'Get-VMCSDDCCluster', 'New-VMCSDDCCluster', 'Remove-VMCSDDCCluster' + 'Get-VMCEdge', 'Get-VMCEdgeNic', 'Get-VMCEdgeStatus', 'Get-VMCEdgeNicStat', 'Get-VMCEdgeUplinkStat' From 528eca815c35e4db8f2f935b723a3a2ba8ebf4b8 Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Wed, 27 Mar 2019 00:12:03 -0400 Subject: [PATCH 43/43] Add SDDC Cluster Functions Add the following SDDC Cluster Functions: Get-VMCSDDCCluster New-VMCSDDCCluster Remove-VMCSDDCCluster --- Modules/VMware.VMC/VMware.VMC.psd1 | Bin 8558 -> 8706 bytes Modules/VMware.VMC/VMware.VMC.psm1 | 204 ++++++++++++++++++++++++++++- 2 files changed, 199 insertions(+), 5 deletions(-) diff --git a/Modules/VMware.VMC/VMware.VMC.psd1 b/Modules/VMware.VMC/VMware.VMC.psd1 index 105fec0612b9384cc68ec1d1240ff768945cef05..397ab8df97385b930488b229cabe25d0817ac0b1 100755 GIT binary patch delta 121 zcmaFo)a0^3iiy#9vouq(@MIrRk;#2R9L~-RISi!?#SA43sSHI7>I^yz3JhF841wwl nen9bZ23>|Q244nehF}I4Aan*oBwds3MPx;>%51I{{mcyj;64~% delta 19 acmZp2dFQl2iiy!^vouq(@Ma;g58MDjlLit1 diff --git a/Modules/VMware.VMC/VMware.VMC.psm1 b/Modules/VMware.VMC/VMware.VMC.psm1 index 33f78a7..f2151c9 100644 --- a/Modules/VMware.VMC/VMware.VMC.psm1 +++ b/Modules/VMware.VMC/VMware.VMC.psm1 @@ -690,7 +690,7 @@ Function Get-VMCLogicalNetwork { Created by: Kyle Ruddy Date: 03/06/2018 Organization: VMware - Blog: https://thatcouldbeaproblem.com + Blog: https://www.kmruddy.com Twitter: @kmruddy =========================================================================== @@ -761,7 +761,7 @@ Function Remove-VMCLogicalNetwork { Created by: Kyle Ruddy Date: 03/06/2018 Organization: VMware - Blog: https://thatcouldbeaproblem.com + Blog: https://www.kmruddy.com Twitter: @kmruddy =========================================================================== @@ -808,7 +808,7 @@ Function New-VMCLogicalNetwork { Created by: Kyle Ruddy Date: 03/06/2018 Organization: VMware - Blog: https://thatcouldbeaproblem.com + Blog: https://www.kmruddy.com Twitter: @kmruddy =========================================================================== @@ -1417,11 +1417,205 @@ Twitter: @LucD22 } } } +Function New-VMCSDDCCluster { + <# + .NOTES + =========================================================================== + Created by: Kyle Ruddy + Date: 03/16/2019 + Organization: VMware + Blog: https://www.kmruddy.com + Twitter: @kmruddy + =========================================================================== + + .SYNOPSIS + Creates a new cluster for the designated SDDC + .DESCRIPTION + Creates a new cluster + .EXAMPLE + New-VMCSDDCCluster -OrgName -SDDCName -HostCount 1 -CPUCoreCount 8 + #> + [cmdletbinding(SupportsShouldProcess = $true,ConfirmImpact='High')] + param( + [Parameter(Mandatory=$true)][String]$OrgName, + [Parameter(Mandatory=$true)][String]$SDDCName, + [Parameter(Mandatory=$true)][Int]$HostCount, + [Parameter(Mandatory=$true)][ValidateSet("8","16","32")]$CPUCoreCount + ) + + if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } + + $orgId = Get-VMCOrg -Name $OrgName | Select-Object -ExpandProperty Id + $sddcId = Get-VMCSDDC -Name $SDDCName -Org $OrgName | Select-Object -ExpandProperty Id + + if(-not $orgId) { + Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" + break + } + if(-not $sddcId) { + Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" + break + } + + $sddcClusterSvc = Get-VmcService -Name com.vmware.vmc.orgs.sddcs.clusters + + $sddcClusterCreateSpec = $sddcClusterSvc.Help.create.cluster_config.Create() + $sddcClusterCreateSpec.host_cpu_cores_count = $CPUCoreCount + $sddcClusterCreateSpec.num_hosts = $HostCount + + $sddcClusterTask = $sddcClusterSvc.Create($org.Id, $sddc.Id, $sddcClusterCreateSpec) + $sddcClusterTask | Select-Object Id,Task_Type,Status,Created | Format-Table +} +Function Get-VMCSDDCCluster { + <# + .NOTES + =========================================================================== + Created by: Kyle Ruddy + Date: 03/16/2019 + Organization: VMware + Blog: https://www.kmruddy.com + Twitter: @kmruddy + =========================================================================== + + .SYNOPSIS + Retreives cluster information for the designated SDDC + .DESCRIPTION + Lists cluster information for an SDDC + .EXAMPLE + Get-VMCSDDCCluster -OrgName -SDDCName -HostCount 1 -CPUCoreCount 8 + #> + [cmdletbinding(SupportsShouldProcess = $true,ConfirmImpact='Low')] + param( + [Parameter(Mandatory=$true)][String]$OrgName, + [Parameter(Mandatory=$true)][String]$SddcName + ) + + if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } + + $orgId = Get-VMCOrg -Name $OrgName | Select-Object -ExpandProperty Id + $sddcId = Get-VMCSDDC -Name $SDDCName -Org $OrgName | Select-Object -ExpandProperty Id + + if(-not $orgId) { + Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" + break + } + if(-not $sddcId) { + Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" + break + } + + $clusterOutput = @() + $sddcClusters = Get-VMCSDDC -Org $OrgName -Name $SDDCName | Select-Object -ExpandProperty resource_config | Select-Object -ExpandProperty clusters + foreach ($c in $sddcClusters) { + $tempCluster = "" | Select-Object Id, Name, State + $tempCluster.Id = $c.cluster_id + $tempCluster.Name = $c.cluster_name + $tempCluster.State = $c.cluster_state + $clusterOutput += $tempCluster + } + return $clusterOutput +} +Function New-VMCSDDCCluster { + <# + .NOTES + =========================================================================== + Created by: Kyle Ruddy + Date: 03/16/2019 + Organization: VMware + Blog: https://www.kmruddy.com + Twitter: @kmruddy + =========================================================================== + + .SYNOPSIS + Creates a new cluster for the designated SDDC + .DESCRIPTION + Creates a new cluster + .EXAMPLE + New-VMCSDDCCluster -OrgName -SDDCName -HostCount 1 -CPUCoreCount 8 + #> + [cmdletbinding(SupportsShouldProcess = $true,ConfirmImpact='High')] + param( + [Parameter(Mandatory=$true)][String]$OrgName, + [Parameter(Mandatory=$true)][String]$SddcName, + [Parameter(Mandatory=$true)][Int]$HostCount, + [Parameter(Mandatory=$false)][ValidateSet("8","16","36","48")]$CPUCoreCount + ) + + if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } + + $orgId = Get-VMCOrg -Name $OrgName | Select-Object -ExpandProperty Id + $sddcId = Get-VMCSDDC -Name $SDDCName -Org $OrgName | Select-Object -ExpandProperty Id + + if(-not $orgId) { + Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" + break + } + if(-not $sddcId) { + Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" + break + } + + $sddcClusterSvc = Get-VmcService -Name com.vmware.vmc.orgs.sddcs.clusters + + $sddcClusterCreateSpec = $sddcClusterSvc.Help.create.cluster_config.Create() + $sddcClusterCreateSpec.host_cpu_cores_count = $CPUCoreCount + $sddcClusterCreateSpec.num_hosts = $HostCount + + $sddcClusterTask = $sddcClusterSvc.Create($org.Id, $sddc.Id, $sddcClusterCreateSpec) + $sddcClusterTask | Select-Object Id,Task_Type,Status,Created | Format-Table +} +Function Remove-VMCSDDCCluster { + <# + .NOTES + =========================================================================== + Created by: Kyle Ruddy + Date: 03/16/2019 + Organization: VMware + Blog: https://www.kmruddy.com + Twitter: @kmruddy + =========================================================================== + + .SYNOPSIS + Removes a specified cluster from the designated SDDC + .DESCRIPTION + Deletes a cluster from an SDDC + .EXAMPLE + Remove-VMCSDDCCluster -OrgName -SDDCName -Cluster + #> + [cmdletbinding(SupportsShouldProcess = $true,ConfirmImpact='High')] + param( + [Parameter(Mandatory=$true)][String]$OrgName, + [Parameter(Mandatory=$true)][String]$SDDCName, + [Parameter(Mandatory=$true)][String]$ClusterName + ) + + if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } + + $orgId = Get-VMCOrg -Name $OrgName | Select-Object -ExpandProperty Id + $sddcId = Get-VMCSDDC -Name $SDDCName -Org $OrgName | Select-Object -ExpandProperty Id + $clusterId = Get-VMCSDDCCluster -SddcName $SDDCName -OrgName $OrgName | Where-Object {$_.Name -eq $ClusterName} | Select-Object -ExpandProperty Id + + if(-not $orgId) { + Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" + break + } + if(-not $sddcId) { + Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" + break + } + if(-not $clusterId) { + Write-Host -ForegroundColor red "Unable to find cluster $ClusterName, please verify input" + break + } + + $sddcClusterTask = $sddcClusterSvc.Delete($orgId, $sddcId, $clusterId) + $sddcClusterTask | Select-Object Id,Task_Type,Status,Created | Format-Table +} Export-ModuleMember -Function 'Get-VMCCommand', 'Connect-VMCVIServer', 'Get-VMCOrg', 'Get-VMCSDDC', 'Get-VMCTask', 'Get-VMCSDDCDefaultCredential', 'Get-VMCSDDCPublicIP', 'Get-VMCVMHost', 'Get-VMCSDDCVersion', 'Get-VMCFirewallRule', 'Export-VMCFirewallRule', 'Import-VMCFirewallRule', 'Remove-VMCFirewallRule', 'Get-VMCLogicalNetwork', 'Remove-VMCLogicalNetwork', 'New-VMCLogicalNetwork', 'Get-VMCSDDCSummary', 'Get-VMCPublicIP', 'New-VMCPublicIP', 'Remove-VMCPublicIP', 'Set-VMCSDDC', - 'Get-VMCEdge', 'Get-VMCEdgeNic', 'Get-VMCEdgeStatus', 'Get-VMCEdgeNicStat', 'Get-VMCEdgeUplinkStat' - + 'Get-VMCEdge', 'Get-VMCEdgeNic', 'Get-VMCEdgeStatus', 'Get-VMCEdgeNicStat', 'Get-VMCEdgeUplinkStat', + 'Get-VMCSDDCCluster', 'New-VMCSDDCCluster', 'Remove-VMCSDDCCluster' \ No newline at end of file