One of the returning actions that is part of a deployment workflow with vRealize Automation/vRealize Orchestrator, is registering a host in the domain naming system (DNS). If you’re a Windows only shop, deployed Windows (member) servers are most of the time automatically registered in DNS. Things can be different if you have a mixed environment (Windows + Linux) or are using a highly customized DNS zone configuration. In this situation a custom vRO workflow can be used to take care of the DNS registration. In this article I will explain how to build the vRO workflows that can be used to manage a Windows based DNS environment.
Although vRO includes the Microsoft plugin that can have some interaction with Active Directory, DNS functionality is unfortunately not included in this plugin. As an alternative we have to choose for an external command that’s called from vRO to take care of the DNS registration. Options are:
- The dnscmd command, a command line utility used for DNS management. Note that the dnscmd command is deprecated; it still works but it’s not guaranteed to be there in the future;
- Powershell DNS cmdlets, which can also take care of DNS management.
RSAT Requirements
The dnscmd command as well as the Powershell cmdlets are both included in the Remote Server Administration Tools (RSAT) for DNS, so you have install this package on the Windows host where you want to do DNS registration from. In case of a Windows deployment, you can also choose to do DNS registration from the VM that’s deployed as part of the request (using the tools mentioned earlier, assuming AD integrated DNS cannot be used), however I would recommend to centralize these actions so that they are better manageable.
How to run the commands?
We have two options to run these commands:
- Register a Powershell host in vRO and use the vRO workflow Invoke a Powershell script to run the dnscmd or Powershell cmdlet(s). This method will use WINRM to remotely execute the command on the registered Powershell host;
- Use the vRO workflow Run program in guest to run the dnscmd or Powershell cmdlet(s). In this scenario you’re leveraging VMware tools to run the command in the guest OS of the selected host, which can be the same Powershell host mentioned earlier (it’s just another way of accessing the host).
These two options both have there pros and cons:
- The Invoke a Powershell script option is a little bit more difficult to setup, especially if you haven’t registered a Powershell host in your environment yet (check Marco’s post on this here). On top of these you will face some of the challenges WINRM brings, especially with credential delegation, more on this later. A big advantage of using the Invoke a Powershell script vRO workflow option is that you get detailed output the command/cmdlet execution.
- The second option, Run program in guest, is very easy to setup. You just need a virtual machine that has VMware tools, and you have to register the vCenter Server in vRO that manages the virtual machine you’re going to use, otherwise you cannot use Run program in guest. The user account, most probably a service account, that’s running the command/cmdlet required local administrator privileges on the selected virtual machine. A big disadvantage is that the Run program in guest workflow is just fire and forget. This means you execute command, but you don’t know the result. If you to know what happened, you have to do some kind of check on the result of the command.
Powershell DNS cmdlets
For the rest of this article I will focus on the Powershell cmdlets because this is more future proof. Note: if you would like to work with dnscmd, I recommend to read this post by Ryan Kelly.
The Powershell cmdlets we want to use are:
- Add-DnsServerResourceRecordA for adding A and PTR records;
- Add-DnsServerResourceRecordCName for CNAME records (if required);
- Resolve-DnsName for checking if a record already exists;
- Remove-DnsServerResourceRecord for removing records.
So, let’s start with some examples here, adding an A and CNAME record with the corresponding PTR record will look like:
Add-DnsServerResourceRecordA -ComputerName dc01.viktorious.local -ZoneName viktorious.local -name vm01 -IPv4Address 192.168.1.1 -CreatePtr; Add-DnsServerResourceRecordCName -ComputerName dc01.viktorious.local -ZoneName viktorious.local -name alias -HostNameAlias vm01.viktorious.local;
The -CreatePtr will automatically create the PTR record for the A you’ve just created. You can check availability of the A & PTR record with:
Resolve-DnsName -Name vm01.viktorious.local -Type A -Server dc01.viktorious.local | Format-List -Property IPAddress; Resolve-DnsName 192.168.1.1 -Server vm01.viktorious.local | Format-List -Property NameHost
The formatting and the end if these commands is done to use results in vRO (more on this later).
In the disposing workflow you probably want to remove the A, CNAME and PTR record, using:
Remove-DnsServerResourceRecord -ComputerName dc01.viktorious.local -ZoneName viktorious.local -Name alias -RecordData vm01.viktorious.local -RRType CNAME -Force Remove-DnsServerResourceRecord -ComputerName dc01.viktorious.local -ZoneName viktorious.local -Name vm01 -RecordData 192.168.1.1 -RRType A -Force
Notice that removing the A record will automatically remove the PTR record from your DNS server as well. In these Powershell commands I’ve included some extra information on the contents of the DNS record (the RecordData option) to verify that the correct DNS record is removed.
How to execute these commands in vRO
The next step is to execute these commands in vRO. As you know by now you have two options for this, using the Invoke a Powershell script and Run program in guest workflows. The most elegant way is to always use Invoke a Powershell script, but with Add and Remove cmdlets you will face an extra challenge called credential delegation or multi-hop support. This works as follows: you run the vRO workflow containing the Add/Remove command on the vRO host. vRO is using WINRM to executed the command on the Powershell host (the first hop), but the command itself is executed against your domain controller (the second hop). This is not possible and will result in an error. To solve this issue you have four options:
- Create a CimSession;
- Create a PSSession;
- Configure CredSSP, which can be quite a hassle and is not covered here. More information on CredSSP in combination with Powershell is available here;
- Don’t use Invoke a Powershell script but go for Run program in guest instead.
Creating a CimSession or a PSSession is quite similar:
$passwd = ConvertTo-SecureString “PlainTextPassword” -AsPlainText -Force $cred = New-Object System.Management.Automation.PSCredential (“viktorious.local\svc-vro”, $secpasswd) $session = New-CimSession -ComputerName "dc01.viktorious.local" -Credential $cred -Authentication Negotiate Add-DnsServerResourceRecordA -CimSession $session -ComputerName dc01.viktorious.local -ZoneName viktorious.local -name vm01 -IPv4Address 192.168.1.1 -CreatePtr $session | Remove-CimSession
Or as a Powershell session:
$passwd = ConvertTo-SecureString “PlainTextPassword” -AsPlainText -Force $cred = New-Object System.Management.Automation.PSCredential (“viktorious.local\svc-vro”, $secpasswd) $session = New-PsSession -ComputerName "dc01.viktorious.local" -Credential $cred Invoke-Command -Session $session -ScriptBlock {Add-DnsServerResourceRecordA -ComputerName dc01.viktorious.local -ZoneName viktorious.local -name vm01 -IPv4Address 192.168.1.1 -CreatePtr} Remove-PSSession -Session $session
Remember that both options require WinRM to be available on the Powershell host, the one vRO is accessing, as well as the second target host, in this case dc01.viktorious.local. You can check the availability of WINRM with the winrm quickconfig command:
winrm quickconfig WinRM service is already running on this machine. WinRM is already set up for remote management on this computer.
You can check the winrm config using winrm get winrm/config (use an elevated cmd box).
If this is not something you want, because you’re dealing with a domain controller there is alternative: use the Run program in guest vRO workflow. Let’s have a look at this option.
When using Run program in guest to execute Powershell scripts, you have a different approach to run the Powershell script. Run program in guest has the following input parameters:
- username – The user that’s execution the command;
- password – The password of the user;
- program – The executable to run, in this case the Powershell executable, located at c:\windows\system32\windows powershell\v1.0\powershell.exe
- arguments – Your powershell script.
So this will look like:
You can leave Working directory and Environment empty in this workflow. If you want to pass on a multiline Powershell script, put “;” and/or “\n” (new line) between your Powershell commands.
As stated before, the disadvantage of Run program in guest is that is a-synchronous, so just fire and forget. If we want to know if the command successfully completed (and we do want to know this), we have to do some kind of check. The check in this case is to test if the record is successfully created in DNS.
Check DNS record creation
For checking the creation of the DNS records we use the Resolve-DnsName cmdlet. The commands are:
Resolve-DnsName -Name vm01.viktorious.local -Type A -Server dc01.viktorious.local | Format-List -Property IPAddress; Resolve-DnsName 192.168.1.1 -Server vm01.viktorious.local | Format-List -Property NameHost
The following JavaScript how to use the cmdlet: run the cmdlet against a Powershell, interpreter the result and do something useful with it: in this case print a message based on the result of the cmdlet:
var hostName = "vm01.viktorious.local"; //host to check var ipAddress = "192.168.1.1"; //IP address to verify var output, session, result, resolvedIpAddress, errors; //The powershellscript (dc01.viktorious.local is the AD domain controller): var psScript = "Resolve-DnsName -Name " + hostName + " -Type A -Server dc01.viktorious.local | Format-List -Property IPAddress;" try { //Open powershell session, invoke the script in psScript session = host.openSession(); output = session.invokeScript (psScript); } catch (err) { //Unexpected error System.log ("Error in try: " + err); } finally { if (output.getInvocationState() == "Completed") { //Succesful Powershell execution, command returns something like IPAddress: w.x.y.z. resolvedIpAddress = output.getHostOutput().split(":")[1]; if (resolvedIpAddress == ipAddress) System.log ("IP address of " + hostName + " is " + ipAddress); else System.log ("IP address of " + hostName + " is not " + ipAddress + " but " + resolvedIpAddress); } else { //An error in powershell execution occured. System.log ("DNS record not available, or other error in Powershell execution occured"); System.log ("Additional details on error: " + output.getErrors()); } //Close powershell session if (session) host.closeSession(session.getSessionId()); }
Note that the host variable is the Powershell host vRO connects to, and thus of the type PowerShell:PowerShellHost.
Final thoughts
I hope this article helps you in challenges you might face when working with DNS in a vRA/vRO working. Feel free to leave any questions, comments or improvements below in the comment box. Hope this was helpful!
3 Comments
vikrant
Great article, I have really enjoyed your article. It is really helpful. exactly the same challenges I was facing and I am looking for the solution and now my search is over here . you have cleared my all the doubts in this article. The way you explained each and everything is really great. Thanks for sharing.
richard
good stuff
Ruan
Nice Article. Is it possible to do the DNS registration thru an ABX Script invRA 8.1?