├── ADinfo.ps1
├── BuildNimbleDatastore.ps1
├── FormMove-CrossVC.ps1
├── LICENSE
├── Move-CrossVC.ps1
├── NUMAReport.ps1
├── NUMAReportcsv.ps1
├── OVNimbleDataStoreBuild.ps1
├── OVNimbleDatastore.ps1
├── OVVolumeBuild.ps1
├── PSVMReport.ps1
├── PatchCompliance.ps1
├── README.md
├── VMReport.ps1
├── VMinfo.ps1
├── add-stdportgroup.ps1
├── alarms.ps1
├── export.ps1
├── get-LUNinfo.ps1
├── import.ps1
├── set-multipath.ps1
└── show-menu.ps1
/ADinfo.ps1:
--------------------------------------------------------------------------------
1 | $Computers = (Get-ADComputer -Filter *).count
2 | $Workstations = (Get-ADComputer -LDAPFilter "(&(objectClass=Computer)(!operatingSystem=*server*))" -Searchbase (Get-ADDomain).distinguishedName).count
3 | $Servers = (Get-ADComputer -LDAPFilter "(&(objectClass=Computer)(operatingSystem=*server*))" -Searchbase (Get-ADDomain).distinguishedName).count
4 | $Users = (get-aduser -filter *).count
5 | $domain = Get-ADDomain |FT Forest
6 | $FSMO = netdom query FSMO
7 | $ADForest = (Get-ADForest).ForestMode
8 | $ADDomain = (Get-ADDomain).DomainMode
9 | $ADVer = Get-ADObject (Get-ADRootDSE).schemaNamingContext -property objectVersion | Select objectVersion
10 | $ADNUM = $ADVer -replace "@{objectVersion=","" -replace "}",""
11 |
12 | If ($ADNum -eq '88') {$srv = 'Windows Server 2019'}
13 | ElseIf ($ADNum -eq '87') {$srv = 'Windows Server 2016'}
14 | ElseIf ($ADNum -eq '69') {$srv = 'Windows Server 2012 R2'}
15 | ElseIf ($ADNum -eq '56') {$srv = 'Windows Server 2012'}
16 | ElseIf ($ADNum -eq '47') {$srv = 'Windows Server 2008 R2'}
17 | ElseIf ($ADNum -eq '44') {$srv = 'Windows Server 2008'}
18 | ElseIf ($ADNum -eq '31') {$srv = 'Windows Server 2003 R2'}
19 | ElseIf ($ADNum -eq '30') {$srv = 'Windows Server 2003'}
20 |
21 |
22 |
23 | Write-Host "For this Domain there are;"
24 | Write-Host "Computers = "$Computers -ForegroundColor Cyan
25 | Write-Host "Workstions = "$Workstations -ForegroundColor Cyan
26 | Write-Host "Servers = "$Servers -ForegroundColor Cyan
27 | Write-Host "Users = "$Users -ForegroundColor Cyan
28 | Write-host ""
29 | Write-host "Active Directory Info" -ForegroundColor Yellow
30 | Write-Host "Active Directory Forest Mode = "$ADForest -ForegroundColor Cyan
31 | Write-Host "Active Directory Domain Mode = "$ADDomain -ForegroundColor Cyan
32 | Write-Host "Active Directory Schema Version is $ADNum which corresponds to $Srv" -ForegroundColor Cyan
33 | Write-Host ""
34 | Write-Host "FSMO Role Owners" -ForegroundColor Cyan
35 | $FSMO
36 |
37 | Write-Host "Active Directory Health Check" -ForegroundColor Yellow
38 | Write-Host ""
39 | #####################################Get ALL DC Servers#################################
40 | $getForest = [system.directoryservices.activedirectory.Forest]::GetCurrentForest()
41 |
42 | $DCServers = $getForest.domains | ForEach-Object {$_.DomainControllers} | ForEach-Object {$_.Name}
43 |
44 | $timeout = "60"
45 | foreach ($DC in $DCServers){
46 | $Identity = $DC
47 | ################Ping Test######
48 | if ( Test-Connection -ComputerName $DC -Count 1 -ErrorAction SilentlyContinue ) {
49 | Write-Host $DC `t $DC `t Ping Success -ForegroundColor Green
50 | ##############Netlogon Service Status################
51 | $serviceStatus = start-job -scriptblock {get-service -ComputerName $($args[0]) -Name "Netlogon" -ErrorAction SilentlyContinue} -ArgumentList $DC
52 | wait-job $serviceStatus -timeout $timeout
53 | if($serviceStatus.state -like "Running")
54 | {
55 | Write-Host $DC `t Netlogon Service TimeOut -ForegroundColor Yellow
56 | stop-job $serviceStatus
57 | }
58 | else
59 | {
60 | $serviceStatus1 = Receive-job $serviceStatus
61 | if ($serviceStatus1.status -eq "Running") {
62 | Write-Host $DC `t $serviceStatus1.name `t $serviceStatus1.status -ForegroundColor Green
63 | $svcName = $serviceStatus1.name
64 | $svcState = $serviceStatus1.status
65 | }
66 | else
67 | {
68 | Write-Host $DC `t $serviceStatus1.name `t $serviceStatus1.status -ForegroundColor Red
69 | $svcName = $serviceStatus1.name
70 | $svcState = $serviceStatus1.status
71 | }
72 | }
73 | }
74 | ##############NTDS Service Status################
75 | $serviceStatus = start-job -scriptblock {get-service -ComputerName $($args[0]) -Name "NTDS" -ErrorAction SilentlyContinue} -ArgumentList $DC
76 | wait-job $serviceStatus -timeout $timeout
77 | if($serviceStatus.state -like "Running")
78 | {
79 | Write-Host $DC `t NTDS Service TimeOut -ForegroundColor Yellow
80 | stop-job $serviceStatus
81 | }
82 | else
83 | {
84 | $serviceStatus1 = Receive-job $serviceStatus
85 | if ($serviceStatus1.status -eq "Running") {
86 | Write-Host $DC `t $serviceStatus1.name `t $serviceStatus1.status -ForegroundColor Green
87 | $svcName = $serviceStatus1.name
88 | $svcState = $serviceStatus1.status
89 | }
90 | else
91 | {
92 | Write-Host $DC `t $serviceStatus1.name `t $serviceStatus1.status -ForegroundColor Red
93 | $svcName = $serviceStatus1.name
94 | $svcState = $serviceStatus1.status
95 | }
96 | }
97 | ##############DNS Service Status################
98 | $serviceStatus = start-job -scriptblock {get-service -ComputerName $($args[0]) -Name "DNS" -ErrorAction SilentlyContinue} -ArgumentList $DC
99 | wait-job $serviceStatus -timeout $timeout
100 | if($serviceStatus.state -like "Running")
101 | {
102 | Write-Host $DC `t DNS Server Service TimeOut -ForegroundColor Yellow
103 | stop-job $serviceStatus
104 | }
105 | else
106 | {
107 | $serviceStatus1 = Receive-job $serviceStatus
108 | if ($serviceStatus1.status -eq "Running") {
109 | Write-Host $DC `t $serviceStatus1.name `t $serviceStatus1.status -ForegroundColor Green
110 | $svcName = $serviceStatus1.name
111 | $svcState = $serviceStatus1.status
112 | }
113 | else
114 | {
115 | Write-Host $DC `t $serviceStatus1.name `t $serviceStatus1.status -ForegroundColor Red
116 | $svcName = $serviceStatus1.name
117 | $svcState = $serviceStatus1.status
118 | }
119 | }
120 | ####################Netlogons status##################
121 | add-type -AssemblyName microsoft.visualbasic
122 | $cmp = "microsoft.visualbasic.strings" -as [type]
123 | $sysvol = start-job -scriptblock {dcdiag /test:netlogons /s:$($args[0])} -ArgumentList $DC
124 | wait-job $sysvol -timeout $timeout
125 | if($sysvol.state -like "Running")
126 | {
127 | Write-Host $DC `t Netlogons Test TimeOut -ForegroundColor Yellow
128 | stop-job $sysvol
129 | }
130 | else
131 | {
132 | $sysvol1 = Receive-job $sysvol
133 | if($cmp::instr($sysvol1, "passed test NetLogons"))
134 | {
135 | Write-Host $DC `t Netlogons Test passed -ForegroundColor Green
136 | }
137 | else
138 | {
139 | Write-Host $DC `t Netlogons Test Failed -ForegroundColor Red
140 | }
141 | }
142 |
143 | ####################Replications status#################
144 | add-type -AssemblyName microsoft.visualbasic
145 | $cmp = "microsoft.visualbasic.strings" -as [type]
146 | $sysvol = start-job -scriptblock {dcdiag /test:Replications /s:$($args[0])} -ArgumentList $DC
147 | wait-job $sysvol -timeout $timeout
148 | if($sysvol.state -like "Running")
149 | {
150 | Write-Host $DC `t Replications Test TimeOut -ForegroundColor Yellow
151 | stop-job $sysvol
152 | }
153 | else
154 | {
155 | $sysvol1 = Receive-job $sysvol
156 | if($cmp::instr($sysvol1, "passed test Replications"))
157 | {
158 | Write-Host $DC `t Replications Test passed -ForegroundColor Green
159 | }
160 | else
161 | {
162 | Write-Host $DC `t Replications Test Failed -ForegroundColor Red
163 | }
164 | }
165 | ####################Services status#####################
166 | add-type -AssemblyName microsoft.visualbasic
167 | $cmp = "microsoft.visualbasic.strings" -as [type]
168 | $sysvol = start-job -scriptblock {dcdiag /test:Services /s:$($args[0])} -ArgumentList $DC
169 | wait-job $sysvol -timeout $timeout
170 | if($sysvol.state -like "Running")
171 | {
172 | Write-Host $DC `t Services Test TimeOut -ForegroundColor Yellow
173 | stop-job $sysvol
174 | }
175 | else
176 | {
177 | $sysvol1 = Receive-job $sysvol
178 | if($cmp::instr($sysvol1, "passed test Services"))
179 | {
180 | Write-Host $DC `t Services Test passed -ForegroundColor Green
181 | }
182 | else
183 | {
184 | Write-Host $DC `t Services Test Failed -ForegroundColor Red
185 | }
186 | }
187 | ####################Advertising status##################
188 | add-type -AssemblyName microsoft.visualbasic
189 | $cmp = "microsoft.visualbasic.strings" -as [type]
190 | $sysvol = start-job -scriptblock {dcdiag /test:Advertising /s:$($args[0])} -ArgumentList $DC
191 | wait-job $sysvol -timeout $timeout
192 | if($sysvol.state -like "Running")
193 | {
194 | Write-Host $DC `t Advertising Test TimeOut -ForegroundColor Yellow
195 | stop-job $sysvol
196 | }
197 | else
198 | {
199 | $sysvol1 = Receive-job $sysvol
200 | if($cmp::instr($sysvol1, "passed test Advertising"))
201 | {
202 | Write-Host $DC `t Advertising Test passed -ForegroundColor Green
203 | }
204 | else
205 | {
206 | Write-Host $DC `t Advertising Test Failed -ForegroundColor Red
207 | }
208 | }
209 | ####################FSMOCheck status##################
210 | add-type -AssemblyName microsoft.visualbasic
211 | $cmp = "microsoft.visualbasic.strings" -as [type]
212 | $sysvol = start-job -scriptblock {dcdiag /test:FSMOCheck /s:$($args[0])} -ArgumentList $DC
213 | wait-job $sysvol -timeout $timeout
214 | if($sysvol.state -like "Running")
215 | {
216 | Write-Host $DC `t FSMOCheck Test TimeOut -ForegroundColor Yellow
217 | stop-job $sysvol
218 | }
219 | else
220 | {
221 | $sysvol1 = Receive-job $sysvol
222 | if($cmp::instr($sysvol1, "passed test FsmoCheck"))
223 | {
224 | Write-Host $DC `t FSMOCheck Test passed -ForegroundColor Green
225 | }
226 | else
227 | {
228 | Write-Host $DC `t FSMOCheck Test Failed -ForegroundColor Red
229 | }
230 | }
231 | Write-Host ""
232 | }
233 |
--------------------------------------------------------------------------------
/BuildNimbleDatastore.ps1:
--------------------------------------------------------------------------------
1 | #connect to Nimble, be sure to add your Nimble IP or FQDN in the ""
2 | Write-Host "Connecting to Nimble" -ForegroundColor Green
3 | Connect-NSGroup "" -IgnoreServerCertificate -Credential admin
4 |
5 | #VMWare performance policy ID
6 | $id = "0366971348fab73f4b000000000000000000000014"
7 |
8 | #Initiator Groups (per host)
9 | $CMH001 = "0266971348fab73f4b000000000000000000000007"
10 | $CMH002 = "0266971348fab73f4b000000000000000000000008"
11 | $CMH003 = "0266971348fab73f4b000000000000000000000009"
12 | $CMH004 = "0266971348fab73f4b00000000000000000000000a"
13 |
14 | $name = Read-Host "Enter Datastore Name"
15 | $size = Read-Host "Enter Datastore Size in MB"
16 |
17 | New-NSVolume -name $name -size $size -perfpolicy_id $id -thinly_provisioned $true -online $true
18 |
19 | #remove charactors in the volume id so they are usable
20 | $vol = Get-NSvolume -name "test2" | select ID
21 | $id = $vol -replace "@{id=","" -replace "}", ""
22 |
23 | #add new volume to initiator groups
24 | New-NSAccessControlRecord -vol_id $id -apply_to both -initiator_group_id $CMH001 -lun 4
25 | New-NSAccessControlRecord -vol_id $id -apply_to both -initiator_group_id $CMH002 -lun 4
26 | New-NSAccessControlRecord -vol_id $id -apply_to both -initiator_group_id $CMH003 -lun 4
27 | New-NSAccessControlRecord -vol_id $id -apply_to both -initiator_group_id $CMH004 -lun 4
28 |
29 | #connect to vmware to create datastore
30 | Write-host "Connecting to vCenter" -ForegroundColor Green
31 | Connect-viserver 192.168.151.2 -User administrator@vsphere.local
32 |
33 | #rescan host for new storage
34 | Get-VMHost | Get-VMHostStorage -RescanAllHba -Refresh
35 |
36 | #function to find free LUNs found at http://vcloud-lab.com/entries/powercli/find-free-or-unassigned-storage-lun-disks-on-vmware-esxi-server
37 | # removed some of the notes to save space
38 | function Get-FreeEsxiLUNs {
39 | #EXAMPLE
40 | #Get-FreeEsxiLUNs -Esxihost Esxi001.vcloud-lab.com
41 | #Shows free unassigned storage Luns disks on Esxi host name Esxi001.vcloud-lab.com
42 | ###############################
43 |
44 | [CmdletBinding()]
45 | param(
46 | [Parameter(Position=0, Mandatory=$true)]
47 | [System.String]$Esxihost
48 | )
49 | Begin {
50 | if (-not(Get-Module vmware.vimautomation.core)) {
51 | Import-Module vmware.vimautomation.core
52 | }
53 | #Connect-VIServer | Out-Null
54 | }
55 | Process {
56 | $VMhost = Get-VMhost $EsxiHost
57 | $AllLUNs = $VMhost | Get-ScsiLun -LunType disk
58 | $Datastores = $VMhost | Get-Datastore
59 | foreach ($lun in $AllLUNs) {
60 | $Datastore = $Datastores | Where-Object {$_.extensiondata.info.vmfs.extent.Diskname -Match $lun.CanonicalName}
61 | if ($Datastore.Name -eq $null) {
62 | $lun | Select-Object CanonicalName, CapacityGB, Vendor
63 | }
64 | }
65 | }
66 | End {}
67 | }
68 |
69 | $free = Get-FreeEsxiLUNs -Esxihost (get-vmhost | Get-random) | Where-Object {$_.Vendor -eq "Nimble"} |select CanonicalName
70 | $path = $free -replace "@{CanonicalName=","" -replace "}",""
71 |
72 |
73 | #create new Datastore
74 | Get-VMHost| Get-Random | New-Datastore -name "test" -Path $path -Vmfs -FileSystemVersion 6
75 |
76 | #rescan vhost for new Datastore
77 | Get-VMHost | Get-VMHostStorage -RescanAllHba -Refresh
78 |
79 | #Disconnect from Nimble and vCenter
80 | Disconnect-NSGroup
81 | Disconnect-VIServer -Server * -confirm:$false
82 |
--------------------------------------------------------------------------------
/FormMove-CrossVC.ps1:
--------------------------------------------------------------------------------
1 | $inputXML = @"
2 |
3 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | "@
43 |
44 | $inputXML = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace '^ to exit"
114 | }
115 | Else {
116 | # Something else went wrong, just display the text and exit
117 | $Err.Exception
118 | Break
119 | }
120 | }
121 | Else {
122 | Read-Host "User name and password are valid"
123 | Connect-VIServer $SourceVC -Credential $Cred
124 | }
125 | }
126 | Until ($Err.Count -eq 0)
127 |
128 | Do {
129 | # Loop until we get a valid userid/password and can connect, or some other kind of error occurs
130 | $Cred = Get-Credential -Message "Enter $destVC Credentials"
131 | $ConResult = Connect-VIServer -Server $destVC -Credential $Cred -ErrorAction SilentlyContinue -ErrorVariable Err
132 | If ($Err.Count -gt 0) {
133 | # Some kind of error, figure out if its a bad password
134 | If ($Err.Exception.GetType().Name -eq "InvalidLogin") {
135 | Read-Host "Incorrect user name or password, hit any key to try again or to exit"
136 | }
137 | Else {
138 | # Something else went wrong, just display the text and exit
139 | $Err.Exception
140 | Break
141 | }
142 | }
143 | Else {
144 | Read-Host "User name and password are valid"
145 | Connect-VIServer $destVC -Credential $Cred
146 | }
147 | }
148 | Until ($Err.Count -eq 0)
149 |
150 |
151 | $VM = Get-Cluster $sourceCluster -Server $sourceVC | Get-VM $vmname -Server $sourceVC -erroraction SilentlyContinue
152 |
153 | Describe -Name 'Testing vSphere Infrastructure' {
154 | Context -Name 'Checking vCenters for Cross-vCenter vMotion compatibility' {
155 | It -Name "Source and destination vCenter version are compatible with Cross vCenter vMotion (minimum 6.0)" {
156 | #($sourceVC.Version -ge [version]'6.0') -and ($destVC.Version -ge [version]'6.0') | Should Be $True
157 | }
158 |
159 | If ($sourceVC.Version -eq [version]'6.5') {
160 | It -Name "If source version equals 6.5, destination version should not be 6.0" {
161 | ($destVC.Version -eq [version]'6.0') | Should Be $false
162 | }
163 | }
164 | }
165 |
166 | Context -Name 'Testing Clusters translation table' {
167 | foreach ($cluster in $sourceCluster) {
168 | It "Source cluster $($SourceCluster) exists" {
169 | {Get-Cluster -Name $sourceCluster -Server $sourceVC} | Should Not Throw
170 | }
171 | It "Destination cluster $($DestCluster) exists" {
172 | {Get-Cluster -Name $DestCluster -Server $destVC} | Should Not Throw
173 | }
174 | }
175 | }
176 |
177 | Context -Name 'Testing VMHosts' {
178 |
179 | $sourceVMHosts = @()
180 |
181 | foreach ($cluster in $SourceCluster) {
182 | $sourceVMHosts += Get-Cluster -Name $sourceCluster -Server $sourceVC -ErrorAction SilentlyContinue | Get-VMHost -ErrorAction SilentlyContinue
183 | }
184 |
185 | $destinationVMHosts = @()
186 |
187 | foreach ($cluster in $DestCluster) {
188 | $destinationVMHosts += Get-Cluster -Name $destCluster -Server $destVC -ErrorAction SilentlyContinue | Get-VMHost -ErrorAction SilentlyContinue
189 | }
190 |
191 | It -Name "Source cluster contains VMhosts" {
192 | $sourceVMHosts.Count | Should BeGreaterThan 0
193 | }
194 |
195 | Foreach ($VMHost in $sourceVMHosts) {
196 | It -Name "Source VMHost $($VMHost.Name) version is compatible with Cross-vCenter vMotion (minimum 6.0)" {
197 | $VMHost.Version -ge [version]'6.0' | Should Be $True
198 | }
199 | }
200 |
201 | It -Name "Destination cluster contains VMhosts" {
202 | $destinationVMHosts.Count | Should BeGreaterThan 0
203 | }
204 |
205 | Foreach ($VMHost in $destinationVMHosts) {
206 | It -Name "Destination VMHost $($VMHost.Name) version is compatible with Cross vCenter vMotion (minimum 6.0)" {
207 | $VMHost.Version -ge [version]'6.0' | Should Be $True
208 | }
209 | }
210 | }
211 |
212 | Context -Name "Testing VMs" {
213 | It -Name "Found VM matching scope $($vmname)" {
214 | $VM.count | Should BeGreaterThan 0
215 | }
216 | }
217 |
218 | If ($PG) {
219 | Context -Name 'Testing Portgroups translation table' {
220 | Foreach ($portgroup in $PG) {
221 |
222 | $sourcePortgroup = Get-VirtualPortGroup -Name $sourcePG -Server $sourceVC -ErrorAction SilentlyContinue
223 |
224 | It -name "Source portgroup $($sourcePG) exists" {
225 | $sourcePortgroup.count | Should BeGreaterThan 0
226 | }
227 |
228 | $Destinationportgroup = Get-VirtualPortGroup -Name $destPG -Server $destVC -ErrorAction SilentlyContinue
229 |
230 | It -name "Destination portgroup $($destPG) exists" {
231 | $Destinationportgroup.count | Should BeGreaterThan 0
232 | }
233 |
234 | If ($sourcePortgroup.ExtensionData.Key -like 'dvportgroup-*') {
235 | It -name "If source portgroup is a vds, destination can't be a vss" {
236 | ($sourcePortgroup.ExtensionData.Key -like 'dvportgroup-*') -and ($Destinationportgroup.ExtensionData.Key -notlike 'dvportgroup-*') | Should Be $False
237 | }
238 | }
239 | }
240 | }
241 | }
242 |
243 | If ($DS) {
244 | Context -Name 'Testing Datastores translation table' {
245 | Foreach ($datastore in $DS) {
246 | It -name "Source datastore $($sourceDS) exists" {
247 | {Get-Datastore -Name $sourceDS -Server $sourceVC} | Should Not Throw
248 | }
249 | It -name "Destination datastore $($destDS) exists" {
250 | {Get-Datastore -Name $destDS -Server $destVC} | Should Not Throw
251 | }
252 | }
253 | }
254 | }
255 | }
256 |
257 |
258 | Write-host " Powering off $vm" -ForegroundColor Yellow
259 | Try{
260 | $vmm = Get-VM -Name $vmName -ErrorAction Stop
261 | switch($vmm.PowerState){
262 | 'poweredon' {
263 | Shutdown-VMGuest -VM $vm -Confirm:$false
264 | while($vmm.PowerState -eq 'PoweredOn'){
265 | sleep 5
266 |
267 | $vmm = Get-VM -Name $vmName
268 | }
269 | }
270 | Default {
271 | Write-Host "VM '$($vmName)' is not powered on!" -ForegroundColor Yellow
272 | }
273 | }
274 | Write-Host "$($vmName) has shutdown. It should be ready for Migration to $destVC." -ForegroundColor Green
275 | }
276 |
277 | Catch{
278 |
279 | Write-Host "VM '$($vmName)' not found!" -ForegroundColor Red
280 |
281 | }
282 |
283 | Sleep 10
284 | $vm = Get-VM $vmname -Server $sourceVC
285 | $Destination = Get-VMHost -Location $destCluster -Server $DestVC | Get-Random
286 | $NetworkAdapter = Get-NetworkAdapter -VM $vm -Server $sourceVC
287 | $VMPG = Get-VirtualPortGroup -VirtualSwitch $destSwitch -Name $DestPG -Server $destVC
288 | $DS = Get-Datastore -Name $destDS -Server $destVC
289 |
290 | Write-Host " Moving $vm from $sourceVC to $destVC. $vm will be in the $destCluster on host $destination. Please Stand By.." -ForegroundColor yellow
291 |
292 | Move-VM $vm -Destination $Destination -NetworkAdapter $NetworkAdapter -PortGroup $VMPG -Datastore $DS -Confirm:$false
293 |
294 | Sleep 5
295 |
296 | Write-Host " Powering on $vm and waiting for VM Tools to start" -ForegroundColor Green
297 | Start-VM $vmname -Server $DestVC
298 |
299 | do {
300 | $toolsStatus = (Get-VM $vmname | Get-View).Guest.ToolsStatus
301 | write-host $toolsStatus
302 | sleep 3
303 | } until ( $toolsStatus -ne ‘toolsNotRunning’ )
304 |
305 | #Update vmware tools
306 | Write-Host " Checking and upgrading VMware Tools and VM Copatibility if nesessary" -ForegroundColor Yellow
307 | Get-VM $vmname | % { get-view $_.id } |Where-Object {$_.Guest.ToolsVersionStatus -like "guestToolsNeedUpgrade"} |select name, @{Name=“ToolsVersion”; Expression={$_.config.tools.toolsversion}}, @{ Name=“ToolStatus”; Expression={$_.Guest.ToolsVersionStatus}}| Update-Tools -NoReboot -VM {$_.Name} -Verbose
308 |
309 | Write-Host " Rebooting $vmname after VM Compatibility Upgrade"
310 | Restart-VM -VM $vmname -Server $DestVC -Confirm:$false
311 | do {
312 | $toolsStatus = (Get-VM $vmname | Get-View).Guest.ToolsStatus
313 | write-host $toolsStatus
314 | sleep 3
315 | } until ( $toolsStatus -ne ‘toolsNotRunning’ )
316 |
317 |
318 |
319 | $StopWatch.Stop()
320 | #Calculating Migration Time
321 | $migrationTime = [math]::Round(($StopWatch.Elapsed).TotalMinutes ,2)
322 |
323 | Write-Host " $vm is ready to use. Migration is Complete" -ForegroundColor Green
324 | Write-Host " Total Migration time for $vmname was $migrationtime minutes" -ForegroundColor Cyan
325 | sleep 2
326 | Write-Host " Disconnecting from vCenters $sourceVC and $destVC" -ForegroundColor Yellow
327 | Disconnect-VIServer -Server * -Confirm:$false
328 |
329 | }
330 |
331 |
332 | $WPFCancel.Add_Click({$form.Close()})
333 | $WPFMigrate.Add_Click({Move-CrossVC })
334 |
335 |
336 | $Form.ShowDialog() | out-null
337 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/Move-CrossVC.ps1:
--------------------------------------------------------------------------------
1 | Function Move-CrossVC
2 | {
3 | ########################################################################################################################################
4 | # Move-CrossVC #
5 | # Updated by: Shane Moore 12/20/2019 #
6 | # Revision 1.1 12/26/2019 #
7 | # Revision 1.2 1/8/2019 #
8 | # Core code by VMware and the PSxVCvMotion module link here: https://code.vmware.com/samples/2060/psxvcvmotion---cross-vcenter-vmotion #
9 | ########################################################################################################################################
10 |
11 | # making sure Pester is installed and Getting variable information
12 | Import-Module Pester
13 | $sourceVC = Read-Host " Enter Source vCenter Name"
14 | $DestVC = Read-Host " Enter Destination vCenter Name"
15 | $vmname = Read-host " Enter VM name to Migrate"
16 | $sourceCluster = Read-Host " Enter Source Cluster Name"
17 | $destCluster = Read-Host " Enter Destination Cluster Name"
18 | $sourcePG = Read-Host " Enter Source Port Group (Network) information"
19 | $DestPG = Read-Host " Enter Destination Port Group (Network) information"
20 | $destSwitch = Read-Host " Enter Destination Virtual Switch Name"
21 | $PG = $sourcePG, $DestPG
22 | $sourceDS = Read-Host " Enter Source Datastore"
23 | $destDS = Read-Host " Enter Destination DataStore"
24 | $DS = $sourceDS, $destDS
25 |
26 | # Clear Screen and start the stopwatch
27 | cls
28 | $StopWatch = New-Object -TypeName System.Diagnostics.Stopwatch
29 | $stopwatch.Start()
30 |
31 | #Creating connection to both vCenters
32 | Write-Host "Connecting to Source and Destination vCenters" -ForegroundColor Yellow
33 | Do {
34 | # Loop until we get a valid userid/password and can connect, or some other kind of error occurs
35 | $Cred = Get-Credential -Message "Enter $SourceVC Credentials"
36 | $ConResult = Connect-VIServer -Server $SourceVC -Credential $Cred -ErrorAction SilentlyContinue -ErrorVariable Err
37 | If ($Err.Count -gt 0) {
38 | # Some kind of error, figure out if its a bad password
39 | If ($Err.Exception.GetType().Name -eq "InvalidLogin") {
40 | Read-Host "Incorrect user name or password, hit any key to try again or to exit"
41 | }
42 | Else {
43 | # Something else went wrong, just display the text and exit
44 | $Err.Exception
45 | Break
46 | }
47 | }
48 | Else {
49 | Read-Host "User name and password are valid"
50 | Connect-VIServer $SourceVC -Credential $Cred
51 | }
52 | }
53 | Until ($Err.Count -eq 0)
54 |
55 | Do {
56 | # Loop until we get a valid userid/password and can connect, or some other kind of error occurs
57 | $Cred = Get-Credential -Message "Enter $destVC Credentials"
58 | $ConResult = Connect-VIServer -Server $destVC -Credential $Cred -ErrorAction SilentlyContinue -ErrorVariable Err
59 | If ($Err.Count -gt 0) {
60 | # Some kind of error, figure out if its a bad password
61 | If ($Err.Exception.GetType().Name -eq "InvalidLogin") {
62 | Read-Host "Incorrect user name or password, hit any key to try again or to exit"
63 | }
64 | Else {
65 | # Something else went wrong, just display the text and exit
66 | $Err.Exception
67 | Break
68 | }
69 | }
70 | Else {
71 | Read-Host "User name and password are valid"
72 | Connect-VIServer $destVC -Credential $Cred
73 | }
74 | }
75 | Until ($Err.Count -eq 0)
76 |
77 |
78 |
79 | $VM = Get-Cluster $sourceCluster -Server $sourceVC | Get-VM $vmname -Server $sourceVC -erroraction SilentlyContinue
80 |
81 | Describe -Name 'Testing vSphere Infrastructure' {
82 | Context -Name 'Checking vCenters for Cross-vCenter vMotion compatibility' {
83 | It -Name "Source and destination vCenter version are compatible with Cross vCenter vMotion (minimum 6.0)" {
84 | #($sourceVC.Version -ge [version]'6.0') -and ($destVC.Version -ge [version]'6.0') | Should Be $True
85 | }
86 |
87 | If ($sourceVC.Version -eq [version]'6.5') {
88 | It -Name "If source version equals 6.5, destination version should not be 6.0" {
89 | ($destVC.Version -eq [version]'6.0') | Should Be $false
90 | }
91 | }
92 | }
93 |
94 | Context -Name 'Testing Clusters translation table' {
95 | foreach ($cluster in $sourceCluster) {
96 | It "Source cluster $($SourceCluster) exists" {
97 | {Get-Cluster -Name $sourceCluster -Server $sourceVC} | Should Not Throw
98 | }
99 | It "Destination cluster $($DestCluster) exists" {
100 | {Get-Cluster -Name $DestCluster -Server $destVC} | Should Not Throw
101 | }
102 | }
103 | }
104 |
105 | Context -Name 'Testing VMHosts' {
106 |
107 | $sourceVMHosts = @()
108 |
109 | foreach ($cluster in $SourceCluster) {
110 | $sourceVMHosts += Get-Cluster -Name $sourceCluster -Server $sourceVC -ErrorAction SilentlyContinue | Get-VMHost -ErrorAction SilentlyContinue
111 | }
112 |
113 | $destinationVMHosts = @()
114 |
115 | foreach ($cluster in $DestCluster) {
116 | $destinationVMHosts += Get-Cluster -Name $destCluster -Server $destVC -ErrorAction SilentlyContinue | Get-VMHost -ErrorAction SilentlyContinue
117 | }
118 |
119 | It -Name "Source cluster contains VMhosts" {
120 | $sourceVMHosts.Count | Should BeGreaterThan 0
121 | }
122 |
123 | Foreach ($VMHost in $sourceVMHosts) {
124 | It -Name "Source VMHost $($VMHost.Name) version is compatible with Cross-vCenter vMotion (minimum 6.0)" {
125 | $VMHost.Version -ge [version]'6.0' | Should Be $True
126 | }
127 | }
128 |
129 | It -Name "Destination cluster contains VMhosts" {
130 | $destinationVMHosts.Count | Should BeGreaterThan 0
131 | }
132 |
133 | Foreach ($VMHost in $destinationVMHosts) {
134 | It -Name "Destination VMHost $($VMHost.Name) version is compatible with Cross vCenter vMotion (minimum 6.0)" {
135 | $VMHost.Version -ge [version]'6.0' | Should Be $True
136 | }
137 | }
138 | }
139 |
140 | Context -Name "Testing VMs" {
141 | It -Name "Found VM matching scope $($vmname)" {
142 | $VM.count | Should BeGreaterThan 0
143 | }
144 | }
145 |
146 | If ($PG) {
147 | Context -Name 'Testing Portgroups translation table' {
148 | Foreach ($portgroup in $PG) {
149 |
150 | $sourcePortgroup = Get-VirtualPortGroup -Name $sourcePG -Server $sourceVC -ErrorAction SilentlyContinue
151 |
152 | It -name "Source portgroup $($sourcePG) exists" {
153 | $sourcePortgroup.count | Should BeGreaterThan 0
154 | }
155 |
156 | $Destinationportgroup = Get-VirtualPortGroup -Name $destPG -Server $destVC -ErrorAction SilentlyContinue
157 |
158 | It -name "Destination portgroup $($destPG) exists" {
159 | $Destinationportgroup.count | Should BeGreaterThan 0
160 | }
161 |
162 | If ($sourcePortgroup.ExtensionData.Key -like 'dvportgroup-*') {
163 | It -name "If source portgroup is a vds, destination can't be a vss" {
164 | ($sourcePortgroup.ExtensionData.Key -like 'dvportgroup-*') -and ($Destinationportgroup.ExtensionData.Key -notlike 'dvportgroup-*') | Should Be $False
165 | }
166 | }
167 | }
168 | }
169 | }
170 |
171 | If ($DS) {
172 | Context -Name 'Testing Datastores translation table' {
173 | Foreach ($datastore in $DS) {
174 | It -name "Source datastore $($sourceDS) exists" {
175 | {Get-Datastore -Name $sourceDS -Server $sourceVC} | Should Not Throw
176 | }
177 | It -name "Destination datastore $($destDS) exists" {
178 | {Get-Datastore -Name $destDS -Server $destVC} | Should Not Throw
179 | }
180 | }
181 | }
182 | }
183 | }
184 |
185 |
186 | Write-host " Powering off $vm" -ForegroundColor Yellow
187 | Try{
188 | $vmm = Get-VM -Name $vmName -ErrorAction Stop
189 | switch($vmm.PowerState){
190 | 'poweredon' {
191 | Shutdown-VMGuest -VM $vm -Confirm:$false
192 | while($vmm.PowerState -eq 'PoweredOn'){
193 | sleep 5
194 |
195 | $vmm = Get-VM -Name $vmName
196 | }
197 | }
198 | Default {
199 | Write-Host "VM '$($vmName)' is not powered on!" -ForegroundColor Yellow
200 | }
201 | }
202 | Write-Host "$($vmName) has shutdown. It should be ready for Migration to $destVC." -ForegroundColor Green
203 | }
204 |
205 | Catch{
206 |
207 | Write-Host "VM '$($vmName)' not found!" -ForegroundColor Red
208 |
209 | }
210 |
211 | Sleep 10
212 | $vm = Get-VM $vmname -Server $sourceVC
213 | $Destination = Get-VMHost -Location $destCluster -Server $DestVC | Get-Random
214 | $NetworkAdapter = Get-NetworkAdapter -VM $vm -Server $sourceVC
215 | $VMPG = Get-VirtualPortGroup -VirtualSwitch $destSwitch -Name $DestPG -Server $destVC
216 | $DS = Get-Datastore -Name $destDS -Server $destVC
217 |
218 | Write-Host " Moving $vm from $sourceVC to $destVC. $vm will be in the $destCluster on host $destination. Please Stand By...." -ForegroundColor yellow
219 |
220 | Move-VM $vm -Destination $Destination -NetworkAdapter $NetworkAdapter -PortGroup $VMPG -Datastore $DS -Confirm:$false
221 |
222 | Sleep 5
223 |
224 | Write-Host " Powering on $vm and waiting for VM Tools to start" -ForegroundColor Green
225 | Start-VM $vmname -Server $DestVC
226 |
227 | do {
228 | $toolsStatus = (Get-VM $vmname | Get-View).Guest.ToolsStatus
229 | write-host $toolsStatus
230 | sleep 3
231 | } until ( $toolsStatus -eq ‘toolsOk’ )
232 |
233 | #Update vmware tools
234 | Write-Host " Checking and upgrading VMware Tools and VM Copatibility if nesessary" -ForegroundColor Yellow
235 | Get-VM $vmname | % { get-view $_.id } |Where-Object {$_.Guest.ToolsVersionStatus -like "guestToolsNeedUpgrade"} |select name, @{Name=“ToolsVersion”; Expression={$_.config.tools.toolsversion}}, @{ Name=“ToolStatus”; Expression={$_.Guest.ToolsVersionStatus}}| Update-Tools -NoReboot -VM {$_.Name} -Verbose
236 |
237 | Write-Host " Rebooting $vmname after VM Compatibility Upgrade"
238 | Restart-VM -VM $vmname -Server $DestVC -Confirm:$false
239 | do {
240 | $toolsStatus = (Get-VM $vmname | Get-View).Guest.ToolsStatus
241 | write-host $toolsStatus
242 | sleep 3
243 | } until ( $toolsStatus -eq ‘toolsOk’ )
244 |
245 | $StopWatch.Stop()
246 | #Calculating Migration Time
247 | $migrationTime = [math]::Round(($StopWatch.Elapsed).TotalMinutes ,2)
248 |
249 | Write-Host " $vm is ready to use. Migration is Complete" -ForegroundColor Green
250 | Write-Host " Total Migration time for $vmname was $migrationtime minutes" -ForegroundColor Cyan
251 | sleep 2
252 | Write-Host " Disconnecting from vCenters $sourceVC and $destVC" -ForegroundColor Yellow
253 | Disconnect-VIServer -Server * -Confirm:$false
254 |
255 | }
256 |
--------------------------------------------------------------------------------
/NUMAReport.ps1:
--------------------------------------------------------------------------------
1 | #Get vCenter name and Connect
2 | Write-host ""
3 | $vc = Read-Host "Enter vCenter name to conenct to"
4 | Write-Host ""
5 | Write-host "Connecting to $vc, Login prompt to follow.." -ForegroundColor Cyan
6 | Connect-VIServer $vc
7 |
8 | #Get list of all clusters in vCenter
9 | $Clusters = Get-Cluster
10 | ForEach ($c in $Clusters){
11 | Write-host "Processing Cluster $c..." -ForegroundColor Magenta
12 | Write-host ""
13 |
14 | #Process each host in cluster
15 | $NUMAStats = @()
16 | $largeMemVM = @()
17 | $largeCPUVM = @()
18 |
19 | $hosts = Get-VMHost -Location $c
20 |
21 | ForEach ($h in $Hosts) {
22 | $HostView = $h | Get-View
23 | $HostSummary = “” | Select HostName, MemorySizeGB, CPUSockets, CPUCoresSocket, CPUCoresTotal, CPUThreads, NumNUMANodes, NUMANodeCPUSize, NUMANodeMemSize
24 |
25 | #Get Host CPU, Memory & NUMA info
26 | $HostSummary.HostName = $h.Name
27 | $HostSummary.MemorySizeGB =([Math]::Round($HostView.hardware.memorysize / 1GB))
28 | $HostSummary.CPUSockets = $HostView.hardware.cpuinfo.numCpuPackages
29 | $HostSummary.CPUCoresSocket = ($HostView.hardware.cpuinfo.numCpuCores / $HostSummary.CPUSockets)
30 | $HostSummary.CPUCoresTotal = $HostView.hardware.cpuinfo.numCpuCores
31 | $HostSummary.CPUThreads = $HostView.hardware.cpuinfo.numCpuThreads
32 | $HostSummary.NumNUMANodes = $HostView.hardware.numainfo.NumNodes
33 | $HostSummary.NUMANodeCPUSize = ($HostSummary.CPUCoresTotal / $HostSummary.NumNUMANodes)
34 | $HostSummary.NUMANodeMemSize =([Math]::Round($HostSummary.MemorySizeGB / $HostSummary.NumNUMANodes))
35 | $NUMAStats += $HostSummary
36 | }
37 |
38 | #Find the smallest NUMA Node (CPU & Mem) to use for comparison
39 | $x = $HostSummary.NUMANodeMemSize | measure -Minimum
40 | $y = $HostSummary.NUMANodeCPuSize | measure -Minimum
41 |
42 | #Get list of all VMs in cluster that are oversized
43 | $VMDeatils = @()
44 | $VMDeatils = Get-VM -Location $c | where {$_.NumCpu -gt $y.Minimum -or $_.MemoryGB -gt $x.Minimum}
45 |
46 | Write-host "Processing VM's in cluster for NUMA oversizing.." -ForegroundColor Magenta
47 | Write-host ""
48 |
49 | # VM Calculations
50 | #Large MEM VM - Any VM with more memory allocated then the NUMA node.
51 | $largeMemVM += $VMDeatils | Where-Object {$_.MemoryGB -gt $x.Minimum}
52 |
53 | #Large CPU VM - Any VM with more CPU then cores per Proc on a host
54 | $largeCPUVM += $VMDeatils | Where-Object {$_.NumCPU -gt $y.Minimum}
55 |
56 | #Display report for current cluster
57 | Write-Host "NUMA Node Specs for Cluster - $c." -ForegroundColor Yellow
58 | $NUMAStats | ft
59 |
60 | if ($largeMemVM -or $largeCPUVM) {
61 | if ($largeCPUVM) {
62 | Write-host $largeCPUVM.Count "VMs in $c that Exceed CPUCoresSocket." -ForegroundColor Cyan
63 | $largeCPUVM | select name, @{N='Memory GB';E={$_.MemoryGB}}, @{N='Num CPU';E={$_.ExtensionData.Config.Hardware.NumCPU}}, @{N='Num Sockets';E={($_.ExtensionData.Config.Hardware.NumCPU / $_.ExtensionData.Config.Hardware.NumCoresPerSocket)}}, @{N='Cores Per Socket';E={$_.ExtensionData.Config.Hardware.NumCoresPerSocket}}, @{N='CPU Hot Plug Status';E={$_.ExtensionData.Config.CpuHotAddEnabled}} | ft
64 | }
65 | Else { Write-host "All VM CPU allocations are within NUMA ranges" -ForegroundColor Green}
66 |
67 | if ($largeMemVM) {
68 | Write-host $largeMemVM.Count "VMs in $c that Exceed NUMA Node Memory size." -ForegroundColor Cyan
69 | $largeMemVM | select name, @{N='Memory GB';E={$_.MemoryGB}}, @{N='Num CPU';E={$_.ExtensionData.Config.Hardware.NumCPU}}, @{N='Num Sockets';E={($_.ExtensionData.Config.Hardware.NumCPU / $_.ExtensionData.Config.Hardware.NumCoresPerSocket)}}, @{N='Cores Per Socket';E={$_.ExtensionData.Config.Hardware.NumCoresPerSocket}}, @{N='CPU Hot Plug Status';E={$_.ExtensionData.Config.CpuHotAddEnabled}} | ft
70 | }
71 | Else { Write-host "All VM memory allocations are within NUMA ranges" -ForegroundColor Green}
72 | }
73 | Else { Write-Host "No VM's in Cluster - $c to report NUMA issues on" -ForegroundColor Green}
74 | Write-host ""
75 | Write-host ""
76 | }
77 | Write-Host "Disconnecting from $vc" -ForegroundColor Yellow
78 | Disconnect-viserver -Server $vc -Confirm:$false
79 |
--------------------------------------------------------------------------------
/NUMAReportcsv.ps1:
--------------------------------------------------------------------------------
1 |
2 | #Get vCenter name and Connect
3 | Write-host ""
4 | $vc = Read-Host "Enter vCenter name to conenct to"
5 | Write-Host ""
6 | Write-host "Connecting to $vc, Login prompt to follow.." -ForegroundColor Cyan
7 | Connect-VIServer $vc
8 |
9 | #Get list of all clusters in vCenter
10 | $Clusters = Get-Cluster
11 | ForEach ($c in $Clusters){
12 | Write-host "Processing Cluster $c..." -ForegroundColor Magenta
13 | Write-host ""
14 |
15 | #Process each host in cluster
16 | $NUMAStats = @()
17 | $largeMemVM = @()
18 | $largeCPUVM = @()
19 |
20 | $hosts = Get-VMHost -Location $c
21 |
22 | ForEach ($h in $Hosts) {
23 | $HostView = $h | Get-View
24 | $HostSummary = “” | Select HostName, MemorySizeGB, CPUSockets, CPUCoresSocket, CPUCoresTotal, CPUThreads, NumNUMANodes, NUMANodeCPUSize, NUMANodeMemSize
25 |
26 | #Get Host CPU, Memory & NUMA info
27 | $HostSummary.HostName = $h.Name
28 | $HostSummary.MemorySizeGB =([Math]::Round($HostView.hardware.memorysize / 1GB))
29 | $HostSummary.CPUSockets = $HostView.hardware.cpuinfo.numCpuPackages
30 | $HostSummary.CPUCoresSocket = ($HostView.hardware.cpuinfo.numCpuCores / $HostSummary.CPUSockets)
31 | $HostSummary.CPUCoresTotal = $HostView.hardware.cpuinfo.numCpuCores
32 | $HostSummary.CPUThreads = $HostView.hardware.cpuinfo.numCpuThreads
33 | $HostSummary.NumNUMANodes = $HostView.hardware.numainfo.NumNodes
34 | $HostSummary.NUMANodeCPUSize = ($HostSummary.CPUCoresTotal / $HostSummary.NumNUMANodes)
35 | $HostSummary.NUMANodeMemSize =([Math]::Round($HostSummary.MemorySizeGB / $HostSummary.NumNUMANodes))
36 | $NUMAStats += $HostSummary
37 | }
38 |
39 | #Find the smallest NUMA Node (CPU & Mem) to use for comparison
40 | $x = $HostSummary.NUMANodeMemSize | measure -Minimum
41 | $y = $HostSummary.NUMANodeCPuSize | measure -Minimum
42 |
43 | #Get list of all VMs in cluster that are oversized
44 | $VMDeatils = @()
45 | $VMDeatils = Get-VM -Location $c | where {$_.NumCpu -gt $y.Minimum -or $_.MemoryGB -gt $y.Minimum}
46 |
47 | Write-host "Processing VM's in cluster for NUMA oversizing.." -ForegroundColor Magenta
48 | Write-host ""
49 |
50 | # VM Calculations
51 | #Large MEM VM - Any VM with more memory allocated then the NUMA node.
52 | $largeMemVM += $VMDeatils | Where-Object {$_.MemoryGB -gt $x.Minimum}
53 |
54 | #Large CPU VM - Any VM with more CPU then cores per Proc on a host
55 | $largeCPUVM += $VMDeatils | Where-Object {$_.NumCPU -gt $y.Minimum}
56 |
57 | #Display report for current cluster
58 | Write-Host "NUMA Node Specs for Cluster - $c." -ForegroundColor Yellow
59 | $NUMAStats | ft
60 | $NUMAStats| Export-Csv c:\temp\NUMA\"$C numa.csv" -NoTypeInformation
61 |
62 | if ($largeMemVM -or $largeCPUVM) {
63 | if ($largeCPUVM) {
64 | Write-host $largeCPUVM.Count "VMs in $c that Exceed CPUCoresSocket." -ForegroundColor Cyan
65 | $largeCPUVM | select name, @{N='Memory GB';E={$_.MemoryGB}}, @{N='Num CPU';E={$_.ExtensionData.Config.Hardware.NumCPU}}, @{N='Num Sockets';E={($_.ExtensionData.Config.Hardware.NumCPU / $_.ExtensionData.Config.Hardware.NumCoresPerSocket)}}, @{N='Cores Per Socket';E={$_.ExtensionData.Config.Hardware.NumCoresPerSocket}}, @{N='CPU Hot Plug Status';E={$_.ExtensionData.Config.CpuHotAddEnabled}} | ft
66 | $largeCPUVM |Export-Csv c:\temp\NUMA\"$C LargeCPUVM.csv" -NoTypeInformation
67 | }
68 | Else { Write-host "All VM CPU allocations are within NUMA ranges" -ForegroundColor Green}
69 |
70 | if ($largeMemVM) {
71 | Write-host $largeMemVM.Count "VMs in $c that Exceed NUMA Node Memory size." -ForegroundColor Cyan
72 | $largeMemVM | select name, @{N='Memory GB';E={$_.MemoryGB}}, @{N='Num CPU';E={$_.ExtensionData.Config.Hardware.NumCPU}}, @{N='Num Sockets';E={($_.ExtensionData.Config.Hardware.NumCPU / $_.ExtensionData.Config.Hardware.NumCoresPerSocket)}}, @{N='Cores Per Socket';E={$_.ExtensionData.Config.Hardware.NumCoresPerSocket}}, @{N='CPU Hot Plug Status';E={$_.ExtensionData.Config.CpuHotAddEnabled}} | ft
73 | $largeMemVM | Export-Csv c:\temp\NUMA\"$C LargeMEMVM.csv" -NoTypeInformation
74 | }
75 | Else { Write-host "All VM memory allocations are within NUMA ranges" -ForegroundColor Green}
76 | }
77 | Else { Write-Host "No VM's in Cluster - $c to report NUMA issues on" -ForegroundColor Green}
78 | Write-host ""
79 | Write-host ""
80 | }
81 |
82 | #Combine all csv's into single spreadsheet
83 | Write-Host "Compiling CSV's into a single spreadsheet" -ForegroundColor Yellow
84 | $path= "C:\temp\NUMA\*"
85 | $csvs = Get-ChildItem $path -Include *.csv
86 | $y=$csvs.Count
87 | Write-Host “Detected the following CSV files: ($y)”
88 | foreach ($csv in $csvs)
89 | {
90 | Write-Host ” “$csv.Name -ForegroundColor Green
91 | }
92 | $outputfilename = read-host “Please enter a name for the spreadsheet: ”
93 | $date = Get-Date -Format FileDate
94 | #$outputfilename = "Natco_Vmware_Health_Report_$date"
95 | Write-Host Creating: $outputfilename -ForegroundColor Green
96 | $excelapp = new-object -comobject Excel.Application
97 | $excelapp.sheetsInNewWorkbook = $csvs.Count
98 | $xlsx = $excelapp.Workbooks.Add()
99 | $sheet=1
100 |
101 | foreach ($csv in $csvs)
102 | {
103 | $row=1
104 | $column=1
105 | $worksheet = $xlsx.Worksheets.Item($sheet)
106 | $worksheet.Name = $csv.Name
107 | $file = (Get-Content $csv)
108 | foreach($line in $file)
109 | {
110 | $linecontents=$line -split ‘,(?!\s*\w+”)’
111 | foreach($cell in $linecontents)
112 | {
113 | $cell = $cell.TrimStart(‘"‘)
114 | $cell = $cell.TrimEnd(‘"‘)
115 | $worksheet.Cells.Item($row,$column) = $cell
116 | $column++
117 | }
118 | $column=1
119 | $row++
120 | }
121 | $sheet++
122 | }
123 | $output = "C:\temp\NUMA\Reports\$outputfilename.xlsx"
124 | $xlsx.SaveAs($output)
125 | $excelapp.quit()
126 | Write-Host "Done, Spreadsheet is located" $output -ForegroundColor Green
127 |
128 | Write-Host "Disconnecting from $vc" -ForegroundColor Yellow
129 | Disconnect-viserver -Server $vc -Confirm:$false
130 |
131 |
--------------------------------------------------------------------------------
/OVNimbleDataStoreBuild.ps1:
--------------------------------------------------------------------------------
1 | $HPOV = Read-host "Enter the OneView Server name /IP"
2 | $HPOVUsr = Read-Host "Enter your OneView User name"
3 | Write-host "Enter OneView password at the prompt" -ForegroundColor Yellow
4 | Connect-HPOVMgmt -Hostname $HPOV -UserName $HPOVUsr
5 | $VC = Read-Host "Enter vCenter name/ip to connect to"
6 | Connect-viserver $VC
7 |
8 | Get-HPOVStoragePool
9 | Write-host "For the next two questions refer to the data on screen" -ForegroundColor Yellow
10 | $Pool = Read-host "Enter the name of the Storage Pool to use for the new volume"
11 | $System = Read-Host "Enter the name of the Storage System that Pool is on"
12 | $cap = Read-host "Enter the size of the volume in GB"
13 | $name = Read-Host "Enter the name of the new volume"
14 | $ID = Read-Host "Enter the Lun ID for the new volume"
15 | $cluster = Read-Host "Enter VMware cluster to add datastore"
16 |
17 | $policy = Get-HPOVStorageSystem -Name $system | Show-HPOVStorageSystemPerformancePolicy -Name "VMware ESX 5"
18 | $SP = Get-HPOVStoragePool -Name $Pool -StorageSystem $System
19 | #create volume
20 | Write-Host " Creating new volume named $name with $cap gb of storage" -ForegroundColor Cyan
21 | New-HPOVStorageVolume -Name $name -StoragePool $SP -Capacity $cap -ProvisioningType Thin -PerformancePolicy $policy -Shared | Wait-HPOVTaskComplete
22 |
23 |
24 | $vol = Get-HPOVStorageVolume -Name $name
25 |
26 | Write-host " Connecting the new volume $name to the HPC Server profiles" -ForegroundColor Cyan
27 | $blades1 = Get-HPOVServerProfile -Name *HPC*
28 | $blades2 = Get-HPOVServerProfile -Name *Tenant*
29 | Foreach ($svr in $blades1) {
30 | New-HPOVServerProfileAttachVolume -ServerProfile $svr -Volume $vol -LunID $ID -LunIdType Manual | Wait-HPOVTaskComplete
31 | }
32 |
33 | Foreach ($svr in $blades2) {
34 | New-HPOVServerProfileAttachVolume -ServerProfile $svr -Volume $vol -LunID $ID -LunIdType Manual | Wait-HPOVTaskComplete
35 | }
36 | #scan all the host in the cluster to new storage volume
37 |
38 | Sleep 20
39 | Write-host " connecting to $cluster and scanning for new storage" -ForegroundColor Yellow
40 | Get-Cluster $cluster | Get-VMHost | Get-VMHostStorage -RescanAllHba -RescanVmfs
41 |
42 | #function to find free LUNs found at http://vcloud-lab.com/entries/powercli/find-free-or-unassigned-storage-lun-disks-on-vmware-esxi-server
43 | # removed some of the notes to save space
44 | function Get-FreeEsxiLUNs {
45 | #EXAMPLE
46 | #Get-FreeEsxiLUNs -Esxihost Esxi001.vcloud-lab.com
47 | #Shows free unassigned storage Luns disks on Esxi host name Esxi001.vcloud-lab.com
48 | ###############################
49 |
50 | [CmdletBinding()]
51 | param(
52 | [Parameter(Position=0, Mandatory=$true)]
53 | [System.String]$Esxihost
54 | )
55 | Begin {
56 | if (-not(Get-Module vmware.vimautomation.core)) {
57 | Import-Module vmware.vimautomation.core
58 | }
59 | #Connect-VIServer | Out-Null
60 | }
61 | Process {
62 | $VMhost = Get-VMhost $EsxiHost
63 | $AllLUNs = $VMhost | Get-ScsiLun -LunType disk
64 | $Datastores = $VMhost | Get-Datastore
65 | foreach ($lun in $AllLUNs) {
66 | $Datastore = $Datastores | Where-Object {$_.extensiondata.info.vmfs.extent.Diskname -Match $lun.CanonicalName}
67 | if ($Datastore.Name -eq $null) {
68 | $lun | Select-Object CanonicalName, CapacityGB, Vendor
69 | }
70 | }
71 | }
72 | End {}
73 | }
74 |
75 | $free = Get-FreeEsxiLUNs -Esxihost (Get-cluster $cluster |get-vmhost | Get-random) | Where-Object {$_.Vendor -eq "Nimble"} |select CanonicalName
76 | $path = $free -replace "@{CanonicalName=","" -replace "}",""
77 |
78 |
79 | #create new Datastore
80 | Write-host " Creating new Datastore named $name in cluster $cluster" -ForegroundColor Cyan
81 | Get-VMHost | Get-Random | New-Datastore -name $name -Path $path -Vmfs -FileSystemVersion 6
82 |
83 | #rescan vhost for new Datastore
84 | Get-VMHost | Get-VMHostStorage -RescanAllHba -Refresh
85 |
86 | #Create Datastore Tag and Storage policy for vCloud Director
87 | Write-Host "Creating Datastore Tag and Storage Policy for vCloud Director" -ForegroundColor Yellow
88 | $tag = New-Tag -Name $name -Category Datastore
89 | $rule = New-SpbmRule -AnyOfTags $tag
90 | $ruleset = New-SpbmRuleSet -AllOfRules $rule
91 | $policy = New-SpbmStoragePolicy -Name $name -AnyOfRuleSets $ruleset
92 | Get-Datastore -Server $VC -Name $name | New-TagAssignment -Tag $tag
93 |
94 |
95 |
96 |
97 | Write-Host "Volume $name has been created and attached to vmware cluster $cluster" -ForegroundColor Green
98 | Write-host "Disconnecting from OneView and vCenter" -ForegroundColor Green
99 | Disconnect-HPOVMgmt
100 | Disconnect-VIServer -Server * -Confirm:$false
101 |
--------------------------------------------------------------------------------
/OVNimbleDatastore.ps1:
--------------------------------------------------------------------------------
1 | Write-host "Enter OneView password at the prompt" -ForegroundColor Yellow
2 | Connect-HPOVMgmt -Hostname 192.168.219.70 -UserName hpadmin
3 | $VC = Read-Host "Enter vCenter name/ip to connect to"
4 | Connect-viserver $VC
5 |
6 | $Pool = "default"
7 | $System = "Edafio-Cloud"
8 | $cap = Read-host "Enter the size of the volume in GB"
9 | $name = Read-Host "Enter the name of the new volume"
10 | $ID = Read-Host "Enter the Lun ID for the new volume"
11 | $cluster = "HPC"
12 |
13 | $policy = Get-HPOVStorageSystem -Name $system | Show-HPOVStorageSystemPerformancePolicy -Name "VMware ESX 5"
14 | $SP = Get-HPOVStoragePool -Name $Pool -StorageSystem $System
15 | #create volume
16 | Write-Host " Creating new volume named $name with $cap gb of storage" -ForegroundColor Cyan
17 | New-HPOVStorageVolume -Name $name -StoragePool $SP -Capacity $cap -ProvisioningType Thin -PerformancePolicy $policy -Shared | Wait-HPOVTaskComplete
18 |
19 |
20 | $vol = Get-HPOVStorageVolume -Name $name
21 |
22 | Write-host " Connecting the new volume $name to the HPC Server profiles" -ForegroundColor Cyan
23 | $blades = Get-HPOVServerProfile -Name *HPC*
24 | Foreach ($svr in $blades) {
25 | New-HPOVServerProfileAttachVolume -ServerProfile $svr -Volume $vol -LunID $ID -LunIdType Manual | Wait-HPOVTaskComplete
26 | }
27 | #scan all the host in the cluster to new storage volume
28 |
29 | Sleep 10
30 | Write-host " connecting to $cluster cluster and scanning for new storage" -ForegroundColor Yellow
31 | Get-Cluster $cluster | Get-VMHost | Get-VMHostStorage -RescanAllHba -RescanVmfs
32 |
33 | #function to find free LUNs found at http://vcloud-lab.com/entries/powercli/find-free-or-unassigned-storage-lun-disks-on-vmware-esxi-server
34 | # removed some of the notes to save space
35 | function Get-FreeEsxiLUNs {
36 | #EXAMPLE
37 | #Get-FreeEsxiLUNs -Esxihost Esxi001.vcloud-lab.com
38 | #Shows free unassigned storage Luns disks on Esxi host name Esxi001.vcloud-lab.com
39 | ###############################
40 |
41 | [CmdletBinding()]
42 | param(
43 | [Parameter(Position=0, Mandatory=$true)]
44 | [System.String]$Esxihost
45 | )
46 | Begin {
47 | if (-not(Get-Module vmware.vimautomation.core)) {
48 | Import-Module vmware.vimautomation.core
49 | }
50 | #Connect-VIServer | Out-Null
51 | }
52 | Process {
53 | $VMhost = Get-VMhost $EsxiHost
54 | $AllLUNs = $VMhost | Get-ScsiLun -LunType disk
55 | $Datastores = $VMhost | Get-Datastore
56 | foreach ($lun in $AllLUNs) {
57 | $Datastore = $Datastores | Where-Object {$_.extensiondata.info.vmfs.extent.Diskname -Match $lun.CanonicalName}
58 | if ($Datastore.Name -eq $null) {
59 | $lun | Select-Object CanonicalName, CapacityGB, Vendor
60 | }
61 | }
62 | }
63 | End {}
64 | }
65 |
66 | $free = Get-FreeEsxiLUNs -Esxihost (Get-cluster $cluster |get-vmhost | Get-random) | Where-Object {$_.Vendor -eq "Nimble"} |select CanonicalName
67 | $path = $free -replace "@{CanonicalName=","" -replace "}",""
68 |
69 |
70 | #create new Datastore
71 | Write-host " Creating new Datastore named $name in cluster $cluster" -ForegroundColor Cyan
72 | Get-cluster $cluster |get-vmhost | Get-random| New-Datastore -name $name -Path $path -Vmfs -FileSystemVersion 6
73 |
74 | #rescan vhost for new Datastore
75 | Get-VMHost | Get-VMHostStorage -RescanAllHba -Refresh
76 |
77 | #Create Datastore Tag and Storage policy for vCloud Director
78 | Write-Host "Creating Datastore Tag and Storage Policy for vCloud Director" -ForegroundColor Yellow
79 | $tag = New-Tag -Name $name -Category Datastore
80 | $rule = New-SpbmRule -AnyOfTags $tag
81 | $ruleset = New-SpbmRuleSet -AllOfRules $rule
82 | $policy = New-SpbmStoragePolicy -Name $name -AnyOfRuleSets $ruleset
83 | Get-Datastore -Server $VC -Name $name | New-TagAssignment -Tag $tag
84 |
85 | Write-Host "Volume $name has been created and attached to vmware cluster $cluster" -ForegroundColor Green
86 | Write-host "Disconnecting from OneView and vCenter" -ForegroundColor Green
87 | Disconnect-HPOVMgmt
88 | Disconnect-VIServer -Server * -Confirm:$false
89 |
--------------------------------------------------------------------------------
/OVVolumeBuild.ps1:
--------------------------------------------------------------------------------
1 | Write-host "Enter OneView password at the prompt" -ForegroundColor Yellow
2 | Connect-HPOVMgmt -Hostname "" -UserName ""
3 | $VC = Read-Host "Enter vCenter name/ip to connect to" -ForegroundColor Cyan
4 | Connect-viserver $VC
5 |
6 | Get-HPOVStoragePool
7 | Write-host "For the next two questions refer to the data on screen" -ForegroundColor Yellow
8 | $Pool = Read-host "Enter the name of the Storage Pool to use for the new volume"
9 | $System = Read-Host "Enter the name of the Storage System that Pool is on"
10 | $cap = Read-host "Enter the size of the volume in GB"
11 | $name = Read-Host "Enter the name of the new volume"
12 | $ID = Read-Host "Enter the Lun ID fo rthe new volume"
13 | $cluster = Read-Host "Enter VMware cluster to add datastore"
14 |
15 | $SP = Get-HPOVStoragePool -Name $Pool -StorageSystem $System
16 | New-HPOVStorageVolume -Name $name -StoragePool $SP -Capacity $cap -ProvisioningType Thin
17 |
18 | $vol = Get-HPOVStorageVolume -Name $name
19 | # the *CA1ESX* will get all the host in the shared production cluster
20 | # use *Tenant* to get all the host in the Cloud environment
21 | $blades = Get-HPOVServerProfile -Name *CA1ESX*
22 | Foreach ($svr in $blades) {
23 | New-HPOVServerProfileAttachVolume -ServerProfile $profile -Volume $vol -LunID $ID -LunIdType Manual | Wait-HPOVTaskComplete
24 | }
25 | #scan all the host in the cluster to new storage volume
26 | Get-Cluster $cluster | Get-VMHost | Get-VMHostStorage -RescanAllHba -RescanVmfs
27 |
--------------------------------------------------------------------------------
/PSVMReport.ps1:
--------------------------------------------------------------------------------
1 | param ([System.Management.Automation.SwitchParameter] $PassThru)
2 |
3 |
4 | Import-Module PScribo -Force;
5 |
6 | $ReportName = "Virtual Machine Inventory Report"
7 | $CompanyName = Read-Host "Enter Company Name"
8 | $Author = Read-Host "Enter Author Name"
9 | $Version = Read-Host "Enter Version Number"
10 | $vc = Read-Host "Enter vCenter Name/IP"
11 | #$creds = Get-Credential
12 | $name = "$CompanyName $ReportName"
13 |
14 | <# The document name is used in the file output #>
15 | $document = Document $name -Verbose {
16 | <# Enforce uppercase section headers/names
17 | Enable automatic section numbering
18 | Set the page size to US Letter with 0.5inch margins #>
19 | $DefaultFont = 'Calibri'
20 |
21 | #region VMware Document Style
22 | DocumentOption -EnableSectionNumbering -PageSize Letter -DefaultFont $DefaultFont -MarginLeftAndRight 71 -MarginTopAndBottom 71
23 |
24 | Style -Name 'Title' -Size 24 -Color '002538' -Align Center
25 | Style -Name 'Title 2' -Size 18 -Color '007CBB' -Align Center
26 | Style -Name 'Title 3' -Size 12 -Color '007CBB' -Align Left
27 | Style -Name 'Heading 1' -Size 16 -Color '007CBB'
28 | Style -Name 'Heading 2' -Size 14 -Color '007CBB'
29 | Style -Name 'Heading 3' -Size 12 -Color '007CBB'
30 | Style -Name 'Heading 4' -Size 11 -Color '007CBB'
31 | Style -Name 'Heading 5' -Size 10 -Color '007CBB'
32 | Style -Name 'H1 Exclude TOC' -Size 16 -Color '007CBB'
33 | Style -Name 'Normal' -Size 10 -Color '565656' -Default
34 | Style -Name 'TOC' -Size 16 -Color '007CBB'
35 | Style -Name 'TableDefaultHeading' -Size 10 -Color 'FAF7EE' -BackgroundColor '002538'
36 | Style -Name 'TableDefaultRow' -Size 10
37 | Style -Name 'TableDefaultAltRow' -Size 10 -BackgroundColor 'D9E4EA'
38 | Style -Name 'Critical' -Size 10 -BackgroundColor 'FFB38F'
39 | Style -Name 'Warning' -Size 10 -BackgroundColor 'FFE860'
40 | Style -Name 'Info' -Size 10 -BackgroundColor 'A6D8E7'
41 | Style -Name 'OK' -Size 10 -BackgroundColor 'AADB1E'
42 |
43 | TableStyle -Id 'TableDefault' -HeaderStyle 'TableDefaultHeading' -RowStyle 'TableDefaultRow' -AlternateRowStyle 'TableDefaultAltRow' -BorderColor '002538' -Align Left -BorderWidth 0.5 -Default
44 | TableStyle -Id 'Borderless' -BorderWidth 0
45 |
46 | # VMware Cover Page
47 | BlankLine -Count 5
48 | Paragraph -Style Title $ReportName
49 | Paragraph -Style Title2 "Prepared for $CompanyName"
50 | BlankLine -Count 36
51 | Table -Name 'Cover Page' -List -Style Borderless -Width 0 -Hashtable ([Ordered] @{
52 | 'Author:' = $Author
53 | 'Date:' = Get-Date -Format 'dd MMMM yyyy'
54 | 'Version:' = $Version
55 | })
56 |
57 | PageBreak;
58 |
59 | # Table of Contents
60 | TOC -Name 'Table of Contents'
61 | PageBreak;
62 |
63 | Connect-VIServer $vc
64 | Section -Style Heading2 'Virtual Machine' {
65 | #Add VM properties for vmtools version
66 | Write-Host "Adding VM Properties for vmtools" -ForegroundColor Yellow
67 | New-VIProperty -Name ToolsVersion -ObjectType VirtualMachine -ValueFromExtensionProperty 'Config.tools.ToolsVersion' -Force
68 | New-VIProperty -Name ToolsVersionStatus -ObjectType VirtualMachine -ValueFromExtensionProperty 'Guest.ToolsVersionStatus' -Force
69 |
70 | #Get VM info
71 | Write-Host "Gathering VM info" -ForegroundColor Yellow
72 | $VMS = get-cluster | Get-VM | Select Name, Folder, @{N="IP Address";E={@($_.guest.IPAddress[0])}}, @{N='FQDN';E={$_.ExtensionData.Guest.IPStack[0].DnsConfig.HostName, $_.ExtensionData.Guest.IPStack[0].DnsConfig.DomainName -join '.'}}, Guest, Version, ToolsVersion, ToolsVersionStatus, PowerState, NumCpu, MemoryGB, ProvisionedSpaceGB, UsedSpaceGB | Sort-Object Folder
73 |
74 | $VMS |Table -List -Name 'Virtual Machines' -ColumnWidths 25,75
75 |
76 | }
77 |
78 | }
79 | $document | Export-Document -Path ~\Desktop -Format Word,Html -PassThru:$PassThru -Verbose;
80 |
81 |
82 | Disconnect-VIServer -Server * -Confirm:$false
83 |
--------------------------------------------------------------------------------
/PatchCompliance.ps1:
--------------------------------------------------------------------------------
1 | $WSUS = Read-Host "Enter Name/IP of WSUS server"
2 | $VC = Read-Host "Enter vCenter Name/IP"
3 | $reportname = Read-Host "Enter Report Name"
4 | $CompanyName = Read-Host "Enter Company Name "
5 | $author = Read-Host "Enter Author Name"
6 |
7 |
8 | Connect-PSWSUSServer $WSUS -Port 8530
9 | Connect-VIServer $VC
10 |
11 |
12 |
13 |
14 | <# The document name is used in the file output #>
15 | $document = Document $ReportName -Verbose {
16 | <# Enforce uppercase section headers/names
17 | Enable automatic section numbering
18 | Set the page size to US Letter with 0.5inch margins #>
19 | $DefaultFont = 'Calibri'
20 |
21 | #region VMware Document Style
22 | DocumentOption -EnableSectionNumbering -PageSize Letter -DefaultFont $DefaultFont -MarginLeftAndRight 40 -MarginTopAndBottom 50
23 |
24 | Style -Name 'Title' -Size 22 -Color '002538' -Align Center
25 | Style -Name 'Title 2' -Size 18 -Color '007CBB' -Align Center
26 | Style -Name 'Title 3' -Size 12 -Color '007CBB' -Align Left
27 | Style -Name 'Heading 1' -Size 16 -Color '007CBB'
28 | Style -Name 'Heading 2' -Size 14 -Color '007CBB'
29 | Style -Name 'Heading 3' -Size 12 -Color '007CBB'
30 | Style -Name 'Heading 4' -Size 11 -Color '007CBB'
31 | Style -Name 'Heading 5' -Size 10 -Color '007CBB'
32 | Style -Name 'H1 Exclude TOC' -Size 16 -Color '007CBB'
33 | Style -Name 'Normal' -Size 10 -Color '565656' -Default
34 | Style -Name 'TOC' -Size 16 -Color '007CBB'
35 | Style -Name 'TableDefaultHeading' -Size 10 -Color 'FAF7EE' -BackgroundColor '002538'
36 | Style -Name 'TableDefaultRow' -Size 10
37 | Style -Name 'TableDefaultAltRow' -Size 10 -BackgroundColor 'D9E4EA'
38 | Style -Name 'Critical' -Size 10 -BackgroundColor 'FFB38F'
39 | Style -Name 'Warning' -Size 10 -BackgroundColor 'FFE860'
40 | Style -Name 'Info' -Size 10 -BackgroundColor 'A6D8E7'
41 | Style -Name 'OK' -Size 10 -BackgroundColor 'AADB1E'
42 |
43 | TableStyle -Id 'TableDefault' -HeaderStyle 'TableDefaultHeading' -RowStyle 'TableDefaultRow' -AlternateRowStyle 'TableDefaultAltRow' -BorderColor '002538' -Align Left -BorderWidth 0.5 -Default
44 | TableStyle -Id 'Borderless' -BorderWidth 0
45 |
46 | # VMware Cover Page
47 | BlankLine -Count 4
48 | Paragraph -Style Title $ReportName
49 | Paragraph -Style Title2 "Prepared for $CompanyName"
50 | BlankLine -Count 36
51 | Table -Name 'Cover Page' -List -Style Borderless -Width 0 -Hashtable ([Ordered] @{
52 | 'Author:' = $author
53 | 'Date:' = Get-Date -Format 'dd MMMM yyyy'
54 | 'Version:' = Get-date -Format 'yyyyMM'
55 | })
56 |
57 | PageBreak;
58 |
59 | # Table of Contents
60 | TOC -Name 'Table of Contents'
61 | PageBreak;
62 | Section -Style Heading1 ". Windows Server Patch Compliance" {
63 | Paragraph "This Section shows the patch compliance of the Windows servers in the Edafio Cloud Management Cluster"
64 | Get-PSWSUSUpdateSummaryPerClient |Select Computer, Installed, Needed, Failed, PendingReboot, NotApplicable, LastUpdated | Sort-Object Computer| Table
65 | Blankline}
66 | PageBreak;
67 |
68 | Section -Style Heading1 ". VMware Host Patch Compliance" {
69 | Paragraph "This Section shows the patch compliance of the VMware Host in the Edafio Cloud "
70 | $clusters = Get-Cluster
71 | $BL = Get-Baseline -Name "HP Host" -BaselineType Patch
72 |
73 | Foreach ($Cluster in $Clusters) {
74 | Section -Style Heading3 " $cluster Cluster Compliance" {
75 |
76 | Write-host "Compliance for $cluster Cluster" -ForegroundColor Yellow
77 | Test-Compliance -Entity $cluster -UpdateType HostPatch
78 | Get-Compliance -Entity $cluster -Baseline $BL -Detailed | Select-object Entity, @{N=’Baseline’;E={$_.Baseline.Name}}, Status, @{N=’CompliantPatches’;E={$_.CompliantPatches.Length}}, @{N=’NotCompliantPatches’;E={$_.NotCompliantPatches.Length}},@{N=’UnknownPatches’;E={$_.UnknownPatches.Length}}, @{N=’NotApplicablePatches’;E={$_.NotApplicablePatches.Length}} | Table
79 | Blankline}
80 | PageBreak;
81 | }
82 | }
83 | Section -Style Heading1 ". Missing VMware Host Patches" {
84 | Paragraph "This Section shows what patches are missing from the VMware Host in the Edafio Cloud "
85 | $esx = Get-VMHost |Get-Random
86 |
87 | Test-Compliance -Entity $esx -UpdateType HostPatch
88 |
89 | $report = $esx | Get-Compliance -Detailed | %{
90 |
91 | $_.NotCompliantPatches |
92 |
93 | Select-Object Name,IDByVendor,Description,@{n='Product';e={$_.product | Select-Object -expandproperty Version}},ReleaseDate
94 |
95 | }
96 |
97 |
98 |
99 | $report |Table
100 | BlankLine}
101 | PageBreak;
102 | }
103 | $document | Export-Document -Path ~\Desktop -Format Word,Html -PassThru:$PassThru -Verbose;
104 |
105 | Disconnect-PSWSUSServer
106 | Disconnect-VIServer -Server * -Confirm:$False
107 |
108 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Powershell/Powercli scripts
2 |
--------------------------------------------------------------------------------
/VMReport.ps1:
--------------------------------------------------------------------------------
1 | #Enter the vCenter or ESXi name or ip
2 | $vc = Read-Host "Enter vCenter or ESXi name or IP address"
3 | Connect-VIServer $vc
4 |
5 | #Add VM properties for vmtools version
6 | Write-Host "Adding VM Properties for vmtools" -ForegroundColor Yellow
7 | New-VIProperty -Name ToolsVersion -ObjectType VirtualMachine -ValueFromExtensionProperty 'Config.tools.ToolsVersion' -Force
8 | New-VIProperty -Name ToolsVersionStatus -ObjectType VirtualMachine -ValueFromExtensionProperty 'Guest.ToolsVersionStatus' -Force
9 |
10 | #Get VM info
11 | Write-Host "Gathering VM info" -ForegroundColor Yellow
12 | get-cluster | Get-VM | Select Name, Folder, @{N="IP Address";E={@($_.guest.IPAddress[0])}}, @{N='FQDN';E={$_.ExtensionData.Guest.IPStack[0].DnsConfig.HostName, $_.ExtensionData.Guest.IPStack[0].DnsConfig.DomainName -join '.'}}, Guest, Version, ToolsVersion, ToolsVersionStatus, PowerState, NumCpu, MemoryGB, ProvisionedSpaceGB, UsedSpaceGB | Export-Csv C:\Temp\VMinfo.csv -NoTypeInformation
13 |
14 | Write-host "Spreadsheet is located at C:\temp\VMinfo.csv" -ForegroundColor Green
15 |
16 | Disconnect-viserver -server * -confirm:$false
17 |
--------------------------------------------------------------------------------
/VMinfo.ps1:
--------------------------------------------------------------------------------
1 | $VC = read-host " Enter vCenter Name"
2 | Connect-viserver $VC
3 |
4 | #Add VM properties for vmtools version
5 | Write-Host "Adding VM Properties for vmtools" -ForegroundColor Yellow
6 | New-VIProperty -Name ToolsVersion -ObjectType VirtualMachine -ValueFromExtensionProperty 'Config.tools.ToolsVersion' -Force
7 | New-VIProperty -Name ToolsVersionStatus -ObjectType VirtualMachine -ValueFromExtensionProperty 'Guest.ToolsVersionStatus' -Force
8 |
9 |
10 | #Get VM info
11 | Write-Host "Gathering VM info" -ForegroundColor Yellow
12 | get-cluster | Get-VM | Select Name, @{N="IP Address";E={@($_.guest.IPAddress[0])}}, @{N='FQDN';E={$_.ExtensionData.Guest.IPStack[0].DnsConfig.HostName, $_.ExtensionData.Guest.IPStack[0].DnsConfig.DomainName -join '.'}}, Guest, Version, ToolsVersion, ToolsVersionStatus, PowerState, NumCpu, MemoryGB, ProvisionedSpaceGB, UsedSpaceGB | Export-Csv F:\Powercli\Inventory\VMinfo.csv -NoTypeInformation
13 |
14 | disconnect-viserver -Server * -Confirm:$false
--------------------------------------------------------------------------------
/add-stdportgroup.ps1:
--------------------------------------------------------------------------------
1 | $VC = Read-Host " Enter vCenter name:"
2 | Connect-VIServer $VC
3 | $VMHosts = Get-cluster "Production" | Get-VMHost
4 | foreach ($VMHost in $VMHosts) {
5 | Get-VMHost -name $VMhost | Get-VirtualSwitch -name vswitch2 | New-VirtualPortGroup -name Name-219 -VLanId 219
6 | Get-VMHost -name $VMhost | Get-VirtualSwitch -name vswitch2 | New-VirtualPortGroup -name Name-1201 -VLanId 1201
7 | Get-VMHost -name $VMhost | Get-VirtualSwitch -name vswitch2 | New-VirtualPortGroup -name Name-1300 -VLanId 1300
8 | Get-VMHost -name $VMhost | Get-VirtualSwitch -name vswitch2 | New-VirtualPortGroup -name Name-217 -VLanId 217
9 | Get-VMHost -name $VMhost | Get-VirtualSwitch -name vswitch2 | New-VirtualPortGroup -name Name-103 -VLanId 103
10 | Get-VMHost -name $VMhost | Get-VirtualSwitch -name vswitch2 | New-VirtualPortGroup -name Name-104 -VLanId 104
11 | Get-VMHost -name $VMhost | Get-VirtualSwitch -name vswitch2 | New-VirtualPortGroup -name Name-105 -VLanId 105
12 | Get-VMHost -name $VMhost | Get-VirtualSwitch -name vswitch2 | New-VirtualPortGroup -name Name-106 -VLanId 106
13 | Get-VMHost -name $VMhost | Get-VirtualSwitch -name vswitch2 | New-VirtualPortGroup -name Name-107 -VLanId 107
14 | Get-VMHost -name $VMhost | Get-VirtualSwitch -name vswitch2 | New-VirtualPortGroup -name Name-112 -VLanId 112
15 | Get-VMHost -name $VMhost | Get-VirtualSwitch -name vswitch2 | New-VirtualPortGroup -name Name-118 -VLanId 118
16 | Get-VMHost -name $VMhost | Get-VirtualSwitch -name vswitch2 | New-VirtualPortGroup -name Name-2000 -VLanId 2000
17 | Get-VMHost -name $VMhost | Get-VirtualSwitch -name vswitch2 | New-VirtualPortGroup -name Name-2001 -VLanId 201
18 | Get-VMHost -name $VMhost | Get-VirtualSwitch -name vswitch2 | New-VirtualPortGroup -name Name-1207 -VLanId 1207
19 | }
20 | Disconnect-viserver -Server * -Confirm:$false
21 |
--------------------------------------------------------------------------------
/alarms.ps1:
--------------------------------------------------------------------------------
1 | $VC = Read-Host "Enter vCenter Name/IP"
2 | Connect-Viserver $VC
3 |
4 |
5 | #Gather VM Active Alerts
6 | $VMs = Get-View -ViewType VirtualMachine -Property Name,OverallStatus,TriggeredAlarmstate
7 | $FaultyVMs = $VMs | Where-Object {$_.OverallStatus -ne "Green"}
8 |
9 | $progress = 1
10 | $report = @()
11 | if ($FaultyVMs -ne $null) {
12 | foreach ($FaultyVM in $FaultyVMs) {
13 | foreach ($TriggeredAlarm in $FaultyVM.TriggeredAlarmstate) {
14 | Write-Progress -Activity "Gathering alarms" -Status "Working on $($FaultyVM.Name)" -PercentComplete ($progress/$FaultyVMs.count*100) -Id 1 -ErrorAction SilentlyContinue
15 | $alarmID = $TriggeredAlarm.Alarm.ToString()
16 | $object = New-Object PSObject
17 | Add-Member -InputObject $object NoteProperty VM $FaultyVM.Name
18 | Add-Member -InputObject $object NoteProperty TriggeredAlarms ("$(Get-AlarmDefinition -Id $alarmID)")
19 | $report += $object
20 | }
21 | $progress++
22 | }
23 | }
24 | Write-Progress -Activity "Gathering Active VM alarms" -Status "All done" -Completed -Id 1 -ErrorAction SilentlyContinue
25 |
26 | $report | Where-Object {$_.TriggeredAlarms -ne ""} |Export-Csv C:\Temp\vmAlert.csv -NoTypeInformation
27 |
28 | #Gather vHost Active Alerms
29 | Write-host "Gathering Active vHost Alarms" -ForegroundColor Yellow
30 | $esx_all = Get-VMHost | Get-View
31 | $Report=@()
32 | foreach ($esx in $esx_all){
33 | foreach($triggered in $esx.TriggeredAlarmState){
34 | If ($triggered.OverallStatus -like "red" ){
35 | $lineitem={} | Select Name, AlarmInfo
36 | $alarmDef = Get-View -Id $triggered.Alarm
37 | $lineitem.Name = $esx.Name
38 | $lineitem.AlarmInfo = $alarmDef.Info.Name
39 | $Report+=$lineitem
40 | }
41 | }
42 | }
43 | $Report |Sort Name | Export-Csv C:\Temp\HostAlarms.csv -NoTypeInformation
44 |
45 | Disconnect-viserver -Server * -Confirm:$false
46 |
--------------------------------------------------------------------------------
/export.ps1:
--------------------------------------------------------------------------------
1 | #$VC = Read-Host "Enter vCenter Name /IP"
2 | #Connect-VIServer -$VC
3 |
4 | #Get Data from Source vCenter
5 | #Built to be used with Set-SourceSettings.ps1 to recreate those same settings in another vCenter.
6 | #Does not support vApps or multiple datacenters in the same vCenter.
7 | param
8 | (
9 | $directory = $(read-host "Enter local output directory"),
10 | $datacenter = $(read-host "Enter datacenter"),
11 | [switch]$getTemplates
12 | )
13 | #Takes a VI Folder object and returns an array of strings that represents that folder's absolute path in the inventory
14 | function get-folderpath
15 | {
16 | param
17 | (
18 | $thisFolder
19 | )
20 | #Creates an array of folders back to the root folder
21 | if ($thisFolder.id -like "Folder*")
22 | {
23 | $folderArray = @()
24 | $folderArray += $thisFolder
25 | while ($folderArray[-1].parent.parent.id -match "Folder")
26 | {
27 | $folderArray += $folderArray[-1].parent
28 | }
29 | [array]::Reverse($folderArray)
30 | #convert the array of folders to an array of strings with just the folder names
31 | $folderStrArray = @()
32 | $folderArray | %{$folderStrArray += $_.name}
33 | $folderStrArray
34 | }
35 | else
36 | {
37 | write-error "Unexpected input provided; does not appear to be a Folder."
38 | }
39 | }
40 |
41 | $directory = $directory.trim("\") #" This comment is to fix the gistit syntax highlighting.
42 | new-item $directory -type directory -erroraction silentlycontinue
43 |
44 | if ((get-datacenter).count -gt 1){write-error "These scripts do not support multiple Datacenters in a single inventory"}
45 |
46 | #Get Roles
47 | get-virole | ? {$_.issystem -eq $false} | export-clixml $directory\$($datacenter)-roles.xml
48 |
49 | #Get Permissions
50 | $allPermissions = @()
51 | $foundPermissions = get-vipermission
52 | $i = 0
53 | foreach ($thisPermission in $foundPermissions)
54 | {
55 | write-progress -Activity "Getting permissions" -percentComplete ($i / $foundPermissions.count * 100)
56 | $objPerm = "" | select entity,type,Role,Principal,Propagate,folderType
57 | $objPerm.type = $thisPermission.entity.id.split("-")[0]
58 | $objPerm.Role = $thisPermission.role
59 | $objPerm.Principal = $thisPermission.Principal
60 | $objPerm.Propagate = $thisPermission.propagate
61 | #Create an absolute path for a folder, otherwise store the name of the entity
62 | if ($objPerm.type -eq "Folder")
63 | {
64 | $objPerm.entity = get-folderpath $thisPermission.entity
65 | $objPerm.folderType = $thisPermission.entity.type
66 | }
67 | else
68 | {
69 | $objPerm.entity = $thisPermission.entity.name
70 | $objPerm.folderType = ""
71 | }
72 | $allPermissions += $objPerm
73 | $i++
74 | }
75 | $allPermissions | export-clixml $directory\$($datacenter)-permissions.xml
76 |
77 |
78 | #Get VM Folder Structure
79 | $outFolders = @()
80 | $i = 0
81 | $foundFolders = get-datacenter $datacenter | get-folder | ? {$_.type.tostring() -eq "VM" -and $_.parent.id -notLike "Datacenter*"}
82 | foreach ($thisFolder in $foundFolders)
83 | {
84 | write-progress -Activity "Getting VM folder structure" -percentComplete ($i / $foundFolders.count * 100)
85 | $myFolder = "" | select path
86 | $myFolder.path = get-folderpath $thisFolder
87 | $outFolders += $myFolder
88 | $i++
89 | }
90 | $outFolders | export-clixml $directory\$($datacenter)-folders.xml
91 |
92 | #Convert Templates to VMs (so that they can transition vCenters)
93 | get-template | select name | export-clixml $directory\$($datacenter)-Templates.xml
94 | if ($getTemplates){get-datacenter $datacenter | get-template | set-template -ToVM -confirm:$false}
95 |
96 | #Get VM Locations
97 | $outVMs = @()
98 | $allVApps = get-datacenter $datacenter | get-vapp
99 | $vAppVMs = $allVApps | get-vm
100 | if ($vAppVMs)
101 | {
102 | $allVMs = Get-VM | ? {!($vAppVMs.contains($_))}
103 | #Deal with vApps... maybe try this guy's technique to capture settings and make a best effort at recreating the vApp?
104 | # http://www.lukaslundell.com/2013/06/modifying-vapp-properties-with-powershell-and-powercli/
105 | $outVApps = @()
106 | foreach ($thisVApp in $allVApps)
107 | {
108 | write-error "Discovered VAPP: $($thisVApp.name) - vAPPs must be recreated manually."
109 | $myVApp = "" | select name,VMs
110 | $myVApp.name = $thisVApp.name
111 | $myVApp.VMs = ($thisVApp | get-vm).name
112 | $outVApps += $myVApp
113 | }
114 | $outVApps | export-clixml $directory\$($datacenter)-vApps.xml
115 | }
116 | else
117 | {
118 | $allVMs = get-datacenter $datacenter | get-VM
119 | }
120 | $i = 0
121 | foreach ($thisVM in $allVMs)
122 | {
123 | write-progress -Activity "Getting VM locations" -percentComplete ($i / $allVMs.count * 100)
124 | $myVM = "" | select name,folderPath
125 | $myVM.name = $thisVM.name
126 | if ($thisVM.folder.name -eq "VM")
127 | {
128 | $myVM.folderPath = $NULL
129 | }
130 | else
131 | {
132 | $myVM.folderPath = get-folderpath $thisVM.folder
133 | }
134 | $outVMs += $myVM
135 | $i++
136 | }
137 | $outVMs | export-clixml $directory\$($datacenter)-VMs.xml
138 |
139 |
140 | Disconnect-VIServer -Server * -Confirm:$false
141 |
--------------------------------------------------------------------------------
/get-LUNinfo.ps1:
--------------------------------------------------------------------------------
1 |
2 | $VC = read-host "Enter vCenter name or IP address"
3 |
4 | Connect-Viserver $VC
5 |
6 | Write-Host "Gather LUN info" -ForegroundColor Yellow
7 | # Get VMFS volumes. Ignore local SCSILuns.
8 | Get-VMHost | Get-ScsiLun | Sort-Object VMhost | Select-Object VMHost, CanonicalName, CapacityGB, Vendor, MultipathPolicy, LunType, IsLocal, IsSsd, @{n='LunID';E={
9 |
10 | $esxcli = Get-EsxCli -VMHost $_.VMHost -V2
11 |
12 | $esxcli.storage.nmp.path.list.Invoke(@{'device'=$_.CanonicalName}).RuntimeName.Split(':')[-1].TrimStart('L')}} |
13 | Sort-Object -Property {[int]$_.LUN} | Export-Csv C:\Temp\Luns.csv -NoTypeInformation
14 |
15 | Disconnect-viserver -server * -confirm:$false
16 |
--------------------------------------------------------------------------------
/import.ps1:
--------------------------------------------------------------------------------
1 | $VC = Read-Host "Enter vCenter Name /IP"
2 | Connect-VIServer -$VC
3 |
4 |
5 |
6 | param
7 | (
8 | $directory = $(read-host "Enter local input directory"),
9 | $datacenter = $(read-host "Enter datacenter"),
10 | [switch]$roles,
11 | [switch]$permissions,
12 | [switch]$folders,
13 | [switch]$vms
14 | )
15 |
16 | function make-ParentFolder
17 | {
18 | Param
19 | (
20 | $inFolderArray
21 | )
22 | $parentFolder = get-datacenter $datacenter | get-folder "VM"
23 | foreach ($thisSubFolder in $inFolderArray)
24 | {
25 | if (!($parentFolder | get-folder $thisSubFolder -noRecursion -erroraction silentlycontinue))
26 | {
27 | $ParentFolder = $parentFolder | new-folder $thisSubFolder
28 | }
29 | else
30 | {
31 | $ParentFolder = $ParentFolder | get-folder $thisSubFolder -noRecursion
32 | }
33 | }
34 | $ParentFolder
35 | }
36 |
37 | $directory = $directory.trim("\") #" fix the gistit syntax highlighting
38 |
39 | #Rebuild Folder Structure
40 | if ($folders)
41 | {
42 | $folderArray = import-clixml $directory\$($datacenter)-folders.xml
43 | $i = 0
44 | foreach ($thisFolder in $folderArray)
45 | {
46 | write-progress -Activity "Creating Folders" -percentComplete ($i / $folderArray.count * 100)
47 | make-ParentFolder -inFolderArray $thisFolder.path
48 | $i++
49 | }
50 | }
51 |
52 | #Rebuild Roles
53 | if ($roles)
54 | {
55 | $allRoles = import-clixml $directory\$($datacenter)-roles.xml
56 | $i = 0
57 | foreach ($thisRole in $allRoles)
58 | {
59 | write-progress -Activity "Creating Roles" -percentComplete ($i / $allRoles.count * 100)
60 | if (!(get-virole $thisRole.name -erroraction silentlycontinue))
61 | {
62 | new-virole -name $thisRole.name -privilege (get-viprivilege -id $thisRole.PrivilegeList) -erroraction silentlycontinue
63 | }
64 | $i++
65 | }
66 | }
67 |
68 | #Rebuild Permissions
69 | if ($permissions)
70 | {
71 | $allPermissions = import-clixml $directory\$($datacenter)-permissions.xml
72 | $i = 0
73 | foreach ($thisPermission in $allPermissions)
74 | {
75 | write-progress -Activity "Creating Permissions" -percentComplete ($i / $allPermissions.count * 100)
76 | $target = ""
77 | if ($thisPermission.type -eq "Folder")
78 | {
79 | #permission is assigned to a folder, use make-folder to get the precise folder
80 | $target = make-Parentfolder -inFolderArray $thisPermission.entity
81 | }
82 | elseif ($thisPermission.type -eq "VirtualMachine")
83 | {
84 | #permission is assigned to VM
85 | $target = get-datacenter $datacenter | get-vm $thisPermission.entity
86 | }
87 | elseif ($thisPermission.type -eq "Datacenter")
88 | {
89 | #permission is assigned to Datacenter
90 | $target = get-datacenter $thisPermission.entity
91 | }
92 | else
93 | {
94 | write-error "Unexpected permission target, $($thisPermission.type)"
95 | }
96 |
97 | if ($target)
98 | {
99 | $target | new-vipermission -role $thisPermission.role -principal $thisPermission.principal -propagate $thisPermission.propagate
100 | }
101 | else
102 | {
103 | write-error "Unable to find permission object $($thisPermission.entity)"
104 | }
105 | $i++
106 | }
107 | }
108 |
109 | #Replace VMs
110 | if ($VMs)
111 | {
112 | $allVMs = import-clixml $directory\$($datacenter)-VMs.xml
113 | $allVApps = $NULL
114 | $i = 0
115 | if (test-path $directory\vApps.xml){$allVApps = import-clixml $directory\$($datacenter)-vApps.xml}
116 | foreach ($thisVM in $allVMs)
117 | {
118 | write-progress -Activity "Placing VMs" -percentComplete ($i / $allVMs.count * 100)
119 | if ($foundVM = get-vm $thisVM.name)
120 | {
121 | $ParentFolder = make-ParentFolder -inFolderArray $thisVM.folderPath
122 | $foundVM | move-vm -destination $ParentFolder
123 | }
124 | $i++
125 | }
126 | foreach ($thisVApp in $allVApps)
127 | {
128 | echo "===$($thisVApp.name)==="
129 | $thisvApp.VMs
130 | }
131 | #Convert Template VMs back to Templates
132 | }
133 |
134 | if (!($VMs -or $folders -or $permissions -or $roles))
135 | {
136 | echo "Please use one or more of the -VMs, -Folders, -Permissions, or -Roles switches to do something"
137 | }
138 |
139 |
140 |
141 | Disconnect-VIServer -Server * -Confirm:$false
--------------------------------------------------------------------------------
/set-multipath.ps1:
--------------------------------------------------------------------------------
1 | #Setting Storage Luns to Round Robin
2 | $VC = Read-Host " Enter vCenter name:"
3 |
4 | Connect-VIServer $VC
5 |
6 | Get-Cluster | Select name | FT
7 | $Cluster = Read-Host " Enter Cluster name fron list above:"
8 |
9 | $VMhosts = Get-cluster $cluster | Get-VMHost
10 | Foreach ($VMhost in $VMhosts) {
11 | Write-Host "Setting Multipath Policy on $VMhost to Round Robin" -ForegroundColor Green
12 | Get-VMHost $VMhost | Get-ScsiLun -LunType disk | Where {$_.MultipathPolicy-notlike "RoundRobin"} | Set-Scsilun -MultiPathPolicy RoundRobin
13 | Get-VMhost $VMhost | Get-ScsiLun -LunType Disk | Where-Object {$_.CanonicalName-like ‘naa.*’ -and $_.MultipathPolicy-like ‘RoundRobin’} | Set-ScsiLun -CommandsToSwitchPath 1
14 | }
15 |
16 | Write-host "disconnecting from $VC" -ForegroundColor Yellow
17 | Disconnect-VIServer -Server * -Confirm:$False
18 |
--------------------------------------------------------------------------------
/show-menu.ps1:
--------------------------------------------------------------------------------
1 | function Show-Menu
2 | {
3 | param (
4 | [string]$Title = 'Select Script'
5 | )
6 | Clear-Host
7 | Write-Host "================ $Title ================" -ForegroundColor Yellow
8 | Write-Host "1: Press '1' to list all the Edge Gateway for each vCloud org." -ForegroundColor Yellow
9 | Write-Host "2: Press '2' to Create a new Tenant in vCloud Director" -ForegroundColor Yellow
10 | Write-Host "3: Press '3' to Get Virtual Machine Information" -ForegroundColor Yellow
11 | Write-Host "4: Press '4' to get Capacity Information for the Clusters in a vCenter" -ForegroundColor Yellow
12 | Write-Host "5: Press '5' to Set All FC Datastores Multipathing to Round Robin" -ForegroundColor Yellow
13 | Write-Host "6: Press '6' to Change the number of vCPU of a VM" -ForegroundColor Yellow
14 | Write-Host "7: Press '7' to Change the amount of Memory of a VM" -ForegroundColor Yellow
15 | Write-Host "Q: Press 'Q' to quit." -ForegroundColor Yellow
16 | }
17 |
18 | Function Get-VDCEdge {
19 | Import-Module VMware.VimAutomation.Cloud, PowerNSX
20 | Connect-CIServer 192.168.151.13
21 | Connect-NsxServer -vCenterServer 192.168.151.9
22 |
23 | $Orgs = Get-Org
24 | $Edges = Get-NsxEdge
25 |
26 | $myView = @()
27 | Foreach ($Edge in $Edges) {
28 | $Report = [PSCustomObject] @{
29 | EdgeName = $Edge.Name
30 | VcdOrg = ($orgs | where {$_.Id -match $edge.Tenant})
31 | }
32 | $MyView += $Report
33 | }
34 |
35 | $MyView | Sort UpdateAvailable, VcdOrg | ft -AutoSize
36 |
37 | Disconnect-NsxServer -confirm:$false
38 | Disconnect-CIServer -Server * -Confirm:$false
39 |
40 | }
41 | Function New-Tenant {
42 |
43 | $Client = Read-Host " Enter Client Name:"
44 | $CPUMhz = Read-Host " Enter Amount of CPU needed in Ghz"
45 | $MemGB = Read-Host " Enter amount of Ram needed in GB"
46 | $StoGB = Read-host " Enter amount of Storage needed in GB"
47 |
48 | #Getting Credentials for VCSA and vCD
49 | $vcsacred = Get-Credential -Message "Enter vCenter Credentials:"
50 | $vcdcred = Get-Credential -Message "Enter vCloud Director Credentials:"
51 |
52 | #connecting to VCSA and vCD
53 | Write-host " Connecting to vCenter and vCloud Director" -ForegroundColor Yellow
54 | Connect-viserver 192.168.151.9 -Credential $vcsacred
55 | Connect-ciserver 192.168.151.13 -Credential $vcdcred
56 |
57 | #Creating required Ditributed Port Groups for vCD
58 | $ExDVPG = Read-Host " Enter External Distributed Port Group Name"
59 | $ExDVPGvLAN = Read-Host " Enter vLAN ID for $ExDVPG "
60 | Write-Host " Creating $ExDVPG with vLAN ID $ExDVPGvLAN " -ForegroundColor Yellow
61 | Get-VDSwitch -Name "TenantDVSwitch01" | New-VDPortgroup -Name $ExDVPG -NumPorts 24 -VLanId $ExDVPGvLAN
62 |
63 | $InDVPG = Read-Host " Enter Internal Distributed Port Group Name"
64 | $InDVPGvLAN = Read-Host " Enter vLAN ID for $InDVPG "
65 | Write-Host " Creating $InDVPG with vLAN ID $InDVPGvLAN " -ForegroundColor Yellow
66 | Get-VDSwitch -Name "TenantDVSwitch01" | New-VDPortgroup -Name $InDVPG -NumPorts 24 -VlanId $InDVPGvLAN
67 |
68 | #Create Org in vCD
69 | Write-host " Creating Org and vDC for $client" -ForegroundColor Yellow
70 | $PVDC = "Edafio CLoud"
71 | New-Org -Name $Client
72 | #Create vDC for new Org
73 | New-OrgVdc -Name $Client -Org $Client -ProviderVdc $PVDC -AllocationModelAllocationPool -CpuAllocationGHz $CPUMhz -MemoryAllocationGB $MemGB -StorageAllocationGB $StoGB
74 |
75 | #Create Network pool
76 |
77 | #create External Network
78 |
79 | #create Edge GW
80 |
81 |
82 |
83 |
84 | Write-host " Disconnecting from vCenter and vCloud Director" -ForegroundColor Yellow
85 | Disconnect-VIServer -Server * -Confirm:$false
86 | Disconnect-CIServer -Server * -Confirm:$false
87 |
88 | }
89 | Function Get-VMinfo {
90 |
91 | $VC = Read-Host " Enter vCenter name"
92 | Connect-VIServer $VC
93 |
94 | #Add VM properties for vmtools version
95 | Write-Host "Adding VM Properties for vmtools" -ForegroundColor Yellow
96 | New-VIProperty -Name ToolsVersion -ObjectType VirtualMachine -ValueFromExtensionProperty 'Config.tools.ToolsVersion' -Force
97 | New-VIProperty -Name ToolsVersionStatus -ObjectType VirtualMachine -ValueFromExtensionProperty 'Guest.ToolsVersionStatus' -Force
98 |
99 | #Get VM info
100 | Write-Host "Gathering VM info" -ForegroundColor Yellow
101 | get-cluster | Get-VM | Select Name, @{N="IP Address";E={@($_.guest.IPAddress[0])}}, @{N='FQDN';E={$_.ExtensionData.Guest.IPStack[0].DnsConfig.HostName, $_.ExtensionData.Guest.IPStack[0].DnsConfig.DomainName -join '.'}}, Guest, Version, ToolsVersion, ToolsVersionStatus, PowerState, NumCpu, MemoryGB, ProvisionedSpaceGB, UsedSpaceGB | Export-Csv F:\Powercli\Inventory\13.VMinfo.csv -NoTypeInformation
102 |
103 | Disconnect-VIServer -Server * -Confirm:$false
104 |
105 | }
106 | Function Get-Capacity {
107 |
108 | param ([System.Management.Automation.SwitchParameter] $PassThru)
109 |
110 | Import-Module PScribo -Force;
111 |
112 | Add-Type -AssemblyName system.speech
113 | $synthesizer = New-Object system.Speech.Synthesis.SpeechSynthesizer
114 | $synthesizer.SelectVoice('Microsoft Zira Desktop')
115 |
116 | #$synthesizer.Speak('Enter Report Name')
117 | $ReportName = "vSphere Capacity and Performance Report"
118 |
119 | #$synthesizer.Speak('Enter Company Name')
120 | $CompanyName = Read-Host "Enter Company Name"
121 |
122 | #$synthesizer.Speak('Enter Author Name')
123 | $Author = Read-Host "Enter Author Name"
124 |
125 | #$synthesizer.Speak('Enter Version Number')
126 | $Version = Read-Host "Enter Version Number"
127 |
128 | #$synthesizer.Speak('Enter vCenter Name or IP')
129 | $vc = Read-Host "Enter vCenter Name/IP"
130 |
131 | #$synthesizer.speak('Enter vCenter User Name')
132 | #$user = Read-Host "Enter vCenter User Name"
133 |
134 | #synthesizer.speak('Enter vCenter Password')
135 | #$pass = Read-Host "Enter vCenter Password"
136 |
137 |
138 |
139 | #$synthesizer.Speak('Building Documentation')
140 | <# The document name is used in the file output #>
141 | $document = Document $ReportName -Verbose {
142 | <# Enforce uppercase section headers/names
143 | Enable automatic section numbering
144 | Set the page size to US Letter with 0.5inch margins #>
145 | $DefaultFont = 'Calibri'
146 |
147 | #region VMware Document Style
148 | DocumentOption -EnableSectionNumbering -PageSize Letter -DefaultFont $DefaultFont -MarginLeftAndRight 40 -MarginTopAndBottom 50
149 |
150 | Style -Name 'Title' -Size 22 -Color '002538' -Align Center
151 | Style -Name 'Title 2' -Size 18 -Color '007CBB' -Align Center
152 | Style -Name 'Title 3' -Size 12 -Color '007CBB' -Align Left
153 | Style -Name 'Heading 1' -Size 16 -Color '007CBB'
154 | Style -Name 'Heading 2' -Size 14 -Color '007CBB'
155 | Style -Name 'Heading 3' -Size 12 -Color '007CBB'
156 | Style -Name 'Heading 4' -Size 11 -Color '007CBB'
157 | Style -Name 'Heading 5' -Size 10 -Color '007CBB'
158 | Style -Name 'H1 Exclude TOC' -Size 16 -Color '007CBB'
159 | Style -Name 'Normal' -Size 10 -Color '565656' -Default
160 | Style -Name 'TOC' -Size 16 -Color '007CBB'
161 | Style -Name 'TableDefaultHeading' -Size 10 -Color 'FAF7EE' -BackgroundColor '002538'
162 | Style -Name 'TableDefaultRow' -Size 10
163 | Style -Name 'TableDefaultAltRow' -Size 10 -BackgroundColor 'D9E4EA'
164 | Style -Name 'Critical' -Size 10 -BackgroundColor 'FFB38F'
165 | Style -Name 'Warning' -Size 10 -BackgroundColor 'FFE860'
166 | Style -Name 'Info' -Size 10 -BackgroundColor 'A6D8E7'
167 | Style -Name 'OK' -Size 10 -BackgroundColor 'AADB1E'
168 |
169 | TableStyle -Id 'TableDefault' -HeaderStyle 'TableDefaultHeading' -RowStyle 'TableDefaultRow' -AlternateRowStyle 'TableDefaultAltRow' -BorderColor '002538' -Align Left -BorderWidth 0.5 -Default
170 | TableStyle -Id 'Borderless' -BorderWidth 0
171 |
172 | # VMware Cover Page
173 | BlankLine -Count 4
174 | Paragraph -Style Title $ReportName
175 | Paragraph -Style Title2 "Prepared for $CompanyName"
176 | BlankLine -Count 36
177 | Table -Name 'Cover Page' -List -Style Borderless -Width 0 -Hashtable ([Ordered] @{
178 | 'Author:' = $Author
179 | 'Date:' = Get-Date -Format 'dd MMMM yyyy'
180 | 'Version:' = $Version
181 | })
182 |
183 | PageBreak;
184 |
185 | # Table of Contents
186 | TOC -Name 'Table of Contents'
187 | PageBreak;
188 |
189 |
190 | #Sets up paths and variables.
191 | $vcenters = $VC
192 | $output = @()
193 | $capacity = @()
194 | $captable = @()
195 | $cpuready = @()
196 | $vmcpuready = @()
197 | $scriptpath = "F:\powercli"
198 | $listpath = "$scriptpath\PscriboCapacity\serverlists"
199 | $outfile = "$scriptpath\PScriboCapacity\Reports\capacity_$CompanyName.csv"
200 | #$vCPUTargetRatio = read-host "vCPU to pCPU Target Ratio?"
201 | #$vRAMTargetRatio = read-host "vRAM to pRAM Target Ratio?"
202 | $vCPUTargetRatio = 5
203 | $vRAMTargetRatio = 1
204 |
205 | connect-viserver $vc
206 | $synthesizer.Speak('Log in with administrator credentials at the prompt')
207 |
208 |
209 |
210 | #Gets CPU, RAM, and Storage allocation values and calculates ratios.
211 | foreach ($item in Get-Cluster) {
212 |
213 | $vmcpuready = $null
214 | $vmcpuready = @()
215 | $cpuready = $null
216 | $cpurdytop10 = $null
217 | $cpurdytop10ave = $null
218 |
219 | #Connect to correct vCenter based on input file.
220 | #if (($global:DefaultViServers).Name -ne $vc) {
221 | #disconnect-viserver * -confirm:$false -ErrorAction SilentlyContinue
222 | #connect-viserver $vc
223 | #}
224 |
225 |
226 | #Get hosts from clusters.
227 | write-host "Get hosts from $item" -ForegroundColor Yellow
228 | $vmhosts = Get-Cluster $item | get-vmhost
229 | $vms = $vmhosts | Get-VM
230 | $pwronvms = $vms | where {$_.PowerState -eq "PoweredOn"}
231 |
232 | #Gather physical stats and VM data from hosts.
233 | #CPU
234 | write-host "Gather CPU stats from $item" -ForegroundColor Yellow
235 | $pCPU = $vmhosts | Measure-Object NumCpu -Sum
236 | $pCPU = $pCPU.Sum
237 | $vCPUCap = ($pCPU * $vCPUTargetRatio)
238 | #RAM
239 | write-host "Gather RAM stats from $item" -ForegroundColor Yellow
240 | $pRAM = $vmhosts | Measure-Object MemoryTotalGB -Sum
241 | $pRAM = $pRAM.Sum
242 | $vRAMCap = ($pRAM * $vRAMTargetRatio)
243 | #Storage
244 | write-host "Gather Storage stats from $item" -ForegroundColor Yellow
245 | $ds = get-cluster $item | get-datastore | Select Name, CapacityGB, FreeSpaceGB
246 | $PhysCap = $ds | where-object {$_.Name -NotLike "*local*"} | measure-object CapacityGB -Sum
247 | $PhysCap = $PhysCap.Sum
248 |
249 |
250 | #Calculate vCPU values for Powered On only.
251 | write-host "Measure and calculate stats." -ForegroundColor Yellow
252 | $vCPU = $vms | where-object {$_.PowerState -eq "PoweredOn"} | measure-object NumCPU -Sum
253 | $vCPU = $vCPU.Sum
254 | #Calculate vCPU to pCPU ratio for Powered On VMs.
255 | $vCPURatio = ([math]::round($vCPU / $pCPU,1))
256 | $vCPURatio = "{0:N1}" -f $vCPURatio
257 | $vCPURemaining = ($vCPUCap - $vCPU)
258 |
259 | #Calculate vRAM allocation and compares to physical RAM
260 |
261 | #Calculate vRAM values Powered On VMs
262 | $vRAM = $vms | where-object {$_.PowerState -eq "PoweredOn"} | measure-object MemoryGB -Sum
263 | $vRAM = $vRAM.Sum
264 | #Calculate vRAM to pRAM Ratio (Powered On)
265 | $vRAMRatio = ([math]::round($vRAM / $pRAM,1))
266 | $vRAMRatio = "{0:N1}" -f $vRAMRatio
267 | $vRAMRemaining = ($vRAMCap - $vRAM)
268 |
269 | #Storage usage for All VMs.
270 | $ProvSpace = $vms | measure-object ProvisionedSpaceGB -Sum
271 | $ProvSpace = $ProvSpace.Sum
272 | $UsedSpace = $vms | measure-object UsedSpaceGB -Sum
273 | $UsedSpace = $UsedSpace.Sum
274 | $FreeSpace = $ds | where-object {$_.Name -NotLike "*local*"} | measure-object FreeSpaceGB -Sum
275 | $FreeSpace = $FreeSpace.Sum
276 | $ProvPercent = ([math]::round(($ProvSpace / $PhysCap) * 100,1))
277 |
278 | #Calculate average CPU Ready over past 7 days.
279 | #Loop through the VM list and gather stats for each Powered On VM.
280 | foreach ($vm in $vms | where {$_.PowerState -eq "PoweredOn"}) {
281 | $tempcpurdy = $null
282 | $tempcpurdyave = $null
283 | #Capture stats.
284 | write-host "Calculate CPU Ready stats for $vm." -ForegroundColor Green
285 | $tempcpurdy = get-stat -entity $vm -stat cpu.ready.summation -start (get-date).adddays(-7) -intervalmins 30 -instance ""
286 | #Calculate average for time period and convert to % value.
287 | #Average divided by 30 minute interval converted to milliseconds, multiply by 100 and divide by number of CPU's.
288 | $tempcpurdyave = ([math]::round((((($tempcpurdy | measure-object value -ave).average) / 1800000) * 100) / $vm.NumCPU,2))
289 | #Add average to array, reject values that are less than 0.01%.
290 | $vmcpuready += ($tempcpurdyave | where {$_ -ge .01})
291 | #Repeat for next VM.
292 | }
293 |
294 | #Calculate average of all VMs on cluster.
295 | write-host "Aggregate CPU ready values from $item" -ForegroundColor Yellow
296 | $cpuready = ([math]::round(($vmcpuready | measure-object -ave).average,2))
297 | # $cpureadymax = ([math]::round(($vmcpuready | measure-object -max).maximum,2))
298 | $cpurdytop10 = $vmcpuready | sort -desc | select -first ([math]::round($vmcpuready.count * .1,0))
299 | $cpurdytop10ave = ([math]::round(($cpurdytop10 | measure-object -ave).average,2))
300 | if ($vms.count -eq 0) {
301 | $cpuready = 0
302 | $cpurdytop10ave = 0
303 | }
304 |
305 |
306 | #Adds counts and ratios to table.
307 | write-host "Add values to table for $item" -ForegroundColor Green
308 | $capacity = New-Object PSObject
309 | $capacity | Add-Member -MemberType Noteproperty "Cluster" -value $item
310 | $capacity | Add-Member -MemberType Noteproperty "Total # of Hosts" -value $vmhosts.count
311 | $capacity | Add-Member -MemberType Noteproperty "Total # of VMs" -value $pwronvms.count
312 | $capacity | Add-Member -MemberType Noteproperty "vCPURatio" -value "$vCPURatio`:1"
313 | $capacity | Add-Member -MemberType Noteproperty "pCPU" -value $pCPU
314 | $capacity | Add-Member -MemberType Noteproperty "vCPU" -value $vCPU
315 | $capacity | Add-Member -MemberType Noteproperty "vCPU Cap" -value $vCPUCap
316 | $capacity | Add-Member -MemberType Noteproperty "vCPU Remaining" -value $vCPURemaining
317 | $capacity | Add-Member -MemberType Noteproperty "CPUReady%" -value "$cpuready`%"
318 | $capacity | Add-Member -MemberType Noteproperty "Top10%CPUReady" -value "$cpurdytop10ave`%"
319 | $capacity | Add-Member -MemberType Noteproperty "vRAMRatio" -value "$vRAMRatio`:1"
320 | $capacity | Add-Member -MemberType Noteproperty "pRAM \TB" -value ([math]::round($pRAM / 1024,3)) #Change the 3 to a 2 for GB
321 | $capacity | Add-Member -MemberType Noteproperty "vRAM \TB" -value ([math]::round($vRAM / 1024,3)) #Change the 3 to a 2 for GB
322 | $capacity | Add-Member -MemberType Noteproperty "vRAM Cap \TB" -value ([math]::round($vRAMCap / 1024,3)) #Change the 3 to a 2 for GB
323 | $capacity | Add-Member -MemberType Noteproperty "vRAM Remaining \TB" -value ([math]::round($vRAMRemaining / 1024,3)) #Change the 3 to a 2 for GB
324 | $capacity | Add-Member -MemberType Noteproperty "Provisioned Space \TB" -value ([math]::round($ProvSpace / 1024,3)) #Change the 3 to a 2 for GB
325 | $capacity | Add-Member -MemberType Noteproperty "Physical Capacity \TB" -value ([math]::round($PhysCap / 1024,3)) #Change the 3 to a 2 for GB
326 | $capacity | Add-Member -MemberType Noteproperty "Used Space \TB" -value ([math]::round($UsedSpace / 1024,3)) #Change the 3 to a 2 for GB
327 | $capacity | Add-Member -MemberType Noteproperty "Free Space \TB" -value ([math]::round($FreeSpace / 1024,3))
328 | $capacity | Add-Member -MemberType Noteproperty "Provisioned %" -value "$ProvPercent`%"
329 | $captable += $capacity
330 | }
331 | #$output += $captable | Convertto-CSV -NoTypeInformation
332 |
333 | $output | Set-Content $outfile
334 | #start excel $outfile
335 |
336 | Write-Host " Starting Performance Tables" -ForegroundColor Yellow
337 | Section -Style Heading2 " -Cluster Capacity Report for $VC" {
338 | Paragraph "This section provides information on the capacity of each Cluster in $vc."
339 | $captable | Table -List -ColumnWidths 25, 75
340 | Blankline}
341 | PageBreak;
342 |
343 | Write-Host "Gathering vHost Stats" -ForegroundColor Yellow
344 | Section -Style Heading2 " -vHost Usage stats" {
345 | Paragraph "This section provides usage stats on the vHost in $vc over the last 7 days."
346 | Get-VMHost | Where {$_.PowerState -eq "PoweredOn"} | Select Name,CpuTotalMhz,MemoryTotalGB, `
347 | @{N="CPU Usage (Average) Mhz" ; E={[Math]::Round((($_ | Get-Stat -Stat cpu.usagemhz.average -Start (Get-Date).AddDays(-7) -IntervalMins 5 | Measure-Object Value -Average).Average),2)}}, `
348 | @{N="Memory Usage (Average) %" ; E={[Math]::Round((($_ | Get-Stat -Stat mem.usage.average -Start (Get-Date).AddDays(-7) -IntervalMins 5 | Measure-Object Value -Average).Average),2)}} , `
349 | @{N="Network Usage (Average) KBps" ; E={[Math]::Round((($_ | Get-Stat -Stat net.usage.average -Start (Get-Date).AddDays(-7) -IntervalMins 5 | Measure-Object Value -Average).Average),2)}} , `
350 | @{N="Disk Usage (Average) KBps" ; E={[Math]::Round((($_ | Get-Stat -Stat disk.usage.average -Start (Get-Date).AddDays(-7) -IntervalMins 5 | Measure-Object Value -Average).Average),2)}} |`
351 | Table
352 | Blankline}
353 | PageBreak;
354 |
355 | #Get vHost Uptime info
356 | function Get-VMHostUptime
357 | {
358 | [CmdletBinding()]
359 | Param (
360 | [Parameter(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)][Alias('Name')][string]$VMHosts,
361 | [string]$Cluster
362 | )
363 | Process{
364 | If ($VMHosts) {
365 | foreach ($VMHost in $VMHosts) {Get-View -ViewType hostsystem -Property name,runtime.boottime -Filter @{"name" = "$VMHost"} | Select-Object Name, @{N="UptimeDays"; E={[math]::round((((Get-Date) - ($_.Runtime.BootTime)).TotalDays),0)}}, @{N="UptimeHours"; E={[math]::round((((Get-Date) - ($_.Runtime.BootTime)).TotalHours),0)}}, @{N="UptimeMinutes"; E={[math]::round((((Get-Date) - ($_.Runtime.BootTime)).TotalMinutes),0)}}}
366 | }
367 |
368 | elseif ($Cluster) {
369 | foreach ($VMHost in (Get-VMHost -Location $Cluster)) {Get-View -ViewType hostsystem -Property name,runtime.boottime -Filter @{"name" = "$VMHost"} | Select-Object Name, @{N="UptimeDays"; E={[math]::round((((Get-Date) - ($_.Runtime.BootTime)).TotalDays),0)}}, @{N="UptimeHours"; E={[math]::round((((Get-Date) - ($_.Runtime.BootTime)).TotalHours),0)}}, @{N="UptimeMinutes"; E={[math]::round((((Get-Date) - ($_.Runtime.BootTime)).TotalMinutes),0)}}}
370 | }
371 |
372 | else {
373 | Get-View -ViewType hostsystem -Property name,runtime.boottime | Select-Object Name, @{N="UptimeDays"; E={[math]::round((((Get-Date) - ($_.Runtime.BootTime)).TotalDays),0)}}, @{N="UptimeHours"; E={[math]::round((((Get-Date) - ($_.Runtime.BootTime)).TotalHours),0)}}, @{N="UptimeMinutes"; E={[math]::round((((Get-Date) - ($_.Runtime.BootTime)).TotalMinutes),0)}}
374 | }
375 | }
376 | }
377 |
378 | #Get vHost Uptime
379 | Write-host "Gathering vHost Uptime Information" -ForegroundColor Yellow
380 | Section -Style Heading2 " -vHost Uptime" {
381 | Paragraph "This section provides information on vHost Uptime."
382 | Get-VMHostUptime $vmhost | select name, uptimedays | Table
383 | BlankLine}
384 |
385 |
386 | #Gather vHost Active Alerms
387 | Write-host "Gathering Active vHost Alarms" -ForegroundColor Yellow
388 | Section -Style Heading2 " -vHost Active Alerts" {
389 | Paragraph "This section provides information on Active vHost Alerts."
390 | $esx_all = Get-VMHost | Get-View
391 | $Report=@()
392 | foreach ($esx in $esx_all){
393 | foreach($triggered in $esx.TriggeredAlarmState){
394 | If ($triggered.OverallStatus -like "red" ){
395 | $lineitem={} | Select Name, AlarmInfo
396 | $alarmDef = Get-View -Id $triggered.Alarm
397 | $lineitem.Name = $esx.Name
398 | $lineitem.AlarmInfo = $alarmDef.Info.Name
399 | $Report+=$lineitem
400 | }
401 | }
402 | }
403 | $Report |Sort Name | Table
404 | BlankLine}
405 | PageBreak;
406 |
407 | #Get Datastore Information
408 | Write-Host "Gathering Datastore info" -ForegroundColor Yellow
409 | Section -Style Heading2 " -Datastore Information" {
410 | Paragraph "This section provides usage stats for all Datastores."
411 | Get-Datastore |select name, state, id, @{N="Type";E={$_.Type}}, @{N="Version";E={$_.FileSystemVersion}}, @{N="Number of Host";E={$_.ExtensionData.Host.Count}}, @{N="Number of VMs";E={$_.ExtensionData.VM.Count}}, CapacityGB, FreeSpaceGB, @{N="% Used";E={[math]::Round((100 - (($_.FreeSpaceGB) / ($_.CapacityGB) * 100)), 2)}}, StorageIOControlEnabled | Table
412 | BlankLine}
413 | PageBreak;
414 |
415 | #Get LUN info
416 | Write-Host "Gather LUN info" -ForegroundColor Yellow
417 | Section -Style Heading2 " -LUN Information" {
418 | Paragraph "This section provides information on all connected LUNS."
419 | Get-VMHost | Get-ScsiLun | Sort-Object VMhost | Select-Object VMHost, CanonicalName, CapacityGB, Vendor, MultipathPolicy, LunType, IsLocal, IsSsd | Table
420 | BlankLine}
421 | PageBreak;
422 |
423 | #Get VM Stats
424 | Write-Host "Gathering VM Stats" -ForegroundColor Yellow
425 | Section -Style Heading2 " -VM Usage Stats" {
426 | Paragraph "This section provides usage stats for all VM's in $vc over the last 7 days."
427 | Get-VM | Where {$_.PowerState -eq "PoweredOn"} | Select Name, VMHost, NumCpu, MemoryMB, `
428 | @{N="CPU Usage (Average) Mhz" ; E={[Math]::Round((($_ | Get-Stat -Stat cpu.usagemhz.average -Start (Get-Date).AddDays(-7) -IntervalMins 5 | Measure-Object Value -Average).Average),2)}}, `
429 | @{N="Memory Usage (Average) %" ; E={[Math]::Round((($_ | Get-Stat -Stat mem.usage.average -Start (Get-Date).AddDays(-7) -IntervalMins 5 | Measure-Object Value -Average).Average),2)}} , `
430 | @{N="Network Usage (Average) KBps" ; E={[Math]::Round((($_ | Get-Stat -Stat net.usage.average -Start (Get-Date).AddDays(-7) -IntervalMins 5 | Measure-Object Value -Average).Average),2)}} , `
431 | @{N="Disk Usage (Average) KBps" ; E={[Math]::Round((($_ | Get-Stat -Stat disk.usage.average -Start (Get-Date).AddDays(-7) -IntervalMins 5 | Measure-Object Value -Average).Average),2)}} |`
432 | Table
433 | Blankline}
434 | PageBreak;
435 |
436 | #Get VM uptime info
437 | Write-host "Gathering VM Uptime Information" -ForegroundColor Yellow
438 | Section -Style Heading2 " -VM Uptime" {
439 | Paragraph "This section provides information on VM Uptime."
440 | $VMs = Get-VM | Where-Object {$_.PowerState -eq "PoweredOn"}
441 | $Output = ForEach ($VM in $VMs)
442 |
443 | {
444 | "" | Select @{N="Name";E={$VM.Name}},
445 | @{N="Powered On";E={$Event = Get-VM $VM.Name | Get-VIEvent -MaxSamples [int]::MaxValue | Where-Object {$_.FullFormattedMessage -like "*powered on*"} | Select-First 1
446 | $Event.CreatedTime}},
447 | @{N="Up Time";E={$Timespan = New-Timespan -Seconds (Get-Stat -Entity $VM.Name -Stat sys.uptime.latest -Realtime -MaxSamples 1).Value
448 | "" + $Timespan.Days + " Days, "+ $Timespan.Hours + " Hours, " +$Timespan.Minutes + " Minutes"}}
449 | }
450 | Write-host "Gathering VM Uptime information" -ForegroundColor Yellow
451 | $Output | Table
452 | BlankLine}
453 | PageBreak;
454 |
455 | #SnapShot data over 5 days old
456 | Write-Host "Gathering Snapshot Data over 5 days old" -ForegroundColor Yellow
457 | Section -Style Heading2 " -SnapShots Over 5 Days Old" {
458 | Paragraph "This section provides information on Snapshots over 3 days old."
459 | Get-VM | Get-Snapshot | Where {$_.Created -Lt (Get-Date).AddDays(-3)} |Select-Object vm, name, created, PowerState, SizeGB | Table
460 | Blankline}
461 |
462 | #Gather VM Active Alerts
463 | Write-host "Gathering Active VM Alarms" -ForegroundColor Yellow
464 | Section -Style Heading2 " -VM Active Alerts" {
465 | Paragraph "This section provides information on Active VM Alerts."
466 | $VMs = Get-View -ViewType VirtualMachine -Property Name,OverallStatus,TriggeredAlarmstate
467 | $FaultyVMs = $VMs | Where-Object {$_.OverallStatus -ne "Green"}
468 |
469 | $progress = 1
470 | $report = @()
471 | if ($FaultyVMs -ne $null) {
472 | foreach ($FaultyVM in $FaultyVMs) {
473 | foreach ($TriggeredAlarm in $FaultyVM.TriggeredAlarmstate) {
474 | Write-Progress -Activity "Gathering alarms" -Status "Working on $($FaultyVM.Name)" -PercentComplete ($progress/$FaultyVMs.count*100) -Id 1 -ErrorAction SilentlyContinue
475 | $alarmID = $TriggeredAlarm.Alarm.ToString()
476 | $object = New-Object PSObject
477 | Add-Member -InputObject $object NoteProperty VM $FaultyVM.Name
478 | Add-Member -InputObject $object NoteProperty TriggeredAlarms ("$(Get-AlarmDefinition -Id $alarmID)")
479 | $report += $object
480 | }
481 | $progress++
482 | }
483 | }
484 | Write-Progress -Activity "Gathering Active VM alarms" -Status "All done" -Completed -Id 1 -ErrorAction SilentlyContinue
485 |
486 | $report | Where-Object {$_.TriggeredAlarms -ne ""} |Table
487 | Blankline}
488 |
489 |
490 | }
491 |
492 | $document | Export-Document -Path ~\Desktop -Format Word,Html -PassThru:$PassThru -Verbose;
493 | $synthesizer.SelectVoice('Microsoft David Desktop')
494 | $synthesizer.Speak('Documentation Complete. Word and HTML files are located on your desktop')
495 |
496 |
497 | Disconnect-viserver -Server * -Confirm:$false
498 |
499 | }
500 | Function Set-RR {
501 | #Setting Storage Luns to Round Robin
502 |
503 | $VC = Read-Host " Enter vCenter name:"
504 |
505 |
506 | Connect-VIServer $VC
507 |
508 | Get-Cluster | Select name | FT
509 | $Cluster = Read-Host " Enter Cluster name fron list above:"
510 |
511 |
512 | $VMhosts = Get-cluster $cluster | Get-VMHost
513 |
514 | Foreach ($VMhost in $VMhosts) {
515 | Write-Host "Setting Multipath Policy on $VMhost to Round Robin" -ForegroundColor Green
516 | Get-VMHost $VMhost | Get-ScsiLun -LunType disk | Where {$_.MultipathPolicy -notlike "RoundRobin"} | Set-Scsilun -MultiPathPolicy RoundRobin
517 | Get-VMhost $VMhost | Get-ScsiLun -LunType Disk | Where-Object {$_.CanonicalName -like ‘naa.*’ -and $_.MultipathPolicy -like ‘RoundRobin’} | Set-ScsiLun -CommandsToSwitchPath 1
518 |
519 | }
520 |
521 |
522 | Write-host "disconnecting from $VC" -ForegroundColor Yellow
523 | Disconnect-VIServer -Server * -Confirm:$False
524 |
525 | }
526 | Function Change-CPU {
527 | $VC = Read-Host "Enter the vCenter name or IP"
528 | Connect-VIServer $VC
529 |
530 | CLS
531 |
532 | $VM = Read-Host "Enter the name of the VM to change the vCPU of"
533 | $NumCPU = Read-Host "Enter the total number of vCPU $VM needs to have"
534 |
535 | Write-Host "Shutting Down $VM to make change" -ForegroundColor Yellow
536 | Get-VM $VM | Shutdown-VMGuest -Confirm:$false
537 | sleep 60
538 | Set-VM -VM $VM -NumCpu $NumCPU -Confirm:$false
539 | sleep 5
540 | Start-VM $VM
541 |
542 | Write-Host "Change complete, $VM is powering on" -ForegroundColor Yellow
543 |
544 | Disconnect-VIServer -Server * -Confirm:$false
545 |
546 | }
547 | Function Change-Memory {
548 | $VC = Read-Host "Enter the vCenter name or IP"
549 | Connect-VIServer $VC
550 |
551 | CLS
552 |
553 | $VM = Read-Host "Enter the name of the VM to change the Memory on"
554 | $NumMEM = Read-Host "Enter the total amount of Memory $VM needs to have in GB"
555 |
556 | Write-Host "Shutting Down $VM to make change" -ForegroundColor Yellow
557 | Get-VM $VM | Shutdown-VMGuest -Confirm:$false
558 | sleep 60
559 | Set-VM $VM -MemoryGB $NumMem -Confirm:$false
560 | sleep 5
561 | Start-VM $VM
562 |
563 | Write-Host "Change complete, $VM is powering on" -ForegroundColor Yellow
564 |
565 | Disconnect-VIServer -Server * -Confirm:$false
566 |
567 | }
568 |
569 |
570 | do
571 | {
572 | Show-Menu –Title 'Select Script'
573 | $input = Read-Host "what do you want to do?"
574 | switch ($input)
575 | {
576 | '1' {
577 | Get-VDCEdge
578 | }
579 | '2' {
580 | New-Tenant
581 | }
582 | '3' {
583 | Get-VMinfo
584 | }
585 | '4' {
586 | Get-Capacity
587 | }
588 | '5' {
589 | Set-RR
590 | }
591 | '6' {
592 | Change-CPU
593 | }
594 | '7' {
595 | Change-Memory
596 | }
597 | 'q' {
598 | return
599 | }
600 | }
601 | pause
602 | }
603 | until ($input -eq 'q')
604 |
--------------------------------------------------------------------------------