en-us/about_AutomatedLabBasics.help.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
TOPIC
    about_automatedlabbasics
 
SHORT DESCRIPTION
    Generic help about the basics of AutomatedLab
 
LONG DESCRIPTION
Getting started
    PLACING ISO FILES
    Of course AutomatedLab (AL) cannot install an operating system without
    actually having the bits. Hence you need to download an ISO file from MSDN,
    TechNet Evaluation Center or somewhere else. These files need to go to your
    folder "ISOs" located in the "LabSoures" folder.
    The "ISOs" folder contains only one file after the installation of AL: "_Put
    all ISO images in here.txt". I have downloaded Windows Server 2016 from the
    TechNet Evaluation Center and put the file like shown below.
    !
    ISOs
 
    TESTING THE ISO FILES
    To make sure that AL can read the file, try to get a list of available
    operating systems. Open an
    elevated
    PowerShell ISE and call the following command (make sure you point to the
    right location for the LabSources folder:
 
    powershell
    Get-LabAvailableOperatingSystem -Path E:\LabSources
 
    This returns a list of all operating system images found on the ISO file (of
    course this works also if there are a bunch of different OS ISOS in the folder).
    !
    OSList
 
    INSTALL THE FIRST LAB
    Please open an
    elevated
    PowerShell ISE and create a new empty document (CTRL+N) if not already open.
    Copy and paste the following lines into the ISE:
    *
 
    powershell
    New-LabDefinition -Name GettingStarted -DefaultVirtualizationEngine HyperV
     
    Add-LabMachineDefinition -Name FirstServer -OperatingSystem 'Windows Server 2016 SERVERSTANDARD'
     
    Install-Lab
     
    Show-LabDeploymentSummary
 
    *
    The just press the run button or hit F5 to start the deployment.
    This is what is going to happen. Many things happen automatically but can be
    customized: * AutomatedLab starts a new lab named "GettingStarted". The lab
    defininition will be stored in
    C:\ProgramData\AutomatedLab\Labs\GettingStarted. The location can be
    customized
    "Advanced AutomatedLab Configurations"
    with the setting LabAppDataRoot. * AL will update download the SysInternals
    tools and put them into the LabSources folder.
    * AL looks for an ISO file that contains the specified OS. If the ISO file
    cannot be found, the deployment stops.
    * AL adds the one and only machine to the lab and recognizes that no network
    was defined. In this case, AL creates a virtual switch automatically and
    uses an free IP range.
    * The AL measures the disk speed and chooses the fastet drive for the lab,
    as no location is defined in the call to "New-LabDefinition". In my case, it
    chooses D. Measuring is done only once and the result is cached.
    * Then the actual deployment starts. AL creates
 
    1. The virtual switch 2. Then it creates the a base image for the
    operating system that is shared among all machines with the same OS. 3.
    Afterwards the VM is created and started 4. AL waits for the machine to
    become ready and shows the overall installation time.
 
    REMOVING A LAB
    If you want to get rid of the lab, just call Remove-Lab. The cmdlet removes
    the VMs including the disks and the virtual switches, and leaves the base
    disks for the next deployment.
    If you have closed the ISE in the meantime, either specify the lab name or
    import it first.
    !
    Remove1
 
    SUMMARY
    With AutomatedLab it is extremely easy to create various kinds of labs. The
    more you define your lab by code, the easier it is to re-deploy it and the
    less time you invest in the long term.
    If you like what you have seen, take a look at the folder
    "LabSources\Sample Scripts\Introduction"
    . These scripts demo how to create domains, internet facing labs, PKI, etc.
    Please provide feedback if something does not work as expected. If you are
    missing a feature or have some great ideas, please open an
    issue
    .
 
    NEXT STEPS
    Now that you have deployed your first lab, what comes next? Would you like
    to connect to the machines and run remote commands without you knowing the
    password? Then start with
    the docs on lab management
    .
Wondering how to transfer data to your new lab? Then start with
    the docs on data exchange
    .
If you - like us - like to tinker around with things, check out the
    possible settings
    . Generally speaking AutomatedLab takes care of everything for you when
    deploying your labs on Azure. Since additional authentication is required it
    is possible that you need to login to your Azure account before using
    AutomatedLab.
 
    AutomatedLab works with Azure Resource Manager, so you can either execute
    the cmdlet `Connect-AzAccount` before deploying your lab or save your Azure
    Resource Manager profile.
    If you choose to login to your Azure account before a lab deployment your
    profile is being saved for you to be able to import the lab at a later
    stage. Since it is possible that your profile expires you might see an error
    message indicating your profile expiration. In that case, simply login to
    your Azure account again.
 
    New-LabDefinition -Name 'MyLab' -DefaultVirtualizationEngine Azure
     
    ## Optional to set e.g. your preferred location
    Add-LabAzureSubscription -DefaultLocation 'West Europe'
 
    This will enable AutomatedLab to create a lab sources resource group for you
    as well as a separate resource group for each lab you deploy. Your lab
    resource group will contain the entire lab deployment and will be removed
    when you call `Remove-Lab`. Adding machines to a lab ranges from extremely
    easy to fairly complicated. Both is achieved with one cmdlet though,
    Add-LabMachineDefinition.
 
    ## Add the root domain controller for the domain contoso.com
    ## Network, memory, ... will all be handled automatically
    Add-LabMachineDefinition -Name DC1 -Roles RootDC -OperatingSystem 'Windows Server 2019 Datacenter' -Domain contoso.com
 
    When you are using the automatic machine definitions, the memory
    requirements will be calculated based on the machines' roles.
 
    DEPLOYING A LAB WITH LINUX VMS
    With AutomatedLab Linux VMs can be deployed just as easily as Windows VMs.
    The current implementation should take care of the following distributions:
    - RHEL 7 (*)
    - CentOS 7
    - Fedora 27
    - SLES 12.3 (*)
    - OpenSuSE
    At the moment the machines do not support any of AutomatedLab's roles since
    our roles are Windows-based. However, your VMs should come up domain-joined
    and capable of receiving WinRM requests. AutomatedLab uses kickstart
    (RHEL-based) or AutoYAST (SLES-based) to configure everything that would be
    configured in the unattend file of a Windows machine.
    WinRM support is spotty with distributions like OpenSuSE and Fedora. Fedora
    being too cutting-edge does not allow PowerShell and omi-psrp-server to be
    installed, while OpenSuSE currently has the wrong package dependencies and
    fails installing PowerShell as well.
 
    SIMPLE LINUX LAB
    You can find the Linux lab here:
    AL Loves Linux
    As you can see, integrating Linux clients is very simple in general:
 
 
    Add-LabMachineDefinition -Name LINCN2 -OperatingSystem 'CentOS 7.4'
 
 
    If you want to add additional package groups to be installed during setup,
    you can do so by specifying them:
 
 
    Add-LabMachineDefinition -RhelPackage domain-client -Name LINCN1 -OperatingSystem 'CentOS 7.4' -DomainName contoso.com
 
 
    You can find all available packages with
 
    -LabAvailableOperatingSystem | Select-Object -Expand LinuxPackageGroup
 
    . However, the basics should be fine for most cases.
 
    At them moment, your Linux-based labs need an internet connection (i.e. a
    routing VM) so that the PowerShell and omi-psrp-server can be downloaded
    during setup. Without omid running on the Linux machines, your lab will run
    into a timeout during installation. While this will not break things, it
    will certainly cause a long wait.
 
    AZURE-SPECIFIC PROPERTIES
    There are several properties that can be used with the `AzureProperties`
    parameter of the `Add-LabMachineDefinition` cmdlet.
    - ResourceGroupName - Resource group this machine is deployed into, if it
    should be different
    - UseAllRoleSizes - Use a random role size of the available role sizes
    - RoleSize - Use specific role size like Standard_D2_v2
    - LoadBalancerRdpPort - Use a different port for the inbound NAT rule. Needs
    to be unique in your lab!
    - LoadBalancerWinRmHttpPort - Use a different port for the inbound NAT rule.
    Needs to be unique in your lab!
    - LoadBalancerWinRmHttpsPort - Use a different port for the inbound NAT
    rule. Needs to be unique in your lab!
    - LoadBalancerAllowedIp - A comma-separated string (NOT an array) containing
    IP addresses allowed to connect, e.g. "$(Get-PublicIpAddress), 1.2.3.4"
    - SubnetName - The subnet name this machine is deployed into
    - UseByolImage - Boolean as string indicating that BYOL licensing is used
    - AutoshutdownTime - The timespan as string when the machines shut be shut down
    - AutoshutdownTimezoneId - The time zone ID as string for the auto shutdown time
    - StorageSku - The storage SKU for additional disks. OS disks are managed
    disks. Either 'Standard_LRS', 'Premium_LRS' or 'StandardSSD_LRS'
    Creating your lab starts with New-LabDefinition. This cmdlet creates a
    container that holds all the lab items like networks and machines.
    It is mandatory to define the name of the lab and the virtualization engine.
    So far AL supports Hyper-V and Azure.
 
    powershell
    New-LabDefinition -Name $labName -DefaultVirtualizationEngine HyperV -Path D:\AutomatedLabs -VmPath D:\AutomatedLab-VMs
 
    -
    New-LabDefinition
    Parameters -
    Name
    : The name if the lab to create. The name must be unique. -
    DefaultVirtualizationEngine
    : HyperV for local deployments or Azure to deploy into the cloud. -
    Path
    : This is the path were the lab files will go (screenshot 1). If not defined
    the labs will be stored in "C:\Users<username>\Documents\AutomatedLab-Labs".
      -
    VmPath
    : This is where AL creates the virtual machines. If this path is not defined
    AL will choose the fastest drive by trying not to use the system drive and
    create a folder there names "AutomatedLab-VMs".
    During the lab deployment, AL exports your definitions into XML files. By
    default these are stored in
    'C:\Users<username>\Documents\AutomatedLab-Labs'. If you close the
    PowerShell session after the lab deployment, you can import the lab again
    using the Import-Lab cmdlet.
    !https://cloud.githubusercontent.com/assets/11280760/20555110/6f12f9a8-b160-11e6-863a-bac119eac71b.png!
    The virtual machines are stored in a different folder. AL tries to determine
    the fastest drive and uses the cmdlet Get-DiskSpeed for this. AL tries to
    avoid using the system drive. The speed test runs only once and results are
    cached. However if you plug in a new drive, AL takes it into consideration
    and measure its speed.
    !https://cloud.githubusercontent.com/assets/11280760/20642671/252e839a-b415-11e6-8c80-307f7662d64a.JPG!
    Starting with version 5.23, each lab deployment will not only be validated
    before the deployment but also when the installation is finished. To enable
    the deployment validation, you need to install Pester 5.0.1+. We did not
    mark Pester as a dependency, as these tests are optional.
 
    LAB BUILDING WITH THE REST API
    With the custom role 'LabBuilder' it is now possible to create a simple REST
    API powered by
    Polaris
    on any virtualization host. The REST API provides the following
    functionality:
 
    CREATE
    $request = @{
        LabScript = Get-Content "$labsources\Sample Scripts\Introduction\01 Single Win10 Client.ps1" -Raw
    } | ConvertTo-Json
     
    ## Queue new job, use GUID to request status update with GET method
    $guid = Invoke-RestMethod -Method Post -Uri http://NestedBuilder/Lab -Body $request -ContentType application/json
 
    READ
    ## All labs (Get-Lab -List)
    Invoke-RestMethod -Method Get -Uri http://NestedBuilder/Labs
    ## Specific lab
    Invoke-RestMethod -Method Get -Uri http://NestedBuilder/Lab?Name=Win10
    ## Lab creation job (monitoring long running jobs)
    Invoke-RestMethod -Method Get -Uri http://NestedBuilder/Lab?Id=5b89babb-7402-4a7a-9c16-86e1d52613fa
 
    DELETE
    ## As query parameter
    Invoke-RestMethod -Method Delete -Uri http://NestedBuilder/Lab?Name=Win10
     
    ## Or as JSON body
    $request = @{Name = 'Win10'} | ConvertTo-Json
    Invoke-RestMethod -Method Delete -Uri http://NestedBuilder/Lab -Body $request -ContentType application/json
 
    LAB SCENARIO INCLUDING THE BUILDER
    The following lab scenario configures a simple VM to test-drive this
    feature. Be aware that when using this on Azure your lab sources need to be
    uploaded first. Otherwise you will need to manually copy all necessary ISO
    files to your Azure VM.
 
    <#
    Build a lab with the help of nested virtualization. Adjust the machine memory if necessary.
    The build worker will use Polaris as a simple REST endpoint that takes your lab data to deploy.
     
    AutomatedLab will be copied to the machine. Lab sources will be mirrored to the machine as well, so that lab deployments can start immediately
    ##>
    param
    (
        [string]
        $LabName = 'LabAsAService',
     
        [ValidateSet('yes','no')]
        $TelemetryOptOut = 'no' # Opt out of telemetry for build worker by saying yes here
    )
     
    New-LabDefinition -Name $labName -DefaultVirtualizationEngine HyperV
    Add-LabVirtualNetworkDefinition -Name $labName -HyperVProperties @{ SwitchType = 'External'; AdapterName = 'Ethernet' }
     
    $role = Get-LabPostInstallationActivity -CustomRole LabBuilder -Properties @{TelemetryOptOut = $TelemetryOptOut}
     
    $machineParameters = @{
        Name = 'NestedBuilder'
        PostInstallationActivity = $role
        OperatingSystem = 'Windows Server 2016 Datacenter (Desktop Experience)'
        Memory = 16GB
        Network = $labName
        DiskName = 'vmDisk'
    }
     
    $estimatedSize = [Math]::Round(((Get-ChildItem $labsources -File -Recurse | Measure-Object -Property Length -Sum).Sum / 1GB + 20), 0)
    $disk = Add-LabDiskDefinition -Name vmDisk -DiskSizeInGb $estimatedSize -PassThru
     
    Add-LabMachineDefinition @machineParameters
     
    Install-Lab
 
    SUMMARY
    One basic requirement is sending files to a lab machine as well as receiving
    files. Both is supported by AutomatedLab, for files and also directory
    trees. This feature works with Hyper-V VMs as well as Azure VMs.
 
    HOW TO USE IT €" SEND
    To send a file or directory to a lab machine, only the local source path and
    the machine name is required. There is no difference whether the machine is
    on Hyper-V or Azure.
 
    Note: Copy-LabFileItem wraps the cmdlets Send-File and Send-Directory,
    both define in the PSFileTransfer module.
 
    If the target path is not defined, the file or folder will be put in C:\.
    The parameter ComputerName is an array and data can be copied to a single or
    multiple machines with a single command.
    The following command copies a file to the specified machine trying SMB
    first and falling back to WinRM.
 
    PowerShell
    Copy-LabFileItem -Path 'D:\170630 AL' -ComputerName wServer1 -DestinationFolderPath C:\Temp
 
    The following samples are Using the PSFileTransfer cmdlets directly. These
    do not support SMB and send the files over the PSSession right away. The
    Force switch creates the target folder if not already existing.
 
    Note: It is recommended to use Copy-LabFileItem as SMB is much faster
    then sending a byte array over WinRM.
 
    PowerShell
    $s = New-LabPSSession LabVM1
    Send-File -SourceFilePath D:\Untitled1.ps1 -DestinationFolderPath C:\Temp\Untitled1.ps1 -Session $s -Force
    Send-Directory -SourceFolderPath D:\Test -DestinationFolderPath C:\Windows -Session $s
 
    HOW TO USE IT €" RECEIVE
    This also works the other way around. If some process creates files on a lab
    machine that are required for another process on another lab machine, you
    can retrieve and re-send the file to another machine.
    For example, this process is used in the AutomatedLab’s certificate
    functions like Get-LabCAInstallCertificates.
 
    PowerShell
    Receive-File -SourceFilePath C:\Unattend.xml -DestinationFilePath D:\Unattend.xml -Session $s
    Receive-Directory -SourceFolderPath 'C:\Program Files\Wireshark' -DestinationFolderPath D:\Wireshark -Session $s
 
    INTERNALS
    Hyper-V machines are usually reachable from the host by SMB. However, it is
    not sure or pretty unlikely if the other way works as well, accessing the
    host machines from the VM.
    Copy-LabFileItem always tries SMB first. If this does not work, it uses the
    PowerShell session and transfers the file as a Byte[]. Reading and writing a
    file as a byte array, serializing the by byte array and sending it over the
    network is much slower than SMB but totally sufficient for most scenarios.
    If you transfer large files, make sure SMB works from the host to the VMs.
 
    Note: All the functions of the module PSFileTransfer do not rely on other modules
    of AutomatedLab and can be used separately.
 
Offline lab scenario
    To deploy complex lab scenarios offline you will at some point run into
    issues due to additional dependencies being downloaded. This article aims to
    give you all the necessary information to prepare for a fully offline
    environment.
 
    BASICS
    First of all, install AutomatedLab from the MSI installer and get some ISO
    files - like you would for an online scenario. Place your ISO files in
    LabSources\ISOs. The MSI installer contains all static files that we need
    like ProductKeys.xml, WinSAT and so on.
 
    DSC PULL SERVER
    To deploy the pull server role, we download the Access Database Engine from
    `Get-LabConfigurationItem -Name AccessDatabaseEngine2016x86` to
    LabSources/SoftwarePackages without renaming the file.
 
    OFFICE
    To deploy Office Server, the Office deployment toolkit is needed at
    LabSources/SoftwarePackages/OfficeDeploymentTool.exe. You can download the
    tool from `Get-LabConfigurationItem -Name OfficeDeploymentTool`.
 
    SHAREPOINT
    SharePoint requires a whole slew of prerequisites. First of all, you should
    download all CPP redistributables from 2012 up to 2017, 32 and 64 bit,
    following the naming pattern vcredist_BITS_YEAR e.g. vcredist_64_2012. The
    links can be easily accessed using `Get-LabConfigurationItem -Name cppredist
    `. The more descriptive version is `Get-PSFConfig -Module AutomatedLab -Name
    cppredist
    ` which shows you the version as well. All packages need to be downloaded to LabSources/SoftwarePackages
    The rest of the requirements is version-dependent. The links are best
    accessed using `Get-LabConfigurationItem -Name SharePoint2019Prerequisites`.
    Please make sure that for SharePoint 2013 the download with an URI
    containing 1CAA41C7 needs to be renamed to WcfDataServices56.exe.
 
    SQL
    SQL also requires a bunch of prerequisites. First of all, you should
    download all CPP redistributables from 2015 up to 2017, 32 and 64 bit,
    following the naming pattern vcredist_xARCHITECTURE_YEAR e.g.
    vcredist_x86_2015.exe. The links can be easily accessed using
    `Get-LabConfigurationItem -Name cppredist
    `. The more descriptive version is `Get-PSFConfig -Module AutomatedLab -Name
    cppredist
    ` which shows you the version as well. All packages need to be downloaded to LabSources/SoftwarePackages.
    Additionally, .NET 4.8 will be required on SQL 2017 and newer when reporting
    services are deployed, which can be downloaded from
    `Get-LabConfigurationItem -Name dotnet48DownloadLink`. The download should
    be stored in LabSources/SoftwarePackages.
    While not strictly required, you might want to download the following
    packages as well, thereby reducing some error messages: - SQL Server
    Reporting Services: `Get-LabConfigurationItem -Name
    Sql$($server.SqlVersion)SSRS` to `LabSources/SoftwarePackages/Sql$($server.SqlVersion)\SQLServerReportingServices.exe`
    - SQL Server Report Builder: `Get-LabConfigurationItem -Name
    SqlServerReportBuilder` to `LabSources\SoftwarePackages\ReportBuilder.msi`
    - SQL Server Management Studio: `Get-LabConfigurationItem -Name
    Sql$($server.SqlVersion)ManagementStudio` to `LabSources/SoftwarePackages/Sql$($server.SqlVersion)/SSMS-Setup-ENU.exe`
    - Sample Databases: Download the desired sample databases as .bak files to
    LabSources\SoftwarePackages\SqlSampleDbs\SqlServerXXXX. The files should be
    called as the directory, SqlServerXXXX.bak, where XXXX is the version of
    SQL.
 
    TEAM FOUNDATION SERVER AND AZURE DEVOPS
    A recent TFS/Azure DevOps agent is required which can be downloaded from
    `Get-LabConfigurationItem -Name BuildAgentUri` and needs to be stored as
    `LabSources\Tools\TfsBuildWorker.zip`.
 
Getting started
    PLACING ISO FILES
    Of course AutomatedLab (AL) cannot install an operating system without
    actually having the bits. Hence you need to download an ISO file from MSDN,
    TechNet Evaluation Center or somewhere else. These files need to go to your
    folder "ISOs" located in the "LabSoures" folder.
    The "ISOs" folder contains only one file after the installation of AL: "_Put
    all ISO images in here.txt". I have downloaded Windows Server 2016 from the
    TechNet Evaluation Center and put the file like shown below.
    !
    ISOs
 
    TESTING THE ISO FILES
    To make sure that AL can read the file, try to get a list of available
    operating systems. Open an
    elevated
    PowerShell ISE and call the following command (make sure you point to the
    right location for the LabSources folder:
 
    powershell
    Get-LabAvailableOperatingSystem -Path E:\LabSources
 
    This returns a list of all operating system images found on the ISO file (of
    course this works also if there are a bunch of different OS ISOS in the folder).
    !
    OSList
 
    INSTALL THE FIRST LAB
    Please open an
    elevated
    PowerShell ISE and create a new empty document (CTRL+N) if not already open.
    Copy and paste the following lines into the ISE:
    *
 
    powershell
    New-LabDefinition -Name GettingStarted -DefaultVirtualizationEngine HyperV
     
    Add-LabMachineDefinition -Name FirstServer -OperatingSystem 'Windows Server 2016 SERVERSTANDARD'
     
    Install-Lab
     
    Show-LabDeploymentSummary
 
    *
    The just press the run button or hit F5 to start the deployment.
    This is what is going to happen. Many things happen automatically but can be
    customized: * AutomatedLab starts a new lab named "GettingStarted". The lab
    defininition will be stored in
    C:\ProgramData\AutomatedLab\Labs\GettingStarted. The location can be
    customized
    "Advanced AutomatedLab Configurations"
    with the setting LabAppDataRoot. * AL will update download the SysInternals
    tools and put them into the LabSources folder.
    * AL looks for an ISO file that contains the specified OS. If the ISO file
    cannot be found, the deployment stops.
    * AL adds the one and only machine to the lab and recognizes that no network
    was defined. In this case, AL creates a virtual switch automatically and
    uses an free IP range.
    * The AL measures the disk speed and chooses the fastet drive for the lab,
    as no location is defined in the call to "New-LabDefinition". In my case, it
    chooses D. Measuring is done only once and the result is cached.
    * Then the actual deployment starts. AL creates
 
    1. The virtual switch 2. Then it creates the a base image for the
    operating system that is shared among all machines with the same OS. 3.
    Afterwards the VM is created and started 4. AL waits for the machine to
    become ready and shows the overall installation time.
 
    REMOVING A LAB
    If you want to get rid of the lab, just call Remove-Lab. The cmdlet removes
    the VMs including the disks and the virtual switches, and leaves the base
    disks for the next deployment.
    If you have closed the ISE in the meantime, either specify the lab name or
    import it first.
    !
    Remove1
 
    SUMMARY
    With AutomatedLab it is extremely easy to create various kinds of labs. The
    more you define your lab by code, the easier it is to re-deploy it and the
    less time you invest in the long term.
    If you like what you have seen, take a look at the folder
    "LabSources\Sample Scripts\Introduction"
    . These scripts demo how to create domains, internet facing labs, PKI, etc.
    Please provide feedback if something does not work as expected. If you are
    missing a feature or have some great ideas, please open an
    issue
    .
 
    NEXT STEPS
    Now that you have deployed your first lab, what comes next? Would you like
    to connect to the machines and run remote commands without you knowing the
    password? Then start with
    the docs on lab management
    .
Wondering how to transfer data to your new lab? Then start with
    the docs on data exchange
    .
If you - like us - like to tinker around with things, check out the
    possible settings
    .
 
Installation
    There are two options installing AutomatedLab:
- You can use the
    MSI installer
    published on GitHub. - Or you install from the
    PowerShell Gallery
    using the cmdlet Install-Module.
 
    Please note that this is the ONLY way to install AutomatedLab and its
    dependencies in PowerShell Core/PowerShell 7 on both Windows and Linux/Azure
    Cloud Shell
 
    FROM GALLERY
    Install-PackageProvider Nuget -Force
    Install-Module AutomatedLab -AllowClobber
     
    ## If you are on Linux and are not starting pwsh with sudo
    ## This needs to executed only once per user - adjust according to your needs!
    Set-PSFConfig -Module AutomatedLab -Name LabAppDataRoot -Value /home/youruser/.alConfig -PassThru | Register-PSFConfig
     
    ## Prepare sample content - modify to your needs
     
    ## Windows
    New-LabSourcesFolder -Drive C
     
    ## Linux
    Set-PSFConfig -Module AutomatedLab -Name LabSourcesLocation -Value /home/youruser/labsources -PassThru | Register-PSFConfig
    New-LabSourcesFolder # Linux
 
    FROM MSI
    AutomatedLab (AL) is a bunch of PowerShell modules. To make the installation
    process easier, it is provided as an MSI.
    Download Link: https://github.com/AutomatedLab/AutomatedLab/releases
    There are not many choices when installing AL.
    !
    Install1
    The options Typical and Complete are actually doing the same and install AL
    to the default locations. The PowerShell modules go to "C:\Program
    Files\WindowsPowerShell\Modules", the rest to "C:\LabSources".
    As LabSources can grow quite big, you should go for a custom installation
    and put this component on a disk with enough free space to store the ISO
    files. This disk does not have to be an SSD. Do not change the location of
    the modules unless you really know what you are doing.
    !
    Install2
    Very important to AL is the LabSources folder that should look like this:
!
    Install3
    If all that worked you are ready to go for
    Getting Started
    .
 
    SUMMARY
    Installing software on lab machines is almost as easy as installing <TODO
    Windows Features>. And there are similar challenges. But additionally,
    there to the challenges some installers have an extra demand, like the .net
    4.5.2 package that cannot be installed remotely. Like for installing Windows
    Features AutomatedLab tries to provide a solution that makes this task as
    simple as possible. It does not matter if the
    installation file is already on the VM or on your host machine
    . And you do not have to care whether it is a
    .exe, .msi or .msu
    file, AL will handle the complexity for you. And there is also a very
    convenient way to work
    install stuff from ISOs
    mounted to the lab VMs.
 
    INSTALL-LABSOFTWAREPACKAGE INTRODUCTION
    The cmdlet that handles the installation is Install-LabSoftwarePackage. It
    is designed to work in various scenarios that will be discussed in this
    article. Internally, it uses Invoke-LabCommand again to connect to the lab
    VMs by using the credentials known to the lab. The files are copied to the
    lab VMs using Copy-LabFileItem.
 
    INSTALL-LABSOFTWAREPACKAGE USAGE
    INSTALLING AN PACKAGE THAT IS ON THE HOST MACHINE
    A very simple demonstration of how the cmdlet can help, is installing
    Notepad++ on a lab VM. Note that $labSources always points to the LabSources
    folder that is created by AL, so you do not have to provide the full path.
    This also works on Azure. A lab VM hosted on Azure accesses the share hosted
    on Azure by default. The Azure LabSources share can be synced with the local
    one. The next command copes the Notepad++.exe file to the VM and invokes the
    installer. The package must support a silent installation. For Notepad++,
    you can switch to the silent mode by providing the argument “/S”
    (case-sensitive).
 
    PowerShell
    Install-LabSoftwarePackage -ComputerName Server1 -Path $labSources\SoftwarePackages\Notepad++.exe -CommandLine /S
 
    If you want to install the same package to all machines in a lab, regardless
    if they run on Hyper-V or Azure, just change the ComputerName parameter:
 
    PowerShell
    Install-LabSoftwarePackage -ComputerName (Get-LabVM) -Path $labSources\SoftwarePackages\Notepad++.exe -CommandLine /S
 
    INSTALLING A PACKAGE THAT IS ON THE HOST MACHINE AS SCHEDULED JOB
    Some software packages are creating headaches, like the .net Framework
    4.5.2. The package calls the Windows Update Service which checks if it is
    called from remote by checking the token for the NETWORK RID, and cancels
    the installation if that’s the case. Install-LabSoftwarePackage offers the
    switch AsScheduledJob to be able to start the installation remotely which
    then actually runs locally. The next example shows how to install .net 4.5.2
    on a VM, restart the VM and then install the Windows Management Framework
    5.1.
 
    PowerShell
    Install-LabSoftwarePackage -Path $labSources\SoftwarePackages\NDP452-KB2901907-x86-x64-AllOS-ENU.exe -CommandLine '/q /log c:\dotnet452.txt' -ComputerName Client7 -AsScheduledJob -UseShellExecute
    Restart-LabVM -ComputerName Client7 -Wait
     
    Install-LabSoftwarePackage -Path $labSources\V5\Win7AndW2K8R2-KB3134760-x64.msu -ComputerName Client7
    Restart-LabVM -ComputerName Client7 -Wait
 
    INSTALLING A PACKAGE THAT IS ALREADY ON THE VM
    Installing software packages that are already on the VM is also possible. In
    this case, you can use the LocalPath parameter instead of the Path parameter.
    The following command installs the Redgate Reflector on all machines with
    the role visual studio, expecting the package already to be at C:\. The
    AsJob switch puts the work into the background.
 
    PowerShell
    Install-LabSoftwarePackage -LocalPath C:\ReflectorInstaller.exe -CommandLine '/qn /IAgreeToTheEula' -ComputerName (Get-LabMachine -Role VisualStudio2015) -AsJob
 
    INSTALLING FILES FROM ISO FILES MOUNTED TO LAB VMS.
    The cmdlet Install-LabSoftwarePackage is even more effective when combined
    with other cmdlets AutomatedLab provides. When mounting an ISO into a VM, it
    is not guaranteed that the ISO will get always the same drive letter. If a
    lab VM has only one drive, the ISO will be pretty likely drive D:, but if
    the lab VM has more than one disk attached, things are getting more complex.
    Mount-LabIsoImage returns the drive an ISO file actually has inside the VM.
    This information can be used to construct the path to call. This is demoed
    in the next example.
 
    PowerShell
    $drive = Mount-LabIsoImage -ComputerName Web1 -IsoPath $labSources\ISOs\SkypeForBusiness2015.iso -PassThru
    Install-LabSoftwarePackage -ComputerName Web1 -LocalPath "$($drive.DriveLetter)\Setup.exe" -CommandLine /BootStrap
    Dismount-LabIsoImage -ComputerName Web1
 
    For further help and details on the available parameters please call
    Get-Help Install-LabSoftwarePackage.
 
    SUMMARY
    A quite common task in a lab is to add Windows features to one or some
    machines. This can be easily done using the cmdlet Install-WindowsFeature
    that is available since Windows Server 2008 R2. It is also quite easy to the
    cmdlet on another machine by using Install-WindowsFeature inside a
    scriptblock that you invoke on a remote machine using Invoke-Command.
    However, this requires authentication, creating the scriptblock and other
    things. The cmdlet Install-LabWindowsFeature does this all for you.
 
    INSTALLING WINDOWS FEATURES USING INSTALL-LABWINDOWSFEATURE
    Install-LabWindowsFeature uses Invoke-LabCommand that is discussed in
    <TODO>. As Invoke-LabCommand handles obstacles like name resolution and
    authentication with the standard lab account, which makes this task even
    easier. The following command installs the Remote Sever Administration tools
    (RSAT) on the machines Server1 and Server2:
 
    PowerShell
    Install-LabWindowsFeature -FeatureName RSAT -ComputerName 'server1', 'server2' -IncludeAllSubFeature
 
    It is also possible to push the activity into the background using the AsJob
    switch. You can start the installation on multiple machines and then wait
    for the jobs to complete. If AsJob is used along with PassThru,
    Install-LabWindowsFeature returns the job objects. If just PassThru is used,
    the cmdlet return the result of the feature installation.
 
    PowerShell
    $jobs = Install-LabWindowsFeature -FeatureName RSAT -ComputerName 'server1', 'server2' -IncludeAllSubFeature -AsJob -PassThru
    $result = Wait-LWLabJob -Job $jobs -ProgressIndicator 10 -NoDisplay -PassThru
 
    PowerShell offers a great way to run code on remote machines by means of the
    cmdlet Invoke-Command. This cmdlet just needs to get a script block to run
    and computer names. However, connecting to a lab machine that is not in the
    same security context requires authentication. Also, double-hop
    authentication scenarios (CredSsp) need some configuration to work. Another
    challenge is making local variables and local functions available to remote
    PowerShell sessions. In this regards AL as a framework gives you some nice
    tools that are making PowerShell Remoting even more effective. Lab
    environments usually do not share the same namespace or DNS servers. Hence
    AL comes up with its own name resolution system. It lets you connect to the
    machines with the short names regardless whether they are hosted on Hyper-V
    or Azure.
 
 
    INVOKE-LABCOMMAND
    Invoke-LabCommand is like a proxy. It works pretty similar to Invoke-Command
    but adds a lot of functionality that makes working in a lab even easier. The
    next sections are describing each of these additional features with some
    samples.
 
    NAME RESOLUTION
    AL needs to support two different ways of name resolution as it supports
    labs on the loal Hyper-V and on Windows Azure. For Hyper-V scenarios AL
    creates an entry in the LMHosts file. Connecting to Hyper-V VMs created by
    AL works with the standard naming resolution. A bit more work is done behind
    the scenes for VMs hosted on Azure. AL reads the public IP address of the
    load balancer each machine is connected to and also discovers the public
    port for WinRM. This information is added to each machine (see
    AzureConnectionInfo property) and used inside Invoke-LabCommand. Actually
    the hard work is done inside the cmdlet New-LabPSSession which also caches
    connections. The cmdlets Enter-LabPSSession and Connect-LabVM are
    implementing the AL name resolution as well. Running a command on a specific
    VM, regardless if it is hosted on Azure or Hyper-V, works like this (Without
    the PassThru switch, Invoke-LabCommand does not return any data):
 
    PowerShell
    Invoke-LabCommand -ScriptBlock { Get-Date } -ComputerName Client1 -PassThru
 
    Running a command on all lab VMs, regardless if they are hosted on Azure or
    Hyper-V, works like this:
 
    PowerShell
    Invoke-LabCommand -ScriptBlock { Get-Date } -ComputerName (Get-LabVM)
 
    MAKING LOCAL VARIABLES AND FUNCTIONS AVAILABLE REMOTELY
    If you have functions and variables defined locally, they are not available
    in the remote session. With the using scope (PowerShell 3+) you can access
    local variables in the remote session but it requires changing the code by
    adding “$using:” to each variable you want to retrieve from the local
    scope. Hence this code will no longer work locally which makes debugging
    your code locally on the VM much harder. Invoke-LabCommand provides the two
    parameters “Variable” and “Function”. All the variables and
    functions given here are pushed to the remove session making them available
    there. The following sample demonstrates this by having a local function
    that just returns the value of a local variable. Invoke-LabCommand runs the
    same code on a remote machine without changing anything. The code you may
    run locally:
 
    PowerShell
    function Foo
    {
        "The calue of '`$someVar' is $someVar"
    }
     
    $someVar = 123
    Foo
 
    To run the same code remotely
 
    PowerShell
    function Foo
    {
        "The calue of '`$someVar' is $someVar"
    }
     
    $someVar = 123
     
    Invoke-LabCommand -ComputerName Client1 -ScriptBlock { Foo } -Variable (Get-Variable -Name someVar) -Function (Get-Command -Name Foo)
 
    DOUBLE-HOP AUTHENTICATION AND CREDSSP
    Every machine deployed with AL has CredSsp enabled as a CredSsp server. This
    is like running “Enable-WSManCredSSP -Role Server”. Invoke-LabCommand
    always tries to make a connection with CredSsp. If this does not work you
    will see a warning and a connection without CredSsp is tried. This is
    definitely not a best practice for a production environment but makes life
    much easier in a lab. Using CredSsp you can create a remote session from a
    remote session which is extremely helpful when installing or setting up a
    lab. For example, reading an AD user account from a remote session does not
    work without CredSsp as reading data from Active Directory requires and
    authentication from the remote machine to a domain controller. Inside an AL
    lab the following code works out of the box.
 
    PowerShell
    Invoke-LabCommand -ComputerName Web1 -ScriptBlock {
        Get-ADUser -Identity John
    }
 
    TRANSFERRING MODULES TO MACHINES
    Invoke-LabCommand is a comfortable way to run scripts and ScriptsBlocks
    defined on your host machine in any lab machine. This cmdlet takes care of
    the authentication and allows you to send variables and functions to the
    remote machine. But how can you use cmdlets defined in a PowerShell module
    that exists on your host machine in a lab VM? With Send-ModuleToPSSession we
    have provided a way to send any PowerShell module available locally to a lab
    VM. Note: This cmdlet makes use of other functions provided within the
    AutomatedLab framework to copy files to Hyper-V or Azure machines like
    Send-Directory and what is provided by the
    PSFileTransfer
    module.
    Send-ModuleToPSSession will try to send the module using SMB first and if
    this does not work, using the PSSession. The module will be copied either to
    the Program Files\WindowsPowerShell\Modules or to the module path of the
    user used for opening the PSSession, depending of the scope you set:
    AllUsers, CurrentUser. There is also a switch to look for all module
    dependencies and copy them as well.
 
    DEMO (PROBLEM)
    The following code block demos the problem. You have a module locally on
    your machine and have successfully tested some code. Now you want to invoke
    that code on all lab machines (Azure or Hyper-V) but the module is not there
    yet.
 
    PowerShell
    Import-Lab -Name POSH -NoValidation
     
    ##works locally
    Get-NTFSAccess -Path C:\
     
    ##does not work remotely unless the module has been copied to the machines
    $vms = Get-LabVM -Role ADDS
    Invoke-LabCommand -ScriptBlock { Get-NTFSAccess -Path C:\ } -ComputerName $vms
 
    The error is
 
    The term 'Get-NTFSAccess' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is
    correct and try again.
        + CategoryInfo : ObjectNotFound: (Get-NTFSAccess:String) [], CommandNotFoundException
        + FullyQualifiedErrorId : CommandNotFoundException
        + PSComputerName : POSHDC1
      
    The term 'Get-NTFSAccess' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is
    correct and try again.
        + CategoryInfo : ObjectNotFound: (Get-NTFSAccess:String) [], CommandNotFoundException
        + FullyQualifiedErrorId : CommandNotFoundException
 
    DEMO (SOLUTION)
    It requires just one additional line and you can use your local module on
    the remote machines and this is, how it works: 1. You deploy your lab or
    import an import an existing one 2. You create a new PSSession to one or
    more machines 3. You send the module to these sessions 4. Then you can use
    the module on the lab VM
    After using Send-ModuleToPSSession, everything works as desired.
 
    PowerShell
    Import-Lab -Name POSH -NoValidation
     
    ##works locally
    Get-NTFSAccess -Path C:\
     
    $vms = Get-LabVM -Role ADDS
     
    ##just one line is required to copy the module to the VMs
    Send-ModuleToPSSession -Module (Get-Module -Name NTFSSecurity -ListAvailable) -Session (New-LabPSSession -ComputerName $vms)
     
    ##now works remotely
    Invoke-LabCommand -ScriptBlock { Get-NTFSAccess -Path C:\ } -ComputerName $vms -PassThru
 
Join Lab VMs to an existing domain
    AutomatedLab can deploy in your existing infrastructure with very little
    modifications necessary. At the moment, this is supported for existing
    domains only, but may be extended in the future.
    The `Add-LabMachineDefinition` cmdlet can make use of the `SkipDeployment`
    parameter in order to add an existing domain controller to your lab. You
    could for example locate an existing DC to join to:
 
 
    $DomainName = 'janhendrikpeters.de'
    $ctx = [System.DirectoryServices.ActiveDirectory.DirectoryContext]::new('Domain', $DomainName)
    $domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($ctx)
    $dc = $domain.FindDomainController([System.DirectoryServices.ActiveDirectory.LocatorOptions]::WriteableRequired).Name
    $dcName = $dc.Replace(".$DomainName", '')
    $dcIp = [System.Net.Dns]::GetHostAddresses($dc).IpAddressToString
 
 
    Now in order to add your domain controller, simply supply the host name and
    IP address of the system, as well as the domain join credentials:
 
    $DomainJoinCredential = Get-Credential
    Set-LabInstallationCredential -Username ($DomainJoinCredential.UserName -split '\\')[-1] -Password $DomainJoinCredential.GetNetworkCredential().Password
    ## We are not using a domain admin as we skip the deployment of the DC. Nevertheless, this credential is used for domain joins.
    Add-LabDomainDefinition -Name $DomainName -AdminUser ($DomainJoinCredential.UserName -split '\\')[-1] -AdminPassword $DomainJoinCredential.GetNetworkCredential().Password
     
    $PSDefaultParameterValues = @{
        'Add-LabMachineDefinition:DomainName' = $DomainName
        'Add-LabMachineDefinition:OperatingSystem' = 'Windows Server Datacenter'
        'Add-LabMachineDefinition:Memory' = 512MB
    }
     
    Add-LabMachineDefinition -Name $dcName -Roles RootDc -SkipDeployment -IpAddress $dcIp
    Add-LabMachineDefinition -Name POSHFS01
    Add-LabMachineDefinition -Name POSHWEB01
     
    Install-Lab
 
    The full sample script can be found in
    the SampleScripts folder
    .
    Stay tuned! Mounting ISO files on Azure is as simple as calling the existing
    cmdlet ``Mount-LabIsoImage``. The only difference is, that the ISO image
    file path lies on Azure. To find out which images are accessible in your
    AutomatedLab storage account you can do the following:
 
    `` Login-AzureRmAccount (Get-LabAzureLabSourcesContent -RegexFilter
    \.iso).FullName ``
    When mounting the ISO file, be sure to specify -PassThru to be able to use
    the drive letter that was used to mount the ISO in later commands:
 
    $mountedVolume = Mount-LabIsoImage -IsoPath https://some/azure/path.iso
    -ComputerName DC1 -PassThru
 
    Invoke-LabCommand DC1 -ScriptBlock { param ( $DriveLetter
     ) Start-Process (Join-Path $DriveLetter "Path\To\My\Setup.exe")
    } -ArgumentList $mountedVolume.DriveLetter AutomatedLab can handle
    everything about networking and IP addresses automatically for you. But, if
    you prefer, you can define everything by your own. AL supported also working
    with multiple subnets and internet connected labs. It takes care about the
    routing if a machine with the role 'Routing' is defined in the network.
 
    FULLY AUTOMATED
    AutomatedLab tries to make defining and deploying labs as easy as possible.
    Quite often you need some machines that can talk to each other but you are
    not interested in the IP configuration. In this case you do not have to care
    about networking and IP addresses at all. AL defines the virtual switch for
    you and also finds a free subnet for you.
    If you take a look at the introduction script
    [04 Single domain-joined server.ps1
    you will not find anything that defines a network. When deploying the lab AL
    tells you the subnet that was chosen.
    AL tries to find new subnets by simply increasing 192.168.1.0 until a free
    network is found. Free means that there is no virtual network switch with an
    IP address in the range of the subnet and the subnet is not routable. If
    these conditions are not met, the subnet is incremented again.
 
    SIMPLE NETWORK DEFINITION
    To manually create network definitions in order to have specific network
    address ranges available, the cmdlet ``Add-LabVirtualNetworkDefinition`` can
    be used for both HyperV- and Azure-based labs.
 
    # Adds a virtual network with no special options
        Add-LabVirtualNetworkDefinition -Name 'MySimpleNetwork' -AddressSpace 10.1.0.0/16
 
    Additionally, the parameters AzureProperties and HyperVProperties can be
    used to pass parameter hashtables. The following are valid keys that can be
    used as properties for AzureProperties: * SubnetName: The name of the subnet
    to create in the virtual network. AL does not segment virtual networks into
    subnets. One virtual network per network definition will be created
    * SubnetAddressPrefix: The address prefix (e.g. 24) of the subnet that will
    be created.
    * LocationName: The Azure location name (e.g. westeurope). Bear in mind that
    this should not differ from your lab's default location.
    * DnsServers: Comma-separated DNS servers for the network.
    * ConnectToVnets: Connections to other VNETs by leveraging VNET peering.
    When connecting two or more lab networks through this parameter, please also
    specifiy this for all additional network definitions
    For HyperV, the following properties are valid: * SwitchType: Internal or
    External. Defaults to internal. If External is specified, AdapterName needs
    to be set as well
    * AdapterName: The network adapter of the OS that will bridge the connection
    to the external network
 
    SIMPLE INTERNET CONNECTED
    Reviewing the HyperV and Azure properties for
    ``Add-LabVirtualNetworkDefinition`` we can see that internet-connected
    virtual networks can easily be created.
    To enable HyperV labs to have an internet connection, the following syntax
    can be used:
 
 
    Add-LabVirtualNetworkDefinition -Name 'MySimpleConnectedNetwork' -AddressSpace 10.1.0.0/16 -HyperVProperties @{SwitchType = 'External'; AdapterName = 'Ethernet'}
 
    This is all it takes for machines to connect to the internet.
    Azure networks by default are connected to the internet through a load
    balancer that initially only gives access to WinRM and RDP. Through NAT
    rules random external ports are mapped to the ports 5985, 5986 and 3389 on
    each machine. The random ports are stored for each machine, so that all
    connection-related cmdlets like ``Enter-LabPSSession`` or ``Connect-LabVm``
    work transparently.
    Additionally, Azure RDP files can be created by using
    ``Get-AzureRmRemoteDesktopFile``.
 
    COMPLEX INTERNET CONNECTED
    here be dragons. While creating an Azure-based lab is very easy and only
    requires to set the default virtualization engine to Azure instead of HyperV
    not all features are readily available from the start. To fully make use of
    Azure, you should also synch your lab sources with Azure.
 
    Doing so only requires a single line of code:
 
    ` Sync-LabAzureLabSources `
    This by default will synchronize your entire local lab sources folder with a
    pre-created Azure file share called labsources in the resource group
    AutomatedLabSources and the lab's randomly-named storage account. This file
    share will automatically be mapped on each virtual machine.
 
    Operating system images are automatically skipped in the synchronization
    process as they are readily available on Azure and are not being used.
    During the lab initialization the builtin variable $labsources will be
    automatically updated to point to your Azure lab sources location if you are
    deploying an Azure-based lab. There is no need to declare the variable in
    any script, as it is dynamically calculated to match the default
    virtualization engine.
    To skip large files or entire ISOs for certain products like e.g. Exchange
    or Skype for Business the following parameters are available: * SkipIsos:
    This switch parameter indicates that all ISO files should be skipped.
    * MaxFileSizeInMb: This parameter takes an integer value indicating the
    maximum size of the files to synch.
    Now you can simply use the other cmdlets provided by AutomatedLab to access
    files from the file share:
 
    * `$postInstallActivity = Get-LabPostInstallationActivity -ScriptFileName
    PrepareRootDomain.ps1 -DependencyFolder $labSources\PostInstallationActivities\PrepareRootDomain`
    * `Install-LabSoftwarePackage -ComputerName $machines -Path
    $labSources\SoftwarePackages\Notepad++.exe -CommandLine /S -AsJob`
 
Using Azure Bastion Hosts
    Azure Bastion Hosts are in preview as of 2020-05-19 and allow you to connect
    to your lab machines via the Remote Desktop Web Client from an Azure
    Bastion. Starting with release 5.21 AutomatedLab supports these as well.
    When opting to deploy a bastion, note that this will increase the time your
    lab deployment takes. This is due to: - The resource provider feature
    AllowBastionHost takes time to activate, if it is not registered. (
    *This step can take up to 20 minutes!
    *) - The resource group deployment eventually takes up to five minutes
    longer
 
    USAGE
    The easiest way to add a Bastion to your lab is by using the new
    AllowBastionHost parameter:
 
 
    New-LabDefinition -Name Bastion1 -DefaultVirtualizationEngine Azure
    Add-LabAzureSubscription -SubscriptionName JHPaaS -DefaultLocationName 'West Europe' -AllowBastionHost
     
    Add-LabMachineDefinition -Name DC1 -Memory 1GB -OperatingSystem 'Windows Server 2016 Datacenter (Desktop Experience)' -Roles RootDC -DomainName contoso.com
     
    Install-Lab
     
    Show-LabDeploymentSummary -Detailed
 
 
    Specifying this parameter will mean that your virtual network is extended to
    accomodate the bastion host subnet. Additionally, the lab network security
    group will receive additional rules.
 
    MORE CONTROL WITH CUSTOM SUBNETS
    If you do not want to extend the virtual network you defined in your lab,
    you can simply add a bastion subnet called AzureBastionSubnet - AutomatedLab
    will take care of the rest.
 
    New-LabDefinition -Name Bastion2 -DefaultVirtualizationEngine Azure
    Add-LabAzureSubscription -SubscriptionName JHPaaS -AllowBastionHost -DefaultLocationName 'West Europe'
     
    Add-LabVirtualNetworkDefinition -Name Lab2Vnet -AddressSpace 192.168.10.0/23 -AzureProperties @{ Subnets = @{
        'default' = '192.168.10.0/24'
        'AzureBastionSubnet' = '192.168.11.0/24'
    }}
    Add-LabMachineDefinition -Name DC1 -Memory 1GB -OperatingSystem 'Windows Server 2016 Datacenter (Desktop Experience)' -Roles RootDC -DomainName contoso.com -Network Bastion2Vnet -IpAddress 192.168.10.11
     
    Install-Lab
     
    Show-LabDeploymentSummary -Detailed
 
    CONNECTING VIA THE BASTION
    At the moment, you need to use the
    Azure portal
    to connect to your bastion host. In the future, we might be able to use
    Connect-LabVm instead.