Wednesday, October 5, 2011

Not a big fan of new Microsoft Touch mouse

I upgraded from the Microsoft Touch Arch mouse to the new TouchMouse.  I must say I am not a fan.

The new mouse looks nice and all but does not work as well as I would like.


The new TouchMouse has a single button.  It utilizes touch sensors to detect if you are using the left or right finger to press down.  The problem that I have it is I rest my fingers on my mouse.  This causes the mouse to think I am using the multi-touch (two finger) to minimize or maximize windows. It also sometimes thinks I am pressing the right button when I press the left.

Tuesday, August 16, 2011

Home Automation with Insteon - New Ceiling fan

I got my first Insteon switches and setup in 2005. At the time it was an early product and still had issues and did not have the number of options that exist today.

I live in a 4 story townhome that faces southwest. Because of this the top floor can get super warm in the summer time. To help resolve this we desided to install a ceiling fan where there was just a light before.

There are 2x 3 way switches that control the light at the top of my stairs. There are also lights on the wall controlled by the same switches.


Here is how it looked before I started.



Insteon

I replaced the 2 standard decora switches with Insteon KeypadLinc Switches .  Then added 2 wire-in controllers.  1 dimming controller and 1 non-Dimming controller.

Once all that was done I installed the new fan and wired the fan load to the non-dimming controller and the lights to the dimming controller.

Here is what it looks like now.

Friday, August 5, 2011

WDS and Symbolic Links

Windows Deployment Services (WDS) is all my team and I use for OS deployments. We regularly use the $OEM$\$1 option to copy files and scripts to the target install. More on $OEM$

Recently we started updating scripts that are in a $OEM$, $$ or $1 folder. This was very time consuming because you had to update a large number (~50) different images.

The solution to this problem: Hard Links http://msdn.microsoft.com/en-us/library/aa365006(v=vs.85).aspx
We use the Mklink command to create a Hard link to a “source file”. WDS follows this link and copies the script\file to the target OS during install. This allows us to have a GOLD set of scripts that will get copied yet we only have to make a change in 1 location.

The important thing when making the link with mklink is to pass the /k argument. This will tell mklink to make a hard link not a Symbolic link. You can find more on Mklink at http://technet.microsoft.com/en-us/library/cc753194(WS.10).aspx


WDS will not work with a Symbolic link and will throw an error like:
Windows cannot copy files from \$OEM$ to C:\$WINDOWS.~LS\Sources. The files do not exist. Make sure all files required for installation are available, and restart the installation. Error code: 0x80070003]


This works on Windows Server 2008, Windows Server 2008 R2.

Wednesday, July 27, 2011

Windows Server 2008 Hyper-V Geographically Dispersed Cluster with IBM XIV Storage iSCSI

Here is a paper that I worked on at my team at Microsoft. The Enterprise Engineering Center (http://www.microsoft.com/eec) has a IBM XIV array that we used with the other array on campus.

Windows Server 2008 Hyper-V Geographically Dispersed Cluster with IBM XIV Storage iSCSI

You can find more info on the Tunnel used in this whitepaper at http://www.mikepoulson.com/2011/06/l2tpv3-performance-tweaks-for-hyperv.html

How to create differencing disk VM from template on SCVMM 2012 via powershell

This quick post will provide an example of how to create a Virtual Machine (VM) based off an VMM template that utilizes differencing disks. 

This is special because VMM does not support this natively.  So you have to contact the target HyperV host (via WMI) to create the Diff disk.  In addition to need to make sure that the HyperV host has the parent VHD already in place. 

The Powershell cmdlet below does the following
  1. Looks up the specified Hardware profile
  2. Looks up the specified template (this is used to get the parent VHD location/name)
  3. Looks up info on the specified target HyperV host (so we can find the placement drive)
  4. Checks to see if the ParentVHD already exists on the HyperV hosts Placement Drive
  5. If the VHD does not exist it copies it to the HyperV host
  6. Creates Diff Disk via WMI on hyperV host pointing to parent VHD
  7. Creates the VM via the New-SCVirtualMachine cmdlet using the UseLocalVirtualHardDisk command. (this tells VMM to allow Diff disks).
It can be downloaded from http://dl.dropbox.com/u/3275573/Create_Diff_VM_From_Template.ps1
    param($VMName,$TemplateName = "Windows Server 2008 R2 SP1 Enterprise", $HardwareProfileName = "ServerHardware", $VMMHost = "SCVMM",$targethostname = $null)
    
    $Err = 0
    
    If ($VMName -eq $null)
    {
      Write-Host "`nERROR: Incorrect arguments" -foregroundcolor red -backgroundcolor black
       Write-Host "`nREQUIRED ARGUMENTS:" -foregroundcolor cyan
       Write-Host "`n   -VMName `"Name of the VM to create`"" -foregroundcolor cyan
       Write-Host "`n   -TemplateName `"Name of the VMM Template`"" -foregroundcolor cyan
       Write-Host "`n   -HardwareProfileName `"Name of the VMM Hardware Profile to use with the template`"" -foregroundcolor cyan
       Write-Host "`n   -VMMHost `"VMM Computername`"" -foregroundcolor cyan
       Write-Host "`n   -targetHostname `"Computername of HyperV host to target`"" -foregroundcolor cyan
      Exit $Err
    }
    
    function CreateDiffDiskOnHost
    {
                    param([string]$hostComputerName, [string]$childPath, [string]$parentPath)
                    #get the image mgmt service instance for the host computer
                    $VHDService = get-wmiobject -class "Msvm_ImageManagementService" -namespace "root\virtualization" -computername $hostComputerName
                    
                    #create a differencing disk from the base disk
                    $Result = $VHDService.CreateDifferencingVirtualHardDisk($childPath, $parentPath)
    }
    function TestFileLock {
        ## Attempts to open a file and trap the resulting error if the file is already open/locked
        param ([string]$filePath )
        $filelocked = $false
        $fileInfo = New-Object System.IO.FileInfo $filePath
        trap {
            Set-Variable -name locked -value $true -scope 1
            continue
        }
        $fileStream = $fileInfo.Open( [System.IO.FileMode]::OpenOrCreate, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None )
        if ($fileStream) {
            $fileStream.Close()
        }
        $obj = New-Object Object
        $obj | Add-Member Noteproperty FilePath -value $filePath
        $obj | Add-Member Noteproperty IsLocked -value $filelocked
        $obj
    }
    
    
    write-host "VMName is $VMName"
    write-host "Template is $TemplateName"
    write-host "Hardware Profile is $HardwareProfileName"
    write-host "VMMHost is $VMMHost"
    write-host "Target Host is $targethostname"
    
    $guid = [guid]::NewGuid()
    
    write-host "Lookup the base hardware Profile $HardwareProfileName"
    $HardwareProfile = Get-SCHardwareProfile -VMMServer $VMMHost  | where {$_.Name -eq $HardwareProfileName}
    if ($HardwareProfile -eq $null)
        {
            write-host "Failed to lookup HardwareProfile $HardwareProfileName"  -foregroundcolor red -backgroundcolor black
         EXIT 1
        }
    
    write-host "Getting information for template $TemplateName"
    $Template = Get-SCVMTemplate -VMMServer $VMMHost  -All | where {$_.Name -eq $TemplateName}
     if ($Template -eq $null)
        {
            write-host "Failed to lookup Template $TemplateName"  -foregroundcolor red -backgroundcolor black
         EXIT 1
        }
        
    #Get the VHD info for the template
    $VHD =  Get-SCVirtualharddisk | where {$_.Name -eq $template.VirtualDiskDrives[0].VirtualHardDisk}
    
    write-host "Template VHD Path " $VHD.SharePath
    
    if ($targethostname -eq $null)
    {
        write-host "Invalid targethostname"  -foregroundcolor red -backgroundcolor black
        exit 1
    }
    $vmhost = Get-SCVMHost $targethostname
    
    $vmHostPath = [string]$vmhost.vmpaths
    write-host "Target VMHost: "  $vmhost.name
    write-host "Target Drive: "  $vmhost.VMPaths
    
    $remotePath = "\\" + $vmhost.name + "\" + $vmHostPath.substring(0,1) + "$\" + [system.io.path]::GetFileName($VHD.SharePath)
    "Checking to see if Parent VHD exists on HV Host Drive"
    "RemotePath: $remotePath"
    
    if (Test-Path $remotePath)
    {
     "Parent VHD already exists on HV Host"
    }
    else
    {
     "$RemotePath does not exist, going to Copy"
     [System.IO.File]::Copy($VHD.SharePath,$remotePath); 
    }
    
    "Creating Diff Disk"
    $targetVHDPath = $vmHostPath + $VMName + ".vhd"
    $ParentVHDPath = $vmHostPath + [system.io.path]::GetFileName($VHD.SharePath)
    CreateDiffDiskOnHost "$vmhost" "$targetVHDPath" "$ParentVHDPath"
    Start-Sleep -s 20
    
    $targetVHDRemotePath = "\\" + $vmhost.name + "\" + $vmHostPath.substring(0,1) + "$\" + $VMName + ".vhd"
    if (Test-Path $targetVHDRemotePath)
    {
     "Diff Disk Created at:$targetVHDRemotePath"
    }
    else
    {
     "$targetVHDRemotePath does not exist yet.  Sleeping for a few"
     Start-Sleep -s 30
        if (Test-Path $targetVHDRemotePath)
        {
            "Disk was created."
        }
        else
        {
            write-host "Failed to find VHD $targetVHDRemotePath after sleep, exiting" -foregroundcolor red -backgroundcolor black
            exit 1
        }
    
    }
    #Set a random startup delay to reduce VM startup IOPs overload
    $startDelay = Get-Random -minimum 1 -maximum 30
    
    
    $lockstate = TestFileLock "$targetVHDRemotePath"
    if ($lockstate.IsLocked)
    {
        "File locked, sleeping"
        Start-Sleep -s 30
    }
    
    $mv = move-SCvirtualharddisk -Bus 0 -Lun 0 -IDE -path $targetVHDPath  -jobgroup $guid
    $description = $template.tag
    New-SCVirtualMachine -Name $vmName -VMHost $vmHost -VMTemplate $template -UseLocalVirtualHardDisk -HardwareProfile $HardwareProfile -ComputerName $vmName -path $vmHostPath -delaystartseconds $startDelay  -Description "$description" -mergeanswerfile $true -BlockDynamicOptimization $false -StartVM -JobGroup "$guid" -RunAsynchronously -StartAction "AlwaysAutoTurnOnVM" -StopAction "SaveVM"
    

    Monday, July 18, 2011

    Home Circuit Power Monitoring

    Ever wonder why your home power bill is so high?   Or just want to know how much power you use in various parts of your house through the whole day? 
      
    I have one of the Blue Line Power monitors for Microsoft Hohm (http://www.bluelineinnovations.com/Products/PowerCost-Monitor/).  This product did not allow me to see how much a single room or circuit was using.  It was a start. 

    I have the LCD display in my living room near the TV so that I can quickly see how much energy my home is consuming.

    Microsoft Hohm Data (Sunday, Got up at ~9am)

    For my 30th birthday I got all the parts I need to do per-circuit power monitoring for my whole house. By doing branch circuit monitoring I can answer many questions about my enery usage.

    • What does this mean?  I can tell you things like:
    • Exactly how much does it cost me for it to run
      • How much power does my house use when I turn off all my normal items
    • Leaving things like laptop and cell phone chargers on
      • How much does it cost me to run my AC in the summer?  Is it worth leaving on all day or turning on just when I get home
    • Or in my case thanks to Insteon I can turn it on before I leave work!
      
    The Solution:
    I got the ECM1240 system from Brultech.com.  Specifically the PP3-200-X (http://www.brultech.com/home/store/product.php?id_product=34)
      
    I installed solid core CTs on each breaker on my home circuit panel.  

      

    To hold the ECM1240 brains I installed a PVC box just next to my main panel to hold all the low voltage items.  

      
    The ECM1240 allows me to view my data in real-time via the my1240.com website, read the data from google powermeter or push it into my own data collection environment.
      
    The CONS about the 1240 system are:
    1. The software to manage the 1240 collection devices has more bugs in it than Windows ME. It crashes often and overall is a piece of junk.
    2. The solution by default only supports Google powermeter not www.Microsoft-hohm.com
      • While google powermeter has its ups one thing that is has a serious issue with it is the User interface sucks
      • The ability to export the data into CSV format from google is nice. Not an option on www.Microsoft-hohm.com
      • The ability to share access to my power data from google is nice. Not an option on www.Microsoft-hohm.com
    3. With Google Powermeter and Microsoft-hohm.com being retired I will have to find a new way to view my power data.

    Google Power Meter Data





    My1240.com Data

    Controller 1
    Controller 2
    Controller 3



    Sunday, July 17, 2011

    The Delta Touch2O faucet

    How I love my Delta Touch2O faucet.

    http://www.youtube.com/watch?v=niy8WlqHw3M

    We had to have an additional hole drilled so that we could install it. Most of the videos/blogs talk about how it is a big pain to install. But I found it quite simple. We don't have a lot of room under the sink but i was able to get it done by myself in less than 1 hour.

    Also we read that there are issues with the batteries draining quickly and needing replacements often. We have had the same batteries installed for over 1 year now. It is used everyday by 3 sometimes 4 people.

    I cannot wait to get one for the bathrooms!

    Managing Microsoft IIS, Active Directory and DNS from .net

    Update 7/17/2011:  New links

    This code was one of my first coding project from 11-10-2006

    Today I am posting sample code on how to manage IIS 6 and Active directory using ADSI in VB.NET.
    And managing DNS (creating zones, records and enumeration) using WMI in VB.NET.
    There are four separate projects. 
    This code is posted as-is!  It is to be used as a sample on how to do the work.  It is not intended to be used in production!
    http://dl.dropbox.com/u/3275573/blog/web.zip - ADSI management of IIS 6 Sites and AppPools
    http://dl.dropbox.com/u/3275573/blog/DNS.zip - WMI management of Microsoft DNS Zones and Records
    http://dl.dropbox.com/u/3275573/blog/ActiveDirectory.zip- ADSI management of Active Directory contacts, Groups, Users, Recipient Policies, Accepted Domains objects (Exchange 2007)
    http://dl.dropbox.com/u/3275573/blog/IISSiteID.zip - C# code on generating IIS SiteID

    Saturday, June 18, 2011

    Managing lots of Cisco consoles from one location

    Repost from old blog

    Any who. The issue: Lets say you have 16 or so Cisco devices (extreme works also) that connect to various parts of your network. Now you want to be able to manage these devices remotely but not make a huge security hole using Vlans and attempting to keep it all secure with ACLs.

    So the easy way is to do all the management via the console port. No ACLs to worry about and easier to secure.

    So I have 16+ Cisco devices from Routers to switches (2950s, 3550s, 2621s, 2651s, 3750s, 4912s and even an AS5300) all in my lab. So with all those in my lab I got myself a DIGI portserver TS 16 Rack mount device (we use them for kernel debugging also). With a special digi to cisco cable (yes I will give you the pin-outs if you want them) I connect each cisco's console port to the digi and then the DIGI's Ethernet port to my "management network". The management network is where my management workstation lives.

    The digi device will let you telnet or ssh (SSH is better) into it. Then from there connect to each of its ports (using the connect command). Now where the fun comes in is how to setup the DIGI to talk to the cisco. Then create a menu so you dont alway have to know the port number each device is connected to.

    So below are the steps to allow you to connect the DIGI to the cisco (once you have the cable).
    1.Make sure your device is up to date. I am using 82000685_E.bin and 82000684_L.bin
    2.Know your port numbers (we are going to use ports 1-16)
    3.Set the port type to printer (set ports range=1-16 dev=prn)
    4.set the ip on your digi (set config dhcp=off ip= submask=)

    At this point you should be able to use "connect 1" and connect to port 1. A few hits of the enter key and it should show you the cisco console.

    Now we need to secure the device a little more by turning off things that are not needed. This will leave only telnet and ssh on (I would turn off telnet also but if you dont have an ssh client then it is kinda hard to use).
    1.set secureaccess http=off snmp=off rlogin=off rsh=off https=off realport=off securerealport=off
    2.set secureaccess reversessh=off securesockets=off reversetcp=off reversetelnet=off

    We need to make our menu before we assign a user to use it. This will be an example of ports 1-3 with a title bar
    1.set menu range=1 t1="Cisco management" t2="Make sure you save!" name=menu1
    2.set menu range=1 m1="cisco 1" c1="connect 1"
    3.set menu range=1 m2="cisco 2" c2="connect 2"
    4.set menu range=1 m3="cisco 3" c3="connect 3"

    Now lets make a user that we will connect with to see our menu
    1.set user name= defaultaccess=menu menu=1

    Set the password for our new digi user
    1.newpass name=

    Now a little know tip. When use the default escape char with digi it will leave the port open and not let you reconnect until you do a kill tty= (you can see the ttys by running the 'who' command). But if you use the escapekill command (default is a . (that is a period)) then it will close the tty when you escape. So the default escape command is "+]" . Now add a period after that and hit enter and you will kill the connection not just disconnect so a "+].". Now you press the control and ] key in one key stroke then the period in another.

    Now you should be able to telnet or ssh into your ip and get a menu. Press 1 to connect cisco 1, 2 to connect to cisco 2, and 3 to connect to cisco 3.

    How great!

    Disk Quota and .net (WMI and Microsoft.DiskQuota.1)

    Repost from old Blog

    Today I had a con-call to talk about disk quota and how to automate the setting and reading of Quota. So i thought that I would post a little about Disk quota stuff.

    There are 2 okay options.

    #1 WMI (way to slow for a lot of things (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/disk_quota_provider.asp))

    #2 Microsoft.DiskQuota.1

    So my team needed a way to enumerate a users current quota limits and then + or - from them. WMI was very slow to do this. But DiskQuota.1 is quite fast. It is not well documented that it works on remote servers either. So I wrote a little something up.

    So here is some cs (and vb.net) that has functions on how to get and set quota info with Microsoft.diskquota.1

    CSharp: http://dl.dropbox.com/u/3275573/blog/QuotaFunctions.cs.txt
    VB.NET: http://dl.dropbox.com/u/3275573/blog/QuotaFunctions.vb.txt

    Regular Expressions and IP addresses (ipv4 and IPv6)

    Repost from old blog

    Over the last year or so I have been writing automation that uses IPv4 and IPv6 addresses. In the beginning I had to dig up and make some regular expressions for verifying that a given value was a valid IPv4 or IPv6 address.

    The ones I came up with are (in VB.net)

    Const strIPv4Pattern as string = "\A(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\z" 'IPv4 Address Regex pattern (x.x.x.x)

    Const strIPv6Pattern as string = "\A(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\z"

    Const strIPv6Pattern_HEXCompressed as string = "\A((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)\z"

    Const StrIPv6Pattern_6Hex4Dec as string = "\A((?:[0-9A-Fa-f]{1,4}:){6,6})(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\z"

    Const StrIPv6Pattern_Hex4DecCompressed as string = "\A((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) ::((?:[0-9A-Fa-f]{1,4}:)*)(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\z"

    Now because an IPv6 address can take a few forms we have 4 different expressions for IPv6. If someone finds a bug in one of these please let me know. Because RegExp is something that I am not good at.

    Hope these will help some one.

    IPv6 6over4 tunnels with Windows and Cisco

    Repost from old blog
    A few years ago I began working with Art Shelest here at Microsoft to get Native IPv6 running in my lab.  After a few weeks we had it up and running. 
    We had to work with MSIT (was known as ITG at the time) to get a 6over4 tunnel setup so that we could connect to the 6bone even though my upstream routers did not support IPv6 (still don't at this time).  Once the tunnel was setup on the ITG Router we ran a command on my Windows IPv6 Router in my lab and it was up and running. 
    We run our entire lab IPv6 network on Windows Routers.  We use Windows Server 2003 but you could use Windows XP Pro if you wanted.  Unlike RRAS the IPv6 routing stack is included in Windows XP.  And after Windows XP SP1 this stack was fully supported by Microsoft support.  So if you follow the steps at http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/sag_ip_v6_imp_lab_node.mspx you can get your internal test network setup.
    Now to create a 6over4 tunnel to another router you simply run the below commands from a cmd prompt on your main IPv6  router
    1. netsh
    2. int ipv6
    3. add v6v4tunnel interface="V6v4 Tunnel" localaddress=<local ipv4 address> remoteaddress=<remote ipv4 address>
    4. set interface "v6v4 Tunnel for=en
    5. add address int="v6v4 tunnel" address=<IPv6 address from provider>
    6. add route ::/0 "v6v4 tunnel" <remote IPv6 address> publish=yes
    Key things to note with the above
    • The Local IPv4 address is the IP address that the tunnel is going to use to talk to the Upstream V6 Router (With my example below it would be 1.1.1.1). 
    • The Remote IPv4 Address is the IP address of the upstream V6 router (with my example below it would be 2.2.2.1).
    • The IPv6 address from provider would be a IPv6 address that you get from your v6 provider (with my example below it would be 3ffe:ffee:100:2::2)
    • The Remote IPv6 address is the IPv6 address of the upstream IPv6 router (with my example below it would be 3FFE:FFEE:100:2::1)
    The Cisco side of the config looks like this
    interface Tunnel1
     description v6in4 tunnel to  lab 1.1.1.1/3FFE:FFEE:100:2::2
     no ip address
     ipv6 address 3FFE:FFEE:100:2::1/64
     tunnel source 2.2.2.1
     tunnel destination 1.1.1.1
     tunnel mode ipv6ip



    Once the machines are all setup important things to know are "how do you back up your ipv6 configuration?" Well with netsh it could not be easier.
    Simply run 'netsh int ipv6 dump > c:\ipv6backup.txt'  this will dump all the ipv6 config out to the txt file.  Now if the router was to ever go down you can run the command  'netsh exec c:\ipv6backup.txt'.   With these 2 commands it will backup and restore your ipv6 configuration..  You can also modify the backup command to be 'netsh dump > c:\netshbackup.txt' and it will back up 99% of all the settings for your network configuration.
    If you would like to know more about how I have my IPv6 network setup please let me know.  Also I recommend the Microsoft Press Book Understanding IPv6 (http://www.microsoft.com/MSPress/books/4883.asp) ISBN: 0-7356-1245-5

    How does IIS generate the Site ID?

    Repost from old blog

    So in IIS 6 (and maybe IIS 7) when you create a new site programmatically you have the option to specify a SiteID or you can let IIS 6 do it for you. 

    If you let it do it for you it will make this kinda hash of the site name.  You have to use this ID when you are doing any modifications to the site (programmatically).  So it would be the value in IIS://<servername>/W3SVC/<SiteID>

    So how do you get the SiteID?

    • Well you could create the site then enumerate it from WMI or ADSI. 
    • Use my little c# function below to generate the sitename

     



    public static uint GenerateSiteID(string SiteName)
    {
    uint id = 0;
    char[] arr = SiteName.ToCharArray(); //Convert the sitename to a Char Array
    for (int i = 0; i < arr.Length; i++)
    {
    char c = arr[i];
    int intc = c;

    int upper = intc & '\x00df'; //Upper case the letter
    id = (
    uint)(id * 101) + (uint)upper;
    }
    return (id % Int32.MaxValue) + 1; //do a MOD and add 1
    }

    Now a good thing to remember is that this might not be the sitename the IIS is using.  If there is a SiteID collision then IIS will try to move the ID up by 1 digit then try again.  So dont let this be the end all be all of how this is determined. 

    Using the code above is much faster then parsing through all the sites via ADSI or WMI to get the siteID.  So if you have 2000 sites on a server the site was created most recently (bottom of the Metabase) will take longer to query for then the first site created (top of the metabase). 

    Also note that if you try to convert this code to VB.net you will get an exception becasue VB.net does more bounds checking.

    How to speed up Queries to MicrosoftDNS with WMI

    Repost from old blog

    So there are many key things to remember when creating your WMI queries make them as specific as you can.

    For example if you have ~5000 zones on your Microsoft DNS server and you are looking to see if a single record exists in one of those zones the wrong query could take 1 min+ to complete.

    Why?

    If you do a query like Select * from MicrosoftDNS_AType where ownername="www.mydomain.com" it is going to take a while. Because you did not specify where to look for this record it is going to look in the RootHints and in the DNS Cache also. So if you have a public DNS server that does recursive lookups it could have a few hundred thousand extra records.

    So a better query would be Select TextRepresentation from MicrosoftDNS_AType where containername="mydomainname" and domainname="mydomain.com" and ownername=www.mydomain.com

    You can use a vbscript like the one below to test your queries. This will show you the correct domainname and other settings to use in your query. You can remove the where clause to show all the data on the server.

    The containername will be the name of the zone that holds the records that you want to query for (Ie mydomain.com). If you leave the containername empty it will also search through the DNS cache.

    The domainname specifies the child folder (don’t know how else to describe it). So if you have www.user.mydomain.com the domainname is user.mydomain.com

    Now the domainname will change depending on if there are sub domains to the subdomain (ie www from example above). So if www does not exist then the domainname is mydomain.com. And of course there are exceptions to this rule. If there ever was a child to the sub (you deleted www but left user.mydomain.com) then the domainname is user.mydomain.com. If you don’t want to attempt to do the logic around making sure you have the correct domainname you can omit it. But if you have a large number of records it could make it slow.

    Like SQL the order of the statements in the query is also important.

    If you know the full record info (hostname, TYPE, data) it is fastest to generate the text representation and query on that. You can do that by adding changing your query to something like:

    Select * from MicrosoftDNS_AType where containername=”test.com” and domainname=”test.com” and TextRepresentation="test.com IN A 192.168.0.1"



    on error resume next
    servername = "."
    domainname = "test.com"

    recordtype = "A"

    set dnsserver = Getobject("winmgmts:{Authenticationlevel=pktPrivacy}!\\" & servername & "\root\MicrosoftDNS")

    query = "Select * from MicrosoftDNS_" & recordtype & "Type where containername=""" & domainname & """"
    wscript.echo "Query=" & query

    Set colItems = dnsserver.ExecQuery(query,,48)
    if colitems.count <> 0 then
    For Each objItem in colItems
    Wscript.Echo "ContainerName: " & objItem.ContainerName
    Wscript.Echo "DnsServerName: " & objItem.DnsServerName
    Wscript.Echo "DomainName: " & objItem.DomainName
    Wscript.Echo "OwnerName: " & objItem.OwnerName
    Wscript.Echo "PrimaryName: " & objItem.PrimaryName
    Wscript.Echo "RecordClass: " & objItem.RecordClass
    Wscript.Echo "RecordData: " & objItem.RecordData
    Wscript.Echo "TextRepresentation: " & objItem.TextRepresentation
    Wscript.Echo "Timestamp: " & objItem.Timestamp
    Wscript.Echo "TTL: " & objItem.TTL
    Next
    end if

    L2TPv3 performance tweaks for HyperV GeoCluster Live Migration

    L2TPv3 is a great feature for extending a Layer2 network across sites. This is very useful when you are using Live Migration with HyperV or when you want to pass traffic (at Layer 2) to a different location. 
     
    Recently while working on a SAN GeoClustering test case we want to do a stretched VLan from one lab to another (in different buildings). This gets tricky because we (my team) don’t own or manage the network infrastructure between these buildings. Many companies will use MPLS/VPLS to create a VPN or VLL (Virtual Leased Line) between two sites. This can be expensive and a pain to get setup if you only need a link for a short period of time.
     
    Stretched VLans are becoming more and more common as feature like Live Migration allow the moving of a system from one datacenter to another at the push of a button (well mouse clicks). 
     
    The setup:
    Sites: We were testing at labs that are about &frac14; of a mile apart from each other on opposite sides of Main Campus
     
    The test network consisted for 4 vlans. These networks were duplicated at both sites
    ·         Public -- internet facing for request to HyperV hosted servers
    ·         Cluster – heartbeat network for Fail over Cluster
    ·         Live Migration – network to pass server state during live migration
    ·         Management – backend network to access remove desktop to servers and devices
     
    Servers: We had 6 physical servers for the test (3 at each site). Each site had the same setup for servers
    ·         Server 1 – Host infrastructure systems (AD, DNS, DHCP, WDS)
    ·         Server 2 &3 – Fail over cluster hosts that would host the workload VMs
     
    To interconnect the 4 vlans across buildings we uses the existing IPv4 infrastructure and 2 cisco routers. The building infrastructure offers > 1gbps in an out of each lab, so we connected with 1gig interfaces to uplinks. We also do not have visibility into MTU on building (intra and inter) infrastructure.
     
    So down to what we found and what we changed:
    Original Setup (poor performance): - config shown below
    ·         Single L2TPv3 Tunnel between sites
    ·         Lab facing interfaces were connected to switch that was a trunk port allowing our 4 VLans
              o   Switchport mode trunk
    Original design findings:
    ·         Traffic passed (with 802.1q tags) correctly through tunnel
    ·         MAX bandwidth when coping files/Live Migration from site to site was 20-30mbps
    ·         Large amount of dropped packets in queue
    ·         CPU maxed at 100%
     
    Tweaked design (best performance)
    ·         4 tunnels (one for each vlan) using sub interfaces
    ·         No change to switch trunk config
    ·         Modified hold-queue on each physical interface
    ·         Enabled MTU tuning on pseudowire-class (ip pmtu)
    ·         Enabled Don’t Fragment bit on pseudowire-class (ip dfbit set)
    Tweaked design Findings:
    ·         Traffic passed correctly through tunnel
              o   Each VLan correctly mapped on either side
    ·         MAX bandwidth when coping files/Live Migration from site to site was ~800mbps
    ·         CPU would be around 40%
     
    Original Config (each site was identical except swapped xconnect ip with interface ip address) – SLOW!
    ---
    l2tp-class class1
    authentication
    password 0 123456789
    !
    pseudowire-class ethernet
    encapsulation l2tpv3
    protocol l2tpv3 class1
    ip local interface GigabitEthernet0/1
    !
    interface GigabitEthernet0/0
    no ip address
    duplex full
    speed auto
    no cdp enable
    xconnect 10.216.44.47 125 pw-class ethernet
    !
    interface GigabitEthernet0/1
    ip address 10.197.251.215 255.255.255.240
    duplex auto
    speed auto
    no cdp enable
    !
    ip route 0.0.0.0 0.0.0.0 10.197.251.209
    !
    no cdp run
    !
    End
     
    Tweaked Design
    --
    l2tp-class class1
    authentication
    password 0 123456789
    !
    pseudowire-class ethernet
    encapsulation l2tpv3
    protocol l2tpv3 class1
    ip local interface GigabitEthernet0/1
    ip pmtu
    ip dfbit set
    !
    interface GigabitEthernet0/0
    no ip address
    duplex full
    speed auto
    no cdp enable
    hold-queue 2048 in
    hold-queue 2048 out
    !
    interface GigabitEthernet0/0.2996
    encapsulation dot1Q 2996
    no cdp enable
    xconnect 10.216.44.47 126 encapsulation l2tpv3 pw-class ethernet
    !
    interface GigabitEthernet0/0.2997
    encapsulation dot1Q 2997
    no cdp enable
    xconnect 10.216.44.47 127 encapsulation l2tpv3 pw-class ethernet
    !
    interface GigabitEthernet0/0.2998
    encapsulation dot1Q 2998
    no cdp enable
    xconnect 10.216.44.47 128 encapsulation l2tpv3 pw-class ethernet
    !
    interface GigabitEthernet0/0.2999
    encapsulation dot1Q 2999
    no cdp enable
    xconnect 10.216.44.47 125 encapsulation l2tpv3 pw-class ethernet
    !
    interface GigabitEthernet0/1
    ip address 10.197.251.215 255.255.255.240
    duplex auto
    speed auto
    no cdp enable
    hold-queue 2048 in
    hold-queue 2048 out
    !
    ip route 0.0.0.0 0.0.0.0 10.197.251.209
    !
    no cdp run
    !
     

    Programmatically Controlling Pioneer Receivers and BluRay Players

    I recently got a new Pioneer Elite SC-35 receiver (http://www.pioneerelectronics.com/PUSA/Products/HomeEntertainment/AV-Receivers/EliteReceivers/ci.SC-35.Kuro).  This receiver has an ethernet plug on the rear and is supported by the iPhone/iPOD app called iControlAV. 
    While the receiver has a web interface called "Pioneer Web Control System" I wanted a way to control this receiver via script. The web interface has support for
    • Powering the receiver on/off
    • Changing the Volume including mute
    • Changing the Input (Zones 1-3)
    • Changing the "Listening Mode"
    The iControlAV app for iPhone supports the same plus a few more options.
    The iControlAV uses SSDP query to find the receiver. Which runs NU-OS 1.13.  You can Browse to http://<Receiver IP>/BasicDevice.xml to get the info on your device. 
    My receiver has port 23 (telnet) open along with 80 and 8102 (referenced in BasicDevice.xml)
    Basic process:
    • Send command as ASCII on telnet (23) or TCP/8102 (see your BasicDevice.xml)
    • Commands that check status or query the device begin with a ?
    • Commands that perform a command sometimes have parameters (input number) at begining, some at end
    • You can monitor the telnet window to see the "response" for each command sent.  This includes commands sent through IR remote or from the device its self.
    Basic Commands (more commands to come in another post):
    ?P
    Is Device powered ON?
    PWR0 Device is ON
    PWR1 Device is OFF
    PF Power Device OFF
    PO Power Device ON
    ?M  Is Zone MAIN muted
    MUT1 Zone is NOT Muted
    MUT0 Zone is Muted
    MO  Mute MAIN zone
    MF  unMute MAIN zone
    ?V Get Current Volume level
    VOLxxx Current volume level, xxx is 000-200
    VOL121 -20.0db
    VOL081 -40.0db
    XXXVL Set Volume Level to XXX (000 - 200)
    001VL Set Volume Level to -80.0db
    081VL Set Volume Level to -40.0db
    ?RGC Get inputs on device (i think)
    RGC111001002 *Unknown*
    ?RGBxx Get inputs Name (related to above command), available inputs will change based on model
    ?RGB01 RGB010CD
    ?RGB02 RGB020TUNER
    ?RGB03 RGB030CD-R/TAPE
    ?F Get current input (use ?RGB to get name)
    FN19 Input 19
    FN15 Input 15
    XXFN Set current input (XX = Input number)
    XX Input number
    19FN Set to input 19
    15FN Set to input 15
    ?BP *UNKNOWN*
    BPR1
    ?AP *UNKNOWN*
    APR1
    Example
    Turn on device, set input to HDMI1 (19 in my case), and volume to -40db

    PO

    19FN

    081VL

    (Update: 7/17/2011)
    I was able to find a doc that has all the commands (better than what I was able to determine). 
    http://dl.dropbox.com/u/3275573/2010%20USA%20AVR%20RS-232C%20%26%20IP%20Commands%20for%20CI.pdf

    Configuring Dell EqualLogic management interface

    The Dell EqualLogic iSCSI SAN supports an out-of-band management network interface. This is for managing the device from a separate network than the iSCSI traffic is on.
    The documentation for the PS6000E is some of the worse I have ever seen. In addition to that the CLI (command line interface) is about as bad as a big pile of dog poo.
     
     
    So this is a quick set of commands that are used to configure the management (eth2) interface on the device. The web interface is nice and all but you have to have your 10Gig network setup before you can access it. Also the "setup" does not really give you an easy option to configure the management interface.
     
     
    Steps:

    Login to Console Port with grpadmin username and grpadmin password.

    After you run setup you will need to know the "member name". You can get your member name by running the "member show" command. This will list the name, Status, Version, Size information for each member configured on the array.
     
    grpname> member show
    Name Status Version Disks Capacity FreeSpace Connections
    ---------- ------- ---------- ----- ---------- ---------- -----------
    EEC-DellEqual online V4.3.6 (R1 16 621.53GB 0MB 0
    grpname>
    The member name for my device is EEC-DellEqual.
    Once you know the member name you will need to set the IP address for your management interface. This IP address will need to be one that you can access from your management network. The port is an untagged port similar to other out-of-band management ports on devices (network switches).
    To configure the IP use the member command again.
    First set the interface to be management ONLY
    -member select EEC-DellEqual eth select 2 mgmt-only enable
    Set the IP address and Network Mask
    -member select EEC-DellEqual eth select 2 ipaddress xxx.xxx.xxx.xxx netmask 255.255.255.0
    Enable the interface (by default the MGMT (eth2) interface is disabled and will not provide a LINK).
    -member select EEC-DellEqual eth select 2 up
    You will be asked to confirm that you wish to enable the Management port
    This port is for group management only. If enabling, make sure it is connected to a dedicated management network. If disabling, make sure you can access the group through another Ethernet port.
    Do you really want to enable the management interface? (y/n) [n] y
    To view current IP and state of an Eth interface use
    -member select <member Name> show eths
    Once that is complete you can use the management IP address to create an http or https connection to the Array.
     

    Securing a TS connection with Smart Cards

    Repost from old blog
    Well today is going to be a busy day here at the Microsoft Enterprise Engineering Center. At about 11:30 I am going to have lunch some of the RedvsBlue people (http://www.redvsblue.com). Then I have the job of setting up and testing a remote access solution for a customer. Note that the steps below are technical and you should know a little something about Active Directory and PKI before you start.

    The problem: How do you provide a customer secure remote access into a scenario?
    Solution: Smart cards and Terminal Services on Windows Server 2003! Smart cards keep the Private PKI key stored on the card, and cannot be removed from the card. It requires two-factor authentication. Something you have (the smart card) and something you know (the PIN).

    How: First we set up a DC (or 2). Then install cert services on box (domain member). Then install Terminal Services on to another box (aka the Jump box).

    We are using the Microsoft Base CSP (http://www.microsoft.com/resources/documentation/WindowsServ/2003/all/techref/en-us/Default.asp?url=/Resources/Documentation/windowsserv/2003/all/techref/en-us/w2k3tr_certs_how.asp) on some Amtel Smart cards.

    I create user accounts in the Domain for each person that will need remote access. Each Account has a Very LONG and Very RANDOM password. This is because the user will never use a password. They will not be able to use their smart card. Once the users are created make sure that you go in the properties of each user and under the Account tab select the following options: User Cannot change password, Password never expires and Smart Card is required for interactive logon.

    Now create a separate Admin account. This will be the account that I use to manage the TS (terminal Services) jump box and issue the smart cards. Make sure it has a secure password.
     
    To issue a smart card the issuing user account must have an Enrollment Agent Cert. To get this cert you must first enable it on the CA. (Open the CA MMC snapin -> select Certificate Templates -> Right-click on Certificate Templates -> Select New -> Select Certificate Template to issue. In the list select Enrollment Agent.

    Repeat the steps above to also add the Smart Card Logon Cert. This is the cert that we will put on each Smart Card.

    After you have enabled that cert (Enrollment Agent) you must now request it with the user account that will be issuing the Smart Cards. So for my solution that is the separate admin account. I will use runas.exe /u:<domainName>\<adminUser> "mmc certmgr.msc". This will allow me to open the MMC without logging in as that user.

    To request the new cert select personal -> right-click on personal -> select all tasks -> select Request new Cert... Once the Wizard opens select Next to start it -> Select Enrollment Agent -> Select Next -> Enter a Name (like SC enrollment Cert) -> Select Next -> then Select Finish to issue the cert.

    Now we will need to make sure we have our smart card reader installed on the machine that has our enrollment Cert and http access to the CA. With all of the above done you can now open a web browser to http://<CA Machine Name>/certsrv/certsces.asp (note: that you might have to add this site to your trusted sites to get the Active X control to load).

    From this browser window we can select the type of Cert we want to put on the Smart Card. We are going to use Smart Card Logon Cert. You will need to select the Microsoft Base Smart Card Crypto Provider as your CSP. The Administrator Signing Certificate is the Enrollment Cert that we requested earlier. At this point you can select any user in the domain to issue a smart card for.

    One thing to note is that when you have a smart card for user account it does not matter if the user changes their password. The smart card will allow the user to be authenticated without a password. So make sure that you keep accounts that have the Enrollment Agent Cert secure.

    In the future I will also write about how to use the AD to further secure the Solution.

    10 Years from last post

     Well world!   After the last almost 10 years I have been up to a few things in life and work.  Most recently I was working at Microsoft on ...