diff --git a/Modules/ContentLibrary/ContentLibrary.psm1 b/Modules/ContentLibrary/ContentLibrary.psm1 index 9a8574b..5729445 100644 --- a/Modules/ContentLibrary/ContentLibrary.psm1 +++ b/Modules/ContentLibrary/ContentLibrary.psm1 @@ -190,7 +190,7 @@ Function Get-ContentLibraryItemFiles { $itemIds = $contentLibraryItemService.list($libraryID) $DatastoreID = $library.storage_backings.datastore_id.Value $Datastore = get-datastore -id "Datastore-$DatastoreID" - + foreach($itemId in $itemIds) { $itemName = ($contentLibraryItemService.get($itemId)).name $contentLibraryItemFileSerice = Get-CisService com.vmware.content.library.item.file @@ -205,7 +205,7 @@ Function Get-ContentLibraryItemFiles { else{ $fullfilepath = "UNKNOWN" } - + if(!$LibraryItemName) { $fileResult = [pscustomobject] @{ Name = $file.name; @@ -709,4 +709,72 @@ Function New-VMFromVMTX { Write-Host "`nDeploying new VM $NewVMName from VMTX Template $VMTXName ..." $results = $vmtxService.deploy($vmtxId,$vmtxDeploySpec) -} +} + +Function New-SubscribedContentLibrary { +<# + .NOTES + =========================================================================== + Created by: William Lam + Organization: VMware + Blog: www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + .DESCRIPTION + This function creates a new Subscriber Content Library from Subscription URL + .PARAMETER LibraryName + The name of the new vSphere Content Library + .PARAMETER DatastoreName + The name of the vSphere Datastore to store the Content Library + .PARAMETER SubscriptionURL + The URL of the published Content Library + .PARAMETER SubscriptionThumbprint + The SSL Thumbprint for the published Content Library + .PARAMETER OnDemand + Specifies whether content is downloaded on-demand (e.g. no immediately) + .PARAMETER AutomaticSync + Specifies whether automatic synchronization with the external content library is enabled + .EXAMPLE + New-SubscribedContentLibrary -LibraryName NestedESXi -DatastoreName vsanDatastore -SubscriptionURL https://download3.vmware.com/software/vmw-tools/lib.json -SubscriptionThumbprint "7a:c4:08:2d:d3:55:56:af:9f:26:43:65:d0:31:99:0b:d2:f3:d8:69" -AutomaticSync + .EXAMPLE + New-SubscribedContentLibrary -LibraryName NestedESXi -DatastoreName vsanDatastore -SubscriptionURL https://download3.vmware.com/software/vmw-tools/lib.json -SubscriptionThumbprint "7a:c4:08:2d:d3:55:56:af:9f:26:43:65:d0:31:99:0b:d2:f3:d8:69" -OnDemand +#> + param( + [Parameter(Mandatory=$true)][String]$LibraryName, + [Parameter(Mandatory=$true)][String]$DatastoreName, + [Parameter(Mandatory=$true)][String]$SubscriptionURL, + [Parameter(Mandatory=$true)][String]$SubscriptionThumbprint, + [Parameter(Mandatory=$false)][Switch]$OnDemand, + [Parameter(Mandatory=$false)][Switch]$AutomaticSync + ) + + $datastore = Get-Datastore -Name $DatastoreName + + if($datastore) { + $datastoreId = $datastore.ExtensionData.MoRef.Value + $subscribeLibraryService = Get-CisService -Name "com.vmware.content.subscribed_library" + + $StorageSpec = [pscustomobject] @{ + datastore_id = $datastoreId; + type = "DATASTORE"; + } + + $UniqueChangeId = [guid]::NewGuid().tostring() + + $createSpec = $subscribeLibraryService.help.create.create_spec.create() + $createSpec.name = $LibraryName + $createSpec.type = "SUBSCRIBED" + $addResults = $createSpec.storage_backings.Add($StorageSpec) + + if($OnDemand) { $OnDemandFlag = $true } else { $OnDemandFlag = $false } + if($AutomaticSync) { $AutomaticSyncFlag = $true } else { $AutomaticSyncFlag = $false } + $createSpec.subscription_info.on_demand = $OnDemandFlag + $createSpec.subscription_info.automatic_sync_enabled = $AutomaticSyncFlag + $createSpec.subscription_info.subscription_url = $SubscriptionURL + $createSpec.subscription_info.authentication_method = "NONE" + $createSpec.subscription_info.ssl_thumbprint = $SubscriptionThumbprint + + Write-Host "Creating new Subscribed Content Library called $LibraryName ..." + $library = $subscribeLibraryService.create($UniqueChangeId, $createSpec) + } +} \ No newline at end of file diff --git a/Modules/CrossvCentervmotion/XVM.psm1 b/Modules/CrossvCentervmotion/XVM.psm1 index cb9d225..555ec5d 100644 --- a/Modules/CrossvCentervmotion/XVM.psm1 +++ b/Modules/CrossvCentervmotion/XVM.psm1 @@ -152,10 +152,12 @@ Function New-XVCMRequest { The name of the source vSphere Datacenter .PARAMETER DstDatacenter The name of the destination vSphere Datacenter - .PARAMETER SrcCluster - .PARAMETER DstCluster The name of the destination vSphere Cluster, set to null if DstHost is defined + .PARAMETER DstPool + The name of the destination vSphere Resource Pool + .PARAMETER DstFolder + The name of the destination vSphere Folder .PARAMETER DstDatastore The name of the destination Datastore .PARAMETER DstHost @@ -171,6 +173,15 @@ Function New-XVCMRequest { -DstDatastore vsanDatastore ` -srcVMs @("PhotonOS-01","PhotonOS-02","PhotonOS-03","PhotonOS-04") ` -NetworkMapping @{"DVPG-VM Network 1"="DVPG-Internal Network";"DVPG-VM Network 2"="DVPG-External Network"} + .EXAMPLE + New-XVCMRequest -opType Clone -SrcSite OREGON -DstSite CALIF ` + -SrcDatacenter SDDC-Datacenter -srcVMs @(“DUDE-ubuntu”) ` + -DstDatacenter SDDC-Datacenter ` + -DstCluster "Cluster-1" -DstHost $null ` + -DstPool Compute-ResourcePool ` + -DstFolder Workloads ` + -DstDatastore WorkloadDatastore ` + -NetworkMapping @{"OREGON-VMs-sddc"="CALIF-sddc-VMs"} #> param( [Parameter(Mandatory=$true)][String]$opType, #Added by CPM for 2.0 @@ -178,8 +189,9 @@ Function New-XVCMRequest { [Parameter(Mandatory=$true)][String]$DstSite, [Parameter(Mandatory=$true)][String]$SrcDatacenter, [Parameter(Mandatory=$true)][String]$DstDatacenter, - #[Parameter(Mandatory=$true)][String]$SrcCluster, #Removed by CPM for 2.0 [Parameter(Mandatory=$true)][AllowNull()] $DstCluster, #Added [AllowNull()], removed [String] by CPM for 2.0 + [Parameter(Mandatory=$true)][String]$DstPool, + [Parameter(Mandatory=$true)][String]$DstFolder, [Parameter(Mandatory=$true)][String]$DstDatastore, [Parameter(Mandatory=$true)][AllowNull()] $DstHost, #Added by CPM for 2.0 [Parameter(Mandatory=$true)][String[]]$srcVMs, @@ -193,7 +205,8 @@ Function New-XVCMRequest { "targetSite"=$DstSite; "sourceDatacenter"=$SrcDatacenter; "targetDatacenter"=$dstDatacenter; - #"sourceCluster"=$SrcCluster; #Removed by CPM for 2.0 + "targetPool"=$DstPool; + "targetFolder"=$DstFolder; "targetCluster"=$DstCluster; "targetDatastore"=$DstDatastore; "targetHost"=$DstHost; #Added by CPM for 2.0 diff --git a/Modules/VMware.DRaaS/VMware.DRaaS.psd1 b/Modules/VMware.DRaaS/VMware.DRaaS.psd1 new file mode 100755 index 0000000..fd5ab06 Binary files /dev/null and b/Modules/VMware.DRaaS/VMware.DRaaS.psd1 differ diff --git a/Modules/VMware.DRaaS/VMware.DRaaS.psm1 b/Modules/VMware.DRaaS/VMware.DRaaS.psm1 new file mode 100644 index 0000000..3028c8c --- /dev/null +++ b/Modules/VMware.DRaaS/VMware.DRaaS.psm1 @@ -0,0 +1,256 @@ +Function Connect-DRaas { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 05/23/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + This cmdlet creates $global:draasConnection object containing the DRaaS URL along with CSP Token Header + .DESCRIPTION + This cmdlet creates $global:draasConnection object containing the DRaaS URL along with CSP Token Header + .EXAMPLE + Connect-DRaaS -RefreshToken $RefreshToken -OrgName $OrgName -SDDCName $SDDCName + .NOTES + You must be logged into VMC using Connect-VmcServer cmdlet +#> + Param ( + [Parameter(Mandatory=$true)][String]$RefreshToken, + [Parameter(Mandatory=$true)][String]$OrgName, + [Parameter(Mandatory=$true)][String]$SDDCName + ) + + If (-Not $global:DefaultVMCServers.IsConnected) { Write-error "No valid VMC Connection found, please use the Connect-VMC to connect"; break } Else { + $sddcService = Get-VmcService "com.vmware.vmc.orgs.sddcs" + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + $sddc = $sddcService.get($orgId,$sddcId) + + } + + $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"} + 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 + } + $accessToken = ($results | ConvertFrom-Json).access_token + + $headers = @{ + "csp-auth-token"="$accessToken" + "Content-Type"="application/json" + "Accept"="application/json" + } + $global:draasConnection = new-object PSObject -Property @{ + 'Server' = "https://vmc.vmware.com/vmc/draas/api/orgs/$orgId/sddcs/$sddcId/site-recovery" + 'headers' = $headers + } + $global:draasConnection +} + +Function Get-DRaas { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 05/23/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Returns information about DRaaS configuration for a given SDDC + .DESCRIPTION + This cmdlet returns information about DRaaS configuration for a given SDDC. Can be used to monitor both activate and deactivate operations. + .EXAMPLE + Get-DRaas +#> + Param ( + [Switch]$Troubleshoot + ) + + If (-Not $global:draasConnection) { Write-error "No DRaaS Connection found, please use Connect-DRaaS" } Else { + $method = "GET" + $draasUrl = $global:draasConnection.Server + $draasVersionUrl = $global:draasConnection.Server + "/versions" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $METHOD`n$draasUrl`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $draasUrl -Method $method -Headers $global:draasConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $draasUrl -Method $method -Headers $global:draasConnection.headers + } + } catch { + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe CSP session is no longer valid, please re-run the Connect-DRaaS cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in retrieving DRaaS Information" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + $json = ($requests.Content | ConvertFrom-Json) + + $draasId = $json.id; + $draasState = $json.site_recovery_state; + $srmNode = $json.srm_node.ip_address; + $srmNodeState = $json.site_recovery_state; + $vrNode = $json.vr_node.ip_address; + $vrNodeState = $json.vr_node.state; + $draasUrl = $json.draas_h5_url; + + if($srmNodeState -eq "ACTIVATED") { + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $METHOD`n$draasVersionUrl`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $draasVersionUrl -Method $method -Headers $global:draasConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $draasVersionUrl -Method $method -Headers $global:draasConnection.headers + } + } catch { + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe CSP session is no longer valid, please re-run the Connect-DRaaS cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in retrieving DRaaS Information" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + $json = ($requests.Content | ConvertFrom-Json).node_versions + + $srmVersion,$srmDescription = ($json | where {$_.node_ip -eq $srmNode}).full_version.split("`n") + $vrVersion,$vrDescription = ($json | where {$_.node_ip -eq $vrNode}).full_version.split("`n") + + $results = [pscustomobject] @{ + ID = $draasId; + DRaaSState = $draasState; + SRMNode = $srmNode; + SRMVersion = $srmVersion; + SRMNodeState = $srmNodeState; + VRNode = $vrNode; + VRVersion = $vrVersion; + VRNodeState = $vrNodeState; + DRaaSURL = $draasUrl; + } + + $results + } + } elseif ($srmNodeState -eq "ACTIVATING" -or $srmNodeState -eq "DEACTIVATING") { + $results = [pscustomobject] @{ + ID = $draasId; + DRaaSState = $draasState; + SRMNode = $srmNode; + SRMNodeState = $srmNodeState; + VRNode = $vrNode; + VRNodeState = $vrNodeState; + DRaaSURL = $draasUrl; + } + + $results + } else { + Write-Host "`nDRaaS is currently deactivated, please run Set-DRaas -Activate`n" + } + } else { + Write-Host "`nDRaaS has not been activated before, please run Set-DRaas -Activate`n" + } + } +} + + +Function Set-DRaas { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 05/23/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Activate or deactivate DRaaS for a given SDDC + .DESCRIPTION + This cmdlet activates or deactivates DRaaS for a given SDDC + .EXAMPLE + Get-DRaas +#> + Param ( + [Switch]$Activate, + [Switch]$Deactivate, + [Switch]$Troubleshoot + ) + + If (-Not $global:draasConnection) { Write-error "No DRaaS Connection found, please use Connect-DRaaS" } Else { + $draasUrl = $global:draasConnection.server + + if($Activate) { + $method = "POST" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $METHOD`n$draasUrl`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $draasUrl -Method $method -Headers $global:draasConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $draasUrl -Method $method -Headers $global:draasConnection.headers + } + } catch { + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe CSP session is no longer valid, please re-run the Connect-DRaaS cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in activating DRaaS" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + Write-Host "`nActivating DRaaS, this will take some time and you can monitor the progress using Get-DRaaS or using the VMC Console UI`n" + } elseif ($Deactivate) { + $method = "DELETE" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $METHOD`n$draasUrl`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $draasUrl -Method $method -Headers $global:draasConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $draasUrl -Method $method -Headers $global:draasConnection.headers + } + } catch { + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe CSP session is no longer valid, please re-run the Connect-DRaaS cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in deactivating DRaaS" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + Write-Host "`nDeactivating DRaaS, this will take some time and you can monitor the progress using Get-DRaaS or the VMC Console UI`n" + } else { + Write-Error "Invalid Operation" + } + } +} \ No newline at end of file diff --git a/Modules/VMware.HCX/VMware.HCX.psd1 b/Modules/VMware.HCX/VMware.HCX.psd1 index a5e74f0..3b3f3b0 100644 --- a/Modules/VMware.HCX/VMware.HCX.psd1 +++ b/Modules/VMware.HCX/VMware.HCX.psd1 @@ -36,7 +36,7 @@ Description = 'PowerShell Module for Managing Hybrid Cloud Extension (HCX) on VM 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-HcxServer', 'Get-HcxCloudConfig', 'Get-HcxEndpoint', 'New-HcxMigration', 'Get-HcxMigration', 'Connect-HcxVAMI', 'Get-HcxVCConfig', 'Set-HcxLicense', 'Set-HcxVCConfig', 'Get-HcxNSXConfig', 'Set-HcxNSXConfig', 'Get-HcxCity', 'Get-HcxLocation', 'Set-HcxLocation', 'Get-HcxRoleMapping', 'Set-HcxRoleMapping', 'Get-HcxProxy', 'Set-HcxProxy', 'Remove-HcxProxy' +FunctionsToExport = 'Connect-HcxServer', 'Get-HcxCloudConfig', 'Get-HcxEndpoint', 'New-HcxMigration', 'Get-HcxMigration', 'Connect-HcxVAMI', 'Get-HcxVCConfig', 'Set-HcxLicense', 'Set-HcxVCConfig', 'Get-HcxNSXConfig', 'Set-HcxNSXConfig', 'Get-HcxCity', 'Get-HcxLocation', 'Set-HcxLocation', 'Get-HcxRoleMapping', 'Set-HcxRoleMapping', 'Get-HcxProxy', 'Set-HcxProxy', 'Remove-HcxProxy', 'Get-HcxLicense' # 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.HCX/VMware.HCX.psm1 b/Modules/VMware.HCX/VMware.HCX.psm1 index cfbe95b..b8f8866 100644 --- a/Modules/VMware.HCX/VMware.HCX.psm1 +++ b/Modules/VMware.HCX/VMware.HCX.psm1 @@ -453,12 +453,23 @@ Function Get-HcxMigration { Get-HcxMigration -MigrationId #> Param ( - [Parameter(Mandatory=$false)][String]$MigrationId, + [Parameter(Mandatory=$false)][String[]]$MigrationId, [Switch]$RunningMigrations ) If (-Not $global:hcxConnection) { Write-error "HCX Auth Token not found, please run Connect-HcxManager " } Else { - $spec = @{} + If($PSBoundParameters.ContainsKey("MigrationId")){ + $spec = @{ + filter = @{ + migrationId = $MigrationId + } + paging =@{ + pageSize = $MigrationId.Count + } + } + } Else { + $spec = @{} + } $body = $spec | ConvertTo-Json $hcxQueryUrl = $global:hcxConnection.Server + "/migrations?action=query" @@ -468,10 +479,10 @@ Function Get-HcxMigration { $requests = Invoke-WebRequest -Uri $hcxQueryUrl -Method POST -Headers $global:hcxConnection.headers -UseBasicParsing } - $migrations = ($requests.content | ConvertFrom-Json).rows - if($PSBoundParameters.ContainsKey("MigrationId")){ - $migrations = $migrations | where { $_.migrationId -eq $MigrationId } + $migrations = ($requests.content | ConvertFrom-Json).items + } else { + $migrations = ($requests.content | ConvertFrom-Json).rows } if($RunningMigrations){ @@ -559,16 +570,22 @@ Function Get-HcxVCConfig { #> If (-Not $global:hcxVAMIConnection) { Write-error "HCX Auth Token not found, please run Connect-HcxVAMI " } Else { $vcConfigUrl = $global:hcxVAMIConnection.Server + "/api/admin/global/config/vcenter" + $pscConfigUrl = $global:hcxVAMIConnection.Server + "/api/admin/global/config/lookupservice" if($PSVersionTable.PSEdition -eq "Core") { $vcRequests = Invoke-WebRequest -Uri $vcConfigUrl -Method GET -Headers $global:hcxVAMIConnection.headers -UseBasicParsing -SkipCertificateCheck + $ssoRequests = Invoke-WebRequest -Uri $pscConfigUrl -Method GET -Headers $global:hcxVAMIConnection.headers -UseBasicParsing -SkipCertificateCheck } else { $vcRequests = Invoke-WebRequest -Uri $vcConfigUrl -Method GET -Headers $global:hcxVAMIConnection.headers -UseBasicParsing + $ssoRequests = Invoke-WebRequest -Uri $pscConfigUrl -Method GET -Headers $global:hcxVAMIConnection.headers -UseBasicParsing } $vcData = ($vcRequests.content | ConvertFrom-Json).data.items + $ssoData = ($ssoRequests.content | ConvertFrom-Json).data.items $tmp = [pscustomobject] @{ Name = $vcData.config.name; + UserName = $vcData.Config.userName + LookupServiceUrl = $ssoData.config.lookupServiceUrl Version = $vcData.config.version; Build = $vcData.config.buildNumber; UUID = $vcData.config.vcuuid; @@ -578,6 +595,38 @@ Function Get-HcxVCConfig { } } +Function Get-HcxLicense { + <# + .NOTES + =========================================================================== + Created by: Mark McGilly + Date: 4/29/2019 + Organization: Liberty Mutual Insurance + =========================================================================== + + .SYNOPSIS + Returns the license key that is registered with HCX Manager + .DESCRIPTION + This cmdlet returns the license key registered with HCX Manager + .EXAMPLE + Get-HcxLicense + #> + + If (-Not $global:hcxVAMIConnection) { Write-error "HCX Auth Token not found, please run Connect-HcxVAMI " } Else { + $hcxConfigUrl = $global:hcxVAMIConnection.Server + "/api/admin/global/config/hcx" + + if($PSVersionTable.PSEdition -eq "Core") { + $licenseRequests = Invoke-WebRequest -Uri $hcxConfigUrl -Method GET -Headers $global:hcxVAMIConnection.headers -UseBasicParsing -SkipCertificateCheck + } else { + $licenseRequests = Invoke-WebRequest -Uri $hcxConfigUrl -Method GET -Headers $global:hcxVAMIConnection.headers -UseBasicParsing + } + $license = ($licenseRequests.content | ConvertFrom-Json).data.items + if($licenseRequests) { + $license.config.activationKey + } + } +} + Function Set-HcxLicense { <# .NOTES @@ -789,6 +838,7 @@ Function Get-HcxNSXConfig { $tmp = [pscustomobject] @{ Name = $nsxData.config.url; + UserName = $nsxData.config.userName Version = $nsxData.config.version; HCXUUID = $nsxData.config.uuid; } @@ -1200,6 +1250,7 @@ Function Set-HcxProxy { [Parameter(Mandatory=$True)]$ProxyPort, [Parameter(Mandatory=$False)]$ProxyUser, [Parameter(Mandatory=$False)]$ProxyPassword, + [Parameter(Mandatory=$False)]$ProxyExclusions, [Switch]$Troubleshoot ) @@ -1214,7 +1265,7 @@ Function Set-HcxProxy { config = @{ proxyHost = "$ProxyServer"; proxyPort = "$ProxyPort"; - nonProxyHosts = ""; + nonProxyHosts = "$ProxyExclusions"; userName = "$ProxyUser"; password = "$ProxyPassword"; } diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index c150c5f..a73fc56 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -94,6 +94,159 @@ function Get-VcenterID { return $virtualCenterId } +function Get-HVvCenterServer { + <# + .Synopsis + Gets a list of all configured vCenter Servers + + .DESCRIPTION + Queries and returns the vCenter Servers configured for the pod of the specified HVServer. + + .PARAMETER HvServer + Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered inplace of hvServer + + .PARAMETER Name + A string value to query a vCenter Server by Name, if it is known. + + .EXAMPLE + Get-HVvCenterServer + + .EXAMPLE + Get-HVvCenterServer -Name 'vCenter1' + + .OUTPUTS + Returns array of object type VMware.Hv.VirtualCenterInfo + + .NOTES + Author : Matt Frey. + Author email : mfrey@vmware.com + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.7 + PowerCLI Version : PowerCLI 11.2.0 + PowerShell Version : 5.1 + #> + + param( + [Parameter(Mandatory = $false)] + $HvServer = $null, + + [Parameter(Mandatory = $false)] + [string]$Name = $null + ) + + begin { + $services = Get-ViewAPIService -hvServer $hvServer + + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + + if ($null -ne $PSBoundParameters.Name) { + $vCenterList = $services.VirtualCenter.VirtualCenter_List() | Where-Object {$_.ServerSpec.ServerName -eq $Name} + } else { + $vCenterList = $services.VirtualCenter.VirtualCenter_List() + } + + } + + end { + + return $vCenterList + + } +} + +function Get-HVvCenterServerHealth { + <# + .Synopsis + Gets a the health info for a given vCenter Server. + + .DESCRIPTION + Queries and returns the VirtualCenterHealthInfo specified HVServer. + + .PARAMETER HvServer + Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered inplace of hvServer + + .PARAMETER VirtualCenter + A parameter to specify which vCenter Server to check health for. If not specified, this function will return the + health info for all vCenter Servers. + + .EXAMPLE + Get-HVvCenterServerHealth -VirtualCenter 'vCenter1' + + .EXAMPLE + Get-HVvCenterServerHealth -VirtualCenter $vCenter1 + + .EXAMPLE + Get-HVvCenterServerHealth + + .OUTPUTS + Returns array of object type VMware.Hv.VirtualCenterInfo + + .NOTES + Author : Matt Frey. + Author email : mfrey@vmware.com + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.7 + PowerCLI Version : PowerCLI 11.2.0 + PowerShell Version : 5.1 + #> + + param( + [Parameter(Mandatory = $false)] + $HvServer = $null, + + [Parameter(Mandatory = $false)] + $VirtualCenter = $null + ) + + begin { + $services = Get-ViewAPIService -hvServer $hvServer + + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + + if ($null -eq $PSBoundParameters.VirtualCenter) { + $VirtualCenterHealth = $services.VirtualCenterHealth.VirtualCenterHealth_List() + } else { + $objType = $VirtualCenter.getType() | Select-Object -ExpandProperty Name + Switch ($objType) { + 'String' { + $VirtualCenterHealth = $services.VirtualCenterHealth.VirtualCenterHealth_Get($(Get-HVvCenterServer -Name $VirtualCenter | Select-Object -ExpandProperty Id)) + } + 'VirtualCenterInfo' { + $VirtualCenterHealth = $services.VirtualCenterHealth.VirtualCenterHealth_Get($($VirtualCenter | Select-Object -ExpandProperty Id)) + } + 'VirtualCenterId' { + $VirtualCenterHealth = $services.VirtualCenterHealth.VirtualCenterHealth_Get($VirtualCenter) + } + } + } + + } + + end { + + return $VirtualCenterHealth + + } +} + function Get-JsonObject { param( [Parameter(Mandatory = $true)] @@ -462,8 +615,6 @@ function Add-HVRDSServer { } } - - function Connect-HVEvent { <# .SYNOPSIS @@ -1004,8 +1155,7 @@ function Get-HVFarm { if (! $farmList) { if (! $SuppressInfo) { Write-Host "Get-HVFarm: No Farm Found with given search parameters" - } - return $farmList + } } $farm_service_helper = New-Object VMware.Hv.FarmService $queryResults = @() @@ -1906,7 +2056,7 @@ function New-HVFarm { Set to true to enable provision of RDSServers immediately in farm. Applicable to Linked Clone and Instant Clone farms. -.PARAMETER StopOnProvisioningError +.PARAMETER StopProvisioningOnError Set to true to stop provisioning of all RDSServers on error. Applicable to Linked Clone and Instant Clone farms. @@ -1979,11 +2129,11 @@ function New-HVFarm { Reference to Horizon View Server to query the farms from. If the value is not passed or null then first element from global:DefaultHVServers would be considered in-place of hvServer. .EXAMPLE - New-HVFarm -LinkedClone -FarmName 'LCFarmTest' -ParentVM 'Win_Server_2012_R2' -SnapshotVM 'Snap_RDS' -VmFolder 'PoolVM' -HostOrCluster 'cls' -ResourcePool 'cls' -Datastores 'datastore1 (5)' -FarmDisplayName 'LC Farm Test' -Description 'created LC Farm from PS' -EnableProvisioning $true -StopOnProvisioningError $false -NamingPattern "LCFarmVM_PS" -MinReady 1 -MaximumCount 1 -SysPrepName "RDSH_Cust2" -NetBiosName "adviewdev" + New-HVFarm -LinkedClone -FarmName 'LCFarmTest' -ParentVM 'Win_Server_2012_R2' -SnapshotVM 'Snap_RDS' -VmFolder 'PoolVM' -HostOrCluster 'cls' -ResourcePool 'cls' -Datastores 'datastore1 (5)' -FarmDisplayName 'LC Farm Test' -Description 'created LC Farm from PS' -EnableProvisioning $true -StopProvisioningOnError $false -NamingPattern "LCFarmVM_PS" -MinReady 1 -MaximumCount 1 -SysPrepName "RDSH_Cust2" -NetBiosName "adviewdev" Creates new linkedClone farm by using naming pattern .EXAMPLE - New-HVFarm -InstantClone -FarmName 'ICFarmCL' -ParentVM 'vm-rdsh-ic' -SnapshotVM 'Snap_5' -VmFolder 'Instant_Clone_VMs' -HostOrCluster 'vimal-cluster' -ResourcePool 'vimal-cluster' -Datastores 'datastore1' -FarmDisplayName 'IC Farm using CL' -Description 'created IC Farm from PS command-line' -EnableProvisioning $true -StopOnProvisioningError $false -NamingPattern "ICFarmCL-" -NetBiosName "ad-vimalg" + New-HVFarm -InstantClone -FarmName 'ICFarmCL' -ParentVM 'vm-rdsh-ic' -SnapshotVM 'Snap_5' -VmFolder 'Instant_Clone_VMs' -HostOrCluster 'vimal-cluster' -ResourcePool 'vimal-cluster' -Datastores 'datastore1' -FarmDisplayName 'IC Farm using CL' -Description 'created IC Farm from PS command-line' -EnableProvisioning $true -StopProvisioningOnError $false -NamingPattern "ICFarmCL-" -NetBiosName "ad-vimalg" Creates new linkedClone farm by using naming pattern .EXAMPLE @@ -2193,11 +2343,11 @@ function New-HVFarm { [boolean] $EnableProvisioning = $true, - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.stopOnProvisioningError if LINKED_CLONE, INSTANT_CLONE + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.stopProvisioningOnError if LINKED_CLONE, INSTANT_CLONE [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [boolean] - $StopOnProvisioningError = $true, + $StopProvisioningOnError = $true, [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] @@ -2790,7 +2940,6 @@ function Test-HVFarmSpec { } } - function Get-HVFarmProvisioningData { param( [Parameter(Mandatory = $false)] @@ -2865,7 +3014,6 @@ function Get-HVFarmProvisioningData { return $vmObject } - function Get-HVFarmStorageObject { param( @@ -2933,7 +3081,6 @@ function Get-HVFarmStorageObject { return $storageObject } - function Get-HVFarmNetworkSetting { param( [Parameter(Mandatory = $false)] @@ -2945,7 +3092,6 @@ function Get-HVFarmNetworkSetting { return $networkObject } - function Get-HVFarmCustomizationSetting { param( [Parameter(Mandatory = $false)] @@ -3078,7 +3224,6 @@ function Get-FarmSpec { return $farm_spec_helper.getDataObject() } - function New-HVPool { <# .Synopsis @@ -3302,7 +3447,7 @@ function New-HVPool { .PARAMETER BlackoutTimes A list of blackout times. -.PARAMETER StopOnProvisioningError +.PARAMETER StopProvisioningOnError Set to true to stop provisioning of all VMs on error. Applicable to Full, Linked, Instant Clone Pools. @@ -3429,7 +3574,7 @@ function New-HVPool { first element from global:DefaultHVServers would be considered in-place of hvServer. .EXAMPLE - C:\PS>New-HVPool -LinkedClone -PoolName 'vmwarepool' -UserAssignment FLOATING -ParentVM 'Agent_vmware' -SnapshotVM 'kb-hotfix' -VmFolder 'vmware' -HostOrCluster 'CS-1' -ResourcePool 'CS-1' -Datastores 'datastore1' -NamingMethod PATTERN -PoolDisplayName 'vmware linkedclone pool' -Description 'created linkedclone pool from ps' -EnableProvisioning $true -StopOnProvisioningError $false -NamingPattern "vmware2" -MinReady 0 -MaximumCount 1 -SpareCount 1 -ProvisioningTime UP_FRONT -SysPrepName vmwarecust -CustType SYS_PREP -NetBiosName adviewdev -DomainAdmin root + C:\PS>New-HVPool -LinkedClone -PoolName 'vmwarepool' -UserAssignment FLOATING -ParentVM 'Agent_vmware' -SnapshotVM 'kb-hotfix' -VmFolder 'vmware' -HostOrCluster 'CS-1' -ResourcePool 'CS-1' -Datastores 'datastore1' -NamingMethod PATTERN -PoolDisplayName 'vmware linkedclone pool' -Description 'created linkedclone pool from ps' -EnableProvisioning $true -StopProvisioningOnError $false -NamingPattern "vmware2" -MinReady 0 -MaximumCount 1 -SpareCount 1 -ProvisioningTime UP_FRONT -SysPrepName vmwarecust -CustType SYS_PREP -NetBiosName adviewdev -DomainAdmin root Create new automated linked clone pool with naming method pattern .EXAMPLE @@ -3667,13 +3812,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 @@ -3878,12 +4029,12 @@ function New-HVPool { [boolean] $EnableProvisioning = $true, - #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.stopOnProvisioningError if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.stopProvisioningOnError if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] [boolean] - $StopOnProvisioningError = $true, + $StopProvisioningOnError = $true, [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] @@ -4158,6 +4309,7 @@ function New-HVPool { $adContainer = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.AdContainer } $custType = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.CustomizationType + $reusePreExistingAccounts = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.reusePreExistingAccounts if ($jsonObject.AutomatedDesktopSpec.ProvisioningType -eq "INSTANT_CLONE_ENGINE") { $InstantClone = $true if ($null -ne $jsonObject.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings) { @@ -4178,7 +4330,6 @@ function New-HVPool { 'SYS_PREP' { $sysprepCustomizationSettings = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.SysprepCustomizationSettings $sysPrepName = $sysprepCustomizationSettings.customizationSpec - $reusePreExistingAccounts = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.reusePreExistingAccounts } 'QUICK_PREP' { $powerOffScriptName = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.QuickprepCustomizationSettings.PowerOffScriptName @@ -4922,7 +5073,6 @@ function Get-HVPoolProvisioningData { return $vmObject } - function Get-HVHostOrClusterID { <# .Synopsis @@ -5250,7 +5400,7 @@ function Get-HVPoolCustomizationSetting { } if ($null -eq $ViewComposerDomainAdministratorID) { throw "No Composer Domain Administrator found with netBiosName: [$netBiosName]" - } + } if ($custType -eq 'SYS_PREP') { $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = 'SYS_PREP' $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.SysprepCustomizationSettings = Get-CustomizationObject @@ -5274,6 +5424,7 @@ function Get-HVPoolCustomizationSetting { throw "The customization type: [$custType] is not supported for LinkedClone Pool" } $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.DomainAdministrator = $ViewComposerDomainAdministratorID + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.ReusePreExistingAccounts = $reusePreExistingAccounts } elseIf ($FullClone) { if ($custType -eq 'SYS_PREP') { $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = 'SYS_PREP' @@ -6902,6 +7053,239 @@ function Get-Machine ($Pool,$MachineList) { return $machines } +function Get-HVBaseImageVM { + <# + .Synopsis + Gets a list of compatible base image virtual machines. + + .DESCRIPTION + Queries and returns BaseImageVmInfo for the specified vCenter Server. + + .PARAMETER HvServer + Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered in place of hvServer. + + .PARAMETER VirtualCenter + A parameter to specify which vCenter Server to check base image VMs for. It can be specified as a String, + containing the name of the vCenter, or as a vCenter object as returned by Get-HVvCenterServer. If the value is + not passed or null then first element returned from Get-HVvCenterServer would be considered in place of VirtualCenter. + + .PARAMETER Type + A parameter to define the type of compatability to check the base image VM list against. Valid options are 'VDI', 'RDS', or 'ALL' + 'VDI' will return all desktop compatible Base Image VMs. + 'RDS' will return all RDSH compatible Base Image VMs. + 'ALL' will return all Base Image VMs, regardless of compatibility. + The default value is 'ALL'. + + .PARAMETER Name + The name of a virtual machine (if known), to filter Base Image VMs on. Wildcards are accepted. If Name is specified, then Type + is not considered for filtering. + + .EXAMPLE + Get-HVBaseImageVM -VirtualCenter 'vCenter1' -Type VDI + + .EXAMPLE + Get-HVBaseImageVM -VirtualCenter $vCenter1 -Type ALL + + .EXAMPLE + Get-HVBaseImageVM -Name '*WIN10*' + + .OUTPUTS + Returns array of object type VMware.Hv.BaseImageVmInfo + + .NOTES + Author : Matt Frey. + Author email : mfrey@vmware.com + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.7 + PowerCLI Version : PowerCLI 11.2.0 + PowerShell Version : 5.1 + #> + + [cmdletbinding( + DefaultParameterSetName='Type' + )] + + param( + [Parameter(Mandatory = $false)] + $HvServer = $null, + + [Parameter(Mandatory = $false)] + $VirtualCenter = $null, + + [Parameter(Mandatory = $false,ParameterSetName = 'Type')] + [ValidateSet('VDI','RDS','ALL')] + $Type = 'VDI', + + [Parameter(Mandatory = $false,ParameterSetName = 'Name')] + [string]$Name = $null + ) + + begin { + $services = Get-ViewAPIService -hvServer $hvServer + + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + + if ($null -eq $PSBoundParameters.VirtualCenter) { + $VirtualCenterId = Get-HVvCenterServer | Select-Object -First 1 -ExpandProperty Id + } else { + $objType = $VirtualCenter.getType() | Select-Object -ExpandProperty Name + Switch ($objType) { + 'String' { + $VirtualCenterId = Get-HVvCenterServer -Name $VirtualCenter | Select-Object -ExpandProperty Id + } + 'VirtualCenterInfo' { + $VirtualCenterId = $VirtualCenter | Select-Object -ExpandProperty Id + } + 'VirtualCenterId' { + $VirtualCenterId = $VirtualCenter + } + } + } + + } + + process { + + $BaseImageVMList = $services.BaseImageVM.BaseImageVM_List($VirtualCenterId) + + #For all conditions, see https://vdc-download.vmware.com/vmwb-repository/dcr-public/3721109b-48a5-4ffb-a0ad-6d6a44f2f288/ff45dfca-1050-4265-93ef-4e7d702322e4/vdi.utils.virtualcenter.BaseImageVm.BaseImageVmIncompatibleReasons.html + + If ($null -ne $PSBoundParameters.Name) { + $CompatibleBaseImageVMs = $BaseImageVMList | Where-Object {$_.Name -like $Name} + } Else { + Switch ($Type) { + + 'VDI' { + $CompatibleBaseImageVMs = $BaseImageVMList | Where-Object { + ($_.IncompatibleReasons.InUseByDesktop -eq $false) -and + ($_.IncompatibleReasons.InUseByLinkedCloneDesktop -eq $false) -and + ($_.IncompatibleReasons.ViewComposerReplica -eq $false) -and + ($_.IncompatibleReasons.UnsupportedOS -eq $false) -and + ($_.IncompatibleReasons.NoSnapshots -eq $false) -and + (($null -eq $_.IncompatibleReasons.InstantInternal) -or ($_.IncompatibleReasons.InstantInternal -eq $false)) + } + } + 'RDS' { + $CompatibleBaseImageVMs = $BaseImageVMList | Where-Object { + ($_.IncompatibleReasons.InUseByDesktop -eq $false) -and + ($_.IncompatibleReasons.InUseByLinkedCloneDesktop -eq $false) -and + ($_.IncompatibleReasons.ViewComposerReplica -eq $false) -and + ($_.IncompatibleReasons.UnsupportedOSForLinkedCloneFarm -eq $false) -and + ($_.IncompatibleReasons.NoSnapshots -eq $false) -and + (($null -eq $_.IncompatibleReasons.InstantInternal) -or ($_.IncompatibleReasons.InstantInternal -eq $false)) + } + } + 'ALL' { + $CompatibleBaseImageVMs = $BaseImageVMList + } + + } + } + + } + + end { + + return $CompatibleBaseImageVMs + + } +} + +function Get-HVBaseImageSnapshot { + <# + .Synopsis + Gets a list of compatible base image virtual machines. + + .DESCRIPTION + Queries and returns BaseImageVmInfo for the specified vCenter Server. + + .PARAMETER HvServer + Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered in place of hvServer. + + .PARAMETER BaseImageVM + The BaseImageVM to query snapshots for. This parameter is required. Wildcards are accepted. This parameter also supports + pipeline operations with Get-HVBaseImageVM + + .EXAMPLE + Get-HVBaseImageSnapshots -BaseImageVM 'WIN10-BaseImage' + + .EXAMPLE + Get-HVBaseImageSnapshots -BaseImageVM '*WIN10*' + + .EXAMPLE + Get-HVBaseImageVM -Name 'WIN10-BaseImage' | Get-HVBaseImageSnapshots + + .OUTPUTS + Array of object type VMware.Hv.BaseImageSnapshotInfo + + .NOTES + Author : Matt Frey. + Author email : mfrey@vmware.com + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.7 + PowerCLI Version : PowerCLI 11.2.0 + PowerShell Version : 5.1 + #> + + [cmdletbinding( + DefaultParameterSetName='Type' + )] + + param( + [Parameter(Mandatory = $false)] + $HvServer = $null, + + [Parameter(Mandatory = $true,ValueFromPipeLine=$true)] + $BaseImageVM = $null + ) + + begin { + $services = Get-ViewAPIService -hvServer $hvServer + + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + + } + + process { + + if ($null -ne $PSBoundParameters.BaseImageVM) { + $objType = $BaseImageVM.getType() | Select-Object -ExpandProperty Name + Switch ($objType) { + 'String' { + $BaseImageVMObj = Get-HVBaseImageVM -Name $BaseImageVM + } + 'BaseImageVMInfo' { + $BaseImageVMObj = $BaseImageVM + } + 'Object[]' { + Write-Error 'This function cannot accept an array of Base Image VMs. You must specify only a single Base Image VM.' + Break + } + } + $BaseImageSnapshotList = $services.BaseImageSnapshot.BaseImageSnapshot_List($BaseImageVMObj.Id) + } + + } + + end { + + return $BaseImageSnapshotList + + } +} + function Set-HVPoolSpec { param( [Parameter(Mandatory = $true)] @@ -11562,12 +11946,542 @@ function Set-HVInstantCloneMaintenance { [System.gc]::collect() } } + +Function Get-HVApplication { +<# +.Synopsis + Gets the application information. + +.DESCRIPTION + Gets the application information. This will be useful to find out whether the specified application exists or not. If the application name is not specified, this will lists all the applications in the Pod. + +.PARAMETER ApplicationName + Name of the application. + +.PARAMETER HvServer + View API service object of Connect-HVServer cmdlet. + +.PARAMETER FormatList + Displays the list of the available applications in Table Format if this parameter is set to True. + +.EXAMPLE + Get-HVApplication -ApplicationName 'App1' -HvServer $HvServer + Queries and returns 'App1' information. + +.EXAMPLE + Get-HVApplication -HvServer $HvServer -FormatList:$True + Lists all the applications in the Pod. + +.OUTPUTS + Returns the information of the specified application if it specified, else displays all the available applications. + +.NOTES + Author : Samiullasha S + Author email : ssami@vmware.com + Version : 1.2 + + ===Tested Against Environment==== + Horizon View Server Version : 7.8.0 + PowerCLI Version : PowerCLI 11.1 + PowerShell Version : 5.0 +#> + param ( + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [string]$ApplicationName = $Null, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + $HvServer = $Null, + + [Parameter(Mandatory = $False)] + [string]$FormatList = $False + ) + begin { + $services = Get-ViewAPIService -HvServer $HvServer + if ($null -eq $services) { + Write-Error "Could not retrieve View API services from connection object." + break + } + } + process { + if ($ApplicationName) { + $eqFilter = Get-HVQueryFilter 'data.name' -Eq $ApplicationName + $ResourceObjs = Get-HVQueryResult -EntityType ApplicationInfo -Filter $eqFilter -HvServer $HvServer + if(!$ResourceObjs){Write-host "No application found with specified name: $ApplicationName"; return} + Write-host "Application found with specified name: $ApplicationName" + return $ResourceObjs + } + $ResourceObjs = Get-HVQueryResult -EntityType ApplicationInfo -HvServer $HvServer + if ($FormatList -eq $True){ return $ResourceObjs.data | Format-Table -AutoSize} + return $ResourceObjs.data + } + end { + [System.GC]::Collect() + } +} + +Function Remove-HVApplication { +<# +.Synopsis + Removes the specified application if exists. + +.DESCRIPTION + Removes the specified application if exists. + +.PARAMETER ApplicationName + Application to be deleted. + The name of the application must be given that is to be searched for and remove if exists. + +.PARAMETER HvServer + View API service object of Connect-HVServer cmdlet. + +.EXAMPLE + Remove-HVApplication -ApplicationName 'App1' -HvServer $HvServer + Removes 'App1', if exists. + +.OUTPUTS + Removes the specified application if exists. + +.NOTES + Author : Samiullasha S + Author email : ssami@vmware.com + Version : 1.2 + + ===Tested Against Environment==== + Horizon View Server Version : 7.8.0 + PowerCLI Version : PowerCLI 11.1 + PowerShell Version : 5.0 +#> + param ( + [Parameter(Mandatory = $True, ValueFromPipeline = $True)] + [string]$ApplicationName, + + [Parameter(Mandatory = $False)] + $HvServer = $null + ) + begin { + $services = Get-ViewAPIService -HvServer $HvServer + if ($null -eq $services) { + Write-Error "Could not retrieve View API services from connection object" + break + } + } + process { + $App= Get-HVApplication -ApplicationName $ApplicationName -HvServer $HvServer + if (!$App) { + Write-Host "Application '$ApplicationName' not found. $_" + return + } + $AppService= New-Object VMware.Hv.ApplicationService + $AppService.Application_Delete($services,$App.Id) + if ($?) { + Write-Host "'$ApplicationName' has been successfully removed." + } + } + end { + [System.GC]::Collect() + } +} + +Function New-HVManualApplication { +<# +.Synopsis + Creates a Manual Application. + +.DESCRIPTION + Creates Application manually with given parameters. + +.PARAMETER HvServer + View API service object of Connect-HVServer cmdlet. + +.PARAMETER Name + The Application name is the unique identifier used to identify this Application. + +.PARAMETER DisplayName + The display name is the name that users will see when they connect to view client. If the display name is left blank, it defaults to Name. + +.PARAMETER Description + The description is a set of notes about the Application. + +.PARAMETER ExecutablePath + Path to Application executable. + +.PARAMETER Version + Application version. + +.PARAMETER Publisher + Application publisher. + +.PARAMETER Enabled + Indicates if Application is enabled. + +.PARAMETER EnablePreLaunch + Application can be pre-launched if value is true. + +.PARAMETER ConnectionServerRestrictions + Connection server restrictions. This is a list of tags that access to the application is restricted to. Empty/Null list means that the application can be accessed from any connection server. + +.PARAMETER CategoryFolderName + Name of the category folder in the user's OS containing a shortcut to the application. Unset if the application does not belong to a category. + +.PARAMETER ClientRestrictions + Client restrictions to be applied to Application. Currently it is valid for RDSH pools. + +.PARAMETER ShortcutLocations + Locations of the category folder in the user's OS containing a shortcut to the desktop. The value must be set if categoryFolderName is provided. + +.PARAMETER MultiSessionMode + Multi-session mode for the application. An application launched in multi-session mode does not support reconnect behavior when user logs in from a different client instance. + +.PARAMETER MaxMultiSessions + Maximum number of multi-sessions a user can have in this application pool. + +.PARAMETER StartFolder + Starting folder for Application. + +.PARAMETER Args + Parameters to pass to application when launching. + +.PARAMETER Farm + Farm name. + +.PARAMETER AutoUpdateFileTypes + Whether or not the file types supported by this application should be allowed to automatically update to reflect changes reported by the agent. + +.PARAMETER AutoUpdateOtherFileTypes + Whether or not the other file types supported by this application should be allowed to automatically update to reflect changes reported by the agent. + +.EXAMPLE + New-HVManualApplication -Name 'App1' -DisplayName 'DisplayName' -Description 'ApplicationDescription' -ExecutablePath "PathOfTheExecutable" -Version 'AppVersion' -Publisher 'PublisherName' -Farm 'FarmName' + Creates a manual application App1 in the farm specified. + +.OUTPUTS + A success message is displayed when done. + +.NOTES + Author : Samiullasha S + Author email : ssami@vmware.com + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.8.0 + PowerCLI Version : PowerCLI 11.1 + PowerShell Version : 5.0 +#> + param ( + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [VMware.VimAutomation.HorizonView.Impl.V1.ViewServerImpl]$HvServer, + + [Parameter(Mandatory = $True, ValueFromPipeline = $True)] + [string][ValidateLength(1,64)]$Name, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [String][ValidateLength(1,256)]$DisplayName = $Name, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [String][ValidateLength(1,1024)]$Description, + + [Parameter(Mandatory = $True, ValueFromPipeline = $True)] + [String]$ExecutablePath, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [String]$Version, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [String]$Publisher, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [Boolean]$Enabled = $True, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [Boolean]$EnablePreLaunch=$False, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [string[]]$ConnectionServerRestrictions, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True, ParameterSetName = 'categoryFolderName')] + [String][ValidateRange(1,64)]$CategoryFolderName, + + #Below Parameter is for Client restrictions to be applied to Application. Currently it is valid for RDSH pools. + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [Boolean]$clientRestrictions = $False, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True, ParameterSetName = 'categoryFolderName')] + [String[]]$ShortcutLocations, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [ValidateSet('DISABLED','ENABLED_DEFAULT_OFF','ENABLED_DEFAULT_ON','ENABLED_ENFORCED')] + [String]$MultiSessionMode = 'DISABLED', + + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [ValidateScript({if(($MultiSessionMode -eq 'ENABLED_DEFAULT_OFF') -or ($MultiSessionMode -eq 'ENABLED_DEFAULT_ON') -or ($MultiSessionMode -eq 'ENABLED_ENFORCED')){$_ -eq 1}})] + [Int]$MaxMultiSessions, + + #Below parameters are for ExecutionData, moved ExecutablePath, Version and Publisher to above from this. + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [String]$StartFolder, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [String]$Args, + + [Parameter(Mandatory = $True, ValueFromPipeline = $True)] + [String]$Farm, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [Boolean]$AutoUpdateFileTypes = $True, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [Boolean]$AutoUpdateOtherFileTypes = $True + ) + begin { + $services = Get-ViewAPIService -HvServer $HvServer + if ($null -eq $services) { + Write-Error "Could not retrieve View API services from connection object" + break + } + $FarmInfo = Get-HVFarm -FarmName $Farm + if ($null -eq $FarmInfo) { + Write-Error "Could not find the specified Farm." + break + } + } + process { + $App = Get-HVApplication -ApplicationName $Name -HvServer $HvServer + if ($App) { + Write-Host "Application already exists with the name : $Name" + return + } + $AppData = New-Object VMware.Hv.ApplicationData -Property @{ 'Name' = $Name; 'DisplayName' = $DisplayName; 'Description' = $Description; 'Enabled' = $Enabled; 'EnableAntiAffinityRules' = $EnableAntiAffinityRules; 'AntiAffinityPatterns' = $AntiAffinityPatterns; 'AntiAffinityCount' = $AntiAffinityCount; 'EnablePreLaunch' = $EnablePreLaunch; 'multiSessionMode' = $MultiSessionMode; 'maxMultiSessions' = $MaxMultiSessions; 'ConnectionServerRestrictions' = $ConnectionServerRestrictions; 'CategoryFolderName' = $CategoryFolderName; 'ClientRestrictions' = $ClientRestrictions; 'ShortcutLocations' = $ShortcutLocations} + $ExecutionData = New-object VMware.Hv.ApplicationExecutionData -Property @{ 'ExecutablePath' = $ExecutablePath; 'Version' = $Version; 'Publisher' = $Publisher; 'StartFolder' = $StartFolder; 'Args' = $Args; 'Farm' = $FarmInfo.id; 'AutoUpdateFileTypes' = $AutoUpdateFileTypes; 'AutoUpdateOtherFileTypes' = $AutoUpdateOtherFileTypes} + $AppSpec = New-Object VMware.Hv.ApplicationSpec -Property @{ 'Data' = $AppData; 'ExecutionData' = $ExecutionData} + $AppService = New-Object VMware.Hv.ApplicationService + $AppService.Application_Create($services,$AppSpec) + if ($?) { + Write-Host "Application '$Name' created successfully" + return + } + Write-Host "Application creation of '$Name' has failed. $_" + } + end { + [System.GC]::Collect() + } +} + +Function Get-HVPreInstalledApplication { +<# +.Synopsis + Gets the list of Pre-installed Applications from the RDS Server(s). + +.DESCRIPTION + Gets the list of Pre-installed Applications from the RDS Server(s). + +.PARAMETER FarmName + Name of the Farm on which to discover installed applications. + +.PARAMETER HvServer + View API service object of Connect-HVServer cmdlet. + +.EXAMPLE + Get-HVPreInstalledApplication -FarmName 'Farm1' -HvServer $HvServer + Gets the list of Applications present in 'Farm1', if exists. + +.OUTPUTS + Gets the list of Applications from the specified Farm if exists. + +.NOTES + Author : Samiullasha S + Author email : ssami@vmware.com + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.8.0 + PowerCLI Version : PowerCLI 11.1 + PowerShell Version : 5.0 +#> + param ( + [Parameter(Mandatory = $True, ValueFromPipeline = $True)] + [String][ValidateLength(1,64)]$FarmName, + + [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 + } + $Farm = Get-HVFarm -FarmName $FarmName + if($null -eq $Farm) { + Write-Error "Could not find the specified Farm." + break + } + } + process { + $FarmService = New-Object VMware.Hv.FarmService + $Data = $FarmService.Farm_DiscoverInstalledApplications($services,$Farm.Id) + return $Data + } + end { + [System.GC]::Collect() + } +} + +Function New-HVPreInstalledApplication { +<# +.Synopsis + Creates a application pool from Pre-installed applications on RDS Server(s). + +.DESCRIPTION + Creates a application pool from Pre-installed applications on RDS Server(s). + +.PARAMETER HvServer + View API service object of Connect-HVServer cmdlet. + +.PARAMETER ApplicationName + The Application name is the unique identifier used to identify this Application. + +.PARAMETER DisplayName + The display name is the name that users will see when they connect to view client. If the display name is left blank, it defaults to Name. + +.PARAMETER FarmName + Farm name. + +.PARAMETER EnablePreLaunch + Application can be pre-launched if value is true. + +.PARAMETER ConnectionServerRestrictions + Connection server restrictions. This is a list of tags that access to the application is restricted to. Empty/Null list means that the application can be accessed from any connection server. + +.PARAMETER CategoryFolderName + Name of the category folder in the user's OS containing a shortcut to the application. Unset if the application does not belong to a category. + +.PARAMETER ClientRestrictions + Client restrictions to be applied to Application. Currently it is valid for RDSH pools. + +.EXAMPLE + New-HVPreInstalledApplication -ApplicationName 'App1' -DisplayName 'DisplayName' -FarmName 'FarmName' + Creates a application App1 from the farm specified. + +.EXAMPLE + New-HVPreInstalledApplication -ApplicationName 'App2' -FarmName FarmManual -EnablePreLaunch $True + Creates a application App2 from the farm specified and the PreLaunch option will be enabled. + +.OUTPUTS + A success message is displayed when done. + +.NOTES + Author : Samiullasha S + Author email : ssami@vmware.com + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.8.0 + PowerCLI Version : PowerCLI 11.1 + PowerShell Version : 5.0 +#> + param ( + [Parameter(Mandatory = $False)] + $HvServer = $null, + + [Parameter(Mandatory = $True, ValueFromPipeline = $True)] + [string][ValidateLength(1,64)]$ApplicationName, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [String][ValidateLength(1,256)]$DisplayName = $ApplicationName, + + [Parameter(Mandatory = $True, ValueFromPipeline = $True)] + [String][ValidateLength(1,64)]$FarmName, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [Boolean]$EnablePreLaunch=$False, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [string[]]$ConnectionServerRestrictions, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True,ParameterSetName = 'categoryFolderName')] + [String][ValidateRange(1,64)]$CategoryFolderName, + + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] + [Boolean]$clientRestrictions = $False + ) + begin { + $services = Get-ViewAPIService -HvServer $HvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + $FarmInfo = Get-HVFarm -FarmName $FarmName + if($null -eq $FarmInfo) { + Write-Error "Could not find the specified Farm $FarmName." + break + } + } + process { + #Validate the Application name uniqueness with existing applications. + $ResourceObjs = Get-HVApplication -HvServer $HvServer + foreach($App in ($ResourceObjs.name)) { + if($App -eq $ApplicationName) { + Write-Host "$ApplicationName already exists in the Application Pool." + return + } + } + #Validate the application name uniqueness with Desktops. + $DesktopSummary = Get-HVQueryResult -EntityType DesktopSummaryView -HvServer $hvserver + foreach($App in $DesktopSummary) { + if($App.DesktopSummaryData.Name -eq $ApplicationName) { + Write-Host "$ApplicationName already exists in the Desktop Pool." + return + } + } + #get all the applications installed in RDS Server(s). + $AppsInRDS = Get-HVPreinstalledApplication -FarmName $FarmName + $AppFoundInRDS = $False + foreach($App in ($AppsInRDS)) { + if($($App.name) -eq ($ApplicationName)) { + $AppFoundInRDS = $True + $ApplicationID = $ApplicationName -replace " ","_" + $ApplicationData = New-Object VMware.Hv.ApplicationData -Property @{ 'Name' = $ApplicationID; + 'DisplayName' = $DisplayName; + 'EnablePreLaunch' = $EnablePreLaunch; + 'ConnectionServerRestrictions' = $ConnectionServerRestrictions; + 'CategoryFolderName' = $CategoryFolderName; + 'ClientRestrictions' = $ClientRestrictions } + $ExecutionData = New-object VMware.Hv.ApplicationExecutionData -Property @{ 'ExecutablePath' = $App.ExecutionData.ExecutablePath; + 'Version' = $App.ExecutionData.Version; + 'Publisher' = $App.ExecutionData.Publisher; + 'Args' = $App.ExecutionData.Args; + 'StartFolder' = $App.ExecutionData.StartFolder; + 'Farm' = $FarmInfo.Id; + 'AutoUpdateFileTypes' = $App.ExecutionData.AutoUpdateFileTypes; + 'AutoUpdateOtherFileTypes' = $App.executionData.AutoUpdateOtherFileTypes } + $ApplicationSpec = New-Object VMware.Hv.ApplicationSpec -Property @{ 'Data' = $ApplicationData; 'ExecutionData' = $ExecutionData} + $AppService = New-Object VMware.Hv.ApplicationService + $AppService.Application_Create($services,$ApplicationSpec) + if($?) { + Write-Host "Application '$ApplicationName' created successfully" + return + } + Write-Host "Failed to create Application '$ApplicationName'. $_ " + return + } + } + if ($AppFoundInRDS -eq $False) { + Write-Host ""$ApplicationName" does not exist in any of the RDS Server(s) belongs to the Farm $FarmName." + } + } + end { + [System.GC]::Collect() + } +} + # 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 +# Application Pool related +Export-ModuleMember -Function Get-HVApplication, Remove-HVApplication, New-HVManualApplication, Get-HVPreInstalledApplication, New-HVPreInstalledApplication # Entitlement related Export-ModuleMember -Function New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement Export-ModuleMember -Function Set-HVMachine, Reset-HVMachine, Remove-HVMachine @@ -11579,5 +12493,7 @@ Export-ModuleMember -Function Get-HVGlobalSettings, Set-HVApplicationIcon, Remov 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 +# vCenter Server related +Export-ModuleMember -Function Get-HVvCenterServer, Get-HVvCenterServerHealth # 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, Get-HVBaseImageVM, Get-HVBaseImageVMSnapshot diff --git a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psd1 b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psd1 index b74bad7..1b97cd3 100644 --- a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psd1 +++ b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psd1 @@ -36,7 +36,13 @@ 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', 'Get-NSXTRouteTable', 'Get-NSXTOverviewInfo' +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', 'Get-NSXTInfraScope', 'Get-NSXTInfraGroup', 'New-NSXTRouteBasedVPN', ` +'Get-NSXTRouteBasedVPN', 'Remove-NSXTRouteBasedVPN', 'Remove-NSXTService', 'New-NSXTDistFirewallSection', 'Get-NSXTDistFirewallSection', ` +'New-NSXTPolicyBasedVPN', 'Get-NSXTPolicyBasedVPN', 'Remove-NSXTPolicyBasedVPN', 'Get-NSXTDNS', 'Set-NSXTDNS' # 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 d120086..5004034 100644 --- a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 +++ b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 @@ -152,6 +152,8 @@ Function New-NSXTSegment { This cmdlet creates a new NSX-T Segment (Logical Networks) .EXAMPLE New-NSXTSegment -Name "sddc-cgw-network-4" -Gateway "192.168.4.1/24" -DHCP -DHCPRange "192.168.4.2-192.168.4.254" + .EXAMPLE + New-NSXTSegment -Name "sddc-cgw-network-5" -Gateway "192.168.5.1/24" #> Param ( [Parameter(Mandatory=$True)]$Name, @@ -163,14 +165,14 @@ Function New-NSXTSegment { If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { if($DHCP) { - $dhcpConf = @($DHCPRange) + $subnets = @{ + gateway_address = $gateway; + dhcp_ranges = @($DHCPRange) + } } else { - $dhcpConf = @($null) - } - - $subnets = @{ - gateway_address = $gateway; - dhcp_ranges = $dhcpConf; + $subnets = @{ + gateway_address = $gateway; + } } $payload = @{ @@ -205,7 +207,7 @@ Function New-NSXTSegment { } if($requests.StatusCode -eq 200) { - Write-Host "Succesfully created new NSX-T Segment $Name" + Write-Host "Successfully created new NSX-T Segment $Name" ($requests.Content | ConvertFrom-Json) | select display_name, id } } @@ -260,7 +262,7 @@ Function Remove-NSXTSegment { } if($requests.StatusCode -eq 200) { - Write-Host "Succesfully removed NSX-T Segment $Name" + Write-Host "Successfully removed NSX-T Segment $Name" } } } @@ -403,6 +405,27 @@ Function Get-NSXTFirewall { } } + $scopeEntries = $rule.scope + $scopes = @() + foreach ($scopeEntry in $scopeEntries) { + $scopeLabelURL = $global:nsxtProxyConnection.Server + "/policy/api/v1" + $scopeEntry + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$scopeLabelURL`n" + } + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $scopeLabelURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $scopeLabelURL -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 + } + $scope = ($requests.Content | ConvertFrom-Json) + $scopes += $scope.display_name + } + $tmp = [pscustomobject] @{ SequenceNumber = $rule.sequence_number; Name = $rule.display_name; @@ -410,6 +433,7 @@ Function Get-NSXTFirewall { Source = $source; Destination = $destination; Services = $service; + Scope = $scopes; Action = $rule.action; } $results+=$tmp @@ -442,10 +466,13 @@ Function New-NSXTFirewall { [Parameter(Mandatory=$True)]$Name, [Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType, [Parameter(Mandatory=$True)]$SequenceNumber, - [Parameter(Mandatory=$True)]$SourceGroup, - [Parameter(Mandatory=$True)]$DestinationGroup, + [Parameter(Mandatory=$False)]$SourceGroup, + [Parameter(Mandatory=$False)]$DestinationGroup, [Parameter(Mandatory=$True)]$Service, [Parameter(Mandatory=$True)][ValidateSet("ALLOW","DENY")]$Action, + [Parameter(Mandatory=$false)]$InfraScope, + [Parameter(Mandatory=$false)]$SourceInfraGroup, + [Parameter(Mandatory=$false)]$DestinationInfraGroup, [Parameter(Mandatory=$false)][Boolean]$Logged=$false, [Switch]$Troubleshoot ) @@ -464,6 +491,13 @@ Function New-NSXTFirewall { } } + if($DestinationInfraGroup) { + foreach ($group in $DestinationInfraGroup) { + $tmp = (Get-NSXTInfraGroup -Name $group).Path + $destinationGroups+= $tmp + } + } + $sourceGroups = @() foreach ($group in $SourceGroup) { if($group -eq "ANY") { @@ -474,16 +508,37 @@ Function New-NSXTFirewall { } } + if($SourceInfraGroup) { + foreach ($group in $SourceInfraGroup) { + $tmp = (Get-NSXTInfraGroup -Name $group).Path + $sourceGroups+= $tmp + } + } + $services = @() foreach ($serviceName in $Service) { if($serviceName -eq "ANY") { $services = @("ANY") } else { - $tmp = "/infra/services/$serviceName" + $tmp = (Get-NSXTService -Name "$serviceName").Path $services+=$tmp } } + $scopeLabels = @() + if(!$InfraScope) { + if($GatewayType.toLower() -eq "cgw") { + $scopeLabels = @("/infra/labels/$($GatewayType.toLower())-all") + } else { + $scopeLabels = @("/infra/labels/$($GatewayType.toLower())") + } + } else { + foreach ($infraScopeName in $InfraScope) { + $scope = Get-NSXTInfraScope -Name $infraScopeName + $scopeLabels += $scope.Path + } + } + $payload = @{ display_name = $Name; resource_type = "CommunicationEntry"; @@ -491,7 +546,7 @@ Function New-NSXTFirewall { destination_groups = $destinationGroups; source_groups = $sourceGroups; logged = $Logged; - scope = @("/infra/labels/$($GatewayType.toLower())"); + scope = $scopeLabels; services = $services; action = $Action; } @@ -524,7 +579,7 @@ Function New-NSXTFirewall { } if($requests.StatusCode -eq 200) { - Write-Host "Succesfully created new NSX-T Firewall Rule $Name" + Write-Host "Successfully created new NSX-T Firewall Rule $Name" ($requests.Content | ConvertFrom-Json) | select display_name, id } } @@ -580,7 +635,7 @@ Function Remove-NSXTFirewall { } if($requests.StatusCode -eq 200) { - Write-Host "Succesfully removed NSX-T Firewall Rule" + Write-Host "Successfully removed NSX-T Firewall Rule" } } } @@ -738,7 +793,7 @@ Function New-NSXTGroup { } if($requests.StatusCode -eq 200) { - Write-Host "Succesfully created new NSX-T Group $Name" + Write-Host "Successfully created new NSX-T Group $Name" ($requests.Content | ConvertFrom-Json) | select display_name, id } } @@ -794,7 +849,7 @@ Function Remove-NSXTGroup { } if($requests.StatusCode -eq 200) { - Write-Host "Succesfully removed NSX-T Group $Name" + Write-Host "Successfully removed NSX-T Group $Name" } } } @@ -869,6 +924,7 @@ Function Get-NSXTService { Protocol = $serviceProtocol; Source = $serviceSourcePorts; Destination = $serviceDestinationPorts; + Path = $service.path; } $results += $tmp } @@ -877,6 +933,60 @@ Function Get-NSXTService { } } +Function Remove-NSXTService { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 04/10/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Removes an NSX-T Service + .DESCRIPTION + This cmdlet removes an NSX-T Service + .EXAMPLE + Remove-NSXTService -Id VMware-Blast -Troubleshoot +#> + Param ( + [Parameter(Mandatory=$True)]$Id, + [Switch]$Troubleshoot + ) + + If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { + $method = "DELETE" + $deleteServiceURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/services/$Id" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$deleteServiceURL`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $deleteServiceURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $deleteServiceURL -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 removing NSX-T Service" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + Write-Host "Successfully removed NSX-T Service $Id" + } + } +} + Function New-NSXTService { <# .NOTES @@ -944,7 +1054,72 @@ Function New-NSXTService { } if($requests.StatusCode -eq 200) { - Write-Host "Succesfully created new NSX-T Service $Name" + Write-Host "Successfully created new NSX-T Service $Name" + ($requests.Content | ConvertFrom-Json) | select display_name, id + } + } +} + +Function New-NSXTDistFirewallSection { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 04/19/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Creates new NSX-T Distributed Firewall Section + .DESCRIPTION + This cmdlet to create new NSX-T Distributed Firewall Section + .EXAMPLE + Get-NSXTDistFirewallSection -Name "App Section 1" -Category Application +#> + 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 { + $payload = @{ + display_name = $Name; + category = $Category; + resource_type = "CommunicationMap"; + } + + $body = $payload | ConvertTo-Json -depth 5 + + $method = "PUT" + $generatedId = (New-Guid).Guid + $distFirewallSectionURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/cgw/communication-maps/$generatedId" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$distFirewallSectionURL`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $distFirewallSectionURL -Method $method -Body $body -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $distFirewallSectionURL -Method $method -Body $body -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 NSX-T Distributed Firewall Section" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + Write-Host "Successfully created new NSX-T Distributed Firewall Section $Section" ($requests.Content | ConvertFrom-Json) | select display_name, id } } @@ -955,76 +1130,111 @@ Function Get-NSXTDistFirewallSection { .NOTES =========================================================================== Created by: William Lam - Date: 01/01/2019 + Date: 04/19/2019 Organization: VMware Blog: http://www.virtuallyghetto.com Twitter: @lamw =========================================================================== .SYNOPSIS - Returns all NSX-T Distributed Firewall Groups + Returns all NSX-T Distributed Firewall Sections .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" + $distFirewallSectionURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/cgw/communication-maps" if($Troubleshoot) { - Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$distFirewallGroupURL`n" + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$distFirewallSectionURL`n" } try { if($PSVersionTable.PSEdition -eq "Core") { - $requests = Invoke-WebRequest -Uri $distFirewallGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + $requests = Invoke-WebRequest -Uri $distFirewallSectionURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck } else { - $requests = Invoke-WebRequest -Uri $distFirewallGroupURL -Method $method -Headers $global:nsxtProxyConnection.headers + $requests = Invoke-WebRequest -Uri $distFirdistFirewallSectionURLwallURL -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 Distributed Firewall Sections" + Write-Error "Error in retrieving NSX-T Distributed Firewall Section" Write-Error "`n($_.Exception.Message)`n" break } } if($requests.StatusCode -eq 200) { - $groups = ($requests.Content | ConvertFrom-Json).results + $sections = ($requests.Content | ConvertFrom-Json).results if ($PSBoundParameters.ContainsKey("Name")){ - $groups = $groups | where {$_.display_name -eq $Name} + $sections = $sections | where {$_.display_name -eq $Name} } - if ($PSBoundParameters.ContainsKey("Category")){ - $groups = $groups | where {$_.category -eq $Category} - } + $sections | Sort-Object -Propert display_name | select display_name, id + } + } +} - $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 +Function Remove-NSXTDistFirewallSection { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 04/20/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Removes an NSX-T Distributed Firewall Section + .DESCRIPTION + This cmdlet removes an NSX-T Distributed Firewall Section + .EXAMPLE + Remove-NSXTDistFirewallSection -Id -Troubleshoot +#> + Param ( + [Parameter(Mandatory=$True)]$Id, + [Switch]$Troubleshoot + ) + + If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { + $method = "DELETE" + $deleteDistFirewallSectioneURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/cgw/communication-maps/$Id" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$deleteDistFirewallSectioneURL`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $deleteDistFirewallSectioneURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $deleteDistFirewallSectioneURL -Method $method -Headers $global:nsxtProxyConnection.headers } - $results + } 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 removing NSX-T Distributed Firewall Section" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + Write-Host "Successfully removed NSX-T Distributed Firewall Section $Id" } } } @@ -1220,7 +1430,7 @@ Function New-NSXTDistFirewall { [Parameter(Mandatory=$True)]$SourceGroup, [Parameter(Mandatory=$True)]$DestinationGroup, [Parameter(Mandatory=$True)]$Service, - [Parameter(Mandatory=$True)][ValidateSet("ALLOW","DENY")]$Action, + [Parameter(Mandatory=$True)][ValidateSet("ALLOW","DROP")]$Action, [Parameter(Mandatory=$false)][Boolean]$Logged=$false, [Switch]$Troubleshoot ) @@ -1274,7 +1484,7 @@ Function New-NSXTDistFirewall { $method = "PUT" $generatedId = (New-Guid).Guid - $newDistFirewallURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/domains/cgw/communication-maps/$sectionId/communication-entries/$generatedId" + $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" @@ -1299,7 +1509,7 @@ Function New-NSXTDistFirewall { } if($requests.StatusCode -eq 200) { - Write-Host "Succesfully created new NSX-T Distributed Firewall Rule $Name" + Write-Host "Successfully created new NSX-T Distributed Firewall Rule $Name" ($requests.Content | ConvertFrom-Json) | select display_name, id } } @@ -1358,7 +1568,7 @@ Function Remove-NSXTDistFirewall { } if($requests.StatusCode -eq 200) { - Write-Host "Succesfully removed NSX-T Distributed Firewall Rule" + Write-Host "Successfully removed NSX-T Distributed Firewall Rule" } } } @@ -1424,7 +1634,7 @@ Function Get-NSXTRouteTable { } if($requests.StatusCode -eq 200) { - Write-Host "Succesfully retrieved NSX-T Routing Table`n" + Write-Host "Successfully retrieved NSX-T Routing Table`n" $routeTables = ($requests.Content | ConvertFrom-Json).results foreach ($routeTable in $routeTables) { @@ -1491,8 +1701,905 @@ If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection f } if($requests.StatusCode -eq 200) { - Write-Host "Succesfully retrieved NSX-T Overview Information" + Write-Host "Successfully retrieved NSX-T Overview Information" ($requests.Content | ConvertFrom-Json) } } +} + +Function Get-NSXTInfraScope { + <# + .NOTES + =========================================================================== + Created by: William Lam + Date: 03/14/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Returns all NSX-T Infrastructure Scopes + .DESCRIPTION + This cmdlet retrieves all NSX-T Infrastructure Scopes + .EXAMPLE + Get-NSXTInfraScope + .EXAMPLE + Get-NSXTInfraGroup -Name "VPN Tunnel Interface" + #> + param( + [Parameter(Mandatory=$false)][String]$Name, + [Switch]$Troubleshoot + ) + + If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { + $method = "GET" + $infraLabelURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/labels" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$infraLabelURL`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $infraLabelURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $infraLabelURL -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 Infrastructure Scopes" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + $infraLables = ($requests.Content | ConvertFrom-Json).results + + if ($PSBoundParameters.ContainsKey("Name")){ + $infraLables = $infraLables | where {$_.display_name -eq $Name} + } + + $results = @() + foreach ($infraLabel in $infraLables) { + $tmp = [pscustomobject] @{ + Name = $infraLabel.display_name; + Id = $infraLabel.Id; + Path = $infraLabel.Path; + } + $results+=$tmp + } + $results + } + } +} + +Function Get-NSXTInfraGroup { + <# + .NOTES + =========================================================================== + Created by: William Lam + Date: 03/14/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Returns all NSX-T Infrastructure Groups for CGW + .DESCRIPTION + This cmdlet retrieves all NSX-T Infrastructure Groups for CGW + .EXAMPLE + Get-NSXTInfraGroup + .EXAMPLE + Get-NSXTInfraGroup -Name "S3 Prefixes" + #> + param( + [Parameter(Mandatory=$false)][String]$Name, + [Switch]$Troubleshoot + ) + + If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { + $method = "GET" + $infraGroupsURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/tier-0s/vmc/groups" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$infraGroupsURL`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $infraGroupsURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $infraGroupsURL -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 Infrastructure Groups" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + $groups = ($requests.Content | ConvertFrom-Json).results + + if ($PSBoundParameters.ContainsKey("Name")){ + $groups = $groups | where {$_.display_name -eq $Name} + } + + $results = @() + foreach ($group in $groups) { + $tmp = [pscustomobject] @{ + Name = $group.display_name; + ID = $group.id; + Path = $group.path; + } + $results+=$tmp + } + $results + } + } +} + +Function New-NSXTRouteBasedVPN { + <# + .NOTES + =========================================================================== + Created by: William Lam + Date: 04/13/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Returns all NSX-T Infrastructure Scopes + .DESCRIPTION + This cmdlet retrieves all NSX-T Infrastructure Scopes + .EXAMPLE + New-NSXTRouteBasedVPN -Name VPN3 ` + -PublicIP 18.184.241.223 ` + -RemotePublicIP 18.194.148.62 ` + -BGPLocalIP 169.254.51.2 ` + -BGPRemoteIP 169.254.51.1 ` + -BGPLocalASN 65056 ` + -BGPremoteASN 64512 ` + -BGPNeighborID 60 ` + -TunnelEncryption AES_256 ` + -TunnelDigestEncryption SHA2_256 ` + -IKEEncryption AES_256 ` + -IKEDigestEncryption SHA2_256 ` + -DHGroup GROUP14 ` + -IKEVersion IKE_V1 ` + -PresharedPassword VMware123. ` + -Troubleshoot + #> + param( + [Parameter(Mandatory=$true)][String]$Name, + [Parameter(Mandatory=$true)][String]$PublicIP, + [Parameter(Mandatory=$true)][String]$RemotePublicIP, + [Parameter(Mandatory=$true)][String]$BGPLocalIP, + [Parameter(Mandatory=$true)][String]$BGPRemoteIP, + [Parameter(Mandatory=$false)][int]$BGPLocalPrefix=30, + [Parameter(Mandatory=$true)][ValidateRange(64512,65534)][int]$BGPLocalASN, + [Parameter(Mandatory=$true)][ValidateRange(64512,65534)][int]$RemoteBGPASN, + [Parameter(Mandatory=$true)][String]$BGPNeighborID, + [Parameter(Mandatory=$true)][String][ValidateSet("AES_128","AES_256","AES_GCM_128","AES_GCM_192","AES_GCM_256")]$TunnelEncryption, + [Parameter(Mandatory=$true)][String][ValidateSet("SHA1","SHA2_256")]$TunnelDigestEncryption, + [Parameter(Mandatory=$true)][String][ValidateSet("AES_128","AES_256","AES_GCM_128","AES_GCM_192","AES_GCM_256")]$IKEEncryption, + [Parameter(Mandatory=$true)][String][ValidateSet("SHA1","SHA2_256")]$IKEDigestEncryption, + [Parameter(Mandatory=$true)][String][ValidateSet("GROUP2","GROUP5","GROUP14","GROUP15","GROUP16")]$DHGroup, + [Parameter(Mandatory=$true)][String][ValidateSet("IKE_V1","IKE_V2","IKE_FLEX")]$IKEVersion, + [Parameter(Mandatory=$true)][String]$PresharedPassword, + [Switch]$Troubleshoot + ) + + If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { + + ## Configure BGP ASN + + $payload = @{ + local_as_num = $BGPLocalASN; + } + $body = $payload | ConvertTo-Json -Depth 5 + + $ASNmethod = "patch" + $bgpAsnURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/tier-0s/vmc/locale-services/default/bgp" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $ASNmethod`n$bgpAsnURL`n" + Write-Host -ForegroundColor cyan "[DEBUG]`n$body`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $bgpAsnURL -Body $body -Method $ASNmethod -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $bgpAsnURL -Body $body -Method $ASNmethod -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 updating BGP ASN" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + ## Configure BGP Neighbor + + $payload = @{ + resource_type = "BgpNeighborConfig"; + id = $BGPNeighborID; + remote_as_num = $RemoteBGPASN; + neighbor_address = $BGPRemoteIP; + } + $body = $payload | ConvertTo-Json -Depth 5 + + $method = "put" + $bgpNeighborURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/tier-0s/vmc/locale-services/default/bgp/neighbors/$BGPNeighborID" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$bgpNeighborURL`n" + Write-Host -ForegroundColor cyan "[DEBUG]`n$body`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $bgpNeighborURL -Body $body -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $bgpNeighborURL -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 configuring BGP Neighbor" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + ## Configure Route Based Policy VPN + + $TunnelSubnets = @{ + ip_addresses = @("$BGPLocalIP"); + prefix_length = $BGPLocalPrefix; + } + + $payload = @{ + display_name = $Name; + enabled = $true; + local_address = $PublicIP; + remote_private_address = $RemotePublicIP; + remote_public_address = $RemotePublicIP; + passphrases = @("$PresharedPassword"); + tunnel_digest_algorithms = @("$TunnelDigestEncryption"); + ike_digest_algorithms = @("$IKEDigestEncryption"); + ike_encryption_algorithms = @("$IKEEncryption"); + enable_perfect_forward_secrecy = $true; + dh_groups = @("$DHGroup"); + ike_version = $IKEVersion; + l3vpn_session = @{ + resource_type = "RouteBasedL3VpnSession"; + tunnel_subnets = @($TunnelSubnets); + default_rule_logging = $false; + force_whitelisting = $false; + routing_config_path = "/infra/tier-0s/vmc/locale-services/default/bgp/neighbors/$BGPNeighborID"; + }; + tunnel_encryption_algorithms = @("$TunnelEncryption"); + } + $body = $payload | ConvertTo-Json -Depth 5 + + $routeBasedVPNURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/tier-0s/vmc/locale-services/default/l3vpns/$Name" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$bgpNeighborURL`n" + Write-Host -ForegroundColor cyan "[DEBUG]`n$body`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $routeBasedVPNURL -Body $body -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $routeBasedVPNURL -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 configuring Route Based VPN" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + Write-Host "Successfully created Route Based VPN" + ($requests.Content | ConvertFrom-Json) + } + } + } + } +} + +Function Get-NSXTRouteBasedVPN { + <# + .NOTES + =========================================================================== + Created by: William Lam + Date: 04/13/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Returns all NSX-T Route Based VPN Tunnels + .DESCRIPTION + This cmdlet retrieves all NSX-T Route Based VPN Tunnels description + .EXAMPLE + Get-NSXTRouteBasedVPN + .EXAMPLE + Get-NSXTRouteBasedVPN -Name "VPN-T1" + #> + param( + [Parameter(Mandatory=$false)][String]$Name, + [Switch]$Troubleshoot + ) + + If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { + $method = "GET" + $routeBaseVPNURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/tier-0s/vmc/locale-services/default/l3vpns" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$routeBaseVPNURL`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $routeBaseVPNURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $routeBaseVPNURL -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 Route Based VPN Tunnels" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + $groups = ($requests.Content | ConvertFrom-Json).results + if ($PSBoundParameters.ContainsKey("Name")){ + $groups = $groups | where {$_.display_name -eq $Name} + } + + $results = @() + foreach ($group in $groups) { + if($group.l3vpn_session.resource_type -eq "RouteBasedL3VpnSession") { + $tmp = [pscustomobject] @{ + Name = $group.display_name; + ID = $group.id; + Path = $group.path; + Routing_Config_Path = $group.l3vpn_session.routing_config_path; + Local_IP = $group.local_address; + Remote_Public_IP = $group.remote_public_address; + Tunnel_IP_Address = $group.l3vpn_session.tunnel_subnets.ip_addresses + IKE_Version = $group.ike_version; + IKE_Encryption = $group.ike_encryption_algorithms; + IKE_Digest = $group.ike_digest_algorithms; + Tunnel_Encryption = $group.tunnel_encryption_algorithms; + Tunnel_Digest = $group.tunnel_digest_algorithms; + DH_Group = $group.dh_groups; + Created_by = $group._create_user; + Last_Modified_by = $group._last_modified_user; + } + $results+=$tmp + } + } + $results + } + } +} + +Function Remove-NSXTRouteBasedVPN { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 04/13/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Removes a route based VPN Tunnel and it's associated BGP neighbor + .DESCRIPTION + This cmdlet removes a route based VPN Tunnel and it's associated BGP neighbor + .EXAMPLE + Remove-NSXTRouteBasedVPN -Name VPN1 -Troubleshoot +#> + Param ( + [Parameter(Mandatory=$True)]$Name, + [Switch]$Troubleshoot + ) + + If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { + $TunnelId = (Get-NSXTRouteBasedVPN -Name $Name).ID + $path = (Get-NSXTRouteBasedVPN -Name $Name).RoutingConfigPath + + # Delete IPSEC tunnel + $method = "DELETE" + $deleteVPNtunnelURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/tier-0s/vmc/locale-services/default/l3vpns/$TunnelId" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$deleteVPNtunnelURL`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $deleteVPNtunnelURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $deleteVPNtunnelURL -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 removing NSX-T IPSEC Tunnel: $Name" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + Write-Host "Successfully removed NSX-T IPSEC Tunnel: $Name" + } + + # Delete BGP Neighbor + $method = "DELETE" + $deleteBGPnbURL = $global:nsxtProxyConnection.Server + "/policy/api/v1$path" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$deleteBGPnbURL`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $deleteBGPnbURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $deleteBGPnbURL -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 removing NSX-T BGP Neighbor" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + Write-Host "Successfully removed NSX-T BGP Neighbor" + } + } +} + +Function New-NSXTPolicyBasedVPN { +<# +.NOTES +=========================================================================== +Created by: William Lam +Date: 05/09/2019 +Organization: VMware +Blog: http://www.virtuallyghetto.com +Twitter: @lamw +=========================================================================== + +.SYNOPSIS + Creates a new NSX-T Policy Based VPN +.DESCRIPTION + This cmdlet creates a new NSX-T Policy Based VPN +.EXAMPLE + New-NSXTPolicyBasedVPN -Name Policy1 ` + -LocalIP 18.194.102.229 ` + -RemotePublicIP 3.122.124.16 ` + -RemotePrivateIP 169.254.90.1 ` + -SequenceNumber 0 ` + -SourceIPs @("192.168.4.0/24", "192.168.5.0/24") ` + -DestinationIPs @("172.204.10.0/24", "172.204.20.0/24") ` + -TunnelEncryption AES_256 ` + -TunnelDigestEncryption SHA2_256 ` + -IKEEncryption AES_256 ` + -IKEDigestEncryption SHA2_256 ` + -DHGroup GROUP14 ` + -IKEVersion IKE_V1 ` + -PresharedPassword VMware123. ` + -Troubleshoot +#> + param( + [Parameter(Mandatory=$true)][String]$Name, + [Parameter(Mandatory=$true)][String]$LocalIP, + [Parameter(Mandatory=$true)][String]$RemotePublicIP, + [Parameter(Mandatory=$true)][String]$RemotePrivateIP, + [Parameter(Mandatory=$True)]$SequenceNumber, + [Parameter(Mandatory=$true)][String[]]$SourceIPs, + [Parameter(Mandatory=$true)][String[]]$DestinationIPs, + [Parameter(Mandatory=$true)][String][ValidateSet("AES_128","AES_256","AES_GCM_128","AES_GCM_192","AES_GCM_256")]$TunnelEncryption, + [Parameter(Mandatory=$true)][String][ValidateSet("SHA1","SHA2_256")]$TunnelDigestEncryption, + [Parameter(Mandatory=$true)][String][ValidateSet("AES_128","AES_256","AES_GCM_128","AES_GCM_192","AES_GCM_256")]$IKEEncryption, + [Parameter(Mandatory=$true)][String][ValidateSet("SHA1","SHA2_256")]$IKEDigestEncryption, + [Parameter(Mandatory=$true)][String][ValidateSet("GROUP2","GROUP5","GROUP14","GROUP15","GROUP16")]$DHGroup, + [Parameter(Mandatory=$true)][String][ValidateSet("IKE_V1","IKE_V2","IKE_FLEX")]$IKEVersion, + [Parameter(Mandatory=$true)][String]$PresharedPassword, + [Switch]$Troubleshoot + ) + + If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { + + $generatedId = (New-Guid).Guid + + $sources = @() + foreach ($source in $SourceIPs) { + $tmp = @{ subnet = $source} + $sources+=$tmp + } + + $destinations = @() + foreach ($destination in $DestinationIPs) { + $tmp = @{ subnet = $destination} + $destinations+=$tmp + } + + $payload = @{ + display_name = $Name; + enabled = $true; + local_address = $LocalIP; + remote_private_address = $RemotePrivateIP; + remote_public_address = $RemotePublicIP; + passphrases = @("$PresharedPassword"); + tunnel_digest_algorithms = @("$TunnelDigestEncryption"); + tunnel_encryption_algorithms = @("$TunnelEncryption"); + ike_digest_algorithms = @("$IKEDigestEncryption"); + ike_encryption_algorithms = @("$IKEEncryption"); + enable_perfect_forward_secrecy = $true; + dh_groups = @("$DHGroup"); + ike_version = $IKEVersion; + + l3vpn_session = @{ + resource_type = "PolicyBasedL3VpnSession"; + rules = @( + @{ + id = $generatedId; + display_name = $generatedId; + sequence_number = $SequenceNumber; + sources = @($sources) + destinations = @($destinations) + } + ) + } + } + $body = $payload | ConvertTo-Json -Depth 5 + + $method = "put" + $policyBasedVPNURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/tier-0s/vmc/locale-services/default/l3vpns/$Name" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $METHOD`n$policyBasedVPNURL`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $policyBasedVPNURL -Body $body -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $policyBasedVPNURL -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 configuring Policy Based VPN" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + Write-Host "Successfully created Policy Based VPN" + ($requests.Content | ConvertFrom-Json) + } + } +} + +Function Get-NSXTPolicyBasedVPN { +<# +.NOTES +=========================================================================== +Created by: William Lam +Date: 05/09/2019 +Organization: VMware +Blog: http://www.virtuallyghetto.com +Twitter: @lamw +=========================================================================== + +.SYNOPSIS + Returns all NSX-T Policy Based VPN Tunnels +.DESCRIPTION + This cmdlet retrieves all NSX-T Policy Based VPN Tunnels description +.EXAMPLE + Get-NSXTPolicyBasedVPN +.EXAMPLE + Get-NSXTPolicyBasedVPN -Name "VPN-T1" +#> + param( + [Parameter(Mandatory=$false)][String]$Name, + [Switch]$Troubleshoot + ) + + If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { + $method = "GET" + $policyBaseVPNURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/tier-0s/vmc/locale-services/default/l3vpns" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$routeBaseVPNURL`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $policyBaseVPNURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $policyBaseVPNURL -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 Policy Based VPN Tunnels" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + $groups = ($requests.Content | ConvertFrom-Json).results + if ($PSBoundParameters.ContainsKey("Name")){ + $groups = $groups | where {$_.display_name -eq $Name} + } + + $results = @() + foreach ($group in $groups) { + if($group.l3vpn_session.resource_type -eq "PolicyBasedL3VpnSession") { + $tmp = [pscustomobject] @{ + Name = $group.display_name; + ID = $group.id; + Path = $group.path; + Local_IP = $group.local_address; + Remote_Public_IP = $group.remote_public_address; + Tunnel_IP_Address = $group.remote_private_address; + IKE_Version = $group.ike_version; + IKE_Encryption = $group.ike_encryption_algorithms; + IKE_Digest = $group.ike_digest_algorithms; + Tunnel_Encryption = $group.tunnel_encryption_algorithms; + Tunnel_Digest = $group.tunnel_digest_algorithms; + DH_Group = $group.dh_groups; + IP_Sources = $group.l3vpn_session.rules.sources.subnet; + IP_Destinations = $group.l3vpn_session.rules.destinations.subnet + Created_by = $group._create_user; + Last_Modified_by = $group._last_modified_user; + } + $results+=$tmp + } + } + $results + } + } +} + +Function Remove-NSXTPolicyBasedVPN { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 05/09/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Removes a policy based VPN Tunnel + .DESCRIPTION + This cmdlet removes a policy based VPN Tunnel + .EXAMPLE + Remove-NSXTPolicyBasedVPN -Name "Policy1" -Troubleshoot +#> + Param ( + [Parameter(Mandatory=$True)]$Name, + [Switch]$Troubleshoot + ) + + If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { + $TunnelId = (Get-NSXTPolicyBasedVPN -Name $Name).ID + + # Delete IPSEC tunnel + $method = "DELETE" + $deleteVPNtunnelURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/tier-0s/vmc/locale-services/default/l3vpns/$TunnelId" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$deleteVPNtunnelURL`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $deleteVPNtunnelURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $deleteVPNtunnelURL -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 removing NSX-T VPN Tunnel: $Name" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + Write-Host "Successfully removed NSX-T VPN Tunnel: $Name" + } + } +} + +Function Get-NSXTDNS { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 06/08/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Returns DNS Zone configuration for MGW or CGW + .DESCRIPTION + This cmdlet retrieves DNS Zone configuration for MGW or CGW + .EXAMPLE + Get-NSXTDNS -GatewayType MGW + .EXAMPLE + Get-NSXTDNS -GatewayType CGW +#> + param( + [Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType, + [Switch]$Troubleshoot + ) + + If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { + $method = "GET" + $dnsURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/dns-forwarder-zones/$($GatewayType.toLower())-dns-zone" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$dnsURL`n" + } + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $dnsURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $dnsURL -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 DNS Zones" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + $dnsZone = ($requests.Content | ConvertFrom-Json) + + $results = [pscustomobject] @{ + Name = $dnsZone.display_name; + DNS1 = $dnsZone.upstream_servers[0]; + DNS2 = $dnsZone.upstream_servers[1]; + Domain = $dnsZone.dns_domain_names; + } + $results + } + } +} + +Function Set-NSXTDNS { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 06/08/2019 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Returns DNS Zone configuration for MGW or CGW + .DESCRIPTION + This cmdlet retrieves DNS Zone configuration for MGW or CGW + .EXAMPLE + Set-NSXTDNS -GatewayType MGW -DNS @("192.168.1.14","192.168.1.15") + .EXAMPLE + Set-NSXTDNS -GatewayType CGW -DNS @("8.8.8.8") +#> + param( + [Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType, + [Parameter(Mandatory=$true)][String[]]$DNS, + [Switch]$Troubleshoot + ) + + If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { + $method = "PATCH" + $dnsURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/dns-forwarder-zones/$($GatewayType.toLower())-dns-zone" + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] - $method`n$dnsURL`n" + } + + $payload = @{ + upstream_servers = @($DNS) + } + + $body = $payload | ConvertTo-Json -Depth 5 + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $dnsURL -Body $body -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $dnsURL -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 updating NSX-T DNS Zones" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + + if($requests.StatusCode -eq 200) { + Write-Host "Successfully updated NSX-T DNS for $GatewayType" + } + } } \ No newline at end of file diff --git a/Modules/VMware.VMC/VMware.VMC.psm1 b/Modules/VMware.VMC/VMware.VMC.psm1 index f2151c9..92df1e8 100644 --- a/Modules/VMware.VMC/VMware.VMC.psm1 +++ b/Modules/VMware.VMC/VMware.VMC.psm1 @@ -874,8 +874,8 @@ Function Get-VMCSDDCSummary { Get-VMCSDDCSummary -Name -Org #> Param ( - [Parameter(Mandatory=$True)]$OrgName, - [Parameter(Mandatory=$True)]$SDDCName + [Parameter(Mandatory=$True)]$Org, + [Parameter(Mandatory=$True)]$Name ) If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { @@ -895,6 +895,7 @@ Function Get-VMCSDDCSummary { InstanceType = $sddc.resource_config.sddc_manifest.esx_ami.instance_type; VpcCIDR = $sddc.resource_config.vpc_info.vpc_cidr; NSXT = $sddc.resource_config.nsxt; + VPC_VGW = $sddc.resource_config.vpc_info.vgw_id; } $results } @@ -903,7 +904,7 @@ Function Get-VMCPublicIP { <# .NOTES =========================================================================== - Created by: William Lam + Created by: William LamVPC_VGW Date: 09/12/2018 Organization: VMware Blog: http://www.virtuallyghetto.com diff --git a/Scripts/Get-Migrations.ps1 b/Scripts/Get-Migrations.ps1 new file mode 100644 index 0000000..8336de7 --- /dev/null +++ b/Scripts/Get-Migrations.ps1 @@ -0,0 +1,12 @@ +<# +Script name: get-migrations.ps1 +Created on: 20/12/2018 +Author: Chris Bradshaw @aldershotchris +Description: The purpose of the script is to list the currently running + recently finished VM migrations. +Dependencies: None known +#> +Function Get-Migrations{ + Get-Task | + Where-Object{$_.Name -eq "RelocateVM_Task"} | + Select-Object @{Name="VM";Expression={Get-VM -Id $_.ObjectID}}, State, @{Name="% Complete";Expression={$_.PercentComplete}},StartTime +} diff --git a/Scripts/Save-PowerCLI.ps1 b/Scripts/Save-PowerCLI.ps1 index e9127bc..495c153 100644 --- a/Scripts/Save-PowerCLI.ps1 +++ b/Scripts/Save-PowerCLI.ps1 @@ -1,147 +1,158 @@ -function Save-PowerCLI { - <# - .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 +function Save-PowerCLI { +<# +.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 + Author: 2.1 - Luc Dekens, @LucD22 + - fixed issue with downloading the correct versions + - added a working cleanup of unwanted versions +.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 $PSBoundParameters.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} } - - 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 } - 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 } } - - 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 { + Get-Item -Path "$($Path)\*" -PipelineVariable dir | + ForEach-Object -Process { + $children = Get-ChildItem -Path $dir.FullName -Directory + if($children.Count -gt 1){ + $tgtVersion = $orderedDependencies.GetEnumerator() | where {$_.Name -eq $dir.Name} + $children | where{$_.Name -ne $tgtVersion.MinimumVersion} | + ForEach-Object -Process { + Remove-Item -Path $_.FullName -Recurse -Force -Confirm:$false } } } - - 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) - } - + + 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 - } - + + # 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 + } +}