<?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>Scripting Archives - VirtJunkie</title>
	<atom:link href="/category/automation/scripting/feed/" rel="self" type="application/rss+xml" />
	<link>/category/automation/scripting/</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>Scripting Archives - VirtJunkie</title>
	<link>/category/automation/scripting/</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-667f6dd203aa1289702247" 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-667f6dd203aaf228964802" 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-667f6dd203ab4341906924" 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-667f6dd203ab5954685989" 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-667f6dd203ab7324092246" 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-667f6dd203ab8634657232" 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-667f6dd203ab9914913209" 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-667f6dd203aba774258121" 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>Jitsi for Just in Time Conferencing using Terraform on Vultr with Route 53</title>
		<link>/2020/05/04/jitsi-jit-conferencing-tf-vultr-route53/</link>
					<comments>/2020/05/04/jitsi-jit-conferencing-tf-vultr-route53/#respond</comments>
		
		<dc:creator><![CDATA[Jon]]></dc:creator>
		<pubDate>Mon, 04 May 2020 13:00:00 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[BASH]]></category>
		<category><![CDATA[Hashicorp]]></category>
		<category><![CDATA[InfrastructureAsCode]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Servers]]></category>
		<category><![CDATA[Terraform]]></category>
		<guid isPermaLink="false">http://www.virtjunkie.com/?p=1304</guid>

					<description><![CDATA[<p>With everything going on in the world with COVID-19 and the social distancing that is happening, people are looking to connect with friends, family and co-workers via Video conferencing more than ever. Recent vulnerabilities in Zoom have made people more cognizant than ever that security needs to be considered when using these platforms no matter [&#8230;]</p>
<p>The post <a href="/2020/05/04/jitsi-jit-conferencing-tf-vultr-route53/">Jitsi for Just in Time Conferencing using Terraform on Vultr with Route 53</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>With everything going on in the world with COVID-19 and the social distancing that is happening, people are looking to connect with friends, family and co-workers via Video conferencing more than ever. Recent vulnerabilities in Zoom have made people more cognizant than ever that security needs to be considered when using these platforms no matter what you are using them for.</p>



<p><a href="https://jitsi.org/" target="_blank" rel="noreferrer noopener">Jitsi is an open source video conferencing platform</a> that I&#8217;ve been hearing about a lot lately, and finally had a chance to look into. In this post I&#8217;ll explain how to use Terraform to provision a Jitsi instance when you need a conference and tear it down when you are done. We&#8217;ll be using Vultr and their Jitsi &#8220;application&#8221; and AWS Route 53 for DNS.</p>



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



<h2 class="wp-block-heading">Why Am I Writing This Article, and What Does It Accomplish?</h2>



<p>Why am I writing this article?</p>



<ol><li>We <strong>always</strong> want to have our apps and infrastructure defined in code</li><li>We pay for traditional web conferencing software 24 hours a day, 7 days a week, regardless of if we are are using running a conference or not. Why don&#8217;t we spin up conference infrastructure <strong>when we need it, and tear it down when we don&#8217;t</strong>?</li></ol>



<p>At a high level, this project will accomplish the following:</p>



<ol><li>Provision a Vultr VPS that is pre-configured with Jitsi</li><li>Take the IP Address that Vultr assigns the VPS and use it to create an A Record in Route 53</li><li>Copy a script to your VPS that will be used to finish the Jitsi configuration</li><li>Run the script that we copied and pass a few command line arguments that are specific to our environment</li></ol>



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



<p>In addition to having Terraform downloaded and installed, we&#8217;ll need the following items:</p>



<h3 class="wp-block-heading">Vultr Account + API Access</h3>



<p>Vultr is definitely my go-to for VPS&#8217;s these days. Not only because of their price/performance/feature availability ratio, but because they provide a number of pre-configured applications that are ready, or near ready for use. <a rel="noreferrer noopener" href="https://www.vultr.com/docs/one-click-jitsi" target="_blank">Jitsi is one of these applications</a>. If you do use Vultr, please do me a favor and use&nbsp;<a rel="noreferrer noopener" href="https://www.vultr.com/?ref=8531966-6G" target="_blank">this link</a>&nbsp;to sign up. I’ll get a little kickback, but you’ll get $100 USD to use on the site in your first month.</p>



<div class="wp-block-media-text alignwide has-media-on-the-right is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="1024" height="450" src="https://www.virtjunkie.com/wp-content/uploads/2020/05/2020-05-02_19-45-1024x450.png" alt="" class="wp-image-1305" srcset="/wp-content/uploads/2020/05/2020-05-02_19-45-1024x450.png 1024w, /wp-content/uploads/2020/05/2020-05-02_19-45-300x132.png 300w, /wp-content/uploads/2020/05/2020-05-02_19-45-768x338.png 768w, /wp-content/uploads/2020/05/2020-05-02_19-45.png 1273w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure><div class="wp-block-media-text__content">
<p class="has-normal-font-size">Once you have a Vultr account, you&#8217;ll need to generate and record an API key to use with Terraform. Use the steps below to generate it.</p>



<ol><li>Log into Vultr</li><li>Navigate to Settings, and then API</li><li>Generate an API key, and copy it somewhere safe, we&#8217;ll be using it later</li></ol>
</div></div>



<h3 class="wp-block-heading">AWS Account + API Access</h3>



<p>We&#8217;ll be using <a rel="noreferrer noopener" href="https://aws.amazon.com/route53/" target="_blank">AWS&#8217;s Route 53 service</a>, which is really just a fancy DNS service that&#8217;s hooked into AWS.  In order to automate Route 53 with Terraform, we&#8217;ll need to enable API access.</p>



<div class="wp-block-media-text alignwide has-media-on-the-right is-stacked-on-mobile" style="grid-template-columns:auto 70%"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="1024" height="400" src="https://www.virtjunkie.com/wp-content/uploads/2020/05/2020-05-02_20-13-1024x400.png" alt="" class="wp-image-1307" srcset="/wp-content/uploads/2020/05/2020-05-02_20-13-1024x400.png 1024w, /wp-content/uploads/2020/05/2020-05-02_20-13-300x117.png 300w, /wp-content/uploads/2020/05/2020-05-02_20-13-768x300.png 768w, /wp-content/uploads/2020/05/2020-05-02_20-13-1536x599.png 1536w, /wp-content/uploads/2020/05/2020-05-02_20-13-1568x612.png 1568w, /wp-content/uploads/2020/05/2020-05-02_20-13.png 1607w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure><div class="wp-block-media-text__content">
<p><a rel="noreferrer noopener" href="https://console.aws.amazon.com/iam/home?#security_credential" target="_blank">Use this link to access the IAM Management page</a></p>



<ol><li>Expand the &#8220;Access Keys&#8221; blade</li><li>Select &#8220;Create New Access Key</li><li>Save the resulting file, as we&#8217;ll use the contents later</li></ol>
</div></div>



<h3 class="wp-block-heading">Domain Registrar Using Custom Nameservers</h3>



<p>In addition to the above, the domain you want to use will need to be configured to use the Route 53 Name Servers. Route 53 will provide you the nameservers when you create a zone, and you&#8217;ll simply plug those into your registrar DNS settings page. I&#8217;m not going to explain how to create a zone in Route 53, or how to configure your registrar, but if you have questions, throw them in the comments and I&#8217;ll do my best to help.</p>



<h2 class="wp-block-heading">Getting Started</h2>



<h3 class="wp-block-heading">Run This Project</h3>



<ol><li>Grab the files below, or copy them from my <a rel="noreferrer noopener" href="https://github.com/jonhowe/Virtjunkie.com/tree/master/Jitsi-JIT-Conferencing-TF-Vultr-Route53" target="_blank">Github Repository</a></li><li>Enter the directory that contains the files</li><li>At a minimum, modify the fields in the auto.tfvars file<ol><li>vultr_api_key</li></ol><ol><li>aws_access_key</li><li>aws_secret_key</li><li>domain</li><li>email</li></ol></li><li>Initialize Terraform by running <strong><code>terraform init</code></strong></li><li>Create a terraform plan by running <strong><code>terraform plan</code></strong></li><li>Apply the configuration by running <strong><code>terraform apply</code></strong></li><li>Voila! In less than 5 minutes, you&#8217;ve got a functional, secure Jitsi instance, running on a server and domain you control. Upon successful creation, you&#8217;ll see text like what we see below giving you the URL and credentials. When you are done with your conference, just run <code><strong>terraform destroy</strong></code> to stop from receiving charges on a server/service you aren&#8217;t using.</li></ol>



<pre class="urvanov-syntax-highlighter-plain-tag">null_resource.jitsi_config (remote-exec): ------------------------------
null_resource.jitsi_config (remote-exec): |                            |
null_resource.jitsi_config (remote-exec): |   JITSI SETUP COMPLETED!   |
null_resource.jitsi_config (remote-exec): |                            |
null_resource.jitsi_config (remote-exec): ------------------------------
null_resource.jitsi_config (remote-exec): JITSI URL: https://conference.yourdomain.com/

null_resource.jitsi_config (remote-exec): USERNAME: admin
null_resource.jitsi_config (remote-exec): PASSWORD: @#$asdfahgsd34579--23%4asdf</pre>



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



<h3 class="wp-block-heading">Main.tf</h3>



<p>This file does all of the work.</p>



<pre class="urvanov-syntax-highlighter-plain-tag">#main.tf
#https://www.virtjunkie.com/jitsi-jit-conferencing-tf-vultr-route53/
#https://github.com/jonhowe/Virtjunkie.com/tree/master/Jitsi-JIT-Conferencing-TF-Vultr-Route53

#Conifugre the Vultr provider
provider &quot;vultr&quot; {
  api_key = var.vultr_api_key
  rate_limit = 700
  retry_limit = 3
}

#Configure the AWS Provider
provider &quot;aws&quot; {
  #profile    = &quot;default&quot;
  #shared_credentials_file = &quot;/home/jhowe/storage/btsync/folders/Sync/awscredentials/credentials&quot;
  region     = var.aws_region
  access_key = var.aws_access_key
  secret_key = var.aws_secret_key
}

#https://www.terraform.io/docs/providers/aws/d/route53_zone.html
data &quot;aws_route53_zone&quot; &quot;selected&quot; {
  name         = &quot;${var.domain}.&quot;
  private_zone = false
}

#Provision Vultr Server
resource &quot;vultr_server&quot; &quot;my_server&quot; {
    plan_id = var.vultr_plan_id
    region_id = var.vultr_region
    app_id = var.vultr_app_id
    label = &quot;${var.hostname}.${var.domain}&quot;
    tag = var.vultr_tag
    hostname = &quot;${var.hostname}.${var.domain}&quot;
    enable_ipv6 = false
    auto_backup = false
    ddos_protection = false
    notify_activate = false

    connection {
        type     = &quot;ssh&quot;
        user     = &quot;root&quot;
        
        #https://www.terraform.io/docs/providers/vultr/r/server.html#default_password
        password = self.default_password

        #https://www.terraform.io/docs/provisioners/connection.html#the-self-object
        host     = self.main_ip
    }

    provisioner &quot;local-exec&quot; {
      command = &quot;echo SSH to this server with the command: ssh root@${vultr_server.my_server.main_ip} with the password '${vultr_server.my_server.default_password}'&quot;
    }
}

#Create the Route 53 A Record
#https://www.terraform.io/docs/providers/aws/r/route53_record.html
resource &quot;aws_route53_record&quot; &quot;conference&quot; {
  zone_id = data.aws_route53_zone.selected.zone_id
  name    = &quot;${var.hostname}.${data.aws_route53_zone.selected.name}&quot;
  type    = &quot;A&quot;
  ttl     = &quot;300&quot;
  records = &amp;#91;&quot;${vultr_server.my_server.main_ip}&quot;]
}

#This null resource exists to handle configuration of the Vultr VPS after Route 53
resource &quot;null_resource&quot; &quot;jitsi_config&quot; {
    
    connection {
        type     = &quot;ssh&quot;
        user     = &quot;root&quot;
        
        #https://www.terraform.io/docs/providers/vultr/r/server.html#default_password
        password = vultr_server.my_server.default_password

        #https://www.terraform.io/docs/provisioners/connection.html#the-self-object
        host     = vultr_server.my_server.main_ip
    }

    provisioner &quot;file&quot; {
        source      = &quot;./configure_jitsi_param.sh&quot;
        destination = &quot;/root/configure_jitsi_param.sh&quot;
    }

    provisioner &quot;remote-exec&quot; {
        inline = &amp;#91;
            &quot;chmod +x /root/configure_jitsi_param.sh&quot;,
            &quot;/root/configure_jitsi_param.sh ${var.hostname}.${var.domain} ${var.email} y&quot;
        ]
    }
}</pre>



<h3 class="wp-block-heading">Variables.tf</h3>



<p>This file defines the variables that we will use in main.tf</p>



<pre class="urvanov-syntax-highlighter-plain-tag">#variables.tf
#https://www.virtjunkie.com/jitsi-jit-conferencing-tf-vultr-route53/
#https://github.com/jonhowe/Virtjunkie.com/tree/master/Jitsi-JIT-Conferencing-TF-Vultr-Route53

variable &quot;vultr_api_key&quot; {
    description = &quot;API Key Used by Vultr (https://my.vultr.com/settings/#settingsapi)&quot;
}

variable &quot;vultr_region&quot; {
    description = &quot;Vultr Region Selection (curl https://api.vultr.com/v1/regions/availability?DCID=1)&quot;
    default = 1
}

variable &quot;vultr_plan_id&quot; {
    description = &quot;Vultr Plan for the VPS to use (curl https://api.vultr.com/v1/plans/list)&quot;
    default = 202
}

variable &quot;vultr_tag&quot; {
    description = &quot;Vultr Tag to apply to the new VPS&quot;
    default = &quot;jitsi-conference&quot;
}

variable &quot;vultr_app_id&quot; {
    description = &quot;Vultr App to pre-install. This should always be '47', if jitsi is being provisioned (curl https://api.vultr.com/v1/app/list)&quot;
    default = 47
}

variable &quot;hostname&quot; {
    description = &quot;Hostname to be used&quot;
    default = &quot;conferences&quot;
}

variable &quot;email&quot; {
    description = &quot;email to be used for let's encrypt acme config&quot;
    default = &quot;john.doe@email.com&quot;
}

variable &quot;domain&quot; {
    description = &quot;domain to be used&quot;
    default = &quot;aremyj.am&quot;
}

variable &quot;aws_access_key&quot; {
    description = &quot;AWS Access Key - get it here: (https://console.aws.amazon.com/iam/home?#security_credential)&quot;
}

variable &quot;aws_secret_key&quot; {
    description = &quot;AWS Secret Key - get it here: (https://console.aws.amazon.com/iam/home?#security_credential)&quot;
}

variable &quot;aws_region&quot; {
    description = &quot;AWS Region&quot;
    default = &quot;us-east-1&quot;
}</pre>



<h3 class="wp-block-heading">[yourdomain].auto.tfvars</h3>



<p>The auto.tfvars file provides values to the variables defined in the variables.tf file. You&#8217;ll have to create this file from scratch, and terraform best practices dictate that you exclude this file from source control. Here&#8217;s an example you can use. Modify this for your environment. The name doesn&#8217;t matter, as long as it ends with auto.tfvars.</p>



<pre class="urvanov-syntax-highlighter-plain-tag">vultr_api_key = &quot;&amp;#91;fill this in]&quot;
vultr_region = 1
vultr_plan_id = 202
vultr_app_id = 47
vultr_tag = &quot;jitsi-conference&quot;
hostname = &quot;conference&quot;
email = &quot;your.email@address.org&quot;
domain = &quot;your-domain.com&quot;
aws_region = &quot;us-east-1&quot;
aws_access_key = &quot;&amp;#91;fill this in]&quot;
aws_secret_key = &quot;&amp;#91;fill this in]&quot;</pre>



<h3 class="wp-block-heading">configure_jitsi_param.sh</h3>



<p>Full disclosure, I did not create this script. Vultr created it, and provides it on your Jitsi VPS when you request it. Unfortunately, the version they provide is intended to be executed interactively, so I made a few very minor modifications to allow for us to run it with parameters.</p>



<pre class="urvanov-syntax-highlighter-plain-tag">#!/bin/bash
#This script was copied from /opt/vultr/configure_jitsi.sh on a Vultr VPS that has the one-click Jitsi App
#I added lines 7-9 to allow for adding parameters on the CLI and commented lines 11-13 to force the variables to be provided on the CLI
#https://www.vultr.com/docs/one-click-jitsi
#https://www.virtjunkie.com/jitsi-jit-conferencing-tf-vultr-route53/
#https://github.com/jonhowe/Virtjunkie.com/tree/master/Jitsi-JIT-Conferencing-TF-Vultr-Route53
HOSTNAME=$1
EMAIL=$2
response=$3
# User choices
#read -ep &quot;Please specify which domain you would like to use: &quot; HOSTNAME
#read -ep &quot;Please enter your email address for Let's Encrypt Registration: &quot; EMAIL
#read -r -p &quot;Would you like to enable password authorization? &amp;#91;y/N] &quot; response
case &quot;$response&quot; in
    &amp;#91;yY]&amp;#91;eE]&amp;#91;sS]|&amp;#91;yY])
        AUTH=1
        ;;
    *)
        AUTH=0
        ;;
esac


PROSODYPATH=/etc/prosody/conf.avail/${HOSTNAME}.cfg.lua
JITSIPATH=/etc/jitsi/meet/${HOSTNAME}-config.js
JICOFOPATH=/etc/jitsi/jicofo/sip-communicator.properties

# Remove and purge (Stop first and wait to avoid race condition)
purgeold() {        
        /opt/vultr/stopjitsi.sh
        sleep 5
        apt -y purge jigasi jitsi-meet jitsi-meet-web-config jitsi-meet-prosody jitsi-meet-turnserver jitsi-meet-web jicofo jitsi-videobridge2 jitsi*
}

# Reinstall
reinstalljitsi() {
        echo &quot;jitsi-videobridge2 jitsi-videobridge/jvb-hostname string ${HOSTNAME}&quot; | debconf-set-selections
        echo &quot;jitsi-meet-web-config jitsi-meet/cert-choice string Generate a new self-signed certificate (You will later get a chance to obtain a Let's encrypt certificate)&quot; | debconf-set-selections
        apt-get -y install jitsi-meet
}

# Remove nginx defaults
wipenginx() {
        rm -f /etc/nginx/sites-enabled/default
}

# Configure Lets Encrypt
configssl(){
    systemctl restart nginx
    sed -i -e 's/echo.*Enter your email and press.*/EMAIL=$1/' /usr/share/jitsi-meet/scripts/install-letsencrypt-cert.sh
    sed -i -e 's/read EMAIL//'  /usr/share/jitsi-meet/scripts/install-letsencrypt-cert.sh
    /usr/share/jitsi-meet/scripts/install-letsencrypt-cert.sh ${EMAIL}
}

configprosody() {
  AUHTLINE='authentication = &quot;internal_plain&quot;'
  sed -i &quot;s/authentication\ \=\ \&quot;anonymous\&quot;/${AUTHLINE}/g&quot; ${PROSODYPATH}
  cat &amp;lt;&amp;lt; EOT &gt;&gt; ${PROSODYPATH}

VirtualHost &quot;guest.${HOSTNAME}&quot;
    authentication = &quot;anonymous&quot;
    c2s_require_encryption = false

EOT
}

configjitsi() {
        sed -i &quot;s/\/\/\ anonymousdomain\:\ 'guest.example.com',/anonymousdomain\:\ 'guest.${HOSTNAME}',/g&quot; ${JITSIPATH}
}

configjicofo() {
        echo &quot;org.jitsi.jicofo.auth.URL=XMPP:${HOSTNAME}&quot; &gt;&gt; ${JICOFOPATH}
}

registeruser(){
        PASSWORD=$(&amp;lt; /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-16};echo;)
        prosodyctl register admin ${HOSTNAME} ${PASSWORD}
}

restartjitsi() {
        /opt/vultr/stopjitsi.sh
        /opt/vultr/startjitsi.sh
}

completedsetup(){
    echo &quot;&quot;
    echo &quot;------------------------------&quot;
    echo &quot;|                            |&quot;
    echo &quot;|   JITSI SETUP COMPLETED!   |&quot;
    echo &quot;|                            |&quot;
    echo &quot;------------------------------&quot;
    echo &quot;JITSI URL: https://${HOSTNAME}&quot;/
    echo &quot;&quot;
}

outputUser(){
    echo &quot;USERNAME: admin&quot;
    echo &quot;PASSWORD: ${PASSWORD}&quot;
    echo &quot;&quot;
}

# Script start

purgeold
reinstalljitsi
wipenginx
configssl
if &amp;#91; &quot;$AUTH&quot; == &quot;1&quot; ]; then
    configprosody
    configjitsi
    configjicofo
    registeruser
    restartjitsi    
fi
completedsetup
if &amp;#91; &quot;$AUTH&quot; == &quot;1&quot; ]; then
    outputUser
fi</pre>



<h2 class="wp-block-heading">Summary + More Reading</h2>



<p>There you have it! With this project you can have a fully functional Jitsi instance on your own domain with end to end encryption in less than 5 minutes. When you are done, there&#8217;s no harm in deleting it so you aren&#8217;t charged.</p>



<p>Here are some references I used while creating this:</p>



<ul><li><a href="https://github.com/jonhowe/Virtjunkie.com/tree/master/Jitsi-JIT-Conferencing-TF-Vultr-Route53">https://github.com/jonhowe/Virtjunkie.com/tree/master/Jitsi-JIT-Conferencing-TF-Vultr-Route53</a></li><li><a href="https://www.vultr.com/docs/one-click-jitsi">https://www.vultr.com/docs/one-click-jitsi</a></li><li><a href="https://www.terraform.io/docs/providers/aws/d/route53_zone.html">https://www.terraform.io/docs/providers/aws/d/route53_zone.html</a></li><li><a href="https://www.terraform.io/docs/providers/aws/r/route53_record.html">https://www.terraform.io/docs/providers/aws/r/route53_record.html</a></li><li><a href="https://www.terraform.io/docs/providers/vultr/r/server.html#default_password">https://www.terraform.io/docs/providers/vultr/r/server.html#default_password</a></li><li><a href="https://www.terraform.io/docs/provisioners/connection.html#the-self-object">https://www.terraform.io/docs/provisioners/connection.html#the-self-object</a></li><li>Create Vultr API Key: <a href="https://my.vultr.com/settings/#settingsapi">https://my.vultr.com/settings/#settingsapi</a></li><li>Create AWS Access/Secret Key: <a href="https://console.aws.amazon.com/iam/home?#security_credential">https://console.aws.amazon.com/iam/home?#security_credential</a></li><li>Vultr API Reference &#8211; has examples that will get you plan, region, and app IDs. <a href="https://www.vultr.com/api/">https://www.vultr.com/api/</a></li></ul>
<p>The post <a href="/2020/05/04/jitsi-jit-conferencing-tf-vultr-route53/">Jitsi for Just in Time Conferencing using Terraform on Vultr with Route 53</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2020/05/04/jitsi-jit-conferencing-tf-vultr-route53/feed/</wfw:commentRss>
			<slash:comments>0</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-2 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-3 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-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" id="Features"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">Features</h2>



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



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



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



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



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



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



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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

$deploymentTarget = $targettype.'vCenter or ESXi'

#endregion import excel file into sections and validate input

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

#region Create and format the JSON

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

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

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

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

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

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

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

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

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

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



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



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



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

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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



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



<p></p>



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

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

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

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

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

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

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

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

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

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

		#add object to array
		$RS += $PingResults

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

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

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



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



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



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



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



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



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



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



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



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

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

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

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

)

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

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

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

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

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

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

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

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

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

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

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



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



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



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



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

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

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

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

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

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

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



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



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



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



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



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

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

    return $rs
}

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



<p></p>
<p>The post <a href="/2019/03/04/get-details-from-get-task/">PowerCLI &#8211; Get All VM Details from get-task</a> appeared first on <a href="/">VirtJunkie</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2019/03/04/get-details-from-get-task/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
