├── Configurations ├── PowerCLI │ └── pcli01-PowerCLI.ps1 ├── VmwDatacenter │ ├── cd01-vCenter-Datacenter.ps1 │ ├── cd02-vCenter-Datacenter.ps1 │ └── cd03-vCenter-Datacenter.ps1 └── vmwFolder │ ├── cf01-vCenter-Folder.ps1 │ ├── cf02-vCenter-Folder.ps1 │ └── cf03-vCenter-Folder.ps1 ├── History.txt ├── LICENSE.txt ├── README.md ├── Tools ├── Get-TargetGuid.ps1 ├── Test-DscConfiguration.ps1 ├── vSphereDSC-Logo-small.jpg └── vSphereDSC-Module-To-Pull-Server.ps1 ├── vSphereDSC.psd1 ├── vSphereDSC.psm1 └── vSphereDSCHelper.ps1 /Configurations/PowerCLI/pcli01-PowerCLI.ps1: -------------------------------------------------------------------------------- 1 | # Configure PowerCLi on vEng 2 | # 3 | # Tested platform: 4 | # Windows 2012 R2 5 | # PowerShell v5 Production Preview 6 | # 7 | 8 | $tgtName = 'vEng.local.lab' 9 | $pcliName = 'VMware-PowerCLI-6.3.0-3737840.exe' 10 | 11 | $configName = $tgtName.Split('.')[0] 12 | 13 | Configuration $configName 14 | { 15 | Import-DscResource -ModuleName PSDesiredStateConfiguration 16 | 17 | Node $AllNodes.NodeName 18 | { 19 | File DirectoryCopy 20 | { 21 | Ensure = "Present" 22 | Type = "File" 23 | Recurse = $true 24 | SourcePath = "\\Pull\Repository\PowerCLI\$($pcliName)" 25 | DestinationPath = "%windir%\Temp\$($pcliName)" 26 | } 27 | 28 | Log AfterDirectoryCopy 29 | { 30 | Message = "PowerCLI installation file copied" 31 | DependsOn = "[File]DirectoryCopy" 32 | } 33 | 34 | Package Install-PowerCli 35 | { 36 | Name = "VMware vSphere PowerCLI" 37 | Path = "C:\Windows\Temp\$($pcliName)" 38 | Arguments = '/b"C:\Windows\Temp" /VADDLOCAL=ALL /S /V"/qn REBOOT=ReallySuppress"' 39 | ProductId = '' 40 | Ensure= "Present" 41 | DependsOn = "[File]DirectoryCopy" 42 | } 43 | 44 | Log AfterInstall 45 | { 46 | Message = "PowerCLI installed" 47 | DependsOn = "[Package]Install-PowerCLI" 48 | } 49 | } 50 | } 51 | 52 | $configData = @{ 53 | AllNodes = @( 54 | @{ 55 | NodeName = $configName 56 | } 57 | ) 58 | } 59 | 60 | Invoke-Expression "$($configName) -ConfigurationData `$configData -OutputPath '.\DSC'" 61 | 62 | Start-DscConfiguration -ComputerName $configName -Wait -Verbose -Force -Path .\DSC 63 | -------------------------------------------------------------------------------- /Configurations/VmwDatacenter/cd01-vCenter-Datacenter.ps1: -------------------------------------------------------------------------------- 1 | enum Ensure { 2 | Absent 3 | Present 4 | } 5 | 6 | $tgtName = 'vEng.local.lab' 7 | $configName = 'vmw' 8 | 9 | Configuration $configName 10 | { 11 | param( 12 | [System.Management.Automation.PSCredential]$Credential 13 | ) 14 | 15 | Import-DscResource -ModuleName vSphereDSC 16 | 17 | Node $AllNodes.NodeName 18 | { 19 | $number = 0 20 | foreach($datacenter in $Node.Datacenters) 21 | { 22 | $number++ 23 | $dcName = "Datacenter$number" 24 | VmwDatacenter $dcName 25 | { 26 | Name = $datacenter.DatacenterName 27 | Path = $datacenter.Path 28 | Ensure = $datacenter.Ensure 29 | vServer = $Allnodes.Server 30 | vCredential = $Allnodes.Credential 31 | } 32 | } 33 | } 34 | } 35 | 36 | #region VCSA Account 37 | $vcUser = '' 38 | $vcPswd = '' 39 | $sVcCred = @{ 40 | TypeName = 'System.Management.Automation.PSCredential' 41 | ArgumentList = $vcUser,(ConvertTo-SecureString -String $vcPswd -AsPlainText -Force) 42 | } 43 | $vcCred = New-Object @sVcCred 44 | #endregion 45 | 46 | $ConfigData = @{ 47 | AllNodes = @( 48 | @{ 49 | NodeName = '*' 50 | Server = 'vcsa.local.lab' 51 | Credential = $vcCred 52 | PSDscAllowPlainTextPassword=$true 53 | PSDscAllowDomainUser = $true 54 | }, 55 | @{ 56 | NodeName = $configName 57 | Datacenters = @( 58 | @{ 59 | DatacenterName = 'DC1' 60 | Path = '/' 61 | Ensure = [Ensure]::Present 62 | } 63 | ) 64 | } 65 | ) 66 | } 67 | 68 | . "$(Split-Path $MyInvocation.MyCommand.Path)\..\..\Tools\Get-TargetGuid.ps1" 69 | $guid = Get-TargetGuid -TargetName $tgtName 70 | 71 | Invoke-Expression "$($configName) -ConfigurationData `$configData -OutputPath '.\DSC'" 72 | 73 | $pullShare = '\\pull\DSCService\Configuration\' 74 | $mof = ".\DSC\$($configName).mof" 75 | $tgtMof = "$pullshare\$guid.mof" 76 | 77 | Copy-Item -Path $mof -Destination $tgtMof 78 | New-DSCChecksum $tgtMof -Force 79 | 80 | # For testing with Start-DscCOnfiguration 81 | Copy-Item -Path $mof -Destination ".\DSC\$($tgtName.Split('.')[0]).mof" 82 | -------------------------------------------------------------------------------- /Configurations/VmwDatacenter/cd02-vCenter-Datacenter.ps1: -------------------------------------------------------------------------------- 1 | enum Ensure { 2 | Absent 3 | Present 4 | } 5 | 6 | $tgtName = 'vEng.local.lab' 7 | $configName = 'vmw' 8 | 9 | Configuration $configName 10 | { 11 | param( 12 | [System.Management.Automation.PSCredential]$Credential 13 | ) 14 | 15 | Import-DscResource -ModuleName vSphereDSC 16 | 17 | Node $AllNodes.NodeName 18 | { 19 | $number = 0 20 | foreach($datacenter in $Node.Datacenters) 21 | { 22 | $number++ 23 | $dcName = "Datacenter$number" 24 | VmwDatacenter $dcName 25 | { 26 | Name = $datacenter.DatacenterName 27 | Path = $datacenter.Path 28 | Ensure = $datacenter.Ensure 29 | vServer = $Allnodes.Server 30 | vCredential = $Allnodes.Credential 31 | } 32 | } 33 | } 34 | } 35 | 36 | #region VCSA Account 37 | $vcUser = '' 38 | $vcPswd = '' 39 | $sVcCred = @{ 40 | TypeName = 'System.Management.Automation.PSCredential' 41 | ArgumentList = $vcUser,(ConvertTo-SecureString -String $vcPswd -AsPlainText -Force) 42 | } 43 | $vcCred = New-Object @sVcCred 44 | #endregion 45 | 46 | $ConfigData = @{ 47 | AllNodes = @( 48 | @{ 49 | NodeName = '*' 50 | Server = 'vcsa.local.lab' 51 | Credential = $vcCred 52 | PSDscAllowPlainTextPassword=$true 53 | PSDscAllowDomainUser = $true 54 | }, 55 | @{ 56 | NodeName = $configName 57 | Datacenters = @( 58 | @{ 59 | DatacenterName = 'DC2' 60 | Path = '/Folder3' 61 | Ensure = [Ensure]::Present 62 | }, 63 | @{ 64 | DatacenterName = 'DC3' 65 | Path = '/' 66 | Ensure = [Ensure]::Present 67 | } 68 | ) 69 | } 70 | ) 71 | } 72 | 73 | . "$(Split-Path $MyInvocation.MyCommand.Path)\..\..\Tools\Get-TargetGuid.ps1" 74 | $guid = Get-TargetGuid -TargetName $tgtName 75 | 76 | Invoke-Expression "$($configName) -ConfigurationData `$configData -OutputPath '.\DSC'" 77 | 78 | $pullShare = '\\pull\DSCService\Configuration\' 79 | $mof = ".\DSC\$($configName).mof" 80 | $tgtMof = "$pullshare\$guid.mof" 81 | 82 | Copy-Item -Path $mof -Destination $tgtMof 83 | New-DSCChecksum $tgtMof -Force 84 | 85 | # For testing with Start-DscCOnfiguration 86 | Copy-Item -Path $mof -Destination ".\DSC\$($tgtName.Split('.')[0]).mof" 87 | -------------------------------------------------------------------------------- /Configurations/VmwDatacenter/cd03-vCenter-Datacenter.ps1: -------------------------------------------------------------------------------- 1 | enum Ensure { 2 | Absent 3 | Present 4 | } 5 | 6 | $tgtName = 'vEng.local.lab' 7 | $configName = 'vmw' 8 | 9 | Configuration $configName 10 | { 11 | param( 12 | [System.Management.Automation.PSCredential]$Credential 13 | ) 14 | 15 | Import-DscResource -ModuleName vSphereDSC 16 | 17 | Node $AllNodes.NodeName 18 | { 19 | $number = 0 20 | foreach($datacenter in $Node.Datacenters) 21 | { 22 | $number++ 23 | $dcName = "Datacenter$number" 24 | VmwDatacenter $dcName 25 | { 26 | Name = $datacenter.DatacenterName 27 | Path = $datacenter.Path 28 | Ensure = $datacenter.Ensure 29 | vServer = $Allnodes.Server 30 | vCredential = $Allnodes.Credential 31 | } 32 | } 33 | } 34 | } 35 | 36 | #region VCSA Account 37 | $vcUser = '' 38 | $vcPswd = '' 39 | $sVcCred = @{ 40 | TypeName = 'System.Management.Automation.PSCredential' 41 | ArgumentList = $vcUser,(ConvertTo-SecureString -String $vcPswd -AsPlainText -Force) 42 | } 43 | $vcCred = New-Object @sVcCred 44 | #endregion 45 | 46 | $ConfigData = @{ 47 | AllNodes = @( 48 | @{ 49 | NodeName = '*' 50 | Server = 'vcsa.local.lab' 51 | Credential = $vcCred 52 | PSDscAllowPlainTextPassword=$true 53 | PSDscAllowDomainUser = $true 54 | }, 55 | @{ 56 | NodeName = $configName 57 | Datacenters = @( 58 | @{ 59 | DatacenterName = 'DC2' 60 | Path = '/Folder3' 61 | Ensure = [Ensure]::Absent 62 | }, 63 | @{ 64 | DatacenterName = 'DC3' 65 | Path = '/' 66 | Ensure = [Ensure]::Absent 67 | } 68 | ) 69 | } 70 | ) 71 | } 72 | 73 | . "$(Split-Path $MyInvocation.MyCommand.Path)\..\..\Tools\Get-TargetGuid.ps1" 74 | $guid = Get-TargetGuid -TargetName $tgtName 75 | 76 | Invoke-Expression "$($configName) -ConfigurationData `$configData -OutputPath '.\DSC'" 77 | 78 | $pullShare = '\\pull\DSCService\Configuration\' 79 | $mof = ".\DSC\$($configName).mof" 80 | $tgtMof = "$pullshare\$guid.mof" 81 | 82 | Copy-Item -Path $mof -Destination $tgtMof 83 | New-DSCChecksum $tgtMof -Force 84 | 85 | # For testing with Start-DscCOnfiguration 86 | Copy-Item -Path $mof -Destination ".\DSC\$($tgtName.Split('.')[0]).mof" 87 | -------------------------------------------------------------------------------- /Configurations/vmwFolder/cf01-vCenter-Folder.ps1: -------------------------------------------------------------------------------- 1 | enum Ensure { 2 | Absent 3 | Present 4 | } 5 | 6 | $tgtName = 'vEng.local.lab' 7 | $configName = 'Vmw' 8 | 9 | Configuration $configName 10 | { 11 | param( 12 | [System.Management.Automation.PSCredential]$Credential 13 | ) 14 | 15 | Import-DscResource -ModuleName vSphereDSC 16 | 17 | Node $AllNodes.NodeName 18 | { 19 | $number = 0 20 | foreach($folder in $Node.Folders) 21 | { 22 | $number++ 23 | $folderName = "Folder$number" 24 | VmwFolder $folderName 25 | { 26 | Name = $folder.FolderName 27 | Path = $folder.Path 28 | Ensure = $folder.Ensure 29 | Type = $folder.Type 30 | vServer = $Allnodes.Server 31 | vCredential = $Allnodes.Credential 32 | } 33 | } 34 | } 35 | } 36 | 37 | #region VCSA Account 38 | $vcUser = '' 39 | $vcPswd = '' 40 | $sVcCred = @{ 41 | TypeName = 'System.Management.Automation.PSCredential' 42 | ArgumentList = $vcUser,(ConvertTo-SecureString -String $vcPswd -AsPlainText -Force) 43 | } 44 | $vcCred = New-Object @sVcCred 45 | #endregion 46 | 47 | $ConfigData = @{ 48 | AllNodes = @( 49 | @{ 50 | NodeName = '*' 51 | Server = 'vcsa.local.lab' 52 | Credential = $vcCred 53 | PSDscAllowPlainTextPassword=$true 54 | PSDscAllowDomainUser = $true 55 | }, 56 | @{ 57 | NodeName = $configName 58 | Folders = @( 59 | @{ 60 | FolderName = 'Folder1' 61 | Path = '/' 62 | Type = 'Yellow' 63 | Ensure = [Ensure]::Present 64 | } 65 | ) 66 | } 67 | ) 68 | } 69 | 70 | . "$(Split-Path $MyInvocation.MyCommand.Path)\..\..\Tools\Get-TargetGuid.ps1" 71 | $guid = Get-TargetGuid -TargetName $tgtName 72 | 73 | Invoke-Expression "$($configName) -ConfigurationData `$configData -OutputPath '.\DSC'" 74 | 75 | $pullShare = '\\pull\DSCService\Configuration\' 76 | $mof = ".\DSC\$($configName).mof" 77 | $tgtMof = "$pullshare\$guid.mof" 78 | 79 | Copy-Item -Path $mof -Destination $tgtMof 80 | New-DSCChecksum $tgtMof -Force 81 | 82 | # For testing with Start-DscCOnfiguration 83 | Copy-Item -Path $mof -Destination ".\DSC\$($tgtName.Split('.')[0]).mof" 84 | -------------------------------------------------------------------------------- /Configurations/vmwFolder/cf02-vCenter-Folder.ps1: -------------------------------------------------------------------------------- 1 | enum Ensure { 2 | Absent 3 | Present 4 | } 5 | 6 | $tgtName = 'vEng.local.lab' 7 | $configName = 'Vmw' 8 | 9 | Configuration $configName 10 | { 11 | param( 12 | [System.Management.Automation.PSCredential]$Credential 13 | ) 14 | 15 | Import-DscResource -ModuleName vSphereDSC 16 | 17 | Node $AllNodes.NodeName 18 | { 19 | $number = 0 20 | foreach($folder in $Node.Folders) 21 | { 22 | $number++ 23 | $folderName = "Folder$number" 24 | VmwFolder $folderName 25 | { 26 | Name = $folder.FolderName 27 | Path = $folder.Path 28 | Ensure = $folder.Ensure 29 | Type = $folder.Type 30 | vServer = $Allnodes.Server 31 | vCredential = $Allnodes.Credential 32 | } 33 | } 34 | } 35 | } 36 | 37 | #region VCSA Account 38 | $vcUser = '' 39 | $vcPswd = '' 40 | $sVcCred = @{ 41 | TypeName = 'System.Management.Automation.PSCredential' 42 | ArgumentList = $vcUser,(ConvertTo-SecureString -String $vcPswd -AsPlainText -Force) 43 | } 44 | $vcCred = New-Object @sVcCred 45 | #endregion 46 | 47 | $ConfigData = @{ 48 | AllNodes = @( 49 | @{ 50 | NodeName = '*' 51 | Server = 'vcsa.local.lab' 52 | Credential = $vcCred 53 | PSDscAllowPlainTextPassword=$true 54 | PSDscAllowDomainUser = $true 55 | }, 56 | @{ 57 | NodeName = $configName 58 | Folders = @( 59 | @{ 60 | FolderName = 'Folder1' 61 | Path = '/' 62 | Type = 'Yellow' 63 | Ensure = [Ensure]::Absent 64 | }, 65 | @{ 66 | FolderName = 'Folder2' 67 | Path = 'Datacenters' 68 | Type = 'Blue' 69 | Ensure = [Ensure]::Present 70 | } 71 | ) 72 | } 73 | ) 74 | } 75 | 76 | . "$(Split-Path $MyInvocation.MyCommand.Path)\..\Tools\Get-TargetGuid.ps1" 77 | $guid = Get-TargetGuid -TargetName $tgtName 78 | 79 | Invoke-Expression "$($configName) -ConfigurationData `$configData -OutputPath '.\DSC'" 80 | 81 | $pullShare = '\\pull\DSCService\Configuration\' 82 | $mof = ".\DSC\$($configName).mof" 83 | $tgtMof = "$pullshare\$guid.mof" 84 | 85 | Copy-Item -Path $mof -Destination $tgtMof 86 | New-DSCChecksum $tgtMof -Force 87 | 88 | # For testing with Start-DscCOnfiguration 89 | Copy-Item -Path $mof -Destination ".\DSC\$($tgtName.Split('.')[0]).mof" 90 | -------------------------------------------------------------------------------- /Configurations/vmwFolder/cf03-vCenter-Folder.ps1: -------------------------------------------------------------------------------- 1 | $tgtName = 'vEng.local.lab' 2 | $vCenterName = 'vcsa.local.lab' 3 | 4 | $configName = $tgtName.Split('.')[0] 5 | 6 | enum Ensure { 7 | Absent 8 | Present 9 | } 10 | 11 | enum VmwFolderType { 12 | Yellow 13 | Blue 14 | } 15 | 16 | Configuration $configName 17 | { 18 | param( 19 | [System.Management.Automation.PSCredential]$Credential 20 | ) 21 | 22 | Import-DscResource -ModuleName vSphereDSC 23 | 24 | Node $AllNodes.NodeName 25 | { 26 | $number = 0 27 | foreach($folder in $Node.Folders) 28 | { 29 | $number++ 30 | $folderName = "Folder$number" 31 | VmwFolder $folderName 32 | { 33 | Name = $folder.FolderName 34 | Path = $folder.Path 35 | Ensure = $folder.Ensure 36 | Type = $folder.Type 37 | vServer = $Allnodes.Server 38 | vCredential = $Allnodes.Credential 39 | } 40 | } 41 | } 42 | } 43 | 44 | #region VCSA Account 45 | $vcUser = '' 46 | $vcPswd = '' 47 | $sVcCred = @{ 48 | TypeName = 'System.Management.Automation.PSCredential' 49 | ArgumentList = $vcUser,(ConvertTo-SecureString -String $vcPswd -AsPlainText -Force) 50 | } 51 | $vcCred = New-Object @sVcCred 52 | #endregion 53 | 54 | $ConfigData = @{ 55 | AllNodes = @( 56 | @{ 57 | NodeName = '*' 58 | Server = $vCenterName 59 | Credential = $vcCred 60 | PSDscAllowPlainTextPassword=$true 61 | PSDscAllowDomainUser = $true 62 | }, 63 | @{ 64 | NodeName = $configName 65 | Folders = @( 66 | @{ 67 | FolderName = 'Folder2' 68 | Path = '/Homelab' 69 | Type = [VmwFolderType]::Blue 70 | Ensure = [Ensure]::Present 71 | }, 72 | @{ 73 | FolderName = 'Folder2' 74 | Path = '/Homelab' 75 | Type = [VmwFolderType]::Yellow 76 | Ensure = [Ensure]::Present 77 | } 78 | ) 79 | } 80 | ) 81 | } 82 | 83 | . "$(Split-Path $MyInvocation.MyCommand.Path)\..\..\Tools\Get-TargetGuid.ps1" 84 | $guid = Get-TargetGuid -TargetName $tgtName 85 | 86 | Invoke-Expression "$($configName) -ConfigurationData `$configData -OutputPath '.\DSC'" 87 | 88 | $pullShare = '\\pull\DSCService\Configuration\' 89 | $mof = ".\DSC\$($configName).mof" 90 | $tgtMof = "$pullshare\$guid.mof" 91 | 92 | Copy-Item -Path $mof -Destination $tgtMof 93 | New-DSCChecksum $tgtMof -Force 94 | 95 | # For testing with Start-DscCOnfiguration 96 | #Copy-Item -Path $mof -Destination ".\DSC\$($tgtName.Split('.')[0]).mof" 97 | -------------------------------------------------------------------------------- /History.txt: -------------------------------------------------------------------------------- 1 | DSC Resource vSphere-DSC 2 | Author: Luc Dekens 3 | 4 | v1.0.1 - 5 June 2016 5 | - Basic functionality 6 | - VmwFolder 7 | v1.0.2 - 6 June 2016 8 | - VmwDatacenter -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Luc Dekens 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Logo](https://github.com/lucdekens/vSphereDSC/blob/master/Tools/vSphereDSC-Logo-small.jpg) 2 | 3 | # vSphereDSC 4 | DSC Resource module for vSphere environments 5 | 6 | ## Documentation 7 | [Intro](http://www.lucd.info/2016/06/04/vspheredsc-intro/) 8 | 9 | [Principles of Operation](http://www.lucd.info/2016/06/07/vspheredsc-principles-operation/) 10 | 11 | [VmwFolder](http://www.lucd.info/2016/06/05/vspheredsc-vmwfolder) 12 | 13 | [VmwDatacenter](http://www.lucd.info/2016/06/06/vspheredsc-vmwdatacenter) 14 | -------------------------------------------------------------------------------- /Tools/Get-TargetGuid.ps1: -------------------------------------------------------------------------------- 1 | function Get-TargetGuid 2 | { 3 | param( 4 | [string]$TargetName 5 | ) 6 | 7 | $guidMaster = '\\Pull\Repository\guidMaster.csv' 8 | 9 | if(Test-Path -Path $guidMaster){ 10 | $guids = Import-Csv -Path $guidMaster 11 | } 12 | else{ 13 | $guids = @() 14 | } 15 | $tgtGuid = $guids | where{$_.target -eq $TargetName} | Select -ExpandProperty guid 16 | if(!$tgtGuid){ 17 | $tgtGuid = New-Guid 18 | $guids += New-Object PSObject -Property @{ 19 | target = $TargetName 20 | guid = $tgtGuid 21 | } 22 | $guids | Export-Csv -Path $guidMaster -NoTypeInformation -UseCulture 23 | } 24 | $tgtGuid 25 | } 26 | -------------------------------------------------------------------------------- /Tools/Test-DscConfiguration.ps1: -------------------------------------------------------------------------------- 1 | $tgtName = 'vEng.local.lab' 2 | 3 | $configName = $tgtName.Split('.')[0] 4 | 5 | Start-DscConfiguration -ComputerName $configName -Wait -Verbose -Force -Path .\DSC 6 | -------------------------------------------------------------------------------- /Tools/vSphereDSC-Logo-small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lucdekens/vSphereDSC/37d0f7e851a148dea7a0a8acfa6a734a3796450e/Tools/vSphereDSC-Logo-small.jpg -------------------------------------------------------------------------------- /Tools/vSphereDSC-Module-To-Pull-Server.ps1: -------------------------------------------------------------------------------- 1 | $moduleName = 'vSphereDSC' 2 | $sourceFolder = "$($env:userprofile)\OneDrive\BitBucket" 3 | $pullSrvName = 'pull.local.lab' 4 | 5 | $srcPath = "$($sourceFolder)\$($moduleName)" 6 | $pullSrv = "\\$($pullSrvName)\DscService\Modules" 7 | 8 | $localPath = $env:PSModulePath.split(';') | where{$_ -like "$($env:userprofile)*"} 9 | 10 | # Increment Version Build 11 | $modVersion = Test-ModuleManifest -Path "$($srcPath)\$($moduleName).psd1" | Select -ExpandProperty Version 12 | $newVersion = [Version]::new($modVersion.Major,$modVersion.Minor,$modVersion.Build + 1,$modVersion.Revision) 13 | Update-ModuleManifest -Path "$($srcPath)\$($moduleName).psd1" -ModuleVersion $newVersion 14 | 15 | # Copy new build to Pull server 16 | $compressedModuleName = "$($srcPath)\..\$($moduleName)_$($newVersion.Major).$($newVersion.Minor).$($newVersion.Build).$($newVersion.Revision).zip" 17 | Compress-Archive -Path "$($srcPath)\*" -DestinationPath $compressedModuleName 18 | Copy-item -Path "$($srcPath)\..\$($moduleName)_$($newVersion.ToString()).zip" -Destination $pullSrv 19 | New-DscChecksum -Path "$($pullSrv)\$($moduleName)*.zip" 20 | 21 | # Copy new build to local Modules folder 22 | if(Test-Path -Path "$localPath\$moduleName") 23 | { 24 | Get-ChildItem -Path "$localPath\$moduleName" -Recurse | Remove-Item -Recurse -Force -Confirm:$false -ErrorAction SilentlyContinue 25 | Remove-Item -Path "$localPath\$moduleName" -Recurse -Force -Confirm:$false -ErrorAction SilentlyContinue 26 | } 27 | Copy-Item -Path $srcPath -Destination $localPath -Recurse 28 | -------------------------------------------------------------------------------- /vSphereDSC.psd1: -------------------------------------------------------------------------------- 1 | # 2 | # Module manifest for module 'NewManifest' 3 | # 4 | # Generated by: Luc Dekens 5 | # 6 | # Generated on: 05-Jun-16 7 | # 8 | 9 | @{ 10 | 11 | # Script module or binary module file associated with this manifest. 12 | RootModule = 'vSphereDSC.psm1' 13 | 14 | # Version number of this module. 15 | ModuleVersion = '1.0.2.1' 16 | 17 | # ID used to uniquely identify this module 18 | GUID = 'd87b6489-19d9-4eae-a328-af93806825c3' 19 | 20 | # Author of this module 21 | Author = 'Luc Dekens' 22 | 23 | # Company or vendor of this module 24 | CompanyName = 'Community' 25 | 26 | # Copyright statement for this module 27 | Copyright = '(c) 2016 Luc Dekens. All rights reserved.' 28 | 29 | # Description of the functionality provided by this module 30 | Description = 'DSC Resource for a vSphere environment' 31 | 32 | # Minimum version of the Windows PowerShell engine required by this module 33 | PowerShellVersion = '5.0' 34 | 35 | # Name of the Windows PowerShell host required by this module 36 | # PowerShellHostName = '' 37 | 38 | # Minimum version of the Windows PowerShell host required by this module 39 | # PowerShellHostVersion = '' 40 | 41 | # Minimum version of Microsoft .NET Framework required by this module 42 | # DotNetFrameworkVersion = '' 43 | 44 | # Minimum version of the common language runtime (CLR) required by this module 45 | # CLRVersion = '' 46 | 47 | # Processor architecture (None, X86, Amd64) required by this module 48 | ProcessorArchitecture = 'None' 49 | 50 | # Modules that must be imported into the global environment prior to importing this module 51 | # RequiredModules = @() 52 | 53 | # Assemblies that must be loaded prior to importing this module 54 | RequiredAssemblies = @() 55 | 56 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 57 | ScriptsToProcess = @() 58 | 59 | # Type files (.ps1xml) to be loaded when importing this module 60 | TypesToProcess = @() 61 | 62 | # Format files (.ps1xml) to be loaded when importing this module 63 | FormatsToProcess = @() 64 | 65 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 66 | # NestedModules = @() 67 | 68 | # Functions to export from this module 69 | FunctionsToExport = @() 70 | 71 | # Cmdlets to export from this module 72 | CmdletsToExport = @() 73 | 74 | # Variables to export from this module 75 | VariablesToExport = @() 76 | 77 | # Aliases to export from this module 78 | AliasesToExport = @() 79 | 80 | # DSC resources to export from this module 81 | DscResourcesToExport = @('VmwFolder','VmwDatacenter') 82 | 83 | # List of all modules packaged with this module 84 | # ModuleList = @() 85 | 86 | # List of all files packaged with this module 87 | FileList = @() 88 | 89 | # 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. 90 | PrivateData = @{ 91 | 92 | PSData = @{ 93 | 94 | # Tags applied to this module. These help with module discovery in online galleries. 95 | Tags = 'VMware','vSphere','DSC','Community','VmwFolder','VmwDatacenter','LucD' 96 | 97 | # A URL to the license for this module. 98 | LicenseUri = 'https://www.tldrlegal.com/l/mit' 99 | 100 | # A URL to the main website for this project. 101 | ProjectUri = 'https://github.com/lucdekens/vSphereDSC' 102 | 103 | # A URL to an icon representing this module. 104 | IconUri = 'http://lucd.info/wp-content/uploads/2016/06/vSphereDSC-Logo.png' 105 | 106 | # ReleaseNotes of this module 107 | # ReleaseNotes = '' 108 | 109 | # External dependent modules of this module 110 | # ExternalModuleDependencies = '' 111 | 112 | } # End of PSData hashtable 113 | 114 | } # End of PrivateData hashtable 115 | 116 | # HelpInfo URI of this module 117 | # HelpInfoURI = '' 118 | 119 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 120 | # DefaultCommandPrefix = '' 121 | 122 | } 123 | 124 | -------------------------------------------------------------------------------- /vSphereDSC.psm1: -------------------------------------------------------------------------------- 1 | enum Ensure { 2 | Absent 3 | Present 4 | } 5 | 6 | enum VmwFolderType { 7 | Yellow 8 | Blue 9 | } 10 | 11 | $PSDefaultParameterValues = @{ 12 | "Get-View:Verbose"=$false 13 | "Add-PSSnapin:Verbose"=$false 14 | "Import-Module:Verbose"=$false 15 | } 16 | 17 | [DscResource()] 18 | class VmwFolder 19 | { 20 | #region Properties 21 | [DscProperty(Key)] 22 | [string]$Name 23 | [DscProperty(Key)] 24 | [string]$Path 25 | [DscProperty()] 26 | [Ensure]$Ensure 27 | [DscProperty(Key)] 28 | [VmwFolderType]$Type 29 | [DscProperty(Mandatory)] 30 | [string]$vServer 31 | [DscProperty(Mandatory)] 32 | [PSCredential]$vCredential 33 | [DscProperty()] 34 | hidden[String]$vSessionId 35 | #endregion 36 | 37 | #region DSC Functions 38 | [void]Set() 39 | { 40 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 41 | Write-Verbose -Message "$(Get-Date) $('{0}-{1}-{2}-{3}' -f $this.vServer,$this.Name,$this.Path,$this.Type)" 42 | 43 | . "$($PSScriptRoot)\vSphereDSCHelper.ps1" 44 | 45 | $this.vSessionId = Connect-VmwVIServer -Server $this.vServer -Credential $this.vCredential -Id $this.vSessionId 46 | 47 | $folderPresent = $this.TestVmwFolder() 48 | 49 | if ($this.Ensure -eq [Ensure]::Present) 50 | { 51 | if(-not $folderPresent) 52 | { 53 | Write-Verbose -Message "$(Get-Date) Creating the folder $($this.Name) at $($this.Path)" 54 | $this.NewVmwFolder() 55 | } 56 | } 57 | else 58 | { 59 | if ($folderPresent) 60 | { 61 | Write-Verbose -Message "$(Get-Date) Deleting the folder $($this.Name) at $($this.Path)" 62 | $this.RemoveVmwFolder() 63 | } 64 | } 65 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Leaving {0}" -f $s[0].FunctionName)" 66 | } 67 | 68 | [bool]Test() 69 | { 70 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 71 | Write-Verbose -Message "$(Get-Date) $('{0}-{1}-{2}-{3}' -f $this.vServer,$this.Name,$this.Path,$this.Type)" 72 | 73 | . "$($PSScriptRoot)\vSphereDSCHelper.ps1" 74 | 75 | $this.vSessionId = Connect-VmwVIServer -Server $this.vServer -Credential $this.vCredential -Id $this.vSessionId 76 | 77 | $folderPresent = $this.TestVmwFolder() 78 | Write-Verbose -Message "$(Get-Date) Folder Present $($folderPresent)" 79 | 80 | if ($this.Ensure -eq [Ensure]::Present) 81 | { 82 | return $folderPresent 83 | } 84 | else 85 | { 86 | return -not $folderPresent 87 | } 88 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Leaving {0}" -f $s[0].FunctionName)" 89 | } 90 | 91 | [VmwFolder]Get() 92 | { 93 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 94 | 95 | return $this.GetVmwFolder() 96 | 97 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Leaving {0}" -f $s[0].FunctionName)" 98 | } 99 | #endregion 100 | 101 | #region VmwFolder Helper Functions 102 | [bool]TestVmwFolder() 103 | { 104 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 105 | Write-Verbose -Message "$(Get-Date) Looking for a $($this.Type) folder, named $($this.Name) at $($this.Path)" 106 | 107 | if($this.Path -match "/$"){ 108 | $nodePath = "$($this.Path)$($this.Name)" 109 | } 110 | else{ 111 | $nodePath = "$($this.Path)/$($this.Name)" 112 | } 113 | Write-Verbose -Message "$(Get-Date) Looking for $($nodePath)" 114 | 115 | $nodeFound = Get-VmwNodeFromPath -Path $nodePath | 116 | where {$_.Found -and (Test-VmwFolderType -Node $_.Node -FolderType $this.Type)} 117 | 118 | Write-Verbose -Message "$(Get-Date) Find it ? $($nodeFound -ne $null)" 119 | return ($nodeFound -ne $null) 120 | 121 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Leaving {0}" -f $s[0].FunctionName)" 122 | } 123 | 124 | [void]NewVmwFolder() 125 | { 126 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 127 | Write-Verbose -Message "$(Get-Date) Looking for parent $($this.Path)" 128 | 129 | $parent = Get-VmwNodeFromPath -Path "$($this.Path)" 130 | 131 | # Take action on node 132 | if($parent.Found){ 133 | New-VmwFolder -Parent $parent.Node -FolderName $this.Name -FolderType $this.Type 134 | } 135 | 136 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Leaving {0}" -f $s[0].FunctionName)" 137 | } 138 | 139 | [void]RemoveVmwFolder() 140 | { 141 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 142 | 143 | if($this.Path -match "/$"){ 144 | $nodePath = "$($this.Path)$($this.Name)" 145 | } 146 | else{ 147 | $nodePath = "$($this.Path)/$($this.Name)" 148 | } 149 | 150 | $folder = Get-VmwNodeFromPath -Path $nodePath 151 | 152 | # Take action on node 153 | if($folder.Found){ 154 | $folder.Node.Destroy() | Out-Null 155 | } 156 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Leaving {0}" -f $s[0].FunctionName)" 157 | } 158 | #endregion 159 | } 160 | 161 | [DscResource()] 162 | class VmwDatacenter 163 | { 164 | #region Properties 165 | [DscProperty(Key)] 166 | [string]$Name 167 | [DscProperty(Key)] 168 | [string]$Path 169 | [DscProperty()] 170 | [Ensure]$Ensure 171 | [DscProperty(Mandatory)] 172 | [string]$vServer 173 | [DscProperty(Mandatory)] 174 | [PSCredential]$vCredential 175 | hidden[string]$vSessionId 176 | #endregion 177 | 178 | #region DSC Functions 179 | [void]Set() 180 | { 181 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 182 | Write-Verbose -Message "$(Get-Date) $('{0}-{1}-{2}' -f $this.vServer,$this.Name,$this.Path)" 183 | 184 | if(!($global:DefaultVIServer.SessionId -eq $this.vSessionId) -or !$global:DefaultVIServer.IsConnected) 185 | { 186 | $this.vSessionId = Connect-VmwVIServer -Server $this.vServer -Credential $this.vCredential 187 | } 188 | 189 | $dcPresent = $this.TestVmwDatacenter() 190 | 191 | if ($this.Ensure -eq [Ensure]::Present) 192 | { 193 | if(-not $dcPresent) 194 | { 195 | Write-Verbose -Message "$(Get-Date) Creating the datacenter $($this.Path)/$($this.Name)" 196 | $this.NewVmwDatacenter() 197 | } 198 | } 199 | else 200 | { 201 | if ($dcPresent) 202 | { 203 | Write-Verbose -Message "$(Get-Date) Deleting the datacenter $($this.Path)/$($this.Name)" 204 | $this.RemoveVmwDatacenter() 205 | } 206 | } 207 | } 208 | 209 | [bool]Test() 210 | { 211 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 212 | Write-Verbose -Message "$(Get-Date) $('{0}-{1}-{2}' -f $this.vServer,$this.Name,$this.Path)" 213 | 214 | if(!($global:DefaultVIServer.SessionId -eq $this.vSessionId) -or !$global:DefaultVIServer.IsConnected) 215 | { 216 | $this.vSessionId = Connect-VmwVIServer -Server $this.vServer -Credential $this.vCredential 217 | } 218 | 219 | $dcPresent = $this.TestVmwDatacenter() 220 | 221 | if ($this.Ensure -eq [Ensure]::Present) 222 | { 223 | return $dcPresent 224 | } 225 | else 226 | { 227 | return -not $dcPresent 228 | } 229 | } 230 | 231 | [VmwDatacenter]Get() 232 | { 233 | return $this.GetVmwDatacenter() 234 | } 235 | #endregion 236 | 237 | #region VmwDatacenter Helper Functions 238 | [bool]TestVmwDatacenter() 239 | { 240 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 241 | 242 | if($this.GetVmwDatacenter()){ 243 | return $true 244 | } 245 | else{ 246 | return $false 247 | } 248 | } 249 | 250 | [string]GetVmwDatacenter() 251 | { 252 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 253 | 254 | $obj = $null 255 | $sView = @{ 256 | ViewType = 'Datacenter' 257 | Property = 'Name','Parent' 258 | Filter = @{ 259 | Name = $this.Name 260 | } 261 | } 262 | $dc = Get-View @sView 263 | if($dc){ 264 | $obj = $dc.MoRef.ToString() 265 | } 266 | return $obj 267 | } 268 | 269 | [void]NewVmwDatacenter() 270 | { 271 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 272 | 273 | $node = Find-VmwLeaf -Path $this.Path 274 | 275 | if($node){ 276 | # Take action on node 277 | $node = Get-View -Id $node -Property Name,ChildEntity 278 | if(!$node.ChildEntity -or (Get-View -Id $node.ChildEntity -Property Name).Name -notcontains $this.Name){ 279 | $node.CreateDatacenter($this.Name) | Out-Null 280 | } 281 | } 282 | 283 | } 284 | 285 | [void]RemoveVmwDatacenter() 286 | { 287 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 288 | 289 | $node = Find-VmwLeaf -Path $this.Path 290 | 291 | if($node){ 292 | $node = Get-View -Id $node -Property Name 293 | $sView = @{ 294 | ViewType = 'Datacenter' 295 | SearchRoot = $node.MoRef 296 | Filter = @{ 297 | Name = $this.Name 298 | } 299 | ErrorAction = 'SilentlyContinue' 300 | } 301 | $dc = Get-View @sView 302 | if($dc){ 303 | $dc.Destroy() 304 | } 305 | 306 | } 307 | } 308 | #endregion 309 | } 310 | -------------------------------------------------------------------------------- /vSphereDSCHelper.ps1: -------------------------------------------------------------------------------- 1 | enum VmwFolderType { 2 | Yellow 3 | Blue 4 | } 5 | 6 | function Enable-PowerCLI 7 | { 8 | <# 9 | .SYNOPSIS 10 | Load PowerCLI modules and PSSnapins 11 | .DESCRIPTION 12 | This function will load all requested PowerCLI 13 | modules and PSSnapins. 14 | The function will, depending on the installed PowerCLI version, 15 | determine what needs to be loaded. 16 | .NOTES 17 | Author: Luc Dekens 18 | .PARAMETER Cloud 19 | Switch to indicate if the Cloud related cmdlets shall be loaded 20 | .PARAMETER InitScript 21 | The PowerCLI PSSnapin have associated initialisation scripts. 22 | This switch will indicate if that script needs to be executed or not. 23 | .EXAMPLE 24 | PS> Enable-PowerCLI 25 | .EXAMPLE 26 | PS> Enable-PowerCLI -Cloud 27 | #> 28 | 29 | [CmdletBinding()] 30 | param( 31 | [switch]$Cloud=$false, 32 | [switch]$InitScript=$true 33 | ) 34 | 35 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 36 | 37 | $Global:PSDefaultParameterValues = @{ 38 | "Get-View:Verbose"=$false 39 | "Add-PSSnapin:Verbose"=$false 40 | "Import-Module:Verbose"=$false 41 | } 42 | 43 | $PcliPssnapin = @{ 44 | 'VMware.VimAutomation.License' = @(2548067) 45 | 'VMware.DeployAutomation' =@(2548067,3056836,3205540,3737840) 46 | 'VMware.ImageBuilder' = @(2548067,3056836,3205540,3737840) 47 | } 48 | 49 | $PcliModule = @{ 50 | 'VMware.VimAutomation.Core' = @(2548067,3056836,3205540,3737840) 51 | 'VMware.VimAutomation.Vds' = @(2548067,3056836,3205540,3737840) 52 | 'VMware.VimAutomation.Cloud' = @(2548067,3056836,3205540,3737840) 53 | 'VMware.VimAutomation.PCloud' = @(2548067,3056836,3205540,3737840) 54 | 'VMware.VimAutomation.Cis.Core' = @(2548067,3056836,3205540,3737840) 55 | 'VMware.VimAutomation.Storage' = @(2548067,3056836,3205540,3737840) 56 | 'VMware.VimAutomation.HA' = @(2548067,3056836,3205540,3737840) 57 | 'VMware.VimAutomation.vROps' = @(3056836,3205540,3737840) 58 | 'VMware.VumAutomation' = @(3056836,3205540,3737840) 59 | 'VMware.VimAutomation.License' = @(3056836,3205540,3737840) 60 | } 61 | 62 | # 32- or 64-bit process 63 | $procArch = (Get-Process -Id $Global:pid).StartInfo.EnvironmentVariables["PROCESSOR_ARCHITECTURE"] 64 | if($procArch -eq 'x86'){ 65 | $regPath = 'HKLM:\Software\VMware, Inc.\VMware vSphere PowerCLI' 66 | } 67 | else{ 68 | $regPath = 'HKLM:\Software\WOW6432Node\VMware, Inc.\VMware vSphere PowerCLI' 69 | } 70 | 71 | # Check if PowerCLI (regular or Tenant) is installed 72 | if(!(Test-Path -Path $regPath)) 73 | { 74 | $regPath = $regPath.Replace('VMware vSphere PowerCLI','VMware vSphere PowerCLI for Tenants') 75 | if(!(Test-Path -Path $regPath)) 76 | { 77 | Throw 'Can not find a PowerCLI installation!' 78 | } 79 | } 80 | 81 | # Get build 82 | $buildKey = 'InstalledBuild' 83 | Try{ 84 | $pcliBuild = Get-ItemProperty -Path $regPath -Name $buildKey | 85 | Select -ExpandProperty $buildKey -ErrorAction Stop 86 | } 87 | Catch{ 88 | Throw "PowerCLI doesn't seem to be installed on this system!" 89 | } 90 | # Get installation path 91 | $installPathKey = 'InstallPath' 92 | Try{ 93 | $pcliInstallPath = Get-ItemProperty -Path $regPath -Name $installPathKey | 94 | Select -ExpandProperty $installPathKey -ErrorAction Stop 95 | } 96 | Catch{ 97 | Throw "PowerCLI doesn't seem to be installed on this system!" 98 | } 99 | # Load modules 100 | if($pcliBuild -ge 2548067) 101 | { 102 | $loadedModule = Get-Module -Name VMware* -ErrorAction SilentlyContinue | %{$_.Name} 103 | if($loadedModule -and $pcliBuild -ge 3737840) 104 | { 105 | $loadedModule = $loadedModule | where{$_ -notmatch 'Common$|SDK$'} 106 | } 107 | 108 | $targetModule = $PcliModule.GetEnumerator() | where{$_.Value -contains $pcliBuild} | %{$_.Key} 109 | $targetModule = $targetModule | where{$loadedModule -notcontains $_} 110 | if(!$Cloud) 111 | { 112 | $targetModule = $targetModule | where{$_ -notmatch 'Cloud'} 113 | } 114 | if($targetModule) 115 | { 116 | $targetModule | where{$loadedModule -notcontains $_.Name} | %{ 117 | Import-Module -Name $_ 118 | } 119 | } 120 | } 121 | 122 | # Load PSSnapin 123 | $loadedSnap = Get-PSSnapin -Name VMware* -ErrorAction SilentlyContinue -Verbose:$false | %{$_.Name} 124 | if($pcliBuild -ge 3737840) 125 | { 126 | $loadedSnap = $loadedSnap | where{$_ -notmatch 'Core$'} 127 | } 128 | 129 | $targetSnap = $PcliPssnapin.GetEnumerator() | where{$_.Value -contains $pcliBuild} | %{$_.Key} 130 | $targetSnap = $targetSnap | where{$loadedSnap -notcontains $_} 131 | if(!$Cloud) 132 | { 133 | $targetSnap = $targetSnap | where{$_ -notmatch 'Cloud'} 134 | } 135 | if($targetSnap) 136 | { 137 | $targetSnap | where{$loadedSnap -notcontains $_} | %{ 138 | Add-PSSnapin -Name $_ 139 | 140 | # Run initialisation script 141 | if($InitScript) 142 | { 143 | $filePath = "{0}Scripts\Initialize-{1}.ps1" -f $pcliInstallPath,$_.ToString().Replace(".", "_") 144 | if (Test-Path $filePath) { 145 | & $filePath 146 | } 147 | } 148 | } 149 | } 150 | 151 | # $global:VerbosePreference = $SaveVerbosePreference 152 | 153 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Leaving {0}" -f $s[0].FunctionName)" 154 | } 155 | 156 | function Connect-VmwVIServer 157 | { 158 | [CmdletBinding()] 159 | [OutputType([System.String])] 160 | param( 161 | [string]$Server, 162 | [PSCredential]$Credential, 163 | [string]$Id 164 | ) 165 | 166 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 167 | Write-Verbose -Message "$(Get-Date) Connect with credential $($Credential.UserName)" 168 | Write-Verbose -Message "$(Get-Date) SessionId $($Id)" 169 | 170 | Enable-PowerCLI 171 | 172 | Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -DisplayDeprecationWarnings $false -Confirm:$false | Out-Null 173 | $srv = Connect-VIServer -Server $Server -Credential $Credential 174 | 175 | Write-Verbose -Message "$(Get-Date) Connected with credential $($Credential.UserName)" 176 | Write-Verbose -Message "$(Get-Date) $('Got session ID {0}' -f $srv.SessionId)" 177 | 178 | return $srv.SessionId 179 | 180 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Leaving {0}" -f $s[0].FunctionName)" 181 | } 182 | 183 | function Get-VmwNodeFromPath 184 | { 185 | [CmdletBinding()] 186 | [OutputType([System.Management.Automation.PSCustomObject])] 187 | param( 188 | [PSObject]$StartNode = (Get-View -Id (Get-View -Id ServiceInstance).Content.RootFolder), 189 | [String]$Path 190 | ) 191 | 192 | function Get-NodeChild{ 193 | param( 194 | [VMware.Vim.ManagedEntity]$Node 195 | ) 196 | 197 | $hidden = 'vm','host','network','datastore','Resources' 198 | switch($Node){ 199 | {$_ -is [VMware.Vim.Folder]}{ 200 | if($Node.ChildEntity){ 201 | Get-View -Id $Node.ChildEntity 202 | } 203 | } 204 | {$_ -is [VMware.Vim.Datacenter]}{ 205 | $all = @() 206 | $all += Get-View -Id $Node.VmFolder 207 | $all += Get-View -Id $Node.HostFolder 208 | $all += Get-View -Id $Node.DatastoreFolder 209 | $all += Get-View -Id $Node.NetworkFolder 210 | $all | %{ 211 | if($hidden -contains $_.Name){ 212 | Get-NodeChild -Node $_ 213 | } 214 | else{ 215 | $_ 216 | } 217 | } 218 | } 219 | {$_ -is [VMware.Vim.ClusterComputeResource]}{ 220 | $all = @() 221 | $all += Get-View -Id $Node.Host 222 | $all += Get-View -Id $Node.ResourcePool 223 | $all = $all | %{ 224 | if($hidden -contains $_.Name){ 225 | Get-NodeChild -Node $_ 226 | } 227 | else{ 228 | $_ 229 | } 230 | } 231 | $all 232 | } 233 | {$_ -is [VMware.Vim.ResourcePool]}{ 234 | $all = @() 235 | if($Node.ResourcePool){ 236 | $all += Get-View -Id $Node.ResourcePool 237 | } 238 | if($Node.vm){ 239 | $all += Get-View -Id $Node.vm 240 | } 241 | $all 242 | } 243 | {$_ -is [VMware.Vim.DistributedVirtualSwitch]}{ 244 | Get-View -Id $Node.Portgroup 245 | } 246 | } 247 | } 248 | 249 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 250 | Write-Verbose -Message "$(Get-Date) Start: $($StartNode.Name)" 251 | Write-Verbose -Message "$(Get-Date) Path: $($Path)" 252 | 253 | $found = $true 254 | 255 | # Loop through Path 256 | $node = @($StartNode) 257 | foreach($qualifier in $Path.TrimStart('/').Split('/',[StringSplitOptions]::RemoveEmptyEntries)){ 258 | $nodeMatch = @($node) | %{ 259 | Get-NodeChild -Node $_ | where{$_.Name -eq $qualifier} 260 | } 261 | if(!$nodeMatch){ 262 | $found = $false 263 | $node = $null 264 | break 265 | } 266 | $node = $nodeMatch 267 | } 268 | 269 | Write-Verbose -Message "$(Get-Date) Nodes found $($node.Count)" 270 | Write-Verbose -Message "$(Get-Date) Nodes: $(($node | %{$_.Name}) -join '|')" 271 | 272 | if($node -eq $null){ 273 | return New-Object PSObject -Property @{ 274 | Path = $Path 275 | Found = $false 276 | Node = $null 277 | } 278 | } 279 | else{ 280 | @($node) | %{ 281 | return New-Object PSObject -Property @{ 282 | Path = $Path 283 | Found = $true 284 | Node = $_ 285 | } 286 | } 287 | } 288 | 289 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Leaving {0}" -f $s[0].FunctionName)" 290 | } 291 | 292 | function Test-VmwNodePath 293 | { 294 | [CmdletBinding()] 295 | [OutputType([System.Boolean])] 296 | param( 297 | [PSObject]$StartNode = (Get-View -Id (Get-View -Id ServiceInstance).Content.RootFolder), 298 | [String]$Path 299 | ) 300 | 301 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 302 | Write-Verbose -Message "$(Get-Date) Start: $($StartNode.Name)" 303 | Write-Verbose -Message "$(Get-Date) Path: $($Path)" 304 | 305 | $nodeObj = Get-VmwNodeFromPath -StartNode $StartNode -Path $Path 306 | 307 | return $nodeObj.Found 308 | 309 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Leaving {0}" -f $s[0].FunctionName)" 310 | } 311 | 312 | function New-VmwFolder 313 | { 314 | [CmdletBinding()] 315 | param( 316 | [VMware.Vim.ManagedEntity]$Parent, 317 | [String]$FolderName, 318 | [VmwFolderType]$FolderType 319 | ) 320 | 321 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 322 | Write-Verbose -Message "$(Get-Date) Create a $($FolderType) folder, named $($FolderName), in $($Parent.Name) " 323 | 324 | if($parent -is [VMware.Vim.Datacenter]){ 325 | if($FolderType -eq [VmwFolderType]::Blue){ 326 | $Parent.UpdateViewData('VmFolder') 327 | $leaf = Get-view -Id $parent.VmFolder -Property Name 328 | } 329 | else{ 330 | $Parent.UpdateViewData('HostFolder') 331 | $leaf = Get-view -Id $parent.HostFolder -Property Name 332 | } 333 | } 334 | else{ 335 | $leaf = $Parent 336 | } 337 | 338 | Write-Verbose -Message "$(Get-Date) Creating folder $($FolderName) at $($leaf.Name)" 339 | $leaf.CreateFolder($FolderName) | Out-Null 340 | 341 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Leaving {0}" -f $s[0].FunctionName)" 342 | } 343 | 344 | function Test-VmwFolderType 345 | { 346 | [CmdletBinding()] 347 | [OutputType([System.Boolean])] 348 | param( 349 | [VMware.Vim.ManagedEntity]$Node, 350 | [VmwFolderType]$FolderType 351 | ) 352 | 353 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 354 | Write-Verbose -Message "$(Get-Date) Testing if folder $($Node.Name) is $($FolderType)" 355 | 356 | if($FolderType -eq [VmwFolderType]::Yellow) 357 | { 358 | $targetParent = 'host' 359 | } 360 | else 361 | { 362 | $targetParent = 'vm' 363 | } 364 | 365 | $si = Get-View -Id ServiceInstance 366 | $rootFolder = Get-View -Id $si.Content.RootFolder 367 | 368 | $foundType = $false 369 | if($Node.Parent -eq $rootFolder.MoRef -and $FolderType -eq [VmwFolderType]::Yellow){ 370 | $foundType = $true 371 | } 372 | else{ 373 | while($Node.Parent -ne $null){ 374 | $Node = Get-View -Id $Node.Parent 375 | if($Node -is [VMware.Vim.Folder] -and $Node.Name -eq $targetParent){ 376 | $foundType = $true 377 | break 378 | } 379 | } 380 | } 381 | 382 | Write-Verbose -Message "$(Get-Date) FoundType: $($foundType)" 383 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Leaving {0}" -f $s[0].FunctionName)" 384 | 385 | return $foundType 386 | } 387 | 388 | function Test-VmwDatacenterIsNested 389 | { 390 | [CmdletBinding()] 391 | param( 392 | [VMware.Vim.ManagedEntity]$Node 393 | ) 394 | 395 | $isNested = $false 396 | $parent = $Node.Parent 397 | while($parent){ 398 | $parentObj = Get-View -Id $parent -Property Name,Parent 399 | if($parentObj -is [VMware.Vim.Datacenter]){ 400 | $isNedsted = $true 401 | } 402 | $parent = $parentObj.Parent 403 | } 404 | } 405 | 406 | function New-VmwDatacenter 407 | { 408 | [CmdletBinding()] 409 | param( 410 | [VMware.Vim.ManagedEntity]$Parent, 411 | [String]$DatacenterName 412 | ) 413 | 414 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Entering {0}" -f $s[0].FunctionName)" 415 | Write-Verbose -Message "$(Get-Date) Create a datacenter, named $($DatacenterName), in $($Parent.Name) " 416 | 417 | $si = Get-View -Id ServiceInstance 418 | $rootFolder = Get-View -Id $si.Content.RootFolder 419 | 420 | if($parent -is [VMware.Vim.Folder] -and 421 | (($parent.MoRef -eq $si.Content.RootFolder) -or 422 | (Test-VmwFolderType -Node $Parent -FolderType ([VmwFolderType]::Yellow))) -and 423 | !(Test-VmwDatacenterIsNested -Node $Parent)){ 424 | 425 | Write-Verbose -Message "$(Get-Date) Creating datacenter $($DatacenterName) at $($Parent.Name)" 426 | $Parent.CreateDatacenter($DatacenterName) | Out-Null 427 | } 428 | 429 | Write-Verbose -Message "$(Get-Date) $($s = Get-PSCallStack;"Leaving {0}" -f $s[0].FunctionName)" 430 | } 431 | --------------------------------------------------------------------------------