Posted in
Windows Powershell,
Windows Server |
No Comment | 2,747 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.
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" |
# 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" |
# 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' |
# 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" |
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."
}
} |
# 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,305 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) |
[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} |
$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} |
$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..