as yesterday the RC of the Windows 2012 came I thought i would give it a try.
First of all, i wanted to test if I could upgrade my win8 beta server to the Windows 2012 RC but as you can see on the picture from the installation this is not possible. So what to do, as I had two nodes i live migrated my VM´s to the other win8 beta and did a fresh install.
When it was finished I wanted to add the server to the domain and of course this should be done with powershell. When installing you all know that the OS get a not so friendly name so with the parameter -NewName I rename it at the same time as I add it to the domain.
Next step was of course to add the Hyper-V role,
And what to do next, well i want to live migrate my VM´s from my other node but that was unfortunately not possible 🙁 cause of some kind of mismatch with the protocol as you can see on my next screendump
Ok so my next plan was to export the VM´s and then import them, this also with powershell, but as the win8 beta set the dynamic memory maximum to 2 TB i got a configuration issue so I had to handle that before i had an successfull import
After this I could import it ( notice though I could not use the parameter -copy when using -CompabilityReport, so I had to manually copy the VM to the Hyp31 server )
Good luck in your migration to the Windows 2012 RC 🙂
I did not get this idea all by my self, a customer I was at for a couple of weeks ago showed me a small script he had to check the services set to automatic after patching to see that they actually was running again.
I thought this could be somewhat more sophisticated done, so I created a script function that can handle single servers or an array of servers and in the script you can either start all services that are stopped or select just the ones you want, you can also in the function add services that you know are not important.
As you can see, I can get the servers from the Active Directory, In this example I have created a OU that contains the servers I want to check. I can also check for example in VMware with PowerCLI and getting an array of running VM´s. This can also be done on my Hyper-V environment with SCVMM. The different arrays I collect is just to get the server names and then I do an Get-wmiObject on the servers.
Here in this screen dump I check the computers in my AD, As you can see I select (N)o and that mean that I want all services that are not running and set to automatic to be started
In this next example I check the VM´s in my VMware vSphere environment
In this last example where i query a SCVMM server for the VM´s on the Hyper-V cluster I use the -AutoRestart parameter to start up all the services that the function finds.
And here is the powershell function, the tricky part here was to get the starting of services remote working and I had to use the -InputObject command as I did not get the pipeline of Get-Service -Computer xyz -Name Spooler | Start-Service to work.
function Check-Service{
<#
.SYNOPSIS
Check if Autostart Services has not started after patching
.DESCRIPTION
Use this function to check that all autostart services have started on the servers after patching
.PARAMETER xyz
.NOTES
Author: Niklas Akerlund / RTS
Date: 2012-05-28
#>
param (
[Parameter(Position=0,Mandatory=$true,HelpMessage="A server",
ValueFromPipeline=$True)]
$Servers,
[switch]$AutoRestart
)
$report = @()
$IgnoreServices = "ShellHWDetection","clr_optimization_v4.0.30319_32","clr_optimization_v4.0.30319_64","sppsvc"
if ($Servers.GetType().Name -eq "String"){
$Services = Get-WmiObject -ComputerName $Servers -Class win32_service -ErrorAction SilentlyContinue | where {$_.Startmode -EQ "Auto" -and $_.State -NE "Running"}
if ($Services -ne $null) {
foreach ($Service in $Services){
if(!($IgnoreServices -contains $Service.Name)){
$data = New-Object PSObject -property @{
Server = $Servers
Name = $Service.Name
StartMode = $Service.StartMode
State = $Service.State
}
$report +=$data
}
}
}
}else{
foreach ($Server in $Servers){
$Services = Get-WmiObject -ComputerName $Server.Name -Class win32_service -ErrorAction SilentlyContinue | where {$_.Startmode -EQ "Auto" -and $_.State -NE "Running"}
if ($Services -ne $null) {
foreach ($Service in $Services){
if(!($IgnoreServices -contains $Service.Name)){
$data = New-Object PSObject -property @{
Server = $Server.Name
Name = $Service.Name
StartMode = $Service.StartMode
State = $Service.State
}
$report +=$data
}
}
} else {
Write-Host "Could not query server: $Server"
}
}
}
$report
if($AutoRestart){
$report |%{ Start-Service -InputObject (Get-Service -ComputerName $_.Server -Name $_.Name)}
}else{
if($report -ne $null){
Write-Host "Do you want to select which services to start? (Y) (N) (Q):"
$select = Read-Host
if ($select -eq "Y"){
foreach ($item in $report){
Write-Host "Start service " $item.Name " on server" $item.Server " (Y) (N)"
$restart = Read-Host
if ($restart -eq "Y"){
Start-Service -InputObject (Get-Service -ComputerName $item.Server -Name $item.Name)
}
}
}elseif($select -eq "N"){
$report |%{ Start-Service -InputObject (Get-Service -ComputerName $_.Server -Name $_.Name)}
}
}
}
}
Good luck in finding services that should be running in your environment 🙂
So first I have to shrink the partition inside the VM, for this I use the New-CIMSession (instead of powershell remoting and such) and then I shut down the VM and shrink the VHDx file, As someone correctly noted, this shrink of the virtual disk file is only possible when using the new VHDx format.
The VM is part of the same domain as the hyper-V server from which I am running the script, this made it easier to make a cim connection. The VM is also a Win 8 beta cause I need the latest win framework with powershell 3.
As you can see, the disk in my VM is 60 GB and I want to shrink it to the minimum size * 20% (so i get at least some space left 😉
Now I will run my little script and here is what that looks like
And here you can see the result, a quite simple solution..
Good luck in your shrinking 🙂
Update: I totally missed that Ben had done a post about doing it with powershell, just after his other post when i was making this post… At least my solution show how to connect to a VM with CIM 🙂
Today I was at a customer and upgraded their VMM 2012 from RC to RTM. We got an issue when trying to run a bare metal deploy after the upgrade, at first we did not understand what was causing the error, but my suspicion was on the winpe that was published by VMM in the WDS PXE.
Here is the error in the VMM Console also
And then i used PowerShell to update the VMM WinPE that resides in the WDS, this because their environment had new HP blades and i needed to add a nic driver. If you do not need to add anything to the winpe you can right click on the VMM console and the PXE and you find a selection “Update WinPE Image” this will use an image from the WAIK installed on the VMM Server. Here is the link for the powershell cmdlet that updates the WinPE
The Powershell I ran was as below, I had to run the dism tools with elevated rights, this can be done by right click on the Powershell console and “Run As Administrator”
To fully utilize the performance in a vApp in vCloud Director I got the task to create an affinity rule based on the VMs in the vApp. This can be the case for example when you have VMs in an vApp that exchange high loads of data. In our case we have virtual ESXi Servers that have a vsa for shared storage and need good performance when deploying VM´s and storage vMotion etc.
When deploying several vApps from the same template it is not just to run Get-CIVM and then use the VM name returned to run Get-VM for the correlation between the VM in VCD and in vCenter, as you can see in the screendumps these two have the same name but followed with an identifier from vCD in the vSphere Client. This is also described in the vSphere blog.
The fine part is that the MoRef is unique (in the relation one vcd <-> one vcenter) so I can check on that which VMs in the vCenter belongs to the same vCloud Director vApp.
<#
.Synopsis
Add an affinity rule for a vCloud Director vAPP
.DESCRIPTION
This function takes a vApp as parameter and creates an affinity rule for them to keep them together
.EXAMPLE
Add-CIVAppAffinity -CIVApp Green01
.NOTES
Author: Niklas Akerlund / RTS
Date: 2012-05-03
#>
function Add-CIVAppAffinity
{
Param
(
# Parameter for the vAPP
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
$CIVApp,
# If the rule should apply on a different cluster
$Cluster = "vCD-Cluster"
)
$pod = Get-CIVapp $CIVApp
if ($pod){
$PodVMs = Get-CIVM -VApp $pod
$VMs = @()
$Cluster = Get-Cluster $Cluster
Foreach ($PodVM in $PodVMs) {
$VMname = $PodVM.Name + "*"
$VM = Get-VM $VMname | where {$_.ExtensionData.MoRef.Value -eq $PodVM.ExtensionData.VCloudExtension[0].Any[0].VmVimObjectRef.MoRef}
$VMs +=$VM
}
if (!(Get-DrsRule -Cluster $Cluster -Name $pod.Name -ErrorAction SilentlyContinue)){
New-DrsRule -Name $pod.Name -Cluster $Cluster -KeepTogether $true -VM $VMs
}else{
Remove-DrsRule -Rule (Get-DrsRule -Cluster $Cluster -Name $pod.Name) -Confirm:$false
New-DrsRule -Name $pod.Name -Cluster $Cluster -KeepTogether $true -VM $VMs
}
}
}
And when checking the cluster i can see that my DRS affinity rule has been created and the VMs have been migrated to the same host
It is not so extensive but it helps us with the case to create DRS affinity on the VMs in a particular vApp 🙂 , The Rule is deleted when the vApp is removed, I have an extra check in the script and remove it if it still exist of some reason.
I am in the hotel waiting for the MMS 2012 to start so there is time for some automation ;-). Last week when I was teaching a course one of the attendes said after I showed the custom value function, that he also wanted a similar function for easy in the console check how many snapshots every VM had. In the VMM 2012 console I have not found an built-in function to actually show this.
I have modified the function and created the run script, this is scheduled to run once a hour so you have a updated view of your environment. At least in the Hyper-V for Windows 2008 R2 it is not recommended to use in production.
It is quite easy to create a new custom property that we then will populate,
In the GUI there is no way to remove a custom property, I can only remove it from assigned properties. During the course I created an property just for showing and want to get rid of it. Of course there is a powershell cmdlet for that:
But now to the part of getting the script to show snapshots (yes I know, in VMM it is called Checkpoints but i refuse to call it that)
First I have the PowerShell function
function Set-CVSnapShot{
<#
.SYNOPSIS
Function to Update custom values for VM´s in VMM 2012
.DESCRIPTION
Use this function to set the custom value Snapshot count
.PARAMETER VMs
Use this parameter to update just that VM´s custom snapshot value
.NOTES
Author: Niklas Akerlund / RTS
Date: 2012-04-16
#>
param (
[Parameter(Position=0,HelpMessage="A virtual machine pleaze",
ValueFromPipeline=$True)]
$VMs = " "
)
if ($VMs -eq " "){
$VMs = Get-SCVirtualMachine
}else{
$VMs = Get-SCVirtualMachine $VMs
}
$CustomSnapShot = Get-SCCustomProperty -Name "Snapshot Count"
foreach ($VM in $VMs){
$count = ($VM | Get-SCVMCheckpoint).Count
if($count -ne $null){
Set-SCCustomPropertyValue -InputObject $VM -CustomProperty $CustomSnapShot -Value $count
}else{
Set-SCCustomPropertyValue -InputObject $VM -CustomProperty $CustomSnapShot -Value 0
}
}
}
then I have a very easy script that I task scheduled in my VMM server
# Script to use for scheduled updates of Custom values
#
# Niklas Akerlund / RTS 2012-04-16
ipmo 'C:\Program Files\Microsoft System Center 2012\Virtual Machine Manager\bin\psModules\VirtualMachineManager' | Out-Null
. .\Set-CVSnapshot.ps1
Set-CVSnapshot
And in the VMM Console it looks like this
I will talk to some VMM responsibles at MMS and see if they find an interest and build the view instead of me running it in a sheduled task (as the information is there in the database)
As always ( or at least in my world) you should do everything in powershell/powerCLI. Now the turn comes to handling licensing in VMware vSphere.
I searched the web and found some information from Luc Dekens post and from Joe Keegan post. I also used the Onyx VMware fling to get some more functionality.
I decided to do some powershell functions and came up with the following, I have created three functions that can do some magic with your licenses
Get-vLicense – query the vCenter for licenses
Add-vLicense – add a license or assign an existing license to a host/vCenter
Remove-vLicense – remove a license that is not in use
Of course there might be other things regarding licensing i have forgot but see this as a version 0.1 and that you can give me input on what to add or change
Here you can see how the function get the information:
You have to bare with me and my paintbrush skills, but I cannot show my license keys on the Internet 🙂
I can also use a switch to just show the ones that are not used with
Get-vLicense -showUnused
I would like to move my hosts to the new license that i have that has unlimited cores
I can also in the Add function just add without assigning the license right now just use the -AddKey switch
And if I want to remove the unused license I use the following function, It can utilize a pipeline parameter as you see
And here is the whole code for the functions:
function Get-vLicense{
<#
.SYNOPSIS
Function to show all licenses in vCenter
.DESCRIPTION
Use this function to get all licenses in vcenter
.PARAMETER xyz
.NOTES
Author: Niklas Akerlund / RTS
Date: 2012-03-28
#>
param (
[Parameter(ValueFromPipeline=$True, HelpMessage="Enter the license key or object")]$LicenseKey = $null,
[Switch]$showUnused,
[Switch]$showEval
)
$servInst = Get-View ServiceInstance
$licenceMgr = Get-View $servInst.Content.licenseManager
if ($showUnused -and $showEval){
$licenses = $licenceMgr.Licenses | where {$_.EditionKey -eq "eval" -or $_.Used -eq 0}
}elseif($showUnused){
$licenses = $licenceMgr.Licenses | where {$_.EditionKey -ne "eval" -and $_.Used -eq 0}
}elseif($showEval){
$licenses = $licenceMgr.Licenses | where {$_.EditionKey -eq "eval"}
}elseif ($LicenseKey -ne $null) {
if (($LicenseKey.GetType()).Name -eq "String"){
$licenses = $licenceMgr.Licenses | where {$_.LicenseKey -eq $LicenseKey}
}else {
$licenses = $licenceMgr.Licenses | where {$_.LicenseKey -eq $LicenseKey.LicenseKey}
}
}
else {
$licenses = $licenceMgr.Licenses | where {$_.EditionKey -ne "eval"}
}
$licenses
}
function Add-vLicense{
<#
.SYNOPSIS
Add New Licenses to the vCenter license manager
.DESCRIPTION
Use this function to add licenses and assing to either the vcenter or the hosts
.PARAMETER xyz
.NOTES
Author: Niklas Akerlund / RTS
Date: 2012-03-28
#>
param (
$VMHost ,
[Parameter(ValueFromPipeline=$True)]$License = $null,
[string]$LicenseKey = "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX",
[switch]$AddKey
)
$LicenseMgr = Get-View -Id 'LicenseManager-LicenseManager'
$LicenseAssignMgr = Get-View -Id 'LicenseAssignmentManager-LicenseAssignmentManager'
if($License){
$LicenseKey = $License.LicenseKey
$LicenseType = $LicenseMgr.DecodeLicense($LicenseKey)
}else{
$LicenseType = $LicenseMgr.DecodeLicense($LicenseKey)
}
if ($LicenseType) {
if ($AddKey){
$LicenseMgr.AddLicense($LicenseKey, $null)
}else{
if ($LicenseType.EditionKey -eq "vc"){
#$servInst = Get-View ServiceInstance
$Uuid = (Get-View ServiceInstance).Content.About.InstanceUuid
$licenseAssignMgr.UpdateAssignedLicense($Uuid, $LicenseKey,$null)
} else {
$key = Get-vLicense -LicenseKey $LicenseKey
if($key -and ($key.Total-$key.Used) -lt (get-vmhost $VMHost | get-view).Hardware.CpuInfo.NumCpuPackages){
Write-Host "Not Enough licenses left"
} else{
$Uuid = (Get-VMhost $VMHost | Get-View).MoRef.Value
$licenseAssignMgr.UpdateAssignedLicense($Uuid, $LicenseKey,$null)
}
}
}
}
}
function Remove-vLicense{
<#
.SYNOPSIS
Function to remove a licenses that is not in use in vCenter
.DESCRIPTION
Use this function to remove a license
.PARAMETER xyz
.NOTES
Author: Niklas Akerlund / RTS
Date: 2012-03-28
#>
param (
[Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$True, HelpMessage="Enter the key or keyobject to remove")]$License
)
$LicObj = Get-vLicense $License
if($LicObj.Used -eq 0){
$LicenseMgr = Get-View -Id 'LicenseManager-LicenseManager'
$LicenseMgr.RemoveLicense($LicObj.LicenseKey)
}else{
Write-Host " The license is assigned and cannot be removed"
}
}
In the new win8 there is a function to merge the snapshot taken on a VM without putting it into saved state/turn off. In the Windows 2008 and 2008 R2 there was a big no-no to taking snapshots on production machines, how about now in the new version? Well their replication function uses snapshots so it must be good enough. Then as always you should consider the consequences of taking snapshots and rolling back on different systems as the data in a database may be lost when jumping around.
The Cmdlets that are relevant for Snapshots :
Checkpoint-VM
Get-VMSnapshot
Remove-VMSnapshot
Export-VMSnapshot
Restore-VMSnapshot
Rename-VMSnapshot
If you search among the cmdlets the first CheckPoint-VM is not very easy to find, I am woundering why they(MS) has decided that name?! (I have before complained about checkpoint in SCVMM, maybe it is from there it has the roots)
Here is a PowerShell oneliner that makes 50 Snapshots on a VM (the limit of 50 snapshots is still valid as i tested to make 60 snapshots and got errors from 50+)
When I now have 50 snapshots I have to remove one before taking a new, the Remove-VMSnapshot has a parameter -IncludeAllChildSnapshots that is quite handy if you have like me 50 snapshots that you want to remove. I use the Select-Object -First 1 to get the first snapshot so i can remove all at once.
How about the cmdlet Export-VMSnapshot, it cannot be run when the VM is running, but it creates an exported VM that is from the snapshot. This can be very useful if you want to have a machine from a specific snapshot built.
How to go to a snapshot with Restore-VMSnapshot then, when I restore I have to confirm but not when deleting?
If you haven´t found the reference page on technet for WIN 8 Hyper-V powershell cmdlets it is here.
But I wanted a more sophistical approach where my function shutdown the VM properly and then change the controller and starts the VM, the tricky part here was to check that the VM actually had shutdown before I change controller 🙂
function Change-ScsiController{
<#
.SYNOPSIS
Stop a VM and replace the SCSI controller and start it again
.DESCRIPTION
Use this function to change scsi cntroller
.PARAMETER xyz
.NOTES
Author: Niklas Akerlund / RTS
Date: 2012-03-21
#>
param (
[Parameter(Position=0,Mandatory=$true,HelpMessage="A virtual machine",
ValueFromPipeline=$True)]
$VM
)
$VM = Get-VM $VM
Shutdown-VMGuest -VM $VM -Confirm:$false
while ($VM.PowerState -eq "PoweredOn")
{
$VM = Get-VM $VM
Start-Sleep -s 1
}
Get-ScsiController -VM $VM | where {$_.Type -eq "Paravirtual"} | Set-ScsiController -Type VirtualLsiLogicSAS
Start-VM -VM $VM
}
Today i had the pleasure to install and configure the Windows PowerShell Web Access in Windows 8. This gives you an opportunity to administer your internal servers with a Web Powershell Console. The really nice part here is that when I have enabled this I can connect to an Windows Server 2008 R2 with Powershell v2.
I have configured it with Authorization to everything, now this is a test environment but in your maybe you should be more restrictive,
So I can connect with for example a Ipad and administer my Hyper-V Cluster in SCVMM2012 😛
In this link you can see how to configure this on your Windows 8 Server Beta.
Here is the login prompt…
And here you can see how i run commands in the console, As you can see I must use Import-Module to import the VMM 2012 cmdlets before I can use them. This is a flash embedded video from youtube (where i uploaded it to) If you do not see it you can go to this link
I still have to find out why I cannot use the PowerCLI PSSnapin, I get an OutOfMemory exception when trying to connect-viserver 🙁 will have to dig a bit deeper to check that one out. Maybe there is a bug in the PSSnapin, an excellent time for VMware to make a Module instead!