Posted in Virtual Machine Manager, Windows Powershell, Windows Server | 1 Comment | 3,570 views | 16/07/2013 09:23
You can get Cluster names from your Hyper-V host list with following PowerShell script:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| # Prepare Cluster Array
$ClusterArray = New-Object System.Collections.ArrayList
$Servers = Get-Content -Path C:\Servers.txt
foreach ($Server in $Servers)
{
$VMHost = Get-VMHost -ComputerName $Server
$HyperVFQDN = $VMHost.FullyQualifiedDomainName
if ($VMHost)
{
$ClusterName = (@(Get-Cluster $Server | Get-ClusterGroup | where GroupType -eq "VirtualMachine") | Select-Object -First 1).Cluster.Name
if ($ClusterName)
{
$TestCluster = $ClusterArray.Contains("$ClusterName")
if ($TestCluster -ne $True)
{
# Update Cluster Array
$ClusterArray.Add("$ClusterName") | Out-Null
}
Write-Host $ClusterName
}
}
} |
# Prepare Cluster Array
$ClusterArray = New-Object System.Collections.ArrayList
$Servers = Get-Content -Path C:\Servers.txt
foreach ($Server in $Servers)
{
$VMHost = Get-VMHost -ComputerName $Server
$HyperVFQDN = $VMHost.FullyQualifiedDomainName
if ($VMHost)
{
$ClusterName = (@(Get-Cluster $Server | Get-ClusterGroup | where GroupType -eq "VirtualMachine") | Select-Object -First 1).Cluster.Name
if ($ClusterName)
{
$TestCluster = $ClusterArray.Contains("$ClusterName")
if ($TestCluster -ne $True)
{
# Update Cluster Array
$ClusterArray.Add("$ClusterName") | Out-Null
}
Write-Host $ClusterName
}
}
}
After that you can use your Cluster names to get CSV reports.
Posted in Virtual Machine Manager, Windows Powershell | No Comment | 4,552 views | 16/07/2013 09:21
You can get CSV reports from your all Clusters with following PowerShell script:
1
2
3
4
5
6
7
8
9
10
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
| $Clusters = Get-Content -Path C:\Clusters.txt
foreach ($Cluster in $Clusters)
{
# Get CSV Disks
$CSVDisks = Get-ClusterSharedVolume -Cluster $Cluster
foreach ($CSVDisk in $CSVDisks)
{
# Get CSV Volume Information
$CSVVolumeInfo = $CSVDisk | Select -Expand SharedVolumeInfo
$CSVFriendlyName = $CSVVolumeInfo.FriendlyVolumeName
$CSVVolume = $CSVFriendlyName.Split("\")[2]
$CSVVolume = $CSVVolume.ToLower()
$CSVVolumeID = $CSVDisk.Id
$CSVState = $CSVDisk.State
# CSV Free Disk Space
[int]$CSVDiskDriveFreeSpace = ([math]::round((($CSVVolumeInfo | Select -Expand Partition).FreeSpace / 1GB), 0))
# CSV Total Disk Space
[int]$CSVDiskSpace = ([math]::round((($CSVVolumeInfo | Select -Expand Partition).Size / 1GB), 0))
# CSV Used Disk Space
[int]$CSVDiskDriveUsedSpace = [int]$CSVDiskSpace - [int]$CSVDiskDriveFreeSpace
# CSV Health
if ($CSVState -eq "Online")
{
if ($CSVVolumeInfo.MaintenanceMode -eq $False)
{
if ($CSVVolumeInfo.RedirectedAccess -eq $True)
{
$CSVHealth = "Warning"
$CSVHealthDetails = "Volume is in redirected access."
}
else
{
$CSVHealth = "Healthy"
$CSVHealthDetails = "Volume is healthy."
}
}
else
{
$CSVHealth = "Monitor"
$CSVHealthDetails = "Volume is in maintenance mode."
}
}
else
{
$CSVHealth = "Critical"
$CSVHealthDetails = "Volume is in offline state."
}
# CSV Reports
Write-Host $Cluster
$Value = $Cluster + ";" + $CSVVolume + ";" + $CSVDiskSpace + ";" + $CSVDiskDriveUsedSpace + ";" + $CSVDiskDriveFreeSpace + ";" + $CSVHealth
Add-Content -Value $Value -Path C:\CSVVolumes.txt
}
} |
$Clusters = Get-Content -Path C:\Clusters.txt
foreach ($Cluster in $Clusters)
{
# Get CSV Disks
$CSVDisks = Get-ClusterSharedVolume -Cluster $Cluster
foreach ($CSVDisk in $CSVDisks)
{
# Get CSV Volume Information
$CSVVolumeInfo = $CSVDisk | Select -Expand SharedVolumeInfo
$CSVFriendlyName = $CSVVolumeInfo.FriendlyVolumeName
$CSVVolume = $CSVFriendlyName.Split("\")[2]
$CSVVolume = $CSVVolume.ToLower()
$CSVVolumeID = $CSVDisk.Id
$CSVState = $CSVDisk.State
# CSV Free Disk Space
[int]$CSVDiskDriveFreeSpace = ([math]::round((($CSVVolumeInfo | Select -Expand Partition).FreeSpace / 1GB), 0))
# CSV Total Disk Space
[int]$CSVDiskSpace = ([math]::round((($CSVVolumeInfo | Select -Expand Partition).Size / 1GB), 0))
# CSV Used Disk Space
[int]$CSVDiskDriveUsedSpace = [int]$CSVDiskSpace - [int]$CSVDiskDriveFreeSpace
# CSV Health
if ($CSVState -eq "Online")
{
if ($CSVVolumeInfo.MaintenanceMode -eq $False)
{
if ($CSVVolumeInfo.RedirectedAccess -eq $True)
{
$CSVHealth = "Warning"
$CSVHealthDetails = "Volume is in redirected access."
}
else
{
$CSVHealth = "Healthy"
$CSVHealthDetails = "Volume is healthy."
}
}
else
{
$CSVHealth = "Monitor"
$CSVHealthDetails = "Volume is in maintenance mode."
}
}
else
{
$CSVHealth = "Critical"
$CSVHealthDetails = "Volume is in offline state."
}
# CSV Reports
Write-Host $Cluster
$Value = $Cluster + ";" + $CSVVolume + ";" + $CSVDiskSpace + ";" + $CSVDiskDriveUsedSpace + ";" + $CSVDiskDriveFreeSpace + ";" + $CSVHealth
Add-Content -Value $Value -Path C:\CSVVolumes.txt
}
}
You can export CSVVolumes.txt into Excel file for a good looking reporting :)
Posted in Windows Powershell, Windows Server | No Comment | 3,056 views | 09/07/2013 17:37
This will give you host and guest CPU usage on your Hyper-V host.
1
2
3
4
5
6
7
| $ClusterNode = "Host01"
While ($True)
{
$ChildCPU = ((Get-Counter -ComputerName $ClusterNode -Counter "\Hyper-V Hypervisor Logical Processor(_Total)\% Total Run Time" -MaxSamples 3).CounterSamples | Measure-Object CookedValue -Max).Maximum
$ParentCPU = ((Get-Counter -ComputerName $ClusterNode -Counter "\Processor Information(_Total)\% Processor Time" -MaxSamples 3).CounterSamples | Measure-Object CookedValue -Max).Maximum
Start-Sleep 5
} |
$ClusterNode = "Host01"
While ($True)
{
$ChildCPU = ((Get-Counter -ComputerName $ClusterNode -Counter "\Hyper-V Hypervisor Logical Processor(_Total)\% Total Run Time" -MaxSamples 3).CounterSamples | Measure-Object CookedValue -Max).Maximum
$ParentCPU = ((Get-Counter -ComputerName $ClusterNode -Counter "\Processor Information(_Total)\% Processor Time" -MaxSamples 3).CounterSamples | Measure-Object CookedValue -Max).Maximum
Start-Sleep 5
}
You should change $ClusterNode to start monitoring.
Posted in Windows Powershell, Windows Server | No Comment | 1,649 views | 09/07/2013 15:56
You can get all passthrough disks and total disk counts like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| $Servers = Get-Content C:\Servers2.txt
foreach ($Server in $Servers)
{
$VMs = Get-VM -ComputerName $Server
Write-Host $Server
foreach ($VM in $VMs)
{
$Count = 0;
$TotalDisk = 0;
$Disks = $VM | Select -Expand HardDrives
foreach ($Disk in $Disks)
{
if ($Disk.Path -like "Disk*")
{
$Count++
[string]$DiskSize = $Disk.Path.Split(" ")[2]
Write-Host $DiskSize
$DiskSize = $DiskSize.Split(".")[0]
$TotalDisk = $TotalDisk + [int]$DiskSize
}
}
if ($Count -gt "0")
{
$Value = $VM.Name + "," + $Count + "," + $TotalDisk + "," + $VM.ComputerName
Add-Content -Value $Value -Path C:\passthrough2.txt
}
}
} |
$Servers = Get-Content C:\Servers2.txt
foreach ($Server in $Servers)
{
$VMs = Get-VM -ComputerName $Server
Write-Host $Server
foreach ($VM in $VMs)
{
$Count = 0;
$TotalDisk = 0;
$Disks = $VM | Select -Expand HardDrives
foreach ($Disk in $Disks)
{
if ($Disk.Path -like "Disk*")
{
$Count++
[string]$DiskSize = $Disk.Path.Split(" ")[2]
Write-Host $DiskSize
$DiskSize = $DiskSize.Split(".")[0]
$TotalDisk = $TotalDisk + [int]$DiskSize
}
}
if ($Count -gt "0")
{
$Value = $VM.Name + "," + $Count + "," + $TotalDisk + "," + $VM.ComputerName
Add-Content -Value $Value -Path C:\passthrough2.txt
}
}
}
This will give you sum of all passthrough disks.
Posted in Windows Powershell, Windows Server | No Comment | 1,948 views | 09/07/2013 10:05
As you may know, if you have SCCM 2007 agent on your Windows Server 2012, then you may see some problems with WMI. That issue blocks all WMI communication, Remote Desktop Services and Cluster functionality.
Recommended way to upgrade your SCCM 2007 to SCCM 2012, or you need to apply latest patches to your SCCM server.
You can disable all agents like this:
1
2
3
4
5
6
7
8
9
| $Servers = Get-Content C:\Servers.txt
foreach ($Server in $Servers)
{
Write-Host $Server
(Get-WmiObject win32_process -Filter "name = 'CcmExec.exe'" -ComputerName $Server).Terminate()
Set-Service -ComputerName $Server -Name "CcmExec" -StartupType "Disabled"
Set-Service -ComputerName $Server -Name "smstsmgr" -StartupType "Disabled"
Start-Sleep 1
} |
$Servers = Get-Content C:\Servers.txt
foreach ($Server in $Servers)
{
Write-Host $Server
(Get-WmiObject win32_process -Filter "name = 'CcmExec.exe'" -ComputerName $Server).Terminate()
Set-Service -ComputerName $Server -Name "CcmExec" -StartupType "Disabled"
Set-Service -ComputerName $Server -Name "smstsmgr" -StartupType "Disabled"
Start-Sleep 1
}
After that, service will stopped and startup type will be disabled to avoid automatic startup after reboot.
Posted in Windows Powershell, Windows Server | No Comment | 5,916 views | 09/07/2013 09:45
If you have “HP ProLiant Smart Array SAS/SATA Controller Driver for Windows Server 2012 x64 Edition (HPCISSS2.SYS) Version 62.26.0.64”, then you need to downgrade it to version 62.24.2.64. Otherwise you will see some problems and unexpected shutdowns on your Windows Servers and Hyper-V hosts.
But if you have many servers, it will not be easy to see which servers has latest version. So you use this script to get driver versions:
1
2
3
4
5
6
7
8
| $Servers = Get-Content C:\Servers.txt
foreach ($Server in $Servers)
{
Write-Host $Server
$ProductVersion = (Get-Item \\$Server\C$\Windows\System32\Drivers\HPCISSs2.sys).VersionInfo.ProductVersion
$Value = $Server + "," + $ProductVersion
Add-Content -Value $Value -Path C:\driverversions.txt
} |
$Servers = Get-Content C:\Servers.txt
foreach ($Server in $Servers)
{
Write-Host $Server
$ProductVersion = (Get-Item \\$Server\C$\Windows\System32\Drivers\HPCISSs2.sys).VersionInfo.ProductVersion
$Value = $Server + "," + $ProductVersion
Add-Content -Value $Value -Path C:\driverversions.txt
}
You need to add your all servers into Servers.txt file.
Posted in Virtual Machine Manager, Windows Powershell | No Comment | 4,493 views | 25/06/2013 08:40
If you need to sync OS name with VM name on Hyper-V, you can use KVP exchange feature:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| $HyperVHost = "MyHyperV"
filter Import-CimXml
{
$CimXml = [Xml]$_
$CimObj = New-Object -TypeName System.Object
foreach ($CimProperty in $CimXml.SelectNodes("/INSTANCE/PROPERTY"))
{
$CimObj | Add-Member -MemberType NoteProperty -Name $CimProperty.NAME -Value $CimProperty.VALUE
}
$CimObj
}
$VMs = Get-VM -ComputerName $HyperVHost
foreach ($VM in $VMs)
{
$VMInfo = Get-WmiObject -ComputerName $HyperVHost -Namespace root\virtualization -Query "Select * From Msvm_ComputerSystem Where ElementName='$VM'"
$KVPData = Get-WmiObject -ComputerName $HyperVHost -Namespace root\virtualization -Query "Associators of {$VMInfo} Where AssocClass=Msvm_SystemDevice ResultClass=Msvm_KvpExchangeComponent"
$KVPExport = $KVPData.GuestIntrinsicExchangeItems
$Hostname = ($KVPExport | where {$_.Name -eq "FullyQualifiedDomainName"}).Data
$VM | Rename-VM -NewName $Hostname
} |
$HyperVHost = "MyHyperV"
filter Import-CimXml
{
$CimXml = [Xml]$_
$CimObj = New-Object -TypeName System.Object
foreach ($CimProperty in $CimXml.SelectNodes("/INSTANCE/PROPERTY"))
{
$CimObj | Add-Member -MemberType NoteProperty -Name $CimProperty.NAME -Value $CimProperty.VALUE
}
$CimObj
}
$VMs = Get-VM -ComputerName $HyperVHost
foreach ($VM in $VMs)
{
$VMInfo = Get-WmiObject -ComputerName $HyperVHost -Namespace root\virtualization -Query "Select * From Msvm_ComputerSystem Where ElementName='$VM'"
$KVPData = Get-WmiObject -ComputerName $HyperVHost -Namespace root\virtualization -Query "Associators of {$VMInfo} Where AssocClass=Msvm_SystemDevice ResultClass=Msvm_KvpExchangeComponent"
$KVPExport = $KVPData.GuestIntrinsicExchangeItems
$Hostname = ($KVPExport | where {$_.Name -eq "FullyQualifiedDomainName"}).Data
$VM | Rename-VM -NewName $Hostname
}
Btw, I haven’t tested this script yet. But that should work :)
|