search
Categories
Sponsors
VirtualMetric Hyper-V Monitoring, Hyper-V Reporting
Archive
Blogroll

Badges
MCSE
Community

Cozumpark Bilisim Portali
Posted in Windows Powershell, Windows Server | No Comment | 3,705 views | 10/07/2014 15:43

You may need to see passthrough disk information from Hyper-V VMs on several clusters.

So you can use following 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
# Get Clusters
$Clusters = Get-Content Clusters.txt
 
foreach ($Cluster in $Clusters)
{
	# Get Cluster Nodes
	$ClusterNodes = Get-Cluster $Cluster | Get-ClusterNode
 
	foreach ($ClusterNode in $ClusterNodes)
	{
		# Clear PT Values
		$PTDisks = $Null;
 
		# Get Passthrough Disks
		$PTDisks = Get-VM -ComputerName $ClusterNode | Get-VMHardDiskDrive | Where Path -like Disk*
 
		if ($PTDisks)
		{
			# Get VM Name
			$VMName = $PTDisks[0].VMName
 
			# Informational Output
			Write-Host Working on $VMName..
 
			foreach ($PTDisk in $PTDisks)
			{
				# Get Passthrough Disk Info
				$PTInfo = $PTDisk.Path
 
				# Informational Output
				Write-Host $PTInfo
			}
 
			# Informational Output
			Write-Host " "
			Write-Host " "
		}
	}
}

That will give you disk information output. You should add all clusters names into Cluster.txt file.


Posted in Windows Powershell, Windows Server | No Comment | 2,748 views | 04/07/2014 18:00

Lets assume that you have a 3 years old storage and you are using it to place your virtual machines on Hyper-V Cluster. Then you bought a new storage box, you created LUNs on it and assign them as a CSV volumes on your existing Hyper-V Cluster. So next achievement would be migrating your virtual machines from old storage to new one.

Update: This script is now a function called Start-CSVMigration, you can reach it from:
http://www.yusufozturk.info/virtual-machine-manager/hyper-v-csv-migration-start-csvmigration.html

That migration could be a headache if you have many VMs and many storage LUNs. So in that case, you can use following script to migrate Virtual Machines per CSV Volume. Just you need to specify which CSV volume you would like to drain. So let’s assume that volume is Volume1. I will specify that volume by following line:

1
2
# Target Volume
$TargetVolume = "Volume1"

Now you need to specify other CSV Luns as well to filter them. Otherwise, you can migrate a VM to old storage again. So we are filtering them by following lines:

1
2
3
4
5
6
7
8
# Filtered Volumes
$FilteredVolumes = @()
$FilteredVolumes += $TargetVolume
$FilteredVolumes += "Volume2"
$FilteredVolumes += "Volume3"
$FilteredVolumes += "Volume4"
$FilteredVolumes += "Volume5"
$FilteredVolumes += "Volume6"

We are creating an array called FilteredVolumes then adding our old storage luns to this array. You will see that I’m also adding $TargetVolume to same array. Because there is a chance to try to migrate a VM to same volume. So that will prevent that kind of issues.

So how can I get destination volume?

1
2
# Full Query
$FullQuery = '((Get-ClusterSharedVolume |' + $Query + ' Select -ExpandProperty SharedVolumeInfo | Select @{label="Name";expression={(($_.FriendlyVolumeName).Split("\"))[-1]}},@{label="FreeSpace";expression={($_ | Select -Expand Partition).FreeSpace}} | Sort FreeSpace -Descending)[0]).Name'

As you can notice from the code below, i’m getting all CSV volumes, filtering old storage volumes, sorting new storage CSVs by their free space and selecting the storage which has biggest available disk space.

So I’ll place VM into that volume:

Move-VMStorage -ComputerName "$ClusterNode" -VMName "$VMName" -DestinationStoragePath "C:\ClusterStorage\$Volume\$VMName"

If you get the idea, now I can share full 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
# Target Volume
$TargetVolume = "Volume1"
 
# Filtered Volumes
$FilteredVolumes = @()
$FilteredVolumes += $TargetVolume
$FilteredVolumes += "Volume2"
$FilteredVolumes += "Volume3"
$FilteredVolumes += "Volume4"
$FilteredVolumes += "Volume5"
$FilteredVolumes += "Volume6"
 
# Clear Query
$Query = $Null;
 
# Create Query
foreach ($FilteredVolume in $FilteredVolumes)
{
	$Query = $Query + ' Where {$_.SharedVolumeInfo.FriendlyVolumeName -notlike "*' + $FilteredVolume + '"} |'
}
 
# Full Query
$FullQuery = '((Get-ClusterSharedVolume |' + $Query + ' Select -ExpandProperty SharedVolumeInfo | Select @{label="Name";expression={(($_.FriendlyVolumeName).Split("\"))[-1]}},@{label="FreeSpace";expression={($_ | Select -Expand Partition).FreeSpace}} | Sort FreeSpace -Descending)[0]).Name'
 
# Get Cluster Nodes
$ClusterNodes = Get-Cluster | Get-ClusterNode
 
foreach ($ClusterNode in $ClusterNodes)
{
	# Clear Variables
	$VMs = $Null;
 
	# Get All Virtual Machines on Target Volume
	$VMs = Get-VM -ComputerName "$ClusterNode" | Where ConfigurationLocation -like "C:\ClusterStorage\$TargetVolume\*"
 
	foreach ($VM in $VMs)
	{
		# Get VM Information
		$VMName = $VM.Name
 
		Write-Host " "
		Write-Host "Working on $VMName .."
		Write-Host "Hyper-V Host: $ClusterNode"
 
		# Get Volume Information
		$Volume = Invoke-Expression $FullQuery
 
		# Move Virtual Machine
		Move-VMStorage -ComputerName "$ClusterNode" -VMName "$VMName" -DestinationStoragePath "C:\ClusterStorage\$Volume\$VMName"
 
		Write-Host "Done."
	}
}

It’s enough to run this script on one of the Cluster Node, so that will start migrating virtual machines. That will also give an output, so you will be able to see which VM you are migrating. I hope you will find it useful. See you!


Posted in Windows Powershell, Windows Server | No Comment | 3,307 views | 03/07/2014 11:34

You can use following script to get pwdlastset value of a computer:

1
[datetime]::fromfiletime((Get-ADComputer SLESGTRM04 -Properties pwdlastset).pwdlastset)

Also you can use conditional query:

1
2
$RefDate = (Get-Date).AddDays(-90)
Get-ADComputer -Filter * -Properties pwdlastset | Where {[datetime]::fromfiletime($_.pwdlastset) -lt $RefDate}

If you want to filter workstations:

1
2
$RefDate = (Get-Date).AddDays(-90)
Get-ADComputer -Filter * -Properties pwdlastset,OperatingSystem | Where OperatingSystem -like "*Server*" | Where {[datetime]::fromfiletime($_.pwdlastset) -lt $RefDate}

I hope you will find it helpful. Script should run on Windows Server 2012 and later..


Posted in Windows Powershell, Windows Server | No Comment | 3,158 views | 30/06/2014 17:32

You can use following script to get Port and Fabric WWN information from FCinfo via PowerShell.

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
# Get FCInfo Details
$FcToolCmd = "C:\StorageTools\fcinfo\fcinfo.exe /details"
 
# Create WWN Array
$WWNArray = @()
 
# Create Hash Table
$WWNInformation = @{}
 
# Port WWN Information
$FabricDetails = Invoke-Expression $FcToolCmd | Where {$_ -match "port_wwn"}
foreach ($FabricInfo in $FabricDetails)
{
	# Get Port WWN
	$FabricRegex = $FabricInfo -match "\b\S{2}\:\S{2}\:\S{2}\:\S{2}\:\S{2}\:\S{2}\:\S{2}\:\S{2}\b"
	$PortWWN = $Matches[0]
 
	# Add Hash Table
	$WWNInformation."$PortWWN" = "NULL"
 
	# Add WWN Array
	$WWNArray += $PortWWN
}
 
# Fabric Index
$FabricIndex = 0;
 
# Fabric WWN Information
$FabricDetails = Invoke-Expression $FcToolCmd | Where {$_ -match "fabric"}
foreach ($FabricInfo in $FabricDetails)
{
	# Get Fabric WWN
	$FabricRegex = $FabricInfo -match "\b\S{2}\:\S{2}\:\S{2}\:\S{2}\:\S{2}\:\S{2}\:\S{2}\:\S{2}\b"
	$FabricWWN = $Matches[0]
 
	# Get Port WWN
	$PortWWN = $WWNArray[$FabricIndex]
 
	# Add Hash Table
	$WWNInformation."$PortWWN" = "$FabricWWN"
 
	# Update Fabric Index
	$FabricIndex++
}
 
# Output Results
$WWNInformation

That will give you a hashtable as a result, so you can see details.


Posted in Windows Powershell, Windows Server | No Comment | 38,089 views | 27/06/2014 09:55

Following scripts require EMC Storage Integrator (ESI) PowerShell Toolkit (ESIPSToolkit).

Getting EMC Storage Snapshot Pools:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Import-Module ESIPSToolkit
function Get-EMCStorageSnapPools {
	$Storages = Get-EMCStorageSystem
	foreach ($Storage in $Storages) {
		$GlobalID = $Storage.GlobalID
		$Snappool = Get-EMCSnapshotPool | Where StorageSystemGlobalId -eq $GlobalID
		$Properties = New-Object Psobject
		$Properties | Add-Member Noteproperty StorageName $Storage.UserFriendlyName
		$Properties | Add-Member Noteproperty AvailableCapacity $Snappool.AvailableCapacity
		$Properties | Add-Member Noteproperty UserCapacity $Snappool.UserCapacity
		Write-Output $Properties
	}
}
Get-EMCStorageSnapPools

Getting Storage List:

1
2
3
Import-Module ESIPSToolkit
$Storage = Get-EMCStorageSystem
$Storage.UserFriendlyName

Getting Storage Thin Pools:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Import-Module ESIPSToolkit
function Get-EMCStorageThinPools {
	$Storages = Get-EMCStorageSystem
	foreach ($Storage in $Storages) {
		$GlobalID = $Storage.GlobalID
		$Thinpool = Get-EMCStoragePool | Where SupportsThinProvisioning -eq "True" | where StorageSystemGlobalId -eq $GlobalID
 
		foreach ($Pool in $Thinpool) {
			$Properties = New-Object Psobject
			$Properties | Add-Member Noteproperty StorageName $storage.UserFriendlyName
			$Properties | Add-Member Noteproperty PoolName $pool.Name
			$Properties | Add-Member Noteproperty TotalCapacity $pool.TotalCapacity.ValueGB
			$Properties | Add-Member Noteproperty AvailableCapacity $pool.AvailableCapacity.ValueGB
			$Properties | Add-Member Noteproperty SubscribedCapacity $pool.SubscribedCapacity.ValueGB
			Write-Output $Properties
		}
	}
}
Get-EMCStorageThinPools

Registering Host:

1
2
3
$StorageArray = Get-EMCStorageSystem "CX4_1"
$HostRegistration = "C0:03:FF:00:00:FF:FF:00:C0:03:FF:65:4D:A6:00:00","C0:03:FF:00:00:FF:FF:00:C0:03:FF:37:25:4E:00:16"
$RegisterHost = New-EMCStorageRegisteredHost -StorageSystem $StorageArray -HostName "Server01" -IpAddress "192.168.0.114" -HostBusAdapterIds $HostRegistration

To be continued.. :)


Posted in Virtual Machine Manager, Windows Powershell, Windows Server | No Comment | 2,043 views | 24/06/2014 09:42

You can update all SCVMM agents with following script:

1
2
3
4
5
6
7
$Credential = Get-SCRunAsAccount -Name "Domain_Account"
$HyperVHosts = Get-SCVMMManagedComputer
foreach ($HyperVHost in $HyperVHosts)
{
	$ManagedComputer = Get-SCVMMManagedComputer -ComputerName $HyperVHost
	Update-SCVMMManagedComputer -Credential $Credential -VMMManagedComputer $HyperVHost
}

That will update all Hyper-V hosts agents as soon as possible.


Posted in Windows Powershell, Windows Server | 3 Comments | 1,998 views | 23/06/2014 11:44

This is third version of Hyper-V Cluster Memory Reports.

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
$Clusters = Get-Content Clusters.txt
foreach ($Cluster in $Clusters)
{
	[int]$TotalFreeMemory = 0;
	[int]$TotalMemory = 0;
	[int]$TotalUsedMemory = 0;
	[int]$NodeCount = 0;
	$ClusterNodes = Get-Cluster $Cluster | Get-ClusterNode
	foreach ($ClusterNode in $ClusterNodes)
	{
		[int]$FreeMemory = [math]::round(((Get-WmiObject -ComputerName $ClusterNode -Class Win32_OperatingSystem).FreePhysicalMemory / 1MB), 0) - ([math]::round(((Get-WmiObject -ComputerName $ClusterNode -Class Win32_OperatingSystem).TotalVisibleMemorySize / 1MB), 0)*10/100)
		[int]$TotalFreeMemory = [int]$TotalFreeMemory + [int]$FreeMemory
		[int]$NodeMemory = [math]::round(((Get-WmiObject -ComputerName $ClusterNode -Class Win32_OperatingSystem).TotalVisibleMemorySize / 1MB), 0)
		[int]$TotalMemory = [int]$TotalMemory + [int]$NodeMemory
		[int]$UsedMemory = [int]$NodeMemory - [int]$FreeMemory
		[int]$TotalUsedMemory = [int]$TotalUsedMemory + [int]$UsedMemory;
		[int]$NodeCount = [int]$NodeCount + 1
	}
	[int]$TotalAvailableMemory = [int]$TotalFreeMemory - [int]$NodeMemory - ([int]$NodeMemory*10/100)
 
	Write-Host "Cluster: $Cluster"
	Write-Host "Total Memory: $TotalMemory"
	Write-Host "Total Free Memory: $TotalFreeMemory"
	Write-Host "Total Used Memory: $TotalUsedMemory"
	Write-Host "Total Available Memory: $TotalAvailableMemory"
	Write-Host "Node Count: $NodeCount"
 
	Write-Host " "
 
	$Value = $Cluster + ";" + $TotalMemory + ";" + $TotalFreeMemory + ";" + $TotalUsedMemory + ";" + $TotalAvailableMemory + ";" + $NodeCount + ";" + $NodeMemory
	Add-Content -Value $Value -Path Memory.txt
}

You should add your clusters into Clusters.txt file.