{"id":474,"date":"2014-10-27T00:01:00","date_gmt":"2014-10-27T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2014\/10\/27\/automatedlab-tutorial-part-2-create-a-simple-lab\/"},"modified":"2022-06-22T08:55:01","modified_gmt":"2022-06-22T15:55:01","slug":"automatedlab-tutorial-part-2-create-a-simple-lab","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/automatedlab-tutorial-part-2-create-a-simple-lab\/","title":{"rendered":"AutomatedLab Tutorial Part 2: Create a Simple Lab"},"content":{"rendered":"<p><b style=\"font-size:12px\">Summary<\/b><span style=\"font-size:12px\">: Learn how to create a small lab environment by using AutomatedLab.<\/span><\/p>\n<p align=\"left\">\n  Microsoft Scripting Guy, Ed Wilson, is here. Today we have Part 2 of the series by Microsoft PFEs, Raimund Andree and Per Pedersen. Today they talk about installing the Windows PowerShell modules to use with AutomatedLab, and the steps required to create a simple lab. If you follow along, you will have AutomatedLab installed on your Hyper-V host and a lab set up with two machines.\n<\/p>\n<p style=\"margin-left:30px\">\n  <b>Note<\/b>\u00a0\u00a0Before you read this post, you might benefit from reading <a href=\"https:\/\/devblogs.microsoft.com\/scripting\/automatedlab-tutorial-part-1-introduction-to-automatedlab\/\" target=\"_blank\" rel=\"noopener\">AutomatedLab Tutorial Part 1: Introduction to AutomatedLab<\/a>.\n<\/p>\n<h2>Installation<\/h2>\n<p>The installation of AutomatedLab is very easy. You can find the information you need on Microsoft TechNet: <a href=\"https:\/\/gallery.technet.microsoft.com\/AutomatedLab-026d81f9\">AutomateLab<\/a>. The download consists of one .msi file.<\/p>\n<p>After starting the installer (the .msi file), you will see three options: Typical, Custom, or Complete. If you have more than one logical disk (or even better, more than one physical disk), you can take advantage of it and choose the Custom setup.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-10-27-14-1.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-10-27-14-1.png\" alt=\"Image of menu\" title=\"Image of menu\" \/><\/a><\/p>\n<p>In time, the <strong>Lab Sources<\/strong> folder can grow quite large, so you might want to choose a drive other than drive C.<\/p>\n<p style=\"margin-left:30px\">\n  <b>Note\u00a0 <\/b>Feel free to change installation folders as you wish. However, to automatically import the Windows PowerShell modules that come with AutomatedLab, the modules must be installed in either the user-specific path (C:\\Users\\<user>\\Documents\\WindowsPowerShell\\Modules) or the computer-specific path (C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\Modules).<b><\/b>\n<\/p>\n<p>Assuming that you did not change the default directories, after you perform the installation, you will have seven new Windows PowerShell modules in the user-specific path for Windows PowerShell modules: C:\\Users\\<user>\\Documents\\WindowsPowerShell\\Modules.<\/p>\n<p>In your documents folder, you will find the sample scripts and the documentation. \u00a0The folder names are AutomatedLab Sample Scripts and AutomatedLab Documentation.<\/p>\n<p>An important part is the folder hierarchy of <strong>Lab Sources<\/strong>. (The purpose of this folder was explained in <a href=\"https:\/\/devblogs.microsoft.com\/scripting\/weekend-scripter-deploy-automatedlab-with-powershell-part-1\/\" target=\"_blank\" rel=\"noopener\">AutomatedLab Tutorial Part 1: Introduction to AutomatedLab<\/a>.)<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-10-27-14-2.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-10-27-14-2.png\" alt=\"Image of menu\" title=\"Image of menu\" \/><\/a><\/p>\n<p>Installation done.<\/p>\n<h2>Prerequisites for installing the first lab<\/h2>\n<p>Three requirements need to be verified, before a lab can be created:<\/p>\n<ol start=\"1\">\n<li>\n    AutomatedLab requires Hyper-V in Windows Server\u00a02012\u00a0R2 or Windows\u00a08.1\n  <\/li>\n<li>\n    The ISO files to be used during creation of the lab need to be present in \\LabSources\\ISOs.\n  <\/li>\n<li>\n    Windows PowerShell remoting needs to be enabled on the host machine.\n  <\/li>\n<\/ol>\n<p>The first thing to do is to acquire ISO files for Windows Server\u00a02012\u00a0R2 and Windows\u00a08.1. The ISO files must provide a Standard or Datacenter version of Windows Server\u00a02012\u00a0R2 and a Professional or Enterprise version of Windows\u00a08.1.<\/p>\n<p>If you want to know which operating system versions your ISO files contain, use the following command:<\/p>\n<p style=\"margin-left:30px\">\n  Get-LabAvailableOperatingSystems -Path <path><\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-10-27-14-3.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-10-27-14-3.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Enable Windows PowerShell remoting on the host computer (described in the previous post). This is required, and it has to be done only once.<\/p>\n<p>Open an elevated command prompt in Windows PowerShell and type the command <strong>Set-LabHostRemoting<\/strong>.\u00a0<span style=\"font-size:12px\">The output looks like this:<\/span><\/p>\n<p style=\"margin-left:30px\">\n  VERBOSE: starting log\n<\/p>\n<p style=\"margin-left:30px\">\n  VERBOSE: Set-LabHostRemoting Entering&#8230; )\n<\/p>\n<p style=\"margin-left:30px\">\n  VERBOSE: Remoting is enabled on the host machine\n<\/p>\n<p style=\"margin-left:30px\">\n  WARNING: TrustedHosts does not include &#8216;*&#8217;. Replacing the currernt value &#8221; with &#8216;*&#8217;\n<\/p>\n<p style=\"margin-left:30px\">\n  VERBOSE: Local policy &#8216;Computer Configuration -> Administrative Templates -> System -> Credentials Delegation -> Allow Delegating Fresh Credentials&#8217;\u00a0<span style=\"font-size:12px\">configured correctly<\/span>\n<\/p>\n<p style=\"margin-left:30px\">\n  VERBOSE: Local policy &#8216;Computer Configuration -> Administrative Templates -> System -> Credentials Delegation -> Allow Delegating Fresh Credentials&#8217;\u00a0<span style=\"font-size:12px\">configured correctly<\/span>\n<\/p>\n<p style=\"margin-left:30px\">\n  VERBOSE: Set-LabHostRemoting&#8230;leaving.\n<\/p>\n<p><strong>Note\u00a0 **Because running the command **Set-LabHostRemoting<\/strong> sets <strong>TrustedHosts<\/strong> to <strong>\u2018*\u2019<\/strong>, your host computer will now allow (any) credentials to be sent from your host computer to any other computer. This is a security risk that you need to be aware of. If you will not allow this, you will need to modify this configuration manually after running the command <strong>Set-LabHostRemoting<\/strong>.<br \/>\nTo modify trusted hosts:<\/p>\n<p style=\"margin-left:30px\">\n  1. Opening gpedit.msc, go to Computer Configuration > Administrative Templates > System > Credentials Delegation.<br \/><span style=\"font-size:12px\">2. Modify the following policies: <strong>Allow delegating fresh credentials<\/strong> and <strong>Allow delegating fresh credentials with NTLM-only server authentication<\/strong>.<br \/><\/span><span style=\"font-size:12px\">3. Change content to only allow credentials to be sent to the computers of your choice. For AutomatedLab to work, you will need to enter names for all virtual machines deployed by using AutomatedLab.<\/span>\n<\/p>\n<h2>Create the first lab<\/h2>\n<p>When the prerequisites are fulfilled, a lab can be created. Creating a lab consists of several tasks, which are described in the following sections of this post.<\/p>\n<h3>Basic metadata information<\/h3>\n<p>First you need to define the metadata information regarding where to look for data and where to store data. The files that need to be read are the files in the <strong>LabSources<\/strong> directory. You need to define information about the lab definition (to make is persist when exiting the Windows PowerShell session and restarting the host computer). Also, information about where to store the virtual machines is needed.<\/p>\n<p style=\"margin-left:30px\">\n  <b>Note\u00a0 <\/b>For performance reasons, it is a good idea to place the virtual machines on a separate (physical) drive from the operating system, and preferably this drive should be an SSD. AutomatedLab uses a parent disk for each operating system, and creates differentiating disks for each virtual machine using the parent disks as base disks. By placing the ISO files on a separate drive from the virtual machines (where the reference disks are also stored), creating the reference disks will be faster (although this task only needs to be executed once because the parent disks are never modified after they are created).<b><br \/> <\/b>Also, for performance reasons, it is highly recommended to exclude the folder of the ISO files and the folder for the virtual machines from being scanned by antivirus software (real-time scanning).<b><\/b>\n<\/p>\n<p>In the following example, <strong>Lab Sources<\/strong> (containing the ISO files) is placed on drive E (which is a mechanical drive), and he virtual machines will be created on drive D (which is an SSD):<\/p>\n<p style=\"margin-left:30px\">\n  $labSources = &#8216;E:\\LabSources&#8217; #here are the lab sources\n<\/p>\n<p style=\"margin-left:30px\">\n  $vmDrive = &#8216;D:&#8217; #this is the drive where to create the VMs\n<\/p>\n<p style=\"margin-left:30px\">\n  $labName = &#8216;FirstLab&#8217; #the name of the lab, virtual machine folder and network switch\n<\/p>\n<p style=\"margin-left:30px\">\n  #create the folder path for the lab using Join-Path\n<\/p>\n<p style=\"margin-left:30px\">\n  $labPath = Join-Path -Path $vmDrive -ChildPath $labName\n<\/p>\n<p style=\"margin-left:30px\">\n  #create the target directory if it does not exist\n<\/p>\n<p style=\"margin-left:30px\">\n  if (-not (Test-Path $labPath)) { New-Item $labPath -ItemType Directory | Out-Null }\n<\/p>\n<h3>Define the lab<\/h3>\n<p>A lab definition is a set of data that contains information about the lab environment, such as the lab name, network adapter, the domains, and the configuration of the machines (for example, name, number of CPUs, amount of memory, machine roles). This definition is created by calling <strong>New-LabDefinition<\/strong>.<\/p>\n<p>The following command will create a new lab definition:<\/p>\n<p style=\"margin-left:30px\">\n  New-LabDefinition -Path $labPath -VmPath $labPath -Name $labName -ReferenceDiskSizeInGB 60\n<\/p>\n<h3>Define the network<\/h3>\n<p>All virtual machines in the lab need to have a network adapter. This network adapter is connected to a Hyper-V virtual switch. This Hyper-V virtual switch needs to be created for the lab. By default, this Hyper-V virtual switch will be created as an internal switch, providing the host computer network access to the virtual machines and vice versa. However, the virtual machines cannot connect to your physical network or vice versa. Here, for simplicity, the network name will be the same as the lab name:<\/p>\n<p style=\"margin-left:30px\">\n  #define the network\n<\/p>\n<p style=\"margin-left:30px\">\n  Add-LabVirtualNetworkDefinition -Name $labNetworkName -IpAddress 192.168.81.1 -PrefixLength 24\n<\/p>\n<p>In this scenario, the lab is going to use IP addresses in the subnet 192.168.81.x, which has the subnet mask 255.255.255.0. Possible IP addresses are 192.168.81.1-192.168.81.255<\/p>\n<p style=\"margin-left:30px\">\n  <b>Note\u00a0 <\/b>The IP address 192.168.81.1 will automatically be used as the IP address of the Hyper-V virtual switch that is seen from the host operating system. Therefore, this IP address cannot be used for virtual machines in the lab.<b><\/b>\n<\/p>\n<h3>Define domains<\/h3>\n<p>If you want to create only standalone machines (machines in a workgroup), no domain is required. However, in this lab, there will be one domain with one domain controller and one member server. As such, a domain needs to be defined for the lab.<\/p>\n<p>This domain definition will include the domain name, the administrator, and the password of the administrator. This account is used for all domain-related tasks such as the domain controller promotion, setting the DSRM\/DSREPAIR password, and joining machines to the domain.<\/p>\n<p style=\"margin-left:30px\">\n  #domain definition with the domain administrator account\n<\/p>\n<p style=\"margin-left:30px\">\n  Add-LabDomainDefinition -Name test1.net -AdminUser administrator -AdminPassword Password1\n<\/p>\n<h3>Add ISOs to the lab<\/h3>\n<p>All required ISO files for software (operating systems, server applications, and client applications) to be used in the lab need to be defined for AutomatedLab to find it. If you add an operating system ISO, you need to mark it with the <strong>IsOperatingSystem<\/strong> switch. The <strong>Name<\/strong> parameter is used only to uniquely identify the ISO definition, and it is not used elsewhere. The name is your choice, but it has to be unique in the lab.<\/p>\n<p style=\"margin-left:30px\">\n  #these images are used to install the machines\n<\/p>\n<p style=\"margin-left:30px\">\n  Add-LabIsoImageDefinition -Name Server2012R2 -Path $labSources\\ISOs\\ en_windows_server_2012_r2_with_update_x64_dvd_4065220.iso\n<\/p>\n<p style=\"margin-left:30px\">\n  \u2013IsOperatingSystem\n<\/p>\n<h3>Choose credentials to be used to connect to machines<\/h3>\n<p>For the initial setup of each virtual machine, a user name and password is needed to define the user name and password of the local administrator. This information is stored in a file named <strong>unattended.xml<\/strong>. This file is then used to perform the initial set up for each virtual machine.<\/p>\n<p>**Disclaimer\u00a0 **Creating a PSCredential object by using a plain text password is absolutely not a best practice for any production environment. However, because this lab environment will not be a production environment, a plain text password will be used.****<\/p>\n<p style=\"margin-left:30px\">\n  #these credentials are used for connecting to the machines. As this is a test lab we use clear-text passwords\n<\/p>\n<p style=\"margin-left:30px\">\n  $installationCredential = New-Object PSCredential(&#8216;Administrator&#8217;, (&#8216;Password1&#8217; | ConvertTo-SecureString -AsPlainText -Force))\n<\/p>\n<h3>Define roles<\/h3>\n<p>Using roles in AutomatedLab will be the easiest way to customize a machine and set it up as required. In version 2.1.0, AutomatedLab supports the following roles:<span style=\"font-size:12px\">\u00a0<\/span><\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"319\" valign=\"top\">\n<p>\n          RootDC\n        <\/p>\n<\/td>\n<td width=\"319\" valign=\"top\">\n<p>\n          Root domain controller for a domain\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"319\" valign=\"top\">\n<p>\n          FirstChildDC\n        <\/p>\n<\/td>\n<td width=\"319\" valign=\"top\">\n<p>\n          First child domain controller for a domain\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"319\" valign=\"top\">\n<p>\n          DC\n        <\/p>\n<\/td>\n<td width=\"319\" valign=\"top\">\n<p>\n          Additional domain controller for a domain\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"319\" valign=\"top\">\n<p>\n          DHCP\n        <\/p>\n<\/td>\n<td width=\"319\" valign=\"top\">\n<p>\n          DHCP server role\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"319\" valign=\"top\">\n<p>\n          FileServer\n        <\/p>\n<\/td>\n<td width=\"319\" valign=\"top\">\n<p>\n          File Server role\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"319\" valign=\"top\">\n<p>\n          WebServer\n        <\/p>\n<\/td>\n<td width=\"319\" valign=\"top\">\n<p>\n          Web Server role (all web role services)\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"319\" valign=\"top\">\n<p>\n          SQLServer2012\n        <\/p>\n<\/td>\n<td width=\"319\" valign=\"top\">\n<p>\n          SQL Server 2012 with default instance\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"319\" valign=\"top\">\n<p>\n          Exchange2013\n        <\/p>\n<\/td>\n<td width=\"319\" valign=\"top\">\n<p>\n          Exchange Server 2013\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"319\" valign=\"top\">\n<p>\n          Orchestrator\n        <\/p>\n<\/td>\n<td width=\"319\" valign=\"top\">\n<p>\n          System Center Orchestrator 2012\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"319\" valign=\"top\">\n<p>\n          CaRoot\n        <\/p>\n<\/td>\n<td width=\"319\" valign=\"top\">\n<p>\n          Enterprise or standalone Root Certificate Authority <br \/> (Windows Server\u00a02012 or Windows Server\u00a02012\u00a0R2)\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"319\" valign=\"top\">\n<p>\n          CaSubordinate\n        <\/p>\n<\/td>\n<td width=\"319\" valign=\"top\">\n<p>\n          Enterprise or standalone subordinate certification authority<br \/> (Windows Server\u00a02012 or Windows Server\u00a02012\u00a0R2)\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"319\" valign=\"top\">\n<p>\n          Office2013\n        <\/p>\n<\/td>\n<td width=\"319\" valign=\"top\">\n<p>\n          Microsoft Office 2013\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"319\" valign=\"top\">\n<p>\n          DevTools\n        <\/p>\n<\/td>\n<td width=\"319\" valign=\"top\">\n<p>\n          Visual Studio 2013 and Visual Studio 2012\n        <\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In this lab, only a single role will be used: the <strong>RootDC<\/strong> role. The lab will contain a domain, so a new Active Directory forest is required\u2014and this, of course, requires a root domain controller. A requirement for defining a root domain controller is to provide the <strong>ForestFunctionalLevel<\/strong> and the <strong>DomainFunctionalLevel<\/strong>.<\/p>\n<p>This information is specified by using a <strong>Properties<\/strong> parameter, which is a hash table. There is no documentation yet for this part, so this is a good opportunity to make mistakes. However, avoiding mistakes in regards to this parameter is not crucial because all the lab definitions will be validated by AutomatedLab before the installation is actually started.<\/p>\n<p>In our case, the validation component makes sure that the <strong>ForestFunctionalLevel<\/strong> and <strong>DomainFunctionalLevel<\/strong> parameters are defined, and that they are not higher than the version of the operating system of the machine.<\/p>\n<p>The cmdlet <strong>Get-LabMachineRoleDefinition<\/strong> has a <strong>role<\/strong> parameter and a <strong>properties<\/strong> parameter. Although the <strong>properties<\/strong> parameter is not mandatory for some roles, it is mandatory for domain controllers. Calling <strong>Get-LabMachineRoleDefinition<\/strong> returns a role object. This role object is later used when defining a lab machine.<\/p>\n<p style=\"margin-left:30px\">\n  $role = Get-LabMachineRoleDefinition -Role RootDC -Properties @{ DomainFunctionalLevel = &#8216;Win2012R2&#8217;; ForestFunctionalLevel = &#8216;Win2012R2&#8217; }\n<\/p>\n<h3>Define a lab machine<\/h3>\n<p>The first lab machine is defined by using the cmdlet <strong>Add-LabMachineDefinition<\/strong>. Here, the name of machine is provided in addition to basic information such as number of CPUs, memory, and IP configuration.<\/p>\n<p>Furthermore, it can be specified that the machine is to be domain-joined, will be in the domain <strong>test1.net<\/strong>, and that the machine should have the root domain controller role (defined in the previous step). This effectively results in defining that we want a root domain controller in the forest <strong>test1.net<\/strong>.<\/p>\n<p>Next, you need to provide the installation credentials. These credentials will be required to connect to the machine later for doing administrative tasks.<\/p>\n<p>The <strong>ToolsPath<\/strong> parameter is optional, and it points to a folder of your choice on the host. If you use this parameter, AutomatedLab will copy the contents of this folder to all of the virtual machines in the lab, prior to starting them. This is an effective way of copying the tools and utilities of your choice to all of the virtual machines in the lab.<\/p>\n<p>Finally, the operating system needs to be defined. This parameter is restricted to a number of supported operating systems. IntelliSense in Windows PowerShell helps you finding the desired value. Make sure to provide the value in quotation marks (after IntelliSense) because the operating system names contain white spaces.<\/p>\n<p style=\"margin-left:30px\">\n  Add-LabMachineDefinition -Name S1DC1 `\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -MemoryInMb 512 `\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -Network $labNetworkName `\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -IpAddress 192.168.81.10 `\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -DnsServer1 192.168.81.10 `\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -DomainName test1.net `\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -IsDomainJoined `\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -Roles $role `\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -InstallationUserCredential $installationCredential `\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -ToolsPath $labSources\\Tools `\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -OperatingSystem &#8216;Windows Server 2012 R2 SERVERDATACENTER&#8217;\n<\/p>\n<p>The first machine is now defined.<\/p>\n<p>To add a second machine to the lab, merely a copy and paste the previous command. Only the name and the IP address are different. In addition, this virtual machine will not be associated with any role. If no role is defined, the virtual machine will simply be a member of the domain.<\/p>\n<p style=\"margin-left:30px\">\n  Add-LabMachineDefinition -Name S1Server1 `\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -MemoryInMb 512 `\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -Network $labNetworkName `\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -IpAddress 192.168.81.20 `\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -DnsServer1 192.168.81.10 `\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -DomainName test1.net `\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -IsDomainJoined\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -InstallationUserCredential $installationCredential `\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -ToolsPath $labSources\\Tools `\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 -OperatingSystem &#8216;Windows Server 2012 R2 SERVERDATACENTER&#8217;\n<\/p>\n<h3>Export the lab<\/h3>\n<p>After configuring all the lab definitions, you can export the lab configuration by using the <strong>Export-LabDefinition<\/strong> cmdlet. This cmdlet creates two XML files in the directory \u2018D:\\FirstLab\u2019. These files contain the configuration of the lab, which makes them persistent.<\/p>\n<p style=\"margin-left:30px\">\n  Export-LabDefinition -ExportDefaultUnattendedXml \u2013Force\n<\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/3175.4.PNG\"><img decoding=\"async\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/3175.4.PNG\" alt=\"Image of file names\" title=\"Image of file names\" \/><\/a><\/p>\n<p>The <strong>Force<\/strong> switch overwrites existing files without asking for permission.<\/p>\n<h3>Install the first lab<\/h3>\n<p>After you have configured all the lab definitions and the configuration has been saved to disk, the lab can be installed. This is done by using the <strong>Install-Lab<\/strong> cmdlet. By using different switches, you can activate different tasks to be performed by <strong><em>Install-Lab<\/em><\/strong>. The following table lists the switches that are currently available.<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"170\" valign=\"top\">\n<p>\n          <b>Switch<\/b>\n        <\/p>\n<\/td>\n<td width=\"434\" valign=\"top\">\n<p>\n          <b>Task<\/b>\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"170\" valign=\"top\">\n<p>\n          NetworkSwitches\n        <\/p>\n<\/td>\n<td width=\"434\" valign=\"top\">\n<p>\n          Creates the virtual switch\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"170\" valign=\"top\">\n<p>\n          BaseImages\n        <\/p>\n<\/td>\n<td width=\"434\" valign=\"top\">\n<p>\n          Creates all parent disks\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"170\" valign=\"top\">\n<p>\n          VMs\n        <\/p>\n<\/td>\n<td width=\"434\" valign=\"top\">\n<p>\n          Creates and configures all the Hyper-V virtual machines\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"170\" valign=\"top\">\n<p>\n          Domains\n        <\/p>\n<\/td>\n<td width=\"434\" valign=\"top\">\n<p>\n          Starts installation of all domain controllers starting with root domain controllers, then child domain controller and additional domain controllers\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"170\" valign=\"top\">\n<p>\n          DHCP\n        <\/p>\n<\/td>\n<td width=\"434\" valign=\"top\">\n<p>\n          Installs DHCP role on machines where this role is specified\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"170\" valign=\"top\">\n<p>\n          CA\n        <\/p>\n<\/td>\n<td width=\"434\" valign=\"top\">\n<p>\n          Installs the Certificate Authority roles if specified\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"170\" valign=\"top\">\n<p>\n          PostInstallations\n        <\/p>\n<\/td>\n<td width=\"434\" valign=\"top\">\n<p>\n          Starts on post installation actions\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"170\" valign=\"top\">\n<p>\n          SQLServer2012\n        <\/p>\n<\/td>\n<td width=\"434\" valign=\"top\">\n<p>\n          Installs SQL server on machines where this role is specified\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"170\" valign=\"top\">\n<p>\n          Orchestrator\n        <\/p>\n<\/td>\n<td width=\"434\" valign=\"top\">\n<p>\n          Installs SC Orchestrator on machines where this role is specified\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"170\" valign=\"top\">\n<p>\n          WebServers\n        <\/p>\n<\/td>\n<td width=\"434\" valign=\"top\">\n<p>\n          Installs Web server role on machines where this role is specified\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"170\" valign=\"top\">\n<p>\n          Exchange2013\n        <\/p>\n<\/td>\n<td width=\"434\" valign=\"top\">\n<p>\n          Installs Exchange Server on machines where this role is specified\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"170\" valign=\"top\">\n<p>\n          DevTools\n        <\/p>\n<\/td>\n<td width=\"434\" valign=\"top\">\n<p>\n          Installs DevTools (Visual Studio) on machines where this role is specified\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"170\" valign=\"top\">\n<p>\n          Office2013\n        <\/p>\n<\/td>\n<td width=\"434\" valign=\"top\">\n<p>\n          Installs Office 2013 where this role is specified\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"170\" valign=\"top\">\n<p>\n          StartRemainingMachines\n        <\/p>\n<\/td>\n<td width=\"434\" valign=\"top\">\n<p>\n          Starts all remaining machines (the machines which has not yet been started)\n        <\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Call Install-Lab<\/h3>\n<p>The current lab contains only a domain controller and a member machine, so the following parameters for <strong>Install-Lab<\/strong> are needed:<\/p>\n<ul>\n<li><strong>NetworkSwitches<\/strong><br \/>\nThis creates the virtual switch. By default, the virtual switch is an internal switch, so the virtual machines cannot connect to any network resources outside of the lab and the host.<\/li>\n<li><strong>BaseImages<\/strong><br \/>\nAutomatedLab creates one base image for every operating system. All virtual machines use these disks as parent disks.<\/li>\n<li><strong>VMs<\/strong><br \/>\nThis creates and configures each virtual machine using differencing disks.<\/li>\n<li><strong>Domains<\/strong><br \/>\nThis installs all domain controllers. In one lab, it is possible to create multiple forests, multiple child domains, or domain trees, and use both RODCs and RWDCs. This task installs all specific roles for the domain controller.<\/li>\n<li><strong>StartRemainingMachines<\/strong><br \/>\nAll machines defined in the lab that have not been started will be started in this task. This task is important because starting the machines triggers the unattended installation based in the XML files that AutomatedLab created for you. This <strong>unattended.xml<\/strong> file contains configuration for each machine, such as computer name, IP address, locale, and domain.<\/li>\n<\/ul>\n<p>In the following example, <strong>Install-Lab<\/strong> is called three times to separate the process. However, you can start all tasks in a single call by using all the required switch parameters.<\/p>\n<p style=\"margin-left:30px\">\n  Install-Lab -NetworkSwitches -BaseImages -VMs\n<\/p>\n<p style=\"margin-left:30px\">\n  #This sets up all domains \/ domain controllers\n<\/p>\n<p style=\"margin-left:30px\">\n  Install-Lab -Domains\n<\/p>\n<p style=\"margin-left:30px\">\n  #Start all machines which have not yet been started\n<\/p>\n<p style=\"margin-left:30px\">\n  Install-Lab -StartRemainingMachines\n<\/p>\n<p>These tasks will take a considerable amount of time, depending on the speed of you disks. When the tasks are complete, the lab is ready to use. Congratulations!<\/p>\n<h3>Remove a lab<\/h3>\n<p>Removing the small lab described in this post is quite easy. However, if a lab of 10+ machines needs to be removed, the task becomes tedious. AutomatedLab also contains a cmdlet that can help clean up all the machines used in a lab.<\/p>\n<p>The <strong>Remove-Lab<\/strong> cmdlet first removes all the virtual machines used in a lab, then the disks, and finally the network adapter. This enables you to sequentially perform lab installations first, then perform tests in the lab, remove the lab, install a new lab, perform tests, and so on.<\/p>\n<p>Of course, checkpoints that enable you to revert are also available. One of the later blog posts in this series will show how you can take advantage of this functionality.<\/p>\n<h2>The full script<\/h2>\n<p>This is how the full script should look like after putting all the pieces together:<\/p>\n<p style=\"margin-left:30px\">\n  $start = Get-Date\n<\/p>\n<p style=\"margin-left:30px\">\n  $labSources = &#8216;E:\\LabSources&#8217; #here are the lab sources\n<\/p>\n<p style=\"margin-left:30px\">\n  $vmDrive = &#8216;D:&#8217; #this is the drive where to create the virtual machines\n<\/p>\n<p style=\"margin-left:30px\">\n  $labName = &#8216;FirstLab&#8217; #the name of the lab, virtual machine folder and network Switch\n<\/p>\n<p style=\"margin-left:30px\">\n  #create the folder path for the lab using Join-Path\n<\/p>\n<p style=\"margin-left:30px\">\n  $labPath = Join-Path -Path $vmDrive -ChildPath $labName\n<\/p>\n<p style=\"margin-left:30px\">\n  #create the target directory if it does not exist\n<\/p>\n<p style=\"margin-left:30px\">\n  if (-not (Test-Path $labPath)) { New-Item $labPath -ItemType Directory | Out-Null }\n<\/p>\n<p style=\"margin-left:30px\">\n  New-LabDefinition -Path $labPath -VmPath $labPath -Name $labName -ReferenceDiskSizeInGB 60\n<\/p>\n<p style=\"margin-left:30px\">\n  Add-LabVirtualNetworkDefinition -Name $labName -IpAddress 192.168.81.1 -PrefixLength 24\n<\/p>\n<p style=\"margin-left:30px\">\n  Add-LabDomainDefinition -Name test1.net -AdminUser administrator -AdminPassword Password1\n<\/p>\n<p style=\"margin-left:30px\">\n  Add-LabIsoImageDefinition -Name Server2012R2 -Path $labSources\\ISOs\\en_windows_server_2012_r2_with_update_x64_dvd_4065220.iso \u2013IsOperatingSystem\n<\/p>\n<p style=\"margin-left:30px\">\n  $installationCredential = New-Object PSCredential(&#8216;Administrator&#8217;, (&#8216;Password1&#8217; | ConvertTo-SecureString -AsPlainText -Force))\n<\/p>\n<p style=\"margin-left:30px\">\n  $role = Get-LabMachineRoleDefinition -Role RootDC -Properties @{ DomainFunctionalLevel = &#8216;Win2012R2&#8217;; ForestFunctionalLevel = &#8216;Win2012R2&#8217; }\n<\/p>\n<p style=\"margin-left:30px\">\n  Add-LabMachineDefinition -Name S1DC1 `\n<\/p>\n<p style=\"margin-left:30px\">\n  -MemoryInMb 512 `\n<\/p>\n<p style=\"margin-left:30px\">\n  -Network $labName `\n<\/p>\n<p style=\"margin-left:30px\">\n  -IpAddress 192.168.81.10 `\n<\/p>\n<p style=\"margin-left:30px\">\n  -DnsServer1 192.168.81.10 `\n<\/p>\n<p style=\"margin-left:30px\">\n  -DomainName test1.net `\n<\/p>\n<p style=\"margin-left:30px\">\n  -IsDomainJoined `\n<\/p>\n<p style=\"margin-left:30px\">\n  -Roles $role `\n<\/p>\n<p style=\"margin-left:30px\">\n  -InstallationUserCredential $installationCredential `\n<\/p>\n<p style=\"margin-left:30px\">\n  -ToolsPath $labSources\\Tools `\n<\/p>\n<p style=\"margin-left:30px\">\n  -OperatingSystem &#8216;Windows Server 2012 R2 SERVERDATACENTER&#8217;\n<\/p>\n<p style=\"margin-left:30px\">\n  Add-LabMachineDefinition -Name S1Server1 `\n<\/p>\n<p style=\"margin-left:30px\">\n  -MemoryInMb 512 `\n<\/p>\n<p style=\"margin-left:30px\">\n  -Network $labName `\n<\/p>\n<p style=\"margin-left:30px\">\n  -IpAddress 192.168.81.20 `\n<\/p>\n<p style=\"margin-left:30px\">\n  -DnsServer1 192.168.81.10 `\n<\/p>\n<p style=\"margin-left:30px\">\n  -DomainName test1.net `\n<\/p>\n<p style=\"margin-left:30px\">\n  -IsDomainJoined `\n<\/p>\n<p style=\"margin-left:30px\">\n  -InstallationUserCredential $installationCredential `\n<\/p>\n<p style=\"margin-left:30px\">\n  -ToolsPath $labSources\\Tools `\n<\/p>\n<p style=\"margin-left:30px\">\n  -OperatingSystem &#8216;Windows Server 2012 R2 SERVERDATACENTER&#8217;\n<\/p>\n<p style=\"margin-left:30px\">\n  Export-LabDefinition \u2013Force -ExportDefaultUnattendedXml\n<\/p>\n<p style=\"margin-left:30px\">\n  Import-Lab -Path (Get-LabDefinition).LabFilePath\n<\/p>\n<p style=\"margin-left:30px\">\n  Install-Lab -NetworkSwitches -BaseImages -VMs\n<\/p>\n<p style=\"margin-left:30px\">\n  #This sets up all domains \/ domain Controllers\n<\/p>\n<p style=\"margin-left:30px\">\n  Install-Lab -Domains\n<\/p>\n<p style=\"margin-left:30px\">\n  #Start all machines which have not yet been started\n<\/p>\n<p style=\"margin-left:30px\">\n  Install-Lab -StartRemainingMachines\n<\/p>\n<p style=\"margin-left:30px\">\n  $end = Get-Date\n<\/p>\n<p style=\"margin-left:30px\">\n  Write-Host &#8220;Setting up the lab took $($end &#8211; $start)&#8221;\n<\/p>\n<h2>What\u2019s next?<\/h2>\n<p>The next post describes how checkpoints work in AutomatedLab and how to define your own post-installation activities to help you customize your lab even further.<\/p>\n<p>~Raimund and Per<\/p>\n<p>Way cool! Join us tomorrow for more goodies by Raimund and Per.<\/p>\n<p>I invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\" rel=\"noopener\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\" rel=\"noopener\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\" rel=\"noopener\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\" rel=\"noopener\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p><strong>Ed Wilson, Microsoft Scripting Guy<\/strong><span style=\"font-size:12px\">\u00a0<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Learn how to create a small lab environment by using AutomatedLab. Microsoft Scripting Guy, Ed Wilson, is here. Today we have Part 2 of the series by Microsoft PFEs, Raimund Andree and Per Pedersen. Today they talk about installing the Windows PowerShell modules to use with AutomatedLab, and the steps required to create a [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[56,543,544,3,45],"class_list":["post-474","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-guest-blogger","tag-per-pedersen","tag-raimund-andree","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Learn how to create a small lab environment by using AutomatedLab. Microsoft Scripting Guy, Ed Wilson, is here. Today we have Part 2 of the series by Microsoft PFEs, Raimund Andree and Per Pedersen. Today they talk about installing the Windows PowerShell modules to use with AutomatedLab, and the steps required to create a [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/474","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=474"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/474\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=474"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=474"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=474"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}