{"id":731,"date":"2021-09-21T12:05:50","date_gmt":"2021-09-21T12:05:50","guid":{"rendered":"https:\/\/bogdanburuiana.com\/?p=731"},"modified":"2022-02-15T11:50:16","modified_gmt":"2022-02-15T11:50:16","slug":"deploy-vmware-vm-with-azure-dsc","status":"publish","type":"post","link":"https:\/\/bogdanburuiana.com\/index.php\/2021\/09\/21\/deploy-vmware-vm-with-azure-dsc\/","title":{"rendered":"Deploy VMware VMs using Azure DSC"},"content":{"rendered":"\n<p>Desired State Configuration (DSC) resources for VMware allows you to apply standard configuration management processes through PowerShell DSC and PowerCLI.  DSC can manage and monitor a system\u2019s configuration based on configuration files.<\/p>\n\n\n\n<p>The image below from VMware\u2019s <a href=\"https:\/\/blogs.vmware.com\/PowerCLI\/2018\/12\/getting-started-dsc-for-vmware.html\">website<\/a> provides a good overview of the layout :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"763\" height=\"482\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_7.jpg\" alt=\"\" class=\"wp-image-689\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_7.jpg 763w, \/wp-content\/uploads\/2021\/09\/Screenshot_7-300x190.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_7-480x303.jpg 480w\" sizes=\"(max-width: 763px) 100vw, 763px\" \/><\/figure>\n\n\n\n<p>DSC Resources for VMware is a little different than a standard DSC configuration, using a proxy because the LCM cannot run on VCSA or ESXi host.<\/p>\n\n\n\n<p><strong>Setting Up<\/strong> <strong>Azure Automation Configuration Management as a pull server<\/strong><\/p>\n\n\n\n<p>First of all we need to create an Automation Account. <\/p>\n\n\n\n<ul><li>Log into Azure, do a search for <strong>Automation Accounts<\/strong>. <\/li><li>Then select <strong>Add<\/strong> to create an <strong>Automation account<\/strong>. <\/li><li>Next, fill out the blade with your <strong>Name<\/strong>, <strong>Subscription<\/strong>, <strong>Resource group<\/strong> and <strong>Location<\/strong>. <\/li><\/ul>\n\n\n\n<p>No<em>te: Keep the option for <strong>Azure Run As Account<\/strong> on <strong>Yes<\/strong> and select <strong>Create<\/strong>:<\/em><\/p>\n\n\n\n<p><span class=\"has-inline-color has-vivid-red-color\">The <strong>Run As account<\/strong> expires one year from the date of creation. At some point before your Run As account expires, you must renew the certificate. You can renew it any time before it expires.<\/span><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"720\" height=\"846\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_1.jpg\" alt=\"\" class=\"wp-image-694\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_1.jpg 720w, \/wp-content\/uploads\/2021\/09\/Screenshot_1-255x300.jpg 255w, \/wp-content\/uploads\/2021\/09\/Screenshot_1-480x564.jpg 480w\" sizes=\"(max-width: 720px) 100vw, 720px\" \/><\/figure>\n\n\n\n<p>Now we need two modules (AzureRM.Automation &amp; xPSDesiredStateConfiguration) which can be installed on the LCM node itself or on the management workstation. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Install-Module AzureRM.Automation -Force<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>Install-Module -name xPSDesiredStateConfiguration -Force\n<\/code><\/pre>\n\n\n\n<p>We will need to fill out the parameters to match our newly created automation account.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Define the parameters for Get-AzureRmAutomationDscOnboardingMetaconfig using PowerShell Splatting\n$Params = @{\n    ResourceGroupName = 'BogdanLabDSC'; # The name of the Resource Group that contains your Azure Automation Account\n    AutomationAccountName = 'BogdanLabDSC'; # The name of the Azure Automation Account where you want a node on-boarded to\n    ComputerName = @('<strong>computername<\/strong>'); # The names of the computers that the meta configuration will be generated for\n    OutputFolder = \"C:\\DSCConfigs\";\n}\n# Use PowerShell splatting to pass parameters to the Azure Automation cmdlet being invoked\n# For more info about splatting, run: Get-Help -Name about_Splatting\nGet-AzureRmAutomationDscOnboardingMetaconfig @Params<\/code><\/pre>\n\n\n\n<p>Note: Make sure the <strong>com<\/strong><em><strong>putername<\/strong> field matches the name of the LCM node.<\/em><\/p>\n\n\n\n<p>Connect to Azure by typing in: <code>connect-azurermaccount<\/code><\/p>\n\n\n\n<p>A prompt window to log in to Azure will appear asking for your credentials.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"495\" height=\"434\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_8.jpg\" alt=\"\" class=\"wp-image-708\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_8.jpg 495w, \/wp-content\/uploads\/2021\/09\/Screenshot_8-300x263.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_8-480x421.jpg 480w\" sizes=\"(max-width: 495px) 100vw, 495px\" \/><\/figure>\n\n\n\n<p>Once logged in, we&#8217;ll run the code mentioned above generating our meta.mof file, the file that configures the LCM engine. In other words, this tell our vSphere DSC node to report into Azure for its config. file.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"584\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_5-1024x584.jpg\" alt=\"\" class=\"wp-image-736\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_5-1024x584.jpg 1024w, \/wp-content\/uploads\/2021\/09\/Screenshot_5-300x171.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_5-768x438.jpg 768w, \/wp-content\/uploads\/2021\/09\/Screenshot_5-1226x699.jpg 1226w, \/wp-content\/uploads\/2021\/09\/Screenshot_5-928x529.jpg 928w, \/wp-content\/uploads\/2021\/09\/Screenshot_5-480x274.jpg 480w, \/wp-content\/uploads\/2021\/09\/Screenshot_5.jpg 1443w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Copy the <strong>.meta.mof<\/strong> file to the LCM node itself and run <strong>Set-DSLOcalConfigurationManager<\/strong> locally (also you can use PSRemoting to push the configuration)<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Set-DSCLocalConfigurationManager -path \"C:\\DscConfigs\\DscMetaConfigs\" -Computername <strong>computername<\/strong> <code>-credential $creds -verbose<\/code><\/pre>\n\n\n\n<p> Note: Make sure the <strong>com<\/strong><em><strong>putername<\/strong> field matches the name of the LCM node.<\/em> <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"426\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_6-2-1024x426.jpg\" alt=\"\" class=\"wp-image-737\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_6-2-1024x426.jpg 1024w, \/wp-content\/uploads\/2021\/09\/Screenshot_6-2-300x125.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_6-2-768x320.jpg 768w, \/wp-content\/uploads\/2021\/09\/Screenshot_6-2-1226x510.jpg 1226w, \/wp-content\/uploads\/2021\/09\/Screenshot_6-2-928x386.jpg 928w, \/wp-content\/uploads\/2021\/09\/Screenshot_6-2-480x200.jpg 480w, \/wp-content\/uploads\/2021\/09\/Screenshot_6-2.jpg 1442w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Now, when we take a peek at our Automation Account in Azure, and select<strong> State Configuration (DSC)<\/strong>, we can see our added node and a pretty graph for managing all of our nodes:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"608\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_7-1-1024x608.jpg\" alt=\"\" class=\"wp-image-738\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_7-1-1024x608.jpg 1024w, \/wp-content\/uploads\/2021\/09\/Screenshot_7-1-300x178.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_7-1-768x456.jpg 768w, \/wp-content\/uploads\/2021\/09\/Screenshot_7-1-1536x912.jpg 1536w, \/wp-content\/uploads\/2021\/09\/Screenshot_7-1-1226x728.jpg 1226w, \/wp-content\/uploads\/2021\/09\/Screenshot_7-1-928x551.jpg 928w, \/wp-content\/uploads\/2021\/09\/Screenshot_7-1-480x285.jpg 480w, \/wp-content\/uploads\/2021\/09\/Screenshot_7-1.jpg 1547w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><em>Note that <strong>the LCM node cannot be a part of a domain<\/strong>.<\/em><\/p>\n\n\n\n<p>For VMware VMs deployment I will use an existing VM templates from my LAB, called <strong>TestVM<\/strong> and  a Custom OS configuration. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"305\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_33-1024x305.jpg\" alt=\"\" class=\"wp-image-741\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_33-1024x305.jpg 1024w, \/wp-content\/uploads\/2021\/09\/Screenshot_33-300x89.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_33-768x228.jpg 768w, \/wp-content\/uploads\/2021\/09\/Screenshot_33-928x276.jpg 928w, \/wp-content\/uploads\/2021\/09\/Screenshot_33-480x143.jpg 480w, \/wp-content\/uploads\/2021\/09\/Screenshot_33.jpg 1217w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"159\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_9-1-1024x159.jpg\" alt=\"\" class=\"wp-image-740\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_9-1-1024x159.jpg 1024w, \/wp-content\/uploads\/2021\/09\/Screenshot_9-1-300x47.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_9-1-768x119.jpg 768w, \/wp-content\/uploads\/2021\/09\/Screenshot_9-1-1536x239.jpg 1536w, \/wp-content\/uploads\/2021\/09\/Screenshot_9-1-2048x319.jpg 2048w, \/wp-content\/uploads\/2021\/09\/Screenshot_9-1-1226x191.jpg 1226w, \/wp-content\/uploads\/2021\/09\/Screenshot_9-1-928x144.jpg 928w, \/wp-content\/uploads\/2021\/09\/Screenshot_9-1-480x75.jpg 480w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Now we need to create DSC Resource module and upload it into created Automation Account. DSC Custom Resource for deploying VM\u2019s will consist of a module file (.psm1) and a manifest file (.psd1)<\/p>\n\n\n\n<p><strong>DeployVM.psm1<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;DscResource()]\nclass DeployVM {\n        &#91;DscProperty(key)]\n        &#91;String]$VMname\n        &#91;DscProperty(Mandatory)]\n        &#91;String]$VCenter\n        &#91;DscProperty(Mandatory)]\n        &#91;PSCredential]$Credentials\n        &#91;DSCProperty()]\n        &#91;String]$Template\n        &#91;DscProperty(Mandatory)]\n        &#91;String]$Customization\n        &#91;DscProperty()]\n        &#91;int]$CPU\n        &#91;DscProperty()]\n        &#91;int]$MemoryGB\n        &#91;DscProperty(Mandatory)]\n        &#91;String]$VMhost\n        &#91;DscProperty(Mandatory)]\n        &#91;String]$datastore\n        &#91;DscProperty(Mandatory)]\n        &#91;String]$cluster\n        hidden &#91;PSObject] $Connection\n        #Create VM or update with settings if its already created\n        &#91;void] Set(){\n            Try{\n                $this.ConnectVIServer()\n                $vm = $this.getvm()\n                if ($null -eq $vm){\n                        #if VM doesnt exist, create it, if it does check Mem and CPU\n                    Write-Verbose \"Creating $($this.VMname)\"\n                    $result = $this.CreateVM()\n                    if ($result -eq $true){\n                        Write-Verbose \"$($this.VMname) has been created \"\n                    } else {\n                        throw \"There was an issue creating the VM\"\n                    }\n                }else{\n                        #Set Memory\n                    if ($vm.MemoryGB -ne $this.MemoryGB) {\n                        \n                        #verify if VM is powered off or on if so check for hot add\n                        if ($vm.PowerState -eq 'Poweredon'){\n                            Write-Verbose \"$($this.VMname) is powered on, checking for Hot Add\"\n                            #if hot add is enabled and memory is less than what is declared\n                            if($vm.ExtensionData.Config.MemoryHotAddEnabled -eq $true -and $vm.MemoryGB -lt $this.MemoryGB){\n                                Write-Verbose \"Hot add is enabled, adding memory\"\n                                $this.UpdateMemory()\n                            } else {\n                                Write-Error \"Cannot set Memory while VM is powered on\"\n                            }\n                        } Else{\n                            $this.UpdateMemory()\n                        }else {Write-error \"Unable to set memory while VM is powered on\"}\n                    }\n                        #Set CPU\n                    if ($vm.NumCpu -ne $this.CPU) {\n                        \n                        #verify if VM is powered off or on if so check for hot add\n                        if ($vm.PowerState -eq 'Poweredon'){\n                            Write-Verbose \"$($this.VMname) is powered on, checking for Hot Add\"\n                            \n                            #if hot add is enabled and CPU is less than what is declared\n                            if($vm.ExtensionData.Config.CpuHotAddEnabled -eq $true -and $vm.NumCpu -lt $this.CPU){\n                                Write-Verbose \"Hot add is enabled, adding CPU\"\n                                $this.UpdateCPU()\n                            } else {\n                                Write-Error \"Cannot increase CPU while VM is powered on\"\n                            }\n                        } Else {\n                            $this.UpdateCPU()\n                        }\n                    }\n                }\n            } Catch{\n                Write-Verbose \"There was an issue with setting the resource: $($_.Exception.Message)\"\n            }\n            \n        }\n        #Check if current settings of VM equal settings of the DSC config\n        &#91;bool] Test() {\n            $this.ConnectVIServer()\n            Write-Verbose \"Looking for VM: $($this.VMname)\"\n            $VMConfig = $this.getvm()\n            return $this.Equals($VMConfig)\n           \n        \n        }\n        #Get the current settings of the VM\n        &#91;DeployVM] Get() {\n            $result = &#91;DeployVM]::new()\n            $this.ConnectVIServer()\n            Write-Verbose \"Looking for VM: $($this.VMname)\"\n            $vm = $this.getvm()\n            \n            \n            $result.VMname = $vm.name\n            $result.VCenter = $this.VCenter\n            $result.Credentials = $this.Credentials\n            $result.template = $this.Template\n            $result.Customization = $this.Customization\n            $result.CPU = $vm.NumCpu\n            $result.MemoryGB = $vm.MemoryGB\n            $result.VMhost = $vm.VMHost\n            $result.datastore = (get-datastore | where-object {$_.id -eq $vm.DatastoreIdList}).Name\n            $result.cluster = (get-cluster -vm $vm).name\n                \n            return $result\n                \n                \n            }\n        #Helpers\n        \n        #Import modules and connect to VC\n        &#91;void] ConnectVIServer() {\n            $savedVerbosePreference = $global:VerbosePreference\n            $global:VerbosePreference = 'SilentlyContinue'\n            Import-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue\n             $global:VerbosePreference = $savedVerbosePreference\n            if ($null -eq $this.Connection) {\n                try {\n                    $this.Connection = Connect-VIServer -Server $this.vcenter -Credential $this.Credentials -ErrorAction Stop\n                }\n                catch {\n                    throw \"Cannot establish connection to server $($this.vcenter). For more information: $($_.Exception.Message)\"\n                }\n            }\n        }\n        #create VM if doesnt esxist, if it does set the CPU and Memory\n        &#91;bool] CreateVM() {\n                \n              \n                $VMcluster = Get-Cluster -Name $this.cluster\n                $props = @{\n                    Name = $this.VMname\n                    template = $this.Template\n                    OSCustomizationSpec = $this.Customization\n                    VMhost = (Get-VMHost -name $this.vmhost)\n                    Datastore = $this.datastore\n                    Server = $this.VCenter\n                    resourcepool = $VMcluster\n                }\n                $VM = New-VM @props\n                if($vm.NumCpu -ne $this.CPU){ set-vm $vm -NumCpu $this.cpu -Confirm:$false }\n                if($vm.MemoryGB -ne $this.MemoryGB){ set-vm $vm -MemoryGB $this.MemoryGB -confirm:$false}\n                Start-vm $vm\n                if ($null -ne $vm){\n                    return $true\n                } else {\n                    return $false\n                }\n        \n            }\n        &#91;PSObject] GetVM(){\n             \n             try{\n                $VM = Get-VM -Name $this.VMName -verbose:$false -ErrorAction SilentlyContinue | select -First 1\n                return $vm\n            }\n            catch{ \n            write-verbose \"VM is not there\" \n            return $null\n            \n            }\n        }\n        &#91;void] UpdateMemory(){\n            Try{\n                \n                 set-vm $this.VMname -MemoryGB $this.MemoryGB -confirm:$false\n            }\n            Catch{\n                Throw \"there is an issue setting the Memory\"\n            }\n        }\n        &#91;bool] Equals($VMConfig) {\n                $vm = $this.getvm()\n                #Check if VM exists\n                if ($null -eq $vm){ \n                    Write-Verbose \"$($this.VMname) does not exist\"\n                    return $false\n                }\n                #Check CPU\n                if ($VMConfig.NumCpu -ne $this.CPU){\n                    Write-Verbose \"$($this.VMname) has $($vmconfig.NumCpu) vCPUs and should have $($this.CPU)\"\n                    return $false\n                }\n                #check Memory\n                if ($VMConfig.MemoryGB -ne $this.MemoryGB){\n                    Write-Verbose \"$($this.VMname) has $($vmconfig.MemoryGB) Memory and should have $($this.MemoryGB)\"\n                    return $false\n                }\n            \n                return $true\n        }\n        &#91;void] UpdateCPU(){\n            Try{       \n                 set-vm $this.VMname -NumCpu $this.CPU -confirm:$false\n            }\n            Catch{\n                Throw \"there is an issue setting the CPU\"\n            }\n        \n        }\n}<\/code><\/pre>\n\n\n\n<p><strong>DeployVM.psd1<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#\n# Module manifest for module 'DeployVM'\n#\n# Generated by: Bogdan\n#\n# Generated on: 21\/09\/2021\n#\n@{\n# Script module or binary module file associated with this manifest.\nRootModule = 'DeployVM.psm1'\n# Version number of this module.\nModuleVersion = '2.0'\n# Supported PSEditions\n# CompatiblePSEditions = @()\n# ID used to uniquely identify this module\nGUID = '184099d3-bb59-49f8-a4dc-f0f0gfg8b5cb'\n# Author of this module\nAuthor = 'Bogdan'\n# Company or vendor of this module\nCompanyName = 'Lab'\n# Copyright statement for this module\nCopyright = '(c) 2021 Bogdan. All rights reserved.'\n# Description of the functionality provided by this module\nDescription = 'Deploy VMwawre VM Module'\n# Minimum version of the Windows PowerShell engine required by this module\n# PowerShellVersion = ''\n# Name of the Windows PowerShell host required by this module\n# PowerShellHostName = ''\n# Minimum version of the Windows PowerShell host required by this module\n# PowerShellHostVersion = ''\n# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.\n# DotNetFrameworkVersion = ''\n# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.\n# CLRVersion = ''\n# Processor architecture (None, X86, Amd64) required by this module\n# ProcessorArchitecture = ''\n# Modules that must be imported into the global environment prior to importing this module\n# RequiredModules = @()\n# Assemblies that must be loaded prior to importing this module\n# RequiredAssemblies = @()\n# Script files (.ps1) that are run in the caller's environment prior to importing this module.\n# ScriptsToProcess = @()\n# Type files (.ps1xml) to be loaded when importing this module\n# TypesToProcess = @()\n# Format files (.ps1xml) to be loaded when importing this module\n# FormatsToProcess = @()\n# Modules to import as nested modules of the module specified in RootModule\/ModuleToProcess\n# NestedModules = @()\n# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.\nFunctionsToExport = '*'\n# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.\nCmdletsToExport = '*'\n# Variables to export from this module\nVariablesToExport = '*'\n# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.\nAliasesToExport = '*'\n# DSC resources to export from this module\nDscResourcesToExport = 'DeployVM'<\/code><\/pre>\n\n\n\n<p>Zip the two files together and upload it into Azure. Navigate to your <strong>Azure Automation<\/strong> account and select<strong> Modules<\/strong> and choose the <strong>Add a module <\/strong>button. Upload the .zip file created and choose&nbsp;<strong>Ok<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"888\" height=\"235\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_7-2.jpg\" alt=\"\" class=\"wp-image-746\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_7-2.jpg 888w, \/wp-content\/uploads\/2021\/09\/Screenshot_7-2-300x79.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_7-2-768x203.jpg 768w, \/wp-content\/uploads\/2021\/09\/Screenshot_7-2-480x127.jpg 480w\" sizes=\"(max-width: 888px) 100vw, 888px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"419\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_6-3-1024x419.jpg\" alt=\"\" class=\"wp-image-748\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_6-3-1024x419.jpg 1024w, \/wp-content\/uploads\/2021\/09\/Screenshot_6-3-300x123.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_6-3-768x314.jpg 768w, \/wp-content\/uploads\/2021\/09\/Screenshot_6-3-1536x629.jpg 1536w, \/wp-content\/uploads\/2021\/09\/Screenshot_6-3-2048x838.jpg 2048w, \/wp-content\/uploads\/2021\/09\/Screenshot_6-3-1226x502.jpg 1226w, \/wp-content\/uploads\/2021\/09\/Screenshot_6-3-928x380.jpg 928w, \/wp-content\/uploads\/2021\/09\/Screenshot_6-3-480x196.jpg 480w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>DeployVM module has \u201cavailable\u201d status now.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"368\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_34-1024x368.jpg\" alt=\"\" class=\"wp-image-750\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_34-1024x368.jpg 1024w, \/wp-content\/uploads\/2021\/09\/Screenshot_34-300x108.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_34-768x276.jpg 768w, \/wp-content\/uploads\/2021\/09\/Screenshot_34-1536x553.jpg 1536w, \/wp-content\/uploads\/2021\/09\/Screenshot_34-2048x737.jpg 2048w, \/wp-content\/uploads\/2021\/09\/Screenshot_34-1226x441.jpg 1226w, \/wp-content\/uploads\/2021\/09\/Screenshot_34-928x334.jpg 928w, \/wp-content\/uploads\/2021\/09\/Screenshot_34-480x173.jpg 480w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>We&#8217;ll create a configuration to deploy two VM\u2019s \u201cTestVM1\u201d and \u201cTestVM2\u201d. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_10-1-1024x343.jpg\" alt=\"\" class=\"wp-image-752\" width=\"840\" height=\"281\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_10-1-1024x343.jpg 1024w, \/wp-content\/uploads\/2021\/09\/Screenshot_10-1-300x101.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_10-1-768x257.jpg 768w, \/wp-content\/uploads\/2021\/09\/Screenshot_10-1-1226x411.jpg 1226w, \/wp-content\/uploads\/2021\/09\/Screenshot_10-1-928x311.jpg 928w, \/wp-content\/uploads\/2021\/09\/Screenshot_10-1-480x161.jpg 480w, \/wp-content\/uploads\/2021\/09\/Screenshot_10-1.jpg 1271w\" sizes=\"(max-width: 840px) 100vw, 840px\" \/><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code>Configuration DeployVM {\n    Import-DscResource -ModuleName DeployVM\n    Node LCMNODE {\n       \n        #Credentials from Azure\n        $Cred = Get-AutomationPSCredential 'VMware'\n        $vccreds = New-Object System.Management.Automation.PSCredential (\"administrator@vsphere.local\", $cred.password)\n        #Apply Config to each host\n        foreach ($VMname in @(\"TestVM1\",\"TestVM2\")) {\n         \n            DeployVM \"VMConfig_$($VMName)\" {\n                VMName = $VMName\n                VCenter = \"192.168.0.111\"\n                Credentials = $vccreds\n                Template = \"TestVM\"\n                Customization = \"TestVM\"\n                CPU = 2\n                MemoryGB = 4\n                VMhost = \"192.168.0.103\"\n                Datastore = \"datastore1\"\n                Cluster = \"Cluster\"\n            }\n            \n        }\n    }\n}<\/code><\/pre>\n\n\n\n<p>Make sure you specify the name of the credential you are storing, for example, mine is \u201cVMware\u201d.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_11-1024x372.jpg\" alt=\"\" class=\"wp-image-753\" width=\"840\" height=\"305\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_11-1024x372.jpg 1024w, \/wp-content\/uploads\/2021\/09\/Screenshot_11-300x109.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_11-768x279.jpg 768w, \/wp-content\/uploads\/2021\/09\/Screenshot_11-1536x559.jpg 1536w, \/wp-content\/uploads\/2021\/09\/Screenshot_11-2048x745.jpg 2048w, \/wp-content\/uploads\/2021\/09\/Screenshot_11-1226x446.jpg 1226w, \/wp-content\/uploads\/2021\/09\/Screenshot_11-928x338.jpg 928w, \/wp-content\/uploads\/2021\/09\/Screenshot_11-480x175.jpg 480w\" sizes=\"(max-width: 840px) 100vw, 840px\" \/><\/figure>\n\n\n\n<p>Save the config file to a .ps1 and upload it as a configuration into Azure DSC. Under the<strong> Automation Account<\/strong>, select <strong>State Configuration (DSC)<\/strong> and select the<strong> configurations<\/strong> tab. Then click the&nbsp;<strong>Add<\/strong> button and upload the configuration file (.ps1). Click&nbsp;<strong>refresh<\/strong> and it will appear as a list of configurations. Select <strong>Compose Configuration<\/strong> to create our MOF file for our node:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_12-1024x436.jpg\" alt=\"\" class=\"wp-image-755\" width=\"840\" height=\"357\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_12-1024x436.jpg 1024w, \/wp-content\/uploads\/2021\/09\/Screenshot_12-300x128.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_12-768x327.jpg 768w, \/wp-content\/uploads\/2021\/09\/Screenshot_12-1226x522.jpg 1226w, \/wp-content\/uploads\/2021\/09\/Screenshot_12-928x395.jpg 928w, \/wp-content\/uploads\/2021\/09\/Screenshot_12-480x204.jpg 480w, \/wp-content\/uploads\/2021\/09\/Screenshot_12.jpg 1471w\" sizes=\"(max-width: 840px) 100vw, 840px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_13.jpg\" alt=\"\" class=\"wp-image-756\" width=\"800\" height=\"507\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_13.jpg 800w, \/wp-content\/uploads\/2021\/09\/Screenshot_13-300x190.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_13-768x487.jpg 768w, \/wp-content\/uploads\/2021\/09\/Screenshot_13-480x304.jpg 480w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_16-1024x242.jpg\" alt=\"\" class=\"wp-image-757\" width=\"840\" height=\"198\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_16-1024x242.jpg 1024w, \/wp-content\/uploads\/2021\/09\/Screenshot_16-300x71.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_16-768x182.jpg 768w, \/wp-content\/uploads\/2021\/09\/Screenshot_16-1536x364.jpg 1536w, \/wp-content\/uploads\/2021\/09\/Screenshot_16-1226x290.jpg 1226w, \/wp-content\/uploads\/2021\/09\/Screenshot_16-928x220.jpg 928w, \/wp-content\/uploads\/2021\/09\/Screenshot_16-480x114.jpg 480w, \/wp-content\/uploads\/2021\/09\/Screenshot_16.jpg 2036w\" sizes=\"(max-width: 840px) 100vw, 840px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_17-1024x203.jpg\" alt=\"\" class=\"wp-image-758\" width=\"840\" height=\"166\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_17-1024x203.jpg 1024w, \/wp-content\/uploads\/2021\/09\/Screenshot_17-300x59.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_17-768x152.jpg 768w, \/wp-content\/uploads\/2021\/09\/Screenshot_17-1536x304.jpg 1536w, \/wp-content\/uploads\/2021\/09\/Screenshot_17-2048x405.jpg 2048w, \/wp-content\/uploads\/2021\/09\/Screenshot_17-1226x243.jpg 1226w, \/wp-content\/uploads\/2021\/09\/Screenshot_17-928x184.jpg 928w, \/wp-content\/uploads\/2021\/09\/Screenshot_17-480x95.jpg 480w\" sizes=\"(max-width: 840px) 100vw, 840px\" \/><\/figure>\n\n\n\n<p>Now we are ready to assign the new compiled configuration to our LCM node. Select the LCM node under the <strong>Nodes<\/strong> tab:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_18-1024x290.jpg\" alt=\"\" class=\"wp-image-759\" width=\"840\" height=\"237\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_18-1024x290.jpg 1024w, \/wp-content\/uploads\/2021\/09\/Screenshot_18-300x85.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_18-768x217.jpg 768w, \/wp-content\/uploads\/2021\/09\/Screenshot_18-1536x435.jpg 1536w, \/wp-content\/uploads\/2021\/09\/Screenshot_18-1226x347.jpg 1226w, \/wp-content\/uploads\/2021\/09\/Screenshot_18-928x263.jpg 928w, \/wp-content\/uploads\/2021\/09\/Screenshot_18-480x136.jpg 480w, \/wp-content\/uploads\/2021\/09\/Screenshot_18.jpg 1990w\" sizes=\"(max-width: 840px) 100vw, 840px\" \/><\/figure>\n\n\n\n<p>Select <strong>Assign Node Configuration<\/strong> and we\u2019ll choose our \u201cDeployVM.LCMNODE\u201d configuration<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"661\" height=\"324\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_19.jpg\" alt=\"\" class=\"wp-image-760\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_19.jpg 661w, \/wp-content\/uploads\/2021\/09\/Screenshot_19-300x147.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_19-480x235.jpg 480w\" sizes=\"(max-width: 661px) 100vw, 661px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"216\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_20-1024x216.jpg\" alt=\"\" class=\"wp-image-763\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_20-1024x216.jpg 1024w, \/wp-content\/uploads\/2021\/09\/Screenshot_20-300x63.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_20-768x162.jpg 768w, \/wp-content\/uploads\/2021\/09\/Screenshot_20-1536x324.jpg 1536w, \/wp-content\/uploads\/2021\/09\/Screenshot_20-2048x433.jpg 2048w, \/wp-content\/uploads\/2021\/09\/Screenshot_20-1226x259.jpg 1226w, \/wp-content\/uploads\/2021\/09\/Screenshot_20-928x196.jpg 928w, \/wp-content\/uploads\/2021\/09\/Screenshot_20-480x101.jpg 480w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Remote into the node and run the following command update the configuration:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Update-DscConfiguration -wait -verbose<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"210\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_27-1024x210.jpg\" alt=\"\" class=\"wp-image-764\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_27-1024x210.jpg 1024w, \/wp-content\/uploads\/2021\/09\/Screenshot_27-300x61.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_27-768x157.jpg 768w, \/wp-content\/uploads\/2021\/09\/Screenshot_27-1536x314.jpg 1536w, \/wp-content\/uploads\/2021\/09\/Screenshot_27-2048x419.jpg 2048w, \/wp-content\/uploads\/2021\/09\/Screenshot_27-1226x251.jpg 1226w, \/wp-content\/uploads\/2021\/09\/Screenshot_27-928x190.jpg 928w, \/wp-content\/uploads\/2021\/09\/Screenshot_27-480x98.jpg 480w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>We can see our VMs declared in the config file now exist:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"509\" height=\"429\" src=\"https:\/\/bogdanburuiana.com\/wp-content\/uploads\/2021\/09\/Screenshot_28.jpg\" alt=\"\" class=\"wp-image-765\" srcset=\"\/wp-content\/uploads\/2021\/09\/Screenshot_28.jpg 509w, \/wp-content\/uploads\/2021\/09\/Screenshot_28-300x253.jpg 300w, \/wp-content\/uploads\/2021\/09\/Screenshot_28-480x405.jpg 480w\" sizes=\"(max-width: 509px) 100vw, 509px\" \/><\/figure>\n\n\n\n<p>If we delete a VM, change the CPU, or modify the Memory <strong>it will automatically get recreated\/reconfigured again in 15 minutes during the next poll.<\/strong> This can be extremely powerful and we can get as granular with the configuration file and custom resources as we want. <\/p>\n\n\n\n<p><strong>Unique Visitors<\/strong><\/p>\n\n\n\n<!-- hitwebcounter Code START -->\n<a href=\"https:\/\/www.hitwebcounter.com\" target=\"_blank\" rel=\"noopener\">\n<img decoding=\"async\" src=\"https:\/\/hitwebcounter.com\/counter\/counter.php?page=7868713&amp;style=0003&amp;nbdigits=3&amp;type=ip&amp;initCount=175\" title=\"Free Counter\" alt=\"web counter\" border=\"0\"><\/a>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Desired State Configuration (DSC) resources for VMware allows you to apply standard configuration management processes through PowerShell DSC and PowerCLI. DSC can manage and monitor a system\u2019s configuration based on configuration files. The image below from VMware\u2019s website provides a good overview of the layout : DSC Resources for VMware is a little different than [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":117,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"_links":{"self":[{"href":"https:\/\/bogdanburuiana.com\/index.php\/wp-json\/wp\/v2\/posts\/731"}],"collection":[{"href":"https:\/\/bogdanburuiana.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bogdanburuiana.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bogdanburuiana.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bogdanburuiana.com\/index.php\/wp-json\/wp\/v2\/comments?post=731"}],"version-history":[{"count":16,"href":"https:\/\/bogdanburuiana.com\/index.php\/wp-json\/wp\/v2\/posts\/731\/revisions"}],"predecessor-version":[{"id":771,"href":"https:\/\/bogdanburuiana.com\/index.php\/wp-json\/wp\/v2\/posts\/731\/revisions\/771"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/bogdanburuiana.com\/index.php\/wp-json\/wp\/v2\/media\/117"}],"wp:attachment":[{"href":"https:\/\/bogdanburuiana.com\/index.php\/wp-json\/wp\/v2\/media?parent=731"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bogdanburuiana.com\/index.php\/wp-json\/wp\/v2\/categories?post=731"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bogdanburuiana.com\/index.php\/wp-json\/wp\/v2\/tags?post=731"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}