VMware Cloud Community
Zsoldier
Expert
Expert
Jump to solution

Trying Get Folder Path for VM in VC...

So here is what I'm trying to do. I've seen other posts relating to this, but they only seem to get the immediate parent path rather than the full path. We've basically setup a tree structure like this:

DATA_Center\business_service\SLDC\VM (SLDC = Software Development Cycle)

We've set it up this way so it is easier for admins to find systems related to a particular business service. When a SAN maintenance occurs, we like to inform the business service admins affected by the maintenance. So we basically build a spreadsheet and find all the LUN's attached to that particular SAN, find the VM's, then lookup folder path the VM lies under to find what what business service is affected. I've attached a photo of our VC folder setup as an example.

I was wondering if it was possible through powershell to get a VM's associated folder path like what I have above. I'm able to grab all other information needed, except the folder path. Here is what I have so far:

Get-VM | % {Get-View $_.ID} |

select name,

@{ Name="Datastore";Expression={(Get-Datastore -VM $_.Name).Name}}

(All VMDK's for a server reside on the same datastore so I have no need to look for or list other datastores for a single VM)

I tried messing w/ the script in the below thread for folder pathing, but I can't seem to get what I'm looking for.

http://communities.vmware.com/thread/170864

Chris Nakagaki (中垣浩一)
Blog: https://tech.zsoldier.com
Twitter: @zsoldier
Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Ok, the following script should do the trick.

One remark though, if a guest is stored over multiple datastores, only the first datastore will be reported.

$report = @()
Get-VM | Get-View | %{
  $row = "" | select Name, Datastore, Path
  $row.Name = $_.Name
  $row.Datastore = (Get-View $_.Datastore[0]).Summary.Name
  $current = Get-View $_.Parent
  $path = $_.Name
  do {
    $parent = $current
	if($parent.Name -ne "vm"){$path =  $parent.Name + "\" + $path}
	$current = Get-View $current.Parent
  } while ($current.Parent -ne $null)
  $row.Path = $path
  $report += $row
}
$report

Note1: that this is the view of the "blue" folders. The "Virtual Machines and Templates" view in the VI client.

Note2: the script suppresses the display of the hidden "vm" folder


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

View solution in original post

19 Replies
LucD
Leadership
Leadership
Jump to solution

Did you have a look at my script in .

It lists all guests with their complete path and that for the "Hosts & Clusters" view as well as for the "Virtual Machines & Templates" view (blue folders).


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

Reply
0 Kudos
Zsoldier
Expert
Expert
Jump to solution

I did not see that. I'll take a look now, thanks. (_)

Chris Nakagaki (中垣浩一)
Blog: https://tech.zsoldier.com
Twitter: @zsoldier
Reply
0 Kudos
Zsoldier
Expert
Expert
Jump to solution

So I finally got a few minutes to look over the script you referenced. It works great for going top down, but I'm looking to get folder pathing the other way around. From VM to top, you think this is doable?

Chris Nakagaki (中垣浩一)
Blog: https://tech.zsoldier.com
Twitter: @zsoldier
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

If I understand it correctly you want the list to be

<VM-name>\<folder-name>\<cluster-name>\<datacenter-name>

instead of

<datacenter-name>\<cluster-name>\<folder-name>\<VM-name>

.

If that is the case, the following script will do that:

function get-children-reverse($entity,$path){
  if($entity.Name -ne "vm"){
	$path = $entity.Name + "\" + $path
  }
  foreach($child in $entity.ChildEntity){
    $childfld = Get-View -Id $child
	switch($childfld.gettype().name){
	  "Folder" {
		Write-Host ($childfld.Name + "\" + $path)
		get-children-reverse $childfld $path
	  }
         "VirtualMachine"{
		$vm = $childfld.Name + "\" + $path
                Write-Host $vm
	  }
	  "Datacenter"{
		Write-Host ($childfld.Name + "\" + $path)
                get-children-reverse $childfld $path
	  }
	  "ClusterComputeResource" {
		Write-Host ($childfld.Name + "\" + $path)
                foreach($esxMoRef in $childfld.Host){
                     $esx = Get-View -Id $esxMorEF
		     $h = $esx.Name+ "\" + $childfld.Name + "\" + $path
		     Write-Host $h
		 }
	  }
     }
  }
}

# Virtual machines & Templates

Write-Host "Virtual Machines & Templates`n"
Get-Datacenter | %{
  $dc = Get-View -Id ($_).id
  $folder = Get-View -Id $dc.VmFolder
  get-children-reverse $folder $dc.Name
}

# Hosts & Clusters

Write-Host "`nHosts & Clusters`n"
Get-Datacenter | %{
  $dc = Get-View -Id ($_).id
  $folder = Get-View -Id $dc.HostFolder
  get-children-reverse $folder $dc.Name
}

Note: if you only want VMs and Templates to be listed it can be done easily by removing the Write-Host cmdlets in the get-children-reverse function except for the "VirtualMachine" case.


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

Reply
0 Kudos
Zsoldier
Expert
Expert
Jump to solution

Err, not exactly looking for just semantics. What I meant was using my above script, I'm looking for systems that are inside certain datastores. I think I can use your script, but I don't have an idea as how to reference the objects outputted by your function. For instance:

$VIserver = Read-Host "VC Server Name"

connect-viserver -server $VIserver

Get-VM | % {Get-View $_.ID} |

select name,

@{ Name="Datastore";Expression={(Get-Datastore -VM $_.Name) | where {$_.Name -inotmatch 'nfs_share'}}}

This outputs a table that lists a VM's Name and the name of the datastore where the VM resides. I want to add folder path to this. Using your function I was trying to do something like this:

@{ Name="Path";Expression={Get-Datacenter | % {(get-children $_.VmFolder $_.Name) | where {$_ -contains '$_'} }}}

Basically to only output the path that contains the VM's name. I'm pretty sure I'm screwed up on the where command if not elsewhere.

Chris Nakagaki (中垣浩一)
Blog: https://tech.zsoldier.com
Twitter: @zsoldier
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Before I start coding, you want a report showing

Name                         Path
VM1                          datacenter1\folder1\VM1
VM2                          datacenter1\folder2\VM2
VM3                          datacenter2\folder2\VM3

Did I understand it correctly now ?


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

Reply
0 Kudos
Zsoldier
Expert
Expert
Jump to solution

Yeppers. Datastore column as well.

Thanks.

Chris Nakagaki (中垣浩一)
Blog: https://tech.zsoldier.com
Twitter: @zsoldier
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Ok, the following script should do the trick.

One remark though, if a guest is stored over multiple datastores, only the first datastore will be reported.

$report = @()
Get-VM | Get-View | %{
  $row = "" | select Name, Datastore, Path
  $row.Name = $_.Name
  $row.Datastore = (Get-View $_.Datastore[0]).Summary.Name
  $current = Get-View $_.Parent
  $path = $_.Name
  do {
    $parent = $current
	if($parent.Name -ne "vm"){$path =  $parent.Name + "\" + $path}
	$current = Get-View $current.Parent
  } while ($current.Parent -ne $null)
  $row.Path = $path
  $report += $row
}
$report

Note1: that this is the view of the "blue" folders. The "Virtual Machines and Templates" view in the VI client.

Note2: the script suppresses the display of the hidden "vm" folder


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

Zsoldier
Expert
Expert
Jump to solution

Dude, that is awesome. Thanks.

Chris Nakagaki (中垣浩一)
Blog: https://tech.zsoldier.com
Twitter: @zsoldier
Reply
0 Kudos
mwent46
Contributor
Contributor
Jump to solution

Is it also possible to get the annotations with that.

thanx

Reply
0 Kudos
BaluVirigineni
Enthusiast
Enthusiast
Jump to solution

Hi LucD,

I am trying to move VMs to their respective folders after deploying from Template, however we have multiple folders by the same name in the Datacenter, hence tried your Get-Folder path..but didnt work for me. Can you help me in this.

I want to move VM like this Datacenter\Folder1\Folder2\Folder3..

Below is the PowerCLI Script I used, I just ran the script in PCLI and tried to ran Get-FolderByPath cmdlet,  but it is saying that there is no such cmdlet or function..

function Get-FolderByPath{

  <#

.SYNOPSIS  Retrieve folders by giving a path

.DESCRIPTION The function will retrieve a folder by it's

  path. The path can contain any type of leave (folder or

  datacenter).

.NOTES  Author:  Luc Dekens

.PARAMETER Path

  The path to the folder.

  This is a required parameter.

.PARAMETER Path

  The path to the folder.

  This is a required parameter.

.PARAMETER Separator

  The character that is used to separate the leaves in the

  path. The default is '/'

.EXAMPLE

  PS> Get-FolderByPath -Path "Folder1/Datacenter/Folder2"

.EXAMPLE

  PS> Get-FolderByPath -Path "Folder1>Folder2" -Separator '>'

#>

  param(

  [CmdletBinding()]

  [parameter(Mandatory = $true)]

  [System.String[]]${Path},

  [char]${Separator} = '/'

  )

  process{

    if((Get-PowerCLIConfiguration).DefaultVIServerMode -eq "Multiple"){

      $vcs = $defaultVIServers

    }

    else{

      $vcs = $defaultVIServers[0]

    }

    foreach($vc in $vcs){

      foreach($strPath in $Path){

        $root = Get-Folder -Name Datacenters -Server $vc

        $strPath.Split($Separator) | %{

          $root = Get-Inventory -Name $_ -Location $root -Server $vc -NoRecursion

          if((Get-Inventory -Location $root -NoRecursion | Select -ExpandProperty Name) -contains "vm"){

            $root = Get-Inventory -Name "vm" -Location $root -Server $vc -NoRecursion

          }

        }

        $root | where {$_ -is [VMware.VimAutomation.ViCore.Impl.V1.Inventory.FolderImpl]}|%{

          Get-Folder -Name $_.Name -Location $root.Parent -Server $vc

        }

      }

    }

  }

}

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

See my reply (with example) on the other thread where you raised this question.


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

Reply
0 Kudos
rachappachalmi
Enthusiast
Enthusiast
Jump to solution

Hi LucD,

I also have the same requirement as this thread but I need to list all the datastore where VMs active files are residing, because SimpliVity restore dont support if the active files of the VMs are in multiple folders in same datastore or different datastores. can you help me with this pls.

Reply
0 Kudos
bansne
Enthusiast
Enthusiast
Jump to solution

Is there a way to ignore name of vm in end from output of path please

only <dc>\<parent>\<child>\ 

currently i am getting  <dc>\<parent>\<child>\<VM name>

@LucD 

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You mean like this?

$report = @()
Get-View -ViewType VirtualMachine | ForEach-Object -Process {
  $row = "" | Select-Object -Property Name, Datastore, Path
  $row.Name = $_.Name
  $row.Datastore = (Get-View $_.Datastore[0]).Summary.Name
  $current = Get-View $_.Parent
  $path = ''
  do {
    $parent = $current
    if ($parent.Name -ne "vm") { 
      if($path -ne ''){
        $path = $parent.Name + "\" + $path
      }
      else {
        $path = $parent.Name
      }
    }
    $current = Get-View $current.Parent
  } while ($current.Parent -ne $null)

  $row.Path = $path
  $report += $row
}
$report


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

Reply
0 Kudos
bansne
Enthusiast
Enthusiast
Jump to solution

Exactly but only one additional thing i need report  for specific vms only in vc

 

Get-VM -Name $VM | Get-View maybe?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You can use the Filter parameter on Get-View, but remember that it uses a RegEx.
For example

# Name in a variable
Get-View -ViewType VirtualMachine -Filter @{Name=$vm}
# Starting with "VM"
Get-View -ViewType VirtualMachine -Filter @{Name="^VM"}
# Or
Get-View -ViewType VirtualMachine -Filter @{Name="vm1|vm2|vm3"}


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

G_e_r_g
Contributor
Contributor
Jump to solution

I have been struggling with this for a couple days.  We have an environment that uses vCenter Enhanced Linked Mode (linking 4 different vCenters across the country).  VMware doesn't ensure uniqueness of the parent value.  I have the same "parent" in different vCenters, so the "path" I get ends ups confusing/combining different vCenters.  Is there any way to figure out the path when the parent value might be in more than 1 vCenter??

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

When you make the vCenter part of the path, that should create uniqueness I assume?


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

Reply
0 Kudos