<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Powershell Archives - VirtJunkie</title>
	<atom:link href="/category/automation/scripting/powershell/feed/" rel="self" type="application/rss+xml" />
	<link>/category/automation/scripting/powershell/</link>
	<description>Virtualization, Automation, and anything else that might be on my mind</description>
	<lastBuildDate>Mon, 15 Aug 2022 13:27:41 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.5.2</generator>

<image>
	<url>/wp-content/uploads/2020/04/cropped-vj4-150x150.png</url>
	<title>Powershell Archives - VirtJunkie</title>
	<link>/category/automation/scripting/powershell/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Authenticate to vRealize Orchestrator API using PowerShell</title>
		<link>/2022/08/15/authenticate-to-vrealize-orchestrator-api-using-powershell/</link>
					<comments>/2022/08/15/authenticate-to-vrealize-orchestrator-api-using-powershell/#respond</comments>
		
		<dc:creator><![CDATA[Jon]]></dc:creator>
		<pubDate>Mon, 15 Aug 2022 13:27:40 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[VMware]]></category>
		<guid isPermaLink="false">https://www.virtjunkie.com/?p=1479</guid>

					<description><![CDATA[<p>I&#8217;m working on a project that requires direct interaction with the vRO API from a third party system. Maybe I&#8217;m getting less effective at using Google in my old age, but I had a heck of a time finding good solid code for authenticating to the API using anything, including PowerShell. Typically I&#8217;d use Invoke-vRARestMethod [&#8230;]</p>
<p>The post <a href="/2022/08/15/authenticate-to-vrealize-orchestrator-api-using-powershell/">Authenticate to vRealize Orchestrator API using PowerShell</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p><br></p>



<div class="wp-block-media-text alignwide has-media-on-the-right is-stacked-on-mobile is-vertically-aligned-top" style="grid-template-columns:auto 36%"><figure class="wp-block-media-text__media"><img fetchpriority="high" decoding="async" width="925" height="1024" src="https://www.virtjunkie.com/wp-content/uploads/2022/08/image-925x1024.png" alt="" class="wp-image-1481 size-full" srcset="/wp-content/uploads/2022/08/image-925x1024.png 925w, /wp-content/uploads/2022/08/image-271x300.png 271w, /wp-content/uploads/2022/08/image-768x850.png 768w, /wp-content/uploads/2022/08/image-1388x1536.png 1388w, /wp-content/uploads/2022/08/image.png 1641w" sizes="(max-width: 925px) 100vw, 925px" /></figure><div class="wp-block-media-text__content">
<p>I&#8217;m working on a project that requires direct interaction with the vRO API from a third party system. Maybe I&#8217;m getting less effective at using Google in my old age, but I had a heck of a time finding good solid code for authenticating to the API using anything, including PowerShell. </p>



<p>Typically I&#8217;d use <a rel="noreferrer noopener" href="https://jakkulabs.github.io/PowervRA/functions/Invoke-vRARestMethod/" target="_blank">Invoke-vRARestMethod </a>from <a rel="noreferrer noopener" href="https://github.com/jakkulabs/PowervRA" target="_blank">PowerVRA</a> for this, but unfortunately I had some additional requirements that mandate me using a bearer token.</p>



<p>As a point of reference, you can view all of of the available APIs for vRealize Automation by navigating to this url: https://{your-vra-url}/automation-ui/api-docs/. We&#8217;ll be working with the &#8220;Orchestrator&#8221; API</p>
</div></div>



<p>The function below will return a bearer token, which you can use in future API calls to vRA.</p>



<script src="https://gist.github.com/jonhowe/36304d54b77e794427534b8b38f0bd0d.js"></script>



<p>Param&#8217;s:<br>Line 3: vra_server &#8211; the fqdn of your vRA 8 instance<br>Line 4: password &#8211; password associated with your vRA 8 account used to authenticate. As mentioned, please be smart here. Plantext passwords are bad.<br>Line 5: username &#8211; Unlike vRA 7, vRA 8 needs you to split your username and domain apart. For example, in vRA 7 you&#8217;d authenticate using the username jon.smith@rainpole.com, where in vRA 8 you authenticate using just the username jon.smith<br>Line 6: domain &#8211; This is where the domain goes (Example: rainpole.com)<br><br>Lines 14-24: We&#8217;re setting the body up to be included in the rest request. There&#8217;s some special formatting required so we&#8217;re using the replace method to modify the string.<br><br>Line 27: Build a simple variable with the URI used for authentication. More can be found on this in the API documentation mentioned above.<br><br>Lines 29-35: Make the API call, build the bearer token (essentially add the word &#8220;Bearer &#8221; to the beginning of the authentication token), and return it.</p>



<p>Short and sweet. I&#8217;ll be adding some more snippets and problems in the future.</p>
<p>The post <a href="/2022/08/15/authenticate-to-vrealize-orchestrator-api-using-powershell/">Authenticate to vRealize Orchestrator API using PowerShell</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2022/08/15/authenticate-to-vrealize-orchestrator-api-using-powershell/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Deploy VCSA via PowerShell</title>
		<link>/2020/03/16/deploy-vcsa-via-powershell/</link>
					<comments>/2020/03/16/deploy-vcsa-via-powershell/#comments</comments>
		
		<dc:creator><![CDATA[Jon]]></dc:creator>
		<pubDate>Mon, 16 Mar 2020 13:00:00 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[VMware]]></category>
		<guid isPermaLink="false">http://www.virtjunkie.com/?p=866</guid>

					<description><![CDATA[<p>I've been spending a lot of time lately thinking about how organizations can provide services can operationalize the principles behind Infrastructure as Code in a way that's accessible. In my experience, if a tool isn't easy to use, it won't be used. This is one of the biggest barriers to organizations (and companies that provide services, like mine) benefiting from IaC. It's my intention that this script will achieve a high level of usability and will also generate and consume reusable code for future use.</p>
<p>The post <a href="/2020/03/16/deploy-vcsa-via-powershell/">Deploy VCSA via PowerShell</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-image is-style-default"><figure class="alignleft size-large is-resized"><img decoding="async" src="https://new.virtjunkie.com/wp-content/uploads/2014/04/powercli-icon.jpg" alt="" class="wp-image-585" width="101" height="101"/></figure></div>



<p>I&#8217;ve been spending a lot of time lately thinking about how organizations can provide services can operationalize the principles behind Infrastructure as Code in a way that&#8217;s accessible. In my experience, if a tool isn&#8217;t easy to use, it won&#8217;t be used. This is one of the biggest barriers to organizations (and companies that provide services, like mine) benefiting from IaC. It&#8217;s my intention that this script will achieve a high level of usability and will also generate and consume reusable code for future use.</p>



<span id="more-866"></span>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="has-text-align-center wp-block-heading">Recap</h2>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-1 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h3 class="wp-block-heading">Challenge</h3>



<p>You want to use Infrastructure as Code principles to deploy your vCenter Server, but you want to ensure that your solution is accessible without code as well.</p>
</div></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-group" id="Solution"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h3 class="wp-block-heading">Solution</h3>



<p>Create a script that gathers all relevant information for a VCSA deployment via the the <a rel="noreferrer noopener" href="https://docs.vmware.com/en/VMware-vSphere/6.7/com.vmware.vcenter.install.doc/GUID-4CCC26AB-D2E4-40D0-97A8-804FB6274009.html" target="_blank">vcsa-deploy</a> and generates the JSON file that the utility consumes, while also allowing for the download of the VCSA ISO from a web server.</p>
</div></div>
</div>
</div>
</div></div>



<div class="wp-block-group" id="Background"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">Background</h2>



<p>In order for this to fit my definition of infrastructure as code, we should be able to define all details of the vCenter in a structured format. Additionally, we should not assume that the vCenter installer is local, and should pull it from an external location if we need it to. While the vcsa-deploy utility can handle the installation of the vCenter, I&#8217;ve found most people don&#8217;t like it. </p>



<p>With this script, I allow a VI  admin to fill out all relevant details of the vCenter in a spreadsheet. The script will then access the spreadsheet directly, and generate the JSON file used by vcsa-deploy. As a bonus, it will call the vcsa-deploy utility and kick off the actual deployment.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="233" src="https://www.virtjunkie.com/wp-content/uploads/2020/03/2020-03-15_12-07-1024x233.png" alt="" class="wp-image-872" srcset="/wp-content/uploads/2020/03/2020-03-15_12-07-1024x233.png 1024w, /wp-content/uploads/2020/03/2020-03-15_12-07-300x68.png 300w, /wp-content/uploads/2020/03/2020-03-15_12-07-768x175.png 768w, /wp-content/uploads/2020/03/2020-03-15_12-07.png 1160w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Screenshot of the excel file <a rel="noreferrer noopener" href="https://github.com/jonhowe/Virtjunkie.com/tree/master/VCSA-AutoDeploy" target="_blank">on my GitHub account</a>.</figcaption></figure>
</div></div>



<div class="wp-block-group" id="Demo"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">Demo</h2>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="726" src="https://www.virtjunkie.com/wp-content/uploads/2020/03/image-1024x726.png" alt="" class="wp-image-944" srcset="/wp-content/uploads/2020/03/image-1024x726.png 1024w, /wp-content/uploads/2020/03/image-300x213.png 300w, /wp-content/uploads/2020/03/image-768x544.png 768w, /wp-content/uploads/2020/03/image.png 1043w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Quick demo &#8211; the installer up to where it deploys the VCSA</figcaption></figure>
</div></div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-2 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-group" id="Features"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">Features</h2>



<ul><li>Validate Password Complexity</li><li>Provide Input via Excel Spreadsheet or JSON file</li><li>Download ISO, extract contents</li><li>Deploy vCenter to either ESXi or vCenter</li></ul>
</div></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-group" id="Requirements"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">Requirements</h2>



<ul><li><a rel="noreferrer noopener" href="https://github.com/dfinke/ImportExcel" target="_blank">ImportExcel module</a></li><li>7-zip</li><li>URL to a vCenter Server 6.7 Appliance ISO</li><li>Standard vCenter Prerequisites (forward/reverse DNS, space, networking, etc) (<a rel="noreferrer noopener" aria-label="link (opens in a new tab)" href="https://docs.vmware.com/en/VMware-vSphere/6.7/com.vmware.vcenter.upgrade.doc/GUID-752FCA83-1A9B-499E-9C65-D5625351C0B5.html" target="_blank">link</a>)</li></ul>
</div></div>
</div>
</div>



<div class="wp-block-group" id="Code-Review"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">Code Review</h2>



<p>The code can be located on my <a rel="noreferrer noopener" aria-label="github account (opens in a new tab)" href="https://github.com/jonhowe/Virtjunkie.com/tree/master/VCSA-AutoDeploy" target="_blank">github account</a>. As per usual, let&#8217;s go through the code.<br><br><strong>Lines 1-31</strong><br>Documentation<br><br><strong>Lines 32-58</strong><br>Define parameters<br><br><strong>Lines 66-91</strong><br>Download and install the ISO<br><br><strong>Lines</strong> <strong>93-130</strong><br>Extract the ISO using 7-zip<br><br><strong>Lines 133-139</strong><br>Use import-excel to grab sections of the spreadsheet. There&#8217;s a bit of overhead, but my goal here was for the spreadsheet to look good.<br><br><strong>Lines 141-152</strong><br>Validate the password specified meets VMware&#8217;s requirements for the VCSA<br><br><strong>Lines 154-172</strong><br>Detect the OS<br><br><strong>Lines 176-224</strong><br>Determine whether we are deploying to a vCenter or an ESXi host and create the respective JSON. This is the only difference between deploying to a vCenter or an ESXi host.<br><br><strong>Lines 226-298</strong><br>Create a hashtable used for to create the rest of parameters common to a the json used by vcsa-deploy.<br><br><strong>Lines 300-312</strong><br>Write the JSON file to disk<br><br><strong>Lines 314-333</strong><br>Begin the install<br><br><strong>Lines 335-343</strong><br>Determine if the install was successful. If it failed, print out the error messages.</p>
</div></div>



<div class="wp-block-group" id="Code"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">Code</h2>



<pre class="urvanov-syntax-highlighter-plain-tag">#Github: https://github.com/jonhowe/Virtjunkie.com/tree/master/VCSA-AutoDeploy
#Blog Post: http://www.virtjunkie.com/deploy-vcsa-via-powershell/

&amp;lt;#
.SYNOPSIS
Install the VMware vCenter Server Appliance based on input from a Microsoft Excel File

.DESCRIPTION
This script will install the VMware vCenter Server Appliance based on input from a Microsoft Excel File.

.PARAMETER ForceDownload
Switch parameter that will force a (re) download and extract of the ISO

.PARAMETER URI
This is the URL of the vCenter Installer ISO

.PARAMETER Workspace
Absolute path to the directory that will be used as a workspace. The vCenter ISO will be downloaded there, and will be
extracted there as well.

.PARAMETER DeploymentTarget
Location that the new VCSA will be deployed to.
Valid options are: ESXi, vCenter

.PARAMETER ExcelFile
Absolute path to the Excel file that contains the parameters required for vCenter to be built

.PARAMETER 7z
Absolute path path to the 7z binary
#&gt;
#Requires -modules Microsoft.powershell.archive,importexcel
[CmdletBinding()]
param (
    [switch]$ForceDownload
    ,
    $URI = &quot;http://jondesktop.home.lan:8123/files/VMware/VSMRepo/dlg_VC67U3B/VMware-VCSA-all-6.7.0-15132721.iso&quot;
    ,
    [Parameter(Mandatory=$true)]
    [ValidateScript( {
            if ( -Not ($_ | Test-Path) ) {
                throw &quot;File or folder does not exist&quot;
            }
            return $true
        })]
    $Workspace
    ,
    [validateset(&quot;vCenter&quot;, &quot;ESXi&quot;)]
    $deploymentTarget
    ,
    [ValidateScript( { Test-Path $_ })]
    [string]
    $ExcelFile = &quot;/home/jhowe/git/Personal/AutomatedLab/JonAutoLab/HostDetails.xlsx&quot;
    ,
    [Parameter(Mandatory=$true)]
    [ValidateScript( { Test-Path $_ })]
    [string]
    $7z = '/usr/bin/7z'
)
$ErrorActionPreference = 'Stop'

#region Download and Extract the ISO
$VCSA_Installer_Archive = $workspace + ($uri.Split('/')[-1])
$VCSA_Extracted_Directory = ($VCSA_Installer_Archive.Split(&quot;.iso&quot;)[0])
$VCSA_CLI_Installer_Path = ($VCSA_Extracted_Directory + &quot;/vcsa-cli-installer/&quot;)

#Download the VCSA only if it doesn't already exist
if ((Test-Path $VCSA_Installer_Archive) -eq $false -or $forcedownload) {
    $filesize = (Invoke-WebRequest $uri -Method Head).Headers.'Content-Length'
    [int]$WebServerFileSize = ([convert]::ToInt64($filesize, 10)) / 1024

    Write-Output &quot;Downloading VCSA Installer&quot;
    $wc = New-Object System.Net.WebClient
    $wc.DownloadFileAsync($uri, $VCSA_Installer_Archive)

    #The following loop will print the progressof the download every 15 seconds
    $incomplete = $true
    while ($incomplete) {
        $CurrentSize = ((Get-Item $VCSA_Installer_Archive).length) / 1024
    
        if ($CurrentSize -eq $WebServerFileSize) {
            $incomplete = $false
        }
        else {
            Write-Output &quot;File Download Size is $([math]::round($CurrentSize,0)) / $($WebServerFileSize) ($(($CurrentSize / $WebServerFileSize).ToString(&quot;P&quot;) )%)&quot;
            Start-Sleep -Seconds 15
        }
    }
}
else {
    Write-Output &quot;VCSA Installer already exists&quot;    
}

#Extract the VCSA only if the directory it should be extracted to doesn't already exist
if ((Test-Path ($VCSA_Extracted_Directory)) -eq $false -or $forcedownload) {
    Write-Output &quot;Unzipping VCSA&quot;
    #Expand-Archive -LiteralPath $VCSA_Installer_Archive -destinationpath $workspace

    Write-Output &quot;Extracting the ISO now...&quot;
    $arguments = &quot;x -bb0 -bd -y -o$($VCSA_Extracted_Directory) $($VCSA_Installer_Archive)&quot;
    Write-Verbose -Message ($7z + &quot; &quot; + $arguments)

    $pinfo = New-Object System.Diagnostics.ProcessStartInfo
    $pinfo.FileName = $7z
    $pinfo.RedirectStandardError = $true
    $pinfo.RedirectStandardOutput = $true
    $pinfo.UseShellExecute = $false
    $pinfo.Arguments = $arguments
    $p = New-Object System.Diagnostics.Process
    $p.StartInfo = $pinfo
    $p.Start() | Out-Null
    $p.WaitForExit()
    $7z_stdout = $p.StandardOutput.ReadToEnd()
    $7z_stderr = $p.StandardError.ReadToEnd()

    $7z_stdout | out-file -Path ($workspace + &quot;7z-stdout.txt&quot;)
    $7z_stderr | out-file -Path ($workspace + &quot;7z-stderr.txt&quot;)

    if ($p.ExitCode -ne 0) {
        Write-Output &quot;There was an error...&quot;
        Write-Output &quot;Process finished with exit code $($p.ExitCode)&quot;
        Write-Output &quot;Log data written to: $($workspace)7z-stdout.txt and $($workspace)7z-stderr.txt&quot;
        $7z_stderr
    }
    else {
        Write-Output &quot;Extraction completed successfully.&quot;
    }
}
else {
    Write-Output &quot;VCSA has already been unzipped&quot;
}
#endregion Download and Extract the ISO

#region import excel file into sections and validate input
$targettype = Import-Excel $excelfile -WorksheetName vCenter -StartRow 1 -EndRow 2 -StartColumn 1 -EndColumn 1
$targetinfo = Import-Excel $excelfile -WorksheetName vCenter -StartRow 1 -EndRow 2 -StartColumn 2 -EndColumn 8
$applianceinfo = Import-Excel $excelfile  -WorksheetName vCenter -StartRow 4 -EndRow 5 -StartColumn 1 -EndColumn 3
$networkinfo = Import-Excel $excelfile  -WorksheetName vCenter -StartRow 7 -EndRow 8 -StartColumn 1 -EndColumn 7
$os = Import-Excel $excelfile  -WorksheetName vCenter -StartRow 10 -EndRow 11 -StartColumn 1 -EndColumn 3 
$sso_ciep = Import-Excel $excelfile  -WorksheetName vCenter -StartRow 13 -EndRow 14 -StartColumn 1 -EndColumn 3

#Ensure the password specified has the appropriate complexity based on vCenter's requirements
$input = ($os.&quot;vCenter Root Password&quot;)
if (($input -cmatch '[a-z]') `
        -and ($input -match '\d') `
        -and ($input.length -ge 8) `
        -and ($input -match '!|@|#|%|^|&amp;amp;|$')) {
    Write-Output &quot;Password complexity is sufficient. Continuing.&quot;
}
else {
    Write-Output &quot;$input does not meet complexity requirements. Password must be at least 8 characters, include one numeric, and one special character.&quot;
    exit
}

$deploymentTarget = $targettype.'vCenter or ESXi'

#endregion import excel file into sections and validate input

#region Detect the OS (Windows, Linux, OSX)
if ($IsWindows -or $ENV:OS) {
    $installer_dir = ($VCSA_CLI_Installer_Path + &quot;win32/&quot;)
    $installer = ($installer_dir + &quot;vcsa-deploy.exe&quot;)
} 
elseif ($IsLinux) {
    $installer_dir = ($VCSA_CLI_Installer_Path + &quot;lin64/&quot;)
    $installer = ($installer_dir + &quot;vcsa-deploy&quot;)
    chmod -R +x $workspace
}
elseif ($IsMacOS) {
    $installer_dir = ($VCSA_CLI_Installer_Path + &quot;mac/&quot;)
    $installer = ($installer_dir + &quot;vcsa-deploy&quot;)
}
#endregion Detect the OS (Windows, Linux, OSX)

#region Create and format the JSON

#Detect whether we are deploying to vCenter or ESXi
switch ($deploymentTarget) {
    'vCenter' {
        Write-Output &quot;Deploying to vCenter&quot;
        $target = [ordered] @{
            vc = [ordered]@{
                __comments         = @(&quot;'datacenter' must end with a datacenter name, and only with a datacenter name. &quot;,
                    &quot;'target' must end with an ESXi hostname, a cluster name, or a resource pool name. &quot;,
                    &quot;The item 'Resources' must precede the resource pool name. &quot;,
                    &quot;All names are case-sensitive. &quot;,
                    &quot;For details and examples, refer to template help, i.e. vcsa-deploy {install|upgrade|migrate} --template-help&quot;)
                hostname           = $targetinfo.&quot;Target Host or vCenter&quot;
                username           = $targetinfo.&quot;Username&quot;
                password           = $targetinfo.&quot;Password&quot;
                deployment_network = $targetinfo.&quot;PortGroup&quot;

                &amp;lt;#
                datacenter         = @(&quot;Folder 1 (parent of Folder 2)&quot;,
                                        &quot;Folder 2 (parent of Your Datacenter)&quot;,
                                        &quot;Your Datacenter&quot;)
                #&gt;
                datacenter         = $targetinfo.&quot;Datacenter (vCenter Only)&quot;
                datastore          = $targetinfo.&quot;Datastore&quot;
                &amp;lt;#
                target             = @( &quot;Folder A (parent of Folder B)&quot;,
                                        &quot;Folder B (parent of Your ESXi Host, or Cluster)&quot;,
                                        &quot;Your ESXi Host, or Cluster&quot;)
                #&gt;
                target             = $targetinfo.&quot;Cluster Name (vCenter Only)&quot;
            }
        }
    }
    'ESXi' {
        Write-Output &quot;Deploying to ESXi&quot;
        $target = [ordered] @{
            esxi = [ordered]@{
                hostname           = $targetinfo.&quot;Target Host or vCenter&quot;
                username           = $targetinfo.&quot;Username&quot;
                password           = $targetinfo.&quot;Password&quot;
                deployment_network = $targetinfo.&quot;PortGroup&quot;
                datastore          = $targetinfo.&quot;Datastore&quot;
            }
        }
    }
    Default {
        Write-Error &quot;Invalid Deployment Target Specified. Exiting.&quot;
        exit
    }
}

&amp;lt;#
I'm aware that others have imported the json file provided by the installer...
I don't have a great reason that I didn't do that.. maybe I'm just different :-)
Either way - we are simply generating a hashtable here, and then writing it to a file.
#&gt;
$common_properties = @{
    appliance = [ordered]@{
        __comments        = @(&quot;You must provide the 'deployment_option' key with a value, which will affect the VCSA's configuration parameters, such as the VCSA's number of vCPUs, the memory size, the storage size, and the maximum numbers of ESXi hosts and VMs which can be managed. For a list of acceptable values, run the supported deployment sizes help, i.e. vcsa-deploy --supported-deployment-sizes&quot;)
        thin_disk_mode    = $applianceinfo.&quot;Thin Disk?&quot;
        deployment_option = $applianceinfo.&quot;vCenter Size&quot;
        name              = $applianceinfo.&quot;VM Name&quot;
    }
    network   = [ordered]@{
        ip_family   = $networkinfo.&quot;IP v4 or v6&quot;
        mode        = $networkinfo.&quot;IP Allocation Mode&quot;
        ip          = $networkinfo.&quot;IP Address&quot;
        dns_servers = @($networkinfo.'DNS Server List').split(&quot;,&quot;)
        prefix      = ($networkinfo.&quot;CIDR Block&quot;).tostring()
        gateway     = $networkinfo.&quot;Default Gateway&quot;
        system_name = $networkinfo.&quot;vCenter Hostname&quot;
    }
    os        = [ordered]@{
        password    = $os.&quot;vCenter Root Password&quot;
        ntp_servers = $os.&quot;NTP Servers&quot;
        ssh_enable  = $os.&quot;Enable SSH By Default?&quot;
    }
    sso       = [ordered]@{
        password    = $sso_ciep.&quot;SSO Password&quot;
        domain_name = $sso_ciep.&quot;SSO Domain Name&quot;
    }
}

$combined = [ordered]@{
    __version  = &quot;2.13.0&quot;
    __comments = &quot;Sample template to deploy a vCenter Server Appliance with an embedded Platform Services Controller on an ESXi host.&quot;
    new_vcsa   = $target + $common_properties
    ceip       = [ordered]@{
        description = @{
            __comments = @(&quot;++++VMware Customer Experience Improvement Program (CEIP)++++&quot;,
                &quot;VMware's Customer Experience Improvement Program (CEIP) &quot;,
                &quot;provides VMware with information that enables VMware to &quot;,
                &quot;improve its products and services, to fix problems, &quot;,
                &quot;and to advise you on how best to deploy and use our &quot;,
                &quot;products. As part of CEIP, VMware collects technical &quot;,
                &quot;information about your organization's use of VMware &quot;,
                &quot;products and services on a regular basis in association &quot;,
                &quot;with your organization's VMware license key(s). This &quot;,
                &quot;information does not personally identify any individual. &quot;,
                &quot;&quot;,
                &quot;Additional information regarding the data collected &quot;,
                &quot;through CEIP and the purposes for which it is used by &quot;,
                &quot;VMware is set forth in the Trust &amp;amp; Assurance Center at &quot;,
                &quot;http://www.vmware.com/trustvmware/ceip.html . If you &quot;,
                &quot;prefer not to participate in VMware's CEIP for this &quot;,
                &quot;product, you should disable CEIP by setting &quot;,
                &quot;'ceip_enabled': false. You may join or leave VMware's &quot;,
                &quot;CEIP for this product at any time. Please confirm your &quot;,
                &quot;acknowledgement by passing in the parameter &quot;,
                &quot;--acknowledge-ceip in the command line.&quot;,
                &quot;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++&quot;)       
        }
        
        settings    = @{ 
            #TODO I believe an extra member is needed if this is enabled
            ceip_enabled = $sso_ciep.&quot;Enable CIEP?&quot;
        }
    }
}

$json = $combined | ConvertTo-Json -Depth 99
$fixtrue = $json.replace(&quot;`&quot;true`&quot;&quot;, &quot;true&quot;)
$FinalJSON = $fixtrue.replace(&quot;`&quot;false`&quot;&quot;, &quot;false&quot;)
#endregion Create and format the JSON

#region Write the json file to disk
switch ($deploymentTarget) {
    'vCenter' {  
        $FinalConfigFile = $workspace + &quot;$(($FinalJSON | convertfrom-json).new_vcsa.vc.hostname).json&quot;
    }
    'ESXi' {  
        $FinalConfigFile = $workspace + &quot;$(($FinalJSON | convertfrom-json).new_vcsa.esxi.hostname).json&quot;
    }
    Default { }
}
$FinalJSON | out-file -FilePath $FinalConfigFile
Write-Output (&quot;JSON file written to: &quot; + $FinalConfigFile)
#endregion Write the json file to disk

#region Start the install
Write-Output &quot;Beginning install now.. this will take a few minutes. Please wait.&quot;
$arguments = &quot;install --accept-eula --no-ssl-certificate-verification --log-dir $($VCSA_CLI_Installer_Path) $($FinalConfigFile)&quot;

$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = $installer
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = $arguments
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()

$stdout | out-file -Path ($VCSA_CLI_Installer_Path + &quot;stdout.txt&quot;)
$stderr | out-file -Path ($VCSA_CLI_Installer_Path + &quot;stderr.txt&quot;)
#endregion Start the install

if ($p.ExitCode -ne 0) {
    Write-Output &quot;There was an error...&quot;
    Write-Output &quot;Process finished with exit code $($p.ExitCode)&quot;
    Write-Output &quot;Log data written to: $($VCSA_CLI_Installer_Path)stdout.txt and $($VCSA_CLI_Installer_Path)stderr.txt&quot;
    $stderr
}
else {
    Write-Output &quot;Install completed successfully.&quot;
}</pre>
</div></div>



<div class="wp-block-group" id="WhatsNext"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">What&#8217;s next?</h2>



<p>Good question! vSphere 7 is releasing vCenter Server Profiles and Image Cluster Management.  Creating tools that can consume these new features will be helpful.<br><br>I&#8217;m working on template management using <a rel="noreferrer noopener" aria-label="packer (opens in a new tab)" href="https://packer.io/" target="_blank">Hashicorp&#8217;s Packer</a> and will be posting some of my work on that soon. In addition, I have done some work on <a rel="noreferrer noopener" aria-label="Hashicorp's Terraform (opens in a new tab)" href="https://www.terraform.io/" target="_blank">Hashicorp&#8217;s Terraform</a> for deploying lab VMs that I&#8217;ll share too. Finally &#8211; I&#8217;ve got a few skeleton <a rel="noreferrer noopener" aria-label="Ansible Playbooks (opens in a new tab)" href="https://www.ansible.com/" target="_blank">Ansible Playbooks</a> that I&#8217;m working on for configuration of the lab VMs, as well as a playbook for doing high level configuration of a bare vCenter. So in short &#8211; lots more coming!</p>
</div></div>



<p>Thanks for viewing,<br>Jon</p>
<p>The post <a href="/2020/03/16/deploy-vcsa-via-powershell/">Deploy VCSA via PowerShell</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2020/03/16/deploy-vcsa-via-powershell/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>Validate Network Connectivity Across A VMware Cluster</title>
		<link>/2019/10/21/vsphere-test-cluster-connectivity/</link>
					<comments>/2019/10/21/vsphere-test-cluster-connectivity/#respond</comments>
		
		<dc:creator><![CDATA[Jon]]></dc:creator>
		<pubDate>Mon, 21 Oct 2019 23:45:26 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[VMware]]></category>
		<guid isPermaLink="false">http://www.virtjunkie.com/?p=818</guid>

					<description><![CDATA[<p>It&#8217;s the network team&#8217;s fault&#8230; The Scenario Imagine you have an environment that has hundreds of VLANs. When you build a new cluster, there&#8217;s a real possibility that one host out of many is mis-configured on just a single port group or VLAN. It&#8217;s a pretty simple issue, but it&#8217;s like finding a needle in [&#8230;]</p>
<p>The post <a href="/2019/10/21/vsphere-test-cluster-connectivity/">Validate Network Connectivity Across A VMware Cluster</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<blockquote class="wp-block-quote is-style-large is-layout-flow wp-block-quote-is-layout-flow"><p>It&#8217;s the network team&#8217;s fault&#8230;</p></blockquote>



<h2 class="wp-block-heading">The  Scenario</h2>



<p>Imagine you have an environment that has hundreds of VLANs. When you build a new cluster, there&#8217;s a real possibility that one host out of many is mis-configured on just a single port group or VLAN. It&#8217;s a pretty simple issue, but it&#8217;s like finding a needle in a haystack. Because of that, it&#8217;s incredibly difficult to troubleshoot, so I wrote a script to run through every ESXi host, and test connectivity on each port group.</p>



<span id="more-818"></span>



<h2 class="wp-block-heading">How do we achieve this?</h2>



<p>To recap, the goal here is to test network connectivity on all VLANs on all ESXi hosts in a cluster. The best way to do this is by creating a VMKernel port on each Port Group, and pinging a separate IP on the network <em>from</em> that VMKernel port. Once the ping results are recorded, the VMKernel port is deleted. Rinse and repeat for every VLAN on every ESXi host. The script will pull all info required for creating the VMKernel ports from a CSV file.</p>



<h2 class="wp-block-heading">Example Output</h2>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="762" height="262" src="https://www.virtjunkie.com/wp-content/uploads/2019/10/image-1.png" alt="" class="wp-image-836" srcset="/wp-content/uploads/2019/10/image-1.png 762w, /wp-content/uploads/2019/10/image-1-300x103.png 300w" sizes="(max-width: 762px) 100vw, 762px" /><figcaption>This is an example of the output you will get from running this script</figcaption></figure>



<h2 class="wp-block-heading">CSV File Details</h2>



<p>The CSV file will contain the following fields: IP,&nbsp;GW,&nbsp;PG,&nbsp;NetMask,&nbsp;VLAN. Each row in the CSV will contain deails for a single VMKernel port. Here&#8217;s an example:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="555" height="81" src="https://www.virtjunkie.com/wp-content/uploads/2019/10/image.png" alt="" class="wp-image-821" srcset="/wp-content/uploads/2019/10/image.png 555w, /wp-content/uploads/2019/10/image-300x44.png 300w" sizes="(max-width: 555px) 100vw, 555px" /></figure>



<p>In the example above, three VMKernel ports will be created on every ESXi host in the cluster, and a ping attempt will occur to the IP listed in the &#8220;gw&#8221; column from the entry in the &#8220;IP&#8221; column.</p>



<h2 class="wp-block-heading">The Script</h2>



<p>Now to the fun part, and why you&#8217;re actually here. First and foremost, you can see a copy of <a rel="noreferrer noopener" aria-label="GitHub Repository (opens in a new tab)" href="https://github.com/jonhowe/Virtjunkie.com" target="_blank">GitHub Repository</a>.</p>



<p>To run this script, you&#8217;ll need to pass variables as parameters or modify the default values. For example, you can run the script like this:</p>



<pre class="urvanov-syntax-highlighter-plain-tag">PS&gt; Test-ClusterNetworkConnectivity -vcenterserver &quot;myvcenterserver.local&quot; -vswitch &quot;distributed switch name&quot; -clustername &quot;my special cluster&quot; -csvpath c:\path\to\my.csv -verbose</pre>



<ul><li>vCenter Server (-vcenterserver)</li><li>The VDS in use (-vswitch)</li><li>The desired cluster you want to focus on (-clustername)</li><li>The CSV that contains info for the VMKernel ports (-csvpath)</li><li>If you want verbose output printed to the screen (-verbose:$true/$false)</li></ul>



<h2 class="wp-block-heading">Code Overview (and code)</h2>



<p><strong>Lines 1-17</strong><br>Documentation and parameters<br><br><strong>Lines 18-30</strong><br>Set up the environment, connect to vCenter, import the CSV, get the list of ESXi hosts to work with<br><br><strong>Lines 31&#8211;33</strong><br>Begin loop that goes through all ESXi hosts<br><br><strong>Lines 34-36</strong><br>Begin loop for each VMKernel port<br><br><strong>Lines 37-50</strong><br>Create splatting for variables<br>Instantiate object<br><br><strong>Lines 51-70</strong><br>Create the VMKernel adapter, test the ping, optionally print verbose logging<br><br><strong>Lines 71-80</strong><br>Add results to an array<br><br><strong>Lines 81-82</strong><br>Remove the VMKernel port<br><br><strong>Line 85-97</strong><br>This block exists to handle an error with creating the VMKernel port.<br><br><strong>Line 100</strong><br>Add the results of the ping test to an array<br><br><strong>Line 105-107</strong><br>Output the array of results and disconnect from the vcenter server</p>



<p></p>



<pre class="urvanov-syntax-highlighter-plain-tag">&amp;lt;#
.LINK http://www.virtjunkie.com/vsphere-test-cluster-connectivity/
.LINK https://github.com/jonhowe/Virtjunkie.com/blob/master/Test-ClusterNetworkConnectivity.ps1
#&gt;
param(
	$vcenterserver = &quot;vcenter67.pcm.net&quot;,
	$vswitch = &quot;UCS-vDS001&quot;,
	$clustername = &quot;UCS Cluster&quot;,
	$verbose = $false,
	$csvpath = &quot;C:\powershell\PCMlab_test_csv.csv&quot;
)

&amp;lt;#
***Fields in the CSV***
IP, GW, PG, netmask, vlan
#&gt;

#1.) connect to the vcenter
$credential = get-credential
$conn = connect-viserver -server $vcenterserver -credential $credential | out-null

#2.) Get a list of all VMhosts attached to the specified Switch and cluster
$vmhosts = get-vdswitch -name $vswitch | get-vmhost | Where-Object { $_.parent.name -eq $clustername }

#3.) Import the CSV file that has the IP, Gateway, Port Group, NetMask, and vLAN
$ALL_VMK_CSV_Rows = import-csv -path $csvpath

#Create array that stores results
$RS = @()

#3a.) Loop through each VMhost one at a time
foreach ($vmhost in $vmhosts)
{
	#Loop through each VMkernel in the CSV one at a time
	foreach ($ONE_VMK_CSV_ROW in $ALL_VMK_CSV_Rows)
	{
		#Splatting for parameters for new-vmhostnetworkadapter
		$NewVMKParams = @{
			VMHost = $vmhost
			PortGroup = $ONE_VMK_CSV_ROW.pg
			VirtualSwitch = $vswitch
			IP = $ONE_VMK_CSV_ROW.ip
			SubnetMask = $ONE_VMK_CSV_ROW.netmask
		}
		#Optional logging - disabled by default
		Write-Verbose -vb:$true -Message ($NewVMKParams | Out-String)
		
		#create new object to contain results
		$PingResults = New-Object System.Object

		#Test to see if the vmkernel port is created successfully.. if so, continue to test connectivity
		if ($vmkernel = new-vmhostnetworkadapter @NewVMKParams -ErrorAction SilentlyContinue)
		{
			#Get the newly created VMKernel adapter
			$vmkobj = Get-VMHostNetworkAdapter -VMHost $vmhost -VirtualSwitch (Get-VDSwitch -Name $vswitch) -VMKernel | 
				Where-Object { $_.devicename -eq $vmkernel.devicename }
		
			#Use ESXCli to emulate this command: vmkping -I [newly created vmkernel IP] TO: [Gateway IP Specified in the CSV]
			$esxcli = Get-EsxCli -VMHost $vmhost -V2
			$params = $esxcli.network.diag.ping.CreateArgs()
			$params.host = $ONE_VMK_CSV_ROW.GW
			$params.interface = $vmkobj.devicename
			#the $res variable contains the results of the ping.. if you want, you can see all of the result info by printing $res.summary
			$res = $esxcli.network.diag.ping.Invoke($params)
			
			#optional logging - disabled by default
			write-verbose -vb:$verbose -Message ($res.summary | Out-String)
			$output = (&quot;[$($vmhost.name)]: $($res.summary.Recieved / $res.summary.transmitted * 100)% success. Source: $($ONE_VMK_CSV_ROW.ip) Target: $($res.summary.hostaddr) || PG $($ONE_VMK_CSV_ROW.pg) (VLAN: $($ONE_VMK_CSV_ROW.vlan))&quot;)
			Write-Verbose -vb:$verbose -Message $output

			#Add properties to the object
			$PingResults | Add-Member -type NoteProperty -name Cluster -Value $clustername        
			$PingResults | Add-Member -type NoteProperty -name VMHost -Value $vmhost.name
			$PingResults | Add-Member -type NoteProperty -name SourceIP -Value $ONE_VMK_CSV_ROW.ip
			$PingResults | Add-Member -type NoteProperty -name TargetIP -Value $res.summary.hostaddr
			$PingResults | Add-Member -type NoteProperty -name PortGroup -Value $ONE_VMK_CSV_ROW.pg
			$PingResults | Add-Member -type NoteProperty -name VLAN -Value $ONE_VMK_CSV_ROW.vlan
			$PingResults | Add-Member -type NoteProperty -name PercentSuccess -Value ($res.summary.Recieved / $res.summary.transmitted * 100)
			$PingResults | Add-Member -type NoteProperty -name vSwitch -Value $vswitch
			
			#3d.) Remove vmkernel port
			remove-vmhostnetworkadapter -nic $vmkobj -confirm:$false
		}
		#if the vmkernel adapter is not created successfully, report the failure
		Else
		{
			#Optional Logging - disabled by default
			$output = (&quot;[$($vmhost.name)]: ERROR || PG $($ONE_VMK_CSV_ROW.pg) (VLAN: $($ONE_VMK_CSV_ROW.vlan)) does not exist on $($vswitch)&quot;)
			write-verbose -verbose:$verbose $output

			#Add properties to the object
			$PingResults | Add-Member -type NoteProperty -name Cluster -Value $clustername
			$PingResults | Add-Member -type NoteProperty -name VMHost -Value $vmhost.name
			$PingResults | Add-Member -type NoteProperty -name SourceIP -Value &quot;ERROR&quot;
			$PingResults | Add-Member -type NoteProperty -name TargetIP -Value &quot;ERROR&quot;
			$PingResults | Add-Member -type NoteProperty -name PortGroup -Value $ONE_VMK_CSV_ROW.pg
			$PingResults | Add-Member -type NoteProperty -name VLAN -Value $ONE_VMK_CSV_ROW.vlan
			$PingResults | Add-Member -type NoteProperty -name vSwitch -Value $vswitch
			$PingResults | Add-Member -type NoteProperty -name PercentSuccess -Value &quot;ERROR&quot;
		}

		#add object to array
		$RS += $PingResults

	} # end foreach ($ONE_VMK_CSV_ROW in $ALL_VMK_CSV_Rows)
} # end foreach ($vmhost in $vmhosts)

Write-Output $RS
#3e.) Disconnect from all vCenters
disconnect-viserver -server * -confirm:$false</pre>
<p>The post <a href="/2019/10/21/vsphere-test-cluster-connectivity/">Validate Network Connectivity Across A VMware Cluster</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2019/10/21/vsphere-test-cluster-connectivity/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>RVTools: Parse Multiple Outputs Using Powershell</title>
		<link>/2019/08/11/powershell-parse-rvtools/</link>
					<comments>/2019/08/11/powershell-parse-rvtools/#respond</comments>
		
		<dc:creator><![CDATA[Jon]]></dc:creator>
		<pubDate>Sun, 11 Aug 2019 15:00:14 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[VMware]]></category>
		<guid isPermaLink="false">http://www.virtjunkie.com/?p=794</guid>

					<description><![CDATA[<p>If you haven&#8217;t used RVTools before, I&#8217;d definitely suggest taking a look. In case you&#8217;re one of the few that has not used it, it&#8217;s a quick tool to generate a point-in-time report of the inventory/configuration/health of a vSphere environment. While it&#8217;s one of the best tools out there for a quick and dirty report [&#8230;]</p>
<p>The post <a href="/2019/08/11/powershell-parse-rvtools/">RVTools: Parse Multiple Outputs Using Powershell</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>If you haven&#8217;t used <a rel="noreferrer noopener" aria-label=" (opens in a new tab)" href="https://www.robware.net/rvtools/" target="_blank">RVTools</a> before, I&#8217;d definitely suggest taking a look. In case you&#8217;re one of the few that has not used it, it&#8217;s a quick tool to generate a point-in-time report of the inventory/configuration/health of a vSphere environment. While it&#8217;s one of the best tools out there for a quick and dirty report of an environment, the challenge I often face is that it outputs <em>too much</em> data. The other challenge I&#8217;ve faced is that it&#8217;s incredibly difficult to combine and analyze data from multiple outputs. </p>



<span id="more-794"></span>



<p>I created a PowerShell script to help with this. The end result is a PowerShell object that can be consumed in any way you like. In a future post, I&#8217;ll show how to take this output and create a new Excel spreadsheet.</p>



<p>The image below is an example of what the script below generates.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1024" height="366" src="https://www.virtjunkie.com/wp-content/uploads/2019/08/image-4-1024x366.png" alt="" class="wp-image-813" srcset="/wp-content/uploads/2019/08/image-4-1024x366.png 1024w, /wp-content/uploads/2019/08/image-4-300x107.png 300w, /wp-content/uploads/2019/08/image-4-768x275.png 768w, /wp-content/uploads/2019/08/image-4.png 1484w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Example Output</figcaption></figure>



<p>As an FYI, we&#8217;ll need to install the <a rel="noreferrer noopener" aria-label=" (opens in a new tab)" href="https://www.powershellgallery.com/packages/ImportExcel" target="_blank">ImportExcel modul</a><a href="https://www.powershellgallery.com/packages/ImportExcel">e</a> in order to parse the excel file. If you want more information, check out the <a rel="noreferrer noopener" aria-label="github repository (opens in a new tab)" href="https://github.com/dfinke/ImportExcel" target="_blank">GitHub repository</a> for ImportExcel.</p>



<p>To run this script, at a minimum, you&#8217;ll need to modify the <code>$spreadsheetdir </code>variable to point to a directory that contains your RVTools outputs. This is a parameter, so it can be done by adding the <code>-spreadsheetdir "[path to my RVTools directory]"</code> if you like, or just feel free to modify the script.</p>



<p><strong>Lines 12-45</strong><br>Define column headers to be pulled for each spreadsheet<br><br><strong>Line 50</strong><br>Get the contents of the spreadsheet directory<br><br><strong>Line 54</strong><br>Loop through each spreadsheet in the spreadsheet directory<br><br><strong>Lines 58</strong><br>Get a distinct list of all clusters in the particular RVTools file. This will allow us to present the results one cluster at a time<br><br><strong>Lines 68-82</strong><br>Import the properties defined in lines 10-44 from the vInfo, vHost, and vDisk worksheet for later consumption<br><br><strong>Lines 84-101</strong><br>Do some math/formatting/voodoo to convert the values from RVTools into something useful<br><br><strong>Lines 63,64 and 103-110</strong><br>Take values from RVTools and calculations (from lines 84-101) and put them into a custom PowerShell object.</p>



<p>You can find the script in the public GitHub repository I keep all of the scripts for this site in:<br><a href="https://github.com/jonhowe/Virtjunkie.com">https://github.com/jonhowe/Virtjunkie.com</a></p>



<pre class="urvanov-syntax-highlighter-plain-tag">&amp;lt;#
.LINK http://www.virtjunkie.com/powershell-parse-rvtools/
.LINK https://github.com/jonhowe/Virtjunkie.com/blob/master/Parse-RVTools-Generic.ps1
#&gt;
param(
    # Migrate Powered Off VMs?
    [switch]$IncludePoweredOffVMs,

    # Directory that contains RVTools Exports
    $spreadsheetdir = &quot;/path/to/directory/&quot;,
    
    # Array that contains column headers to be gathered from the vHost worksheet
    $vHostProperties = @(
        'Host', 
        &quot;CPU usage %&quot;,
        &quot;Memory usage %&quot;,
        'model',
        &quot;Service Tag&quot;,
        &quot;Current EVC&quot;,
        &quot;Max EVC&quot;,
        &quot;# VMs&quot;,
        &quot;# Memory&quot;,
        &quot;# Cores&quot;,
        &quot;HT Active&quot;,
        &quot;vCPUs per Core&quot;
    ),

    # Array that contains column headers to be gathered from the vInfo worksheet
    $vInfoProperties = @(
        'VM',
        'Template',
        &quot;HW version&quot;,
        &quot;Provisioned MB&quot;,
        &quot;In Use MB&quot;,
        &quot;OS according to the VMware Tools&quot;,
        'memory'
    ),

    # Array that contains column headers to be gathered from the vDisk worksheet
    $vDiskProperties = @(
        &quot;vm&quot;,
        &quot;Raw LUN ID&quot;,
        &quot;Raw Comp. Mode&quot;,
        &quot;Shared Bus&quot;
    )

)

# Get all spreadsheets in the spreadsheet directory
$spreadsheets = $spreadsheetdir | Get-ChildItem

$rs = @()
# Loop through all spreadsheets in the spreadsheet dir
foreach ($sheet in $SpreadSheets)
{
    # Use the importexcel module to import the vCluster Worksheet
    # We do this as an easy way to get the 
    $vCluster = Import-Excel -Path $sheet -Sheet vCluster
    
    foreach ($cluster in $vCluster)
    {
        $ClusterDetails = New-Object System.Object
        $ClusterDetails | Add-Member -type NoteProperty -name vCenter -Value ($cluster.&quot;VI SDK Server&quot;)
        $ClusterDetails | Add-Member -type NoteProperty -name Cluster -Value $cluster.name 
       
        # Parse and store the properties defined in the $vInfoProperties array
        #   from the vInfo tab
        $vInfo = Import-Excel -Path $sheet -WorksheetName vInfo | 
            Where-Object { $_.Cluster -eq $cluster.name } | 
            Select-Object $vInfoProperties

        # Parse and store the properties defined in the $vHostProperties array
        #   from the vHost tab
        $vHost = Import-Excel -Path $sheet -WorksheetName vHost | 
            Where-Object { $_.Cluster -eq $cluster.name } | 
            Select-Object $vHostProperties

        # Parse and store the properties defined in the $vDiskProperties array
        #   from the vDisk tab
        $vDisk = Import-Excel -Path $sheet -WorksheetName vDisk | 
            Where-Object {$_.Cluster -eq $cluster.name } | 
            Select-Object $vDiskProperties

        # Calculate the sum of the column Provisioned MB from all rows in the vInfo tab, convert to GB, and round
        $TotalProvisionedGB = [math]::round(($vInfo | Measure-Object -Sum &quot;Provisioned MB&quot;).Sum / 1024, 2)
        $ClusterDetails | Add-Member -type NoteProperty -name TotalProvisionedGB -Value $TotalProvisionedGB        

        # Calculate the sum of the column In Use MB from all rows in the vInfo tab, convert to GB, and round
        $TotalInUseGB = [math]::round(($vInfo | Measure-Object -Sum &quot;In Use MB&quot;).Sum / 1024, 2)
        $ClusterDetails | Add-Member -type NoteProperty -name TotalInUseGB -Value $TotalInUseGB
        
        # Calculate average vCPU to PCPU, the total RAM in the cluster, and the average RAM Usage
        $vCPUtoPCPU = [math]::round(($vHost | Measure-Object -Average &quot;vCPUs per Core&quot;).average, 2)
        $clusterRAM = [math]::round(($vHost | Measure-Object -Sum &quot;# Memory&quot;).Sum / 1024, 2)
        $AvgClusterRamUsage = [math]::round(($vHost | Measure-Object -Average &quot;Memory Usage %&quot;).average, 2)

        #Detect RDMs and VMs with Shared Bus based on info in the vDisk sheet
        $RDMs = ($vDisk | ? { $_.&quot;Raw LUN ID&quot; -ne $null})
        $SharedBusVMs = ($vDisk | ? { $_.&quot;Shared Bus&quot; -ne $null -and $_.&quot;Shared Bus&quot; -ne &quot;noSharing&quot; -and $_.&quot;Shared Bus&quot; -ne 0})

        $clusterCoreCount = [math]::round(($cluster | Measure-Object -Sum &quot;NumCpuCores&quot;).sum,0)

        $ClusterDetails | Add-Member -type NoteProperty -name AvgClusterRamUsage -Value $AvgClusterRamUsage
        $ClusterDetails | Add-Member -type NoteProperty -name ClusterRamGB -Value $clusterRAM
        $ClusterDetails | Add-Member -type NoteProperty -name ClusterVMCount -Value $vInfo.count
        $ClusterDetails | Add-Member -type NoteProperty -name ClusterHostCount -Value ($vHost.count)
        $ClusterDetails | Add-Member -type NoteProperty -name TotalClusterCores -Value $clusterCoreCount
        $ClusterDetails | Add-Member -type NoteProperty -name vCPUtoPCPU -Value ($vCPUtoPCPU)
        $ClusterDetails | Add-Member -type NoteProperty -name RDMCount -Value ($RDMs.count)
        $ClusterDetails | Add-Member -type NoteProperty -name SharedBusVMs -Value ($SharedBusVMs.count)
        
        $rs += $ClusterDetails
    }
}

$rs</pre>
<p>The post <a href="/2019/08/11/powershell-parse-rvtools/">RVTools: Parse Multiple Outputs Using Powershell</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2019/08/11/powershell-parse-rvtools/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PowerCli &#8211; Deploy Linked Clone with Static IP</title>
		<link>/2019/07/18/powercli-linked-clone-static-ip/</link>
					<comments>/2019/07/18/powercli-linked-clone-static-ip/#respond</comments>
		
		<dc:creator><![CDATA[Jon]]></dc:creator>
		<pubDate>Fri, 19 Jul 2019 02:36:32 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Servers]]></category>
		<category><![CDATA[VMware]]></category>
		<guid isPermaLink="false">http://www.virtjunkie.com/?p=774</guid>

					<description><![CDATA[<p>I'm not sure why it's been so hard to find a snippet online that gives me the ability to create a linked clone while selecting a static IP address, but it was. I ended up writing a quick function to help.</p>
<p>The post <a href="/2019/07/18/powercli-linked-clone-static-ip/">PowerCli &#8211; Deploy Linked Clone with Static IP</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>I&#8217;m not sure why it&#8217;s been so hard to find a snippet online that gives me the ability to create a linked clone while selecting a static IP address, but it was. I ended up writing a quick function to help.</p>



<span id="more-774"></span>



<p>It should be pretty self explanatory.. just edit the variables in the parameter section and call the function.<br><br>Cheers!</p>



<p>Github: <a href="https://github.com/jonhowe/Virtjunkie.com/blob/master/Deploy-VM.ps1">https://github.com/jonhowe/Virtjunkie.com/blob/master/Deploy-VM.ps1</a></p>



<pre class="urvanov-syntax-highlighter-plain-tag">function New-VirtJunkieLinkedClone {
    [CmdletBinding()]
    &amp;lt;#
    Github: https://github.com/jonhowe/Virtjunkie.com/blob/master/Deploy-VM.ps1
    Link: https://www.virtjunkie.com/?p=774
    #&gt;
    param (
        #vCenter Info
        $vCenter            = 'vcsa.home.lab',
        $username           = 'administrator@vsphere.local',
        $password           = 'VMWare1!',
        $TemplateCustomSpec = 'WS16to19',

        #Parent VM Info
        $ParentVMName       = 'WS16-GUI',
        $SnapshotName       = &quot;Base&quot;,

        #New VM Info
        $VMName             = &quot;vra-iaas-2&quot;,
        $VMIP               = &quot;192.168.86.214&quot;,
        $VMNetmask          = &quot;255.255.255.0&quot;,
        $VMGateway          = &quot;192.168.86.1&quot;,
        $VMDNS              = &quot;192.168.86.232&quot;
    )
    
    begin {
        $vc_conn = Connect-VIServer -Server $vCenter -User $username -Password $password
    }
    
    process {
        # Get the OS CustomizationSpec and clone
        $OSCusSpec = Get-OSCustomizationSpec -Name $TemplateCustomSpec | 
            New-OSCustomizationSpec -Name 'tempcustomspec' -Type NonPersistent

        #Update Spec with IP information
        Get-OSCustomizationNicMapping -OSCustomizationSpec $OSCusSpec |
            Set-OSCustomizationNicMapping -IPMode UseStaticIP `
                -IPAddress $VMIP `
                -SubnetMask $VMNetmask  `
                -DefaultGateway $VMGateway `
                -Dns $VMDNS

        $mySourceVM = Get-VM -Name $ParentVMName
        $myReferenceSnapshot = Get-Snapshot -VM $mySourceVM -Name $SnapshotName 
        $Cluster = Get-Cluster 'Cluster'
        $myDatastore = Get-Datastore -Name 'Shared'

        New-VM -Name $VMName -VM $mySourceVM -LinkedClone -ReferenceSnapshot $myReferenceSnapshot -ResourcePool $Cluster `
        -Datastore $myDatastore -OSCustomizationSpec $OSCusSpec
    }
    
    end {
        Get-OSCustomizationSpec -Name $OSCusSpec | Remove-OSCustomizationSpec -Confirm:$false
    }
}</pre>
<p>The post <a href="/2019/07/18/powercli-linked-clone-static-ip/">PowerCli &#8211; Deploy Linked Clone with Static IP</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2019/07/18/powercli-linked-clone-static-ip/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PowerCLI &#8211; Get All VM Details from get-task</title>
		<link>/2019/03/04/get-details-from-get-task/</link>
					<comments>/2019/03/04/get-details-from-get-task/#respond</comments>
		
		<dc:creator><![CDATA[Jon]]></dc:creator>
		<pubDate>Tue, 05 Mar 2019 03:18:20 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[VMware]]></category>
		<guid isPermaLink="false">http://www.virtjunkie.com/?p=752</guid>

					<description><![CDATA[<p>I&#8217;ve been working on a project that uses the -runasync parameter on the move-vm cmdlet. The obvious problem with running jobs asynchronously is that you lose the ability to determine the status of whatever task as soon as you submit it. I ran into a challenge on this project where I needed to validate some [&#8230;]</p>
<p>The post <a href="/2019/03/04/get-details-from-get-task/">PowerCLI &#8211; Get All VM Details from get-task</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>I&#8217;ve been working on a project that uses the -runasync parameter on the move-vm cmdlet. The obvious problem with running jobs asynchronously is that you lose the ability to determine the status of whatever task as soon as you submit it. </p>



<span id="more-752"></span>



<p>I ran into a challenge on this project where I needed to validate some details from the job that was submitted asynchronously. It was more difficult and annoying than I thought it would be, but I managed to get a function together that can get a bunch of information.</p>



<p>The script assumes a pre-existing connection to vCenter and accepts the parameters below.</p>



<ol><li>Status_to_check &#8211; with a default value of &#8220;Initiate vMotion Receive operation&#8221;</li><li>vCenter &#8211; the FQDN of the vCenter server. I added this in case you are connected to multiple vCenter servers.</li></ol>



<pre class="urvanov-syntax-highlighter-plain-tag">function Test-vCenterTasks
{
    param(
        $status_to_check = &quot;Initiate vMotion receive operation&quot;,
        $vcenter
    )
    
    $tasks = get-task -Server $vcenter
    $vmotions=$tasks | ? { $_.name -eq $status_to_check}
    $rs = @()
    foreach ($vmotion in $vmotions)
    {
        $vminflight = $vmotion.ExtensionData.Info.EntityName
        $vmobj = get-vm $vminflight -Server $vcenter
        $cluster = $vmobj | Get-Cluster -Server $vcenter

        $obj = New-Object &ndash;typename PSObject
        $obj | Add-Member &ndash;membertype NoteProperty &ndash;name VM_Name &ndash;value $vmobj.name
        $obj | Add-Member &ndash;membertype NoteProperty &ndash;name VM_Cluster &ndash;value $cluster.name
        $obj | Add-Member &ndash;membertype NoteProperty &ndash;name StartTime &ndash;value $vmotion.StartTime
        $obj | Add-Member &ndash;membertype NoteProperty &ndash;name Progress &ndash;value $vmotion.PercentComplete
        $obj | Add-Member &ndash;membertype NoteProperty &ndash;name Description &ndash;value $vmotion.Description
        $rs += $obj
    }

    return $rs
}

Test-vCenterTasks -vcenter &quot;vcenter-server-fqdn&quot;</pre>



<p></p>
<p>The post <a href="/2019/03/04/get-details-from-get-task/">PowerCLI &#8211; Get All VM Details from get-task</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2019/03/04/get-details-from-get-task/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Use PowerCLI to determine the ESXi host with the most available RAM</title>
		<link>/2018/12/11/powercli-determine-best-esxi-host/</link>
					<comments>/2018/12/11/powercli-determine-best-esxi-host/#respond</comments>
		
		<dc:creator><![CDATA[Jon]]></dc:creator>
		<pubDate>Tue, 11 Dec 2018 22:30:28 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[VMware]]></category>
		<guid isPermaLink="false">http://www.virtjunkie.com/?p=690</guid>

					<description><![CDATA[<p>Use PowerCLI To determine the ESXi host with the most available RAM. </p>
<p>The post <a href="/2018/12/11/powercli-determine-best-esxi-host/">Use PowerCLI to determine the ESXi host with the most available RAM</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>I&#8217;m working on a project right now that requires me to do a shared nothing cross vCenter vMotion of about 6K VMs. As you might know, cross vCenter vMotion requires you to specify the ESXi host and the Datastore your VM will live in within the target vCenter; no targeting a cluster of any kind. This brings up some interesting challenges when trying to automate the migration of such a large amount of VMs. One in particular, is the need to target the ESXi host that has the most free space. I am using the function below to do just this &#8211; hopefully it helps!</p>



<pre class="urvanov-syntax-highlighter-plain-tag">Function Get-BestDatastore
{
    Param (
        $vmhostlist
    )

    $destination_compute = $vmhostlist | get-vmhost -Server $vc_destination |
        Select-Object name,@{Name = &quot;MemoryFreeGB&quot;; Expression = {($_.MemoryTotalGB - $_.MemoryUsageGB)}} | 
        Sort-Object -Descending -Property MemoryFreeGB |
        Select-Object -First 1

    return $destination_compute
}

$vmhosts = get-cluster -name &quot;destinationcluster&quot; | get-vmhost</pre>
<p>The post <a href="/2018/12/11/powercli-determine-best-esxi-host/">Use PowerCLI to determine the ESXi host with the most available RAM</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2018/12/11/powercli-determine-best-esxi-host/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Clone VM in Workstation 15 Pro via REST API using Powershell</title>
		<link>/2018/11/26/clone-vm-in-workstation-15-pro-via-rest-api-using-powershell/</link>
					<comments>/2018/11/26/clone-vm-in-workstation-15-pro-via-rest-api-using-powershell/#respond</comments>
		
		<dc:creator><![CDATA[Jon]]></dc:creator>
		<pubDate>Mon, 26 Nov 2018 14:51:36 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[VMware]]></category>
		<guid isPermaLink="false">http://www.virtjunkie.com/?p=662</guid>

					<description><![CDATA[<p>After posting yesterday about modifying the parent image to allow for hostname changes, I was still looking for something a little more streamlined. I remember reading about the new REST API that is available on workstation, so I wrote a little script to use the Workstation API to clone a VM. Also just FYI &#8211; [&#8230;]</p>
<p>The post <a href="/2018/11/26/clone-vm-in-workstation-15-pro-via-rest-api-using-powershell/">Clone VM in Workstation 15 Pro via REST API using Powershell</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>After <a href="http://www.virtjunkie.com/prompt-for-a-new-hostname-on-boot/" target="_blank" rel="noopener">posting yesterday about modifying the parent image to allow for hostname changes</a>, I was still looking for something a little more streamlined. I remember r<a href="https://blogs.vmware.com/workstation/2018/09/workstation-15-is-here.html" target="_blank" rel="noopener">eading about the new REST API</a> that is available on workstation, so I wrote a little script to use the Workstation API to clone a VM.</p>
<p><span id="more-662"></span></p>
<p>Also just FYI &#8211; this performs a full clone, not a linked clone. I&#8217;m not sure that linked clone functionality is available via the API yet. I&#8217;m hoping to use the vmrun command to accomplish this, and while I know it is packaged with Workstation Pro, <a href="https://docs.vmware.com/en/VMware-Fusion/11/com.vmware.fusion.using.doc/GUID-FF306A59-080E-497E-857D-F45125927FB3.html" target="_blank" rel="noopener">the only documentation I can find</a> for it is associated with Fusion. I also have been thinking about using <a href="https://www.vagrantup.com/vmware/index.html" target="_blank" rel="noopener">vagrant</a> for this as well.</p>
<p>This is very basic functionality, and exists simply to showcase the functionality. There&#8217;s no error checking, and it could be expanded a lot. Regardless, enjoy!</p><pre class="urvanov-syntax-highlighter-plain-tag">&lt;#
Original Links: 
https://github.com/jonhowe/Virtjunkie.com/blob/master/clone-workstation-vm.ps1
http://www.virtjunkie.com/clone-vm-in-workstation-15-pro-via-rest-api-using-powershell/
The API will need to be running. Use this link to configure it.
https://docs.vmware.com/en/VMware-Workstation-Pro/15.0/com.vmware.ws.using.doc/GUID-C3361DF5-A4C1-432E-850C-8F60D83E5E2B.html
#&gt;
$user = '[Username]'
$pass = '[Password]'
$VMToClone = "[Template Name To Clone]"
$newvmname = "[New VM Name]"
$REST_URL = "https://[Your/ IP and port]/api/vms"

function Select-VM {
    param (
        $vmname
    )

    $rs=Invoke-WorkstationRestRequest -method Get

    foreach ($vm in $rs)
    {
        $pathsplit = ($vm.path).split("/")
        $vmxfile = $pathsplit[($pathsplit.Length)-1]
        $thisVM = ($vmxfile).split(".")[0]
        if ($thisVM -eq $vmname) { return $vm;break}
    } 
}

function Select-OneVM {
    param (
        $vmid
    )
    $rs=Invoke-WorkstationRestRequest -method Get -uri ($REST_URL + "/$($vmid.id)")
    return $rs
}
function Set-Credentials {
    param (
        $username,
        $password
    )

    $pair = "${username}:${password}"
    $bytes = [System.Text.Encoding]::ASCII.GetBytes($pair)
    $base64 = [System.Convert]::ToBase64String($bytes)

    $basicAuthValue = "Basic $base64"
    return $basicAuthValue
}

function New-WorkstationVM {
    param (
        $sourcevmid,
        $newvmname
    )
    $body = @{
        'name' = $newvmname;
        'parentId' = $sourcevmid
    }
    $requestbody = ($body | ConvertTo-Json)
    $rs=Invoke-WorkstationRestRequest -method "POST" -body $requestbody
    return $rs
}

function Invoke-WorkstationRestRequest {
    param (
        $uri=$REST_URL,
        $method,
        $body=$null
    )

    $headers = @{
        'authorization' =  $basicAuthValue;
        'content-type' =  'application/vnd.vmware.vmw.rest-v1+json';
        'accept' = 'application/vnd.vmware.vmw.rest-v1+json';
        'cache-control' = 'no-cache'
    }
    $rs=Invoke-RestMethod -uri $uri -Headers $headers -SkipCertificateCheck -Method $method -Body $body
    return $rs
}

$creds = Set-Credentials -username $user -password $pass
$vmtoclone = Select-VM -vmname $VMToClone 
$result=New-WorkstationVM -sourcevmid $VMToClone.id -newvmname $newvmname
$newvm = select-onevm -vmid $result

return $newvm</pre><p></p>
<p>The post <a href="/2018/11/26/clone-vm-in-workstation-15-pro-via-rest-api-using-powershell/">Clone VM in Workstation 15 Pro via REST API using Powershell</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2018/11/26/clone-vm-in-workstation-15-pro-via-rest-api-using-powershell/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>VMware Powercli &#8211; Gather NIC Driver and Firmware Versions from Hosts via vCenter</title>
		<link>/2014/10/20/vmware-powercli-gather-nic-driver-and-firmware-versions-from-hosts-via-vcenter/</link>
					<comments>/2014/10/20/vmware-powercli-gather-nic-driver-and-firmware-versions-from-hosts-via-vcenter/#respond</comments>
		
		<dc:creator><![CDATA[Jon]]></dc:creator>
		<pubDate>Mon, 20 Oct 2014 19:46:58 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[VMware]]></category>
		<guid isPermaLink="false">http://45.63.13.214/?p=612</guid>

					<description><![CDATA[<p>I recently encountered an issue in vSphere 5.5 where I wasn&#8217;t able to change the interface speed on an ESXi host from auto-negotiate to anything else. After a good amount of troubleshooting I was able to determine that this issue was occurring due to the fact that the NIC firmware version and driver version on [&#8230;]</p>
<p>The post <a href="/2014/10/20/vmware-powercli-gather-nic-driver-and-firmware-versions-from-hosts-via-vcenter/">VMware Powercli &#8211; Gather NIC Driver and Firmware Versions from Hosts via vCenter</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>I recently encountered an issue in vSphere 5.5 where I wasn&#8217;t able to change the interface speed on an ESXi host from auto-negotiate to anything else. After a good amount of troubleshooting I was able to determine that this issue was occurring due to the fact that the NIC firmware version and driver version on a blade server was out of date. VMware has a <a href="http://kb.vmware.com/kb/1027206" target="_blank" rel="noopener noreferrer">good KB article</a> on how to grab the firmware and driver versions that I followed. However, the problem is that even on the most modest ESXi host that isn&#8217;t running 10G to it, you&#8217;ll likely have a minimum of 4 NICs on it. This means that you&#8217;ll have to enable SSH on every host you want to check, run one command per NIC each of them (or run a one line script that loops through them, but will that really save you time..?). It doesn&#8217;t take a very large cluster for that to become a very large endeavor.</p>
<p>This PowerShell script will connect to a vCenter server, allow you to scan all ESXi hosts, or only hosts within a particular cluster, and output the results in object format so that you can manipulate them how you wish.</p>
<p><span id="more-612"></span></p>
<p>As a refresher, the esxcli command you&#8217;ll run to list the required information is below. Substitute [#IFINDEX] with the interface index you want to look at (ie, vmnic1)</p>
<p><strong>esxcli network nic get -n vmnic[#IFINDEX]</strong></p>
<p>Which will output something like this:</p>
<p>Advertised Auto Negotiation: true<br />
Advertised Link Modes: 1000baseT/Full, 2500baseT/Full, 10000baseT/Full<br />
Auto Negotiation: true<br />
Cable Type: FIBRE<br />
Current Message Level: 0<br />
<strong>Driver Info:</strong><br />
<strong>       Bus Info: 0000:02:00.0</strong><br />
<strong>        Driver: bnx2x</strong><br />
<strong>        Firmware Version: bc 6.2.28 phy baa0.105</strong><br />
<strong>        Version: 2.710.39.v55.2</strong><br />
Link Detected: true<br />
Link Status: Up<br />
Name: vmnic0<br />
PHYAddress: 16<br />
Pause Autonegotiate: true<br />
Pause RX: true<br />
Pause TX: true<br />
Supported Ports: FIBRE<br />
Supports Auto Negotiation: true<br />
Supports Pause: true<br />
Supports Wakeon: true<br />
Transceiver: internal<br />
Wakeon: MagicPacket(tm)</p>
<p>The key info is bold above. The Version: line is referring to the Driver version.</p>
<p>Now, what if you could gather the same information for every host in attached to a vCenter server by simply running a single command specifying your VirtualCenter server and the cluster name. The script below will do exactly that. See comment based help for more info.</p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">&lt;#	
	.NOTES
	===========================================================================
	 Created with: 	SAPIEN Technologies, Inc., PowerShell Studio 2014 v4.1.65
	 Created on:   	10/17/2014 10:43 AM
	 Created by:   	Jon Howe
	 Filename:     	Get-NICAndFirmware.ps1
	===========================================================================
	.SYNOPSIS
		Connects to VirtualCenter and lists pertinent NIC driver and version information
	.DESCRIPTION
		Connects to VirtualCenter and lists pertinent NIC driver and version information
	.PARAMETER $VirtualCenterServer
		Required String Parameter. The fully qualified domain name of the virtualcenter server
	.PARAMETER $cluster
		Optional StringParameter. The name of the cluster you want to filter by.
	.PARAMETER $asLocalUser
		Optional Boolean Parameter. Do you want to connect to vC as you, or do you want to manually 
		authenticate as a different user
	.EXAMPLE
		Get-NicDriverAndFirmware -VirtualCenterServer vc-tst-1.test.in
		Actions Taken:
		This will connect to the specified virtualcenter server and list the driver name, version, 
		and firmware version for every NIC in every host attached to your vCenter server. The script will
		authenticate to vCenter as your locally logged in user.
		Results:
		Host_Name                VMNic_Name DriverName DriverVersion FirmwareVersion
		---------                ---------- ---------- ------------- ---------------
		ESXi-1.test.in.parata.local vmnic0     bnx2x      1.72.56.v55.2 bc 5.2.7 phy baa0.105
		ESXi-1.test.in.parata.local vmnic1     bnx2x      1.72.56.v55.2 bc 5.2.7 phy baa0.105
		ESXi-1.test.in.parata.local vmnic2     e1000e     1.1.2-NAPI    5.12-6
		ESXi-1.test.in.parata.local vmnic3     e1000e     1.1.2-NAPI    5.12-6
		ESXi-1.test.in.parata.local vmnic4     e1000e     1.1.2-NAPI    5.12-6
		ESXi-1.test.in.parata.local vmnic5     e1000e     1.1.2-NAPI    5.12-6
	.EXAMPLE
		Get-NicDriverAndFirmware -VirtualCenterServer vc-tst-1.test.in -ClusterName Production -asLocalUser $False | Format-Table -AutoSize
		Actions Taken:
		This will connect to the specified virtualcenter server and list the driver name, version,
		and firmware version for each NIC in every host in the cluster &quot;Production&quot;, and will prompt for a username and password.
		Resuts:
		Same as example 1
	.EXAMPLE
		Get-NicDriverAndFirmware -VirtualCenterServer vc-tst-1.test.in -ClusterName Production -asLocalUser $False | c:\temp\vCenterInterfaceDriverandFirmware.csv -notypeinformation
		Actions Taken:
		This script outputs an object, so you can do anything you want with the output, such as create a CSV, sort, etc.
		Results:
		Sames as example 1

	.LINK
		Original Published Location
		http://45.63.13.214/vmware-powercli-gather-nic-driver-and-firmware-versions-from-hosts-via-vcenter
	.LINK
		VMware KB for gathering NIC Driver and Firmware versions
		http://kb.vmware.com/kb/1027206
	.LINK
		VMware Documentation on PowerCLI's Get-EsxCli commandlet
		http://pubs.vmware.com/vsphere-55/topic/com.vmware.powercli.cmdletref.doc/Get-EsxCli.html
#&gt;
[CmdletBinding()]
param (
	[Parameter(Position = 0, Mandatory = $true)]
	[System.String]
	$VirtualCenterServer,
	[Parameter(Position = 1)]
	[System.String]
	$ClusterName,
	[Parameter(Position = 2)]
	[System.Boolean]
	$asLocalUser = $true
)

#region Add Snapin and Connect to vC
#Check to see if the VMware.VimAutomation.Core snapin is loaded - load it if it's not
if ((Get-PSSnapin -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) -eq $null)
{
	Add-PsSnapin VMware.VimAutomation.Core
}

#Check to see if we're already connected to the correct VC Server
if ($DefaultVIServers.name -ne $VirtualCenterServer)
{
	#Determine if we're logging in to VirtualCenter as a local user or if we should prompt for credentials
	if ($asLocalUser)
	{
		Connect-VIServer -Server $VirtualCenterServer | Out-Null
		Write-Debug &quot;Logging in as local user to vc: $VirtualCenterServer&quot;
	}
	else
	{
		Connect-VIServer -Server $VirtualCenterServer -Credential (Get-Credential) | Out-Null
		Write-Debug &quot;Logging in as manually selected user to vc: $VirtualCenterServer&quot;
	}
}
else
{
	Write-Debug &quot;Looks like we're already connected to: $VirtualCenterServer in this session&quot;
}
#endregion Add Snapin and Connect to vC

#region Get List of Hosts
if ($ClusterName)
{
	$VMHosts = Get-Cluster -Name $ClusterName | Get-VMHost | Where-Object { $_.ConnectionState -eq &quot;Connected&quot; }
}
else
{
	$VMhosts = Get-VMHost | Where-Object { $_.ConnectionState -eq &quot;Connected&quot; }
}
#endregion Get List of Hosts

$results = @()
foreach ($VMHost in $VMHosts)
{
	#Get list of network interfaces on host
	$VMHostNetworkAdapters = Get-VMHost $VMHost | Get-VMHostNetworkAdapter | Where-Object { $_.Name -like &quot;vmnic*&quot; }
	
	$esxcli = Get-VMHost $VMHost | Get-EsxCli
	
	$arrNicDetail = @()
	foreach ($VMNic in $VMHostNetworkAdapters)
	{
		$objOneNic = New-Object System.Object
		$objDriverInfo = ($esxcli.network.nic.get($VMNic.Name)).DriverInfo
		
		$objOneNic | Add-Member -type NoteProperty -name Host_Name -Value $VMHost.Name
		$objOneNic | Add-Member -type NoteProperty -name VMNic_Name -Value $VMNic.Name
		$objOneNic | Add-Member -type NoteProperty -name DriverName -Value $objDriverInfo.Driver
		$objOneNic | Add-Member -type NoteProperty -name DriverVersion -Value $objDriverInfo.Version
		$objOneNic | Add-Member -type NoteProperty -name FirmwareVersion -Value $objDriverInfo.FirmwareVersion
		$arrNicDetail += $objOneNic
	}
	
	$results += $arrNicDetail
}

$results
Disconnect-VIServer -Server $VirtualCenterServer -Confirm:$false
Remove-PSSnapin VMware.VimAutomation.Core</pre><p></p>
<p>The post <a href="/2014/10/20/vmware-powercli-gather-nic-driver-and-firmware-versions-from-hosts-via-vcenter/">VMware Powercli &#8211; Gather NIC Driver and Firmware Versions from Hosts via vCenter</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2014/10/20/vmware-powercli-gather-nic-driver-and-firmware-versions-from-hosts-via-vcenter/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Use VMware PowerCLI to Pull CDP information from ESXi Hosts</title>
		<link>/2014/07/25/vmware-powercli-cdp/</link>
					<comments>/2014/07/25/vmware-powercli-cdp/#respond</comments>
		
		<dc:creator><![CDATA[Jon]]></dc:creator>
		<pubDate>Fri, 25 Jul 2014 20:48:21 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[VMware]]></category>
		<guid isPermaLink="false">http://45.63.13.214/?p=596</guid>

					<description><![CDATA[<p>I like having documentation, but I hate creating documentation.  I&#8217;ll be the first to admit that I&#8217;m slightly lazy at times, however, my own personal preferences for what I&#8217;ll call &#8220;Effort Allocation&#8221;, are not the root of my dislike for creating documentation.  The issue really stems from the fact that creating it is very time consuming, [&#8230;]</p>
<p>The post <a href="/2014/07/25/vmware-powercli-cdp/">Use VMware PowerCLI to Pull CDP information from ESXi Hosts</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>I like having documentation, but I hate creating documentation.  I&#8217;ll be the first to admit that I&#8217;m <em>slightly</em> lazy at times, however, my own personal preferences for what I&#8217;ll call &#8220;Effort Allocation&#8221;, are not the root of my dislike for creating documentation.  The issue really stems from the fact that creating it is very time consuming, tedious, and usually lower on the priority list.</p>
<p>However, sometimes it&#8217;s not you that failed to create the documentation. Consultants frequently fall into this category.</p>
<p>The issue I&#8217;m handling here is documenting CDP information from the perspective of ESXi hosts using PowerCLI.</p>
<p><span id="more-596"></span></p>
<p>Rather than navigating to each host and grabbing the CDP info from each host in a cluster like the screenshot below, you can run the commandlet I&#8217;m publishing in this article.</p>
<p><img decoding="async" src="http://kb.vmware.com/Platform/Publishing/images/1007069_cdp_gui_vc_3.jpg" alt="" /></p>
<p><a href="https://new.virtjunkie.com/wp-content/uploads/2014/07/Get-CDP.zip">Download the PS1 file</a>, and check out examples in the comment based help below.</p>
<p>References: <a href="http://kb.vmware.com/kb/1007069" target="_blank" rel="noopener noreferrer">VMware KB 1007069</a></p>
<p></p><pre class="urvanov-syntax-highlighter-plain-tag">&lt;#
	.NOTES
	===========================================================================
	 Created with: 	SAPIEN Technologies, Inc., PowerShell Studio 2014 v4.1.61
	 Created on:   	7/25/2014 1:00 PM
	 Created by:   	Jon Howe
	 Filename:     	Get-CDP.ps1
	===========================================================================
	.SYNOPSIS
		Connects to VirtualCenter and lists pertinent CDP information
	.DESCRIPTION
		Connects to VirtualCenter and lists pertinent CDP information
	.PARAMETER $VirtualCenterServer
		Required String Parameter. The fully qualified domain name of the virtualcenter server
	.PARAMETER $cluster
		Optional StringParameter. The name of the cluster you want to filter by.
	.PARAMETER $asLocalUser
		Optional Boolean Parameter. Do you want to connect to vC as you, or do you want to manually
		authenticate as a different user.
	.EXAMPLE
		Get-CDP -VirtualCenterServer vc-tst-1.test.in
		Actions Taken:
		This will connect to the specified virtualcenter server and list the CDP Information
		Results:
		ESXi_HostName  : ESXi-1.test.in
		VMnic          : vmnic1
		SwitchIdentity : test-3750.test.in
		ManagementIP   : 10.1.1.1
		SwitchPort     : GigabitEthernet1/0/1
		SwitchPlatform : cisco WS-C3750G-48TS
		Interfce_Vlan  : 999

		ESXi_HostName  : ESXi-1.test.in
		VMnic          : vmnic2
		SwitchIdentity : test-3750.test.in
		ManagementIP   : 10.1.1.1
		SwitchPort     : GigabitEthernet1/0/2
		SwitchPlatform : cisco WS-C3750G-48TS
		Interfce_Vlan  : 999
	.EXAMPLE
		Get-CDP -VirtualCenterServer vc-tst-1.test.in -cluster testCluster -asLocalUser $false
		Actions Taken:
		This will connect you to the specified VirtualCenter server and only search hosts specified in
		the cluster. It will prompt you to enter your username and password.
		Results:
		Same as example 1
	.EXAMPLE
		Get-CDP -VirtualCenterServer vc-tst-1.test.in | export-csv -path c:\temp\cdp_information.csv -notypeinformation
		Actions Taken:
		This script outputs an object, so you can do anything you want with the output, such as create a CSV, sort, etc.
		Results:
		Sames as example 1
	.LINK
		http://45.63.13.214/vmware-powercli-cdp/
	.LINK
		http://kb.vmware.com/kb/1007069
#&gt;
[CmdletBinding()]
param (
	[Parameter(Position = 0, Mandatory = $true)]
	[System.String]
	$VirtualCenterServer,
	[Parameter(Position = 1)]
	[System.String]
	$ClusterName,
	[Parameter(Position = 2)]
	[System.Boolean]
	$asLocalUser=$true
)

#region Add Snapin and Connect to vC
#Check to see if the VMware.VimAutomation.Core snapin is loaded - load it if it's not
if ((Get-PSSnapin -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) -eq $null)
{
	Add-PsSnapin VMware.VimAutomation.Core
}

#Check to see if we're already connected to the correct VC Server
if ($DefaultVIServers.name -ne $VirtualCenterServer)
{
	#Determine if we're logging in to VirtualCenter as a local user or if we should prompt for credentials
	if ($asLocalUser)
	{
		Connect-VIServer -Server $VirtualCenterServer | Out-Null
		Write-Debug &amp;quot;Logging in as local user to vc: $VirtualCenterServer&amp;quot;
	}
	else
	{
		Connect-VIServer -Server $VirtualCenterServer -Credential (Get-Credential) | Out-Null
		Write-Debug &amp;quot;Logging in as manually selected user to vc: $VirtualCenterServer&amp;quot;
	}
}
else
{
	Write-Debug &amp;quot;Looks like we're already connected to: $VirtualCenterServer in this session&amp;quot;
}
#endregion Add Snapin and Connect to vC

$cdpDetails = @()

#Get List of Hosts
if ($ClusterName)
{
	$hosts = Get-Cluster -Name $ClusterName | Get-VMHost | Where-Object { $_.ConnectionState -eq &amp;quot;Connected&amp;quot; }
}
else
{
	$hosts = Get-VMHost | Where-Object { $_.ConnectionState -eq &amp;quot;Connected&amp;quot; }
}

#Get the Network Config information from each host
$hosts | % { Get-View $_.ID } | % { $esxname = $_.Name; Get-View $_.ConfigManager.NetworkSystem } |
% {
	foreach ($physnic in $_.NetworkInfo.Pnic)
	{
		#Get detailed CDP information for all interfaces
		$result = ($_.QueryNetworkHint($physnic.Device)).ConnectedSwitchPort
		if ($result)
		{
			$objOneHost = New-Object System.Object
			$objOneHost | Add-Member -type NoteProperty -name ESXi_HostName -Value $esxname
			$objOneHost | Add-Member -type NoteProperty -name VMnic -Value $physnic.Device
			$objOneHost | Add-Member -type NoteProperty -name SwitchIdentity -Value $result.DevId
			$objOneHost | Add-Member -type NoteProperty -name ManagementIP -Value $result.Address
			$objOneHost | Add-Member -type NoteProperty -name SwitchPort -Value $result.PortID
			$objOneHost | Add-Member -type NoteProperty -name SwitchPlatform -Value $result.HardwarePlatform
			$objOneHost | Add-Member -type NoteProperty -name Interfce_Vlan -Value $result.Vlan
			$cdpDetails += $objOneHost
		}
	}
}

$cdpDetails

Disconnect-VIServer -Server $VirtualCenterServer | Out-Null</pre><p></p>
<p>The post <a href="/2014/07/25/vmware-powercli-cdp/">Use VMware PowerCLI to Pull CDP information from ESXi Hosts</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2014/07/25/vmware-powercli-cdp/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
