vespavbb
Enthusiast
Enthusiast

Get-vm with certian custom Attributes

Jump to solution

Hi

I want to create an arry or csv of vm´s with certian attributes.

The script basically works, but the output is strange, i want to cut the output to the value only

$vms = Get-cluster C01-Test* | get-vm

$myCol=@()

foreach($vm in $vms)

{

$col =  "" | select Name, Att1,Att2, Att3

$col.name = $vm.name

$col.Att1 = $vm | select {$_.CustomFields.Item("test-APP")}

$col.Att2 = $vm | select {$_.CustomFields.Item("test-System")}

$col.Att3 = $vm | select {$_.CustomFields.Item("test-Produkt")}

$myCol += $col

}

$mycol

VCP4,VCP5,VCP6
1 Solution

Accepted Solutions
LucD
Leadership
Leadership

That is due to the Select you use.
Try like this

$vms = Get-Cluster C01-Test* | Get-VM


$myCol = @()


foreach ($vm in $vms) {

    $col = "" | Select-Object Name, Att1, Att2, Att3

    $col.name = $vm.name

    $col.Att1 = $vm.CustomFields.Item("test-APP")

    $col.Att2 = $vm.CustomFields.Item("test-System")

    $col.Att3 = $vm.CustomFields.Item("test-Produkt")

    $myCol += $col

}


$mycol


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

0 Kudos
10 Replies
LucD
Leadership
Leadership

That is due to the Select you use.
Try like this

$vms = Get-Cluster C01-Test* | Get-VM


$myCol = @()


foreach ($vm in $vms) {

    $col = "" | Select-Object Name, Att1, Att2, Att3

    $col.name = $vm.name

    $col.Att1 = $vm.CustomFields.Item("test-APP")

    $col.Att2 = $vm.CustomFields.Item("test-System")

    $col.Att3 = $vm.CustomFields.Item("test-Produkt")

    $myCol += $col

}


$mycol


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

0 Kudos
vespavbb
Enthusiast
Enthusiast

cool thanks

i have a secound question and secound script...

the oupt is fine, I get all VMs with all Attributes. but how can i modify the $valueList to select only certian Attributes, mostly like the script before. just different

$valueList =@()

Get-cluster C01-Test | get-vm  | % {

for($i = 0; $i -lt $_.CustomFields.Count; $i ++ ){

$row = “” | Select vmname, FieldKey, FieldValue

$row.VMname = $_.Name

$row.FieldKey = $_.CustomFields.Keys[$i]

$row.FieldValue = $_.CustomFields.Values[$i]

$valueList += $row

}

}

$valueList

### maybe it works if i can do a select from the $valueList and select only vmname and some fieldkeys I want to

$valueList  | select-object vmname,  Fieldkey where value like ""TEST-Value"...

VCP4,VCP5,VCP6
0 Kudos
LucD
Leadership
Leadership

You could use a Where-clause.
Something like this

$valueList  |

where{$_.FieldKey -eq 'Your-CA'} |

select-object -Property *

You can also select multiple keys by adapting the Where-clause

$valueList  |

where{'CA1','CA2','CA3' -contains $_.FieldKey} |

select-object -Property *

And you also use the Where-clause on the Value instead of the Key

$valueList  |

where{$_.FieldValue -eq 'Test-Value'} |

select-object -Property *


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
vespavbb
Enthusiast
Enthusiast

ah ok thanks, thats nice

but I think the first script is easier

now lets get deeper.

If I modify the csv file ( only the FieldValue) and I want to import the csv file back to overwrite the values of all vm´s

how could I do it?

a foreach loop with set-annotation ??

$vms = Get-Cluster C01-Test* | Get-VM

$myCol = @()

foreach ($vm in $vms) {

    $col = "" | Select-Object Name, Att1, Att2, Att3

    $col.name = $vm.name

    $col.Att1 = $vm.CustomFields.Item("test-APP")

    $col.Att2 = $vm.CustomFields.Item("test-System")

    $col.Att3 = $vm.CustomFields.Item("test-Produkt")

    $myCol += $col

}

$mycol | Export-Csv “C:\00-Scripts\vms-attributes-value.csv” -NoTypeInformation

VCP4,VCP5,VCP6
0 Kudos
LucD
Leadership
Leadership

You could do something like this.
Wherever a Custom Attribute value in the CSV is different from the actual CA value on the VM, the script will update the value.

Import-Csv -Path .\your.csv -UseCulture -PipelineVariable row |

ForEach-Object -Process {

    $vm = Get-VM -Name $row.Name

    $row | Get-Member -MemberType NoteProperty |

    where{$_.Name -ne 'Name'} |

    ForEach-Object -Process {

        $ca = Get-Annotation -Entity $vm -CustomAttribute $_.Name

        if($ca.Value -ne $row."$($_.Name)"){

            Set-Annotation -Entity $vm -CustomAttribute $ca.Name -Value $row."$($_.Name)" -Confirm:$false

        }

    }

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

vespavbb
Enthusiast
Enthusiast

thanks Luc,

I will try

VCP4,VCP5,VCP6
0 Kudos
vespavbb
Enthusiast
Enthusiast

Hi Luc,

an other question, here is an example to export all attributes of all vms´. the output looks different, but ok.

How could i import this list and set it on all vm´s. Like a backup and restore thing...

$valueList =@()

Get-cluster  | get-vm  | % {

for($i = 0; $i -lt $_.CustomFields.Count; $i ++ ){

$row = “” | Select Name, FieldKey, FieldValue

$row.name = $_.Name

$row.FieldKey = $_.CustomFields.Keys[$i]

$row.FieldValue = $_.CustomFields.Values[$i]

$valueList += $row

}

}

$valueList | Export-Csv “C:\00-Scripts\exported-attributes-value.csv” -NoTypeInformation

VCP4,VCP5,VCP6
0 Kudos
LucD
Leadership
Leadership

You could do something like this.

The try-catch makes sure that the Custom Attribute is created, shouldn't it exist yet.

Import-Csv -Path 'C:\00-Scripts\exported-attributes-value.csv' -UseCulture |

ForEach-Object -Process {

    try{

        $ca = Get-CustomAttribute -Name $row.FieldKey -TargetType VirtualMachine -ErrorAction Stop

    }

    catch{

        $ca = New-CustomAttribute -Name $row.FieldKey -TargetType VirtualMachine -Confirm:$false

    }

    Get-Vm -Name $row.Name | Set-Annotation -CustomAttribute $ca -Value $row.FieldValue -Confirm:$false

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

vespavbb
Enthusiast
Enthusiast

 

Hi Luc,

this Script is great, but I have a new challenge, 

If a Attribute Value is empty this script will write an empty value to the Attribute, but I want to make sure, if it is empty , skip the SET

 

 

Import-Csv -Path .\your.csv -UseCulture -PipelineVariable row |
ForEach-Object -Process {

    $vm = Get-VM -Name $row.Name

    $row | Get-Member -MemberType NoteProperty |

    where{$_.Name -ne 'Name'} |

    ForEach-Object -Process {

        $ca = Get-Annotation -Entity $vm -CustomAttribute $_.Name

        if($ca.Value -ne $row."$($_.Name)"){

            Set-Annotation -Entity $vm -CustomAttribute $ca.Name -Value $row."$($_.Name)" -Confirm:$false

        }

    }

}

 

VCP4,VCP5,VCP6
0 Kudos
LucD
Leadership
Leadership

You can add this to the IF

if ($row."$($_.Name)" -ne '' -and $ca.Value -ne $row."$($_.Name)") {


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference