Showing posts with label Windows 8. Show all posts
Showing posts with label Windows 8. Show all posts

Wednesday, September 4, 2013

PowerShell to disable IE Enhanced Security

So, my employer has a number of web consoles for various applications.

This is fine, except for pesky IE Enhanced Security.

So, to automatically disable this for members of the local Administrators group just comment out the User section from the script below.

Now, before you reply that I should be adding the URL to the exclusion list and all that.  This is so much simpler.  Why?  Because I don’t have to worry about a shortcut having localhost vs. the FQDN in it.

This one section of my script runs and Administrators are happy.  After all, these are servers.  And outside of hitting a local console once or twice or applying updates, they should not even be logged in locally, right(?)

# Disable IE Enhanced Security Configuration for Administrators and Users for web consoles
try {
$AdminKey = “HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A7-37EF-4b3f-8CFC-4F3A74704073}”
$UserKey = “HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A8-37EF-4b3f-8CFC-4F3A74704073}”
Set-ItemProperty -Path $AdminKey -Name “IsInstalled” -Value 0
Set-ItemProperty -Path $UserKey -Name “IsInstalled” -Value 0
Stop-Process -Name Explorer
“IE Enhanced Security Configuration (ESC) has been disabled on this machine.”
}
catch {"Failed to disable IE ESC" }

Tuesday, May 7, 2013

The IP the NIC on a particular domain or address space

I have this VM.  This VM has multiple interfaces.  One interface is _the_ management interface and it is the one that the VM used when it joined my domain.

I want to discover this NIC.  I then want its IP address so I can embed that into a configuration file.

The initial list of questions that I began with were:

  • Am I domain joined?  If so, what domain?
  • What network connection reports that domain?
  • What NIC is that?
  • What is the IPv4 address on that NIC?

I have discovered that there are multiple ways to handle this.

First of all, asking the questions; Am I joined and what domain am I joined to.

$env:USERDNSDOMAIN or Get-WmiObject -Class Win32_ComputerSystem | select domain

Both give you results, but different objects back.

BRIANEH.LOCAL (a string) vs.

domain                (a portion of a WMI object)                                                                                                
------

brianeh.local

Now, lets look at the question of what NIC is on what domain or connected to any domain.  If you only have one NIC connected to any domain (or that can resolve any domain) you can probably simplify this to:

Get-NetConnectionProfile | where {$_.NetworkCategory -eq "DomainAuthenticated" }

The alternate to that is to be more verbose (or precise if you like).

Get-NetConnectionProfile | where { $_.Name -eq $env:USERDNSDOMAIN }

What you get back is a Connection Profile object.  And to some this looks familiar, you know that status that you see on the network icon in your system tray?  The one that says if you have internet connectivity, or what DNS domain is discovered?  This is the information behind that.

I have two and they look like this:

Name             : Unidentified network
InterfaceAlias   : Ethernet 2
InterfaceIndex   : 13
NetworkCategory  : Public
IPv4Connectivity : LocalNetwork
IPv6Connectivity : LocalNetwork

Name             : brianeh.local
InterfaceAlias   : Ethernet
InterfaceIndex   : 12
NetworkCategory  : DomainAuthenticated
IPv4Connectivity : Internet
IPv6Connectivity : LocalNetwork

In the example I went straight to the selection of the desired one.

Now, how do I get to the IP you might wonder.  One more step.

Get-NetIPAddress -InterfaceIndex $netProfile.InterfaceIndex -AddressFamily IPv4

Again, I went straight to the IPv4 filter.  I used the Network Profile object captured as $netProfile and its InterfaceIndex property.  But, as you play with the Network IP Address object you will see that it can be selected multiple ways.

And if you only want the IP address itself, take that Network IP Address object and select only the IPv4Address property.

$netIpAddress.IPv4Address

And there you have it.  Now, off to building my configuration file…

Tuesday, March 26, 2013

Converting VHDX VHD and back without Hyper-V

So.  I am really rehashing another script that I already did a few posts ago.

If you look back here: http://itproctology.blogspot.com/2013/01/powershell-for-reducing-size-of-vhd.html

If you being with a virtual disk that is a VHD.

And you alter this one line:

$newVhdPath = $orgvhd.ImagePath.Split(".")[0] + $partNum +"New." + "vhdx"

You end up with a VHDX instead of a VHD.  Go backward, flip it around. 

Server 2012 / Windows 8 have some built in assumptions based on the extension. You get the VHD format that the extension defines. That is why you just cannot modify the file extension.

 

What got me started on this?  Well, my original post was because I was annoyed with certain cmdlets being only bound to the existence of the Hyper-V virtual machine management service (having Hyper-V installed).  Since the OS storage layer knows about these virtual disks, why can’t I natively manipulate them?

And then this post came through the Hyper-V forums: http://social.technet.microsoft.com/Forums/en-US/winserverhyperv/thread/51984c52-cc69-459f-8999-6ca186d48931

Again, folks with my same original complaint.  It requires Hyper-V.  Ugh.

 

So. Let’s make this script a one trick pony.  And ONLY let it convert virtual disk formats.

Now, that said.  This is a hack folks.  I did it because I can, and the tools are built in to the OS.  DISM does not convert disks or volumes, it converts partitions.  So you get one virtual disk per partition. (Frankly, who partitions disks anymore anyway?)

 

# Server 2012 / Windows 8 VHD / VHDX converter.  Using DISM.
# Prototyped on Server 2012 not running Hyper-V
# This utilizes PowerShell v3 and cmdlets from Server 2012 / Windows 8 - it will not run on any older OS.
# Copy write – Brian Ehlert

# Ask the path of the VHD and test it
Do {
    $imagePath = Read-Host "Please enter the full path to your VHD.  i.e. D:\VMs\MyVhd.vhd "
} until ((Test-Path -Path $imagePath ) -eq $true)  # Mount the VHD that will be getting resized

$orgVhd = Mount-DiskImage -ImagePath $imagePath -PassThru
$orgVhd = Get-DiskImage -ImagePath $orgVhd.ImagePath  # Get the partitions
$orgParts = Get-Partition -DiskNumber $orgVhd.Number  # Use DISM command line to capture the VHD one WIM file. Each partition with a different name.
$wimName = ($orgvhd.ImagePath.Split(".")[0] + ".wim") 
foreach ($part in $orgParts) {
    if ($part.Size -gt 524288000){ # skip the partition if it is less than 500MB, most likely there is no OS or it is the System Reserved partition.
        $capDir = $part.DriveLetter + ":\"
        $partNum = $part.PartitionNumber
        "Be patient, this could take a long time"
        & dism /capture-image /ImageFile:$wimName /CaptureDir:$capDir /Name:$partNum
    }
}
# dismount the VHD that was just captured
Dismount-DiskImage -ImagePath $orgvhd.ImagePath

# Change the extension
Switch ($orgvhd.ImagePath.Split(".")[1]){
    vhd {$diskFormat = "vhdx"}
    vhdx {$diskFormat = "vhd"}
}

foreach ($part in $orgParts)
    {
    if ($part.Size -gt 367001600){ # skip the partition if it is less than 350MB.
        $capDir = $part.DriveLetter + ":\"
        $partNum = $part.PartitionNumber
        $newVhdPath = $orgvhd.ImagePath.Split(".")[0] + $partNum + "." + $diskFormat           
        $newSize = (([uint64]$orgVhd.Size) /1024 /1024)
        $diskPart = @"
        create vdisk file="$newVhdPath" type=expandable maximum=$newSize
        select vdisk file="$newVhdPath"
        attach vdisk
        create partition primary
        active
        format fs=ntfs quick
        assign
"@
        $diskPart | diskpart
        $newVhd = Get-DiskImage -ImagePath $newvhdPath
        $newVhdDrive = (Get-Partition -DiskNumber $newVhd.Number)
        $newVhdLetter = (Get-Partition -DiskNumber $newVhd.Number).DriveLetter + ":"         
        "Be patient, this could take a long time"
        & dism /apply-image /ImageFile:$wimName /ApplyDir:$newVhdLetter /Name:$partNum
        New-PSDrive -PSProvider FileSystem -Name $newVhdDrive.DriveLetter -root ($newVhdDrive.DriveLetter + ":\") # Make the new volume known to your PowerShell session
        # if \Windows then assume a boot volume and create the BCD
        if ((Test-Path -Path ($newVhdLetter + "\Windows") -PathType Container) -eq $true)
        {
            bcdboot $newVhdLetter\Windows /s $newVhdLetter
        }
         Remove-PSDrive -PSProvider FileSystem -Name $newVhdDrive.DriveLetter
        Start-Sleep 10  # Settling time
        Dismount-DiskImage -ImagePath $newVhdPath
    }
}

Friday, January 25, 2013

PowerShell for reducing the size of a VHD

Recently I have gotten myself into a situation where a VHD that I created was too large for a situation.  And as many of us know, there are tools to make VHDs smaller, only larger. 
In my case, this was an important VM to the testing that I was doing, I had absolutely no desire to build a new one.  I just wanted my VHD to be smaller so I could use it for the test I intended.
Now, since the VHD has been around we have been telling folks in the forums that there is no programmatic way to reduce the size of a VHD.  There have been lots of opinions about this, but it isn’t just a case or truncating a binary file.

The problem becomes difficult because you have no idea how the OS in that VHD has laid data down into that VHD.  Are there files way out at the far end, which would be corrupted if you simply chopped it off?  Does your program have the right to go looking and figure that out and expose my data?  If there is data out there, what should be done with it to make sure the OS that sues the VHD can actually find it – it is not as easy as moving that file, it could be a system file.  And there is always the disk layout that must be honored, sectors, blocks, etc are part of how that VHD is made.
So, what have we been telling folks that get into this situation – use disk imaging software to create an image and then apply that to a new VHD of the proper size.

I decided – lets script that.   This way I can answer a couple questions and pay attention to other things.

I use diskpart and DISM.  DISM is built in to Windows 8 / Server 2012.  And so is DiskPart.  Without the full Hyper-V Role there is no way to create a VHD using PowerShell.  Go figure.

* Disclaimer – I have only tried this with VMs that contain Server 2008 or newer.  Older than that will not have a BCD, but the script will make one.

Here is my entire script, hopefully you can follow my comments.

# Server 2012 / Windows 8 VHD resizer.  Using DISM.
# Prototyped on Server 2012 not running Hyper-V
# This utilizes PowerShell v3 and cmdlets from Server 2012 / Windows 8 - it will not run on any older OS.
# Copy write – Brian Ehlert

# Ask the path of the VHD and test it
Do {
    $imagePath = Read-Host "Please enter the full path to you VHD.  i.e. D:\VMs\MyTooBigVhd.vhd "
} until ((Test-Path -Path $imagePath ) -eq $true)  # Mount the VHD that will be getting resized

$orgVhd = Mount-DiskImage -ImagePath $imagePath -PassThru
$orgVhd = Get-DiskImage -ImagePath $orgVhd.ImagePath  # Get the partitions
$orgParts = Get-Partition -DiskNumber $orgVhd.Number  # Use DISM command line to capture the VHD one WIM file. Each partition with a different name.
$wimName = ($orgvhd.ImagePath.Split(".")[0] + ".wim") 
foreach ($part in $orgParts) {
    if ($part.Size -gt 524288000){ # skip the partition if it is less than 500MB, most likely there is no OS or it is the System Reserved partition.
        $capDir = $part.DriveLetter + ":\"
        $partNum = $part.PartitionNumber
        "Be patient, this could take a long time"
        & dism /capture-image /ImageFile:$wimName /CaptureDir:$capDir /Name:$partNum
    }
}
# dismount the VHD that was just captured
Dismount-DiskImage -ImagePath $orgvhd.ImagePath
# Get the size of the WIM. As the new VHD must be larger.
$wimFile = Get-ItemProperty $wimName
# Ask the size of the new VHD in GB
Do {
$newSize = [uint32](Read-Host "How large would you like the new VHD (in whole GB)?  The WIM is" ([uint32]($wimFile.Length /1024 /1024 /1024))"GB of data ")
} until ($newSize -gt ([uint32]($wimFile.Length /1024 /1024 /1024)))
$newSize = [uint64]$newSize * 1024  # convert GB to MB 
foreach ($part in $orgParts)
    {
    if ($part.Size -gt 524288000){ # skip the partition if it is less than 500MB.
        $capDir = $part.DriveLetter + ":\"
        $partNum = $part.PartitionNumber
        $newVhdPath = $orgvhd.ImagePath.Split(".")[0] + $partNum +"New." + $orgvhd.ImagePath.Split(".")[1]         
        $diskPart = @"
        create vdisk file="$newVhdPath" type=expandable maximum=$newSize
        select vdisk file="$newVhdPath"
        attach vdisk
        create partition primary
        active
        format fs=ntfs quick
        assign
"@
        $diskPart | diskpart
        $newVhd = Get-DiskImage -ImagePath $newvhdPath
        $newVhdDrive = (Get-Partition -DiskNumber $newVhd.Number)
        $newVhdLetter = (Get-Partition -DiskNumber $newVhd.Number).DriveLetter + ":"         
       
        "Be patient, this could take a long time"
       
        & dism /apply-image /ImageFile:$wimName /ApplyDir:$newVhdLetter /Name:$partNum
       
        New-PSDrive -PSProvider FileSystem -Name $newVhdDrive.DriveLetter -root ($newVhdDrive.DriveLetter + ":\") # Make the new volume known to your PowerShell session
       
        # if \Windows then assume a boot volume and create the BCD
        if ((Test-Path -Path ($newVhdLetter + "\Windows") -PathType Container) -eq $true)
        {
            bcdboot $newVhdLetter\Windows /s $newVhdLetter
        }
        Remove-PSDrive -PSProvider FileSystem -Name $newVhdDrive.DriveLetter
       
        Start-Sleep 10  # Settling time
        Dismount-DiskImage -ImagePath $newVhdPath
    }
}
 


Thursday, December 20, 2012

Hyper-V Resource Pool Introduction

There is a feature of Hyper-V 2012 that is rarely discussed but is highly useful.

First, the Resource Pool concept; 

For this I pulled a definition from the Office documentation; “A set of resources that is available for assignment”  that is the best way that I can describe it.

Second, this is not VMware style resource pools.  Their implementation is very unique.  It is closer to the XenServer implementation of resource pools.  However, it does not follow that either.

If you head over to the DMTF and search on Resource Pool you find something nice and vague about Resource Pool Hierarchies.  Okay, we will see that in the implementation.

So, before I move on, those of you with VMware backgrounds, just forget using resource pools to manage reservations and what not.  It might eventually get there, but not today.

As I mentioned in the Office quote, the Resource Pools represent assignment.  A connection.  A relationship (DMTF). 

If you want to see an easy example of the Resource Pools in action (and in the GUI), you need to create one.

The example

Lets look at Networking.  Connecting VMs, enabling VMs for all kinds of migrations, and inconsistent configurations.

I have two Hyper-V Servers.  They were set up by different folks, with different naming preferences.  Joe names his virtual network “VMs” and Gale names hers “LAN”.  Each time they move a VM back and forth they need to reconfigure the network settings of the VM. 

There has to be a way to do that without renaming their virtual switches.  There is.  Create an “Ethernet” Resource Pool.

Okay, now some PowerShell and some details

PS C:\Users\Administrator> get-command *resourcepool*

CommandType     Name                                               ModuleName
-----------     ----                                               ----------
Cmdlet          Get-VMResourcePool                                 Hyper-V
Cmdlet          Measure-VMResourcePool                             Hyper-V
Cmdlet          New-VMResourcePool                                 Hyper-V
Cmdlet          Remove-VMResourcePool                              Hyper-V
Cmdlet          Rename-VMResourcePool                              Hyper-V
Cmdlet          Set-VMResourcePool                                 Hyper-V

If you have done nothing with Resource Pools on a Hyper-V Server and you simply type Get-VMResourcePool you actually get a bunch back.

PS C:\Users\Administrator> Get-VMResourcePool

Name       ResourcePoolType       ParentName ResourceMeteringEnabled
----       ----------------       ---------- -----------------------
Primordial FibreChannelConnection            False
Primordial FibreChannelPort                  False
Primordial ISO                               False
Primordial VFD                               False
Primordial VHD                               False
Primordial Ethernet                          False
Primordial Memory                            False
Primordial Processor                         False

These are the Primordial Resource Pools.  Hyper-V gives these to you because you can only add children, the Server must provide the first Parent.  In this case they called it Primordial.  Sounds all medieval doesn’t it?  It simply means there is nothing before, it is definitely the Root, not some Pool that someone called “root”.

So, lets make a new Resource Pool and attach it to the Ethernet Primordial Pool.

PS C:\Users\Administrator> New-VMResourcePool -Name "VM LAN" -ResourcePoolType Ethernet

Name   ResourcePoolType ParentName   ResourceMeteringEnabled
----   ---------------- ----------   -----------------------
VM LAN Ethernet         {Primordial} False

Notice how the Primordial pool was assumed in this case?  Handy.

Now, I could have explicitly defined –ParentName and I probably would have if I had multiples.  Because I could branch Resource Pools if I wanted to. 

If I branch Resource Pools I can use them to create logical groupings for metering or connecting devices.  And each one would have different options because it is at a different level and combination of parents.

This familial stuff can get pretty messy so I will keep this example simple.

Now that I have my Resource Pool.  How do I use it?

Well, now that I created a Resource Pool. If I open the settings of the Network Adapter for any VM on that Hyper-V Server I see something totally new.

image

And if I drop the selection list I can connect to the Primordial ( “<Root>” ) or the Resource Pool I just created.

If I select the Pool I just created the Virtual Switch setting is changed.

image

Because I didn't associate a Virtual Switch with my new Resource Pool.  This command is not totally intuitive, I expect to use Set-VMSwitch to modify the setting, however, the clever PM behind the Hyper-V cmdlets decided to use a different verb.

PS C:\Users\Administrator> Add-VMSwitch -ResourcePoolName "VM LAN" -Name VMs

Now, If I open the settings of the VM again.  It makes sense to select “automatic connection” for the switch.  This way the Pool is connected to, not the switch.

image

I can actually name the switch in some way unique to the server or hardware, and have the consistent naming abstracted above that.  So, whatever switch is associated with this Pool, the VM will be connected to it.

What else can I do with that Resource Pool?

Well, I can Measure it of course.

First, enable Metering then measure it.

PS C:\Users\Administrator> Enable-VMResourceMetering -ResourcePoolType Ethernet -Name "VM LAN"
PS C:\Users\Administrator> Measure-VMResourcePool -ResourcePoolType Ethernet -Name "VM LAN"

Name   ResourcePoolType AvgCPU(MHz) AvgRAM(M) TotalDisk(M) NetworkInbound(M) NetworkOutbound(M)
----   ---------------- ----------- --------- ------------ ----------------- ------------------
VM LAN {Ethernet}                                          0                 0

Hmm, seems that no time passed, so there is no data.  Waiting a bit, lets Measure again.

PS C:\Users\Administrator> Measure-VMResourcePool -ResourcePoolType Ethernet -Name "VM LAN"

Name   ResourcePoolType AvgCPU(MHz) AvgRAM(M) TotalDisk(M) NetworkInbound(M) NetworkOutbound(M)
----   ---------------- ----------- --------- ------------ ----------------- ------------------
VM LAN {Ethernet}                                          2                 1

Hey, some network traffic.  Excellent.

This is just an introduction to Resource Pools.  I hope to bring some more in the future as they are highly useful, yet relatively invisible.

Thursday, December 6, 2012

Setting VM IP with Hyper-V WMI

There is a hidden feature in Server 2012.  Buried deep in the bowels of the WMI classes is this little tidbit that is discoverable, but not talked about.

You can set the IP of a VM through Hyper-V 2012. 

For a long time now, in the forums we have told folks that this cannot be done.  Well, it can be.  And at small scale it works.  I have used it to set up my Network Virtualization demonstration environment.

The thing that you need to be aware of is that this is one of those cases where you send your command to WMI / CIM and you need to double back and check what happened.  Did the IP actually set? 

Be sure to check that before going off and expecting that it did.  If it didn’t, you have event logs in the VM.  Check there.

This took a bit of working through and discovery.  I never did work through IPv6, I stopped when I got IPv4 working.

<speculation>

As you might imagine, there has to be a dependency on the aligning of the version of the Integration Services within the VM and the Hyper-V Server.  I could not imagine this working with Hyper-V 2012 and a Server 2008 VM when the Integration Components in the VM have not been updated to the current Hyper-V level.

</speculation>

One thing that I did not blog about with the Network Virtualization script was how I set up my environment, more on that next, I scripted it, and it is not small.

Back the the subject, setting the IP of a VM through WMI of the Hyper-V Server.  I am going to leave out all the error handling just to make this easier to read through.

Here is a PowerShell function where you can see the WMI in action:

function Set-VMIPAddress ($VMName, $IPSettings)

{

    $Service = Get-WmiObject -Class "Msvm_VirtualSystemManagementService" -Namespace "root\virtualization\v2"

    $Query = "SELECT * FROM Msvm_ComputerSystem WHERE ElementName = '" + $VMName + "'"

    $VM = Get-WmiObject -Query $Query -Namespace "root\virtualization\v2"

    $setIP = $Service.SetGuestNetworkAdapterConfiguration($VM, $IPSettings.GetText(1))

}

Of course, you want to consider $setIP.ReturnValue

Like all WMI / CIM commands if the return value is “0” then you have success, “4096” generally means it is running.  And anything else means something went wrong in most cases.

If you have “4096” then query for the status of the job itself.  $job = [WMI]$setIP.job

By the way, if you want to get the IP of the VM don’t think $Service.GetGuestNetworkAdapterConfiguration.  This is proper thinking for PowerShell but not for WMI / CIM.  CIM could never be that easy.  ;-)

Look for the class Msvm_GuestNetworkAdapterConfiguration to get the IP of a VM.  Find the VM NIC with Msvm_SyntheticEthernetPortSettingData first.

Tuesday, September 18, 2012

PowerShell v3 everywhere

If you have not caught wind of this yet, you can download and install the “Windows Management Framework 3.0” on your boxes that are not Server 2012 or Windows 8.

As in the past this is more than just PowerShell, it includes WMI and WinRM compatibility updates.  (just not a big BITS update like v2 did).

You can find it here: http://www.microsoft.com/en-us/download/details.aspx?id=34595

This is for Windows 7 SP1 and Server 2008 SP2 or Server 2008 R2 SP1.

And, don’t forget Update-Help after you install it.

But you might as well be on your way to managing your Server 2012 / Windows 8 infrastructure the PowerShell way.

If you need .Net 4 you can find that for Server over here: http://www.microsoft.com/en-us/download/details.aspx?id=17718

And for Server Core here: http://www.microsoft.com/en-us/download/details.aspx?id=22833

If you run an OS that is older.  I am sorry, MSFT does not look back.  You can be one version old, but XP / 2003 is way out.  Winking smile

Wednesday, June 20, 2012

Server 2012 Install-WindowsFeature Net-Framework-Features fail. Use the source, Luke

Let go.

The force is strong on this one.

Trust your feelings.

I don’t know if you have noticed or not.  But if you attempt to install the .Net 3.5 on Server 2012 it always fails.

This seems to have been particularly troublesome to application installers that ‘just expect it to work’ and fail instead.    Then you end up here, desperately trying to figure out how to install .Net 3.5.

If you wan to see the error that these installers are tossing; simply open a PowerShell windows and attempt to install .Net 3.5 using install- (or add- ) Windows Feature:

image

A nice big fat failure.  But you think, this always worked before.  Server 2008 / R2 / SP1 this worked without a hitch or problem.  It was built-in. What gives?

The issue is in the detail of that error:  Use the “source” option to specify the location of the files…

Well, seems that the files are not there, at least for .Net 3.5 they are not installed to the local WinSxS source location when the OS is installed.  (Ever wondered how you can add features after install?  ‘Sources’)

Looking around a bit, you will eventually find it.  On the installation CD / ISO.  So that becomes your source path.  Insert the DVD or mount the ISO to your VM and use the following:

Add-WindowsFeature –name NET-Framework-Features –source D:\sources\sxs

The “D:” in my case is the drive letter of the CD drive of my VM.

image

Tuesday, May 29, 2012

Creating Server 2012 LBFO Teams grouping by default gateway

Here is where I take my two previous posts and splice them together into something useful.

The previous posts contain the details of picking through the various portions of the script, here I just toss it together with some useful loops and work through the Groups that I created.

Once again, this is all PowerShell v3 and Server 2012. 

Recall that my scenario is:

Someone racked this server, they jacked it to the management network, the VM production network, and the storage network. I want to know what NICs are jacked where and group and summarize them.  And each of these networks has DHCP running as I have no time to manually assign IP addresses any longer. They are divided physically in the top of the rack with three switches.

The meat of the script is:

$ips = Get-NetAdapter -Physical | where {$_.Status -eq "Up"} | Get-NetIPConfiguration | Group-Object -property IPv4DefaultGateway


foreach ($group in $ips) {
    # test for no gateway we expect DHCP to give one, if there isn’t one then this really isn’t useful is it?


    If ([string]$group.Values.nexthop -ne "0.0.0.0") {

        $nicList = @()
        foreach ($nic in $group.Group) {
            $nicList += $nic.InterfaceAlias
        }

        $name = [string]$group.Values.nexthop

        $team = New-NetLbfoTeam -Name $name -TeamNicName ($name + "Team") -TeamMembers ($nicList) -TeamingMode SwitchIndependent -LoadBalancingAlgorithm HyperVPort -Confirm:$false 
            
        Clear-Variable -Name nicList

        Do {$team = Get-NetLbfoTeam -Name $team.Name
            sleep 2}
        until ($team.Status -eq "Up")

        Get-NetIPAddress -InterfaceAlias $team.TeamNics | select IPAddress

    }
}

The default LoadBalancingAlgorithm is TransportPorts and works in most general cases. 
If the team is specific to supporting VMs and it has an External Virtual Switch attached then HyperVPort should be used.

Friday, May 25, 2012

Creating an LBFO Team with PowerShell

Moving right along this PowerShell theme I have been working a bit is writing a script that would build me an LBFO team.

For those of you that have not heard of an LBFO team – lets just say that you will love it.  In-the-box NIC teaming.

Yes!  Windows Server 2012 has in-box NIC teaming.  The term is LBFO – Load Balancing FailOver.  You will need that to find the cmdlets.

You can create an LBFO team using Server Manager – it is quick, painless, works well.

With PowerShell I will simply guide you past the problem that I kept tripping over.  And that is sending your list of NIC aliases in as an array of strings.

Back to what I am doing.  I got all fancy with my one liner for selecting my NICs.

That is another post.

But, now that I have that list of NICs – it is the interface alias that is the important part.  That is what the New-NetLBFOTeam cmdlet wants.

Once you have that, it is really simple.

$team = New-NetLbfoTeam -Name $name -TeamNicName ($name ) -TeamMembers ($nicList) -TeamingMode SwitchIndependent -LoadBalancingAlgorithm HyperVPort -Confirm:$false

On a side note: the default LoadBalancingAlgorithm is TransportPorts and works in most general cases.  If the team is specific to supporting VMs and it has an External Virtual Switch attached then HyperVPort should be used.

This has been discussed in the //BUILD/ presentations that are so frequently referenced.

Now, if you have gotten used to Hyper-V VM objects you know that those are ‘live’ – this is not the case with the networking objects.

So, if you want your script to wait until the team is ‘up’ you need a bit of a loop.  I did it this way, a simple Do Until testing for the status to change to Up.

Do {$team = Get-NetLbfoTeam -Name $team.Name
    sleep 2}
until ($team.Status -eq "Up")

Notice that I need to keep querying the team. 

You will recall that Hyper-V PowerShell objects are ‘live’ – that is; you grab a VM object, change it, and the object that you already had is updated.  Not the case here, this is much more like CIM / WMI – where you have to do something then check on it.

Monday, May 21, 2012

Finding and sorting Server 2012 NICs with PowerShell

If you are using Server 2008 (any release) you should just go on now, this is about PowerShell v3 in Server 2012.

You can stay to see how easy this is becoming though.

So, I came up with this one liner – I am pretty proud of it, I am not a developer and not a big fan of one-liners as they are difficult to pass to other folks for them to understand, but this works.

$ips = Get-NetAdapter -Physical | where {$_.Status -eq "Up"} | Get-NetIPConfiguration | Group-Object -property IPv4DefaultGateway

Now, what does this give me?

This gives me an array (a couple levels deep due to the Group (which I had never used before).

I end up with an array of Groups.  Each Group is named with the IPv4 Default Gateway of the NICs.

Within the group is a list of NICs that all have that IPv4 default gateway in common.

The one liner first Gets the Network Adapter object for only the Physical NICs that are jacked ( ‘up’ ).

Get-NetAdapter -Physical | where {$_.Status -eq "Up"}

The NICs that meet that criteria – I then get the NetIPConfiguration of (as this is where the Gateway property is hiding).  And I group them based on the IPvDefaultGateway. 

Get-NetIPConfiguration | Group-Object -property IPv4DefaultGateway

My assumption here is that if the NIC is ‘up’ it has a DHCP address.

This is all fine and good you think, but how is this real?  What is the scenario? 

Someone racked this server, they jacked it to the management network, the VM production network, and the storage network.  I want to know what NICs are jacked where and group and summarize them.  And each of these networks has DHCP running as I have no time to manually assign IP addresses any longer.  They are divided physically in the top of the rack with three switches.  (two posts into the future will use this).

Wednesday, April 25, 2012

Setting custom DNS settings with PowerShell in Server 2012

Okay, the time has come, I can finally say; “Server 2012”
I frequently use custom DNS settings in my lab environments to override the provided DHCP settings and use my own personal domain controllers.
For Server 2008 I used the following commands:
netsh interface ipv4 add dnsserver "local area connection" x.x.x.x 1
netsh interface ipv4 add dnsserver "local area connection" x.x.x.x 2
For the Windows 8 Preview I simply adapted this:
netsh interface ipv4 add dnsserver "Wired Ethernet Connection" x.x.x.x 1
netsh interface ipv4 add dnsserver "Wired Ethernet Connection" x.x.x.x 2
*Note the change to the interface name
Being an embracer of PowerShell and all the 2000+ new cmdlets in Windows Server I decided to figure out how to do this the PowerShell way.
Well, I have to say it took a while just to find the right cmdlets because I began at IPAddress or IPAdapter.  Not thinking that there would be a DnsClientServerAddress.
Get-DnsClientServerAddress
Now, to set, just turn this around to the Set-
Set-DnsClientServerAddress -InterfaceAlias vEthernet* -ServerAddresses "x.x.x.x","x.x.x.x"
Note how I feed in the multiple addresses, as list of individual comma separated strings.

Then, there is the one-liner (I discuss finding the proper NetAdapter is other posts).

Get-NetAdapter | Set-DnsClientServerAddress -ServerAddresses "x.x.x.x","x.x.x.x"

Monday, April 16, 2012

Windows 8 in a VM on 2008 R2 Hyper-V

Update:  As of October 9, 2012, the update has been superseded by 2744129. Go to http://support.microsoft.com/kb/2744129 to find that update, where it states the supersedence in the documentation.

This is an interesting patch that someone recently pointed me to:  http://support.microsoft.com/kb/2526776
Apply this patch to your Server 2008 R2 Hyper-V Server so that you can install Windows 8 in a VM.
If you do not apply this patch and you attempt to run Windows 8 within a VM: note the symptoms in the KB article:
  • The Windows Developer Preview or Windows Server Developer Preview virtual machine stops responding.
  • The Windows Server 2008 R2 host computer displays a stop error message and restarts automatically. This behavior brings down all other running virtual machines together with the host computer.
That does not sound good.
So, if you have a Hyper-V server that suddenly crashes and reboots, and you know that someone has downloaded the Windows 8 beta and might be installing it into a VM…  Well, you suddenly have an idea what might be going on.

Thursday, March 29, 2012

Windows 8 Hyper-V objects are aLive

For those folks new to PowerShell you need to wrap your brain around the object concept.  It is fundamental to understanding (grok-ing actually) tons of stuff.

In the Hyper-V cmdlet set in Windows 8 if you ‘get’ a VM object  (  $vm = Get-VM –Name Foo) you can simply type of object out and see its properties ( $vm ).

PS C:\Users\Administrator> $vm

Name                    State CPUUsage(%) MemoryAssigned(M)

----                    ----- ----------- -----------------
BrianEhDC.BrianEh.local Off   0           0

  

Now, lets say that Admin Joe or XenDesktop brokering  just turned on that VM that you have captured as your object.  Type its properties again.

PS C:\Users\Administrator> $vm

Name                    State   CPUUsage(%) MemoryAssigned(M)
----                    -----   ----------- -----------------
BrianEhDC.BrianEh.local Running 4           512

Notice that it is now running.  And you didn’t have to re-query to get that.

As stated by the Feature lead for the Hyper-V cmdlets:  “You get it for free” – In other words you didn’t have to do extra work to see that a property changed.  You did not have to do Get-VM again.

Cool!

Friday, March 23, 2012

Server 2012 on the Acer PDC Laptop with Hyper-V

This is all about getting Hyper-V working on a laptop when SLAT is not available on your hardware.  Because not all of us can afford a new shiny laptop to support Client Hyper-V.

Now, here is the big warning;

This is Server, not Client – In the end, the experience is nearly identical.

This is a computer with Hyper-V running (it has –V or –VT on the chipset).  It works, but if you want the fancy Windows 8 Client experience, you will not get it here.

There is also an order to adding the Roles and Features.  This is not rocket science, just proper ordering.

Now, I did add an SSD to my PDC laptop and I am incredibly happy I did.

  1. Install Windows Server 8
  2. Get the needed drivers from the Acer website (the display will be horrible, the disk will be slow) - http://support.acer.com/drivers_download.aspx
    1. Intel Chipset driver
    2. Intel VGA driver (this is the only driver that is necessary)
    3. and you might need the wireless LAN driver (the wired NIC is definitely in the installer)
    4. I also grabbed the audio driver
  3. Get that all working and patch the machine.
  4. Add the following Features:
    1. Wireless LAN Service
    2. Media Foundation
    3. User Interfaces and Infrastructure
      1. Desktop Experience
    4. reboot
  5. Now you can add the Hyper-V Role
  6. If you need sound, be sure to enable the Windows Audio service (set it to automatic and start it if you need it right away)

Now you have your PDC Laptop – still useful – running Server 8 Hyper-V.

You can fully play with all the new PowerShell commands.  (well, isn’t that why you would want to do this!)

If you want the Marketplace, then you need to create a user account as you cannot use the built-in local administrator to access the marketplace.  Otherwise, it is all there – touchscreen, Metro experience, etc..

Monday, March 19, 2012

Handy PowerShell tasks for Hyper-V in Windows 8

Okay, so you have committed yourself to learning how to use PowerShell and you have the Windows 8 Server Beta.

You don’t want to write all kinds of fancy scripts, you just want to do the same tasks that you did in the GUI.  And for increased pain (forced learning) you even installed Server Core or Hyper-V Server.

Here are a few of those good old one-off type of actions that we have grown used to, but using PowerShell to drive them.

This should introduce you to doing tasks using PowerShell as well as getting started with the Hyper-V cmdlets.

Create a new VM:

New-VM or

New-VM –Name “DemoVM” or

New-VM -Name "DemoVM" -MemoryStartupBytes 2gb -bootdevice HardDrive -SwitchName Lab -path C:\users\public\documents -NewVHDSizeBytes 36gb –NewVHDPath C:\users\public\documents\DemoVM

Insert an ISO into the virtual DVD drive:

Set-VMDvdDrive –VMName DemoVM -Path C:\users\public\Documents\DemoOSInstaller.iso

Boot the VM:

Start-VM –Name DemoVM

Launch a VMConnect VM Console (after all you have a clean OS to install and all you have is the beta ISO):

vmconnect localhost DemoVM

Eject the DVD from the virtual DVD drive:

Set-VMDvdDrive –VMName DemoVM -Path $NULL

Friday, March 16, 2012

Linking a VM and a Virtual Switch with PowerShell and Windows 8

So far I have discovered a physical NIC of my Hyper-V Server and created an External Virtual Switch (Have I ever mentioned how happy I am that MSFT calls them Virtual Switches now!?)

I have not blogged about creating a New-VM – frankly it is super simple.  Just type New-VM with no parameters and you have a VM.

If you do this you have a New Virtual Machine and all Hyper-V VMs have a Network Adapter by default. 

This kind of dictates the Verb that we use.  Since there is one we won’t Add, we need to change properties.  So we Get and then Set.  Or if you are feeling brash just Set.

The traditional way (the way I learned in .Net programming class) to make a change without causing extra harm is to Get, change your setting, and Set. 

Wait, hold the phone.  That does not apply here.  There is a Verb we don’t see much.  Connect.

Using Get-VMNetworkAdapter -VMName New* I get the vNIC of the VM.  And I need to capture that to an object.

$vmNic = Get-VMNetworkAdapter -VMName New*

In my last article I created a VMSwitch named “VMs”.  This is what I need to attach the VM to.  I cannot just modify the $vmNic.SwitchName, this is a ReadOnly property.

Connect-VMNetworkAdapter -VMNetworkAdapter $vmNic -SwitchName VMs

And, it is pretty flexible.  I fed in the VM vNIC object using –VMNetworkAdapter.  But I could also have used the –VMName (if it only has one vNIC) or pass in the VMSwitch object using –VMSwitch instead of –SwitchName

Also, New-VM also allows you to define a -SwitchName at creation time.  But that is not as universally applicable.

Thursday, March 15, 2012

Creating an External Virtual Switch in PowerShell and Windows 8

In a previous post I spent a lot of time trying to discover my physical NIC.

That was all leading up to this post.

Now, we need the Hyper-V cmdlets at the front:  Get-Command –Module Hyper-V and I want to create a new VM Switch so the cmdlet is New-VMSwitch.

New-VMSwitch needs a couple very basic pieces of information.  All of which we have seen in the GUI (Name, allow management OS, NetAdapterName, SwitchType, etc.

I need an Interface Name or Interface Description.  This is fine If I know what those are.  I can get that from Get-NetAdapter.

But, in my previous post I wanted to select the IP subnet that the NIC is attached to.

If I use this: Get-NetIPAddress –IPv4Address 10* | Get-NetIPInterface to return the NetIPInterface object to me based on a selection of the IPAddress starting with 192

I can used the returned NetIPInterface to then feed in to the Interface name or description of the New-VMSwitch cmdlet.

$if = Get-NetIPAddress –IPv4Address 192* | Get-NetIPInterface

The property ifAlias is the same as the NetAdapterName that New-VMSwitch is looking for.

New-VMSwitch –NetAdapterName $if.ifAlias -Name VMs

If you want to enable SR-IOV then you add the true at the end – you can only do this when you create a switch.

New-VMSwitch -NetAdapterName $if.ifAlias -Name VMs -EnableIov $true

Now, be aware of something.  The default behavior is to allow the Management OS to share this switch, so if you don’t want that to happen you have to be explicit about it.

New-VMSwitch -NetAdapterName $if.ifAlias -Name VMs –AllowManagementOS $false

Wednesday, March 14, 2012

Finding a physical network adapter with PowerShell in Windows 8

Get-NetAdapter

Okay, done.  That was a bit lackluster, wasn’t it?

First of all, try this:  Get-Command –Module NetAdapter
Okay, lots of cmdlets.  Recall all those intricate levels to netsh?  It is all here:  Get-Command –Noun Net*  but I only want to look at the physical NIC of the operating system.

Lets examine a Network Adapter object to determine what we can select on.

$nic = Get-NetworkAdapter (I am assuming that you only have one, if you have more than one $nic becomes an array and that changes inspection a bit)

If I type $nic I get (Name, InterfaceDescription, ifIndex, MacAddress, LinkSpeed):


Okay, but there are more properties.  Try this: $nic | Format-List


Okay, a bit more.  But there are actually more properties than that.  You will see this if you type $nic. and then hit TAB a bit.  Lots of properties.  Or:  Format-List –InputObject $nic –Property *

So, what can I select on here?  Name, Description, MAC, Up or Down or Connected, Link Speed.  Properties of the physical NIC adapter.  But I want to select a NIC based on the network it is attached to, where it this?

Lets go back to our list of Network cmdlets.  I see Get-NetIpAddress and Get-NetIpInterface.  Hmm..  I list those out and I see all kinds of stuff.  Loopback adapters, physical adapters, missing adapters.  Must be everything that is configured.

If I Get-NetIPInterface –Interface Wired* –ConnectionState Connected I filter down to those interfaces that are physically connected.

From here I see that I have an interface for the IPv6 address and an interface for the IPv4 address.  And they have the same ifIndex (physical NIC device).  But I am still stuck as the physical device and nothing with the DNS of the network or the IP or subnet that came from DHCP.  But, I have the ifIndex.

Lets capture that NetIPInterface object $nic = Get-NetIPInterface –Interface Wired* –ConnectionState Connected

Let’s focus on Get-NetIPAddress   If I Get-NetIPAddress I can select (or filter) using IPv4Address, Alias (Name), InterfaceAlias (the discovered DNS), and InterfaceIndex.  Yea!

Now, what are the IP addresses associated with this interface:  Get-NetIPAddress –InterfaceIndex $nic.ifIndex

I got both an IPv6 and IPv4 back and the Name, Preferred, and that it came from DHCP.  So, I could have selected here and went the other way to the interface as well.

Getting a bit more advanced and linking these two selection criteria together.

Get-NetIPAddress –IPv4Address 192* | Get-NetIPInterface

Or

Get-NetIPInterface | Get-NetIPAddress –IPv4Address 192*

The difference is the object you get back.  In the first one I get the Interface object as my result.  With the second one I get the IP Address object as the result.

I could also select my NICs using Get-NetAdapter.  For example the Intel NICs are always for VMs and I only want a physical NIC.

Get-NetAdapter -InterfaceDescription *Intel* –Physical

I can feed my other return into this to verify that what I got back also meets this criteria or compare the InterfaceIndex that was returned by both.  This way I know if the cable guys have a patch or port incorrect.

Tuesday, March 13, 2012

Hyper-V cmdlets built in to Windows 8

One of the big criticisms of Hyper-V to date is that if you install the Free edition “Hyper-V Server” you do the whole; “okay, now what?”

Oh, I need to manage it remotely?  Oh, it is a royal pain if it is not domain joined?

Well, Microsoft heard you.  And in Windows 8 there is a complete set of PowerShell cmdlets for Hyper-V to save your day.

You can get a video tour here: http://social.technet.microsoft.com/wiki/contents/articles/7944.hyper-v-cmdlets-in-windows-server-8.aspx

Or, you can add the Hyper-V cmdlets Feature to any Windows 8 system (Server and Client) and type; 

Get-Command –Module Hyper-V

and see the vast array of cmdlets that you have.  Everything you could do in the Hyper-V Manager and more.

http://technet.microsoft.com/library/hh848559.aspx