<?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>VMware Archives - VirtJunkie</title>
	<atom:link href="/category/vmware/feed/" rel="self" type="application/rss+xml" />
	<link>/category/vmware/</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.5</generator>

<image>
	<url>/wp-content/uploads/2020/04/cropped-vj4-150x150.png</url>
	<title>VMware Archives - VirtJunkie</title>
	<link>/category/vmware/</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>Configure vROps To Send Alerts to OpsGenie and Microsoft Teams</title>
		<link>/2021/07/23/vrops-opsgenie-production-setup/</link>
					<comments>/2021/07/23/vrops-opsgenie-production-setup/#comments</comments>
		
		<dc:creator><![CDATA[Jon]]></dc:creator>
		<pubDate>Fri, 23 Jul 2021 18:35:59 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[Hashicorp]]></category>
		<category><![CDATA[InfrastructureAsCode]]></category>
		<category><![CDATA[Packer]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[vExpert]]></category>
		<category><![CDATA[VMware]]></category>
		<guid isPermaLink="false">https://www.virtjunkie.com/?p=1431</guid>

					<description><![CDATA[<p>Packer, Photon, Python, Flask, WSGI, vROps. Holy smokes folks.. I&#8217;m not sure I could make a more click-bait-y post if I tried! I recently took a position at a new company and had the opportunity to stand up a greenfield environment. Part of this environment was obviously configuring monitoring. Since we&#8217;re pretty heavily tied to [&#8230;]</p>
<p>The post <a href="/2021/07/23/vrops-opsgenie-production-setup/">Configure vROps To Send Alerts to OpsGenie and Microsoft Teams</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Packer, Photon, Python, Flask, WSGI, vROps. Holy smokes folks.. I&#8217;m not sure I could make a more click-bait-y post if I tried!</p>



<p>I recently took a position at a new company and had the opportunity to stand up a greenfield environment. Part of this environment was obviously configuring monitoring. Since we&#8217;re pretty heavily tied to VMware here, we&#8217;re using vROps for our monitoring. For escalation of alerts, we&#8217;re using OpsGenie, and for normal collaboration we&#8217;re using Teams. Unfortunately, vROps versions older than 8.4 do not support sending alerts to OpsGenie or Teams out of the box. Fortunately, we can still get this working with a bit of work.</p>



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



<h2 class="wp-block-heading">Overview</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" style="flex-basis:66.66%">
<p class="has-black-color has-pale-cyan-blue-background-color has-text-color has-background">Update &#8211; Starting in vROps 8.4 you can use the webhook plugin that is delivered with vROps to accomplish this. <a href="https://docs.vmware.com/en/vRealize-Operations-Manager/8.4/com.vmware.vcom.core.doc/GUID-9314313D-1DE6-4160-AEFD-76B23AB5DAD9.html" target="_blank" rel="noreferrer noopener"><strong>LINK</strong></a></p>



<p>While vROps does have the ability to send outgoing notifications via REST API, it doesn&#8217;t have the ability to let you customize what fields are sent, or how they are formatted. Because of this limitation, <a rel="noreferrer noopener" href="https://github.com/vmw-loginsight/webhook-shims/graphs/contributors" target="_blank">some very thoughtful folks</a> created <a rel="noreferrer noopener" href="https://github.com/vmw-loginsight/webhook-shims" target="_blank">a project called webhook-shims</a>. This is essentially a Python Flask project that accepts web requests, translates them, then forwards the correctly formatted request off to whatever system you want notifications sent to.</p>



<p>This project hasn&#8217;t been updated in over 3 years, has a number of pending PR&#8217;s and Issues, so my spidey sense says it&#8217;s likely dead. So please be smart about how and where you use this, and consider the implications of running this in production. That said, from a functional standpoint, it seems to work well, and in the rest of this post I&#8217;ll go over how to set this up to run in a production fashion.</p>



<p>The list to the right are the applications that the project supports, and the bold items are what I&#8217;ll show example configuration for.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%">
<ul><li>bigpanda</li><li>bugzilla</li><li>groove</li><li>hipchat</li><li>jenkins</li><li>jira</li><li>kafkatopic</li><li><strong>opsgenie</strong></li><li>pagerduty</li><li>pivotaltracker</li><li>pushbullet</li><li>servicenow</li><li>slack</li><li>socialcast</li><li>travisci</li><li>vrealizeorchestrator</li><li>zendesk</li><li>moogsoft</li><li><strong>msteams</strong></li></ul>
</div>
</div>



<h2 class="wp-block-heading">Approach</h2>



<p>We&#8217;ll be running this whole project using Photon OS 4.</p>



<p>While we could simply run the python script in a <a rel="noreferrer noopener" href="https://www.gnu.org/software/screen/" target="_blank">screen</a>, <a rel="noreferrer noopener" href="https://github.com/tmux/tmux/wiki" target="_blank">tmux</a>, or similar session, but there are serious limitations in doing that. Admittedly, my python isn&#8217;t as strong as some of my other scripting languages, but after a bit of digging, it became clear that things like security, performance, and monitoring are either limited or unavailable if we do this. We&#8217;ll use a WSGI server called <a rel="noreferrer noopener" href="https://gunicorn.org/" target="_blank">Gunicorn</a> to run the python script, and use systemd to create a socket and service, and finally, use Nginx to connect directly to the socket. Whew! Even just reading that after completing this entire project feels like a lot, but don&#8217;t worry. As always, I&#8217;ll explain each step in detail and give you code to create this project.</p>



<h2 class="wp-block-heading">Create Photon Packer Template</h2>



<p>If you don&#8217;t know this about me by now, I&#8217;m a huge fan of packer. As such, we&#8217;ll be using it to create a template. You can find the source code for this packer template on <a href="https://github.com/jonhowe/Virtjunkie.com/tree/master/Packer/PhotonOS4" data-type="URL" data-id="https://github.com/jonhowe/Virtjunkie.com/tree/master/Packer/PhotonOS4">my website&#8217;s github repository</a></p>



<p>To get a local copy, run the following command:</p>



<p>
			<span id="urvanov-syntax-highlighter-667f6dd472a21233230751" class="urvanov-syntax-highlighter-syntax urvanov-syntax-highlighter-syntax-inline  crayon-theme-classic crayon-theme-classic-inline urvanov-syntax-highlighter-font-monaco" style="font-size: 12px !important; line-height: 15px !important;font-size: 12px !important;"><span class="crayon-pre urvanov-syntax-highlighter-code" style="font-size: 12px !important; line-height: 15px !important;font-size: 12px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;"><span class="crayon-e">git </span><span class="crayon-r">clone</span><span class="crayon-h"> </span><span class="crayon-v">https</span><span class="crayon-o">:</span><span class="crayon-o">/</span><span class="crayon-o">/</span><span class="crayon-v">github</span><span class="crayon-e">.com</span><span class="crayon-o">/</span><span class="crayon-v">jonhowe</span><span class="crayon-o">/</span><span class="crayon-v">Virtjunkie</span><span class="crayon-e">.com</span><span class="crayon-e">.git</span></span></span></p>



<p>You can find all source code in the directory Virtjunkie.com/Packer/PhotonOS4.</p>



<h3 class="wp-block-heading">Create Custom ISO</h3>



<p>Unfortunately, Photon OS, even in v4, doesn&#8217;t support providing the kickstart file via CD-ROM or floppy (see <a rel="noreferrer noopener" href="https://github.com/vmware/photon/issues/1113" target="_blank">Issue#1113</a>, <a rel="noreferrer noopener" href="https://github.com/vmware/photon/issues/798" data-type="URL" data-id="https://github.com/vmware/photon/issues/798" target="_blank">Issue#798)</a>.  Unfortunately, this means that if we want (or need) to use the vsphere-iso builder, we&#8217;ll need to create an ISO with the kickstart file embedded. <a rel="noreferrer noopener" href="https://vmware.github.io/photon/docs/user-guide/working-with-kickstart/#building-an-iso-with-a-kickstart-config-file" target="_blank">I&#8217;m not going to duplicate documentation, so here&#8217;s the official documentation from VMware on how to add a kickstart file.</a></p>



<p>Instead of using the sample my_ks.cfg file provided in the ISO, use the version below.</p>



<p class="has-black-color has-luminous-vivid-amber-background-color has-text-color has-background">IMPORTANT: Ensure that you replace [yourpassword] with your actual password</p>



<script src="https://gist.github.com/jonhowe/7da290c7cfd660ddb220c96349d0f024.js"></script>



<h3 class="wp-block-heading">Use Packer To Create vSphere Template</h3>



<p class="has-luminous-vivid-amber-background-color has-background">IMPORTANT: Ensure that the password assigned to &#8220;root_password&#8221; in Virtjunkie.com/Packer/PhotonOS4/packer-photon.json.pkr.hcl matches what is set in the kickstart file above</p>



<pre class="urvanov-syntax-highlighter-plain-tag">packer build -var-file=nable.auto.pkrvars.hcl -var-file=vars iso-local-4.0GA.json -only=vsphere-iso.vmware-template packer-photon.json.pkr.hcl</pre>



<h2 class="wp-block-heading">Deploy Photon 4 VM</h2>



<p>For production systems, I typically use Terraform to deploy my VMs, and that&#8217;s what I did. I&#8217;m not going to go over that, as I&#8217;ve done it before. If nothing else, just deploy the VM from a template, assign it a static IP in the guest customization specification, and then log in using credentials set in the kickstart file.</p>



<h2 class="wp-block-heading">Configure Server</h2>



<h3 class="wp-block-heading">Install Packages</h3>



<p>Execute the commands below to install required packages, and to clone the repository</p>



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



<h3 class="wp-block-heading">Configure Shims</h3>



<p>There&#8217;s a bit of config we&#8217;ll need to do in order to make this production ready.</p>



<h4 class="wp-block-heading">Configure Teams</h4>



<p>A fellow VMware vExpert, Shane Moore has an excellent article. So that I don&#8217;t recreate the wheel, please <a rel="noreferrer noopener" href="https://www.virtuallyshane.com/posts/how-to-send-vrealize-operations-alerts-into-microsoft-teams" target="_blank">see his instructions</a> for how to prep your environment to use Microsoft Teams.</p>



<p>In short, you&#8217;ll create a webhook connector in the Microsoft Teams channel, and plug the URL that you get from Teams into the teams shim file.</p>



<h4 class="wp-block-heading">Configure OpsGenie</h4>



<p>OpsGenie is pretty simple. All we&#8217;ll need to do is create an integration by selecting your team in Opsgenie, navigating to Integrations, then selecting Add Integration.</p>



<figure class="wp-block-gallery columns-1 is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex"><ul class="blocks-gallery-grid"><li class="blocks-gallery-item"><figure><a href="https://www.virtjunkie.com/wp-content/uploads/2021/07/image-1024x138.png"><img decoding="async" width="1024" height="138" src="https://www.virtjunkie.com/wp-content/uploads/2021/07/image-1024x138.png" alt="" data-id="1447" class="wp-image-1447" srcset="/wp-content/uploads/2021/07/image-1024x138.png 1024w, /wp-content/uploads/2021/07/image-300x40.png 300w, /wp-content/uploads/2021/07/image-768x104.png 768w, /wp-content/uploads/2021/07/image-1536x207.png 1536w, /wp-content/uploads/2021/07/image.png 1660w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></figure></li></ul></figure>



<p>In the resulting list of available integrations, select API.</p>



<figure class="wp-block-gallery columns-1 is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex"><ul class="blocks-gallery-grid"><li class="blocks-gallery-item"><figure><a href="https://www.virtjunkie.com/wp-content/uploads/2021/07/image-1.png"><img decoding="async" width="229" height="189" src="https://www.virtjunkie.com/wp-content/uploads/2021/07/image-1.png" alt="" data-id="1448" class="wp-image-1448"/></a></figure></li></ul></figure>



<p>Then note the API key (you can grab it later, it doesn&#8217;t disappear when you navigate away). We&#8217;ll use that when we configure outbound settings in vROps to use OpsGenie.</p>



<h4 class="wp-block-heading">Disable Unused Shims</h4>



<p>In my environment, I&#8217;m only going to be using Teams and OpsGenie alerts. To reduce bloat and access points that could cause me security issues, I&#8217;m disabling all shims not in use.</p>



<p>Edit the file 
			<span id="urvanov-syntax-highlighter-667f6dd472a2d621469366" class="urvanov-syntax-highlighter-syntax urvanov-syntax-highlighter-syntax-inline  crayon-theme-classic crayon-theme-classic-inline urvanov-syntax-highlighter-font-monaco" style="font-size: 12px !important; line-height: 15px !important;font-size: 12px !important;"><span class="crayon-pre urvanov-syntax-highlighter-code" style="font-size: 12px !important; line-height: 15px !important;font-size: 12px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;"><span class="crayon-v">loginsightwebhookdemo</span><span class="crayon-o">/</span><span class="crayon-v">webhook</span><span class="crayon-o">-</span><span class="crayon-v">shims</span><span class="crayon-o">/</span><span class="crayon-v">loginsightwebhookdemo</span><span class="crayon-o">/</span><span class="crayon-v">__init__</span><span class="crayon-sy">.</span><span class="crayon-v">py</span></span></span></p>



<script src="https://gist.github.com/jonhowe/1d6fa1a003732c7200ec1ca28e509751.js"></script>



<h4 class="wp-block-heading">Disable Welcome Page</h4>



<p>This could probably be optional, but I appreciate not having a welcome/hello world webpage open for a production service. We&#8217;ll disable it.</p>



<p><meta http-equiv="content-type" content="text/html; charset=utf-8">Edit the file 
			<span id="urvanov-syntax-highlighter-667f6dd472a31776865240" class="urvanov-syntax-highlighter-syntax urvanov-syntax-highlighter-syntax-inline  crayon-theme-classic crayon-theme-classic-inline urvanov-syntax-highlighter-font-monaco" style="font-size: 12px !important; line-height: 15px !important;font-size: 12px !important;"><span class="crayon-pre urvanov-syntax-highlighter-code" style="font-size: 12px !important; line-height: 15px !important;font-size: 12px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;"><span class="crayon-v">loginsightwebhookdemo</span><span class="crayon-o">/</span><span class="crayon-v">webhook</span><span class="crayon-o">-</span><span class="crayon-v">shims</span><span class="crayon-o">/</span><span class="crayon-v">loginsightwebhookdemo</span><span class="crayon-o">/</span><span class="crayon-v">__init__</span><span class="crayon-sy">.</span><span class="crayon-v">py</span></span></span></p>



<script src="https://gist.github.com/jonhowe/872a49c369ee36ff9bee6be431572a49.js"></script>



<h2 class="wp-block-heading">Configure Systemd</h2>



<p>Create two files: 
			<span id="urvanov-syntax-highlighter-667f6dd472a32397019482" class="urvanov-syntax-highlighter-syntax urvanov-syntax-highlighter-syntax-inline  crayon-theme-classic crayon-theme-classic-inline urvanov-syntax-highlighter-font-monaco" style="font-size: 12px !important; line-height: 15px !important;font-size: 12px !important;"><span class="crayon-pre urvanov-syntax-highlighter-code" style="font-size: 12px !important; line-height: 15px !important;font-size: 12px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;"><span class="crayon-o">/</span><span class="crayon-v">etc</span><span class="crayon-o">/</span><span class="crayon-v">systemd</span><span class="crayon-o">/</span><span class="crayon-v">system</span><span class="crayon-o">/</span><span class="crayon-v">gunicorn</span><span class="crayon-sy">.</span><span class="crayon-v">service</span></span></span> and 
			<span id="urvanov-syntax-highlighter-667f6dd472a34930981274" class="urvanov-syntax-highlighter-syntax urvanov-syntax-highlighter-syntax-inline  crayon-theme-classic crayon-theme-classic-inline urvanov-syntax-highlighter-font-monaco" style="font-size: 12px !important; line-height: 15px !important;font-size: 12px !important;"><span class="crayon-pre urvanov-syntax-highlighter-code" style="font-size: 12px !important; line-height: 15px !important;font-size: 12px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;"><span class="crayon-o">/</span><span class="crayon-v">etc</span><span class="crayon-o">/</span><span class="crayon-v">systemd</span><span class="crayon-o">/</span><span class="crayon-v">system</span><span class="crayon-o">/</span><span class="crayon-v">gunicorn</span><span class="crayon-sy">.</span><span class="crayon-v">socket</span></span></span> and populate with the text below. </p>



<p>
			<span id="urvanov-syntax-highlighter-667f6dd472a35293395456" class="urvanov-syntax-highlighter-syntax urvanov-syntax-highlighter-syntax-inline  crayon-theme-classic crayon-theme-classic-inline urvanov-syntax-highlighter-font-monaco" style="font-size: 12px !important; line-height: 15px !important;font-size: 12px !important;"><span class="crayon-pre urvanov-syntax-highlighter-code" style="font-size: 12px !important; line-height: 15px !important;font-size: 12px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;"><span class="crayon-o">/</span><span class="crayon-v">etc</span><span class="crayon-o">/</span><span class="crayon-v">systemd</span><span class="crayon-o">/</span><span class="crayon-v">system</span><span class="crayon-o">/</span><span class="crayon-v">gunicorn</span><span class="crayon-sy">.</span><span class="crayon-v">service</span></span></span></p>



<p>This service file ensures that Gunicorn is started the same way, and is managed by systemd. You&#8217;ll note that it <em>requires</em> gunicorn.socket, which we will create later.</p>



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



<p>
			<span id="urvanov-syntax-highlighter-667f6dd472a36606332940" class="urvanov-syntax-highlighter-syntax urvanov-syntax-highlighter-syntax-inline  crayon-theme-classic crayon-theme-classic-inline urvanov-syntax-highlighter-font-monaco" style="font-size: 12px !important; line-height: 15px !important;font-size: 12px !important;"><span class="crayon-pre urvanov-syntax-highlighter-code" style="font-size: 12px !important; line-height: 15px !important;font-size: 12px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;"><span class="crayon-o">/</span><span class="crayon-v">etc</span><span class="crayon-o">/</span><span class="crayon-v">systemd</span><span class="crayon-o">/</span><span class="crayon-v">system</span><span class="crayon-o">/</span><span class="crayon-v">gunicorn</span><span class="crayon-sy">.</span><span class="crayon-v">socket</span></span></span></p>



<p>This socket file sets permissions for the socket assigned to gunicorn</p>



<script src="https://gist.github.com/jonhowe/8398a06c4395763a82faa480de19206e.js"></script>



<h2 class="wp-block-heading">Configure Nginx</h2>



<p>Replace the file 
			<span id="urvanov-syntax-highlighter-667f6dd472a37307294691" class="urvanov-syntax-highlighter-syntax urvanov-syntax-highlighter-syntax-inline  crayon-theme-classic crayon-theme-classic-inline urvanov-syntax-highlighter-font-monaco" style="font-size: 12px !important; line-height: 15px !important;font-size: 12px !important;"><span class="crayon-pre urvanov-syntax-highlighter-code" style="font-size: 12px !important; line-height: 15px !important;font-size: 12px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;"><span class="crayon-o">/</span><span class="crayon-v">etc</span><span class="crayon-o">/</span><span class="crayon-v">nginx</span><span class="crayon-o">/</span><span class="crayon-v">nginx</span><span class="crayon-sy">.</span><span class="crayon-v">conf</span></span></span> with the contents below</p>



<p>This is telling Nginx to connect directly to the socket we&#8217;re creating with the systemd socket gunicorn.socket we created earlier.</p>



<script src="https://gist.github.com/jonhowe/78964d1cc4a32bf5e13a7369a36eaa13.js"></script>



<h2 class="wp-block-heading">Enable and Start All Services</h2>



<p>Finally, enable, and start both services, and restart Nginx</p>



<div class="wp-block-urvanov-syntax-highlighter-code-block"><pre class="urvanov-syntax-highlighter-plain-tag">systemctl enable gunicorn.socket
systemctl enable gunicorn.service
systemctl restart gunicorn.socket 
systemctl restart gunicorn.service
systemctl restart nginx.service</pre></div>



<h2 class="wp-block-heading">Configure vRealize Operations Manager</h2>



<p>At this point, all we need to do is configure an outbound instance for Microsoft Teams and OpsGenie. </p>



<h3 class="wp-block-heading">Add a New Rest Notification Plugin</h3>



<h4 class="wp-block-heading">OpsGenie</h4>



<p>To do this, sign into vROps, and navigate to Administration -&gt;Management-&gt;Outbound Settings, or https://[Your_vROps_URL]/ui/index.action#/administration/outbound-alert-settings</p>



<figure class="wp-block-gallery columns-1 is-cropped wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex"><ul class="blocks-gallery-grid"><li class="blocks-gallery-item"><figure><a href="https://www.virtjunkie.com/wp-content/uploads/2021/07/image-2.png"><img loading="lazy" decoding="async" width="636" height="351" src="https://www.virtjunkie.com/wp-content/uploads/2021/07/image-2.png" alt="" data-id="1452" class="wp-image-1452" srcset="/wp-content/uploads/2021/07/image-2.png 636w, /wp-content/uploads/2021/07/image-2-300x166.png 300w" sizes="(max-width: 636px) 100vw, 636px" /></a></figure></li></ul></figure>



<p>After you select the Rest Notification Plugin, there are 3 fields required in the Add/Edit Outbound Instance box</p>



<figure class="wp-block-table"><table><tbody><tr><td>Item</td><td>Description</td><td>Example</td></tr><tr><td>Instance Name</td><td>Name of the rest notification plugin created</td><td>Opsgenie</td></tr><tr><td>URL</td><td>URL to OpsGenie shim endpoint</td><td>http://&lt;IP/ or Hostname of Photon VM&gt;/endpoint/opsgenie/&lt;api key&gt;</td></tr><tr><td>Content Type</td><td>Content Type &#8211; Unless you&#8217;re working with a SOAP API (which we aren&#8217;t), this will always be application/json</td><td></td></tr></tbody></table></figure>



<figure class="wp-block-gallery columns-1 is-cropped wp-block-gallery-4 is-layout-flex wp-block-gallery-is-layout-flex"><ul class="blocks-gallery-grid"><li class="blocks-gallery-item"><figure><a href="https://www.virtjunkie.com/wp-content/uploads/2021/07/image-3.png"><img loading="lazy" decoding="async" width="580" height="479" src="https://www.virtjunkie.com/wp-content/uploads/2021/07/image-3.png" alt="" data-id="1453" class="wp-image-1453" srcset="/wp-content/uploads/2021/07/image-3.png 580w, /wp-content/uploads/2021/07/image-3-300x248.png 300w" sizes="(max-width: 580px) 100vw, 580px" /></a></figure></li></ul></figure>



<p>Finally, navigate to Alerts -&gt; Configuration -&gt; Notification (https://<meta http-equiv="content-type" content="text/html; charset=utf-8">[Your_vROps_URL]/ui/index.action#/alerts/notifications) and add a new rule that targets the adapter you just created.</p>



<figure class="wp-block-gallery columns-1 is-cropped wp-block-gallery-5 is-layout-flex wp-block-gallery-is-layout-flex"><ul class="blocks-gallery-grid"><li class="blocks-gallery-item"><figure><a href="https://www.virtjunkie.com/wp-content/uploads/2021/07/image-4.png"><img loading="lazy" decoding="async" width="883" height="486" src="https://www.virtjunkie.com/wp-content/uploads/2021/07/image-4.png" alt="" data-id="1454" class="wp-image-1454" srcset="/wp-content/uploads/2021/07/image-4.png 883w, /wp-content/uploads/2021/07/image-4-300x165.png 300w, /wp-content/uploads/2021/07/image-4-768x423.png 768w" sizes="(max-width: 883px) 100vw, 883px" /></a></figure></li></ul></figure>



<h4 class="wp-block-heading">Teams</h4>



<p>Again, I&#8217;m not in the business of recreating the wheel, <a href="https://www.virtuallyshane.com/posts/how-to-send-vrealize-operations-alerts-into-microsoft-teams" target="_blank" rel="noreferrer noopener">so check out Shane&#8217;s blog for info on how to do this</a>.</p>



<h2 class="wp-block-heading">References</h2>



<figure class="wp-block-table"><table><tbody><tr><td><a href="https://www.virtuallyshane.com/posts/how-to-send-vrealize-operations-alerts-into-microsoft-teams" target="_blank" rel="noreferrer noopener">https://www.virtuallyshane.com/posts/how-to-send-vrealize-operations-alerts-into-microsoft-teams</a></td><td>Fellow vExpert Shane Moore&#8217;s article for setting MS Teams forwarding</td></tr><tr><td><a href="https://github.com/vmw-loginsight/webhook-shims" target="_blank" rel="noreferrer noopener">https://github.com/vmw-loginsight/webhook-shims</a></td><td>Official Github site for the webhook-shims project</td></tr><tr><td><a href="https://blogs.vmware.com/management/2017/01/vrealize-webhooks-infinite-integrations.html" target="_blank" rel="noreferrer noopener">https://blogs.vmware.com/management/2017/01/vrealize-webhooks-infinite-integrations.html</a></td><td>VMware Blog article that got me started on this journey</td></tr><tr><td><a href="https://vmware.github.io/photon/docs/user-guide/working-with-kickstart/" target="_blank" rel="noreferrer noopener">https://vmware.github.io/photon/docs/user-guide/working-with-kickstart/</a></td><td>VMware Photon documentation</td></tr><tr><td><a href="https://github.com/vmware/photon/issues/1113" target="_blank" rel="noreferrer noopener">https://github.com/vmware/photon/issues/1113</a></td><td>Github Issue for presenting Kickstart file to Photon over cdrom/floppy</td></tr><tr><td><a href="https://github.com/vmware/photon/issues/798" target="_blank" rel="noreferrer noopener">https://github.com/vmware/photon/issues/798</a></td><td><meta http-equiv="content-type" content="text/html; charset=utf-8">Another Github Issue for presenting Kickstart file to Photon over cdrom/floppy</td></tr></tbody></table></figure>
<p>The post <a href="/2021/07/23/vrops-opsgenie-production-setup/">Configure vROps To Send Alerts to OpsGenie and Microsoft Teams</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2021/07/23/vrops-opsgenie-production-setup/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Big Things have Small Beginnings &#8211; How I Beat 2020</title>
		<link>/2020/08/26/big-things-have-small-beginnings-how-i-beat-2020/</link>
					<comments>/2020/08/26/big-things-have-small-beginnings-how-i-beat-2020/#comments</comments>
		
		<dc:creator><![CDATA[Jon]]></dc:creator>
		<pubDate>Wed, 26 Aug 2020 13:56:22 +0000</pubDate>
				<category><![CDATA[Certification]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[vExpert]]></category>
		<category><![CDATA[VMware]]></category>
		<guid isPermaLink="false">http://www.virtjunkie.com/?p=1378</guid>

					<description><![CDATA[<p>I finally took the the VCP-DCV exam, but more importantly, this marks three certs in the last month. COVID bummed me out, I didn't like it, so I beat it by hard learning and pushing myself.</p>
<p>The post <a href="/2020/08/26/big-things-have-small-beginnings-how-i-beat-2020/">Big Things have Small Beginnings &#8211; How I Beat 2020</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>I&#8217;ve got well north of a decade of VMware experience and I finally took the the VCP-DCV exam. Much more importantly, this is the third cert I&#8217;ve achieved&nbsp;in the last month. The state of the world got me down. I decided I didn&#8217;t like that feeling, so I did something about it. I&#8217;m embracing hard learning and pushing myself to learn net new technologies while also expanding my current baseline. I&#8217;ll get the AWS Certified Solution Architect &#8211; Associate cert before October, and a couple more before the end of the year. I&#8217;m not quite ready to talk about the last two, but they are going to be significant. Most importantly, I&#8217;m feeling good!</p>



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



<p>Everything happening in the world these days started to get me down a bit starting a few months ago. I decided to embrace change in my life with things I could affect instead of letting the things that I couldn&#8217;t affect get me down. A leader in my organization once brought up the concept of &#8220;hard learning&#8221;, which is learning things that are outside of your comfort zone. I decided that hard learning is what I&#8217;ll embrace in order to get the serotonin boost I&#8217;ve been craving. </p>



<p>Anyone that has talked to me about certification is aware that I haven&#8217;t placed a lot of value on achieving them in the past, and that I&#8217;ve relied on the ability to hit the ground running as proof of competency. What I didn&#8217;t think about until recently is that very few people have a certificate AND can hit the ground running. An even smaller group contains people that receive certs that actually have hands on experience with their particular certification area. I aim to be a part of the very small group of people that can hit the ground running, is certified, and has significant experience backing everything up.</p>



<p>Part of the hard learning for me here was realizing that I was wrong about certs. I needed to make them work for me, by studying and ensuring I have actual experience&nbsp;so they are not just a meaningless piece of (digital) paper. The other hard learning part is pushing myself to learn new things. It&#8217;s easy to get stuck in your comfort zone. Mario Andretti said, &#8220;If everything seems under control, you&#8217;re not going fast enough&#8221;. In tech, we die on the vine when we are not pushing and innovating ourselves. I&#8217;m working hard to apply this principle to myself by learning things that aren&#8217;t connected to my current skill set.</p>



<p>Anyhow, that&#8217;s all I&#8217;ve got right now. Big things have small beginnings. I appreciate you spending the time to read this.</p>



<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-image"><figure class="aligncenter size-medium"><img loading="lazy" decoding="async" width="300" height="300" src="https://www.virtjunkie.com/wp-content/uploads/2020/08/vmware-certified-professional-data-center-virtualization-2020-300x300.png" alt="" class="wp-image-1380" srcset="/wp-content/uploads/2020/08/vmware-certified-professional-data-center-virtualization-2020-300x300.png 300w, /wp-content/uploads/2020/08/vmware-certified-professional-data-center-virtualization-2020-150x150.png 150w, /wp-content/uploads/2020/08/vmware-certified-professional-data-center-virtualization-2020.png 600w" sizes="(max-width: 300px) 100vw, 300px" /><figcaption><a href="https://www.youracclaim.com/badges/f0b2b22f-b7c2-4c61-a753-37a21a9bd588/public_url" target="_blank" rel="noreferrer noopener">View on Acclaim</a></figcaption></figure></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-image"><figure class="aligncenter size-medium"><img loading="lazy" decoding="async" width="300" height="300" src="https://www.virtjunkie.com/wp-content/uploads/2020/08/double-vcp-data-center-virtualization-cloud-management-1-300x300.png" alt="" class="wp-image-1381" srcset="/wp-content/uploads/2020/08/double-vcp-data-center-virtualization-cloud-management-1-300x300.png 300w, /wp-content/uploads/2020/08/double-vcp-data-center-virtualization-cloud-management-1-150x150.png 150w, /wp-content/uploads/2020/08/double-vcp-data-center-virtualization-cloud-management-1.png 352w" sizes="(max-width: 300px) 100vw, 300px" /><figcaption><a href="https://www.youracclaim.com/badges/a9d308c6-6bb9-416d-a14f-44bde5b1bdb2/public_url" data-type="URL" data-id="https://www.youracclaim.com/badges/a9d308c6-6bb9-416d-a14f-44bde5b1bdb2/public_url" target="_blank" rel="noreferrer noopener">View on Acclaim</a></figcaption></figure></div>
</div>
</div>
<p>The post <a href="/2020/08/26/big-things-have-small-beginnings-how-i-beat-2020/">Big Things have Small Beginnings &#8211; How I Beat 2020</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2020/08/26/big-things-have-small-beginnings-how-i-beat-2020/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>VMware Provisioning using Hashicorp Terraform  &#8211; Part 2</title>
		<link>/2020/07/06/vmware-provisioning-using-hashicorp-terraform-part-2/</link>
					<comments>/2020/07/06/vmware-provisioning-using-hashicorp-terraform-part-2/#respond</comments>
		
		<dc:creator><![CDATA[Jon]]></dc:creator>
		<pubDate>Mon, 06 Jul 2020 13:00:00 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[Hashicorp]]></category>
		<category><![CDATA[InfrastructureAsCode]]></category>
		<category><![CDATA[Terraform]]></category>
		<category><![CDATA[VMware]]></category>
		<guid isPermaLink="false">http://www.virtjunkie.com/?p=1334</guid>

					<description><![CDATA[<p>In the first part of this series we went over Terraform at a very high level and discussed a basic example of using it to provision a single Windows VM or a single Linux VM. While this is a helpful baseline, it doesn&#8217;t realistically help us when defining our application structure in code. For example, [&#8230;]</p>
<p>The post <a href="/2020/07/06/vmware-provisioning-using-hashicorp-terraform-part-2/">VMware Provisioning using Hashicorp Terraform  &#8211; Part 2</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>In the <a href="https://www.virtjunkie.com/vmware-provisioning-using-hashicorp-terraform/" target="_blank" rel="noreferrer noopener">first part of this series</a> we went over Terraform at a very high level and discussed a basic example of using it to provision a single Windows VM or a single Linux VM. While this is a helpful baseline, it doesn&#8217;t realistically help us when defining our application structure in code. For example, if you wanted to set up a <a rel="noreferrer noopener" href="https://en.wikipedia.org/wiki/Multitier_architecture#Three-tier_architecture" target="_blank">three tier application</a> you&#8217;ll need to have three separate instances of the project we used. At that point we&#8217;re not really gaining much efficiency over deploying a template in vCenter. In this post I&#8217;ll discuss Terraform Modules, give an example of how to store your Terraform Module in GitHub, and provide a real-life example of how to deploy a three tier application using multiple source images.</p>



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



<h2 class="wp-block-heading">Introduction to Terraform Modules</h2>



<p>In Part 1 of this series I <a href="https://www.virtjunkie.com/vmware-provisioning-using-hashicorp-terraform/#main_tf" target="_blank" rel="noreferrer noopener">compared traditional programming languages to Terraform</a>. We can do the same thing with Modules. For example, with Powershell or Python, you can download a module that provides functionality and consume that functionality in your code without having to author it. The same thing happens in Terraform, and just like with other languages, you can create your own, or download one from a third party.</p>



<h3 class="wp-block-heading">Terraform Registry</h3>



<p>Thankfully, <a rel="noreferrer noopener" href="https://registry.terraform.io/" target="_blank">Hashicorp provides us with a registry</a> that we can use to find and consume Terraform Modules. At the time this post is published, the Terraform Registry contains support for <a rel="noreferrer noopener" href="https://registry.terraform.io/browse/providers" target="_blank">63 providers</a> and has <a rel="noreferrer noopener" href="https://registry.terraform.io/browse/modules" target="_blank">3454 Modules</a>. So if you are looking for specific functionality, check there first!</p>



<h2 class="wp-block-heading">Roll Your Own Module</h2>



<p>That said, you may have a need to create your own module, or if you&#8217;re like me, want to make sure you understand how modules work before you use one that someone else created.</p>



<h3 class="wp-block-heading">Best Practices</h3>



<p>First and foremost, you&#8217;ll want to take a look at the official documentation from Hashicorp on the standard module structure. It gets pretty in-depth, but I&#8217;ll hit on a few high level important items.</p>



<ul><li>Store your module in github</li><li>At the very least, make sure you split your variables and outputs into different TF files</li><li>Include an examples directory and show every variation of how to call your module. For example, if you can create a linux image or a windows image, but you need to call them differently, show an example for each.</li><li>Include a README.md file that has a description of the module, but also references your examples</li></ul>



<h3 class="wp-block-heading">Why store your module in GitHub?</h3>



<p>Aside from the wide ranging benefits of using version control, using GitHub will allow you to call a specific version of your module.</p>



<h3 class="wp-block-heading">File Structure</h3>



<p>The following files should be in your GitHub reposity. When you run <code>terraform init</code>, it will be downloaded to the .terraform directory on the machine running the project.</p>



<h4 class="wp-block-heading">main.tf</h4>



<script src="https://gist.github.com/jonhowe/7526c2316eda915116ae63248154b4cb.js"></script>



<h4 class="wp-block-heading">variables.tf</h4>



<script src="https://gist.github.com/jonhowe/5d44ecc0680f4c64447f9e7bab7b5150.js"></script>



<h4 class="wp-block-heading">output.tf</h4>



<script src="https://gist.github.com/jonhowe/81b6205c683c0a9273e29b9c62ee8a79.js"></script>



<h2 class="wp-block-heading">How to use this module?</h2>



<p>Now that we&#8217;ve created our module and have it in Github, all we need to do in order to complete our initial goal of having a three tier application is to create a single main.tf file, and call the module 3 times. Below is an example that allows us to set separate information for each of the new VMs.</p>



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



<h2 class="wp-block-heading">References and what&#8217;s next?</h2>



<h3 class="wp-block-heading">What&#8217;s Next?</h3>



<p>At this point we have shown how to create and <a href="https://www.virtjunkie.com/vmware-template-packer/" target="_blank" rel="noreferrer noopener">manage images using packer</a>, a <a href="https://www.virtjunkie.com/vmware-provisioning-using-hashicorp-terraform/" target="_blank" rel="noreferrer noopener">couple</a> of <a href="https://www.virtjunkie.com/vmware-provisioning-using-hashicorp-terraform-part-2/" target="_blank" rel="noreferrer noopener">parts</a> on how to use Terraform to deploy infrastructure, so all we have left is doing configuration of our newly created VMs.</p>



<ul><li>Use Ansible to configure our newly provisioned VMs</li><li>Wrap the Terraform VM Deployment process, as well as the Ansible VM configuration process together into a single process you execute once</li><li>Use Ansible to do a greenfield deployment of a vSphere environment</li></ul>



<h3 class="wp-block-heading">References</h3>



<ul><li><a rel="noreferrer noopener" href="https://www.virtjunkie.com/vmware-provisioning-using-hashicorp-terraform/" target="_blank">Part 1 &#8211; Provision VMware VMs using Terraform</a></li><li><a href="https://registry.terraform.io/">Terraform Registry</a></li><li><a rel="noreferrer noopener" href="https://www.terraform.io/docs/modules/index.html#standard-module-structure" target="_blank">Module Structure</a></li></ul>
<p>The post <a href="/2020/07/06/vmware-provisioning-using-hashicorp-terraform-part-2/">VMware Provisioning using Hashicorp Terraform  &#8211; Part 2</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2020/07/06/vmware-provisioning-using-hashicorp-terraform-part-2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>VMware Provisioning using Hashicorp Terraform</title>
		<link>/2020/04/22/vmware-provisioning-using-hashicorp-terraform/</link>
					<comments>/2020/04/22/vmware-provisioning-using-hashicorp-terraform/#comments</comments>
		
		<dc:creator><![CDATA[Jon]]></dc:creator>
		<pubDate>Wed, 22 Apr 2020 13:00:00 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[Hashicorp]]></category>
		<category><![CDATA[Terraform]]></category>
		<category><![CDATA[VMware]]></category>
		<guid isPermaLink="false">http://www.virtjunkie.com/?p=1181</guid>

					<description><![CDATA[<p>As a part of my effort to use Infrastructure as Code to define and automate VMware environments, I'm taking a look at Terraform for VMware provisioning. In this article, I will give a brief intro to Terraform, talk about how it can help in managing your enterprise environments, as well as how it's different than Ansible. I'll also provide example code and description for how to provision Windows and Linux VMs. </p>
<p>The post <a href="/2020/04/22/vmware-provisioning-using-hashicorp-terraform/">VMware Provisioning using Hashicorp Terraform</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>As a part of my effort to use Infrastructure as Code to define and automate VMware environments, I&#8217;m taking a look at Terraform for VMware provisioning. In this article, I will give a brief intro to Terraform, talk about how it can help in managing your enterprise environments, as well as how it&#8217;s different than Ansible. I&#8217;ll also provide example code and description for how to provision Windows and Linux VMs. </p>



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



<h2 class="wp-block-heading">Source Code</h2>



<p>As always, you can find all of the source code for this project on my <a href="https://github.com/jonhowe/Virtjunkie.com/tree/master/Terraform" target="_blank" rel="noreferrer noopener">Github account</a>.</p>



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



<p>According to Hashicorp, <em>&#8220;Terraform is a tool for building, changing, and versioning infrastructure safely and efficiently. Terraform can manage existing and popular service providers as well as custom in-house solutions&#8221;</em>. </p>
</div></div>



<p>Like in <a rel="noreferrer noopener" href="https://www.virtjunkie.com/vmware-template-packer/" target="_blank">my packer article</a>, I want to be clear that this isn&#8217;t a Terraform 101 article. Hashicorp provides some fairly good documentation, and the internet is full of articles explaining how to get going with Terraform.  That said, I will provide a short references for some of the building blocks of Terraform.</p>
</div></div>
</div></div>
</div></div>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">Terraform VS. Deploying VMware Templates in vCenter VS. Ansible</h2>



<p>Should you use Terraform to provision VMs instead of deploying a VM from vCenter? Should you use Ansible instead of either of them? As with everything in technology these days, it depends. The skill we should all work towards is developing the ability to determine what tool we should use for the task at hand.</p>
</div></div>



<h3 class="wp-block-heading">Deploying VMware Templates in vCenter</h3>



<p>Nothing new here.. log into vCenter, deploy a VM from a template, use a guest customization specification. The pro&#8217;s are obvious, so I&#8217;ll skip over them and focus on the cons.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<p><strong>Cons:</strong></p>



<ul><li>Multi-step manual process for each VM</li><li>Guest Customization Specification is tied to a single vCenter Server which reduces scalability</li><li>Multiple VMs require multiple iterations of the same manual process</li></ul>
</div></div>



<h3 class="wp-block-heading">Deploy VMs via Ansible</h3>



<p>Ansible communicates with an OS via SSH on Linux, and via WinRM on Windows. It has different modules that can be used to communicate with different providers, such as AWS, GCP, and yes, VMware.</p>



<p><strong>Pros:</strong></p>



<ul><li>Infrastructure is defined in code</li><li>Excellent at ensuring desired state configuration of </li><li>Multi-os, and multi-cloud support</li></ul>



<p><strong>Cons:</strong></p>



<ul><li>This could end up being a bit of a holy war, but I consider it a con that Ansible requires different modules to connect to different cloud providers. They are maintained by different teams and individuals, and end up working differently than each other.</li></ul>



<h3 class="wp-block-heading">Deploy VMs using Terraform</h3>



<p>Terraform, similarly to Ansible, is able to communicate with Linux via SSH and Windows via WinRM. Where it differs, is it&#8217;s ability to communicate with cloud providers such as AWS, GCP, Azure, and VMware. Terraform uses the concept of &#8220;Providers&#8221;, with a number of them being maintained by Hashicorp, and a number of them being maintained by the community. In addition to cloud providers, they also have providers that allow for configuration of networking hardware, storage, databases, monitoring, DNS systems, and many more, all using the same structure in your code.</p>



<h2 class="wp-block-heading">Terraform Component Overview</h2>



<p>Few points to get us started here:</p>



<ul><li>Terraform will look in a directory for all files that have the extension of .tf, and .auto.tfvars</li><li>Terraform configuration files are written in <a rel="noreferrer noopener" href="https://www.terraform.io/docs/configuration/syntax.html" target="_blank">a language called HCL</a>, but can also be written in JSON.</li><li>Terraform uses the concept of blocks, I&#8217;ll go through them below</li></ul>



<h3 class="wp-block-heading">Resource Block</h3>



<p><a rel="noreferrer noopener" href="https://www.terraform.io/docs/configuration/resources.html" target="_blank">Hashicorp defines resources</a> as <em>the most important element in the Terraform language. Each resource block describes one or more infrastructure objects, such as virtual networks, compute instances, or higher-level components such as DNS records.</em> </p>



<p>In our example, we will be working with the resource type &#8220;vsphere_virtual_machine&#8221; that is defined by the vSphere provider. This resource block contains all information needed to provision and customize a new VM.</p>



<h3 class="wp-block-heading">Provider Block</h3>



<p>We&#8217;ll be working with the vSphere provider in this project. Providers have two main functions we should keep in mind when using Terraform with VMware.</p>



<ul><li>They define parameters used to connect to vCenter</li><li>They expose additional resources we can use. Most notably, the vsphere_virtual_machine resource.</li></ul>



<p><a href="https://www.terraform.io/docs/configuration/providers.html" target="_blank" rel="noreferrer noopener">Hashicorp Provider Documentation</a></p>



<h3 class="wp-block-heading">Data Source Blocks</h3>



<p>Hashicorp tells us that &#8220;<em><em>Data sources</em>&nbsp;allow data to be fetched or computed for use elsewhere in Terraform configuration. Use of data sources allows a Terraform configuration to make use of information defined outside of Terraform, or defined by another separate Terraform configuration</em>&#8221; and that <em>&#8220;Each&nbsp;provider&nbsp;may offer data sources alongside its set of&nbsp;resource types&#8221;</em>. </p>



<p>To say this &#8220;cloud agnostically&#8221;, data sources allow us to fetch information from a provider (whether it be something like AWS, GCP, Azure, or vSphere), and use that information in a resource.</p>



<p>To say this in &#8220;VMware Speak&#8221;, we use data sources to pull information like a datacenter, cluster, datastore, or port group from a vCenter, and use it to build a VM.</p>



<h3 class="wp-block-heading">Input Variable Block</h3>



<p>Hashicorp&#8217;s documentation says that Input Variables <em>&#8220;serve as parameters for a Terraform module, allowing aspects of the module to be customized without altering the module&#8217;s own source code, and allowing modules to be shared between different configurations</em>&#8220;. To say this another way, input variables end up working like parameters added on the command line on a script.</p>



<h2 class="wp-block-heading">Examples</h2>



<p>Let&#8217;s put all of this together. I&#8217;ll give you two examples here, one for setting up a Linux VM and one for a Windows VM.</p>



<h3 class="wp-block-heading">Provision Linux VM with Terraform</h3>



<p>The three files below are required for this project, and can be found in the <a href="https://github.com/jonhowe/Virtjunkie.com/tree/master/Terraform" target="_blank" rel="noreferrer noopener">github repository</a>.</p>



<pre class="urvanov-syntax-highlighter-plain-tag">├── main.tf
├── variables.tf
└── homelab.auto.tfvars</pre>



<h4 class="wp-block-heading">Quick Start</h4>



<p>Run the following commands to get started!</p>



<pre class="urvanov-syntax-highlighter-plain-tag">git clone https://github.com/jonhowe/Virtjunkie.com.git
cd Virtjunkie.com/Terraform/SingleLinuxVM
terraform init
terraform plan
terraform apply</pre>



<p>Running <strong><code>terraform init</code> </strong>will set up the Terraform project. It will download any required modules and plugins for the project to be created. It will store all of it&#8217;s files in a hidden directory called &#8220;.terraform&#8221;.</p>



<p>The command <code><strong>terraform plan</strong></code> looks at the destination and determines what needs to change. Optionally, you can have Terraform store this &#8220;plan&#8221; in a file to be used at a later time. To do this, you&#8217;ll run this command: <code><strong>terraform plan -out myplan.tfplan</strong></code>. The extension and file name are not important.</p>



<p>Finally, the command <code><strong>terraform apply</strong></code> is used to make changes to the environment that were determined in the &#8220;plan&#8221; step. Optionally, you can tell terraform to &#8220;apply&#8221; based on the output. To do this, you&#8217;ll run the following command: <code><strong>terraform apply myplan.tfplan</strong></code>. This isn&#8217;t necessary for a single VM deployment, but if you are using automation, or deploying multiple VMs, it is more important.</p>



<h4 class="wp-block-heading">main.tf</h4>



<p>As the name states, this is the main file in the project. It contains the provider, data source, and resource blocks.</p>



<p>The provider block simply is pretty self explanatory. If this is your first time looking at a Terraform file, you&#8217;ll probably be interested in the var.&#8221;whatever&#8221; lines. In the provider block, there&#8217;s a variable in the variables.tf file called vsphere_user (and the others as well). The &#8220;var.&#8221; prefix tells us that we should look for this variable definition in an input variables block.</p>



<p>The data blocks take raw data from the vSphere environment (datacenter, datastore, cluster, and port group) and store them in variables used for building a VM. </p>



<p>To understand this a bit more, please take a look at the picture below. We are creating a variable called <strong><code>datacenter_id</code></strong> on line 19 and assigning it the value <strong><code>data.vsphere_datacenter.dc.id</code></strong>. Understanding this concept is key to understanding how Terraform creates and consumes variables. The below image will elaborate a bit. The value of <strong><code>data.vsphere_datacenter.dc.id</code></strong> is returned from the datacenter object in the vCenter Server.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="775" height="368" src="https://www.virtjunkie.com/wp-content/uploads/2020/04/terraform-config.png" alt="" class="wp-image-1228" srcset="/wp-content/uploads/2020/04/terraform-config.png 775w, /wp-content/uploads/2020/04/terraform-config-300x142.png 300w, /wp-content/uploads/2020/04/terraform-config-768x365.png 768w" sizes="(max-width: 775px) 100vw, 775px" /></figure>



<p>I&#8217;ll be comparing the way that Terraform blocks work together to the way that a programming function works. I&#8217;ll be using the following pseudocode to show similarities. The main.tf file, alongside with the blocks it contains would correspond with the area below:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="797" height="276" src="https://www.virtjunkie.com/wp-content/uploads/2020/04/terraform-main.png" alt="" class="wp-image-1236" srcset="/wp-content/uploads/2020/04/terraform-main.png 797w, /wp-content/uploads/2020/04/terraform-main-300x104.png 300w, /wp-content/uploads/2020/04/terraform-main-768x266.png 768w" sizes="(max-width: 797px) 100vw, 797px" /></figure>



<p><strong>Line 40 &#8211; Resource block begins</strong><br>Now that we understand how to reference values from input and data variables, most of this should be pretty clear. The one area I want to spend a little bit of time on is the customize block, starting on line 67. In this example, we are simply setting the host name and the domain inside of the provisioned VM. However, there you could set static networking, dns and the time zone as well, if you like.</p>



<p>Here&#8217;s the code for the main.tf file. It&#8217;s also <a href="https://github.com/jonhowe/Virtjunkie.com/blob/master/Terraform/SingleLinuxVM/main.tf" target="_blank" rel="noreferrer noopener">available on github</a>.</p>



<pre class="urvanov-syntax-highlighter-plain-tag">#The variables are all defined in the variables.tf file. The values assigned to the variables are set in the auto.tfvars file

provider &quot;vsphere&quot; {
  #https://www.terraform.io/docs/providers/vsphere/index.html
  user                 = var.vsphere_user
  password             = var.vsphere_password
  vsphere_server       = var.vsphere_server
  allow_unverified_ssl = true
}

data &quot;vsphere_datacenter&quot; &quot;dc&quot; {
  #https://www.terraform.io/docs/providers/vsphere/d/datacenter.html
  name = var.datacenter
}

data &quot;vsphere_datastore&quot; &quot;datastore&quot; {
  #https://www.terraform.io/docs/providers/vsphere/d/datastore.html
  name          = var.datastore
  datacenter_id = data.vsphere_datacenter.dc.id
}

data &quot;vsphere_compute_cluster&quot; &quot;cluster&quot; {
  #https://www.terraform.io/docs/providers/vsphere/d/compute_cluster.html
  var.cluster
  datacenter_id = data.vsphere_datacenter.dc.id
}

data &quot;vsphere_network&quot; &quot;network&quot; {
  #https://www.terraform.io/docs/providers/vsphere/d/network.html
  name          = var.portgroup
  datacenter_id = data.vsphere_datacenter.dc.id
}

data &quot;vsphere_virtual_machine&quot; &quot;template&quot; {
  #https://www.terraform.io/docs/providers/vsphere/d/virtual_machine.html
  name          = var.template_name
  datacenter_id = data.vsphere_datacenter.dc.id
}

resource &quot;vsphere_virtual_machine&quot; &quot;vm&quot; {
  #https://www.terraform.io/docs/providers/vsphere/r/virtual_machine.html
  name             = var.vm_name
  resource_pool_id = data.vsphere_compute_cluster.cluster.resource_pool_id
  datastore_id     = data.vsphere_datastore.datastore.id

  num_cpus = var.vcpu_count
  memory   = var.memory
  guest_id = data.vsphere_virtual_machine.template.guest_id

  scsi_type = data.vsphere_virtual_machine.template.scsi_type

  network_interface {
    network_id   = data.vsphere_network.network.id
    adapter_type = data.vsphere_virtual_machine.template.network_interface_types&amp;#91;0]
  }

  disk {
    label            = &quot;disk0&quot;
    size             = data.vsphere_virtual_machine.template.disks.0.size
    eagerly_scrub    = data.vsphere_virtual_machine.template.disks.0.eagerly_scrub
    thin_provisioned = data.vsphere_virtual_machine.template.disks.0.thin_provisioned
  }

  clone {
    template_uuid = data.vsphere_virtual_machine.template.id

    customize {
      #https://www.terraform.io/docs/providers/vsphere/r/virtual_machine.html#linux-customization-options
      linux_options {
        host_name = var.vm_name
        domain    = var.domain_name
      }

      #This example uses DHCP. To switch to static IP addresses, comment the line below...
      network_interface {}

      #... and uncomment this bloc
      /*
      network_interface {
        ipv4_address = var.vm_ip
        ipv4_netmask = var.vm_cidr
    }
      ipv4_gateway = var.default_gw
      dns_server_list = &amp;#91;&quot;1.2.3.4&quot;]
    */

    }

  }
}</pre>



<h4 class="wp-block-heading">variables.tf</h4>



<p>Terraform can be most easily understood by comparing the structure of a project to a programming function. The main file is the body of the function, and it consumes values of variables to &#8220;do stuff&#8221;. Most programming languages require us to declare a variable before we can assign a value to it or use it. That&#8217;s really all the input variables block is for. In the example below, we are defining the variable name, providing a description for it, and assigning a default value.</p>



<p>If you want to use a pseudocode example, the variable definition below is the function of the input variable block, and the function of the entire variables.tf file</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="795" height="294" src="https://www.virtjunkie.com/wp-content/uploads/2020/04/terraform-variables-1.png" alt="" class="wp-image-1232" srcset="/wp-content/uploads/2020/04/terraform-variables-1.png 795w, /wp-content/uploads/2020/04/terraform-variables-1-300x111.png 300w, /wp-content/uploads/2020/04/terraform-variables-1-768x284.png 768w" sizes="(max-width: 795px) 100vw, 795px" /></figure>



<p>Here&#8217;s the code for the variables.tf file, which is also <a href="https://github.com/jonhowe/Virtjunkie.com/blob/master/Terraform/SingleLinuxVM/variables.tf" target="_blank" rel="noreferrer noopener">available on github</a>.</p>



<pre class="urvanov-syntax-highlighter-plain-tag">variable &quot;vsphere_server&quot; {
  description = &quot;vsphere server for the environment - EXAMPLE: vcenter01.hosted.local&quot;
  default     = &quot;vcenter.corp.lab&quot;
}

variable &quot;vsphere_user&quot; {
  description = &quot;vsphere server for the environment - EXAMPLE: vsphereuser&quot;
  default     = &quot;administrator@vsphere.local&quot;
}

variable &quot;vsphere_password&quot; {
  description = &quot;vsphere server password for the environment&quot;
  default     = &quot;VMware1!&quot;
}

variable &quot;adminpassword&quot; { 
    default = &quot;terraform&quot; 
    description = &quot;Administrator password for windows builds&quot;
}

variable &quot;datacenter&quot; { 
    default = &quot;Datacenter&quot;
    description = &quot;Datacenter name in vCenter&quot;
}

variable &quot;datastore&quot; { 
    default = &quot;vsanDatastore&quot; 
    description = &quot;datastore name in vCenter&quot;
}

variable &quot;cluster&quot; { 
    default = &quot;Cluster&quot; 
    description = &quot;Cluster name in vCenter&quot;
}

variable &quot;portgroup&quot; { 
    default = &quot;VM Network&quot; 
    description = &quot;Port Group new VM(s) will use&quot;
}

variable &quot;domain_name&quot; { 
    default = &quot;contoso.lan&quot;
    description = &quot;Domain Search name&quot;
}
variable &quot;default_gw&quot; { 
    default = &quot;172.16.1.1&quot; 
    description = &quot;Default Gateway&quot;
}

variable &quot;template_name&quot; { 
    default = &quot;Windows2019&quot; 
    description = &quot;VMware Template Name&quot;
}

variable &quot;vm_name&quot; { 
    default = &quot;WS19-1&quot; 
    description = &quot;New VM Name&quot;

}

variable &quot;vm_ip&quot; { 
    default = &quot;172.16.1.150&quot; 
    description = &quot;IP Address to assign to VM&quot;
}

variable &quot;vm_cidr&quot; { 
    default = 24 
    description = &quot;CIDR Block for VM&quot;
}

variable &quot;vcpu_count&quot; { 
    default = 1 
    description = &quot;How many vCPUs do you want?&quot;
}

variable &quot;memory&quot; { 
    default = 1024 
    description = &quot;RAM in MB&quot;
}</pre>



<h4 class="wp-block-heading">homelab.auto.tfvars</h4>



<p>If you&#8217;ve been reading in order up to this point, you understand the programming function analogy. Ansible will look in it&#8217;s directory for a file with the extension of .auto.tfvars. It will use it to assign values to input variables that are defined in the variables.tf file.</p>



<p>Below is a pseudo code example that shows how we&#8217;d compare terraform to a function in a conventional programming language.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="787" height="303" src="https://www.virtjunkie.com/wp-content/uploads/2020/04/terraform-tfvars.png" alt="" class="wp-image-1234" srcset="/wp-content/uploads/2020/04/terraform-tfvars.png 787w, /wp-content/uploads/2020/04/terraform-tfvars-300x116.png 300w, /wp-content/uploads/2020/04/terraform-tfvars-768x296.png 768w" sizes="(max-width: 787px) 100vw, 787px" /></figure>



<p>Below is the tfvars file I use in my home lab, and for your reference, it&#8217;s also <a href="https://github.com/jonhowe/Virtjunkie.com/blob/master/Terraform/SingleLinuxVM/homelab.auto.tfvars" target="_blank" rel="noreferrer noopener">available on github</a>.</p>



<pre class="urvanov-syntax-highlighter-plain-tag">vsphere_server = &quot;vcenter.home.lab&quot;

vsphere_user = &quot;administrator@vsphere.local&quot;

vsphere_password = &quot;VMware1!&quot;

adminpassword = &quot;terraform&quot; 

datacenter = &quot;Datacenter&quot;

datastore = &quot;vsanDatastore&quot; 

cluster = &quot;Cluster&quot;

portgroup = &quot;100-LabNetwork&quot; 

domain_name = &quot;home.lab&quot;

default_gw = &quot;172.16.1.1&quot; 

template_name = &quot;Ubuntu18&quot; 

vm_name = &quot;Ubuntu18-1&quot; 

vm_ip = &quot;172.16.1.150&quot;

vm_cidr = 24

vcpu_count = 1

memory = 1024</pre>



<h3 class="wp-block-heading">Provision Windows VM with Terraform</h3>



<p>Since provisioning a Windows and Linux VM share literally everything in a virtual environment with exception of the OS itself, there&#8217;s not a whole lot that&#8217;s different in provisioning Windows VMs. The one are that is different is the Customize block inside of the Resource block.</p>



<p>We are handling this the exact same as the Linux VM, however, we have a handful of options we can add, such as</p>



<ul><li>Join a domain</li><li>Execute a list of commands</li><li>Add a product key</li><li>Enable auto login for a specified amount of logins</li><li>Supply your own SysPrep file</li></ul>



<p>Here&#8217;s the code, but all files are <a href="https://github.com/jonhowe/Virtjunkie.com/tree/master/Terraform/SingleWindowsVM" target="_blank" rel="noreferrer noopener">stored on Github</a>.</p>



<pre class="urvanov-syntax-highlighter-plain-tag">resource &quot;vsphere_virtual_machine&quot; &quot;vm&quot; {
  name             = var.vm_name
  resource_pool_id = data.vsphere_compute_cluster.cluster.resource_pool_id
  datastore_id     = data.vsphere_datastore.datastore.id

  num_cpus = var.vcpu_count
  memory   = var.memory
  guest_id = data.vsphere_virtual_machine.template.guest_id

  scsi_type = data.vsphere_virtual_machine.template.scsi_type

  network_interface {
    network_id   = data.vsphere_network.network.id
    adapter_type = data.vsphere_virtual_machine.template.network_interface_types&amp;#91;0]
  }

  disk {
    label            = &quot;disk0&quot;
    size             = data.vsphere_virtual_machine.template.disks.0.size
    eagerly_scrub    = data.vsphere_virtual_machine.template.disks.0.eagerly_scrub
    thin_provisioned = data.vsphere_virtual_machine.template.disks.0.thin_provisioned
  }

  clone {
    template_uuid = data.vsphere_virtual_machine.template.id

    customize {
      #https://www.terraform.io/docs/providers/vsphere/r/virtual_machine.html#windows-customization-options
      windows_options {
        computer_name  = var.vm_name
        admin_password = var.adminpassword
        /*
        join_domain = &quot;cloud.local&quot;
	      domain_admin_user = &quot;administrator@cloud.local&quot;
	      domain_admin_password = &quot;password&quot;
        run_once_command_list = &amp;#91;

        ]
        */
      }
      network_interface {}

      /*
      network_interface {
        ipv4_address = var.vm_ip
        ipv4_netmask = var.vm_cidr
      }
      ipv4_gateway = var.default_gw
      dns_server_list = &amp;#91;&quot;1.2.3.4&quot;]
      */
    }
  }
}</pre>



<h2 class="wp-block-heading">References</h2>



<p>The following resources were helpful for me getting started, and I suggest you take a look at them as well.</p>



<p>The Terraform documentation is the best place to start (<a rel="noreferrer noopener" href="https://www.terraform.io/docs/cli-index.html" target="_blank">link</a>)<br>Dmitry Teslya has a great article that got me started here, but like the packer article he created, wasn&#8217;t working for me. Highly recommend this one (<a rel="noreferrer noopener" href="https://dteslya.engineer/automation/2019-01-21-creating_vms_with_terraform/" target="_blank">link</a>)<br></p>



<h2 class="wp-block-heading">What&#8217;s next?</h2>



<p>Good Question! At this point, I&#8217;ve written <a href="https://www.virtjunkie.com/vmware-template-packer/" target="_blank" rel="noreferrer noopener">about how to manage images (read: vmware templates) using Packer</a>. I&#8217;ve written this article, which speaks to how to deploy the VMs. The next things I&#8217;ll speak about are:</p>



<ul><li><a href="https://www.virtjunkie.com/vmware-provisioning-using-hashicorp-terraform-part-2/" target="_blank" rel="noreferrer noopener">Write our own Terraform Module, store it in Github, and use that, instead of a full Terraform project, so we can deploy multiple VMs, from different templates, all at once.</a></li><li>Use Ansible to configure our newly provisioned VMs</li><li>Wrap the Terraform VM Deployment process, as well as the Ansible VM configuration process together into a single process you execute once</li><li>Use Ansible to do a greenfield deployment of a vSphere environment</li></ul>



<p></p>
<p>The post <a href="/2020/04/22/vmware-provisioning-using-hashicorp-terraform/">VMware Provisioning using Hashicorp Terraform</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2020/04/22/vmware-provisioning-using-hashicorp-terraform/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Poor Man&#8217;s AutoDeploy Using Custom Kickstart, and Python</title>
		<link>/2020/04/09/poor-mans-autodeploy/</link>
					<comments>/2020/04/09/poor-mans-autodeploy/#comments</comments>
		
		<dc:creator><![CDATA[Jon]]></dc:creator>
		<pubDate>Thu, 09 Apr 2020 13:00:00 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[VMware]]></category>
		<guid isPermaLink="false">http://www.virtjunkie.com/?p=1107</guid>

					<description><![CDATA[<p>I recently encountered a situation where I needed to provision hundreds of ESXi hosts. The thing is, there was no vSphere Autodeploy, or HPE Synergy Image Streamer, and no ability to (long story, trust me here). No way I'm going to manually provision all of those hosts by hand, so what's a guy to do?!</p>
<p>While I designed this solution to work with hundreds of production ESXi hosts, there's nothing from preventing you from using this method in smaller production environments, or even your own home lab.</p>
<p>The post <a href="/2020/04/09/poor-mans-autodeploy/">Poor Man&#8217;s AutoDeploy Using Custom Kickstart, and Python</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>I recently encountered a situation where I needed to provision hundreds of ESXi hosts. The thing is, there was no vSphere Autodeploy, or HPE Synergy Image Streamer, and no ability to (long story, trust me here) spin them up. No way I&#8217;m going to manually provision all of those hosts by hand, so what&#8217;s a guy to do?!</p>



<p>This solution will automatically provision ESXi hosts and &#8220;get them on the network&#8221; so you can add them to vCenter just by using tools that VMware gives us, and a little bit of creativity.</p>



<p>While I designed this solution to work with hundreds of production ESXi hosts, there&#8217;s nothing from preventing you from using this method in smaller production environments, or even your own home lab.</p>



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



<h2 class="wp-block-heading">Overview</h2>



<p>At a very high level, the process works as follows.. The physical server boots from an ISO, USB Image, or even CD/DVD, if you&#8217;re into that sort of thing. The ESXi image on this media will contain a slightly customized ESXi image that looks for a kickstart file pulls the rest of the install instructions from a kickstart file on a web server. This kickstart fill will handle the silent install of ESXi, reboot into the newly installed OS, set a few settings, then download a CSV that contains ESXi host configuration info (such as host name, IP, and Default Gateway), and a python script that will send esxcli commands to the host in order to configure networking.</p>



<h3 class="wp-block-heading">Diagram</h3>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="412" src="https://new.virtjunkie.com/wp-content/uploads/2020/04/Poor-Mans-AutoDeploy-1024x412.jpeg" alt="" class="wp-image-1146" srcset="/wp-content/uploads/2020/04/Poor-Mans-AutoDeploy-1024x412.jpeg 1024w, /wp-content/uploads/2020/04/Poor-Mans-AutoDeploy-300x121.jpeg 300w, /wp-content/uploads/2020/04/Poor-Mans-AutoDeploy-768x309.jpeg 768w, /wp-content/uploads/2020/04/Poor-Mans-AutoDeploy-1536x617.jpeg 1536w, /wp-content/uploads/2020/04/Poor-Mans-AutoDeploy-2048x823.jpeg 2048w, /wp-content/uploads/2020/04/Poor-Mans-AutoDeploy-1568x630.jpeg 1568w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">Modified Boot.cfg file</h2>



<p>First and foremost, I need to emphasize the fact that there are two places you need to put your boot.cfg file. One in the root of the filesystem you have on your media, and one in the efi folder. This file is read during the boot process and instructs ESXi on how to boot. We care about the line that begins with <strong>kernelopt=</strong>. By default, this line tells ESXi to start with the traditional GUI installer which we definitely don&#8217;t want. Instead, we&#8217;ll modify it to tell the installer to look for a kickstart file on a web server, and will set static networking for the host.</p>



<p>At a high level, the modifications here accomplish the following:</p>



<ol><li>Instruct the ESXi host to find a kickstart file on a web server</li><li>Set a static IP, netmask, default gateway, and nameserver to use prior to automatically configuring the host</li></ol>



<h3 class="wp-block-heading">boot.cfg code</h3>



<p><a href="https://github.com/jonhowe/Virtjunkie.com/tree/master/PoorMansAutoDeploy/esxi-iso" target="_blank" rel="noreferrer noopener">Here&#8217;s a link to the code</a></p>



<pre class="urvanov-syntax-highlighter-plain-tag">bootstate=0
title=Loading ESXi installer
timeout=5
prefix=
kernel=/b.b00
#kernelopt=cdromBoot runweasel
kernelopt=ks=http://vmware-ks.home.lab:8123/files/VMware/ks/ks.cfg nameserver=192.168.1.60 ip=192.168.1.5 netmask=255.255.255.0 gateway=192.168.1.1
modules=/jumpstrt.gz --- /useropts.gz --- /features.gz --- /k.b00 --- /chardevs.b00 --- /user.b00 --- /procfs.b00 --- /uc_intel.b00 --- /uc_amd.b00 --- /uc_hygon.b00 --- /vmx.v00 --- /vim.v00 --- /sb.v00 --- /s.v00 --- /ata_liba.v00 --- /ata_pata.v00 --- /ata_pata.v01 --- /ata_pata.v02 --- /ata_pata.v03 --- /ata_pata.v04 --- /ata_pata.v05 --- /ata_pata.v06 --- /ata_pata.v07 --- /block_cc.v00 --- /bnxtnet.v00 --- /bnxtroce.v00 --- /brcmfcoe.v00 --- /char_ran.v00 --- /ehci_ehc.v00 --- /elxiscsi.v00 --- /elxnet.v00 --- /hid_hid.v00 --- /i40en.v00 --- /iavmd.v00 --- /igbn.v00 --- /ima_qla4.v00 --- /ipmi_ipm.v00 --- /ipmi_ipm.v01 --- /ipmi_ipm.v02 --- /iser.v00 --- /ixgben.v00 --- /lpfc.v00 --- /lpnic.v00 --- /lsi_mr3.v00 --- /lsi_msgp.v00 --- /lsi_msgp.v01 --- /lsi_msgp.v02 --- /misc_cni.v00 --- /misc_dri.v00 --- /mtip32xx.v00 --- /ne1000.v00 --- /nenic.v00 --- /net_bnx2.v00 --- /net_bnx2.v01 --- /net_cdc_.v00 --- /net_cnic.v00 --- /net_e100.v00 --- /net_e100.v01 --- /net_enic.v00 --- /net_fcoe.v00 --- /net_forc.v00 --- /net_igb.v00 --- /net_ixgb.v00 --- /net_libf.v00 --- /net_mlx4.v00 --- /net_mlx4.v01 --- /net_nx_n.v00 --- /net_tg3.v00 --- /net_usbn.v00 --- /net_vmxn.v00 --- /nfnic.v00 --- /nhpsa.v00 --- /nmlx4_co.v00 --- /nmlx4_en.v00 --- /nmlx4_rd.v00 --- /nmlx5_co.v00 --- /nmlx5_rd.v00 --- /ntg3.v00 --- /nvme.v00 --- /nvmxnet3.v00 --- /nvmxnet3.v01 --- /ohci_usb.v00 --- /pvscsi.v00 --- /qcnic.v00 --- /qedentv.v00 --- /qfle3.v00 --- /qfle3f.v00 --- /qfle3i.v00 --- /qflge.v00 --- /sata_ahc.v00 --- /sata_ata.v00 --- /sata_sat.v00 --- /sata_sat.v01 --- /sata_sat.v02 --- /sata_sat.v03 --- /sata_sat.v04 --- /scsi_aac.v00 --- /scsi_adp.v00 --- /scsi_aic.v00 --- /scsi_bnx.v00 --- /scsi_bnx.v01 --- /scsi_fni.v00 --- /scsi_hps.v00 --- /scsi_ips.v00 --- /scsi_isc.v00 --- /scsi_lib.v00 --- /scsi_meg.v00 --- /scsi_meg.v01 --- /scsi_meg.v02 --- /scsi_mpt.v00 --- /scsi_mpt.v01 --- /scsi_mpt.v02 --- /scsi_qla.v00 --- /sfvmk.v00 --- /shim_isc.v00 --- /shim_isc.v01 --- /shim_lib.v00 --- /shim_lib.v01 --- /shim_lib.v02 --- /shim_lib.v03 --- /shim_lib.v04 --- /shim_lib.v05 --- /shim_vmk.v00 --- /shim_vmk.v01 --- /shim_vmk.v02 --- /smartpqi.v00 --- /uhci_usb.v00 --- /usb_stor.v00 --- /usbcore_.v00 --- /vmkata.v00 --- /vmkfcoe.v00 --- /vmkplexe.v00 --- /vmkusb.v00 --- /vmw_ahci.v00 --- /xhci_xhc.v00 --- /elx_esx_.v00 --- /btldr.t00 --- /esx_dvfi.v00 --- /esx_ui.v00 --- /esxupdt.v00 --- /weaselin.t00 --- /lsu_hp_h.v00 --- /lsu_inte.v00 --- /lsu_lsi_.v00 --- /lsu_lsi_.v01 --- /lsu_lsi_.v02 --- /lsu_lsi_.v03 --- /lsu_lsi_.v04 --- /lsu_smar.v00 --- /native_m.v00 --- /qlnative.v00 --- /rste.v00 --- /vmware_e.v00 --- /vsan.v00 --- /vsanheal.v00 --- /vsanmgmt.v00 --- /tools.t00 --- /xorg.v00 --- /imgdb.tgz --- /imgpayld.tgz
build=
updated=0</pre>
</div></div>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">Kickstart file (ks.cfg)</h2>



<p>The kickstart file provides the ESXi installer with all the information it needs to perform the installation without manual intervention. We are handling this in two stages by using the firstboot parameter.</p>



<h3 class="wp-block-heading">Stage 1</h3>



<p>Handles the installation of ESXi to physical hardware. The following tasks are completed:</p>



<ol><li>Accept EULA</li><li>Select disk for ESXi to be installed to</li><li>Set root password</li><li>Set IP to be used on first boot (Default is DHCP, but the code to use static is included/commented in the code)</li></ol>



<h3 class="wp-block-heading">Stage 2</h3>



<p>All of stage two is executed in the newly installed ESXi OS using the firstboot parameter. The following tasks are completed:</p>



<ol><li>Enable SSH and ESXi Shell</li><li>Disable warnings for #1</li><li>Disable ESXi Firewall so we can use wget</li><li>Using wget, download the following files<ol><li>ListOfHosts.csv</li><li>configurehost.py</li></ol></li><li>Set the execution bit on the python script</li><li>Execute the python script</li></ol>



<h3 class="wp-block-heading">ks.cfg code</h3>



<p><a href="https://github.com/jonhowe/Virtjunkie.com/blob/master/PoorMansAutoDeploy/ks.cfg" target="_blank" rel="noreferrer noopener">Here&#8217;s a link to the code</a></p>



<pre class="urvanov-syntax-highlighter-plain-tag">#__      ___      _       _             _    _      
#\ \    / (_)    | |     | |           | |  (_)     
# \ \  / / _ _ __| |_    | |_   _ _ __ | | ___  ___ 
#  \ \/ / | | '__| __|   | | | | | '_ \| |/ / |/ _ \
#   \  /  | | |  | || |__| | |_| | | | |   &amp;lt;| |  __/
#    \/   |_|_|   \__\____/ \__,_|_| |_|_|\_\_|\___|

#Jon Howe
#https://www.virtjunkie.com/Poor-Mans-AutoDeploy
#https://github.com/jonhowe/Virtjunkie.com/tree/master/PoorMansAutoDeploy

#  _____ _                     __            _____           _        _ _       _   _             
# / ____| |                   /_ |          |_   _|         | |      | | |     | | (_)            
#| (___ | |_ __ _  __ _  ___   | |  ______    | |  _ __  ___| |_ __ _| | | __ _| |_ _  ___  _ __  
# \___ \| __/ _` |/ _` |/ _ \  | | |______|   | | | '_ \/ __| __/ _` | | |/ _` | __| |/ _ \| '_ \ 
# ____) | || (_| | (_| |  __/  | |           _| |_| | | \__ \ || (_| | | | (_| | |_| | (_) | | | |
#|_____/ \__\__,_|\__, |\___|  |_|          |_____|_| |_|___/\__\__,_|_|_|\__,_|\__|_|\___/|_| |_|
#                  __/ |                                                                          
#                 |___/                                                                           

# Accept the VMware End User License Agreement
vmaccepteula

# The install media is in the CD-ROM drive
#   This was the hardest part for some reason. I was installing from a USB drive TO a separate USB drive.
#   https://docs.vmware.com/en/VMware-vSphere/6.7/com.vmware.esxi.upgrade.doc/GUID-61A14EBB-5CF3-43EE-87EF-DB8EC6D83698.html
#   https://docs.vmware.com/en/VMware-vSphere/6.7/com.vmware.esxi.upgrade.doc/GUID-E7274FBA-CABC-43E8-BF74-2924FD3EFE1E.html
#   If you find the wrong device is being selected, you can hit CTRL+F1 during the install, log in (root/&amp;#91;no password]) and enter
#   the following command to get a list of the available devices:
#   localcli storage core device list
install --disk=/vmfs/devices/disks/mpx.vmhba33:C0:T0:L0 --overwritevmfs --novmfsondisk

# Set the root password for the DCUI and Tech Support Mode
rootpw VMware1!

### Temporary Network Configuration
#   Keep in mind, this is temporary. The actual IP address will be set in Stage 2
#   We don't even technically need this, but I wanted to include it in case we need network connectivity in Stage 1

# Set the network to DHCP on the first network adapter
network --bootproto=dhcp --device=vmnic0
# ... or if you want, you can set this to static
# network --bootproto=static --ip=192.168.30.13 --netmask=255.255.255.0 --gateway=192.168.30.1 --hostname=esxi1-mgmt.home.lab --nameserver=192.168.0.1 --addvmportgroup=1

reboot

#  _____ _                     ___              _____ _                 _         _____             __ _       
# / ____| |                   |__ \            / ____(_)               | |       / ____|           / _(_)      
#| (___ | |_ __ _  __ _  ___     ) |  ______  | (___  _ _ __ ___  _ __ | | ___  | |     ___  _ __ | |_ _  __ _ 
# \___ \| __/ _` |/ _` |/ _ \   / /  |______|  \___ \| | '_ ` _ \| '_ \| |/ _ \ | |    / _ \| '_ \|  _| |/ _` |
# ____) | || (_| | (_| |  __/  / /_            ____) | | | | | | | |_) | |  __/ | |___| (_) | | | | | | | (_| |
#|_____/ \__\__,_|\__, |\___| |____|          |_____/|_|_| |_| |_| .__/|_|\___|  \_____\___/|_| |_|_| |_|\__, |
#                  __/ |                                         | |                                      __/ |
#                 |___/                                          |_|                                     |___/ 

%firstboot --interpreter=busybox

# enable &amp;amp; start SSH
vim-cmd hostsvc/enable_ssh
vim-cmd hostsvc/start_ssh

# enable &amp;amp; start ESXi Shell
vim-cmd hostsvc/enable_esx_shell
vim-cmd hostsvc/start_esx_shell

# Suppress ESXi Shell warning
esxcli system settings advanced set -o /UserVars/SuppressShellWarning -i 1

#Temporarily disable the firewall so we can grab a couple files using wget
esxcli network firewall set --enabled false

# Download Host Config CSV, host configuration script, and execute the host configuration script
wget -O ListOfHosts.csv http://jondesktop.home.lan:8123/files/VMware/ks/ListOfHosts.csv
wget -O configurehost.py http://jondesktop.home.lan:8123/files/VMware/ks/configurehost.py
chmod u+x configurehost.py
/bin/python configurehost.py

#Re-enable the firewall
esxcli network firewall set --enabled true</pre>
</div></div>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">Host Detail Spreadsheet</h2>



<p>I like to have all, or as much configuration as possible defined in a document, and consume that as a part of the provisioning process. In this case, since I&#8217;m executing this on an ESXi host using the version of python that is available to the host, I&#8217;m simply using a CSV file. This strikes a healthy balance between usability and functionality.<br><br><a rel="noreferrer noopener" href="https://github.com/jonhowe/Virtjunkie.com/blob/master/PoorMansAutoDeploy/ListOfHosts.csv" target="_blank">Here&#8217;s a link to the CSV on my github account</a></p>



<p>The columns are as follows:</p>



<figure class="wp-block-table"><table><tbody><tr><td>Column A</td><td>ESXi Hostname</td></tr><tr><td>Column B</td><td>MAC Address of vmnic0</td></tr><tr><td>Column C</td><td>Desired Management IP Address (vmk0)</td></tr><tr><td>Column D</td><td>Subnet Mask for vmk0</td></tr><tr><td>Column E</td><td>Default Gateway for vmk0</td></tr><tr><td>Column F</td><td>VLAN Assigned to vmk0</td></tr></tbody></table><figcaption>Note: Columns have been converted to rows in this table. The actual representation is shown in the image below.</figcaption></figure>
</div></div>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="789" height="127" src="https://www.virtjunkie.com/wp-content/uploads/2020/04/image.png" alt="" class="wp-image-1137" srcset="/wp-content/uploads/2020/04/image.png 789w, /wp-content/uploads/2020/04/image-300x48.png 300w, /wp-content/uploads/2020/04/image-768x124.png 768w" sizes="(max-width: 789px) 100vw, 789px" /></figure>



<h2 class="wp-block-heading">configureHost.py</h2>



<p>Here&#8217;s where the magic comes in&#8230; Since ESXi is deployed with python, we can use it to parse a CSV file that has a list of all details for an ESXi host, and set the relevant details for the host.<br><a rel="noreferrer noopener" href="https://github.com/jonhowe/Virtjunkie.com/blob/master/PoorMansAutoDeploy/configurehost.py" target="_blank">Here&#8217;s a link to the code</a></p>



<p>In this very basic example, we are doing the following based on input in the CSV file:</p>



<ol><li>Set the hostname</li><li>Set the IP Address and Netmask of vmk0</li><li>Set the default gateway for the host</li><li>Set the VLAN for the management port group on vSwitch0</li></ol>
</div></div>



<h3 class="wp-block-heading">configureHost.py code</h3>



<pre class="urvanov-syntax-highlighter-plain-tag">#__      ___      _       _             _    _      
#\ \    / (_)    | |     | |           | |  (_)     
# \ \  / / _ _ __| |_    | |_   _ _ __ | | ___  ___ 
#  \ \/ / | | '__| __|   | | | | | '_ \| |/ / |/ _ \
#   \  /  | | |  | || |__| | |_| | | | |   &amp;lt;| |  __/
#    \/   |_|_|   \__\____/ \__,_|_| |_|_|\_\_|\___|
                                                  
#Jon Howe
#https://www.virtjunkie.com/Poor-Mans-AutoDeploy
#https://github.com/jonhowe/Virtjunkie.com/tree/master/PoorMansAutoDeploy

import os, csv, subprocess

CSVPATH = '/ListOfHosts.csv'

#Gets all mac addresses of interfaces
MAC=subprocess.check_output(&quot;esxcli network ip interface list |grep MAC | cut -d ' ' -f 6&quot;,shell=True)
                                                                                                                                                                                                                                                                                    
MACADDR = MAC.split()
print(&quot;MAC Addresses:&quot;)
print(MACADDR)

#Open the CSV file
with open(CSVPATH, 'rt') as csvFile:
        csvReader = csv.reader(csvFile)
        #Process the CSV file, row by row
        for csvRow in csvReader:
                #Check to see if the Mac Address of vmnic0 (IE: MACADDR&amp;#91;0]) matches the row in the CSV we are looking at
                if ((MACADDR&amp;#91;0]).decode('utf-8')) == csvRow&amp;#91;1]:
                        #print(&quot;esxcli system hostname set --fqdn=&quot; + csvRow&amp;#91;0])
                        #print(&quot;esxcli network ip interface ipv4 set --interface-name=vmk0 --ipv4=&quot; + csvRow&amp;#91;2] + &quot; --netmask=&quot; + csvRow&amp;#91;3] + &quot; --type=static&quot;)
                        
                        #Set the hostname to the value in the CSV
                        os.system(&quot;esxcli system hostname set --fqdn=&quot; + csvRow&amp;#91;0])
                        
                        #Set the IP Address and Netmask of vmk0
                        os.system(&quot;esxcli network ip interface ipv4 set --interface-name=vmk0 --ipv4=&quot; + csvRow&amp;#91;2] + &quot; --netmask=&quot; + csvRow&amp;#91;3] + &quot; --type=static&quot;)
                        
                        #Add the default gateway
                        os.system(&quot;esxcfg-route &quot; + csvRow&amp;#91;4])
                        
                        #Add the desired VLAN for the Management Network on the vSwitch that gets created by default (vSwitch0)
                        os.system(&quot;esxcfg-vswitch -p 'Management Network' -v &quot; + csvRow&amp;#91;5] + &quot; vSwitch0&quot;)</pre>



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



<p>Since none of this works without a web server, we&#8217;ll need to make sure we have one available. My goal in creating this was to have the whole project be as portable as possible. To that effort, I use a small docker container I can start/stop on my laptop or workstation that hosts the required files, but there&#8217;s nothing preventing you from doing this on a production server as well. I&#8217;m using a container that has a nice graphical directory browser, but also allows for direct downloading of files. <a rel="noreferrer noopener" href="https://hub.docker.com/r/mohamnag/nginx-file-browser" target="_blank">Here&#8217;s a link to more information about this container</a></p>



<p>As a side note, in a <a rel="noreferrer noopener" href="https://www.virtjunkie.com/deploy-vcsa-via-powershell/" target="_blank">previous blog post, I spoke about deploying VCSA</a> based on properties in an Excel file. One of the prerequisites for this to work is to have a web server that hosts the ISO file. I use this same container to serve the files for that project.</p>



<h3 class="wp-block-heading">Docker Container</h3>



<p>The following snippet can be used to create a docker container to host the files required by this project.</p>



<pre class="urvanov-syntax-highlighter-plain-tag">docker run -p 8123:80 -v /storage/poormansautodeploy/ks/:/opt/www/files --name=filebrowser -d --restart unless-stopped --log-opt max-size=15m --log-opt max-file=2 mohamnag/nginx-file-browser</pre>



<h3 class="wp-block-heading">Directory structure</h3>



<pre class="urvanov-syntax-highlighter-plain-tag">ks
├── configurehost.py
├── ks.cfg
└── ListOfHosts.csv</pre>
</div></div>



<h3 class="wp-block-heading">Web Server In Action</h3>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="464" height="408" src="https://www.virtjunkie.com/wp-content/uploads/2020/04/image-1.png" alt="" class="wp-image-1159" srcset="/wp-content/uploads/2020/04/image-1.png 464w, /wp-content/uploads/2020/04/image-1-300x264.png 300w" sizes="(max-width: 464px) 100vw, 464px" /></figure>



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



<p>This is the process to create a custom ISO</p>
</div></div>



<pre class="urvanov-syntax-highlighter-plain-tag">genisoimage -relaxed-filenames -J -R -o &amp;#91;yourisoname].iso -b isolinux.bin -c boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -e efiboot.img -no-emul-boot &amp;#91;path to extracted iso]</pre>



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



<ul><li>I owe a big thank you to Andrew Dauncey (<a rel="noreferrer noopener" href="https://twitter.com/daunce_" target="_blank">twitter</a>, <a rel="noreferrer noopener" href="https://theoddangryshot.com/" target="_blank">blog</a>, <a rel="noreferrer noopener" href="https://github.com/daunce" target="_blank">github</a>). He created <a rel="noreferrer noopener" href="https://theoddangryshot.com/2016/09/07/esxi-kickstart-with-python/" target="_blank">a post</a> back in 2016 that accomplished something similar to this, but was no longer working with modern versions of vSphere. I updated the code to work with vSphere, and added some additional functionality. Thanks again Andrew!</li><li>As always, the VMware documentation is a good place to start. Here&#8217;s the documentation for 6.7 (<a rel="noreferrer noopener" href="https://docs.vmware.com/en/VMware-vSphere/6.7/com.vmware.esxi.upgrade.doc/GUID-870A07BC-F8B4-47AF-9476-D542BA53F1F5.html" target="_blank">link</a>) and here&#8217;s the documentation for 7.0 (<a href="https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.esxi.upgrade.doc/GUID-870A07BC-F8B4-47AF-9476-D542BA53F1F5.html" target="_blank" rel="noreferrer noopener">link</a>)</li></ul>
</div></div>



<p></p>
<p>The post <a href="/2020/04/09/poor-mans-autodeploy/">Poor Man&#8217;s AutoDeploy Using Custom Kickstart, and Python</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2020/04/09/poor-mans-autodeploy/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>VMware Template Management using Hashicorp Packer</title>
		<link>/2020/03/23/vmware-template-packer/</link>
					<comments>/2020/03/23/vmware-template-packer/#comments</comments>
		
		<dc:creator><![CDATA[Jon]]></dc:creator>
		<pubDate>Mon, 23 Mar 2020 13:00:00 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[Packer]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[VMware]]></category>
		<guid isPermaLink="false">http://www.virtjunkie.com/?p=964</guid>

					<description><![CDATA[<p>VMware Templates: they make life amazing, don’t they? Initial creation of a template isn’t too hard, but there are downsides. In this article, I will talk about the downsides of traditional enterprise template management, how Packer can help, and give examples (and code!) for creating Windows and Linux templates in VMware vCenter using Packer.</p>
<p>The post <a href="/2020/03/23/vmware-template-packer/">VMware Template Management using Hashicorp Packer</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="has-text-align-left">VMware Templates: they make life amazing, don&#8217;t they? Creating a your first vSphere template is easy, but there are limitations when using them in enterprise environments. In this article, I will talk about the downsides of traditional enterprise template management, how Packer can help, and give examples (and code!) for creating Windows and Linux templates in VMware vCenter using Packer. </p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">Traditional Enterprise Template Management</h2>



<ol><li>Templates Across Multiple Sites &#8211; create a master template and replicate to ensure the same state exists<ol><li>Introduces operational complexity</li><li>Extends the total amount of time it takes to patch all templates</li></ol></li><li>OS and Application updates need to be performed for every application on every template<ol><li>Repetition sucks!</li><li>Introduces risk due to <a rel="noreferrer noopener" aria-label="C2K errors (opens in a new tab)" href="https://www.lifewire.com/have-you-been-the-butt-of-a-tech-joke-2619218" target="_blank">C2K errors</a></li></ol></li><li>Template creation ends up being a work of art.<ol><li>Individuals sometimes spend years fine-tuning all of the customization in a windows template.</li><li>On-boarding time is significantly increased</li><li>Projects delivered by third parties will take extra time to complete projects, as reverse engineering will need to occur in templates</li></ol></li><li>Documentation? Do you have it for your Windows and Linux Template?</li></ol>
</div></div>



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



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">Enterprise Template Management With Packer</h2>



<ol><li>You are no longer limited to VMware! The effort used to create the template code can be used to create templates in other hypervisors, and in the cloud</li><li>Create net-new templates consistently, eliminating the old method of creating one template, and copying that to data-centers over the world.</li><li>Packer defines every configured setting and change for templates in code. Documentation: Check!</li><li>Changes to your templates make it into the wild faster and with zero configuration drift.</li></ol>
</div></div>



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



<p>You can find source code for Windows 2019, Windows 2016, and Ubuntu 18 in my GitHub repository: <a href="https://github.com/jonhowe/Virtjunkie.com/tree/master/Packer">https://github.com/jonhowe/Virtjunkie.com/tree/master/Packer</a></p>



<p>The remainder of this post will explain how this code works.</p>
</div></div>



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



<p>First and foremost, this is not a packer tutorial. Packer actually <a rel="noreferrer noopener" aria-label="provides an excellent getting started guide (opens in a new tab)" href="https://packer.io/intro/getting-started/install.html" target="_blank">provides an excellent getting started guide</a>. I&#8217;d actually recommend you start there if you have no background with packer. That said, I will blaze through a few concepts.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">Packer Template File &amp; User Variables</h2>



<p>Packer stores it&#8217;s configuration in JSON files and calls them Packer Templates. There are two types of files. Master packer templates, and user variable files. Both are stored in JSON. The easiest way to think of this is the master packer template file contains properties that will be used as a part of the build. The user variable file (that is specified when you actually execute the build.. more on this later) in JSON format provides the values to the properties.</p>
</div></div>



<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">Builders</h3>



<p>Hashicorp defines builders as:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p><em>Builders are responsible for creating machines and generating images from them for various platforms. For example, there are separate builders for EC2, VMware, VirtualBox, etc. Packer comes with many builders by default, and can also be extended to add new builders.</em></p></blockquote>



<p>We will be using the builder called <a rel="noreferrer noopener" aria-label="VSphere-ISO (opens in a new tab)" href="https://packer.io/docs/builders/vsphere-iso.html" target="_blank">VSphere-ISO</a>.  This builder communicates directly with the vCenter API, which also makes this relevant for <a rel="noreferrer noopener" aria-label="VMC on AWS (opens in a new tab)" href="https://cloud.vmware.com/vmc-aws" target="_blank">VMC on AWS</a>.</p>
</div></div>



<h3 class="wp-block-heading">Attaching ISOs and Floppy Images</h3>



<p>Packer allows us to attach both <a rel="noreferrer noopener" aria-label="ISOs (opens in a new tab)" href="https://packer.io/docs/builders/vsphere-iso.html#iso_paths" target="_blank">ISOs</a> and <a rel="noreferrer noopener" aria-label="Floppy images (opens in a new tab)" href="https://packer.io/docs/builders/vsphere-iso.html#floppy-configuration" target="_blank">Floppy images</a> to the VM we are working with. </p>



<h4 class="wp-block-heading">ISOs</h4>



<p>You can attach multiple ISOs to an image. For example, you can attach a Windows installer ISO, as well as a VMware tools ISO to a Windows VM. Here&#8217;s an example of how this works:</p>



<pre class="urvanov-syntax-highlighter-plain-tag">&quot;iso_paths&quot;: [
    &quot;[esxi1-nvme] ISO/Windows/14393.0.161119-1705.RS1_REFRESH_SERVER_EVAL_X64FRE_EN-US.ISO&quot;,
    &quot;[esxi1-nvme] ISO/VMTools/VMware-tools-windows-11.0.1-14773994.iso&quot;
]</pre>



<h4 class="wp-block-heading">Floppy Images</h4>



<p>Packer gives us the ability to take a file, a directory, or a floppy image, and present it to the target VM as a floppy image. This is very useful if you want to copy scripts to the VM to be executed locally. Here&#8217;s an example of how this works:</p>



<pre class="urvanov-syntax-highlighter-plain-tag">&quot;floppy_files&quot;: [
    &quot;./autounattend.xml&quot;,
    &quot;Scripts/vmtools.cmd&quot;,
    &quot;Scripts/level0-setup.ps1&quot;
]</pre>



<h3 class="wp-block-heading">Communicators</h3>



<p><a rel="noreferrer noopener" aria-label="Communicators (opens in a new tab)" href="https://packer.io/docs/communicators/index.html" target="_blank">Communicators</a> are the mechanism Packer uses to upload files, execute scripts,  after the machine is created. Packer uses WinRM and SSH communicators. More on this later.</p>



<h3 class="wp-block-heading">Provisioners</h3>



<p>Provisioners are used to handle post image creation tasks, such as OS Customization and installing updates. Provisioners require communicators. In this case, the WinRM communicator will be used with Windows Images, while the SSH communicator will be used to communicate with Linux. We will be using the following provisioners:</p>



<figure class="wp-block-table"><table class=""><thead><tr><th class="has-text-align-left" data-align="left">Provisioner Name</th><th class="has-text-align-left" data-align="left">Used For</th></tr></thead><tbody><tr><td class="has-text-align-left" data-align="left"><a href="https://packer.io/docs/provisioners/powershell.html" target="_blank" rel="noreferrer noopener" aria-label="Powershell (opens in a new tab)">Powershell</a></td><td class="has-text-align-left" data-align="left">Performing all OS Customization Steps in Windows Images</td></tr><tr><td class="has-text-align-left" data-align="left"><a href="https://packer.io/docs/provisioners/windows-restart.html" target="_blank" rel="noreferrer noopener" aria-label="Windows-Restart (opens in a new tab)">Windows-Restart</a></td><td class="has-text-align-left" data-align="left">Restart Windows Images</td></tr><tr><td class="has-text-align-left" data-align="left"><a href="https://github.com/rgl/packer-provisioner-windows-update" target="_blank" rel="noreferrer noopener" aria-label="Windows-Update (opens in a new tab)">Windows-Update</a></td><td class="has-text-align-left" data-align="left">Apply Windows updates (community supported)</td></tr><tr><td class="has-text-align-left" data-align="left"><a href="https://packer.io/docs/provisioners/shell.html" target="_blank" rel="noreferrer noopener" aria-label="Shell (opens in a new tab)">Shell</a></td><td class="has-text-align-left" data-align="left">Used to install updates on Linux machines. We also set a custom &#8220;execution_command&#8221; that will allow for sudo to be used for all commands.</td></tr></tbody></table></figure>
</div></div>



<h2 class="wp-block-heading">Linux Templates</h2>



<p>Linux templates are pretty straight forward. Being born in open source, they are much easier to automate than Windows. Debian based distributions use a preseed file to silently execute the build. We will use packer to do the following:</p>



<ol><li>Create a blank VM</li><li>Attach Linux installer ISO</li><li>Create and attach media that has preseed.cfg file to the newly created image</li><li>Start VM</li><li>Send commands to the running VM via USB emulation to tell the Ubuntu installer to use the preseed.cfg file</li><li>Update all packages on the template</li><li>Shut Down VM</li><li>Mark as Template</li></ol>



<p>Here&#8217;s the directory structure:</p>



<pre class="urvanov-syntax-highlighter-plain-tag">Ubuntu18/
 ├── preseed.cfg
 ├── ubuntu-18.04.json
 └── ubuntu-vars.json
 0 directories, 3 files</pre>



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



<p>Most consumers of Packer are using it to manage Linux images, but I rarely hear about managing Windows images. Windows has a bit more moving parts that cause more complexity. It was way harder for me to figure out, even with a couple of great posts I&#8217;ll list in the reference area. In order to have a complete windows template, we will need to achieve the following steps:</p>



<ol><li>Create a blank VM</li><li>Attach Windows Installer and VMware Tools ISO</li><li>Attach floppy image that contains scripts and autounattend.xml</li><li>Start VM</li><li>Silently Install Windows Server (windowsPE pass in Autounattend.xml)</li><li>Install VMware Tools (Specialize pass in Autounattend.xml executes vmtools.cmd)</li><li>Configure WinRM (oobeSystem pass in Autounattend.xml executes level0-setup.ps1)</li><li>Perform OS Customization (Packer PowerShell provisioner executes level1-setup.ps1)</li><li>Install Windows Updates (Packer Windows Update provisioner applies updates)</li><li>Shut Down VM</li><li>Mark as Template</li></ol>



<p>Definitely more complex than Linux, eh? Don&#8217;t worry though. I&#8217;ll do my best to add some value on top of documentation and blog articles that are out there. Here&#8217;s the directory structure:</p>



<pre class="urvanov-syntax-highlighter-plain-tag">WS19
 ├── autounattend.xml
 ├── Scripts
 │&amp;nbsp;&amp;nbsp; ├── level0-setup.ps1
 │&amp;nbsp;&amp;nbsp; ├── level1-setup.ps1
 │&amp;nbsp;&amp;nbsp; └── vmtools.cmd
 ├── vars-ws19.json
 └── ws19.json
 1 directory, 6 files</pre>
</div></div>



<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">Autounattend.xml</h3>



<p>Microsoft allows us to provide an answer file to the Windows installer to achieve a silent install of Windows Server. The installer will look in all attached media to find a file named Autounattend.xml. This file contains a number of settings that are explained in a decent amount of detail on this <a rel="noreferrer noopener" href="https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/how-configuration-passes-work" target="_blank">Microsoft documentation page</a>. Below is a high level overview of the passes and how we are using them.<br><br>I found <a rel="noreferrer noopener" aria-label="this page helpful (opens in a new tab)" href="https://www.windowsafg.com/server2016.html" target="_blank">this page helpful</a> in creating the skeleton of the XML file.</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-3 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" src="https://new.virtjunkie.com/wp-content/uploads/2020/03/dep-win8-l-configpassesandexes.jpg" alt="" class="wp-image-1005" width="610" height="341" srcset="/wp-content/uploads/2020/03/dep-win8-l-configpassesandexes.jpg 610w, /wp-content/uploads/2020/03/dep-win8-l-configpassesandexes-300x168.jpg 300w" sizes="(max-width: 610px) 100vw, 610px" /></figure>
</div>



<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">
<h4 class="wp-block-heading"><strong>windowsPE</strong></h4>



<ul><li>Select disk format</li><li>Select the OS Image (Core, GUI, Datacenter, Standard)</li><li>Add the product key (we&#8217;ll be using the 6 month trial)</li><li>Select Locale, Name, Organization</li></ul>
</div></div>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h4 class="wp-block-heading">offlineServicing</h4>



<ul><li>This configuration pass is used to apply updates, drivers, or language packs to a Windows image.</li></ul>
</div></div>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h4 class="wp-block-heading">generalize</h4>



<ul><li>We are setting the <a rel="noreferrer noopener" href="https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-security-spp-skiprearm" target="_blank">property SkipRearm</a></li><li>Resets the SID</li></ul>
</div></div>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h4 class="wp-block-heading">specialize</h4>



<ul><li>This configuration pass is used to create and configure information in the Windows image, and is specific to the hardware that the Windows image is installing to.</li><li>Install VMware Tools by executing (vmtools.cmd) in this step to ensure it&#8217;s available ASAP for Packer to perform the rest of template configuration steps</li><li>Computer name is set</li><li>Reboots the machine</li></ul>
</div></div>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h4 class="wp-block-heading">oobeSystem</h4>



<ul><li>Add user, set password</li><li>Execute powershell script (level0-setup.ps1) to enable WinRM, which is required for Packer provisioning</li></ul>
</div></div>
</div>
</div>
</div></div>



<h2 class="wp-block-heading">Examples</h2>



<p>Here are a few examples of how the script works</p>



<h3 class="wp-block-heading">Windows</h3>



<p>The command below will create a windows template with the following details.</p>



<figure class="wp-block-table"><table class=""><tbody><tr><td>Username</td><td>Administrator</td></tr><tr><td>Password</td><td>VMware1!</td></tr><tr><td>Additional User</td><td>Labadmin</td></tr></tbody></table></figure>



<p>If you want to change the password, you will need to specify it both in the vars file, as well as the autounattend.xml. The section you will change looks like this:</p>



<pre class="urvanov-syntax-highlighter-plain-tag">&amp;lt;UserAccounts&gt;
    &amp;lt;AdministratorPassword&gt;
        &amp;lt;Value&gt;VMware1!&amp;lt;/Value&gt;
        &amp;lt;PlainText&gt;true&amp;lt;/PlainText&gt;
    &amp;lt;/AdministratorPassword&gt;
    &amp;lt;LocalAccounts&gt;
        &amp;lt;LocalAccount wcm:action=&quot;add&quot;&gt;
            &amp;lt;Description&gt;Lab Administrator&amp;lt;/Description&gt;
            &amp;lt;DisplayName&gt;labadmin&amp;lt;/DisplayName&gt;
            &amp;lt;Group&gt;Administrators&amp;lt;/Group&gt;
            &amp;lt;Name&gt;labadmin&amp;lt;/Name&gt;
        &amp;lt;/LocalAccount&gt;
    &amp;lt;/LocalAccounts&gt;
&amp;lt;/UserAccounts&gt;
&amp;lt;AutoLogon&gt;
    &amp;lt;Password&gt;
        &amp;lt;Value&gt;VMware1!&amp;lt;/Value&gt;
        &amp;lt;PlainText&gt;true&amp;lt;/PlainText&gt;
    &amp;lt;/Password&gt;
    &amp;lt;Enabled&gt;true&amp;lt;/Enabled&gt;
    &amp;lt;Username&gt;Administrator&amp;lt;/Username&gt;
&amp;lt;/AutoLogon&gt;</pre>



<h4 class="wp-block-heading">In Action</h4>



<pre class="urvanov-syntax-highlighter-plain-tag">packer build -var-file vars-ws19.json ws19.json
vsphere-iso: output will be in this color.

==&gt; vsphere-iso: Creating VM...
==&gt; vsphere-iso: Customizing hardware...
==&gt; vsphere-iso: Mounting ISO images...
==&gt; vsphere-iso: Creating floppy disk...
    vsphere-iso: Copying files flatly from floppy_files
    vsphere-iso: Copying file: ./autounattend.xml
    vsphere-iso: Copying file: Scripts/vmtools.cmd
    vsphere-iso: Copying file: Scripts/level0-setup.ps1
    vsphere-iso: Done copying files from floppy_files
    vsphere-iso: Collecting paths from floppy_dirs
    vsphere-iso: Resulting paths from floppy_dirs : []
    vsphere-iso: Done copying paths from floppy_dirs
==&gt; vsphere-iso: Uploading created floppy image
==&gt; vsphere-iso: Adding generated Floppy...
==&gt; vsphere-iso: Set boot order...
==&gt; vsphere-iso: Power on VM...
==&gt; vsphere-iso: Waiting for IP...
==&gt; vsphere-iso: IP address: 172.16.1.73
==&gt; vsphere-iso: Using winrm communicator to connect: 172.16.1.73
==&gt; vsphere-iso: Waiting for WinRM to become available...
    vsphere-iso: WinRM connected.
==&gt; vsphere-iso: #&amp;lt; CLIXML
==&gt; vsphere-iso: &amp;lt;Objs Version=&quot;1.1.0.1&quot; xmlns=&quot;http://schemas.microsoft.com/powershell/2004/04&quot;&gt;&amp;lt;Obj S=&quot;progress&quot; RefId=&quot;0&quot;&gt;&amp;lt;TN RefId=&quot;0&quot;&gt;&amp;lt;T&gt;System.Management.Automation.PSCustomObject&amp;lt;/T&gt;&amp;lt;T&gt;System.Object&amp;lt;/T&gt;&amp;lt;/TN&gt;&amp;lt;MS&gt;&amp;lt;I64 N=&quot;SourceId&quot;&gt;1&amp;lt;/I64&gt;&amp;lt;PR N=&quot;Record&quot;&gt;&amp;lt;AV&gt;Preparing modules for first use.&amp;lt;/AV&gt;&amp;lt;AI&gt;0&amp;lt;/AI&gt;&amp;lt;Nil /&gt;&amp;lt;PI&gt;-1&amp;lt;/PI&gt;&amp;lt;PC&gt;-1&amp;lt;/PC&gt;&amp;lt;T&gt;Completed&amp;lt;/T&gt;&amp;lt;SR&gt;-1&amp;lt;/SR&gt;&amp;lt;SD&gt; &amp;lt;/SD&gt;&amp;lt;/PR&gt;&amp;lt;/MS&gt;&amp;lt;/Obj&gt;&amp;lt;Obj S=&quot;progress&quot; RefId=&quot;1&quot;&gt;&amp;lt;TNRef RefId=&quot;0&quot; /&gt;&amp;lt;MS&gt;&amp;lt;I64 N=&quot;SourceId&quot;&gt;1&amp;lt;/I64&gt;&amp;lt;PR N=&quot;Record&quot;&gt;&amp;lt;AV&gt;Preparing modules for first use.&amp;lt;/AV&gt;&amp;lt;AI&gt;0&amp;lt;/AI&gt;&amp;lt;Nil /&gt;&amp;lt;PI&gt;-1&amp;lt;/PI&gt;&amp;lt;PC&gt;-1&amp;lt;/PC&gt;&amp;lt;T&gt;Completed&amp;lt;/T&gt;&amp;lt;SR&gt;-1&amp;lt;/SR&gt;&amp;lt;SD&gt; &amp;lt;/SD&gt;&amp;lt;/PR&gt;&amp;lt;/MS&gt;&amp;lt;/Obj&gt;&amp;lt;/Objs&gt;
==&gt; vsphere-iso: Connected to WinRM!
==&gt; vsphere-iso: Provisioning with Powershell...
==&gt; vsphere-iso: Provisioning with powershell script: Scripts/level1-setup.ps1
    vsphere-iso:
    vsphere-iso:
    vsphere-iso:     Directory: C:\Users\Administrator\Documents\WindowsPowerShell
    vsphere-iso:
    vsphere-iso:
    vsphere-iso: Mode                LastWriteTime         Length Name
    vsphere-iso: ----                -------------         ------ ----
    vsphere-iso: -a----        3/22/2020   3:02 PM              0 Microsoft.PowerShell_profile.ps1
==&gt; vsphere-iso: Restarting Machine
==&gt; vsphere-iso: Waiting for machine to restart...
==&gt; vsphere-iso: A system shutdown is in progress.(1115)
==&gt; vsphere-iso: #&amp;lt; CLIXML
    vsphere-iso: WS19-TPL restarted.
==&gt; vsphere-iso: &amp;lt;Objs Version=&quot;1.1.0.1&quot; xmlns=&quot;http://schemas.microsoft.com/powershell/2004/04&quot;&gt;&amp;lt;Obj S=&quot;progress&quot; RefId=&quot;0&quot;&gt;&amp;lt;TN RefId=&quot;0&quot;&gt;&amp;lt;T&gt;System.Management.Automation.PSCustomObject&amp;lt;/T&gt;&amp;lt;T&gt;System.Object&amp;lt;/T&gt;&amp;lt;/TN&gt;&amp;lt;MS&gt;&amp;lt;I64 N=&quot;SourceId&quot;&gt;1&amp;lt;/I64&gt;&amp;lt;PR N=&quot;Record&quot;&gt;&amp;lt;AV&gt;Preparing modules for first use.&amp;lt;/AV&gt;&amp;lt;AI&gt;0&amp;lt;/AI&gt;&amp;lt;Nil /&gt;&amp;lt;PI&gt;-1&amp;lt;/PI&gt;&amp;lt;PC&gt;-1&amp;lt;/PC&gt;&amp;lt;T&gt;Completed&amp;lt;/T&gt;&amp;lt;SR&gt;-1&amp;lt;/SR&gt;&amp;lt;SD&gt; &amp;lt;/SD&gt;&amp;lt;/PR&gt;&amp;lt;/MS&gt;&amp;lt;/Obj&gt;&amp;lt;Obj S=&quot;progress&quot; RefId=&quot;1&quot;&gt;&amp;lt;TNRef RefId=&quot;0&quot; /&gt;&amp;lt;MS&gt;&amp;lt;I64 N=&quot;SourceId&quot;&gt;2&amp;lt;/I64&gt;&amp;lt;PR N=&quot;Record&quot;&gt;&amp;lt;AV&gt;Preparing modules for first use.&amp;lt;/AV&gt;&amp;lt;AI&gt;0&amp;lt;/AI&gt;&amp;lt;Nil /&gt;&amp;lt;PI&gt;-1&amp;lt;/PI&gt;&amp;lt;PC&gt;-1&amp;lt;/PC&gt;&amp;lt;T&gt;Completed&amp;lt;/T&gt;&amp;lt;SR&gt;-1&amp;lt;/SR&gt;&amp;lt;SD&gt; &amp;lt;/SD&gt;&amp;lt;/PR&gt;&amp;lt;/MS&gt;&amp;lt;/Obj&gt;&amp;lt;/Objs&gt;
==&gt; vsphere-iso: Machine successfully restarted, moving on
==&gt; vsphere-iso: Uploading the Windows update elevated script...
==&gt; vsphere-iso: Uploading the Windows update check for reboot required elevated script...
==&gt; vsphere-iso: Uploading the Windows update script...
==&gt; vsphere-iso: Running Windows update...
    vsphere-iso: Searching for Windows updates...
    vsphere-iso: Found Windows update (2018-10-15; 20.72 MB): Update for Adobe Flash Player for Windows Server 2019 (1809) for x64-based Systems (KB4462930)
    vsphere-iso: Found Windows update (2020-02-11; 20.75 MB): 2020-02 Security Update for Adobe Flash Player for Windows Server 2019 for x64-based Systems (KB4537759)
    vsphere-iso: Found Windows update (2020-02-25; 71.37 MB): 2020-02 Cumulative Update for .NET Framework 3.5, 4.7.2 and 4.8 for Windows Server 2019 for x64 (KB4538156)
    vsphere-iso: Found Windows update (2020-02-25; 2.34 MB): 2020-01 Update for Windows Server 2019 for x64-based Systems (KB4494174)
    vsphere-iso: Found Windows update (2020-03-10; 30.62 MB): Windows Malicious Software Removal Tool x64 - March 2020 (KB890830)
    vsphere-iso: Found Windows update (2020-03-22; 114.85 MB): Security Intelligence Update for Windows Defender Antivirus - KB2267602 (Version 1.311.1752.0)
    vsphere-iso: Found Windows update (2020-03-10; 15349.68 MB): 2020-03 Cumulative Update for Windows Server 2019 (1809) for x64-based Systems (KB4538461)
    vsphere-iso: Downloading Windows updates (7 updates; 15610.33 MB)...
    vsphere-iso: Waiting for operation to complete (system performance: 44% cpu; 31% memory)...
    vsphere-iso: Installing Windows updates...
    vsphere-iso: Waiting for operation to complete (system performance: 20% cpu; 41% memory)...
    vsphere-iso: Waiting for operation to complete (system performance: 51% cpu; 51% memory)...
    vsphere-iso: Waiting for operation to complete (system performance: 51% cpu; 50% memory)...
    vsphere-iso: Waiting for operation to complete (system performance: 50% cpu; 54% memory)...
    vsphere-iso: Waiting for operation to complete (system performance: 43% cpu; 55% memory)...
    vsphere-iso: Waiting for operation to complete (system performance: 0% cpu; 61% memory)...
    vsphere-iso: Waiting for operation to complete (system performance: 38% cpu; 52% memory)...
    vsphere-iso: Waiting for operation to complete (system performance: 63% cpu; 48% memory)...
    vsphere-iso: Waiting for operation to complete (system performance: 27% cpu; 46% memory)...
    vsphere-iso: Waiting for operation to complete (system performance: 45% cpu; 47% memory)...
    vsphere-iso: Waiting for operation to complete (system performance: 55% cpu; 46% memory)...
    vsphere-iso: Waiting for operation to complete (system performance: 53% cpu; 44% memory)...
    vsphere-iso: Waiting for the Windows Modules Installer to exit...
    vsphere-iso: Waiting for operation to complete (system performance: 81% cpu; 44% memory)...
==&gt; vsphere-iso: Restarting the machine...
==&gt; vsphere-iso: Waiting for machine to become available...
==&gt; vsphere-iso: A system shutdown is in progress.(1115)
==&gt; vsphere-iso: A system shutdown is in progress.(1115)
    vsphere-iso: Waiting for the Windows Modules Installer to exit...
    vsphere-iso: WS19-TPL restarted.
==&gt; vsphere-iso: Running Windows update...
    vsphere-iso: Searching for Windows updates...
    vsphere-iso: Found Windows update (2020-03-19; 4.91 MB): Update for Windows Defender Antivirus antimalware platform - KB4052623 (Version 4.18.2003.6)
    vsphere-iso: Downloading Windows updates (1 updates; 4.91 MB)...
    vsphere-iso: Installing Windows updates...
==&gt; vsphere-iso: Shut down VM...
==&gt; vsphere-iso: Deleting Floppy drives...
==&gt; vsphere-iso: Deleting Floppy image...
==&gt; vsphere-iso: Eject CD-ROM drives...
==&gt; vsphere-iso: Convert VM into template...
Build 'vsphere-iso' finished.

==&gt; Builds finished. The artifacts of successful builds are:
--&gt; vsphere-iso: WS19-TPL</pre>



<h3 class="wp-block-heading">Linux</h3>



<p>The command below will create a Ubuntu template with the following details:</p>



<figure class="wp-block-table"><table class=""><tbody><tr><td>Root Password</td><td>VMware1!</td></tr><tr><td>Additional Username (also added to sudoers)</td><td>jhowe</td></tr><tr><td>Additional username&#8217;s password</td><td>VMware1!</td></tr></tbody></table></figure>



<p>All of the above can be changed by modifying values in the preseed.cfg file.</p>



<h4 class="wp-block-heading">In Action</h4>



<pre class="urvanov-syntax-highlighter-plain-tag">packer build -var-file ubuntu-vars.json ubuntu-18.04.json

jhowe@jonlaptopalt:~/git/Personal/HomeLab/packer/Ubuntu18$ packer build -var-file ubuntu-vars.json ubuntu-18.04.json 
vsphere-iso: output will be in this color.

==&gt; vsphere-iso: Creating VM...
==&gt; vsphere-iso: Customizing hardware...
==&gt; vsphere-iso: Mounting ISO images...
==&gt; vsphere-iso: Creating floppy disk...
    vsphere-iso: Copying files flatly from floppy_files
    vsphere-iso: Copying file: ./preseed.cfg
    vsphere-iso: Done copying files from floppy_files
    vsphere-iso: Collecting paths from floppy_dirs
    vsphere-iso: Resulting paths from floppy_dirs : []
    vsphere-iso: Done copying paths from floppy_dirs
==&gt; vsphere-iso: Uploading created floppy image
==&gt; vsphere-iso: Adding generated Floppy...
==&gt; vsphere-iso: Set boot order...
==&gt; vsphere-iso: Power on VM...
==&gt; vsphere-iso: Waiting 10s for boot...
==&gt; vsphere-iso: Typing boot command...
==&gt; vsphere-iso: Waiting for IP...
==&gt; vsphere-iso: IP address: 172.16.1.72
==&gt; vsphere-iso: Using ssh communicator to connect: 172.16.1.72
==&gt; vsphere-iso: Waiting for SSH to become available...
==&gt; vsphere-iso: Connected to SSH!
==&gt; vsphere-iso: Provisioning with shell script: /tmp/packer-shell338854810
    vsphere-iso: Hit:1 http://security.ubuntu.com/ubuntu bionic-security InRelease
    vsphere-iso: Hit:2 http://us.archive.ubuntu.com/ubuntu bionic InRelease
    vsphere-iso: Hit:3 http://us.archive.ubuntu.com/ubuntu bionic-updates InRelease
    vsphere-iso: Hit:4 http://us.archive.ubuntu.com/ubuntu bionic-backports InRelease
    vsphere-iso: Reading package lists...
    vsphere-iso: Reading package lists...
    vsphere-iso: Building dependency tree...
    vsphere-iso: Reading state information...
    vsphere-iso: Calculating upgrade...
    vsphere-iso: The following packages have been kept back:
    vsphere-iso:   linux-generic linux-headers-generic linux-image-generic
    vsphere-iso: The following packages will be upgraded:
    vsphere-iso:   dmidecode gcc-8-base libdrm-common libdrm2 libgcc1 libicu60 libnss-systemd
    vsphere-iso:   libpam-systemd libsqlite3-0 libstdc++6 libsystemd0 libudev1 libxml2
    vsphere-iso:   linux-firmware rsync systemd systemd-sysv udev
    vsphere-iso: 18 upgraded, 0 newly installed, 0 to remove and 3 not upgraded.
    vsphere-iso: Need to get 89.7 MB of archives.
    vsphere-iso: After this operation, 572 kB of additional disk space will be used.
    vsphere-iso: Get:1 http://us.archive.ubuntu.com/ubuntu bionic-updates/main amd64 perl-modules-5.26 all 5.26.1-6ubuntu0.3 [2,763 kB]

[Omitted some output in order to save space. Apt is downloading new packages]

[Omitted some output in order to save space. Apt is unpacking packages]

[Omitted some output in order to save space. Apt is &quot;Setting up... all upgraded packages]

    vsphere-iso: Processing triggers for systemd (237-3ubuntu10.39) ...
    vsphere-iso: Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
    vsphere-iso: Processing triggers for dbus (1.12.2-1ubuntu1.1) ...
    vsphere-iso: Processing triggers for mime-support (3.60ubuntu1) ...
    vsphere-iso: Processing triggers for ureadahead (0.100.0-21) ...
    vsphere-iso: Processing triggers for install-info (6.5.0.dfsg.1-2) ...
    vsphere-iso: Processing triggers for libc-bin (2.27-3ubuntu1) ...
    vsphere-iso: Template Build Complete
==&gt; vsphere-iso: Shut down VM...
==&gt; vsphere-iso: Deleting Floppy drives...
==&gt; vsphere-iso: Deleting Floppy image...
==&gt; vsphere-iso: Eject CD-ROM drives...
==&gt; vsphere-iso: Convert VM into template...
Build 'vsphere-iso' finished.

==&gt; Builds finished. The artifacts of successful builds are:
--&gt; vsphere-iso: Ubuntu18</pre>



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



<p>I did a lot of research as when getting this up and running. The following sites were helpful.</p>



<ul><li>This is an EXCELLENT blog. The article he created unfortunately didn&#8217;t work, but it got me started. Either way, it&#8217;s worth a look. (<a href="https://dteslya.engineer/automation/2018-12-20-creating_vm_templates_with_packer/">https://dteslya.engineer/automation/2018-12-20-creating_vm_templates_with_packer/</a>)</li><li>Official Packer Documentation (<a href="https://packer.io/docs/index.html">https://packer.io/docs/index.html</a>)</li></ul>
</div></div>
<p>The post <a href="/2020/03/23/vmware-template-packer/">VMware Template Management using Hashicorp Packer</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2020/03/23/vmware-template-packer/feed/</wfw:commentRss>
			<slash:comments>2</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 loading="lazy" 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-4 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 loading="lazy" 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-5 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>vExpert 2020</title>
		<link>/2020/03/01/vexpert-2020/</link>
					<comments>/2020/03/01/vexpert-2020/#respond</comments>
		
		<dc:creator><![CDATA[Jon]]></dc:creator>
		<pubDate>Mon, 02 Mar 2020 01:43:04 +0000</pubDate>
				<category><![CDATA[VMware]]></category>
		<guid isPermaLink="false">http://www.virtjunkie.com/?p=851</guid>

					<description><![CDATA[<p>I&#8217;m happy to announce that I have been selected as a vExpert in 2020! I was very fortunate early in my career to have some folks that took me under their wing and shared knowledge with me. I&#8217;ve always made it a priority to pass along information as well, so it&#8217;s nice to be recognized. [&#8230;]</p>
<p>The post <a href="/2020/03/01/vexpert-2020/">vExpert 2020</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-image"><figure class="aligncenter size-medium"><img loading="lazy" decoding="async" width="300" height="203" src="https://www.virtjunkie.com/wp-content/uploads/2020/03/vexpert-2020-300x203.png" alt="" class="wp-image-854" srcset="/wp-content/uploads/2020/03/vexpert-2020-300x203.png 300w, /wp-content/uploads/2020/03/vexpert-2020-1024x692.png 1024w, /wp-content/uploads/2020/03/vexpert-2020-768x519.png 768w, /wp-content/uploads/2020/03/vexpert-2020.png 1061w" sizes="(max-width: 300px) 100vw, 300px" /></figure></div>



<p>I&#8217;m happy to announce that I have been selected as a vExpert in 2020!</p>



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



<p>I was very fortunate early in my career to have some folks that took me under their wing and shared knowledge with me. I&#8217;ve always made it a priority to pass along information as well, so it&#8217;s nice to be recognized.<br><br>In addition to my community contributions, I am fortunate to work for a VMware partner that has invested heavily in yours truly, and am able to share knowledge internally. It&#8217;s my intention to share as much information as I can here as well.<br><br>Additionally, I&#8217;ve been spending a lot of time working on the concept of infrastructure as code as it pertains specifically to VMware, so I hope to share some thoughts I have on that front shortly.<br><br>Finally, I&#8217;m spending a lot of time professionally looking at VMC on AWS, and vRealize Automation 8, so I&#8217;l be hitting on those, as well as the next version of vSphere, when it&#8217;s released.</p>



<p>Here&#8217;s my profile: <a href="https://vexpert.vmware.com/directory/2496">https://vexpert.vmware.com/directory/2496</a></p>
<p>The post <a href="/2020/03/01/vexpert-2020/">vExpert 2020</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2020/03/01/vexpert-2020/feed/</wfw:commentRss>
			<slash:comments>0</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>
	</channel>
</rss>
