Tuesday, October 13, 2009

Who's VM is This? Custom Fields for VMs with PowerShell

Being new into an environment, it is often difficult to sort through the hundreds of new servers that are now under your care. Seasoned veterans in your organization will already have intimate knowledge about each system that they support, and more often than not it is not fully documented as to who owns what system. I find myself often asking my new coworkers..."Who's VM is This?"

You may already know that within vCenter server you can easily add notes to VMs by selecting the VM, clicking on the Summary tab, and look under 'Annotations'.

Clicking on the Edit link will display the "Edit Custom Attributes" box where you can enter notes.



You should also see a button for creating custom Attributes. Attributes are custom fields (which is important to remember when using PowerCLI) that you can set name and values for at your pleasure. This can be applied to Hosts, Virtual Machines, or Globally which will apply the new attribute to both Host and Virtual Machine.


Note: Adding a custom attribute to one Host or Virtual Machine will add that attribute to all like systems. It does NOT populate the value for this attribute on other systems however. This is still our responsibility. Likewise if you delete an attribute it will also remove it and all values from like systems. These values are stored in the vCenter database and could possibly be recovered from your database backup. I have not tried testing this but have verified that the data is there and reference the VM in tables VPX_FIELD_DEF and VPX_FIELD_VAL.

In our environment it was my goal to create a custom attribute for "Owner", "Director", "App Owner" so that I could easily run an "Owners Report" that could be used for change notifications.

If you've read any of my other posts you probably know what's coming next...A Script!

Since there are so many VMs in my environment and I was relying on other people to populate the necessary data I created an Excel spreadsheet on a shared drive with a list of the VMs and columns for Owner, Director, App Owner, and Notes (which I'll share a separate script for later).

While that information was being populated I put together a quick script to import the file (.csv) and implement the attributes.

$import = Import-Csv "\\server\share\VM-Owner-Info.csv"

$import | %{
$field = $_.Field
$value = $_.Value
$server = Get-VM -Name $_.Name

#Create/Set custom attribute based on CSV values
$server | Set-CustomField -Name $field -Value $value
}

Note: Each new custom attribute that is added will appear at the top of the annotations section, just above the previous attribute added. i.e. If you have an attribute that you wish to have on top, then make sure you add it last.

For the sake of simplicity and under reasonable time constraints I reformatted my completed excel spreadsheet so that each Field was isolated on it's own line along with the VM and Value. This involved an extra minute but knowing Excel pretty well you should be able to accomplish this very quickly as well. My .CSV thus looks as such:

Name,Field,Value
Josh-Test-01,Owner,Josh 1
Josh-Test-02,Owner,Josh 2
JoshNet-DC,Owner,Josh 3
Josh-Test-01,Director,Jason 1
Josh-Test-02,Director,Jason 2
JoshNet-DC,Director,Jason 3
Josh-Test-01,App Owner,Rod 1
Josh-Test-02,App Owner,Rod 2
JoshNet-DC,App Owner,Rod 3


The script will process each line and assign the custom attribute accordingly. Since this serves the purpose and within the right time criteria I consider it in order. I'll be working hard later to allow you to generate an easier to manage table/CSV where the script will determine the Attribute name based on the header, and enter the value accordingly.

Host,Owner,Director,App Owner
Josh-Test-o1,Josh 1,Jason 1,Rod 1
Josh-Test-02,Josh 2, Jason 3, Rod 2
JoshNet-DC,Josh 3, Jason 3, Rod 3


This would be easier to edit and manage in Excel rather than having to define the attribute and value on each line. If anyone has some insight on how to make this possible since my initial attempt failed then please let me know.

Once run, the final product appears as so on all VMs:

I can now see the Owner, Director, and App Owner for this VM. Certainly you can use whatever attributes you'd like. I highly recommend using Excel and collaborating with your team to gather the pertinent information.

Now that you have this data populated for your VMs it is only really good to you if you can get it out. The PowerCLI Blog has a post for moving this data between vCenter servers (in the DB as you recall). I have modified it slight where it will display the attributes and their values for each VM.

function Get-CustomField {
param($item)
foreach ($cf in $item.CustomFields) {
if ($cf.Value) {
$field = "" | Select Key, Value, EntityName
$field.Key = $cf.Key
$field.Value = $cf.Value
$field.EntityName = $item.Name
Write-Output $field
}
}
}
$fields = Get-VM -server $server1 | Foreach { Get-CustomField $_ }
$fields


You can also use the quick one-liner:

Get-VM | Select -ExpandProperty customfields

Hope you find this useful.

Links:
Eric Siebert on Custom Attributes - http://itknowledgeexchange.techtarget.com/virtualization-pro/using-custom-attributes-with-vcenter-server/

When researching additional information for this post I came across where Arne Fokkema also created a one-liner to populate custom attributes from a .CSV file. It seems he beat me to it by about a month and I somehow didn't find it before creating my own. Here are two links from his blog where he performs the same task as well as adding notes as I mentioned earlier.
http://ict-freak.nl/2009/08/14/powercli-add-notes-to-multiple-vms/
http://ict-freak.nl/2009/08/17/powercli-set-custom-fields/

http://blogs.vmware.com/vipowershell/2009/05/moving-custom-fields-from-one-vcenter-to-another.html

1 comment: