Vous êtes sur la page 1sur 40

Automating Windows Deployment

in a Cisco UCS Manager


Environment
Contents
Introduction................................................................................................................ 2
Outline..................................................................................................................... 3
Workstation Configuration.......................................................................................... 4
Assessment and Deployment Kit (ADK)...................................................................4
Directory Configuration........................................................................................... 5
C:\WinPE............................................................................................................... 5
E:\Share................................................................................................................ 6
NewSPdirectory.ps1.............................................................................................. 7
Copy Files............................................................................................................. 8
Local User Account.................................................................................................. 8
NewShareUser.ps1............................................................................................... 8
Cisco UCS PowerTool / [Java]................................................................................... 9
Microsoft Operating System Virtual Hard Disks........................................................10
Windows Server (Hyper-V Server).........................................................................10
NewWindowsServerVHD.ps1..............................................................................11
Nano Server.......................................................................................................... 12
Remote Management......................................................................................... 14
Consistent Device Naming.................................................................................... 15
Tailor WinPE.............................................................................................................. 15
Basics.................................................................................................................... 16
Inject Cisco Device Drivers.................................................................................... 16
Intel Chipset Drivers.............................................................................................. 17
Windows PowerShell.............................................................................................. 17
Cisco UCS PowerTool............................................................................................. 19
Custom WinPE Scripts........................................................................................... 19
Startnet.cmd...................................................................................................... 19
WinPE_Automation.ps1...................................................................................... 20
Dismount WinPE Media.......................................................................................... 21

1 | Page
Create Bootable WinPE Media...............................................................................21
Sample Automation Scripts...................................................................................... 21
Automation.ps1..................................................................................................... 22
Get-ServiceProfile............................................................................................... 22
Populate Parameters.......................................................................................... 23
Partition-Disk...................................................................................................... 24
Mount-Vdisk........................................................................................................ 25
Create-Unattend................................................................................................. 26
Setup-Complete..................................................................................................... 27
ServerSetup.ps1 (Windows Server)....................................................................28
NanoSetup.ps1 (Nano Server)............................................................................30
Variables.xml...................................................................................................... 31
ForcePxeBoot......................................................................................................... 31
Summary.................................................................................................................. 32
Author...................................................................................................................... 32

Introduction
If you are regularly deploying Windows operating systems, the combination of Cisco
UCS tools and Microsoft tools work together to speed up the deployment of Windows
Server operating systems. The purpose of this document is to provide step-by-step
guidance to configure an environment that enables automating the deployment of
Windows Server. This includes the various operating system installation options,
such has Hyper-V Server, Standard or Datacenter, Core or Full, plus it shows how to
use the procedure for a new installation option available in Windows Server 2016
called Nano Server.
The primary components used for this automation process are Cisco UCS Manager,
Cisco UCS PowerTool, Microsoft PowerShell, and Microsoft WinPE.

Cisco UCS Manager (UCSM) is designed to streamline many of the most


time-consuming daily activities, including configuration, provisioning,
monitoring, and problem resolution. Through a comprehensive and open XML
API, UCSM enables programmatically managing hardware configurations.
Cisco UCS PowerTool is Ciscos PowerShell module that enables full
programmatic access to the UCSM environment by providing a Microsoft
PowerShell module that accesses the UCS API.
Microsoft PowerShell is Microsofts task automation and configuration
management framework, consisting of a command-line shell and associated
scripting language built on the.NET Framework. PowerShell provides full
access to COM and WMI, enabling administrators to perform administrative
tasks on both local and remote Windows systems.

2 | Page
Microsoft WinPE Windows Preinstallation Environment (WinPE) is a
lightweight version of Windows used for the deployment of PCs, workstations,
and servers, or troubleshooting an operating system while it is offline.
The core of this solution is WinPE. WinPE is a stripped down version of Windows
that can be booted via PXE, USB, DVD, or UCS Manager virtual media, providing a
way to quickly get a working operating system onto the system being targeted for
deployment.
Out of the box, WinPE contains basic elements. To make it really useful, it generally
has to be modified. For example, it comes with a minimum number of device
drivers. Therefore, it is often necessary to add additional device drivers that you
know will be needed to deploy your system. For Cisco, that means the enic driver at
a minimum, but can also include other specific hardware drivers. It also comes with
basic scripting abilities. For purposes of this document, it will be tailored to provide
the flexibility of PowerShell.
This document will describe the procedure to create virtual hard disk (VHD) images
of Windows Server and Nano Server and a bootable WinPE image that can used for
deploying those VHDs to Cisco UCS hardware. This procedure will create a virtual
hard disk that can be used for natively booting the physical system. This actually
provides more flexibility in deployment because a VHD can be easily mounted to
another Microsoft operating system and files added or removed, making the options
for deployment nearly limitless.
There are four major sections in this document.
1. Workstation configuration what tools, directories, etc. need to be configured
to run the sample automation shown in this document
2. Microsoft operating system virtual hard disks automating the creation of the
virtual hard disks that will eventually be used to boot the Cisco UCS server
3. Tailor WinPE how to tailor WinPE to automate the deployment of the VHDs
4. Sample automation scripts scripts developed to automate the deployment
and configuration of the VHDs
Note: Though these scripts have been extensively tested, they are provided AS IS
with no warranties, confer no rights, and are not supported by the author or Cisco
Systems. They should be evaluated and tested for each individual environment to
ensure they meet the standards in place.

Outline
1. Workstation configuration
a. Download and install the latest Assessment and Deployment Kit (ADK)
b. Directory configuration
c. Local user account
d. Cisco UCS PowerTool / [Java]
2. Microsoft operating system virtual hard disks
a. Windows Server (Hyper-V Server)
b. Nano Server
3. Tailor WinPE

3 | Page
a. Basics
b. Inject Cisco drivers
c. Install Windows PowerShell
d. Install Cisco UCS PowerTool
e. Custom Scripts
f. Create bootable WinPE media
4. Sample Automation Scripts
This document assumes deployment into a Cisco UCS managed environment. The
scripts automatically determine the name of the computer on which the scripts are
running by making use of the capabilities of Cisco UCS Manager. If these scripts are
to be used in an environment that is not managed by UCS Manager, for example a
CIMC managed environment, a different method will have to be used to determine
the computer name. Once that method is implemented and the scripts changed to
reflect the alternate method, these scripts should work (though they have not been
tested in a CIMC environment).

Workstation Configuration
A workstation for preparing the WinPE environment will need to be configured. This
can be a Windows 8.1, Windows 10, Windows Server 2012 R2, or Windows Server
2016 system. It is recommended to use the latest version available of the operating
system to ensure that you are using the latest tools. This process assumes
Windows 10 (Windows Server 2016), but slight modification will make it possible to
use Windows 8.1 (Windows Server 2012 R2).
You will also be using this workstation for creating the VHD files that will eventually
be deployed to the physical servers. The target VHD file will be copied to a local
physical disk on the server being deployed and then be used to native boot from
VHD instead of booting from an installation performed to the local physical disk.

Assessment and Deployment Kit (ADK)


The copy of WinPE to be used in this process is available as part of Microsofts
Assessment and Deployment Kit. It is best to always use the latest kit. Newer kits
work with earlier versions of the operating system. The latest kit available at the
time of this writing is for Windows 10 Version 1511. Download the Windows ADK for
Windows 10 (http://go.microsoft.com/fwlink/p/?LinkId=526740).
When you launch the installation program from the above link, you will be presented
with two options one to install the ADK and the second to copy down all the files
needed for offline installation. Choose which option you want.
The ADK contains more capabilities than we need. When you run the installation,
you will be presented with a window that looks something like this:

4 | Page
By default, several options will be pre-selected. All that is needed for this process
are the Deployment Tools and Windows Preinstallation Environment (Windows PE).
Unselect all options but those two and click Install.

Directory Configuration
The workstation in this example is used for several purposes:

Creating WinPE media


Creating the VHD files for deployment
File share for automation files

A specific directory structure is assumed throughout this document. There is a


great deal of flexibility in how you may want to create your directory structure. Just
be aware that the samples shown in this document assume the structure as defined
in the following descriptions.

C:\WinPE
This directory and three subdirectories are created by the ADK. These directories
hold the content of the files used to create the targeted WinPE media. You specify
the exact location and name of this directory when you start the WinPE creation
process and it creates the directory structure.

5 | Page
C:\WinPE\fwfiles there are two files contained in this directory. They are used
when you create bootable WinPE media, depending on the type of media created.
The proper file is automatically selected so you do not need to be concerned about
these files.
C:\WinPE\media this directory contains all the files needed for creating the
WinPE media. For the most part, the only file you are likely to reference is the
C:\WinPE\sources\boot.wim. This is the file you are going to mount and tailor to
your needs.
C:\WinPE\mount this directory is used to mount the boot.wim file so you can
access the contents of the WIM file.

E:\Share
You create this directory and the subdirectories on the workstation. It files that will
be used in the tailoring of both the WinPE media and the VHD target, as well as the
automation scripts and configuration files. Again, this directory structure is the
structure used for this document. It can be on any volume, and it needs to be
shared for network access with specific ACLs.
Note: Some of the sample scripts presented in this document have this value hard-
coded. If you use a different root directory, you will need to make changes to the
hard-coded values in the sample scripts.
The following subdirectories of the \Share need to be in place. The first subdirectory
is \Automation. It contains six common subdirectories and then a series of
subdirectories used to contain information specific to individual servers that are
being deployed.
E:\Share\Automation\Base This is an optional subdirectory that can be used
during the creation of the Nano Server image.
E:\Share\Automation\Drivers This subdirectory contains all the device drivers
that need to be added to any image being created. At a minimum, you should
include the UCS VIC enic driver. Go to Cisco.com and download the appropriate
driver ISO files. Mount the ISO file. Copy the driver files for each driver that you
want to add to the image into this directory. You may want to create a separate
subdirectory for each unique driver, just to keep things straight. For example, here
is a sample directory for the Cisco UCS C240 M4 servers used for this document.

6 | Page
E:\Share\Automation\Mount This subdirectory is used as a mount point for the
install.wim file when tailoring it into a virtual hard disk. Nothing is permanently
stored here.
E:\Share\Automation\Nano This subdirectory is used to contain the automation
scripts for building a Nano Server image. The scripts are copied to this subdirectory
from the Windows Server distribution media.
E:\Share\Automation\Scripts This subdirectory contains scripts that are
common across any deployment process used to automate the deployment of a
specific server. These scripts will be executed by WinPE, but it is easier to manage
these scripts on the workstation than it is to manage them on the WinPE image.
Scripts that are used to tailor a specific image will be contained within a different
subdirectory.
E:\Share\Automation\VHDs This subdirectory will contain the created VHD from
the Windows Server or Nano Server wim file. Each VHD will be a base image that
can be tailored later in the process by including other script files. For example, you
might want to have four images for Windows Server 2016 Standard Core, Standard
with Desktop, Datacenter Core, and Datacenter with Desktop. Due to the way Nano
Server images are created, you might want to have images for Compute with
Cluster, Compute Standalone, File Services with Cluster, File Services Standalone,
and any other combinations that are appropriate to your environment. This
document will show you how to create an individual image, but it will not show the
creation of all those listed above.
The following PowerShell commands will create the above directory structure.
New-Item -Path E:\Share\Automation -ItemType Directory
New-Item -Path E:\Share\Automation\Base -ItemType Directory
New-Item -Path E:\Share\Automation\Drivers -ItemType Directory
New-Item -Path E:\Share\Automation\Mount -ItemType Directory
New-Item -Path E:\Share\Automation\Nano -ItemType Directory
New-Item -Path E:\Share\Automation\Scripts -ItemType Directory
New-Item -Path E:\Share\Automation\VHDs -ItemType Directory

E:\Share\Automation\<SPname> There will be multiple subdirectories of this


format. You will need one for each Service Profile being deployed. <SPname> must
match the name of the Service Profile, as the Service Profile is used to determine
which configuration is being deployed. This allows a single file server to contain the
automation files for multiple deployments, and the deployments can be occurring
simultaneously.
E:\Share\Automation\<SPname>\Executables Any executables that you want
to get onto the VHD file so they can be executed by the Windows
StartupComplete.cmd script or other automation scripts you may include. For
example, you might want to install an agent or utility on every system you deploy.
You would place the .exe or .msi file into this directory and its contents would get
copied to the VHD. Then at the appropriate time after the systems initial boot, the
StartupComplete.cmd script can be modified to run these installations.

7 | Page
E:\Share\Automation\<SPname>\Scripts This subdirectory contains scripts
particular to tailoring the system. It must contains a Variables.xml file that define
things like IP addressing, passwords, domain join information, etc. A sample is
shown later in this document. If anything besides the basics covered in the
common automation file is required, those files would also be present. For example,
you might need a SetupComplete.cmd file which is executed upon completion of the
installation. That script may call another script, ServerSetup.ps1, to perform other
functions such as domain join or role installation.
E:\Share\Automation\<SPname>\Logs This subdirectory is used to store log
files created during the automation steps. The access to this subdirectory differs
from the rest of the subdirectories. The rest of the subdirectories are configured for
Read/Execute access for the local account used to access the root share. Because
log files will be written during the automation process, the ACL on this subdirectory
is changed to add Write and Modify access for the local account.

NewSPdirectory.ps1
The following script will take a Service Profile name as input and create the proper
subdirectory structure. It requires that the $shareRoot and $shareUser variables be
modified to reflect the customer environment. Before running this script, the
$shareUser variable must be defined as a local user on the workstation
(NewShareUser.ps1 script is shown in the next section).
Note: Remember when entering the Service Profile name that is it case sensitive
within UCS Manager.
Param
(
[Parameter(Mandatory = $true, Position = 0)] # Service Profile name
[String]$spName
)

$shareRoot = "E:\Share\Automation" # Local share root


$shareUser = $env:ComputerName + '\' + 'BuilderUser' # Local user account to add to share ACL

$spPath = Join-Path $shareRoot $spName


$spExecutables = Join-Path $spPath "Executables"
$spScripts = Join-Path $spPath "Scripts"
$spLogs = Join-Path $spPath "Logs"

If (Test-Path $spPath)
{
Write-Host "Directory $spPath already exists. Exiting" -ForegroundColor Red
Exit
}

$null = New-Item -Path $spPath -ItemType Container


$null = New-Item -Path $spExecutables -ItemType Container
$null = New-Item -Path $spScripts -ItemType Container
$null = New-Item -Path $spLogs -ItemType Container

# Get ACL on log directory. Build Modify permission for share user. Add to ACL.
$acl = Get-Acl $spLogs
$colRights = [System.Security.AccessControl.FileSystemRights]"Read,Modify,ExecuteFile,ListDirectory"
$permission = $shareUser,$colRights,"ContainerInherit,ObjectInherit,None,Allow

8 | Page
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.AddAccessRule($accessRule)
$acl | Set-Acl $spLogs

Write-Host "Directories created:"


Write-Host " $spPath"
Write-Host " $spExecutables"
Write-Host " $spScripts"
Write-Host " $spLogs`n"
Write-Host "$shareUser granted Modify access to $spLogs`n`n" -ForegroundColor Yellow

Copy Files
Once the above directory structure is created, you must copy in any custom script
files (Variables.xml, ServerSetup.ps1) and executables appropriate for the platform
you are targeting. Additional scripts and executables you may reference within
ServerSetup.ps1 also must be copied into the appropriate directories.

Local User Account


The above share needs to be accessed by the WinPE automation scripts. The
simplest way to provide access to the share is to create a local user account on the
workstation that has read access to the share. It only needs read access because
the complete process copies the VHD file from the share to WinPE which writes it
out to the local disk. So all modification of the VHD file occurs on the targeted
server. Once you have successfully created your WinPE media, you can reuse the
VHD file to many different servers simply by modifying a couple variables in the
scripts.
The Logs subdirectory mentioned above needs to allow Write/Modify access to the
local user account as log files will be written to that subdirectory.
In this sample, the user account created is BuilderUser with a password of
P@55w0rd.
It is also possible to configure the share with Anonymous access, but that opens a
larger security surface to exploit, so I opted for this method.
The following script asks for a user name and password and uses the entries to
create a local account on the machine running the script. The account is set to
have a non-expiring password that cannot be changed by the user.

NewShareUser.ps1
$userName = Read-Host "Username for share access"
$password = Read-Host "New password for $userName" -AsSecureString
$confirmpassword = Read-Host "Confirm the password" -AsSecureString
If ($password -ne $confirmpassword)
{
Write-Host "Entered passwords are not same. Script is exiting" -ForegroundColor Red
Exit
}

$pwd =
[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringTo
BSTR($password))

$computerName = $env:ComputerName

9 | Page
$compobj = [ADSI]"WinNT://$computerName"
$user = $compobj.create("user", $userName)
$user.SetPassword($pwd1)
$user.SetInfo()
$user.Description = "Special account for deployment automation"
$user.SetInfo()

# Mask values to set Password cannot be changed and never expires


$PASSWD_CANT_CHANGE = 64
$DONT_EXPIRE_PASSWD = 65536

$computer = [ADSI]"WinNT://$computerName,computer"
$Users = $computer.psbase.Children | Where-Object {$_.psbase.schemaclassname -eq "user"}
ForEach ($user in $users)
{
If ($user.Name -eq $userName)
{
$Name = $user.Name
$flags = $user.userFlags.Value
$flags = $flags -bor $PASSWD_CANT_CHANGE
$flags = $flags -bor $DONT_EXPIRE_PASSWD
$user.userFlags.Value = $flags
$user.SetInfo()
Break
}
}

Cisco UCS PowerTool / [Java]


This sample automation procedure tailors the name of the computer to match the
name of the UCS Manager Service Profile that is assigned to the physical computer.
It does this by using Cisco UCS PowerTool to connect to UCS Manager and find the
Service Profile assigned and then insert that name into the created unattend.xml
file. This is not necessary if you have a different naming convention, but it does
show some of the power that can be achieved by UCS automation techniques. And,
the examples shown in this document assume that is what is occurring. If you have
a different naming convention, you will need to adapt scripts and procedures.
To use this capability, you need to install Cisco UCS PowerTool within the WinPE
image. Instructions for installing PowerTool into the WinPE image are detailed
below. But in order to tailor the WinPE image, PowerTool must also be installed on
the workstation. The latest version of Cisco UCS PowerTool can be found at:
https://software.cisco.com/download/release.html?
mdfid=286305108&flowid=79283&softwareid=284574017&release=2.0.1&relind=
AVAILABLE&rellifecycle=&reltype=latest
The easiest way to ensure the Cisco UCS PowerTool modules are loaded is to edit
the PowerShell profile to import the requisite PowerTool modules. There are four
different PowerShell profiles.

%windir%\system32\WindowsPowerShell\v1.0\profile.ps1 applies to
all users and all shells

10 | P a g e
%windir%\system32\WindowsPowerShell\v1.0\
Microsoft.PowerShell_profile.ps1 applies to all users, but only to the
Microsoft.PowerShell shell
%UserProfile%\My Documents\WindowsPowerShell\profile.ps1
applies only to the current user, but affects all shells
%UserProfile%\My
Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
applies only to the current user and the Microsoft.PowerShell shell
At a minimum you should modify the third one for the user that will be running the
scripts. If you do not modify the appropriate profile(s), it will be necessary to import
the proper PowerTool module(s) within any script that calls PowerTool cmdlets.
The following PowerShell command provides a sample import command to be
inserted into the appropriate profiles:
Import-Module Cisco.UCS.Core, Cisco.UCSManager

Optionally, if you plan on running the UCS Manager console or UCS KVM from your
workstation, you will need to install the latest version of Java. UCS Manager version
3 and later has an HTML5 interface that can be used from any browser supporting
HTML5, but the UCS KVM still requires Java.

Microsoft Operating System Virtual Hard Disks


These samples show how to create a virtual hard disk that can be used to natively
boot the physical computer from a VHD. This VHD is copied to a physical disk (or
LUN) and is configured to enable booting from it.
Two processes exist for creating the VHD. One exists for the traditional Windows
operating system environments Windows Server Datacenter GUI/Core, Windows
Server Standard GUI/Core, and Hyper-V Server. This process has been around and in
use for some time.
Nano Server is a new installation option for Windows Server 2016. It has been
reduced to its basic capabilities, and this required Microsoft to create a new way to
create bootable VHDs. Both processes will be shown here.

Windows Server (Hyper-V Server)


The script shown below creates a fairly basic installation image for Windows Server.
There are some prerequisites to running this script.

Script must be run from an account with administrator privileges


ISO distribution of the desired operating system is mounted (this sample
assumes Windows Server 2016 TP) and drive letter of mounted image is
entered into the script (-isoPath)
Desktop Experience option is selected for installation (-osIndex Datacenter
for this sample)

11 | P a g e
A local share is specified to contain the output, as well as containing a
subdirectory with Cisco drivers needed for installation (- localShare
E:\Share\Automation for this sample)
The sample command line for executing this script (assuming it is in the connected
directory) is:
PS E:\Share\Automation\Scripts> .\NewWindowsServerVHD.ps1 isoPath F:
-osIndex Datacenter localShare E:\Share\Automation

The output from this script using the above parameters is a 50 GB dynamically
expanding VHDX file with the Windows Server 2016 Datacenter Desktop Experience
installation. The VHDX contains the UCS drivers required to boot physical UCS
servers. It relies on the previous automation scripts and processes to tailor for this
environment by inserting unattend.xml and StartupComplete.cmd files and making
the VHDX file bootable by the physical machine.

NewWindowsServerVHD.ps1
#Requires -RunAsAdministrator

Param
(
[Parameter(Mandatory = $true, Position = 0)] # Drive letter of ISO
[String]$isoPath,

[Parameter(Mandatory = $true, Position = 1)] # Location of share for config files


[String $localShare,

[Parameter(Mandatory = $true, Position = 2)] # Image to use


[ValidateSet("Standard", "StandardCore", "Datacenter", "DatacenterCore")]
[String]$osIndex

Write-Output "Processing started at:" (Get-Date)

$isoPath = $isoPath.trim()
$sourcesPath = Join-Path $isoPath "sources"
$wimSource = Join-Path $sourcesPath "install.wim"
$localShare = $localShare.trim()
$driversPath = Join-Path $localShare "Drivers"
$wimPath = Join-Path $localShare "install.wim"
$mountDir = Join-Path $localShare "Mount"
$fatalErr = $false

# Test entered ISO drive letter has proper media


If (!(Test-Path $wimSource))
{
$fatalErr = $true
Write-Warning "Invalid drive letter for ISO or invalid ISO file"
}

# Test entered local share exists and has proper driver files
If (!(Test-Path $localShare -PathType Container))
{
$fatalErr = $true
Write-Warning "Local share directory does not exist"
}

12 | P a g e
If (!(Test-Path $driversPath -PathType Container))
{
$fatalErr = $true
Write-Warning "Local share directory does not contain Drivers sub-directory"
}
If (!(Get-ChildItem -Path $driversPath -Filter enic6x64.inf -Recurse ))
{
$fatalErr = $true
Write-Warning "Local share directory does not contain Ethernet driver files"
}

If ($fatalErr)
{
Write-Error "Argument error prevents script from running. Aborting." -Category InvalidArgument
Exit
}

Switch ($osIndex)
{
StandardCore {$installIndex=1;$vhdName="WS2016_Std_Core.vhdx"}
Standard {$installIndex=2;$vhdName="WS2016_Std.vhdx"}
DatacenterCore {$installIndex=3;$vhdName="WS2016_DC_Core.vhdx"}
Datacenter {$installIndex=4;$vhdName="WS2016_DC.vhdx"}
}
$vhdxPath = Join-Path $localShare "VHDs\$vhdName"

# Test for existence of $mountDir - if not there, mkdir


If (!(Test-Path $mountDir)) {mkdir $mountDir}

# Create a writable copy of the install.wim


Write-Output "Copying $wimSource to $wimpath"
Copy-Item -Path $wimSource -Destination $wimPath -Force
attrib -r $wimPath

# Mount the wim file and add the Cisco drivers. Use version from ISO to ensure compatibility
. $sourcesPath\Dism.exe /Mount-Image /ImageFile:$wimPath /index:$installIndex /MountDir:$mountDir
. $sourcesPath\Dism.exe /Add-Driver /Image:$mountDir /Driver:$driversPath /Recurse
. $sourcesPath\Dism.exe /Unmount-Image /MountDir:$mountDir /commit

# Create a VHDX
$drive = New-VHD -path $vhdxPath -SizeBytes 50gb -Dynamic | `
Mount-VHD -Passthru | `
Get-Disk -number {$_.DiskNumber} | `
Initialize-Disk -PartitionStyle MBR -PassThru | `
New-Partition -UseMaximumSize -AssignDriveLetter:$false -MbrType IFS | `
Format-Volume -Confirm:$false -FileSystem NTFS -NewFileSystemLabel $osIndex -Force | `
Get-Partition | `
Add-PartitionAccessPath -AssignDriveLetter -PassThru | `
Get-Volume).DriveLetter
$driveLetter = "$($drive):\"

# Write the modified wim file to the VHDX


Write-Output "Applying image to $vhdxPath"
Dism /apply-image /imagefile:$wimPath /index:$installIndex /applydir:$driveLetter

Dismount-VHD $vhdpath

# Cleanup
Remove-Item $localShare\install.wim

13 | P a g e
Write-Output "Processing completed at:" (Get-Date)

Note: The above script assumes Windows Server 2016 for the naming convention
of the created VHD file. The script will work with Windows Server 2012 R2 media,
too, but it will still use the Windows Server 2016 naming convention. You would
need to manually change the name of the created VHDs to reflect a different
naming convention. It can also be used for Hyper-V Server. For Hyper-V Server, the
only valid index value is 1, so you would select StandardCore as the image to
use.

Nano Server
Nano Server is a remotely administered server operating system optimized for
private clouds and data centers. It is similar to Windows Server in Server Core
mode, but significantly smaller, has minimal local logon capability, and only
supports 64-bit applications, tools, and agents. It takes up far less disk space, sets
up significantly faster, and requires far fewer updates and restarts than Windows
Server. When it does restart, it restarts much faster.
This process creates a VHD that is used to boot a physical machine using the pre-
installed Cisco UCS drivers.
1. Start PowerShell as an administrator. Mount the Windows Server ISO. This
example assumes it is mounted to drive letter J: Create a directory in which
you will build the Nano Server VHD. This example assumes
E:\Share\Automation\VHDs.
2. Copy the required Cisco driver files into the Drivers subdirectory
(E:\Share\Automation\Drivers).
3. Connect to E:\Share\Automation\Nano and copy the files from
J:\Nanoserver\NanoServerImageGenerator\ to this directory.

Copy J:\Nanoserver\NanoServerImageGenerator*.*

4. Import the NanoServerImageGenerator script.

Import-Module .\NanoServerImageGenerator.psm1 -Verbose

5. Create a VHD that sets a computer name, includes the OEM and Cisco
drivers, and the Hyper-V role and Failover Clustering feature by running the
following command. It will prompt you for an administrator password for the
new VHD:

New-NanoServerImage -MediaPath J:\ -TargetPath E:\Share\Automation\VHDs\Nano_C_C.vhdx


-ComputerName Nano_C_C -OEMDrivers DriverPath E:\Share\Automation\Drivers
DeploymentType Host Edition Datacenter -Compute Clustering
-EnableRemoteManagementPort

a. MediaPath J:\ the Windows Server ISO is mounted to drive letter J:


b. TargetPath E:\Share\Automation\VHDs\Nano_C_C.vhdx path name of
the created virtual hard disk. The file extension, .vhd or .vhdx,
specifies the type of VHD created. It is recommended that you define
a naming standard that allows you to quickly identify the roles/features

14 | P a g e
selected. This will assist in writing the automation scripts because you
will be working with known values in referencing the base images.
c. ComputerName Nano_C_C creates an unattend.xml file in the VHD
which sets the name of the computer to Nano_C_C.
d. OEMDrivers include the OEM device drivers for the most common
hardware that are included with the Nano Server distribution. This
does not include any of the Cisco-specific drivers.
e. DriverPath E:\Share\Automation\Drivers include all drivers in this
subdirectory. This is where the Cisco drivers are stored.
f. DeploymentType Host specify the deployment type. Host to a
physical server. Guest to a VM.
g. Edition Datacenter specify the edition, Standard or Datacenter. This
specifies licensing and capabilities. Datacenter should be selected if
the server is being deployed with Hyper-V (-Computer parameter), as a
member of a Storage Spaces Direct cluster (-Storage parameter),
and/or it will have shielded VMs deployed to it (-Packages Microsoft-
NanoServer-ShieldedVM-Package parameter).
h. Compute include the Hyper-V role in the image.
i. Clustering include the Failover Cluster feature in the image.
j. EnableRemoteManagementPort allow for remote management of the
system
k. The execution of above script will ask for the local administrators
password. It is possible to include the password in the above
command by adding this parameter: AdministratorPassword (ConvertTo-
SecureString String P@55w0rd AsPlainText Force)

Note: The EnableRemoteManagementPort parameter creates a SetupComplete.cmd


file on the VHD that defines a firewall rule to allow for remote management. If you
use the sample files in this document, they also create a SetupComplete.cmd file
with a firewall rule enabling remote management. During your debugging process
of your scripts, you may want to continue to use the EnableRemoteManagementPort
parameter until you are sure your scripts properly set the Nano Server for remote
management.
When this script completes, it has created a virtual hard disk ready to be configured
for booting. The creation process creates a \Windows\Panther\unattend.xml file that
provides a name for the computer (specified by the Computername parameter)
and the local administrators password.
If you plan on using the full automation that is demonstrated in this document, the
default unattend.xml file created above will not be used. Instead, the automation
process will create a new file to be used in its place. This is because the overall
automation procedure works with both Nano Server and Windows Server images.
The sample script for creating the base Windows Server image shown earlier does
not include an unattend.xml file, as later steps in this sample automation process
will create it.
If you plan to deploy manually to multiple physical servers, you can:
1. Make a copy of the virtual hard disk created by New-NanoServerImage.ps1

15 | P a g e
2. Mount the copied VHD
3. Open <driveletter>:\Windows\Panther\Unattend.xml with Notepad
4. Change the name of the computer (<ComputerName></ComputerName>)
5. Save the changes when exiting from Notepad
6. Proceed to passing each file to each physical server by using the WinPE
bootable media described at the beginning of this document
Besides the Compute and Clustering switches shown above, there are several
other switches that can be used independently or in conjunction with other switches
to define roles and features to be included in the image. See Getting Started with
Nano Server for more switches. https://technet.microsoft.com/en-
us/library/mt126167.aspx

Option Role or Feature


-Storage File Server role and other components
-Defender Windows Defender Antimalware, including a default signature
file
- Reverse forwarders for application compatibility
ReverseForwarder
s
-Containers Host support for Windows Containers
-Packages Several roles and features are deployed as packages, for
example DNS, DSC, IIS and more. See Getting Started with
Name Server for more details.

Remote Management
Since Nano Server does not support either a GUI or RDP for remote management,
you need to manage it remotely. The above process will configure a Nano Server for
remote management. There are also some things that you need to do on the
system from which you are going to manage the Nano Server. For complete details
on how to set up a PowerShell remote management session to the Nano Server, see
the above referenced document, Getting Started with Nano Server, for more details.

Consistent Device Naming


Windows Server and Cisco UCS support Consistent Device Naming (CDN). CDN
enables specifying a string within UCS vNIC definition that will be automatically
passed to Windows Server. Windows Server uses this string to name the NIC within
Windows instead of using the default strings of Ethernet, Ethernet #2, Ethernet
#3, etc. One common use of this capability is to automatically assign NIC
configurations. Prior to CDN support being available, it was necessary to perform
some sort of comparison between the MAC address in the UCS Service Profile to the
MAC address assigned by Windows. With CDN, it is possible to simply test on the
name.
If you plan to automate the IP addressing configurations, it is recommended that
you define a unique value to each of your vNICs in either your Service Profile
Templates or Service Profiles. The following image illustrates within UCSM where
the CDN value is set for a vNIC.

16 | P a g e
Examples shown in this document depend upon CDN being defined in the Service
Profiles.

Tailor WinPE
Once the above setup is complete, click on the Windows icon on the task bar and
type Deployment. This will automatically search and find the Deployment and
Imaging Tools Environment. Right-click and select Run as Administrator. This will
bring up a command window in the deployment tools directory. All commands
shown in this section are performed from this command window.
Shortcut for launching is C:\ProgramData\Microsoft\Windows\Start
Menu\Programs\Windows Kits\Windows ADK\Deployment and Imaging Tools
Environment.

Basics
The first thing we need to do is create a distribution copy the basic WinPE files that
we will be using into a directory. Execute the following copype command in the
command window:
copype amd64 C:\WinPE

This command creates the specified directory for you. It specifies to create a
distribution for 64-bit Windows because Windows Server 2012 and later only come
in 64-bit versions, and we are not concerned with building a distribution for 32-bit
operating systems at this time. You can place this anywhere on your system. The
above directory will be used as the example directory throughout this document.

17 | P a g e
Included in the files copied is a boot.wim file that we will be modifying. In order to
modify it, we need to mount it to make it available to the system. The following
DISM command mounts the file.
Dism /Mount-Image /ImageFile:C:\WinPE\media\sources\boot.wim /index:1
/MountDir:C:\WinPE\mount

Inject Cisco Device Drivers


The boot.wim image that was just mounted contains default Windows device
drivers. We need to add the Cisco device drivers to the image. For sample
purposes, this example will be using the Cisco UCS VIC driver for networking. If you
plan on using this image for more than just one model of Cisco UCS system, you can
add additional drivers. A sample directory with multiple files is shown later in this
document.
The following example shows injecting the VIC networking device driver directly
from the share directory created earlier on E: Notice that you just specify the .inf
file to the DISM command to load the device driver.
Dism /Add-Driver /Image:C:\WinPE\mount /Driver:
E:\Share\Automation\Drivers\enic6x64.inf

When inserting multiple device drivers into the image, you may issue a single
command to load all the drivers. This command will find all .inf files in the specified
directory and any subdirectories.
Dism /Add-Driver /Image:C:\WinPE\mount /Driver:E:\Share\Automation\Drivers /Recurse

NOTE: If you plan on using onboard RAID for the boot SSDs that are available for
some systems (Wellsburg Dual 4-port SATA Storage Control Unit from Intel), make
sure to include those drivers in the WinPE image. This also requires the addition of
a Storage Profile to be used in your Service Profile. It will be configured like this:

18 | P a g e
To see what device drivers are injected into this image, issue the following
command:
Dism /Get-Drivers /Image:C:\WinPE\mount

At this time you could create a bootable copy of WinPE that would be able to boot
the physical hardware and present you with access to both the network and storage
devices. But the goal is to automate the deployment of the Windows operating
system, so we will perform a few more steps.

Intel Chipset Drivers


Even though the Intel Chipset drivers are not required to be loaded into WinPE, it
makes sense to capture them at this time so you do not have to mount the driver
media again in the future. Early you should have copied the appropriate
SetupChipset.exe file to its own subdirectory within the share directory. The
following command, executed from a command prompt, demonstrates how to
extract the chipset driver files and store them within the same subdirectory:
E:\Share\Automation\Drivers\Intel-Chipset\SetupChipset.exe -extract
E:\Share\Automation\Drivers\Intel-Chipset

After extracting the driver installation files, you can delete the ChipsetSetup.exe file.

Sample \Share\Automation\Drivers Directory


Here is a sample listing of the drivers used for a UCS-managed C240 M4 that has
the onboard RAID for the boot SSDs and the LSI RAID controller for hard drives.
Note that this is configured for local storage. If you were configuring this to use FC
or FCoE storage, you would also need to include the fnic driver.

19 | P a g e
Directory of E:\Share\Automation\Drivers
<DIR> Cisco-VIC
<DIR> Cisco-VICmgmt
<DIR> Intel-C600
<DIR> Intel-Chipset
<DIR> LSI-12GSAS

Directory of E:\Share\Automation\Drivers\Cisco-VIC
10,092 enic6x64.cat
9,094 enic6x64.inf
292,016 enic6x64.sys

Directory of E:\Share\Automation\Drivers\Cisco-VICmgmt
8,781 vicmgmt64.cat
2,432 vicmgmt64.inf
31,432 vicmgmt64.sys
1,721,576 WdfCoInstaller01009.dll

Directory of E:\Share\Automation\Drivers\Intel-C600
721 dpinst.xml
7 MegaSR1
105,533 MegaSR1.cat
237,623 MegaSR1.inf
444 megasr1.md5
910,248 megasr1.sys
1,014 nodev.inf
50,282 txtsetup.oem

Directory of E:\Share\Automation\Drivers\Intel-Chipset
39,638 Chipset.cat
14,634 Chipset_SMBus.inf
61,224 Chipset_System.inf
9,182 Chipset_Thermal.inf
6,618 Chipset_USB.inf
8,154 Chipset_Win78only.inf

Directory of E:\Share\Automation\Drivers\LSI-12GSAS
42,261 DriverConfigParam.def
13,376 lsinodrv.inf
18,024 lsi_sas3.cat
26,990 LSI_SAS3.inf
839,680 lsi_sas3.pdb
100,688 lsi_sas3.sys
14,603 lsi_sas3_win8.1_2012R2.txt
159,056 wdcfg.exe

Windows PowerShell
WinPE is designed to be a very compact image because it is often used for PXE
booting a system, and for that purpose it is desired to keep the image as small as

20 | P a g e
possible. As a result, it comes with the basic command-line capabilities. But with
higher speed networks, and using WinPE from bootable USB or DVD media, the
larger image created by adding PowerShell to the image gives you the ability to
create powerful scripts for WinPE to execute for tailoring images.
The following commands demonstrate how to install the six optional PowerShell
components into the WinPE image that are required for this example. You will notice
that there are two lines per component the component and its associated
language pack. Both are required to be installed. Additionally, the added
components often need to be added in a specific sequence. The following list
follows the prescribed sequence.
For a full list of optional components that can be added to WinPE, see
http://msdn.microsoft.com/windows/hardware/commercialize/manufacture/desktop/
winpe-add-packages--optional-components-reference.

21 | P a g e
Dism /Add-Package /Image:C:\WinPE\mount /PackagePath:C:\Program Files (x86)\Windows
Kits\10\Assessment and Deployment Kit\Windows Preinstallation
Environment\amd64\WinPE_OCs\WinPE-WMI.cab
Dism /Add-Package /Image:C:\WinPE\mount /PackagePath:"C:\Program Files (x86)\Windows
Kits\10\Assessment and Deployment Kit\Windows Preinstallation
Environment\amd64\WinPE_OCs\en-us\WinPE-WMI_en-us.cab"
Dism /Add-Package /Image:C:\WinPE\mount /PackagePath:"C:\Program Files (x86)\Windows
Kits\10\Assessment and Deployment Kit\Windows Preinstallation
Environment\amd64\WinPE_OCs\WinPE-NetFX.cab"
Dism /Add-Package /Image:C:\WinPE\mount /PackagePath:"C:\Program Files (x86)\Windows
Kits\10\Assessment and Deployment Kit\Windows Preinstallation
Environment\amd64\WinPE_OCs\en-us\WinPE-NetFX_en-us.cab"
Dism /Add-Package /Image:C:\WinPE\mount /PackagePath:"C:\Program Files (x86)\Windows
Kits\10\Assessment and Deployment Kit\Windows Preinstallation
Environment\amd64\WinPE_OCs\WinPE-Scripting.cab"
Dism /Add-Package /Image:C:\WinPE\mount /PackagePath:"C:\Program Files (x86)\Windows
Kits\10\Assessment and Deployment Kit\Windows Preinstallation
Environment\amd64\WinPE_OCs\en-us\WinPE-Scripting_en-us.cab"
Dism /Add-Package /Image:C:\WinPE\mount /PackagePath:"C:\Program Files (x86)\Windows
Kits\10\Assessment and Deployment Kit\Windows Preinstallation
Environment\amd64\WinPE_OCs\WinPE-PowerShell.cab"
Dism /Add-Package /Image:C:\WinPE\mount /PackagePath:"C:\Program Files (x86)\Windows
Kits\10\Assessment and Deployment Kit\Windows Preinstallation
Environment\amd64\WinPE_OCs\en-us\WinPE-PowerShell_en-us.cab"
Dism /Add-Package /Image:C:\WinPE\mount /PackagePath:"C:\Program Files (x86)\Windows
Kits\10\Assessment and Deployment Kit\Windows Preinstallation
Environment\amd64\WinPE_OCs\WinPE-StorageWMI.cab"
Dism /Add-Package /Image:C:\WinPE\mount /PackagePath:"C:\Program Files (x86)\Windows
Kits\10\Assessment and Deployment Kit\Windows Preinstallation
Environment\amd64\WinPE_OCs\en-us\WinPE-StorageWMI_en-us.cab"
Dism /Add-Package /Image:C:\WinPE\mount /PackagePath:"C:\Program Files (x86)\Windows
Kits\10\Assessment and Deployment Kit\Windows Preinstallation
Environment\amd64\WinPE_OCs\WinPE-DismCmdlets.cab"
Dism /Add-Package /Image:C:\WinPE\mount /PackagePath:"C:\Program Files (x86)\Windows
Kits\10\Assessment and Deployment Kit\Windows Preinstallation
Environment\amd64\WinPE_OCs\en-us\WinPE-DismCmdlets_en-us.cab"

Note: The location of PowerShell packages to be installed will vary according to the
version of the system on which the ADK is installed. The commands shown above
were installed on Windows 10 (Windows Server 2016). If using Windows 8.1
(Windows Server 2012 R2), the /PackagePath will need to point to C:\Program Files
(x86)\Windows Kits\8.1\Assessment and Deployment Kit\Windows Preinstallation
Environment\amd64\WinPE_OCs\.

Cisco UCS PowerTool


In addition to installing Windows PowerShell into WinPE, it is also possible to install
Cisco UCS PowerTool. (PowerTool is dependent upon PowerShell, so PowerShell must
first be installed). Having PowerTool available makes it possible to communicate to
the Cisco UCS Management API to find out information from the service profile of
the system that booted WinPE.

22 | P a g e
The following steps perform a manual installation of UCS PowerTool. It assumes that
UCS PowerTool is installed on the system that is tailoring the WinPE image.
mkdir "C:\WinPE\mount\Program Files\WindowsPowerShell\Modules\Cisco.UCS.Core "
mkdir "C:\WinPE\mount\Program Files\WindowsPowerShell\Modules\Cisco.UCSManager "
attrib +s "C:\WinPE\mount\Program Files\WindowsPowerShell\Modules\Cisco.UCS.Core "
attrib +s "C:\WinPE\mount\Program Files\WindowsPowerShell\Modules\Cisco.UCSManager "
copy C:\Program Files (x86)\WindowsPowerShell\Modules\Cisco.UCS.Core\*.*
C:\WinPE\mount\Program Files\WindowsPowerShell\Modules\Cisco.UCS.Core
copy C:\Program Files (x86)\WindowsPowerShell\Modules\Cisco.UCSManager\*.*
C:\WinPE\mount\Program Files\WindowsPowerShell\Modules\Cisco.UCSManager

Custom WinPE Scripts


Upon boot, WinPE automatically launches the Startnet.cmd file. This example will
illustrate modifying Startnet.cmd just enough to execute a PowerShell script file,
WinPE_Automation.ps1, that will perform the basics necessary to start the
automation. WinPE_Automation.ps1 will copy the Automation.ps1 file for the server
from the share and then execute it. Since it takes more effort to tailor the WinPE
boot image than it does to modify script files, most of the automation steps will be
performed from within Automation.ps1.
To minimize the amount of changes that need to be performed to the WinPE image,
this example will create the WinPE_Automation.ps1 script file within the WinPE
image and modify Startnet.cmd to launch it.

Startnet.cmd
When WinPE is booted, simply use Notepad to edit the contents of this file.
Notepad C:\WinPE\mount\Windows\System32\Startnet.cmd

When you are modifying Startnet.cmd, make sure you keep the wpeinit command at
the beginning of the file. Here is a sample Startnet.cmd file. Note in the PowerShell
command that there is a space between the period (.) and X:. This is required.
WinPE uses X: as its in-memory drive when it is running.
wpeinit

REM If DHCP is unavailable, configure the following command for your environment
REM netsh int ip set address "ethernet" static 192.168.10.190 255.255.255.0
192.168.10.1

REM Launch the automation process


PowerShell "Set-ExecutionPolicy Bypass Force
PowerShell . X:\Temp\WinPE_Automation.ps1"
exit

Note: During your initial testing and debugging of your scripts, you may want to
remove the trailing exit command. This allows you to manipulate your scripts

23 | P a g e
within WinPE. The trailing exit command will cause WinPE to automatically reboot
the system.

WinPE_Automation.ps1
Since we have PowerShell available to us, it is easy to write the basic file necessary
to perform the minimum number of steps on the environment before launching the
primary script, Automation.ps1.
This sample file performs the following tasks:

initializes customer specific variables to define the environment for accessing


UCSM and the file share on the workstation
connect to the share using the provided credentials
launch the Automation.ps1 file from the share for this service profile
exit PowerShell

Using a procedure like this allows for files to be changed in the download directory
quickly to change the deployment procedure without any need to make alterations
to the created WinPE image.
Though you can create this file in any existing directory on the WinPE image,
because it is not part of the regular distribution, I like to create a temp directory and
create the file there. Create a temp directory and use Notepad to create the file. (If
you do create the file in a different directory, make sure you change your
Startnet.cmd to reflect the different location than that shown in this sample).
md C:\WinPE\mount\Temp
notepad C:\WinPE\mount\Temp\WinPE_Automation.ps1

# The following parameters must be modified for each user's environment

$shareName = '\\192.168.20.25\Share' # Share location for automation files


$shareUser = 'BuilderUser' # Local user account on Share server
$sharePWD = 'P@55w0rd' # Local user account password
$shareScripts = S:\Automation\Scripts # Location of remote script

# Access the share for the automation files and for writing log files
New-SmbMapping -LocalPath S: -RemotePath $shareName -UserName $shareUser -Password
$sharePWD
Try
{
dir $shareScripts\Automation.ps1
}
Catch
{
# Failed to connect to share. Exit
Exit
}

# Launch the primary automation script


. $shareScripts\Automation.ps1

Exit

24 | P a g e
Dismount WinPE Media
When all modifications have been performed, dismount the WinPE image and
commit the changes.
Dism /Unmount-Image /MountDir:C:\WinPE\mount /commit

If you do not want to save the image with modifications, discard all changes made.
Dism /Unmount-Image /MountDir:C:\WinPE\mount /discard

Create Bootable WinPE Media


Once the tailoring of WinPE is complete, the files can be saved for use as a bootable
image to either an ISO file or a USB drive.
To create an ISO file, use the following command:
MakeWinPEMedia /ISO C:\WinPE C:\Temp\WinPE.iso

You can burn this to a DVD or simply mount it as virtual media to UCS Manager. I
will be using it as virtual media.
To create a bootable USB device, use the following command (F: is the location of
the USB media):
MakeWinPEMedia /UFD C:\WinPE F:

Windows Server comes with an optional role that can make it a PXE-boot server.
This role is known as Windows Deployment Services (WDS). This is a role that has
been available on Windows Server almost since the beginning of Windows Server
and it is well-established and used in many customer environments. It is common
to install the modified WinPE into a WDS deployment as the boot image for a PXE
boot. Installation of WDS and its configuration are beyond the scope of this
document. More information can be found at https://technet.microsoft.com/en-
us/library/hh831764(v=ws.11).aspx.

Sample Automation Scripts


The following sample scripts are used in the defined automation process.

Automation.ps1 primary script for driving the automation process. Stored in


E:\Share\Automation\Scripts.
UCSM-Variables.xml XML file defining the access to UCS Manager. Read by
Automation.ps1. Stored in E:\Share\Automation\Scripts.
Variables.xml XML file defining configuration information for a specific
Service Profile. Read by Automation.ps1. Stored in
E:\Share\Automation\<SPname>\Scripts.

25 | P a g e
Unattend.xml XML file written by Automation.ps1 to the VHD created by this
process to automate the operating system deployment.
ServerSetup.ps1 custom script called by Setupcomplete.cmd to run against
any installation of Windows Server that is not a Nano installation. Stored in
E:\Share\Automation\<SPname>\Scripts.
NanoSetup.ps1 custom script called by Setupcomplete.cmd to run against
any installation of Nano Server. Stored in
E:\Share\Automation\<SPname>\Scripts.
The following examples demonstrate some of the things that you might want to
include in your automation scripts.

Automation.ps1
This is the primary script called by WinPE_Automation.ps1 in Startnet.cmd that will
tailor the installation environment when WinPE boots. You can add and remove
things here according to your specific needs. I will separate the complete file into
smaller sections to explain what the different sample sections are doing.
It is assumed that a single script named Automation.ps1 will be created. It will
include a mandatory parameter be passed to it. This script will be called by the
automation built into Startnet.cmd and will pass the Service Profile name as the
parameter.

Get-ServiceProfile
This section determines the name of the Service Profile assigned to the physical
machine on which it is running. The name of the Service Profile is used for finding
the directory in which the files customized for this Service Profiles configuration are
storage.
<#
Create paths to root automation shares
Read UCSM variable file
Import the Cisco UCSM PowerTool module
Connect to UCSM using credentials from above variables
Get the NIC information for the physical machine
Get all Service Profiles from UCSM
Compare NIC MAC addresses between running machine and each Service Profile until match is found
Match on MAC means we have found the Service Profile that defines this physical machine
Save the Service Profile name to be used for unique identification

Sample UCSM-Variable.xml file


<UCSM>
<IP>192.168.10.210</IP>
<Name>admin</Name>
<PWD>password.1</PWD>
</UCSM>

#>

# Create paths to root automation shares


$shareRoot = "S:\Automation"
$shareDrivers = Join-Path -Path $shareRoot -ChildPath "Drivers"
$shareScripts = Join-Path -Path $shareRoot -ChildPath "Scripts"
$shareVHDs = Join-Path -Path $shareRoot -ChildPath "VHDs"

26 | P a g e
$ucs = [XML](Get-Content -Path $shareScripts\UCSM-Variables.xml)

Import-Module Cisco.UCS.Core, Cisco.UcsManager

$pwd = ConvertTo-SecureString -String $($ucs.UCSM.PWD) -AsPlainText -Force


$creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $
($ucs.UCSM.User), $pwd
$dustbin = Connect-Ucs -Name $($ucs.UCSM.IP) -Credential $creds
If (!$dustbin)
{
# Did not connect to UCS Manager. Exit
Exit
}

$NICs = Get-CimInstance Win32_NetworkAdapterConfiguration


$SPs = Get-UcsServiceProfile

:macchk Foreach ($NIC in $NICs)


{
If ($NIC.IPenabled -eq $true)
{
Foreach ($SP in $SPs)
{
$vnics = $SP | Get-UcsVnic
Foreach ($vnic in $vnics)
{
If ($vnic.Addr -ne 'derived')
{
If ($NIC.MACaddress -eq $vnic.Addr)
{
Break macchk
}
}
}
}
}
}
$computerName = $SP.Name

Note: The above script references a file named UCSM-Variables that contains
access information stored in plain text not a secure way to handle credentials. A
more secure way would be to capture the password and store it securely into a file.
The following command will capture and store the password securely.
Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File C:\Creds.txt

You can then retrieve the secure password from the file whenever needed and build
the needed credentials to use to connect to UCS Manager.
$pwd = Get-Content C:\cred.txt | ConvertTo-SecureString

Populate Parameters
WinPE_Automation.ps1 finds that information and passes it to this script when it
launches Automation.ps1. That value is used to determine the location of share
subdirectories and is also used to rename the computer to match the name of the
Service Profile.

27 | P a g e
NOTE: The <JoinDomain> section in this sample XML file works for non-Nano Server
installations. This sort of domain join operation is not supported in Nano Server,
yet.
<#
This section tailors the automation to a specific machine.
Using the $computerName variable defined in the previous section, it defines
some paths in order to read an .xml file configured for this specific
Service Profile.

Sample XML file

<Var>
<LocalAdminPwd>password.1</LocalAdminPwd>
<WindowsProductKey>6XBNX-4JQGW-QX6QG-74P76-72V67</WindowsProductKey>
<TimeZone>Pacific Standard Time</TimeZone>
<BaseVHD>WS2016_DC.vhdx</BaseVHD>
<MgmtNIC>
<Name>Mgmt</Name>
<IP>192.168.10.75</IP>
<Mask>24</Mask>
<GW>192.168.10.1</GW>
<DNS>192.168.20.201</DNS>
</MgmtNIC>
<JoinDomain>
<Short>LJ</Short>
<FQDN>LJ.net</FQDN>
<User>Adminstrator</User>
<PWD>password.1</PWD>
</JoinDomain>
</Var>

#>

# Create paths for accessing the Service Profile Name share subdirectory
$spRoot = Join-Path -Path $shareRoot -ChildPath $computerName
$spExecutables = Join-Path -Path $spRoot -ChildPath "Executables"
$spLogs = Join-Path -Path $spRoot -ChildPath "Logs"
$spScripts = Join-Path -Path $spRoot -ChildPath "Scripts"

Start-Transcript -Path $spLogs\$computername.txt

$xVar = [XML](Get-Content -Path $spScripts\Variables.xml)

Partition-Disk
This section partitions a raw disk that will be used to host the native boot VHD
<#
Define variables used in the creation of the various partitions
Determine type of boot BIOS or UEFI
Clean data from ANY disk that has data ***
Find the first of the smallest disks to use as the OS disk
Initial disk and create partitions
#>

$Guid_GptType_Recovery = "{de94bba4-06d1-4d40-a16a-bfd50179d6ac}"
$Guid_GptType_Efi = "{c12a7328-f81f-11d2-ba4b-00a0c93ec93b}"
$Guid_GptType_Msr = "{e3c9e316-0b5c-4db8-817d-f92df00215ae}"

28 | P a g e
$Partition_Size_BIOSboot = 500MB
$Partition_Size_EFIboot = 99MB
$Partition_Size_Msr = 16MB
$Partition_Size_Recovery = 450MB

wpeinit
wpeutil InitializeNetwork
wpeutil WaitForNetwork
wpeutil UpdateBootInfo

$firmware = Get-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control -Name PEFirmwareType


If ($firmware.PEFirmwareType -eq 1)
{
$bootType = "BIOS"
}
Elseif ($firmware.PEFirmwareType -eq 2)
{
$bootType = "UEFI"
}

$disk = Get-Disk | Where-Object -Property OperationalStatus -eq Online

Foreach ($currentDisk in $disk)


{
If ($currentDisk.PartitionStyle -ne "RAW")
{
Clear-Disk -InputObject $currentDisk -RemoveData -RemoveOEM -Confirm:$false
}
}

$osDisk = $disk | Sort-Object -Property Size, Number | Select-Object -First 1


If ($bootType -eq "BIOS")
{
Initialize-Disk -InputObject $osDisk -PartitionStyle MBR
$bootPartition = New-Partition -InputObject $osDisk -Size $Partition_Size_BIOSboot -IsActive
Format-Volume -Partition $bootPartition -FileSystem NTFS -Confirm:$false | Out-Null
}
Elseif ($bootType -eq "UEFI")
{
Initialize-Disk -InputObject $osDisk -PartitionStyle GPT
Get-Partition -Disk $osDisk | Remove-Partition -Confirm:$false
$WinREPartition = New-Partition -InputObject $osDisk -Size $Partition_Size_Recovery -GptType
$Guid_GptType_Recovery
Format-Volume -Partition $WinREPartition -FileSystem NTFS -Confirm:$false | Out-Null
$bootPartition = New-Partition -InputObject $osDisk -Size $Partition_Size_EFIboot -GptType
$Guid_GptType_Efi
@"
select disk $($osDisk.Number)
select partition $($bootPartition.PartitionNumber)
format fs=fat32 quick
"@ | diskpart | Out-Null
New-Partition -InputObject $osDisk -Size $Partition_Size_Msr -GptType $Guid_GptType_Msr | Out-Null
}
$osDisk = Get-Disk -Number $osDisk.Number
$priPartitionSize = $osDisk.LargestFreeExtent
$priPartition = New-Partition -InputObject $osDisk -Size $priPartitionSize -AssignDriveLetter
Format-Volume -Partition $priPartition -FileSystem NTFS -Confirm:$false | Out-Null
$localDrive = $priPartition.DriveLetter + :

29 | P a g e
Mount-Vdisk
This section configures the virtual hard disk to native boot the physical server.
<#
Copy VHDX file from share
Mount VHDX file
Find the diskpart volume number of the mounted vdisk
Assign a letter to that volume
Create bcdboot file on that volume
Copy tailoring scripts and executables to the VHD
Creates directories on the VHD and copies files to them
#>

$robocopy = Join-Path -Path $env:SystemRoot -ChildPath \system32\robocopy.exe


$robocopyArgs = $xVar.Var.BaseVHD
Start-Process -FilePath $robocopy -ArgumentList $shareVHDs, $localDrive, $robocopyArgs, /E, /J,
/ETA, /R:10 -NoNewWindow -Wait

$imagePath = Join-Path -Path $localDrive -ChildPath $xVar.Var.BaseVHD


Mount-DiskImage -ImagePath $imagePath
$mountedImage = Get-DiskImage -ImagePath $imagePath
$vhdPartition = Get-Partition -DiskNumber $mountedImage.Number | Where-Object -Property
DriveLetter | Select-Object -Last 1
$vhdDrive = $vhdPartition.DriveLetter + :

Add-PartitionAccessPath -InputObject $bootPartition -AssignDriveLetter


Get-PSDrive | Out-Null
$bootPartition = Get-Partition -DiskNumber $bootPartition.DiskNumber -PartitionNumber
$bootPartition.PartitionNumber
$bootDrive = $bootPartition.DriveLetter + :
$winPath = Join-Path -Path $vhdDrive -ChildPath \Windows
$bcdBoot = Join-Path -Path $env:SystemRoot -ChildPath \system32\bcdboot.exe
Start-Process -FilePath $bcdBoot -ArgumentList $winPath, /s, $bootDrive, /f, $bootType -WindowStyle
Hidden -Wait

New-Item -Path "$($vhdDrive)\Cisco" -ItemType Directory


New-Item -Path "$($vhdDrive)\Cisco\Drivers" -ItemType Directory
New-Item -Path "$($vhdDrive)\Cisco\Executables" -ItemType Directory
New-Item -Path "$($vhdDrive)\Cisco\Scripts" -ItemType Directory

If (!(Test-Path "$($vhdDrive)\Windows\Setup\Scripts"))
{
New-Item -Path "$($vhdDrive)\Windows\Setup\Scripts" -ItemType Directory
}
Copy-Item -Path $shareDrivers\*.* -Destination "$($vhdDrive)\Cisco\Drivers"
Copy-Item -Path $spExecutables\*.* -Destination "$($vhdDrive)\Cisco\Executables"
Copy-Item -Path $spScripts\*.* -Destination "$($vhdDrive)\Windows\Setup\Scripts"

# Leave disk mounted. Following steps write content to disk.

Create-Unattend
This section creates an unattend.xml file that is automatically read during the
automatic installation process of the Windows operating system. This unattend.xml
file is created to a lowest common denominator regarding features that are

30 | P a g e
available to both Nano Server and Windows Server. Windows Server unattend.xml
supports many additional parameters. The file is written into the root directory of
the VHD file created.
Caution: Do not use this file without first determining that it meets your specific
needs.
<#
Set Registered Organization and Owner
Set computer name
Set time zone
Set Windows Product Key
Set local administrator password
Hide display of EULA
Set locale to en-US
#>

@"
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">

<settings pass="specialize">

<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64"


publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
<RegisteredOrganization>Apollo</RegisteredOrganization>
<RegisteredOwner>Windows</RegisteredOwner>
<ComputerName>$computerName</ComputerName>
<TimeZone>$($xVar.Var.TimeZone)</TimeZone>
<ProductKey>$($xVar.Var.windowsProductKey)</ProductKey>
</component>

</settings>

<settings pass="oobeSystem">
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64"
publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" >
<AutoLogon>
<Password>
<Value>$($xVar.Var.LocalAdminPwd)</Value>
<PlainText>true</PlainText>
</Password>
<LogonCount>1</LogonCount>
<Username>Administrator</Username>
<Enabled>true</Enabled>
</AutoLogon>
<UserAccounts>
<AdministratorPassword>
<Value>$($xVar.Var.LocalAdminPwd)</Value>
<PlainText>true</PlainText>
</AdministratorPassword>
</UserAccounts>
<OOBE>
<HideEULAPage>true</HideEULAPage>
<NetworkLocation>Other</NetworkLocation>
</OOBE>
</component>

31 | P a g e
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64"
publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" >
<InputLocale>en-us</InputLocale>
<SystemLocale>en-us</SystemLocale>
<UILanguage>en-us</UILanguage>
<UserLocale>en-us</UserLocale>
</component>
</settings>

</unattend>

"@ | Out-File "$($vhdDrive)\unattend.xml" -Encoding ascii

Setup-Complete
This section create a SetupComplete.cmd file. Once the Windows installation setup
is completed, it looks for this file on the first boot. If found, it will execute whatever
is in this file. It is a handy place to create additional tailoring that could not be
accomplished with the unattend.xml file.
Caution: Do not use this file without first determining that it meets your specific
needs.
<#
Set pagefile settings to small pagefile.sys
Set power configuration to run at maximum
Change PowerShell execution policy to allow for execution of script files
Determine OS being deployed and execute appropriate server setup script
Delete unattend.xml file
#>

@"
PowerShell "Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session
Manager\Memory Management' -Name ExistingPageFiles -Value
'\??\C:\pagefile.sys','\??\D:\pagefile.sys'"

PowerShell "Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session


Manager\Memory Management' -Name PagingFiles -Value 'C:\pagefile.sys 32 2048','D:\pagefile.sys 16
16'"

set LOCALAPPDATA=%USERPROFILE%\AppData\Local

powercfg /setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c

PowerShell "Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser -Force"

PowerShell "If ($($xvar.var.BaseVHD) -match 'Nano') {. C:\Windows\Setup\Scripts\NanoSetup.ps1} Else


{. C:\Windows\Setup\Scripts\ServerSetup.ps1}"

del C:\unattend.xml
Shutdown -r -t 0
"@ | Out-File "$($vhdDrive)\Windows\Setup\Scripts\SetupComplete.cmd" -Encoding asci -Append

Notice the last PowerShell command above that is being written to the
SetupComplete.cmd file. It is testing the name of the VHD used to provision the
environment. It is assuming a naming convention whereby any Nano installation

32 | P a g e
has a VHD name starting with Nano. Anything else is assumed to be a Windows
Server installation, not a Nano Server installation.
This process of a script calling another script shows how easy it is to chain
additional scripts together and to start their execution from within
SetupComplete.cmd. For example, you might want to enable/disable firewall rules,
set system parameters, and/or run specific applications. Below show a couple of
scripts that could be used to configure a Windows Server (full or core) or Nano
Server installation. If you want to set up something that requires a system reboot,
such as joining a domain or installing a role like Hyper-V, you will need to define that
as a PowerShell workflow, as a workflow will continue running after a system reboot.

Clean-BCD
When using UEFI booting, the Windows boot process makes use of firmware storage
for storing boot options. If you redeploy the same server more than once, old
entries in the bootmgfw.efi file can cause the automation process to fail. This
section of the script examines the contents of bootmfgw.efi and removes any stale
entries, i.e. any entries that are not valid for the current environment.
$BcdEdit = Join-Path -Path $env:SystemRoot -ChildPath "\system32\bcdedit.exe"
Start-Process -FilePath $BcdEdit -WindowStyle Hidden -Wait

if ($BootType -eq "UEFI")


{
# Cleaning old boot entries
$BcdEnum = & $BcdEdit /enum FIRMWARE
foreach ($line in $BcdEnum)
{
if (!$line) # separator between entries
{
$BcdEntryName = ""
$BcdEntry = @{}
}
elseif ($line[0] -eq "-")
{
continue
}
elseif ($BcdEntryName -eq "")
{
$BcdEntryName = $line
}
else
{
$SplitLine = $line.Split(" ")
$ParameterName = $SplitLine[0]
$ParameterValue = ($SplitLine[1..($SplitLine.Count-1)] -join " ").TrimStart(" ")
if ($ParameterName)
{
$BcdEntry.Add($ParameterName, $ParameterValue)
}
}
if ($BcdEntry.description -eq "Windows Boot Manager" -and $BcdEntry.identifier -ne "{bootmgr}")
{
Start-Process -FilePath $BcdEdit -ArgumentList "/delete", $BcdEntry.identifier -WindowStyle
Hidden -Wait
}
}

33 | P a g e
}

You should end your Automation.ps1 script with the following commands to
dismount the VHD, disconnect from UCSM, and exit PowerShell.
Dismount-DiskImage -ImagePath $imagePath
Disconnect-Ucs

Exit

Variables.xml
This is a sample file containing just the basic information. It is possible to modify
some of the other scripts or add additional scripts to read more information from
this file to increase the automation capabilities. This sample file contains a
minimum number of variables to demonstrate what is possible. Additional
variables can be added to augment other automation capabilities that you may wish
to implement.
<?xml version="1.0" encoding="utf-8"?>
<Var>
<LocalAdminPwd>password.1</LocalAdminPwd>
<WindowsProductKey>6XBNX-4JQGW-QX6QG-74P76-72V67</WindowsProductKey>
<TimeZone>Pacific Standard Time</TimeZone>
<BaseVHD>Nano_C_C.vhdx</BaseVHD>
<MgmtNIC>
<name>Mgmt</name>
<IP>192.168.10.75</IP>
<Mask>24</Mask>
<GW>192.168.10.1</GW>
<DNS>192.168.20.201</DNS>
</MgmtNIC>
<JoinDomain>
<Short>LJ</Short>
<FQDN>LJ.net</FQDN>
<User>Adminstrator</User>
<PWD>password.1</PWD>
</JoinDomain>
</Var>

LocalAdminPwd value to be used to set the local administrator password on the


operating system.
WindowsProductKey Windows Server activation key. Note that the key shown is a
key used for activating the Windows Server 2016 Technology Preview. This should
be changed to the appropriate value for the customer environment.
TimeZone time zone where the server is deployed.
BaseVHD name of the VHD file that will be used in the deployment.
MgmtNIC IP configuration of the management NIC. This is dependent upon CDN
being configured on the Service Profile used to boot the server. Mgmt is the CDN
value specified in the Service Profile for the vNIC that you want to configure. If all
servers are defined with DHCP addresses, this variable can be omitted.

34 | P a g e
JoinDomain specify domain to join and credentials with privileges that can join
members to the domain. These values can be passed into the unattend.xml file to
automate the joining to the domain. This sample shows using the domain
administrator account. It is common practice to create an account with just the
privilege to add members to the domain instead of using domain administrator
credentials. It is possible to pass these values into an unattend file that will be used
for a non-Nano Server installation. Nano Server does not implement the unattend
steps that support joining a domain in this manner. See Getting Started with Nano
Server for details on how to configure an unattend that can be used by Nano Server.

UCSM-Variables.xml
This file contains the basic information needed to log into the UCS Management
domain.
<?xml version="1.0" encoding="utf-8"?>
<UCSM>
<IP>192.168.10.210</IP>
<User>admin</User>
<PWD>password.1</PWD>
</UCSM>

Unattend.xml
This file is created in the Create-Unattend section of the Automation.ps1 file. The
sample shown in this document is a simplistic example, as the unattend file has lots
of capabilities of configuring options. This capability has been around since the
beginning of Windows Server and is well understood by any customer that has any
form of deployment automation. Explanation of the capabilities of this file is beyond
the scope of this document.
When reviewing the Create-Unattend section of the Automation.ps1 file, you will see
there is variable substitution used. This allows for variable values to be passed into
the unattend file to tailor the file for each server being deployed.

ServerSetup.ps1 (Windows Server)


This section shows a PowerShell script to perform a series of configuration steps
that may be done to each Windows Server system (will not work with Nano Server).
Or, it could do whatever you want. I simply demonstrate enabling a number of
firewall rules and some other things. It could be as sophisticated as querying UCSM
to read information from the service profile configuration to tailor the installation in
any other manner.
Caution: Do not use this file without first determining that it meets your specific
needs.
<#
Read the Variables file for this Service Profile
Configure the management NIC with a fixed IP if it is defined
Enable several firewall rules that make remote management easier
Enable Remote Desktop
Set Windows SmartScreen to require administrator approval
Disable expiration of local Administrator password
#>

35 | P a g e
$xVar = [XML](Get-Content -Path C:\Windows\Setup\Scripts\Variables.xml)

# Fix an anomaly from using CDN to name NICs.


$NICs = Get-NetAdapter
Foreach ($NIC in $NICs)
{
$old = $NIC.Name
$new = $NIC.Name.Trim()
Rename-NetAdapter -Name $old -NewName $new
Set-DnsClient $($xVar.Var.MgmtNIC.Name) -RegisterThisConnectionisAddress $False
}

# If Mgmt NIC is named, assume fixed IP to be assigned


$tmp = $($xVar.Var.MgmtNIC.Name)
If ($tmp)
{
Get-NetAdapter $($xVar.Var.MgmtNIC.Name) | New-NetIpAddress -IPAddress $($xVar.Var.MgmtNIC.IP)
-PrefixLength $($xVar.Var.MgmtNIC.Mask) -DefaultGateway $($xVar.Var.MgmtNIC.GW)
Get-NetAdapter $($xVar.Var.MgmtNIC.Name) | Set-DnsClientServerAddress -ServerAddress $
($xVar.Var.MgmtNIC.DNS)
Set-DnsClient $($xVar.Var.MgmtNIC.Name) -RegisterThisConnectionsAddress $True
-ConnectionSpecificSuffix $($xvar.var.JoinDomain.FQDN)
Set-DnsClient $($xVar.Var.MgmtNIC.Name) -UseSuffixWhenRegistering $False
Register-DnsClient
}

# Enable ping requests in and out


Set-NetFirewallRule -Name FPS-ICMP4-ERQ-In -Enabled True -Profile Any -RemoteAddress Any
Set-NetFirewallRule -Name FPS-ICMP6-ERQ-In -Enabled True -Profile Any -RemoteAddress Any
Set-NetFirewallRule -Name FPS-ICMP4-ERQ-Out -Enabled True -Profile Any -RemoteAddress Any
Set-NetFirewallRule -Name FPS-ICMP6-ERQ-Out -Enabled True -Profile Any -RemoteAddress Any

# Enable remote volume management


Set-NetFirewallRule -Name RVM-VDS-In-TCP -Enabled True -Profile Any
Set-NetFirewallRule -Name RVM-VDSLDR-In-TCP -Enabled True -Profile Any
Set-NetFirewallRule -Name RVM-RPCSS-In-TCP -Enabled True -Profile Any

# Enable remote service management


Set-NetFirewallRule -Name RemoteSvcAdmin-In-TCP -Enabled True -Profile Any
Set-NetFirewallRule -Name RemoteSvcAdmin-NP-In-TCP -Enabled True -Profile Any
Set-NetFirewallRule -Name RemoteSvcAdmin-RPCSS-In-TCP -Enabled True -Profile Any

# Enable Remote Event Log Management


Set-NetFirewallRule -Name RemoteEventLogSvc-In-TCP -Enabled True -Profile Any
Set-NetFirewallRule -Name RemoteEventLogSvc-NP-In-TCP -Enabled True -Profile Any
Set-NetFirewallRule -Name RemoteEventLogSvc-RPCSS-In-TCP -Enabled True -Profile Any

# Enable Remote Scheduled Tasks Management


Set-NetFirewallRule -Name RemoteTask-In-TCP -Enabled True -Profile Any
Set-NetFirewallRule -Name RemoteTask-RPCSS-In-TCP -Enabled True -Profile Any

# Enable Windows Firewall Remote Management


Set-NetFirewallRule -Name RemoteFwAdmin-In-TCP -Enabled True -Profile Any
Set-NetFirewallRule -Name RemoteFwAdmin-RPCSS-In-TCP -Enabled True -Profile Any

# Allow PowerShell remoting from any subnet


Set-NetFirewallRule -Name WinRM-HTTP-In-TCP-Public -RemoteAddress Any -Profile Public

# Enable WMI management requests in


Set-NetFirewallRule -Name WMI-WINMGMT-In-TCP -Enabled True -Profile Any

36 | P a g e
# Enable Remote Shutdown
Set-NetFirewallRule -Name Wininit-Shutdown-In-Rule-TCP-RPC -Enabled True -Profile Any

# Enable Network Discovery on the Domain Network


Set-NetFirewallRule -Name NETDIS-FDPHOST-In-UDP -Enabled True -Profile Domain
Set-NetFirewallRule -Name NETDIS-FDPHOST-Out-UDP -Enabled True -Profile Domain

# Set some services to automatically start and start them.


Set-Service -Name PlugPlay -StartupType Automatic
Start-Service PlugPlay
Set-Service -Name RemoteRegistry -StartupType Automatic
Start-Service RemoteRegistry
Set-Service -Name vds -StartupType Automatic
Start-Service vds

# Enable Remote Desktop


(Get-CimInstance Win32_TerminalServiceSetting -Namespace
root\cimv2\TerminalServices).SetAllowTsConnections(1,1) | Out-Null
(Get-CimInstance -Class Win32_TSGeneralSetting -Namespace root\cimv2\TerminalServices -Filter
"TerminalName='RDP-tcp'").SetUserAuthenticationRequired(0) | Out-Null

# Enable Remote Desktop rules for all profiles


Set-NetfirewallRule -Name RemoteDesktop-UserMode-In-TCP -Enabled True -Profile Any
Set-NetfirewallRule -Name RemoteDesktop-UserMode-In-UDP -Enabled True -Profile Any

##################
# Not Remote Management requirements, but common changes
##################

# Set Windows SmartScreen to require administrator approval


New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" `
-Name EnableSmartScreen -Value 2 `
-PropertyType DWord -Force | Out-Null

# Set local administrator password to never expire


$localAdmin = Get-CimInstance -Class Win32_UserAccount -Filter "LocalAccount=True AND
Name='Administrator'"
$localAdmin.PasswordExpires = $false
Set-CimInstance $localAdmin

NanoSetup.ps1 (Nano Server)


Nano Server has a subset of the PowerShell commands available to, nor does it
have all the firewall settings of a non-Nano installation. Therefore, the
NanoSetup.ps1 file will differ from the Windows Server file.
Nano first boots with minimum installation PowerShell, so you must first import the
modules for the cmdlets that will be used in this script. The modules imported will
vary depending upon the particular PowerShell cmdlets used.
Import-Module Microsoft.PowerShell.Utility
Import-Module Microsoft.PowerShell.Management
Import-Module NetAdapter
Import-Module NetTCPIP
Import-Module NetSecurity
Import-Module DnsClient
Import-Module CimCmdlets

37 | P a g e
$xVar = [XML](Get-Content -Path C:\Windows\Setup\Scripts\Variables.xml)

# Fix an anomaly from using CDN to name NICs.


$NICs = Get-NetAdapter
Foreach ($NIC in $NICs)
{
$old = $NIC.Name
$new = $NIC.Name.Trim()
Rename-NetAdapter -Name $old -NewName $new
Set-DnsClient $($xVar.Var.MgmtNIC.Name) -RegisterThisConnectionisAddress $False
}

# If Mgmt NIC is named, assume fixed IP to be assigned


$tmp = $($xVar.Var.MgmtNIC.Name)
If ($tmp)
{
Get-NetAdapter $($xVar.Var.MgmtNIC.Name) | New-NetIpAddress -IPAddress $($xVar.Var.MgmtNIC.IP)
-PrefixLength $($xVar.Var.MgmtNIC.Mask) -DefaultGateway $($xVar.Var.MgmtNIC.GW)
Get-NetAdapter $($xVar.Var.MgmtNIC.Name) | Set-DnsClientServerAddress -ServerAddress $
($xVar.Var.MgmtNIC.DNS)
Set-DnsClient $($xVar.Var.MgmtNIC.Name) -RegisterThisConnectionsAddress $True
-ConnectionSpecificSuffix $($xvar.var.JoinDomain.FQDN)
Set-DnsClient $($xVar.Var.MgmtNIC.Name) -UseSuffixWhenRegistering $False
Register-DnsClient
}

# Enable ping requests in and out


Set-NetFirewallRule -Name FPS-ICMP4-ERQ-In -Enabled True -Profile Any -RemoteAddress Any
Set-NetFirewallRule -Name FPS-ICMP6-ERQ-In -Enabled True -Profile Any -RemoteAddress Any
Set-NetFirewallRule -Name FPS-ICMP4-ERQ-Out -Enabled True -Profile Any -RemoteAddress Any
Set-NetFirewallRule -Name FPS-ICMP6-ERQ-Out -Enabled True -Profile Any -RemoteAddress Any

# Enable remote service management


Set-NetFirewallRule -Name RemoteSvcAdmin-In-TCP -Enabled True -Profile Any
Set-NetFirewallRule -Name RemoteSvcAdmin-NP-In-TCP -Enabled True -Profile Any
Set-NetFirewallRule -Name RemoteSvcAdmin-RPCSS-In-TCP -Enabled True -Profile Any

# Enable Remote Event Log Management


Set-NetFirewallRule -Name RemoteEventLogSvc-In-TCP -Enabled True -Profile Any
Set-NetFirewallRule -Name RemoteEventLogSvc-NP-In-TCP -Enabled True -Profile Any
Set-NetFirewallRule -Name RemoteEventLogSvc-RPCSS-In-TCP -Enabled True -Profile Any

# Enable Windows Firewall Remote Management


Set-NetFirewallRule -Name RemoteFwAdmin-In-TCP -Enabled True -Profile Any
Set-NetFirewallRule -Name RemoteFwAdmin-RPCSS-In-TCP -Enabled True -Profile Any

# Allow PowerShell remoting from any subnet


Set-NetFirewallRule -Name WinRM-HTTP-In-TCP-Public -RemoteAddress Any -Profile Public

# Set power policy to high performance


powercfg /setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c

# Set local administrator password to never expire


$localAdmin = Get-CimInstance -Class Win32_UserAccount -Filter "LocalAccount=True AND
Name='Administrator'"
$localAdmin.PasswordExpires = $false
Set-CimInstance $localAdmin

38 | P a g e
ForcePxeBoot
The following script can be used to force a PXE boot of your system. This is handy
during testing. After you have installed an operating system to a server, it will want
to boot to the operating system when the system is restarted. The following script
uses IPMI to make a one-time change to the boot environment to boot from LAN and
then restarts the machine. It requires that you have an IPMI user and IPMI Policy
defined in the Service Profile assigned to the server. Inputs to this script include the
IPMI username (it is case-sensitive), its password, and the CIMC IP address.
# Restart server to PXE boot

Write-Host ''
Write-Host -ForegroundColor Yellow 'Enter credentials for IPMI user. Username is case-sensitive.'

$creds = Get-Credential -Message 'Case-sensitive credentials for IPMI'

$ipAddr = Read-Host 'Enter CIMC IP address of targeted server'

$device = Get-PcsvDevice -TargetAddress $ipAddr -Credential $creds -ManagementProtocol IPMI


Set-PcsvDeviceBootConfiguration -TargetAddress $ipAddr -Credential $creds -ManagementProtocol IPMI
-OneTimeBootSource $device.StructuredBootString[0]
If ($device.Status -eq 'enabled')
{
Stop-PcsvDevice -TargetAddress $ipAddr -Credential $creds -ManagementProtocol IPMI -Confirm:
$false
}
Do
{
Start-Sleep -Seconds 5
$device = Get-PcsvDevice -TargetAddress $ipAddr -Credential $creds -ManagementProtocol IPMI
} While ($device.Status -eq 'enabled')

Start-PcsvDevice -TargetAddress $ipAddr -Credential $creds -ManagementProtocol IPMI

IPMI Policy

39 | P a g e
Service Profile Policy

Summary
The above sample shows a fairly minimal solution to automating the deployment of
Windows Server operating systems. You could add additional variables in the
Variables.xml file to define different options that you want to perform. Then modify
the above scripts to make additional changes, such as adding roles and features to
Windows Server installations or joining a domain, depending upon the variables
defined.
Cisco UCS Manager and PowerTool add other capabilities that are not possible with
other computer systems. For example, you may find situations where you would
want WinPE to perform some different tasks. You could keep a library of different
WinPE images tailored for specific situations. Then you could script the addition of
the WinPE ISO to the virtual media of a given server and then initiate a boot. This
means that it would be possible to automatically deploy servers on demand without
the need to customize a PXE server.
With a little imagination, you can automate just about anything you can think of.
Enjoy!

Author
Tim Cerling
Technical Marketing Engineer
Cisco Systems

40 | P a g e

Vous aimerez peut-être aussi