Tag Archives: VM

PowerShell.org’s Azure Journey, Part 4: Incoming Advice and Fun Facts


Had an opportunity to speak with some folks on the Azure team yesterday – Mark Russinovich was kind enough to make a contact for me.

First of all, fun fact: Azure only charges you for used pages in VHDs. That is, if you create a 100GB VHD and load 1GB of data on it, you’re paying for 1GB of data. Very clever. So it’s charging you as if it was a dynamically expanding VHD, but of course it’s a fixed VHD with all of the related performance improvements. Nice.

Second, they basically confirmed something I’d suspected. Azure’s “website model” tends to appeal more to smaller businesses or personal Web sites; most “serious” players (my word) are using the IaaS model, meaning they’re hosting VMs in the cloud, not just hosting a Web site. Having a full VM under your control obviously has advantages in terms of management, along with the ability to run things like in-memory caching software, load additional Web extensions, and so on. IaaS is absolutely the right model for PowerShell.org for many of those reasons.

That said, they also confirmed that the Web site model and the IaaS model cost about the same, at least as you get started. So it’s really – for a smaller Web site – a matter of what you want to do. Again, there are specifics about the IaaS model that work well for us, so that’s what we’re looking to do.

Azure also costs about the same, in an apples-to-apples comparison, as Amazon Web Services. That’s probably somewhat deliberate on Microsoft’s part, but Azure has advantages. For one, their virtualization layer has been approved by the various Microsoft product teams, so if you’re running SharePoint or SQL Server in an Azure VM, the team will support you. Not the case with AWS. Also, I frankly found Azure’s presentation of the costs easier to grok.

Fifth (I love numbered lists, sorry), I confirmed that the IaaS option charges you for (a) the VM’s you’re running, by the minute; (b) the storage used by all VM VHDs’ used pages, and (c) outbound bandwidth. This can potentially make IaaS more expensive than the “website” model because Azure won’t spin down an IaaS VM, so you run 24×7 unless you’re manually deallocating. With a website, Azure only spins up worker processes when they’re needed, so your site isn’t “running” 24×7, so you might pay less if it’s not being “hit” 24×7. Again, though, the website model offers us less control and flexibility.

Just thought you’d enjoy some of those details!

Hyper-V ID Hash Table


Microsoft Hyper-VIn Hyper-V, one of the challenges (at least that I’ve run into) has to do with naming. In addition to a name, Hyper-V objects such as virtual machines, are identified with a GUID. Most of the VM-related PowerShell cmdlets will let you specify a virtual machine name. But sometimes you’ll run across the GUID and wonder what is the corresponding virtual machine. Here’s a WMI query using Get-CIMInstance that shows the currently open terminal connections to a few virtual machines.

PS C:\> get-ciminstance -Namespace root\virtualization -class msvm_terminalconnection | Select connectionID,installdate

connectionID                                      installdate
————                                      ———–
Microsoft:13876524-BFD8-40A1-95E3-926E37ACFBAB\1  1/3/2013 11:27:50 AM
Microsoft:80E967E6-57F9-4ECF-998A-D07B20B2287F\2  1/3/2013 8:12:56 AM
Microsoft:E1EDE8DA-D632-4F77-81C4-B117FFF1FE15\1  1/3/2013 8:08:35 AM

The GUID in the connection ID corresponds to a virtual machine. Here’s my approach for “translating” the GUID to a name. Every VM has an ID.

PS C:\> (get-vm chi-dc01).id

Guid
—-
f7d3ad8b-6329-43a3-991e-8a630a94ec40

There is also an VMID property but that is merely an alias to ID. As you can see, the ID is a GUID object so to get just the GUID string takes another step.

PS C:\> (get-vm chi-dc01).id.guid
f7d3ad8b-6329-43a3-991e-8a630a94ec40

Now that I know how to capture this information, I can build a “lookup” object using a hash table.

PS C:\> Get-VM | Group-Object  -property {$_.ID.GUID} -AsHashTable -AsString

Here’s what I end up with:

vmidhash

Naturally, it makes more sense to save this to a variable.

PS C:\> $vmhash = Get-VM | Group-Object  -property {$_.ID.GUID} -AsHashTable -AsString

The VM GUID is the key and the VM object is the value. I can get items a few ways.

PS C:\> $vmhash.’13876524-bfd8-40a1-95e3-926e37acfbab’

Name     State   CPUUsage(%) MemoryAssigned(M) Uptime   Status
—-     —–   ———– —————– ——   ——
CHI-FP01 Running 0           761               03:34:51 Operating normally

PS C:\> $vmhash.item(‘13876524-bfd8-40a1-95e3-926e37acfbab’)

Name     State   CPUUsage(%) MemoryAssigned(M) Uptime   Status
—-     —–   ———– —————– ——   ——
CHI-FP01 Running 0           761               03:35:11 Operating normally

PS C:\> $vmhash.GetEnumerator() | where {$_.name -match ‘13876524-bfd8-40a1-95e3-926e37acfbab’} | se
lect -ExpandProperty Value

Name     State   CPUUsage(%) MemoryAssigned(M) Uptime   Status
—-     —–   ———– —————– ——   ——
CHI-FP01 Running 0           761               03:36:29 Operating normally

Now I can add some logic to my Get-CIMInstance command to resolve the GUID to the VM name.

$vmhash = Get-VM | Group-Object  -property {$_.ID.GUID} -AsHashTable -AsString

Get-CimInstance -Namespace root\virtualization -class msvm_terminalconnection |
Select @{Name="Started";Expression={$_.installdate}},
@{Name="RunTime";Expression={(Get-Date)-$_.InstallDate}},
@{Name="VM";Expression={  
  #define a GUID regex
 [regex]$rx="(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}"
 
 $guid = $rx.Match($_.ConnectionID).Value
 $vmhash.item($guid).Name
}}

I also tweaked a few other properties. I extracted the GUID using a regular expression and then found the corresponding entry in the hash table. I could have added a little extra logic to test if the GUID existed as a key but I decided to just plow ahead.

vmidhashlookup

The hash table makes it very easy now to resolve virtual machine GUID’s to a user friendly name.

Post to Twitter Post to Plurk Post to Yahoo Buzz Post to Delicious Post to Digg Post to Facebook Post to FriendFeed Post to Google Buzz Post to Ping.fm Post to Reddit Post to Slashdot Post to StumbleUpon Post to Technorati

Copy and Mount a CD with PowerCLI


The other day I realized I needed to rebuild my SQL Server 2012 installation which I’m running on a virtual machine running on an ESX box. Given that I have PowerCLI and I like to do things from the command prompt when I can, I decided to mount the SQL Server 2012 ISO on the VM using PowerShell. This actually requires a few steps that I thought I would share.

First, you naturally need to have PowerCLI installed. You will need to import the necessary snapins and connect to the ESX host.

Add-PSSnapin VMware.VimAutomation.core
Connect-viserver -Server ESX

Once connected, I can begin the process. Next, I need to copy the ISO file the datastore so that I can mount it from the VM. While the vmstore: PSDrive is fun to work with, you can’t copy from the filesystem. Copying between providers is simply not allowed. Instead I’ll use the Copy-DatastoreItem cmdlet. This will allow me to copy a local file to the VMware datastore.

The tricky part here is to get the right format for the datastore destination. This is where I want to copy to:

PS vmstore:\ha-datacenter\datastore3\ISO> dir

   Datastore path: [datastore3] ISO

            LastWriteTime            Type       Length Name
            ————-            —-       —— —-
      8/18/2009   9:09 AM    IsoImageFile   2996799488 en_windows_server…

The “trick” is to grab the value for Datastore path from the directory listing. Thus, I can run this to copy the ISO file to the datastore.

$iso="C:\users\jeff\Downloads\en_sql_server_2012_standard_edition_with_sp1_x86_x64_dvd_1228143.iso"
$dest="vmstore:\ha-datacenter\datastore3\ISO"
Copy-DatastoreItem -Item $iso  -Destination $dest -passthru

You get a nice progress bar and in a few minutes the file is copied. Now I can mount it in the VM’s CDDrive using Set-CDDrive. The cmdlet will need a CDDrive object from a VM and the path to the ISO file. I’ll have to construct a path using the VMware datastore format. It looks a little funny because it is not a typical Windows path.

$isopath = "[datastore3] ISO\en_sql_server_2012_standard_edition_with_sp1_x86_x64_dvd_1228143.iso"

For situations like this, I find it easiest to use the corresponding Get cmdlet, and pipe the resulting object to the Set cmdlet.

get-cddrive -VM "globomantics db" | set-cddrive -IsoPath $isopath -Connected $true

The only other parameter I specified was to connect the CDDrive to the VM. This command takes a moment to run and then in the VM I can “see” the DVD and use it normally. Awesome. When I’m finished I can dismount the CD much the same way.

get-cddrive -VM "globomantics db" | set-cddrive -NoMedia

This may seem like a lot of typing, but if it is something I need to do a lot I could build a simple script or function. And it is still faster (for me) than navigating the GUI.

Post to Twitter Post to Plurk Post to Yahoo Buzz Post to Delicious Post to Digg Post to Facebook Post to FriendFeed Post to Google Buzz Post to Ping.fm Post to Reddit Post to Slashdot Post to StumbleUpon Post to Technorati

PowerShell Hyper-V Memory Report


Since moving to Windows 8, I’ve continued exploring all the possibilities around Hyper-V on the client, especially using PowerShell. Because I’m trying to run as many virtual machines on my laptop as I can, memory considerations are paramount as I only have 8GB to work with. Actually less since I still have to run Windows 8!

Anyway, I need to be able to see how much memory my virtual machines are using. The Get-VM cmdlet can show me some of the data.

PS C:\> get-vm chi-dc03

Name     State   CPUUsage(%) MemoryAssigned(M) Uptime   Status
—-     —–   ———– —————– ——   ——
CHI-DC03 Running 0           559               23:29:12 Operating normally

Actually, there are more properties I can get as well.

PS C:\> get-vm chi-dc03 | select *mem*

MemoryAssigned       : 586153984
MemoryDemand         : 491782144
MemoryStatus         : OK
MemoryStartup        : 402653184
DynamicMemoryEnabled : True
MemoryMinimum        : 402653184
MemoryMaximum        : 1073741824

Those values are in bytes so I would need to reformat them to get them into something more meaningful like bytes. Not especially difficult, but not something I want to have to type all the time. Now, I can also get memory information with Get-VMMemory and this is formatted a little nicer.

PS C:\> get-vmmemory chi-dc03

VMName   DynamicMemoryEnabled Minimum(M) Startup(M) Maximum(M)
——   ——————– ———- ———- ———-
CHI-DC03 True                 384        384        1024

What I like about this cmdlet is that it also shows the buffer and priority settings.

PS C:\> get-vmmemory chi-dc03 | select Startup,Buffer,Priority,Minimum,Maximum

Startup  : 402653184
Buffer   : 20
Priority : 50
Minimum  : 402653184
Maximum  : 1073741824

In the end, I decided the best course of action was to build my own function that combined information from both cmdlets. The result is a custom object that gives me a good picture of memory configuration and current use. The function, Get-VMMemoryReport, is part of a larger HyperV toolkit module I’m developing but I thought I’d share this with you now.

Function Get-VMMemoryReport {
#comment based help is here

[cmdletbinding()]
Param(
[Parameter(Position=0,Mandatory=$True,HelpMessage="Enter a VM",
ValueFromPipeline=$True)]
[alias("VM")]
[object]$Name,
[ValidateNotNullorEmpty()]
[string]$Computername=$env:COMPUTERNAME
)

Process {
    if ($Name -is [String]) {
        Try {
            $Name = Get-VM -name $Name -ComputerName $computername -ErrorAction Stop
        }
        Catch {
            Write-Warning "Failed to find VM $vm on $computername"
            Return
        }
    } #if
    elseif ($name -isnot [Microsoft.HyperV.PowerShell.VirtualMachine]) {
        Write-Warning "You did not pass a string or a VM object"
        Return
    }

    #get memory values
    $memorysettings = Get-VMMemory -VMName $Name.name -ComputerName $Computername

    #all values are in MB
    $hash=[ordered]@{
        Name = $Name.Name
        Dynamic = $Name.DynamicMemoryEnabled
        Assigned = $Name.MemoryAssigned/1MB
        Demand = $Name.MemoryDemand/1MB
        Startup = $Name.MemoryStartup/1MB
        Minimum = $Name.MemoryMinimum/1MB
        Maximum = $Name.MemoryMaximum/1MB
        Buffer =  $memorysettings.buffer
        Priority = $memorysettings.priority
    }
   
    #write the new object to the pipeline
    New-Object -TypeName PSObject -Property $hash
   
} #process
} #end Get-VMMemoryReport

I wrote the function with the assumption of piping Hyper-V virtual machines to it. Although I can also pipe names to it and the function will then get the virtual machine.

 if ($Name -is [String]) {
        Try {
            $Name = Get-VM -name $Name -ErrorAction Stop
        }
        Catch {
            Write-Warning "Failed to find VM $vm"
            Return
        }
    } #if
    elseif ($name -isnot [Microsoft.HyperV.PowerShell.VirtualMachine]) {
        Write-Warning "You did not pass a string or a VM object"
        Return
    }

Once the function has the virtual machine object, it also gets data from Get-VMMemory.

$memorysettings = Get-VMMemory -VM $Name

Finally, it creates a hash table using the new [ordered] attribute so that the key names will be displayed in the order I enter them. I use this hash table to write a custom object to the pipeline. I could have used the new [pscustomobject] attribute as well, but I felt in a script using New-Object was a bit more meaningful. With this command, I get output like this:

PS C:\> get-VMMemoryreport chi-dc03

Name     : CHI-DC03
Dynamic  : True
Assigned : 559
Demand   : 469
Startup  : 384
Minimum  : 384
Maximum  : 1024
Buffer   : 20
Priority : 50

Or I can explore the data in other ways. I can create an HTML report, export to a CSV or take advantage of Out-GridView.

PS C:\> get-vm | where state -eq running | get-vmmemoryreport | out-gridview -title ‘VM Memory Report’

Here’s the report for my currently running virtual machines.

The function defaults to connecting to the localhost, but I am assuming that if you have an Hyper-V server you could use this from any system that has they Hyper-V module also installed. I don’t have a dedicated Hyper-V server to test with so maybe someone will confirm this for me.

In the meantime, download Get-VMMemoryReport and let me know what you think.

Post to Twitter Post to Plurk Post to Yahoo Buzz Post to Delicious Post to Digg Post to Facebook Post to FriendFeed Post to Google Buzz Post to Ping.fm Post to Reddit Post to Slashdot Post to StumbleUpon Post to Technorati

Episode 34 – VMware in the House


A Podcast about Windows PowerShell.

Listen:

We have a great show lined up for you today.  We’ll be talking to Carter Shanklin from VMware about their PowerShell Toolkit.  He’s got some exciting NEW news to share with us, so that’s cool.  We’ll also bring you news, resources, tips and whatever else we can scrape up.

News

This segment is brought to you by Quest Software.

Do you have what it takes to be the ultimate script warrior? Find out with Quest’s PowerPack Challenge ’08.

Quest Software is sponsoring a PowerShell Scripting contest where you can test your skills and get paid. Just create some cool PowerShell scripts using Quest’s PowerGUI and then post them to our site. You’ll get a score and our celebrity judges will weigh in as well.

Do you have the muscle to bring home the prize? Check out the details here.

  • PowerShellASP (powershelltoys.com) – PowerShellASP is an ASP-like template language for Web Applications; templates contain a mixture of markup (HTML, XML or whatever you want to generate) and inline PowerShell code. At runtime, templates/pages are fully translated to PowerShell code and exe
  • Codeplex project PowerShell Pages (codeplex.com/powershellpages)- PowerShell Pages is an ASP like language, based on the PowerShell runtime. Using a simple HTTP Handler, ASP.NET can render pages scripted using PowerShell script (including cmdlets, and CLR/.NET objects) to the web. Simple, fast and intuitive programming
  • VMware Toolkit 1.0 is out of beta!  (vmware.com/go/powershell)
    • 125 cmdlets
    • focus on VM lifecycle and ESX server deployment and configuration

Interview

Today’s news is brought to you by iTripoli.

“Admin Script Editor provides a true integrated scripting environment for PowerShell.  Advanced features include an integrated PowerShell debugger, advanced code generating tools for Active Directory, Databases, XML files and the exclusive PowerShell forms designer.  Come see for yourself– Admin Script Editor v3.5 is availble for a 45 day trial at AdminScriptEditor.com.”

  1. Background
    1. long time developer in Unix-land
    2. VMware for 8 months
  2. Current Role
    1. Product Manager
  3. Solving Problems
    1. change CD drives on 1500 VMs
  4. VMware Toolkit for Windows
    1. Works on VMS 2.0
    2. Lab Manager, VDM — future potential
    3. 125 cmdlets
    4. focus on ESX & VC
      1. side one: VM lifecycle
      2. side two: VM host deployment
    5. 1.0 released TODAY!
    6. download: http://vmware.com/go/powershell
    7. blog: http://blogs.vmware.com/vipowershell
    8. for help
      1. online docs
      2. community (link from download site)
  5. Discussion
    1. VM automation
      1. they are working on it, will use VIX
    2. Developers & PowerShell
      1. key is powershell is application focused
      2. scripts write like you think the task should work
    3. Excel automation
      1. great for general powershell — not vmware specific
    4. v2 ctp module?

Resources

Tips

  • Jeffrey Snover reminds us to update your GAC!  This really speeds up the start time for a powershell console.
  • Enabling WinRM with Powershell / Get-Powershell – Don’t forget you can use Configure-WSman.ps1 to configure WinRM using PowerShell.
  • you can get a much faster file count of a directory by doing a get-item on the parent folder and calling the getFiles() method. Thanks Jaykul!
    • measure-command {
      $folder = get-item ‘\servershare’
      Write-Host ($folder.getfiles()).count} # 524 Milliseconds
      Measure-Command {(gci ‘\servershare’).count} # 1min 18 sec
    • note that getfiles() will not count any directories

Cmdlet-of-the-Week

  • out-host has a -Paging parameter

Gotcha

Talk to you next week!  Don’t forget to follow Jonathan and Hal on Twitter.