From f9ca007ae5faded62b347e778b0ab0105e88611e Mon Sep 17 00:00:00 2001 From: Conor Tolan Date: Mon, 18 Feb 2019 21:57:52 +0000 Subject: [PATCH 01/42] Added two pester tests for Get-VMCCommand and Connect-VMCVIServer. --- Modules/VMware.VMC/VMware.VMC.psm1 | 2 +- .../Functions/Connect-VMCVIServer.tests.ps1 | 57 +++++++++++++++++++ Pester/Functions/Get-VMCCommand.tests.ps1 | 20 +++++++ Pester/Functions/Shared.ps1 | 6 ++ 4 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 Pester/Functions/Connect-VMCVIServer.tests.ps1 create mode 100644 Pester/Functions/Get-VMCCommand.tests.ps1 create mode 100644 Pester/Functions/Shared.ps1 diff --git a/Modules/VMware.VMC/VMware.VMC.psm1 b/Modules/VMware.VMC/VMware.VMC.psm1 index 33f78a7..538501e 100644 --- a/Modules/VMware.VMC/VMware.VMC.psm1 +++ b/Modules/VMware.VMC/VMware.VMC.psm1 @@ -20,7 +20,7 @@ Function Get-VMCCommand { .NOTES You can either use this cmdlet or the Get-Command cmdlet as seen in Example 2 #> - Get-command -Module VMware.VimAutomation.Vmc + Get-command -Module VimppppppMware.VimAutomation.Vmc Get-Command -Module VMware.VMC } diff --git a/Pester/Functions/Connect-VMCVIServer.tests.ps1 b/Pester/Functions/Connect-VMCVIServer.tests.ps1 new file mode 100644 index 0000000..4a7feec --- /dev/null +++ b/Pester/Functions/Connect-VMCVIServer.tests.ps1 @@ -0,0 +1,57 @@ +#Requires -Modules Pester, VMware.VMC +$functionName = $MyInvocation.MyCommand.Name.TrimEnd(".Tests.ps1") +Describe "$functionName" -Tag 'Unit' { + . "$PSScriptRoot/Shared.ps1" + + $Org = 'MyOrg' + $Sddc = 'MySddc' + + $global:DefaultVMCServers = $true + + $secpasswd = ConvertTo-SecureString "password" -AsPlainText -Force + $Mockedcreds = New-Object System.Management.Automation.PSCredential ("username", $secpasswd) + $cloud_username = "MockedUserName" + $vc_public_ip = "MockedServer" + + Mock Get-VMCSDDCDefaultCredential { + $object = [PSCustomObject] @{ + 'vc_public_ip' = $vc_public_ip + 'cloud_username' = $cloud_username + 'cloud_password' = $Mockedcreds.Password + } + return $object + } + + Mock Connect-VIServer {} + + Mock Connect-CisServer {} + + Context "Sanity checking" { + $command = Get-Command -Name $functionName + + defParam $command 'Org' + defParam $command 'Sddc' + defParam $command 'Autologin' + } + + Context "Behavior testing" { + It "gets creds via Get-VMCSDDCDefaultCredential" { + { Connect-VMCVIServer -org $Org -Sddc $Sddc } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCSDDCDefaultCredential -Times 1 -Scope It -ParameterFilter { $org -eq $Org -and $Sddc -eq $Sddc } + } + It "calls the Connect-VIServer" { + { Connect-VMCVIServer -org $Org -Sddc $Sddc } | Should Not Throw + Assert-MockCalled -CommandName Connect-VIServer -Times 1 -Scope It -ParameterFilter { ` + $Server -eq $vc_public_ip ` + -and $User -eq $cloud_username ` + -and $Password -eq $Mockedcreds.Password } + } + It "calls the Connect-CisServer" { + { Connect-VMCVIServer -org $Org -Sddc $Sddc } | Should Not Throw + Assert-MockCalled -CommandName Connect-CisServer -Times 1 -Scope It -ParameterFilter { ` + $Server -eq $vc_public_ip ` + -and $User -eq $cloud_username ` + -and $Password -eq $Mockedcreds.password } + } + } +} diff --git a/Pester/Functions/Get-VMCCommand.tests.ps1 b/Pester/Functions/Get-VMCCommand.tests.ps1 new file mode 100644 index 0000000..230594c --- /dev/null +++ b/Pester/Functions/Get-VMCCommand.tests.ps1 @@ -0,0 +1,20 @@ +#Requires -Modules Pester, VMware.VMC, VMware.VimAutomation.Vmc +$functionName = $MyInvocation.MyCommand.Name.TrimEnd(".Tests.ps1") + +Describe "$functionName" -Tag 'Unit' { + Mock Get-Command { + "Mocked Command Response" + } + + Context "Behavior testing" { + It "should call get-command on VMware.VimAutomation.Vmc" { + { Get-VMCCommand } | Should Not Throw + Assert-MockCalled -CommandName Get-command -Times 1 -Scope It -ParameterFilter { $Module -eq 'VMware.VimAutomation.Vmc' } + + } + It "should call get-command on VMware.Vmc" { + { Get-VMCCommand } | Should Not Throw + Assert-MockCalled -CommandName Get-command -Times 1 -Scope It -ParameterFilter { $Module -eq 'VMware.VMC' } + } + } +} \ No newline at end of file diff --git a/Pester/Functions/Shared.ps1 b/Pester/Functions/Shared.ps1 new file mode 100644 index 0000000..d49d97c --- /dev/null +++ b/Pester/Functions/Shared.ps1 @@ -0,0 +1,6 @@ +#Requires -Modules Pester +function defParam($command, $name) { + It "Has a -$name parameter" { + $command.Parameters.Item($name) | Should Not BeNullOrEmpty + } +} \ No newline at end of file From 783319a624a296e391bd4c05b43ce9e44d94147c Mon Sep 17 00:00:00 2001 From: Conor Tolan Date: Wed, 20 Feb 2019 22:17:59 +0000 Subject: [PATCH 02/42] Finished org tests --- Pester/Functions/Get-VMCOrg.tests.1.ps1 | 73 +++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 Pester/Functions/Get-VMCOrg.tests.1.ps1 diff --git a/Pester/Functions/Get-VMCOrg.tests.1.ps1 b/Pester/Functions/Get-VMCOrg.tests.1.ps1 new file mode 100644 index 0000000..19d79fc --- /dev/null +++ b/Pester/Functions/Get-VMCOrg.tests.1.ps1 @@ -0,0 +1,73 @@ +#Requires -Modules Pester, VMware.VMC +$functionName = $MyInvocation.MyCommand.Name.TrimEnd(".Tests.ps1") +Import-Module -Name VMware.VimAutomation.Cis.Core + +Describe "$functionName" -Tag 'Unit' { + . "$PSScriptRoot/Shared.ps1" + + $global:DefaultVMCServers = $true + + $display_name = "MockedDisplayName" + $user_name = "MockedUserName" + $OrgName = "MockedDisplayName" + $created = "MockedDate" + $id = "MockedId" + $Service = "com.vmware.vmc.orgs" + + $MockedList = [PSCustomObject]@{ + "display_name" = $display_name + "name" = $OrgName + "created" = $created + "user_name" = $user_name + "id" = $id + } + #$object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } + + + $MockedArray = @() + $MockedArray += $MockedList + $MockedArray += $MockedList + + Mock -CommandName Get-VMCService -MockWith { $object } + + Context "Sanity checking" { + $command = Get-Command -Name $functionName + + defParam $command 'Name' + } + + Context "Behavior testing" { + It "calls get-service to com.vmware.vmc.orgs" { + { Get-VMCOrg -name $OrgName } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCService -Times 1 -Scope It -ParameterFilter { $name -eq $Service } + } + # Testing a single SDDC response + It "gets the orgs via list method and returns the properties" { + $object = [PSCustomObject]@{} + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } + $(Get-VMCOrg -name $OrgName).display_name | Should -be $display_name + $(Get-VMCOrg -name $OrgName).name | Should -be $OrgName + $(Get-VMCOrg -name $OrgName).user_name | Should -be $user_name + $(Get-VMCOrg -name $OrgName).created | Should -be $created + $(Get-VMCOrg -name $OrgName).id | Should -be $id + } + # Testing the multiple SDDC response + It "calls the Connect-CisServer" { + $object = [PSCustomObject]@{} + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedArray } + { Get-VMCOrg -name $OrgName } | Should Not Throw + + $(Get-VMCOrg -name $OrgName)[0].display_name | Should -be $display_name + $(Get-VMCOrg -name $OrgName)[0].name | Should -be $OrgName + $(Get-VMCOrg -name $OrgName)[0].user_name | Should -be $user_name + $(Get-VMCOrg -name $OrgName)[0].created | Should -be $created + $(Get-VMCOrg -name $OrgName)[0].id | Should -be $id + + $(Get-VMCOrg -name $OrgName)[1].display_name | Should -be $display_name + $(Get-VMCOrg -name $OrgName)[1].name | Should -be $OrgName + $(Get-VMCOrg -name $OrgName)[1].user_name | Should -be $user_name + $(Get-VMCOrg -name $OrgName)[1].created | Should -be $created + $(Get-VMCOrg -name $OrgName)[1].id | Should -be $id + } + } +} From 3a61850b41ac8927195a6694ba7e9c82825ad452 Mon Sep 17 00:00:00 2001 From: Conor Tolan Date: Wed, 20 Feb 2019 22:26:26 +0000 Subject: [PATCH 03/42] Randomly wrote over import. undone. --- Modules/VMware.VMC/VMware.VMC.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/VMware.VMC/VMware.VMC.psm1 b/Modules/VMware.VMC/VMware.VMC.psm1 index 538501e..33f78a7 100644 --- a/Modules/VMware.VMC/VMware.VMC.psm1 +++ b/Modules/VMware.VMC/VMware.VMC.psm1 @@ -20,7 +20,7 @@ Function Get-VMCCommand { .NOTES You can either use this cmdlet or the Get-Command cmdlet as seen in Example 2 #> - Get-command -Module VimppppppMware.VimAutomation.Vmc + Get-command -Module VMware.VimAutomation.Vmc Get-Command -Module VMware.VMC } From 6c578f7b78899453bc1b5b62875d4f406cbae22d Mon Sep 17 00:00:00 2001 From: Conor Tolan Date: Sat, 23 Feb 2019 16:37:03 +0000 Subject: [PATCH 04/42] Added mock write-host to clean up output. Added the general creation of the $object needed to mock the function. --- Pester/Functions/Connect-VMCVIServer.tests.ps1 | 2 ++ Pester/Functions/Get-VMCOrg.tests.1.ps1 | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Pester/Functions/Connect-VMCVIServer.tests.ps1 b/Pester/Functions/Connect-VMCVIServer.tests.ps1 index 4a7feec..2448ab3 100644 --- a/Pester/Functions/Connect-VMCVIServer.tests.ps1 +++ b/Pester/Functions/Connect-VMCVIServer.tests.ps1 @@ -22,6 +22,8 @@ Describe "$functionName" -Tag 'Unit' { return $object } + Mock Write-host {} + Mock Connect-VIServer {} Mock Connect-CisServer {} diff --git a/Pester/Functions/Get-VMCOrg.tests.1.ps1 b/Pester/Functions/Get-VMCOrg.tests.1.ps1 index 19d79fc..6f451aa 100644 --- a/Pester/Functions/Get-VMCOrg.tests.1.ps1 +++ b/Pester/Functions/Get-VMCOrg.tests.1.ps1 @@ -21,8 +21,9 @@ Describe "$functionName" -Tag 'Unit' { "user_name" = $user_name "id" = $id } - #$object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } + $object = [PSCustomObject]@{} + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } $MockedArray = @() $MockedArray += $MockedList @@ -37,6 +38,7 @@ Describe "$functionName" -Tag 'Unit' { } Context "Behavior testing" { + It "calls get-service to com.vmware.vmc.orgs" { { Get-VMCOrg -name $OrgName } | Should Not Throw Assert-MockCalled -CommandName Get-VMCService -Times 1 -Scope It -ParameterFilter { $name -eq $Service } From a95e01066d920969371b3cde4d7b00d29b583410 Mon Sep 17 00:00:00 2001 From: Conor Tolan Date: Sat, 23 Feb 2019 16:40:31 +0000 Subject: [PATCH 05/42] Renamed VMC Org test file. Added VMC Sddc test file. --- ...MCOrg.tests.1.ps1 => Get-VMCOrg.tests.ps1} | 0 Pester/Functions/Get-VmcSddc.tests.ps1 | 75 +++++++++++++++++++ 2 files changed, 75 insertions(+) rename Pester/Functions/{Get-VMCOrg.tests.1.ps1 => Get-VMCOrg.tests.ps1} (100%) create mode 100644 Pester/Functions/Get-VmcSddc.tests.ps1 diff --git a/Pester/Functions/Get-VMCOrg.tests.1.ps1 b/Pester/Functions/Get-VMCOrg.tests.ps1 similarity index 100% rename from Pester/Functions/Get-VMCOrg.tests.1.ps1 rename to Pester/Functions/Get-VMCOrg.tests.ps1 diff --git a/Pester/Functions/Get-VmcSddc.tests.ps1 b/Pester/Functions/Get-VmcSddc.tests.ps1 new file mode 100644 index 0000000..6f451aa --- /dev/null +++ b/Pester/Functions/Get-VmcSddc.tests.ps1 @@ -0,0 +1,75 @@ +#Requires -Modules Pester, VMware.VMC +$functionName = $MyInvocation.MyCommand.Name.TrimEnd(".Tests.ps1") +Import-Module -Name VMware.VimAutomation.Cis.Core + +Describe "$functionName" -Tag 'Unit' { + . "$PSScriptRoot/Shared.ps1" + + $global:DefaultVMCServers = $true + + $display_name = "MockedDisplayName" + $user_name = "MockedUserName" + $OrgName = "MockedDisplayName" + $created = "MockedDate" + $id = "MockedId" + $Service = "com.vmware.vmc.orgs" + + $MockedList = [PSCustomObject]@{ + "display_name" = $display_name + "name" = $OrgName + "created" = $created + "user_name" = $user_name + "id" = $id + } + + $object = [PSCustomObject]@{} + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } + + $MockedArray = @() + $MockedArray += $MockedList + $MockedArray += $MockedList + + Mock -CommandName Get-VMCService -MockWith { $object } + + Context "Sanity checking" { + $command = Get-Command -Name $functionName + + defParam $command 'Name' + } + + Context "Behavior testing" { + + It "calls get-service to com.vmware.vmc.orgs" { + { Get-VMCOrg -name $OrgName } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCService -Times 1 -Scope It -ParameterFilter { $name -eq $Service } + } + # Testing a single SDDC response + It "gets the orgs via list method and returns the properties" { + $object = [PSCustomObject]@{} + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } + $(Get-VMCOrg -name $OrgName).display_name | Should -be $display_name + $(Get-VMCOrg -name $OrgName).name | Should -be $OrgName + $(Get-VMCOrg -name $OrgName).user_name | Should -be $user_name + $(Get-VMCOrg -name $OrgName).created | Should -be $created + $(Get-VMCOrg -name $OrgName).id | Should -be $id + } + # Testing the multiple SDDC response + It "calls the Connect-CisServer" { + $object = [PSCustomObject]@{} + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedArray } + { Get-VMCOrg -name $OrgName } | Should Not Throw + + $(Get-VMCOrg -name $OrgName)[0].display_name | Should -be $display_name + $(Get-VMCOrg -name $OrgName)[0].name | Should -be $OrgName + $(Get-VMCOrg -name $OrgName)[0].user_name | Should -be $user_name + $(Get-VMCOrg -name $OrgName)[0].created | Should -be $created + $(Get-VMCOrg -name $OrgName)[0].id | Should -be $id + + $(Get-VMCOrg -name $OrgName)[1].display_name | Should -be $display_name + $(Get-VMCOrg -name $OrgName)[1].name | Should -be $OrgName + $(Get-VMCOrg -name $OrgName)[1].user_name | Should -be $user_name + $(Get-VMCOrg -name $OrgName)[1].created | Should -be $created + $(Get-VMCOrg -name $OrgName)[1].id | Should -be $id + } + } +} From f642290b2d2548c182cf99b152e7e5f8838ce7f1 Mon Sep 17 00:00:00 2001 From: Conor Tolan Date: Sat, 23 Feb 2019 17:41:23 +0000 Subject: [PATCH 06/42] Tidied up the object creation in tests. --- Pester/Functions/Get-VMCOrg.tests.ps1 | 4 +- Pester/Functions/Get-VmcSddc.tests.ps1 | 78 ++++++++++++++++---------- 2 files changed, 49 insertions(+), 33 deletions(-) diff --git a/Pester/Functions/Get-VMCOrg.tests.ps1 b/Pester/Functions/Get-VMCOrg.tests.ps1 index 6f451aa..0726f5a 100644 --- a/Pester/Functions/Get-VMCOrg.tests.ps1 +++ b/Pester/Functions/Get-VMCOrg.tests.ps1 @@ -25,9 +25,7 @@ Describe "$functionName" -Tag 'Unit' { $object = [PSCustomObject]@{} $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } - $MockedArray = @() - $MockedArray += $MockedList - $MockedArray += $MockedList + $MockedArray = @($MockedList, $MockedList) Mock -CommandName Get-VMCService -MockWith { $object } diff --git a/Pester/Functions/Get-VmcSddc.tests.ps1 b/Pester/Functions/Get-VmcSddc.tests.ps1 index 6f451aa..7d848a3 100644 --- a/Pester/Functions/Get-VmcSddc.tests.ps1 +++ b/Pester/Functions/Get-VmcSddc.tests.ps1 @@ -9,67 +9,85 @@ Describe "$functionName" -Tag 'Unit' { $display_name = "MockedDisplayName" $user_name = "MockedUserName" - $OrgName = "MockedDisplayName" + $OrgName = "MockedOrgName" $created = "MockedDate" + $OrgId = "Mocked OrgID" + $name = "MockedSDDCName" + $Notname = "NotTheName" $id = "MockedId" - $Service = "com.vmware.vmc.orgs" + $Service = "com.vmware.vmc.orgs.sddcs" $MockedList = [PSCustomObject]@{ "display_name" = $display_name - "name" = $OrgName + "name" = $name + "created" = $created + "user_name" = $user_name + "id" = $id + } + $MockedList2 = [PSCustomObject]@{ + "display_name" = $display_name + "name" = $Notname "created" = $created "user_name" = $user_name "id" = $id } - $object = [PSCustomObject]@{} + $object = @( + @{"Id" = $Id} + ) $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } - $MockedArray = @() - $MockedArray += $MockedList - $MockedArray += $MockedList + $MockedArray = @($MockedList, $MockedList2) Mock -CommandName Get-VMCService -MockWith { $object } + Mock -CommandName Get-VMCOrg { $object } + Context "Sanity checking" { $command = Get-Command -Name $functionName defParam $command 'Name' + defParam $command 'Org' } Context "Behavior testing" { - It "calls get-service to com.vmware.vmc.orgs" { - { Get-VMCOrg -name $OrgName } | Should Not Throw + It "calls Get-VMCOrg" { + { Get-VMCSDDC -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCOrg -Times 1 -Scope It + } + It "calls Get-VMCOrg with the SDDC name supplied" { + { Get-VMCSDDC -Org $OrgId -name $name} | Should Not Throw + Assert-MockCalled -CommandName Get-VMCOrg -Times 1 -Scope It -ParameterFilter { $name -eq $name } + } + # Testing with single "Org" so assert call twice. + It "calls get-service to com.vmware.vmc.orgs.sddcs" { + { Get-VMCSDDC -Org $OrgId } | Should Not Throw Assert-MockCalled -CommandName Get-VMCService -Times 1 -Scope It -ParameterFilter { $name -eq $Service } } + + # Testing with two "Orgs" so assert call twice. + It "calls get-service to com.vmware.vmc.orgs.sddcs" { + $object = @( + @{"Id" = 1} + @{"Id" = 2} + ) + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedArray } + { Get-VMCSDDC -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCService -Times 2 -Scope It -ParameterFilter { $name -eq $Service } + } + # Testing a single SDDC response - It "gets the orgs via list method and returns the properties" { + It "gets the SDDC details via list method and returns the properties" { $object = [PSCustomObject]@{} $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } - $(Get-VMCOrg -name $OrgName).display_name | Should -be $display_name - $(Get-VMCOrg -name $OrgName).name | Should -be $OrgName - $(Get-VMCOrg -name $OrgName).user_name | Should -be $user_name - $(Get-VMCOrg -name $OrgName).created | Should -be $created - $(Get-VMCOrg -name $OrgName).id | Should -be $id + $(Get-VMCSDDC -Org $OrgId).display_name | Should -be $display_name } # Testing the multiple SDDC response - It "calls the Connect-CisServer" { - $object = [PSCustomObject]@{} + It "gets the SDDC details of the SDDC supplied and returns the properties" { + $object = @{} $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedArray } - { Get-VMCOrg -name $OrgName } | Should Not Throw - - $(Get-VMCOrg -name $OrgName)[0].display_name | Should -be $display_name - $(Get-VMCOrg -name $OrgName)[0].name | Should -be $OrgName - $(Get-VMCOrg -name $OrgName)[0].user_name | Should -be $user_name - $(Get-VMCOrg -name $OrgName)[0].created | Should -be $created - $(Get-VMCOrg -name $OrgName)[0].id | Should -be $id - - $(Get-VMCOrg -name $OrgName)[1].display_name | Should -be $display_name - $(Get-VMCOrg -name $OrgName)[1].name | Should -be $OrgName - $(Get-VMCOrg -name $OrgName)[1].user_name | Should -be $user_name - $(Get-VMCOrg -name $OrgName)[1].created | Should -be $created - $(Get-VMCOrg -name $OrgName)[1].id | Should -be $id + $(Get-VMCSDDC -Org $OrgId -name $name).name | Should -be $name } } } From b90c83ac56f1440b671e08fcba95f80efb8dfd0c Mon Sep 17 00:00:00 2001 From: Conor Tolan Date: Sat, 23 Feb 2019 18:06:09 +0000 Subject: [PATCH 07/42] Created tests for get VMC Task Trimed out excess fom get SDDC parameters in the object. --- Pester/Functions/Get-VmcSddc.tests.ps1 | 17 +----- Pester/Functions/Get-VmcTask.tests.ps1 | 78 ++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 15 deletions(-) create mode 100644 Pester/Functions/Get-VmcTask.tests.ps1 diff --git a/Pester/Functions/Get-VmcSddc.tests.ps1 b/Pester/Functions/Get-VmcSddc.tests.ps1 index 7d848a3..de27e79 100644 --- a/Pester/Functions/Get-VmcSddc.tests.ps1 +++ b/Pester/Functions/Get-VmcSddc.tests.ps1 @@ -7,33 +7,20 @@ Describe "$functionName" -Tag 'Unit' { $global:DefaultVMCServers = $true - $display_name = "MockedDisplayName" - $user_name = "MockedUserName" - $OrgName = "MockedOrgName" - $created = "MockedDate" $OrgId = "Mocked OrgID" $name = "MockedSDDCName" $Notname = "NotTheName" - $id = "MockedId" $Service = "com.vmware.vmc.orgs.sddcs" $MockedList = [PSCustomObject]@{ - "display_name" = $display_name "name" = $name - "created" = $created - "user_name" = $user_name - "id" = $id } $MockedList2 = [PSCustomObject]@{ - "display_name" = $display_name "name" = $Notname - "created" = $created - "user_name" = $user_name - "id" = $id } $object = @( - @{"Id" = $Id} + @{"Id" = 1} ) $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } @@ -81,7 +68,7 @@ Describe "$functionName" -Tag 'Unit' { It "gets the SDDC details via list method and returns the properties" { $object = [PSCustomObject]@{} $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } - $(Get-VMCSDDC -Org $OrgId).display_name | Should -be $display_name + $(Get-VMCSDDC -Org $OrgId).name | Should -be $name } # Testing the multiple SDDC response It "gets the SDDC details of the SDDC supplied and returns the properties" { diff --git a/Pester/Functions/Get-VmcTask.tests.ps1 b/Pester/Functions/Get-VmcTask.tests.ps1 new file mode 100644 index 0000000..f54e944 --- /dev/null +++ b/Pester/Functions/Get-VmcTask.tests.ps1 @@ -0,0 +1,78 @@ +#Requires -Modules Pester, VMware.VMC +$functionName = $MyInvocation.MyCommand.Name.TrimEnd(".Tests.ps1") +Import-Module -Name VMware.VimAutomation.Cis.Core + +Describe "$functionName" -Tag 'Unit' { + . "$PSScriptRoot/Shared.ps1" + + $global:DefaultVMCServers = $true + + $OrgId = "Mocked OrgID" + $name = "MockedSDDCName" + $Notname = "NotTheName" + $id = "MockedId" + $Service = "com.vmware.vmc.orgs.tasks" + + $MockedList = [PSCustomObject]@{ + "name" = $name + } + $MockedList2 = [PSCustomObject]@{ + "name" = $Notname + } + + $object = @( + @{"Id" = $Id} + ) + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } + + $MockedArray = @($MockedList, $MockedList2) + + Mock -CommandName Get-VMCService -MockWith { $object } + + Mock -CommandName Get-VMCOrg { $object } + + Context "Sanity checking" { + $command = Get-Command -Name $functionName + + defParam $command 'Org' + } + + Context "Behavior testing" { + + It "calls Get-VMCOrg with the Org name supplied" { + { Get-VMCTask -Org $name} | Should Not Throw + Assert-MockCalled -CommandName Get-VMCOrg -Times 1 -Scope It -ParameterFilter { $name -eq $name } + } + + # Testing with single "Org" so assert call twice. + It "calls get-service to com.vmware.vmc.orgs.tasks" { + { Get-VMCTask -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCService -Times 1 -Scope It -ParameterFilter { $name -eq $Service } + } + + # Testing with two "Orgs" so assert call twice. + It "calls get-service to com.vmware.vmc.orgs.tasks" { + $object = @( + @{"Id" = 1} + @{"Id" = 2} + ) + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedArray } + { Get-VMCTask -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCService -Times 2 -Scope It -ParameterFilter { $name -eq $Service } + } + + # Testing a single SDDC response + It "gets the task details via list method and returns the properties" { + $object = [PSCustomObject]@{} + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } + $(Get-VMCTask -Org $OrgId).name | Should -be $name + } + # Testing the multiple SDDC response + It "gets the task details of the SDDC supplied and returns the properties" { + $object = @{} + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedArray } + $(Get-VMCTask -Org $OrgId)[0].name | Should -be $name + $(Get-VMCTask -Org $OrgId)[1].name | Should -be $Notname + } + } +} From 5c833d4ce5b93f7668d95be2a422f44e37edfdf2 Mon Sep 17 00:00:00 2001 From: Conor Tolan Date: Sat, 23 Feb 2019 18:56:44 +0000 Subject: [PATCH 08/42] Wraped all the tests inModuleScope for invoke-pester invocation. Moved function name into module scope. --- .../Functions/Connect-VMCVIServer.tests.ps1 | 95 ++++++------ Pester/Functions/Get-VMCCommand.tests.ps1 | 29 ++-- Pester/Functions/Get-VMCOrg.tests.ps1 | 124 ++++++++-------- Pester/Functions/Get-VmcSddc.tests.ps1 | 136 +++++++++--------- Pester/Functions/Get-VmcTask.tests.ps1 | 132 ++++++++--------- 5 files changed, 264 insertions(+), 252 deletions(-) diff --git a/Pester/Functions/Connect-VMCVIServer.tests.ps1 b/Pester/Functions/Connect-VMCVIServer.tests.ps1 index 2448ab3..b8d87f0 100644 --- a/Pester/Functions/Connect-VMCVIServer.tests.ps1 +++ b/Pester/Functions/Connect-VMCVIServer.tests.ps1 @@ -1,59 +1,62 @@ #Requires -Modules Pester, VMware.VMC -$functionName = $MyInvocation.MyCommand.Name.TrimEnd(".Tests.ps1") -Describe "$functionName" -Tag 'Unit' { - . "$PSScriptRoot/Shared.ps1" - $Org = 'MyOrg' - $Sddc = 'MySddc' - - $global:DefaultVMCServers = $true +inModuleScope VMware.VMC { + $functionName = "Connect-VMCVIServer" + Describe "$functionName" -Tag 'Unit' { + . "$PSScriptRoot/Shared.ps1" - $secpasswd = ConvertTo-SecureString "password" -AsPlainText -Force - $Mockedcreds = New-Object System.Management.Automation.PSCredential ("username", $secpasswd) - $cloud_username = "MockedUserName" - $vc_public_ip = "MockedServer" + $Org = 'MyOrg' + $Sddc = 'MySddc' + + $global:DefaultVMCServers = $true - Mock Get-VMCSDDCDefaultCredential { - $object = [PSCustomObject] @{ - 'vc_public_ip' = $vc_public_ip - 'cloud_username' = $cloud_username - 'cloud_password' = $Mockedcreds.Password + $secpasswd = ConvertTo-SecureString "password" -AsPlainText -Force + $Mockedcreds = New-Object System.Management.Automation.PSCredential ("username", $secpasswd) + $cloud_username = "MockedUserName" + $vc_public_ip = "MockedServer" + + Mock Get-VMCSDDCDefaultCredential { + $object = [PSCustomObject] @{ + 'vc_public_ip' = $vc_public_ip + 'cloud_username' = $cloud_username + 'cloud_password' = $Mockedcreds.Password + } + return $object } - return $object - } - Mock Write-host {} + Mock Write-host {} - Mock Connect-VIServer {} + Mock Connect-VIServer {} - Mock Connect-CisServer {} + Mock Connect-CisServer {} - Context "Sanity checking" { - $command = Get-Command -Name $functionName + Context "Sanity checking" { + $command = Get-Command -Name $functionName - defParam $command 'Org' - defParam $command 'Sddc' - defParam $command 'Autologin' - } - - Context "Behavior testing" { - It "gets creds via Get-VMCSDDCDefaultCredential" { - { Connect-VMCVIServer -org $Org -Sddc $Sddc } | Should Not Throw - Assert-MockCalled -CommandName Get-VMCSDDCDefaultCredential -Times 1 -Scope It -ParameterFilter { $org -eq $Org -and $Sddc -eq $Sddc } + defParam $command 'Org' + defParam $command 'Sddc' + defParam $command 'Autologin' } - It "calls the Connect-VIServer" { - { Connect-VMCVIServer -org $Org -Sddc $Sddc } | Should Not Throw - Assert-MockCalled -CommandName Connect-VIServer -Times 1 -Scope It -ParameterFilter { ` - $Server -eq $vc_public_ip ` - -and $User -eq $cloud_username ` - -and $Password -eq $Mockedcreds.Password } - } - It "calls the Connect-CisServer" { - { Connect-VMCVIServer -org $Org -Sddc $Sddc } | Should Not Throw - Assert-MockCalled -CommandName Connect-CisServer -Times 1 -Scope It -ParameterFilter { ` - $Server -eq $vc_public_ip ` - -and $User -eq $cloud_username ` - -and $Password -eq $Mockedcreds.password } + + Context "Behavior testing" { + It "gets creds via Get-VMCSDDCDefaultCredential" { + { Connect-VMCVIServer -org $Org -Sddc $Sddc } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCSDDCDefaultCredential -Times 1 -Scope It -ParameterFilter { $org -eq $Org -and $Sddc -eq $Sddc } + } + It "calls the Connect-VIServer" { + { Connect-VMCVIServer -org $Org -Sddc $Sddc } | Should Not Throw + Assert-MockCalled -CommandName Connect-VIServer -Times 1 -Scope It -ParameterFilter { ` + $Server -eq $vc_public_ip ` + -and $User -eq $cloud_username ` + -and $Password -eq $Mockedcreds.Password } + } + It "calls the Connect-CisServer" { + { Connect-VMCVIServer -org $Org -Sddc $Sddc } | Should Not Throw + Assert-MockCalled -CommandName Connect-CisServer -Times 1 -Scope It -ParameterFilter { ` + $Server -eq $vc_public_ip ` + -and $User -eq $cloud_username ` + -and $Password -eq $Mockedcreds.password } + } } } -} +} \ No newline at end of file diff --git a/Pester/Functions/Get-VMCCommand.tests.ps1 b/Pester/Functions/Get-VMCCommand.tests.ps1 index 230594c..eb84490 100644 --- a/Pester/Functions/Get-VMCCommand.tests.ps1 +++ b/Pester/Functions/Get-VMCCommand.tests.ps1 @@ -1,20 +1,23 @@ #Requires -Modules Pester, VMware.VMC, VMware.VimAutomation.Vmc -$functionName = $MyInvocation.MyCommand.Name.TrimEnd(".Tests.ps1") -Describe "$functionName" -Tag 'Unit' { - Mock Get-Command { - "Mocked Command Response" - } - - Context "Behavior testing" { - It "should call get-command on VMware.VimAutomation.Vmc" { - { Get-VMCCommand } | Should Not Throw - Assert-MockCalled -CommandName Get-command -Times 1 -Scope It -ParameterFilter { $Module -eq 'VMware.VimAutomation.Vmc' } +inModuleScope VMware.VMC { + $functionName = "Get-VMCCommand" + Describe "$functionName" -Tag 'Unit' { + Mock Get-Command { + "Mocked Command Response" } - It "should call get-command on VMware.Vmc" { - { Get-VMCCommand } | Should Not Throw - Assert-MockCalled -CommandName Get-command -Times 1 -Scope It -ParameterFilter { $Module -eq 'VMware.VMC' } + + Context "Behavior testing" { + It "should call get-command on VMware.VimAutomation.Vmc" { + { Get-VMCCommand } | Should Not Throw + Assert-MockCalled -CommandName Get-command -Times 1 -Scope It -ParameterFilter { $Module -eq 'VMware.VimAutomation.Vmc' } + + } + It "should call get-command on VMware.Vmc" { + { Get-VMCCommand } | Should Not Throw + Assert-MockCalled -CommandName Get-command -Times 1 -Scope It -ParameterFilter { $Module -eq 'VMware.VMC' } + } } } } \ No newline at end of file diff --git a/Pester/Functions/Get-VMCOrg.tests.ps1 b/Pester/Functions/Get-VMCOrg.tests.ps1 index 0726f5a..983703e 100644 --- a/Pester/Functions/Get-VMCOrg.tests.ps1 +++ b/Pester/Functions/Get-VMCOrg.tests.ps1 @@ -1,73 +1,75 @@ #Requires -Modules Pester, VMware.VMC -$functionName = $MyInvocation.MyCommand.Name.TrimEnd(".Tests.ps1") Import-Module -Name VMware.VimAutomation.Cis.Core -Describe "$functionName" -Tag 'Unit' { - . "$PSScriptRoot/Shared.ps1" +inModuleScope VMware.VMC { + $functionName = "Get-VMCOrg" + Describe "$functionName" -Tag 'Unit' { + . "$PSScriptRoot/Shared.ps1" - $global:DefaultVMCServers = $true + $global:DefaultVMCServers = $true - $display_name = "MockedDisplayName" - $user_name = "MockedUserName" - $OrgName = "MockedDisplayName" - $created = "MockedDate" - $id = "MockedId" - $Service = "com.vmware.vmc.orgs" + $display_name = "MockedDisplayName" + $user_name = "MockedUserName" + $OrgName = "MockedDisplayName" + $created = "MockedDate" + $id = "MockedId" + $Service = "com.vmware.vmc.orgs" - $MockedList = [PSCustomObject]@{ - "display_name" = $display_name - "name" = $OrgName - "created" = $created - "user_name" = $user_name - "id" = $id - } - - $object = [PSCustomObject]@{} - $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } - - $MockedArray = @($MockedList, $MockedList) - - Mock -CommandName Get-VMCService -MockWith { $object } - - Context "Sanity checking" { - $command = Get-Command -Name $functionName - - defParam $command 'Name' - } - - Context "Behavior testing" { - - It "calls get-service to com.vmware.vmc.orgs" { - { Get-VMCOrg -name $OrgName } | Should Not Throw - Assert-MockCalled -CommandName Get-VMCService -Times 1 -Scope It -ParameterFilter { $name -eq $Service } + $MockedList = [PSCustomObject]@{ + "display_name" = $display_name + "name" = $OrgName + "created" = $created + "user_name" = $user_name + "id" = $id } - # Testing a single SDDC response - It "gets the orgs via list method and returns the properties" { - $object = [PSCustomObject]@{} - $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } - $(Get-VMCOrg -name $OrgName).display_name | Should -be $display_name - $(Get-VMCOrg -name $OrgName).name | Should -be $OrgName - $(Get-VMCOrg -name $OrgName).user_name | Should -be $user_name - $(Get-VMCOrg -name $OrgName).created | Should -be $created - $(Get-VMCOrg -name $OrgName).id | Should -be $id + + $object = [PSCustomObject]@{} + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } + + $MockedArray = @($MockedList, $MockedList) + + Mock -CommandName Get-VMCService -MockWith { $object } + + Context "Sanity checking" { + $command = Get-Command -Name $functionName + + defParam $command 'Name' } - # Testing the multiple SDDC response - It "calls the Connect-CisServer" { - $object = [PSCustomObject]@{} - $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedArray } - { Get-VMCOrg -name $OrgName } | Should Not Throw - $(Get-VMCOrg -name $OrgName)[0].display_name | Should -be $display_name - $(Get-VMCOrg -name $OrgName)[0].name | Should -be $OrgName - $(Get-VMCOrg -name $OrgName)[0].user_name | Should -be $user_name - $(Get-VMCOrg -name $OrgName)[0].created | Should -be $created - $(Get-VMCOrg -name $OrgName)[0].id | Should -be $id + Context "Behavior testing" { - $(Get-VMCOrg -name $OrgName)[1].display_name | Should -be $display_name - $(Get-VMCOrg -name $OrgName)[1].name | Should -be $OrgName - $(Get-VMCOrg -name $OrgName)[1].user_name | Should -be $user_name - $(Get-VMCOrg -name $OrgName)[1].created | Should -be $created - $(Get-VMCOrg -name $OrgName)[1].id | Should -be $id + It "calls get-service to com.vmware.vmc.orgs" { + { Get-VMCOrg -name $OrgName } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCService -Times 1 -Scope It -ParameterFilter { $name -eq $Service } + } + # Testing a single SDDC response + It "gets the orgs via list method and returns the properties" { + $object = [PSCustomObject]@{} + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } + $(Get-VMCOrg -name $OrgName).display_name | Should -be $display_name + $(Get-VMCOrg -name $OrgName).name | Should -be $OrgName + $(Get-VMCOrg -name $OrgName).user_name | Should -be $user_name + $(Get-VMCOrg -name $OrgName).created | Should -be $created + $(Get-VMCOrg -name $OrgName).id | Should -be $id + } + # Testing the multiple SDDC response + It "calls the Connect-CisServer" { + $object = [PSCustomObject]@{} + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedArray } + { Get-VMCOrg -name $OrgName } | Should Not Throw + + $(Get-VMCOrg -name $OrgName)[0].display_name | Should -be $display_name + $(Get-VMCOrg -name $OrgName)[0].name | Should -be $OrgName + $(Get-VMCOrg -name $OrgName)[0].user_name | Should -be $user_name + $(Get-VMCOrg -name $OrgName)[0].created | Should -be $created + $(Get-VMCOrg -name $OrgName)[0].id | Should -be $id + + $(Get-VMCOrg -name $OrgName)[1].display_name | Should -be $display_name + $(Get-VMCOrg -name $OrgName)[1].name | Should -be $OrgName + $(Get-VMCOrg -name $OrgName)[1].user_name | Should -be $user_name + $(Get-VMCOrg -name $OrgName)[1].created | Should -be $created + $(Get-VMCOrg -name $OrgName)[1].id | Should -be $id + } } } -} +} \ No newline at end of file diff --git a/Pester/Functions/Get-VmcSddc.tests.ps1 b/Pester/Functions/Get-VmcSddc.tests.ps1 index de27e79..3bc7d09 100644 --- a/Pester/Functions/Get-VmcSddc.tests.ps1 +++ b/Pester/Functions/Get-VmcSddc.tests.ps1 @@ -1,80 +1,82 @@ #Requires -Modules Pester, VMware.VMC -$functionName = $MyInvocation.MyCommand.Name.TrimEnd(".Tests.ps1") Import-Module -Name VMware.VimAutomation.Cis.Core -Describe "$functionName" -Tag 'Unit' { - . "$PSScriptRoot/Shared.ps1" +inModuleScope VMware.VMC { + $functionName ="Get-VmcSddc" + Describe "$functionName" -Tag 'Unit' { + . "$PSScriptRoot/Shared.ps1" - $global:DefaultVMCServers = $true + $global:DefaultVMCServers = $true - $OrgId = "Mocked OrgID" - $name = "MockedSDDCName" - $Notname = "NotTheName" - $Service = "com.vmware.vmc.orgs.sddcs" + $OrgId = "Mocked OrgID" + $name = "MockedSDDCName" + $Notname = "NotTheName" + $Service = "com.vmware.vmc.orgs.sddcs" - $MockedList = [PSCustomObject]@{ - "name" = $name - } - $MockedList2 = [PSCustomObject]@{ - "name" = $Notname - } - - $object = @( - @{"Id" = 1} - ) - $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } - - $MockedArray = @($MockedList, $MockedList2) - - Mock -CommandName Get-VMCService -MockWith { $object } - - Mock -CommandName Get-VMCOrg { $object } - - Context "Sanity checking" { - $command = Get-Command -Name $functionName - - defParam $command 'Name' - defParam $command 'Org' - } - - Context "Behavior testing" { - - It "calls Get-VMCOrg" { - { Get-VMCSDDC -Org $OrgId } | Should Not Throw - Assert-MockCalled -CommandName Get-VMCOrg -Times 1 -Scope It + $MockedList = [PSCustomObject]@{ + "name" = $name } - It "calls Get-VMCOrg with the SDDC name supplied" { - { Get-VMCSDDC -Org $OrgId -name $name} | Should Not Throw - Assert-MockCalled -CommandName Get-VMCOrg -Times 1 -Scope It -ParameterFilter { $name -eq $name } - } - # Testing with single "Org" so assert call twice. - It "calls get-service to com.vmware.vmc.orgs.sddcs" { - { Get-VMCSDDC -Org $OrgId } | Should Not Throw - Assert-MockCalled -CommandName Get-VMCService -Times 1 -Scope It -ParameterFilter { $name -eq $Service } + $MockedList2 = [PSCustomObject]@{ + "name" = $Notname } - # Testing with two "Orgs" so assert call twice. - It "calls get-service to com.vmware.vmc.orgs.sddcs" { - $object = @( - @{"Id" = 1} - @{"Id" = 2} - ) - $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedArray } - { Get-VMCSDDC -Org $OrgId } | Should Not Throw - Assert-MockCalled -CommandName Get-VMCService -Times 2 -Scope It -ParameterFilter { $name -eq $Service } + $object = @( + @{"Id" = 1} + ) + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } + + $MockedArray = @($MockedList, $MockedList2) + + Mock -CommandName Get-VMCService -MockWith { $object } + + Mock -CommandName Get-VMCOrg { $object } + + Context "Sanity checking" { + $command = Get-Command -Name $functionName + + defParam $command 'Name' + defParam $command 'Org' } - # Testing a single SDDC response - It "gets the SDDC details via list method and returns the properties" { - $object = [PSCustomObject]@{} - $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } - $(Get-VMCSDDC -Org $OrgId).name | Should -be $name - } - # Testing the multiple SDDC response - It "gets the SDDC details of the SDDC supplied and returns the properties" { - $object = @{} - $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedArray } - $(Get-VMCSDDC -Org $OrgId -name $name).name | Should -be $name + Context "Behavior testing" { + + It "calls Get-VMCOrg" { + { Get-VMCSDDC -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCOrg -Times 1 -Scope It + } + It "calls Get-VMCOrg with the SDDC name supplied" { + { Get-VMCSDDC -Org $OrgId -name $name} | Should Not Throw + Assert-MockCalled -CommandName Get-VMCOrg -Times 1 -Scope It -ParameterFilter { $name -eq $name } + } + # Testing with single "Org" so assert call twice. + It "calls get-service to com.vmware.vmc.orgs.sddcs" { + { Get-VMCSDDC -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCService -Times 1 -Scope It -ParameterFilter { $name -eq $Service } + } + + # Testing with two "Orgs" so assert call twice. + It "calls get-service to com.vmware.vmc.orgs.sddcs" { + $object = @( + @{"Id" = 1} + @{"Id" = 2} + ) + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedArray } + { Get-VMCSDDC -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCService -Times 2 -Scope It -ParameterFilter { $name -eq $Service } + } + + # Testing a single SDDC response + It "gets the SDDC details via list method and returns the properties" { + $object = [PSCustomObject]@{} + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } + $(Get-VMCSDDC -Org $OrgId).name | Should -be $name + } + # Testing the multiple SDDC response + It "gets the SDDC details of the SDDC supplied and returns the properties" { + $object = @{} + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedArray } + $(Get-VMCSDDC -Org $OrgId -name $name).name | Should -be $name + } } } -} +} \ No newline at end of file diff --git a/Pester/Functions/Get-VmcTask.tests.ps1 b/Pester/Functions/Get-VmcTask.tests.ps1 index f54e944..0ee9f19 100644 --- a/Pester/Functions/Get-VmcTask.tests.ps1 +++ b/Pester/Functions/Get-VmcTask.tests.ps1 @@ -1,78 +1,80 @@ #Requires -Modules Pester, VMware.VMC -$functionName = $MyInvocation.MyCommand.Name.TrimEnd(".Tests.ps1") Import-Module -Name VMware.VimAutomation.Cis.Core -Describe "$functionName" -Tag 'Unit' { - . "$PSScriptRoot/Shared.ps1" +inModuleScope VMware.VMC { + $functionName = "Get-VMCTask" + Describe "$functionName" -Tag 'Unit' { + . "$PSScriptRoot/Shared.ps1" - $global:DefaultVMCServers = $true + $global:DefaultVMCServers = $true - $OrgId = "Mocked OrgID" - $name = "MockedSDDCName" - $Notname = "NotTheName" - $id = "MockedId" - $Service = "com.vmware.vmc.orgs.tasks" + $OrgId = "Mocked OrgID" + $name = "MockedSDDCName" + $Notname = "NotTheName" + $id = "MockedId" + $Service = "com.vmware.vmc.orgs.tasks" - $MockedList = [PSCustomObject]@{ - "name" = $name - } - $MockedList2 = [PSCustomObject]@{ - "name" = $Notname - } - - $object = @( - @{"Id" = $Id} - ) - $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } - - $MockedArray = @($MockedList, $MockedList2) - - Mock -CommandName Get-VMCService -MockWith { $object } - - Mock -CommandName Get-VMCOrg { $object } - - Context "Sanity checking" { - $command = Get-Command -Name $functionName - - defParam $command 'Org' - } - - Context "Behavior testing" { - - It "calls Get-VMCOrg with the Org name supplied" { - { Get-VMCTask -Org $name} | Should Not Throw - Assert-MockCalled -CommandName Get-VMCOrg -Times 1 -Scope It -ParameterFilter { $name -eq $name } + $MockedList = [PSCustomObject]@{ + "name" = $name + } + $MockedList2 = [PSCustomObject]@{ + "name" = $Notname } - # Testing with single "Org" so assert call twice. - It "calls get-service to com.vmware.vmc.orgs.tasks" { - { Get-VMCTask -Org $OrgId } | Should Not Throw - Assert-MockCalled -CommandName Get-VMCService -Times 1 -Scope It -ParameterFilter { $name -eq $Service } + $object = @( + @{"Id" = $Id} + ) + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } + + $MockedArray = @($MockedList, $MockedList2) + + Mock -CommandName Get-VMCService -MockWith { $object } + + Mock -CommandName Get-VMCOrg { $object } + + Context "Sanity checking" { + $command = Get-Command -Name $functionName + + defParam $command 'Org' } - # Testing with two "Orgs" so assert call twice. - It "calls get-service to com.vmware.vmc.orgs.tasks" { - $object = @( - @{"Id" = 1} - @{"Id" = 2} - ) - $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedArray } - { Get-VMCTask -Org $OrgId } | Should Not Throw - Assert-MockCalled -CommandName Get-VMCService -Times 2 -Scope It -ParameterFilter { $name -eq $Service } - } + Context "Behavior testing" { - # Testing a single SDDC response - It "gets the task details via list method and returns the properties" { - $object = [PSCustomObject]@{} - $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } - $(Get-VMCTask -Org $OrgId).name | Should -be $name - } - # Testing the multiple SDDC response - It "gets the task details of the SDDC supplied and returns the properties" { - $object = @{} - $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedArray } - $(Get-VMCTask -Org $OrgId)[0].name | Should -be $name - $(Get-VMCTask -Org $OrgId)[1].name | Should -be $Notname + It "calls Get-VMCOrg with the Org name supplied" { + { Get-VMCTask -Org $name} | Should Not Throw + Assert-MockCalled -CommandName Get-VMCOrg -Times 1 -Scope It -ParameterFilter { $name -eq $name } + } + + # Testing with single "Org" so assert call twice. + It "calls get-service to com.vmware.vmc.orgs.tasks" { + { Get-VMCTask -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCService -Times 1 -Scope It -ParameterFilter { $name -eq $Service } + } + + # Testing with two "Orgs" so assert call twice. + It "calls get-service to com.vmware.vmc.orgs.tasks" { + $object = @( + @{"Id" = 1} + @{"Id" = 2} + ) + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedArray } + { Get-VMCTask -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCService -Times 2 -Scope It -ParameterFilter { $name -eq $Service } + } + + # Testing a single SDDC response + It "gets the task details via list method and returns the properties" { + $object = [PSCustomObject]@{} + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } + $(Get-VMCTask -Org $OrgId).name | Should -be $name + } + # Testing the multiple SDDC response + It "gets the task details of the SDDC supplied and returns the properties" { + $object = @{} + $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedArray } + $(Get-VMCTask -Org $OrgId)[0].name | Should -be $name + $(Get-VMCTask -Org $OrgId)[1].name | Should -be $Notname + } } } -} +} \ No newline at end of file From b5111e1fab1fa2c919556c7adcad4f8e6b373d8c Mon Sep 17 00:00:00 2001 From: Conor Tolan Date: Sat, 23 Feb 2019 19:33:24 +0000 Subject: [PATCH 09/42] Adding a VMC code coverage script to invoke the coverage report. --- Pester/VMCCode-Coverage.ps1 | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 Pester/VMCCode-Coverage.ps1 diff --git a/Pester/VMCCode-Coverage.ps1 b/Pester/VMCCode-Coverage.ps1 new file mode 100644 index 0000000..28aa114 --- /dev/null +++ b/Pester/VMCCode-Coverage.ps1 @@ -0,0 +1,4 @@ +Remove-Module VMware.VMC +import-module ../Modules/VMware.VMC/VMware.VMC.psm1 + +invoke-pester ./Functions -CodeCoverage ..\Modules\VMware.VMC\VMware.VMC.psm1 \ No newline at end of file From 2bb82249cab5cd86a2ba46deabd0554139e62830 Mon Sep 17 00:00:00 2001 From: Conor Tolan Date: Sun, 24 Feb 2019 14:41:16 +0000 Subject: [PATCH 10/42] Added new tests for get default creds Added test for not connected route in functions to increase coverage. --- .../Functions/Connect-VMCVIServer.tests.ps1 | 7 ++ Pester/Functions/Get-VMCOrg.tests.ps1 | 17 +++- .../Get-VMCSDDCDefaultCredential.tests.ps1 | 98 +++++++++++++++++++ Pester/Functions/Get-VmcSddc.tests.ps1 | 7 ++ Pester/Functions/Get-VmcTask.tests.ps1 | 7 ++ 5 files changed, 131 insertions(+), 5 deletions(-) create mode 100644 Pester/Functions/Get-VMCSDDCDefaultCredential.tests.ps1 diff --git a/Pester/Functions/Connect-VMCVIServer.tests.ps1 b/Pester/Functions/Connect-VMCVIServer.tests.ps1 index b8d87f0..a98a277 100644 --- a/Pester/Functions/Connect-VMCVIServer.tests.ps1 +++ b/Pester/Functions/Connect-VMCVIServer.tests.ps1 @@ -30,6 +30,8 @@ inModuleScope VMware.VMC { Mock Connect-CisServer {} + Mock Write-Error + Context "Sanity checking" { $command = Get-Command -Name $functionName @@ -57,6 +59,11 @@ inModuleScope VMware.VMC { -and $User -eq $cloud_username ` -and $Password -eq $Mockedcreds.password } } + It "gets writes an error if not connected" { + $global:DefaultVMCServers = $false + { Connect-VMCVIServer -org $Org -Sddc $Sddc } | Should Not Throw + Assert-MockCalled -CommandName Write-Error -Times 1 -Scope It -ParameterFilter { $org -eq $Org -and $Sddc -eq $Sddc } + } } } } \ No newline at end of file diff --git a/Pester/Functions/Get-VMCOrg.tests.ps1 b/Pester/Functions/Get-VMCOrg.tests.ps1 index 983703e..2a8c589 100644 --- a/Pester/Functions/Get-VMCOrg.tests.ps1 +++ b/Pester/Functions/Get-VMCOrg.tests.ps1 @@ -30,6 +30,8 @@ inModuleScope VMware.VMC { Mock -CommandName Get-VMCService -MockWith { $object } + Mock -CommandName Write-Error -MockWith {} + Context "Sanity checking" { $command = Get-Command -Name $functionName @@ -46,11 +48,11 @@ inModuleScope VMware.VMC { It "gets the orgs via list method and returns the properties" { $object = [PSCustomObject]@{} $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedList } - $(Get-VMCOrg -name $OrgName).display_name | Should -be $display_name - $(Get-VMCOrg -name $OrgName).name | Should -be $OrgName - $(Get-VMCOrg -name $OrgName).user_name | Should -be $user_name - $(Get-VMCOrg -name $OrgName).created | Should -be $created - $(Get-VMCOrg -name $OrgName).id | Should -be $id + $(Get-VMCOrg).display_name | Should -be $display_name + $(Get-VMCOrg).name | Should -be $OrgName + $(Get-VMCOrg).user_name | Should -be $user_name + $(Get-VMCOrg).created | Should -be $created + $(Get-VMCOrg).id | Should -be $id } # Testing the multiple SDDC response It "calls the Connect-CisServer" { @@ -70,6 +72,11 @@ inModuleScope VMware.VMC { $(Get-VMCOrg -name $OrgName)[1].created | Should -be $created $(Get-VMCOrg -name $OrgName)[1].id | Should -be $id } + It "gets writes an error if not connected" { + $global:DefaultVMCServers = $false + { Get-VMCOrg -name $OrgName } | Should Not Throw + Assert-MockCalled -CommandName Write-Error -Times 1 -Scope It -ParameterFilter { $org -eq $Org -and $Sddc -eq $Sddc } + } } } } \ No newline at end of file diff --git a/Pester/Functions/Get-VMCSDDCDefaultCredential.tests.ps1 b/Pester/Functions/Get-VMCSDDCDefaultCredential.tests.ps1 new file mode 100644 index 0000000..c0a1393 --- /dev/null +++ b/Pester/Functions/Get-VMCSDDCDefaultCredential.tests.ps1 @@ -0,0 +1,98 @@ +#Requires -Modules Pester, VMware.VMC +Import-Module -Name VMware.VimAutomation.Cis.Core + +inModuleScope VMware.VMC { + $functionName = "Get-VMCSDDCDefaultCredential" + Describe "$functionName" -Tag 'Unit' { + . "$PSScriptRoot/Shared.ps1" + + $global:DefaultVMCServers = $true + + $OrgId = "Mocked OrgID" + $SddcName = "MockedSDDCName" + $vc_url = "Mockedvc_url" + $vc_management_ip = "MockedVCmanage_ip" + $vc_public_ip = "MockedVCpublic_ip" + $cloud_username = "MockedCloudUser" + $cloud_password = "MockedCloudPass" + + $MockedList = [PSCustomObject]@{ + "vc_url" = $vc_url + "vc_management_ip" = $vc_management_ip + "vc_public_ip" = $vc_public_ip + "cloud_username" = $cloud_username + "cloud_password" = $cloud_password + } + $MockedList2 = [PSCustomObject]@{ + "vc_url" = $vc_url + "vc_management_ip" = $vc_management_ip + "vc_public_ip" = $vc_public_ip + "cloud_username" = $cloud_username + "cloud_password" = $cloud_password + } + + $object = [PSCustomObject]@{ + "resource_config" = @($MockedList) + } + + $MockedArray = @{ + "resource_config" = @($MockedList, $MockedList2) + } + + Mock -CommandName Get-VMCSDDC -MockWith { $object } + + Mock -CommandName Write-Error -MockWith {} + + Mock -CommandName Select-Object { $MockedList } + + Context "Sanity checking" { + $command = Get-Command -Name $functionName + + defParam $command 'Org' + defParam $command 'Sddc' + } + + Context "Behavior testing" { + # Testing single Org with optional SDDC parameter + It "calls Get-VMCSDDC with the Org name supplied" { + { Get-VMCSDDCDefaultCredential -Org $OrgId -sddc $SddcName} | Should Not Throw + Assert-MockCalled -CommandName Get-VMCSDDC -Times 1 -Scope It -ParameterFilter { $Org -eq $OrgId -and $name -eq $SddcName } + } + # Testing single Org without SDDC parameter. + It "calls get-VMCSDDC without SDDC name supplied" { + { Get-VMCSDDCDefaultCredential -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCSDDC -Times 1 -Scope It -ParameterFilter { $org -eq $OrgId } + } + # Testing a single SDDC response + It "gets the task details via list method and returns the properties" { + $(Get-VMCSDDCDefaultCredential -Org $OrgId).vc_url | Should -be $vc_url + $(Get-VMCSDDCDefaultCredential -Org $OrgId).vc_management_ip | Should -be $vc_management_ip + $(Get-VMCSDDCDefaultCredential -Org $OrgId).vc_public_ip | Should -be $vc_public_ip + $(Get-VMCSDDCDefaultCredential -Org $OrgId).cloud_username | Should -be $cloud_username + $(Get-VMCSDDCDefaultCredential -Org $OrgId).cloud_password | Should -be $cloud_password + Assert-MockCalled -CommandName Select-Object -Times 1 -Scope It + } + # Testing the multiple SDDC response + It "gets the task details of the Org supplied and returns the properties" { + Mock -CommandName Get-VMCSDDC -MockWith { $MockedArray } + $(Get-VMCSDDCDefaultCredential -Org $OrgId)[0].vc_url | Should -be $vc_url + $(Get-VMCSDDCDefaultCredential -Org $OrgId)[0].vc_management_ip | Should -be $vc_management_ip + $(Get-VMCSDDCDefaultCredential -Org $OrgId)[0].vc_public_ip | Should -be $vc_public_ip + $(Get-VMCSDDCDefaultCredential -Org $OrgId)[0].cloud_username | Should -be $cloud_username + $(Get-VMCSDDCDefaultCredential -Org $OrgId)[0].cloud_password | Should -be $cloud_password + + $(Get-VMCSDDCDefaultCredential -Org $OrgId)[1].vc_url | Should -be $vc_url + $(Get-VMCSDDCDefaultCredential -Org $OrgId)[1].vc_management_ip | Should -be $vc_management_ip + $(Get-VMCSDDCDefaultCredential -Org $OrgId)[1].vc_public_ip | Should -be $vc_public_ip + $(Get-VMCSDDCDefaultCredential -Org $OrgId)[1].cloud_username | Should -be $cloud_username + $(Get-VMCSDDCDefaultCredential -Org $OrgId)[1].cloud_password | Should -be $cloud_password + Assert-MockCalled -CommandName Select-Object -Times 2 -Scope It + } + It "writes an error if not connected" { + $global:DefaultVMCServers = $false + { Get-VMCSDDCDefaultCredential -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Write-Error -Times 1 -Scope It -ParameterFilter { $org -eq $Org -and $Sddc -eq $Sddc } + } + } + } +} \ No newline at end of file diff --git a/Pester/Functions/Get-VmcSddc.tests.ps1 b/Pester/Functions/Get-VmcSddc.tests.ps1 index 3bc7d09..f5182b9 100644 --- a/Pester/Functions/Get-VmcSddc.tests.ps1 +++ b/Pester/Functions/Get-VmcSddc.tests.ps1 @@ -31,6 +31,8 @@ inModuleScope VMware.VMC { Mock -CommandName Get-VMCOrg { $object } + Mock -CommandName Write-Error -MockWith {} + Context "Sanity checking" { $command = Get-Command -Name $functionName @@ -77,6 +79,11 @@ inModuleScope VMware.VMC { $object | Add-Member -MemberType ScriptMethod -Name "list" -Value { $MockedArray } $(Get-VMCSDDC -Org $OrgId -name $name).name | Should -be $name } + It "gets writes an error if not connected" { + $global:DefaultVMCServers = $false + { Get-VMCSDDC -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Write-Error -Times 1 -Scope It -ParameterFilter { $org -eq $Org -and $Sddc -eq $Sddc } + } } } } \ No newline at end of file diff --git a/Pester/Functions/Get-VmcTask.tests.ps1 b/Pester/Functions/Get-VmcTask.tests.ps1 index 0ee9f19..5f0ab11 100644 --- a/Pester/Functions/Get-VmcTask.tests.ps1 +++ b/Pester/Functions/Get-VmcTask.tests.ps1 @@ -32,6 +32,8 @@ inModuleScope VMware.VMC { Mock -CommandName Get-VMCOrg { $object } + Mock -CommandName Write-Error -MockWith {} + Context "Sanity checking" { $command = Get-Command -Name $functionName @@ -75,6 +77,11 @@ inModuleScope VMware.VMC { $(Get-VMCTask -Org $OrgId)[0].name | Should -be $name $(Get-VMCTask -Org $OrgId)[1].name | Should -be $Notname } + It "gets writes an error if not connected" { + $global:DefaultVMCServers = $false + { Get-VMCTask -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Write-Error -Times 1 -Scope It -ParameterFilter { $org -eq $Org -and $Sddc -eq $Sddc } + } } } } \ No newline at end of file From c01427f6f4a75c83fd5c271ccb0d856332ef74fd Mon Sep 17 00:00:00 2001 From: Conor Tolan Date: Sun, 24 Feb 2019 16:06:47 +0000 Subject: [PATCH 11/42] Added new tests. --- .../Functions/Get-VMCSDDCPublicIP.tests.ps1 | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 Pester/Functions/Get-VMCSDDCPublicIP.tests.ps1 diff --git a/Pester/Functions/Get-VMCSDDCPublicIP.tests.ps1 b/Pester/Functions/Get-VMCSDDCPublicIP.tests.ps1 new file mode 100644 index 0000000..16c2e15 --- /dev/null +++ b/Pester/Functions/Get-VMCSDDCPublicIP.tests.ps1 @@ -0,0 +1,72 @@ +#Requires -Modules Pester, VMware.VMC +Import-Module -Name VMware.VimAutomation.Cis.Core + +inModuleScope VMware.VMC { + $functionName = "Get-VMCSDDCPublicIP" + Describe "$functionName" -Tag 'Unit' { + . "$PSScriptRoot/Shared.ps1" + + $global:DefaultVMCServers = $true + + $OrgId = "Mocked OrgID" + $SddcName = "MockedSDDCName" + $public_ip_pool = "MockedPublic_ip_pool" + + $MockedList = [PSCustomObject]@{ + "public_ip_pool" = $public_ip_pool + } + $MockedList2 = [PSCustomObject]@{ + "public_ip_pool" = $public_ip_pool + } + + $object = [PSCustomObject]@{ + "resource_config" = @($MockedList) + } + + $MockedArray = @{ + "resource_config" = @($MockedList, $MockedList2) + } + + Mock -CommandName Get-VMCSDDC -MockWith { $object } + + Mock -CommandName Write-Error -MockWith {} + + Context "Sanity checking" { + $command = Get-Command -Name $functionName + + defParam $command 'Org' + defParam $command 'Sddc' + } + + Context "Behavior testing" { + # Testing single Org with optional SDDC parameter + It "calls Get-VMCSDDC with the Org name supplied" { + { Get-VMCSDDCPublicIP -Org $OrgId -sddc $SddcName} | Should Not Throw + Assert-MockCalled -CommandName Get-VMCSDDC -Times 1 -Scope It -ParameterFilter { $Org -eq $OrgId -and $name -eq $SddcName } + } + # Testing single Org without SDDC parameter. + It "calls get-VMCSDDC without SDDC name supplied" { + { Get-VMCSDDCPublicIP -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCSDDC -Times 1 -Scope It -ParameterFilter { $org -eq $OrgId } + } + # Testing a single SDDC response + It "gets the task details via list method and returns the properties" { + $(Get-VMCSDDCPublicIP -Org $OrgId) | Should -be $Public_ip_pool + #Assert-MockCalled -CommandName Select-Object -Times 1 -Scope It + } + # Testing the multiple SDDC response + It "gets the task details of the Org supplied and returns the properties" { + Mock -CommandName Get-VMCSDDC -MockWith { $MockedArray } + $(Get-VMCSDDCPublicIP -Org $OrgId)[0] | Should -be $Public_ip_pool + + $(Get-VMCSDDCPublicIP -Org $OrgId)[1] | Should -be $Public_ip_pool + #Assert-MockCalled -CommandName Select-Object -Times 2 -Scope It + } + It "writes an error if not connected" { + $global:DefaultVMCServers = $false + { Get-VMCSDDCPublicIP -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Write-Error -Times 1 -Scope It -ParameterFilter { $org -eq $Org -and $Sddc -eq $Sddc } + } + } + } +} \ No newline at end of file From f926508d1f9386f637362fa22a4c16c4757cead7 Mon Sep 17 00:00:00 2001 From: Conor Tolan Date: Mon, 25 Feb 2019 21:09:18 +0000 Subject: [PATCH 12/42] Added test for Get-VMCVMHost, complicated object mocking. --- Pester/Functions/Get-VMCHost.tests.ps1 | 88 ++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 Pester/Functions/Get-VMCHost.tests.ps1 diff --git a/Pester/Functions/Get-VMCHost.tests.ps1 b/Pester/Functions/Get-VMCHost.tests.ps1 new file mode 100644 index 0000000..40bde0c --- /dev/null +++ b/Pester/Functions/Get-VMCHost.tests.ps1 @@ -0,0 +1,88 @@ +#Requires -Modules Pester, VMware.VMC +Import-Module -Name VMware.VimAutomation.Cis.Core + +inModuleScope VMware.VMC { + $functionName = "Get-VMCVMHost" + Describe "$functionName" -Tag 'Unit' { + . "$PSScriptRoot/Shared.ps1" + + $global:DefaultVMCServers = $true + + $OrgId = "Mocked OrgID" + $SddcId = "MockedSDDCName" + $VMhostName = "Mockedvc_url" + $VMHost_name = "MockedVCmanage_ip" + $esx_state = "MockedVCpublic_ip" + $esx_id = "Mocked_esx_id" + + $object = @([PSCustomObject]@{ + "resource_config" = @{ + esx_hosts = @(@{ + esx_id = $esx_id + name = $VMHost_name + hostname = $VMhostName + esx_state = $esx_state + }) + } + "id" = $SddcId + "Org_Id" = $OrgId + }) + + $MockedArray = @($object, $object) + + Mock -CommandName Get-VMCSDDC -MockWith { $object } + + Mock -CommandName Write-Error -MockWith {} + + Context "Sanity checking" { + $command = Get-Command -Name $functionName + + defParam $command 'Org' + defParam $command 'Sddc' + } + + Context "Behavior testing" { + # Testing single Org with optional SDDC parameter + It "calls Get-VMCVMHost with the Org name supplied" { + { Get-VMCVMHost -Org $OrgId -sddc $SddcName} | Should Not Throw + Assert-MockCalled -CommandName Get-VMCSDDC -Times 1 -Scope It -ParameterFilter { $Org -eq $OrgId -and $name -eq $SddcName } + } + # Testing single Org without SDDC parameter. + It "calls get-VMCVMHost without SDDC name supplied" { + { Get-VMCVMHost -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCSDDC -Times 1 -Scope It -ParameterFilter { $org -eq $OrgId } + } + # Testing a single SDDC response + It "gets the task details via list method and returns the properties" { + $(Get-VMCVMHost -Org $OrgId).esx_id | Should -be "Mocked_esx_id"#$esx_id + $(Get-VMCVMHost -Org $OrgId).name | Should -be $VMHost_name + $(Get-VMCVMHost -Org $OrgId).hostname | Should -be $VMhostName + $(Get-VMCVMHost -Org $OrgId).esx_state | Should -be $esx_state + $(Get-VMCVMHost -Org $OrgId).sddc_id | Should -be $SddcId + $(Get-VMCVMHost -Org $OrgId).org_id | Should -be $OrgId + } + # Testing the multiple SDDC response + It "gets the task details of the Org supplied and returns the properties" { + Mock -CommandName Get-VMCSDDC -MockWith { $MockedArray } + $(Get-VMCVMHost -Org $OrgId)[0].esx_id | Should -be $esx_id + $(Get-VMCVMHost -Org $OrgId)[0].name | Should -be $VMHost_name + $(Get-VMCVMHost -Org $OrgId)[0].hostname | Should -be $VMhostName + $(Get-VMCVMHost -Org $OrgId)[0].esx_state | Should -be $esx_state + $(Get-VMCVMHost -Org $OrgId)[0].sddc_id | Should -be $SddcId + $(Get-VMCVMHost -Org $OrgId)[0].org_id | Should -be $OrgId + + $(Get-VMCVMHost -Org $OrgId)[1].esx_id | Should -be $esx_id + $(Get-VMCVMHost -Org $OrgId)[1].name | Should -be $VMHost_name + $(Get-VMCVMHost -Org $OrgId)[1].hostname | Should -be $VMhostName + $(Get-VMCVMHost -Org $OrgId)[1].esx_state | Should -be $esx_state + $(Get-VMCVMHost -Org $OrgId)[1].sddc_id | Should -be $SddcId + $(Get-VMCVMHost -Org $OrgId)[1].org_id | Should -be $OrgId + } + It "writes an error if not connected" { + $global:DefaultVMCServers = $false + { Get-VMCVMHost -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Write-Error -Times 1 -Scope It -ParameterFilter { $org -eq $Org -and $Sddc -eq $Sddc } + } + } + } +} \ No newline at end of file From 3e09f0a601f43ffae443b1f33f228e193f56c7f2 Mon Sep 17 00:00:00 2001 From: Conor Tolan Date: Mon, 25 Feb 2019 22:28:23 +0000 Subject: [PATCH 13/42] Wrote tests covering get VMC SDDC Version Fixed up get VMC Hosts a bit. --- Pester/Functions/Get-VMCHost.tests.ps1 | 2 +- Pester/Functions/Get-VMCSDDCVersion.tests.ps1 | 75 +++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 Pester/Functions/Get-VMCSDDCVersion.tests.ps1 diff --git a/Pester/Functions/Get-VMCHost.tests.ps1 b/Pester/Functions/Get-VMCHost.tests.ps1 index 40bde0c..921b2a0 100644 --- a/Pester/Functions/Get-VMCHost.tests.ps1 +++ b/Pester/Functions/Get-VMCHost.tests.ps1 @@ -54,7 +54,7 @@ inModuleScope VMware.VMC { } # Testing a single SDDC response It "gets the task details via list method and returns the properties" { - $(Get-VMCVMHost -Org $OrgId).esx_id | Should -be "Mocked_esx_id"#$esx_id + $(Get-VMCVMHost -Org $OrgId).esx_id | Should -be $esx_id $(Get-VMCVMHost -Org $OrgId).name | Should -be $VMHost_name $(Get-VMCVMHost -Org $OrgId).hostname | Should -be $VMhostName $(Get-VMCVMHost -Org $OrgId).esx_state | Should -be $esx_state diff --git a/Pester/Functions/Get-VMCSDDCVersion.tests.ps1 b/Pester/Functions/Get-VMCSDDCVersion.tests.ps1 new file mode 100644 index 0000000..52da5ee --- /dev/null +++ b/Pester/Functions/Get-VMCSDDCVersion.tests.ps1 @@ -0,0 +1,75 @@ +#Requires -Modules Pester, VMware.VMC +Import-Module -Name VMware.VimAutomation.Cis.Core + +inModuleScope VMware.VMC { + $functionName = "Get-VMCSDDCVersion" + Describe "$functionName" -Tag 'Unit' { + . "$PSScriptRoot/Shared.ps1" + + $global:DefaultVMCServers = $true + + $Service = "com.vmware.vmc.orgs.sddcs" + $OrgId = "Mocked OrgID" + $SddcName = "MockedSDDCName" + $version = "MockedVersion" + + $orgs = @( + [PSCustomObject]@{ + "Id" = $OrgId + "Org_Id" = $OrgId + }) + + $MockedServiceObj = [PSCustomObject]{} + + $ServicesObject = @([PSCustomObject]@{ + "resource_config" = @{ + sddc_manifest = [PSCustomObject]@{ + version = $version + } + } + }) + + Mock -CommandName Get-VMCOrg -MockWith { $orgs } + + Mock -CommandName Get-VMCService -MockWith { $MockedServiceObj } + + $MockedServiceObj | Add-Member -MemberType ScriptMethod -Name "list" -Value { $ServicesObject } + + Mock -CommandName Write-Error -MockWith {} + + Context "Sanity checking" { + $command = Get-Command -Name $functionName + + defParam $command 'Org' + defParam $command 'Name' + } + + Context "Behavior testing" { + # Testing single Org with optional SDDC parameter + It "calls Get-VMCSDDCVersion with the Org name supplied" { + { Get-VMCSDDCVersion -Org $OrgId -Name $SddcName} | Should Not Throw + Assert-MockCalled -CommandName Get-VMCOrg -Times 1 -Scope It -ParameterFilter { $Name -eq $OrgId } + } + It "calls get-service to com.vmware.vmc.orgs.sddcs" { + { Get-VMCSDDC -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCService -Times 1 -Scope It -ParameterFilter { $name -eq $Service } + } + # Testing a single SDDC response + It "gets the task details via list method and returns the properties" { + $(Get-VMCSDDCVersion -Org $OrgId).version | Should -be $version + } + # Testing the multiple SDDC response + It "gets the task details of the Org supplied and returns the properties" { + Mock -CommandName Get-VMCOrg -MockWith { @($orgs, $orgs) } + + $(Get-VMCSDDCVersion -Org $OrgId)[0].version | Should -be $version + $(Get-VMCSDDCVersion -Org $OrgId)[1].version | Should -be $version + } + It "writes an error if not connected" { + $global:DefaultVMCServers = $false + { Get-VMCSDDCVersion -Org $OrgId } | Should Not Throw + Assert-MockCalled -CommandName Write-Error -Times 1 -Scope It -ParameterFilter { $org -eq $Org -and $Sddc -eq $Sddc } + } + } + } +} \ No newline at end of file From bbc6d0f77550bdf688c25746df10db038b4f541c Mon Sep 17 00:00:00 2001 From: Conor Tolan Date: Wed, 27 Feb 2019 22:23:05 +0000 Subject: [PATCH 14/42] Started tests for VMCFirewall. Fixed incorrect function call in sddc version test. --- .../Functions/Get-VMCFirewallRule.tests.ps1 | 75 +++++++++++++++++++ Pester/Functions/Get-VMCSDDCVersion.tests.ps1 | 2 +- 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 Pester/Functions/Get-VMCFirewallRule.tests.ps1 diff --git a/Pester/Functions/Get-VMCFirewallRule.tests.ps1 b/Pester/Functions/Get-VMCFirewallRule.tests.ps1 new file mode 100644 index 0000000..b508dbd --- /dev/null +++ b/Pester/Functions/Get-VMCFirewallRule.tests.ps1 @@ -0,0 +1,75 @@ +#Requires -Modules Pester, VMware.VMC +Import-Module -Name VMware.VimAutomation.Cis.Core + +inModuleScope VMware.VMC { + $functionName = "Get-VMCFirewallRule" + Describe "$functionName" -Tag 'Unit' { + . "$PSScriptRoot/Shared.ps1" + + $global:DefaultVMCServers = $true + + $Service = "com.vmware.vmc.orgs.sddcs.networks.edges.firewall.config" + $OrgId = "Mocked OrgID" + $GatewayType = "MGW" + $SddcName = "MockedSDDCName" + $OrgName = "MockedOrgName" + $version = "MockedVersion" + + $orgs = @( + [PSCustomObject]@{ + "Id" = $OrgId + "Org_Id" = $OrgId + }) + + $MockedServiceObj = [PSCustomObject]{} + + $ServicesObject = @([PSCustomObject]@{ + "resource_config" = @{ + sddc_manifest = [PSCustomObject]@{ + version = $version + } + } + }) + + Mock -CommandName Get-VMCOrg -MockWith { $orgs } + Mock -CommandName Get-VMCSDDC -MockWith { $orgs } + + Mock -CommandName Get-VMCService -MockWith { $MockedServiceObj } + + $MockedServiceObj | Add-Member -MemberType ScriptMethod -Name "Get" -Value { $ServicesObject } + $MockedServiceObj | Add-Member -MemberType ScriptMethod -Name "list" -Value { $ServicesObject } + + Mock -CommandName Write-Error -MockWith {} + + Context "Sanity checking" { + $command = Get-Command -Name $functionName + + defParam $command 'OrgName' + defParam $command 'SDDCName' + defParam $command 'ShowAll' + defParam $command 'GatewayType' + } + + Context "Behavior testing" { + # Testing single Org with optional SDDC parameter + It "calls Get-VMCFirewallRule with the Org name supplied" { + { Get-VMCFirewallRule -GatewayType $GatewayType -SDDCName $SddcName -OrgName $OrgName} | Should Not Throw + Assert-MockCalled -CommandName Get-VMCOrg -Times 1 -Scope It #-ParameterFilter { $Name -eq $SddcName } + Assert-MockCalled -CommandName Get-VMCSDDC -Times 1 -Scope It -ParameterFilter { $Name -eq $SddcName -and $Org -eq $OrgName } + } + It "calls get-service to com.vmware.vmc.orgs.sddcs" { + { Get-VMCFirewallRule -GatewayType $GatewayType } | Should Not Throw + Assert-MockCalled -CommandName Get-VMCService -Times 1 -Scope It -ParameterFilter { $name -eq $Service } + } + # Testing a single SDDC response + It "gets the task details via list method and returns the properties" { + $(Get-VMCFirewallRule -GatewayType $GatewayType).version | Should -be $version + } + It "writes an error if not connected" { + $global:DefaultVMCServers = $false + { Get-VMCFirewallRule -GatewayType $GatewayType } | Should Not Throw + Assert-MockCalled -CommandName Write-Error -Times 1 -Scope It -ParameterFilter { $org -eq $Org -and $Sddc -eq $Sddc } + } + } + } +} \ No newline at end of file diff --git a/Pester/Functions/Get-VMCSDDCVersion.tests.ps1 b/Pester/Functions/Get-VMCSDDCVersion.tests.ps1 index 52da5ee..203801a 100644 --- a/Pester/Functions/Get-VMCSDDCVersion.tests.ps1 +++ b/Pester/Functions/Get-VMCSDDCVersion.tests.ps1 @@ -51,7 +51,7 @@ inModuleScope VMware.VMC { Assert-MockCalled -CommandName Get-VMCOrg -Times 1 -Scope It -ParameterFilter { $Name -eq $OrgId } } It "calls get-service to com.vmware.vmc.orgs.sddcs" { - { Get-VMCSDDC -Org $OrgId } | Should Not Throw + { Get-VMCSDDCVersion -Org $OrgId } | Should Not Throw Assert-MockCalled -CommandName Get-VMCService -Times 1 -Scope It -ParameterFilter { $name -eq $Service } } # Testing a single SDDC response From 1e7033a66fda46a904e8ffda1c9bfc71ca1fee79 Mon Sep 17 00:00:00 2001 From: William Lam Date: Sat, 7 Mar 2020 13:39:29 -0800 Subject: [PATCH 15/42] Add support for pagination for retrieving NSX-T Segments --- Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 | 48 ++++++++++++++++++-- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 index 649efe2..fd4c364 100644 --- a/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 +++ b/Modules/VMware.VMC.NSXT/VMware.VMC.NSXT.psm1 @@ -83,13 +83,14 @@ Function Get-NSXTSegment { If (-Not $global:nsxtProxyConnection) { Write-error "No NSX-T Proxy Connection found, please use Connect-NSXTProxy" } Else { $method = "GET" - $segmentsURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/tier-1s/cgw/segments" + $segmentsURL = $global:nsxtProxyConnection.Server + "/policy/api/v1/infra/tier-1s/cgw/segments?page_size=100" if($Troubleshoot) { Write-Host -ForegroundColor cyan "`n[DEBUG] - $METHOD`n$segmentsURL`n" } try { + Write-Host "Retrievig NSX-T Segments ..." if($PSVersionTable.PSEdition -eq "Core") { $requests = Invoke-WebRequest -Uri $segmentsURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck } else { @@ -107,14 +108,53 @@ Function Get-NSXTSegment { } if($requests.StatusCode -eq 200) { - $segments = ($requests.Content | ConvertFrom-Json).results + $baseSegmentsURL = $segmentsURL + $totalSegmentCount = ($requests.Content | ConvertFrom-Json).result_count + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] totalSegmentCount = $totalSegmentCount" + } + $totalSegments = ($requests.Content | ConvertFrom-Json).results + $seenSegments = $totalSegments.count + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] $segmentsURL (currentCount = $seenSegments)" + } + + while ( $seenSegments -lt $totalSegmentCount) { + $segmentsURL = $baseSegmentsURL + "&cursor=$(($requests.Content | ConvertFrom-Json).cursor)" + + try { + if($PSVersionTable.PSEdition -eq "Core") { + $requests = Invoke-WebRequest -Uri $segmentsURL -Method $method -Headers $global:nsxtProxyConnection.headers -SkipCertificateCheck + } else { + $requests = Invoke-WebRequest -Uri $segmentsURL -Method $method -Headers $global:nsxtProxyConnection.headers + } + } catch { + if($_.Exception.Response.StatusCode -eq "Unauthorized") { + Write-Host -ForegroundColor Red "`nThe NSX-T Proxy session is no longer valid, please re-run the Connect-NSXTProxy cmdlet to retrieve a new token`n" + break + } else { + Write-Error "Error in retrieving NSX-T Segments" + Write-Error "`n($_.Exception.Message)`n" + break + } + } + $segments = ($requests.Content | ConvertFrom-Json).results + $totalSegments += $segments + $seenSegments += $segments.count + + if($Troubleshoot) { + Write-Host -ForegroundColor cyan "`n[DEBUG] $segmentsURL (currentCount = $seenSegments)" + } + } if ($PSBoundParameters.ContainsKey("Name")){ - $segments = $segments | where {$_.display_name -eq $Name} + $totalSegments = $totalSegments | where {$_.display_name -eq $Name} } $results = @() - foreach ($segment in $segments) { + foreach ($segment in $totalSegments) { $subnets = $segment.subnets $network = $subnets.network From 76d01e7eb817704a128109afe2dc73d4ba207d04 Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Wed, 29 Apr 2020 23:04:18 +0200 Subject: [PATCH 16/42] Create Get-UplinkDetail.ps1 --- Scripts/Get-UplinkDetail.ps1 | 147 +++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 Scripts/Get-UplinkDetail.ps1 diff --git a/Scripts/Get-UplinkDetail.ps1 b/Scripts/Get-UplinkDetail.ps1 new file mode 100644 index 0000000..6bdbb46 --- /dev/null +++ b/Scripts/Get-UplinkDetail.ps1 @@ -0,0 +1,147 @@ +function Get-UplinkDetails { +<# + .NOTES + =========================================================================== + Created by: Markus Kraus + =========================================================================== + Changelog: + 2017.03 ver 1.0 Base Release + 2020.03 ver 1.1 Add LLDP Support + =========================================================================== + External Code Sources: + Get-CDP Version from @LucD22 + https://communities.vmware.com/thread/319553 + + LLDP PowerCLI Tweak + https://tech.zsoldier.com/2018/05/vmware-get-cdplldp-info-from.html + =========================================================================== + Tested Against Environment: + vSphere Version: vSphere 6.7 U3 + PowerCLI Version: PowerCLI 11.5 + PowerShell Version: 5.1 + OS Version: Server 2016 + Keyword: ESXi, Network, CDP, LLDP, VDS, vSwitch, VMNIC + =========================================================================== + + .DESCRIPTION + This Function collects detailed informations about your ESXi Host connections to pSwitch and VDS / vSwitch. + LLDP Informations might only be available when uplinks are connected to a VDS. + + .Example + Get-VMHost -Name MyHost | Get-UplinkDetails -Type LLDP | Where-Object {$_.VDS -ne "-No Backing-"} | Format-Table -AutoSize + + .Example + Get-VMHost -Name MyHost | Get-UplinkDetails -Type CDP | Where-Object {$_.VDS -ne "-No Backing-"} | Format-Table -AutoSize + + .Example + Get-Cluster -Name MyCluster | Get-VMHost | Get-UplinkDetails -Type LLDP | Format-Table -AutoSize + + .Example + Get-Cluster -Name MyCluster | Get-VMHost | Get-UplinkDetails -Type CDP | Format-Table -AutoSize + + .PARAMETER myHosts + Hosts to process + + +#Requires PS -Version 5.0 +#Requires -Modules VMware.VimAutomation.Core, @{ModuleName="VMware.VimAutomation.Core";ModuleVersion="6.3.0.0"} +#> + +[CmdletBinding()] +param( + [Parameter(Mandatory=$True, ValueFromPipeline=$True, Position=0, HelpMessage = "Hosts to process")] + [ValidateNotNullorEmpty()] + [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] $myHosts, + [Parameter(Mandatory=$True, ValueFromPipeline=$False, Position=1, HelpMessage = "Type of infos to collect (CDP / LLDP)")] + [ValidateSet("CDP","LLDP")] + [String] $Type + +) + +Begin { + + + function Get-Info ($VMhost){ + $VMhostProxySwitch = $VMhost.NetworkInfo.ExtensionData.ProxySwitch + $VMhostSwitch = $VMhost.NetworkInfo.VirtualSwitch + + $objReport = @() + $VMhost| %{Get-View $_.ID} | + %{ Get-View $_.ConfigManager.NetworkSystem} | + %{ foreach($physnic in $_.NetworkInfo.Pnic){ + + if($Type -eq "CDP"){ + $obj = "" | Select-Object ClusterName,HostName,vmnic,PCI,MAC,VDS,vSwitch,CDP_Port,CDP_Device,CDP_Address + } + elseif($Type -eq "LLDP"){ + $obj = "" | Select-Object ClusterName,HostName,vmnic,PCI,MAC,VDS,vSwitch,LLDP_Port,LLDP_Chassis,LLDP_SystemName + } + else{ + Throw "Invalide Type" + } + + $pnicInfo = $_.QueryNetworkHint($physnic.Device) + foreach($hint in $pnicInfo){ + $obj.ClusterName = $VMhost.parent.name + $obj.HostName = $VMhost.name + $obj.vmnic = $physnic.Device + $obj.PCI = $physnic.PCI + $obj.MAC = $physnic.Mac + if ($backing = ($VMhostProxySwitch | where {$_.Spec.Backing.PnicSpec.PnicDevice -eq $physnic.Device})) { + $obj.VDS = $backing.DvsName + } else { + $obj.VDS = "-No Backing-" + } + if ($backing = ($VMhostSwitch | where {$_.Nic -eq $physnic.Device})) { + $obj.vSwitch = $backing.name + } else { + $obj.vSwitch = "-No Backing-" + } + if($Type -eq "CDP"){ + if( $hint.ConnectedSwitchPort ) { + $obj.CDP_Port = $hint.ConnectedSwitchPort.PortId + $obj.CDP_Device = $hint.ConnectedSwitchPort.DevId + $obj.CDP_Address = $hint.ConnectedSwitchPort.Address + } else { + $obj.CDP_Port = "-No Info-" + $obj.CDP_Device = "-No Info-" + $obj.CDP_Address = "-No Info-" + } + } + if($Type -eq "LLDP"){ + if( $hint.LldpInfo ) { + $obj.LLDP_Port = $hint.LldpInfo.PortId + $obj.LLDP_Chassis = $hint.LldpInfo.ChassisId + $obj.LLDP_SystemName = ($hint.LldpInfo.Parameter | where key -eq "System Name").Value + } else { + $obj.LLDP_Port = "-No Info-" + $obj.LLDP_Chassis = "-No Info-" + $obj.LLDP_SystemName = "-No Info-" + } + } + + + } + $objReport += $obj + } + } + $objReport + } + +} + +Process { + + $MyView = @() + + foreach ($myHost in $myHosts) { + + $Info = Get-Info $myHost + $MyView += $Info + + } + + $MyView | Sort-Object ClusterName, HostName, vmnic + + } +} From a918eacdadaf95fcd5d1e53852f2b8a54876016c Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Wed, 29 Apr 2020 23:04:44 +0200 Subject: [PATCH 17/42] Rename Get-UplinkDetail.ps1 to Get-UplinkDetails.ps1 --- Scripts/{Get-UplinkDetail.ps1 => Get-UplinkDetails.ps1} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Scripts/{Get-UplinkDetail.ps1 => Get-UplinkDetails.ps1} (100%) diff --git a/Scripts/Get-UplinkDetail.ps1 b/Scripts/Get-UplinkDetails.ps1 similarity index 100% rename from Scripts/Get-UplinkDetail.ps1 rename to Scripts/Get-UplinkDetails.ps1 From 3a4dada48d4586edd1f7701ba09c15d808a14d44 Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Thu, 7 May 2020 20:20:13 +0200 Subject: [PATCH 18/42] Rename Function --- ...t-UplinkDetails.ps1 => Get-VMHostUplinkDetails.ps1} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename Scripts/{Get-UplinkDetails.ps1 => Get-VMHostUplinkDetails.ps1} (90%) diff --git a/Scripts/Get-UplinkDetails.ps1 b/Scripts/Get-VMHostUplinkDetails.ps1 similarity index 90% rename from Scripts/Get-UplinkDetails.ps1 rename to Scripts/Get-VMHostUplinkDetails.ps1 index 6bdbb46..9b47018 100644 --- a/Scripts/Get-UplinkDetails.ps1 +++ b/Scripts/Get-VMHostUplinkDetails.ps1 @@ -1,4 +1,4 @@ -function Get-UplinkDetails { +function Get-VMHostUplinkDetails { <# .NOTES =========================================================================== @@ -28,16 +28,16 @@ function Get-UplinkDetails { LLDP Informations might only be available when uplinks are connected to a VDS. .Example - Get-VMHost -Name MyHost | Get-UplinkDetails -Type LLDP | Where-Object {$_.VDS -ne "-No Backing-"} | Format-Table -AutoSize + Get-VMHost -Name MyHost | Get-VMHostUplinkDetails -Type LLDP | Where-Object {$_.VDS -ne "-No Backing-"} | Format-Table -AutoSize .Example - Get-VMHost -Name MyHost | Get-UplinkDetails -Type CDP | Where-Object {$_.VDS -ne "-No Backing-"} | Format-Table -AutoSize + Get-VMHost -Name MyHost | Get-VMHostUplinkDetails -Type CDP | Where-Object {$_.VDS -ne "-No Backing-"} | Format-Table -AutoSize .Example - Get-Cluster -Name MyCluster | Get-VMHost | Get-UplinkDetails -Type LLDP | Format-Table -AutoSize + Get-Cluster -Name MyCluster | Get-VMHost | Get-VMHostUplinkDetails -Type LLDP | Format-Table -AutoSize .Example - Get-Cluster -Name MyCluster | Get-VMHost | Get-UplinkDetails -Type CDP | Format-Table -AutoSize + Get-Cluster -Name MyCluster | Get-VMHost | Get-VMHostUplinkDetails -Type CDP | Format-Table -AutoSize .PARAMETER myHosts Hosts to process From be7f9827671b049ecb922fd69f9be582ceb42d0b Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Thu, 7 May 2020 20:25:40 +0200 Subject: [PATCH 19/42] Update Parameter --- Scripts/Get-VMHostUplinkDetails.ps1 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Scripts/Get-VMHostUplinkDetails.ps1 b/Scripts/Get-VMHostUplinkDetails.ps1 index 9b47018..a39c920 100644 --- a/Scripts/Get-VMHostUplinkDetails.ps1 +++ b/Scripts/Get-VMHostUplinkDetails.ps1 @@ -49,10 +49,11 @@ function Get-VMHostUplinkDetails { [CmdletBinding()] param( - [Parameter(Mandatory=$True, ValueFromPipeline=$True, Position=0, HelpMessage = "Hosts to process")] + [Parameter(Mandatory=$True, ValueFromPipeline=$True, Position=0, HelpMessage = "Specifies the hosts for which you want to retrieve the uplink details.")] [ValidateNotNullorEmpty()] - [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] $myHosts, - [Parameter(Mandatory=$True, ValueFromPipeline=$False, Position=1, HelpMessage = "Type of infos to collect (CDP / LLDP)")] + [Alias("myHosts")] + [VMware.VimAutomation.Types.VMHost[]] $VMHost, + [Parameter(Mandatory=$True, ValueFromPipeline=$False, Position=1, HelpMessage = "Type of infos you want to collect (CDP / LLDP)")] [ValidateSet("CDP","LLDP")] [String] $Type From e24187a954a52f7b6718a7106d8b093a9e4ed79d Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Thu, 7 May 2020 20:32:06 +0200 Subject: [PATCH 20/42] rename VMHost Parameter --- Scripts/Get-VMHostUplinkDetails.ps1 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Scripts/Get-VMHostUplinkDetails.ps1 b/Scripts/Get-VMHostUplinkDetails.ps1 index a39c920..ef843ec 100644 --- a/Scripts/Get-VMHostUplinkDetails.ps1 +++ b/Scripts/Get-VMHostUplinkDetails.ps1 @@ -62,12 +62,12 @@ param( Begin { - function Get-Info ($VMhost){ - $VMhostProxySwitch = $VMhost.NetworkInfo.ExtensionData.ProxySwitch - $VMhostSwitch = $VMhost.NetworkInfo.VirtualSwitch + function Get-Info ($VMhostToProcess){ + $VMhostProxySwitch = $VMhostToProcess.NetworkInfo.ExtensionData.ProxySwitch + $VMhostSwitch = $VMhostToProcess.NetworkInfo.VirtualSwitch $objReport = @() - $VMhost| %{Get-View $_.ID} | + $VMhostToProcess| %{Get-View $_.ID} | %{ Get-View $_.ConfigManager.NetworkSystem} | %{ foreach($physnic in $_.NetworkInfo.Pnic){ @@ -83,8 +83,8 @@ Begin { $pnicInfo = $_.QueryNetworkHint($physnic.Device) foreach($hint in $pnicInfo){ - $obj.ClusterName = $VMhost.parent.name - $obj.HostName = $VMhost.name + $obj.ClusterName = $VMhostToProcess.parent.name + $obj.HostName = $VMhostToProcess.name $obj.vmnic = $physnic.Device $obj.PCI = $physnic.PCI $obj.MAC = $physnic.Mac @@ -135,7 +135,7 @@ Process { $MyView = @() - foreach ($myHost in $myHosts) { + foreach ($myHost in $VMhost) { $Info = Get-Info $myHost $MyView += $Info From 228de51f25378d4a2fa57ebd8b03592d5502698d Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Thu, 7 May 2020 20:33:25 +0200 Subject: [PATCH 21/42] Fix code formatting --- Scripts/Get-VMHostUplinkDetails.ps1 | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Scripts/Get-VMHostUplinkDetails.ps1 b/Scripts/Get-VMHostUplinkDetails.ps1 index ef843ec..c5cd4c1 100644 --- a/Scripts/Get-VMHostUplinkDetails.ps1 +++ b/Scripts/Get-VMHostUplinkDetails.ps1 @@ -77,7 +77,7 @@ Begin { elseif($Type -eq "LLDP"){ $obj = "" | Select-Object ClusterName,HostName,vmnic,PCI,MAC,VDS,vSwitch,LLDP_Port,LLDP_Chassis,LLDP_SystemName } - else{ + else { Throw "Invalide Type" } @@ -90,12 +90,14 @@ Begin { $obj.MAC = $physnic.Mac if ($backing = ($VMhostProxySwitch | where {$_.Spec.Backing.PnicSpec.PnicDevice -eq $physnic.Device})) { $obj.VDS = $backing.DvsName - } else { + } + else { $obj.VDS = "-No Backing-" } if ($backing = ($VMhostSwitch | where {$_.Nic -eq $physnic.Device})) { $obj.vSwitch = $backing.name - } else { + } + else { $obj.vSwitch = "-No Backing-" } if($Type -eq "CDP"){ @@ -103,7 +105,8 @@ Begin { $obj.CDP_Port = $hint.ConnectedSwitchPort.PortId $obj.CDP_Device = $hint.ConnectedSwitchPort.DevId $obj.CDP_Address = $hint.ConnectedSwitchPort.Address - } else { + } + else { $obj.CDP_Port = "-No Info-" $obj.CDP_Device = "-No Info-" $obj.CDP_Address = "-No Info-" @@ -114,7 +117,8 @@ Begin { $obj.LLDP_Port = $hint.LldpInfo.PortId $obj.LLDP_Chassis = $hint.LldpInfo.ChassisId $obj.LLDP_SystemName = ($hint.LldpInfo.Parameter | where key -eq "System Name").Value - } else { + } + else { $obj.LLDP_Port = "-No Info-" $obj.LLDP_Chassis = "-No Info-" $obj.LLDP_SystemName = "-No Info-" From 0c3ff917d09fc93632b5ae99d8dc9720fe0c2663 Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Thu, 7 May 2020 20:34:28 +0200 Subject: [PATCH 22/42] Replace where with Where-Object --- Scripts/Get-VMHostUplinkDetails.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Scripts/Get-VMHostUplinkDetails.ps1 b/Scripts/Get-VMHostUplinkDetails.ps1 index c5cd4c1..05414df 100644 --- a/Scripts/Get-VMHostUplinkDetails.ps1 +++ b/Scripts/Get-VMHostUplinkDetails.ps1 @@ -88,13 +88,13 @@ Begin { $obj.vmnic = $physnic.Device $obj.PCI = $physnic.PCI $obj.MAC = $physnic.Mac - if ($backing = ($VMhostProxySwitch | where {$_.Spec.Backing.PnicSpec.PnicDevice -eq $physnic.Device})) { + if ($backing = ($VMhostProxySwitch | Where-Object {$_.Spec.Backing.PnicSpec.PnicDevice -eq $physnic.Device})) { $obj.VDS = $backing.DvsName } else { $obj.VDS = "-No Backing-" } - if ($backing = ($VMhostSwitch | where {$_.Nic -eq $physnic.Device})) { + if ($backing = ($VMhostSwitch | Where-Object {$_.Nic -eq $physnic.Device})) { $obj.vSwitch = $backing.name } else { @@ -116,7 +116,7 @@ Begin { if( $hint.LldpInfo ) { $obj.LLDP_Port = $hint.LldpInfo.PortId $obj.LLDP_Chassis = $hint.LldpInfo.ChassisId - $obj.LLDP_SystemName = ($hint.LldpInfo.Parameter | where key -eq "System Name").Value + $obj.LLDP_SystemName = ($hint.LldpInfo.Parameter | Where-Object key -eq "System Name").Value } else { $obj.LLDP_Port = "-No Info-" From f53c09ae036d951d432e8696aa7151126ebc897d Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Thu, 7 May 2020 20:35:44 +0200 Subject: [PATCH 23/42] Replace % with Foreach-Object. --- Scripts/Get-VMHostUplinkDetails.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Scripts/Get-VMHostUplinkDetails.ps1 b/Scripts/Get-VMHostUplinkDetails.ps1 index 05414df..899eb54 100644 --- a/Scripts/Get-VMHostUplinkDetails.ps1 +++ b/Scripts/Get-VMHostUplinkDetails.ps1 @@ -67,9 +67,9 @@ Begin { $VMhostSwitch = $VMhostToProcess.NetworkInfo.VirtualSwitch $objReport = @() - $VMhostToProcess| %{Get-View $_.ID} | - %{ Get-View $_.ConfigManager.NetworkSystem} | - %{ foreach($physnic in $_.NetworkInfo.Pnic){ + $VMhostToProcess| ForEach-Object{Get-View $_.ID} | + ForEach-Object{ Get-View $_.ConfigManager.NetworkSystem} | + ForEach-Object{ foreach($physnic in $_.NetworkInfo.Pnic){ if($Type -eq "CDP"){ $obj = "" | Select-Object ClusterName,HostName,vmnic,PCI,MAC,VDS,vSwitch,CDP_Port,CDP_Device,CDP_Address From ca6f6abeb7c36d79075da7fef2cf868f4bc1cec0 Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Thu, 7 May 2020 20:42:54 +0200 Subject: [PATCH 24/42] remove reporting array and sort --- Scripts/Get-VMHostUplinkDetails.ps1 | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/Scripts/Get-VMHostUplinkDetails.ps1 b/Scripts/Get-VMHostUplinkDetails.ps1 index 899eb54..9c0b25e 100644 --- a/Scripts/Get-VMHostUplinkDetails.ps1 +++ b/Scripts/Get-VMHostUplinkDetails.ps1 @@ -31,7 +31,7 @@ function Get-VMHostUplinkDetails { Get-VMHost -Name MyHost | Get-VMHostUplinkDetails -Type LLDP | Where-Object {$_.VDS -ne "-No Backing-"} | Format-Table -AutoSize .Example - Get-VMHost -Name MyHost | Get-VMHostUplinkDetails -Type CDP | Where-Object {$_.VDS -ne "-No Backing-"} | Format-Table -AutoSize + Get-VMHost -Name MyHost | Get-VMHostUplinkDetails -Type CDP | Where-Object {$_.VDS -ne "-No Backing-"} | Sort-Object ClusterName, HostName, vmnic | Format-Table -AutoSize .Example Get-Cluster -Name MyCluster | Get-VMHost | Get-VMHostUplinkDetails -Type LLDP | Format-Table -AutoSize @@ -137,16 +137,8 @@ Begin { Process { - $MyView = @() + $VMHost | Foreach-Object { Write-Output (Get-Info $_) } + +} - foreach ($myHost in $VMhost) { - - $Info = Get-Info $myHost - $MyView += $Info - - } - - $MyView | Sort-Object ClusterName, HostName, vmnic - - } } From 29b3b756040f4f830a8af5d4dfc7d67af1994404 Mon Sep 17 00:00:00 2001 From: William Lam Date: Tue, 19 May 2020 10:23:58 -0700 Subject: [PATCH 25/42] Added Workload Management module for vSphere with Kubernetes Updating Banner --- .../VMware.WorkloadManagement.psd1 | 90 +++++ .../VMware.WorkloadManagement.psm1 | 356 ++++++++++++++++++ 2 files changed, 446 insertions(+) create mode 100644 Modules/VMware.WorkloadManagement/VMware.WorkloadManagement.psd1 create mode 100644 Modules/VMware.WorkloadManagement/VMware.WorkloadManagement.psm1 diff --git a/Modules/VMware.WorkloadManagement/VMware.WorkloadManagement.psd1 b/Modules/VMware.WorkloadManagement/VMware.WorkloadManagement.psd1 new file mode 100644 index 0000000..85758ed --- /dev/null +++ b/Modules/VMware.WorkloadManagement/VMware.WorkloadManagement.psd1 @@ -0,0 +1,90 @@ +# +# Module manifest for module 'VMware.WorkloadManagement' +# +# Generated by: wlam@vmware.com +# +# Generated on: 05/19/20 +# + +@{ + +# Script module or binary module file associated with this manifest. +RootModule = 'VMware.WorkloadManagement.psm1' + +# Version number of this module. +ModuleVersion = '1.0.0' + +# Supported PSEditions +# CompatiblePSEditions = @() + +# ID used to uniquely identify this module +GUID = 'VMware.WorkloadManagement' + +# Author of this module +Author = 'William Lam' + +# Company or vendor of this module +CompanyName = 'VMware' + +# Copyright statement for this module +Copyright = '(c) 2020 VMware. All rights reserved.' + +# Description of the functionality provided by this module +Description = 'PowerShell Module for vSphere with Kubernetes Workload Management' + +# Minimum version of the Windows PowerShell engine required by this module +PowerShellVersion = '6.0' + +# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. + +FunctionsToExport = 'New-WorkloadManagement','Get-WorkloadManagement','Remove-WorkloadManagement' + +# 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.WorkloadManagement/VMware.WorkloadManagement.psm1 b/Modules/VMware.WorkloadManagement/VMware.WorkloadManagement.psm1 new file mode 100644 index 0000000..6eda487 --- /dev/null +++ b/Modules/VMware.WorkloadManagement/VMware.WorkloadManagement.psm1 @@ -0,0 +1,356 @@ +Function New-WorkloadManagement { + <# + .NOTES + =========================================================================== + Created by: William Lam + Date: 05/19/2020 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Enable Workload Management on vSphere 7 Cluster + .DESCRIPTION + Enable Workload Management on vSphere 7 Cluster + .PARAMETER ClusterName + Name of vSphere Cluster to enable Workload Management + .PARAMETER ControlPlaneSize + Size of Control Plane VMs (TINY, SMALL, MEDIUM, LARGE) + .PARAMETER MgmtNetwork + Management Network for Control Plane VMs + .PARAMETER MgmtNetworkStartIP + Starting IP Address for Control Plane VMs (5 consecutive free addresses) + .PARAMETER MgmtNetworkSubnet + Netmask for Management Network + .PARAMETER MgmtNetworkGateway + Gateway for Management Network + .PARAMETER MgmtNetworkDNS + DNS Server(s) to use for Management Network + .PARAMETER MgmtNetworkDNSDomain + DNS Domain(s) + .PARAMETER MgmtNetworkNTP + NTP Server(s) + .PARAMETER WorkloadNetworkVDS + Name of vSphere 7 Distributed Virtual Switch (VDS) configured with NSX-T + .PARAMETER WorkloadNetworkEdgeCluster + Name of NSX-T Edge Cluster + .PARAMETER WorkloadNetworkDNS + DNS Server(s) to use for Workloads + .PARAMETER WorkloadNetworkPodCIDR + K8s POD CIDR (default: 10.244.0.0/21) + .PARAMETER WorkloadNetworkServiceCIDR + K8S Service CIDR (default: 10.96.0.0/24) + .PARAMETER WorkloadNetworkIngressCIDR + CIDR for Workload Ingress (recommend /27 or larger) + .PARAMETER WorkloadNetworkEgressCIDR + CIDR for Workload Egress (recommend /27 or larger) + .PARAMETER ControlPlaneStoragePolicy + Name of VM Storage Policy to use for Control Plane VMs + .PARAMETER EphemeralDiskStoragePolicy + Name of VM Storage Policy to use for Ephemeral Disk + .PARAMETER ImageCacheStoragePolicy + Name of VM Storage Policy to use for Image Cache + .PARAMETER LoginBanner + Login message to show during kubectl login + .EXAMPLE + New-WorkloadManagement ` + -ClusterName "Workload-Cluster" ` + -ControlPlaneSize TINY ` + -MgmtNetwork "DVPG-Management Network" ` + -MgmtNetworkStartIP "172.17.36.51" ` + -MgmtNetworkSubnet "255.255.255.0" ` + -MgmtNetworkGateway "172.17.36.253" ` + -MgmtNetworkDNS "172.17.31.5" ` + -MgmtNetworkDNSDomain "cpub.corp" ` + -MgmtNetworkNTP "5.199.135.170" ` + -WorkloadNetworkVDS "Pacific-VDS" ` + -WorkloadNetworkEdgeCluster "Edge-Cluster-01" ` + -WorkloadNetworkDNS "172.17.31.5" ` + -WorkloadNetworkIngressCIDR "172.17.36.64/27" ` + -WorkloadNetworkEgressCIDR "172.17.36.96/27" ` + -ControlPlaneStoragePolicy "pacific-gold-storage-policy" ` + -EphemeralDiskStoragePolicy "pacific-gold-storage-policy" ` + -ImageCacheStoragePolicy "pacific-gold-storage-policy" + + #> + Param ( + [Parameter(Mandatory=$True)]$ClusterName, + [Parameter(Mandatory=$True)][ValidateSet("TINY","SMALL","MEDIUM","LARGE")][string]$ControlPlaneSize, + [Parameter(Mandatory=$True)]$MgmtNetwork, + [Parameter(Mandatory=$True)]$MgmtNetworkStartIP, + [Parameter(Mandatory=$True)]$MgmtNetworkSubnet, + [Parameter(Mandatory=$True)]$MgmtNetworkGateway, + [Parameter(Mandatory=$True)][string[]]$MgmtNetworkDNS, + [Parameter(Mandatory=$True)][string[]]$MgmtNetworkDNSDomain, + [Parameter(Mandatory=$True)]$MgmtNetworkNTP, + [Parameter(Mandatory=$True)]$WorkloadNetworkVDS, + [Parameter(Mandatory=$True)]$WorkloadNetworkEdgeCluster, + [Parameter(Mandatory=$True)][string[]]$WorkloadNetworkDNS, + [Parameter(Mandatory=$False)]$WorkloadNetworkPodCIDR="10.244.0.0/21", + [Parameter(Mandatory=$False)]$WorkloadNetworkServiceCIDR="10.96.0.0/24", + [Parameter(Mandatory=$True)]$WorkloadNetworkIngressCIDR, + [Parameter(Mandatory=$True)]$WorkloadNetworkEgressCIDR, + [Parameter(Mandatory=$True)]$ControlPlaneStoragePolicy, + [Parameter(Mandatory=$True)]$EphemeralDiskStoragePolicy, + [Parameter(Mandatory=$True)]$ImageCacheStoragePolicy, + [Parameter(Mandatory=$False)]$LoginBanner + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CiS Connection found, please use Connect-CisServer`n" } Else { + + # Management Network Moref + $networkService = Get-CisService "com.vmware.vcenter.network" + $networkFilterSpec = $networkService.help.list.filter.Create() + $networkFilterSpec.names = @("$MgmtNetwork") + $mgmtNetworkMoRef = $networkService.list($networkFilterSpec).network.Value + if ($mgmtNetworkMoRef -eq $NULL) { + Write-Host -ForegroundColor Red "Unable to find vSphere Cluster ${MgmtNetwork}" + break + } + + # Cluster Moref + $clusterService = Get-CisService "com.vmware.vcenter.cluster" + $clusterFilterSpec = $clusterService.help.list.filter.Create() + $clusterFilterSpec.names = @("$ClusterName") + $clusterMoRef = $clusterService.list($clusterFilterSpec).cluster.Value + if ($clusterMoRef -eq $NULL) { + Write-Host -ForegroundColor Red "Unable to find vSphere Cluster ${ClusterName}" + break + } + + # VDS MoRef + $vdsCompatService = Get-CisService "com.vmware.vcenter.namespace_management.distributed_switch_compatibility" + $vdsMoRef = ($vdsCompatService.list($clusterMoref)).distributed_switch.Value + if ($vdsMoRef -eq $NULL) { + Write-Host -ForegroundColor Red "Unable to find VDS ${WorkloadNetworkVDS}" + break + } + + # NSX-T Edge Cluster + $edgeClusterService = Get-CisService "com.vmware.vcenter.namespace_management.edge_cluster_compatibility" + $edgeClusterMoRef = ($edgeClusterService.list($clusterMoref,$vdsMoRef)).edge_cluster.Value + if ($edgeClusterMoRef -eq $NULL) { + Write-Host -ForegroundColor Red "Unable to find NSX-T Edge Cluster ${WorkloadNetworkEdgeCluster}" + break + } + + # VM Storage Policy MoRef + $storagePolicyService = Get-CisService "com.vmware.vcenter.storage.policies" + $sps= $storagePolicyService.list() + $cpSP = ($sps | where {$_.name -eq $ControlPlaneStoragePolicy}).Policy.Value + $edSP = ($sps | where {$_.name -eq $EphemeralDiskStoragePolicy}).Policy.Value + $icSP = ($sps | where {$_.name -eq $ImageCacheStoragePolicy}).Policy.Value + if ($cpSP -eq $NULL) { + Write-Host -ForegroundColor Red "Unable to find VM Storage Policy ${ControlPlaneStoragePolicy}" + break + } + + if ($edSP -eq $NULL) { + Write-Host -ForegroundColor Red "Unable to find VM Storage Policy ${EphemeralDiskStoragePolicy}" + break + } + + if ($icSP -eq $NULL) { + Write-Host -ForegroundColor Red "Unable to find VM Storage Policy ${ImageCacheStoragePolicy}" + break + } + + $nsmClusterService = Get-CisService "com.vmware.vcenter.namespace_management.clusters" + $spec = $nsmClusterService.help.enable.spec.Create() + + $spec.size_hint = $ControlPlaneSize + $spec.network_provider = "NSXT_CONTAINER_PLUGIN" + + $mgmtNetworkSpec = $nsmClusterService.help.enable.spec.master_management_network.Create() + $mgmtNetworkSpec.mode = "STATICRANGE" + $mgmtNetworkSpec.network = $mgmtNetworkMoRef + $mgmtNetworkSpec.address_range.starting_address = $MgmtNetworkStartIP + $mgmtNetworkSpec.address_range.address_count = 5 + $mgmtNetworkSpec.address_range.subnet_mask = $MgmtNetworkSubnet + $mgmtNetworkSpec.address_range.gateway = $MgmtNetworkGateway + + $spec.master_management_network = $mgmtNetworkSpec + $spec.master_DNS = $MgmtNetworkDNS + $spec.master_DNS_search_domains = $MgmtNetworkDNSDomain + $spec.master_NTP_servers = $MgmtNetworkNTP + + $spec.ncp_cluster_network_spec.cluster_distributed_switch = $vdsMoRef + $spec.ncp_cluster_network_spec.nsx_edge_cluster = $edgeClusterMoRef + + $spec.worker_DNS = $WorkloadNetworkDNS + + $serviceCidrSpec = $nsmClusterService.help.enable.spec.service_cidr.Create() + $serviceAddress,$servicePrefix = $WorkloadNetworkServiceCIDR.split("/") + $serviceCidrSpec.address = $serviceAddress + $serviceCidrSpec.prefix = $servicePrefix + $spec.service_cidr = $serviceCidrSpec + + $podCidrSpec = $nsmClusterService.help.enable.spec.ncp_cluster_network_spec.pod_cidrs.Element.Create() + $podAddress,$podPrefix = $WorkloadNetworkPodCIDR.split("/") + $podCidrSpec.address = $podAddress + $podCidrSpec.prefix = $podPrefix + $spec.ncp_cluster_network_spec.pod_cidrs = @($podCidrSpec) + + $egressCidrSpec = $nsmClusterService.help.enable.spec.ncp_cluster_network_spec.egress_cidrs.Element.Create() + $egressAddress,$egressPrefix = $WorkloadNetworkEgressCIDR.split("/") + $egressCidrSpec.address = $egressAddress + $egressCidrSpec.prefix = $egressPrefix + $spec.ncp_cluster_network_spec.egress_cidrs = @($egressCidrSpec) + + $ingressCidrSpec = $nsmClusterService.help.enable.spec.ncp_cluster_network_spec.ingress_cidrs.Element.Create() + $ingressAddress,$ingressPrefix = $WorkloadNetworkIngressCIDR.split("/") + $ingressCidrSpec.address = $ingressAddress + $ingressCidrSpec.prefix = $ingressPrefix + $spec.ncp_cluster_network_spec.ingress_cidrs = @($ingressCidrSpec) + + $spec.master_storage_policy = $cpSP + $spec.ephemeral_storage_policy = $edSP + + $imagePolicySpec = $nsmClusterService.help.enable.spec.image_storage.Create() + $imagePolicySpec.storage_policy = $icSP + $spec.image_storage = $imagePolicySpec + + if($LoginBanner -eq $NULL) { + $LoginBanner = " + + " + [char]::ConvertFromUtf32(0x1F973) + "vSphere with Kubernetes Cluster enabled by virtuallyGhetto " + [char]::ConvertFromUtf32(0x1F973) + " + +" + } + $spec.login_banner = $LoginBanner + + try { + Write-Host -Foreground Green "`nEnabling Workload Management on vSphere Cluster ${ClusterName} ..." + $nsmClusterService.enable($clusterMoRef,$spec) + } catch { + Write-Error "Error in attempting to enable Workload Management on vSphere Cluster ${ClusterName}" + Write-Error "`n($_.Exception.Message)`n" + break + } + Write-Host -Foreground Green "Please refer to the Workload Management UI in vCenter Server to monitor the progress of this operation" + } +} + +Function Get-WorkloadManagement { + <# + .NOTES + =========================================================================== + Created by: William Lam + Date: 05/19/2020 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Retrieve all Workload Management Clusters + .DESCRIPTION + Retrieve all Workload Management Clusters + .PARAMETER Stats + Output additional stats pertaining to CPU, Memory and Storage + .EXAMPLE + Get-WorkloadManagement + .EXAMPLE + Get-WorkloadManagement -Stats + #> + Param ( + [Switch]$Stats + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CiS Connection found, please use Connect-CisServer`n" } Else { + If (-Not $global:DefaultVIServers) { Write-error "No VI Connection found, please use Connect-VIServer`n" } Else { + $nssClusterService = Get-CisService "com.vmware.vcenter.namespace_management.software.clusters" + $nsInstanceService = Get-CisService "com.vmware.vcenter.namespaces.instances" + $nsmClusterService = Get-CisService "com.vmware.vcenter.namespace_management.clusters" + $wlClusters = $nsmClusterService.list() + + $results = @() + foreach ($wlCluster in $wlClusters) { + $workloadClusterId = $wlCluster.cluster + $vSphereCluster = Get-Cluster | where {$_.id -eq "ClusterComputeResource-${workloadClusterId}"} + $workloadCluster = $nsmClusterService.get($workloadClusterId) + + $nsCount = ($nsInstanceService.list() | where {$_.cluster -eq $workloadClusterId}).count + $hostCount = ($vSphereCluster.ExtensionData.Host).count + if($workloadCluster.kubernetes_status -ne "ERROR") { + $k8sVersion = $nssClusterService.get($workloadClusterId).current_version + } else { $k8sVersion = "UNKNOWN" } + + $tmp = [pscustomobject] @{ + NAME = $vSphereCluster.name; + NAMESPACES = $nsCount; + HOSTS = $hostCount; + CONTROL_PLANE_IP = $workloadCluster.api_server_cluster_endpoint; + CLUSTER_STATUS = $workloadCluster.config_status; + K8S_STATUS = $workloadCluster.kubernetes_status; + VERSION = $k8sVersion; + } + + if($Stats) { + $tmp | Add-Member -NotePropertyName CPU_CAPACITY -NotePropertyValue $workloadCluster.stat_summary.cpu_capacity + $tmp | Add-Member -NotePropertyName MEM_CAPACITY -NotePropertyValue $workloadCluster.stat_summary.memory_capacity + $tmp | Add-Member -NotePropertyName STORAGE_CAPACITY -NotePropertyValue $workloadCluster.stat_summary.storage_capacity + $tmp | Add-Member -NotePropertyName CPU_USED -NotePropertyValue $workloadCluster.stat_summary.cpu_used + $tmp | Add-Member -NotePropertyName MEM_USED -NotePropertyValue $workloadCluster.stat_summary.memory_used + $tmp | Add-Member -NotePropertyName STORAGE_USED -NotePropertyValue $workloadCluster.stat_summary.storage_used + } + + $results+=$tmp + } + $results + } + } +} + +Function Remove-WorkloadManagement { + <# + .NOTES + =========================================================================== + Created by: William Lam + Date: 05/19/2020 + Organization: VMware + Blog: http://www.virtuallyghetto.com + Twitter: @lamw + =========================================================================== + + .SYNOPSIS + Disable Workload Management on vSphere Cluster + .DESCRIPTION + Disable Workload Management on vSphere Cluster + .PARAMETER ClusterName + Name of vSphere Cluster to disable Workload Management + .EXAMPLE + Remove-WorkloadManagement -ClusterName "Workload-Cluster" + #> + Param ( + [Parameter(Mandatory=$True)]$ClusterName + ) + + If (-Not $global:DefaultCisServers) { Write-error "No CiS Connection found, please use Connect-CisServer`n" } Else { + + $vSphereCluster = Get-Cluster | where {$_.Name -eq $ClusterName} + if($vSphereCluster -eq $null) { + Write-Host -ForegroundColor Red "Unable to find vSphere Cluster ${ClusterName}" + break + } + $vSphereClusterID = ($vSphereCluster.id).replace("ClusterComputeResource-","") + + $nsmClusterService = Get-CisService "com.vmware.vcenter.namespace_management.clusters" + $workloadClusterID = ($nsmClusterService.list() | where {$_.cluster -eq $vSphereClusterID}).cluster.Value + if($workloadClusterID -eq $null) { + Write-Host -ForegroundColor Red "Unable to find Workload Management Cluster ${ClusterName}" + break + } + + try { + Write-Host -Foreground Green "`nDisabling Workload Management on vSphere Cluster ${ClusterName} ..." + $nsmClusterService.disable($workloadClusterID) + } catch { + Write-Error "Error in attempting to disable Workload Management on vSphere Cluster ${ClusterName}" + Write-Error "`n($_.Exception.Message)`n" + break + } + Write-Host -Foreground Green "Please refer to the Workload Management UI in vCenter Server to monitor the progress of this operation" + } +} \ No newline at end of file From 5c3e80bbf6e4e9272d1b13dbd2a70f1cac8b188a Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Mon, 25 May 2020 21:41:22 +0200 Subject: [PATCH 26/42] SetSecure inlline function --- Scripts/Set-VMHostSecureNTP.ps1 | 90 +++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 Scripts/Set-VMHostSecureNTP.ps1 diff --git a/Scripts/Set-VMHostSecureNTP.ps1 b/Scripts/Set-VMHostSecureNTP.ps1 new file mode 100644 index 0000000..fb3204b --- /dev/null +++ b/Scripts/Set-VMHostSecureNTP.ps1 @@ -0,0 +1,90 @@ +function Set-VMHostSecureNTP { + [CmdletBinding()] + param( + [Parameter(Mandatory=$True, ValueFromPipeline=$True, Position=0, HelpMessage = "Specifies the hosts to configure.")] + [ValidateNotNullorEmpty()] + [VMware.VimAutomation.Types.VMHost[]] $VMHost, + [Parameter(Mandatory=$False, ValueFromPipeline=$False, Position=1, HelpMessage = "Type of confugration")] + [ValidateSet("SetSecure","Secure")] + [String] $Type = "SetSecure", + [Parameter(Mandatory=$True, ValueFromPipeline=$False, Position=2, HelpMessage = "Array of NTP Serbers")] + [ValidateNotNullorEmpty()] + [Array] $NTP + ) + + begin { + + function SetSecure ($MyHost) { + ## Get NTP Service + $NTPService = $MyHost | Get-VMHostService | Where-Object {$_.key -eq "ntpd"} + ## Stop NTP Service if running + if($NTPService.Running -eq $True){ + Stop-VMHostService -HostService $NTPService -Confirm:$false | Out-Null + } + ## Enable NTP Service + if($NTPService.Policy -ne "on"){ + Set-VMHostService -HostService $NTPService -Policy "on" -confirm:$False | Out-Null + } + ## Remove all existiing NTP Servers + try { + foreach ($OldNtpServer in ($MyHost | Get-VMHostNtpServer)) { + $MyHost | Remove-VMHostNtpServer -NtpServer $OldNtpServer -Confirm:$false + } + } + catch [System.Exception] { + Write-Warning "Error during removing existing NTP Servers on Host '$($MyHost.Name)'." + } + ## Set New NTP Servers + foreach ($myNTP in $NTP) { + $MyHost | Add-VMHostNtpServer -ntpserver $myNTP -confirm:$False | Out-Null + } + ## Set Current time on Host + $HostTimeSystem = Get-View $MyHost.ExtensionData.ConfigManager.DateTimeSystem + $HostTimeSystem.UpdateDateTime([DateTime]::UtcNow) + ## Start NTP Service + Start-VMHostService -HostService $NTPService -confirm:$False | Out-Null + ## Get NTP CLient Forewall Rule + $esxcli = Get-ESXCLI -VMHost $MyHost -v2 + $esxcliargs = $esxcli.network.firewall.ruleset.rule.list.CreateArgs() + $esxcliargs.rulesetid = "ntpClient" + try { + $esxcli.network.firewall.ruleset.rule.list.Invoke($esxcliargs) + } + catch [System.Exception] { + Write-Warning "Error during Rule List. See latest errors..." + } + ## Set NTP Client Firewall Rule + $esxcliargs = $esxcli.network.firewall.ruleset.set.CreateArgs() + $esxcliargs.enabled = "true" + $esxcliargs.allowedall = "false" + $esxcliargs.rulesetid = "ntpClient" + try { + $esxcli.network.firewall.ruleset.set.Invoke($esxcliargs) + } + catch [System.Exception] { + Write-Warning "Error during Rule Set. See latest errors..." + } + ## Set NTP Client Firewall Rule AllowedIP + foreach ($myNTP in $NTP) { + $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.add.CreateArgs() + $esxcliargs.ipaddress = $myNTP + $esxcliargs.rulesetid = "ntpClient" + try { + $esxcli.network.firewall.ruleset.allowedip.add.Invoke($esxcliargs) + } + catch [System.Exception] { + Write-Warning "Error during Rule Update. See latest errors..." + } + } + } + + } + + process { + + } + + end { + + } +} \ No newline at end of file From bd70bfb5dc8afdc606895e27e9f52414ba65cbc3 Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Mon, 25 May 2020 21:45:13 +0200 Subject: [PATCH 27/42] processing for SetSecure --- Scripts/Set-VMHostSecureNTP.ps1 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Scripts/Set-VMHostSecureNTP.ps1 b/Scripts/Set-VMHostSecureNTP.ps1 index fb3204b..e862fe1 100644 --- a/Scripts/Set-VMHostSecureNTP.ps1 +++ b/Scripts/Set-VMHostSecureNTP.ps1 @@ -82,6 +82,11 @@ function Set-VMHostSecureNTP { process { + if ($Type -eq "SetSecure") { + "Executing Set and Secure operation..." + $VMHost | Foreach-Object { Write-Output (SetSecure $_) } + } + } end { From 9a7dc6dd592728933ea403023a2620cbca3a6002 Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Tue, 26 May 2020 22:37:26 +0200 Subject: [PATCH 28/42] Added Error Handling and Pre-Checks --- Scripts/Set-VMHostSecureNTP.ps1 | 84 ++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 13 deletions(-) diff --git a/Scripts/Set-VMHostSecureNTP.ps1 b/Scripts/Set-VMHostSecureNTP.ps1 index e862fe1..1148bb1 100644 --- a/Scripts/Set-VMHostSecureNTP.ps1 +++ b/Scripts/Set-VMHostSecureNTP.ps1 @@ -15,17 +15,21 @@ function Set-VMHostSecureNTP { begin { function SetSecure ($MyHost) { - ## Get NTP Service + ## Get NTP Service + "Get NTP Service from VMHost ..." $NTPService = $MyHost | Get-VMHostService | Where-Object {$_.key -eq "ntpd"} - ## Stop NTP Service if running + ## Stop NTP Service if running + "Stop NTP Service if running ..." if($NTPService.Running -eq $True){ Stop-VMHostService -HostService $NTPService -Confirm:$false | Out-Null } ## Enable NTP Service + "Enable NTP Service if disabled..." if($NTPService.Policy -ne "on"){ Set-VMHostService -HostService $NTPService -Policy "on" -confirm:$False | Out-Null } ## Remove all existiing NTP Servers + "Remove all existiing NTP Servers ..." try { foreach ($OldNtpServer in ($MyHost | Get-VMHostNtpServer)) { $MyHost | Remove-VMHostNtpServer -NtpServer $OldNtpServer -Confirm:$false @@ -35,36 +39,90 @@ function Set-VMHostSecureNTP { Write-Warning "Error during removing existing NTP Servers on Host '$($MyHost.Name)'." } ## Set New NTP Servers + "Set New NTP Servers ..." foreach ($myNTP in $NTP) { $MyHost | Add-VMHostNtpServer -ntpserver $myNTP -confirm:$False | Out-Null } ## Set Current time on Host + "Set Current time on VMHost ..." $HostTimeSystem = Get-View $MyHost.ExtensionData.ConfigManager.DateTimeSystem $HostTimeSystem.UpdateDateTime([DateTime]::UtcNow) ## Start NTP Service + "Start NTP Service ..." Start-VMHostService -HostService $NTPService -confirm:$False | Out-Null - ## Get NTP CLient Forewall Rule + ## Get ESXCLI -V2 $esxcli = Get-ESXCLI -VMHost $MyHost -v2 - $esxcliargs = $esxcli.network.firewall.ruleset.rule.list.CreateArgs() - $esxcliargs.rulesetid = "ntpClient" + ## Get NTP Client Firewall + "Get NTP Client Firewall ..." try { - $esxcli.network.firewall.ruleset.rule.list.Invoke($esxcliargs) + $FirewallGet = $esxcli.network.firewall.get.Invoke() } catch [System.Exception] { Write-Warning "Error during Rule List. See latest errors..." } - ## Set NTP Client Firewall Rule - $esxcliargs = $esxcli.network.firewall.ruleset.set.CreateArgs() - $esxcliargs.enabled = "true" - $esxcliargs.allowedall = "false" + "`tLoded: $($FirewallGet.Loaded)" + "`tEnabled: $($FirewallGet.Enabled)" + "`tDefaultAction: $($FirewallGet.DefaultAction)" + ## Get NTP Client Firewall Rule + "Get NTP Client Firewall RuleSet ..." + $esxcliargs = $esxcli.network.firewall.ruleset.list.CreateArgs() $esxcliargs.rulesetid = "ntpClient" try { - $esxcli.network.firewall.ruleset.set.Invoke($esxcliargs) + $FirewallRuleList = $esxcli.network.firewall.ruleset.list.Invoke($esxcliargs) } catch [System.Exception] { - Write-Warning "Error during Rule Set. See latest errors..." + Write-Warning "Error during Rule List. See latest errors..." } + "`tEnabled: $($FirewallRuleList.Enabled)" + "Get NTP Client Firewall Rule AllowedIP ..." + $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.list.CreateArgs() + $esxcliargs.rulesetid = "ntpClient" + try { + $FirewallRuleAllowedIPList = $esxcli.network.firewall.ruleset.allowedip.list.Invoke($esxcliargs) + } + catch [System.Exception] { + Write-Warning "Error during Rule List. See latest errors..." + } + "`tAllowed IP Addresses: $($FirewallRuleAllowedIPList.AllowedIPAddresses)" + ## Remove Existing IP from firewall rule + ## BUG: If AllowedIP was enabled and is disabled now, old IPs will not be removed + "Remove Existing IP from firewall rule ..." + if ($FirewallRuleAllowedIPList.AllowedIPAddresses -ne "All") { + foreach ($IP in $FirewallRuleAllowedIPList.AllowedIPAddresses) { + $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.remove.CreateArgs() + $esxcliargs.rulesetid = "ntpClient" + $esxcliargs.ipaddress = $IP + try { + $esxcli.network.firewall.ruleset.allowedip.remove.Invoke($esxcliargs) + } + catch [System.Exception] { + Write-Warning "Error during AllowedIP remove. See latest errors..." + } + + } + + } + ## Set NTP Client Firewall Rule + "Set NTP Client Firewall Rule ..." + if ($FirewallRuleList.Enabled -ne $True -or $FirewallRuleAllowedIPList.AllowedIPAddresses -eq "All") { + $esxcliargs = $esxcli.network.firewall.ruleset.set.CreateArgs() + if ($FirewallRuleList.Enabled -ne $True) { + $esxcliargs.enabled = "true" + } + if ($FirewallRuleAllowedIPList.AllowedIPAddresses -eq "All") { + $esxcliargs.allowedall = "false" + } + $esxcliargs.rulesetid = "ntpClient" + try { + $esxcli.network.firewall.ruleset.set.Invoke($esxcliargs) + } + catch [System.Exception] { + Write-Warning "Error during Rule Set. See latest errors..." + } + } ## Set NTP Client Firewall Rule AllowedIP + ## BUG: If AllowedIP was enabled and is disabled now, a duplicate Ip Cannot be added + "Set NTP Client Firewall Rule AllowedIP ..." foreach ($myNTP in $NTP) { $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.add.CreateArgs() $esxcliargs.ipaddress = $myNTP @@ -73,7 +131,7 @@ function Set-VMHostSecureNTP { $esxcli.network.firewall.ruleset.allowedip.add.Invoke($esxcliargs) } catch [System.Exception] { - Write-Warning "Error during Rule Update. See latest errors..." + Write-Warning "Error during Rule AllowedIP Update. See latest errors..." } } } From 222f75a6ca9465eb975404530560692a62e3d9fb Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Wed, 27 May 2020 18:59:32 +0200 Subject: [PATCH 29/42] Workaround for duplicate IP --- Scripts/Set-VMHostSecureNTP.ps1 | 41 +++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/Scripts/Set-VMHostSecureNTP.ps1 b/Scripts/Set-VMHostSecureNTP.ps1 index 1148bb1..f323c31 100644 --- a/Scripts/Set-VMHostSecureNTP.ps1 +++ b/Scripts/Set-VMHostSecureNTP.ps1 @@ -121,7 +121,7 @@ function Set-VMHostSecureNTP { } } ## Set NTP Client Firewall Rule AllowedIP - ## BUG: If AllowedIP was enabled and is disabled now, a duplicate Ip Cannot be added + ### BUG: If AllowedIP was enabled and is disabled now, a duplicate Ip Cannot be added --> Workarund done "Set NTP Client Firewall Rule AllowedIP ..." foreach ($myNTP in $NTP) { $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.add.CreateArgs() @@ -131,7 +131,44 @@ function Set-VMHostSecureNTP { $esxcli.network.firewall.ruleset.allowedip.add.Invoke($esxcliargs) } catch [System.Exception] { - Write-Warning "Error during Rule AllowedIP Update. See latest errors..." + $ErrorMessage = $_.Exception.Message + if ($ErrorMessage -eq "Ip address already exist.") { + + $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.list.CreateArgs() + $esxcliargs.rulesetid = "ntpClient" + try { + $FirewallRuleAllowedIPList = $esxcli.network.firewall.ruleset.allowedip.list.Invoke($esxcliargs) + } + catch [System.Exception] { + Write-Warning "Error during Rule List. See latest errors..." + } + if ($FirewallRuleAllowedIPList.AllowedIPAddresses -ne "All") { + foreach ($IP in $FirewallRuleAllowedIPList.AllowedIPAddresses) { + $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.remove.CreateArgs() + $esxcliargs.rulesetid = "ntpClient" + $esxcliargs.ipaddress = $IP + try { + $esxcli.network.firewall.ruleset.allowedip.remove.Invoke($esxcliargs) + } + catch [System.Exception] { + Write-Warning "Error during AllowedIP remove. See latest errors..." + } + + } + + } + $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.add.CreateArgs() + $esxcliargs.ipaddress = $myNTP + $esxcliargs.rulesetid = "ntpClient" + try { + $esxcli.network.firewall.ruleset.allowedip.add.Invoke($esxcliargs) + } + catch [System.Exception] { + Write-Warning "Error during Rule AllowedIP Update. '$ErrorMessage' See latest errors..." + + } + + } } } } From 91cac83589168dcd130d39cc88074ce2eb518d9e Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Thu, 28 May 2020 20:38:09 +0200 Subject: [PATCH 30/42] Fix for existing configurations --- Scripts/Set-VMHostSecureNTP.ps1 | 116 ++++++++++++++------------------ 1 file changed, 50 insertions(+), 66 deletions(-) diff --git a/Scripts/Set-VMHostSecureNTP.ps1 b/Scripts/Set-VMHostSecureNTP.ps1 index f323c31..69d420c 100644 --- a/Scripts/Set-VMHostSecureNTP.ps1 +++ b/Scripts/Set-VMHostSecureNTP.ps1 @@ -1,15 +1,17 @@ function Set-VMHostSecureNTP { [CmdletBinding()] param( - [Parameter(Mandatory=$True, ValueFromPipeline=$True, Position=0, HelpMessage = "Specifies the hosts to configure.")] + [Parameter(Mandatory=$True, ValueFromPipeline=$True, HelpMessage = "Specifies the hosts to configure.")] [ValidateNotNullorEmpty()] [VMware.VimAutomation.Types.VMHost[]] $VMHost, - [Parameter(Mandatory=$False, ValueFromPipeline=$False, Position=1, HelpMessage = "Type of confugration")] - [ValidateSet("SetSecure","Secure")] - [String] $Type = "SetSecure", - [Parameter(Mandatory=$True, ValueFromPipeline=$False, Position=2, HelpMessage = "Array of NTP Serbers")] + [Parameter(Mandatory=$False, ValueFromPipeline=$False, ParameterSetName="SetSecure", HelpMessage = "Execute Set and Secure operation for new NTP Servers")] + [Switch] $SetSecure, + [Parameter(Mandatory=$True, ValueFromPipeline=$False, ParameterSetName="SetSecure", HelpMessage = "Array of NTP Serbers")] [ValidateNotNullorEmpty()] - [Array] $NTP + [Array] $NTP, + [Parameter(Mandatory=$False, ValueFromPipeline=$False, ParameterSetName="SetSecure", HelpMessage = "Execute Secure operation for exitsting NTP Servers")] + [Switch] $Secure + ) begin { @@ -74,6 +76,23 @@ function Set-VMHostSecureNTP { Write-Warning "Error during Rule List. See latest errors..." } "`tEnabled: $($FirewallRuleList.Enabled)" + ## Set NTP Client Firewall Rule + "Set NTP Client Firewall Rule ..." + $esxcliargs = $esxcli.network.firewall.ruleset.set.CreateArgs() + $esxcliargs.enabled = "true" + $esxcliargs.allowedall = "false" + $esxcliargs.rulesetid = "ntpClient" + try { + $esxcli.network.firewall.ruleset.set.Invoke($esxcliargs) + } + catch [System.Exception] { + $ErrorMessage = $_.Exception.Message + if ($ErrorMessage -ne "Already use allowed ip list") { + Write-Warning "Error during Rule Set. See latest errors..." + + } + + } "Get NTP Client Firewall Rule AllowedIP ..." $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.list.CreateArgs() $esxcliargs.rulesetid = "ntpClient" @@ -83,9 +102,8 @@ function Set-VMHostSecureNTP { catch [System.Exception] { Write-Warning "Error during Rule List. See latest errors..." } - "`tAllowed IP Addresses: $($FirewallRuleAllowedIPList.AllowedIPAddresses)" + "`tAllowed IP Addresses: $($FirewallRuleAllowedIPList.AllowedIPAddresses -join ", ")" ## Remove Existing IP from firewall rule - ## BUG: If AllowedIP was enabled and is disabled now, old IPs will not be removed "Remove Existing IP from firewall rule ..." if ($FirewallRuleAllowedIPList.AllowedIPAddresses -ne "All") { foreach ($IP in $FirewallRuleAllowedIPList.AllowedIPAddresses) { @@ -98,30 +116,10 @@ function Set-VMHostSecureNTP { catch [System.Exception] { Write-Warning "Error during AllowedIP remove. See latest errors..." } - } } - ## Set NTP Client Firewall Rule - "Set NTP Client Firewall Rule ..." - if ($FirewallRuleList.Enabled -ne $True -or $FirewallRuleAllowedIPList.AllowedIPAddresses -eq "All") { - $esxcliargs = $esxcli.network.firewall.ruleset.set.CreateArgs() - if ($FirewallRuleList.Enabled -ne $True) { - $esxcliargs.enabled = "true" - } - if ($FirewallRuleAllowedIPList.AllowedIPAddresses -eq "All") { - $esxcliargs.allowedall = "false" - } - $esxcliargs.rulesetid = "ntpClient" - try { - $esxcli.network.firewall.ruleset.set.Invoke($esxcliargs) - } - catch [System.Exception] { - Write-Warning "Error during Rule Set. See latest errors..." - } - } ## Set NTP Client Firewall Rule AllowedIP - ### BUG: If AllowedIP was enabled and is disabled now, a duplicate Ip Cannot be added --> Workarund done "Set NTP Client Firewall Rule AllowedIP ..." foreach ($myNTP in $NTP) { $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.add.CreateArgs() @@ -132,55 +130,41 @@ function Set-VMHostSecureNTP { } catch [System.Exception] { $ErrorMessage = $_.Exception.Message - if ($ErrorMessage -eq "Ip address already exist.") { - - $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.list.CreateArgs() - $esxcliargs.rulesetid = "ntpClient" - try { - $FirewallRuleAllowedIPList = $esxcli.network.firewall.ruleset.allowedip.list.Invoke($esxcliargs) - } - catch [System.Exception] { - Write-Warning "Error during Rule List. See latest errors..." - } - if ($FirewallRuleAllowedIPList.AllowedIPAddresses -ne "All") { - foreach ($IP in $FirewallRuleAllowedIPList.AllowedIPAddresses) { - $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.remove.CreateArgs() - $esxcliargs.rulesetid = "ntpClient" - $esxcliargs.ipaddress = $IP - try { - $esxcli.network.firewall.ruleset.allowedip.remove.Invoke($esxcliargs) - } - catch [System.Exception] { - Write-Warning "Error during AllowedIP remove. See latest errors..." - } - - } - - } - $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.add.CreateArgs() - $esxcliargs.ipaddress = $myNTP - $esxcliargs.rulesetid = "ntpClient" - try { - $esxcli.network.firewall.ruleset.allowedip.add.Invoke($esxcliargs) - } - catch [System.Exception] { - Write-Warning "Error during Rule AllowedIP Update. '$ErrorMessage' See latest errors..." - - } - + if ($ErrorMessage -ne "Ip address already exist.") { + Write-Warning "Error during AllowedIP remove. See latest errors..." } } } + ## Get New NTP Client Firewall Rule AllowedIP + "Get New NTP Client Firewall Rule AllowedIP ..." + $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.list.CreateArgs() + $esxcliargs.rulesetid = "ntpClient" + try { + $FirewallRuleAllowedIPList = $esxcli.network.firewall.ruleset.allowedip.list.Invoke($esxcliargs) + } + catch [System.Exception] { + Write-Warning "Error during Rule List. See latest errors..." + } + "`tNew Allowed IP Addresses: $($FirewallRuleAllowedIPList.AllowedIPAddresses -join ", ")" + ## Get New NTP Servers + "Get New NTP Servers ..." + $NewNTPServers = $MyHost | Get-VMHostNtpServer + "`tNew NTP Servers: $($NewNTPServers -join ", ")" + } } process { - if ($Type -eq "SetSecure") { - "Executing Set and Secure operation..." + if ($SetSecure) { + "Execute Set and Secure operation for new NTP Servers ..." $VMHost | Foreach-Object { Write-Output (SetSecure $_) } } + if ($Secure) { + "Execute Secure operation for exitsting NTP Servers ..." + $VMHost | Foreach-Object { Write-Output (Secure $_) } + } } From 3a91b48f15a6b8c917ae303f0db90ec6f1d2f460 Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Thu, 28 May 2020 20:45:46 +0200 Subject: [PATCH 31/42] Add Secure Operation --- Scripts/Set-VMHostSecureNTP.ps1 | 103 +++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/Scripts/Set-VMHostSecureNTP.ps1 b/Scripts/Set-VMHostSecureNTP.ps1 index 69d420c..9fa4f44 100644 --- a/Scripts/Set-VMHostSecureNTP.ps1 +++ b/Scripts/Set-VMHostSecureNTP.ps1 @@ -9,7 +9,7 @@ function Set-VMHostSecureNTP { [Parameter(Mandatory=$True, ValueFromPipeline=$False, ParameterSetName="SetSecure", HelpMessage = "Array of NTP Serbers")] [ValidateNotNullorEmpty()] [Array] $NTP, - [Parameter(Mandatory=$False, ValueFromPipeline=$False, ParameterSetName="SetSecure", HelpMessage = "Execute Secure operation for exitsting NTP Servers")] + [Parameter(Mandatory=$False, ValueFromPipeline=$False, ParameterSetName="Secure", HelpMessage = "Execute Secure operation for exitsting NTP Servers")] [Switch] $Secure ) @@ -152,6 +152,107 @@ function Set-VMHostSecureNTP { "`tNew NTP Servers: $($NewNTPServers -join ", ")" } + + function Secure ($myhost) { + ## Get NTP Servers + "Get NTP Servers ..." + [Array]$CurrentNTPServers = $MyHost | Get-VMHostNtpServer + "`tNTP Servers: $($NewNTPServers -join ", ")" + ## Get NTP Client Firewall + "Get NTP Client Firewall ..." + try { + $FirewallGet = $esxcli.network.firewall.get.Invoke() + } + catch [System.Exception] { + Write-Warning "Error during Rule List. See latest errors..." + } + "`tLoded: $($FirewallGet.Loaded)" + "`tEnabled: $($FirewallGet.Enabled)" + "`tDefaultAction: $($FirewallGet.DefaultAction)" + ## Get NTP Client Firewall Rule + "Get NTP Client Firewall RuleSet ..." + $esxcliargs = $esxcli.network.firewall.ruleset.list.CreateArgs() + $esxcliargs.rulesetid = "ntpClient" + try { + $FirewallRuleList = $esxcli.network.firewall.ruleset.list.Invoke($esxcliargs) + } + catch [System.Exception] { + Write-Warning "Error during Rule List. See latest errors..." + } + "`tEnabled: $($FirewallRuleList.Enabled)" + ## Set NTP Client Firewall Rule + "Set NTP Client Firewall Rule ..." + $esxcliargs = $esxcli.network.firewall.ruleset.set.CreateArgs() + $esxcliargs.enabled = "true" + $esxcliargs.allowedall = "false" + $esxcliargs.rulesetid = "ntpClient" + try { + $esxcli.network.firewall.ruleset.set.Invoke($esxcliargs) + } + catch [System.Exception] { + $ErrorMessage = $_.Exception.Message + if ($ErrorMessage -ne "Already use allowed ip list") { + Write-Warning "Error during Rule Set. See latest errors..." + + } + + } + "Get NTP Client Firewall Rule AllowedIP ..." + $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.list.CreateArgs() + $esxcliargs.rulesetid = "ntpClient" + try { + $FirewallRuleAllowedIPList = $esxcli.network.firewall.ruleset.allowedip.list.Invoke($esxcliargs) + } + catch [System.Exception] { + Write-Warning "Error during Rule List. See latest errors..." + } + "`tAllowed IP Addresses: $($FirewallRuleAllowedIPList.AllowedIPAddresses -join ", ")" + ## Remove Existing IP from firewall rule + "Remove Existing IP from firewall rule ..." + if ($FirewallRuleAllowedIPList.AllowedIPAddresses -ne "All") { + foreach ($IP in $FirewallRuleAllowedIPList.AllowedIPAddresses) { + $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.remove.CreateArgs() + $esxcliargs.rulesetid = "ntpClient" + $esxcliargs.ipaddress = $IP + try { + $esxcli.network.firewall.ruleset.allowedip.remove.Invoke($esxcliargs) + } + catch [System.Exception] { + Write-Warning "Error during AllowedIP remove. See latest errors..." + } + } + + } + ## Set NTP Client Firewall Rule AllowedIP + "Set NTP Client Firewall Rule AllowedIP ..." + foreach ($myNTP in $CurrentNTPServers) { + $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.add.CreateArgs() + $esxcliargs.ipaddress = $myNTP + $esxcliargs.rulesetid = "ntpClient" + try { + $esxcli.network.firewall.ruleset.allowedip.add.Invoke($esxcliargs) + } + catch [System.Exception] { + $ErrorMessage = $_.Exception.Message + if ($ErrorMessage -ne "Ip address already exist.") { + Write-Warning "Error during AllowedIP remove. See latest errors..." + } + } + } + ## Get New NTP Client Firewall Rule AllowedIP + "Get New NTP Client Firewall Rule AllowedIP ..." + $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.list.CreateArgs() + $esxcliargs.rulesetid = "ntpClient" + try { + $FirewallRuleAllowedIPList = $esxcli.network.firewall.ruleset.allowedip.list.Invoke($esxcliargs) + } + catch [System.Exception] { + Write-Warning "Error during Rule List. See latest errors..." + } + "`tNew Allowed IP Addresses: $($FirewallRuleAllowedIPList.AllowedIPAddresses -join ", ")" + + + } } From 4af6de8e1d5b00fb9d13fe051f97c68648a4bae3 Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Thu, 28 May 2020 20:58:53 +0200 Subject: [PATCH 32/42] Add MetaData --- Scripts/Set-VMHostSecureNTP.ps1 | 51 +++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/Scripts/Set-VMHostSecureNTP.ps1 b/Scripts/Set-VMHostSecureNTP.ps1 index 9fa4f44..2ad6771 100644 --- a/Scripts/Set-VMHostSecureNTP.ps1 +++ b/Scripts/Set-VMHostSecureNTP.ps1 @@ -1,4 +1,48 @@ function Set-VMHostSecureNTP { +<# + .NOTES + =========================================================================== + Created by: Markus Kraus + =========================================================================== + Changelog: + 2020.05 ver 1.0 Base Release + =========================================================================== + External Code Sources: + - + =========================================================================== + Tested Against Environment: + vSphere Version: vSphere 6.7 U3 + PowerCLI Version: PowerCLI 11.5 + PowerShell Version: 5.1 + OS Version: Windows 10 + Keyword: ESXi, NTP, Hardening, Security, Firewall + =========================================================================== + + .DESCRIPTION + This function sets new NTP Servers on given ESXi Hosts and configures the host firewall to only accept NTP connections from this servers. + + .Example + Get-VMHost | Set-VMHostSecureNTP -Secure + + .Example + Get-VMHost | Set-VMHostSecureNTP -Type SetSecure -NTP 10.100.1.1, 192.168.2.1 + + .PARAMETER VMHost + Specifies the hosts to configure + + .PARAMETER SetSecure + Execute Set and Secure operation for new NTP Servers + + .PARAMETER NTP + Specifies a Array of NTP Servers + + .PARAMETER Secure + Execute Secure operation for exitsting NTP Servers + +#Requires PS -Version 5.1 +#Requires -Modules VMware.VimAutomation.Core, @{ModuleName="VMware.VimAutomation.Core";ModuleVersion="11.5.0.0"} +#> + [CmdletBinding()] param( [Parameter(Mandatory=$True, ValueFromPipeline=$True, HelpMessage = "Specifies the hosts to configure.")] @@ -6,7 +50,7 @@ function Set-VMHostSecureNTP { [VMware.VimAutomation.Types.VMHost[]] $VMHost, [Parameter(Mandatory=$False, ValueFromPipeline=$False, ParameterSetName="SetSecure", HelpMessage = "Execute Set and Secure operation for new NTP Servers")] [Switch] $SetSecure, - [Parameter(Mandatory=$True, ValueFromPipeline=$False, ParameterSetName="SetSecure", HelpMessage = "Array of NTP Serbers")] + [Parameter(Mandatory=$True, ValueFromPipeline=$False, ParameterSetName="SetSecure", HelpMessage = "Specifies a Array of NTP Servers")] [ValidateNotNullorEmpty()] [Array] $NTP, [Parameter(Mandatory=$False, ValueFromPipeline=$False, ParameterSetName="Secure", HelpMessage = "Execute Secure operation for exitsting NTP Servers")] @@ -268,8 +312,5 @@ function Set-VMHostSecureNTP { } } - - end { - - } + } \ No newline at end of file From 4d1436b857e7a79b5ec14138cfe5e09b07cedaf6 Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Thu, 28 May 2020 21:01:09 +0200 Subject: [PATCH 33/42] Fix Var Naming --- Scripts/Set-VMHostSecureNTP.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/Set-VMHostSecureNTP.ps1 b/Scripts/Set-VMHostSecureNTP.ps1 index 2ad6771..1b5464e 100644 --- a/Scripts/Set-VMHostSecureNTP.ps1 +++ b/Scripts/Set-VMHostSecureNTP.ps1 @@ -197,7 +197,7 @@ function Set-VMHostSecureNTP { } - function Secure ($myhost) { + function Secure ($MyHost) { ## Get NTP Servers "Get NTP Servers ..." [Array]$CurrentNTPServers = $MyHost | Get-VMHostNtpServer From dd4bb2f415216e993d5a89fafc39f2628ddd8fbd Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Thu, 28 May 2020 21:06:40 +0200 Subject: [PATCH 34/42] fix Typos --- Scripts/Set-VMHostSecureNTP.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Scripts/Set-VMHostSecureNTP.ps1 b/Scripts/Set-VMHostSecureNTP.ps1 index 1b5464e..e6fb2b0 100644 --- a/Scripts/Set-VMHostSecureNTP.ps1 +++ b/Scripts/Set-VMHostSecureNTP.ps1 @@ -19,7 +19,7 @@ function Set-VMHostSecureNTP { =========================================================================== .DESCRIPTION - This function sets new NTP Servers on given ESXi Hosts and configures the host firewall to only accept NTP connections from this servers. + This function sets new NTP Servers on given ESXi Hosts and configures the host firewall to only accept NTP connections from these servers. .Example Get-VMHost | Set-VMHostSecureNTP -Secure @@ -74,8 +74,8 @@ function Set-VMHostSecureNTP { if($NTPService.Policy -ne "on"){ Set-VMHostService -HostService $NTPService -Policy "on" -confirm:$False | Out-Null } - ## Remove all existiing NTP Servers - "Remove all existiing NTP Servers ..." + ## Remove all existing NTP Servers + "Remove all existing NTP Servers ..." try { foreach ($OldNtpServer in ($MyHost | Get-VMHostNtpServer)) { $MyHost | Remove-VMHostNtpServer -NtpServer $OldNtpServer -Confirm:$false From 91053171e738441b8021e4c95c6246a22d915d75 Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Fri, 29 May 2020 19:17:01 +0200 Subject: [PATCH 35/42] Add Parameter Position --- Scripts/Set-VMHostSecureNTP.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/Set-VMHostSecureNTP.ps1 b/Scripts/Set-VMHostSecureNTP.ps1 index e6fb2b0..3b386fd 100644 --- a/Scripts/Set-VMHostSecureNTP.ps1 +++ b/Scripts/Set-VMHostSecureNTP.ps1 @@ -45,7 +45,7 @@ function Set-VMHostSecureNTP { [CmdletBinding()] param( - [Parameter(Mandatory=$True, ValueFromPipeline=$True, HelpMessage = "Specifies the hosts to configure.")] + [Parameter(Mandatory=$True, ValueFromPipeline=$True, Position=0, HelpMessage = "Specifies the hosts to configure.")] [ValidateNotNullorEmpty()] [VMware.VimAutomation.Types.VMHost[]] $VMHost, [Parameter(Mandatory=$False, ValueFromPipeline=$False, ParameterSetName="SetSecure", HelpMessage = "Execute Set and Secure operation for new NTP Servers")] From 7ecfd1309dc5b3b81b5b7c93e6e4c4a8ae3c268a Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Sat, 30 May 2020 20:48:19 +0200 Subject: [PATCH 36/42] ReOrg the inline function --- Scripts/Set-VMHostSecureNTP.ps1 | 109 +++----------------------------- 1 file changed, 9 insertions(+), 100 deletions(-) diff --git a/Scripts/Set-VMHostSecureNTP.ps1 b/Scripts/Set-VMHostSecureNTP.ps1 index 3b386fd..2fd2dcd 100644 --- a/Scripts/Set-VMHostSecureNTP.ps1 +++ b/Scripts/Set-VMHostSecureNTP.ps1 @@ -60,7 +60,7 @@ function Set-VMHostSecureNTP { begin { - function SetSecure ($MyHost) { + function SetNTP ($MyHost) { ## Get NTP Service "Get NTP Service from VMHost ..." $NTPService = $MyHost | Get-VMHostService | Where-Object {$_.key -eq "ntpd"} @@ -96,100 +96,6 @@ function Set-VMHostSecureNTP { ## Start NTP Service "Start NTP Service ..." Start-VMHostService -HostService $NTPService -confirm:$False | Out-Null - ## Get ESXCLI -V2 - $esxcli = Get-ESXCLI -VMHost $MyHost -v2 - ## Get NTP Client Firewall - "Get NTP Client Firewall ..." - try { - $FirewallGet = $esxcli.network.firewall.get.Invoke() - } - catch [System.Exception] { - Write-Warning "Error during Rule List. See latest errors..." - } - "`tLoded: $($FirewallGet.Loaded)" - "`tEnabled: $($FirewallGet.Enabled)" - "`tDefaultAction: $($FirewallGet.DefaultAction)" - ## Get NTP Client Firewall Rule - "Get NTP Client Firewall RuleSet ..." - $esxcliargs = $esxcli.network.firewall.ruleset.list.CreateArgs() - $esxcliargs.rulesetid = "ntpClient" - try { - $FirewallRuleList = $esxcli.network.firewall.ruleset.list.Invoke($esxcliargs) - } - catch [System.Exception] { - Write-Warning "Error during Rule List. See latest errors..." - } - "`tEnabled: $($FirewallRuleList.Enabled)" - ## Set NTP Client Firewall Rule - "Set NTP Client Firewall Rule ..." - $esxcliargs = $esxcli.network.firewall.ruleset.set.CreateArgs() - $esxcliargs.enabled = "true" - $esxcliargs.allowedall = "false" - $esxcliargs.rulesetid = "ntpClient" - try { - $esxcli.network.firewall.ruleset.set.Invoke($esxcliargs) - } - catch [System.Exception] { - $ErrorMessage = $_.Exception.Message - if ($ErrorMessage -ne "Already use allowed ip list") { - Write-Warning "Error during Rule Set. See latest errors..." - - } - - } - "Get NTP Client Firewall Rule AllowedIP ..." - $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.list.CreateArgs() - $esxcliargs.rulesetid = "ntpClient" - try { - $FirewallRuleAllowedIPList = $esxcli.network.firewall.ruleset.allowedip.list.Invoke($esxcliargs) - } - catch [System.Exception] { - Write-Warning "Error during Rule List. See latest errors..." - } - "`tAllowed IP Addresses: $($FirewallRuleAllowedIPList.AllowedIPAddresses -join ", ")" - ## Remove Existing IP from firewall rule - "Remove Existing IP from firewall rule ..." - if ($FirewallRuleAllowedIPList.AllowedIPAddresses -ne "All") { - foreach ($IP in $FirewallRuleAllowedIPList.AllowedIPAddresses) { - $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.remove.CreateArgs() - $esxcliargs.rulesetid = "ntpClient" - $esxcliargs.ipaddress = $IP - try { - $esxcli.network.firewall.ruleset.allowedip.remove.Invoke($esxcliargs) - } - catch [System.Exception] { - Write-Warning "Error during AllowedIP remove. See latest errors..." - } - } - - } - ## Set NTP Client Firewall Rule AllowedIP - "Set NTP Client Firewall Rule AllowedIP ..." - foreach ($myNTP in $NTP) { - $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.add.CreateArgs() - $esxcliargs.ipaddress = $myNTP - $esxcliargs.rulesetid = "ntpClient" - try { - $esxcli.network.firewall.ruleset.allowedip.add.Invoke($esxcliargs) - } - catch [System.Exception] { - $ErrorMessage = $_.Exception.Message - if ($ErrorMessage -ne "Ip address already exist.") { - Write-Warning "Error during AllowedIP remove. See latest errors..." - } - } - } - ## Get New NTP Client Firewall Rule AllowedIP - "Get New NTP Client Firewall Rule AllowedIP ..." - $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.list.CreateArgs() - $esxcliargs.rulesetid = "ntpClient" - try { - $FirewallRuleAllowedIPList = $esxcli.network.firewall.ruleset.allowedip.list.Invoke($esxcliargs) - } - catch [System.Exception] { - Write-Warning "Error during Rule List. See latest errors..." - } - "`tNew Allowed IP Addresses: $($FirewallRuleAllowedIPList.AllowedIPAddresses -join ", ")" ## Get New NTP Servers "Get New NTP Servers ..." $NewNTPServers = $MyHost | Get-VMHostNtpServer @@ -197,11 +103,13 @@ function Set-VMHostSecureNTP { } - function Secure ($MyHost) { + function SecureNTP ($MyHost) { ## Get NTP Servers - "Get NTP Servers ..." + "Get NTP Servers to Secure ..." [Array]$CurrentNTPServers = $MyHost | Get-VMHostNtpServer - "`tNTP Servers: $($NewNTPServers -join ", ")" + "`tNTP Servers: $($CurrentNTPServers -join ", ")" + ## Get ESXCLI -V2 + $esxcli = Get-ESXCLI -VMHost $MyHost -v2 ## Get NTP Client Firewall "Get NTP Client Firewall ..." try { @@ -304,11 +212,12 @@ function Set-VMHostSecureNTP { if ($SetSecure) { "Execute Set and Secure operation for new NTP Servers ..." - $VMHost | Foreach-Object { Write-Output (SetSecure $_) } + $VMHost | Foreach-Object { Write-Output (SetNTP $_) } + $VMHost | Foreach-Object { Write-Output (SecureNTP $_) } } if ($Secure) { "Execute Secure operation for exitsting NTP Servers ..." - $VMHost | Foreach-Object { Write-Output (Secure $_) } + $VMHost | Foreach-Object { Write-Output (SecureNTP $_) } } } From 8de58854370e1a7663d9d08ceb6e58cb8bbd8ee2 Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Sat, 30 May 2020 20:51:00 +0200 Subject: [PATCH 37/42] Change NTP input to type ipaddress --- Scripts/Set-VMHostSecureNTP.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/Set-VMHostSecureNTP.ps1 b/Scripts/Set-VMHostSecureNTP.ps1 index 2fd2dcd..c491331 100644 --- a/Scripts/Set-VMHostSecureNTP.ps1 +++ b/Scripts/Set-VMHostSecureNTP.ps1 @@ -52,7 +52,7 @@ function Set-VMHostSecureNTP { [Switch] $SetSecure, [Parameter(Mandatory=$True, ValueFromPipeline=$False, ParameterSetName="SetSecure", HelpMessage = "Specifies a Array of NTP Servers")] [ValidateNotNullorEmpty()] - [Array] $NTP, + [ipaddress[]] $NTP, [Parameter(Mandatory=$False, ValueFromPipeline=$False, ParameterSetName="Secure", HelpMessage = "Execute Secure operation for exitsting NTP Servers")] [Switch] $Secure From d2544c9418135da410670f0d5f2e89ea71c9f347 Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Sat, 30 May 2020 20:59:57 +0200 Subject: [PATCH 38/42] Other loop for "Remove all existing NTP Servers" --- Scripts/Set-VMHostSecureNTP.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Scripts/Set-VMHostSecureNTP.ps1 b/Scripts/Set-VMHostSecureNTP.ps1 index c491331..773e016 100644 --- a/Scripts/Set-VMHostSecureNTP.ps1 +++ b/Scripts/Set-VMHostSecureNTP.ps1 @@ -77,8 +77,8 @@ function Set-VMHostSecureNTP { ## Remove all existing NTP Servers "Remove all existing NTP Servers ..." try { - foreach ($OldNtpServer in ($MyHost | Get-VMHostNtpServer)) { - $MyHost | Remove-VMHostNtpServer -NtpServer $OldNtpServer -Confirm:$false + $MyHost | Get-VMHostNtpServer | Foreach-Object { + Remove-VMHostNtpServer -VMHost $MyHost -NtpServer $_ -Confirm:$false } } catch [System.Exception] { From b0dcb843aa15de12bc2c4fe1c52be3e73059b471 Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Sat, 30 May 2020 21:02:25 +0200 Subject: [PATCH 39/42] Fix tab alignments --- Scripts/Set-VMHostSecureNTP.ps1 | 54 ++++++++++++++++----------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/Scripts/Set-VMHostSecureNTP.ps1 b/Scripts/Set-VMHostSecureNTP.ps1 index 773e016..42e1885 100644 --- a/Scripts/Set-VMHostSecureNTP.ps1 +++ b/Scripts/Set-VMHostSecureNTP.ps1 @@ -114,10 +114,10 @@ function Set-VMHostSecureNTP { "Get NTP Client Firewall ..." try { $FirewallGet = $esxcli.network.firewall.get.Invoke() - } - catch [System.Exception] { - Write-Warning "Error during Rule List. See latest errors..." - } + } + catch [System.Exception] { + Write-Warning "Error during Rule List. See latest errors..." + } "`tLoded: $($FirewallGet.Loaded)" "`tEnabled: $($FirewallGet.Enabled)" "`tDefaultAction: $($FirewallGet.DefaultAction)" @@ -127,10 +127,10 @@ function Set-VMHostSecureNTP { $esxcliargs.rulesetid = "ntpClient" try { $FirewallRuleList = $esxcli.network.firewall.ruleset.list.Invoke($esxcliargs) - } - catch [System.Exception] { - Write-Warning "Error during Rule List. See latest errors..." - } + } + catch [System.Exception] { + Write-Warning "Error during Rule List. See latest errors..." + } "`tEnabled: $($FirewallRuleList.Enabled)" ## Set NTP Client Firewall Rule "Set NTP Client Firewall Rule ..." @@ -140,24 +140,24 @@ function Set-VMHostSecureNTP { $esxcliargs.rulesetid = "ntpClient" try { $esxcli.network.firewall.ruleset.set.Invoke($esxcliargs) - } - catch [System.Exception] { - $ErrorMessage = $_.Exception.Message - if ($ErrorMessage -ne "Already use allowed ip list") { - Write-Warning "Error during Rule Set. See latest errors..." - - } + } + catch [System.Exception] { + $ErrorMessage = $_.Exception.Message + if ($ErrorMessage -ne "Already use allowed ip list") { + Write-Warning "Error during Rule Set. See latest errors..." } + + } "Get NTP Client Firewall Rule AllowedIP ..." $esxcliargs = $esxcli.network.firewall.ruleset.allowedip.list.CreateArgs() $esxcliargs.rulesetid = "ntpClient" try { $FirewallRuleAllowedIPList = $esxcli.network.firewall.ruleset.allowedip.list.Invoke($esxcliargs) - } - catch [System.Exception] { - Write-Warning "Error during Rule List. See latest errors..." - } + } + catch [System.Exception] { + Write-Warning "Error during Rule List. See latest errors..." + } "`tAllowed IP Addresses: $($FirewallRuleAllowedIPList.AllowedIPAddresses -join ", ")" ## Remove Existing IP from firewall rule "Remove Existing IP from firewall rule ..." @@ -168,10 +168,10 @@ function Set-VMHostSecureNTP { $esxcliargs.ipaddress = $IP try { $esxcli.network.firewall.ruleset.allowedip.remove.Invoke($esxcliargs) - } - catch [System.Exception] { - Write-Warning "Error during AllowedIP remove. See latest errors..." - } + } + catch [System.Exception] { + Write-Warning "Error during AllowedIP remove. See latest errors..." + } } } @@ -197,10 +197,10 @@ function Set-VMHostSecureNTP { $esxcliargs.rulesetid = "ntpClient" try { $FirewallRuleAllowedIPList = $esxcli.network.firewall.ruleset.allowedip.list.Invoke($esxcliargs) - } - catch [System.Exception] { - Write-Warning "Error during Rule List. See latest errors..." - } + } + catch [System.Exception] { + Write-Warning "Error during Rule List. See latest errors..." + } "`tNew Allowed IP Addresses: $($FirewallRuleAllowedIPList.AllowedIPAddresses -join ", ")" From 9532ea9facdcabf92b46883f1e746261c8b26705 Mon Sep 17 00:00:00 2001 From: Markus Kraus Date: Thu, 30 Jul 2020 20:45:13 +0200 Subject: [PATCH 40/42] pply-OMRightsizing --- Scripts/Apply-OMRightsizing.ps1 | 145 ++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 Scripts/Apply-OMRightsizing.ps1 diff --git a/Scripts/Apply-OMRightsizing.ps1 b/Scripts/Apply-OMRightsizing.ps1 new file mode 100644 index 0000000..3972d4a --- /dev/null +++ b/Scripts/Apply-OMRightsizing.ps1 @@ -0,0 +1,145 @@ +function Apply-OMRightsizing { +<# + .NOTES + =========================================================================== + Created by: Markus Kraus + =========================================================================== + Changelog: + 2020.07 ver 1.0 Base Release + =========================================================================== + External Code Sources: + - + =========================================================================== + Tested Against Environment: + vSphere Version: vSphere 6.7 U3 + PowerCLI Version: PowerCLI 11.5 + PowerShell Version: 5.1 + OS Version: Windows 10 + Keyword: vSphere, vRealize, Rightsizing + =========================================================================== + + .DESCRIPTION + This function views or applies rightsizing recommendations from vRealize Operations to your vSphere VMs. + + .Example + Get-VM -Name test-* | Get-OMResource | Apply-OMRightsizing -ViewOnly | Sort-Object DownSizeMemGB, DownSizeCPU -Descending | Format-Table -AutoSize + + .Example + Get-VM -Name test-* | Get-OMResource | Apply-OMRightsizing -Apply -NoUpsizing + + .PARAMETER OMResources + vRealize Operations Ressources to process + + .PARAMETER ViewOnly + View Recommendations + + .PARAMETER Apply + Apply Recommendations + + .PARAMETER NoUpsizing + Apply only Downsizing Recommendations + +#Requires PS -Version 5.1 +#Requires -Modules VMware.VimAutomation.Core, @{ModuleName="VMware.VimAutomation.Core";ModuleVersion="11.5.0.0"} +#> + + [CmdletBinding()] + param( + [Parameter(Mandatory=$True, ValueFromPipeline=$True, Position=0, HelpMessage = "OM Ressources to process")] + [ValidateNotNullorEmpty()] + $OMResources, + [Parameter(Mandatory=$False, ValueFromPipeline=$False, ParameterSetName="ViewOnly", HelpMessage = "View Recommendations")] + [Switch] $ViewOnly, + [Parameter(Mandatory=$False, ValueFromPipeline=$False, ParameterSetName="Apply", HelpMessage = "Apply Recommendations")] + [Switch] $Apply, + [Parameter(Mandatory=$False, ValueFromPipeline=$False, ParameterSetName="Apply", HelpMessage = "Apply only Downsizing Recommendations")] + [Switch] $NoUpsizing + ) + Process { + if ($ViewOnly -or $Apply){ + "Collecting Report ..." + + $View = @() + + foreach ($OMResource in $OMResources){ + $DownSize = ($OMResource | Get-OMStat -Key "summary|oversized" -From ([DateTime]::Now).AddMinutes(-120) | Select-Object -Last 1).Value + $UpSize = ($OMResource | Get-OMStat -Key "summary|undersized" -From ([DateTime]::Now).AddMinutes(-120) | Select-Object -Last 1).Value + + # Mem is in KB + if($DownSize -gt 0){ + $DownSizeMem = ($OMResource | Get-OMStat -Key "summary|oversized|memory" -From ([DateTime]::Now).AddMinutes(-120) | Select-Object -Last 1).Value + $DownSizeCPU = ($OMResource | Get-OMStat -Key "summary|oversized|vcpus" -From ([DateTime]::Now).AddMinutes(-120) | Select-Object -Last 1).Value + } + else { + $DownSizeMem = 0 + $DownSizeCPU = 0 + } + + # Mem is in KB + if($UpSize -gt 0){ + $UpSizeMem = ($OMResource | Get-OMStat -Key "summary|undersized|memory" -From ([DateTime]::Now).AddMinutes(-120) | Select-Object -Last 1).Value + $UpSizeCPU = ($OMResource | Get-OMStat -Key "summary|undersized|vcpus" -From ([DateTime]::Now).AddMinutes(-120) | Select-Object -Last 1).Value + } + else { + $UpSizeMem = 0 + $UpSizeCPU = 0 + } + + $Report = [PSCustomObject] @{ + Name = $OMResource.name + DownSize = $DownSize + UpSize = $UpSize + DownSizeMem = $DownSizeMem + DownSizeMemGB = [Math]::Round(($DownSizeMem / 1048576), 0) + DownSizeCPU = $DownSizeCPU + UpSizeMem = $UpSizeMem + UpSizeMemGB = [Math]::Round(($UpSizeMem / 1048576), 0) + UpSizeCPU = $upSizeCPU + + } + $View += $Report + } + + } + if ($ViewOnly){ + $View + } + if ($Apply){ + foreach ($Object in $View) { + + if ($Object.DownSize -gt 0 -or $Object.UpSize -gt 0){ + "Processing '$($Object.Name)' ..." + $VM = Get-VM -Name $Object.Name + "Shut down '$($Object.Name)' ..." + $VM | Shutdown-VMGuest -Confirm:$False + $i = 0 + while((Get-VM -Name $VM.Name).PowerState -eq "PoweredOn"){ + $i++ + Start-Sleep 1 + Write-Progress -Activity "Check PowerState" -Status "Wait for PowerState Task..." + } + "Create Snapshot for '$($Object.Name)' ..." + $VM | New-Snapshot -Name "Pre Resize" -Memory:$false -Quiesce:$false + if ($Object.DownSize -gt 0){ + "Downsize '$($Object.Name)' ..." + $VM | Set-VM -NumCPU $($VM.NumCpu - $Object.DownSizeCPU) -MemoryGB $($VM.MemoryGB - $Object.DownSizeMemGB) -Confirm:$False + + } + if ($Object.UpSize -gt 0 -and $NoUpsizing -eq $False){ + "Upsize '$($Object.Name)' ..." + $VM = Get-VM -Name $Object.Name + $VM | Set-VM -NumCPU $($VM.NumCpu + $Object.UpSizeCPU) -MemoryGB $($VM.MemoryGB + $Object.UpSizeMemGB) -Confirm:$False + + } + #$VM = Get-VM -Name $Object.Name + #$VM | Get-VMResourceConfiguration | Set-VMResourceConfiguration -CpuReservationMhz $($VM.NumCpu * 200) -MemReservationGB $($VM.MemoryGB / 2) -Confirm:$False + "Power on '$($Object.Name)' ..." + $VM | Start-VM -Confirm:$False + } + + } + + } + + } +} \ No newline at end of file From 368ec747ac11bad953544c1fdaebeab41b31c4f8 Mon Sep 17 00:00:00 2001 From: Michael Dunsdon <38795007+dunsdon@users.noreply.github.com> Date: Mon, 21 Sep 2020 14:35:17 -0500 Subject: [PATCH 41/42] Update Backup-VCSA.psm1 Updated Code based on Comments --- Modules/Backup-VCSA/Backup-VCSA.psm1 | 655 ++++++++++++++++++++------- 1 file changed, 495 insertions(+), 160 deletions(-) diff --git a/Modules/Backup-VCSA/Backup-VCSA.psm1 b/Modules/Backup-VCSA/Backup-VCSA.psm1 index 7b790d0..b240e4c 100644 --- a/Modules/Backup-VCSA/Backup-VCSA.psm1 +++ b/Modules/Backup-VCSA/Backup-VCSA.psm1 @@ -1,204 +1,539 @@ -Function Backup-VCSAToFile { +Function Backup-VCSAToFile { <# - .NOTES - =========================================================================== + .NOTES + =========================================================================== Created by: Brian Graf - Date: October 30, 2016 + Date: October 30, 2016 Organization: VMware - Blog: www.vtagion.com - Twitter: @vBrianGraf + Blog: www.vtagion.com + Twitter: @vBrianGraf + Modifed by: Michael Dunsdon + Twitter: @MJDunsdon + Date: September 21, 2020 =========================================================================== .SYNOPSIS This function will allow you to create a full or partial backup of your - VCSA appliance. (vSphere 6.5 and higher) - + VCSA appliance. (vSphere 6.5 and higher) .DESCRIPTION Use this function to backup your VCSA to a remote location - .EXAMPLE - [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$BackupPassword = "VMw@re123" - $Comment = "First API Backup" - $LocationType = "FTP" - $location = "10.144.99.5/vcsabackup-$((Get-Date).ToString('yyyy-MM-dd-hh-mm'))" - $LocationUser = "admin" - [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$locationPassword = "VMw@re123" + [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$BackupPassword = "VMw@re123" + $Comment = "First API Backup" + $LocationType = "FTP" + $location = "10.144.99.5/vcsabackup-$((Get-Date).ToString('yyyy-MM-dd-hh-mm'))" + $LocationUser = "admin" + [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$locationPassword = "VMw@re123" PS C:\> Backup-VCSAToFile -BackupPassword $BackupPassword -LocationType $LocationType -Location $location -LocationUser $LocationUser -LocationPassword $locationPassword -Comment "This is a demo" -ShowProgress -FullBackup - - .NOTES - Credit goes to @AlanRenouf for sharing the base of this function with me which I was able to take and make more robust as well as add in progress indicators - You must be connected to the CisService for this to work, if you are not connected, the function will prompt you for your credentials + Credit goes to @AlanRenouf for sharing the base of this function with me which I was able to take and make more robust as well as add in progress indicators + You must be connected to the CisService for this to work, if you are not connected, the function will prompt you for your credentials + A CisService can also be supplied as a parameter. If a -LocationType is not chosen, the function will default to FTP. - The destination location for a backup must be an empty folder (easiest to use the get-date cmdlet in the location) - -ShowProgress will give you a progressbar as well as updates in the console - -CommonBackup will only backup the config whereas -Fullbackup grabs the historical data as well + The destination location for a backup must be an empty folder (easiest to use the get-date cmdlet in the location) + -ShowProgress will give you a progressbar as well as updates in the console + -CommonBackup will only backup the config whereas -Fullbackup grabs the historical data as well #> - param ( - [Parameter(ParameterSetName=’FullBackup’)] - [switch]$FullBackup, - [Parameter(ParameterSetName=’CommonBackup’)] - [switch]$CommonBackup, - [ValidateSet('FTPS', 'HTTP', 'SCP', 'HTTPS', 'FTP')] - $LocationType = "FTP", - $Location, - $LocationUser, - [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$LocationPassword, - [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$BackupPassword, - $Comment = "Backup job", - [switch]$ShowProgress - ) - Begin { - if (!($global:DefaultCisServers)){ - Add-Type -Assembly System.Windows.Forms - [System.Windows.Forms.MessageBox]::Show("It appears you have not created a connection to the CisServer. You will now be prompted to enter your vCenter credentials to continue" , "Connect to CisServer") | out-null - $Connection = Connect-CisServer $global:DefaultVIServer - } else { - $Connection = $global:DefaultCisServers - } - if ($FullBackup) {$parts = @("common","seat")} - if ($CommonBackup) {$parts = @("common")} - } - Process{ - $BackupAPI = Get-CisService com.vmware.appliance.recovery.backup.job - $CreateSpec = $BackupAPI.Help.create.piece.CreateExample() - $CreateSpec.parts = $parts - $CreateSpec.backup_password = $BackupPassword - $CreateSpec.location_type = $LocationType - $CreateSpec.location = $Location - $CreateSpec.location_user = $LocationUser - $CreateSpec.location_password = $LocationPassword - $CreateSpec.comment = $Comment - try { - $BackupJob = $BackupAPI.create($CreateSpec) - } - catch { - throw $_.Exception.Message - } - - - If ($ShowProgress){ - do { - $BackupAPI.get("$($BackupJob.ID)") | select id, progress, state - $progress = ($BackupAPI.get("$($BackupJob.ID)").progress) - Write-Progress -Activity "Backing up VCSA" -Status $BackupAPI.get("$($BackupJob.ID)").state -PercentComplete ($BackupAPI.get("$($BackupJob.ID)").progress) -CurrentOperation "$progress% Complete" - start-sleep -seconds 5 - } until ($BackupAPI.get("$($BackupJob.ID)").progress -eq 100 -or $BackupAPI.get("$($BackupJob.ID)").state -ne "INPROGRESS") - - Write-Progress -Activity "Backing up VCSA" -Completed - $BackupAPI.get("$($BackupJob.ID)") | select id, progress, state - } - Else { - $BackupJob | select id, progress, state - } - } - End {} + param ( + [Parameter(ParameterSetName=’FullBackup’)] + [switch]$FullBackup, + [Parameter(ParameterSetName=’CommonBackup’)] + [switch]$CommonBackup, + [ValidateSet('FTPS', 'HTTP', 'SCP', 'HTTPS', 'FTP')] + $LocationType = "FTP", + $Location, + $LocationUser, + [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$LocationPassword, + [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$BackupPassword, + $Comment = "Backup job", + [Parameter(Mandatory=$false)]$CisServer = $global:DefaultCisServers, + [switch]$ShowProgress + ) + Begin { + if ($CisServer.IsConnected) { + Write-Verbose "Connected to $($CisServer.Name)" + $connection = $CisServer + } elseif ($CisServer.gettype().name -eq "String") { + Write-Host "Prompting for CIS Server credentials. Connecting to $($CisServer)." + $Connection = Connect-CisServer $CisServer + } elseif ($global:DefaultCisServers) { + $connection = $global:DefaultCisServers + } elseif ($global:DefaultVIServer) { + Write-Host "Prompting for CIS Server credentials. Connecting to $($global:DefaultVIServer.name)." + $Connection = Connect-CisServer $global:DefaultVIServer + } + if (!$Connection) { + Write-Error "It appears you have not created a connection to the CisServer. Please Connect First and try command again. (Connect-CisServer)" + } + if ($FullBackup) {$parts = @("common","seat")} + if ($CommonBackup) {$parts = @("common")} + } + Process{ + $BackupAPI = Get-CisService 'com.vmware.appliance.recovery.backup.job' + $CreateSpec = $BackupAPI.Help.create.piece.CreateExample() + $CreateSpec.parts = $parts + $CreateSpec.backup_password = $BackupPassword + $CreateSpec.location_type = $LocationType + $CreateSpec.location = $Location + $CreateSpec.location_user = $LocationUser + $CreateSpec.location_password = $LocationPassword + $CreateSpec.comment = $Comment + try { + $BackupJob = $BackupAPI.create($CreateSpec) + } catch { + throw $_.Exception.Message + } + If ($ShowProgress){ + do { + $BackupAPI.get("$($BackupJob.ID)") | Select-Object id, progress, state + $progress = ($BackupAPI.get("$($BackupJob.ID)").progress) + Write-Progress -Activity "Backing up VCSA" -Status $BackupAPI.get("$($BackupJob.ID)").state -PercentComplete ($BackupAPI.get("$($BackupJob.ID)").progress) -CurrentOperation "$progress% Complete" + Start-Sleep -seconds 5 + } until ($BackupAPI.get("$($BackupJob.ID)").progress -eq 100 -or $BackupAPI.get("$($BackupJob.ID)").state -ne "INPROGRESS") + Write-Progress -Activity "Backing up VCSA" -Completed + $BackupAPI.get("$($BackupJob.ID)") | Select-Object id, progress, state + } Else { + $BackupJob | Select-Object id, progress, state + } + } + End {} } Function Get-VCSABackupJobs { <# - .NOTES - =========================================================================== - Created by: Brian Graf - Date: October 30, 2016 - Organization: VMware - Blog: www.vtagion.com - Twitter: @vBrianGraf + .NOTES + =========================================================================== + Created by: Brian Graf + Date: October 30, 2016 + Organization: VMware + Blog: www.vtagion.com + Twitter: @vBrianGraf + Modifed by: Michael Dunsdon + Twitter: @MJDunsdon + Date: September 21, 2020 =========================================================================== .SYNOPSIS Get-VCSABackupJobs returns a list of all backup jobs VCSA has ever performed (vSphere 6.5 and higher) - .DESCRIPTION Get-VCSABackupJobs returns a list of all backup jobs VCSA has ever performed - .EXAMPLE PS C:\> Get-VCSABackupJobs - + .EXAMPLE + PS C:\> Get-VCSABackupJobs -ShowNewest -CisServer "vcserver.sphere.local" .NOTES The values returned are read as follows: - YYYYMMDD-hhmmss-vcsabuildnumber - You can pipe the results of this function into the Get-VCSABackupStatus function - Get-VCSABackupJobs | select -First 1 | Get-VCSABackupStatus <- Most recent backup + YYYYMMDD-hhmmss-vcsabuildnumber + You can pipe the results of this function into the Get-VCSABackupStatus function + Get-VCSABackupJobs | select -First 1 | Get-VCSABackupStatus <- Most recent backup #> - param ( - [switch]$ShowNewest - ) - Begin { - if (!($global:DefaultCisServers)){ - [System.Windows.Forms.MessageBox]::Show("It appears you have not created a connection to the CisServer. You will now be prompted to enter your vCenter credentials to continue" , "Connect to CisServer") | out-null - $Connection = Connect-CisServer $global:DefaultVIServer - } else { - $Connection = $global:DefaultCisServers - } - } - Process{ - - $BackupAPI = Get-CisService com.vmware.appliance.recovery.backup.job - - try { - if ($ShowNewest) { - $results = $BackupAPI.list() - $results[0] - } else { - $BackupAPI.list() - } - } - catch { - Write-Error $Error[0].exception.Message - } - - } - - End {} + param ( + [Parameter(Mandatory=$false)][switch]$ShowNewest, + [Parameter(Mandatory=$false)]$CisServer = $global:DefaultCisServers + ) + Begin { + if ($CisServer.IsConnected) { + Write-Verbose "Connected to $($CisServer.Name)" + $connection = $CisServer + } elseif ($CisServer.gettype().name -eq "String") { + Write-Host "Prompting for CIS Server credentials. Connecting to $($CisServer)." + $Connection = Connect-CisServer $CisServer + } elseif ($global:DefaultCisServers) { + $connection = $global:DefaultCisServers + } elseif ($global:DefaultVIServer) { + Write-Host "Prompting for CIS Server credentials. Connecting to $($global:DefaultVIServer.name)." + $Connection = Connect-CisServer $global:DefaultVIServer + } + if (!$Connection) { + Write-Error "It appears you have not created a connection to the CisServer. Please Connect First and try command again. (Connect-CisServer)" + } + } + Process{ + $BackupAPI = Get-CisService 'com.vmware.appliance.recovery.backup.job' + try { + if ($ShowNewest) { + $results = $BackupAPI.list() + $results[0] + } else { + $BackupAPI.list() + } + } catch { + Write-Error $Error[0].exception.Message + } + } + End {} } Function Get-VCSABackupStatus { <# - .NOTES - =========================================================================== - Created by: Brian Graf - Date: October 30, 2016 - Organization: VMware - Blog: www.vtagion.com - Twitter: @vBrianGraf + .NOTES + =========================================================================== + Created by: Brian Graf + Date: October 30, 2016 + Organization: VMware + Blog: www.vtagion.com + Twitter: @vBrianGraf + Modifed by: Michael Dunsdon + Twitter: @MJDunsdon + Date: September 21, 2020 =========================================================================== .SYNOPSIS Returns the ID, Progress, and State of a VCSA backup (vSphere 6.5 and higher) - .DESCRIPTION Returns the ID, Progress, and State of a VCSA backup - - .EXAMPLE + .EXAMPLE PS C:\> $backups = Get-VCSABackupJobs - $backups[0] | Get-VCSABackupStatus - + $backups[0] | Get-VCSABackupStatus .NOTES The BackupID can be piped in from the Get-VCSABackupJobs function and can return multiple job statuses #> - Param ( - [parameter(ValueFromPipeline=$True)] - [string[]]$BackupID - ) - Begin { - if (!($global:DefaultCisServers)){ - [System.Windows.Forms.MessageBox]::Show("It appears you have not created a connection to the CisServer. You will now be prompted to enter your vCenter credentials to continue" , "Connect to CisServer") | out-null - $Connection = Connect-CisServer $global:DefaultVIServer - } else { - $Connection = $global:DefaultCisServers - } - - $BackupAPI = Get-CisService com.vmware.appliance.recovery.backup.job - } - Process{ - - foreach ($id in $BackupID) { - $BackupAPI.get("$id") | select id, progress, state - } - - - } - - End {} + Param ( + [parameter(Mandatory=$false,ValueFromPipeline=$True)][string[]]$BackupID, + [Parameter(Mandatory=$false)]$CisServer = $global:DefaultCisServers + ) + Begin { + if ($CisServer.IsConnected) { + Write-Verbose "Connected to $($CisServer.Name)" + $connection = $CisServer + } elseif ($CisServer.gettype().name -eq "String") { + Write-Host "Prompting for CIS Server credentials. Connecting to $($CisServer)." + $Connection = Connect-CisServer $CisServer + } elseif ($global:DefaultCisServers) { + $connection = $global:DefaultCisServers + } elseif ($global:DefaultVIServer) { + Write-Host "Prompting for CIS Server credentials. Connecting to $($global:DefaultVIServer.name)." + $Connection = Connect-CisServer $global:DefaultVIServer + } + if (!$Connection) { + Write-Error "It appears you have not created a connection to the CisServer. Please Connect First and try command again. (Connect-CisServer)" + } + } + Process{ + $BackupAPI = Get-CisService 'com.vmware.appliance.recovery.backup.job' + Foreach ($id in $BackupID) { + $BackupAPI.get("$id") | Select-Object id, progress, state + } + } + End {} +} + +Function New-VCSASchedule { +<# + .NOTES + =========================================================================== + Original Created by: Brian Graf + Blog: www.vtagion.com + Twitter: @vBrianGraf + Organization: VMware + Created / Modifed by: Michael Dunsdon + Twitter: @MJDunsdon + Date: September 21, 2020 + =========================================================================== + + .SYNOPSIS + This function will allow you to create a scheduled to backup your + VCSA appliance. (vSphere 6.7 and higher) + .DESCRIPTION + Use this function to create a schedule to backup your VCSA to a remote location + .EXAMPLE + The Below Create a schedule on Monday @11:30pm to FTP location 10.1.1.10:/vcsabackup/vcenter01 + and keep 4 backups with a Encryption Passowrd of "VMw@re123" + + $location = "ftp://10.1.1.10/vcsabackup/vcenter01" + $LocationUser = "admin" + [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$locationPassword = "VMw@re123" + $BHour = 23 + $BMin = 30 + $BDays = @("Monday") + $MaxCount = 4 + [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$BackupPassword = "VMw@re123" + + PS C:\> New-VCSASchedule -Location $location -LocationUser $LocationUser -LocationPassword $locationPassword -BackupHour $BHour -BackupMinute $BMin -backupDays $BDays -MaxCount $MaxCount -BackupPassword $BackupPassword + .EXAMPLE + The Below Create a schedule on Sunday & Wednesday @5:15am + to NFS location 10.1.1.10:/vcsabackup/vcenter01 + keep 10 backups with a Encryption Passowrd of "VMw@re123" + with Event Data included (Seat) and will delete any existing schedule. + + $location = "nfs://10.1.1.10/vcsabackup/vcenter01" + $LocationUser = "admin" + [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$locationPassword = "VMw@re123" + $BHour = 5 + $BMin = 15 + $BDays = @("Sunday", "Monday") + $MaxCount = 10 + [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$BackupPassword = "VMw@re123" + + PS C:\> New-VCSASchedule -IncludeSeat -force -Location $location -LocationUser $LocationUser -LocationPassword $locationPassword -BackupHour $BHour -BackupMinute $BMin -backupDays $BDays -MaxCount $MaxCount -BackupPassword $BackupPassword -CisServer "vcserver.sphere.local" + .NOTES + Credit goes to @AlanRenouf & @vBrianGraf for sharing the base of this function. + You must be connected to the CisService for this to work, if you are not connected, the function will prompt you for your credentials +#> + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] + param ( + [Parameter(Mandatory=$true)]$Location, + [Parameter(Mandatory=$true)]$LocationUser, + [Parameter(Mandatory=$true)][VMware.VimAutomation.Cis.Core.Types.V1.Secret]$LocationPassword, + [Parameter(Mandatory=$true)][VMware.VimAutomation.Cis.Core.Types.V1.Secret]$BackupPassword, + [Parameter(Mandatory=$true)][ValidateRange(0,23)]$BackupHour, + [Parameter(Mandatory=$true)][ValidateRange(0,59)]$BackupMinute, + [Parameter(Mandatory=$true)][ValidateSet('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday')][Array]$BackupDays = $null, + [Parameter(Mandatory=$true)][Integer]$MaxCount, + [Parameter(Mandatory=$false)]$BackupID = "default", + [Parameter(Mandatory=$false)]$CisServer = $global:DefaultCisServers, + [Parameter(Mandatory=$false)][switch]$IncludeSeat, + [Parameter(Mandatory=$false)][switch]$Force + ) + Begin { + if ($CisServer.IsConnected) { + Write-Verbose "Connected to $($CisServer.Name)" + $connection = $CisServer + } elseif ($CisServer.gettype().name -eq "String") { + Write-Host "Prompting for CIS Server credentials. Connecting to $($CisServer)." + $Connection = Connect-CisServer $CisServer + } elseif ($global:DefaultCisServers) { + $connection = $global:DefaultCisServers + } elseif ($global:DefaultVIServer) { + Write-Host "Prompting for CIS Server credentials. Connecting to $($global:DefaultVIServer.name)." + $Connection = Connect-CisServer $global:DefaultVIServer + } + if (!$Connection) { + Write-Error "It appears you have not created a connection to the CisServer. Please Connect First and try command again. (Connect-CisServer)" + } + } + Process{ + if (!(Test-VCSAScheduleSupport)) { + Write-Error "This VCSA does not support Backup Schedules." + return + } + $BackupAPI = Get-CisService -name 'com.vmware.appliance.recovery.backup.schedules' + $CreateSpec = $BackupAPI.Help.create.spec.Create() + $CreateSpec.backup_password = $BackupPassword + $CreateSpec.location = $Location + $CreateSpec.location_user = $LocationUser + $CreateSpec.location_password = $LocationPassword + $CreateSpec.Enable = $true + $CreateSpec.recurrence_info.Hour = $BackupHour + $CreateSpec.recurrence_info.Minute = $BackupMinute + $CreateSpec.recurrence_info.Days = $BackupDays + $CreateSpec.retention_info.max_count = $MaxCount + if ($IncludeSeat) { + $CreateSpec.parts = @("seat") + } else { + $CreateSpec.parts = @() + } + $CurrentSchedule = $BackupAPI.list() + + + if ($CurrentSchedule.keys.value) { + if($Force -or $PSCmdlet.ShouldContinue($CurrentSchedule.keys.value,'Delete Old Schedule')){ + $BackupAPI.delete($CurrentSchedule.keys.value) + } else { + Write-Error "There is an exisiting Schedule. Please delete before Creating a new one." + return + } + } + if ($PSCmdlet.ShouldProcess($BackupID, 'Create New Schedule.')) { + try { + $BackupJob = $BackupAPI.create($BackupID, $CreateSpec) + } + catch { + throw $_.Exception.Message + } + } + if ($BackupJob) { + Write-Host "Backup up Job Created." + return $BackupJob + } + } + End {} +} + +Function Get-VCSASchedule { +<# + .NOTES + =========================================================================== + Original Created by: Brian Graf + Blog: www.vtagion.com + Twitter: @vBrianGraf + Organization: VMware + Created / Modifed by: Michael Dunsdon + Twitter: @MJDunsdon + Date: September 21, 2020 + =========================================================================== + + .SYNOPSIS + This function will allow you to Get the scheduled backup of your + VCSA appliance. (vSphere 6.7 and higher) + .DESCRIPTION + Use this function to Get the backup schedule for your VCSA appliance. + .EXAMPLE + PS C:\> Get-VCSASchedule + .EXAMPLE + PS C:\> Get-VCSASchedule -ScheduleID 1 -CisServer "vcserver.sphere.local" + .NOTES + Credit goes to @AlanRenouf & @vBrianGraf for sharing the base of this function. + Returns a simplified object with the schedule details. + You must be connected to the CisService for this to work, if you are not connected, the function will prompt you for your credentials +#> + param ( + [Parameter(Mandatory=$False,HelpMessage="Will Filter List By ScheduleID")]$ScheduleID, + [Parameter(Mandatory=$false)]$CisServer = $global:DefaultCisServers + ) + Begin { + if ($CisServer.IsConnected) { + Write-Verbose "Connected to $($CisServer.Name)" + $connection = $CisServer + } elseif ($CisServer.gettype().name -eq "String") { + Write-Host "Prompting for CIS Server credentials. Connecting to $($CisServer)." + $Connection = Connect-CisServer $CisServer + } elseif ($global:DefaultCisServers) { + $connection = $global:DefaultCisServers + } elseif ($global:DefaultVIServer) { + Write-Host "Prompting for CIS Server credentials. Connecting to $($global:DefaultVIServer.name)." + $Connection = Connect-CisServer $global:DefaultVIServer + } + if (!$Connection) { + Write-Error "It appears you have not created a connection to the CisServer. Please Connect First and try command again. (Connect-CisServer)" + } + } + Process{ + if (!(Test-VCSAScheduleSupport)) { + Write-Error "This VCSA does not support Backup Schedules." + return + } + $BackupAPI = Get-CisService -name 'com.vmware.appliance.recovery.backup.schedules' + $Schedules = $BackupAPI.list() + if ($Schedules.count -ge 1) { + $ObjSchedule = @() + foreach ($Schedule in $Schedules) { + $ObjSchedule += $Schedule.values | Select-Object *,@{N = "ID"; e = {"$($schedule.keys.value)"}} -ExpandProperty recurrence_info -ExcludeProperty Help | Select-Object * -ExcludeProperty recurrence_info,Help | Select-Object * -ExpandProperty retention_info | Select-Object * -ExcludeProperty retention_info,Help + } + if ($ScheduleID) { + $ObjSchedule = $ObjSchedule | Where-Object {$_.ID -eq $ScheduleID} + } + return $ObjSchedule + } else { + Write-Information "No Schedule Defined." + } + } + End {} +} + +Function Remove-VCSASchedule { +<# + .NOTES + =========================================================================== + Original Created by: Brian Graf + Blog: www.vtagion.com + Twitter: @vBrianGraf + Organization: VMware + Created / Modifed by: Michael Dunsdon + Twitter: @MJDunsdon + Date: September 21, 2020 + ============================================================================ + .SYNOPSIS + This function will remove any scheduled backups of your + VCSA appliance. (vSphere 6.7 and higher) + .DESCRIPTION + Use this function to remove the backup schedule for your VCSA appliance. + .EXAMPLE + PS C:\> Remove-VCSASchedule + .EXAMPLE + PS C:\> Remove-VCSASchedule -ScheduleID 1 -CisServer "vcserver.sphere.local" + .NOTES + Credit goes to @AlanRenouf & @vBrianGraf for sharing the base of this function. + You must be connected to the CisService for this to work, if you are not connected, the function will prompt you for your credentials +#> + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] + param ( + [Parameter(Mandatory=$false)]$ScheduleID = "default", + [Parameter(Mandatory=$false)]$CisServer = $global:DefaultCisServers + ) + Begin { + if ($CisServer.IsConnected) { + Write-Verbose "Connected to $($CisServer.Name)" + $connection = $CisServer + } elseif ($CisServer.gettype().name -eq "String") { + Write-Host "Prompting for CIS Server credentials. Connecting to $($CisServer)." + $Connection = Connect-CisServer $CisServer + } elseif ($global:DefaultCisServers) { + $connection = $global:DefaultCisServers + } elseif ($global:DefaultVIServer) { + Write-Host "Prompting for CIS Server credentials. Connecting to $($global:DefaultVIServer.name)." + $Connection = Connect-CisServer $global:DefaultVIServer + } + if (!$Connection) { + Write-Error "It appears you have not created a connection to the CisServer. Please Connect First and try command again. (Connect-CisServer)" + } + } + Process{ + if (!(Test-VCSAScheduleSupport)) { + Write-Error "This VCSA does not support Backup Schedules." + return + } + if ($PSCmdlet.ShouldProcess($ScheduleID, "Removes Current Backup Schedule")) { + $BackupAPI = Get-CisService -name 'com.vmware.appliance.recovery.backup.schedules' + $BackupAPI.delete($ScheduleID) + } + } + End {} +} + +Function Test-VCSAScheduleSupport { +<# + .NOTES + =========================================================================== + Original Created by: Brian Graf + Blog: www.vtagion.com + Twitter: @vBrianGraf + Organization: VMware + Created / Modifed by: Michael Dunsdon + Twitter: @MJDunsdon + Date: September 21, 2020 + =========================================================================== + .SYNOPSIS + This function will check to see if your VCSA supports Scheduled Backups. + (vSphere 6.7 and higher) + .DESCRIPTION + Use this function to check if your VCSA supports Scheduled Backups. + .EXAMPLE + PS C:\> Test-VCSAScheduleSupport + .EXAMPLE + PS C:\> Test-VCSAScheduleSupport -CisServer "vcserver.sphere.local" + .NOTES + Credit goes to @AlanRenouf & @vBrianGraf for sharing the base of this function. + You must be connected to the CisService for this to work, if you are not connected, the function will prompt you for your credentia +#> + param ( + [Parameter(Mandatory=$false)]$CisServer = $global:DefaultCisServers + ) + Begin { + if ($CisServer.IsConnected) { + Write-Verbose "Connected to $($CisServer.Name)" + $connection = $CisServer + } elseif ($CisServer.gettype().name -eq "String") { + Write-Host "Prompting for CIS Server credentials. Connecting to $($CisServer)." + $Connection = Connect-CisServer $CisServer + } elseif ($global:DefaultCisServers) { + $connection = $global:DefaultCisServers + } elseif ($global:DefaultVIServer) { + Write-Host "Prompting for CIS Server credentials. Connecting to $($global:DefaultVIServer.name)." + $Connection = Connect-CisServer $global:DefaultVIServer + } + if (!$Connection) { + Write-Error "It appears you have not created a connection to the CisServer. Please Connect First and try command again. (Connect-CisServer)" + } + } + Process{ + if ((Get-CisService).name -contains "com.vmware.appliance.recovery.backup.schedules" ) { + Write-Verbose "This VCSA does supports Backup Schedules." + return $true + } else { + Write-Verbose "This VCSA does not support Backup Schedules." + return $false + } + } + End {} } From 0c3cad8410e13c20e675043e21b61447b51a75ea Mon Sep 17 00:00:00 2001 From: Michael Dunsdon <38795007+dunsdon@users.noreply.github.com> Date: Tue, 22 Sep 2020 13:10:16 -0500 Subject: [PATCH 42/42] Update VAMI.psm1 Made some additional Changes and adjusted the Case of Variables. --- Modules/VAMI/VAMI.psm1 | 512 ++++++++++++++++++++++++++++------------- 1 file changed, 358 insertions(+), 154 deletions(-) diff --git a/Modules/VAMI/VAMI.psm1 b/Modules/VAMI/VAMI.psm1 index 92c5d5f..ae1a985 100755 --- a/Modules/VAMI/VAMI.psm1 +++ b/Modules/VAMI/VAMI.psm1 @@ -1,4 +1,4 @@ -Function Get-VAMISummary { +Function Get-VAMISummary { <# .NOTES =========================================================================== @@ -17,7 +17,7 @@ Get-VAMISummary #> $systemVersionAPI = Get-CisService -Name 'com.vmware.appliance.system.version' - $results = $systemVersionAPI.get() | select product, type, version, build, install_time + $results = $systemVersionAPI.get() | select product, type, version, build, install_time, releasedate $systemUptimeAPI = Get-CisService -Name 'com.vmware.appliance.system.uptime' $ts = [timespan]::fromseconds($systemUptimeAPI.get().toString()) @@ -29,6 +29,7 @@ Version = $results.version; Build = $results.build; InstallTime = $results.install_time; + ReleaseDate = $results.releasedate; Uptime = $uptime } $summaryResult @@ -109,6 +110,7 @@ Function Get-VAMIAccess { Console = $consoleAccess; DCUI = $dcuiAccess; BashShell = $shellAccess.enabled; + BashTimeout = $shellAccess.timeout; SSH = $sshAccess } $accessResult @@ -122,7 +124,10 @@ Function Get-VAMITime { Organization: VMware Blog: www.virtuallyghetto.com Twitter: @lamw - =========================================================================== + Modifed by: Michael Dunsdon + Twitter: @MJDunsdon + Date: September 16, 2020 + =========================================================================== .SYNOPSIS This function retrieves the time and NTP info from VAMI interface (5480) for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA. @@ -131,12 +136,16 @@ Function Get-VAMITime { .EXAMPLE Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1! Get-VAMITime + .NOTES + Modified script to account for Newer VCSA. Script supports 6.5 and 6.7 VCSAs #> - $systemTimeAPI = Get-CisService -Name 'com.vmware.appliance.system.time' + $systemTimeAPI = ( Get-VAMIServiceAPI -NameFilter "system.time") $timeResults = $systemTimeAPI.get() - $timeSync = (Get-CisService -Name 'com.vmware.appliance.techpreview.timesync').get() - $timeSyncMode = $timeSync.mode + $timeSyncMode = ( Get-VAMIServiceAPI -NameFilter "timesync").get() + if ($timeSyncMode.mode) { + $timeSyncMode = $timeSync.mode + } $timeResult = [pscustomobject] @{ Timezone = $timeResults.timezone; @@ -148,13 +157,84 @@ Function Get-VAMITime { } if($timeSyncMode -eq "NTP") { - $ntpServers = (Get-CisService -Name 'com.vmware.appliance.techpreview.ntp').get() - $timeResult.NTPServers = $ntpServers.servers - $timeResult.NTPStatus = $ntpServers.status + $ntpServers = ( Get-VAMIServiceAPI -NameFilter "ntp").get() + if ($ntpServers.servers) { + $timeResult.NTPServers = $ntpServers.servers + $timeResult.NTPStatus = $ntpServers.status + } else { + $timeResult.NTPServers = $ntpServers + $timeResult.NTPStatus = ( Get-VAMIServiceAPI -NameFilter "ntp").test(( Get-VAMIServiceAPI -NameFilter "ntp").get()).status + } } $timeResult } +Function Set-VAMITimeSync { +<# + .NOTES + =========================================================================== + Inspired by: William Lam + Organization: VMware + Blog: www.virtuallyghetto.com + Twitter: @lamw + Created by: Michael Dunsdon + Twitter: @MJDunsdon + Date: September 21, 2020 + =========================================================================== + .SYNOPSIS + This function sets the time and NTP info from VAMI interface (5480) + for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA. + .DESCRIPTION + Function to return current Time and NTP information + .EXAMPLE + Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1! + Set-VAMITimeSync -SyncMode "NTP" -TimeZone "US/Pacific" -NTPServers "10.0.0.10,10.0.0.11,10.0.0.12" + .NOTES + Create script to Set NTP for Newer VCSA. Script supports 6.7 VCSAs +#> + param( + [Parameter(Mandatory=$true)] + [ValidateSet('Disabled', 'NTP', 'Host')] + [String]$SyncMode, + [Parameter(Mandatory=$False,HelpMessage="TimeZone Name needs to be in Posix Naming / Unix format")] + [String]$TimeZone, + [Parameter(Mandatory=$false,HelpMessage="NTP Servers need to be either a string separated by ',' or an array of servers")] + $NTPServers + ) + + $timeSyncMode = ( Get-VAMIServiceAPI -NameFilter "timesync").get() + if ($timeSyncMode.gettype().name -eq "PSCustomObject") { + if ($SyncMode.ToUpper() -ne $timeSyncMode.mode.toupper()) { + $timesyncapi = (Get-VAMIServiceAPI -NameFilter "timesync") + $timesyncconfig = $timesyncapi.help.set.config.createexample() + $timesyncconfig = $Sync + $timesyncapi.set($timesyncconfig) + } + } else { + if ($SyncMode.ToUpper() -ne $timeSyncMode.toupper()) { + $timesyncapi = (Get-VAMIServiceAPI -NameFilter "timesync") + $timesyncapi.set($Sync) + } + if ($NTPServers) { + $ntpapi = (Get-VAMIServiceAPI -NameFilter "ntp") + if ($NTPServers.gettype().Name -eq "String") { + $NTPServersArray = ($NTPServers -split ",").trim() + } else { + $NTPServersArray = $NTPServers + } + if ($NTPServersArray -ne $ntpapi.get()) { + $ntpapi.set($NTPServersArray) + } + } + if ($TimeZone) { + $timezoneapi = (Get-VAMIServiceAPI -NameFilter "timezone") + if ($TimeZone -ne ($timezoneapi.get())) { + $timezoneapi.set($TimeZone) + } + } + } +} + Function Get-VAMINetwork { <# .NOTES @@ -163,6 +243,9 @@ Function Get-VAMINetwork { Organization: VMware Blog: www.virtuallyghetto.com Twitter: @lamw + Modifed by: Michael Dunsdon + Twitter: @MJDunsdon + Date: September 21, 2020 =========================================================================== .SYNOPSIS This function retrieves network information from VAMI interface (5480) @@ -172,22 +255,27 @@ Function Get-VAMINetwork { .EXAMPLE Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1! Get-VAMINetwork + .NOTES + Modified script to account for Newer VCSA. Script supports 6.5 and 6.7 VCSAs #> $netResults = @() - $Hostname = (Get-CisService -Name 'com.vmware.appliance.networking.dns.hostname').get() - $dns = (Get-CisService -Name 'com.vmware.appliance.networking.dns.servers').get() + $Hostname = ( Get-VAMIServiceAPI -NameFilter "dns.hostname").get() + $dns = (Get-VAMIServiceAPI -NameFilter "dns.servers").get() Write-Host "Hostname: " $hostname Write-Host "DNS Servers: " $dns.servers - $interfaces = (Get-CisService -Name 'com.vmware.appliance.networking.interfaces').list() + $interfaces = (Get-VAMIServiceAPI -NameFilter "interfaces").list() foreach ($interface in $interfaces) { - $ipv4API = (Get-CisService -Name 'com.vmware.appliance.techpreview.networking.ipv4') - $spec = $ipv4API.Help.get.interfaces.CreateExample() - $spec+= $interface.name - $ipv4result = $ipv4API.get($spec) - + $ipv4API = (Get-VAMIServiceAPI -NameFilter "ipv4") + if ($ipv4API.help.get.psobject.properties.name -like "*_*") { + $ipv4result = $ipv4API.get($interface.Name) + $Updateable = $ipv4result.configurable + } else { + $ipv4result = $ipv4API.get(@($interface.Name)) + $Updateable = $ipv4result.updateable + } $interfaceResult = [pscustomobject] @{ Inteface = $interface.name; MAC = $interface.mac; @@ -196,7 +284,7 @@ Function Get-VAMINetwork { IP = $ipv4result.address; Prefix = $ipv4result.prefix; Gateway = $ipv4result.default_gateway; - Updateable = $ipv4result.updateable + Updateable = $Updateable } $netResults += $interfaceResult } @@ -286,6 +374,9 @@ Function Get-VAMIStorageUsed { Organization: VMware Blog: www.virtuallyghetto.com Twitter: @lamw + Modifed by: Michael Dunsdon + Twitter: @MJDunsdon + Date: September 16, 2020 =========================================================================== .SYNOPSIS This function retrieves the individaul OS partition storage utilization @@ -295,70 +386,49 @@ Function Get-VAMIStorageUsed { .EXAMPLE Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1! Get-VAMIStorageUsed + .NOTES + Modified script to account for Newer VCSA. Script supports 6.5 and 6.7 VCSAs. + Also modifed the static list of filesystems to be more dynamic in nature to account for the differences in VCSA versions. #> + $monitoringAPI = Get-CisService 'com.vmware.appliance.monitoring' $querySpec = $monitoringAPI.help.query.item.CreateExample() # List of IDs from Get-VAMIStatsList to query - $querySpec.Names = @( - "storage.used.filesystem.autodeploy", - "storage.used.filesystem.boot", - "storage.used.filesystem.coredump", - "storage.used.filesystem.imagebuilder", - "storage.used.filesystem.invsvc", - "storage.used.filesystem.log", - "storage.used.filesystem.netdump", - "storage.used.filesystem.root", - "storage.used.filesystem.updatemgr", - "storage.used.filesystem.vcdb_core_inventory", - "storage.used.filesystem.vcdb_seat", - "storage.used.filesystem.vcdb_transaction_log", - "storage.totalsize.filesystem.autodeploy", - "storage.totalsize.filesystem.boot", - "storage.totalsize.filesystem.coredump", - "storage.totalsize.filesystem.imagebuilder", - "storage.totalsize.filesystem.invsvc", - "storage.totalsize.filesystem.log", - "storage.totalsize.filesystem.netdump", - "storage.totalsize.filesystem.root", - "storage.totalsize.filesystem.updatemgr", - "storage.totalsize.filesystem.vcdb_core_inventory", - "storage.totalsize.filesystem.vcdb_seat", - "storage.totalsize.filesystem.vcdb_transaction_log" - ) + $querySpec.Names = ($monitoringAPI.list() | Where-Object {($_.name -like "*storage.used.filesystem*") -or ($_.name -like "*storage.totalsize.filesystem*") } | Select-Object id | Sort-Object -Property id).id.value # Tuple (Filesystem Name, Used, Total) to store results $storageStats = @{ + "archive"=@{"name"="/storage/archive";"used"=0;"total"=0}; "autodeploy"=@{"name"="/storage/autodeploy";"used"=0;"total"=0}; "boot"=@{"name"="/boot";"used"=0;"total"=0}; - "coredump"=@{"name"="/storage/core";"used"=0;"total"=0}; + "core"=@{"name"="/storage/core";"used"=0;"total"=0}; "imagebuilder"=@{"name"="/storage/imagebuilder";"used"=0;"total"=0}; "invsvc"=@{"name"="/storage/invsvc";"used"=0;"total"=0}; "log"=@{"name"="/storage/log";"used"=0;"total"=0}; "netdump"=@{"name"="/storage/netdump";"used"=0;"total"=0}; "root"=@{"name"="/";"used"=0;"total"=0}; "updatemgr"=@{"name"="/storage/updatemgr";"used"=0;"total"=0}; - "vcdb_core_inventory"=@{"name"="/storage/db";"used"=0;"total"=0}; - "vcdb_seat"=@{"name"="/storage/seat";"used"=0;"total"=0}; - "vcdb_transaction_log"=@{"name"="/storage/dblog";"used"=0;"total"=0} + "db"=@{"name"="/storage/db";"used"=0;"total"=0}; + "seat"=@{"name"="/storage/seat";"used"=0;"total"=0}; + "dblog"=@{"name"="/storage/dblog";"used"=0;"total"=0}; + "swap"=@{"name"="swap";"used"=0;"total"=0} } $querySpec.interval = "DAY1" $querySpec.function = "MAX" - $querySpec.start_time = ((get-date).AddDays(-1)) + $querySpec.start_time = ((Get-Date).AddDays(-1)) $querySpec.end_time = (Get-Date) - $queryResults = $monitoringAPI.query($querySpec) | Select * -ExcludeProperty Help + $queryResults = $monitoringAPI.query($querySpec) | Select-Object * -ExcludeProperty Help foreach ($queryResult in $queryResults) { # Update hash if its used storage results + $key = ((($queryResult.name).toString()).split(".")[-1]) -replace "coredump","core" -replace "vcdb_","" -replace "core_inventory","db" -replace "transaction_log","dblog" + $value = [Math]::Round([int]($queryResult.data[1]).toString()/1MB,2) if($queryResult.name -match "used") { - $key = (($queryResult.name).toString()).split(".")[-1] - $value = [Math]::Round([int]($queryResult.data[1]).toString()/1MB,2) $storageStats[$key]["used"] = $value # Update hash if its total storage results } else { - $key = (($queryResult.name).toString()).split(".")[-1] - $value = [Math]::Round([int]($queryResult.data[1]).toString()/1MB,2) $storageStats[$key]["total"] = $value } } @@ -406,7 +476,6 @@ Function Get-VAMIService { if($Name -ne "") { $vMonAPI = Get-CisService 'com.vmware.appliance.vmon.service' - try { $serviceStatus = $vMonAPI.get($name,0) $serviceString = [pscustomobject] @{ @@ -423,7 +492,6 @@ Function Get-VAMIService { } else { $vMonAPI = Get-CisService 'com.vmware.appliance.vmon.service' $services = $vMonAPI.list_details() - $serviceResult = @() foreach ($key in $services.keys | Sort-Object -Property Value) { $serviceString = [pscustomobject] @{ @@ -448,7 +516,7 @@ Function Start-VAMIService { Organization: VMware Blog: www.virtuallyghetto.com Twitter: @lamw - =========================================================================== + =========================================================================== .SYNOPSIS This function retrieves list of services in VAMI interface (5480) for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA. @@ -470,8 +538,8 @@ Function Start-VAMIService { $vMonAPI = Get-CisService 'com.vmware.appliance.vmon.service' try { - Write-Host "Starting $name service ..." - $vMonAPI.start($name) + Write-Host "Starting $Name service ..." + $vMonAPI.start($Name) } catch { Write-Error $Error[0].exception.Message } @@ -507,8 +575,8 @@ Function Stop-VAMIService { $vMonAPI = Get-CisService 'com.vmware.appliance.vmon.service' try { - Write-Host "Stopping $name service ..." - $vMonAPI.stop($name) + Write-Host "Stopping $Name service ..." + $vMonAPI.stop($Name) } catch { Write-Error $Error[0].exception.Message } @@ -556,15 +624,20 @@ Function Get-VAMIUser { Organization: VMware Blog: www.virtuallyghetto.com Twitter: @lamw - =========================================================================== - .SYNOPSIS - This function retrieves VAMI local users using VAMI interface (5480) + Modifed by: Michael Dunsdon + Twitter: @MJDunsdon + Date: September 16, 2020 + =========================================================================== + .SYNOPSIS + This function retrieves VAMI local users using VAMI interface (5480) for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA. - .DESCRIPTION - Function to retrieve VAMI local users - .EXAMPLE + .DESCRIPTION + Function to retrieve VAMI local users + .EXAMPLE Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1! Get-VAMIUser + .NOTES + Modified script to account for Newer VCSA. Script supports 6.5 and 6.7 VCSAs. #> param( [Parameter( @@ -575,42 +648,47 @@ Function Get-VAMIUser { [String]$Name ) - $userAPI = Get-CisService 'com.vmware.appliance.techpreview.localaccounts.user' + $userAPI = Get-VAMIServiceAPI -NameFilter "accounts" + $UserResults = @() - $userResults = @() - - if($Name -ne "") { + if (($Name -ne "") -and ($null -ne $Name)) { try { - $user = $userAPI.get($name) - - $userString = [pscustomobject] @{ - User = $user.username - Name = $user.fullname - Email = $user.email - Status = $user.status - PasswordStatus = $user.passwordstatus - Role = $user.role - } - $userResults += $userString + $Users = $UserAPI.get($name) } catch { Write-Error $Error[0].exception.Message } } else { - $users = $userAPI.list() - - foreach ($user in $users) { - $userString = [pscustomobject] @{ - User = $user.username - Name = $user.fullname - Email = $user.email - Status = $user.status - PasswordStatus = $user.passwordstatus - Role = $user.role + $Users = $UserAPI.list() + } + if ($Users.status) { + foreach ($User in $Users) { + $UserString = [pscustomobject] @{ + User = $User.username + Name = $User.fullname + Email = $User.email + Status = $User.status + PasswordStatus = $User.passwordstatus + Roles = @($User.role) } - $userResults += $userString + $UserResults += $UserString + } + } else { + foreach ($User in $Users) { + $UserInfo = $userAPI.get($user) + $UserString = [pscustomobject] @{ + User = $User.value + Name = $UserInfo.fullname + Email = $UserInfo.email + Status = $UserInfo.enabled + LastPasswordChange = $UserInfo.last_password_change + PasswordExpiresAt = $UserInfo.password_expires_at + PasswordStatus = if ($UserInfo.has_password) { if ((!!$UserInfo.password_expires_at) -and ([datetime]$UserInfo.password_expires_at -lt (get-date))) {"good"} else {"expired"}} else { "notset"} + Roles = $UserInfo.roles + } + $UserResults += $UserString } } - $userResults + $UserResults } Function New-VAMIUser { @@ -621,53 +699,144 @@ Function New-VAMIUser { Organization: VMware Blog: www.virtuallyghetto.com Twitter: @lamw - =========================================================================== - .SYNOPSIS - This function to create new VAMI local user using VAMI interface (5480) + Modifed by: Michael Dunsdon + Twitter: @MJDunsdon + Date: September 16, 2020 + =========================================================================== + .SYNOPSIS + This function to create new VAMI local user using VAMI interface (5480) for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA. - .DESCRIPTION - Function to create a new VAMI local user - .EXAMPLE + .DESCRIPTION + Function to create a new VAMI local user + .EXAMPLE Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1! - New-VAMIUser -name lamw -fullname "William Lam" -role "operator" -email "lamw@virtuallyghetto.com" -password "VMware1!" + New-VAMIUser -name lamw -fullname "William Lam" -role "operator" -email "lamw@virtuallyghetto.com" -password "VMware1!" -passwordexpires -passwordexpiresat "1/1/1970" -maxpasswordage 90 + .NOTES + Modified script to account for Newer VCSA. Script supports 6.5 and 6.7 VCSAs. + Also added new Parameters to script. #> param( - [Parameter( - Mandatory=$true) - ] - [String]$name, - [Parameter( - Mandatory=$true) - ] - [String]$fullname, - [Parameter( - Mandatory=$true) - ] - [ValidateSet("admin","operator","superAdmin")][String]$role, - [Parameter( - Mandatory=$false) - ] - [String]$email="", - [Parameter( - Mandatory=$true) - ] - [String]$password + [Parameter(Mandatory=$true)] + [String]$Name, + [Parameter(Mandatory=$true)] + [String]$FullName, + [Parameter(Mandatory=$true)] + [ValidateSet("admin","operator","superAdmin")] + [String]$Role, + [Parameter(Mandatory=$false)] + [String]$Email="", + [Parameter(Mandatory=$true)] + [String]$Password, + [Parameter(Mandatory=$false)] + [switch]$PasswordExpires, + [Parameter(Mandatory=$false)] + [String]$PasswordExpiresAt = $null, + [Parameter(Mandatory=$false)] + [String]$MaxPasswordAge = 90 ) - $userAPI = Get-CisService 'com.vmware.appliance.techpreview.localaccounts.user' - $createSpec = $userAPI.Help.add.config.CreateExample() + $userAPI = Get-VAMIServiceAPI -NameFilter "accounts" + if ($userAPI.name -eq 'com.vmware.appliance.techpreview.localaccounts.user') { + $CreateSpec = $UserAPI.Help.add.config.CreateExample() + } else { + $CreateSpec = $UserAPI.Help.create.config.CreateExample() + } - $createSpec.username = $name - $createSpec.fullname = $fullname - $createSpec.role = $role - $createSpec.email = $email - $createSpec.password = [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$password + $CreateSpec.fullname = $FullName + $CreateSpec.role = $Role + $CreateSpec.email = $Email + $CreateSpec.password = [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$Password + + if ($CreateSpec.psobject.properties.name -contains "username") { + $CreateSpec.username = $Name + try { + Write-Host "Creating new user $Name ..." + $UserAPI.add($CreateSpec) + } catch { + Write-Error $Error[0].exception.Message + } + } else { + $CreateSpec.password_expires = $PasswordExpires + $CreateSpec.password_expires_at = $PasswordExpiresAt + $CreateSpec.max_days_between_password_change = $MaxPasswordAge + try { + Write-Host "Creating new user $Name ..." + $UserAPI.create($Name, $CreateSpec) + } catch { + Write-Error $Error[0].exception.Message + } + } +} - try { - Write-Host "Creating new user $name ..." - $userAPI.add($createSpec) - } catch { - Write-Error $Error[0].exception.Message +Function Update-VAMIUser { +<# + .NOTES + =========================================================================== + Inspired by: William Lam + Organization: VMware + Blog: www.virtuallyghetto.com + Twitter: @lamw + Created by: Michael Dunsdon + Twitter: @MJDunsdon + Date: September 21, 2020 + =========================================================================== + .SYNOPSIS + This function to update fields of a VAMI local user using VAMI interface (5480) + for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA. + .DESCRIPTION + Function to update fields of a VAMI local user + .EXAMPLE + Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1! + Update-VAMIUser -name lamw -fullname "William Lam" -role "operator" -email "lamw@virtuallyghetto.com" -password "VMware1!" -passwordexpires -passwordexpiresat "1/1/1970" -maxpasswordage 90 + .NOTES + Created script to allow updating of an exisiting user account. Script supports 6.5 and 6.7 VCSAs. +#> + param( + [Parameter(Mandatory=$true)] + [String]$Name, + [Parameter(Mandatory=$false)] + [String]$FullName, + [Parameter(Mandatory=$false)] + [ValidateSet("admin","operator","superAdmin")] + [String]$Role, + [Parameter(Mandatory=$false)] + [String]$Email="", + [Parameter(Mandatory=$false)] + [String]$Password = $null, + [Parameter(Mandatory=$false)] + [switch]$PasswordExpires, + [Parameter(Mandatory=$false)] + [String]$PasswordExpiresAt = $null, + [Parameter(Mandatory=$false)] + [String]$MaxPasswordAge = 90 + ) + + $userAPI = Get-VAMIServiceAPI -NameFilter "accounts" + $UpdateSpec = $UserAPI.Help.set.config.CreateExample() + + $UpdateSpec.fullname = $FullName + $UpdateSpec.role = $Role + $UpdateSpec.email = $Email + + if ($UpdateSpec.psobject.properties.name -contains "username") { + $UpdateSpec.username = $Name + try { + Write-Host "Updating Settings for user $Name ..." + $UserAPI.set($UpdateSpec) + } catch { + Write-Error $Error[0].exception.Message + } + } else { + $UpdateSpec.password = [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$Password + $UpdateSpec.password_expires = $PasswordExpires + $UpdateSpec.password_expires_at = $PasswordExpiresAt + $UpdateSpec.max_days_between_password_change = $MaxPasswordAge + try { + Write-Host "Updating Settings for user $Name ..." + $UserAPI.update($Name, $UpdateSpec) + } catch { + Write-Error $Error[0].exception.Message + } } } @@ -679,32 +848,30 @@ Function Remove-VAMIUser { Organization: VMware Blog: www.virtuallyghetto.com Twitter: @lamw - =========================================================================== - .SYNOPSIS - This function to remove VAMI local user using VAMI interface (5480) + Modifed by: Michael Dunsdon + Twitter: @MJDunsdon + Date: September 21, 2020 + =========================================================================== + .SYNOPSIS + This function to remove VAMI local user using VAMI interface (5480) for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA. - .DESCRIPTION - Function to remove VAMI local user - .EXAMPLE + .DESCRIPTION + Function to remove VAMI local user + .EXAMPLE Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1! Get-VAMIAccess + .NOTES + Modified script to account for Newer VCSA. Script supports 6.5 and 6.7 VCSAs. #> + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param( - [Parameter( - Mandatory=$true) - ] - [String]$name, - [Parameter( - Mandatory=$false) - ] - [boolean]$confirm=$false + [Parameter(Mandatory=$true)] + [String]$Name ) - - if(!$confirm) { - $answer = Read-Host -Prompt "Do you want to delete user $name (Y or N)" - if($answer -eq "Y" -or $answer -eq "y") { - $userAPI = Get-CisService 'com.vmware.appliance.techpreview.localaccounts.user' - + Begin {} + Process{ + if($PSCmdlet.ShouldProcess($Name,'Delete')) { + $userAPI = Get-VAMIServiceAPI -NameFilter "accounts" try { Write-Host "Deleting user $name ..." $userAPI.delete($name) @@ -713,4 +880,41 @@ Function Remove-VAMIUser { } } } -} \ No newline at end of file + End{} +} + +Function Get-VAMIServiceAPI { +<# + .NOTES + =========================================================================== + Inspired by: William Lam + Organization: VMware + Blog: www.virtuallyghetto.com + Twitter: @lamw + Created by: Michael Dunsdon + Twitter: @MJDunsdon + Date: September 21, 2020 + =========================================================================== + .SYNOPSIS + This function returns the Service Api Based on a String of Service Name. + .DESCRIPTION + Function to find and get service api based on service name string + .EXAMPLE + Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1! + Get-VAMIUser -NameFilter "accounts" + .NOTES + Script supports 6.5 and 6.7 VCSAs. + Function Gets all Service Api Names and filters the list based on NameFilter + If Multiple Serivces are returned it takes the Top one. +#> + param( + [Parameter(Mandatory=$true)] + [String]$NameFilter + ) + + $ServiceAPI = Get-CisService | Where-Object {$_.name -like "*$($NameFilter)*"} + if (($ServiceAPI.count -gt 1) -and $NameFilter) { + $ServiceAPI = ($ServiceAPI | Sort-Object -Property Name)[0] + } + return $ServiceAPI +}