From 73d7eaa99256fdb84cf9e4db0029413a0c79375e Mon Sep 17 00:00:00 2001 From: Wouter Kursten Date: Tue, 22 May 2018 19:22:02 +0200 Subject: [PATCH 01/65] added function to create vmware.hv.securestring password --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index a0bfb26..faecc37 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -106,6 +106,23 @@ function Get-JsonObject { } } +function new-hvpassword{ +#Requires input of type securestring and replies with vmware.hv.securestring + param( + [string]$pwin + ) + + $temppw = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pwin) + $PlainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($temppw) + $plainpassword + $SecPassword = New-Object VMware.Hv.SecureString + $enc = [system.Text.Encoding]::UTF8 + $SecPassword.Utf8String = $enc.GetBytes($PlainPassword) + return $SecPassword + +} + + function Get-MapEntry { param( [Parameter(Mandatory = $true)] From b88f3a286a11eef53c2196459dc5721d82352980 Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Fri, 29 Jun 2018 08:38:24 -0400 Subject: [PATCH 02/65] Add VMWonAWS_InviteUsers.ps1 Script which can be used to automate the process of adding new users to a specified VMware Cloud on AWS Organization --- .../VMWonAWS_InviteUsers.ps1 | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 Scripts/VMware_Cloud_on_AWS/VMWonAWS_InviteUsers.ps1 diff --git a/Scripts/VMware_Cloud_on_AWS/VMWonAWS_InviteUsers.ps1 b/Scripts/VMware_Cloud_on_AWS/VMWonAWS_InviteUsers.ps1 new file mode 100644 index 0000000..59ddb7a --- /dev/null +++ b/Scripts/VMware_Cloud_on_AWS/VMWonAWS_InviteUsers.ps1 @@ -0,0 +1,114 @@ +<# +.SYNOPSIS + Takes email address input in order to create VMware Cloud on AWS invites for the desired Organization +.DESCRIPTION + Script which can be used to automate the process of adding new users to a specified VMware Cloud on AWS Organization +.NOTES + Author: Kyle Ruddy, @kmruddy, kmruddy.com +.PARAMETER newUserEmail + Plain text email address or array of email addresses +.PARAMETER roleName + Desired role name of the new users, default is Organization Member +.EXAMPLE + PS > ./VMWonAWS_InviteUsers.ps1 -newUserEmail 'testuser@vmware.com' +.EXAMPLE + PS > ./VMWonAWS_InviteUsers.ps1 -newUserEmail $arrayOfEmailAddresses +#> +[CmdletBinding(SupportsShouldProcess=$True)] + param ( + + [Parameter (Mandatory = $True, Position=0)] + $newUserEmail, + [Parameter (Mandatory = $False, Position=1)] + [ValidateSet("Organization Member","Organization Owner","Support User")] + [string]$roleName = "Organization Member" + ) + + # Set Static Variables for your environment + $oauthToken = 'xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' + $orgID = 'xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' + + ### DO NOT MODIFY CODE BELOW THIS LINE ### + $inviteReport = @() + $userEmail = @() + + # Email Validation Testing + if ($newUserEmail -is [array]) { + foreach ($email in $newUserEmail) { + try { + $userEmail += [mailAddress]$email | select-object -ExpandProperty Address + } + catch { + Write-Warning "$email is not a valid email address" + } + } + } + else { + try { + $userEmail += [mailAddress]$newUserEmail | select-object -ExpandProperty Address + } + catch { + Write-Warning "$newUserEmail is not a valid email address" + } + } + + if ($userEmail.Count -eq 0) { + Write-Warning "No valid email addresses found." + Break + } + + # Validation and translation of the role name to the role ID + if ($roleName -eq 'Organization Member') { + $orgRoleNames = @("org_member") + } + elseif ($roleName -eq 'Organization Owner') { + $orgRoleNames = @("org_owner") + } + elseif ($roleName -eq 'Support User') { + $orgRoleNames = @("support_user") + } + + # Creating custom objects to start building out the body input + $bodyObj = new-object -TypeName System.Object + $SvcRoleNames = @("vmc-user:full") + $SvcDefinitionLink = '/csp/gateway/slc/api/definitions/external/ybUdoTC05kYFC9ZG560kpsn0I8M_' + $bodyObj | Add-Member -Name 'orgRoleNames' -MemberType Noteproperty -Value $orgRoleNames + $serviceRolesDtos = New-Object -TypeName System.Object + $serviceRolesDtos | Add-Member -Name 'serviceDefinitionLink' -MemberType Noteproperty -Value $SvcDefinitionLink + $serviceRolesDtos | Add-Member -Name 'serviceRoleNames' -MemberType Noteproperty -Value $SvcRoleNames + $bodyObj | Add-Member -Name 'serviceRolesDtos' -MemberType Noteproperty -Value @($serviceRolesDtos) + $bodyObj | Add-Member -Name 'usernames' -MemberType Noteproperty -Value $userEmail + $body = $bodyObj | ConvertTo-Json -Depth 100 + + # Connecting to the REST API service for authentication and then to perform the POST method + $connection = Invoke-WebRequest -Uri "https://console.cloud.vmware.com/csp/gateway/am/api/auth/api-tokens/authorize?refresh_token=$oauthToken" -Method Post + $accesskey = ($connection.content | Convertfrom-json).access_token + $inviteUsers = Invoke-WebRequest -Uri "https://console.cloud.vmware.com/csp/gateway/am/api/orgs/$orgID/invitations" -headers @{"csp-auth-token"="$accesskey"} -Method Post -Body $body -ContentType "application/json" + + # Outputting the successful invite which was just created + $orgInviteRefResponse = Invoke-WebRequest -Uri "https://console.cloud.vmware.com/csp/gateway/am/api/orgs/$orgid/invitations" -headers @{"csp-auth-token"="$accessKey"} -Method Get + if ($orgInviteRefResponse) { + $orgInviteRefObject = $orgInviteRefResponse | ConvertFrom-Json + + foreach ($inviteRef in $orgInviteRefObject) { + $link = $inviteRef.refLink + $orgInviteResponse = Invoke-WebRequest -Uri "https://console.cloud.vmware.com$link" -headers @{"csp-auth-token"="$accessKey"} -Method Get + + $orgInviteObject = $orgInviteResponse.content | ConvertFrom-Json + + foreach ($emailInput in $userEmail) { + + if ($orgInviteObject.username -eq $emailInput) { + $i = New-Object System.Object + $i | Add-Member -Type NoteProperty -Name InviteID -Value $orgInviteObject.refLink.Substring($orgInviteObject.refLink.Length - 36) + $i | Add-Member -Type NoteProperty -Name Username -Value $orgInviteObject.username + $i | Add-Member -Type NoteProperty -Name Status -Value $orgInviteObject.status + $i | Add-Member -Type NoteProperty -Name OrgRoles -Value ($orgInviteObject.OrgRoleNames -join ", ") + $i | Add-Member -Type NoteProperty -Name Requester -Value $orgInviteObject.generatedBy + $inviteReport += $i + } + } + } + } + + return $inviteReport \ No newline at end of file From e36208e2db0b3a3b369c9638a9c326169d99f6e6 Mon Sep 17 00:00:00 2001 From: simonfangyingzhang Date: Tue, 3 Jul 2018 03:25:29 +0100 Subject: [PATCH 03/65] Update VMware.VMEncryption.psd1 VMware.VimAutomation.Core 10.1.0.8344055 instead of VMware.VimAutomation.Core 10.1.0.8346946 --- Modules/VMware.VMEncryption/VMware.VMEncryption.psd1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/VMware.VMEncryption/VMware.VMEncryption.psd1 b/Modules/VMware.VMEncryption/VMware.VMEncryption.psd1 index aa83854..8a93a97 100644 --- a/Modules/VMware.VMEncryption/VMware.VMEncryption.psd1 +++ b/Modules/VMware.VMEncryption/VMware.VMEncryption.psd1 @@ -49,7 +49,7 @@ Copyright = 'Copyright (c) 2016 VMware, Inc. All rights reserved.' # Modules that must be imported into the global environment prior to importing this module RequiredModules = @( -@{"ModuleName"="VMware.VimAutomation.Core";"ModuleVersion"="10.1.0.8346946"} +@{"ModuleName"="VMware.VimAutomation.Core";"ModuleVersion"="10.1.0.8344055"} ) # Assemblies that must be loaded prior to importing this module From f567922869ab1bc0efb2605e49b4f6ac6faecf24 Mon Sep 17 00:00:00 2001 From: Wouter Kursten Date: Fri, 6 Jul 2018 09:32:23 +0200 Subject: [PATCH 04/65] Several changes added new-hvhomesite, get-hvhomesite removed new-hvpassword (never pulled to master) --- .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 226 ++++++++++++++++-- 1 file changed, 208 insertions(+), 18 deletions(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 3b88028..9744188 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -106,23 +106,6 @@ function Get-JsonObject { } } -function new-hvpassword{ -#Requires input of type securestring and replies with vmware.hv.securestring - param( - [string]$pwin - ) - - $temppw = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pwin) - $PlainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($temppw) - $plainpassword - $SecPassword = New-Object VMware.Hv.SecureString - $enc = [system.Text.Encoding]::UTF8 - $SecPassword.Utf8String = $enc.GetBytes($PlainPassword) - return $SecPassword - -} - - function Get-MapEntry { param( [Parameter(Mandatory = $true)] @@ -10903,4 +10886,211 @@ function remove-hvsite { [System.gc]::collect() } -Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-hvlocalsession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, new-hvpodfederation, remove-hvpodfederation, get-hvpodfederation, register-hvpod, unregister-hvpod, set-hvpodfederation,get-hvsite,new-hvsite,set-hvsite,remove-hvsite +function Get-HVHomeSite { + <# + .Synopsis + Gets the configured Horizon View Homesites + + .DESCRIPTION + Gets the configured Horizon View Homesites + + .PARAMETER Group + User principal name of a group + + .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 + + .EXAMPLE + Get-HVHomeSite + + .EXAMPLE + Get-HVHomeSite -group group@domain + + .NOTES + Author : Wouter Kursten + Author email : wouter@retouw.nl + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.4 + PowerCLI Version : PowerCLI 10 + PowerShell Version : 5.0 + #> + + [CmdletBinding( + SupportsShouldProcess = $false, + ConfirmImpact = 'High' + )] + + param( + [Parameter(Mandatory = $false)] + [ValidatePattern("^.+?[@\\].+?$")] + [String] + $Group, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin{ + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process{ + $hsresults = Get-HVQueryResult -EntityType UserHomeSiteInfo -HvServer $HvServer + $resultsoverview=@() + + foreach ($hsresult in $hsresults){ + if ($hsresult.Globalentitlement){ + $Globalentitlement = ($services.GlobalEntitlement.GlobalEntitlement_Get($hsresult.base.GlobalEntitlement)).base.displayname + } + else{ + $Globalentitlement="" + } + + if (($hsresult.globalapplicationEntitlement)){ + $GlobalApplicationEntitlement = ($services.GlobalApplicationEntitlement.GlobalApplicationEntitlement_Get($hsresult.base.GlobalApplicationEntitlement)).base.displayname + } + else{ + $GlobalApplicationEntitlement="" + } + + $resultsoverview+=New-Object PSObject -Property @{"id" = ($hsresult).id; + "Group" = ($services.ADUserOrGroup.ADUserOrGroup_Get(($hsresult.base).userorgroup)).base.displayname; + "Site" = ($services.site.site_Get($hsresult.base.site)).base.displayname; + "Globalentitlement" =$Globalentitlement; + "Globalapplicationentitlement" =$GlobalApplicationEntitlement; + } + } + if ($group){ + $results=$resultsoverview | where-object {$_.Group -eq $group} | select-object id,Group,Site,Globalentitlement,GlobalApplicationEntitlement + } + else{ + $results=$resultsoverview | select-object id,Group,Site,Globalentitlement,GlobalApplicationEntitlement + } + return $results + } + [System.gc]::collect() +} + +function New-HVHomeSite { + <# + .Synopsis + Defines a homesite within a Horizon View Cloud Pod architecture + + .DESCRIPTION + Creates a new homesite within a Cloud Pod Archtitecture. By default it will be applied to everything + but the choice can be made to only apply for a single global entitlement or singel global application entitlement + + .PARAMETER Group + User principal name of a group + + .PARAMETER Site + Name of the Horizon View Site + + .PARAMETER globalEntitlement + Name of the global entitlement + + .PARAMETER globalApplicationEntitlement + Name of the global application entitlement + + .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 + + .EXAMPLE + New-HVHomeSite -group group@domain -site SITE + + .EXAMPLE + New-HVHomeSite -group group@domain -site SITE -globalapplicationentitlement ge-ap01 + + .EXAMPLE + New-HVHomeSite -group group@domain -site SITE -globalentitlement GE_Production + + .NOTES + Author : Wouter Kursten + Author email : wouter@retouw.nl + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.4 + PowerCLI Version : PowerCLI 10.1.1 + PowerShell Version : 5.0 + #> + + + [CmdletBinding(DefaultParameterSetName="Default")] + param( + [Parameter(Mandatory = $true,ParameterSetName="Default")] + [Parameter(ParameterSetName = "globalEntitlement")] + [Parameter(ParameterSetName = "globalApplicationEntitlement")] + [ValidatePattern("^.+?[@\\].+?$")] + [String] + $Group, + + [Parameter(Mandatory = $true,ParameterSetName="Default")] + [Parameter(ParameterSetName = "globalEntitlement")] + [Parameter(ParameterSetName = "globalApplicationEntitlement")] + [String] + $Site, + + [Parameter(Mandatory = $false,ParameterSetName="globalEntitlement")] + [String] + $globalEntitlement , + + [Parameter(Mandatory = $false,ParameterSetName="globalApplicationEntitlement")] + [String] + $globalApplicationEntitlement , + + [Parameter(Mandatory = $false,ParameterSetName="Default")] + [Parameter(ParameterSetName = "globalEntitlement")] + [Parameter(ParameterSetName = "globalApplicationEntitlement")] + $HvServer = $null + ) + + begin{ + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + $confirmFlag = Get-HVConfirmFlag -keys $PsBoundParameters.Keys + $groupinfo = Get-UserInfo -UserName $Group + $UserOrGroupName = $groupinfo.Name + $Domain = $groupinfo.Domain + $filter1 = Get-HVQueryFilter 'base.name' -Eq $UserOrGroupName + $filter2 = Get-HVQueryFilter 'base.domain' -Eq $Domain + $filter3 = Get-HVQueryFilter 'base.group' -Eq $true + $andFilter = Get-HVQueryFilter -And -Filters @($filter1, $filter2, $filter3) + $adresults = Get-HVQueryResult -EntityType ADUserOrGroupSummaryView -Filter $andFilter -HvServer $HvServer + + if ($adresults.length -ne 1) { + Write-host "Unable to find specific group with given search parameters" + break + } + $userhomesitebase=new-object VMware.Hv.UserHomeSiteBase + $userhomesitebase.UserOrGroup=$adresults.id + $userhomesitebase.site=($services.site.site_list() | where-object {$_.base.displayname -eq $site}).id + if ($globalEntitlement){ + $geresults = Get-HVQueryResult -EntityType GlobalEntitlementSummaryView -HvServer $HvServer + $geid=$geresults | where-object {$_.base.displayname -eq $globalEntitlement} + $userhomesitebase.globalEntitlement=$geid.id + } + elseif($globalApplicationEntitlement){ + $gaefilter1 = Get-HVQueryFilter 'data.name' -Eq $globalApplicationEntitlement + $gaeresults = Get-HVQueryResult -EntityType ApplicationInfo -Filter $gaefilter1 -HvServer $HvServer + $userhomesitebase.GlobalApplicationEntitlement=$gaeresults.id + } + $services.UserHomeSite.UserHomeSite_Create($userhomesitebase) + } +} + +Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-hvlocalsession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, new-hvpodfederation, remove-hvpodfederation, get-hvpodfederation, register-hvpod, unregister-hvpod, set-hvpodfederation,get-hvsite,new-hvsite,set-hvsite,remove-hvsite,New-HVHomeSite,Get-HVHomeSite From 2200c4d25d90d3b651d57f67fa058475d457e05f Mon Sep 17 00:00:00 2001 From: Wouter Kursten Date: Wed, 11 Jul 2018 14:17:56 +0200 Subject: [PATCH 05/65] fix --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 9744188..af8d9dc 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -10974,8 +10974,9 @@ function Get-HVHomeSite { $results=$resultsoverview | select-object id,Group,Site,Globalentitlement,GlobalApplicationEntitlement } return $results + [System.gc]::collect() } - [System.gc]::collect() + } function New-HVHomeSite { From 355d4993018ec8838d7e86554863c049752cbc41 Mon Sep 17 00:00:00 2001 From: Wouter Kursten Date: Tue, 17 Jul 2018 20:40:58 +0200 Subject: [PATCH 06/65] remove break issue #211 remove break issue https://github.com/vmware/PowerCLI-Example-Scripts/issues/211 --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index af8d9dc..fbfe503 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -8119,8 +8119,7 @@ function Get-HVEntitlement { } if (! $results) { Write-Host "Get-HVEntitlement: No entitlements found with given search parameters" - break - } + } return $results } end { From b096ace8ae87fb53ff861c5bea80a6f2bf5b69e6 Mon Sep 17 00:00:00 2001 From: Wouter Kursten Date: Tue, 24 Jul 2018 19:33:41 +0200 Subject: [PATCH 07/65] added function Set-HVEventDatabase --- .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 139 +++++++++++++++++- 1 file changed, 138 insertions(+), 1 deletion(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index fbfe503..36662fb 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11093,4 +11093,141 @@ function New-HVHomeSite { } } -Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-hvlocalsession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, new-hvpodfederation, remove-hvpodfederation, get-hvpodfederation, register-hvpod, unregister-hvpod, set-hvpodfederation,get-hvsite,new-hvsite,set-hvsite,remove-hvsite,New-HVHomeSite,Get-HVHomeSite +function Set-HVEventDatabase { + <# + .Synopsis + Registers or changes a Horizon View Event database. + + .DESCRIPTION + Registers or changes a Horizon View Event database + + .PARAMETER ServerName + Name of the database server (Required) + + .PARAMETER Databasetype + Database type, possible options: MYSQL,SQLSERVER,ORACLE. Defaults to SQLSERVER + + .PARAMETER DatabasePort + Port number on the database server to which View will send events. Defaults to 1433. + + .PARAMETER Databasename + Name of the Database (required) + + .PARAMETER TablePrefix + Prefix to use for the Event Databse. Allowed characters are letters, numbers, and the characters @, $, #, _, and may not be longer than 6 characters. + + .PARAMETER UserName + UserName to connect to the database (required) + + .PARAMETER Password + Password of the user connecting to the database in Securestring format. + Can be created with: $password = Read-Host 'Domain Password' -AsSecureString + + .PARAMETER eventtime + Time to show the events for. Possible options are ONE_WEEK, TWO_WEEKS, THREE_WEEKS, ONE_MONTH,TWO_MONTHS, THREE_MONTHS, SIX_MONTHS + + .PARAMETER EventNewTime + Time in days to classify events for new. Range 1-3 + + .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 + + .EXAMPLE + register-hveventdatabase -server SERVER@domain -database DATABASENAME -username USER@domain -password $password + + .NOTES + Author : Wouter Kursten + Author email : wouter@retouw.nl + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.4 + PowerCLI Version : PowerCLI 10 + PowerShell Version : 5.0 + #> + + [CmdletBinding( + SupportsShouldProcess = $false, + ConfirmImpact = 'High' + )] + + param( + [Parameter(Mandatory = $true)] + [string] + $ServerName, + + [Parameter(Mandatory = $false)] + [string] + $DatabaseType = "SQLSERVER", + + [Parameter(Mandatory = $false)] + [int] + $DatabasePort = 1433, + + [Parameter(Mandatory = $true)] + [string] + $DatabaseName, + + [Parameter(Mandatory = $false)] + [string][ValidateLength(1,6)] + $TablePrefix, + + [Parameter(Mandatory = $true)] + + [String] + $UserName, + + [Parameter(Mandatory = $true)] + [securestring] + $password, + + [Parameter(Mandatory = $false)] + [ValidateSet('ONE_WEEK','TWO_WEEKS','THREE_WEEKS','ONE_MONTH','TWO_MONTHS','THREE_MONTHS','SIX_MONTHS')] + [string] + $eventtime="TWO_WEEKS", + + [Parameter(Mandatory = $false)] + [ValidateRange(1,3)] + [int] + $eventnewtime = 2, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + $temppw = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password) + $PlainevdbPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($temppw) + $dbupassword = New-Object VMware.Hv.SecureString + $enc = [system.Text.Encoding]::UTF8 + $dbupassword.Utf8String = $enc.GetBytes($PlainevdbPassword) + + $eventservice=new-object vmware.hv.eventdatabaseservice + $eventservicehelper=$eventservice.getEventDatabaseInfoHelper() + $eventsettings=new-object VMware.Hv.EventDatabaseEventSettings + $eventdatabase=new-object VMware.Hv.EventDatabaseSettings + $eventsettings.ShowEventsForTime=$eventtime + $eventsettings.ClassifyEventsAsNewForDays=$eventnewtime + $eventdatabase.Server=$ServerName + $eventdatabase.type=$DatabaseType + $eventdatabase.port=$DatabasePort + $eventdatabase.name=$DatabaseName + $eventdatabase.username=$UserName + if($TablePrefix){ + $eventdatabase.tablePrefix=$tableprefix + } + + $eventdatabase.password=$dbupassword + $eventservicehelper.setDatabase($eventdatabase) + $eventservicehelper.setsettings($eventsettings) + $eventservice.update($services, $eventservicehelper) + + [System.gc]::collect() +} + +Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, New-HVPodfederation, Remove-HVPodFederation, Get-HVPodFederation, Register-HVPod, Unregister-HVPod, Set-HVPodFederation,Get-HVSite,New-HVSite,Set-HVSite,Remove-HVSite,New-HVHomeSite,Get-HVHomeSite,Set-HVEventDatabase From 348eb1899edf08cbf73b45c8138cc16b74fe3dc4 Mon Sep 17 00:00:00 2001 From: Wouter Kursten Date: Tue, 24 Jul 2018 19:53:53 +0200 Subject: [PATCH 08/65] added function Get-HVEventDatabase --- .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 63 ++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 36662fb..297e260 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11230,4 +11230,65 @@ function Set-HVEventDatabase { [System.gc]::collect() } -Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, New-HVPodfederation, Remove-HVPodFederation, Get-HVPodFederation, Register-HVPod, Unregister-HVPod, Set-HVPodFederation,Get-HVSite,New-HVSite,Set-HVSite,Remove-HVSite,New-HVHomeSite,Get-HVHomeSite,Set-HVEventDatabase +function Get-HVEventDatabase { + <# + .Synopsis + Retreives information about the configured Event Database + + .DESCRIPTION + Collects information about the configured event database for aHorizon View pod + + .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 + + .EXAMPLE + Get-HVEventDatabase + + .NOTES + Author : Wouter Kursten + Author email : wouter@retouw.nl + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.4 + PowerCLI Version : PowerCLI 10 + PowerShell Version : 5.0 + #> + + [CmdletBinding( + SupportsShouldProcess = $false, + ConfirmImpact = 'High' + )] + + param( + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + + $eventdatabase=$services.EventDatabase.EventDatabase_Get() + if ($eventdatabase.eventdatabaseset -eq $False){ + write-output "No Event Database configuration found" + } + elseif ($eventdatabase.eventdatabaseset -eq $true){ + $Eventdatabaseoverview=@() + $Eventdatabaseoverview+=New-Object PSObject -Property @{"Servername" = $eventdatabase.Database.Server; + "Type" = $eventdatabase.Database.Type; + "DatabaseName" = $eventdatabase.Database.Name; + "UserName" = $eventdatabase.Database.UserName; + "TablePrefix" = $eventdatabase.Database.TablePrefix; + "ShowEventsForTime" = $eventdatabase.settings.ShowEventsForTime; + "ClassifyEventsAsNewForDays" = $eventdatabase.settings.ClassifyEventsAsNewForDays; + } | select-object Servername,Type,DatabaseName,UserName,TablePrefix,ShowEventsForTime,ClassifyEventsAsNewForDays + } + return $Eventdatabaseoverview + [System.gc]::collect() +} + +Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, New-HVPodfederation, Remove-HVPodFederation, Get-HVPodFederation, Register-HVPod, Unregister-HVPod, Set-HVPodFederation,Get-HVSite,New-HVSite,Set-HVSite,Remove-HVSite,New-HVHomeSite,Get-HVHomeSite,Set-HVEventDatabase,Get-HVEventDatabase From fc270dc25686450110adededc9d680bf651d4352 Mon Sep 17 00:00:00 2001 From: Wouter Kursten Date: Tue, 24 Jul 2018 20:41:51 +0200 Subject: [PATCH 09/65] Added Clear-HVEventDatabase --- .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 297e260..cf03410 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11291,4 +11291,53 @@ function Get-HVEventDatabase { [System.gc]::collect() } -Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, New-HVPodfederation, Remove-HVPodFederation, Get-HVPodFederation, Register-HVPod, Unregister-HVPod, Set-HVPodFederation,Get-HVSite,New-HVSite,Set-HVSite,Remove-HVSite,New-HVHomeSite,Get-HVHomeSite,Set-HVEventDatabase,Get-HVEventDatabase +function Clear-HVEventDatabase { + <# + .Synopsis + Clears configurationof the configured Event Database + + .DESCRIPTION + Clears configurationof the configured Event Database + + .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 + + .EXAMPLE + Clear-HVEventDatabase + + .NOTES + Author : Wouter Kursten + Author email : wouter@retouw.nl + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.4 + PowerCLI Version : PowerCLI 10 + PowerShell Version : 5.0 + #> + + [CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High')] + + param( + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + PROCESS { + + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + if ($pscmdlet.ShouldProcess($($msg))) { + $services.EventDatabase.EventDatabase_Clear() + } + [System.gc]::collect() + } +} + +Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, New-HVPodfederation, Remove-HVPodFederation, Get-HVPodFederation, Register-HVPod, Unregister-HVPod, Set-HVPodFederation,Get-HVSite,New-HVSite,Set-HVSite,Remove-HVSite,New-HVHomeSite,Get-HVHomeSite,Set-HVEventDatabase,Get-HVEventDatabase,Clear-HVEventDatabase From a24fbf4e95daf1ab4e3f2e3a153556a7e91ac4f9 Mon Sep 17 00:00:00 2001 From: Wouter Kursten Date: Mon, 13 Aug 2018 09:07:37 +0200 Subject: [PATCH 10/65] added extra query deifinitions added Eventsummaryview and GlobalApplicationEntitlementInfo as they are newly added since PowerCLI 10.1.1 --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index cf03410..74bf078 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -1761,8 +1761,8 @@ function Get-HVQueryResult { Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2, 7.1.0 - PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 + Horizon View Server Version : 7.0.2, 7.1.0,7.4 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1, PowerCLI 10.1.1 PowerShell Version : 5.0 #> @@ -1775,7 +1775,7 @@ function Get-HVQueryResult { 'FarmSummaryView','GlobalApplicationEntitlementInfo','GlobalEntitlementSummaryView', 'MachineNamesView','MachineSummaryView','PersistentDiskInfo','PodAssignmentInfo', 'RDSServerInfo','RDSServerSummaryView','RegisteredPhysicalMachineInfo','SampleInfo', - 'SessionLocalSummaryView','TaskInfo','URLRedirectionInfo','UserHomeSiteInfo')] + 'SessionLocalSummaryView','TaskInfo','URLRedirectionInfo','UserHomeSiteInfo','EventSummaryView','GlobalApplicationEntitlementInfo')] [string]$EntityType, [Parameter(Position = 1,Mandatory = $false)] From 50b76efef612424a73bdedd583ca13ad35c6ab03 Mon Sep 17 00:00:00 2001 From: dmilov Date: Tue, 14 Aug 2018 17:03:12 +0300 Subject: [PATCH 11/65] Functions for reading a VM's vmsd file content and search for specific settings To be able to identify certain VM has linked clone children a specific setting has to be read from the VM's snapshot config file. For the purpose of this I created two functions that enable reading full content of the vmsd file as well as searching for a specific setting in the vmsd file content. --- Scripts/ReadVMSnapshotConfig.ps1 | 104 +++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 Scripts/ReadVMSnapshotConfig.ps1 diff --git a/Scripts/ReadVMSnapshotConfig.ps1 b/Scripts/ReadVMSnapshotConfig.ps1 new file mode 100644 index 0000000..fe274ee --- /dev/null +++ b/Scripts/ReadVMSnapshotConfig.ps1 @@ -0,0 +1,104 @@ +function Get-VMSnapshotConfigContent { +<# + .SYNOPSIS + Reads .vmsd file content + + .DESCRIPTION + Build the vmsd file http URI following https://code.vmware.com/apis/358/vsphere#/doc/vim.FileManager.html + and reads its content with the session established by Connect-VIServer + + .INPUTS + VirtualMachine + + .OUTPUTS + String - the content of the vmsd file + + .NOTES + Author: Dimitar Milov + Version: 1.0 + + .EXAMPLE + Get-VM | Get-VMSnapshotConfigContent +#> + +[CmdletBinding()] +param( + [Parameter(Mandatory=$true, ValueFromPipeline=$true)] + [ValidateNotNull()] + [VMware.VimAutomation.Types.VirtualMachine] + $VM +) + +PROCESS { + # Create web client from current session + $sessionKey = $vm.GetClient().ConnectivityService.CurrentUserSession.SoapSessionKey + $certValidationHandler = $vm.GetClient().ConnectivityService.GetValidationHandlerForCurrentServer() + $webClient = [vmware.vimautomation.common.util10.httpclientUtil]::CreateHttpClientWithSessionReuse($certValidationHandler, $sessionKey, $null) + + # Build VMSD file http URI + # https://code.vmware.com/apis/358/vsphere#/doc/vim.FileManager.html + $vmName = $vm.Name + $datastoreName = ($vm | Get-Datastore).Name + $dcName = ($vm | Get-Datacenter).Name + $serverAddress = $vm.GetClient().ConnectivityService.ServerAddress + $vmsdUri = [uri]"https://$serverAddress/folder/$vmName/$vmName.vmsd?dcPath=$dcName&dsName=$datastoreName" + + # Get VMSD content as string + $task = $webClient.GetAsync($vmsdUri) + $task.Wait() + $vmsdContent = $task.Result.Content.ReadAsStringAsync().Result + + # Dispose web client + $webClient.Dispose() + + # Result + $vmsdContent +} + +} + +function Get-VMSnapshotConfigSetting { +<# + .SYNOPSIS + Gets the value of a specified key from the snapshot config file content + + .DESCRIPTION + Reads the VM's snapshot config file and searches for specified key. + If key is found its value is returned as an output + + .INPUTS + VirtualMachine and key + + .OUTPUTS + String - config value for the specified key + + .NOTES + Author: Dimitar Milov + Version: 1.0 + + .EXAMPLE + Get-VM | Get-VMSnapshotConfigSetting -Key "numSentinels" +#> +[CmdletBinding()] +param( + [Parameter(Mandatory=$true, ValueFromPipeline=$true)] + [ValidateNotNull()] + [VMware.VimAutomation.Types.VirtualMachine] + $VM, + + [Parameter(Mandatory=$true)] + [ValidateNotNull()] + [string] + $Key +) + +PROCESS { + $content = Get-VMSnapshotConfigContent -vm $vm + + $keyMatch = $content | Select-String ('{0} = "(?.*)"' -f $key) + + if ($keyMatch.Matches -ne $null) { + $keyMatch.Matches[0].Groups["value"].Value + } +} +} From 61a9929bcaa37534f85b1655443ff7d96a1869b5 Mon Sep 17 00:00:00 2001 From: AndyG Date: Mon, 20 Aug 2018 15:52:41 -0400 Subject: [PATCH 12/65] Added Get-NSXTTransportNodes Added Get-NSXTTransportNodes --- Modules/NSXT/NSXT.psm1 | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Modules/NSXT/NSXT.psm1 b/Modules/NSXT/NSXT.psm1 index f8dcb49..a6afe2d 100644 --- a/Modules/NSXT/NSXT.psm1 +++ b/Modules/NSXT/NSXT.psm1 @@ -256,5 +256,41 @@ Function Get-NSXTManager { $results+=$tmp } } + $results +} + +Function Get-NSXTTransportNodes { + Param ( + [parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id + ) + + $transport_nodesService = Get-NsxtService -Name "com.vmware.nsx.transport_nodes" + $transport_nodesstateService = Get-NsxtService -Name "com.vmware.nsx.transport_nodes.state" + + if($Id) { + $transport_nodes = $transport_nodesService.get($Id) + } else { + $transport_nodes = $transport_nodesService.list().results + } + + $results = @() + foreach ($transport_node in $transport_nodes) { + + $transport_nodesstate = $transport_nodesstateService.get("$($transport_node.Id)") + + $tmp = [pscustomobject] @{ + Id = $transport_node.Id; + Name = $transport_node.display_name; + Tags = $transport_node.tags; + MaintenanceMode = $transport_node.maintenance_mode; + HostSwitchesName = $transport_node.host_switches.host_switch_name; + Default_gateway = $transport_nodesstate.host_switch_states.endpointsdefault_gateway; + Device_name = $transport_nodesstate.host_switch_states.endpoints.device_name; + Ip = $transport_nodesstate.host_switch_states.endpoints.ip; + Subnet_mask =$transport_nodesstate.host_switch_states.endpoints.subnet_mask + } + $results+=$tmp + } + $results } \ No newline at end of file From 8ae75925af03fac46552e572d9af40b69fab5391 Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Tue, 21 Aug 2018 15:40:01 -0400 Subject: [PATCH 13/65] Update 1 Host Script Updating the script to not require the association of an AWS Account, plus some other general corrections. --- .../VMWonAWS_1nodeDeployment.ps1 | 55 ++++++++++++------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/Scripts/VMware_Cloud_on_AWS/VMWonAWS_1nodeDeployment.ps1 b/Scripts/VMware_Cloud_on_AWS/VMWonAWS_1nodeDeployment.ps1 index 8b17b16..2a41690 100644 --- a/Scripts/VMware_Cloud_on_AWS/VMWonAWS_1nodeDeployment.ps1 +++ b/Scripts/VMware_Cloud_on_AWS/VMWonAWS_1nodeDeployment.ps1 @@ -7,9 +7,10 @@ # Set details for SDDC $oauthToken = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx" -$sddcName = "PowerCLI-1Node-SDDC" +$sddcName = "PowerCLI-1Host-SDDC" $hostCount = "1" $awsRegion = "US_WEST_2" +$useAwsAccount = $false # --- Deployment code --- # Connect to VMware Cloud Service @@ -18,19 +19,25 @@ Connect-Vmc -RefreshToken $oauthToken | Out-Null # Get ORG ID $orgSvc = Get-VmcService -Name com.vmware.vmc.orgs $org = $orgSvc.List() -Write-Host "Org:"$org.display_name" ID:"$org.id +Write-Output -InputObject "Org: $($org.display_name) ID: $($org.id)" -# Get Linked Account ID -$connAcctSvc = Get-VmcService -Name com.vmware.vmc.orgs.account_link.connected_accounts -$connAcctId = $connAcctSvc.get($org.id) | Select-Object -ExpandProperty id -Write-Host "Account ID: $connAcctId" +# Check to use the already existing AWS account connection +if ($useAwsAccount -eq $true) { + # Get Linked Account ID + $connAcctSvc = Get-VmcService -Name com.vmware.vmc.orgs.account_link.connected_accounts + $connAcctId = $connAcctSvc.get($org.id) | Select-Object -ExpandProperty id + Write-Output -InputObject "Account ID: $connAcctId" -# Get Subnet ID -$compSubnetSvc = Get-VmcService -Name com.vmware.vmc.orgs.account_link.compatible_subnets -$vpcMap = $compSubnetSvc.Get($org.id, $connAcctId, $region) | Select-Object -ExpandProperty vpc_map -$compSubnets = $vpcMap | Select-Object -ExpandProperty Values | Select-Object -ExpandProperty subnets -$compSubnet = $compSubnets | where {$_.name -ne $null} | Select-Object -first 1 -Write-Host "Subnet CIDR"$compSubnet.subnet_cidr_block"ID:"$compSubnet.subnet_id + # Get Subnet ID + $compSubnetSvc = Get-VmcService -Name com.vmware.vmc.orgs.account_link.compatible_subnets + $vpcMap = $compSubnetSvc.Get($org.id, $connAcctId, $region) | Select-Object -ExpandProperty vpc_map + $compSubnets = $vpcMap | Select-Object -ExpandProperty Values | Select-Object -ExpandProperty subnets + $compSubnet = $compSubnets | where {$_.name -ne $null} | Select-Object -first 1 + Write-Output -InputObject "Subnet CIDR $($compSubnet.subnet_cidr_block) ID: $($compSubnet.subnet_id)" +} +elseif ($useAwsAccount -eq $false) { + Write-Output -InputObject "AWS Account Not Configured - you must connect to an AWS account within 14 days of creating this SDDC" +} # Deploy the SDDC $sddcSvc = Get-VmcService com.vmware.vmc.orgs.sddcs @@ -40,12 +47,20 @@ $sddcCreateSpec.Name = $sddcName $sddcCreateSpec.num_hosts = $hostCount if ($org.properties.values.sddcTypes) {$sddcCreateSpec.sddc_type = "1NODE"} $sddcCreateSpec.Provider = "AWS" -$accountLinkSpec = $sddcSvc.Help.create.sddc_config.account_link_sddc_config.Element.Create() -$accountLinkSpec.connected_account_id = $connAcctId -$custSubId0 = $sddcSvc.Help.create.sddc_config.account_link_sddc_config.Element.customer_subnet_ids.Element.Create() -$custSubId0 = $compSubnet.subnet_id -$accountLinkSpec.customer_subnet_ids.Add($custSubId0) | Out-Null -$sddcCreateSpec.account_link_sddc_config.Add($accountLinkSpec) | Out-Null -$sddcCreateSpec + +if ($useAwsAccount -eq $true) { + $accountLinkSpec = $sddcSvc.Help.create.sddc_config.account_link_sddc_config.Element.Create() + $accountLinkSpec.connected_account_id = $connAcctId + $custSubId0 = $sddcSvc.Help.create.sddc_config.account_link_sddc_config.Element.customer_subnet_ids.Element.Create() + $custSubId0 = $compSubnet.subnet_id + $accountLinkSpec.customer_subnet_ids.Add($custSubId0) | Out-Null + $sddcCreateSpec.account_link_sddc_config.Add($accountLinkSpec) | Out-Null +} +elseif ($useAwsAccount -eq $false) { + $accountLinkDelaySpec = $sddcSvc.Help.create.sddc_config.account_link_config.delay_account_link.Create() + $accountLinkDelaySpec = $true + $sddcCreateSpec.account_link_config.delay_account_link = $accountLinkDelaySpec +} + $newSddc = $sddcSvc.create($org.Id, $sddcCreateSpec) -$newSddc \ No newline at end of file +$newSddc | Select-Object resource_id,status,task_type,start_time,task_id \ No newline at end of file From a332102392ced2e16d390dd34d6910a5dca91231 Mon Sep 17 00:00:00 2001 From: AndyG Date: Tue, 21 Aug 2018 16:07:17 -0400 Subject: [PATCH 14/65] Added Get-NSXTTransportNodes to FunctionsToExport Added Get-NSXTTransportNodes to FunctionsToExport --- Modules/NSXT/NSXT.psd1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/NSXT/NSXT.psd1 b/Modules/NSXT/NSXT.psd1 index c3371b3..d9e25bc 100644 --- a/Modules/NSXT/NSXT.psd1 +++ b/Modules/NSXT/NSXT.psd1 @@ -7,7 +7,7 @@ Copyright = '(c) 2017. All rights reserved.' Description = 'Powershell Module for NSX-T REST API Functions' PowerShellVersion = '5.0' - FunctionsToExport = 'Get-NSXTComputeManager','Get-NSXTFabricNode','Get-NSXTFirewallRule','Get-NSXTIPPool','Get-NSXTLogicalSwitch','Get-NSXTManager','Get-NSXTTransportZone','Get-NSXTController' + FunctionsToExport = 'Get-NSXTComputeManager','Get-NSXTFabricNode','Get-NSXTFirewallRule','Get-NSXTIPPool','Get-NSXTLogicalSwitch','Get-NSXTManager','Get-NSXTTransportZone','Get-NSXTController','Get-NSXTTransportNodes' PrivateData = @{ PSData = @{ Tags = @('NSX-T','REST') From 3d29306cb651f54f5c5a904c2941bd090641a382 Mon Sep 17 00:00:00 2001 From: mycloudrevolution Date: Fri, 24 Aug 2018 14:20:51 +0200 Subject: [PATCH 15/65] add Module with Validate-ESXiPackages Function --- .../Validate-ESXiPackages.psm1 | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 Modules/Validate-ESXiPackages/Validate-ESXiPackages.psm1 diff --git a/Modules/Validate-ESXiPackages/Validate-ESXiPackages.psm1 b/Modules/Validate-ESXiPackages/Validate-ESXiPackages.psm1 new file mode 100644 index 0000000..ccf5d85 --- /dev/null +++ b/Modules/Validate-ESXiPackages/Validate-ESXiPackages.psm1 @@ -0,0 +1,82 @@ +function Validate-ESXiPackages { + <# + .DESCRIPTION + Compares all ESXi Host VIBs within a vSphere with a reference Hosts. + + .NOTES + File Name : Validate-ESXiPackages.ps1 + Author : Markus Kraus + Version : 1.0 + State : Ready + + Tested Against Environment: + + vSphere Version: 6.0 U2, 6.5 U1 + PowerCLI Version: PowerCLI 10.0.0 build 7895300 + PowerShell Version: 4.0 + OS Version: Windows Server 2012 R2 + + .LINK + https://mycloudrevolution.com/ + + .EXAMPLE + Validate-ESXiPackages -Cluster (Get-Cluster) -RefernceHost (Get-VMHost | Select-Object -First 1) + + .PARAMETER Cluster + vSphere Cluster to verify + + .PARAMETER RefernceHost + The VIB Reference ESXi Host + #> + + [CmdletBinding()] + param( + [Parameter(Mandatory=$True, ValueFromPipeline=$True, HelpMessage="vSphere Cluster to verify")] + [ValidateNotNullorEmpty()] + [VMware.VimAutomation.ViCore.Impl.V1.Inventory.ComputeResourceImpl] $Cluster, + [Parameter(Mandatory=$True, ValueFromPipeline=$false, HelpMessage="The VIB Reference ESXi Host")] + [ValidateNotNullorEmpty()] + [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl] $RefernceHost + ) + + Process { + + #region: Get reference VIBs + $EsxCli2 = Get-ESXCLI -VMHost $RefernceHost -V2 + $RefernceVibList = $esxcli2.software.vib.list.invoke() + #endregion + + #region: Compare reference VIBs + $MyView = @() + foreach ($VmHost in ($Cluster | Get-VMHost)) { + + $EsxCli2 = Get-ESXCLI -VMHost $VmHost -V2 + $VibList = $esxcli2.software.vib.list.invoke() + [Array]$VibDiff = Compare-Object -ReferenceObject $RefernceVibList.ID -DifferenceObject $VibList.ID + + if($VibDiff.Count -gt 0) { + $VibDiffSideIndicator = @() + foreach ($Item in $VibDiff) { + $VibDiffSideIndicator += $($Item.SideIndicator + " " + $Item.InputObject) + } + } + else { + $VibDiffSideIndicator = $null + } + + $Report = [PSCustomObject] @{ + Host = $VmHost.Name + Version = $VmHost.Version + Build = $VmHost.Build + VibDiffCount = $VibDiff.Count + VibDiff = $VibDiff.InputObject + VibDiffSideIndicator = $VibDiffSideIndicator + } + $MyView += $Report + + } + #region: Compare reference VIBs + + $MyView + } +} \ No newline at end of file From cff2f29b9735408dd6a4ffa6e0ba0ffa5ed57948 Mon Sep 17 00:00:00 2001 From: AndyG Date: Fri, 24 Aug 2018 16:32:35 -0400 Subject: [PATCH 16/65] Added Get-TraceFlows Added Get-TraceFlows. Will add to export list if it looks good. --- Modules/NSXT/NSXT.psm1 | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Modules/NSXT/NSXT.psm1 b/Modules/NSXT/NSXT.psm1 index a6afe2d..8616e88 100644 --- a/Modules/NSXT/NSXT.psm1 +++ b/Modules/NSXT/NSXT.psm1 @@ -293,4 +293,37 @@ Function Get-NSXTTransportNodes { } $results +} + +Function Get-NSXTTraceFlows { + Param ( + [parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id + ) + + $NSXTraceFlowsService = Get-NsxtService -Name "com.vmware.nsx.traceflows" + + if($Id) { + $NSXTraceFlows = $NSXTraceFlowsService.get($Id) + } else { + $NSXTraceFlows = $NSXTraceFlowsService.list().results + } + + $results = @() + foreach ($NSXTraceFlow in $NSXTraceFlows) { + + $tmp = [pscustomobject] @{ + Id = $NSXTraceFlow.Id; + Operation_State = $NSXTraceFlow.operation_state; + Delivered = $NSXTraceFlow.Counters.delivered_count; + Dropped = $NSXTraceFlow.Counters.dropped_count; + Analysis = $NSXTraceFlow.maintenance_mode; + } + $results+=$tmp + } + + $results + + if ($Id) { + write-output $Id + } } \ No newline at end of file From 3c5e8363ed71db1a850fb6d31ce06a36ca082910 Mon Sep 17 00:00:00 2001 From: AndyG Date: Fri, 24 Aug 2018 16:34:11 -0400 Subject: [PATCH 17/65] Added Get-TraceFlowsObservations Added Get-TraceFlowsObservations. Will add to export if it looks ok. --- Modules/NSXT/NSXT.psm1 | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Modules/NSXT/NSXT.psm1 b/Modules/NSXT/NSXT.psm1 index 8616e88..bfb320f 100644 --- a/Modules/NSXT/NSXT.psm1 +++ b/Modules/NSXT/NSXT.psm1 @@ -326,4 +326,20 @@ Function Get-NSXTTraceFlows { if ($Id) { write-output $Id } +} + +Function Get-NSXTTraceFlowObservations { + Param ( + [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id + ) + + $NSXTraceFlowsObservService = Get-NsxtService -Name "com.vmware.nsx.traceflows.observations" + + if($Id) { + $NSXTraceFlowsObserv = $NSXTraceFlowsObservService.list($Id) + } else { + throw "TraceFlow ID required" + } + + $NSXTraceFlowsObserv.results | select transport_node_name,component_name,@{N='PacketEvent';E={($_.resource_type).TrimStart("TraceflowObservation")}} } \ No newline at end of file From 1f6ec2c2c2188001bad863a36c0083458b42bdb6 Mon Sep 17 00:00:00 2001 From: AndyG Date: Fri, 24 Aug 2018 16:36:48 -0400 Subject: [PATCH 18/65] First try at a set- function - does not work! First try at a set- function. Does not work! Not clear how to resolve, the .create method ignores required parameters; looking for ideas. --- Modules/NSXT/NSXT.psm1 | 128 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/Modules/NSXT/NSXT.psm1 b/Modules/NSXT/NSXT.psm1 index bfb320f..b2f9c3c 100644 --- a/Modules/NSXT/NSXT.psm1 +++ b/Modules/NSXT/NSXT.psm1 @@ -342,4 +342,132 @@ Function Get-NSXTTraceFlowObservations { } $NSXTraceFlowsObserv.results | select transport_node_name,component_name,@{N='PacketEvent';E={($_.resource_type).TrimStart("TraceflowObservation")}} +} + +Function Set-NSXTTraceFlow { + [CmdletBinding()] + + # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types + Param ( + [parameter(Mandatory=$true, + ParameterSetName='Parameter Set VM Type')] + [ValidateSet("UNICAST")] + [string] + $TrafficType = "UNICAST", + [parameter(Mandatory=$true, + ValueFromPipeline=$true, + ParameterSetName='Parameter Set VM Type')] + [ValidateNotNullOrEmpty()] + #[ValidateScript({Get-NSXTLogicalPort -Id $_}] + [string] + $LPORTID, + [parameter(Mandatory=$true, + ValueFromPipeline=$true, + ParameterSetName='Parameter Set VM Type')] + [ValidateNotNullOrEmpty()] + [ValidateScript({$_ -match [IPAddress]$_})] + [string] + $SIPAddr, + [parameter(Mandatory=$true, + ValueFromPipeline=$true, + ParameterSetName='Parameter Set VM Type')] + [ValidateNotNullOrEmpty()] + [ValidateScript({$pattern = '^(([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2}))|(([0-9A-Fa-f]{2}[-]){5}([0-9A-Fa-f]{2}))$' + if ($_ -match ($pattern -join '|')) {$true} else { + throw "The argument '$_' does not match a valid MAC address format." + } + })] + [string] + $SMAC, + [parameter(Mandatory=$true, + ValueFromPipeline=$true, + ParameterSetName='Parameter Set VM Type')] + [ValidateNotNullOrEmpty()] + [ValidateScript({$_ -match [IPAddress]$_ })] + [string] + $DIPAddr, + [parameter(Mandatory=$true, + ValueFromPipeline=$true, + ParameterSetName='Parameter Set VM Type')] + [ValidateNotNullOrEmpty()] + [ValidateScript({$pattern = '^(([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2}))|(([0-9A-Fa-f]{2}[-]){5}([0-9A-Fa-f]{2}))$' + if ($_ -match ($pattern -join '|')) {$true} else { + throw "The argument '$_' does not match a valid MAC address format." + } + })] + [string] + $DMAC) + + Begin + { + if (-not $global:DefaultNsxtServers.isconnected) + { + + try + { + Connect-NsxtServer -Menu -ErrorAction Stop + } + + catch + { + throw "Could not connect to an NSX-T Manager, please try again" + } + } + + $NSXTraceFlowsService = Get-NsxtService -Name "com.vmware.nsx.traceflows" + + # This is where I need help - the method does not ingest the complete $traceflow_request object! + + # Create the example object + $traceflow_request = $NSXTraceFlowService.help.create.traceflow_request.Create() + $traceflow_request.lport_id = $LPORTID + $traceflow_request.timeout = '15000' + $traceflow_request.packet.routed = 'true' + $traceflow_request.packet.transport_type = $TrafficType.ToUpper() + $traceflow_request.packet.resource_type = 'FieldsPacketData' + $traceflow_request.packet.frame_size = '64' + + # The example object is missing packet data, so we create it. + $eth_header = @{src_mac = $SMAC;eth_type = '2048';dst_mac = $DMAC} + $ip_header = @{src_ip = $SIPAddr;protocol = '1';ttl = '64';dst_ip = $DIPAddr} + $traceflow_request.packet | Add-Member -NotePropertyMembers $eth_header -TypeName eth_header + $traceflow_request.packet | Add-Member -NotePropertyMembers $ip_header -TypeName ip_header + + # Alternative method of creating $traceflow_request (not working either) + <# + $TraceFlow_Request = [PSCustomObject]@{ + packet = @{routed = 'true'; + transport_type = $TrafficType.ToUpper(); + ip_header = @{src_ip = $SIPAddr;dst_ip = $DIPAddr}; + eth_header = @{dst_mac = $DMAC;src_mac = $SMAC}; + payload = 'test_payload'; + resource_type = 'FieldsPacketData'}; + timeout = '10000'; + lport_id = $LPORTID + } + #> + } + + Process + { + try + { + # This does not work, ignores eth_header,ip_header etc.. Not clear why!? + $NSXTraceFlow = $NSXTraceFlowService.create($traceflow_request) + } + + catch + { + $Error[0].Exception.ServerError.data + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. Filter by MONITORING. + } + } + + End + { + if ($NSXTraceFlow) + { + Get-NSXttraceflow + } + } } \ No newline at end of file From cca008ed276773cc93e64c6b997064e5f26937e8 Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Fri, 24 Aug 2018 19:49:32 -0400 Subject: [PATCH 19/65] VMWonAWS Firewall Rule Accelorator Script Addition of the script version of the VMware Cloud on AWS Firewall Rule Accelorator functionality --- .../VMWonAWS_FirewallRuleAccelerator.ps1 | 209 ++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 Scripts/VMware_Cloud_on_AWS/VMWonAWS_FirewallRuleAccelerator.ps1 diff --git a/Scripts/VMware_Cloud_on_AWS/VMWonAWS_FirewallRuleAccelerator.ps1 b/Scripts/VMware_Cloud_on_AWS/VMWonAWS_FirewallRuleAccelerator.ps1 new file mode 100644 index 0000000..de5b870 --- /dev/null +++ b/Scripts/VMware_Cloud_on_AWS/VMWonAWS_FirewallRuleAccelerator.ps1 @@ -0,0 +1,209 @@ +# Author: Kyle Ruddy +# Product: VMware Cloud on AWS +# Description: VMware Cloud on AWS Firewall Rule Accelerator for PowerCLI +# Requirements: +# - PowerShell 3.x or newer +# - PowerCLI 6.5.4 or newer +# - Use Default IP Addresses +# - Use NSX-V on VMware Cloud on AWS + +#---------- USER VARIABLES ---------------------------------------- + +$oauthToken = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx" +$orgId = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx' +$sddcId = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx' + +# ---------- DO NOT MODIFY BELOW THIS ------------------------------ + + +Connect-Vmc -RefreshToken $oauthToken | Out-Null + +$orgSvc = Get-VmcService -Name com.vmware.vmc.orgs + +if ($orgId) { + $org = $orgSvc.List() | where {$_.id -eq $orgId} +} +else {$org = $orgSvc.List()} + +if ($org -eq $null) {Write-Output "No Org Found. Exiting."; break} + +$sddcSvc = Get-VmcService -Name com.vmware.vmc.orgs.sddcs + +if ($sddcId) { + $sddc = $sddcSvc.Get($org.id, $sddcId) +} +else {$sddc = $sddcSvc.List($org.id)} + +if ($sddc -eq $null) {Write-Output "No SDDC Found. Exiting."; break} +elseif ($sddc -is [array]) {Write-Output "Multiple SDDCs Found. Please Specify an SDDC ID. Exiting."; break} + +$edgeSvc = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges +$mgwEdge = ($edgeSvc.Get($org.id,$sddcId,'gatewayServices') | Select-Object -ExpandProperty edge_page).data | where {$_.id -eq 'edge-1'} + +$ipsecSvc = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.ipsec.config +$ipsecVPN = $ipsecSvc.Get($org.id, $sddcId, $mgwEdge.id) + +$localSubnet = $ipsecVPN.sites.sites.local_subnets.subnets +$vpnSubnet = $ipsecVPN.sites.sites.peer_subnets.subnets +$vcMgmtIP = $sddc.resource_config.vc_management_ip +$vcPublicIP = $sddc.resource_config.vc_public_ip +$esxSubnet = $sddc.resource_config.esx_host_subnet +$ipsecVPNname = $ipsecVPN.sites.sites.name + +function Add-VMCFirewallRule { + <# + .NOTES + =========================================================================== + Created by: Kyle Ruddy + Date: 08/22/2018 + Organization: VMware + Blog: https://www.kmruddy.com + Twitter: @kmruddy + =========================================================================== + .SYNOPSIS + Creates a Firewall Rule for a given SDDC + .DESCRIPTION + Creates a Firewall Rule for a given SDDC + .EXAMPLE + Add-VMCFirewallRule -OrgId -sddcId -FwRuleName -SourceIpAddress -DestIpAddress -Service + + #> + param( + [Parameter(Mandatory=$true)] + [String]$OrgId, + [Parameter(Mandatory=$true)] + [String]$SddcId, + [Parameter(Mandatory=$false)] + [ValidateSet('Management Gateway','Compute Gateway')] + [String]$Edge = 'Management Gateway', + [Parameter(Mandatory=$true)] + [String]$FwRuleName, + [Parameter(Mandatory=$false)] + $SourceIpAddress, + [Parameter(Mandatory=$false)] + $DestIpAddress, + [Parameter(Mandatory=$true)] + [ValidateSet('HTTPS','ICMP','SSO','Provisioning','Any','Remote Console')] + [String]$Service, + [Parameter(Mandatory=$false)] + [ValidateSet('accept')] + $FwAction = 'accept' + + ) + + if ($edge -eq 'Management Gateway') {$EdgeId = 'edge-1'} + elseif ($edge -eq 'Compute Gateway') {$EdgeId = 'edge-2'} + else {Write-Output "No Valid Edge Input Found."} + + $fwRuleSvc = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config.rules + + $ruleElementSpec = $fwRuleSvc.Help.add.firewall_rules.firewall_rules.Element.Create() + $fwRules = $fwRuleSvc.Help.add.firewall_rules.Create() + $ruleSpec = $fwRuleSvc.Help.add.firewall_rules.firewall_rules.Create() + + # AppSpec + $appSpec = $fwRuleSvc.Help.add.firewall_rules.firewall_rules.Element.application.Create() + # ServiceSpec + $serviceSpec = $fwRuleSvc.Help.add.firewall_rules.firewall_rules.Element.application.service.Element.Create() + + if ($Service -eq 'HTTPS') { + $protocol = 'TCP' + $port = @("443") + } + elseif ($Service -eq 'ICMP') { + $protocol = 'ICMP' + $icmpType = 'any' + + } + elseif ($Service -eq 'SSO') { + $protocol = 'TCP' + $port = @("7444") + } + elseif ($Service -eq 'Provisioning') { + $protocol = 'TCP' + $port = @("902") + } + elseif ($Service -eq 'Any') { + $protocol = 'Any' + $port = $null + } + elseif ($Service -eq 'Remote Console') { + $protocol = 'TCP' + $port = @("903") + } + else {Write-Output "No Protocol Found."; break} + + $serviceSpec.protocol = $protocol + + # Process ICMP Type from JSON + $icmpType = $null + if($protocol -eq 'ICMP') { + $icmpType = 'any' + } + + if ($icmpType) { + $serviceSpec.icmp_type = $icmpType} + if ($port) { + $serviceSpec.port = $port + $serviceSpec.source_port = @("any") + } + + $addSpec = $ruleElementSpec.application.service.Add($serviceSpec) + + + # Create Source Spec + if($SourceIpAddress) { + $srcSpec = $fwRuleSvc.Help.add.firewall_rules.firewall_rules.Element.source.Create() + $srcSpec.exclude = $false + $srcSpec.ip_address = @($SourceIpAddress) + $ruleElementSpec.source = $srcSpec + } + + + # Create Destination Spec + if($DestIpAddress) { + $destSpec = $fwRuleSvc.Help.add.firewall_rules.firewall_rules.Element.destination.Create() + $destSpec.exclude = $false + $destSpec.ip_address = @($DestIpAddress) + $ruleElementSpec.destination = $destSpec + + } + + + $ruleElementSpec.rule_type = "user" + $ruleElementSpec.enabled = $true + $ruleElementSpec.logging_enabled = $false + + $ruleElementSpec.action = $FwAction + $ruleElementSpec.name = $FwRuleName + + # Add the individual FW rule spec into our overall firewall rules array + Write-Output "Creating VMC Firewall Rule: $FwRuleName" + $ruleSpecAdd = $ruleSpec.Add($ruleElementSpec) + + $fwRules.firewall_rules = $ruleSpec + $fwRuleAdd = $fwRuleSvc.add($orgId,$sddcId,$EdgeId,$fwRules) + +} + + +# vCenter (ANY) to VPN +Add-VMCFirewallRule -OrgId $org.Id -sddcId $sddc.id -FwRuleName "vCenter (ANY) to $ipsecVPNname" -SourceIpAddress $vcMgmtIP -DestIpAddress $vpnSubnet -Service 'Any' + +# ESXi (ANY) to VPN +Add-VMCFirewallRule -OrgId $org.Id -sddcId $sddc.id -FwRuleName "ESXi (ANY) to $ipsecVPNname" -SourceIpAddress $esxSubnet,'10.2.16.0/20' -DestIpAddress $vpnSubnet -Service 'Any' + +# VPN to vCenter (HTTPS) +Add-VMCFirewallRule -OrgId $org.Id -sddcId $sddc.id -FwRuleName "$ipsecVPNname to vCenter (HTTPS)" -SourceIpAddress $vpnSubnet -DestIpAddress $vcMgmtIP -Service 'HTTPS' + +# VPN to vCenter (ICMP) +Add-VMCFirewallRule -OrgId $org.Id -sddcId $sddc.id -FwRuleName "$ipsecVPNname to vCenter (ICMP)" -SourceIpAddress $vpnSubnet -DestIpAddress $vcMgmtIP -Service 'ICMP' + +# VPN to ESXi (Provisioning) +Add-VMCFirewallRule -OrgId $org.Id -sddcId $sddc.id -FwRuleName "$ipsecVPNname to ESXi (Provisioning)" -SourceIpAddress $vpnSubnet -DestIpAddress $esxSubnet,'10.2.16.0/20' -Service 'Provisioning' + +# VPN to ESXi (Remove Console) +Add-VMCFirewallRule -OrgId $org.Id -sddcId $sddc.id -FwRuleName "$ipsecVPNname to ESXi (Remote Console)" -SourceIpAddress $vpnSubnet -DestIpAddress $esxSubnet,'10.2.16.0/20' -Service 'Remote Console' + +# VPN to ESXi (ICMP) +Add-VMCFirewallRule -OrgId $org.Id -sddcId $sddc.id -FwRuleName "$ipsecVPNname to ESXi (ICMP)" -SourceIpAddress $vpnSubnet -DestIpAddress $esxSubnet,'10.2.16.0/20' -Service 'ICMP' \ No newline at end of file From 7086f2c823000d9aaf3672b1bb4d29159198c2dc Mon Sep 17 00:00:00 2001 From: "Michael D. Harlan" <40269730+r3mdh@users.noreply.github.com> Date: Tue, 28 Aug 2018 00:01:03 -0400 Subject: [PATCH 20/65] Update VMware.HV.Helper.psm1 --- .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 74bf078..57e5b2c 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -3568,30 +3568,35 @@ function New-HVPool { [string[]] $ConnectionServerRestrictions, - #desktopSpec.desktopSettings.logoffSettings.powerPloicy + #desktopSpec.desktopSettings.logoffSettings.powerPolicy [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [ValidateSet('TAKE_NO_POWER_ACTION', 'ALWAYS_POWERED_ON', 'SUSPEND', 'POWER_OFF')] [string]$PowerPolicy = 'TAKE_NO_POWER_ACTION', - #desktopSpec.desktopSettings.logoffSettings.powerPloicy + #desktopSpec.desktopSettings.logoffSettings.powerPolicy + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [ValidateSet('IMMEDIATELY', 'NEVER', 'AFTER')] [string]$AutomaticLogoffPolicy = 'NEVER', #desktopSpec.desktopSettings.logoffSettings.automaticLogoffMinutes + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [ValidateRange(1,[int]::MaxValue)] [int]$AutomaticLogoffMinutes = 120, #desktopSpec.desktopSettings.logoffSettings.allowUsersToResetMachines + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [boolean]$allowUsersToResetMachines = $false, #desktopSpec.desktopSettings.logoffSettings.allowMultipleSessionsPerUser + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [boolean]$allowMultipleSessionsPerUser = $false, #desktopSpec.desktopSettings.logoffSettings.deleteOrRefreshMachineAfterLogoff + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [ValidateSet('NEVER', 'DELETE', 'REFRESH')] [string]$deleteOrRefreshMachineAfterLogoff = 'NEVER', @@ -3612,25 +3617,30 @@ function New-HVPool { #DesktopDisplayProtocolSettings #desktopSpec.desktopSettings.logoffSettings.supportedDisplayProtocols + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [ValidateSet('RDP', 'PCOIP', 'BLAST')] [string[]]$supportedDisplayProtocols = @('RDP', 'PCOIP', 'BLAST'), #desktopSpec.desktopSettings.logoffSettings.defaultDisplayProtocol + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [ValidateSet('RDP', 'PCOIP', 'BLAST')] [string]$defaultDisplayProtocol = 'PCOIP', #desktopSpec.desktopSettings.logoffSettings.allowUsersToChooseProtocol + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [int]$allowUsersToChooseProtocol = $true, #desktopSpec.desktopSettings.logoffSettings.enableHTMLAccess + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [boolean]$enableHTMLAccess = $false, # DesktopPCoIPDisplaySettings #desktopSpec.desktopSettings.logoffSettings.pcoipDisplaySettings.renderer3D + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [ValidateSet('MANAGE_BY_VSPHERE_CLIENT', 'AUTOMATIC', 'SOFTWARE', 'HARDWARE', 'DISABLED')] [string]$renderer3D = 'DISABLED', @@ -3725,7 +3735,7 @@ function New-HVPool { [string] $ResourcePool, - #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.datacenter if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.datacenter 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')] @@ -3739,7 +3749,7 @@ function New-HVPool { [string[]] $Datastores, - #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.datastores.storageOvercommit if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.datastores.storageOvercommit 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')] @@ -3980,7 +3990,8 @@ function New-HVPool { [string] $CustType, - #desktopSpec.automatedDesktopSpec.customizationSettings.reusePreExistingAccounts if LINKED_CLONE + #desktopSpec.automatedDesktopSpec.customizationSettings.reusePreExistingAccounts if LINKED_CLONE, INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] [Boolean] $ReusePreExistingAccounts = $false, @@ -5211,6 +5222,7 @@ function Get-HVPoolCustomizationSetting { throw "No Instant Clone Engine Domain Administrator found with netBiosName: [$netBiosName]" } $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings = Get-CustomizationObject + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.ReusePreExistingAccounts = $reusePreExistingAccounts $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.InstantCloneEngineDomainAdministrator = $instantCloneEngineDomainAdministrator $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.powerOffScriptName = $powerOffScriptName $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.powerOffScriptParameters = $powerOffScriptParameters From 760c534cf74e1418d1fa61e232d6e1ecfd4c6f13 Mon Sep 17 00:00:00 2001 From: Matt Frey Date: Fri, 7 Sep 2018 11:02:42 -0500 Subject: [PATCH 21/65] Update VMware.HV.Helper.psm1 Added -DeleteFromDisk parameter to Remove-HVMachine Performed some minor cleanup (remove trailing whitespaces, capitalization) --- .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 98 +++++++++++-------- 1 file changed, 55 insertions(+), 43 deletions(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 74bf078..58026bb 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -9988,63 +9988,75 @@ function Reset-HVMachine { $services.machine.Machine_ResetMachines($machine.id) } } -function Remove-HVMachine(){ +function Remove-HVMachine { <# .Synopsis - Remove a Horizon View desktop or desktops. - + Remove a Horizon View desktop or desktops. + .DESCRIPTION - Deletes a VM or an array of VM's from Horizon. Utilizes an Or query filter to match machine names. + Deletes a VM or an array of VM's from Horizon. Utilizes an Or query filter to match machine names. .PARAMETER HVServer - The Horizon server where the machine to be deleted resides.Parameter is not mandatory, - but if you do not specify the server, than make sure you are connected to a Horizon server + The Horizon server where the machine to be deleted resides. Parameter is not mandatory, + but if you do not specify the server, than make sure you are connected to a Horizon server first with connect-hvserver. .PARAMETER MachineNames - The name or names of the machine(s) to be deleted. Accepts a single VM or an array of VM names.This is a mandatory parameter. + The name or names of the machine(s) to be deleted. Accepts a single VM or an array of VM names.This is a mandatory parameter. + + .PARAMETER DeleteFromDisk + Determines whether the Machine VM should be deleted from vCenter Server. This is only applicable for managed machines. + This must always be true for machines in linked and instant clone desktops. + This defaults to true for linked and instant clone machines and false for all other types. .EXAMPLE - remove-HVMachine -HVServer 'horizonserver123' -MachineNames 'LAX-WIN10-002' - Deletes VM 'LAX-WIN10-002' from HV Server 'horizonserver123' + Remove-HVMachine -HVServer 'horizonserver123' -MachineNames 'LAX-WIN10-002' + Deletes VM 'LAX-WIN10-002' from HV Server 'horizonserver123' .EXAMPLE - remove-HVMachine -HVServer 'horizonserver123' -MachineNames $machines - Deletes VM's contained within an array of machine names from HV Server 'horizonserver123' - + Remove-HVMachine -HVServer 'horizonserver123' -MachineNames $machines + Deletes VM's contained within an array of machine names from HV Server 'horizonserver123' + + .EXAMPLE + Remove-HVMachine -HVServer 'horizonserver123' -MachineNames 'ManualVM01' -DeleteFromDisk:$false + Deletes VM 'ManualVM01' from Horizon inventory, but not from vSphere. Note this only works for Full Clone VMs. + .NOTES Author : Jose Rodriguez Author email : jrodsguitar@gmail.com Version : 1.0 - + ===Tested Against Environment==== Horizon View Server Version : 7.1.1 PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> - - [CmdletBinding( + + [CmdletBinding( SupportsShouldProcess = $true, ConfirmImpact = 'High' )] - - param( - + + param( + [Parameter(Mandatory = $true)] [array] - $MachineNames, - + $MachineNames, + + [Parameter(Mandatory = $false)] + [switch]$DeleteFromDisk = $true, + [Parameter(Mandatory = $false)] $HVServer = $null - ) + ) #Connect to HV Server $services = Get-ViewAPIService -HVServer $HVServer - - if ($null -eq $services) { - Write-Error "Could not retrieve ViewApi services from connection object" + +if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" break - } + } #Connect to Query Service $queryService = New-Object 'Vmware.Hv.QueryServiceService' @@ -10096,9 +10108,9 @@ $trys = 0 foreach($session in $deleteMachine.base.session){ $sessions = $null - [VMware.Hv.SessionId[]]$sessions += $session - - } + [VMware.Hv.SessionId[]]$sessions += $session + + } try{ @@ -10110,8 +10122,8 @@ $trys = 0 #Wait more for Sessions to end - Start-Sleep -Seconds 5 - + Start-Sleep -Seconds 5 + } catch{ @@ -10121,39 +10133,39 @@ $trys = 0 write-host ($deleteMachine.base.Name -join "`n") start-sleep -seconds 5 - + } - - if(($trys -le 10)){ - + + if(($trys -le 10)){ + write-host "`n" write-host "Retrying Logoffs: $trys times" #Recheck existing sessions $deleteMachine = $machineService.Machine_GetInfos($services,$deleteThisMachine.Id) - + } - - $trys++ + + $trys++ } until((!$deleteMachine.base.session.id) -or ($trys -gt 10)) - + } #Create delete spec for the DeleteMachines method $deleteSpec = [VMware.Hv.MachineDeleteSpec]::new() -$deleteSpec.DeleteFromDisk = $true +$deleteSpec.DeleteFromDisk = $DeleteFromDisk $deleteSpec.ArchivePersistentDisk = $false - + #Delete the machines -write-host "Attempting to Delete:" +write-host "Attempting to Delete:" Write-Output ($deleteMachine.base.Name -join "`n") $bye = $machineService.Machine_DeleteMachines($services,$deleteMachine.id,$deleteSpec) [System.gc]::collect() - -} + +} function get-hvhealth { <# From a753d8251bb756aa3c523302859a95874e87d290 Mon Sep 17 00:00:00 2001 From: AndyG Date: Wed, 12 Sep 2018 13:31:03 -0400 Subject: [PATCH 22/65] Major refactoring Major refactoring - replaced hashtables with classes. Can now accept pipeline input. --- Modules/NSXT/NSXT.psm1 | 342 +++++++++++++++++++++++++++++++---------- 1 file changed, 260 insertions(+), 82 deletions(-) diff --git a/Modules/NSXT/NSXT.psm1 b/Modules/NSXT/NSXT.psm1 index b2f9c3c..d80a565 100644 --- a/Modules/NSXT/NSXT.psm1 +++ b/Modules/NSXT/NSXT.psm1 @@ -259,89 +259,114 @@ Function Get-NSXTManager { $results } -Function Get-NSXTTransportNodes { +Function Get-NSXTTransportNode { Param ( - [parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id","Tranportnode_id")] + [string]$transport_node_id ) - $transport_nodesService = Get-NsxtService -Name "com.vmware.nsx.transport_nodes" - $transport_nodesstateService = Get-NsxtService -Name "com.vmware.nsx.transport_nodes.state" - - if($Id) { - $transport_nodes = $transport_nodesService.get($Id) - } else { - $transport_nodes = $transport_nodesService.list().results - } + begin + { + $NSXTransportNodesService = Get-NsxtService -Name "com.vmware.nsx.transport_nodes" - $results = @() - foreach ($transport_node in $transport_nodes) { - - $transport_nodesstate = $transport_nodesstateService.get("$($transport_node.Id)") - - $tmp = [pscustomobject] @{ - Id = $transport_node.Id; - Name = $transport_node.display_name; - Tags = $transport_node.tags; - MaintenanceMode = $transport_node.maintenance_mode; - HostSwitchesName = $transport_node.host_switches.host_switch_name; - Default_gateway = $transport_nodesstate.host_switch_states.endpointsdefault_gateway; - Device_name = $transport_nodesstate.host_switch_states.endpoints.device_name; - Ip = $transport_nodesstate.host_switch_states.endpoints.ip; - Subnet_mask =$transport_nodesstate.host_switch_states.endpoints.subnet_mask + class NSXTransportNode { + [string]$Name + [string]$Tranport_node_id + [string]$maintenance_mode + hidden $tags = [System.Collections.Generic.List[string]]::new() + hidden $host_switches = [System.Collections.Generic.List[string]]::new() + hidden [string]$host_switch_spec + hidden $transport_zone_endpoints = [System.Collections.Generic.List[string]]::new() } - $results+=$tmp } - $results + Process + { + if($transport_node_id) { + $NSXTransportNodes = $NSXTransportNodesService.get($transport_node_id) + } else { + $NSXTransportNodes = $NSXTransportNodesService.list().results + } + + foreach ($NSXTransportNode in $NSXTransportNodes) { + + $results = [NSXTransportNode]::new() + $results.Name = $NSXTransportNode.display_name; + $results.Tranport_node_id = $NSXTransportNode.Id; + $results.maintenance_mode = $NSXTransportNode.maintenance_mode; + $results.Tags = $NSXTransportNode.tags; + $results.host_switches = $NSXTransportNode.host_switches; + $results.host_switch_spec = $NSXTransportNode.host_switch_spec; + $results.transport_zone_endpoints = $NSXTransportNode.transport_zone_endpoints; + $results.host_switches = $NSXTransportNode.host_switches + write-output $results + } + } } -Function Get-NSXTTraceFlows { +Function Get-NSXTTraceFlow { Param ( - [parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id + [parameter(Mandatory=$false,ValueFromPipeline=$true)] + [Alias("Id")] + [string]$traceflow_id ) $NSXTraceFlowsService = Get-NsxtService -Name "com.vmware.nsx.traceflows" - if($Id) { - $NSXTraceFlows = $NSXTraceFlowsService.get($Id) + if($traceflow_id) { + $NSXTraceFlows = $NSXTraceFlowsService.get($traceflow_id) } else { $NSXTraceFlows = $NSXTraceFlowsService.list().results } - $results = @() - foreach ($NSXTraceFlow in $NSXTraceFlows) { - - $tmp = [pscustomobject] @{ - Id = $NSXTraceFlow.Id; - Operation_State = $NSXTraceFlow.operation_state; - Delivered = $NSXTraceFlow.Counters.delivered_count; - Dropped = $NSXTraceFlow.Counters.dropped_count; - Analysis = $NSXTraceFlow.maintenance_mode; - } - $results+=$tmp + class NSXTraceFlow { + [string]$traceflow_id + hidden [string]$lport_id + [string]$Operation_State + [int]$Forwarded + [int]$Delivered + [int]$Received + [int]$Dropped + [string]$Analysis } - $results - - if ($Id) { - write-output $Id - } + foreach ($NSXTraceFlow in $NSXTraceFlows) { + + $results = [NSXTraceFlow]::new() + $results.traceflow_id = $NSXTraceFlow.Id; + $results.Operation_State = $NSXTraceFlow.operation_state; + $results.forwarded = $NSXTraceFlow.Counters.forwarded_count; + $results.delivered = $NSXTraceFlow.Counters.delivered_count; + $results.received = $NSXTraceFlow.Counters.received_count; + $results.dropped = $NSXTraceFlow.Counters.dropped_count; + $results.analysis = $NSXTraceFlow.analysis + write-output $results + } } Function Get-NSXTTraceFlowObservations { Param ( - [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Id + [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$traceflow_id ) - $NSXTraceFlowsObservService = Get-NsxtService -Name "com.vmware.nsx.traceflows.observations" - - if($Id) { - $NSXTraceFlowsObserv = $NSXTraceFlowsObservService.list($Id) - } else { - throw "TraceFlow ID required" + begin + { + $NSXTraceFlowsObservService = Get-NsxtService -Name "com.vmware.nsx.traceflows.observations" } + + Process + { + if($traceflow_id) { + $NSXTraceFlowsObserv = $NSXTraceFlowsObservService.list($traceflow_id) + } else { + throw "TraceFlow ID required" + } - $NSXTraceFlowsObserv.results | select transport_node_name,component_name,@{N='PacketEvent';E={($_.resource_type).TrimStart("TraceflowObservation")}} + $NSXTraceFlowsObserv.results | select transport_node_name,component_name,@{N='PacketEvent';E={($_.resource_type).TrimStart("TraceflowObservation")}} + } } Function Set-NSXTTraceFlow { @@ -416,36 +441,55 @@ Function Set-NSXTTraceFlow { $NSXTraceFlowsService = Get-NsxtService -Name "com.vmware.nsx.traceflows" - # This is where I need help - the method does not ingest the complete $traceflow_request object! + class ip_header { + [string]$src_ip + [string]$dst_ip + } + + class eth_header { + [string]$src_mac + [string]$dst_mac + } + + class packet_data { + [boolean]$routed + [ValidateSet("UNICAST","BROADCAST","MULTICAST","UNKNOWN")] + [string]$transport_type + [ValidateSet("BINARYPACKETDATA","FIELDSPACKETDATA")] + [string]$resource_type + [long]$frame_size + [eth_header]$eth_header = [eth_header]::new() + [ip_header]$ip_header = [ip_header]::new() - # Create the example object - $traceflow_request = $NSXTraceFlowService.help.create.traceflow_request.Create() - $traceflow_request.lport_id = $LPORTID + packet_data(){ + $this.routed = 'true' + $this.transport_type = 'UNICAST' + $this.resource_type = 'FieldsPacketData' + } + } + + class traceflow_request { + [string]$lport_id + [long]$timeout + [packet_data]$packet = [packet_data]::new() + + traceflow_request(){ + $this.timeout = '15000' + } + } + + [traceflow_request]$traceflow_request = [traceflow_request]::new() + + $traceflow_request.lport_id = '8afcd58a-4bdc-483c-97a5-c5f08df7f772' $traceflow_request.timeout = '15000' $traceflow_request.packet.routed = 'true' - $traceflow_request.packet.transport_type = $TrafficType.ToUpper() + $traceflow_request.packet.transport_type = 'UNICAST' $traceflow_request.packet.resource_type = 'FieldsPacketData' - $traceflow_request.packet.frame_size = '64' - - # The example object is missing packet data, so we create it. - $eth_header = @{src_mac = $SMAC;eth_type = '2048';dst_mac = $DMAC} - $ip_header = @{src_ip = $SIPAddr;protocol = '1';ttl = '64';dst_ip = $DIPAddr} - $traceflow_request.packet | Add-Member -NotePropertyMembers $eth_header -TypeName eth_header - $traceflow_request.packet | Add-Member -NotePropertyMembers $ip_header -TypeName ip_header - - # Alternative method of creating $traceflow_request (not working either) - <# - $TraceFlow_Request = [PSCustomObject]@{ - packet = @{routed = 'true'; - transport_type = $TrafficType.ToUpper(); - ip_header = @{src_ip = $SIPAddr;dst_ip = $DIPAddr}; - eth_header = @{dst_mac = $DMAC;src_mac = $SMAC}; - payload = 'test_payload'; - resource_type = 'FieldsPacketData'}; - timeout = '10000'; - lport_id = $LPORTID - } - #> + $traceflow_request.packet.frame_size = '128' + $traceflow_request.packet.eth_header.src_mac = '00:50:56:b3:90:e3' + $traceflow_request.packet.eth_header.dst_mac = '00:50:56:b3:0e:91' + $traceflow_request.packet.ip_header.src_ip = '15.128.160.20' + $traceflow_request.packet.ip_header.dst_ip = '15.128.160.24' } Process @@ -470,4 +514,138 @@ Function Set-NSXTTraceFlow { Get-NSXttraceflow } } -} \ No newline at end of file +} + +Function Get-NSXTEdgeCluster { + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$edge_cluster_id + ) + + Begin + { + $NSXTEdgeClustersService = Get-NsxtService -Name "com.vmware.nsx.edge_clusters" + + class NSXEdgeCluster { + [string]$Name + hidden [string]$Protection + hidden [string]$Tags + [string]$edge_cluster_id + [string]$resource_type + [string]$deployment_type + [string]$member_node_type + $members = [System.Collections.Generic.List[string]]::new() + $cluster_profile_bindings = [System.Collections.Generic.List[string]]::new() + } + } + + Process + { + if ($edge_cluster_id) { + $NSXEdgeClusters = $NSXTEdgeClustersService.get($edge_cluster_id) + } + else { + $NSXEdgeClusters = $NSXTEdgeClustersService.list().results + } + + foreach ($NSXEdgeCluster in $NSXEdgeClusters) { + + $results = [NSXEdgeCluster]::new() + $results.Name = $NSXEdgeCluster.display_name; + $results.Protection = $NSXEdgeCluster.Protection; + $results.edge_cluster_id = $NSXEdgeCluster.Id; + $results.resource_type = $NSXEdgeCluster.resource_type; + $results.Tags = $NSXEdgeCluster.tags; + $results.deployment_type = $NSXEdgeCluster.deployment_type; + $results.member_node_type = $NSXEdgeCluster.member_node_type; + $results.members = $NSXEdgeCluster.members; + $results.cluster_profile_bindings = $NSXEdgeCluster.cluster_profile_bindings + write-output $results + } + } +} + +Function Get-NSXTLogicalRouter { + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$Logical_router_id + ) + + begin + { + $NSXTLogicalRoutersService = Get-NsxtService -Name "com.vmware.nsx.logical_routers" + + class NSXTLogicalRouter { + [string]$Name + [string]$Logical_router_id + hidden [string]$Tags + [string]$edge_cluster_id + [ValidateSet("TIER0","TIER1")] + [string]$router_type + [ValidateSet("ACTIVE_ACTIVE","ACTIVE_STANDBY","")] + [string]$high_availability_mode + [ValidateSet("PREEMPTIVE","NON_PREEMPTIVE","")] + [string]$failover_mode + [string]$external_transit + [string]$internal_transit + } + } + + Process + { + if($Logical_router_id) { + $NSXLogicalRouters = $NSXTLogicalRoutersService.get($Logical_router_id) + } else { + $NSXLogicalRouters = $NSXTLogicalRoutersService.list().results + } + + foreach ($NSXLogicalRouter in $NSXLogicalRouters) { + + $results = [NSXTLogicalRouter]::new() + $results.Name = $NSXLogicalRouter.display_name; + $results.Logical_router_id = $NSXLogicalRouter.Id; + $results.Tags = $NSXLogicalRouter.tags; + $results.edge_cluster_id = $NSXLogicalRouter.edge_cluster_id; + $results.router_type = $NSXLogicalRouter.router_type; + $results.high_availability_mode = $NSXLogicalRouter.high_availability_mode; + $results.failover_mode =$NSXLogicalRouter.failover_mode; + $results.external_transit = $NSXLogicalRouter.advanced_config.external_transit_networks; + $results.internal_transit = $NSXLogicalRouter.advanced_config.internal_transit_network + write-output $results + } + } +} + +Function Get-NSXTRoutingTable { + Param ( + [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] + [string]$Logical_router_id, + [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] + [string]$Tranport_node_id + ) + + Begin + { + $NSXTRoutingTableService = Get-NsxtService -Name "com.vmware.nsx.logical_routers.routing.route_table" + + class NSXTRoutingTable { + [string]$Name + hidden [string]$Id + hidden $tags = [System.Collections.Generic.List[string]]::new() + #more things need to be added when .list actually works + } + } + + Process + { + $NSXTRoutingTable = [NSXTRoutingTable]::new() + + $NSXTRoutingTable = $NSXTRoutingTableService.list($Logical_router_id, $transport_node_id) + + #$NSXTRoutingTable = $NSXTRoutingTableService.list("ca02cb69-0210-4f34-8164-42943a1cc974","309fda89-3439-40ff-996e-b7eb2ec69ace") + + write-output $NSXTRoutingTable + } +} From 75a2562d974f96625c0d4aff7a8be43849362fb6 Mon Sep 17 00:00:00 2001 From: AndyG Date: Wed, 12 Sep 2018 13:45:38 -0400 Subject: [PATCH 23/65] Updates to Set-NSXTraceFlow Updates to Set-NSXTraceFlow. Added more comment and aligned variable names with api --- Modules/NSXT/NSXT.psm1 | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/Modules/NSXT/NSXT.psm1 b/Modules/NSXT/NSXT.psm1 index d80a565..c68b135 100644 --- a/Modules/NSXT/NSXT.psm1 +++ b/Modules/NSXT/NSXT.psm1 @@ -378,21 +378,21 @@ Function Set-NSXTTraceFlow { ParameterSetName='Parameter Set VM Type')] [ValidateSet("UNICAST")] [string] - $TrafficType = "UNICAST", + $transport_type = "UNICAST", [parameter(Mandatory=$true, ValueFromPipeline=$true, ParameterSetName='Parameter Set VM Type')] [ValidateNotNullOrEmpty()] #[ValidateScript({Get-NSXTLogicalPort -Id $_}] [string] - $LPORTID, + $lport_id, [parameter(Mandatory=$true, ValueFromPipeline=$true, ParameterSetName='Parameter Set VM Type')] [ValidateNotNullOrEmpty()] [ValidateScript({$_ -match [IPAddress]$_})] [string] - $SIPAddr, + $src_ip, [parameter(Mandatory=$true, ValueFromPipeline=$true, ParameterSetName='Parameter Set VM Type')] @@ -403,14 +403,14 @@ Function Set-NSXTTraceFlow { } })] [string] - $SMAC, + $src_mac, [parameter(Mandatory=$true, ValueFromPipeline=$true, ParameterSetName='Parameter Set VM Type')] [ValidateNotNullOrEmpty()] [ValidateScript({$_ -match [IPAddress]$_ })] [string] - $DIPAddr, + $dst_ip, [parameter(Mandatory=$true, ValueFromPipeline=$true, ParameterSetName='Parameter Set VM Type')] @@ -421,7 +421,7 @@ Function Set-NSXTTraceFlow { } })] [string] - $DMAC) + $dst_mac) Begin { @@ -477,26 +477,22 @@ Function Set-NSXTTraceFlow { $this.timeout = '15000' } } - - [traceflow_request]$traceflow_request = [traceflow_request]::new() - - $traceflow_request.lport_id = '8afcd58a-4bdc-483c-97a5-c5f08df7f772' - $traceflow_request.timeout = '15000' - $traceflow_request.packet.routed = 'true' - $traceflow_request.packet.transport_type = 'UNICAST' - $traceflow_request.packet.resource_type = 'FieldsPacketData' - $traceflow_request.packet.frame_size = '128' - $traceflow_request.packet.eth_header.src_mac = '00:50:56:b3:90:e3' - $traceflow_request.packet.eth_header.dst_mac = '00:50:56:b3:0e:91' - $traceflow_request.packet.ip_header.src_ip = '15.128.160.20' - $traceflow_request.packet.ip_header.dst_ip = '15.128.160.24' } Process { + [traceflow_request]$traceflow_request = [traceflow_request]::new() + + $traceflow_request.lport_id = $lport_id + $traceflow_request.packet.transport_type = $transport_type + $traceflow_request.packet.eth_header.src_mac = $src_mac + $traceflow_request.packet.eth_header.dst_mac = $dst_mac + $traceflow_request.packet.ip_header.src_ip = $src_ip + $traceflow_request.packet.ip_header.dst_ip = $dst_ip + try { - # This does not work, ignores eth_header,ip_header etc.. Not clear why!? + # This does not work, bug report submitted to PowerCLI team $NSXTraceFlow = $NSXTraceFlowService.create($traceflow_request) } @@ -509,6 +505,7 @@ Function Set-NSXTTraceFlow { End { + # Likely don't need this and will replace with write-output $NSXTraceFlow but I can't test right now due to bug if ($NSXTraceFlow) { Get-NSXttraceflow @@ -642,10 +639,9 @@ Function Get-NSXTRoutingTable { { $NSXTRoutingTable = [NSXTRoutingTable]::new() + # this does not work, bug report submitted to PowerCLI team $NSXTRoutingTable = $NSXTRoutingTableService.list($Logical_router_id, $transport_node_id) - #$NSXTRoutingTable = $NSXTRoutingTableService.list("ca02cb69-0210-4f34-8164-42943a1cc974","309fda89-3439-40ff-996e-b7eb2ec69ace") - write-output $NSXTRoutingTable } } From c34b602bf327bb7afc98e3266b6966561f8565d9 Mon Sep 17 00:00:00 2001 From: AndyG Date: Fri, 14 Sep 2018 08:58:53 -0400 Subject: [PATCH 24/65] Get-NSXTRoutingTable & Get-NSXTForwardingTable now work Get-NSXTRoutingTable & Get-NSXTForwardingTable now work. Thanks for Nick from VMW for pointing out the .help was incorrect and submitting a PR to update the API guide. --- Modules/NSXT/NSXT.psd1 | 18 ++- Modules/NSXT/NSXT.psm1 | 318 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 322 insertions(+), 14 deletions(-) diff --git a/Modules/NSXT/NSXT.psd1 b/Modules/NSXT/NSXT.psd1 index d9e25bc..01b05f0 100644 --- a/Modules/NSXT/NSXT.psd1 +++ b/Modules/NSXT/NSXT.psd1 @@ -7,7 +7,23 @@ Copyright = '(c) 2017. All rights reserved.' Description = 'Powershell Module for NSX-T REST API Functions' PowerShellVersion = '5.0' - FunctionsToExport = 'Get-NSXTComputeManager','Get-NSXTFabricNode','Get-NSXTFirewallRule','Get-NSXTIPPool','Get-NSXTLogicalSwitch','Get-NSXTManager','Get-NSXTTransportZone','Get-NSXTController','Get-NSXTTransportNodes' + FunctionsToExport = 'Get-NSXTComputeManager', + 'Get-NSXTFabricNode', + 'Get-NSXTFirewallRule', + 'Get-NSXTIPPool', + 'Get-NSXTLogicalSwitch', + 'Get-NSXTManager', + 'Get-NSXTTransportZone', + 'Get-NSXTController', + 'Get-NSXTTransportNodes', + 'Get-NSXTTraceFlow', + 'Get-NSXTEdgeCluster', + 'Get-NSXTLogicalRouter', + 'Get-NSXTRoutingTable', + 'Get-NSXTFabricVM', + 'Get-NSXTBGPNeighbors', + 'Get-NSXTForwardingTable', + 'Get-NSXTNetworkRoutes' PrivateData = @{ PSData = @{ Tags = @('NSX-T','REST') diff --git a/Modules/NSXT/NSXT.psm1 b/Modules/NSXT/NSXT.psm1 index c68b135..bc95e6d 100644 --- a/Modules/NSXT/NSXT.psm1 +++ b/Modules/NSXT/NSXT.psm1 @@ -573,10 +573,18 @@ Function Get-NSXTLogicalRouter { begin { $NSXTLogicalRoutersService = Get-NsxtService -Name "com.vmware.nsx.logical_routers" - + $NSXTLogicalRoutersStatusService = Get-NsxtService -Name "com.vmware.nsx.logical_routers.status" + + class per_node_status { + $service_router_id = [System.Collections.ArrayList]::new() + [ValidateSet("ACTIVE","STANDBY","DOWN","SYNC","UNKNOWN")] + $high_availability_status = [System.Collections.ArrayList]::new() + } + class NSXTLogicalRouter { [string]$Name [string]$Logical_router_id + [string]$protection hidden [string]$Tags [string]$edge_cluster_id [ValidateSet("TIER0","TIER1")] @@ -587,6 +595,9 @@ Function Get-NSXTLogicalRouter { [string]$failover_mode [string]$external_transit [string]$internal_transit + hidden [string]$advanced_config = [System.Collections.Generic.List[string]]::new() + hidden [string]$firewall_sections = [System.Collections.Generic.List[string]]::new() + $per_node_status = [per_node_status]::new() } } @@ -600,16 +611,26 @@ Function Get-NSXTLogicalRouter { foreach ($NSXLogicalRouter in $NSXLogicalRouters) { + $NSXTLogicalRoutersStatus = $NSXTLogicalRoutersStatusService.get($NSXLogicalRouter.id) $results = [NSXTLogicalRouter]::new() + + foreach ($NSXTLogicalRouterStatus in $NSXTLogicalRoutersStatus.per_node_status) { + $results.per_node_status.service_router_id.add($NSXTLogicalRouterStatus.service_router_id) 1>$null + $results.per_node_status.high_availability_status.add($NSXTLogicalRouterStatus.high_availability_status) 1>$null + } + $results.Name = $NSXLogicalRouter.display_name; $results.Logical_router_id = $NSXLogicalRouter.Id; + $results.protection = $NSXLogicalRouter.protection; $results.Tags = $NSXLogicalRouter.tags; $results.edge_cluster_id = $NSXLogicalRouter.edge_cluster_id; $results.router_type = $NSXLogicalRouter.router_type; $results.high_availability_mode = $NSXLogicalRouter.high_availability_mode; $results.failover_mode =$NSXLogicalRouter.failover_mode; $results.external_transit = $NSXLogicalRouter.advanced_config.external_transit_networks; - $results.internal_transit = $NSXLogicalRouter.advanced_config.internal_transit_network + $results.internal_transit = $NSXLogicalRouter.advanced_config.internal_transit_network; + $results.advanced_config =$NSXLogicalRouter.advanced_config; + $results.firewall_sections =$NSXLogicalRouter.firewall_sections write-output $results } } @@ -620,28 +641,299 @@ Function Get-NSXTRoutingTable { [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] [string]$Logical_router_id, [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] - [string]$Tranport_node_id + [string]$transport_node_id ) Begin { $NSXTRoutingTableService = Get-NsxtService -Name "com.vmware.nsx.logical_routers.routing.route_table" - class NSXTRoutingTable { - [string]$Name - hidden [string]$Id - hidden $tags = [System.Collections.Generic.List[string]]::new() - #more things need to be added when .list actually works + class NSXTRoutingTable { + hidden [string]$Logical_router_id + [string]$lr_component_id + [string]$lr_component_type + [string]$network + [string]$next_hop + [string]$route_type + hidden [string]$logical_router_port_id + [long]$admin_distance + } + } + + Process + { + $NSXTRoutingTable = $NSXTRoutingTableService.list($Logical_router_id,$transport_node_id,$null,$null,$null,$null,$null,'realtime') + + foreach ($NSXTRoute in $NSXTRoutingTable.results) { + + $results = [NSXTRoutingTable]::new() + $results.Logical_router_id = $Logical_router_id; + $results.lr_component_type = $NSXTRoute.lr_component_type; + $results.lr_component_id = $NSXTRoute.lr_component_id; + $results.next_hop = $NSXTRoute.next_hop; + $results.route_type = $NSXTRoute.route_type; + $results.logical_router_port_id = $NSXTRoute.logical_router_port_id; + $results.admin_distance = $NSXTRoute.admin_distance; + $results.network = $NSXTRoute.network + write-output $results + } + } +} + +Function Get-NSXTFabricVM { + + Begin + { + $NSXTVMService = Get-NsxtService -Name "com.vmware.nsx.fabric.virtual_machines" + + class NSXVM { + [string]$Name + $resource_type + hidden [string]$Tags + hidden $compute_ids + hidden [string]$external_id + [string]$host_id + [string]$power_state + [string]$type + hidden $source + } + } + + Process + { + + $NSXTVMs = $NSXTVMService.list().results + + foreach ($NSXTVM in $NSXTVMs) { + + $results = [NSXVM]::new() + $results.Name = $NSXTVM.display_name; + $results.resource_type = $NSXTVM.resource_type; + $results.compute_ids = $NSXTVM.compute_ids; + $results.resource_type = $NSXTVM.resource_type; + $results.Tags = $NSXTVM.tags; + $results.external_id = $NSXTVM.external_id; + $results.host_id = $NSXTVM.host_id; + $results.power_state = $NSXTVM.power_state; + $results.type = $NSXTVM.type; + $results.source = $NSXTVM.source + write-output $results + } + } +} + +Function Get-NSXTBGPNeighbors { + Param ( + [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$logical_router_id + ) + + begin + { + $NSXTThingsService = Get-NsxtService -Name "com.vmware.nsx.logical_routers.routing.bgp.neighbors" + + class NSXTBGPNeighbors { + [string]$Name + [string]$logical_router_id + hidden $tags = [System.Collections.Generic.List[string]]::new() + [string]$protection + [string]$resource_type + [string]$address_families = [System.Collections.Generic.List[string]]::new() + hidden $bfd_config + [bool]$enable_bfd + [bool]$enabled + hidden $filter_in_ipprefixlist_id + hidden $filter_in_routemap_id + hidden $filter_out_ipprefixlist_id + hidden $filter_out_routemap_id + hidden [long]$hold_down_timer + hidden [long]$keep_alive_timer + hidden [long]$maximum_hop_limit + [string]$neighbor_address + hidden [string]$password + [long]$remote_as + [string]$remote_as_num + [string]$source_address + [string]$source_addresses = [System.Collections.Generic.List[string]]::new() + } + } + + Process + { + $NSXTThings = $NSXTThingsService.list($logical_router_id).results + + foreach ($NSXTThing in $NSXTThings) { + + $results = [NSXTBGPNeighbors]::new() + $results.Name = $NSXTThing.display_name; + $results.logical_router_id = $NSXTThing.logical_router_id; + $results.tags = $NSXTThing.tags; + $results.protection = $NSXTThing.protection; + $results.resource_type = $NSXTThing.resource_type; + $results.address_families = $NSXTThing.address_families; + $results.bfd_config = $NSXTThing.bfd_config; + $results.enable_bfd = $NSXTThing.enable_bfd; + $results.enabled = $NSXTThing.enabled; + $results.filter_in_ipprefixlist_id = $NSXTThing.filter_in_ipprefixlist_id; + $results.filter_in_routemap_id = $NSXTThing.filter_in_routemap_id; + $results.filter_out_ipprefixlist_id = $NSXTThing.filter_out_ipprefixlist_id; + $results.filter_out_routemap_id = $NSXTThing.filter_out_routemap_id; + $results.hold_down_timer = $NSXTThing.hold_down_timer; + $results.keep_alive_timer = $NSXTThing.keep_alive_timer; + $results.maximum_hop_limit = $NSXTThing.maximum_hop_limit; + $results.neighbor_address = $NSXTThing.neighbor_address; + $results.password = $NSXTThing.password; + $results.remote_as = $NSXTThing.remote_as; + $results.remote_as_num = $NSXTThing.remote_as_num; + $results.source_address = $NSXTThing.source_address; + $results.source_addresses = $NSXTThing.source_addresses + write-output $results + } + } +} + +Function Get-NSXTForwardingTable { + Param ( + [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] + [string]$Logical_router_id, + [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] + [string]$transport_node_id + ) + + Begin + { + $NSXTForwardingTableService = Get-NsxtService -Name "com.vmware.nsx.logical_routers.routing.forwarding_table" + + class NSXTForwardingTable { + hidden [string]$Logical_router_id + [string]$lr_component_id + [string]$lr_component_type + [string]$network + [string]$next_hop + [string]$route_type + hidden [string]$logical_router_port_id } } Process { - $NSXTRoutingTable = [NSXTRoutingTable]::new() + $NSXTForwardingTable = $NSXTForwardingTableService.list($Logical_router_id,$transport_node_id,$null,$null,$null,$null,$null,$null,'realtime') - # this does not work, bug report submitted to PowerCLI team - $NSXTRoutingTable = $NSXTRoutingTableService.list($Logical_router_id, $transport_node_id) - - write-output $NSXTRoutingTable + foreach ($NSXTForwarding in $NSXTForwardingTable.results) { + + $results = [NSXTForwardingTable]::new() + $results.Logical_router_id = $Logical_router_id; + $results.lr_component_type = $NSXTForwarding.lr_component_type; + $results.lr_component_id = $NSXTForwarding.lr_component_id; + $results.network = $NSXTForwarding.network; + $results.next_hop = $NSXTForwarding.next_hop; + $results.route_type = $NSXTForwarding.route_type; + $results.logical_router_port_id = $NSXTForwarding.logical_router_port_id + write-output $results + } } } + + Function Get-NSXTNetworkRoutes { + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [string]$route_id + ) + + Begin + { + $NSXTNetworkRoutesService = Get-NsxtService -Name "com.vmware.nsx.node.network.routes" + + class NSXTNetworkRoutes { + [string]$route_id + $route_type + $interface_id + $gateway + $from_address + $destination + $netmask + $metric + $proto + $scope + $src + } + } + + Process + { + if ($route_id) { + $NSXTNetworkRoutes = $NSXTNetworkRoutesService.get($route_id) + } + else { + $NSXTNetworkRoutes = $NSXTNetworkRoutesService.list().results + } + + foreach ($NSXTRoute in $NSXTNetworkRoutes) { + + $results = [NSXTNetworkRoutes]::new() + $results.route_id = $NSXTRoute.route_id; + $results.route_type = $NSXTRoute.route_type; + $results.interface_id = $NSXTRoute.interface_id; + $results.gateway = $NSXTRoute.gateway; + $results.from_address = $NSXTRoute.from_address; + $results.destination = $NSXTRoute.destination; + $results.netmask = $NSXTRoute.netmask; + $results.metric = $NSXTRoute.metric; + $results.proto = $NSXTRoute.proto; + $results.scope = $NSXTRoute.scope; + $results.src = $NSXTRoute.src + write-output $results + } + } +} + +# Get Template +Function Get-NSXTThingTemplate { + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$Thing_id + ) + + begin + { + $NSXTThingsService = Get-NsxtService -Name "com.vmware.nsx.API.Thing" + + class NSXTThing { + [string]$Name + [string]$Thing1 + hidden [string]$Tags = [System.Collections.Generic.List[string]]::new() + [string]$Thing2 + #[ValidateSet("TIER0","TIER1")] + [string]$Thing3 + #[ValidateSet("ACTIVE_ACTIVE","ACTIVE_STANDBY","")] + [string]$Thing4 + #[ValidateSet("PREEMPTIVE","NON_PREEMPTIVE","")] + [string]$Thing5 + [string]$Thing6 + [string]$Thing7 + } + } + + Process + { + if($Thing_id) { + $NSXTThings = $NSXTThingsService.get($Thing_id) + } else { + $NSXTThings = $NSXTThingsService.list().results + } + + foreach ($NSXTThing in $NSXTThings) { + + $results = [NSXTThing]::new() + $results.Name = $NSXTThing.display_name; + $results.Logical_router_id = $NSXTThing.Id; + $results.Tags = $NSXTThing.tags; + $results.thing1 = $NSXTThing.thing1; + $results.thing2 = $NSXTThing.thing2 + + write-output $results + } + } +} \ No newline at end of file From 2103438f8a74bd2059ed3a5729df87ca237e2b94 Mon Sep 17 00:00:00 2001 From: AndyG Date: Fri, 14 Sep 2018 12:27:31 -0400 Subject: [PATCH 25/65] Added Help & Get-NSXTLogicalRouterPorts Added Help & Get-NSXTLogicalRouterPorts --- Modules/NSXT/NSXT.psd1 | 3 +- Modules/NSXT/NSXT.psm1 | 303 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 275 insertions(+), 31 deletions(-) diff --git a/Modules/NSXT/NSXT.psd1 b/Modules/NSXT/NSXT.psd1 index 01b05f0..46ddd8d 100644 --- a/Modules/NSXT/NSXT.psd1 +++ b/Modules/NSXT/NSXT.psd1 @@ -23,7 +23,8 @@ 'Get-NSXTFabricVM', 'Get-NSXTBGPNeighbors', 'Get-NSXTForwardingTable', - 'Get-NSXTNetworkRoutes' + 'Get-NSXTNetworkRoutes', + 'Get-NSXTLogicalRouterPorts' PrivateData = @{ PSData = @{ Tags = @('NSX-T','REST') diff --git a/Modules/NSXT/NSXT.psm1 b/Modules/NSXT/NSXT.psm1 index bc95e6d..145ba10 100644 --- a/Modules/NSXT/NSXT.psm1 +++ b/Modules/NSXT/NSXT.psm1 @@ -260,6 +260,17 @@ Function Get-NSXTManager { } Function Get-NSXTTransportNode { + <# + .Synopsis + Retrieves the transport_node information + .DESCRIPTION + Retrieves transport_node information for a single or multiple IDs. Execute with no parameters to get all ports, specify a transport_node if known. + .EXAMPLE + Get-NSXTTransportNode + .EXAMPLE + Get-NSXTThingTemplate -Tranport_node_id "TN ID" +#> + Param ( [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] [Alias("Id","Tranportnode_id")] @@ -272,7 +283,7 @@ Function Get-NSXTTransportNode { class NSXTransportNode { [string]$Name - [string]$Tranport_node_id + [string]$Transport_node_id [string]$maintenance_mode hidden $tags = [System.Collections.Generic.List[string]]::new() hidden $host_switches = [System.Collections.Generic.List[string]]::new() @@ -293,19 +304,30 @@ Function Get-NSXTTransportNode { $results = [NSXTransportNode]::new() $results.Name = $NSXTransportNode.display_name; - $results.Tranport_node_id = $NSXTransportNode.Id; + $results.Transport_node_id = $NSXTransportNode.Id; $results.maintenance_mode = $NSXTransportNode.maintenance_mode; $results.Tags = $NSXTransportNode.tags; $results.host_switches = $NSXTransportNode.host_switches; $results.host_switch_spec = $NSXTransportNode.host_switch_spec; $results.transport_zone_endpoints = $NSXTransportNode.transport_zone_endpoints; $results.host_switches = $NSXTransportNode.host_switches - write-output $results + $results } } } Function Get-NSXTTraceFlow { + <# + .Synopsis + Retrieves traceflow information + .DESCRIPTION + Retrieves traceflow information for a single or multiple traceflows. Execute with no parameters to get all traceflows, specify a traceflow_id if known. + .EXAMPLE + Get-NSXTTraceFlow + .EXAMPLE + Get-NSXTTraceFlow -traceflow_id "TF ID +#> + Param ( [parameter(Mandatory=$false,ValueFromPipeline=$true)] [Alias("Id")] @@ -341,11 +363,22 @@ Function Get-NSXTTraceFlow { $results.received = $NSXTraceFlow.Counters.received_count; $results.dropped = $NSXTraceFlow.Counters.dropped_count; $results.analysis = $NSXTraceFlow.analysis - write-output $results + $results } } Function Get-NSXTTraceFlowObservations { + <# + .Synopsis + Retrieves traceflow observations information + .DESCRIPTION + Retrieves traceflow observations information for a single traceflow. Must specify a current traceflow_id + .EXAMPLE + Get-NSXTTraceFlowObservations -traceflow_id "TF ID" + .EXAMPLE + Get-NSXTTraceFlow | Get-NSXTTraceFlowObservations +#> + Param ( [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] [Alias("Id")] @@ -370,6 +403,19 @@ Function Get-NSXTTraceFlowObservations { } Function Set-NSXTTraceFlow { + <# + .Synopsis + Creates a TraceFlow + .DESCRIPTION + Create a TraceFlow for later observation. + .EXAMPLE + Set-NSXTTraceFlow -transport_type "UNICAST" -lport_id "LP ID" -src_ip "IP Address" -src_mac "MAC" -dst_ip "IP Address" -dst_mac "MAC" + .EXAMPLE + Set-NSXTTraceFlow -transport_type "UNICAST" -lport_id "LP ID" -src_ip "IP Address" -src_mac "MAC" -dst_ip "IP Address" -dst_mac "MAC" | Get-NSXTTraceFlow + .EXAMPLE + Set-NSXTTraceFlow -transport_type "UNICAST" -lport_id "LP ID" -src_ip "IP Address" -src_mac "MAC" -dst_ip "IP Address" -dst_mac "MAC" | Get-NSXTTraceFlow | Get-NSXTTraceFlowObservations +#> + [CmdletBinding()] # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types @@ -498,22 +544,28 @@ Function Set-NSXTTraceFlow { catch { - $Error[0].Exception.ServerError.data + throw $Error[0].Exception.ServerError.data # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. Filter by MONITORING. } - } - End - { - # Likely don't need this and will replace with write-output $NSXTraceFlow but I can't test right now due to bug - if ($NSXTraceFlow) - { - Get-NSXttraceflow - } + $NSXTraceFlow } } Function Get-NSXTEdgeCluster { + <# + .Synopsis + Retrieves the Edge cluster information + .DESCRIPTION + Retrieves Edge cluster information for a single or multiple clusterss. Execute with no parameters to get all ports, specify a edge_cluster_id if known. + .EXAMPLE + Get-NSXTEdgeCluster + .EXAMPLE + Get-NSXTEdgeCluster -edge_cluster_id "Edge Cluster ID" + .EXAMPLE + Get-NSXTThingTemplate | where name -eq "My Edge Cluster Name" +#> + Param ( [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] [Alias("Id")] @@ -558,12 +610,27 @@ Function Get-NSXTEdgeCluster { $results.member_node_type = $NSXEdgeCluster.member_node_type; $results.members = $NSXEdgeCluster.members; $results.cluster_profile_bindings = $NSXEdgeCluster.cluster_profile_bindings - write-output $results + $results } } } Function Get-NSXTLogicalRouter { + <# + .Synopsis + Retrieves the Logical Router information + .DESCRIPTION + Retrieves Logical Router information for a single or multiple LR's. This includes corresponding SR's and transport_node_id. Execute with no parameters to get all ports, specify a Logical_router_id if known. + .EXAMPLE + Get-NSXTLogicalRouter + .EXAMPLE + Get-NSXTLogicalRouter -Logical_router_id "LR ID" + .EXAMPLE + Get-NSXTLogicalRouter | where name -eq "LR Name" + .EXAMPLE + (Get-NSXTLogicalRouter -Logical_router_id "LR ID").per_node_status +#> + Param ( [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] [Alias("Id")] @@ -576,9 +643,22 @@ Function Get-NSXTLogicalRouter { $NSXTLogicalRoutersStatusService = Get-NsxtService -Name "com.vmware.nsx.logical_routers.status" class per_node_status { - $service_router_id = [System.Collections.ArrayList]::new() + $service_router_id [ValidateSet("ACTIVE","STANDBY","DOWN","SYNC","UNKNOWN")] - $high_availability_status = [System.Collections.ArrayList]::new() + $high_availability_status + $transport_node_id + + per_node_status(){} + + per_node_status( + $service_router_id, + $high_availability_status, + $transport_node_id + ) { + $this.service_router_id = $service_router_id + $this.high_availability_status = $high_availability_status + $this.transport_node_id = $transport_node_id + } } class NSXTLogicalRouter { @@ -597,7 +677,7 @@ Function Get-NSXTLogicalRouter { [string]$internal_transit hidden [string]$advanced_config = [System.Collections.Generic.List[string]]::new() hidden [string]$firewall_sections = [System.Collections.Generic.List[string]]::new() - $per_node_status = [per_node_status]::new() + $per_node_status = [System.Collections.Generic.List[string]]::new() } } @@ -613,10 +693,9 @@ Function Get-NSXTLogicalRouter { $NSXTLogicalRoutersStatus = $NSXTLogicalRoutersStatusService.get($NSXLogicalRouter.id) $results = [NSXTLogicalRouter]::new() - + foreach ($NSXTLogicalRouterStatus in $NSXTLogicalRoutersStatus.per_node_status) { - $results.per_node_status.service_router_id.add($NSXTLogicalRouterStatus.service_router_id) 1>$null - $results.per_node_status.high_availability_status.add($NSXTLogicalRouterStatus.high_availability_status) 1>$null + $results.per_node_status += [per_node_status]::new($NSXTLogicalRouterStatus.service_router_id,$NSXTLogicalRouterStatus.high_availability_status,$NSXTLogicalRouterStatus.transport_node_id) } $results.Name = $NSXLogicalRouter.display_name; @@ -631,12 +710,27 @@ Function Get-NSXTLogicalRouter { $results.internal_transit = $NSXLogicalRouter.advanced_config.internal_transit_network; $results.advanced_config =$NSXLogicalRouter.advanced_config; $results.firewall_sections =$NSXLogicalRouter.firewall_sections - write-output $results + $results } } } Function Get-NSXTRoutingTable { + <# + .Synopsis + Retrieves the routing table information + .DESCRIPTION + Retrieves routing table for a single LR including LR type (SR/DR) and next_hop. Must specify Logical_router_id & transport_node_id. Pipeline input supported. + .EXAMPLE + Get-NSXTRoutingTable -Logical_router_id "LR ID" -transport_node_id "TN ID" | format-table -autosize + .EXAMPLE + Get-NSXTLogicalRouter | where name -eq "LR Name" | Get-NSXTRoutingTable -transport_node_id "TN ID" + .EXAMPLE + Get-NSXTLogicalRouter | where name -eq INT-T1 | Get-NSXTRoutingTable -transport_node_id ((Get-NSXTTransportNode | where name -match "INT")[0].transport_node_id) + .EXAMPLE + Get-NSXTLogicalRouter | where name -eq INT-T1 | Get-NSXTRoutingTable -transport_node_id (((Get-NSXTLogicalRouter | where name -eq INT-T1).per_node_status | where high_availability_status -eq ACTIVE).transport_node_id) +#> + Param ( [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] [string]$Logical_router_id, @@ -675,13 +769,20 @@ Function Get-NSXTRoutingTable { $results.logical_router_port_id = $NSXTRoute.logical_router_port_id; $results.admin_distance = $NSXTRoute.admin_distance; $results.network = $NSXTRoute.network - write-output $results + $results } } } Function Get-NSXTFabricVM { - + <# + .Synopsis + Retrieves the VM's attached to the fabric. + .DESCRIPTION + Retrieves all VM's attached to the fabric. + .EXAMPLE + Get-NSXTFabricVM +#> Begin { $NSXTVMService = Get-NsxtService -Name "com.vmware.nsx.fabric.virtual_machines" @@ -717,12 +818,23 @@ Function Get-NSXTFabricVM { $results.power_state = $NSXTVM.power_state; $results.type = $NSXTVM.type; $results.source = $NSXTVM.source - write-output $results + $results } } } Function Get-NSXTBGPNeighbors { + <# + .Synopsis + Retrieves the BGP neighbor information + .DESCRIPTION + Retrieves BGP neighbor information for a single logical router. Must specify logical_router_id parameter. Pipeline input supported + .EXAMPLE + Get-NSXTBGPNeighbors -logical_router_id "LR ID" + .EXAMPLE + Get-NSXTLogicalRouter | where name -eq "LR Name" | Get-NSXTBGPNeighbors +#> + Param ( [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] [Alias("Id")] @@ -788,12 +900,27 @@ Function Get-NSXTBGPNeighbors { $results.remote_as_num = $NSXTThing.remote_as_num; $results.source_address = $NSXTThing.source_address; $results.source_addresses = $NSXTThing.source_addresses - write-output $results + $results } } } Function Get-NSXTForwardingTable { + <# + .Synopsis + Retrieves the forwarding table information + .DESCRIPTION + Retrieves forwarding table for a single LR including LR type (SR/DR) and next_hop. Must specify Logical_router_id & transport_node_id. Pipeline input supported. + .EXAMPLE + Get-Get-NSXTForwardingTable -Logical_router_id "LR ID" -transport_node_id "TN ID" | format-table -autosize + .EXAMPLE + Get-NSXTLogicalRouter | where name -eq "LR Name" | Get-NSXTForwardingTable -transport_node_id "TN ID" + .EXAMPLE + Get-NSXTLogicalRouter | where name -eq "LR Name" | Get-NSXTForwardingTable -transport_node_id ((Get-NSXTTransportNode | where name -match "Edge Name")[0].transport_node_id) + .EXAMPLE + Get-NSXTLogicalRouter | where name -eq "LR Name" | Get-NSXTForwardingTable -transport_node_id (((Get-NSXTLogicalRouter | where name -eq "Edge Name").per_node_status | where high_availability_status -eq ACTIVE).transport_node_id) +#> + Param ( [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] [string]$Logical_router_id, @@ -830,12 +957,23 @@ Function Get-NSXTForwardingTable { $results.next_hop = $NSXTForwarding.next_hop; $results.route_type = $NSXTForwarding.route_type; $results.logical_router_port_id = $NSXTForwarding.logical_router_port_id - write-output $results + $results } } } - Function Get-NSXTNetworkRoutes { +Function Get-NSXTNetworkRoutes { +<# + .Synopsis + Retrieves the network routes information + .DESCRIPTION + Retrieves the network routes information for a single or multiple routes. + .EXAMPLE + Get-NSXTNetworkRoutes + .EXAMPLE + Get-NSXTNetworkRoutes -route_id "Route ID" +#> + Param ( [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] [string]$route_id @@ -883,13 +1021,118 @@ Function Get-NSXTForwardingTable { $results.proto = $NSXTRoute.proto; $results.scope = $NSXTRoute.scope; $results.src = $NSXTRoute.src - write-output $results + $results } } } +Function Get-NSXTLogicalRouterPorts { +<# + .Synopsis + Retrieves the logical router port information + .DESCRIPTION + Retrieves logical router port information for a single or multiple ports. Execute with no parameters to get all ports, specify a single port if known, or feed a logical switch for filtered output. + .EXAMPLE + Get-NSXTLogicalRouterPorts + .EXAMPLE + Get-NSXTLogicalRouterPorts -logical_router_port_id "LR Port Name" + .EXAMPLE + Get-NSXTLogicalRouterPorts -logical_router_id "LR Name" + .EXAMPLE + Get-NSXTLogicalRouterPorts -logical_router_id (Get-NSXTLogicalRouter | where name -eq "LR Name") +#> + + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$logical_router_port_id, + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [string]$logical_router_id + ) + + begin + { + $NSXTLogicalRouterPortsService = Get-NsxtService -Name "com.vmware.nsx.logical_router_ports" + + class subnets { + $ip_addresses + $prefix_length + + subnets(){} + + subnets( + $ip_addresses, + $prefix_length + ) { + $this.ip_addresses = $ip_addresses + $this.prefix_length = $prefix_length + } + } + + class NSXTLogicalRouterPorts { + [string]$Name + $Id + [string]$logical_router_id + $resource_type + [string]$protection + $mac_address + $subnets = [System.Collections.Generic.List[string]]::new() + hidden [string]$Tags + hidden $linked_logical_switch_port_id + } + } + + Process + { + if($logical_router_port_id) { + $NSXTLogicalRouterPorts = $NSXTLogicalRouterPortsService.get($logical_router_port_id) + } else { + if ($logical_router_id) { + $NSXTLogicalRouterPorts = $NSXTLogicalRouterPortsService.list().results | where {$_.logical_router_id -eq $Logical_router_id} + } + else { + $NSXTLogicalRouterPorts = $NSXTLogicalRouterPortsService.list().results + } + } + + foreach ($NSXTLogicalRouterPort in $NSXTLogicalRouterPorts) { + + $results = [NSXTLogicalRouterPorts]::new() + + foreach ($subnet in $NSXTLogicalRouterPort.subnets) { + $results.subnets += [subnets]::new($subnet.ip_addresses,$subnet.prefix_length) + } + + $results.Name = $NSXTLogicalRouterPort.display_name + $results.Id = $NSXTLogicalRouterPort.Id + $results.Logical_router_id = $NSXTLogicalRouterPort.Logical_router_id + $results.resource_type = $NSXTLogicalRouterPort.resource_type + $results.protection = $NSXTLogicalRouterPort.protection + $results.Tags = $NSXTLogicalRouterPort.tags + $results.mac_address = $NSXTLogicalRouterPort.mac_address + $results.linked_logical_switch_port_id = $NSXTLogicalRouterPort.linked_logical_switch_port_id + $results + } + } +} + # Get Template Function Get-NSXTThingTemplate { + <# + .Synopsis + Retrieves the THING information + .DESCRIPTION + Retrieves THING information for a single or multiple ports. Execute with no parameters to get all ports, specify a PARAM if known. + .EXAMPLE + Get-NSXTThingTemplate + .EXAMPLE + Get-NSXTThingTemplate -param1 "LR Port Name" + .EXAMPLE + Get-NSXTThingTemplate -param2 "LR Name" + .EXAMPLE + Get-NSXTThingTemplate -param2 (Get-NSXTLogicalRouter | where name -eq "LR Name") +#> + Param ( [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] [Alias("Id")] @@ -933,7 +1176,7 @@ Function Get-NSXTThingTemplate { $results.thing1 = $NSXTThing.thing1; $results.thing2 = $NSXTThing.thing2 - write-output $results + $results } } -} \ No newline at end of file +} From 9a4acf5c57445e90cde776f3b17cf3887915e888 Mon Sep 17 00:00:00 2001 From: AndyG Date: Fri, 14 Sep 2018 15:51:11 -0400 Subject: [PATCH 26/65] Adding Set Commands Adding Set Commands --- Modules/NSXT/NSXT.psd1 | 32 +- Modules/NSXT/NSXT.psm1 | 994 +++++++++++++++++++++++++++++++---------- 2 files changed, 773 insertions(+), 253 deletions(-) diff --git a/Modules/NSXT/NSXT.psd1 b/Modules/NSXT/NSXT.psd1 index 46ddd8d..1ebab1e 100644 --- a/Modules/NSXT/NSXT.psd1 +++ b/Modules/NSXT/NSXT.psd1 @@ -7,24 +7,32 @@ Copyright = '(c) 2017. All rights reserved.' Description = 'Powershell Module for NSX-T REST API Functions' PowerShellVersion = '5.0' - FunctionsToExport = 'Get-NSXTComputeManager', + FunctionsToExport = 'Get-NSXTBGPNeighbors', + 'Get-NSXTComputeManager', + 'Get-NSXTController', + 'Get-NSXTEdgeCluster', 'Get-NSXTFabricNode', + 'Get-NSXTFabricVM', 'Get-NSXTFirewallRule', + 'Get-NSXTForwardingTable', 'Get-NSXTIPPool', + 'Get-NSXTLogicalRouter', + 'Get-NSXTLogicalRouterPorts', 'Get-NSXTLogicalSwitch', 'Get-NSXTManager', - 'Get-NSXTTransportZone', - 'Get-NSXTController', - 'Get-NSXTTransportNodes', - 'Get-NSXTTraceFlow', - 'Get-NSXTEdgeCluster', - 'Get-NSXTLogicalRouter', - 'Get-NSXTRoutingTable', - 'Get-NSXTFabricVM', - 'Get-NSXTBGPNeighbors', - 'Get-NSXTForwardingTable', 'Get-NSXTNetworkRoutes', - 'Get-NSXTLogicalRouterPorts' + 'Get-NSXTRoutingTable', + 'Get-NSXTThingTemplate', + 'Get-NSXTTraceFlow', + 'Get-NSXTTraceFlowObservations', + 'Get-NSXTTransportNode', + 'Get-NSXTTransportZone', + 'Set-NSXTIPPool', + 'Set-NSXTLogicalRouter', + 'Set-NSXTLogicalSwitch', + 'Set-NSXTThingTemplate', + 'Set-NSXTTraceFlow' + PrivateData = @{ PSData = @{ Tags = @('NSX-T','REST') diff --git a/Modules/NSXT/NSXT.psm1 b/Modules/NSXT/NSXT.psm1 index 145ba10..aa30c32 100644 --- a/Modules/NSXT/NSXT.psm1 +++ b/Modules/NSXT/NSXT.psm1 @@ -71,63 +71,6 @@ Function Get-NSXTFabricNode { $results } -Function Get-NSXTIPPool { - Param ( - [parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id - ) - - $ipPoolService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_pools" - - if($Id) { - $ipPools = $ipPoolService.get($Id) - } else { - $ipPools = $ipPoolService.list().results - } - - $results = @() - foreach ($ipPool in $ipPools) { - $tmp = [pscustomobject] @{ - Id = $ipPool.Id; - Name = $ipPool.Display_Name; - Total = $ipPool.pool_usage.total_ids; - Free = $ipPool.pool_usage.free_ids; - Network = $ipPool.subnets.cidr; - Gateway = $ipPool.subnets.gateway_ip; - DNS = $ipPool.subnets.dns_nameservers; - RangeStart = $ipPool.subnets.allocation_ranges.start; - RangeEnd = $ipPool.subnets.allocation_ranges.end - } - $results+=$tmp - } - $results -} - -Function Get-NSXTTransportZone { - Param ( - [parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id - ) - - $transportZoneService = Get-NsxtService -Name "com.vmware.nsx.transport_zones" - - if($Id) { - $transportZones = $transportZoneService.get($Id) - } else { - $transportZones = $transportZoneService.list().results - } - - $results = @() - foreach ($transportZone in $transportZones) { - $tmp = [pscustomobject] @{ - Id = $transportZone.Id; - Name = $transportZone.display_name; - Type = $transportZone.transport_type; - HostSwitchName = $transportZone.host_switch_name; - } - $results+=$tmp - } - $results -} - Function Get-NSXTComputeManager { Param ( [parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id @@ -160,38 +103,6 @@ Function Get-NSXTComputeManager { $results } -Function Get-NSXTLogicalSwitch { - Param ( - [parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id - ) - - $logicalSwitchService = Get-NsxtService -Name "com.vmware.nsx.logical_switches" - $logicalSwitchSummaryService = Get-NsxtService -Name "com.vmware.nsx.logical_switches.summary" - - if($Id) { - $logicalSwitches = $logicalSwitchService.get($Id) - } else { - $logicalSwitches = $logicalSwitchService.list().results - } - - $results = @() - foreach ($logicalSwitch in $logicalSwitches) { - $transportZone = (Get-NSXTTransportZone -Id $logicalSwitch.transport_zone_id | Select Name | ft -HideTableHeaders | Out-String).trim() - $ports = $logicalSwitchSummaryService.get($logicalSwitch.id).num_logical_ports - - $tmp = [pscustomobject] @{ - Id = $logicalSwitch.Id; - Name = $logicalSwitch.display_name; - VLAN = $logicalSwitch.vlan; - AdminStatus = $logicalSwitch.admin_state; - Ports = $ports; - TransportZone = $transportZone; - } - $results+=$tmp - } - $results -} - Function Get-NSXTFirewallRule { Param ( [parameter(Mandatory=$false,ValueFromPipeline=$true)][string]$Id @@ -259,6 +170,8 @@ Function Get-NSXTManager { $results } +# Updated Function style below + Function Get-NSXTTransportNode { <# .Synopsis @@ -402,156 +315,6 @@ Function Get-NSXTTraceFlowObservations { } } -Function Set-NSXTTraceFlow { - <# - .Synopsis - Creates a TraceFlow - .DESCRIPTION - Create a TraceFlow for later observation. - .EXAMPLE - Set-NSXTTraceFlow -transport_type "UNICAST" -lport_id "LP ID" -src_ip "IP Address" -src_mac "MAC" -dst_ip "IP Address" -dst_mac "MAC" - .EXAMPLE - Set-NSXTTraceFlow -transport_type "UNICAST" -lport_id "LP ID" -src_ip "IP Address" -src_mac "MAC" -dst_ip "IP Address" -dst_mac "MAC" | Get-NSXTTraceFlow - .EXAMPLE - Set-NSXTTraceFlow -transport_type "UNICAST" -lport_id "LP ID" -src_ip "IP Address" -src_mac "MAC" -dst_ip "IP Address" -dst_mac "MAC" | Get-NSXTTraceFlow | Get-NSXTTraceFlowObservations -#> - - [CmdletBinding()] - - # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types - Param ( - [parameter(Mandatory=$true, - ParameterSetName='Parameter Set VM Type')] - [ValidateSet("UNICAST")] - [string] - $transport_type = "UNICAST", - [parameter(Mandatory=$true, - ValueFromPipeline=$true, - ParameterSetName='Parameter Set VM Type')] - [ValidateNotNullOrEmpty()] - #[ValidateScript({Get-NSXTLogicalPort -Id $_}] - [string] - $lport_id, - [parameter(Mandatory=$true, - ValueFromPipeline=$true, - ParameterSetName='Parameter Set VM Type')] - [ValidateNotNullOrEmpty()] - [ValidateScript({$_ -match [IPAddress]$_})] - [string] - $src_ip, - [parameter(Mandatory=$true, - ValueFromPipeline=$true, - ParameterSetName='Parameter Set VM Type')] - [ValidateNotNullOrEmpty()] - [ValidateScript({$pattern = '^(([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2}))|(([0-9A-Fa-f]{2}[-]){5}([0-9A-Fa-f]{2}))$' - if ($_ -match ($pattern -join '|')) {$true} else { - throw "The argument '$_' does not match a valid MAC address format." - } - })] - [string] - $src_mac, - [parameter(Mandatory=$true, - ValueFromPipeline=$true, - ParameterSetName='Parameter Set VM Type')] - [ValidateNotNullOrEmpty()] - [ValidateScript({$_ -match [IPAddress]$_ })] - [string] - $dst_ip, - [parameter(Mandatory=$true, - ValueFromPipeline=$true, - ParameterSetName='Parameter Set VM Type')] - [ValidateNotNullOrEmpty()] - [ValidateScript({$pattern = '^(([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2}))|(([0-9A-Fa-f]{2}[-]){5}([0-9A-Fa-f]{2}))$' - if ($_ -match ($pattern -join '|')) {$true} else { - throw "The argument '$_' does not match a valid MAC address format." - } - })] - [string] - $dst_mac) - - Begin - { - if (-not $global:DefaultNsxtServers.isconnected) - { - - try - { - Connect-NsxtServer -Menu -ErrorAction Stop - } - - catch - { - throw "Could not connect to an NSX-T Manager, please try again" - } - } - - $NSXTraceFlowsService = Get-NsxtService -Name "com.vmware.nsx.traceflows" - - class ip_header { - [string]$src_ip - [string]$dst_ip - } - - class eth_header { - [string]$src_mac - [string]$dst_mac - } - - class packet_data { - [boolean]$routed - [ValidateSet("UNICAST","BROADCAST","MULTICAST","UNKNOWN")] - [string]$transport_type - [ValidateSet("BINARYPACKETDATA","FIELDSPACKETDATA")] - [string]$resource_type - [long]$frame_size - [eth_header]$eth_header = [eth_header]::new() - [ip_header]$ip_header = [ip_header]::new() - - packet_data(){ - $this.routed = 'true' - $this.transport_type = 'UNICAST' - $this.resource_type = 'FieldsPacketData' - } - } - - class traceflow_request { - [string]$lport_id - [long]$timeout - [packet_data]$packet = [packet_data]::new() - - traceflow_request(){ - $this.timeout = '15000' - } - } - } - - Process - { - [traceflow_request]$traceflow_request = [traceflow_request]::new() - - $traceflow_request.lport_id = $lport_id - $traceflow_request.packet.transport_type = $transport_type - $traceflow_request.packet.eth_header.src_mac = $src_mac - $traceflow_request.packet.eth_header.dst_mac = $dst_mac - $traceflow_request.packet.ip_header.src_ip = $src_ip - $traceflow_request.packet.ip_header.dst_ip = $dst_ip - - try - { - # This does not work, bug report submitted to PowerCLI team - $NSXTraceFlow = $NSXTraceFlowService.create($traceflow_request) - } - - catch - { - throw $Error[0].Exception.ServerError.data - # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. Filter by MONITORING. - } - - $NSXTraceFlow - } -} - Function Get-NSXTEdgeCluster { <# .Synopsis @@ -1116,6 +879,660 @@ Function Get-NSXTLogicalRouterPorts { } } +Function Get-NSXTTransportZone { + <# + .Synopsis + Retrieves the Transport Zone information + .DESCRIPTION + Retrieves THING information for a single or multiple ports. Execute with no parameters to get all ports, specify a PARAM if known. + .EXAMPLE + Get-NSXTTransportZone + .EXAMPLE + Get-NSXTTransportZone -zone_id "Zone ID" + .EXAMPLE + Get-NSXTTransportZone -name "Zone1" +#> + + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$zone_id, + [parameter(Mandatory=$false)] + [string]$name + ) + + begin + { + $NSXTTransportZoneService = Get-NsxtService -Name "com.vmware.nsx.transport_zones" + + class NSXTTransportZone { + [string]$Name + [string]$ID + hidden [string]$description + hidden $tags + $resource_type + $host_switch_name + $transport_type + hidden $transport_zone_profile_ids + $host_switch_mode + $protection + hidden $uplink_teaming_policy_names + } + } + + Process + { + if($zone_id) { + $NSXTTransportZones = $NSXTTransportZoneService.get($zone_id) + } else { + if ($name) { + $NSXTTransportZones = $NSXTTransportZoneService.list().results | where {$_.display_name -eq $name} + } + else { + $NSXTTransportZones = $NSXTTransportZoneService.list().results + } + } + + foreach ($NSXTTransportZone in $NSXTTransportZones) { + + $results = [NSXTTransportZone]::new() + $results.Name = $NSXTTransportZone.display_name; + $results.ID = $NSXTTransportZone.Id; + $results.description = $NSXTTransportZone.description; + $results.tags = $NSXTTransportZone.tags; + $results.resource_type = $NSXTTransportZone.resource_type; + $results.host_switch_name = $NSXTTransportZone.host_switch_name; + $results.transport_type = $NSXTTransportZone.transport_type; + $results.transport_zone_profile_ids = $NSXTTransportZone.transport_zone_profile_ids; + $results.host_switch_mode = $NSXTTransportZone.host_switch_mode; + $results.protection = $NSXTTransportZone.protection; + $results.uplink_teaming_policy_names = $NSXTTransportZone.uplink_teaming_policy_names + $results + } + } +} + +Function Get-NSXTLogicalSwitch { + <# + .Synopsis + Retrieves the Logical Switch information + .DESCRIPTION + Retrieves Logical Switch information for a single or multiple switches. Execute with no parameters to get all ports, specify a name or lswitch_id if known. + .EXAMPLE + Get-NSXTLogicalSwitch + .EXAMPLE + Get-NSXTLogicalSwitch -lswitch_id "switch id" + .EXAMPLE + Get-NSXTLogicalSwitch -name "switch name" +#> + + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$lswitch_id, + [parameter(Mandatory=$false)] + [string]$name + ) + + begin + { + $NSXTLogicalSwitchService = Get-NsxtService -Name "com.vmware.nsx.logical_switches" + + class NSXTLogicalSwitch { + [string]$Name + [string]$ID + $tags + $resource_type + hidden $description + $vni + $transport_zone_id + $admin_state + $replication_mode + hidden $address_bindings + $protection + hidden $extra_configs + $ip_pool_id + hidden $mac_pool_id + hidden $uplink_teaming_policy_name + hidden $vlan + hidden $vlan_trunk_spec + } + } + + Process + { + if($lswitch_id) { + $NSXTLogicalSwitches = $NSXTLogicalSwitchService.get($lswitch_id) + } else { + if ($name) { + $NSXTLogicalSwitches = $NSXTLogicalSwitchService.list().results | where {$_.display_name -eq $name} + } + else { + $NSXTLogicalSwitches = $NSXTLogicalSwitchService.list().results + } + } + + foreach ($NSXTLogicalSwitch in $NSXTLogicalSwitches) { + + $results = [NSXTLogicalSwitch]::new() + $results.Name = $NSXTLogicalSwitch.display_name; + $results.Id = $NSXTLogicalSwitch.Id; + $results.Tags = $NSXTLogicalSwitch.tags; + $results.resource_type = $NSXTLogicalSwitch.resource_type; + $results.description = $NSXTLogicalSwitch.description; + $results.vni = $NSXTLogicalSwitch.vni; + $results.transport_zone_id = $NSXTLogicalSwitch.transport_zone_id; + $results.admin_state = $NSXTLogicalSwitch.admin_state; + $results.replication_mode = $NSXTLogicalSwitch.replication_mode; + $results.address_bindings = $NSXTLogicalSwitch.address_bindings; + $results.protection = $NSXTLogicalSwitch.protection; + $results.extra_configs = $NSXTLogicalSwitch.extra_configs; + $results.ip_pool_id = $NSXTLogicalSwitch.ip_pool_id; + $results.mac_pool_id = $NSXTLogicalSwitch.mac_pool_id; + $results.uplink_teaming_policy_name = $NSXTLogicalSwitch.uplink_teaming_policy_name; + $results.vlan = $NSXTLogicalSwitch.vlan; + $results.vlan_trunk_spec = $NSXTLogicalSwitch.vlan_trunk_spec + $results + } + } +} + +Function Get-NSXTIPPool { + <# + .Synopsis + Retrieves the THING information + .DESCRIPTION + Retrieves THING information for a single or multiple ports. Execute with no parameters to get all ports, specify a PARAM if known. + .EXAMPLE + Get-NSXTIPPool + .EXAMPLE + Get-NSXTThingTemplate -pool_id "Pool ID" +#> + + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$pool_id, + [parameter(Mandatory=$false)] + [string]$name + ) + + begin + { + $NSXTIPPoolService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_pools" + + class NSXTIPPool { + [string]$Name + [string]$id + $total_ids + $free_ids + $allocated_ids + $Network + $Gateway + $DNS + $RangeStart + $RangeEnd + } + } + + Process + { + if($pool_id) { + $NSXTIPPools = $NSXTIPPoolService.get($pool_id) + } else { + if ($name) { + $NSXTIPPools = $NSXTIPPoolService.list().results | where {$_.display_name -eq $name} + } + else { + $NSXTIPPools = $NSXTIPPoolService.list().results + } + } + + foreach ($NSXTIPPool in $NSXTIPPools) { + + $results = [NSXTIPPool]::new() + $results.Name = $NSXTIPPool.display_name; + $results.ID = $NSXTIPPool.id; + $results.total_ids = $NSXTIPPool.pool_usage.total_ids; + $results.free_ids = $NSXTIPPool.pool_usage.free_ids; + $results.allocated_ids = $NSXTIPPool.pool_usage.allocated_ids; + $results.Network = $NSXTIPPool.subnets.cidr; + $results.Gateway = $NSXTIPPool.subnets.gateway_ip; + $results.DNS = $NSXTIPPool.subnets.dns_nameservers; + $results.RangeStart = $NSXTIPPool.subnets.allocation_ranges.start; + $results.RangeEnd = $NSXTIPPool.subnets.allocation_ranges.end + $results + } + } +} + +# Working Set Functions +Function Set-NSXTLogicalRouter { + <# + .Synopsis + Creates a Logical Router + .DESCRIPTION + Create a TIER0 or TIER1 logical router + .EXAMPLE + Set-NSXTLogicalRouter -display_name "Name" -high_availability_mode "ACTIVE_STANDBY" -router_type "TIER1" + .EXAMPLE + Set-NSXTLogicalRouter -display_name "Name" -high_availability_mode "ACTIVE_ACTIVE" -router_type "TIER0" -edge_cluster_id "Edge Cluster ID" + .EXAMPLE + Set-NSXTLogicalRouter -display_name "Name" -high_availability_mode "ACTIVE_STANDBY" -router_type "TIER1" -description "this is my new tier1 lr" +#> + + [CmdletBinding()] + + # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types + Param ( + [parameter(Mandatory=$false, + ParameterSetName='TIER0')] + [parameter(Mandatory=$false, + ParameterSetName='TIER1')] + [string]$description, + + [parameter(Mandatory=$true, + ParameterSetName='TIER0')] + [parameter(Mandatory=$true, + ParameterSetName='TIER1')] + [string]$display_name, + + [parameter(Mandatory=$true, + ParameterSetName='TIER0')] + [parameter(Mandatory=$true, + ParameterSetName='TIER1')] + [ValidateSet("ACTIVE_ACTIVE","ACTIVE_STANDBY")] + [string]$high_availability_mode, + + [parameter(Mandatory=$true, + ParameterSetName='TIER0')] + [parameter(Mandatory=$true, + ParameterSetName='TIER1')] + [ValidateSet("TIER0","TIER1")] + [string]$router_type, + + [parameter(Mandatory=$true, + ParameterSetName='TIER0')] + [string]$edge_cluster_id + ) + + Begin + { + if (-not $global:DefaultNsxtServers.isconnected) + { + try + { + Connect-NsxtServer -Menu -ErrorAction Stop + } + + catch + { + throw "Could not connect to an NSX-T Manager, please try again" + } + } + + $NSXTLogicalRouterService = Get-NsxtService -Name "com.vmware.nsx.logical_routers" + } + + Process + { + $logical_router_request = $NSXTLogicalRouterService.help.create.logical_router.Create() + + $logical_router_request.display_name = $display_name + $logical_router_request.description = $description + $logical_router_request.router_type = $router_type + $logical_router_request.high_availability_mode = $high_availability_mode + $logical_router_request.resource_type = "LogicalRouter" + $logical_router_request.failover_mode = "NON_PREEMPTIVE" + + if ($edge_cluster_id) { + $logical_router_request.edge_cluster_id = $edge_cluster_id + } + + try + { + # + $NSXTLogicalRouter = $NSXTLogicalRouterService.create($logical_router_request) + } + + catch + { + throw $Error[0].Exception.ServerError.data + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. + } + + $NSXTLogicalRouter + } +} + +Function Set-NSXTLogicalSwitch { + <# + .Synopsis + Creates a Logical Switch + .DESCRIPTION + Creates a Logical Switch with a number of required parameters. IP Pool is necessary even for an overlay logical switch + .EXAMPLE + Set-NSXTLogicalSwitch -display_name "Name" -transport_zone_id "TP Zone ID" + .EXAMPLE + Set-NSXTLogicalSwitch -display_name "Name" -transport_zone_id "TP Zone ID" -admin_state "UP" -replication_mode "MTEP" -ip_pool_id "IP Pool Name" +#> + + [CmdletBinding()] + + # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types + Param ( + [parameter(Mandatory=$false)] + [string]$description, + + [parameter(Mandatory=$true)] + [string]$display_name, + + [parameter(Mandatory=$true)] + [string]$transport_zone_id, + + [parameter(Mandatory=$true)] + [ValidateSet("UP","DOWN")] + [string]$admin_state, + + [parameter(Mandatory=$false)] + [ValidateSet("MTEP","SOURCE")] + [string]$replication_mode, + + [parameter(Mandatory=$true)] + [string]$ip_pool_id + ) + + Begin + { + if (-not $global:DefaultNsxtServers.isconnected) + { + try + { + Connect-NsxtServer -Menu -ErrorAction Stop + } + + catch + { + throw "Could not connect to an NSX-T Manager, please try again" + } + } + + $NSXTLogicalSwitchService = Get-NsxtService -Name "com.vmware.nsx.logical_switches" + } + + Process + { + $logical_switch_request = $NSXTLogicalSwitchService.help.create.logical_switch.Create() + + $logical_switch_request.display_name = $display_name + $logical_switch_request.description = $description + $logical_switch_request.admin_state = $admin_state + $logical_switch_request.transport_zone_id = $transport_zone_id + $logical_switch_request.resource_type = "LogicalSwitch" + $logical_switch_request.replication_mode = $replication_mode + $logical_switch_request.ip_pool_id = $ip_pool_id + + try + { + # + $NSXTLogicalSwitch = $NSXTLogicalSwitchService.create($logical_switch_request) + } + + catch + { + throw $Error[0].Exception.ServerError.data + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. + } + + $NSXTLogicalSwitch + } +} + +# Non-working Set Functions +Function Set-NSXTTraceFlow { + <# + .Synopsis + Creates a TraceFlow + .DESCRIPTION + Create a TraceFlow for later observation. + .EXAMPLE + Set-NSXTTraceFlow -transport_type "UNICAST" -lport_id "LP ID" -src_ip "IP Address" -src_mac "MAC" -dst_ip "IP Address" -dst_mac "MAC" + .EXAMPLE + Set-NSXTTraceFlow -transport_type "UNICAST" -lport_id "LP ID" -src_ip "IP Address" -src_mac "MAC" -dst_ip "IP Address" -dst_mac "MAC" | Get-NSXTTraceFlow + .EXAMPLE + Set-NSXTTraceFlow -transport_type "UNICAST" -lport_id "LP ID" -src_ip "IP Address" -src_mac "MAC" -dst_ip "IP Address" -dst_mac "MAC" | Get-NSXTTraceFlow | Get-NSXTTraceFlowObservations +#> + + [CmdletBinding()] + + # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types + Param ( + [parameter(Mandatory=$true, + ParameterSetName='Parameter Set VM Type')] + [ValidateSet("UNICAST")] + [string] + $transport_type = "UNICAST", + [parameter(Mandatory=$true, + ValueFromPipeline=$true, + ParameterSetName='Parameter Set VM Type')] + [ValidateNotNullOrEmpty()] + #[ValidateScript({Get-NSXTLogicalPort -Id $_}] + [string] + $lport_id, + [parameter(Mandatory=$true, + ValueFromPipeline=$true, + ParameterSetName='Parameter Set VM Type')] + [ValidateNotNullOrEmpty()] + [ValidateScript({$_ -match [IPAddress]$_})] + [string] + $src_ip, + [parameter(Mandatory=$true, + ValueFromPipeline=$true, + ParameterSetName='Parameter Set VM Type')] + [ValidateNotNullOrEmpty()] + [ValidateScript({$pattern = '^(([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2}))|(([0-9A-Fa-f]{2}[-]){5}([0-9A-Fa-f]{2}))$' + if ($_ -match ($pattern -join '|')) {$true} else { + throw "The argument '$_' does not match a valid MAC address format." + } + })] + [string] + $src_mac, + [parameter(Mandatory=$true, + ValueFromPipeline=$true, + ParameterSetName='Parameter Set VM Type')] + [ValidateNotNullOrEmpty()] + [ValidateScript({$_ -match [IPAddress]$_ })] + [string] + $dst_ip, + [parameter(Mandatory=$true, + ValueFromPipeline=$true, + ParameterSetName='Parameter Set VM Type')] + [ValidateNotNullOrEmpty()] + [ValidateScript({$pattern = '^(([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2}))|(([0-9A-Fa-f]{2}[-]){5}([0-9A-Fa-f]{2}))$' + if ($_ -match ($pattern -join '|')) {$true} else { + throw "The argument '$_' does not match a valid MAC address format." + } + })] + [string] + $dst_mac) + + Begin + { + if (-not $global:DefaultNsxtServers.isconnected) + { + + try + { + Connect-NsxtServer -Menu -ErrorAction Stop + } + + catch + { + throw "Could not connect to an NSX-T Manager, please try again" + } + } + + $NSXTraceFlowsService = Get-NsxtService -Name "com.vmware.nsx.traceflows" + + # Comment out custom classes + <# + class ip_header { + [string]$src_ip + [string]$dst_ip + } + + class eth_header { + [string]$src_mac + [string]$dst_mac + } + + class packet_data { + [boolean]$routed + [ValidateSet("UNICAST","BROADCAST","MULTICAST","UNKNOWN")] + [string]$transport_type + [ValidateSet("BINARYPACKETDATA","FIELDSPACKETDATA")] + [string]$resource_type + [long]$frame_size + [eth_header]$eth_header = [eth_header]::new() + [ip_header]$ip_header = [ip_header]::new() + + packet_data(){ + $this.routed = 'true' + $this.transport_type = 'UNICAST' + $this.resource_type = 'FieldsPacketData' + } + } + + class traceflow_request { + [string]$lport_id + [long]$timeout + [packet_data]$packet = [packet_data]::new() + + traceflow_request(){ + $this.timeout = '15000' + } + } +#> + } + + Process + { + $traceflow_request = $NSXTraceFlowsService.Help.create.traceflow_request.Create() + + $traceflow_request.lport_id = $lport_id + $traceflow_request.packet.transport_type = $transport_type + + $eth_header = [ordered]@{'src_mac' = $src_mac;'eth_type' = '2048';'dst_mac' = $dst_mac} + $ip_header = [ordered]@{src_ip = $src_ip;protocol = '1';ttl = '64';dst_ip = $dst_ip} + $traceflow_request.packet | Add-Member -NotePropertyMembers $eth_header -TypeName eth_header + $traceflow_request.packet | Add-Member -NotePropertyMembers $ip_header -TypeName ip_header + + try + { + # This does not work, bug report submitted to PowerCLI team + $NSXTraceFlow = $NSXTraceFlowService.create($traceflow_request) + } + + catch + { + throw $Error[0].Exception.ServerError.data + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. Filter by MONITORING. + } + + $NSXTraceFlow + } +} + +Function Set-NSXTIPPool { + <# + .Synopsis + Creates an IP Pool + .DESCRIPTION + Creates a IP Pool with a number of required parameters. Supported IP formats include 192.168.1.1, 192.168.1.1-192.168.1.100, 192.168.0.0/24 + .EXAMPLE + Set-NSXTIPPool -display_name "Pool Name" -allocation_start "192.168.1.1" -allocation_end "192.168.1.100" -cidr "192.168.1.0/24" + .EXAMPLE + Set-NSXTIPPool -display_name "Pool Name" -allocation_start "192.168.1.1" -allocation_end "192.168.1.100" -cidr "192.168.1.0/24" -dns_nameservers "192.168.1.1" -gateway_ip "192.168.1.1" +#> + + [CmdletBinding()] + + # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types + Param ( + [parameter(Mandatory=$true)] + [string]$display_name, + + [parameter(Mandatory=$false)] + [string]$description, + + [parameter(Mandatory=$false)] + [string]$dns_nameservers, + + [parameter(Mandatory=$true)] + [string]$allocation_start, + + [parameter(Mandatory=$true)] + [string]$allocation_end, + + [parameter(Mandatory=$true)] + [string]$cidr, + + [parameter(Mandatory=$false)] + [string]$gateway_ip + ) + + Begin + { + if (-not $global:DefaultNsxtServers.isconnected) + { + try + { + Connect-NsxtServer -Menu -ErrorAction Stop + } + + catch + { + throw "Could not connect to an NSX-T Manager, please try again" + } + } + + $NSXTIPPoolService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_pools" + } + + Process + { + $ip_pool_request = $NSXTIPPoolService.help.create.ip_pool.Create() + $ip_pool_request.subnets = $NSXTIPPoolService.help.create.ip_pool.subnets.Create() + $ip_pool_request.subnets = $NSXTIPPoolService.help.create.ip_pool.subnets.Element.Create() + $ip_pool_request.subnets.allocation_ranges = $NSXTIPPoolService.help.create.ip_pool.subnets.Element.allocation_ranges.create() + $ip_pool_request.subnets.allocation_ranges = $NSXTIPPoolService.help.create.ip_pool.subnets.Element.allocation_ranges.element.create() + + $ip_pool_request.display_name = $display_name + $ip_pool_request.description = $description + $ip_pool_request.resource_type = "IpPool" + $ip_pool_request.subnets.dns_nameservers = $dns_nameservers + $ip_pool_request.subnets.allocation_ranges.start = $allocation_start + $ip_pool_request.subnets.allocation_ranges.end = $allocation_end + $ip_pool_request.subnets.cidr = $cidr + $ip_pool_request.subnets.gateway_ip = $gateway_ip + + try + { + # + $NSXTIPPool = $NSXTIPPoolService.create($ip_pool_request) + } + + catch + { + $Error[0].Exception.ServerError.data + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. + throw + } + + $NSXTIPPool + } +} + # Get Template Function Get-NSXTThingTemplate { <# @@ -1136,7 +1553,9 @@ Function Get-NSXTThingTemplate { Param ( [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] [Alias("Id")] - [string]$Thing_id + [string]$Thing_id, + [parameter(Mandatory=$false)] + [string]$name ) begin @@ -1164,7 +1583,12 @@ Function Get-NSXTThingTemplate { if($Thing_id) { $NSXTThings = $NSXTThingsService.get($Thing_id) } else { - $NSXTThings = $NSXTThingsService.list().results + if ($name) { + $NSXTThings = $NSXTThingsService.list().results | where {$_.display_name -eq $name} + } + else { + $NSXTThings = $NSXTThingsService.list().results + } } foreach ($NSXTThing in $NSXTThings) { @@ -1180,3 +1604,91 @@ Function Get-NSXTThingTemplate { } } } + +# Set Template +Function Set-NSXTThingTemplate { + <# + .Synopsis + Creates a THING + .DESCRIPTION + Creates a THING with a number of required parameters. + .EXAMPLE + Set-NSXTThingTemplateh -param1 "Name" -param2 "TP Zone ID" + .EXAMPLE + Set-NSXTThingTemplateh -param1 "Name" -param2 "TP Zone ID" +#> + + [CmdletBinding()] + + # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types + Param ( + [parameter(Mandatory=$false)] + [string]$description, + + [parameter(Mandatory=$true)] + [string]$display_name, + + [parameter(Mandatory=$true)] + [string]$transport_zone_id, + + [parameter(Mandatory=$true)] + [ValidateSet("UP","DOWN")] + [string]$admin_state, + + [parameter(Mandatory=$false)] + [ValidateSet("MTEP","SOURCE")] + [string]$replication_mode, + + [parameter(Mandatory=$true)] + [string]$ip_pool_id + ) + + Begin + { + if (-not $global:DefaultNsxtServers.isconnected) + { + try + { + Connect-NsxtServer -Menu -ErrorAction Stop + } + + catch + { + throw "Could not connect to an NSX-T Manager, please try again" + } + } + + $NSXTTHINGService = Get-NsxtService -Name "com.vmware.nsx.THING" + } + + Process + { + $logical_THING_request = $NSXTTHINGService.help.create.logical_switch.Create() + + $logical_THING_request.display_name = $display_name + $logical_THING_request.description = $description + $logical_THING_request.admin_state = $admin_state + $logical_THING_request.transport_zone_id = $transport_zone_id + $logical_THING_request.resource_type = "LogicalSwitch" + $logical_THING_request.replication_mode = $replication_mode + $logical_THING_request.ip_pool_id = $ip_pool_id + + try + { + # + $NSXTTHING = $NSXTTHINGService.create($logical_THING_request) + } + + catch + { + throw $Error[0].Exception.ServerError.data + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. + } + + $NSXTTHING + } +} + + + + From 10f1f26ec16a571473bb8880e7ae7a538cf25835 Mon Sep 17 00:00:00 2001 From: AndyG Date: Fri, 14 Sep 2018 16:16:27 -0400 Subject: [PATCH 27/65] Don't want to export templates Don't want to export templates --- Modules/NSXT/NSXT.psd1 | 2 -- Modules/NSXT/NSXT.psm1 | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Modules/NSXT/NSXT.psd1 b/Modules/NSXT/NSXT.psd1 index 1ebab1e..537bf49 100644 --- a/Modules/NSXT/NSXT.psd1 +++ b/Modules/NSXT/NSXT.psd1 @@ -22,7 +22,6 @@ 'Get-NSXTManager', 'Get-NSXTNetworkRoutes', 'Get-NSXTRoutingTable', - 'Get-NSXTThingTemplate', 'Get-NSXTTraceFlow', 'Get-NSXTTraceFlowObservations', 'Get-NSXTTransportNode', @@ -30,7 +29,6 @@ 'Set-NSXTIPPool', 'Set-NSXTLogicalRouter', 'Set-NSXTLogicalSwitch', - 'Set-NSXTThingTemplate', 'Set-NSXTTraceFlow' PrivateData = @{ diff --git a/Modules/NSXT/NSXT.psm1 b/Modules/NSXT/NSXT.psm1 index aa30c32..07befe2 100644 --- a/Modules/NSXT/NSXT.psm1 +++ b/Modules/NSXT/NSXT.psm1 @@ -1452,7 +1452,7 @@ Function Set-NSXTIPPool { .EXAMPLE Set-NSXTIPPool -display_name "Pool Name" -allocation_start "192.168.1.1" -allocation_end "192.168.1.100" -cidr "192.168.1.0/24" .EXAMPLE - Set-NSXTIPPool -display_name "Pool Name" -allocation_start "192.168.1.1" -allocation_end "192.168.1.100" -cidr "192.168.1.0/24" -dns_nameservers "192.168.1.1" -gateway_ip "192.168.1.1" + Set-NSXTIPPool -display_name "Test Pool Name" -allocation_start "192.168.1.1" -allocation_end "192.168.1.100" -cidr "192.168.1.0/24" -dns_nameservers "192.168.1.1" -gateway_ip "192.168.1.1" #> [CmdletBinding()] From 5ee5c5d09a8f57185f0642fe4d47c58cd302dccc Mon Sep 17 00:00:00 2001 From: Wouter Kursten Date: Mon, 17 Sep 2018 09:39:07 +0200 Subject: [PATCH 28/65] added functions --- .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 116 +++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 57e5b2c..4779b9b 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11352,4 +11352,118 @@ function Clear-HVEventDatabase { } } -Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, New-HVPodfederation, Remove-HVPodFederation, Get-HVPodFederation, Register-HVPod, Unregister-HVPod, Set-HVPodFederation,Get-HVSite,New-HVSite,Set-HVSite,Remove-HVSite,New-HVHomeSite,Get-HVHomeSite,Set-HVEventDatabase,Get-HVEventDatabase,Clear-HVEventDatabase +function Set-HVlicense { + <# + .Synopsis + Sets or changes the license for Horizon View + + .DESCRIPTION + Sets or changes the license for Horizon View + + .PARAMETER license + License key (string) + + .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 + + .EXAMPLE + set-hvlicense -license "LICENSE-KEY" + Returns information about the sites within a Horizon View Pod Federation. + + .NOTES + Author : Wouter Kursten + Author email : wouter@retouw.nl + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.4,7.5 + PowerCLI Version : PowerCLI 10 + PowerShell Version : 5.0 + #> + + [CmdletBinding( + SupportsShouldProcess = $false, + ConfirmImpact = 'High' + )] + + param( + [Parameter(Mandatory = $true)] + [string] + $license, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + + try { + $services.license.license_set($license) + } + catch { + write-error $_.exception message + break + } + $licenseresult=$services.license.license_get() + return $licenseresult + [System.gc]::collect() +} + + +function Get-HVlicense { + <# + .Synopsis + Gets the license for Horizon View + + .DESCRIPTION + Gets the license for Horizon View + + + .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 + + .EXAMPLE + get-hvlicense + + + .NOTES + Author : Wouter Kursten + Author email : wouter@retouw.nl + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.4,7.5 + PowerCLI Version : PowerCLI 10 + PowerShell Version : 5.0 + #> + + [CmdletBinding( + SupportsShouldProcess = $false, + ConfirmImpact = 'High' + )] + + param( + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + + $license=$services.license.license_get() + return $license + [System.gc]::collect() +} + +Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, New-HVPodfederation, Remove-HVPodFederation, Get-HVPodFederation, Register-HVPod, Unregister-HVPod, Set-HVPodFederation,Get-HVSite,New-HVSite,Set-HVSite,Remove-HVSite,New-HVHomeSite,Get-HVHomeSite,Set-HVEventDatabase,Get-HVEventDatabase,Clear-HVEventDatabase,Get-HVlicense,Set-HVlicense From 9e569b139aeee0a9e994ff1bc07f6e99ef3b16ff Mon Sep 17 00:00:00 2001 From: AndyG Date: Tue, 18 Sep 2018 09:32:36 -0500 Subject: [PATCH 29/65] Added ShouldProcess to Set functions Added ShouldProcess to Set functions --- Modules/NSXT/NSXT.psm1 | 111 ++++++++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 28 deletions(-) diff --git a/Modules/NSXT/NSXT.psm1 b/Modules/NSXT/NSXT.psm1 index 07befe2..4616168 100644 --- a/Modules/NSXT/NSXT.psm1 +++ b/Modules/NSXT/NSXT.psm1 @@ -1121,7 +1121,8 @@ Function Set-NSXTLogicalRouter { Set-NSXTLogicalRouter -display_name "Name" -high_availability_mode "ACTIVE_STANDBY" -router_type "TIER1" -description "this is my new tier1 lr" #> - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess=$true, + ConfirmImpact='Medium')] # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types Param ( @@ -1191,8 +1192,11 @@ Function Set-NSXTLogicalRouter { try { - # - $NSXTLogicalRouter = $NSXTLogicalRouterService.create($logical_router_request) + # Should process + if ($pscmdlet.ShouldProcess($logical_router_request.display_name, "Create logical router")) + { + $NSXTLogicalRouter = $NSXTLogicalRouterService.create($logical_router_request) + } } catch @@ -1217,7 +1221,8 @@ Function Set-NSXTLogicalSwitch { Set-NSXTLogicalSwitch -display_name "Name" -transport_zone_id "TP Zone ID" -admin_state "UP" -replication_mode "MTEP" -ip_pool_id "IP Pool Name" #> - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess=$true, + ConfirmImpact='Medium')] # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types Param ( @@ -1274,8 +1279,12 @@ Function Set-NSXTLogicalSwitch { try { - # - $NSXTLogicalSwitch = $NSXTLogicalSwitchService.create($logical_switch_request) + # Should process + if ($pscmdlet.ShouldProcess($logical_switch_request.display_name, "Create logical switch")) + { + $NSXTLogicalSwitch = $NSXTLogicalSwitchService.create($logical_switch_request) + } + } catch @@ -1303,7 +1312,8 @@ Function Set-NSXTTraceFlow { Set-NSXTTraceFlow -transport_type "UNICAST" -lport_id "LP ID" -src_ip "IP Address" -src_mac "MAC" -dst_ip "IP Address" -dst_mac "MAC" | Get-NSXTTraceFlow | Get-NSXTTraceFlowObservations #> - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess=$true, + ConfirmImpact='Medium')] # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types Param ( @@ -1429,8 +1439,12 @@ Function Set-NSXTTraceFlow { try { - # This does not work, bug report submitted to PowerCLI team - $NSXTraceFlow = $NSXTraceFlowService.create($traceflow_request) + # Should process + if ($pscmdlet.ShouldProcess($traceflow_request.lport_id, "Create traceflow")) + { + # This does not work, bug report submitted to PowerCLI team + $NSXTraceFlow = $NSXTraceFlowService.create($traceflow_request) + } } catch @@ -1455,7 +1469,8 @@ Function Set-NSXTIPPool { Set-NSXTIPPool -display_name "Test Pool Name" -allocation_start "192.168.1.1" -allocation_end "192.168.1.100" -cidr "192.168.1.0/24" -dns_nameservers "192.168.1.1" -gateway_ip "192.168.1.1" #> - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess=$true, + ConfirmImpact='Medium')] # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types Param ( @@ -1497,29 +1512,65 @@ Function Set-NSXTIPPool { } $NSXTIPPoolService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_pools" + + class allocation_ranges { + [string]$start + [string]$end + $self + } + + class subnets { + [string]$dns_nameservers + [string]$dns_suffix + [string]$cidr + [string]$gateway_ip + $allocation_ranges = [allocation_ranges]::new() + hidden $self + + } + + class ip_pool { + [string]$display_name + [string]$description + [string]$resource_type = 'IpPool' + [long]$revision = '0' + #$subnets = [subnets]::new() + $subnets = [System.Collections.Generic.List[subnets]]::new() + hidden $pool_usage + hidden $tags + hidden $self + hidden $links = [System.Collections.Generic.List[System.Management.Automation.PSObject]]::new() + } + } Process { - $ip_pool_request = $NSXTIPPoolService.help.create.ip_pool.Create() - $ip_pool_request.subnets = $NSXTIPPoolService.help.create.ip_pool.subnets.Create() - $ip_pool_request.subnets = $NSXTIPPoolService.help.create.ip_pool.subnets.Element.Create() - $ip_pool_request.subnets.allocation_ranges = $NSXTIPPoolService.help.create.ip_pool.subnets.Element.allocation_ranges.create() - $ip_pool_request.subnets.allocation_ranges = $NSXTIPPoolService.help.create.ip_pool.subnets.Element.allocation_ranges.element.create() + $ip_pool = [ip_pool]::new() + $ip_pool = $NSXTIPPoolService.help.create.ip_pool.Create() + $ip_pool.subnets = $NSXTIPPoolService.help.create.ip_pool.subnets.Create() + $ip_pool.subnets = $NSXTIPPoolService.help.create.ip_pool.subnets.Element.Create() + $ip_pool.subnets.allocation_ranges = $NSXTIPPoolService.help.create.ip_pool.subnets.Element.allocation_ranges.create() + $ip_pool.subnets.allocation_ranges = $NSXTIPPoolService.help.create.ip_pool.subnets.Element.allocation_ranges.element.create() + #$ip_pool = [ip_pool]::new() - $ip_pool_request.display_name = $display_name - $ip_pool_request.description = $description - $ip_pool_request.resource_type = "IpPool" - $ip_pool_request.subnets.dns_nameservers = $dns_nameservers - $ip_pool_request.subnets.allocation_ranges.start = $allocation_start - $ip_pool_request.subnets.allocation_ranges.end = $allocation_end - $ip_pool_request.subnets.cidr = $cidr - $ip_pool_request.subnets.gateway_ip = $gateway_ip + $ip_pool.display_name = $display_name + $ip_pool.description = $description + $ip_pool.resource_type = "IpPool" + $ip_pool.subnets.dns_nameservers = $dns_nameservers + $ip_pool.subnets.allocation_ranges.start = $allocation_start + $ip_pool.subnets.allocation_ranges.end = $allocation_end + $ip_pool.subnets.cidr = $cidr + $ip_pool.subnets.gateway_ip = $gateway_ip + $ip_pool.revision = 0 try { - # - $NSXTIPPool = $NSXTIPPoolService.create($ip_pool_request) + # Should process + if ($pscmdlet.ShouldProcess($ip_pool.display_name, "Create IP Pool")) + { + $NSXTIPPool = $NSXTIPPoolService.create($ip_pool) + } } catch @@ -1618,7 +1669,8 @@ Function Set-NSXTThingTemplate { Set-NSXTThingTemplateh -param1 "Name" -param2 "TP Zone ID" #> - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess=$true, + ConfirmImpact='Medium')] # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types Param ( @@ -1675,8 +1727,11 @@ Function Set-NSXTThingTemplate { try { - # - $NSXTTHING = $NSXTTHINGService.create($logical_THING_request) + # Should process + if ($pscmdlet.ShouldProcess($ip_pool.display_name, "Create IP Pool")) + { + $NSXTTHING = $NSXTTHINGService.create($logical_THING_request) + } } catch From e8b64517c7b6a5121eba2c0725db3149e7da9010 Mon Sep 17 00:00:00 2001 From: AndyG Date: Tue, 18 Sep 2018 16:45:59 -0500 Subject: [PATCH 30/65] Added Get/Set/Remove IPAMIPBlock Added Get/Set/Remove IPAMIPBlock --- Modules/NSXT/NSXT.psd1 | 5 +- Modules/NSXT/NSXT.psm1 | 281 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 278 insertions(+), 8 deletions(-) diff --git a/Modules/NSXT/NSXT.psd1 b/Modules/NSXT/NSXT.psd1 index 537bf49..83026e8 100644 --- a/Modules/NSXT/NSXT.psd1 +++ b/Modules/NSXT/NSXT.psd1 @@ -29,7 +29,10 @@ 'Set-NSXTIPPool', 'Set-NSXTLogicalRouter', 'Set-NSXTLogicalSwitch', - 'Set-NSXTTraceFlow' + 'Set-NSXTTraceFlow', + 'Get-NSXTIPAMIPBlock', + 'Set-NSXTIPAMIPBlock', + 'Remove-NSXTIPAMIPBlock' PrivateData = @{ PSData = @{ diff --git a/Modules/NSXT/NSXT.psm1 b/Modules/NSXT/NSXT.psm1 index 4616168..3d6a4f7 100644 --- a/Modules/NSXT/NSXT.psm1 +++ b/Modules/NSXT/NSXT.psm1 @@ -1106,6 +1106,72 @@ Function Get-NSXTIPPool { } } +Function Get-NSXTIPAMIPBlock { + <# + .Synopsis + Retrieves the IPAM IP Block information + .DESCRIPTION + Retrieves IPAM IP Block information for a single or multiple ports. Execute with no parameters to get all ports, specify a PARAM if known. + .EXAMPLE + Get-NSXTIPAMIPBlock + .EXAMPLE + Get-NSXTIPAMIPBlock -block_id "Block Id" + .EXAMPLE + Get-NSXTIPAMIPBlock -name "Block Name" + +#> + + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$block_id, + [parameter(Mandatory=$false)] + [string]$name + ) + + begin + { + $NSXTIPAMIPBlocksService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_blocks" + + class ip_block { + [string]$Name + [string]$block_id + hidden [string]$Tags = [System.Collections.Generic.List[string]]::new() + [string]$protection + #[ValidateSet("TIER0","TIER1")] + [string]$cidr + hidden [string]$resource_type + } + } + + Process + { + if($block_id) { + $NSXTIPAMIPBlocks = $NSXTIPAMIPBlocksService.get($block_id) + } else { + if ($name) { + $NSXTIPAMIPBlocks = $NSXTIPAMIPBlocksService.list().results | where {$_.display_name -eq $name} + } + else { + $NSXTIPAMIPBlocks = $NSXTIPAMIPBlocksService.list().results + } + } + + foreach ($NSXTIPAMIPBlock in $NSXTIPAMIPBlocks) { + + $results = [ip_block]::new() + $results.Name = $NSXTIPAMIPBlock.display_name; + $results.block_id = $NSXTIPAMIPBlock.id; + $results.Tags = $NSXTIPAMIPBlock.tags; + $results.protection = $NSXTIPAMIPBlock.protection; + $results.cidr = $NSXTIPAMIPBlock.cidr; + $results.resource_type = $NSXTIPAMIPBlock.resource_type + + $results + } + } +} + # Working Set Functions Function Set-NSXTLogicalRouter { <# @@ -1297,6 +1363,140 @@ Function Set-NSXTLogicalSwitch { } } +Function Set-NSXTIPAMIPBlock { + <# + .Synopsis + Creates an IPAM IP Block + .DESCRIPTION + Creates a IPAM IP Block with a cidr parameter. + .EXAMPLE + Set-NSXTIPAMIPBlock -name "IPAM Block Name" -cidr "192.168.0.0/24" +#> + + [CmdletBinding(SupportsShouldProcess=$true, + ConfirmImpact='Medium')] + + # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types + Param ( + [parameter(Mandatory=$false)] + [string]$description, + + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$display_name, + + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$cidr + ) + + Begin + { + if (-not $global:DefaultNsxtServers.isconnected) + { + try + { + Connect-NsxtServer -Menu -ErrorAction Stop + } + + catch + { + throw "Could not connect to an NSX-T Manager, please try again" + } + } + + $NSXTIPAMIPBlockService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_blocks" + } + + Process + { + $IPAMIPBlock_request = $NSXTIPAMIPBlockService.help.create.ip_block.Create() + + $IPAMIPBlock_request.display_name = $display_name + $IPAMIPBlock_request.description = $description + $IPAMIPBlock_request.resource_type = "IpBlock" + $IPAMIPBlock_request.cidr = $cidr + + + try + { + # Should process + if ($pscmdlet.ShouldProcess($ip_pool.display_name, "Create IP Pool")) + { + $NSXTIPAMIPBlock = $NSXTIPAMIPBlockService.create($IPAMIPBlock_request) + } + } + + catch + { + throw $Error[0].Exception.ServerError.data + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. + } + + $NSXTIPAMIPBlock + } +} + +# Remove functions +Function Remove-NSXTIPAMIPBlock { + <# + .Synopsis + Removes an IPAM IP Block + .DESCRIPTION + Removes a IPAM IP Block with a block_id parameter. + .EXAMPLE + Remove-NSXTIPAMIPBlock -block_id "id" + .EXAMPLE + Get-NSXTIPAMIPBlock | where name -eq "IPAM Test2" | Remove-NSXTIPAMIPBlock +#> + + [CmdletBinding(SupportsShouldProcess=$true, + ConfirmImpact='High')] + + Param ( + [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] + [ValidateNotNullOrEmpty()] + [Alias("Id")] + [string]$block_id + ) + + Begin + { + if (-not $global:DefaultNsxtServers.isconnected) + { + try + { + Connect-NsxtServer -Menu -ErrorAction Stop + } + + catch + { + throw "Could not connect to an NSX-T Manager, please try again" + } + } + + $NSXTIPAMIPBlockService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_blocks" + } + + Process + { + try + { + # Should process + if ($pscmdlet.ShouldProcess($block_id, "Delete IP Pool")) + { + $NSXTIPAMIPBlockService.delete($block_id) + } + } + + catch + { + throw $Error[0].Exception.ServerError.data + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. + } + } +} + # Non-working Set Functions Function Set-NSXTTraceFlow { <# @@ -1475,6 +1675,7 @@ Function Set-NSXTIPPool { # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types Param ( [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] [string]$display_name, [parameter(Mandatory=$false)] @@ -1484,12 +1685,15 @@ Function Set-NSXTIPPool { [string]$dns_nameservers, [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] [string]$allocation_start, [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] [string]$allocation_end, [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] [string]$cidr, [parameter(Mandatory=$false)] @@ -1534,25 +1738,22 @@ Function Set-NSXTIPPool { [string]$description [string]$resource_type = 'IpPool' [long]$revision = '0' - #$subnets = [subnets]::new() - $subnets = [System.Collections.Generic.List[subnets]]::new() + $subnets = [subnets]::new() hidden $pool_usage hidden $tags hidden $self - hidden $links = [System.Collections.Generic.List[System.Management.Automation.PSObject]]::new() + hidden $links = [System.Collections.Generic.List[string]]::new() } } Process { - $ip_pool = [ip_pool]::new() $ip_pool = $NSXTIPPoolService.help.create.ip_pool.Create() $ip_pool.subnets = $NSXTIPPoolService.help.create.ip_pool.subnets.Create() $ip_pool.subnets = $NSXTIPPoolService.help.create.ip_pool.subnets.Element.Create() $ip_pool.subnets.allocation_ranges = $NSXTIPPoolService.help.create.ip_pool.subnets.Element.allocation_ranges.create() $ip_pool.subnets.allocation_ranges = $NSXTIPPoolService.help.create.ip_pool.subnets.Element.allocation_ranges.element.create() - #$ip_pool = [ip_pool]::new() $ip_pool.display_name = $display_name $ip_pool.description = $description @@ -1563,6 +1764,9 @@ Function Set-NSXTIPPool { $ip_pool.subnets.cidr = $cidr $ip_pool.subnets.gateway_ip = $gateway_ip $ip_pool.revision = 0 + + # Accepted JSON object ok yet it did not interpret any of the parameters + #$ip_pool_json = ConvertTo-Json $ip_pool try { @@ -1576,7 +1780,7 @@ Function Set-NSXTIPPool { catch { $Error[0].Exception.ServerError.data - # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file; grep POOL-MGMT throw } @@ -1584,6 +1788,8 @@ Function Set-NSXTIPPool { } } +########################### + # Get Template Function Get-NSXTThingTemplate { <# @@ -1678,9 +1884,11 @@ Function Set-NSXTThingTemplate { [string]$description, [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] [string]$display_name, [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] [string]$transport_zone_id, [parameter(Mandatory=$true)] @@ -1692,6 +1900,7 @@ Function Set-NSXTThingTemplate { [string]$replication_mode, [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] [string]$ip_pool_id ) @@ -1744,6 +1953,64 @@ Function Set-NSXTThingTemplate { } } - +# Remove Template +Function Remove-NSXTThingTemplate { + <# + .Synopsis + Removes an IPAM IP Block + .DESCRIPTION + Removes a IPAM IP Block with a block_id parameter. + .EXAMPLE + Remove-NSXTIPAMIPBlock -block_id "id" +#> + + [CmdletBinding(SupportsShouldProcess=$true, + ConfirmImpact='High')] + + Param ( + [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] + [ValidateNotNullOrEmpty()] + [Alias("Id")] + [string]$thing_id + ) + + Begin + { + if (-not $global:DefaultNsxtServers.isconnected) + { + try + { + Connect-NsxtServer -Menu -ErrorAction Stop + } + + catch + { + throw "Could not connect to an NSX-T Manager, please try again" + } + } + + $NSXTTHINGkService = Get-NsxtService -Name "com.vmware.nsx.THING" + } + + Process + { + try + { + # Should process + if ($pscmdlet.ShouldProcess($thing_id, "Delete IP Pool")) + { + $NSXTTHINGkService.delete($thing_id) + } + } + + catch + { + throw $Error[0].Exception.ServerError.data + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file. + } + } +} + +$NSXTIPSubnetsService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_subnets" From 39c179ae1a2b114d81545bb15794f09824812d2a Mon Sep 17 00:00:00 2001 From: AndyG Date: Wed, 19 Sep 2018 15:01:25 -0500 Subject: [PATCH 31/65] Added Get-NSXTClusterNode Added Get-NSXTClusterNode --- Modules/NSXT/NSXT.psd1 | 2 + Modules/NSXT/NSXT.psm1 | 160 ++++++++++++++++++++++++++++++++--------- 2 files changed, 129 insertions(+), 33 deletions(-) diff --git a/Modules/NSXT/NSXT.psd1 b/Modules/NSXT/NSXT.psd1 index 83026e8..3cee460 100644 --- a/Modules/NSXT/NSXT.psd1 +++ b/Modules/NSXT/NSXT.psd1 @@ -26,6 +26,7 @@ 'Get-NSXTTraceFlowObservations', 'Get-NSXTTransportNode', 'Get-NSXTTransportZone', + 'Get-NSXTClusterNode', 'Set-NSXTIPPool', 'Set-NSXTLogicalRouter', 'Set-NSXTLogicalSwitch', @@ -33,6 +34,7 @@ 'Get-NSXTIPAMIPBlock', 'Set-NSXTIPAMIPBlock', 'Remove-NSXTIPAMIPBlock' + PrivateData = @{ PSData = @{ diff --git a/Modules/NSXT/NSXT.psm1 b/Modules/NSXT/NSXT.psm1 index 3d6a4f7..99e149b 100644 --- a/Modules/NSXT/NSXT.psm1 +++ b/Modules/NSXT/NSXT.psm1 @@ -1172,6 +1172,84 @@ Function Get-NSXTIPAMIPBlock { } } +Function Get-NSXTClusterNode { + <# + .Synopsis + Retrieves the cluster node information + .DESCRIPTION + Retrieves cluster node information including manager and controller nodes. + .EXAMPLE + Get-NSXTClusterNode + .EXAMPLE + Get-NSXTClusterNode -node_id "Node Id" + .EXAMPLE + Get-NSXTClusterNode -name "Name" +#> + + Param ( + [parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)] + [Alias("Id")] + [string]$node_id, + [parameter(Mandatory=$false)] + [string]$name + ) + + begin + { + $NSXTClusterNodesService = Get-NsxtService -Name "com.vmware.nsx.cluster.nodes" + + class NSXTClusterNode { + [string]$Name + [string]$node_id + hidden [array]$Tags = [System.Collections.Generic.List[string]]::new() + hidden [string]$controller_role + hidden [array]$manager_role + [string]$protection + [string]$appliance_mgmt_listen_addr + hidden [string]$external_id + hidden [string]$description + [string]$role + } + } + + Process + { + if($node_id) { + $NSXTThings = $NSXTClusterNodesService.get($node_id) + } else { + if ($name) { + $NSXTClusterNodes = $NSXTClusterNodesService.list().results | where {$_.display_name -eq $name} + } + else { + $NSXTClusterNodes = $NSXTClusterNodesService.list().results + } + } + + foreach ($NSXTClusterNode in $NSXTClusterNodes) { + + $results = [NSXTClusterNode]::new() + $results.Name = $NSXTClusterNode.display_name; + $results.node_id = $NSXTClusterNode.Id; + $results.Tags = $NSXTClusterNode.tags; + $results.controller_role = $NSXTClusterNode.controller_role; + $results.manager_role = $NSXTClusterNode.manager_role; + $results.protection = $NSXTClusterNode.protection; + $results.appliance_mgmt_listen_addr = $NSXTClusterNode.appliance_mgmt_listen_addr; + $results.external_id = $NSXTClusterNode.external_id; + $results.description = $NSXTClusterNode.description + + if ($NSXTClusterNode.manager_role -ne $null) { + $results.role = "Manager" + } + elseif ($NSXTClusterNode.controller_role -ne $null) { + $results.role = "Controller" + } + + $results + } + } +} + # Working Set Functions Function Set-NSXTLogicalRouter { <# @@ -1453,11 +1531,11 @@ Function Remove-NSXTIPAMIPBlock { [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='High')] - Param ( - [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] - [ValidateNotNullOrEmpty()] - [Alias("Id")] - [string]$block_id + Param ( + [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] + [ValidateNotNullOrEmpty()] + [Alias("Id")] + [string]$block_id ) Begin @@ -1664,13 +1742,13 @@ Function Set-NSXTIPPool { .DESCRIPTION Creates a IP Pool with a number of required parameters. Supported IP formats include 192.168.1.1, 192.168.1.1-192.168.1.100, 192.168.0.0/24 .EXAMPLE - Set-NSXTIPPool -display_name "Pool Name" -allocation_start "192.168.1.1" -allocation_end "192.168.1.100" -cidr "192.168.1.0/24" + Set-NSXTIPPool -display_name "Pool Name" -allocation_start "192.168.1.2" -allocation_end "192.168.1.100" -cidr "192.168.1.0/24" .EXAMPLE - Set-NSXTIPPool -display_name "Test Pool Name" -allocation_start "192.168.1.1" -allocation_end "192.168.1.100" -cidr "192.168.1.0/24" -dns_nameservers "192.168.1.1" -gateway_ip "192.168.1.1" + Set-NSXTIPPool -display_name "Test Pool Name" -allocation_start "192.168.1.2" -allocation_end "192.168.1.100" -cidr "192.168.1.0/24" -dns_nameservers "192.168.1.1" -gateway_ip "192.168.1.1" -dns_suffix "evil corp" #> [CmdletBinding(SupportsShouldProcess=$true, - ConfirmImpact='Medium')] + ConfirmImpact='High')] # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types Param ( @@ -1684,6 +1762,9 @@ Function Set-NSXTIPPool { [parameter(Mandatory=$false)] [string]$dns_nameservers, + [parameter(Mandatory=$false)] + [string]$dns_suffix, + [parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$allocation_start, @@ -1720,17 +1801,16 @@ Function Set-NSXTIPPool { class allocation_ranges { [string]$start [string]$end - $self + #$self } class subnets { - [string]$dns_nameservers + [array]$allocation_ranges = [allocation_ranges]::new() + [array]$dns_nameservers [string]$dns_suffix [string]$cidr [string]$gateway_ip - $allocation_ranges = [allocation_ranges]::new() - hidden $self - + #hidden $self } class ip_pool { @@ -1738,42 +1818,51 @@ Function Set-NSXTIPPool { [string]$description [string]$resource_type = 'IpPool' [long]$revision = '0' - $subnets = [subnets]::new() + [array]$subnets = [subnets]::new() hidden $pool_usage - hidden $tags - hidden $self - hidden $links = [System.Collections.Generic.List[string]]::new() + hidden [array]$tags + # hidden $self + hidden $links } - } Process { - $ip_pool = $NSXTIPPoolService.help.create.ip_pool.Create() - $ip_pool.subnets = $NSXTIPPoolService.help.create.ip_pool.subnets.Create() - $ip_pool.subnets = $NSXTIPPoolService.help.create.ip_pool.subnets.Element.Create() - $ip_pool.subnets.allocation_ranges = $NSXTIPPoolService.help.create.ip_pool.subnets.Element.allocation_ranges.create() - $ip_pool.subnets.allocation_ranges = $NSXTIPPoolService.help.create.ip_pool.subnets.Element.allocation_ranges.element.create() + $sample_ip_pool = $NSXTIPPoolService.help.create.ip_pool.Create() + $sample_ip_pool.subnets = @($NSXTIPPoolService.help.create.ip_pool.subnets.Create()) + $sample_ip_pool.subnets = @($NSXTIPPoolService.help.create.ip_pool.subnets.Element.Create()) + $sample_ip_pool.subnets[0].allocation_ranges = @($NSXTIPPoolService.help.create.ip_pool.subnets.Element.allocation_ranges.create()) + $sample_ip_pool.subnets[0].allocation_ranges = @($NSXTIPPoolService.help.create.ip_pool.subnets.Element.allocation_ranges.element.create()) + #Remove buggy self object + $ip_pool = $sample_ip_pool | select -Property * -ExcludeProperty self + $ip_pool.subnets[0] = $sample_ip_pool.subnets[0] | select -Property * -ExcludeProperty self + $ip_pool.subnets[0].allocation_ranges[0] = $sample_ip_pool.subnets[0].allocation_ranges[0] | select -Property * -ExcludeProperty self + + # Assign objects $ip_pool.display_name = $display_name $ip_pool.description = $description $ip_pool.resource_type = "IpPool" - $ip_pool.subnets.dns_nameservers = $dns_nameservers - $ip_pool.subnets.allocation_ranges.start = $allocation_start - $ip_pool.subnets.allocation_ranges.end = $allocation_end - $ip_pool.subnets.cidr = $cidr - $ip_pool.subnets.gateway_ip = $gateway_ip + $ip_pool.subnets[0].dns_nameservers = @($dns_nameservers) + $ip_pool.subnets[0].dns_suffix = $dns_suffix + $ip_pool.subnets[0].allocation_ranges[0].start = $allocation_start + $ip_pool.subnets[0].allocation_ranges[0].end = $allocation_end + $ip_pool.subnets[0].cidr = $cidr + $ip_pool.subnets[0].gateway_ip = $gateway_ip $ip_pool.revision = 0 + $ip_pool.tags = @() # Accepted JSON object ok yet it did not interpret any of the parameters - #$ip_pool_json = ConvertTo-Json $ip_pool + $ip_pool_json = ConvertTo-Json $ip_pool -Depth 10 try { # Should process if ($pscmdlet.ShouldProcess($ip_pool.display_name, "Create IP Pool")) { - $NSXTIPPool = $NSXTIPPoolService.create($ip_pool) + $ip_pool_json + #$NSXTIPPool = $NSXTIPPoolService.create($ip_pool_json) + $NSXTIPPoolService.create($ip_pool_json) } } @@ -1784,10 +1873,14 @@ Function Set-NSXTIPPool { throw } - $NSXTIPPool + #$NSXTIPPool } } +########################### +# # +# TEMPLATES!! # +# # ########################### # Get Template @@ -1934,6 +2027,8 @@ Function Set-NSXTThingTemplate { $logical_THING_request.replication_mode = $replication_mode $logical_THING_request.ip_pool_id = $ip_pool_id + $logical_THING_request_json = ConvertTo-Json $logical_THING_request -Depth 10 + try { # Should process @@ -1967,7 +2062,7 @@ Function Remove-NSXTThingTemplate { [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='High')] - Param ( + Param ( [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] [ValidateNotNullOrEmpty()] [Alias("Id")] @@ -2011,6 +2106,5 @@ Function Remove-NSXTThingTemplate { } } -$NSXTIPSubnetsService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_subnets" From 179cfa82bee88f33e57927d30570f4104bfdf77a Mon Sep 17 00:00:00 2001 From: AndyG Date: Wed, 19 Sep 2018 21:35:23 -0500 Subject: [PATCH 32/65] Set-NSXTIPPool finally working Set-NSXTIPPool finally working --- Modules/NSXT/NSXT.psm1 | 275 ++++++++++++++++++++--------------------- 1 file changed, 135 insertions(+), 140 deletions(-) diff --git a/Modules/NSXT/NSXT.psm1 b/Modules/NSXT/NSXT.psm1 index 99e149b..3a0d270 100644 --- a/Modules/NSXT/NSXT.psm1 +++ b/Modules/NSXT/NSXT.psm1 @@ -1515,6 +1515,141 @@ Function Set-NSXTIPAMIPBlock { } } +Function Set-NSXTIPPool { + <# + .Synopsis + Creates an IP Pool + .DESCRIPTION + Creates a IP Pool with a number of required parameters. Supported IP formats include 192.168.1.1, 192.168.1.1-192.168.1.100, 192.168.0.0/24 + .EXAMPLE + Set-NSXTIPPool -display_name "Pool Name" -allocation_start "192.168.1.2" -allocation_end "192.168.1.100" -cidr "192.168.1.0/24" + .EXAMPLE + Set-NSXTIPPool -display_name "Test Pool Name" -allocation_start "192.168.1.2" -allocation_end "192.168.1.100" -cidr "192.168.1.0/24" -dns_nameservers "192.168.1.1" -gateway_ip "192.168.1.1" -dns_suffix "evil corp" +#> + + [CmdletBinding(SupportsShouldProcess=$true, + ConfirmImpact='High')] + + # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types + Param ( + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$display_name, + + [parameter(Mandatory=$false)] + [string]$description, + + [parameter(Mandatory=$false)] + [string]$dns_nameservers, + + [parameter(Mandatory=$false)] + [string]$dns_suffix, + + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$allocation_start, + + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$allocation_end, + + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$cidr, + + [parameter(Mandatory=$false)] + [string]$gateway_ip + ) + + Begin + { + if (-not $global:DefaultNsxtServers.isconnected) + { + try + { + Connect-NsxtServer -Menu -ErrorAction Stop + } + + catch + { + throw "Could not connect to an NSX-T Manager, please try again" + } + } + + $NSXTIPPoolService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_pools" + + class allocation_ranges { + [string]$start + [string]$end + #$self + } + + class subnets { + [array]$allocation_ranges = [allocation_ranges]::new() + [array]$dns_nameservers + [string]$dns_suffix + [string]$cidr + [string]$gateway_ip + #hidden $self + } + + class ip_pool { + [string]$display_name + [string]$description + [string]$resource_type = 'IpPool' + [long]$revision = '0' + [array]$subnets = [subnets]::new() + hidden $pool_usage + hidden [array]$tags + # hidden $self + hidden $links + } + } + + Process + { + $sample_ip_pool = $NSXTIPPoolService.help.create.ip_pool.Create() + $sample_ip_pool.subnets = @($NSXTIPPoolService.help.create.ip_pool.subnets.Create()) + $sample_ip_pool.subnets = @($NSXTIPPoolService.help.create.ip_pool.subnets.Element.Create()) + $sample_ip_pool.subnets[0].allocation_ranges = @($NSXTIPPoolService.help.create.ip_pool.subnets.Element.allocation_ranges.create()) + $sample_ip_pool.subnets[0].allocation_ranges = @($NSXTIPPoolService.help.create.ip_pool.subnets.Element.allocation_ranges.element.create()) + + #Remove buggy self object + $ip_pool = $sample_ip_pool | select -Property * -ExcludeProperty self + $ip_pool.subnets[0] = $sample_ip_pool.subnets[0] | select -Property * -ExcludeProperty self + $ip_pool.subnets[0].allocation_ranges[0] = $sample_ip_pool.subnets[0].allocation_ranges[0] | select -Property * -ExcludeProperty self + + # Assign objects + $ip_pool.display_name = $display_name + $ip_pool.description = $description + $ip_pool.resource_type = "IpPool" + $ip_pool.subnets[0].dns_nameservers = @($dns_nameservers) + $ip_pool.subnets[0].dns_suffix = $dns_suffix + $ip_pool.subnets[0].allocation_ranges[0].start = $allocation_start + $ip_pool.subnets[0].allocation_ranges[0].end = $allocation_end + $ip_pool.subnets[0].cidr = $cidr + $ip_pool.subnets[0].gateway_ip = $gateway_ip + $ip_pool.revision = 0 + $ip_pool.tags = @() + + try + { + # Should process + if ($pscmdlet.ShouldProcess($ip_pool.display_name, "Create IP Pool")) + { + $NSXTIPPoolService.create($ip_pool) + } + } + + catch + { + $Error[0].Exception.ServerError.data + # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file; grep POOL-MGMT + throw + } + } +} + # Remove functions Function Remove-NSXTIPAMIPBlock { <# @@ -1735,147 +1870,7 @@ Function Set-NSXTTraceFlow { } } -Function Set-NSXTIPPool { - <# - .Synopsis - Creates an IP Pool - .DESCRIPTION - Creates a IP Pool with a number of required parameters. Supported IP formats include 192.168.1.1, 192.168.1.1-192.168.1.100, 192.168.0.0/24 - .EXAMPLE - Set-NSXTIPPool -display_name "Pool Name" -allocation_start "192.168.1.2" -allocation_end "192.168.1.100" -cidr "192.168.1.0/24" - .EXAMPLE - Set-NSXTIPPool -display_name "Test Pool Name" -allocation_start "192.168.1.2" -allocation_end "192.168.1.100" -cidr "192.168.1.0/24" -dns_nameservers "192.168.1.1" -gateway_ip "192.168.1.1" -dns_suffix "evil corp" -#> - [CmdletBinding(SupportsShouldProcess=$true, - ConfirmImpact='High')] - - # Paramameter Set variants will be needed Multicast & Broadcast Traffic Types as well as VM & Logical Port Types - Param ( - [parameter(Mandatory=$true)] - [ValidateNotNullOrEmpty()] - [string]$display_name, - - [parameter(Mandatory=$false)] - [string]$description, - - [parameter(Mandatory=$false)] - [string]$dns_nameservers, - - [parameter(Mandatory=$false)] - [string]$dns_suffix, - - [parameter(Mandatory=$true)] - [ValidateNotNullOrEmpty()] - [string]$allocation_start, - - [parameter(Mandatory=$true)] - [ValidateNotNullOrEmpty()] - [string]$allocation_end, - - [parameter(Mandatory=$true)] - [ValidateNotNullOrEmpty()] - [string]$cidr, - - [parameter(Mandatory=$false)] - [string]$gateway_ip - ) - - Begin - { - if (-not $global:DefaultNsxtServers.isconnected) - { - try - { - Connect-NsxtServer -Menu -ErrorAction Stop - } - - catch - { - throw "Could not connect to an NSX-T Manager, please try again" - } - } - - $NSXTIPPoolService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_pools" - - class allocation_ranges { - [string]$start - [string]$end - #$self - } - - class subnets { - [array]$allocation_ranges = [allocation_ranges]::new() - [array]$dns_nameservers - [string]$dns_suffix - [string]$cidr - [string]$gateway_ip - #hidden $self - } - - class ip_pool { - [string]$display_name - [string]$description - [string]$resource_type = 'IpPool' - [long]$revision = '0' - [array]$subnets = [subnets]::new() - hidden $pool_usage - hidden [array]$tags - # hidden $self - hidden $links - } - } - - Process - { - $sample_ip_pool = $NSXTIPPoolService.help.create.ip_pool.Create() - $sample_ip_pool.subnets = @($NSXTIPPoolService.help.create.ip_pool.subnets.Create()) - $sample_ip_pool.subnets = @($NSXTIPPoolService.help.create.ip_pool.subnets.Element.Create()) - $sample_ip_pool.subnets[0].allocation_ranges = @($NSXTIPPoolService.help.create.ip_pool.subnets.Element.allocation_ranges.create()) - $sample_ip_pool.subnets[0].allocation_ranges = @($NSXTIPPoolService.help.create.ip_pool.subnets.Element.allocation_ranges.element.create()) - - #Remove buggy self object - $ip_pool = $sample_ip_pool | select -Property * -ExcludeProperty self - $ip_pool.subnets[0] = $sample_ip_pool.subnets[0] | select -Property * -ExcludeProperty self - $ip_pool.subnets[0].allocation_ranges[0] = $sample_ip_pool.subnets[0].allocation_ranges[0] | select -Property * -ExcludeProperty self - - # Assign objects - $ip_pool.display_name = $display_name - $ip_pool.description = $description - $ip_pool.resource_type = "IpPool" - $ip_pool.subnets[0].dns_nameservers = @($dns_nameservers) - $ip_pool.subnets[0].dns_suffix = $dns_suffix - $ip_pool.subnets[0].allocation_ranges[0].start = $allocation_start - $ip_pool.subnets[0].allocation_ranges[0].end = $allocation_end - $ip_pool.subnets[0].cidr = $cidr - $ip_pool.subnets[0].gateway_ip = $gateway_ip - $ip_pool.revision = 0 - $ip_pool.tags = @() - - # Accepted JSON object ok yet it did not interpret any of the parameters - $ip_pool_json = ConvertTo-Json $ip_pool -Depth 10 - - try - { - # Should process - if ($pscmdlet.ShouldProcess($ip_pool.display_name, "Create IP Pool")) - { - $ip_pool_json - #$NSXTIPPool = $NSXTIPPoolService.create($ip_pool_json) - $NSXTIPPoolService.create($ip_pool_json) - } - } - - catch - { - $Error[0].Exception.ServerError.data - # more error data found in the NSX-T Manager /var/log/vmware/nsx-manager.log file; grep POOL-MGMT - throw - } - - #$NSXTIPPool - } -} ########################### # # From 3a022777d37e9dff6b2b9fdadc03567fcd650fb7 Mon Sep 17 00:00:00 2001 From: AndyG Date: Wed, 19 Sep 2018 22:06:01 -0500 Subject: [PATCH 33/65] Removed unnecessary JSON conversion in template Removed unnecessary JSON conversion in template --- Modules/NSXT/NSXT.psm1 | 2 -- 1 file changed, 2 deletions(-) diff --git a/Modules/NSXT/NSXT.psm1 b/Modules/NSXT/NSXT.psm1 index 3a0d270..6d52412 100644 --- a/Modules/NSXT/NSXT.psm1 +++ b/Modules/NSXT/NSXT.psm1 @@ -2022,8 +2022,6 @@ Function Set-NSXTThingTemplate { $logical_THING_request.replication_mode = $replication_mode $logical_THING_request.ip_pool_id = $ip_pool_id - $logical_THING_request_json = ConvertTo-Json $logical_THING_request -Depth 10 - try { # Should process From 5052044ae1c7cfd35c85be6d18eaf17a96733e81 Mon Sep 17 00:00:00 2001 From: AndyG Date: Wed, 19 Sep 2018 22:08:39 -0500 Subject: [PATCH 34/65] Added Comment to Set-NSXTIPPool Added Comment to Set-NSXTIPPool --- Modules/NSXT/NSXT.psm1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/NSXT/NSXT.psm1 b/Modules/NSXT/NSXT.psm1 index 6d52412..4e135e8 100644 --- a/Modules/NSXT/NSXT.psm1 +++ b/Modules/NSXT/NSXT.psm1 @@ -1577,7 +1577,8 @@ Function Set-NSXTIPPool { } $NSXTIPPoolService = Get-NsxtService -Name "com.vmware.nsx.pools.ip_pools" - + + # Classes unused - part of early testing class allocation_ranges { [string]$start [string]$end From b25c2807149fc9d8267ac8e5b9a8f76ebd06e2a9 Mon Sep 17 00:00:00 2001 From: Doug Taliaferro Date: Wed, 3 Oct 2018 21:09:18 -0400 Subject: [PATCH 35/65] Sample script to set VM tags in the guestinfo --- Scripts/Set-TagsInGuestinfo.ps1 | 98 +++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 Scripts/Set-TagsInGuestinfo.ps1 diff --git a/Scripts/Set-TagsInGuestinfo.ps1 b/Scripts/Set-TagsInGuestinfo.ps1 new file mode 100644 index 0000000..e895759 --- /dev/null +++ b/Scripts/Set-TagsInGuestinfo.ps1 @@ -0,0 +1,98 @@ +<# +.NOTES + Script name: Set-TagsInGuestinfo.ps1 + Created on: 10/02/2018 + Author: Doug Taliaferro, @virtually_doug + Description: Gets the vSphere Tags assigned to a VM and makes them available to the guest OS. + Dependencies: None known + + ===Tested Against Environment==== + vSphere Version: 6.5 + PowerCLI Version: 10.0.0.7893909 + PowerShell Version: 5.1.14409.1005 + OS Version: Windows 7, 10 + Keyword: VM, Tags, Guestinfo + +.SYNOPSIS + Gets the vSphere Tags assigned to a VM and makes them available to the guest OS. + +.DESCRIPTION + Gets the tags assigned to one or more VMs from one or more categories and sets the tag values + in the VM's 'guestinfo' advanced settings. This makes the tags available within the guest OS + using VM tools (vmtoolsd.exe) and allows the tags to be used as metadata for applications or + management agents that run inside the guest. + + For example, if a VM has a tag named 'Accounting' from the + category 'Departments', the advanced setting becomes: + guestinfo.Departments = Accounting + + This can be retrieved in the guest OS by running: + vmtoolsd.exe --cmd "info-get guestinfo.Departments" + + If multiple tags are assigned from the same category, they are joined using the specified + delimter (a semicolon by default): + guestinfo.Departments = Accounting;Sales + +.PARAMETER VMs + One or more VMs returned from the Get-VM cmdlet. + +.PARAMETER Categories + The names of tag categories that should be set in the advanced settings. + + .PARAMETER Delimiter + The delimiting character used for multiple tags of the same category. Defaults to a + semicolon. + +.PARAMETER vCenter + The vCenter server to connect to. Optional if you are already connected. + +.EXAMPLE + .\Set-TagsInGuestInfo.ps1 -VM (get-vm testvm01) -Categories Departments, Environment + + Gets tags assigned to 'testvm01' in the Departments and Environment categories and + sets their values in 'guestinfo.Departments' and 'guestinfo.Environment'. + +.EXAMPLE + .\Set-TagsInGuestInfo.ps1 -VM (get-cluster Dev-01 | get-vm) -Categories Departments + + Gets tags assigned to all VMs in the Dev-01 cluster and sets 'guestinfo.Departments' + on each VM. +#> +#Requires -modules VMware.VimAutomation.Core +[CmdletBinding()] +param ( + [Parameter(Mandatory=$true,Position=0)] + $VMs, + [Parameter(Mandatory=$true,Position=1)] + [string[]]$Categories, + [string]$Delimiter = ';', + [string]$vCenter +) +if ($vCenter) { + Connect-VIServer $vCenter +} + +ForEach ($categoryName in $Categories) { + $category = Get-TagCategory -Name $categoryName + if ($category) { + $guestinfoName = "guestinfo.$category" + + # Get Tag assignments for the VMs + $tags = Get-TagAssignment -Entity $VMs -Category $category + + # Group the tags by VM (in this case the Entity property of Group-Object) + $groups = $tags | Group-Object -Property Entity + + # Get each VM and set the guestinfo + ForEach ($item in $groups) { + $vm = get-vm $item.Name + # Multiple tags of the same category are joined + $guestinfoValue = $item.Group.Tag.Name -join $Delimiter + + Write-Host "$($vm): setting '$guestinfoName' = '$guestinfoValue'" + New-AdvancedSetting -Entity $vm -Name $guestinfoName -Value $guestinfoValue -Confirm:$false -Force | Out-Null + } + } else { + Write-Host "Category '$categoryName' was not found." + } +} From 0581d89cbe79ccca9968761e9a70ad11cc513113 Mon Sep 17 00:00:00 2001 From: Doug Taliaferro Date: Wed, 3 Oct 2018 21:16:50 -0400 Subject: [PATCH 36/65] Sample script to set VM tags in the guestinfo --- Scripts/Set-TagsInGuestinfo.ps1 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Scripts/Set-TagsInGuestinfo.ps1 b/Scripts/Set-TagsInGuestinfo.ps1 index e895759..c245c05 100644 --- a/Scripts/Set-TagsInGuestinfo.ps1 +++ b/Scripts/Set-TagsInGuestinfo.ps1 @@ -79,16 +79,16 @@ ForEach ($categoryName in $Categories) { # Get Tag assignments for the VMs $tags = Get-TagAssignment -Entity $VMs -Category $category - - # Group the tags by VM (in this case the Entity property of Group-Object) + + # Group the tags by VM (in this case the Entity property of Group-Object) $groups = $tags | Group-Object -Property Entity - - # Get each VM and set the guestinfo + + # Get each VM and set the guestinfo ForEach ($item in $groups) { $vm = get-vm $item.Name - # Multiple tags of the same category are joined + # Multiple tags of the same category are joined $guestinfoValue = $item.Group.Tag.Name -join $Delimiter - + Write-Host "$($vm): setting '$guestinfoName' = '$guestinfoValue'" New-AdvancedSetting -Entity $vm -Name $guestinfoName -Value $guestinfoValue -Confirm:$false -Force | Out-Null } From 4246cfc71f9f185e8d7f6ccc9460782575dbdf09 Mon Sep 17 00:00:00 2001 From: Doug Taliaferro Date: Thu, 4 Oct 2018 19:53:08 -0400 Subject: [PATCH 37/65] Script to set custom attributes in guestinfo --- Scripts/Set-CustomAttributesInGuestinfo.ps1 | 84 +++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 Scripts/Set-CustomAttributesInGuestinfo.ps1 diff --git a/Scripts/Set-CustomAttributesInGuestinfo.ps1 b/Scripts/Set-CustomAttributesInGuestinfo.ps1 new file mode 100644 index 0000000..d76d3ee --- /dev/null +++ b/Scripts/Set-CustomAttributesInGuestinfo.ps1 @@ -0,0 +1,84 @@ +<# +.NOTES + Script name: Set-CustomAttributesInGuestinfo.ps1 + Created on: 10/04/2018 + Author: Doug Taliaferro, @virtually_doug + Description: Gets Custom Attributes assigned to a VM and makes them available to the guest OS. + Dependencies: None known + + ===Tested Against Environment==== + vSphere Version: 6.5 + PowerCLI Version: 10.0.0.7893909 + PowerShell Version: 5.1.14409.1005 + OS Version: Windows 7, 10 + Keyword: VM, Attributes, Guestinfo + +.SYNOPSIS + Gets Custom Attributes assigned to a VM and makes them available to the guest OS. + +.DESCRIPTION + Gets the custom attributes assigned to one or more VMs and sets their values in the + VM's 'guestinfo' advanced settings. This makes the attributes available within the + guest OS using VM tools (vmtoolsd.exe) and allows the attributes to be used as metadata + for applications or management agents that run inside the guest. If the attribute name + contains spaces they are removed in naming the advanced setting. + + For example, if a VM has a custom attribute named 'Created On', the advanced setting + becomes: + 'guestinfo.CreatedOn' = '08/08/2018 14:24:17' + + This can be retrieved in the guest OS by running: + vmtoolsd.exe --cmd "info-get guestinfo.CreatedOn" + +.PARAMETER VMs + One or more VMs returned from the Get-VM cmdlet. + +.PARAMETER Attributes + The names of the Custom Attributes to get. If the names contain spaces they must be + enclosed in quotes. The spaces will be removed to name the advanced setting. + +.PARAMETER vCenter + The vCenter server to connect to. Optional if you are already connected. + +.EXAMPLE + .\Set-CustomAttributesInGuestInfo.ps1 -VM (get-vm testvm01) -Attributes 'Created On', 'Created By' + + Gets the custom attributes 'Created On' and 'Created By' for 'testvm01' and sets their + values in 'guestinfo.CreatedOn' and 'guestinfo.CreatedBy'. + +.EXAMPLE + .\Set-CustomAttributesInGuestInfo.ps1-VM (get-cluster Dev-01 | get-vm) -Attributes 'Created On' + + Gets the custom attribute 'Created On' for all VMs in the Dev-01 cluster and sets 'guestinfo.CreatedOn' + on each VM. +#> +#Requires -modules VMware.VimAutomation.Core +[CmdletBinding()] +param ( + [Parameter(Mandatory=$true,Position=0)] + $VMs, + [Parameter(Mandatory=$true,Position=1)] + [string[]]$Attributes, + [string]$vCenter +) +if ($vCenter) { + Connect-VIServer $vCenter +} + +ForEach ($vm in $VMs) { + ForEach ($attributeName in $Attributes) { + # Get the custom attribute with a matcing key name + $customField = $vm.CustomFields | Where-Object Key -eq $attributeName + if ($customField) { + # Remove white space from the attribute name because the advanced + # setting name cannot contain spaces + $attributeNameNoSpaces = $customField.Key -replace '\s','' + $guestinfoName = "guestinfo.$attributeNameNoSpaces" + $guestinfoValue = $customField.Value + Write-Host "$($vm): setting '$guestinfoName' = '$guestinfoValue'" + New-AdvancedSetting -Entity $vm -Name $guestinfoName -Value $guestinfoValue -Confirm:$false -Force | Out-Null + } else { + Write-Host "$($vm): custom attribute '$attributeName' not set on this VM" + } + } +} From 501bfa7fd2b5ea1111f321caab418faf9a7d8f35 Mon Sep 17 00:00:00 2001 From: Gerasimos Alexiou Date: Tue, 9 Oct 2018 22:48:07 +0300 Subject: [PATCH 38/65] backup-esxi-host-configuration backup-esxi-host-configuration powershell script --- Scripts/backup-esxi-host-configuration.ps1 | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 Scripts/backup-esxi-host-configuration.ps1 diff --git a/Scripts/backup-esxi-host-configuration.ps1 b/Scripts/backup-esxi-host-configuration.ps1 new file mode 100644 index 0000000..924ca06 --- /dev/null +++ b/Scripts/backup-esxi-host-configuration.ps1 @@ -0,0 +1,22 @@ +<# +Script name: backup-esxi-host-configuration.ps1 +Created on: 09/10/2018 +Author: Gerasimos Alexiou, @jerrak0s +Description: The purpose of the script is to backup esxi host configuration for restore purposes. +Dependencies: None known + +===Tested Against Environment==== +vSphere Version: 6.5 U2 +PowerCLI Version: PowerCLI 10.1.1 +PowerShell Version: 5.1 +OS Version: Windows 10 +Keyword: Backup Configuration ESXi Host +#> + + +$serverIp = Read-Host 'What is the server ip address:' +$path = Read-Host 'Give path where backup configuration will be stored:' +$serverPass = Read-Host 'What is the server root password:' -AsSecureString +Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false +Connect-VIServer serverip -user "root" -password $serverPass +Get-VMHostFirmware -vmhost serverip -BackupConfiguration -DestinationPath $path \ No newline at end of file From b68dc6c4e08b7d401f77d291c56ab5c4fee7d1dc Mon Sep 17 00:00:00 2001 From: LucD Date: Thu, 25 Oct 2018 10:02:23 +0200 Subject: [PATCH 39/65] Updated VMware.VMC Fix issue #176 Added functions: - Get-VMCEdge - Get-VMCEdgeNic - Get-VMCEdgeStatus - Get-VMCEdgeNicStat - Get-VMCEdgeUplinkStat --- Modules/VMware.VMC/VMware.VMC.psd1 | Bin 8332 -> 8558 bytes Modules/VMware.VMC/VMware.VMC.psm1 | 573 ++++++++++++++++++++++------- 2 files changed, 435 insertions(+), 138 deletions(-) diff --git a/Modules/VMware.VMC/VMware.VMC.psd1 b/Modules/VMware.VMC/VMware.VMC.psd1 index b33fca99fccc962543854a8ef2a85c1d00f7e2e2..105fec0612b9384cc68ec1d1240ff768945cef05 100755 GIT binary patch delta 162 zcmeBieCM=bj}SW-g8~Rnz9=ZX_?!?UoPSpMJf{u=k}SI`LkdGWL+WICA#q+Po57DE zlOY)-A`BA=W+-7u1maSLVvx8fOdPC|0V)fUk%q~HG88c60L{r`$cD*po+ -SDDCName -GatewayType -Path "C:\Users\lamw\Desktop\VMCFirewallRules.json" #> - param( + param( [Parameter(Mandatory=$false)][String]$SDDCName, [Parameter(Mandatory=$false)][String]$OrgName, [Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType, [Parameter(Mandatory=$false)][String]$Path ) - if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } + if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } - if($GatewayType -eq "MGW") { + if($GatewayType -eq "MGW") { $EdgeId = "edge-1" } else { $EdgeId = "edge-2" } - $orgId = (Get-VMCOrg -Name $OrgName).Id - $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id - if(-not $orgId) { + if(-not $orgId) { Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" break } - if(-not $sddcId) { + if(-not $sddcId) { Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" break } - $firewallConfigService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config + $firewallConfigService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config - $firewallRules = ($firewallConfigService.get($orgId, $sddcId, $EdgeId)).firewall_rules.firewall_rules - if(-not $ShowAll) { + $firewallRules = ($firewallConfigService.get($orgId, $sddcId, $EdgeId)).firewall_rules.firewall_rules + if(-not $ShowAll) { $firewallRules = $firewallRules | where { $_.rule_type -ne "default_policy" -and $_.rule_type -ne "internal_high" -and $_.name -ne "vSphere Cluster HA" -and $_.name -ne "Outbound Access" } | Sort-Object -Property rule_tag } else { $firewallRules = $firewallRules | Sort-Object -Property rule_tag } - $results = @() - $count = 0 - foreach ($firewallRule in $firewallRules) { + $results = @() + $count = 0 + foreach ($firewallRule in $firewallRules) { if($firewallRule.source.ip_address.Count -ne 0) { $source = $firewallRule.source.ip_address } else { @@ -473,16 +471,15 @@ Function Get-VMCFirewallRule { $count+=1 $results+=$tmp } - if($Path) { + if($Path) { Write-Host -ForegroundColor Green "Exporting $count VMC Firewall Rules to $Path ..." $results | ConvertTo-Json | Out-File $Path } else { $results | ConvertTo-Json } - } - - Function Import-VMCFirewallRule { - <# +} +Function Import-VMCFirewallRule { +<# .NOTES =========================================================================== Created by: William Lam @@ -499,43 +496,43 @@ Function Get-VMCFirewallRule { .EXAMPLE Import-VMCFirewallRule -OrgName -SDDCName -GatewayType -Path "C:\Users\lamw\Desktop\VMCFirewallRules.json" #> - param( + param( [Parameter(Mandatory=$false)][String]$SDDCName, [Parameter(Mandatory=$false)][String]$OrgName, [Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType, [Parameter(Mandatory=$false)][String]$Path ) - if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } + if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } - if($GatewayType -eq "MGW") { + if($GatewayType -eq "MGW") { $EdgeId = "edge-1" } else { $EdgeId = "edge-2" } - $orgId = (Get-VMCOrg -Name $OrgName).Id - $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id - if(-not $orgId) { + if(-not $orgId) { Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" break } - if(-not $sddcId) { + if(-not $sddcId) { Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" break } - $firewallService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config.rules + $firewallService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config.rules - $vmcFirewallRulesJSON = Get-Content -Raw $Path | ConvertFrom-Json + $vmcFirewallRulesJSON = Get-Content -Raw $Path | ConvertFrom-Json - # Create top level Firewall Rules Object - $firewallRules = $firewallService.Help.add.firewall_rules.Create() - # Create top top level Firewall Rule Spec which will be an array of individual Firewall rules as we process them in next section - $ruleSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Create() + # Create top level Firewall Rules Object + $firewallRules = $firewallService.Help.add.firewall_rules.Create() + # Create top top level Firewall Rule Spec which will be an array of individual Firewall rules as we process them in next section + $ruleSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Create() - foreach ($vmcFirewallRule in $vmcFirewallRulesJSON) { + foreach ($vmcFirewallRule in $vmcFirewallRulesJSON) { # Create Individual Firewall Rule Element Spec $ruleElementSpec = $firewallService.Help.add.firewall_rules.firewall_rules.Element.Create() @@ -632,14 +629,13 @@ Function Get-VMCFirewallRule { Write-host "Creating VMC Firewall Rule Spec:" $vmcFirewallRule.Name "..." $ruleSpecAdd = $ruleSpec.Add($ruleElementSpec) } - $firewallRules.firewall_rules = $ruleSpec + $firewallRules.firewall_rules = $ruleSpec - Write-host "Adding VMC Firewall Rules ..." - $firewallRuleAdd = $firewallService.add($orgId,$sddcId,$EdgeId,$firewallRules) - } - - Function Remove-VMCFirewallRule { - <# + Write-host "Adding VMC Firewall Rules ..." + $firewallRuleAdd = $firewallService.add($orgId,$sddcId,$EdgeId,$firewallRules) +} +Function Remove-VMCFirewallRule { +<# .NOTES =========================================================================== Created by: William Lam @@ -656,38 +652,37 @@ Function Get-VMCFirewallRule { .EXAMPLE Remove-VMCFirewallRule -OrgName -SDDCName -GatewayType -RuleId #> - param( + param( [Parameter(Mandatory=$false)][String]$SDDCName, [Parameter(Mandatory=$false)][String]$OrgName, [Parameter(Mandatory=$true)][ValidateSet("MGW","CGW")][String]$GatewayType, [Parameter(Mandatory=$false)][String]$RuleId ) - if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } + if (-not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect"; break } - if($GatewayType -eq "MGW") { + if($GatewayType -eq "MGW") { $EdgeId = "edge-1" } else { $EdgeId = "edge-2" } - $orgId = (Get-VMCOrg -Name $OrgName).Id - $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id - if(-not $orgId) { + if(-not $orgId) { Write-Host -ForegroundColor red "Unable to find Org $OrgName, please verify input" break } - if(-not $sddcId) { + if(-not $sddcId) { Write-Host -ForegroundColor red "Unable to find SDDC $SDDCName, please verify input" break } - $firewallService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config.rules - Write-Host "Removing VMC Firewall Rule Id $RuleId ..." - $firewallService.delete($orgId,$sddcId,$EdgeId,$RuleId) - } - + $firewallService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config.rules + Write-Host "Removing VMC Firewall Rule Id $RuleId ..." + $firewallService.delete($orgId,$sddcId,$EdgeId,$RuleId) +} Function Get-VMCLogicalNetwork { <# .NOTES @@ -727,9 +722,17 @@ Function Get-VMCLogicalNetwork { break } - $logicalNetworkService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.logical + # @LucD22 - 21/10/18 - Fix for issue #176 VMware.VMC module only lists firts 20 Logical networks + # Loop until entries (total_count) are returned - $logicalNetworks = ($logicalNetworkService.get_0($orgId, $sddcId)).data | Sort-Object -Property id + $index = [long]0 + + $logicalNetworks = do{ + $netData = $logicalNetworkService.get_0($orgId,$sddcId,$pagesize,$index) + $netData.data | Sort-Object -Property id + $index = $index + $netdata.paging_info.page_size + } + until($index -ge $netData.paging_info.total_count) if($LogicalNetworkName) { $logicalNetworks = $logicalNetworks | Where-Object {$_.Name -eq $LogicalNetworkName} @@ -751,7 +754,6 @@ Function Get-VMCLogicalNetwork { } $results } - Function Remove-VMCLogicalNetwork { <# .NOTES @@ -799,25 +801,24 @@ Function Remove-VMCLogicalNetwork { $logicalNetworkService = Get-VmcService com.vmware.vmc.orgs.sddcs.networks.logical $logicalNetworkService.delete($orgId,$sddcId,$lsId) } - Function New-VMCLogicalNetwork { - <# - .NOTES - =========================================================================== - Created by: Kyle Ruddy - Date: 03/06/2018 - Organization: VMware - Blog: https://thatcouldbeaproblem.com - Twitter: @kmruddy - =========================================================================== +<# + .NOTES + =========================================================================== + Created by: Kyle Ruddy + Date: 03/06/2018 + Organization: VMware + Blog: https://thatcouldbeaproblem.com + Twitter: @kmruddy + =========================================================================== - .SYNOPSIS - Creates a new Logical Network - .DESCRIPTION - Creates a new Logical Network - .EXAMPLE - New-VMCLogicalNetwork -OrgName -SDDCName -LogicalNetworkName -SubnetMask -Gateway - #> + .SYNOPSIS + Creates a new Logical Network + .DESCRIPTION + Creates a new Logical Network + .EXAMPLE + New-VMCLogicalNetwork -OrgName -SDDCName -LogicalNetworkName -SubnetMask -Gateway +#> [cmdletbinding(SupportsShouldProcess = $true,ConfirmImpact='High')] param( [Parameter(Mandatory=$true)][String]$SDDCName, @@ -854,7 +855,6 @@ Function New-VMCLogicalNetwork { $logicalNetworkService.create($orgId, $sddcId, $logicalNetworkSpec) Get-VMCLogicalNetwork -OrgName $OrgName -SDDCName $SDDCName -LogicalNetworkName $LogicalNetworkName } - Function Get-VMCSDDCSummary { <# .NOTES @@ -899,7 +899,6 @@ Function Get-VMCSDDCSummary { $results } } - Function Get-VMCPublicIP { <# .NOTES @@ -933,79 +932,377 @@ Function Get-VMCPublicIP { $publicIPs | select public_ip, name, allocation_id } } +Function New-VMCPublicIP { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 09/12/2018 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== - Function New-VMCPublicIP { - <# - .NOTES - =========================================================================== - Created by: William Lam - Date: 09/12/2018 - Organization: VMware - Blog: http://www.virtuallyghetto.com - Twitter: @lamw - =========================================================================== + .SYNOPSIS + Request a new public IP Address for a given SDDC + .DESCRIPTION + This cmdlet requests a new public IP Address for a given SDDC + .EXAMPLE + New-VMCPublicIP -OrgName $OrgName -SDDCName $SDDCName -Description "Test for Randy" +#> + Param ( + [Parameter(Mandatory=$True)]$OrgName, + [Parameter(Mandatory=$True)]$SDDCName, + [Parameter(Mandatory=$False)]$Description + ) - .SYNOPSIS - Request a new public IP Address for a given SDDC - .DESCRIPTION - This cmdlet requests a new public IP Address for a given SDDC - .EXAMPLE - New-VMCPublicIP -OrgName $OrgName -SDDCName $SDDCName -Description "Test for Randy" - #> - Param ( - [Parameter(Mandatory=$True)]$OrgName, - [Parameter(Mandatory=$True)]$SDDCName, - [Parameter(Mandatory=$False)]$Description - ) + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id - If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { - $orgId = (Get-VMCOrg -Name $OrgName).Id - $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + $publicIPService = Get-VmcService "com.vmware.vmc.orgs.sddcs.publicips" - $publicIPService = Get-VmcService "com.vmware.vmc.orgs.sddcs.publicips" + $publicIPSpec = $publicIPService.Help.create.spec.Create() + $publicIPSpec.count = 1 + $publicIPSpec.names = @($Description) - $publicIPSpec = $publicIPService.Help.create.spec.Create() - $publicIPSpec.count = 1 - $publicIPSpec.names = @($Description) + Write-Host "Requesting a new public IP Address for your SDDC ..." + $results = $publicIPService.create($orgId,$sddcId,$publicIPSpec) + } +} +Function Remove-VMCPublicIP { +<# + .NOTES + =========================================================================== + Created by: William Lam + Date: 09/12/2018 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== - Write-Host "Requesting a new public IP Address for your SDDC ..." - $results = $publicIPService.create($orgId,$sddcId,$publicIPSpec) + .SYNOPSIS + Removes a specific public IP Addresses for a given SDDC + .DESCRIPTION + This cmdlet removes a specific public IP Address for a given SDDC + .EXAMPLE + Remove-VMCPublicIP -OrgName $OrgName -SDDCName $SDDCName -AllocationId "eipalloc-0567acf34e436c01f" +#> + Param ( + [Parameter(Mandatory=$True)]$OrgName, + [Parameter(Mandatory=$True)]$SDDCName, + [Parameter(Mandatory=$True)]$AllocationId + ) + + If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + + $publicIPService = Get-VmcService "com.vmware.vmc.orgs.sddcs.publicips" + + Write-Host "Deleting public IP Address with ID $AllocationId ..." + $results = $publicIPService.delete($orgId,$sddcId,$AllocationId) + } +} +Function Get-VMCEdge { +<# +.NOTES +=========================================================================== +Created by: Luc Dekens +Date: 23/10/2018 +Organization: Community +Blog: http://lucd.info +Twitter: @LucD22 +=========================================================================== + +.SYNOPSIS + Returns all the VMC Edges +.DESCRIPTION + Returns all the VMC Edges +.EXAMPLE + Get-VMCEdge -OrgName $orgName -SddcName $SDDCName -EdgeType gatewayServices +#> + Param ( + [Parameter(Mandatory=$True)] + [string]$OrgName, + [Parameter(Mandatory=$True)] + [string]$SDDCName, + [ValidateSet('gatewayServices','distributedRouter')] + [string]$EdgeType = '' + ) + + If (-Not $global:DefaultVMCServers) { + Write-error "No VMC Connection found, please use the Connect-VMC to connect" + } + Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + + $edgeService = Get-VmcService -Name 'com.vmware.vmc.orgs.sddcs.networks.edges' + $index = [long]0 + $edges = do{ + $edgeData = $edgeService.get($orgId,$sddcId,$EdgeType,'',$index) + $edgeData.edge_page.data | Sort-Object -Property id + $index = $index + $edgeData.edge_page.paging_info.page_size + } + until($index -ge $edgeData.paging_info.total_count) + $edges | %{ + [pscustomobject]@{ + Name = $_.Name + Id = $_.id + Type = $_.edge_type + State = $_.state + Status = $_.edge_status + VNics = $_.number_of_connected_vnics + TenantId = $_.tenant_id + } } } +} +Function Get-VMCEdgeStatus { +<# +.NOTES +=========================================================================== +Created by: Luc Dekens +Date: 23/10/2018 +Organization: Community +Blog: http://lucd.info +Twitter: @LucD22 +=========================================================================== - Function Remove-VMCPublicIP { - <# - .NOTES - =========================================================================== - Created by: William Lam - Date: 09/12/2018 - Organization: VMware - Blog: http://www.virtuallyghetto.com - Twitter: @lamw - =========================================================================== +.SYNOPSIS + Returns the status of the gateway +.DESCRIPTION + Retrieve the status of the specified management or compute gateway (NSX Edge). +.EXAMPLE + Get-VMCEdgeStatus -OrgName $orgName -SddcName $SDDCName -Edge $EdgeName +#> + Param ( + [Parameter(Mandatory=$True)] + [string]$OrgName, + [Parameter(Mandatory=$True)] + [string]$SDDCName, + [Parameter(Mandatory=$True)] + [string]$EdgeName + ) - .SYNOPSIS - Removes a specific public IP Addresses for a given SDDC - .DESCRIPTION - This cmdlet removes a specific public IP Address for a given SDDC - .EXAMPLE - Remove-VMCPublicIP -OrgName $OrgName -SDDCName $SDDCName -AllocationId "eipalloc-0567acf34e436c01f" - #> - Param ( - [Parameter(Mandatory=$True)]$OrgName, - [Parameter(Mandatory=$True)]$SDDCName, - [Parameter(Mandatory=$True)]$AllocationId - ) + If (-Not $global:DefaultVMCServers) { + Write-error "No VMC Connection found, please use the Connect-VMC to connect" + } + Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + $edgeId = Get-VMCEdge -SDDCName $SDDCName -Org $OrgName | where{$_.Name -eq $EdgeName} | select -ExpandProperty Id - If (-Not $global:DefaultVMCServers) { Write-error "No VMC Connection found, please use the Connect-VMC to connect" } Else { - $orgId = (Get-VMCOrg -Name $OrgName).Id - $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + $statusService = Get-VmcService -Name 'com.vmware.vmc.orgs.sddcs.networks.edges.status' + $status = $statusService.get($orgId,$sddcId,$edgeId) - $publicIPService = Get-VmcService "com.vmware.vmc.orgs.sddcs.publicips" - - Write-Host "Deleting public IP Address with ID $AllocationId ..." - $results = $publicIPService.delete($orgId,$sddcId,$AllocationId) + $vmStatus = $status.edge_vm_status | %{ + [pscustomobject]@{ + Name = $_.name + State = $_.edge_VM_status + HAState = $_.ha_state + Index = $_.index + } + } + $featureStatus = $status.feature_statuses | %{ + [pscustomobject]@{ + Service = $_.service + Status = $_.status + } + } + [pscustomobject]@{ + Time = [timezone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddSeconds($status.timestamp/1000)) + Status = $status.edge_status + PublishStatus = $status.publish_status + SystemStatus = $_.system_status + NicInUse = $status.ha_vnic_in_use } } +} +Function Get-VMCEdgeNic { +<# +.NOTES +=========================================================================== +Created by: Luc Dekens +Date: 23/10/2018 +Organization: Community +Blog: http://lucd.info +Twitter: @LucD22 +=========================================================================== -Export-ModuleMember -Function 'Get-VMCCommand', 'Connect-VMCVIServer', 'Get-VMCOrg', 'Get-VMCSDDC', 'Get-VMCTask', 'Get-VMCSDDCDefaultCredential', 'Get-VMCSDDCPublicIP', 'Get-VMCVMHost', 'Get-VMCSDDCVersion', 'Get-VMCFirewallRule', 'Export-VMCFirewallRule', 'Import-VMCFirewallRule', 'Remove-VMCFirewallRule', 'Get-VMCLogicalNetwork', 'Remove-VMCLogicalNetwork', 'New-VMCLogicalNetwork', 'Get-VMCSDDCSummary', 'Get-VMCPublicIP', 'New-VMCPublicIP', 'Remove-VMCPublicIP' +.SYNOPSIS + Returns all interfaces for the gateway +.DESCRIPTION + Retrieve all interfaces for the specified management or compute gateway (NSX Edge). +.EXAMPLE + Get-VMCEdgeNic -OrgName $orgName -SddcName $SDDCName -Edge $EdgeName +#> + Param ( + [Parameter(Mandatory=$True)] + [string]$OrgName, + [Parameter(Mandatory=$True)] + [string]$SDDCName, + [Parameter(Mandatory=$True)] + [string]$EdgeName + ) + + If (-Not $global:DefaultVMCServers) { + Write-error "No VMC Connection found, please use the Connect-VMC to connect" + } + Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + $edgeId = Get-VMCEdge -SDDCName $SDDCName -Org $OrgName | where{$_.Name -eq $EdgeName} | select -ExpandProperty Id + + $vnicService = Get-VmcService -Name 'com.vmware.vmc.orgs.sddcs.networks.edges.vnics' + $vnicService.get($orgId,$sddcId,$edgeId) | select -ExpandProperty vnics | %{ + [pscustomobject]@{ + Label = $_.label + Name = $_.Name + Type = $_.type + Index = $_.index + IsConnected = $_.is_connected + Portgroup = $_.portgroup_name + } + } + } +} +Function Get-VMCEdgeNicStat { +<# +.NOTES +=========================================================================== +Created by: Luc Dekens +Date: 23/10/2018 +Organization: Community +Blog: http://lucd.info +Twitter: @LucD22 +=========================================================================== + +.SYNOPSIS + Returns statistics for the gateway interfaces +.DESCRIPTION + Retrieve interface statistics for a management or compute gateway (NSX Edge). +.EXAMPLE + Get-VMCEdgeNicStat -OrgName $orgName -SddcName $SDDCName -Edge $EdgeName +#> + [CmdletBinding(DefaultParameterSetName='Default')] + Param ( + [Parameter(Mandatory=$True)] + [string]$OrgName, + [Parameter(Mandatory=$True)] + [string]$SDDCName, + [Parameter(Mandatory=$True)] + [string]$EdgeName +# [DateTime]$Start, +# [DateTime]$Finish + ) + + If (-Not $global:DefaultVMCServers) { + Write-error "No VMC Connection found, please use the Connect-VMC to connect" + } + Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + $edgeId = Get-VMCEdge -SDDCName $SDDCName -Org $OrgName | where{$_.Name -eq $EdgeName} | select -ExpandProperty Id + +# $epoch = Get-Date 01/01/1970 +# +# if($start){ +# $startEpoch = (New-TimeSpan -Start $epoch -End $Start.ToUniversalTime()).TotalMilliseconds +# } +# if($Finish){ +# $finishEpoch = (New-TimeSpan -Start $epoch -End $Finish.ToUniversalTime()).TotalMilliseconds +# } + + $vnicStatService = Get-VmcService -Name 'com.vmware.vmc.orgs.sddcs.networks.edges.statistics.interfaces' +# $stats = $vnicStatService.get($orgId,$sddcId,$edgeId,[long]$startEpoch,[long]$finishEpoch) + $stats = $vnicStatService.get($orgId,$sddcId,$edgeId) + + $stats.data_dto | Get-Member -MemberType NoteProperty | where{$_.Name -ne 'Help'} | %{$_.Name} | %{ + $stats.data_dto."$_" | %{ + [pscustomobject]@{ + vNIC = $_.vnic + Timestamp = [timezone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddSeconds($_.timestamp)) + In = $_.in + Out = $_.out + Unit = 'Kbps' + Interval = $stats.meta_dto.interval + } + } + } + } +} +Function Get-VMCEdgeUplinkStat { +<# +.NOTES +=========================================================================== +Created by: Luc Dekens +Date: 23/10/2018 +Organization: Community +Blog: http://lucd.info +Twitter: @LucD22 +=========================================================================== + +.SYNOPSIS + Returns statistics for the uplink interfaces +.DESCRIPTION + Retrieve uplink interface statistics for a management or compute gateway (NSX Edge). +.EXAMPLE + Get-VMCEdgeUplinkStat -OrgName $orgName -SddcName $SDDCName -Edge $EdgeName +#> + Param ( + [Parameter(Mandatory=$True)] + [string]$OrgName, + [Parameter(Mandatory=$True)] + [string]$SDDCName, + [Parameter(Mandatory=$True)] + [string]$EdgeName +# [DateTime]$Start, +# [DateTime]$Finish + ) + + If (-Not $global:DefaultVMCServers) { + Write-error "No VMC Connection found, please use the Connect-VMC to connect" + } + Else { + $orgId = (Get-VMCOrg -Name $OrgName).Id + $sddcId = (Get-VMCSDDC -Name $SDDCName -Org $OrgName).Id + $edgeId = Get-VMCEdge -SDDCName $SDDCName -Org $OrgName | where{$_.Name -eq $EdgeName} | select -ExpandProperty Id + +# $epoch = Get-Date 01/01/1970 +# +# if($start){ +# $startEpoch = (New-TimeSpan -Start $epoch -End $Start.ToUniversalTime()).TotalMilliseconds +# } +# if($Finish){ +# $finishEpoch = (New-TimeSpan -Start $epoch -End $Finish.ToUniversalTime()).TotalMilliseconds +# } + + $uplinkStatService = Get-VmcService -Name 'com.vmware.vmc.orgs.sddcs.networks.edges.statistics.interfaces.uplink' +# $stats = $uplinkStatService.get($orgId,$sddcId,$edgeId,[long]$startEpoch,[long]$finishEpoch) + $stats = $uplinkStatService.get($orgId,$sddcId,$edgeId) + + $stats.data_dto | Get-Member -MemberType NoteProperty | where{$_.Name -ne 'Help'} | %{$_.Name} | %{ + if($stats.data_dto."$_".Count -ne 0){ + $stats.data_dto."$_" | %{ + [pscustomobject]@{ + vNIC = $_.vnic + Timestamp = [timezone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddSeconds($_.timestamp)) + In = $_.in + Out = $_.out + Unit = 'Kbps' + Interval = $stats.meta_dto.interval + } + } + } + } + } +} + +Export-ModuleMember -Function 'Get-VMCCommand', 'Connect-VMCVIServer', 'Get-VMCOrg', 'Get-VMCSDDC', + 'Get-VMCTask', 'Get-VMCSDDCDefaultCredential', 'Get-VMCSDDCPublicIP', 'Get-VMCVMHost', + 'Get-VMCSDDCVersion', 'Get-VMCFirewallRule', 'Export-VMCFirewallRule', 'Import-VMCFirewallRule', + 'Remove-VMCFirewallRule', 'Get-VMCLogicalNetwork', 'Remove-VMCLogicalNetwork', 'New-VMCLogicalNetwork', + 'Get-VMCSDDCSummary', 'Get-VMCPublicIP', 'New-VMCPublicIP', 'Remove-VMCPublicIP', + 'Get-VMCEdge', 'Get-VMCEdgeNic', 'Get-VMCEdgeStatus', 'Get-VMCEdgeNicStat', 'Get-VMCEdgeUplinkStat' From 3904b416b3ddd74827374735911d286437890997 Mon Sep 17 00:00:00 2001 From: LucD Date: Thu, 25 Oct 2018 10:43:04 +0200 Subject: [PATCH 40/65] XRef for VMC services and functions Requires ImportExcel module --- .../VMware_Cloud_on_AWS/XRef-VMC-Services.ps1 | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 Scripts/VMware_Cloud_on_AWS/XRef-VMC-Services.ps1 diff --git a/Scripts/VMware_Cloud_on_AWS/XRef-VMC-Services.ps1 b/Scripts/VMware_Cloud_on_AWS/XRef-VMC-Services.ps1 new file mode 100644 index 0000000..eb591bb --- /dev/null +++ b/Scripts/VMware_Cloud_on_AWS/XRef-VMC-Services.ps1 @@ -0,0 +1,37 @@ +$refreshToken = 'your-refresh-token' + +$reportPath = '.\VMC-services.xlsx' + +Connect-Vmc -RefreshToken $refreshToken > $null + +$columns = @{} +$services = Get-VmcService | Sort-Object -Property Name +$services | ForEach-Object -Process { + $_.Help | Get-Member -MemberType NoteProperty | where{'Constants','Documentation' -notcontains $_.Name} | + ForEach-Object -Process { + if(-not $columns.ContainsKey($_.Name)){ + $columns.Add($_.Name,'') + } + } +} +$columns = $columns.Keys | Sort-Object +$report = @() +foreach($service in $services){ + $obj = [ordered]@{ + Name = $service.Name + } + $columns | ForEach-Object -Process { + $obj.Add($_,'') + } + + $service.Help | Get-Member -MemberType NoteProperty | where{'Constants','Documentation' -notcontains $_.Name} | + ForEach-Object -Process { +# $obj.Item($_.Name) = "$($service.Help.$($_.Name).Documentation)" + $obj.Item($_.Name) = "X" + } + $report += New-Object PSObject -Property $obj +} +$report | Export-Excel -Path $reportPath -WorksheetName 'Services' -FreezeTopRow -BoldTopRow -AutoSize -Show + +Disconnect-Vmc -Confirm:$false + From 37c9effbd79b78337e382ec1290dfb6d974bb810 Mon Sep 17 00:00:00 2001 From: Franciosi Date: Fri, 2 Nov 2018 15:08:07 -0300 Subject: [PATCH 41/65] Update README.md Small typo fix --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 86afe3e..a82900f 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,8 @@ * [Security](https://github.com/vmware/PowerCLI-Example-Scripts#security) * [Resource Maintenance](https://github.com/vmware/PowerCLI-Example-Scripts#resource-maintenance) * [Maintenance Ownership](https://github.com/vmware/PowerCLI-Example-Scripts#maintenance-ownership) - * [Filing issues](https://github.com/vmware/PowerCLI-Example-Scripts#filing-isssues) - * [Resolving issues](https://github.com/vmware/PowerCLI-Example-Scripts#resolving-issues) + * [Filing Issues](https://github.com/vmware/PowerCLI-Example-Scripts#filing-isssues) + * [Resolving Issues](https://github.com/vmware/PowerCLI-Example-Scripts#resolving-issues) * [Additional Resources](https://github.com/vmware/PowerCLI-Example-Scripts#additional-resources) * [Discussions](https://github.com/vmware/PowerCLI-Example-Scripts#discussions) * [VMware Sample Exchange](https://github.com/vmware/PowerCLI-Example-Scripts#vmware-sample-exchange) From ce32e7ab1d5a8706aac618e254f46b243f9fd25b Mon Sep 17 00:00:00 2001 From: Wouter Kursten Date: Thu, 15 Nov 2018 10:07:01 +0100 Subject: [PATCH 42/65] bugfix viewStorageAcceleratorSettings --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 6f176b4..c58e1c0 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -4270,20 +4270,20 @@ function New-HVPool { $redirectWindowsProfile = $false } } - if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.viewStorageAcceleratorSettings) { - $useViewStorageAccelerator = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.viewStorageAcceleratorSettings.UseViewStorageAccelerator + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.viewStorageAcceleratorSettings) { + $useViewStorageAccelerator = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.viewStorageAcceleratorSettings.UseViewStorageAccelerator if ($useViewStorageAccelerator -and $LinkedClone) { - $viewComposerDiskTypes = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.viewStorageAcceleratorSettings.ViewComposerDiskTypes + $viewComposerDiskTypes = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.viewStorageAcceleratorSettings.ViewComposerDiskTypes } if (! $InstantClone -and $useViewStorageAccelerator) { - $regenerateViewStorageAcceleratorDays = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.viewStorageAcceleratorSettings.RegenerateViewStorageAcceleratorDays - if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.viewStorageAcceleratorSettings.blackoutTimes) { - $blackoutTimesList =$jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.viewStorageAcceleratorSettings.blackoutTimes + $regenerateViewStorageAcceleratorDays = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.viewStorageAcceleratorSettings.RegenerateViewStorageAcceleratorDays + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.viewStorageAcceleratorSettings.blackoutTimes) { + $blackoutTimesList =$jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.viewStorageAcceleratorSettings.blackoutTimes foreach ($blackout in $blackoutTimesList) { $blackoutObj = New-Object VMware.Hv.DesktopBlackoutTime $blackoutObj.Days = $blackout.Days $blackoutObj.StartTime = $blackout.StartTime - $blackoutObj.EndTime = $blackoutObj.EndTime + $blackoutObj.EndTime = $blackout.EndTime $blackoutTimes += $blackoutObj } } From 0743c67799b35e155f5e7aaf93b0facdb9a80884 Mon Sep 17 00:00:00 2001 From: Zhoulin Dai Date: Mon, 19 Nov 2018 22:41:26 +0800 Subject: [PATCH 43/65] Initial commit of VMware.VCGChecker module --- .../VMware.VCGChecker/Export-VCGReport.ps1 | 1057 +++++++++++++++++ Modules/VMware.VCGChecker/Get-VCGHWInfo.ps1 | 310 +++++ Modules/VMware.VCGChecker/Get-VCGStatus.ps1 | 168 +++ Modules/VMware.VCGChecker/README.md | 41 + .../VMware.VCGChecker/Save-VCGJsonFile.ps1 | 17 + .../VMware.VCGChecker/VMware.VCGChecker.psd1 | 90 ++ Modules/VMware.VCGChecker/logger.ps1 | 112 ++ 7 files changed, 1795 insertions(+) create mode 100644 Modules/VMware.VCGChecker/Export-VCGReport.ps1 create mode 100644 Modules/VMware.VCGChecker/Get-VCGHWInfo.ps1 create mode 100644 Modules/VMware.VCGChecker/Get-VCGStatus.ps1 create mode 100644 Modules/VMware.VCGChecker/README.md create mode 100644 Modules/VMware.VCGChecker/Save-VCGJsonFile.ps1 create mode 100644 Modules/VMware.VCGChecker/VMware.VCGChecker.psd1 create mode 100644 Modules/VMware.VCGChecker/logger.ps1 diff --git a/Modules/VMware.VCGChecker/Export-VCGReport.ps1 b/Modules/VMware.VCGChecker/Export-VCGReport.ps1 new file mode 100644 index 0000000..1b1253d --- /dev/null +++ b/Modules/VMware.VCGChecker/Export-VCGReport.ps1 @@ -0,0 +1,1057 @@ +# +# Generate the html report and save it to the report folder +# TODO: change to the class +Function Export-VCGReport { + Param( + [Parameter(Mandatory=$true)] $Data, + [Parameter(Mandatory=$true)] $Dir + ) + if (!(Test-Path $Dir)) { + New-Item -Type directory -Confirm:$false -Path $Dir -Force |Out-Null + } + + $Data,$flag = refactorData $Data + + $null=Generate_CsvReport $Data $Dir + $null=Generate_HtmlReport $Data $Dir + $null=Generate_SummaryReport $Data $Dir +} +Function Generate_HtmlReport($Data, $Dir) { + info ("Generating compatibility detail report...") + $content = $generalHead + $content += '

ESXi Hardware Compatibility Report for {0}

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

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

+ + +
+ + + + + + + + + + +'@ + +$generalBodyRest = @' + + + + + + +'@ + +$generalFooter = @' + +
VCDataCenterHostTypeModel NameVendorCompatible StatusHardware DetailComments
+
+ + + +'@ + + +#Summary report +$summaryHead = @' + + + + + Summary Report + + + + + + + +
+
+
+
+
+ +
+ + +'@ + diff --git a/Modules/VMware.VCGChecker/Get-VCGHWInfo.ps1 b/Modules/VMware.VCGChecker/Get-VCGHWInfo.ps1 new file mode 100644 index 0000000..229608f --- /dev/null +++ b/Modules/VMware.VCGChecker/Get-VCGHWInfo.ps1 @@ -0,0 +1,310 @@ +<# +Copyright 2018 VMware, Inc. All rights reserved. +#> + +# Class to manage Host resources +Class HostResource { + [VMware.VimAutomation.Types.VMHost] $vmhost + [string] $vcname + [string] $clustername + [string] $dcname + [string] $hostname + [string] $apitype + [string] $powerstatus + [string] $productname + [string] $version + [string] $fullname + [string] $connectionstatus + [string] $checkRelease + [int] $port + [Array] $ComponentResource = @() + [Array] $JsonProperties = @('__type__', 'dcname', 'vcname','clustername','hostname', 'apitype', + 'powerstatus', 'productname', 'version', 'fullname', 'connectionstatus','checkRelease') + + HostResource( + [VMware.VimAutomation.Types.VMHost] $vmhost) { + $this.vmhost = $vmhost + $view =$vmhost|Get-View + $vCenter_IP = $view.Summary.ManagementServerIp + if($vCenter_IP){ + $this.vcname =$vCenter_IP + $this.dcname = (Get-Datacenter -VMHost $vmhost).Name + $this.clustername = (Get-Cluster -VMHost $vmhost).Name + }else{ + $this.vcname =$this.vmhost.Name + } + $this.hostname = $this.vmhost.Name + $summary = $this.vmhost.ExtensionData.Summary + $this.powerstatus = $summary.runtime.powerState + $this.connectionstatus = $summary.runtime.connectionState + $this.apitype = $summary.Config.Product.apiType + $this.fullname = $summary.Config.Product.FullName + $this.version = $summary.Config.Product.version + $this.productname = $summary.Config.Product.licenseProductName + $this.port = 443 + } + + [Array] query_components() { + if ($this.ComponentResource.Count -eq 0) { + # Get server info + for($count_retry=0;$count_retry -lt 3;$count_retry ++){ + try{ + $svrResoure = [ServerResource]::new() + $svrResoure.set_data($this.vmhost) + $this.ComponentResource += $svrResoure + break + }catch{ + error('query components server for '+$this.vmhost.Name +' error, retry it ' +($count_retry+1) +' times') + } + } + # Get PCI devices + for($count_retry=0;$count_retry -lt 3;$count_retry ++){ + try{ + $this.query_pcidevices() + break + }catch{ + error('query components pcidevice for '+$this.vmhost.Name +' error, retry it ' +($count_retry+1) +' times') + if($count_retry -eq 2){ + error('query components pcidevice for '+$this.vmhost.Name +' faild') + } + } + } + } + return $this.ComponentResource + } + + [void] query_pcidevices() { + $EsxCliV2 = Get-EsxCli -V2 -VMHost $this.vmhost + $AllPciDevice = $EsxCliV2.hardware.pci.list.invoke() + foreach ($Pci in $AllPciDevice) { + # Ignore USB controllers, iLO/iDRAC devices + if ($Pci.DeviceName -like "*USB*" -or $Pci.DeviceName -like "*iLO*" -or $Pci.DeviceName -like "*iDRAC*") { + continue + } + # Get the NICs and storage adapters. + # We found NIC and storage adapters usually have module ID other than 0 or 1 + $pciDevice = [IoDeviceResource]::new() + if ($Pci.ModuleID -ne 0 -and $Pci.ModuleID -ne -1) { + if (!$this.is_pcidevice_exist($Pci)) { + $pciDevice.set_data($Pci, $EsxCliV2) + $this.ComponentResource += $pciDevice + } + } + } + } + + [boolean] is_pcidevice_exist($device) { + foreach ($pci in $this.ComponentResource) { + if ($pci.psobject.TypeNames[0] -eq "IoDeviceResource") { + $vid = [String]::Format("{0:x4}", [int]$device.VendorID) + $did = [String]::Format("{0:x4}", [int]$device.DeviceID) + $svid = [String]::Format("{0:x4}", [int]$device.SubVendorID) + $ssid = [String]::Format("{0:x4}", [int]$device.SubDeviceID) + if ($pci.vid -eq $vid -and $pci.did -eq $did -and + $pci.svid -eq $svid -and $pci.ssid -eq $ssid) { + return $true + } + } + } + return $false + } + + [object] to_jsonobj() { + $Json = $this | Select-Object -Property $this.JsonProperties + $ComponentChildren = @() + $this.ComponentResource | ForEach-Object {$ComponentChildren += $_.to_jsonobj()} + $Json | Add-Member -Name "ComponentResource" -Value $ComponentChildren -MemberType NoteProperty + + return $Json + } + + [string] get_host_status() { + if ($this.powerstatus -and $this.powerstatus -ne 'unknown') { + return $this.powerstatus + } + if ($this.connectionstatus) { + return ("Server " + $this.connectionstatus) + } + else { + return "Server status is unknown" + } + } + + [string] get_prompt_name() { + if ($this.apitype) { + $start = $this.apitype + } + else { + $start = "Host" + } + return $start + " " + $this.hostname + } +} + + +# Class to manage server resources +Class ServerResource { + [string] $type + [string] $model + [string] $vendor + [string] $biosversion + [string] $cpumodel + [string] $cpufeatureid + [string] $uuid + [string] $status + [array] $matchResult + [array] $warnings + [string] $vcgLink + [array] $updateRelease + + [VMware.VimAutomation.Types.VMHost] $vmhost + [Array] $JsonProperties = @('__type__','type', 'model', 'vendor', 'biosversion', + 'cpumodel', 'cpufeatureid', 'uuid','status','matchResult','warnings','vcgLink','updateRelease') + + + [void] set_data( + [VMware.VimAutomation.Types.VMHost] $vmhost) { + $this.vmhost = $vmhost + $this.type = "Server" + $this.model = $this.vmhost.Model + $this.vendor = $this.vmhost.Manufacturer + $this.biosversion = $this.vmhost.ExtensionData.Hardware.BiosInfo.BiosVersion + $this.cpumodel = $this.vmhost.ProcessorType + $cpuFeature = $this.vmhost.ExtensionData.Hardware.CpuFeature + if ($cpuFeature -and $cpuFeature.Count -gt 2) { + $this.cpufeatureid = $this.vmhost.ExtensionData.Hardware.CpuFeature[1].Eax + } + $this.uuid = $this.vmhost.ExtensionData.Hardware.systeminfo.uuid + } + + [object] to_jsonobj() { + return $this | Select-Object -Property $this.JsonProperties + } + +} + +# Class to manage each IO device +Class IoDeviceResource { + + [string] $type + [string] $model + [string] $deviceid + [string] $device + [string] $comptype + [string] $vid + [string] $did + [string] $svid + [string] $ssid + [string] $pciid + [string] $vendor + [string] $driver + [string] $driverversion + [string] $firmware + [string] $status + [array] $matchResult + [array] $warnings + [string] $vcgLink + [array] $updateRelease + + [Array] $JsonProperties = @('__type__','type', 'model', 'deviceid', 'device', + 'comptype', 'vid', 'did', 'svid', 'ssid', 'pciid', + 'vendor', 'driver', 'driverversion', 'firmware','status','matchResult','warnings','vcgLink','updateRelease') + + [void] set_data( + [object] $pci, + [object] $EsxCli) { + $this.type = "IO Device" + $this.model = $Pci.DeviceName + $this.deviceid = $pci.Address + $this.device = $pci.VMKernelName + $this.vid = [String]::Format("{0:x4}", [int]$Pci.VendorID) + $this.did = [String]::Format("{0:x4}", [int]$Pci.DeviceID) + $this.svid = [String]::Format("{0:x4}", [int]$Pci.SubVendorID) + $this.ssid = [String]::Format("{0:x4}", [int]$Pci.SubDeviceID) + $this.pciid = $this.vid + ":" + $this.did + ":" + $this.svid + ":" + $this.ssid + $this.vendor = $pci.VendorName + $this.driver = $Pci.ModuleName + $this.driverversion = "N/A" + $this.firmware = "N/A" + + + # Set component type and driverversion, firmware + if ($this.device -match 'nic') { + $arg = @{} + $arg['nicname'] = $this.device + $nic = $EsxCli.network.nic.get.invoke($arg) + $this.comptype = "Physical NIC" + $this.driverversion = $nic.driverinfo.Version + $this.firmware = $nic.driverinfo.FirmwareVersion + } + elseif ($this.device -match 'hba') { + $arg = @{} + $arg['module'] = $this.driver + $module = $EsxCli.system.module.get.invoke($arg) + $this.comptype = "Storage Adapter" + $this.driverversion = $module.Version + } + } + + [object] to_jsonobj() { + return $this | Select-Object -Property $this.JsonProperties + } + + [string] get_id_detail() { + return $this.driver + " (PCIId:" + $this.pciid + ")" + } +} + +# Class to manage IO device group +Class IoDeviceResourceGroup { + [Array] $iodevices = @() + [Array] $nics = @() + [Array] $adapters = @() + + [void] append_nic([IODeviceResource] $nic) { + $this.iodevices += $nic + $this.nics += $nic + } + + [void] append_storage_adapter([IODeviceResource] $adapter) { + $this.iodevices += $adapter + $this.adapters += $adapter + } + + [boolean] has_nics() { + return $this.nics.Count > 0 + } + + [boolean] has_storage_adapters() { + return $this.adapters.Count > 0 + } + +} + + +# +# Collect hardware inventory data from all the hosts +# +Function Get-VCGHWInfo { + Param( + [Parameter(Mandatory=$true)] $vmHosts + ) + # Collect the hardware data + $Data = @() + foreach($vmHost in $vmHosts) { + $vm = [HostResource]::new($vmHost) + try { + info ("Collecting hardware data from " + $vm.hostname) + $null = $vm.query_components() + if($vm.powerstatus -eq 'poweredOn' -and $vm.connectionstatus -eq 'connected'){ + $Data += $vm + info ("Collecting hardware data from " + $vm.hostname +' success') + } + } + catch { + error ("Failed to collect hardware data from " + $vm.hostname) + } + } + + return $Data +} \ No newline at end of file diff --git a/Modules/VMware.VCGChecker/Get-VCGStatus.ps1 b/Modules/VMware.VCGChecker/Get-VCGStatus.ps1 new file mode 100644 index 0000000..0f7a5de --- /dev/null +++ b/Modules/VMware.VCGChecker/Get-VCGStatus.ps1 @@ -0,0 +1,168 @@ +$Uuid = [guid]::NewGuid() +$Headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" +$Headers.add("x-request-id", $Uuid) +$Headers.add("x-api-toolid", "180209100001") +$Headers.add("x-api-key", "SJyb8QjK2L") +$Url_Perfix = 'https://apigw.vmware.com/m4/compatibility/v1' +$Url = $Url_Perfix + "/compatible/servers/search?" +$UrlPci = $Url_Perfix + "/compatible/iodevices/search?" +$apiQurryDict=@{} + +# +# Ping remote api server. +# +Function PingApiServer(){ + $apiServerIp='apigw.vmware.com' + $results =Test-NetConnection $apiServerIp -InformationLevel 'Quiet' + if($results -ne $true){ + error ("Failed to access VMware Compatibility API, + Unable to use comparison function, only view basic hardware information; + you can use 'Get-VCGHWInfo -g ' create hardware json, + then use 'Check-VCGStatus -f ' load hardware json file to comapre when connect an available network") + Exit(1) + } +} + +# +# Get the web request. +# +Function Get-WebRequest($VCGurl) { + try { + $req = Invoke-WebRequest -Headers $Headers -Uri $VCGUrl -ErrorVariable $err -UseBasicParsing + } + catch { + if ($err[0].errorrecord.exception.response) { + error ("WebReponse code:" + $err[0].errorrecord.exception.response.statuscode.value__) + error ($exitScript) + Exit(1) + } + else { + error ("Failed to check " + $type + " data for " + $HostResource.hostname) + error ("Failed to access VMware Compatibility API, please check your Internet connection or contact VMware Compatibility API administrator") + error ("Exit the script") + Exit(1) + } + } + return $req +} + +Function Get-RemoteApiTitleString([object]$device,$EsxiVersion){ + if ($device.type -eq 'Server') { + $Title = $device.model + $device.vendor + $device.cpufeatureid + $device.biosversion +$EsxiVersion + } + else{ + $Title = $device.vid + $device.did + $device.Svid + $device.Ssid + $EsxiVersion + } + return $Title +} + +Function Get-ResponseFromApi([object]$device,$EsxiVersion){ + if ($device.type -eq 'Server') { + $VCGUrl = $Url + "model=" + $device.model + "&releaseversion=" + $EsxiVersion ` + + "&vendor=" + $device.vendor + "&cpuFeatureId=" + $device.cpufeatureid ` + + "&bios=" + $device.biosversion + debug ("Model:" + $device.model) + debug ("VCG Url:" + $VCGUrl) + $Headers.GetEnumerator() | ForEach-Object {debug ("Req Header:" + $_.key + ":" + $_.value)} + $request = Get-WebRequest $VCGUrl + $Response = ConvertFrom-Json -InputObject $request -Erroraction 'silentlycontinue' + } + elseif ($device.type -eq 'IO Device') { + $VCGUrl = $UrlPci + "vid=0X" + $device.vid + "&did=0X" + $device.did + "&svid=0X" + $device.Svid ` + + "&ssid=0X" + $device.Ssid + "&releaseversion=" + $EsxiVersion ` + + "&driver=" + $device.Driver + "&driverversion=" + $device.driverversion + "&firmware=N/A" + debug ("Model:" + $device.model) + debug ("VCG Url:" + $VCGUrl) + $Headers.GetEnumerator() | ForEach-Object {debug ("Req Header:" + $_.key + ":" + $_.value)} + $request = Get-WebRequest $VCGUrl + $Response = ConvertFrom-Json -InputObject $request -Erroraction 'silentlycontinue' + } + return $Response +} +# +# Get the data from api +# +Function Get-VCGData($HostResource) { + foreach ($device in $HostResource.ComponentResource) { + if ($HostResource.checkRelease) { + $EsxiVersion = $HostResource.checkRelease + } + else { + $EsxiVersion = $HostResource.version + } + $temp=0 + $title=Get-RemoteApiTitleString $device $EsxiVersion + if($apiQurryDict.Count -eq 0){ + $Response= Get-ResponseFromApi $device $EsxiVersion + $apiQurryDict.Add($title,$Response) + }else{ + foreach($onetitle in $apiQurryDict.keys){ + if($onetitle -eq $title){ + $Response= $apiQurryDict[$onetitle] + $temp=1 + break + } + } + if($temp -eq 0){ + $Response= Get-ResponseFromApi $device $EsxiVersion + $apiQurryDict.Add($title,$Response) + } + } + + if ($Response.matches) { + foreach ($match in $Response.matches) { + $device.vcgLink += [string]$match.vcgLink + } + } + else { + foreach ($potentialMatche in $Response.potentialMatches) { + $device.vcgLink += [string]$potentialMatche.vcgLink + } + } + $device.status = [string]$Response.searchResult.status + $device.matchResult = [string]$Response.searchResult.matchResult + $device.warnings = $Response.searchResult.warnings + $device.updateRelease = [string]$Response.searchOption.foundRelease + } +} + +# +# Send the hardware data to VCG API and handle returned result +# +Function Get-DataFromRemoteApi([object]$servers) { + info ("Checking hardware compatibility result with VMware Compatibility Guide API...") + info ("This may take a few minutes depending on your network.") + for ($idx = 0; $idx -lt $servers.Count; $idx++) { + $server = $servers[$idx] + $i = $idx + 1 + info ([string]$i + "/" + [string]$servers.Count + " - Checking hardware compatibility results for " + $server.hostname) + if (!$server -or $server.ComponentResource.Count -eq 0) { + error('Failed to get the hardware info.') + Exit(1) + } + Get-VCGData $server + } + return $servers +} + +Function Get-VCGStatus{ + Param( + [Parameter(Mandatory=$true)] $Data, + [Parameter(Mandatory=$false)] $Version + ) + $checkRelease = $Version + PingApiServer + + foreach ($vmHost in $Data) { + # $vmHost|add-member -Name "checkRelease" -value $checkRelease -MemberType NoteProperty -Force + $vmHost.checkRelease=$checkRelease + } + + $results = Get-DataFromRemoteApi($Data) + if ($results.Count -eq 0) { + error ("Failed to get compatibility results. No report will be generated") + error ("Exit the script") + Exit(1) + } + return $results +} \ No newline at end of file diff --git a/Modules/VMware.VCGChecker/README.md b/Modules/VMware.VCGChecker/README.md new file mode 100644 index 0000000..a38c064 --- /dev/null +++ b/Modules/VMware.VCGChecker/README.md @@ -0,0 +1,41 @@ +# About +This module is designed to ease the work of collecting hardware inventory data and compare it with VMware's official VCG data. Before deploying vSphere, it is required to validate your physical machines with VCG to make sure all the devices in your physical machines are compatible with the vSphere version you want to install. It is a time-consuming and painful experience to collect hardware/driver/firmware data from all of the machines, especially when you have a huge number of machines in your data center. + +# How It Works +By using this module, it will automate the data collection and comparison work. + +When running the module, it will connect to the target vCenter or ESXi to read the hardware data. It is a read-only operation and nothing on the target hosts will be changed. There is almost no impact on the machine's performance as the read operation takes just few seconds. + +The module will then send your hardware inventory data to VMware's offical website to conduct a compatibility check. The result will be 'Compatible', 'May not be compatible' or 'Not compatible'. +* Compatible: the hardware is compatible with the given vSphere release. Link to that VCG page will be provided. +* May not be compatible: manual check is required to confirm the compatibility status of this hardware. A few potential matching VCG records will be provided. +* Not compatible: the hardware is not compatible with the given vSphere release. + +After the checking is completed, the module will generate reports in different formats for your review and future use. A summary view in html will give you an overview of your machines compatibility status; an html file with device details to view each device/driver/firmware you have, their compatibility with vSphere version you specified and links to the corresponding VCG documents online; a csv file with device details to allow customization on report in Excel or by your own tool. + +# Usage +Considering many data center may have control on internet access, we create 3 cmdlets to meet various situations. +* Get-VCGHWInfo: cmdlet to collect hardware info +* Get-VCGStatus: cmdlet to check hardware compatibility by query VCG website +* Export-VCGReport: cmdlet to export the summary/html/csv reports + +1. You need to first import this module after you import PowerCLI module +PS> Import-Module + +2. Connect to the target vSphere hosts using Connect-VIServer and get VMHosts +PS> Connect-VIServer -Server -User -Password +PS> $vmhosts = Get-VMHost + +3. Collect the hardware data +PS> $hwdata = Get-VCGHWInfo -vmHosts $vmhosts +Note: if you don't have internet access, you need to connect your client to internet before proceeding to the next step. + +4. Specify the target vSphere release you want to check and submit the hardware data to VMware website +PS> $vcgdata= Get-VCGStatus -Data $hwdata -Version '' + +5. Save the compatibility reports +PS> Export-VCGReport -Data $vcgdata -Dir + +# Known Limitation +* The module is not able to get the firmware version for HBA devices. +* The module is not able to get the HDD/SSD data. \ No newline at end of file diff --git a/Modules/VMware.VCGChecker/Save-VCGJsonFile.ps1 b/Modules/VMware.VCGChecker/Save-VCGJsonFile.ps1 new file mode 100644 index 0000000..785fc00 --- /dev/null +++ b/Modules/VMware.VCGChecker/Save-VCGJsonFile.ps1 @@ -0,0 +1,17 @@ +Function Save-VCGJsonFile{ + Param( + [Parameter(Mandatory=$true)] $FileName, + [Parameter(Mandatory=$true)] $Data, + [Parameter(Mandatory=$true)] $Dir + ) + $json = @() + $Data | ForEach-Object { $json += $_.to_jsonobj()} + + if (!(Test-Path $Dir)) { + New-Item -Type directory -Confirm:$false -Path $Dir -Force |Out-Null + } + + $Path= $Dir + '\' + $FileName + '.json' + info ("Saving data to " + $Path) + ConvertTo-Json -Depth 10 -Compress $json | Out-File -encoding 'UTF8' -FilePath $Path +} \ No newline at end of file diff --git a/Modules/VMware.VCGChecker/VMware.VCGChecker.psd1 b/Modules/VMware.VCGChecker/VMware.VCGChecker.psd1 new file mode 100644 index 0000000..12493af --- /dev/null +++ b/Modules/VMware.VCGChecker/VMware.VCGChecker.psd1 @@ -0,0 +1,90 @@ +# +# Module manifest for module 'VMware.VCGChecker' +# +# Generated by: fdai@vmware.com, zhangta@vmware.com, linweij@vmware.com +# +# Generated on: 11/15/18 +# + +@{ + + # Script module or binary module file associated with this manifest. + # RootModule = 'VMware.VCGChecker.psm1' + + # Version number of this module. + ModuleVersion = '1.0.0' + + # Supported PSEditions + # CompatiblePSEditions = @() + + # ID used to uniquely identify this module + # GUID = '' + + # Author of this module + Author = 'Frank Dai, Tao Zhang, Linwei Jiang' + + # Company or vendor of this module + CompanyName = 'VMware' + + # Copyright statement for this module + Copyright = '(c) 2018 VMware. All rights reserved.' + + # Description of the functionality provided by this module + Description = 'PowerShell Module for Checking Hardware Compatibility Status' + + RequiredModules = @('VMware.VimAutomation.Core') + + # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess + NestedModules = 'Get-VCGHWInfo.ps1','Get-VCGStatus.ps1','Export-VCGReport.ps1', 'Save-VCGJsonFile.ps1', 'logger.ps1' + + # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. + FunctionsToExport = 'Get-VCGHWInfo', 'Get-VCGStatus', 'Export-VCGReport', 'Save-VCGJsonFile' + # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. + CmdletsToExport = @() + + # Variables to export from this module + VariablesToExport = '*' + + # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. + AliasesToExport = @() + + # DSC resources to export from this module + # DscResourcesToExport = @() + + # List of all modules packaged with this module + # ModuleList = @() + + # List of all files packaged with this module + # FileList = @() + + # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. + PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + # Tags = @() + + # A URL to the license for this module. + # LicenseUri = '' + + # A URL to the main website for this project. + # ProjectUri = '' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + # ReleaseNotes = '' + + } # End of PSData hashtable + + } # End of PrivateData hashtable + + # HelpInfo URI of this module + # HelpInfoURI = '' + + # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. + # DefaultCommandPrefix = '' + + } \ No newline at end of file diff --git a/Modules/VMware.VCGChecker/logger.ps1 b/Modules/VMware.VCGChecker/logger.ps1 new file mode 100644 index 0000000..686611a --- /dev/null +++ b/Modules/VMware.VCGChecker/logger.ps1 @@ -0,0 +1,112 @@ +<# +Copyright 2018 VMware, Inc. All rights reserved. + +#> + +# Messages +$HEADER_OK = "[OK] " +$HEADER_INFO = "[INFO] " +$HEADER_WARNING = "[WARNING] " +$HEADER_ERR = "[ERROR] " + +Class DebugLog +{ + # Static variables of the logger class + static [string] $CAFILE_PATH = "./.certs/" + + [boolean] $debug + [string] $logfile + + DebugLog() + { + $this.debug = $false + $this.logfile = $null + if (!(Test-Path $this::CAFILE_PATH)) + { + New-Item -Type directory -Confirm:$false -Path $this::CAFILE_PATH + } + } + + [void] SetDebug( + [boolean] $debug, + [string] $hostname + ){ + if (!$hostname) {$hostname = ''} + $this.debug = $debug + if ($this.debug) + { + $this.logfile = $this::CAFILE_PATH + $hostname + [DateTime]::Now.ToString("_yyyy-MM-dd_HH-mm") + ".log" + }else{ + $this.logfile = $null + } + } + + [void] log_vars( + [string] $message, + [object] $var + ){ + $this.log($message + $var) + } + + [void] log( + [string] $message + ){ + if (!$this.debug -or !$this.logfile) {return} + try + { + $message | Out-File $this.logfile -Append + }catch { + Out-Host -InputObject ("[Exception] Failed to write to a logfile: " + $this.logfile) + Out-Host -InputObject $_ + } + } +} + +Function debug_vars( + [string] $message, + [object] $var) +{ + $logger.log_vars($message, $var) +} + +Function debug( + [string] $message) +{ + $logger.log($message) +} + +Function vcglog( + [string] $message, + [string] $header="") +{ + $msg = $header + $message + $logger.log($msg) + Out-Host -InputObject $msg +} + +Function ok( + [string] $message) +{ + vcglog $message $HEADER_OK +} + +Function warning( + [string] $message) +{ + vcglog $message $HEADER_WARNING +} + +Function info( + [string] $message) +{ + vcglog $message $HEADER_INFO +} + +Function error( + [string] $message) +{ + vcglog $message $HEADER_ERR +} + +$logger = [DebugLog]::new() +$logger.SetDebug($true, "vcc-debug") \ No newline at end of file From 82b32df293620cc3c4cb41dfac018467ac21e143 Mon Sep 17 00:00:00 2001 From: Adrian Moseley Date: Wed, 21 Nov 2018 16:53:37 -0600 Subject: [PATCH 44/65] Verbage for DeleteFromDisk if False --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index c58e1c0..06527a4 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -10171,7 +10171,7 @@ $deleteSpec.DeleteFromDisk = $DeleteFromDisk $deleteSpec.ArchivePersistentDisk = $false #Delete the machines -write-host "Attempting to Delete:" +if($DeleteFromDisk){write-host "Attempting to Delete:"}else{write-host "Attempting to remove from inventory:"} Write-Output ($deleteMachine.base.Name -join "`n") $bye = $machineService.Machine_DeleteMachines($services,$deleteMachine.id,$deleteSpec) From 1ce8b927ce6d890013df8036ed8167f42df6f424 Mon Sep 17 00:00:00 2001 From: dzl84 Date: Tue, 27 Nov 2018 17:17:46 +0800 Subject: [PATCH 45/65] Update README.md --- Modules/VMware.VCGChecker/README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Modules/VMware.VCGChecker/README.md b/Modules/VMware.VCGChecker/README.md index a38c064..1aa9a58 100644 --- a/Modules/VMware.VCGChecker/README.md +++ b/Modules/VMware.VCGChecker/README.md @@ -19,23 +19,23 @@ Considering many data center may have control on internet access, we create 3 cm * Get-VCGStatus: cmdlet to check hardware compatibility by query VCG website * Export-VCGReport: cmdlet to export the summary/html/csv reports -1. You need to first import this module after you import PowerCLI module +1. You need to first import this module after you import PowerCLI module PS> Import-Module -2. Connect to the target vSphere hosts using Connect-VIServer and get VMHosts -PS> Connect-VIServer -Server -User -Password +2. Connect to the target vSphere hosts using Connect-VIServer and get VMHosts +PS> Connect-VIServer -Server <server> -User <username> -Password <password> PS> $vmhosts = Get-VMHost -3. Collect the hardware data -PS> $hwdata = Get-VCGHWInfo -vmHosts $vmhosts +3. Collect the hardware data +PS> $hwdata = Get-VCGHWInfo -vmHosts $vmhosts Note: if you don't have internet access, you need to connect your client to internet before proceeding to the next step. -4. Specify the target vSphere release you want to check and submit the hardware data to VMware website -PS> $vcgdata= Get-VCGStatus -Data $hwdata -Version '' +4. Specify the target vSphere release you want to check and submit the hardware data to VMware website +PS> $vcgdata= Get-VCGStatus -Data $hwdata -Version '<release>' -5. Save the compatibility reports -PS> Export-VCGReport -Data $vcgdata -Dir +5. Save the compatibility reports +PS> Export-VCGReport -Data $vcgdata -Dir <dir> # Known Limitation * The module is not able to get the firmware version for HBA devices. -* The module is not able to get the HDD/SSD data. \ No newline at end of file +* The module is not able to get the HDD/SSD data. From 3e28c516a7b88bd3964876a04c66743a9e09501a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maik=20St=C3=BCbner?= Date: Fri, 30 Nov 2018 09:12:16 +0100 Subject: [PATCH 46/65] removed brake for issue vmware#74 --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index c58e1c0..d407e2d 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -7173,7 +7173,6 @@ function Get-HVMachine { $machineList = Find-HVMachine -Param $PSBoundParameters if (!$machineList) { Write-Host "Get-HVMachine: No Virtual Machine(s) Found with given search parameters" - break } $queryResults = @() $desktop_helper = New-Object VMware.Hv.MachineService From 560739222dae6638a0612f33cfa3607b62b8da72 Mon Sep 17 00:00:00 2001 From: Zhoulin Dai Date: Fri, 30 Nov 2018 17:15:13 +0800 Subject: [PATCH 47/65] Fix bugs --- .../VMware.VCGChecker/Export-VCGReport.ps1 | 14 ++++++------ Modules/VMware.VCGChecker/Get-VCGStatus.ps1 | 2 +- Modules/VMware.VCGChecker/README.md | 22 +++++++++---------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Modules/VMware.VCGChecker/Export-VCGReport.ps1 b/Modules/VMware.VCGChecker/Export-VCGReport.ps1 index 1b1253d..3774915 100644 --- a/Modules/VMware.VCGChecker/Export-VCGReport.ps1 +++ b/Modules/VMware.VCGChecker/Export-VCGReport.ps1 @@ -140,10 +140,10 @@ Function Generate_HtmlReport($Data, $Dir) { $dataTime = Get-Date -Format 'yyyy-M-d_h-m' $vcName = vcName($Data) $filename = 'compreport_' + $vcName + $dataTime + '.html' - $filePath = $Dir + $filename + $filePath = $Dir + '\' + $filename #save report $content |Out-File -FilePath $filePath -Encoding utf8| Out-Null - info ("Report " + "'" + $Dir + $filename + "'" + " has been created!") + info ("Report " + "'" + $filePath + "'" + " has been created!") } Function Generate_SummaryReport($Data, $Dir) { @@ -440,10 +440,10 @@ Function Generate_SummaryReport($Data, $Dir) { $dataTime = Get-Date -Format 'yyyy-M-d_h-m' $vcName = vcName($Data) $filename = 'sumreport_' + $vcName + $dataTime + '.html' - $filePath = $Dir + $filename + $filePath = $Dir + '\' + $filename # Out-put a html report $content |Out-File -FilePath $filePath -Encoding utf8| Out-Null - info ("Report " + "'" + $Dir + $filename + "'" + " has been created!") + info ("Report " + "'" + $filePath + "'" + " has been created!") } Function Generate_CsvReport($Data, $Dir) { @@ -542,9 +542,9 @@ Function Generate_CsvReport($Data, $Dir) { $dataTime = Get-Date -Format 'yyyy-M-d_h-m' $vcName = vcName($Data) $filename = 'compreport_' + $vcName + $dataTime + '.csv' - $filePath = $Dir + $filename + $filePath = $Dir + '\' + $filename #save csv report - info ("Report " + "'" + $Dir + $filename + "'" + " has been created!") + info ("Report " + "'" + $filePath + "'" + " has been created!") $content |Out-File -FilePath $filePath -Encoding utf8| Out-Null return $content } @@ -785,7 +785,7 @@ $summaryHead = @' height: 100%; background-size: cover; background-repeat: no-repeat; - background-image: url(https://myvmware.workspaceair.com:443/SAAS/jersey/manager/api/images/510495) + background-image: url(https://myvmware.workspaceair.com/SAAS/jersey/manager/api/images/520470) } #header{ margin: 0 auto; diff --git a/Modules/VMware.VCGChecker/Get-VCGStatus.ps1 b/Modules/VMware.VCGChecker/Get-VCGStatus.ps1 index 0f7a5de..426d6ce 100644 --- a/Modules/VMware.VCGChecker/Get-VCGStatus.ps1 +++ b/Modules/VMware.VCGChecker/Get-VCGStatus.ps1 @@ -13,7 +13,7 @@ $apiQurryDict=@{} # Function PingApiServer(){ $apiServerIp='apigw.vmware.com' - $results =Test-NetConnection $apiServerIp -InformationLevel 'Quiet' + $results =Test-Connection $apiServerIp -Quiet if($results -ne $true){ error ("Failed to access VMware Compatibility API, Unable to use comparison function, only view basic hardware information; diff --git a/Modules/VMware.VCGChecker/README.md b/Modules/VMware.VCGChecker/README.md index a38c064..79007d4 100644 --- a/Modules/VMware.VCGChecker/README.md +++ b/Modules/VMware.VCGChecker/README.md @@ -19,23 +19,23 @@ Considering many data center may have control on internet access, we create 3 cm * Get-VCGStatus: cmdlet to check hardware compatibility by query VCG website * Export-VCGReport: cmdlet to export the summary/html/csv reports -1. You need to first import this module after you import PowerCLI module -PS> Import-Module +1. You need to first import this module after you import PowerCLI module +PS> Import-Module <path_to_VMware.VCGChecker.psd1> -2. Connect to the target vSphere hosts using Connect-VIServer and get VMHosts -PS> Connect-VIServer -Server -User -Password +2. Connect to the target vSphere hosts using Connect-VIServer and get VMHosts +PS> Connect-VIServer -Server <server> -User <username> -Password <password> PS> $vmhosts = Get-VMHost -3. Collect the hardware data -PS> $hwdata = Get-VCGHWInfo -vmHosts $vmhosts +3. Collect the hardware data +PS> $hwdata = Get-VCGHWInfo -vmHosts $vmhosts Note: if you don't have internet access, you need to connect your client to internet before proceeding to the next step. -4. Specify the target vSphere release you want to check and submit the hardware data to VMware website -PS> $vcgdata= Get-VCGStatus -Data $hwdata -Version '' +4. Specify the target vSphere release you want to check and submit the hardware data to VMware website +PS> $vcgdata= Get-VCGStatus -Data $hwdata -Version '<release>' -5. Save the compatibility reports -PS> Export-VCGReport -Data $vcgdata -Dir +5. Save the compatibility reports +PS> Export-VCGReport -Data $vcgdata -Dir <dir> # Known Limitation * The module is not able to get the firmware version for HBA devices. -* The module is not able to get the HDD/SSD data. \ No newline at end of file +* The module is not able to get the HDD/SSD data. From 971e4aeec76e83c7b43ae2694428cd2c1a68d9f9 Mon Sep 17 00:00:00 2001 From: jpgrall <33696799+jpgrall@users.noreply.github.com> Date: Fri, 30 Nov 2018 09:43:40 -0600 Subject: [PATCH 48/65] Adding file path to Get-ContentLibraryItemFiles Adding the support to display the actual path of the file on the datastore. This is useful when needing to mount an ISO that is hosted on the Content Library. Also, replaced references of "Libary" to "Library" throughout. --- Modules/ContentLibrary/ContentLibrary.psm1 | 113 +++++++++++---------- 1 file changed, 60 insertions(+), 53 deletions(-) diff --git a/Modules/ContentLibrary/ContentLibrary.psm1 b/Modules/ContentLibrary/ContentLibrary.psm1 index 318b999..d85bd54 100644 --- a/Modules/ContentLibrary/ContentLibrary.psm1 +++ b/Modules/ContentLibrary/ContentLibrary.psm1 @@ -20,12 +20,12 @@ [Parameter(Mandatory=$false)][String]$LibraryName ) - $contentLibaryService = Get-CisService com.vmware.content.library - $libaryIDs = $contentLibaryService.list() + $contentLibraryService = Get-CisService com.vmware.content.library + $LibraryIDs = $contentLibraryService.list() $results = @() - foreach($libraryID in $libaryIDs) { - $library = $contentLibaryService.get($libraryID) + foreach($libraryID in $LibraryIDs) { + $library = $contentLibraryService.get($libraryID) # Use vCenter REST API to retrieve name of Datastore that is backing the Content Library $datastoreService = Get-CisService com.vmware.vcenter.datastore @@ -108,18 +108,18 @@ Function Get-ContentLibraryItems { [Parameter(Mandatory=$false)][String]$LibraryItemName ) - $contentLibaryService = Get-CisService com.vmware.content.library - $libaryIDs = $contentLibaryService.list() + $contentLibraryService = Get-CisService com.vmware.content.library + $LibraryIDs = $contentLibraryService.list() $results = @() - foreach($libraryID in $libaryIDs) { - $library = $contentLibaryService.get($libraryId) + foreach($libraryID in $LibraryIDs) { + $library = $contentLibraryService.get($libraryId) if($library.name -eq $LibraryName) { - $contentLibaryItemService = Get-CisService com.vmware.content.library.item - $itemIds = $contentLibaryItemService.list($libraryID) + $contentLibraryItemService = Get-CisService com.vmware.content.library.item + $itemIds = $contentLibraryItemService.list($libraryID) foreach($itemId in $itemIds) { - $item = $contentLibaryItemService.get($itemId) + $item = $contentLibraryItemService.get($itemId) if(!$LibraryItemName) { $itemResult = [pscustomobject] @{ @@ -179,28 +179,34 @@ Function Get-ContentLibraryItemFiles { [Parameter(Mandatory=$false)][String]$LibraryItemName ) - $contentLibaryService = Get-CisService com.vmware.content.library - $libaryIDs = $contentLibaryService.list() + $contentLibraryService = Get-CisService com.vmware.content.library + $libraryIDs = $contentLibraryService.list() $results = @() - foreach($libraryID in $libaryIDs) { - $library = $contentLibaryService.get($libraryId) + foreach($libraryID in $libraryIDs) { + $library = $contentLibraryService.get($libraryId) if($library.name -eq $LibraryName) { - $contentLibaryItemService = Get-CisService com.vmware.content.library.item - $itemIds = $contentLibaryItemService.list($libraryID) - + $contentLibraryItemService = Get-CisService com.vmware.content.library.item + $itemIds = $contentLibraryItemService.list($libraryID) + $DatastoreID = $library.storage_backings.datastore_id.Value + $Datastore = get-datastore -id "Datastore-$DatastoreID" + foreach($itemId in $itemIds) { - $itemName = ($contentLibaryItemService.get($itemId)).name - $contenLibraryItemFileSerice = Get-CisService com.vmware.content.library.item.file - $files = $contenLibraryItemFileSerice.list($itemId) + $itemName = ($contentLibraryItemService.get($itemId)).name + $contentLibraryItemFileSerice = Get-CisService com.vmware.content.library.item.file + $files = $contentLibraryItemFileSerice.list($itemId) + $contentLibraryItemStorageService = Get-CisService com.vmware.content.library.item.storage foreach($file in $files) { + $filepath = $contentLibraryItemStorageService.get($itemId, $($file.name)).storage_uris.AbsolutePath.split("/")[5..7] -join "/" + $fullfilepath = "[$($datastore.name)] $filepath" if(!$LibraryItemName) { $fileResult = [pscustomobject] @{ Name = $file.name; Version = $file.version; Size = $file.size; Stored = $file.cached; + Path = $fullfilepath; } $results+=$fileResult } else { @@ -210,6 +216,7 @@ Function Get-ContentLibraryItemFiles { Version = $file.version; Size = $file.size; Stored = $file.cached; + Path = $fullfilepath; } $results+=$fileResult } @@ -245,12 +252,12 @@ Function Set-ContentLibrary { [Parameter(Mandatory=$false)][Switch]$JSONPersistenceDisabled ) - $contentLibaryService = Get-CisService com.vmware.content.library - $libaryIDs = $contentLibaryService.list() + $contentLibraryService = Get-CisService com.vmware.content.library + $LibraryIDs = $contentLibraryService.list() $found = $false - foreach($libraryID in $libaryIDs) { - $library = $contentLibaryService.get($libraryId) + foreach($libraryID in $LibraryIDs) { + $library = $contentLibraryService.get($libraryId) if($library.name -eq $LibraryName) { $found = $true break @@ -361,12 +368,12 @@ Function Remove-SubscribedContentLibrary { [Parameter(Mandatory=$true)][String]$LibraryName ) - $contentLibaryService = Get-CisService com.vmware.content.library - $libaryIDs = $contentLibaryService.list() + $contentLibraryService = Get-CisService com.vmware.content.library + $LibraryIDs = $contentLibraryService.list() $found = $false - foreach($libraryID in $libaryIDs) { - $library = $contentLibaryService.get($libraryId) + foreach($libraryID in $LibraryIDs) { + $library = $contentLibraryService.get($libraryId) if($library.name -eq $LibraryName) { $found = $true break @@ -460,12 +467,12 @@ Function Remove-LocalContentLibrary { [Parameter(Mandatory=$true)][String]$LibraryName ) - $contentLibaryService = Get-CisService com.vmware.content.library - $libaryIDs = $contentLibaryService.list() + $contentLibraryService = Get-CisService com.vmware.content.library + $LibraryIDs = $contentLibraryService.list() $found = $false - foreach($libraryID in $libaryIDs) { - $library = $contentLibaryService.get($libraryId) + foreach($libraryID in $LibraryIDs) { + $library = $contentLibraryService.get($libraryId) if($library.name -eq $LibraryName) { $found = $true break @@ -493,49 +500,49 @@ Function Copy-ContentLibrary { =========================================================================== .DESCRIPTION This function copies all library items from one Content Library to another - .PARAMETER SourceLibaryName + .PARAMETER SourceLibraryName The name of the source Content Library to copy from - .PARAMETER DestinationLibaryName + .PARAMETER DestinationLibraryName The name of the desintation Content Library to copy to .PARAMETER DeleteSourceFile Whther or not to delete library item from the source Content Library after copy .EXAMPLE - Copy-ContentLibrary -SourceLibaryName Foo -DestinationLibaryName Bar + Copy-ContentLibrary -SourceLibraryName Foo -DestinationLibraryName Bar .EXAMPLE - Copy-ContentLibrary -SourceLibaryName Foo -DestinationLibaryName Bar -DeleteSourceFile $true + Copy-ContentLibrary -SourceLibraryName Foo -DestinationLibraryName Bar -DeleteSourceFile $true #> param( - [Parameter(Mandatory=$true)][String]$SourceLibaryName, - [Parameter(Mandatory=$true)][String]$DestinationLibaryName, + [Parameter(Mandatory=$true)][String]$SourceLibraryName, + [Parameter(Mandatory=$true)][String]$DestinationLibraryName, [Parameter(Mandatory=$false)][Boolean]$DeleteSourceFile=$false ) - $sourceLibraryId = (Get-ContentLibrary -LibraryName $SourceLibaryName).Id + $sourceLibraryId = (Get-ContentLibrary -LibraryName $SourceLibraryName).Id if($sourceLibraryId -eq $null) { - Write-Host -ForegroundColor red "Unable to find Source Content Library named $SourceLibaryName" + Write-Host -ForegroundColor red "Unable to find Source Content Library named $SourceLibraryName" exit } - $destinationLibraryId = (Get-ContentLibrary -LibraryName $DestinationLibaryName).Id + $destinationLibraryId = (Get-ContentLibrary -LibraryName $DestinationLibraryName).Id if($destinationLibraryId -eq $null) { - Write-Host -ForegroundColor Red "Unable to find Destination Content Library named $DestinationLibaryName" + Write-Host -ForegroundColor Red "Unable to find Destination Content Library named $DestinationLibraryName" break } - $sourceItemFiles = Get-ContentLibraryItems -LibraryName $SourceLibaryName + $sourceItemFiles = Get-ContentLibraryItems -LibraryName $SourceLibraryName if($sourceItemFiles -eq $null) { - Write-Host -ForegroundColor red "Unable to retrieve Content Library Items from $SourceLibaryName" + Write-Host -ForegroundColor red "Unable to retrieve Content Library Items from $SourceLibraryName" break } - $contentLibaryItemService = Get-CisService com.vmware.content.library.item + $contentLibraryItemService = Get-CisService com.vmware.content.library.item foreach ($sourceItemFile in $sourceItemFiles) { # Check to see if file already exists in destination Content Library - $result = Get-ContentLibraryItems -LibraryName $DestinationLibaryName -LibraryItemName $sourceItemFile.Name + $result = Get-ContentLibraryItems -LibraryName $DestinationLibraryName -LibraryItemName $sourceItemFile.Name if($result -eq $null) { # Create CopySpec - $copySpec = $contentLibaryItemService.Help.copy.destination_create_spec.Create() + $copySpec = $contentLibraryItemService.Help.copy.destination_create_spec.Create() $copySpec.library_id = $destinationLibraryId $copySpec.name = $sourceItemFile.Name $copySpec.description = $sourceItemFile.Description @@ -545,7 +552,7 @@ Function Copy-ContentLibrary { # Perform Copy try { Write-Host -ForegroundColor Cyan "Copying" $sourceItemFile.Name "..." - $copyResult = $contentLibaryItemService.copy($UniqueChangeId, $sourceItemFile.Id, $copySpec) + $copyResult = $contentLibraryItemService.copy($UniqueChangeId, $sourceItemFile.Id, $copySpec) } catch { Write-Host -ForegroundColor Red "Failed to copy" $sourceItemFile.Name $Error[0] @@ -556,7 +563,7 @@ Function Copy-ContentLibrary { if($DeleteSourceFile) { try { Write-Host -ForegroundColor Magenta "Deleteing" $sourceItemFile.Name "..." - $deleteResult = $contentLibaryItemService.delete($sourceItemFile.Id) + $deleteResult = $contentLibraryItemService.delete($sourceItemFile.Id) } catch { Write-Host -ForegroundColor Red "Failed to delete" $sourceItemFile.Name $Error[0] @@ -570,7 +577,7 @@ Function Copy-ContentLibrary { if($DeleteSourceFile) { try { Write-Host -ForegroundColor Magenta "Deleteing" $sourceItemFile.Name "..." - $deleteResult = $contentLibaryItemService.delete($sourceItemFile.Id) + $deleteResult = $contentLibraryItemService.delete($sourceItemFile.Id) } catch { Write-Host -ForegroundColor Red "Failed to delete" $sourceItemFile.Name break @@ -597,7 +604,7 @@ Function New-VMTX { The name of the VM Template in Content Library .PARAMETER Description Description of the VM template - .PARAMETER LibaryName + .PARAMETER LibraryName The name of the Content Library to clone to .PARAMETER FolderName The name of vSphere Folder (Defaults to Workloads for VMC) @@ -696,4 +703,4 @@ Function New-VMFromVMTX { Write-Host "`nDeploying new VM $NewVMName from VMTX Template $VMTXName ..." $results = $vmtxService.deploy($vmtxId,$vmtxDeploySpec) -} \ No newline at end of file +} \ No newline at end of file From 7c7f8d3fbf49e04ed6e3e72dbac104067091af5c Mon Sep 17 00:00:00 2001 From: jpgrall <33696799+jpgrall@users.noreply.github.com> Date: Fri, 30 Nov 2018 09:55:46 -0600 Subject: [PATCH 49/65] Update ContentLibrary.psm1 Adding logic incase backing isn't a datastore. --- Modules/ContentLibrary/ContentLibrary.psm1 | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Modules/ContentLibrary/ContentLibrary.psm1 b/Modules/ContentLibrary/ContentLibrary.psm1 index d85bd54..9a8574b 100644 --- a/Modules/ContentLibrary/ContentLibrary.psm1 +++ b/Modules/ContentLibrary/ContentLibrary.psm1 @@ -198,8 +198,14 @@ Function Get-ContentLibraryItemFiles { $contentLibraryItemStorageService = Get-CisService com.vmware.content.library.item.storage foreach($file in $files) { - $filepath = $contentLibraryItemStorageService.get($itemId, $($file.name)).storage_uris.AbsolutePath.split("/")[5..7] -join "/" - $fullfilepath = "[$($datastore.name)] $filepath" + if($contentLibraryItemStorageService.get($itemId, $($file.name)).storage_backing.type -eq "DATASTORE"){ + $filepath = $contentLibraryItemStorageService.get($itemId, $($file.name)).storage_uris.AbsolutePath.split("/")[5..7] -join "/" + $fullfilepath = "[$($datastore.name)] $filepath" + } + else{ + $fullfilepath = "UNKNOWN" + } + if(!$LibraryItemName) { $fileResult = [pscustomobject] @{ Name = $file.name; @@ -703,4 +709,4 @@ Function New-VMFromVMTX { Write-Host "`nDeploying new VM $NewVMName from VMTX Template $VMTXName ..." $results = $vmtxService.deploy($vmtxId,$vmtxDeploySpec) -} \ No newline at end of file +} From 937f21345150233d6ce15d2ca0f5cc781f63e4ab Mon Sep 17 00:00:00 2001 From: Jack McMichael Date: Sat, 1 Dec 2018 17:15:38 -0700 Subject: [PATCH 50/65] Update VMware.HV.Helper.psm1 Added functions to starting and starting Instant Clone maintenance operations on a host for Horizon 7.x --- .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 115 +++++++++++++++++- 1 file changed, 114 insertions(+), 1 deletion(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index c58e1c0..9eb2254 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11478,4 +11478,117 @@ function Get-HVlicense { [System.gc]::collect() } -Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, New-HVPodfederation, Remove-HVPodFederation, Get-HVPodFederation, Register-HVPod, Unregister-HVPod, Set-HVPodFederation,Get-HVSite,New-HVSite,Set-HVSite,Remove-HVSite,New-HVHomeSite,Get-HVHomeSite,Set-HVEventDatabase,Get-HVEventDatabase,Clear-HVEventDatabase,Get-HVlicense,Set-HVlicense +function Start-HVMaintenance { + <# + .Synopsis + Puts a host in instant clone maintanence mode + + .DESCRIPTION + Puts a host in instant clone maintanence mode + + + .PARAMETER Host + ESXi Host name to modify the InstantClone.Maintenance attribute + + .EXAMPLE + Start-HvMaintenance -Host + + .NOTES + Author : Jack McMichael + Author email : @jackwmc4 / jackwmc4@gmail.com + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.6 + PowerCLI Version : PowerCLI 11 + PowerShell Version : 5.1 + #> + + [CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High')] + + param( + [Parameter(Mandatory=$true, Position=0)] + [string]$Server, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + if ((Get-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance").Value -eq ""){ + Set-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance" -Value "1" | Out-Null + } + while ((Get-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance").Value -ne "2") { + shouldcontinue() + Start-Sleep -Seconds 10 + } + [System.gc]::collect() + } +} + +function Stop-HVMaintenance { + <# + .Synopsis + Takes a host out of instant clone maintanence mode + + .DESCRIPTION + Takes a host out of instant clone maintanence mode + + + .PARAMETER Host + ESXi Host name to clear the InstantClone.Maintenance attribute + + .EXAMPLE + Stop-HvMaintenance -Host + + .NOTES + Author : Jack McMichael + Author email : @jackwmc4 / jackwmc4@gmail.com + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.6 + PowerCLI Version : PowerCLI 11 + PowerShell Version : 5.1 + #> + [CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High')] + + param( + [Parameter(Mandatory=$true, Position=0)] + [string]$Server, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + if (-not (Get-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance").Value -eq "") { + Set-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance" -Value "" | Out-Null + } + Set-VMhost $Host -State Connected | Out-Null + [System.gc]::collect() + } + + +} +Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, New-HVPodfederation, Remove-HVPodFederation, Get-HVPodFederation, Register-HVPod, Unregister-HVPod, Set-HVPodFederation,Get-HVSite,New-HVSite,Set-HVSite,Remove-HVSite,New-HVHomeSite,Get-HVHomeSite,Set-HVEventDatabase,Get-HVEventDatabase,Clear-HVEventDatabase,Get-HVlicense,Set-HVlicense, Start-HVMaintenance, Stop-HVMaintenance \ No newline at end of file From f9953ec994ebfe26997656d5292b90c12d9c8e95 Mon Sep 17 00:00:00 2001 From: Jack McMichael Date: Sat, 1 Dec 2018 20:55:50 -0700 Subject: [PATCH 51/65] Update VMware.HV.Helper.psm1 Added Set-HVInstantCloneMaintenance function. --- .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 111 ++++++------------ 1 file changed, 38 insertions(+), 73 deletions(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 9eb2254..3f0fe30 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11478,20 +11478,26 @@ function Get-HVlicense { [System.gc]::collect() } -function Start-HVMaintenance { +function Set-HVInstantCloneMaintenance { <# .Synopsis - Puts a host in instant clone maintanence mode + Enable or disable instant clone maintanence mode .DESCRIPTION - Puts a host in instant clone maintanence mode + Toggles a host in instant clone maintanence mode. Specify the VMHost name and enable or disable to toggle. + .PARAMETER VMHost + ESXi Host name to modify the InstantClone.Maintenance attribute - .PARAMETER Host - ESXi Host name to modify the InstantClone.Maintenance attribute - + .PARAMETER Enable + Enable Instant Clone maintenance mode. + + .PARAMETER Disable + Disable Instant Clone maintenance mode + .EXAMPLE - Start-HvMaintenance -Host + Set-HvInstantCloneMaintenance -VMHost -Enable $true + Set-HvInstantCloneMaintenance -VMHost -Disable $true .NOTES Author : Jack McMichael @@ -11510,11 +11516,20 @@ function Start-HVMaintenance { param( [Parameter(Mandatory=$true, Position=0)] - [string]$Server, + [string] + $VMHost, + + [Parameter(Mandatory = $false)] + [boolean] + $Enable, + + [Parameter(Mandatory = $false)] + [boolean] + $Disable, [Parameter(Mandatory = $false)] $HvServer = $null - ) + ) begin { $services = Get-ViewAPIService -hvServer $hvServer @@ -11525,70 +11540,20 @@ function Start-HVMaintenance { } process { - if ((Get-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance").Value -eq ""){ - Set-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance" -Value "1" | Out-Null + if ($Enable) { + if ((Get-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance").Value -eq ""){ + Set-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance" -Value "1" | Out-Null + } + while ((Get-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance").Value -ne "2") { + Start-Sleep -Seconds 10 + } + } elseif ($Disable) { + if (-not (Get-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance").Value -eq "") { + Set-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance" -Value "" | Out-Null + } + Set-VMhost $VMHost -State Connected | Out-Null } - while ((Get-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance").Value -ne "2") { - shouldcontinue() - Start-Sleep -Seconds 10 - } - [System.gc]::collect() + [System.gc]::collect() } } - -function Stop-HVMaintenance { - <# - .Synopsis - Takes a host out of instant clone maintanence mode - - .DESCRIPTION - Takes a host out of instant clone maintanence mode - - - .PARAMETER Host - ESXi Host name to clear the InstantClone.Maintenance attribute - - .EXAMPLE - Stop-HvMaintenance -Host - - .NOTES - Author : Jack McMichael - Author email : @jackwmc4 / jackwmc4@gmail.com - Version : 1.0 - - ===Tested Against Environment==== - Horizon View Server Version : 7.6 - PowerCLI Version : PowerCLI 11 - PowerShell Version : 5.1 - #> - [CmdletBinding( - SupportsShouldProcess = $true, - ConfirmImpact = 'High')] - - param( - [Parameter(Mandatory=$true, Position=0)] - [string]$Server, - - [Parameter(Mandatory = $false)] - $HvServer = $null - ) - - begin { - $services = Get-ViewAPIService -hvServer $hvServer - if ($null -eq $services) { - Write-Error "Could not retrieve ViewApi services from connection object" - break - } - } - - process { - if (-not (Get-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance").Value -eq "") { - Set-Annotation -Entity (Get-VMHost -Name $Server) -CustomAttribute "InstantClone.Maintenance" -Value "" | Out-Null - } - Set-VMhost $Host -State Connected | Out-Null - [System.gc]::collect() - } - - -} -Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, New-HVPodfederation, Remove-HVPodFederation, Get-HVPodFederation, Register-HVPod, Unregister-HVPod, Set-HVPodFederation,Get-HVSite,New-HVSite,Set-HVSite,Remove-HVSite,New-HVHomeSite,Get-HVHomeSite,Set-HVEventDatabase,Get-HVEventDatabase,Clear-HVEventDatabase,Get-HVlicense,Set-HVlicense, Start-HVMaintenance, Stop-HVMaintenance \ No newline at end of file +Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, New-HVPodfederation, Remove-HVPodFederation, Get-HVPodFederation, Register-HVPod, Unregister-HVPod, Set-HVPodFederation,Get-HVSite,New-HVSite,Set-HVSite,Remove-HVSite,New-HVHomeSite,Get-HVHomeSite,Set-HVEventDatabase,Get-HVEventDatabase,Clear-HVEventDatabase,Get-HVlicense,Set-HVlicense, Set-HVInstantCloneMaintenance \ No newline at end of file From 53b8377c5395c2b699881a09084679561bccd7a2 Mon Sep 17 00:00:00 2001 From: Jack McMichael Date: Sat, 1 Dec 2018 20:59:06 -0700 Subject: [PATCH 52/65] Update VMware.HV.Helper.psm1 --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 3f0fe30..32322e7 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11479,14 +11479,14 @@ function Get-HVlicense { } function Set-HVInstantCloneMaintenance { - <# - .Synopsis + <# + .Synopsis Enable or disable instant clone maintanence mode - - .DESCRIPTION + + .DESCRIPTION Toggles a host in instant clone maintanence mode. Specify the VMHost name and enable or disable to toggle. - .PARAMETER VMHost + .PARAMETER VMHost ESXi Host name to modify the InstantClone.Maintenance attribute .PARAMETER Enable From 4ef4cce5efcc2dce3260058b98e81a71f70f5484 Mon Sep 17 00:00:00 2001 From: Jack McMichael Date: Sat, 1 Dec 2018 21:01:25 -0700 Subject: [PATCH 53/65] Update VMware.HV.Helper.psm1 --- .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 32322e7..4379f31 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11495,19 +11495,19 @@ function Set-HVInstantCloneMaintenance { .PARAMETER Disable Disable Instant Clone maintenance mode - .EXAMPLE + .EXAMPLE Set-HvInstantCloneMaintenance -VMHost -Enable $true Set-HvInstantCloneMaintenance -VMHost -Disable $true - - .NOTES - Author : Jack McMichael - Author email : @jackwmc4 / jackwmc4@gmail.com - Version : 1.0 + + .NOTES + Author : Jack McMichael + Author email : @jackwmc4 / jackwmc4@gmail.com + Version : 1.0 - ===Tested Against Environment==== - Horizon View Server Version : 7.6 - PowerCLI Version : PowerCLI 11 - PowerShell Version : 5.1 + ===Tested Against Environment==== + Horizon View Server Version : 7.6 + PowerCLI Version : PowerCLI 11 + PowerShell Version : 5.1 #> [CmdletBinding( From e5920d40f5069537042f1be5e538f0e8fcb30d2f Mon Sep 17 00:00:00 2001 From: Jack McMichael Date: Sat, 1 Dec 2018 21:15:51 -0700 Subject: [PATCH 54/65] Update VMware.HV.Helper.psm1 Updating exports to be more organized --- .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 4379f31..e42b8e2 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11556,4 +11556,22 @@ function Set-HVInstantCloneMaintenance { [System.gc]::collect() } } -Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVApplicationIcon, Remove-HVApplicationIcon, Get-HVGlobalSettings, Set-HVGlobalSettings, Set-HVGlobalEntitlement, Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession, Reset-HVMachine, Remove-HVMachine, Get-HVHealth, New-HVPodfederation, Remove-HVPodFederation, Get-HVPodFederation, Register-HVPod, Unregister-HVPod, Set-HVPodFederation,Get-HVSite,New-HVSite,Set-HVSite,Remove-HVSite,New-HVHomeSite,Get-HVHomeSite,Set-HVEventDatabase,Get-HVEventDatabase,Clear-HVEventDatabase,Get-HVlicense,Set-HVlicense, Set-HVInstantCloneMaintenance \ No newline at end of file +# Object related +Export-ModuleMember -Function Get-HVMachine, Get-HVMachineSummary, Get-HVQueryResult, Get-HVQueryFilter, Get-HVInternalName +# RDS Farm related +Export-ModuleMember -Function Get-HVFarmSummary, Start-HVFarm, Start-HVPool, New-HVFarm, Remove-HVFarm, Get-HVFarm, Set-HVFarm, Add-HVRDSServer +# Desktop Pool related +Export-ModuleMember -Function Get-HVPoolSummary, New-HVPool, Remove-HVPool, Get-HVPool, Set-HVPool, Get-HVPoolSpec, Add-HVDesktop +# Entitlement related +Export-ModuleMember -Function New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement +Export-ModuleMember -Function Set-HVMachine, Reset-HVMachine, Remove-HVMachine +# Cloud Pod Architecture related +Export-ModuleMember -Function New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement, Set-HVGlobalEntitlement, New-HVPodFederation, Remove-HVPodFederation, Get-HVPodFederation, Set-HVPodFederation +Export-ModuleMember -Function Get-HVSite, New-HVSite, New-HVHomeSite, Remove-HVSite, Get-HVHomeSite, Set-HVSite, Register-HVPod, Unregister-HVPod +# Published App related +Export-ModuleMember -Function Get-HVGlobalSettings, Set-HVApplicationIcon, Remove-HVApplicationIcon, Set-HVGlobalSettings +Export-ModuleMember -Function Get-HVResourceStructure, Get-HVLocalSession, Get-HVGlobalSession +# Event Database related +Export-ModuleMember -Function Get-HVEventDatabase, Set-HVEventDatabase, Clear-HVEventDatabase, Get-HVEvent, Connect-HVEvent, Disconnect-HVEvent +# Misc/other related +Export-ModuleMember -Function Get-HVlicense, Set-HVlicense, Get-HVHealth, Set-HVInstantCloneMaintenance \ No newline at end of file From c7a19c795e2af4bcb578b1710423c14bca62aab0 Mon Sep 17 00:00:00 2001 From: Jack McMichael Date: Sun, 2 Dec 2018 17:01:26 -0700 Subject: [PATCH 55/65] Update VMware.HV.Helper.psm1 Changed booleans to switches after looking at other uses in the code. --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index e42b8e2..30336f5 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11520,11 +11520,11 @@ function Set-HVInstantCloneMaintenance { $VMHost, [Parameter(Mandatory = $false)] - [boolean] + [switch] $Enable, [Parameter(Mandatory = $false)] - [boolean] + [switch] $Disable, [Parameter(Mandatory = $false)] From cea57f11d5f72becdb63f4f29c60b04fae720808 Mon Sep 17 00:00:00 2001 From: Jack McMichael Date: Tue, 4 Dec 2018 14:05:08 -0700 Subject: [PATCH 56/65] Update VMware.HV.Helper.psm1 Added per feedback --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 30336f5..0a4efe9 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11545,11 +11545,13 @@ function Set-HVInstantCloneMaintenance { Set-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance" -Value "1" | Out-Null } while ((Get-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance").Value -ne "2") { + Write-Host "Instant Clone Maintenance Mode: Enabling for $VMHost...(This could take some time)" Start-Sleep -Seconds 10 } } elseif ($Disable) { if (-not (Get-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance").Value -eq "") { Set-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance" -Value "" | Out-Null + Write-Host "Instant Clone Maintenance Mode: Disabling for $VMHost" } Set-VMhost $VMHost -State Connected | Out-Null } From bd983dcd7fc5a7436de6c6243601d38d62f5ecb4 Mon Sep 17 00:00:00 2001 From: Jack McMichael Date: Wed, 5 Dec 2018 13:00:12 -0700 Subject: [PATCH 57/65] Update VMware.HV.Helper.psm1 Moving messaging so it doesn't repeat over and over. --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 0a4efe9..eee2b67 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -11543,9 +11543,9 @@ function Set-HVInstantCloneMaintenance { if ($Enable) { if ((Get-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance").Value -eq ""){ Set-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance" -Value "1" | Out-Null + Write-Host "Instant Clone Maintenance Mode: Enabling for $VMHost...(This could take some time)" } while ((Get-Annotation -Entity (Get-VMHost -Name $VMHost) -CustomAttribute "InstantClone.Maintenance").Value -ne "2") { - Write-Host "Instant Clone Maintenance Mode: Enabling for $VMHost...(This could take some time)" Start-Sleep -Seconds 10 } } elseif ($Disable) { From 76eadeba8a2afcafd9dc96b83e2d5bf3921b968e Mon Sep 17 00:00:00 2001 From: Jase McCarty Date: Fri, 7 Dec 2018 16:11:18 -0700 Subject: [PATCH 58/65] Initial vSAN Encryption Module vSAN Encryption Module --- Modules/VMware.VsanEncryption/README.md | 7 + .../VMware.VsanEncryption.psd1 | Bin 0 -> 5098 bytes .../VMware.VsanEncryption.psm1 | 340 ++++++++++++++++++ 3 files changed, 347 insertions(+) create mode 100644 Modules/VMware.VsanEncryption/README.md create mode 100644 Modules/VMware.VsanEncryption/VMware.VsanEncryption.psd1 create mode 100644 Modules/VMware.VsanEncryption/VMware.VsanEncryption.psm1 diff --git a/Modules/VMware.VsanEncryption/README.md b/Modules/VMware.VsanEncryption/README.md new file mode 100644 index 0000000..8037171 --- /dev/null +++ b/Modules/VMware.VsanEncryption/README.md @@ -0,0 +1,7 @@ +Prerequisites/Steps to use this module: + +1. This module only works for vSphere products that support vSAN Encryption. E.g. vSAN 6.6 and later with a vSAN Enterprise license +2. All the functions in this module only work for KMIP Servers. +3. Install the latest version of Powershell and PowerCLI(11). +4. Import this module by running: Import-Module -Name "location of this module" +5. Get-Command -Module "This module Name" to list all available functions. \ No newline at end of file diff --git a/Modules/VMware.VsanEncryption/VMware.VsanEncryption.psd1 b/Modules/VMware.VsanEncryption/VMware.VsanEncryption.psd1 new file mode 100644 index 0000000000000000000000000000000000000000..47b0ca30d0fd967f4a1e9ee3b4b69b6b61d2b73d GIT binary patch literal 5098 zcmcgwSx-|@5T57$ikt8N7}*p7O-v;02_PwmzP7iEH+Hj&)foS}`h7D!oO60xX`4z& zxyv~-^UXfz{`tKk1zC|quB0s$8AwB_cxp;XT9Qc(Pd(}5O%3Z^T?zNC$~`ED*xkj> zO+59K@&wc=-u;jcs58*EWK|`Zv@`5(;n&6PKCTsTE@Sr_TtklBJ)MGFNwFg@WJ~t( zdm-C+Iv7bR$UFIod*g7ch%!Y)4MROlw=$5nRF@w)O>0;)+mxVV57a5%c=SU&_2o0@ z_&>vrycIV`NQ$6tV_$6Zx1d;6D;eHbKJ?tc?$>y?4X>6*ekJWrfcX%(DBb+`FPju3-fM`$ zSYv#e<&VIxi8x^nP-El%O|`DfBrE1{4Ngr^Cz6-?9B(fmCxtg+1Rcok!p3#z#|&g1 zTD*}L?eDX4ng@tuoR49cw6X>i>)`6LD9*(YX##6D@RtM#8S$(FjGwO1T9rtrV_joa zupD%8?Y%||)imN#XlLssNMUBt4;|39!Pz3v)r>gf!uVSO%`~ZI1#j^yaAl-7A-@Sa z;_pJ2$tXYSZpOk8dlI?PJ5t=jTg(*NhF+@cPHINmFpo05n+^RWzLT@rYvQ9Vw(M+} znM+pjmxcFy#L?q=3fuobJsz|Fe37&%*K#6vh>ugmh1H26EY_7T3&zYbsQchr#s56d z<)Tj^tBF7BPz~T`#1C+-Lq21k{e!t|^>0m%8^~pUW-Vf;=G?*w zCDqQ%d4u(3fH%ar23rw-RaoIZq2ui7-61enaKF1S+B}ZKsVMR};VT&{3@bdVKc@=z zXx?!aU_WNBqLyxwVkNWgO)BoGqaL-fpVidr600b!)Kbq_H(`Bcy`#O1KIBcVbzSlE zjmK!6vj}NnjSHs`YC$dE!Q$%=z4lOjR0WDMuw|hCx3<)yq!S1$=<*Ry#*@b#Pm^vs zB=$9Qy$-b4(YWz`vl-dt1pUUT&Uq+R-*Ce0Vh$i5c8_Iy$xWak`W~uJ8yzgnnMt0y zLl5o%6??SJ!m+mB;lsvAXHJe5ow2`$8jsX_-pF#&XGMFeam;g!%}Gy>I7Bcj>hXNZ zXCW&Y?aq3|DqyoZE3iAgaW(Gz;VS1ydXc9W`qAhu7K@-8KbLGpCy9Kd6tvSgB;)v9 z-pq4OwCri>obT(zsdf@S7g9^JPF21`BddRmO~x@NIA)eRhk5H1&=c8{LQd4`B;sP# z_*pcOvl}o!`)dEiWFG;U=Q4}jd-$7Gxuo^cRY&I6yn5$3%_5(3KBaT2U)<&~ms#Xq zs_&S)7R&5h>|J3j6Aw>mDP|>`IM@>=pTvCxxEdJ7s+Z;>)<>RSi;;v?aDEilFHfN* zW6I0O%V%ZI&r1TTBcIQIIW``m%(#h4G8!Ji&4YLfNwJ7wLd4jd6jc&MQs*lk=4S- zD##}Iy&s(q=^1_vv1-FBpQhvBInvoke-VsanEncryptionRekey -Cluster "ClusterName" -DeepRekey $true/$false -ReducedRedundancy $true/$false + + #> + + # Set our Parameters + [CmdletBinding()]Param( + [Parameter(Mandatory = $True)][String]$Cluster, + [Parameter(Mandatory = $False)][Boolean]$DeepRekey, + [Parameter(Mandatory = $False)][Boolean]$ReducedRedundancy + ) + + # Get the Cluster + $VsanCluster = Get-Cluster -Name $Cluster + + # Get the vSAN Cluster Configuration View + $VsanVcClusterConfig = Get-VsanView -Id "VsanVcClusterConfigSystem-vsan-cluster-config-system" + + # Get Encryption State + $EncryptedVsan = $VsanVcClusterConfig.VsanClusterGetConfig($VsanCluster.ExtensionData.MoRef).DataEncryptionConfig + + # If vSAN is enabled and it is Encrypted + If($VsanCluster.vSanEnabled -And $EncryptedVsan.EncryptionEnabled){ + + # Get a count of hosts to guarantee reduced redundancy for 2 and 3 node clusters + $HostCount = $VsanCluster | Select @{n="count";e={($_ | Get-VMHost).Count}} + + # If reduced redundancy is specified, or there are less than 4 hosts, force reduced redundancy + If (($ReducedRedundancy -eq $true) -or ($HostCount.Value -lt 4)) { + + } + # Determine Rekey Type for messaging + Switch ($DeepRekey) { + $true { $ReKeyType = "deep"} + default { $ReKeyType = "shallow"} + } + + # Determine Reduced Redundancy for messaging + Switch ($ReducedRedundancy) { + $true { $RRMessage = "with reduced redundancy"} + default { $RRMessage = ""} + } + + # Echo task being performed + Write-Host "Executing $ReKeyType rekey of vSAN Cluster $VsanCluster $RRMessage" + + # Execute the rekeying task + $ReKeyTask = $VsanVcClusterConfig.VsanEncryptedClusterRekey_Task($VsanCluster.ExtensionData.MoRef,$DeepRekey,$ReducedRedundancy) + } +} + +Function Set-VsanEncryptionKms { + <# + .SYNOPSIS + This function will set the KMS to be used with vSAN Encryption + + .DESCRIPTION + This function will set the KMS to be used with vSAN Encryption + + .PARAMETER Cluster + Specifies the Cluster to set the KMS server for + + .PARAMETER KmsCluster + Use to set the KMS Cluster to be used with vSAN Encryption + + .EXAMPLE + C:\PS>Set-VsanEncryptionKms -Cluster "ClusterName" -KmsCluster "vCenter KMS Cluster Entry" + + #> + + # Set our Parameters + [CmdletBinding()]Param( + [Parameter(Mandatory = $True)][String]$Cluster, + [Parameter(Mandatory = $False)][String]$KmsCluster + ) + + # Get the Cluster + $VsanCluster = Get-Cluster -Name $Cluster + + # Get the list of KMS Servers that are included + $KmsClusterList = Get-KmsCluster + + # Was a KMS Cluster Specified? + # Specified: Is it in the list? + # Is it not in the list? + # Not Specified: Present a list + If ($KmsCluster) { + If ($KmsClusterList.Name.Contains($KmsCluster)) { + Write-Host "$KmsCluster In the list, proceeding" -ForegroundColor Green + $KmsClusterProfile = $KmsClusterList | Where-Object {$_.Name -eq $KmsCluster} + } else { + + $Count = 0 + Foreach ($KmsClusterItem in $KmsClusterList) { + Write-Host "$Count) $KmsClusterItem " + $Count = $Count + 1 + } + $KmsClusterEntry = Read-Host -Prompt "$KmsCluster is not valid, please select one of the existing KMS Clusters to use" + Write-Host $KmsClusterList[$KmsClusterEntry] + $KmsClusterProfile = $KmsClusterList[$KmsClusterEntry] + } + } else { + + $Count = 0 + Foreach ($KmsClusterItem in $KmsClusterList) { + Write-Host "$Count) $KmsClusterItem " + $Count = $Count + 1 + } + $KmsClusterEntry = Read-Host -Prompt "No KMS provided, please select one of the existing KMS Clusters to use" + Write-Host $KmsClusterList[$KmsClusterEntry] + $KmsClusterProfile = $KmsClusterList[$KmsClusterEntry] + } + + # Get the vSAN Cluster Configuration View + $VsanVcClusterConfig = Get-VsanView -Id "VsanVcClusterConfigSystem-vsan-cluster-config-system" + + # Get Encryption State + $EncryptedVsan = $VsanVcClusterConfig.VsanClusterGetConfig($VsanCluster.ExtensionData.MoRef).DataEncryptionConfig + + # If vSAN is enabled and it is Encrypted + If($VsanCluster.vSanEnabled -And $EncryptedVsan.EncryptionEnabled){ + + If ($EncryptedVsan.KmsProviderId.Id -eq $KmsClusterProfile.Name) { + # If the Specified KMS Profile is the KMS Profile being used, then don't do anything + Write-Host $EncryptedVsan.KmsProviderId.Id "is already the assigned KMS Cluster Profile, exiting" + } else { + Write-Host "Changing the KMS Profile to $KmsClusterProfile on Cluster $VsanCluster" + + # Setup the KMS Provider Id Specification + $KmsProviderIdSpec = New-Object VMware.Vim.KeyProviderId + $KmsProviderIdSpec.Id = $KmsClusterProfile.Name + + # Setup the Data Encryption Configuration Specification + $DataEncryptionConfigSpec = New-Object VMware.Vsan.Views.VsanDataEncryptionConfig + $DataEncryptionConfigSpec.KmsProviderId = $KmsProviderIdSpec + $DataEncryptionConfigSpec.EncryptionEnabled = $true + + # Set the Reconfigure Specification to use the Data Encryption Configuration Spec + $vsanReconfigSpec = New-Object VMware.Vsan.Views.VimVsanReconfigSpec + $vsanReconfigSpec.DataEncryptionConfig = $DataEncryptionConfigSpec + + # Execute the task of changing the KMS Cluster Profile Being Used + $ChangeKmsTask = $VsanVcClusterConfig.VsanClusterReconfig($VsanCluster.ExtensionData.MoRef,$vsanReconfigSpec) + } + + } + } + + Function Get-VsanEncryptionKms { + <# + .SYNOPSIS + This function will set the KMS to be used with vSAN Encryption + + .DESCRIPTION + This function will set the KMS to be used with vSAN Encryption + + .PARAMETER Cluster + Specifies the Cluster to set the KMS server for + + .EXAMPLE + C:\PS>Get-VsanEncryptionKms -Cluster "ClusterName" + #> + + # Set our Parameters + [CmdletBinding()]Param([Parameter(Mandatory = $True)][String]$Cluster) + + # Get the Cluster + $VsanCluster = Get-Cluster -Name $Cluster + + # Get the vSAN Cluster Configuration View + $VsanVcClusterConfig = Get-VsanView -Id "VsanVcClusterConfigSystem-vsan-cluster-config-system" + + # Get Encryption State + $EncryptedVsan = $VsanVcClusterConfig.VsanClusterGetConfig($VsanCluster.ExtensionData.MoRef).DataEncryptionConfig + + # If vSAN is enabled and it is Encrypted + If($VsanCluster.vSanEnabled -And $EncryptedVsan.EncryptionEnabled){ + + $EncryptedVsan.KmsProviderId.Id + } +} + +Function Set-VsanEncryptionDiskWiping { + <# + .SYNOPSIS + This function will update the Disk Wiping option in vSAN Encryption + + .DESCRIPTION + This function will update the Disk Wiping option in vSAN Encryption + + .PARAMETER Cluster + Specifies the Cluster set the Disk Wiping Setting on + + .PARAMETER DiskWiping + Use to set the Disk Wiping setting for vSAN Encryption + + .EXAMPLE + C:\PS>Set-VsanEncryptionDiskWiping -Cluster "ClusterName" -DiskWiping $true + + .EXAMPLE + C:\PS>Set-VsanEncryptionDiskWiping -Cluster "ClusterName" -DiskWiping $false + + #> + + # Set our Parameters + [CmdletBinding()]Param( + [Parameter(Mandatory = $True)][String]$Cluster, + [Parameter(Mandatory = $True)][Boolean]$DiskWiping + ) + + # Get the Cluster + $VsanCluster = Get-Cluster -Name $Cluster + + # Get the vSAN Cluster Configuration View + $VsanVcClusterConfig = Get-VsanView -Id "VsanVcClusterConfigSystem-vsan-cluster-config-system" + + # Get Encryption State + $EncryptedVsan = $VsanVcClusterConfig.VsanClusterGetConfig($VsanCluster.ExtensionData.MoRef).DataEncryptionConfig + + # If vSAN is enabled and it is Encrypted + If($VsanCluster.vSanEnabled -And $EncryptedVsan.EncryptionEnabled){ + + # Determine Rekey Type for messaging + Switch ($DiskWiping) { + $true { $DiskWipingSetting = "enabled" } + default { $DiskWipingSetting = "disabled" } + } + + # Check to see the current Disk Wiping value + If ($DiskWiping -eq $EncryptedVsan.EraseDisksBeforeUse) { + Write-Host "Disk Wiping is already $DiskWipingSetting" -ForegroundColor "Green" + Write-Host "No action necessary" -ForegroundColor "Green" + + } else { + + Write-Host "Disk Wiping is not set to $DiskWipingSetting" -ForegroundColor "Yellow" + Write-Host "Changing Disk Wiping setting on Cluster $VsanCluster" -ForegroundColor "Blue" + + # Setup the Data Encryption Configuration Specification + $DataEncryptionConfigSpec = New-Object VMware.Vsan.Views.VsanDataEncryptionConfig + $DataEncryptionConfigSpec.EncryptionEnabled = $true + $DataEncryptionConfigSpec.EraseDisksBeforeUse = $DiskWiping + + # Set the Reconfigure Specification to use the Data Encryption Configuration Spec + $vsanReconfigSpec = New-Object VMware.Vsan.Views.VimVsanReconfigSpec + $vsanReconfigSpec.DataEncryptionConfig = $DataEncryptionConfigSpec + + # Execute the task of changing the KMS Cluster Profile Being Used + $VsanVcClusterConfig.VsanClusterReconfig($VsanCluster.ExtensionData.MoRef,$vsanReconfigSpec) + + } + } +} + +Function Get-VsanEncryptionDiskWiping { + <# + .SYNOPSIS + This function will retrieve the Disk Wiping option setting in vSAN Encryption + + .DESCRIPTION + This function will retrieve the Disk Wiping option setting in vSAN Encryption + + .PARAMETER Cluster + Specifies the Cluster set the Disk Wiping Setting on + + .EXAMPLE + C:\PS>Get-VsanEncryptionDiskWiping -Cluster "ClusterName" + + #> + + # Set our Parameters + [CmdletBinding()]Param([Parameter(Mandatory = $True)][String]$Cluster) + + # Get the Cluster + $VsanCluster = Get-Cluster -Name $Cluster + + # Get the vSAN Cluster Configuration View + $VsanVcClusterConfig = Get-VsanView -Id "VsanVcClusterConfigSystem-vsan-cluster-config-system" + + # Get Encryption State + $EncryptedVsan = $VsanVcClusterConfig.VsanClusterGetConfig($VsanCluster.ExtensionData.MoRef).DataEncryptionConfig + + # If vSAN is enabled and it is Encrypted + If($VsanCluster.vSanEnabled -And $EncryptedVsan.EncryptionEnabled){ + + $EncryptedVsan.EraseDisksBeforeUse + } +} + + + +# Export Function for vSAN Rekeying +Export-ModuleMember -Function Invoke-VsanEncryptionRekey +Export-ModuleMember -Function Set-VsanEncryptionKms +Export-ModuleMember -Function Get-VsanEncryptionKms +Export-ModuleMember -Function Set-VsanEncryptionDiskWiping +Export-ModuleMember -Function Get-VsanEncryptionDiskWiping \ No newline at end of file From 82c7889cec7c140eae66d9f0f16cbf8776286680 Mon Sep 17 00:00:00 2001 From: Jase McCarty Date: Mon, 10 Dec 2018 13:36:22 -0700 Subject: [PATCH 59/65] Initial Push This is an initial push to PowerCLI-Example-Tools --- Modules/VMware.VsanEncryption/VMware.VsanEncryption.psm1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/VMware.VsanEncryption/VMware.VsanEncryption.psm1 b/Modules/VMware.VsanEncryption/VMware.VsanEncryption.psm1 index e45ab91..870bd44 100644 --- a/Modules/VMware.VsanEncryption/VMware.VsanEncryption.psm1 +++ b/Modules/VMware.VsanEncryption/VMware.VsanEncryption.psm1 @@ -326,6 +326,7 @@ Function Get-VsanEncryptionDiskWiping { # If vSAN is enabled and it is Encrypted If($VsanCluster.vSanEnabled -And $EncryptedVsan.EncryptionEnabled){ + # Change the setting $EncryptedVsan.EraseDisksBeforeUse } } From 3372f3faf39dda82d7082dbf30e4ae79288c3a14 Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Tue, 18 Dec 2018 11:16:26 -0500 Subject: [PATCH 60/65] Introduction of a new Tagging module Introduction of a new module which uses the REST based CIS API to perform tagging operations. More info: http://blogs.vmware.com/PowerCLI/2018/12/new-module-for-tag-management.html --- .../VMware.Community.CISTag.psd1 | 123 ++++ .../VMware.Community.CISTag.psm1 | 693 ++++++++++++++++++ 2 files changed, 816 insertions(+) create mode 100644 Modules/VMware.Community.CISTag/VMware.Community.CISTag.psd1 create mode 100644 Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 diff --git a/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psd1 b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psd1 new file mode 100644 index 0000000..b20f2de --- /dev/null +++ b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psd1 @@ -0,0 +1,123 @@ +# +# Module manifest for module 'VMware.Community.CISTag' +# +# Generated by: Kyle Ruddy +# +# Generated on: 12/14/18 +# + +@{ + +# Script module or binary module file associated with this manifest. +RootModule = 'VMware.Community.CISTag.psm1' + +# Version number of this module. +ModuleVersion = '1.0.0' + +# Supported PSEditions +# CompatiblePSEditions = @() + +# ID used to uniquely identify this module +GUID = 'a0803efd-6017-4049-bfc9-5983a5a0c348' + +# Author of this module +Author = 'Kyle Ruddy' + +# Company or vendor of this module +CompanyName = 'VMware' + +# Copyright statement for this module +Copyright = '(c) VMware. All rights reserved.' + +# Description of the functionality provided by this module +Description = 'Community sourced PowerShell Module for managing vSphere Tags via the CIS Endpoint' + +# Minimum version of the PowerShell engine required by this module +PowerShellVersion = '4.0' + +# Name of the PowerShell host required by this module +# PowerShellHostName = '' + +# Minimum version of the PowerShell host required by this module +# PowerShellHostVersion = '' + +# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# DotNetFrameworkVersion = '' + +# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# CLRVersion = '' + +# Processor architecture (None, X86, Amd64) required by this module +# ProcessorArchitecture = '' + +# Modules that must be imported into the global environment prior to importing this module +# RequiredModules = @() + +# Assemblies that must be loaded prior to importing this module +# RequiredAssemblies = @() + +# Script files (.ps1) that are run in the caller's environment prior to importing this module. +# ScriptsToProcess = @() + +# Type files (.ps1xml) to be loaded when importing this module +# TypesToProcess = @() + +# Format files (.ps1xml) to be loaded when importing this module +# FormatsToProcess = @() + +# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess +# NestedModules = @() + +# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. +FunctionsToExport = 'Get-CISTag', 'Get-CISTagCategory', 'Get-CISTagAssignment', 'New-CISTag', 'New-CISTagCategory', 'New-CISTagAssignment', 'Remove-CISTag', 'Remove-CISTagCategory', 'Remove-CISTagAssignment' + +# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. +# CmdletsToExport = '*' + +# Variables to export from this module +# VariablesToExport = '*' + +# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. +# AliasesToExport = '*' + +# DSC resources to export from this module +# DscResourcesToExport = @() + +# List of all modules packaged with this module +# ModuleList = @() + +# List of all files packaged with this module +# FileList = @() + +# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. +PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + # Tags = @() + + # A URL to the license for this module. + # LicenseUri = '' + + # A URL to the main website for this project. + # ProjectUri = '' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + # ReleaseNotes = '' + + } # End of PSData hashtable + +} # End of PrivateData hashtable + +# HelpInfo URI of this module +# HelpInfoURI = '' + +# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. +# DefaultCommandPrefix = '' + +} + diff --git a/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 new file mode 100644 index 0000000..4dd9c0f --- /dev/null +++ b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 @@ -0,0 +1,693 @@ +function Get-CISTag { +<# +.SYNOPSIS + Gathers tag information from the CIS REST API endpoint +.DESCRIPTION + Will provide a list of tags +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Name + Tag name which should be retreived +.PARAMETER Category + Tag category name which should be retreived +.PARAMETER Id + Tag ID which should be retreived +.EXAMPLE + Get-CISTag + Retreives all tag information +.EXAMPLE + Get-CISTag -Name tagName + Retreives the tag information based on the specified name +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Low')] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + [String]$Name, + [Parameter(Mandatory=$false,Position=1,ValueFromPipelineByPropertyName=$true)] + [String]$Category, + [Parameter(Mandatory=$false,Position=2,ValueFromPipelineByPropertyName=$true)] + [String]$Id + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagSvc = Get-CisService -Name com.vmware.cis.tagging.tag + if ($PSBoundParameters.ContainsKey("Id")) { + $tagOutput = $tagSvc.get($Id) + } else { + $tagArray = @() + $tagIdList = $tagSvc.list() | Select-Object -ExpandProperty Value + foreach ($t in $tagIdList) { + $tagArray += $tagSvc.get($t) + } + if ($PSBoundParameters.ContainsKey("Name")) { + $tagOutput = $tagArray | Where {$_.Name -eq $Name} + } elseif ($PSBoundParameters.ContainsKey("Category")) { + $tagCatid = Get-CISTagCategory -Name $Category | Select-Object -ExpandProperty Id + $tagIdList = $tagSvc.list_tags_for_category($tagCatid) + $tagArray2 = @() + foreach ($t in $tagIdList) { + $tagArray2 += $tagSvc.get($t) + } + $tagOutput = $tagArray2 + } else { + $tagOutput = $tagArray + } + } + $tagOutput | Select-Object Id, Name, Description + } + +} + +function New-CISTag { +<# +.SYNOPSIS + Creates a new tag from the CIS REST API endpoint +.DESCRIPTION + Will create a new tag +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Name + Tag name which should be created +.PARAMETER Category + Category name where the new tag should be associated +.PARAMETER Description + Description for the new tag +.PARAMETER CategoryID + Category ID where the new tag should be associated +.EXAMPLE + New-CISTag -Name tagName -Category categoryName -Description "Tag Descrition" + Creates a new tag based on the specified name +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Medium')] + param( + [Parameter(Mandatory=$true,Position=0)] + [String]$Name, + [Parameter(Mandatory=$false,Position=1)] + [String]$Category, + [Parameter(Mandatory=$false,Position=2)] + [String]$Description, + [Parameter(Mandatory=$false,Position=3)] + [String]$CategoryID + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagSvc = Get-CisService -Name com.vmware.cis.tagging.tag + $tagCreateHelper = $tagSvc.Help.create.create_spec.Create() + $tagCreateHelper.name = $Name + if ($PSBoundParameters.ContainsKey("Category")) { + $tagCreateHelper.category_id = Get-CISTagCategory -Name $Category | Select-Object -ExpandProperty Id + } elseif ($PSBoundParameters.ContainsKey("CategoryId")) { + $tagCreateHelper.category_id = $CategoryID + } else {Write-Warning "No Category input found. Add a Category name or ID."; break} + if ($PSBoundParameters.ContainsKey("Description")) { + $tagCreateHelper.description = $Description + } else { + $tagCreateHelper.description = "" + } + $tagNewId = $tagSvc.create($tagCreateHelper) + Get-CISTag -Id $tagNewId + } + +} + +function Remove-CISTag { +<# +.SYNOPSIS + Removes a tag from the CIS REST API endpoint +.DESCRIPTION + Will delete a new tag +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Name + Tag name which should be removed +.PARAMETER ID + Tag ID which should be removed +.EXAMPLE + Remove-CISTag -Name tagName + Removes a new tag based on the specified name +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + [String]$Name, + [Parameter(Mandatory=$false,Position=1,ValueFromPipelineByPropertyName=$true)] + [String]$ID + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagSvc = Get-CisService -Name com.vmware.cis.tagging.tag + if ($ID) { + $tagSvc.delete($ID) + } else { + $tagId = Get-CISTag -Name $Name | select -ExpandProperty Id + if ($tagId) {$tagSvc.delete($tagId)} + else {Write-Warning "No valid tag found."} + } + } +} + +function Get-CISTagCategory { +<# +.SYNOPSIS + Gathers tag category information from the CIS REST API endpoint +.DESCRIPTION + Will provide a list of tag categories +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Name + Tag category name which should be retreived +.PARAMETER Id + Tag category ID which should be retreived +.EXAMPLE + Get-CISTagCategory + Retreives all tag category information +.EXAMPLE + Get-CISTagCategory -Name tagCategoryName + Retreives the tag category information based on the specified name +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Low')] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + [String]$Name, + [Parameter(Mandatory=$false,Position=2,ValueFromPipelineByPropertyName=$true)] + [String]$Id + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagCatSvc = Get-CisService -Name com.vmware.cis.tagging.category + if ($PSBoundParameters.ContainsKey("Id")) { + $tagCatOutput = $tagCatSvc.get($Id) + } else { + $tagCatArray = @() + $tagCatIdList = $tagCatSvc.list() | Select-Object -ExpandProperty Value + foreach ($tc in $tagCatIdList) { + $tagCatArray += $tagCatSvc.get($tc) + } + if ($PSBoundParameters.ContainsKey("Name")) { + $tagCatOutput = $tagCatArray | Where {$_.Name -eq $Name} + } else { + $tagCatOutput = $tagCatArray + } + } + $tagCatOutput | Select-Object Id, Name, Description, Cardinality + } + +} + +function New-CISTagCategory { +<# +.SYNOPSIS + Creates a new tag category from the CIS REST API endpoint +.DESCRIPTION + Will create a new tag category +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Name + Tag category name which should be created +.PARAMETER Description + Tag category ID which should be retreived +.PARAMETER Cardinality + Tag category ID which should be retreived +.PARAMETER AssociableTypes + Tag category ID which should be retreived +.EXAMPLE + New-CISTagCategory -Name NewTagCategoryName -Description "New Tag Category Description" -Cardinality "Single" -AssociableTypes + Creates a new tag category with the specified information +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Medium')] + param( + [Parameter(Mandatory=$true,Position=0)] + [String]$Name, + [Parameter(Mandatory=$false,Position=1)] + [String]$Description, + [Parameter(Mandatory=$false,Position=2)] + [ValidateSet("SINGLE","MULTIPLE")] + [String]$Cardinality = "SINGLE", + [Parameter(Mandatory=$false,Position=3)] + [ValidateSet("All", "Cluster", "Datacenter", "Datastore", "DatastoreCluster", "DistributedPortGroup", "DistributedSwitch", "Folder", "ResourcePool", "VApp", "VirtualPortGroup", "VirtualMachine", "VMHost")] + [String]$AssociableTypes = "All" + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagCatSvc = Get-CisService -Name com.vmware.cis.tagging.category + $tagCatCreateHelper = $tagCatSvc.Help.create.create_spec.Create() + $tagCatCreateHelper.name = $Name + if ($PSBoundParameters.ContainsKey("Description")) { + $tagCatCreateHelper.description = $Description + } else {$tagCatCreateHelper.description = ""} + $tagCatCreateHelper.cardinality = $Cardinality + $tagCatCreateAssocTypeHelper = $tagCatSvc.help.create.create_spec.associable_types.create() + $tagCatCreateAssocTypeHelper.Add($AssociableTypes) + $tagCatCreateHelper.associable_types = $tagCatCreateAssocTypeHelper + $tagCatNewId = $tagCatSvc.create($tagCatCreateHelper) + Get-CISTagCategory -Id $tagCatNewId + } + +} + +function Remove-CISTagCategory { +<# +.SYNOPSIS + Gathers tag category information from the CIS REST API endpoint +.DESCRIPTION + Will provide a list of tag categories +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Name + Tag category name which should be removed +.PARAMETER Id + Tag category ID which should be removed +.EXAMPLE + Get-CISTagCategory + Retreives all tag category information +.EXAMPLE + Get-CISTagCategory -Name tagCategoryName + Retreives the tag category information based on the specified name + +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + [String]$Name, + [Parameter(Mandatory=$false,Position=2,ValueFromPipelineByPropertyName=$true)] + [String]$Id + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagCatSvc = Get-CisService -Name com.vmware.cis.tagging.category + if ($PSBoundParameters.ContainsKey("Id")) { + $tagCatSvc.delete($Id) + } elseif ($PSBoundParameters.ContainsKey("Name")) { + $tagCatId = Get-CISTagCategory -Name $Name | Select-Object -ExpandProperty Id + $tagCatSvc.delete($tagCatId) + } else {Write-Warning "No tag category found."} + } +} + +function Get-CISTagAssignment { +<# +.SYNOPSIS + Displays a list of the tag assignments from the CIS REST API endpoint +.DESCRIPTION + Will provide a list of the tag assignments +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Category + Tag category name which should be referenced +.PARAMETER Entity + Object name which should be retreived +.PARAMETER ObjectId + Object ID which should be retreived +.EXAMPLE + Get-CISTagAssignment + Retreives all tag assignment information +.EXAMPLE + Get-CISTagAssignment -Entity VMName + Retreives all tag assignments for the VM name +.EXAMPLE + Get-CISTagAssignment -ObjectId 'vm-11' + Retreives all tag assignments for the VM object +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Low')] + param( + [Parameter(Mandatory=$false,Position=0)] + [String]$Category, + [Parameter(Mandatory=$false,Position=1)] + [String]$Entity, + [Parameter(Mandatory=$false,Position=2,ValueFromPipelineByPropertyName=$true)] + [String]$ObjectId + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagOutput = @() + [Boolean]$vCenterConn = $false + $tagAssocSvc = Get-CisService -Name com.vmware.cis.tagging.tag_association + if ($PSBoundParameters.ContainsKey("ObjectId")) { + if ($ObjectId.split('-')[0] -eq 'vm') { + $objType = 'VirtualMachine' + } else {Write-Warning 'Only VirtualMachine types currently supported.'; break} + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $ObjectId + $objObject.type = $objType + $tagIdOutput = $tagAssocSvc.list_attached_tags($objObject) + } elseif ($PSBoundParameters.ContainsKey("Entity")) { + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + [Boolean]$vCenterConn = $true + $viObject = (Get-Inventory -Name $Entity).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $objId + $objObject.type = $objType + } + $tagIdOutput = $tagAssocSvc.list_attached_tags($objObject) + } else { + $tagSvc = Get-CisService -Name com.vmware.cis.tagging.tag + $tagIdOutput = @() + $tagCategories = Get-CISTagCategory | Sort-Object -Property Name + if ($Category) { + $tagCatId = $tagCategories | where {$_.Name -eq $Category} | Select-Object -ExpandProperty Id + $tagIdOutput += $tagSvc.list_tags_for_category($tagCatId) + } else { + foreach ($tagCat in $tagCategories) { + $tagIdOutput += $tagSvc.list_tags_for_category($tagCat.id) + } + } + } + $tagReference = Get-CISTag + + if ($Entity -or $ObjectId) { + foreach ($tagId in $tagIdOutput) { + $tagAttObj = @() + if ($Entity) { + $tagAttObj += $tagAssocSvc.list_attached_objects($tagId) | where {$_.type -eq $viObject.type -and $_.id -eq $viObject.Value} + } else { + $tagAttObj += $tagAssocSvc.list_attached_objects($tagId) | where {$_.id -eq $ObjectId} + } + foreach ($obj in $tagAttObj) { + if ($obj.type -eq "VirtualMachine") { + if (-Not $vmSvc) {$vmSvc = Get-CisService -Name com.vmware.vcenter.vm} + $filterVmObj = $vmsvc.help.list.filter.create() + $filterVmObj.vms.add($obj.Id) | Out-Null + $objName = $vmSvc.list($filterVmObj) | Select-Object -ExpandProperty Name + } + else {$objName = 'Object Not Found'} + $tempObject = "" | Select-Object Tag, Entity + $tempObject.Tag = $tagReference | where {$_.id -eq $tagId} | Select-Object -ExpandProperty Name + $tempObject.Entity = $objName + $tagOutput += $tempObject + } + } + } else { + foreach ($tagId in $tagIdOutput) { + $tagAttObj = @() + $tagAttObj += $tagAssocSvc.list_attached_objects($tagId) + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + [Boolean]$vCenterConn = $true + } elseif ($tagAttObj.Type -contains 'VirtualMachine') { + if (-Not $vmSvc) {$vmSvc = Get-CisService -Name com.vmware.vcenter.vm} + } + foreach ($obj in $tagAttObj) { + if ($vCenterConn) { + $newViObj = New-Object -TypeName VMware.Vim.ManagedObjectReference + $newViObj.Type = $obj.type + $newViObj.Value = $obj.id + $objName = Get-View -Id $newViObj -Property Name | Select-Object -ExpandProperty Name + } elseif ($obj.type -eq "VirtualMachine") { + $filterVmObj = $vmsvc.help.list.filter.create() + $filterVmObj.vms.add($obj.Id) | Out-Null + $objName = $vmSvc.list($filterVmObj) | Select-Object -ExpandProperty Name + } else {$objName = 'Object Not Found'} + $tempObject = "" | Select-Object Tag, Entity + $tempObject.Tag = $tagReference | where {$_.id -eq $tagId} | Select-Object -ExpandProperty Name + $tempObject.Entity = $objName + $tagOutput += $tempObject + } + } + } + return $tagOutput + } +} + +function New-CISTagAssignment { +<# +.SYNOPSIS + Creates new tag assignments from the CIS REST API endpoint +.DESCRIPTION + Will create new tag assignments +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Tag + Tag name which should be referenced +.PARAMETER Entity + Object name which should be retreived +.PARAMETER TagId + Tag ID/s which should be referenced +.PARAMETER ObjectId + Object ID which/s should be retreived +.EXAMPLE + New-CISTagAssignment -Tag TagName -Entity VMName + Creates a tag assignment between the Tag name and the VM name +.EXAMPLE + New-CISTagAssignment -TagId $tagId -ObjectId 'vm-11' + Creates a tag assignment between the Tag ID and the Object ID +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'Medium')] + param( + [Parameter(Mandatory=$false,Position=0)] + $Tag, + [Parameter(Mandatory=$false,Position=1)] + $Entity, + [Parameter(Mandatory=$false,Position=2)] + $TagId, + [Parameter(Mandatory=$false,Position=3)] + $ObjectId + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagAssocSvc = Get-CisService -Name com.vmware.cis.tagging.tag_association + if ($PSBoundParameters.ContainsKey("Tag") -and $PSBoundParameters.ContainsKey("Entity")) { + if ($Tag -is [array] -and $Entity -isnot [array]) { + $tagIdList = $tagAssocSvc.help.attach_multiple_tags_to_object.tag_ids.create() + foreach ($t in $Tag) { + $tempId = Get-CISTag -Name $t | Select-Object -ExpandProperty Id + $tagIdList.add($tempId) | Out-Null + } + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + $viObject = (Get-Inventory -Name $Entity).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $objId + $objObject.type = $objType + } + $tagAssocSvc.attach_multiple_tags_to_object($objObject,$tagIdList) | Out-Null + } elseif ($Tag -isnot [array] -and $Entity -is [array]) { + $tagId = Get-CISTag -Name $Tag | Select-Object -ExpandProperty Id + $objList = $tagAssocSvc.help.attach_tag_to_multiple_objects.object_ids.create() + foreach ($e in $Entity) { + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + $viObject = (Get-Inventory -Name $e).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $objId + $objObject.type = $objType + } + $objList.add($objObject) | Out-Null + } + $tagAssocSvc.attach_tag_to_multiple_objects($TagId,$objList) | Out-Null + } elseif ($Tag -isnot [array] -and $Entity -isnot [array]) { + $tagId = Get-CISTag -Name $Tag | Select-Object -ExpandProperty Id + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + $viObject = (Get-Inventory -Name $Entity).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.list_attached_tags.object_id.create() + $objObject.id = $objId + $objObject.type = $objType + } + $tagAssocSvc.attach($TagId,$objObject) | Out-Null + } + } elseif ($PSBoundParameters.ContainsKey("TagId") -and $PSBoundParameters.ContainsKey("ObjectId")) { + if ($ObjectId.split('-')[0] -eq 'vm') { + $objType = 'VirtualMachine' + } else {Write-Warning 'Only VirtualMachine types currently supported.'; break} + if ($TagId -is [array] -and $ObjectId -isnot [array]) { + $objObject = $tagAssocSvc.help.attach_multiple_tags_to_object.object_id.create() + $objObject.id = $ObjectId + $objObject.type = $objType + $tagIdList = $tagAssocSvc.help.attach_multiple_tags_to_object.tag_ids.create() + foreach ($tId in $TagId) { + $tagIdList.add($tId) | Out-Null + } + $tagAssocSvc.attach_multiple_tags_to_object($objObject,$tagIdList) | Out-Null + } elseif ($TagId -isnot [array] -and $ObjectId -is [array]) { + $objList = $tagAssocSvc.help.attach_tag_to_multiple_objects.object_ids.create() + foreach ($obj in $ObjectId) { + $objObject = $tagAssocSvc.help.attach_tag_to_multiple_objects.object_ids.element.create() + $objObject.id = $obj + $objObject.type = $objType + $objList.add($objObject) | Out-Null + } + $tagAssocSvc.attach_tag_to_multiple_objects($TagId,$objList) | Out-Null + } elseif ($TagId -isnot [array] -and $ObjectId -isnot [array]) { + $objObject = $tagAssocSvc.help.attach.object_id.create() + $objObject.id = $ObjectId + $objObject.type = $objType + $tagAssocSvc.attach($TagId,$objObject) | Out-Null + } + + } else {Write-Output "Multiple tags with multiple objects are not a supported call."} + + } +} + +function Remove-CISTagAssignment { +<# +.SYNOPSIS + Displays a list of the tag assignments from the CIS REST API endpoint +.DESCRIPTION + Will provide a list of the tag assignments +.NOTES + Author: Kyle Ruddy, @kmruddy +.PARAMETER Tag + Tag name which should be removed +.PARAMETER Entity + Object name which should be removed +.PARAMETER TagId + Tag ID/s which should be removed +.PARAMETER ObjectId + Object ID which/s should be removed +.EXAMPLE + Remove-CISTagAssignment -TagId $tagId -ObjectId 'vm-11' + Removes the tag assignment between the Tag ID and the Object ID +.EXAMPLE + Remove-CISTagAssignment -Tag TagName -Entity VMName + Removes the tag assignment between the Tag name and the Entity name +#> +[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + $Tag, + [Parameter(Mandatory=$false,Position=1,ValueFromPipelineByPropertyName=$true)] + $Entity, + [Parameter(Mandatory=$false,Position=2)] + $TagId, + [Parameter(Mandatory=$false,Position=3)] + $ObjectId + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CIS Connection found, please use the Connect-CisServer to connect" } Else { + $tagAssocSvc = Get-CisService -Name com.vmware.cis.tagging.tag_association + if ($PSBoundParameters.ContainsKey("Tag") -and $PSBoundParameters.ContainsKey("Entity")) { + if ($Tag -is [array] -and $Entity -isnot [array]) { + $tagIdList = $tagAssocSvc.help.detach_multiple_tags_from_object.tag_ids.create() + foreach ($t in $Tag) { + $tempId = Get-CISTag -Name $t | Select-Object -ExpandProperty Id + $tagIdList.add($tempId) | Out-Null + } + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + $viObject = (Get-Inventory -Name $Entity).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.detach_multiple_tags_from_object.object_id.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.detach_multiple_tags_from_object.object_id.create() + $objObject.id = $objId + $objObject.type = $objType + } + $tagAssocSvc.detach_multiple_tags_from_object($objObject,$tagIdList) | Out-Null + } elseif ($Tag -isnot [array] -and $Entity -is [array]) { + $tagId = Get-CISTag -Name $Tag | Select-Object -ExpandProperty Id + $objList = $tagAssocSvc.help.detach_tag_from_multiple_objects.object_ids.create() + foreach ($e in $Entity) { + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + $viObject = (Get-Inventory -Name $e).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.detach_tag_from_multiple_objects.object_ids.element.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.detach_tag_from_multiple_objects.object_ids.element.create() + $objObject.id = $objId + $objObject.type = $objType + } + $objList.add($objObject) | Out-Null + } + $tagAssocSvc.detach_tag_from_multiple_objects($TagId,$objList) | Out-Null + } elseif ($Tag -isnot [array] -and $Entity -isnot [array]) { + $tagId = Get-CISTag -Name $Tag | Select-Object -ExpandProperty Id + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + $viObject = (Get-Inventory -Name $Entity).ExtensionData.MoRef + $objObject = $tagAssocSvc.help.detach.object_id.create() + $objObject.id = $viObject.Value + $objObject.type = $viObject.type + } else { + $vmSvc = Get-CisService -Name com.vmware.vcenter.vm + $filterVmNameObj = $vmsvc.help.list.filter.create() + $filterVmNameObj.names.add($Entity) | Out-Null + $objId = $vmSvc.list($filterVmNameObj) | Select-Object -ExpandProperty vm + if ($objId) {$objType = 'VirtualMachine'} + else {Write-Warning "No entities found."; break} + $objObject = $tagAssocSvc.help.detach.object_id.create() + $objObject.id = $objId + $objObject.type = $objType + } + $tagAssocSvc.detach($TagId,$objObject) | Out-Null + } + } elseif ($PSBoundParameters.ContainsKey("TagId") -and $PSBoundParameters.ContainsKey("ObjectId")) { + if ($ObjectId.split('-')[0] -eq 'vm') { + $objType = 'VirtualMachine' + } else {Write-Warning 'Only VirtualMachine types currently supported.'; break} + if ($TagId -is [array] -and $ObjectId -isnot [array]) { + $objObject = $tagAssocSvc.help.detach_multiple_tags_from_object.object_id.create() + $objObject.id = $ObjectId + $objObject.type = $objType + $tagIdList = $tagAssocSvc.help.detach_multiple_tags_from_object.tag_ids.create() + foreach ($tId in $TagId) { + $tagIdList.add($tId) | Out-Null + } + $tagAssocSvc.detach_multiple_tags_from_object($objObject,$tagIdList) | Out-Null + } elseif ($TagId -isnot [array] -and $ObjectId -is [array]) { + $objList = $tagAssocSvc.help.detach_tag_from_multiple_objects.object_ids.create() + foreach ($obj in $ObjectId) { + $objObject = $tagAssocSvc.help.detach_tag_from_multiple_objects.object_ids.element.create() + $objObject.id = $obj + $objObject.type = $objType + $objList.add($objObject) | Out-Null + } + $tagAssocSvc.detach_tag_from_multiple_objects($TagId,$objList) | Out-Null + } elseif ($TagId -isnot [array] -and $ObjectId -isnot [array]) { + $objObject = $tagAssocSvc.help.detach.object_id.create() + $objObject.id = $ObjectId + $objObject.type = $objType + $tagAssocSvc.detach($TagId,$objObject) | Out-Null + } + } else {Write-Output "Multiple tags with multiple objects are not a supported call."} + + } +} \ No newline at end of file From 44879d8c25df1e3b0165d9441be6b236aaaab099 Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Tue, 18 Dec 2018 15:00:39 -0500 Subject: [PATCH 61/65] Update VMware.Community.CISTag.psm1 Updated Synopsis and Examples --- .../VMware.Community.CISTag.psm1 | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 index 4dd9c0f..837a595 100644 --- a/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 +++ b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 @@ -248,9 +248,9 @@ function New-CISTagCategory { function Remove-CISTagCategory { <# .SYNOPSIS - Gathers tag category information from the CIS REST API endpoint + Removes tag category information from the CIS REST API endpoint .DESCRIPTION - Will provide a list of tag categories + Will remove a tag categorie .NOTES Author: Kyle Ruddy, @kmruddy .PARAMETER Name @@ -258,11 +258,8 @@ function Remove-CISTagCategory { .PARAMETER Id Tag category ID which should be removed .EXAMPLE - Get-CISTagCategory - Retreives all tag category information -.EXAMPLE - Get-CISTagCategory -Name tagCategoryName - Retreives the tag category information based on the specified name + Remove-CISTagCategory -Name tagCategoryName + Removes the tag category information based on the specified name #> [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')] @@ -558,9 +555,9 @@ function New-CISTagAssignment { function Remove-CISTagAssignment { <# .SYNOPSIS - Displays a list of the tag assignments from the CIS REST API endpoint + Removes a tag assignment from the CIS REST API endpoint .DESCRIPTION - Will provide a list of the tag assignments + Will remove provided tag assignments .NOTES Author: Kyle Ruddy, @kmruddy .PARAMETER Tag From bfbcbc8faa185709cfa7a527cdc3083da99c9d7a Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Tue, 18 Dec 2018 19:37:42 -0500 Subject: [PATCH 62/65] Update VMware.Community.CISTag.psm1 Add VIServer capabilities to Get-CISTag --- .../VMware.Community.CISTag.psm1 | 41 +++++++++++++------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 index 837a595..05594e4 100644 --- a/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 +++ b/Modules/VMware.Community.CISTag/VMware.Community.CISTag.psm1 @@ -34,23 +34,38 @@ function Get-CISTag { if ($PSBoundParameters.ContainsKey("Id")) { $tagOutput = $tagSvc.get($Id) } else { - $tagArray = @() - $tagIdList = $tagSvc.list() | Select-Object -ExpandProperty Value - foreach ($t in $tagIdList) { - $tagArray += $tagSvc.get($t) + if ($global:DefaultVIServer -and $global:DefaultVIServer.Name -eq $global:DefaultCisServers.Name) { + [Boolean]$vCenterConn = $true + $vCTagList = Get-Tag + } else { + $tagArray = @() + $tagIdList = $tagSvc.list() | Select-Object -ExpandProperty Value + [integer]$counter = 1 + foreach ($t in $tagIdList) { + $tagArray += $tagSvc.get($t) + $counter++ + if ($counter -gt 200) {Start-Sleep -Milliseconds 1; $counter = 1} + } } if ($PSBoundParameters.ContainsKey("Name")) { - $tagOutput = $tagArray | Where {$_.Name -eq $Name} + if ($vCenterConn){ + $tagOutput = $vCTagList | where {$_.Name -eq $Name} + } else {$tagOutput = $tagArray | Where {$_.Name -eq $Name}} } elseif ($PSBoundParameters.ContainsKey("Category")) { - $tagCatid = Get-CISTagCategory -Name $Category | Select-Object -ExpandProperty Id - $tagIdList = $tagSvc.list_tags_for_category($tagCatid) - $tagArray2 = @() - foreach ($t in $tagIdList) { - $tagArray2 += $tagSvc.get($t) + if ($vCenterConn){ + $tagOutput = $vCTagList | where {$_.Category -eq $Category} + } else { + $tagCatid = Get-CISTagCategory -Name $Category | Select-Object -ExpandProperty Id + $tagIdList = $tagSvc.list_tags_for_category($tagCatid) + $tagArray2 = @() + foreach ($t in $tagIdList) { + $tagArray2 += $tagSvc.get($t) + } + $tagOutput = $tagArray2 } - $tagOutput = $tagArray2 } else { - $tagOutput = $tagArray + if ($vCenterConn){$tagOutput = $vCTagList} + else {$tagOutput = $tagArray} } } $tagOutput | Select-Object Id, Name, Description @@ -250,7 +265,7 @@ function Remove-CISTagCategory { .SYNOPSIS Removes tag category information from the CIS REST API endpoint .DESCRIPTION - Will remove a tag categorie + Will remove a tag category .NOTES Author: Kyle Ruddy, @kmruddy .PARAMETER Name From 06d018c7a6abd4657f0b057a31358e008de3dcb1 Mon Sep 17 00:00:00 2001 From: PARAMESHO Date: Wed, 2 Jan 2019 21:55:26 +0530 Subject: [PATCH 63/65] Set-HVApplicationIcon not behaving correctly with .ico and .bmp files When bmp/ico image files are used as customized application icons, short cuts feature on Horizon Client is facing the issues in rendering. Bug 2168320 has been reported for this issue. We have decided to block all the non-png image files for the customization of application icons. Testing: Tested with the changes. Working as expected. Refer review https://reviewboard.eng.vmware.com/r/1446121 for more details. --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 5b68b9f..7717e40 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -8819,6 +8819,16 @@ function Set-HVApplicationIcon { } process { + if (!(Test-Path $IconPath)) { + Write-Error "File:[$IconPath] does not exist." + break + } + + if ([IO.Path]::GetExtension($IconPath) -ne '.png') { + Write-Error "Unsupported file format:[$IconPath]. Only PNG image files are supported." + break + } + try { $appInfo = Get-HVQueryResult -EntityType ApplicationInfo -Filter (Get-HVQueryFilter data.name -Eq $ApplicationName) -HvServer $HvServer } catch { @@ -8832,11 +8842,6 @@ function Set-HVApplicationIcon { break } - if (!(Test-Path $IconPath)) { - Write-Error "File:[$IconPath] does not exists" - break - } - $spec = New-Object VMware.Hv.ApplicationIconSpec $base = New-Object VMware.Hv.ApplicationIconBase From 9073d8f3b23fa1763f68d812f5564ed0a4e7fe32 Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Thu, 10 Jan 2019 09:42:14 -0500 Subject: [PATCH 64/65] Create Save-PowerCLI.ps1 Adding function to download specific versions of PowerCLI from an online repository --- Scripts/Save-PowerCLI.ps1 | 57 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 Scripts/Save-PowerCLI.ps1 diff --git a/Scripts/Save-PowerCLI.ps1 b/Scripts/Save-PowerCLI.ps1 new file mode 100644 index 0000000..8aa3230 --- /dev/null +++ b/Scripts/Save-PowerCLI.ps1 @@ -0,0 +1,57 @@ +function Save-PowerCLI { +<# +.SYNOPSIS + Function which can be used to easily download specific versions of PowerCLI from an online gallery +.DESCRIPTION + Downloads a specific version of PowerCLI and all the dependencies at the appropriate version +.NOTES + Author: 1.0 - Dimitar Milov +.PARAMETER RequiredVersion + Specify the PowerCLI version +.PARAMETER Path + Directory path where the modules should be downloaded +.PARAMETER Repository + Repository to access the PowerCLI modules +.EXAMPLE + Save-PowerCLI -RequiredVersion '10.0.0.7895300' -Path .\Downloads\ + Downloads PowerCLI 10.0.0 to the Downloads folder +#> + param( + [Parameter(Mandatory = $true)] + [version]$RequiredVersion, + + [Parameter(Mandatory = $true)] + [ValidateScript( { Test-Path $_} )] + [string] + $Path, + + [Parameter()] + [string]$Repository = 'PSGallery' + ) + $powercliModuleName = 'VMware.PowerCLI' + $desiredPowerCLIModule = Find-Module -Name $powercliModuleName -RequiredVersion $RequiredVersion + if (-not $desiredPowerCLIModule) { + throw "'VMware.PowerCLI' with version $RequiredVersion' was not found." + } + + $depsOrder = 'VMware.VimAutomation.Sdk', 'VMware.VimAutomation.Common', 'VMware.Vim', 'VMware.VimAutomation.Cis.Core', 'VMware.VimAutomation.Core', 'VMware.VimAutomation.Nsxt', 'VMware.VimAutomation.Vmc', 'VMware.VimAutomation.Vds', 'VMware.VimAutomation.Srm', 'VMware.ImageBuilder', 'VMware.VimAutomation.Storage', 'VMware.VimAutomation.StorageUtility', 'VMware.VimAutomation.License', 'VMware.VumAutomation', 'VMware.VimAutomation.HorizonView', 'VMware.DeployAutomation', 'VMware.VimAutomation.vROps', 'VMware.VimAutomation.PCloud' + $orderedDependncies = @() + foreach ($depModuleName in $depsOrder) { + $orderedDependncies += $desiredPowerCLIModule.Dependencies | ? {$_.Name -eq $depModuleName} + } + + # Save PowerCLI Module Version + Find-Module -Name $powercliModuleName -RequiredVersion $RequiredVersion | Save-Module -Path $Path + + # Save dependencies with minimum version + foreach ($dependency in $orderedDependncies) { + Find-Module $dependency.Name -RequiredVersion $dependency.MinimumVersion | Save-Module -Path $Path + } + + # Remove newer dependencies versoin + foreach ($dependency in $orderedDependncies) { + Get-ChildItem -Path (Join-Path $path $dependency.Name) | ` + Where-Object {$_.Name -ne $dependency.MinimumVersion} | ` + Remove-Item -Confirm:$false -Force -Recurse + } +} \ No newline at end of file From e35e17a04dea99a56123908cda4f29444d2aaaf3 Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Thu, 10 Jan 2019 09:44:58 -0500 Subject: [PATCH 65/65] Update Save-PowerCLI.ps1 Updating function with v2 additions: - Dynamic RequiredVersion parameter - Simple parameter to handle the nested version folders - Address the potential of downloading multiple module folders twice --- Scripts/Save-PowerCLI.ps1 | 202 +++++++++++++++++++++++++++----------- 1 file changed, 146 insertions(+), 56 deletions(-) diff --git a/Scripts/Save-PowerCLI.ps1 b/Scripts/Save-PowerCLI.ps1 index 8aa3230..e9127bc 100644 --- a/Scripts/Save-PowerCLI.ps1 +++ b/Scripts/Save-PowerCLI.ps1 @@ -1,57 +1,147 @@ function Save-PowerCLI { -<# -.SYNOPSIS - Function which can be used to easily download specific versions of PowerCLI from an online gallery -.DESCRIPTION - Downloads a specific version of PowerCLI and all the dependencies at the appropriate version -.NOTES - Author: 1.0 - Dimitar Milov -.PARAMETER RequiredVersion - Specify the PowerCLI version -.PARAMETER Path - Directory path where the modules should be downloaded -.PARAMETER Repository - Repository to access the PowerCLI modules -.EXAMPLE - Save-PowerCLI -RequiredVersion '10.0.0.7895300' -Path .\Downloads\ - Downloads PowerCLI 10.0.0 to the Downloads folder -#> - param( - [Parameter(Mandatory = $true)] - [version]$RequiredVersion, - - [Parameter(Mandatory = $true)] - [ValidateScript( { Test-Path $_} )] - [string] - $Path, - - [Parameter()] - [string]$Repository = 'PSGallery' - ) - $powercliModuleName = 'VMware.PowerCLI' - $desiredPowerCLIModule = Find-Module -Name $powercliModuleName -RequiredVersion $RequiredVersion - if (-not $desiredPowerCLIModule) { - throw "'VMware.PowerCLI' with version $RequiredVersion' was not found." - } - - $depsOrder = 'VMware.VimAutomation.Sdk', 'VMware.VimAutomation.Common', 'VMware.Vim', 'VMware.VimAutomation.Cis.Core', 'VMware.VimAutomation.Core', 'VMware.VimAutomation.Nsxt', 'VMware.VimAutomation.Vmc', 'VMware.VimAutomation.Vds', 'VMware.VimAutomation.Srm', 'VMware.ImageBuilder', 'VMware.VimAutomation.Storage', 'VMware.VimAutomation.StorageUtility', 'VMware.VimAutomation.License', 'VMware.VumAutomation', 'VMware.VimAutomation.HorizonView', 'VMware.DeployAutomation', 'VMware.VimAutomation.vROps', 'VMware.VimAutomation.PCloud' - $orderedDependncies = @() - foreach ($depModuleName in $depsOrder) { - $orderedDependncies += $desiredPowerCLIModule.Dependencies | ? {$_.Name -eq $depModuleName} - } - - # Save PowerCLI Module Version - Find-Module -Name $powercliModuleName -RequiredVersion $RequiredVersion | Save-Module -Path $Path - - # Save dependencies with minimum version - foreach ($dependency in $orderedDependncies) { - Find-Module $dependency.Name -RequiredVersion $dependency.MinimumVersion | Save-Module -Path $Path - } - - # Remove newer dependencies versoin - foreach ($dependency in $orderedDependncies) { - Get-ChildItem -Path (Join-Path $path $dependency.Name) | ` - Where-Object {$_.Name -ne $dependency.MinimumVersion} | ` - Remove-Item -Confirm:$false -Force -Recurse - } -} \ No newline at end of file + <# + .SYNOPSIS + Advanced function which can be used to easily download specific versions of PowerCLI from an online gallery + .DESCRIPTION + Downloads a specific version of PowerCLI and all the dependencies at the appropriate version + .NOTES + Author: 1.0 - Dimitar Milov + Author: 2.0 - Kyle Ruddy, @kmruddy + .PARAMETER RequiredVersion + Dynamic parameter used to specify the PowerCLI version + .PARAMETER Path + Directory path where the modules should be downloaded + .PARAMETER Repository + Repository to access the PowerCLI modules + .PARAMETER Simple + Switch used to specify the nested version folders should be removed (therefore adding PowerShell 3/4 compatibility) + .EXAMPLE + Save-PowerCLI -RequiredVersion '10.0.0.7895300' -Path .\Downloads\ + Downloads PowerCLI 10.0.0 to the Downloads folder + .EXAMPLE + Save-PowerCLI -RequiredVersion '6.5.2.6268016' -Path .\Downloads\ -Simple + Downloads PowerCLI 6.5.2 to the Downloads folder and removes the nested version folders + #> + [CmdletBinding(SupportsShouldProcess = $True)] + param( + [Parameter(Mandatory = $true, Position = 1)] + [ValidateScript( { Test-Path $_} )] + $Path, + [Parameter(Mandatory = $false, Position = 2)] + [string]$Repository = 'PSGallery', + [Parameter(Mandatory = $false, Position = 3)] + [Switch]$Simple + ) + DynamicParam + { + # Set the dynamic parameters name + $ParameterName = 'RequiredVersion' + + # Create the dictionary + $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary + + # Create the collection of attributes + $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] + + # Create and set the parameters' attributes + $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute + $ParameterAttribute.ValueFromPipeline = $true + $ParameterAttribute.ValueFromPipelineByPropertyName = $true + $ParameterAttribute.Mandatory = $true + $ParameterAttribute.Position = 0 + + # Add the attributes to the attributes collection + $AttributeCollection.Add($ParameterAttribute) + + # Generate and set the ValidateSet + $pcliVersions = Find-Module -Name 'VMware.PowerCLI' -AllVersions + $arrSet = $pcliVersions | select-Object -ExpandProperty Version + $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($arrSet) + + # Add the ValidateSet to the attributes collection + $AttributeCollection.Add($ValidateSetAttribute) + + # Create and return the dynamic parameter + $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection) + $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter) + return $RuntimeParameterDictionary + } + + begin { + $powercliModuleName = 'VMware.PowerCLI' + $desiredPowerCLIModule = Find-Module -Name $powercliModuleName -RequiredVersion $RequiredVersion -Repository $Repository + + $depsOrder = 'VMware.VimAutomation.Sdk', 'VMware.VimAutomation.Common', 'VMware.Vim', 'VMware.VimAutomation.Cis.Core', 'VMware.VimAutomation.Core', 'VMware.VimAutomation.Nsxt', 'VMware.VimAutomation.Vmc', 'VMware.VimAutomation.Vds', 'VMware.VimAutomation.Srm', 'VMware.ImageBuilder', 'VMware.VimAutomation.Storage', 'VMware.VimAutomation.StorageUtility', 'VMware.VimAutomation.License', 'VMware.VumAutomation', 'VMware.VimAutomation.HorizonView', 'VMware.DeployAutomation', 'VMware.VimAutomation.vROps', 'VMware.VimAutomation.PCloud' + $orderedDependencies = @() + foreach ($depModuleName in $depsOrder) { + $orderedDependencies += $desiredPowerCLIModule.Dependencies | Where-Object {$_.Name -eq $depModuleName} + } + + foreach ($remainingDep in $desiredPowerCLIModule.Dependencies) { + if ($orderedDependencies.Name -notcontains $remainingDep.Name) { + $orderedDependencies += $remainingDep + } + + } + } + + process { + # Save PowerCLI Module Version + $desiredPowerCLIModule | Save-Module -Path $Path + + # Working with the depenent modules + foreach ($dependency in $orderedDependencies) { + if (Get-ChildItem -Path (Join-Path $path $dependency.Name) | Where-Object {$_.Name -ne $dependency.MinimumVersion}) { + # Save dependencies with minimum version + Find-Module $dependency.Name -RequiredVersion $dependency.MinimumVersion | Save-Module -Path $Path + + # Remove newer dependencies version + Get-ChildItem -Path (Join-Path $path $dependency.Name) | Where-Object {$_.Name -ne $dependency.MinimumVersion} | Remove-Item -Confirm:$false -Force -Recurse + } + } + } + + end { + if ($Simple) { + + function FolderCleanup { + param( + [Parameter(Mandatory = $true, Position = 0)] + [ValidateScript( { Test-Path $_} )] + $ParentFolder, + [Parameter(Mandatory = $true, Position = 1)] + [String]$ModuleName, + [Parameter(Mandatory = $true, Position = 2)] + $Version + ) + + + $topFolder = Get-Item -Path (Join-Path $ParentFolder $ModuleName) + $versionFolder = $topFolder | Get-ChildItem -Directory | Where-Object {$_.Name -eq $Version} + $versionFolder | Get-ChildItem | Copy-Item -Destination $topFolder + + # Checking for any nested folders within the PowerCLI module version folder + if ($versionFolder| Get-ChildItem -Directory) { + + # Obtaining and storing the child items to a variable, then copying the items to the parent folder's nested folder + $nestFolder = $versionFolder| Get-ChildItem -Directory + foreach ($nestDir in $nestFolder) { + $nestDir | Get-ChildItem | Copy-Item -Destination (Join-Path $topFolder $nestDir.Name) + } + + } + + # Removing any of the former, no longer needed, directory structure + $versionFolder| Remove-Item -Recurse -Force + } + + FolderCleanup -ParentFolder $Path -ModuleName $desiredPowerCLIModule.Name -Version $desiredPowerCLIModule.Version + foreach ($cleanUp in $orderedDependencies) { + + FolderCleanup -ParentFolder $Path -ModuleName $cleanUp.Name -Version $cleanUp.MinimumVersion + } + + } + + } + } \ No newline at end of file