{"id":6542,"date":"2020-10-19T13:20:55","date_gmt":"2020-10-19T19:20:55","guid":{"rendered":"http:\/\/gregsowell.com\/?p=6542"},"modified":"2020-10-19T13:20:55","modified_gmt":"2020-10-19T19:20:55","slug":"servicenow-orders-vmware-vms-via-ansible-tower","status":"publish","type":"post","link":"https:\/\/gregsowell.com\/?p=6542","title":{"rendered":"ServiceNow Orders VMWare VMs Via Ansible Tower"},"content":{"rendered":"<p><a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/Untitled-1-1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/Untitled-1-1-300x169.png\" alt=\"\" width=\"300\" height=\"169\" class=\"aligncenter size-medium wp-image-6545\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/Untitled-1-1-300x169.png 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/Untitled-1-1-768x432.png 768w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/Untitled-1-1-1024x576.png 1024w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/Untitled-1-1.png 1280w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nThis is a quick demo that orders a server in ServiceNow, then once approved it calls Ansible Tower which then provisions VMs in VMWare.  <\/p>\n<p>This is built using <a href=\"https:\/\/www.ansible.com\/blog\/ansible-servicenow-howto-part-3-making-outbound-restful-api-calls-to-ansible-tower\">this ansible blog post<\/a> that shows how to tie together ServiceNow and Ansible Tower.<\/p>\n<h2>Video Demo<\/h2>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/pcUQ-5_5kvU\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe><\/p>\n<h2>ServiceNow<\/h2>\n<p>First thing to do is create the OAuth connection between tower and SNOW.  I&#8217;ve spoken about this in a previous post and it is outlined in the blog post linked above, so I won&#8217;t rehash that.  Once OAuth is solid I create an outbound rest message:<br \/>\n<a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-rest1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-rest1-241x300.png\" alt=\"\" width=\"241\" height=\"300\" class=\"aligncenter size-medium wp-image-6547\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-rest1-241x300.png 241w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-rest1.png 708w\" sizes=\"auto, (max-width: 241px) 100vw, 241px\" \/><\/a><br \/>\nTwo things of note are the endpoint I&#8217;m calling which is the launch URL for my tower job and the HTTP query parameters(HQP).  The HQP is where I map variables learned in SNOW to variables I will pass to tower.  So variable1 is passed to tower as vm_name.<\/p>\n<pre class=\"gs-code\"><code class=\"language-plaintext\">{\r\n  &quot;extra_vars&quot;:\r\n  {\r\n    &quot;vm_name&quot;: &quot;${variable1}&quot;,\r\n    &quot;vm_template&quot;: &quot;${variable2}&quot;,\r\n    &quot;vm_disksize&quot;: &quot;${variable10}&quot;,\r\n    &quot;vm_memory&quot;: &quot;${variable9}&quot;,\r\n    &quot;vm_cpus&quot;: &quot;${variable8}&quot;,\r\n    &quot;vm_ip&quot;: &quot;${variable7}&quot;,\r\n    &quot;vm_netmask&quot;: &quot;${variable6}&quot;,\r\n    &quot;vm_gateway&quot;: &quot;${variable5}&quot;,\r\n    &quot;vm_folder&quot;: &quot;${variable4}&quot;,\r\n    &quot;vm_datacenter&quot;: &quot;${variable3}&quot;,\r\n    &quot;vm_datastore&quot;: &quot;SSD&quot;\r\n  }\r\n}<\/code><\/pre>\n<p>I&#8217;ll now create a workflow that ties an approval and my custom script together:<br \/>\n<a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-workflow1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-workflow1-300x98.png\" alt=\"\" width=\"300\" height=\"98\" class=\"aligncenter size-medium wp-image-6549\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-workflow1-300x98.png 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-workflow1-768x250.png 768w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-workflow1.png 900w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Here&#8217;s a peek at my approval workflow item:<br \/>\n<a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-workflow2.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-workflow2-300x221.png\" alt=\"\" width=\"300\" height=\"221\" class=\"aligncenter size-medium wp-image-6550\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-workflow2-300x221.png 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-workflow2.png 680w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nAs you can see I selected a group to approve these requests through.<\/p>\n<p>My custom script looks like the following:<br \/>\n<a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-workflow3.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-workflow3-300x219.png\" alt=\"\" width=\"300\" height=\"219\" class=\"aligncenter size-medium wp-image-6551\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-workflow3-300x219.png 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-workflow3-768x561.png 768w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-workflow3-1024x748.png 1024w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-workflow3.png 1037w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<pre class=\"gs-code\"><code class=\"language-plaintext\"> try { \r\n \/\/var r = new sn_ws.RESTMessageV2(&#039;Tower Default Job&#039;, &#039;Tower Default Job Run&#039;);\r\nvar r = new sn_ws.RESTMessageV2(&#039;Tower VMWare Provision REST&#039;, &#039;Tower VMWare Provision REST HTTP Method&#039;);\r\n r.setStringParameterNoEscape(&#039;variable4&#039;, current.variables.variable4);\r\n r.setStringParameterNoEscape(&#039;variable7&#039;, current.variables.variable7);\r\n r.setStringParameterNoEscape(&#039;variable5&#039;, current.variables.variable5);\r\n r.setStringParameterNoEscape(&#039;variable6&#039;, current.variables.variable6);\r\n r.setStringParameterNoEscape(&#039;variable1&#039;, current.variables.variable1);\r\n r.setStringParameterNoEscape(&#039;variable10&#039;, current.variables.variable10);\r\n r.setStringParameterNoEscape(&#039;variable2&#039;, current.variables.variable2);\r\n r.setStringParameterNoEscape(&#039;variable8&#039;, current.variables.variable8);\r\n r.setStringParameterNoEscape(&#039;variable3&#039;, current.variables.variable3);\r\n r.setStringParameterNoEscape(&#039;variable9&#039;, current.variables.variable9);\r\n\r\n\/\/override authentication profile \r\n\/\/authentication type =&#039;basic&#039;\/ &#039;oauth2&#039;\r\n\/\/r.setAuthenticationProfile(authentication type, profile name);\r\n\r\n\/\/set a MID server name if one wants to run the message on MID\r\n\/\/r.setMIDServer(&#039;MY_MID_SERVER&#039;);\r\n\r\n\/\/if the message is configured to communicate through ECC queue, either\r\n\/\/by setting a MID server or calling executeAsync, one needs to set skip_sensor\r\n\/\/to true. Otherwise, one may get an intermittent error that the response body is null\r\n\/\/r.setEccParameter(&#039;skip_sensor&#039;, true);\r\n\r\n var response = r.execute();\r\n var responseBody = response.getBody();\r\n var httpStatus = response.getStatusCode();\r\n}\r\ncatch(ex) {\r\n var message = ex.message;\r\n}<\/code><\/pre>\n<p>I just went with generic variable names and mapped them from the self service item over.<\/p>\n<p>My service item points towards the workflow:<br \/>\n<a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-item1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-item1-300x175.png\" alt=\"\" width=\"300\" height=\"175\" class=\"aligncenter size-medium wp-image-6552\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-item1-300x175.png 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-item1.png 677w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>I then created simple input and multiple choice variables with all of my options:<br \/>\n<a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-item2.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-item2-300x238.png\" alt=\"\" width=\"300\" height=\"238\" class=\"aligncenter size-medium wp-image-6553\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-item2-300x238.png 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-item2.png 703w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Once I choose the item from the service catalog I&#8217;m presented with a simple form to complete:<br \/>\n<a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-item3.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-item3-210x300.png\" alt=\"\" width=\"210\" height=\"300\" class=\"aligncenter size-medium wp-image-6554\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-item3-210x300.png 210w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/snow-item3.png 620w\" sizes=\"auto, (max-width: 210px) 100vw, 210px\" \/><\/a><\/p>\n<h2>Ansible Tower<\/h2>\n<p><a href=\"https:\/\/github.com\/gregsowell\/ansible-vmware\">My VMWare github repo is here<\/a>.<\/p>\n<p>The playbook in use here is this one:<br \/>\n<script src=\"http:\/\/gist-it.appspot.com\/https:\/\/github.com\/gregsowell\/ansible-vmware\/blob\/main\/snow-vcenter-create-vm.yml\"><\/script><br \/>\nTaking a look at the playbook, you can see that <a href=\"https:\/\/docs.ansible.com\/ansible\/2.9\/modules\/vmware_guest_module.html\">I&#8217;m using the vmware_guest module<\/a>.<br \/>\nThis module is surprisingly easy to use.  This module requires the connection info for the VCenter server(IP, username, password).  I use a custom credential to supply this at run time(this way I can keep the info secure.<br \/>\nAfter that I pass the template I want the VM created from, then standard info like HD size, how much RAM, how many CPUs, etc.<\/p>\n<p>When you add the playbook to your tower, be sure to add &#8220;prompt on launch&#8221; for extra variables to that SNOW is allowed to pass variables in:<br \/>\n<a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/tower1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/tower1-300x108.png\" alt=\"\" width=\"300\" height=\"108\" class=\"aligncenter size-medium wp-image-6556\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/tower1-300x108.png 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2020\/10\/tower1.png 582w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<h2>Conclusion<\/h2>\n<p>Once SNOW launches the job it only really takes about 1.5 minutes for Linux and about 2 minutes for Windows.  The VMWare module is actually really easy to work with and is quite functional.  SNOW can be a bit more finicky, but once it is working it&#8217;s not usually so bad.<\/p>\n<p>Something I learned is that while you can have a tower job template use a survey and be called by SNOW, it&#8217;s likely better(at least while testing) to not use surveys.  If there is a survey, then tower will only launch the job if the survey variables are all passed in at launch(which can cause you issues when trying to troubleshoot why your SNOW service orders aren&#8217;t lunching your tower jobs).<\/p>\n<p>If you have any questions or comments, please let me know.<\/p>\n<p>Thanks and happy automating.  <\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a quick demo that orders a server in ServiceNow, then once approved it calls Ansible Tower which then provisions VMs in VMWare.\u2026<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[49,14,13,40,15],"tags":[],"class_list":["post-6542","post","type-post","status-publish","format-standard","hentry","category-ansible","category-linux","category-server","category-vmware","category-windows"],"_links":{"self":[{"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/posts\/6542","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/gregsowell.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6542"}],"version-history":[{"count":6,"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/posts\/6542\/revisions"}],"predecessor-version":[{"id":6557,"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/posts\/6542\/revisions\/6557"}],"wp:attachment":[{"href":"https:\/\/gregsowell.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6542"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gregsowell.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6542"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gregsowell.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6542"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}