{"id":80,"date":"2016-10-10T14:14:40","date_gmt":"2016-10-10T12:14:40","guid":{"rendered":"https:\/\/room28.it\/?p=80"},"modified":"2016-11-02T10:45:18","modified_gmt":"2016-11-02T09:45:18","slug":"deploy-a-linux-vm-using-customization-wizard-using-perl-sdk","status":"publish","type":"post","link":"https:\/\/room28.it\/index.php\/2016\/10\/10\/deploy-a-linux-vm-using-customization-wizard-using-perl-sdk\/","title":{"rendered":"Deploy a Linux VM using Customization Wizard using Perl SDK"},"content":{"rendered":"<p>This post will show you how to deploy a VM fully operational in a few seconds in a vSphere environment. You must have a working template to use this script.<\/p>\n<p>You will have to install VMware Tools on this template, or OVT (OpenVMwareTools). They are now fully supported by VMware. I would recommand to use them, just for an ease of use during your weekly vulnerability review \ud83d\ude09 Ideed during your OS upgrade, the OVT package will also be updated. More details\u00a0on VMware knowledge base. (<a href=\"http:\/\/kb.vmware.com\/kb\/2073803\">kb.vmware.com\/kb\/2073803<\/a>)<\/p>\n<p>You need to install <a href=\"https:\/\/room28.it\/index.php\/2016\/07\/11\/use-vmware-perl-sdk-to-manage-a-vsphere-infrastructure\/\">vSphere SDK for perl<\/a>\u00a0on your work station to be able to follow this post.<\/p>\n<h4>Overview<\/h4>\n<p>During the deployment you will not only clone the VM with all the template configuration, you will also configure IPs, gateway, hostname, DNS, Timezone and you will choose on which cluster, datastore and folder you will deploy your VM. We are going to use the VMware &#8220;Configuration Wizard&#8221; to deploy your VM.<\/p>\n<p>You understood well, one of the biggest part of the job is not to write the script, you have to configure a\u00a0working template. You need to have VMware Tools installed (OVT) or VMware Tools themselves. After the cloning operation, the VM will be powered on and the customization process will apply.<\/p>\n<p><!--more--><\/p>\n<p>I&#8217;m not going to show you how to build a template, there are many of ways to do it, from scratch with an ISO, by deploying an existing template and change some settings to fit your needs, by downloading an external appliance, etc. The only thing you need to do\u00a0is to install OVT.<\/p>\n<p>Now, on your work station, where you installed the vSphere PERL SDK, you can edit a new script, and paste\u00a0the scripts requirement to connect to your vCenter :<\/p>\n<div class=\"code-embed-wrapper\"> <pre class=\"language-bash code-embed-pre\"  data-start=\"1\" data-line-offset=\"0\"><code class=\"language-bash code-embed-code\">#!\/usr\/bin\/perl\nuse strict;\nuse Data::Dumper;\n\nuse VMware::VIRuntime;\n\nOpts::set_option(&#039;server&#039;, &#039;pcc-178-33-102-10.ovh.com&#039;);\nOpts::set_option(&#039;username&#039;, &#039;apiuser&#039;);\nOpts::set_option(&#039;password&#039;, &#039;XXxxXXxxXX&#039;);\n\n\nprint &quot;Connecting \\n&quot;; \n\nUtil::connect(); \n\n## Later, we are going to make actions there\n\nUtil::disconnect(); \nprint &quot;Disconnected \\n&quot;;<\/code><\/pre> <div class=\"code-embed-infos\"> <\/div> <\/div>\n<p>Now we focus on this post objective : deploy a Linux VM with everything configured.<\/p>\n<p>First, we need to declare our environment :<\/p>\n<div class=\"code-embed-wrapper\"> <pre class=\"language-bash code-embed-pre\"  data-start=\"1\" data-line-offset=\"0\"><code class=\"language-bash code-embed-code\">my $templateName = &#039;myOwnTemplate&#039;;\n\nmy $datacenterName = &#039;pcc-178-33-102-10_datacenter114&#039;;\n\nmy $vmName = &#039;myNewVM&#039;;\nmy $clusterName = &#039;Cluster1&#039;;\nmy $datastoreName = &#039;pcc-003643&#039;;\nmy $folderName = &#039;ProductionFolder&#039;;\n\nmy $custTimezone = &#039;Europe\/Paris&#039;;\n\nmy $domain = &#039;ovh.net&#039;;\nmy $dns = [ &#039;213.186.33.99&#039; ];\nmy $ip = &#039;192.168.0.10&#039;;\nmy $netmask = &#039;255.255.255.0&#039;;\nmy $gateway = &#039;192.168.0.10&#039;;<\/code><\/pre> <div class=\"code-embed-infos\"> <\/div> <\/div>\n<p>This is exactly what you might see in your inventory.<\/p>\n<p>You need now to get all views :<\/p>\n<div class=\"code-embed-wrapper\"> <pre class=\"language-bash code-embed-pre\"  data-start=\"1\" data-line-offset=\"0\"><code class=\"language-bash code-embed-code\">print &quot;Getting Datacenter view \\n&quot;;\nmy $DatacenterView = Vim::find_entity_view(\n\t&#039;view_type&#039; =&gt; &#039;Datacenter&#039;,\n\t&#039;filter&#039; =&gt; {\n\t\t&#039;name&#039; =&gt; $datacenterName\n\t}\n);\n!$DatacenterView and die(&#039;Failed to get Datacenter view&#039;);\n\nprint &quot;Getting Template view\\n&quot;;\nmy $VMView = Vim::find_entity_view(\n\t&#039;view_type&#039; =&gt; &#039;VirtualMachine&#039;,\n\t&#039;filter&#039; =&gt; {\n\t\t&#039;name&#039; =&gt; $templateName\n\t},\n\t&#039;begin_entity&#039; =&gt; $DatacenterView,\n);\n!$VMView and die(&#039;Failed to get Template view&#039;);\n\nprint &quot;Getting destination cluster view\\n&quot;;\nmy $ClusterView = Vim::find_entity_view(\n\t&#039;view_type&#039; =&gt; &#039;ClusterComputeResource&#039;,\n\t&#039;begin_entity&#039; =&gt; $DatacenterView,\n\t&#039;filter&#039; =&gt; { \n\t\t&#039;name&#039; =&gt; $clusterName \n\t}\n);\n!$ClusterView and die(&#039;Failed to get cluster view&#039;);\n\nprint &quot;Getting destination datastore view \\n&quot;;\nmy $DatastoreView = Vim::find_entity_view(\n\t&#039;view_type&#039; =&gt; &#039;Datastore&#039;,\n\t&#039;begin_entity&#039; =&gt; $DatacenterView,\n\t&#039;filter&#039; =&gt; {\n\t\t&#039;name&#039; =&gt; $datastoreName\n\t}\n);\n!$DatastoreView and die(&#039;Failed to get datastore view&#039;);\n\n print &quot;Getting destination folder view\\n&quot;;\nmy $FolderView = Vim::find_entity_view(\n\t&#039;view_type&#039; =&gt; &#039;Folder&#039;,\n\t&#039;begin_entity&#039; =&gt; $DatacenterView,\n\t&#039;filter&#039; =&gt; { \n\t\t&#039;name&#039; =&gt; $folderName \n\t}\n);\n!$FolderView and die $FolderView;<\/code><\/pre> <div class=\"code-embed-infos\"> <\/div> <\/div>\n<p>Right now, if you passed all the checks, you know that you did not miss any deployment requirements.<\/p>\n<p>Now we need to build some VMware Perl Objects to get the guest OS configuration working. You\u00a0don&#8217;t have to custom this part.<\/p>\n<div class=\"code-embed-wrapper\"> <pre class=\"language-bash code-embed-pre\"  data-start=\"1\" data-line-offset=\"0\"><code class=\"language-bash code-embed-code\">my $CustomizationGlobalIPSettings;\nmy $custName = CustomizationFixedName-&gt;new( name =&gt; $vmName );\nmy $custDomain = $domain;\n\n$CustomizationGlobalIPSettings = CustomizationGlobalIPSettings-&gt;new(\n\t&#039;dnsServerList&#039; =&gt; $dns,\n\t&#039;dnsSuffixList&#039; =&gt; [ $domain ],\n);\n\nmy $custUtcClock = &#039;false&#039;;\n\nmy $CustomizationIdentitySettings = CustomizationLinuxPrep-&gt;new(\n\t&#039;hostName&#039; =&gt; $custName,\n\t&#039;domain&#039; =&gt; &quot;$custDomain&quot;,\n\t&#039;hwClockUTC&#039; =&gt; $custUtcClock,\n\t&#039;timeZone&#039; =&gt; &quot;$custTimezone&quot;,\n);\n\nmy $CustIp = CustomizationFixedIp-&gt;new(\n\t&#039;ipAddress&#039; =&gt; $ip\n);\nmy $CustomizationIPSettings = CustomizationIPSettings-&gt;new(\n\t&#039;ip&#039; =&gt; $CustIp,\n\t&#039;subnetMask&#039; =&gt; $netmask,\n\t&#039;dnsServerList&#039; =&gt; $dns,\n\t&#039;gateway&#039; =&gt; [ $gateway ],\n\t&#039;dnsDomain&#039; =&gt; $domain,\n);\nmy $CustomizationAdapterMapping = CustomizationAdapterMapping-&gt;new(\n\t&#039;adapter&#039; =&gt; $CustomizationIPSettings\n);<\/code><\/pre> <div class=\"code-embed-infos\"> <\/div> <\/div>\n<p>Then, here are\u00a0the VMware Objects for the VM itself, you may not change anything there neither :<\/p>\n<div class=\"code-embed-wrapper\"> <pre class=\"language-bash code-embed-pre\"  data-start=\"1\" data-line-offset=\"0\"><code class=\"language-bash code-embed-code\">my $CustomizationSpec = CustomizationSpec-&gt;new(\n\t&#039;globalIPSettings&#039; =&gt; $CustomizationGlobalIPSettings,\n\t&#039;identity&#039; =&gt; $CustomizationIdentitySettings,\n\t&#039;nicSettingMap&#039; =&gt; [ $CustomizationAdapterMapping ],\n);\n\nmy $VirtualMachineRelocateSpec = VirtualMachineRelocateSpec-&gt;new(\n\t&#039;datastore&#039; =&gt; $DatastoreView,\n\t&#039;diskMoveType&#039; =&gt; &#039;moveAllDiskBackingsAndAllowSharing&#039;,\n\t&#039;pool&#039; =&gt; $ClusterView-&gt;resourcePool,\n);\n\nmy $VirtualMachineConfigSpec = new VirtualMachineConfigSpec;\n\nmy $VirtualMachineCloneSpec = VirtualMachineCloneSpec-&gt;new(\n\t&#039;config&#039; =&gt; $VirtualMachineConfigSpec,\n\t&#039;customization&#039; =&gt; $CustomizationSpec,\n\t&#039;location&#039; =&gt; $VirtualMachineRelocateSpec,\n\t&#039;powerOn&#039; =&gt; &#039;true&#039;,\n\t&#039;template&#039; =&gt; &#039;false&#039;\n);<\/code><\/pre> <div class=\"code-embed-infos\"> <\/div> <\/div>\n<p>Finally, 3 lines to deploy our VM :<\/p>\n<div class=\"code-embed-wrapper\"> <pre class=\"language-bash code-embed-pre\"  data-start=\"1\" data-line-offset=\"0\"><code class=\"language-bash code-embed-code\">eval{\n\t$VMView-&gt;CloneVM(\n\t\t&#039;folder&#039; =&gt; $FolderView,\n\t\t&#039;name&#039; =&gt; $vmName,\n\t\t&#039;spec&#039; =&gt; $VirtualMachineCloneSpec,\n\t);\n};\nif($@)\n{\n\tmy @report = (&#039;Error crearting VM : &#039;, $@);\n\tprint Dumper(@report);\n\tUtil::disconnect();\n\tdie;\n}<\/code><\/pre> <div class=\"code-embed-infos\"> <\/div> <\/div>\n<p>Here is the full script :<\/p>\n<div class=\"code-embed-wrapper\"> <pre class=\"language-bash code-embed-pre\"  data-start=\"1\" data-line-offset=\"0\"><code class=\"language-bash code-embed-code\">#!\/usr\/bin\/perl\nuse strict;\nuse Data::Dumper;\n\nuse VMware::VIRuntime;\n\nOpts::set_option(&#039;server&#039;, &#039;pcc-178-33-102-10.ovh.com&#039;);\nOpts::set_option(&#039;username&#039;, &#039;apiuser&#039;);\nOpts::set_option(&#039;password&#039;, &#039;XXxxXXxxXX&#039;);\n\n\nprint &quot;Connecting \\n&quot;; \n\nUtil::connect(); \n\n\n### Custom properties. To fill with your environment requirements\nmy $templateName = &#039;myOwnTemplate&#039;;\nmy $datacenterName = &#039;pcc-178-33-102-10_datacenter114&#039;;\nmy $vmName = &#039;myNewVM&#039;;\nmy $clusterName = &#039;Cluster1&#039;;\nmy $datastoreName = &#039;pcc-003643&#039;;\nmy $folderName = &#039;ProductionFolder&#039;;\nmy $custTimezone = &#039;Europe\/Paris&#039;;\nmy $domain = &#039;ovh.net&#039;;\nmy $dns = [ &#039;213.186.33.99&#039; ];\nmy $ip = &#039;192.168.0.10&#039;;\nmy $netmask = &#039;255.255.255.0&#039;;\nmy $gateway = &#039;192.168.0.10&#039;;\n\n\n### Checks \nprint &quot;Getting Datacenter view \\n&quot;;\nmy $DatacenterView = Vim::find_entity_view(\n\t&#039;view_type&#039; =&gt; &#039;Datacenter&#039;,\n\t&#039;filter&#039; =&gt; {\n\t\t&#039;name&#039; =&gt; $datacenterName\n\t}\n);\n!$DatacenterView and die(&#039;Failed to get Datacenter view&#039;);\n\nprint &quot;Getting Template view\\n&quot;;\nmy $VMView = Vim::find_entity_view(\n\t&#039;view_type&#039; =&gt; &#039;VirtualMachine&#039;,\n\t&#039;filter&#039; =&gt; {\n\t\t&#039;name&#039; =&gt; $templateName\n\t},\n\t&#039;begin_entity&#039; =&gt; $DatacenterView,\n);\n!$VMView and die(&#039;Failed to get Template view&#039;);\n\nprint &quot;Getting destination cluster view\\n&quot;;\nmy $ClusterView = Vim::find_entity_view(\n\t&#039;view_type&#039; =&gt; &#039;ClusterComputeResource&#039;,\n\t&#039;begin_entity&#039; =&gt; $DatacenterView,\n\t&#039;filter&#039; =&gt; { \n\t\t&#039;name&#039; =&gt; $clusterName \n\t}\n);\n!$ClusterView and die(&#039;Failed to get cluster view&#039;);\n\nprint &quot;Getting destination datastore view \\n&quot;;\nmy $DatastoreView = Vim::find_entity_view(\n\t&#039;view_type&#039; =&gt; &#039;Datastore&#039;,\n\t&#039;begin_entity&#039; =&gt; $DatacenterView,\n\t&#039;filter&#039; =&gt; {\n\t\t&#039;name&#039; =&gt; $datastoreName\n\t}\n);\n!$DatastoreView and die(&#039;Failed to get datastore view&#039;);\n\nprint &quot;Getting destination folder view\\n&quot;;\nmy $FolderView = Vim::find_entity_view(\n\t&#039;view_type&#039; =&gt; &#039;Folder&#039;,\n\t&#039;begin_entity&#039; =&gt; $DatacenterView,\n\t&#039;filter&#039; =&gt; { \n\t\t&#039;name&#039; =&gt; $folderName \n\t}\n);\n!$FolderView and die $FolderView;\n\n### Guest OS configuration\nmy $CustomizationGlobalIPSettings;\nmy $custName = CustomizationFixedName-&gt;new( name =&gt; $vmName );\nmy $custDomain = $domain;\n\n$CustomizationGlobalIPSettings = CustomizationGlobalIPSettings-&gt;new(\n\t&#039;dnsServerList&#039; =&gt; $dns,\n\t&#039;dnsSuffixList&#039; =&gt; [ $domain ],\n);\n\nmy $custUtcClock = &#039;false&#039;;\n\nmy $CustomizationIdentitySettings = CustomizationLinuxPrep-&gt;new(\n\t&#039;hostName&#039; =&gt; $custName,\n\t&#039;domain&#039; =&gt; &quot;$custDomain&quot;,\n\t&#039;hwClockUTC&#039; =&gt; $custUtcClock,\n\t&#039;timeZone&#039; =&gt; &quot;$custTimezone&quot;,\n);\n\nmy $CustIp = CustomizationFixedIp-&gt;new(\n\t&#039;ipAddress&#039; =&gt; $ip\n);\nmy $CustomizationIPSettings = CustomizationIPSettings-&gt;new(\n\t&#039;ip&#039; =&gt; $CustIp,\n\t&#039;subnetMask&#039; =&gt; $netmask,\n\t&#039;dnsServerList&#039; =&gt; $dns,\n\t&#039;gateway&#039; =&gt; [ $gateway ],\n\t&#039;dnsDomain&#039; =&gt; $domain,\n);\nmy $CustomizationAdapterMapping = CustomizationAdapterMapping-&gt;new(\n\t&#039;adapter&#039; =&gt; $CustomizationIPSettings\n);\n\n### Virtual Hardware configuration\n \nmy $CustomizationSpec = CustomizationSpec-&gt;new(\n\t&#039;globalIPSettings&#039; =&gt; $CustomizationGlobalIPSettings,\n\t&#039;identity&#039; =&gt; $CustomizationIdentitySettings,\n\t&#039;nicSettingMap&#039; =&gt; [ $CustomizationAdapterMapping ],\n);\n\nmy $VirtualMachineRelocateSpec = VirtualMachineRelocateSpec-&gt;new(\n\t&#039;datastore&#039; =&gt; $DatastoreView,\n\t&#039;diskMoveType&#039; =&gt; &#039;moveAllDiskBackingsAndAllowSharing&#039;,\n\t&#039;pool&#039; =&gt; $ClusterView-&gt;resourcePool,\n);\nmy $VirtualMachineConfigSpec = new VirtualMachineConfigSpec;\n\nmy $VirtualMachineCloneSpec = VirtualMachineCloneSpec-&gt;new(\n\t&#039;config&#039; =&gt; $VirtualMachineConfigSpec,\n\t&#039;customization&#039; =&gt; $CustomizationSpec,\n\t&#039;location&#039; =&gt; $VirtualMachineRelocateSpec,\n\t&#039;powerOn&#039; =&gt; &#039;true&#039;,\n\t&#039;template&#039; =&gt; &#039;false&#039;\n);\n\n### Cloning operation\neval{\n\t$VMView-&gt;CloneVM(\n\t\t&#039;folder&#039; =&gt; $FolderView,\n\t\t&#039;name&#039; =&gt; $vmName,\n\t\t&#039;spec&#039; =&gt; $VirtualMachineCloneSpec,\n\t);\n};\nif($@)\n{\n\tmy @report = (&#039;Error crearting VM : &#039;, $@);\n\tprint Dumper(@report);\n\tUtil::disconnect();\n\tdie;\n}<\/code><\/pre> <div class=\"code-embed-infos\"> <\/div> <\/div>\n","protected":false},"excerpt":{"rendered":"<p>This post will show you how to deploy a VM fully operational in a few seconds in a vSphere environment. You must have a working template to use this script. You will have to install VMware Tools on this template, or OVT (OpenVMwareTools). They are now fully supported by VMware. I would recommand to use &hellip; <a href=\"https:\/\/room28.it\/index.php\/2016\/10\/10\/deploy-a-linux-vm-using-customization-wizard-using-perl-sdk\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Deploy a Linux VM using Customization Wizard using Perl SDK&#8221;<\/span><\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[6,7,18],"tags":[],"_links":{"self":[{"href":"https:\/\/room28.it\/index.php\/wp-json\/wp\/v2\/posts\/80"}],"collection":[{"href":"https:\/\/room28.it\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/room28.it\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/room28.it\/index.php\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/room28.it\/index.php\/wp-json\/wp\/v2\/comments?post=80"}],"version-history":[{"count":19,"href":"https:\/\/room28.it\/index.php\/wp-json\/wp\/v2\/posts\/80\/revisions"}],"predecessor-version":[{"id":190,"href":"https:\/\/room28.it\/index.php\/wp-json\/wp\/v2\/posts\/80\/revisions\/190"}],"wp:attachment":[{"href":"https:\/\/room28.it\/index.php\/wp-json\/wp\/v2\/media?parent=80"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/room28.it\/index.php\/wp-json\/wp\/v2\/categories?post=80"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/room28.it\/index.php\/wp-json\/wp\/v2\/tags?post=80"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}